Merge pull request #2057 from janetournois/PMP-fix_is_outward_oriented-GF

PMP : fix `PMP::is_outward_oriented()`
This commit is contained in:
Laurent Rineau 2017-05-17 12:59:58 +02:00 committed by GitHub
commit 2ad18ad5d7
24 changed files with 477 additions and 111 deletions

View File

@ -96,6 +96,13 @@ namespace CartesianKernelFunctors {
r.x(), r.y(), r.z(),
s.x(), s.y(), s.z());
}
result_type
operator()(const Point_3& p, const Point_3& q,
const Point_3& r, const Vector_3& n) const
{
return enum_cast<Angle>(orientation(p,q,r,r+n));
}
};
template <typename K>

View File

@ -112,6 +112,13 @@ namespace HomogeneousKernelFunctors {
const Point_3& r, const Point_3& s) const
{ return enum_cast<Angle>(CGAL_NTS sign(c(q,p) * c(s,r))); }
// FIXME: scalar product
result_type
operator()(const Point_3& p, const Point_3& q,
const Point_3& r, const Vector_3& n) const
{
return enum_cast<Angle>(orientation(p,q,r,r+n));
}
};

View File

@ -205,11 +205,20 @@ and <code>src/</code> directories).
<h3>2D and 3D Linear Geometry Kernel</h3>
<ul>
<li><b>Breaking change</b>: The function <code>compare_slopes()</code> was renamed <code>compare_slope</code>.
</li>
<li>Added a 2D and 3D weighted point class and predicates and constructions.
</li>
<li>
Add functions <code>l_infinity_distance()</code> for 2D and 3D.
</li>
<li>Add a new functor in CGAL Kernel concept to compare the slope of two 3D segments.
All models of the Kernel concept now provide the functor <code>Compare_slope_3</code>,
and the free function <code>compare_slope()</code> is available.
</li>
<li>Add an operator in CGAL Kernel concept <code>Angle_3</code> to qualify the angle
between the normal of the triangle given by three points, and a vector.
</li>
</ul>
<h3>3D Convex Hull</h3>

View File

@ -38,7 +38,15 @@ const CGAL::Point_2<Kernel>& r,
const CGAL::Point_2<Kernel>& s);
/*!
returns \ref CGAL::OBTUSE, \ref CGAL::RIGHT or \ref CGAL::ACUTE depending
on the angle formed by the two vectors `u` and `v`.
*/
template <typename Kernel>
Angle angle(const CGAL::Vector_3<Kernel>& u,
const CGAL::Vector_3<Kernel>& v);
/*!
returns `CGAL::OBTUSE`, `CGAL::RIGHT` or `CGAL::ACUTE` depending
on the angle formed by the three points `p`, `q`, `r` (`q` being the vertex of
the angle).
@ -48,6 +56,29 @@ Angle angle(const CGAL::Point_3<Kernel>& p,
const CGAL::Point_3<Kernel>& q,
const CGAL::Point_3<Kernel>& r);
/*!
returns \ref CGAL::OBTUSE, \ref CGAL::RIGHT or \ref CGAL::ACUTE depending
on the angle formed by the two vectors `pq`, `rs`. The returned value is
the same as `angle(q - p, s - r)`.
*/
template<typename Kernel >
Angle angle(const CGAL::Point_3<Kernel>&p,
const CGAL::Point_3<Kernel>&q,
const CGAL::Point_3<Kernel>&r,
const CGAL::Point_3<Kernel>&s);
/*!
returns \ref CGAL::OBTUSE, \ref CGAL::RIGHT or \ref CGAL::ACUTE depending
on the angle formed by the normal of the triangle `pqr` and the vector `v`.
*/
template<typename Kernel >
Angle angle(const CGAL::Point_3<Kernel>&p,
const CGAL::Point_3<Kernel>&q,
const CGAL::Point_3<Kernel>&r,
const CGAL::Vector_3<Kernel>&v);
/*!
returns an approximation of the signed dihedral angle in the tetrahedron `pqrs` of edge `pq`.
@ -61,6 +92,7 @@ Kernel::FT approximate_dihedral_angle(const CGAL::Point_3<Kernel>& p,
const CGAL::Point_3<Kernel>& r,
const CGAL::Point_3<Kernel>& s);
/// @}
@ -793,16 +825,28 @@ const CGAL::Point_3<Kernel>& t);
compares the slopes of the lines `l1` and `l2`
*/
template <typename Kernel>
Comparison_result compare_slopes(const CGAL::Line_2<Kernel> &l1,
Comparison_result compare_slope(const CGAL::Line_2<Kernel> &l1,
const CGAL::Line_2<Kernel> &l2);
/*!
compares the slopes of the segments `s1` and `s2`
compares the slopes of the segments `s1` and `s2`,
where the slope is the variation of the `y`-coordinate
from the left to the right endpoint of the segments.
*/
template <typename Kernel>
Comparison_result compare_slopes(const CGAL::Segment_2<Kernel> &s1,
Comparison_result compare_slope(const CGAL::Segment_2<Kernel> &s1,
const CGAL::Segment_2<Kernel> &s2);
/*!
compares the slopes of the segments `(p,q)` and `(r,s)`,
where the slope is the variation of the `z`-coordinate from the first
to the second point of the segment divided by the length of the segment.
*/
template <typename Kernel>
Comparison_result compare_slope(const CGAL::Point_3<Kernel> &p,
const CGAL::Point_3<Kernel> &q,
const CGAL::Point_3<Kernel> &r,
const CGAL::Point_3<Kernel> &s);
/// @}
/// \defgroup compare_squared_distance_grp CGAL::compare_squared_distance()

View File

@ -62,20 +62,20 @@ public:
/// @{
/*!
returns \ref CGAL::OBTUSE, \ref CGAL::RIGHT or \ref CGAL::ACUTE depending
on the angle formed by the two vectors `u` and `v`.
*/
Angle operator()(const Kernel::Vector_3&u,
const Kernel::Vector_3&v);
returns \ref CGAL::OBTUSE, \ref CGAL::RIGHT or \ref CGAL::ACUTE depending
on the angle formed by the two vectors `u` and `v`.
*/
Angle operator()(const Kernel::Vector_3&u,
const Kernel::Vector_3&v);
/*!
returns \ref CGAL::OBTUSE, \ref CGAL::RIGHT or \ref CGAL::ACUTE depending
on the angle formed by the three points `p`, `q`, `r` (`q` being the vertex of
returns \ref CGAL::OBTUSE, \ref CGAL::RIGHT or \ref CGAL::ACUTE depending
on the angle formed by the three points `p`, `q`, `r` (`q` being the vertex of
the angle). The returned value is the same as `operator()(p - q, r - q)`.
*/
Angle operator()(const Kernel::Point_3&p,
const Kernel::Point_3&q,
const Kernel::Point_3&r);
*/
Angle operator()(const Kernel::Point_3&p,
const Kernel::Point_3&q,
const Kernel::Point_3&r);
/*!
returns \ref CGAL::OBTUSE, \ref CGAL::RIGHT or \ref CGAL::ACUTE depending
@ -85,7 +85,16 @@ public:
Angle operator()(const Kernel::Point_3&p,
const Kernel::Point_3&q,
const Kernel::Point_3&r,
const Kernel::Point_3&s);
const Kernel::Point_3&s);
/*!
returns \ref CGAL::OBTUSE, \ref CGAL::RIGHT or \ref CGAL::ACUTE depending
on the angle formed by the normal of the triangle `pqr` and the vector `v`.
*/
Angle operator()(const Kernel::Point_3&p,
const Kernel::Point_3&q,
const Kernel::Point_3&r,
const Kernel::Vector_3&v);
/// @}
}; /* end Kernel::Angle_3 */
@ -991,7 +1000,9 @@ public:
const Kernel::Line_2& l2);
/*!
compares the slopes of the segments `s1` and `s2`
compares the slopes of the segments `s1` and `s2`,
where the slope is the variation of the `y`-coordinate
from the left to the right endpoint of the segments.
*/
Comparison_result operator()(const Kernel::Segment_2& s1,
const Kernel::Segment_2& s2);
@ -1000,6 +1011,42 @@ public:
}; /* end Kernel::CompareSlope_2 */
/*!
\ingroup PkgKernel23ConceptsFunctionObjects
\cgalConcept
\cgalRefines `AdaptableFunctor` (with two arguments)
\sa `compare_slopes_grp`
*/
class CompareSlope_3 {
public:
/// \name Operations
/// A model of this concept must provide:
/// @{
/*!
compares the slopes of the segments `(p,q)` and `(r,s)`,
where the slope is the variation of the `z`-coordinate
from the first to the second point of the segment divided
by the length of the segment.
*/
Comparison_result operator()(const Kernel::Point_3& p,
const Kernel::Point_3& q,
const Kernel::Point_3& r,
const Kernel::Point_3& s);
/// @}
}; /* end Kernel::CompareSlope_3 */
/*!
\ingroup PkgKernel23ConceptsFunctionObjects
\cgalConcept

View File

@ -1433,6 +1433,11 @@ public:
*/
typedef unspecified_type Compare_xyz_3;
/*!
a model of `Kernel::CompareSlope_3`
*/
typedef unspecified_type Compare_slope_3;
/*!
a model of `Kernel::CompareSquaredDistance_3`
*/

View File

@ -276,6 +276,7 @@
- `Kernel::CompareDistance_2`
- `Kernel::CompareDistance_3`
- `Kernel::CompareSlope_2`
- `Kernel::CompareSlope_3`
- `Kernel::ComparePowerDistance_2`
- `Kernel::ComparePowerDistance_3`
- `Kernel::CompareSquaredDistance_2`

View File

@ -752,6 +752,36 @@ namespace CommonKernelFunctors {
}
};
template <typename K>
class Compare_slope_3
{
typedef typename K::FT FT;
typedef typename K::Point_3 Point_3;
public:
typedef typename K::Comparison_result result_type;
result_type operator()(const Point_3& p, const Point_3& q, const Point_3& r, const Point_3& s) const
{
Comparison_result sign_pq = compare(q.z(),p.z());
Comparison_result sign_rs = compare(s.z(),r.z());
if(sign_pq != sign_rs){
return compare(static_cast<int>(sign_pq), static_cast<int>(sign_rs));
}
if((sign_pq == EQUAL) && (sign_rs == EQUAL)){
return EQUAL;
}
CGAL_assertion( (sign_pq == sign_rs) && (sign_pq != EQUAL) );
Comparison_result res = CGAL::compare(square(p.z() - q.z()) * (square(r.x()-s.x())+square(r.y()-s.y())),
square(r.z() - s.z()) * (square(p.x()-q.x())+square(p.y()-q.y())));
return (sign_pq == SMALLER) ? opposite(res) : res;
}
};
template <typename K>
class Compare_squared_distance_2
{

View File

@ -342,18 +342,41 @@ compare_lexicographically_xy(const Point_2<K> &p,
template < class K >
inline
typename K::Comparison_result
compare_slopes(const Line_2<K> &l1, const Line_2<K> &l2)
compare_slope(const Line_2<K> &l1, const Line_2<K> &l2)
{
return internal::compare_slopes(l1, l2, K());
return internal::compare_slope(l1, l2, K());
}
template < class K >
inline
typename K::Comparison_result
compare_slope(const Segment_2<K> &s1, const Segment_2<K> &s2)
{
return internal::compare_slope(s1, s2, K());
}
#ifndef CGAL_NO_DEPRECATED_CODE
// kept for backward compatibility
template < class K >
CGAL_DEPRECATED_MSG("This function is deprecated. CGAL::compare_slope() should be used instead")
inline
typename K::Comparison_result
compare_slopes(const Line_2<K> &l1, const Line_2<K> &l2)
{
return internal::compare_slope(l1, l2, K());
}
// kept for backward compatibility
template < class K >
CGAL_DEPRECATED_MSG("This function is deprecated. CGAL::compare_slope() should be used instead")
inline
typename K::Comparison_result
compare_slopes(const Segment_2<K> &s1, const Segment_2<K> &s2)
{
return internal::compare_slopes(s1, s2, K());
return internal::compare_slope(s1, s2, K());
}
#endif
template < class K >
inline

View File

@ -59,6 +59,15 @@ angle(const Point_3<K> &p, const Point_3<K> &q,
return internal::angle(p, q, r, s, K());
}
template <typename K>
inline
Angle
angle(const Point_3<K> &p, const Point_3<K> &q,
const Point_3<K> &r, const Vector_3<K> &v)
{
return internal::angle(p, q, r, v, K());
}
template < class K >
inline
typename K::FT
@ -354,6 +363,17 @@ compare_power_distance(const Point_3<K> &r,
return internal::compare_power_distance(r, p, q, K());
}
template < class K >
inline
typename K::Comparison_result
compare_slope(const Point_3<K> &p,
const Point_3<K> &q,
const Point_3<K> &r,
const Point_3<K> &s)
{
return internal::compare_slope(p, q, r, s, K());
}
template < class K >
inline
typename K::Comparison_result

View File

@ -370,8 +370,8 @@ compare_signed_distance_to_line(const typename K::Line_2& l,
template < class K >
inline
typename K::Comparison_result
compare_slopes(const typename K::Line_2 &l1,
const typename K::Line_2 &l2, const K& k)
compare_slope(const typename K::Line_2 &l1,
const typename K::Line_2 &l2, const K& k)
{
return k.compare_slope_2_object()(l1, l2);
}
@ -379,8 +379,8 @@ compare_slopes(const typename K::Line_2 &l1,
template < class K >
inline
typename K::Comparison_result
compare_slopes(const typename K::Segment_2 &s1,
const typename K::Segment_2 &s2, const K& k)
compare_slope(const typename K::Segment_2 &s1,
const typename K::Segment_2 &s2, const K& k)
{
return k.compare_slope_2_object()(s1, s2);
}

View File

@ -70,6 +70,18 @@ angle(const typename K::Point_3 &p,
return k.angle_3_object()(p, q, r, s);
}
template <typename K>
inline
typename K::Angle
angle(const typename K::Point_3 &p,
const typename K::Point_3 &q,
const typename K::Point_3 &r,
const typename K::Vector_3 &v,
const K &k)
{
return k.angle_3_object()(p, q, r, v);
}
template < class K >
inline
typename K::FT
@ -413,6 +425,18 @@ compare_power_distance(const typename K::Point_3 &r,
return k.compare_power_distance_3_object()(r, p, q);
}
template < class K >
inline
typename K::Comparison_result
compare_slope(const typename K::Point_3 &p,
const typename K::Point_3 &q,
const typename K::Point_3 &r,
const typename K::Point_3 &s,
const K& k)
{
return k.compare_slope_3_object()(p, q, r, s);
}
template < class K >
inline
typename K::Comparison_result

View File

@ -126,6 +126,8 @@ CGAL_Kernel_pred_RT(Compare_power_distance_3,
compare_power_distance_3_object)
CGAL_Kernel_pred(Compare_slope_2,
compare_slope_2_object)
CGAL_Kernel_pred(Compare_slope_3,
compare_slope_3_object)
CGAL_Kernel_pred(Compare_squared_distance_2,
compare_squared_distance_2_object)
CGAL_Kernel_pred(Compare_squared_distance_3,

View File

@ -33,6 +33,7 @@ _test_angle(const R&)
typedef CGAL::Point_3<R> Point_3;
typedef CGAL::Vector_2<R> Vector_2;
typedef CGAL::Vector_3<R> Vector_3;
Point_2 p(RT(2),RT(1));
Point_2 q(RT(5),RT(4));
@ -67,6 +68,12 @@ _test_angle(const R&)
assert( CGAL::angle( org3 - sz, sz - sy) == CGAL::OBTUSE );
assert( CGAL::angle( org3 - sx, sy - sx) == CGAL::ACUTE );
Vector_3 vz(RT0, RT0, RT1);
Vector_3 vcoplanar(RT1, RT1, RT0);
Vector_3 vmz(RT0, RT0, -RT1);
assert( CGAL::angle( org3, sx, sy, vz) == CGAL::ACUTE );
assert( CGAL::angle( org3, sx, sy, vcoplanar) == CGAL::RIGHT );
assert( CGAL::angle( org3, sx, sy, vmz) == CGAL::OBTUSE );
return true;
}

View File

@ -93,36 +93,36 @@ _test_fct_line_2(const R& )
Line_2 l2(p3, p2);
Line_2 l3(p4, p6);
assert( CGAL::compare_slopes(l1,l2) == CGAL::EQUAL );
assert( CGAL::compare_slopes(l1,l3) == CGAL::EQUAL );
assert( CGAL::compare_slopes(l3,l1) == CGAL::EQUAL );
assert( CGAL::compare_slope(l1,l2) == CGAL::EQUAL );
assert( CGAL::compare_slope(l1,l3) == CGAL::EQUAL );
assert( CGAL::compare_slope(l3,l1) == CGAL::EQUAL );
std::cout <<'.';
// horizontal lines
Line_2 l4(p3, p8);
Line_2 l5(p4, p9);
assert( CGAL::compare_slopes(l4, l5) == CGAL::EQUAL );
assert( CGAL::compare_slopes(l3, l4) == CGAL::LARGER );
assert( CGAL::compare_slopes(l4, l3) == CGAL::SMALLER );
assert( CGAL::compare_slope(l4, l5) == CGAL::EQUAL );
assert( CGAL::compare_slope(l3, l4) == CGAL::LARGER );
assert( CGAL::compare_slope(l4, l3) == CGAL::SMALLER );
std::cout <<'.';
// parallel lines
Line_2 l5a(p6, p7);
Line_2 l5b(p11, p1);
assert( CGAL::compare_slopes(l5a, l5b) == CGAL::EQUAL );
assert( CGAL::compare_slope(l5a, l5b) == CGAL::EQUAL );
assert( CGAL::parallel(l5a, l5b) );
// two positive slopes
Line_2 l6(p2, p4);
Line_2 l7(p2, p6);
Line_2 l8(p7, p10);
assert( CGAL::compare_slopes(l6, l6) == CGAL::EQUAL );
assert( CGAL::compare_slopes(l6, l7) == CGAL::LARGER );
assert( CGAL::compare_slopes(l7, l6) == CGAL::SMALLER );
assert( CGAL::compare_slopes(l6, l8) == CGAL::LARGER );
assert( CGAL::compare_slopes(l8, l6) == CGAL::SMALLER );
assert( CGAL::compare_slope(l6, l6) == CGAL::EQUAL );
assert( CGAL::compare_slope(l6, l7) == CGAL::LARGER );
assert( CGAL::compare_slope(l7, l6) == CGAL::SMALLER );
assert( CGAL::compare_slope(l6, l8) == CGAL::LARGER );
assert( CGAL::compare_slope(l8, l6) == CGAL::SMALLER );
assert( CGAL::parallel(l6, l6) );
assert( ! CGAL::parallel(l6, l7) );
assert( ! CGAL::parallel(l7, l6) );
@ -130,14 +130,14 @@ _test_fct_line_2(const R& )
assert( ! CGAL::parallel(l8, l6) );
// vertical and positive slope
assert( CGAL::compare_slopes(l1, l6) == CGAL::LARGER );
assert( CGAL::compare_slopes(l6, l1) == CGAL::SMALLER );
assert( CGAL::compare_slope(l1, l6) == CGAL::LARGER );
assert( CGAL::compare_slope(l6, l1) == CGAL::SMALLER );
assert( ! CGAL::parallel(l1, l6) );
assert( ! CGAL::parallel(l6, l1) );
// horizontal and positive slope
assert( CGAL::compare_slopes(l5, l6) == CGAL::SMALLER );
assert( CGAL::compare_slopes(l6, l5) == CGAL::LARGER );
assert( CGAL::compare_slope(l5, l6) == CGAL::SMALLER );
assert( CGAL::compare_slope(l6, l5) == CGAL::LARGER );
assert( ! CGAL::parallel(l5, l6) );
assert( ! CGAL::parallel(l6, l5) );
@ -148,28 +148,28 @@ _test_fct_line_2(const R& )
Line_2 l10(p9, p8);
Line_2 l11(p5, p3);
assert( CGAL::compare_slopes(l9, l10) == CGAL::SMALLER );
assert( CGAL::compare_slopes(l10, l9) == CGAL::LARGER );
assert( CGAL::compare_slopes(l11, l10) == CGAL::LARGER );
assert( CGAL::compare_slope(l9, l10) == CGAL::SMALLER );
assert( CGAL::compare_slope(l10, l9) == CGAL::LARGER );
assert( CGAL::compare_slope(l11, l10) == CGAL::LARGER );
assert( ! CGAL::parallel(l9, l10) );
assert( ! CGAL::parallel(l10, l9) );
assert( ! CGAL::parallel(l11, l10) );
// vertical and negative slope
assert( CGAL::compare_slopes(l2, l9) == CGAL::LARGER );
assert( CGAL::compare_slopes(l9, l2) == CGAL::SMALLER );
assert( CGAL::compare_slope(l2, l9) == CGAL::LARGER );
assert( CGAL::compare_slope(l9, l2) == CGAL::SMALLER );
assert( ! CGAL::parallel(l2, l9) );
assert( ! CGAL::parallel(l9, l2) );
// horizontal and negative slope
assert( CGAL::compare_slopes(l5, l9) == CGAL::LARGER );
assert( CGAL::compare_slopes(l9, l5) == CGAL::SMALLER );
assert( CGAL::compare_slope(l5, l9) == CGAL::LARGER );
assert( CGAL::compare_slope(l9, l5) == CGAL::SMALLER );
std::cout <<'.';
// positive and negative slope
assert( CGAL::compare_slopes(l6, l9) == CGAL::LARGER );
assert( CGAL::compare_slopes(l9, l7) == CGAL::SMALLER );
assert( CGAL::compare_slope(l6, l9) == CGAL::LARGER );
assert( CGAL::compare_slope(l9, l7) == CGAL::SMALLER );
assert( ! CGAL::parallel(l6, l9) );
assert( ! CGAL::parallel(l9, l7) );

View File

@ -233,6 +233,21 @@ _test_fct_point_3(const R& )
assert( CGAL::compare_squared_radius(p0, p1, p2, p3, four) == CGAL::EQUAL );
}
{
CGAL::Point_3<R> p0(0,0,1), p1(0,0,2), p2(1,0,1), p3(1,0,2), p4(1,0,3);
assert( CGAL::compare_slope(p0, p2, p1, p3) == CGAL::EQUAL );
assert( CGAL::compare_slope(p0, p2, p0, p3) == CGAL::SMALLER );
assert( CGAL::compare_slope(p0, p2, p1, p2) == CGAL::LARGER );
assert( CGAL::compare_slope(p0, p3, p0, p2) == CGAL::LARGER );
assert( CGAL::compare_slope(p0, p3, p0, p4) == CGAL::SMALLER );
assert( CGAL::compare_slope(p0, p3, p1, p2) == CGAL::LARGER );
assert( CGAL::compare_slope(p1, p2, p0, p2) == CGAL::SMALLER );
assert( CGAL::compare_slope(p1, p2, p0, p3) == CGAL::SMALLER );
assert( CGAL::compare_slope(p1, p2, p4, p0) == CGAL::LARGER );
}
assert(CGAL::l_infinity_distance(p1,p2) == FT(11));
assert(CGAL::l_infinity_distance(p1,p5) == FT(6));
// More tests, that require sqrt().

View File

@ -51,43 +51,43 @@ _test_fct_segment_2(const R& )
Segment_2 l2(p3, p2);
Segment_2 l3(p4, p6);
assert( CGAL::compare_slopes(l1,l2) == CGAL::EQUAL );
assert( CGAL::compare_slopes(l1,l3) == CGAL::EQUAL );
assert( CGAL::compare_slopes(l3,l1) == CGAL::EQUAL );
assert( CGAL::compare_slope(l1,l2) == CGAL::EQUAL );
assert( CGAL::compare_slope(l1,l3) == CGAL::EQUAL );
assert( CGAL::compare_slope(l3,l1) == CGAL::EQUAL );
std::cout <<'.';
// horizontal segments
Segment_2 l4(p3, p8);
Segment_2 l5(p4, p9);
assert( CGAL::compare_slopes(l4, l5) == CGAL::EQUAL );
assert( CGAL::compare_slopes(l3, l4) == CGAL::LARGER );
assert( CGAL::compare_slopes(l4, l3) == CGAL::SMALLER );
assert( CGAL::compare_slope(l4, l5) == CGAL::EQUAL );
assert( CGAL::compare_slope(l3, l4) == CGAL::LARGER );
assert( CGAL::compare_slope(l4, l3) == CGAL::SMALLER );
std::cout <<'.';
// parallel segments
Segment_2 l5a(p6, p7);
Segment_2 l5b(p11, p1);
assert( CGAL::compare_slopes(l5a, l5b) == CGAL::EQUAL );
assert( CGAL::compare_slope(l5a, l5b) == CGAL::EQUAL );
// two positive slopes
// two positive slope
Segment_2 l6(p2, p4);
Segment_2 l7(p2, p6);
Segment_2 l8(p7, p10);
assert( CGAL::compare_slopes(l6, l6) == CGAL::EQUAL );
assert( CGAL::compare_slopes(l6, l7) == CGAL::LARGER );
assert( CGAL::compare_slopes(l7, l6) == CGAL::SMALLER );
assert( CGAL::compare_slopes(l6, l8) == CGAL::LARGER );
assert( CGAL::compare_slopes(l8, l6) == CGAL::SMALLER );
assert( CGAL::compare_slope(l6, l6) == CGAL::EQUAL );
assert( CGAL::compare_slope(l6, l7) == CGAL::LARGER );
assert( CGAL::compare_slope(l7, l6) == CGAL::SMALLER );
assert( CGAL::compare_slope(l6, l8) == CGAL::LARGER );
assert( CGAL::compare_slope(l8, l6) == CGAL::SMALLER );
// vertical and positive slope
assert( CGAL::compare_slopes(l1, l6) == CGAL::LARGER );
assert( CGAL::compare_slopes(l6, l1) == CGAL::SMALLER );
assert( CGAL::compare_slope(l1, l6) == CGAL::LARGER );
assert( CGAL::compare_slope(l6, l1) == CGAL::SMALLER );
// horizontal and positive slope
assert( CGAL::compare_slopes(l5, l6) == CGAL::SMALLER );
assert( CGAL::compare_slopes(l6, l5) == CGAL::LARGER );
assert( CGAL::compare_slope(l5, l6) == CGAL::SMALLER );
assert( CGAL::compare_slope(l6, l5) == CGAL::LARGER );
@ -98,23 +98,23 @@ _test_fct_segment_2(const R& )
Segment_2 l10(p9, p8);
Segment_2 l11(p5, p3);
assert( CGAL::compare_slopes(l9, l10) == CGAL::SMALLER );
assert( CGAL::compare_slopes(l10, l9) == CGAL::LARGER );
assert( CGAL::compare_slopes(l11, l10) == CGAL::LARGER );
assert( CGAL::compare_slope(l9, l10) == CGAL::SMALLER );
assert( CGAL::compare_slope(l10, l9) == CGAL::LARGER );
assert( CGAL::compare_slope(l11, l10) == CGAL::LARGER );
// vertical and negative slope
assert( CGAL::compare_slopes(l2, l9) == CGAL::LARGER );
assert( CGAL::compare_slopes(l9, l2) == CGAL::SMALLER );
assert( CGAL::compare_slope(l2, l9) == CGAL::LARGER );
assert( CGAL::compare_slope(l9, l2) == CGAL::SMALLER );
// horizontal and negative slope
assert( CGAL::compare_slopes(l5, l9) == CGAL::LARGER );
assert( CGAL::compare_slopes(l9, l5) == CGAL::SMALLER );
assert( CGAL::compare_slope(l5, l9) == CGAL::LARGER );
assert( CGAL::compare_slope(l9, l5) == CGAL::SMALLER );
std::cout <<'.';
// positive and negative slope
assert( CGAL::compare_slopes(l6, l9) == CGAL::LARGER );
assert( CGAL::compare_slopes(l9, l7) == CGAL::SMALLER );
assert( CGAL::compare_slope(l6, l9) == CGAL::LARGER );
assert( CGAL::compare_slope(l9, l7) == CGAL::SMALLER );
std::cout << "done" << std::endl;
return true;

View File

@ -50,7 +50,7 @@ bool recursive_does_bound_a_volume(const TriangleMesh& tm,
typedef Side_of_triangle_mesh<TriangleMesh, Kernel, Vpm> Side_of_tm;
// first check that the orientation of the current cc is consistant with its
// parent cc containing it
bool new_is_parent_outward_oriented = internal::is_outward_oriented<Kernel>(
bool new_is_parent_outward_oriented = internal::is_outward_oriented(
xtrm_vertices[xtrm_cc_id], tm, parameters::vertex_point_map(vpm));
if (new_is_parent_outward_oriented==is_parent_outward_oriented)
return false;
@ -91,8 +91,8 @@ bool recursive_does_bound_a_volume(const TriangleMesh& tm,
for (std::size_t i=1;i<nb_candidates;++i)
{
std::size_t candidate = cc_inside[i];
if(get(vpm,xtrm_vertices[candidate]) <
get(vpm,xtrm_vertices[new_xtrm_cc_id])) new_xtrm_cc_id=candidate;
if(get(vpm,xtrm_vertices[candidate]).z() >
get(vpm,xtrm_vertices[new_xtrm_cc_id]).z()) new_xtrm_cc_id=candidate;
new_cc_handled.reset(candidate);
cc_handled.set(candidate);
}
@ -111,7 +111,7 @@ bool recursive_does_bound_a_volume(const TriangleMesh& tm,
candidate < cc_not_handled.npos;
candidate = cc_not_handled.find_next(candidate))
{
if(get(vpm,xtrm_vertices[candidate]) < get(vpm,xtrm_vertices[new_xtrm_cc_id]))
if(get(vpm,xtrm_vertices[candidate]).z() > get(vpm,xtrm_vertices[new_xtrm_cc_id]).z())
new_xtrm_cc_id = candidate;
}
@ -129,7 +129,7 @@ bool recursive_does_bound_a_volume(const TriangleMesh& tm,
*
* @tparam TriangleMesh a model of `MutableFaceGraph`, `HalfedgeListGraph` and `FaceListGraph`.
* If `TriangleMesh` has an internal property map for `CGAL::face_index_t`,
* as a named parameter, then it must initialized.
* as a named parameter, then it must be initialized.
* @tparam NamedParameters a sequence of \ref namedparameters
*
* @param tm a triangulated surface mesh
@ -182,7 +182,7 @@ bool does_bound_a_volume(const TriangleMesh& tm, const NamedParameters& np)
boost::dynamic_bitset<> cc_handled(nb_cc, 0);
// extract the less-xyz vertex of each connected component
// extract a vertex with max z coordinate for each connected component
std::vector<vertex_descriptor> xtrm_vertices(nb_cc, GT::null_vertex());
BOOST_FOREACH(vertex_descriptor vd, vertices(tm))
{
@ -190,18 +190,18 @@ bool does_bound_a_volume(const TriangleMesh& tm, const NamedParameters& np)
if (xtrm_vertices[cc_id]==GT::null_vertex())
xtrm_vertices[cc_id]=vd;
else
if (get(vpm, vd)<get(vpm,xtrm_vertices[cc_id]))
if (get(vpm, vd).z()>get(vpm,xtrm_vertices[cc_id]).z())
xtrm_vertices[cc_id]=vd;
}
//extract the less-xyz of all components
//extract a vertex with max z amongst all components
std::size_t xtrm_cc_id=0;
for(std::size_t id=1; id<nb_cc; ++id)
if (get(vpm, xtrm_vertices[id])<get(vpm,xtrm_vertices[xtrm_cc_id]))
if (get(vpm, xtrm_vertices[id]).z()>get(vpm,xtrm_vertices[xtrm_cc_id]).z())
xtrm_cc_id=id;
bool is_parent_outward_oriented =
!internal::is_outward_oriented<Kernel>(xtrm_vertices[xtrm_cc_id], tm, np);
!internal::is_outward_oriented(xtrm_vertices[xtrm_cc_id], tm, np);
return internal::recursive_does_bound_a_volume<Kernel>(tm, vpm, fid_map,
xtrm_vertices,
@ -433,7 +433,7 @@ boolean_operation( TriangleMesh& tm1,
*
* @tparam TriangleMesh a model of `MutableFaceGraph`, `HalfedgeListGraph` and `FaceListGraph`.
* If `TriangleMesh` has an internal property map for `CGAL::face_index_t`,
* as a named parameter, then it must initialized.
* as a named parameter, then it must be initialized.
*
* @tparam NamedParameters1 a sequence of \ref namedparameters
* @tparam NamedParameters2 a sequence of \ref namedparameters

View File

@ -29,6 +29,7 @@
#include <CGAL/Polygon_mesh_processing/compute_normal.h>
#include <CGAL/Polygon_mesh_processing/internal/named_function_params.h>
#include <CGAL/Polygon_mesh_processing/internal/named_params_helper.h>
#include <CGAL/Projection_traits_xy_3.h>
#include <CGAL/boost/graph/helpers.h>
#include <CGAL/boost/graph/iterator.h>
@ -40,37 +41,100 @@ namespace CGAL {
namespace Polygon_mesh_processing {
namespace internal{
template <class Less_xyz, class VPmap>
struct Compare_vertex_points_xyz_3{
Less_xyz less;
VPmap vpmap;
Compare_vertex_points_xyz_3(VPmap const& vpmap)
: vpmap(vpmap){}
template <class GT, class VPmap>
struct Compare_vertex_points_z_3
{
VPmap vpmap;
typename GT::Compare_z_3 compare_z;
Compare_vertex_points_z_3(VPmap const& vpmap, const GT& gt)
: vpmap(vpmap)
, compare_z(gt.compare_z_3_object())
{}
typedef bool result_type;
template <class vertex_descriptor>
bool operator()(vertex_descriptor v1, vertex_descriptor v2) const
{
return less(get(vpmap, v1), get(vpmap, v2));
return CGAL::SMALLER == compare_z(get(vpmap, v1), get(vpmap, v2));
}
};
template<typename Kernel, typename PM, typename NamedParameters>
bool is_outward_oriented(typename boost::graph_traits<PM>::vertex_descriptor vd,
const PM& pmesh,
template<typename PolygonMesh, typename NamedParameters>
bool is_outward_oriented(typename boost::graph_traits<PolygonMesh>::vertex_descriptor v_max,
const PolygonMesh& pmesh,
const NamedParameters& np)
{
const typename Kernel::Vector_3&
normal_v_min = compute_vertex_normal(vd, pmesh, np);
using boost::choose_param;
using boost::get_param;
return normal_v_min[0] < 0 || (
normal_v_min[0] == 0 && (
normal_v_min[1] < 0 ||
( normal_v_min[1]==0 && normal_v_min[2] < 0 )
)
);
//VertexPointMap
typedef typename GetVertexPointMap<PolygonMesh, NamedParameters>::const_type VPMap;
VPMap vpmap = choose_param(get_param(np, vertex_point),
get_const_property_map(vertex_point, pmesh));
//Kernel
typedef typename GetGeomTraits<PolygonMesh, NamedParameters>::type GT;
GT gt = choose_param(get_param(np, geom_traits), GT());
//among the incoming edges of `v_max`, find one edge `e` with the minimal slope
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
halfedge_descriptor min_slope_he = halfedge(v_max, pmesh);
CGAL_assertion(v_max == target(min_slope_he, pmesh));
typename GT::Compare_slope_3 compare_slope = gt.compare_slope_3_object();
BOOST_FOREACH(halfedge_descriptor he, halfedges_around_target(v_max, pmesh))
{
CGAL_assertion(v_max == target(min_slope_he, pmesh));
CGAL_assertion(v_max == target(he, pmesh));
if(CGAL::SMALLER == compare_slope(get(vpmap, source(he, pmesh)),
get(vpmap, v_max),
get(vpmap, source(min_slope_he, pmesh)),
get(vpmap, v_max)))
{
min_slope_he = he;
}
}
// We compute the orientations of the two triangles incident to the edge
// of `min_slope_he` projected in the xy-plane. We can conclude using
// the 2D orientation of the 3D triangle that is the top one along the z-axis
// in the neighborhood of `min_slope_he`.
Projection_traits_xy_3<GT> p_gt;
typename Projection_traits_xy_3<GT>::Orientation_2 orientation_2 = p_gt.orientation_2_object();
typename boost::property_traits<VPMap>::reference p1 = get(vpmap, source(min_slope_he, pmesh));
typename boost::property_traits<VPMap>::reference p2 = get(vpmap, target(min_slope_he, pmesh));
typename boost::property_traits<VPMap>::reference p3 = get(vpmap, target(next(min_slope_he, pmesh), pmesh));
typename boost::property_traits<VPMap>::reference p4 = get(vpmap, target(next(opposite(min_slope_he, pmesh), pmesh), pmesh));
Orientation p1p2p3_2d = orientation_2(p1, p2, p3);
Orientation p2p1p4_2d = orientation_2(p2, p1, p4);
CGAL_assertion( p1p2p3_2d!=COLLINEAR || p2p1p4_2d!=COLLINEAR ); // no self-intersection
if ( p1p2p3_2d == COLLINEAR)
return p2p1p4_2d == LEFT_TURN;
if (p2p1p4_2d ==COLLINEAR)
return p1p2p3_2d == LEFT_TURN;
// if the local dihedral angle is strictly larger that PI/2, we can conclude with any of two triangles
if (p1p2p3_2d==p2p1p4_2d)
return p1p2p3_2d == LEFT_TURN;
typename GT::Orientation_3 orientation_3 = gt.orientation_3_object();
CGAL_assertion( orientation_3(p1, p2, p3, p4) != COPLANAR ); // same side of min_slope_he and no self-intersection
// if p1p2p3_2d is left turn, then it must be the top face so that the orientation is outward oriented
if (p1p2p3_2d == LEFT_TURN)
return orientation_3(p1, p2, p3, p4) == NEGATIVE;
// same test with the other face
CGAL_assertion(p2p1p4_2d == LEFT_TURN);
return orientation_3(p2, p1, p4, p3) == NEGATIVE;
}
} // end of namespace internal
@ -109,6 +173,11 @@ bool is_outward_oriented(const PolygonMesh& pmesh,
CGAL_warning(CGAL::is_closed(pmesh));
CGAL_precondition(CGAL::is_valid(pmesh));
//check for empty pmesh
CGAL_warning(faces(pmesh).first != faces(pmesh).second);
if (faces(pmesh).first == faces(pmesh).second)
return true;
using boost::choose_param;
using boost::get_param;
@ -117,17 +186,19 @@ bool is_outward_oriented(const PolygonMesh& pmesh,
VPMap vpmap = choose_param(get_param(np, vertex_point),
get_const_property_map(vertex_point, pmesh));
//Kernel
typedef typename GetGeomTraits<PolygonMesh, NamedParameters>::type Kernel;
internal::Compare_vertex_points_xyz_3<typename Kernel::Less_xyz_3, VPMap >
less_xyz(vpmap);
typedef typename GetGeomTraits<PolygonMesh, NamedParameters>::type GT;
GT gt = choose_param(get_param(np, geom_traits), GT());
//find the vertex with maximal z coordinate
typename boost::graph_traits<PolygonMesh>::vertex_iterator vbegin, vend;
cpp11::tie(vbegin, vend) = vertices(pmesh);
typename boost::graph_traits<PolygonMesh>::vertex_iterator v_min
= std::min_element(vbegin, vend, less_xyz);
return internal::is_outward_oriented<Kernel>(*v_min, pmesh, np);
internal::Compare_vertex_points_z_3<GT, VPMap> less_z(vpmap, gt);
typename boost::graph_traits<PolygonMesh>::vertex_iterator v_max_it
= std::max_element(vbegin, vend, less_z);
typename boost::graph_traits<PolygonMesh>::vertex_descriptor v_max = *v_max_it;
return internal::is_outward_oriented(v_max, pmesh, np);
}
///\cond SKIP_IN_MANUAL

View File

@ -0,0 +1,12 @@
OFF
4 4 0
0 0 0
0.65000000000000002 -1.3 0.65000000000000002
0.10000000000000001 -1 1
2 -2 -0.5
3 2 1 0
3 1 3 0
3 3 2 0
3 3 1 2

View File

@ -0,0 +1,12 @@
OFF
4 4 0
0 0 0
0.65000000000000002 -1.3 0.65000000000000002
0.10000000000000001 -1 1
-0.33420955685098419 -0.59067608503190883 0.55877066363146466
3 2 1 0
3 1 3 0
3 3 2 0
3 3 1 2

View File

@ -0,0 +1,12 @@
OFF
4 4 0
0 1 0
1 0 0
0 0 0
0 0 1
3 0 1 2
3 2 3 0
3 1 3 2
3 0 3 1

View File

@ -0,0 +1,12 @@
OFF
4 4 0
0 0 1
0 1 0.8
-1 1 0.9
1 0 0.5
3 0 1 2
3 0 2 3
3 0 3 1
3 1 3 2

View File

@ -61,6 +61,12 @@ int main()
{
test_orient<Epic>("data/elephant.off");
test_orient<Epic>("data-coref/cube.off");
test_orient<Epic>("data/tetra1.off");
test_orient<Epic>("data/tetra2.off");
test_orient<Epic>("data/tetra3.off");
test_orient<Epic>("data/tetra4.off");
test_orient<Epic>("data-coref/cube.off");
test_orient<Epec>("data/elephant.off");
std::cerr << "All done." << std::endl;