mirror of https://github.com/CGAL/cgal
move CGAL::Mesh_3::internal::Polyline class to its own header
This commit is contained in:
parent
b804ec9394
commit
5b574bfaae
|
|
@ -46,7 +46,7 @@
|
||||||
#include <CGAL/iterator.h>
|
#include <CGAL/iterator.h>
|
||||||
#include <CGAL/number_utils.h>
|
#include <CGAL/number_utils.h>
|
||||||
#include <CGAL/Delaunay_triangulation_3.h>
|
#include <CGAL/Delaunay_triangulation_3.h>
|
||||||
#include <CGAL/Mesh_domain_with_polyline_features_3.h>
|
#include <CGAL/Mesh_3/internal/Polyline.h>
|
||||||
|
|
||||||
#include <CGAL/boost/iterator/transform_iterator.hpp>
|
#include <CGAL/boost/iterator/transform_iterator.hpp>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,561 @@
|
||||||
|
// Copyright (c) 2009-2010 INRIA Sophia-Antipolis (France).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
//
|
||||||
|
// $URL$
|
||||||
|
// $Id$
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Author(s) : Stéphane Tayeb, Laurent Rineau
|
||||||
|
//
|
||||||
|
//******************************************************************************
|
||||||
|
// File Description :
|
||||||
|
//
|
||||||
|
//******************************************************************************
|
||||||
|
|
||||||
|
#ifndef CGAL_MESH_3_INTERNAL_POLYLINE_H
|
||||||
|
#define CGAL_MESH_3_INTERNAL_POLYLINE_H
|
||||||
|
|
||||||
|
#include <CGAL/license/Mesh_3.h>
|
||||||
|
|
||||||
|
#include <CGAL/iterator.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
|
||||||
|
/// @cond DEVELOPERS
|
||||||
|
namespace Mesh_3 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
template <typename Kernel>
|
||||||
|
class Polyline
|
||||||
|
{
|
||||||
|
typedef typename Kernel::Point_3 Point_3;
|
||||||
|
typedef typename Kernel::Segment_3 Segment_3;
|
||||||
|
typedef typename Kernel::FT FT;
|
||||||
|
|
||||||
|
typedef std::vector<Point_3> Data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename Data::const_iterator const_iterator;
|
||||||
|
typedef std::pair<Point_3, const_iterator> Point_and_location;
|
||||||
|
|
||||||
|
Polyline() {}
|
||||||
|
~Polyline() {}
|
||||||
|
|
||||||
|
/// adds a point at the end of the polyline
|
||||||
|
void add_point(const Point_3& p)
|
||||||
|
{
|
||||||
|
if( points_.empty() || p != end_point() ) {
|
||||||
|
points_.push_back(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns the starting point of the polyline
|
||||||
|
const Point_3& start_point() const
|
||||||
|
{
|
||||||
|
CGAL_assertion( ! points_.empty() );
|
||||||
|
return points_.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns the ending point of the polyline
|
||||||
|
const Point_3& end_point() const
|
||||||
|
{
|
||||||
|
CGAL_assertion( ! points_.empty() );
|
||||||
|
return points_.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns `true` if the polyline is not degenerate
|
||||||
|
bool is_valid() const
|
||||||
|
{
|
||||||
|
return points_.size() > 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns `true` if polyline is a loop
|
||||||
|
bool is_loop() const
|
||||||
|
{
|
||||||
|
return start_point() == end_point();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator next(const_iterator it, Orientation orientation) const {
|
||||||
|
if(orientation == POSITIVE) {
|
||||||
|
CGAL_assertion(it != (points_.end() - 1));
|
||||||
|
if(it == (points_.end() - 2)) {
|
||||||
|
CGAL_assertion(is_loop());
|
||||||
|
it = points_.begin();
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CGAL_assertion(orientation == NEGATIVE);
|
||||||
|
CGAL_assertion(it != points_.begin());
|
||||||
|
if(it == (points_.begin() + 1)) {
|
||||||
|
CGAL_assertion(is_loop());
|
||||||
|
it = points_.end() - 1;
|
||||||
|
} else {
|
||||||
|
--it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_curve_segment_covered(CGAL::Orientation orientation,
|
||||||
|
const Point_3& c1, const Point_3& c2,
|
||||||
|
const FT sq_r1, const FT sq_r2,
|
||||||
|
const const_iterator cc1_it,
|
||||||
|
const const_iterator cc2_it) const
|
||||||
|
{
|
||||||
|
CGAL_assertion(orientation != CGAL::ZERO);
|
||||||
|
typename Kernel::Has_on_bounded_side_3 cover_pred =
|
||||||
|
Kernel().has_on_bounded_side_3_object();
|
||||||
|
|
||||||
|
typedef typename Kernel::Sphere_3 Sphere_3;
|
||||||
|
const Sphere_3 s1(c1, sq_r1);
|
||||||
|
const Sphere_3 s2(c2, sq_r2);
|
||||||
|
|
||||||
|
const_iterator c1_it = cc1_it;
|
||||||
|
const_iterator c2_it = cc2_it;
|
||||||
|
|
||||||
|
if(orientation == CGAL::NEGATIVE) {
|
||||||
|
++c1_it;
|
||||||
|
++c2_it;
|
||||||
|
CGAL_assertion(c1_it != points_.end());
|
||||||
|
CGAL_assertion(c2_it != points_.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(c1_it == c2_it) return cover_pred(s1, s2, c1, c2);
|
||||||
|
const_iterator next_it = this->next(c1_it, orientation);
|
||||||
|
|
||||||
|
if(!cover_pred(s1, s2, c1, *next_it)) return false;
|
||||||
|
|
||||||
|
for(const_iterator it = next_it; it != c2_it; /* in body */) {
|
||||||
|
next_it = this->next(it, orientation);
|
||||||
|
if(!cover_pred(s1, s2, *it, *next_it)) return false;
|
||||||
|
it = next_it;
|
||||||
|
} // end loop ]c1_it, c2_it[
|
||||||
|
|
||||||
|
return cover_pred(s1, s2, *c2_it, c2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_curve_segment_covered(CGAL::Orientation orientation,
|
||||||
|
const Point_3& c1, const Point_3& c2,
|
||||||
|
const FT sq_r1, const FT sq_r2) const
|
||||||
|
{
|
||||||
|
return is_curve_segment_covered(orientation,
|
||||||
|
c1, c2, sq_r1, sq_r2, locate(c1), locate(c2));
|
||||||
|
}
|
||||||
|
|
||||||
|
FT curve_segment_length(const Point_3& p, const Point_3 q,
|
||||||
|
CGAL::Orientation orientation) const
|
||||||
|
{
|
||||||
|
CGAL_assertion(orientation != CGAL::ZERO);
|
||||||
|
const_iterator p_it = locate(p);
|
||||||
|
const_iterator q_it = locate(q);
|
||||||
|
return curve_segment_length(p, q, orientation, p_it, q_it);
|
||||||
|
}
|
||||||
|
|
||||||
|
FT curve_segment_length(const Point_3& p, const Point_3 q,
|
||||||
|
CGAL::Orientation orientation,
|
||||||
|
const_iterator p_it,
|
||||||
|
const_iterator q_it) const
|
||||||
|
{
|
||||||
|
CGAL_assertion(orientation != CGAL::ZERO);
|
||||||
|
CGAL_assertion(p_it == locate(p));
|
||||||
|
CGAL_assertion(q_it == locate(q));
|
||||||
|
|
||||||
|
if(p_it == q_it) {
|
||||||
|
const CGAL::Comparison_result cmp = compare_distance(*p_it,p,q);
|
||||||
|
if( (cmp != LARGER && orientation == POSITIVE) ||
|
||||||
|
(cmp != SMALLER && orientation == NEGATIVE) )
|
||||||
|
{
|
||||||
|
// If the orientation of `p` and `q` on the segment is compatible
|
||||||
|
// with `orientation`, then return the distance between the two
|
||||||
|
// points.
|
||||||
|
return distance(p, q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(orientation == CGAL::NEGATIVE) {
|
||||||
|
++p_it;
|
||||||
|
++q_it;
|
||||||
|
CGAL_assertion(p_it != points_.end());
|
||||||
|
CGAL_assertion(q_it != points_.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator next_it = this->next(p_it, orientation);
|
||||||
|
FT result = distance(p, *next_it);
|
||||||
|
for(const_iterator it = next_it; it != q_it; /* in body */) {
|
||||||
|
next_it = this->next(it, orientation);
|
||||||
|
result += distance(*it, *next_it);
|
||||||
|
it = next_it;
|
||||||
|
} // end loop ]p_it, q_it[
|
||||||
|
result += distance(*q_it, q);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// returns the angle at the first point.
|
||||||
|
/// \pre The polyline must be a loop.
|
||||||
|
Angle angle_at_first_point() const {
|
||||||
|
CGAL_precondition(is_loop());
|
||||||
|
const Point_3& first = points_.front();
|
||||||
|
const Point_3& next_p = points_[1];
|
||||||
|
const Point_3& prev = points_[points_.size() - 2];
|
||||||
|
return angle(prev, first, next_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns the length of the polyline
|
||||||
|
FT length() const
|
||||||
|
{
|
||||||
|
if(length_ < 0.)
|
||||||
|
{
|
||||||
|
FT result(0);
|
||||||
|
const_iterator it = points_.begin();
|
||||||
|
const_iterator previous = it++;
|
||||||
|
|
||||||
|
for(const_iterator end = points_.end(); it != end; ++it, ++previous) {
|
||||||
|
result += distance(*previous, *it);
|
||||||
|
}
|
||||||
|
length_ = result;
|
||||||
|
}
|
||||||
|
return length_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns the signed geodesic distance between `p` and `q`.
|
||||||
|
FT signed_geodesic_distance(const Point_3& p, const Point_3& q) const
|
||||||
|
{
|
||||||
|
// Locate p & q on polyline
|
||||||
|
const_iterator pit = locate(p);
|
||||||
|
const_iterator qit = locate(q,false);
|
||||||
|
|
||||||
|
return signed_geodesic_distance(p, q, pit, qit);
|
||||||
|
}
|
||||||
|
|
||||||
|
FT signed_geodesic_distance(const Point_3& p, const Point_3& q,
|
||||||
|
const_iterator pit, const_iterator qit) const
|
||||||
|
{
|
||||||
|
CGAL_assertion(pit == locate(p));
|
||||||
|
CGAL_assertion(qit == locate(q, false));
|
||||||
|
|
||||||
|
// If p and q are in the same segment of the polyline
|
||||||
|
if ( pit == qit )
|
||||||
|
{
|
||||||
|
FT result = distance(p,q);
|
||||||
|
|
||||||
|
// Find the closest point to *pit
|
||||||
|
if ( compare_distance(*pit,p,q) != CGAL::LARGER )
|
||||||
|
{ return result; }
|
||||||
|
else
|
||||||
|
{ return -result; }
|
||||||
|
}
|
||||||
|
if(is_loop())
|
||||||
|
{
|
||||||
|
FT positive_distance, negative_distance;
|
||||||
|
if(pit <= qit)
|
||||||
|
{
|
||||||
|
positive_distance = curve_segment_length(p, q, CGAL::POSITIVE, pit, qit);
|
||||||
|
negative_distance = length() - positive_distance;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
negative_distance = curve_segment_length(q, p, CGAL::POSITIVE, qit, pit);
|
||||||
|
positive_distance = length() - negative_distance;
|
||||||
|
}
|
||||||
|
return (positive_distance < negative_distance) ? positive_distance : (-negative_distance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (pit <= qit)
|
||||||
|
? curve_segment_length(p, q, CGAL::POSITIVE, pit, qit)
|
||||||
|
: ( - curve_segment_length(p, q, CGAL::NEGATIVE, pit, qit) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator previous_segment_source(const_iterator it) const
|
||||||
|
{
|
||||||
|
CGAL_assertion(it != points_.end());
|
||||||
|
if(it == first_segment_source())
|
||||||
|
{
|
||||||
|
CGAL_assertion(is_loop());
|
||||||
|
it = last_segment_source();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
--it;
|
||||||
|
}
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator next_segment_source(const_iterator it) const
|
||||||
|
{
|
||||||
|
CGAL_assertion(it != points_.end());
|
||||||
|
if(it == last_segment_source())
|
||||||
|
{
|
||||||
|
if(is_loop())
|
||||||
|
return first_segment_source();
|
||||||
|
else
|
||||||
|
return points_.end();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++it;
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns a point at geodesic distance `distance` from p along the
|
||||||
|
/// polyline. The polyline is oriented from starting point to end point.
|
||||||
|
/// The distance could be negative.
|
||||||
|
Point_3 point_at(const Point_3& start_pt, FT distance) const
|
||||||
|
{
|
||||||
|
return point_at(start_pt, distance, locate(start_pt)).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns a point at geodesic distance `distance` from `start_pt` along the
|
||||||
|
/// polyline. The polyline is oriented from starting point to end point.
|
||||||
|
/// The distance could be negative.
|
||||||
|
Point_and_location point_at(const Point_3& start_pt,
|
||||||
|
FT distance,
|
||||||
|
const_iterator start_it) const
|
||||||
|
{
|
||||||
|
CGAL_assertion(start_it == locate(start_pt));
|
||||||
|
|
||||||
|
const Point_3& start_it_pt = *start_it;
|
||||||
|
const_iterator start_it_locate_pt
|
||||||
|
= (start_it == points_.begin()) ? start_it : std::prev(start_it);
|
||||||
|
|
||||||
|
distance += curve_segment_length(start_it_pt, start_pt, CGAL::POSITIVE,
|
||||||
|
start_it_locate_pt, start_it);
|
||||||
|
|
||||||
|
// If polyline is a loop, ensure that distance is given from start_it
|
||||||
|
if(is_loop())
|
||||||
|
{
|
||||||
|
if(distance < FT(0)) { distance += length(); }
|
||||||
|
else if(distance > length()) { distance -= length(); }
|
||||||
|
}
|
||||||
|
else if(distance < FT(0)) // If polyline is not a loop and distance is < 0, go backward
|
||||||
|
{
|
||||||
|
Point_3 new_start = start_pt;
|
||||||
|
while(distance < FT(0))
|
||||||
|
{
|
||||||
|
start_it = previous_segment_source(start_it);
|
||||||
|
distance += this->distance(new_start, *start_it);
|
||||||
|
new_start = *start_it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CGAL_assertion(distance >= FT(0));
|
||||||
|
CGAL_assertion(distance <= length());
|
||||||
|
|
||||||
|
// Initialize iterators
|
||||||
|
const_iterator pit = start_it; // start at start_it, and walk forward
|
||||||
|
const_iterator previous = pit++;
|
||||||
|
|
||||||
|
// Iterate to find which segment contains the point we want to construct
|
||||||
|
FT segment_length = this->distance(*previous, *pit);
|
||||||
|
while(distance > segment_length)
|
||||||
|
{
|
||||||
|
distance -= segment_length;
|
||||||
|
|
||||||
|
// Increment iterators and update length
|
||||||
|
previous = next_segment_source(previous);
|
||||||
|
pit = next_segment_source(pit);
|
||||||
|
|
||||||
|
if(pit == points_.end())
|
||||||
|
{
|
||||||
|
CGAL_assertion(distance < this->distance(*previous, end_point()));
|
||||||
|
break; // return {*previous, previous}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
segment_length = this->distance(*previous, *pit);
|
||||||
|
}
|
||||||
|
|
||||||
|
// return point at distance from current segment source
|
||||||
|
using Vector_3 = typename Kernel::Vector_3;
|
||||||
|
auto vector = Kernel().construct_vector_3_object();
|
||||||
|
Vector_3 v = (pit != points_.end()) ? vector(*previous, *pit)
|
||||||
|
: vector(*previous, end_point());
|
||||||
|
|
||||||
|
return {(*previous) + (distance / CGAL::sqrt(v.squared_length())) * v,
|
||||||
|
previous};
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator locate_corner(const Point_3& p) const
|
||||||
|
{
|
||||||
|
const_iterator res = points_.end();
|
||||||
|
if(p == start_point())
|
||||||
|
res = points_.begin();
|
||||||
|
else if(p == end_point())
|
||||||
|
res = last_segment_source();
|
||||||
|
|
||||||
|
CGAL_assertion(res == locate(p));
|
||||||
|
CGAL_assertion(res != points_.end());
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator locate_point(const Point_3& p) const
|
||||||
|
{
|
||||||
|
return locate(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool are_ordered_along(const Point_3& p, const Point_3& q,
|
||||||
|
const_iterator pit, const_iterator qit) const
|
||||||
|
{
|
||||||
|
CGAL_precondition(!is_loop());
|
||||||
|
|
||||||
|
// Locate p & q on polyline
|
||||||
|
CGAL_assertion(pit == locate(p));
|
||||||
|
CGAL_assertion(qit == locate(q, true));
|
||||||
|
|
||||||
|
// Points are not located on the same segment
|
||||||
|
if ( pit != qit ) { return (pit <= qit); }
|
||||||
|
|
||||||
|
// pit == qit, then we have to sort p&q along (pit,pit+1)
|
||||||
|
return ( compare_distance(*pit,p,q) != CGAL::LARGER );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool are_ordered_along(const Point_3& p, const Point_3& q) const
|
||||||
|
{
|
||||||
|
return are_ordered_along(p, q, locate(p), locate(q, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const_iterator first_segment_source() const
|
||||||
|
{
|
||||||
|
CGAL_precondition(is_valid());
|
||||||
|
return points_.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator last_segment_source() const
|
||||||
|
{
|
||||||
|
CGAL_precondition(is_valid());
|
||||||
|
return (points_.end() - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns an iterator on the starting point of the segment of the
|
||||||
|
/// polyline which contains p
|
||||||
|
/// if end_point_first is true, then --end is returned instead of begin
|
||||||
|
/// if p is the starting point of a loop.
|
||||||
|
const_iterator locate(const Point_3& p, bool end_point_first=false) const
|
||||||
|
{
|
||||||
|
CGAL_precondition(is_valid());
|
||||||
|
|
||||||
|
// First look if p is one of the points of the polyline
|
||||||
|
const_iterator result = std::find(points_.begin(), points_.end(), p);
|
||||||
|
if ( result != points_.end() )
|
||||||
|
{
|
||||||
|
if ( result != points_.begin() )
|
||||||
|
{ return --result; }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Treat loops
|
||||||
|
if ( end_point_first && p == end_point() )
|
||||||
|
{ return last_segment_source(); }
|
||||||
|
else
|
||||||
|
{ return result; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CGAL_assertion(result == points_.end());
|
||||||
|
|
||||||
|
// Get result by projecting p on the polyline
|
||||||
|
const_iterator it = points_.begin();
|
||||||
|
const_iterator previous = it;
|
||||||
|
Segment_3 nearest_segment;
|
||||||
|
const_iterator nearest_vertex = it;
|
||||||
|
result = nearest_vertex;
|
||||||
|
bool nearest_is_a_segment = false;
|
||||||
|
|
||||||
|
while ( ++it != points_.end() )
|
||||||
|
{
|
||||||
|
Segment_3 seg (*previous, *it);
|
||||||
|
|
||||||
|
if(nearest_is_a_segment)
|
||||||
|
{
|
||||||
|
if(compare_distance(p, *it, nearest_segment) == CGAL::SMALLER)
|
||||||
|
{
|
||||||
|
nearest_vertex = it;
|
||||||
|
nearest_is_a_segment = false;
|
||||||
|
result = it;
|
||||||
|
if (possibly(angle(*previous, *it, p) == CGAL::ACUTE) &&
|
||||||
|
compare_distance(p, seg, *nearest_vertex) == CGAL::SMALLER)
|
||||||
|
{
|
||||||
|
nearest_segment = seg;
|
||||||
|
nearest_is_a_segment = true;
|
||||||
|
result = previous;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(compare_distance(p, seg, nearest_segment) == CGAL::SMALLER)
|
||||||
|
{
|
||||||
|
nearest_segment = seg;
|
||||||
|
result = previous;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(compare_distance(p, *it, *nearest_vertex) == CGAL::SMALLER)
|
||||||
|
{
|
||||||
|
nearest_vertex = it;
|
||||||
|
result = it;
|
||||||
|
}
|
||||||
|
if ((nearest_vertex != it ||
|
||||||
|
possibly(angle(*previous, *it, p) == CGAL::ACUTE)) &&
|
||||||
|
compare_distance(p, seg, *nearest_vertex) == CGAL::SMALLER)
|
||||||
|
{
|
||||||
|
nearest_segment = seg;
|
||||||
|
nearest_is_a_segment = true;
|
||||||
|
result = previous;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
previous = it;
|
||||||
|
} // end the while loop on the vertices of the polyline
|
||||||
|
|
||||||
|
if(result == points_.begin()) {
|
||||||
|
return (end_point_first && !nearest_is_a_segment) ? last_segment_source() : points_.begin();
|
||||||
|
} else {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FT distance(const Point_3& p, const Point_3& q) const
|
||||||
|
{
|
||||||
|
typename Kernel::Compute_squared_distance_3 sq_distance =
|
||||||
|
Kernel().compute_squared_distance_3_object();
|
||||||
|
return CGAL::sqrt(sq_distance(p, q));
|
||||||
|
}
|
||||||
|
|
||||||
|
Angle angle(const Point_3& p,
|
||||||
|
const Point_3& angle_vertex_point,
|
||||||
|
const Point_3& q) const
|
||||||
|
{
|
||||||
|
typename Kernel::Angle_3 compute_angle = Kernel().angle_3_object();
|
||||||
|
return compute_angle(p,angle_vertex_point,q);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
CGAL::Sign compare_distance(const Point_3& p,
|
||||||
|
const T1& obj1,
|
||||||
|
const T2& obj2) const
|
||||||
|
{
|
||||||
|
typename Kernel::Compare_distance_3 compare_distance =
|
||||||
|
Kernel().compare_distance_3_object();
|
||||||
|
return compare_distance(p,obj1,obj2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Data points_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable FT length_ = -1.;
|
||||||
|
|
||||||
|
}; // end class Polyline
|
||||||
|
|
||||||
|
|
||||||
|
} // end namespace internal
|
||||||
|
} // end namespace Mesh_3
|
||||||
|
} // end namespace CGAL
|
||||||
|
|
||||||
|
#endif // CGAL_MESH_3_INTERNAL_POLYLINE_H
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include <CGAL/Real_timer.h>
|
#include <CGAL/Real_timer.h>
|
||||||
#include <CGAL/property_map.h>
|
#include <CGAL/property_map.h>
|
||||||
#include <CGAL/SMDS_3/internal/indices_management.h>
|
#include <CGAL/SMDS_3/internal/indices_management.h>
|
||||||
|
#include <CGAL/Mesh_3/internal/Polyline.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
@ -47,530 +48,6 @@ namespace CGAL {
|
||||||
namespace Mesh_3 {
|
namespace Mesh_3 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <typename Kernel>
|
|
||||||
class Polyline
|
|
||||||
{
|
|
||||||
typedef typename Kernel::Point_3 Point_3;
|
|
||||||
typedef typename Kernel::Segment_3 Segment_3;
|
|
||||||
typedef typename Kernel::FT FT;
|
|
||||||
|
|
||||||
typedef std::vector<Point_3> Data;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef typename Data::const_iterator const_iterator;
|
|
||||||
typedef std::pair<Point_3, const_iterator> Point_and_location;
|
|
||||||
|
|
||||||
Polyline() {}
|
|
||||||
~Polyline() {}
|
|
||||||
|
|
||||||
/// adds a point at the end of the polyline
|
|
||||||
void add_point(const Point_3& p)
|
|
||||||
{
|
|
||||||
if( points_.empty() || p != end_point() ) {
|
|
||||||
points_.push_back(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// returns the starting point of the polyline
|
|
||||||
const Point_3& start_point() const
|
|
||||||
{
|
|
||||||
CGAL_assertion( ! points_.empty() );
|
|
||||||
return points_.front();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// returns the ending point of the polyline
|
|
||||||
const Point_3& end_point() const
|
|
||||||
{
|
|
||||||
CGAL_assertion( ! points_.empty() );
|
|
||||||
return points_.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// returns `true` if the polyline is not degenerate
|
|
||||||
bool is_valid() const
|
|
||||||
{
|
|
||||||
return points_.size() > 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// returns `true` if polyline is a loop
|
|
||||||
bool is_loop() const
|
|
||||||
{
|
|
||||||
return start_point() == end_point();
|
|
||||||
}
|
|
||||||
|
|
||||||
const_iterator next(const_iterator it, Orientation orientation) const {
|
|
||||||
if(orientation == POSITIVE) {
|
|
||||||
CGAL_assertion(it != (points_.end() - 1));
|
|
||||||
if(it == (points_.end() - 2)) {
|
|
||||||
CGAL_assertion(is_loop());
|
|
||||||
it = points_.begin();
|
|
||||||
} else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
CGAL_assertion(orientation == NEGATIVE);
|
|
||||||
CGAL_assertion(it != points_.begin());
|
|
||||||
if(it == (points_.begin() + 1)) {
|
|
||||||
CGAL_assertion(is_loop());
|
|
||||||
it = points_.end() - 1;
|
|
||||||
} else {
|
|
||||||
--it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_curve_segment_covered(CGAL::Orientation orientation,
|
|
||||||
const Point_3& c1, const Point_3& c2,
|
|
||||||
const FT sq_r1, const FT sq_r2,
|
|
||||||
const const_iterator cc1_it,
|
|
||||||
const const_iterator cc2_it) const
|
|
||||||
{
|
|
||||||
CGAL_assertion(orientation != CGAL::ZERO);
|
|
||||||
typename Kernel::Has_on_bounded_side_3 cover_pred =
|
|
||||||
Kernel().has_on_bounded_side_3_object();
|
|
||||||
|
|
||||||
typedef typename Kernel::Sphere_3 Sphere_3;
|
|
||||||
const Sphere_3 s1(c1, sq_r1);
|
|
||||||
const Sphere_3 s2(c2, sq_r2);
|
|
||||||
|
|
||||||
const_iterator c1_it = cc1_it;
|
|
||||||
const_iterator c2_it = cc2_it;
|
|
||||||
|
|
||||||
if(orientation == CGAL::NEGATIVE) {
|
|
||||||
++c1_it;
|
|
||||||
++c2_it;
|
|
||||||
CGAL_assertion(c1_it != points_.end());
|
|
||||||
CGAL_assertion(c2_it != points_.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(c1_it == c2_it) return cover_pred(s1, s2, c1, c2);
|
|
||||||
const_iterator next_it = this->next(c1_it, orientation);
|
|
||||||
|
|
||||||
if(!cover_pred(s1, s2, c1, *next_it)) return false;
|
|
||||||
|
|
||||||
for(const_iterator it = next_it; it != c2_it; /* in body */) {
|
|
||||||
next_it = this->next(it, orientation);
|
|
||||||
if(!cover_pred(s1, s2, *it, *next_it)) return false;
|
|
||||||
it = next_it;
|
|
||||||
} // end loop ]c1_it, c2_it[
|
|
||||||
|
|
||||||
return cover_pred(s1, s2, *c2_it, c2);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_curve_segment_covered(CGAL::Orientation orientation,
|
|
||||||
const Point_3& c1, const Point_3& c2,
|
|
||||||
const FT sq_r1, const FT sq_r2) const
|
|
||||||
{
|
|
||||||
return is_curve_segment_covered(orientation,
|
|
||||||
c1, c2, sq_r1, sq_r2, locate(c1), locate(c2));
|
|
||||||
}
|
|
||||||
|
|
||||||
FT curve_segment_length(const Point_3& p, const Point_3 q,
|
|
||||||
CGAL::Orientation orientation) const
|
|
||||||
{
|
|
||||||
CGAL_assertion(orientation != CGAL::ZERO);
|
|
||||||
const_iterator p_it = locate(p);
|
|
||||||
const_iterator q_it = locate(q);
|
|
||||||
return curve_segment_length(p, q, orientation, p_it, q_it);
|
|
||||||
}
|
|
||||||
|
|
||||||
FT curve_segment_length(const Point_3& p, const Point_3 q,
|
|
||||||
CGAL::Orientation orientation,
|
|
||||||
const_iterator p_it,
|
|
||||||
const_iterator q_it) const
|
|
||||||
{
|
|
||||||
CGAL_assertion(orientation != CGAL::ZERO);
|
|
||||||
CGAL_assertion(p_it == locate(p));
|
|
||||||
CGAL_assertion(q_it == locate(q));
|
|
||||||
|
|
||||||
if(p_it == q_it) {
|
|
||||||
const CGAL::Comparison_result cmp = compare_distance(*p_it,p,q);
|
|
||||||
if( (cmp != LARGER && orientation == POSITIVE) ||
|
|
||||||
(cmp != SMALLER && orientation == NEGATIVE) )
|
|
||||||
{
|
|
||||||
// If the orientation of `p` and `q` on the segment is compatible
|
|
||||||
// with `orientation`, then return the distance between the two
|
|
||||||
// points.
|
|
||||||
return distance(p, q);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(orientation == CGAL::NEGATIVE) {
|
|
||||||
++p_it;
|
|
||||||
++q_it;
|
|
||||||
CGAL_assertion(p_it != points_.end());
|
|
||||||
CGAL_assertion(q_it != points_.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
const_iterator next_it = this->next(p_it, orientation);
|
|
||||||
FT result = distance(p, *next_it);
|
|
||||||
for(const_iterator it = next_it; it != q_it; /* in body */) {
|
|
||||||
next_it = this->next(it, orientation);
|
|
||||||
result += distance(*it, *next_it);
|
|
||||||
it = next_it;
|
|
||||||
} // end loop ]p_it, q_it[
|
|
||||||
result += distance(*q_it, q);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// returns the angle at the first point.
|
|
||||||
/// \pre The polyline must be a loop.
|
|
||||||
Angle angle_at_first_point() const {
|
|
||||||
CGAL_precondition(is_loop());
|
|
||||||
const Point_3& first = points_.front();
|
|
||||||
const Point_3& next_p = points_[1];
|
|
||||||
const Point_3& prev = points_[points_.size() - 2];
|
|
||||||
return angle(prev, first, next_p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// returns the length of the polyline
|
|
||||||
FT length() const
|
|
||||||
{
|
|
||||||
if(length_ < 0.)
|
|
||||||
{
|
|
||||||
FT result(0);
|
|
||||||
const_iterator it = points_.begin();
|
|
||||||
const_iterator previous = it++;
|
|
||||||
|
|
||||||
for(const_iterator end = points_.end(); it != end; ++it, ++previous) {
|
|
||||||
result += distance(*previous, *it);
|
|
||||||
}
|
|
||||||
length_ = result;
|
|
||||||
}
|
|
||||||
return length_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// returns the signed geodesic distance between `p` and `q`.
|
|
||||||
FT signed_geodesic_distance(const Point_3& p, const Point_3& q) const
|
|
||||||
{
|
|
||||||
// Locate p & q on polyline
|
|
||||||
const_iterator pit = locate(p);
|
|
||||||
const_iterator qit = locate(q,false);
|
|
||||||
|
|
||||||
return signed_geodesic_distance(p, q, pit, qit);
|
|
||||||
}
|
|
||||||
|
|
||||||
FT signed_geodesic_distance(const Point_3& p, const Point_3& q,
|
|
||||||
const_iterator pit, const_iterator qit) const
|
|
||||||
{
|
|
||||||
CGAL_assertion(pit == locate(p));
|
|
||||||
CGAL_assertion(qit == locate(q, false));
|
|
||||||
|
|
||||||
// If p and q are in the same segment of the polyline
|
|
||||||
if ( pit == qit )
|
|
||||||
{
|
|
||||||
FT result = distance(p,q);
|
|
||||||
|
|
||||||
// Find the closest point to *pit
|
|
||||||
if ( compare_distance(*pit,p,q) != CGAL::LARGER )
|
|
||||||
{ return result; }
|
|
||||||
else
|
|
||||||
{ return -result; }
|
|
||||||
}
|
|
||||||
if(is_loop())
|
|
||||||
{
|
|
||||||
FT positive_distance, negative_distance;
|
|
||||||
if(pit <= qit)
|
|
||||||
{
|
|
||||||
positive_distance = curve_segment_length(p, q, CGAL::POSITIVE, pit, qit);
|
|
||||||
negative_distance = length() - positive_distance;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
negative_distance = curve_segment_length(q, p, CGAL::POSITIVE, qit, pit);
|
|
||||||
positive_distance = length() - negative_distance;
|
|
||||||
}
|
|
||||||
return (positive_distance < negative_distance) ? positive_distance : (-negative_distance);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return (pit <= qit)
|
|
||||||
? curve_segment_length(p, q, CGAL::POSITIVE, pit, qit)
|
|
||||||
: ( - curve_segment_length(p, q, CGAL::NEGATIVE, pit, qit) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const_iterator previous_segment_source(const_iterator it) const
|
|
||||||
{
|
|
||||||
CGAL_assertion(it != points_.end());
|
|
||||||
if(it == first_segment_source())
|
|
||||||
{
|
|
||||||
CGAL_assertion(is_loop());
|
|
||||||
it = last_segment_source();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
--it;
|
|
||||||
}
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
const_iterator next_segment_source(const_iterator it) const
|
|
||||||
{
|
|
||||||
CGAL_assertion(it != points_.end());
|
|
||||||
if(it == last_segment_source())
|
|
||||||
{
|
|
||||||
if(is_loop())
|
|
||||||
return first_segment_source();
|
|
||||||
else
|
|
||||||
return points_.end();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
++it;
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// returns a point at geodesic distance `distance` from p along the
|
|
||||||
/// polyline. The polyline is oriented from starting point to end point.
|
|
||||||
/// The distance could be negative.
|
|
||||||
Point_3 point_at(const Point_3& start_pt, FT distance) const
|
|
||||||
{
|
|
||||||
return point_at(start_pt, distance, locate(start_pt)).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// returns a point at geodesic distance `distance` from `start_pt` along the
|
|
||||||
/// polyline. The polyline is oriented from starting point to end point.
|
|
||||||
/// The distance could be negative.
|
|
||||||
Point_and_location point_at(const Point_3& start_pt,
|
|
||||||
FT distance,
|
|
||||||
const_iterator start_it) const
|
|
||||||
{
|
|
||||||
CGAL_assertion(start_it == locate(start_pt));
|
|
||||||
|
|
||||||
const Point_3& start_it_pt = *start_it;
|
|
||||||
const_iterator start_it_locate_pt
|
|
||||||
= (start_it == points_.begin()) ? start_it : std::prev(start_it);
|
|
||||||
|
|
||||||
distance += curve_segment_length(start_it_pt, start_pt, CGAL::POSITIVE,
|
|
||||||
start_it_locate_pt, start_it);
|
|
||||||
|
|
||||||
// If polyline is a loop, ensure that distance is given from start_it
|
|
||||||
if(is_loop())
|
|
||||||
{
|
|
||||||
if(distance < FT(0)) { distance += length(); }
|
|
||||||
else if(distance > length()) { distance -= length(); }
|
|
||||||
}
|
|
||||||
else if(distance < FT(0)) // If polyline is not a loop and distance is < 0, go backward
|
|
||||||
{
|
|
||||||
Point_3 new_start = start_pt;
|
|
||||||
while(distance < FT(0))
|
|
||||||
{
|
|
||||||
start_it = previous_segment_source(start_it);
|
|
||||||
distance += this->distance(new_start, *start_it);
|
|
||||||
new_start = *start_it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CGAL_assertion(distance >= FT(0));
|
|
||||||
CGAL_assertion(distance <= length());
|
|
||||||
|
|
||||||
// Initialize iterators
|
|
||||||
const_iterator pit = start_it; // start at start_it, and walk forward
|
|
||||||
const_iterator previous = pit++;
|
|
||||||
|
|
||||||
// Iterate to find which segment contains the point we want to construct
|
|
||||||
FT segment_length = this->distance(*previous, *pit);
|
|
||||||
while(distance > segment_length)
|
|
||||||
{
|
|
||||||
distance -= segment_length;
|
|
||||||
|
|
||||||
// Increment iterators and update length
|
|
||||||
previous = next_segment_source(previous);
|
|
||||||
pit = next_segment_source(pit);
|
|
||||||
|
|
||||||
if(pit == points_.end())
|
|
||||||
{
|
|
||||||
CGAL_assertion(distance < this->distance(*previous, end_point()));
|
|
||||||
break; // return {*previous, previous}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
segment_length = this->distance(*previous, *pit);
|
|
||||||
}
|
|
||||||
|
|
||||||
// return point at distance from current segment source
|
|
||||||
using Vector_3 = typename Kernel::Vector_3;
|
|
||||||
auto vector = Kernel().construct_vector_3_object();
|
|
||||||
Vector_3 v = (pit != points_.end()) ? vector(*previous, *pit)
|
|
||||||
: vector(*previous, end_point());
|
|
||||||
|
|
||||||
return {(*previous) + (distance / CGAL::sqrt(v.squared_length())) * v,
|
|
||||||
previous};
|
|
||||||
}
|
|
||||||
|
|
||||||
const_iterator locate_corner(const Point_3& p) const
|
|
||||||
{
|
|
||||||
const_iterator res = points_.end();
|
|
||||||
if(p == start_point())
|
|
||||||
res = points_.begin();
|
|
||||||
else if(p == end_point())
|
|
||||||
res = last_segment_source();
|
|
||||||
|
|
||||||
CGAL_assertion(res == locate(p));
|
|
||||||
CGAL_assertion(res != points_.end());
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
const_iterator locate_point(const Point_3& p) const
|
|
||||||
{
|
|
||||||
return locate(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool are_ordered_along(const Point_3& p, const Point_3& q,
|
|
||||||
const_iterator pit, const_iterator qit) const
|
|
||||||
{
|
|
||||||
CGAL_precondition(!is_loop());
|
|
||||||
|
|
||||||
// Locate p & q on polyline
|
|
||||||
CGAL_assertion(pit == locate(p));
|
|
||||||
CGAL_assertion(qit == locate(q, true));
|
|
||||||
|
|
||||||
// Points are not located on the same segment
|
|
||||||
if ( pit != qit ) { return (pit <= qit); }
|
|
||||||
|
|
||||||
// pit == qit, then we have to sort p&q along (pit,pit+1)
|
|
||||||
return ( compare_distance(*pit,p,q) != CGAL::LARGER );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool are_ordered_along(const Point_3& p, const Point_3& q) const
|
|
||||||
{
|
|
||||||
return are_ordered_along(p, q, locate(p), locate(q, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const_iterator first_segment_source() const
|
|
||||||
{
|
|
||||||
CGAL_precondition(is_valid());
|
|
||||||
return points_.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
const_iterator last_segment_source() const
|
|
||||||
{
|
|
||||||
CGAL_precondition(is_valid());
|
|
||||||
return (points_.end() - 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// returns an iterator on the starting point of the segment of the
|
|
||||||
/// polyline which contains p
|
|
||||||
/// if end_point_first is true, then --end is returned instead of begin
|
|
||||||
/// if p is the starting point of a loop.
|
|
||||||
const_iterator locate(const Point_3& p, bool end_point_first=false) const
|
|
||||||
{
|
|
||||||
CGAL_precondition(is_valid());
|
|
||||||
|
|
||||||
// First look if p is one of the points of the polyline
|
|
||||||
const_iterator result = std::find(points_.begin(), points_.end(), p);
|
|
||||||
if ( result != points_.end() )
|
|
||||||
{
|
|
||||||
if ( result != points_.begin() )
|
|
||||||
{ return --result; }
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Treat loops
|
|
||||||
if ( end_point_first && p == end_point() )
|
|
||||||
{ return last_segment_source(); }
|
|
||||||
else
|
|
||||||
{ return result; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CGAL_assertion(result == points_.end());
|
|
||||||
|
|
||||||
// Get result by projecting p on the polyline
|
|
||||||
const_iterator it = points_.begin();
|
|
||||||
const_iterator previous = it;
|
|
||||||
Segment_3 nearest_segment;
|
|
||||||
const_iterator nearest_vertex = it;
|
|
||||||
result = nearest_vertex;
|
|
||||||
bool nearest_is_a_segment = false;
|
|
||||||
|
|
||||||
while ( ++it != points_.end() )
|
|
||||||
{
|
|
||||||
Segment_3 seg (*previous, *it);
|
|
||||||
|
|
||||||
if(nearest_is_a_segment)
|
|
||||||
{
|
|
||||||
if(compare_distance(p, *it, nearest_segment) == CGAL::SMALLER)
|
|
||||||
{
|
|
||||||
nearest_vertex = it;
|
|
||||||
nearest_is_a_segment = false;
|
|
||||||
result = it;
|
|
||||||
if (possibly(angle(*previous, *it, p) == CGAL::ACUTE) &&
|
|
||||||
compare_distance(p, seg, *nearest_vertex) == CGAL::SMALLER)
|
|
||||||
{
|
|
||||||
nearest_segment = seg;
|
|
||||||
nearest_is_a_segment = true;
|
|
||||||
result = previous;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(compare_distance(p, seg, nearest_segment) == CGAL::SMALLER)
|
|
||||||
{
|
|
||||||
nearest_segment = seg;
|
|
||||||
result = previous;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(compare_distance(p, *it, *nearest_vertex) == CGAL::SMALLER)
|
|
||||||
{
|
|
||||||
nearest_vertex = it;
|
|
||||||
result = it;
|
|
||||||
}
|
|
||||||
if ((nearest_vertex != it ||
|
|
||||||
possibly(angle(*previous, *it, p) == CGAL::ACUTE)) &&
|
|
||||||
compare_distance(p, seg, *nearest_vertex) == CGAL::SMALLER)
|
|
||||||
{
|
|
||||||
nearest_segment = seg;
|
|
||||||
nearest_is_a_segment = true;
|
|
||||||
result = previous;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
previous = it;
|
|
||||||
} // end the while loop on the vertices of the polyline
|
|
||||||
|
|
||||||
if(result == points_.begin()) {
|
|
||||||
return (end_point_first && !nearest_is_a_segment) ? last_segment_source() : points_.begin();
|
|
||||||
} else {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FT distance(const Point_3& p, const Point_3& q) const
|
|
||||||
{
|
|
||||||
typename Kernel::Compute_squared_distance_3 sq_distance =
|
|
||||||
Kernel().compute_squared_distance_3_object();
|
|
||||||
return CGAL::sqrt(sq_distance(p, q));
|
|
||||||
}
|
|
||||||
|
|
||||||
Angle angle(const Point_3& p,
|
|
||||||
const Point_3& angle_vertex_point,
|
|
||||||
const Point_3& q) const
|
|
||||||
{
|
|
||||||
typename Kernel::Angle_3 compute_angle = Kernel().angle_3_object();
|
|
||||||
return compute_angle(p,angle_vertex_point,q);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
|
||||||
CGAL::Sign compare_distance(const Point_3& p,
|
|
||||||
const T1& obj1,
|
|
||||||
const T2& obj2) const
|
|
||||||
{
|
|
||||||
typename Kernel::Compare_distance_3 compare_distance =
|
|
||||||
Kernel().compare_distance_3_object();
|
|
||||||
return compare_distance(p,obj1,obj2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Data points_;
|
|
||||||
|
|
||||||
private:
|
|
||||||
mutable FT length_ = -1.;
|
|
||||||
|
|
||||||
}; // end class Polyline
|
|
||||||
|
|
||||||
|
|
||||||
template <typename GT, typename MapIterator>
|
template <typename GT, typename MapIterator>
|
||||||
struct Mesh_domain_segment_of_curve_primitive{
|
struct Mesh_domain_segment_of_curve_primitive{
|
||||||
typedef typename std::iterator_traits<MapIterator>::value_type Map_value_type;
|
typedef typename std::iterator_traits<MapIterator>::value_type Map_value_type;
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@
|
||||||
#include <CGAL/Periodic_3_Delaunay_triangulation_traits_3.h>
|
#include <CGAL/Periodic_3_Delaunay_triangulation_traits_3.h>
|
||||||
#include <CGAL/Periodic_3_Delaunay_triangulation_3.h>
|
#include <CGAL/Periodic_3_Delaunay_triangulation_3.h>
|
||||||
#include <CGAL/Time_stamper.h>
|
#include <CGAL/Time_stamper.h>
|
||||||
|
#include <CGAL/Mesh_3/internal/Polyline.h>
|
||||||
|
|
||||||
#include <CGAL/boost/iterator/transform_iterator.hpp>
|
#include <CGAL/boost/iterator/transform_iterator.hpp>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue