52#define ACG_POLYLINET_C
56#include <OpenMesh/Core/Geometry/VectorT.hh>
63#include "PolyLineT.hh"
66#include <ACG/Geometry/Algorithms.hh>
67#include <ACG/Utils/VSToolsT.hh>
89template <
class Po
intT>
95 ref_count_vnormals_(0),
96 ref_count_vbinormals_(0),
97 ref_count_vcolors_(0),
98 ref_count_vscalars_(0),
99 ref_count_vselections_(0),
100 ref_count_vvhandles_(0),
101 ref_count_vehandles_(0),
102 ref_count_vfhandles_(0),
103 ref_count_enormals_(0),
104 ref_count_ecolors_(0),
105 ref_count_escalars_(0),
106 ref_count_eselections_(0),
107 ref_count_epreimage_direction_(0)
114template <
class Po
intT>
119 points_(_line.points_),
121 closed_(_line.closed_),
124 vnormals_(_line.vnormals_),
125 vbinormals_(_line.vbinormals_),
126 vcolors_(_line.vcolors_),
127 vscalars_(_line.vscalars_),
128 vselections_(_line.vselections_),
129 vvhandles_(_line.vvhandles_),
130 vehandles_(_line.vehandles_),
131 vfhandles_(_line.vfhandles_),
134 enormals_(_line.enormals_),
135 ecolors_(_line.ecolors_),
136 escalars_(_line.escalars_),
137 eselections_(_line.eselections_),
138 epreimage_direction_(_line.epreimage_direction_),
141 ref_count_vnormals_(_line.ref_count_vnormals_),
142 ref_count_vbinormals_(_line.ref_count_vbinormals_),
143 ref_count_vcolors_(_line.ref_count_vcolors_),
144 ref_count_vscalars_(_line.ref_count_vscalars_),
145 ref_count_vselections_(_line.ref_count_vselections_),
146 ref_count_vvhandles_(_line.ref_count_vvhandles_),
147 ref_count_vehandles_(_line.ref_count_vehandles_),
148 ref_count_vfhandles_(_line.ref_count_vfhandles_),
150 ref_count_enormals_(_line.ref_count_enormals_),
151 ref_count_ecolors_(_line.ref_count_ecolors_),
152 ref_count_escalars_(_line.ref_count_escalars_),
153 ref_count_eselections_(_line.ref_count_eselections_),
154 ref_count_epreimage_direction_(_line.ref_count_epreimage_direction_)
159 for (
typename CustomPropertyMap::const_iterator it = _line.custom_properties.begin(); it != _line.custom_properties.end(); ++it) {
164 dst->name = src->name;
165 dst->ref_count = src->ref_count;
166 dst->prop_size = src->prop_size;
167 dst->prop_data = src->prop_data;
169 dst->datatype = src->datatype;
170 dst->shader_binding = src->shader_binding;
172 custom_properties[it->first] = dst;
179template <
class Po
intT>
191 vselections_.clear();
199 eselections_.clear();
200 epreimage_direction_.clear();
202 for (
typename CustomPropertyMap::iterator it = custom_properties.begin(); it != custom_properties.end(); ++it)
204 custom_properties.clear();
209template <
class Po
intT>
213 if (n_vertices() <= 1)
216 return n_vertices() - 1 + (
unsigned int) closed_;
223template <
class Po
intT>
228 if( _n < n_vertices())
234 if( vertex_normals_available() )
235 vnormals_.resize( _n);
236 if( vertex_binormals_available() )
237 vbinormals_.resize( _n);
238 if( vertex_colors_available())
239 vcolors_.resize( _n);
240 if( vertex_scalars_available())
241 vscalars_.resize( _n);
242 if( vertex_selections_available())
243 vselections_.resize( _n);
244 if( vertex_vhandles_available())
245 vvhandles_.resize( _n);
246 if( vertex_ehandles_available())
247 vehandles_.resize( _n);
248 if( vertex_fhandles_available())
249 vfhandles_.resize( _n);
251 if( edge_normals_available())
252 enormals_.resize( _n);
253 if( edge_colors_available())
254 ecolors_.resize( _n);
255 if( edge_scalars_available())
256 escalars_.resize( _n);
257 if( edge_preimage_directions_available())
258 epreimage_direction_.resize( _n);
261 for (
typename CustomPropertyMap::iterator it = custom_properties.begin(); it != custom_properties.end(); ++it) {
265 p->prop_data.resize(p->prop_size * _n);
271 while( n_vertices() < _n)
280template <
class Po
intT>
286 points_.push_back( _p );
289 if( vertex_normals_available() )
290 vnormals_.push_back( Point(0,0,0));
292 if( vertex_binormals_available() )
293 vbinormals_.push_back( Point(0,0,0));
295 if( vertex_colors_available())
296 vcolors_.push_back( Point(1,0,1));
298 if( vertex_scalars_available())
299 vscalars_.push_back( 0.0 );
301 if( vertex_selections_available())
302 vselections_.push_back(
false);
304 if( vertex_vhandles_available())
305 vvhandles_.push_back(-1);
307 if( vertex_ehandles_available())
308 vehandles_.push_back(-1);
310 if( vertex_fhandles_available())
311 vfhandles_.push_back(-1);
313 if( edge_normals_available())
314 enormals_.push_back( Point(0,0,0));
316 if( edge_colors_available())
317 ecolors_.push_back( Point(1,0,1));
319 if( edge_scalars_available())
320 escalars_.push_back( 0.0);
322 if( edge_selections_available())
323 eselections_.push_back(
false);
325 if( edge_preimage_directions_available())
326 epreimage_direction_.push_back(Point(0,0,0));
329 for (
typename CustomPropertyMap::iterator it = custom_properties.begin(); it != custom_properties.end(); ++it) {
333 size_t cur_size = p->prop_data.size();
335 p->prop_data.resize(cur_size + p->prop_size);
338 memset(p->buffer() + cur_size, 0, p->prop_size);
344template <
class Po
intT>
349 assert(_idx < (
int)n_vertices() );
352 points_.insert(points_.begin()+_idx, _p);
355 if( vertex_normals_available() )
356 vnormals_.insert(vnormals_.begin()+_idx, Point(0,0,0));
358 if( vertex_binormals_available() )
359 vbinormals_.insert(vbinormals_.begin()+_idx, Point(0,0,0));
361 if( vertex_colors_available())
362 vcolors_.insert(vcolors_.begin()+_idx, Point(1,0,1));
364 if( vertex_scalars_available())
365 vscalars_.insert(vscalars_.begin()+_idx, 0.0 );
367 if( vertex_selections_available())
368 vselections_.insert(vselections_.begin()+_idx,
false);
370 if( vertex_vhandles_available())
371 vvhandles_.insert(vvhandles_.begin()+_idx, -1);
373 if( vertex_ehandles_available())
374 vehandles_.insert(vehandles_.begin()+_idx, -1);
376 if( vertex_fhandles_available())
377 vfhandles_.insert(vfhandles_.begin()+_idx, -1);
379 if( edge_normals_available())
380 enormals_.insert(enormals_.begin()+_idx, Point(0,0,0));
382 if( edge_colors_available())
383 ecolors_.insert(ecolors_.begin()+_idx, Point(1,0,1));
385 if( edge_scalars_available())
386 escalars_.insert(escalars_.begin()+_idx, 0.0);
388 if( edge_selections_available())
389 eselections_.insert(eselections_.begin()+_idx,
false);
391 if( edge_preimage_directions_available())
392 epreimage_direction_.insert(epreimage_direction_.begin()+_idx, Point(0,0,0));
395 for (
typename CustomPropertyMap::iterator it = custom_properties.begin(); it != custom_properties.end(); ++it) {
398 unsigned int offset = p->prop_size * _idx;
400 for (
unsigned int i = 0; i < p->prop_size; ++i)
401 p->prop_data.insert(p->prop_data.begin() + offset, 0);
409template <
class Po
intT>
414 assert(_idx < (
int)n_vertices() );
417 points_.erase(points_.begin()+_idx);
421 if( vertex_normals_available() )
422 vnormals_.erase(vnormals_.begin()+_idx);
424 if( vertex_binormals_available() )
425 vbinormals_.erase(vbinormals_.begin()+_idx);
427 if( vertex_colors_available())
428 vcolors_.erase(vcolors_.begin()+_idx);
430 if( vertex_scalars_available())
431 vscalars_.erase(vscalars_.begin()+_idx);
433 if( vertex_selections_available())
434 vselections_.erase(vselections_.begin()+_idx);
436 if( vertex_vhandles_available())
437 vvhandles_.erase(vvhandles_.begin()+_idx);
439 if( vertex_ehandles_available())
440 vehandles_.erase(vehandles_.begin()+_idx);
442 if( vertex_fhandles_available())
443 vfhandles_.erase(vfhandles_.begin()+_idx);
445 if( edge_normals_available())
446 enormals_.erase(enormals_.begin()+_idx);
448 if( edge_colors_available())
449 ecolors_.erase(ecolors_.begin()+_idx);
451 if( edge_scalars_available())
452 escalars_.erase(escalars_.begin()+_idx);
454 if( edge_selections_available())
455 eselections_.erase(eselections_.begin()+_idx);
457 if( edge_preimage_directions_available())
458 epreimage_direction_.erase(epreimage_direction_.begin()+_idx);
462 for (
typename CustomPropertyMap::iterator it = custom_properties.begin(); it != custom_properties.end(); ++it) {
465 unsigned int offset = p->prop_size * _idx;
467 for (
unsigned int i = 0; i < p->prop_size; ++i)
468 p->prop_data.erase(p->prop_data.begin() + offset);
476template <
class Po
intT>
477typename PolyLineT<PointT>::Scalar
483 unsigned int n = points_.size();
487 for(
unsigned int i=0; i<n-1; ++i)
489 l += (points_[(i+1)]-points_[i]).norm();
494 for(
unsigned int i=0; i<n; ++i)
496 l += (points_[(i+1)%n]-points_[i]).norm();
507template <
class Po
intT>
508typename PolyLineT<PointT>::Point
512 assert(_t >=0.0 && _t<=1.0);
513 return position_arclength(_t*this->length());
520template <
class Po
intT>
521typename PolyLineT<PointT>::Point
526 if(this->n_vertices() < 2)
528 if(this->n_vertices() == 1)
529 return this->front();
532 std::cerr <<
"Warning: called position_arclength on emptu PolyLine!!!" << std::endl;
539 return this->front();
541 unsigned int nv = this->n_vertices();
542 unsigned int ne = this->n_edges();
546 for(
unsigned int i=0; i<ne; ++i)
548 Scalar dl = (points_[(i+1)%nv]-points_[i]).norm();
550 if(l <= _t && _t <= (l+dl))
552 Scalar tl = (_t-l)/dl;
555 return (tl*points_[(i+1)%nv] + (1.0-tl)*points_[i]);
565 return this->front();
572template <
class Po
intT>
577 unsigned int n = std::max((
unsigned int)(2),_n);
578 Scalar l = this->length();
584 new_pl.copy_vertex_complete(*
this, 0, 0);
588 Scalar s = l/Scalar(n-1);
589 for(
unsigned int i=1; i<n-1; ++i)
590 new_pl.
point(i) = this->position_arclength(i*s);
594 Scalar s = l/Scalar(n);
595 for(
unsigned int i=1; i<n; ++i)
596 new_pl.
point(i) = this->position_arclength(i*s);
601 new_pl.copy_vertex_complete(*
this, std::max(
int(0),
int(this->n_vertices())-1), std::max(
int(0),
int(new_pl.
n_vertices())-1));
611template <
class Po
intT>
620 unsigned int n_subdivisions = 1;
622 while (n_subdivisions != 0) {
629 new_pl.copy_vertex_complete(*
this, 0, 0);
632 Scalar l2 = _largest * _largest;
634 for (
unsigned int i = 1; i < points_.size(); ++i) {
635 if ((new_pl.
point(new_pl.
n_vertices() - 1) - points_[i]).sqrnorm() > l2) {
636 Point mid_point = (new_pl.
point(new_pl.
n_vertices() - 1) + points_[i]) * 0.5;
644 new_pl.copy_vertex_complete(*
this, i, new_pl.
n_vertices() - 1);
649 if ((new_pl.
point(new_pl.
n_vertices() - 1) - points_[0]).sqrnorm() > l2) {
650 Point mid_point = (new_pl.
point(new_pl.
n_vertices() - 1) + points_[0]) * 0.5;
664template <
class Po
intT>
670 if(!n_vertices())
return;
672 unsigned int n_collapses = 1;
674 unsigned int n_iter = 0;
676 while( n_collapses != 0 && n_iter < 5)
684 new_pl.copy_vertex_complete( *
this, 0, 0);
687 Scalar l2 = _smallest*_smallest;
689 for(
unsigned int i=1; i<points_.size(); ++i)
692 bool vertex_selected =
false;
693 if( vertex_selections_available() && vertex_selection(i))
694 vertex_selected =
true;
696 if( (new_pl.
point(new_pl.
n_vertices()-1) - points_[i]).sqrnorm() >= l2 ||
698 (!closed_ && i==points_.size()-1) )
702 new_pl.copy_vertex_complete( *
this, i, new_pl.
n_vertices()-1);
711 bool vertex_selected =
false;
712 if( vertex_selections_available() && vertex_selection(points_.size()-1))
713 vertex_selected =
true;
715 if( (new_pl.
point(new_pl.
n_vertices()-1) - points_[0]).sqrnorm() < l2 && !vertex_selected)
730template <
class Po
intT>
736 std::vector<Point> points_old( points_ );
738 int n = points_.size();
749 if( vertex_selections_available())
752 #pragma omp parallel for
754 for(
int i=is; i<ie; ++i)
757 if( !vertex_selection(i))
759 points_[i] = (points_old[ (i-1+n)%n ] +
760 points_old[ (i+n )%n ]*2.0 +
761 points_old[ (i+1 )%n ] )*0.25;
768 #pragma omp parallel for
770 for(
int i=is; i<ie; ++i)
773 points_[i] = (points_old[ (i-1+n)%n ] +
774 points_old[ (i+n )%n ] * 2.0 +
775 points_old[ (i+1 )%n ] )*0.25;
784template <
class Po
intT>
790 std::vector<Point> points_old( points_ );
792 int n = points_.size();
803 if( vertex_selections_available())
806 #pragma omp parallel for
808 for(
int i=is; i<ie; ++i)
811 if( !vertex_selection(i))
813 points_[i] -= (points_old[ (i-2+2*n)%n ] +
814 points_old[ (i-1+2*n)%n ]*-4.0 +
815 points_old[ (i )%n ]* 6.0 +
816 points_old[ (i+1 )%n ]*-4.0 +
817 points_old[ (i+2 )%n ] )/(16.0*2.0);
823 #pragma omp parallel for
825 for(
int i=is; i<ie; ++i)
828 points_[i] -= (points_old[ (i-2+2*n)%n ] +
829 points_old[ (i-1+2*n)%n ]*-4.0 +
830 points_old[ (i )%n ]* 6.0 +
831 points_old[ (i+1 )%n ]*-4.0 +
832 points_old[ (i+2 )%n ] )/(16.0*2.0);
841template <
class Po
intT>
847 std::vector<Point> points_old( points_ );
849 int n = points_.size();
860 if( vertex_selections_available())
863 #pragma omp parallel for
865 for(
int i=is; i<ie; ++i)
868 if( !vertex_selection(i))
870 points_[i] = (points_old[ (i-3+3*n)%n ] +
871 points_old[ (i-2+3*n)%n ]*(-6.0) +
872 points_old[ (i-1+3*n)%n ]*15.0 +
873 points_old[ (i ) ]*(44.0) +
874 points_old[ (i+1 )%n ]*15.0 +
875 points_old[ (i+2 )%n ]*(-6.0) +
876 points_old[ (i+3 )%n ] )/64.0;
883 #pragma omp parallel for
885 for(
int i=is; i<ie; ++i)
888 points_[i] = (points_old[ (i-3+3*n)%n ] +
889 points_old[ (i-2+3*n)%n ]*(-6.0) +
890 points_old[ (i-1+3*n)%n ]*15.0 +
891 points_old[ (i ) ]*(44.0) +
892 points_old[ (i+1 )%n ]*15.0 +
893 points_old[ (i+2 )%n ]*(-6.0) +
894 points_old[ (i+3 )%n ] )/64.0;
903template <
class Po
intT>
906set_to_circle(
const PointT _center,
const PointT _normal,
double _radius,
unsigned int _n_samples)
909 this->set_closed(
true);
912 PointT n = _normal; n.normalize();
916 for(
unsigned int i=0; i<_n_samples; ++i)
918 double alpha = double(i)*2.0*M_PI/double(_n_samples);
920 this->add_point(_center + u*cos(alpha) + v*sin(alpha));
928template <
class Po
intT>
929template <
class MeshT,
class SpatialSearchT>
934 typename MeshT::FaceHandle fh;
937 #pragma omp parallel for
939 for(
unsigned int i=0; i<points_.size(); ++i)
941 points_[i] = find_nearest_point( _mesh, points_[i], fh, _ssearch);
949template <
class Po
intT>
950template <
class MeshT,
class SpatialSearchT>
954 std::vector<SpatialSearchT*>* _ssearch)
956 typename MeshT::FaceHandle fh;
959 #pragma omp parallel for
961 for(
int i=0; i< (int)points_.size(); ++i)
964 typename MeshT::Scalar d_best = -1;
970 for(
unsigned int j=0; j<_mesh.size(); ++j)
976 p_new = find_nearest_point( *(_mesh[j]), points_[i], fh, ((*_ssearch)[j]), &d_new);
978 p_new = find_nearest_point( *(_mesh[j]), points_[i], fh, (SpatialSearchT*)0, &d_new);
981 if( d_new < d_best || d_best == -1)
997template <
class Po
intT>
998template <
class MeshT,
class SpatialSearchT>
999typename PolyLineT<PointT>::Point
1002 const Point& _point,
1003 typename MeshT::FaceHandle& _fh,
1004 SpatialSearchT * _ssearch,
1007 typename MeshT::Point p0 = (
typename MeshT::Point) _point;
1009 typename MeshT::Point p_best = _mesh.point(_mesh.vertex_handle(0));
1010 typename MeshT::Scalar d_best = (p0 - p_best).sqrnorm();
1012 typename MeshT::FaceHandle fh_best;
1014 if (_ssearch == 0) {
1016 typename MeshT::ConstFaceIter cf_it = _mesh.faces_begin();
1017 typename MeshT::ConstFaceIter cf_end = _mesh.faces_end();
1019 for (; cf_it != cf_end; ++cf_it) {
1020 typename MeshT::ConstFaceVertexIter cfv_it = _mesh.cfv_iter(*cf_it);
1022 const typename MeshT::Point& pt0 = _mesh.point(*cfv_it);
1023 const typename MeshT::Point& pt1 = _mesh.point(*(++cfv_it));
1024 const typename MeshT::Point& pt2 = _mesh.point(*(++cfv_it));
1026 typename MeshT::Point ptn;
1028 typename MeshT::Scalar d = Geometry::distPointTriangleSquared(p0, pt0, pt1, pt2, ptn);
1043 *_dbest = sqrt(d_best);
1045 return (Point) p_best;
1047 typename MeshT::FaceHandle fh = _ssearch->nearest(p0).handle;
1048 typename MeshT::CFVIter fv_it = _mesh.cfv_iter(fh);
1050 const typename MeshT::Point& pt0 = _mesh.point(*fv_it);
1051 const typename MeshT::Point& pt1 = _mesh.point(*(++fv_it));
1052 const typename MeshT::Point& pt2 = _mesh.point(*(++fv_it));
1055 d_best = Geometry::distPointTriangleSquared(p0, pt0, pt1, pt2, p_best);
1062 *_dbest = sqrt(d_best);
1064 return (Point) p_best;
1071template <
class Po
intT>
1072template <
class LineNodeT>
1077 typedef typename LineNodeT::value_type Vec3fL;
1083 _line_node =
new LineNodeT(LineNodeT::LineSegmentsMode, 0,
"PolyLine");
1084 _line_node->set_line_width(5.0);
1086 _line_node->set_base_color(
1087 OpenMesh::Vec4f(0.2 +
double(rand()) /
double(RAND_MAX) * 0.8, 0.2 +
double(rand()) /
double(RAND_MAX) * 0.8,
1088 0.2 +
double(rand()) /
double(RAND_MAX) * 0.8, 1.0));
1093 for (
unsigned int i = 0; i < this->points().size() - 1; ++i) {
1094 _line_node->add_line((Vec3fL) this->points()[i], (Vec3fL) this->points()[i + 1]);
1099 if (!this->points().empty()) {
1100 _line_node->add_point((Vec3fL) this->points()[0]);
1106 _line_node =
new LineNodeT(LineNodeT::PolygonMode, 0,
"PolyLine");
1107 _line_node->set_line_width(5.0);
1109 _line_node->set_base_color(
1110 OpenMesh::Vec4f(0.2 +
double(rand()) /
double(RAND_MAX) * 0.8, 0.2 +
double(rand()) /
double(RAND_MAX) * 0.8,
1111 0.2 +
double(rand()) /
double(RAND_MAX) * 0.8, 1.0));
1116 for (
unsigned int i = 0; i < this->points().size(); ++i) {
1117 _line_node->add_point((Vec3fL) this->points()[i]);
1122 if (!this->points().empty()) {
1123 _line_node->add_point((Vec3fL) this->points()[0]);
1134template <
class Po
intT>
1135template <
class LineNodeT>
1148 const typename LineNodeT::PointVector& ln_points = _line_node->points();
1150 for (
unsigned int i = 0; i < ln_points.size();) {
1151 if (i != ln_points.size() - 1)
1152 add_point((Point) ln_points[i]);
1155 if ((ln_points[ln_points.size() - 1] - ln_points[0]).sqrnorm() == 0) {
1159 add_point((Point) ln_points[i]);
1173 const typename LineNodeT::PointVector& ln_points(_line_node->points());
1175 for (
unsigned int i = 0; i < ln_points.size(); ++i) {
1176 add_point((Point) ln_points[i]);
1185template <
class Po
intT>
1190 std::cerr <<
"****** PolyInfo ******\n";
1191 std::cerr <<
"closed : " << closed_ << std::endl;
1192 std::cerr <<
"#points: " << points_.size() << std::endl;
1193 for(
unsigned int i=0; i<points_.size(); ++i)
1194 std::cerr << points_[i] << std::endl;
1201template <
class Po
intT>
1202template <
class PropT>
1211 _prop.
resize(n_vertices());
1220template <
class Po
intT>
1221template <
class PropT>
1224release_prop(
unsigned int& _ref_count, PropT& _prop)
1226 if( _ref_count <= 1)
1238template <
class Po
intT>
1241copy_vertex_complete(
const PolyLineT<PointT>& _pl,
unsigned int _i,
unsigned int _j)
1244 if( n_vertices() <= _j || _pl.n_vertices() <= _i)
1246 std::cerr <<
"Warning: invalid range in PolyLine::copy_vertex_complete ( "
1247 << _i <<
" " << _j <<
" ) " << std::endl;
1252 point(_j) = _pl.point(_i);
1257 if( _pl.vertex_normals_available())
1258 if( vertex_normals_available())
1259 vertex_normal(_j) = _pl.vertex_normal(_i);
1261 if( _pl.vertex_binormals_available())
1262 if( vertex_binormals_available())
1263 vertex_binormal(_j) = _pl.vertex_binormal(_i);
1266 if( _pl.vertex_colors_available())
1267 if( vertex_colors_available())
1268 vertex_color(_j) = _pl.vertex_color(_i);
1271 if( _pl.vertex_scalars_available())
1272 if( vertex_scalars_available())
1273 vertex_scalar(_j) = _pl.vertex_scalar(_i);
1276 if( _pl.vertex_selections_available())
1277 if( vertex_selections_available())
1278 vertex_selection(_j) = _pl.vertex_selection(_i);
1281 if( _pl.vertex_vhandles_available())
1282 if( vertex_vhandles_available())
1283 vertex_vhandle(_j) = _pl.vertex_vhandle(_i);
1286 if( _pl.vertex_ehandles_available())
1287 if( vertex_ehandles_available())
1288 vertex_ehandle(_j) = _pl.vertex_ehandle(_i);
1291 if( _pl.vertex_ehandles_available())
1292 if( vertex_ehandles_available())
1293 vertex_ehandle(_j) = _pl.vertex_ehandle(_i);
1300template <
class Po
intT>
1303copy_edge_complete(
const PolyLineT<PointT>& _pl,
unsigned int _i,
unsigned int _j)
1306 if( n_edges() <= _j || _pl.n_edges() <= _i)
1308 std::cerr <<
"Warning: invalid range in PolyLine::copy_edge_complete ( "
1309 << _i <<
" " << _j <<
" ) " << std::endl;
1314 if( _pl.edge_selections_available())
1315 if( edge_selections_available())
1316 edge_selection(_j) = _pl.edge_selection(_i);
1320 if( _pl.edge_normals_available())
1321 if( edge_normals_available())
1322 edge_normal(_j) = _pl.edge_normal(_i);
1325 if( _pl.edge_colors_available())
1326 if( edge_colors_available())
1327 edge_color(_j) = _pl.edge_color(_i);
1330 if( _pl.edge_scalars_available())
1331 if( edge_scalars_available())
1332 edge_scalar(_j) = _pl.edge_scalar(_i);
1335 if( _pl.edge_selections_available())
1336 if( edge_selections_available())
1337 edge_selection(_j) = _pl.edge_selection(_i);
1340 if( _pl.edge_selections_available())
1341 if( edge_selections_available())
1342 edge_selection(_j) = _pl.edge_selection(_i);
1349template <
class Po
intT>
1357 std::cerr <<
"Warning: inversion for closed polylines is not supported!!!\n";
1364 for(
unsigned int i=0; i<n_vertices(); ++i)
1365 pl_temp.copy_vertex_complete( *
this, n_vertices()-1-i, i);
1368 for(
unsigned int i=0; i<n_edges(); ++i)
1369 pl_temp.copy_edge_complete( *
this, n_edges()-1-i, i);
1379template <
class Po
intT>
1387 std::cerr << is_closed() <<
" " << _pl.
is_closed() << std::endl;
1388 std::cerr <<
"Warning: appending not supported for closed polylines!!!\n";
1392 unsigned int old_nv = n_vertices();
1393 unsigned int old_ne = n_edges();
1397 for(
unsigned int i=0; i<_pl.
n_vertices(); ++i)
1398 copy_vertex_complete( _pl, i, i+old_nv);
1400 for(
unsigned int i=0; i<_pl.
n_edges(); ++i)
1401 copy_edge_complete( _pl, i, i+old_ne+1);
1408template <
class Po
intT>
1423template <
class Po
intT>
1430 std::cerr <<
"Warning: split_closed was called for open polyline!\n";
1436 pl_temp.
resize(n_vertices()+1);
1441 for(
unsigned int i=0; i<n_vertices()+1; ++i)
1442 pl_temp.copy_vertex_complete( *
this, (i+_split_idx)%n_vertices(),i);
1444 for(
unsigned int i=0; i<n_edges(); ++i)
1445 pl_temp.copy_edge_complete( *
this, (i+_split_idx)%n_edges(),i);
1455template <
class Po
intT>
1460 if( is_closed() ) split_closed( _split_idx);
1466 _new_pl.
resize( n_vertices() - _split_idx);
1469 for(
unsigned int i=_split_idx; i<n_vertices(); ++i)
1470 _new_pl.copy_vertex_complete(*
this, i, i-_split_idx);
1472 for(
unsigned int i=_split_idx; i<n_edges(); ++i)
1473 _new_pl.copy_edge_complete(*
this, i, i-_split_idx);
1476 resize(_split_idx+1);
1484template <
class Po
intT>
1485template <
class IPo
int>
1489 const IPoint& _n_plane,
1494 double a = (_n_plane | (_p_plane - _p0));
1495 double b = (_n_plane | (_p1 - _p0));
1497 if (fabs(b) > 1e-9) {
1500 if (s >= 0.0 && s <= 1.0) {
1501 _p_int = _p0 + (_p1 - _p0) * s;
1504 if (fabs((_n_plane | (_p_int - _p_plane))) > 1e-9)
1505 std::cerr <<
"WARNING: wrong intersection point!!!\n";
1518template <
class Po
intT>
1519template<
class MeshT>
1525 const typename MeshT::FaceHandle& _fh0,
1526 const typename MeshT::FaceHandle& _fh1,
1527 std::vector<Point> & _points,
1528 std::vector<typename MeshT::EdgeHandle>& _ehandles )
1534 Point p_start = _p0;
1537 typename MeshT::FaceHandle fh_start = _fh0;
1538 typename MeshT::FaceHandle fh_end = _fh1;
1540 if( fh_start == fh_end)
1544 std::vector<Point> new_points0, new_points1;
1547 std::vector<typename MeshT::EdgeHandle> new_eh0, new_eh1;
1557 Point p1 = (Point)_mesh.point(_mesh.
to_vertex_handle( heh = _mesh.next_halfedge_handle(heh) ));
1558 Point p2 = (Point)_mesh.point(_mesh.
to_vertex_handle( heh = _mesh.next_halfedge_handle(heh) ));
1559 Point n_start = ((p1-p0)%(p2-p0)).normalize();
1564 p1 = _mesh.point(_mesh.
to_vertex_handle( heh = _mesh.next_halfedge_handle(heh) ));
1565 p2 = _mesh.point(_mesh.
to_vertex_handle( heh = _mesh.next_halfedge_handle(heh) ));
1566 Point n_end = ((p1-p0)%(p2-p0)).normalize();
1569 Point n_avg = n_start + n_end;
1570 if( n_avg.sqrnorm() < 1e-7) n_avg = n_start - n_end;
1574 Point n_plane = n_avg % (p_start-p_end).normalize();
1575 if( n_plane.sqrnorm() > 1e-9) n_plane.normalize();
1576 else std::cerr <<
"WARNING: Edge Resampling -> not possible to construct stable cut plane!!!\n";
1577 Point p_plane = (p_start + p_end)*0.5;
1580 std::vector<typename MeshT::HalfedgeHandle > start_hehs;
1581 std::vector<Point> start_ps;
1584 for(
unsigned int i=0; i<3; ++i)
1591 if( plane_line_intersection( p_plane, n_plane, p0, p1, p_int))
1593 start_hehs.push_back( heh );
1594 start_ps.push_back(p_int);
1597 heh = _mesh.next_halfedge_handle(heh);
1602 std::vector<typename MeshT::HalfedgeHandle > end_hehs;
1603 std::vector<Point> end_ps;
1605 for(
unsigned int i=0; i<3; ++i)
1612 if( plane_line_intersection( p_plane, n_plane, p0, p1, p_int))
1614 end_hehs.push_back( heh );
1615 end_ps.push_back(p_int);
1618 heh = _mesh.next_halfedge_handle(heh);
1623 if( start_hehs.size() != 2 || end_hehs.size() != 2)
1625 std::cerr <<
"PolyLineResampling ERROR: wrong number of intersections... ";
1626 std::cerr << start_hehs.size() <<
" ";
1627 std::cerr << end_hehs.size() << std::endl;
1633 if( start_hehs.size() == 2 && end_hehs.size() == 2)
1636 typename MeshT::HalfedgeHandle cur_heh0 = start_hehs[0];
1637 typename MeshT::HalfedgeHandle cur_heh1 = start_hehs[1];
1640 new_points0.push_back( start_ps[0]);
1643 new_points1.push_back( start_ps[1]);
1646 unsigned int count = 0;
1648 while( _mesh.face_handle(_mesh.opposite_halfedge_handle(cur_heh0)) != fh_end &&
1649 _mesh.face_handle(_mesh.opposite_halfedge_handle(cur_heh1)) != fh_end &&
1655 cur_heh0 = _mesh.opposite_halfedge_handle( cur_heh0);
1658 if( _mesh.is_boundary(cur_heh0))
1660 std::cerr <<
"ERROR: found boundary in traversal!!!\n";
1661 cur_heh0 = _mesh.opposite_halfedge_handle( cur_heh0);
1664 unsigned int old_size = new_points0.size();
1666 for(
unsigned int i=0; i<2; ++i)
1669 cur_heh0 = _mesh.next_halfedge_handle(cur_heh0);
1676 if( plane_line_intersection( p_plane, n_plane, p0, p1, p_int))
1678 new_points0.push_back(p_int);
1685 if( new_points0.size() != old_size + 1)
1686 std::cerr <<
"WARNING: could not find new point!!!\n";
1690 cur_heh1 = _mesh.opposite_halfedge_handle( cur_heh1);
1693 if( _mesh.is_boundary(cur_heh1))
1695 std::cerr <<
"ERROR: found boundary in traversal!!!\n";
1696 cur_heh1 = _mesh.opposite_halfedge_handle( cur_heh1);
1699 unsigned int old_size = new_points1.size();
1701 for(
unsigned int i=0; i<2; ++i)
1704 cur_heh1 = _mesh.next_halfedge_handle(cur_heh1);
1711 if( plane_line_intersection( p_plane, n_plane, p0, p1, p_int))
1713 new_points1.push_back(p_int);
1720 if( new_points1.size() != old_size + 1)
1721 std::cerr <<
"WARNING: could not find new point!!!\n";
1731 if(_mesh.face_handle(_mesh.opposite_halfedge_handle(cur_heh0)) == fh_end )
1734 _points = new_points0;
1735 _ehandles = new_eh0;
1738 if (_mesh.face_handle(_mesh.opposite_halfedge_handle(cur_heh1)) == fh_end)
1741 _points = new_points1;
1742 _ehandles = new_eh1;
1751template <
class Po
intT>
1758 for(
int i=0; i<int(n_vertices()); ++i)
1760 int i_next = (i+1) %
int(n_vertices());
1762 if( (point(i) - point(i_next)).norm() < _epsilon)
1764 if( vertex_ehandles_available())
1766 if( !_keep_edge_vertices || vertex_ehandle(i_next) == -1)
1768 delete_point(i_next);
1772 if( vertex_ehandle(i) == -1)
1780 delete_point(i_next);
1788 for(
int i=0; i<int(n_vertices())-1; ++i)
1790 int i_next = (i+1) %
int(n_vertices());
1792 if( (point(i) - point(i_next)).norm() < _epsilon)
1794 if( vertex_ehandles_available())
1796 if( !_keep_edge_vertices || vertex_ehandle(i_next) == -1)
1798 if(i_next !=
int(n_vertices())-1)
1800 delete_point(i_next);
1803 else delete_point(i);
1806 if( vertex_ehandle(i) == -1)
1817 if(i_next !=
int(n_vertices())-1)
1819 delete_point(i_next);
1822 else delete_point(i);
1833template <
class Po
intT>
1834typename PolyLineT<PointT>::Scalar
1841 if (!edge_normals_available() || !is_closed()) {
1842 std::cerr <<
"Warning: PolyLineT::total_gaussian_curvature requires a closed loop and edge normals!!!\n";
1846 for (
unsigned int i = 0; i < n_edges(); ++i) {
1848 Point e0 = edge_vector(i);
1849 Point n0 = edge_normal(i);
1850 Point e1 = edge_vector((i + 1) % n_edges());
1851 Point n1 = edge_normal((i + 1) % n_edges());
1854 if (e0.norm() > 1e-8)
1857 std::cerr <<
"Warning: e0 is undefined...\n";
1860 if (e1.norm() > 1e-8)
1863 std::cerr <<
"Warning: e1 is undefined...\n";
1868 if (n0.norm() > 1e-4)
1871 std::cerr <<
"Warning: n0 is undefined...\n";
1874 if (n1.norm() > 1e-4)
1877 std::cerr <<
"Warning: n1 is undefined...\n";
1886 if (b0.norm() > 1e-8)
1889 std::cerr <<
"Warning: b0 is undefined...\n";
1901 if (d.norm() < 1e-3)
1907 double dp = (-e0 | d);
1908 dp = std::max(-1.0, dp);
1909 dp = std::min(1.0, dp);
1912 double boundary_angle = acos(dp);
1915 dp = std::max(-1.0, dp);
1916 dp = std::min(1.0, dp);
1919 boundary_angle += acos(dp);
1921 gcurv += M_PI - boundary_angle;
1925 return (2.0 * M_PI - gcurv);
1928template <
class Po
intT>
1929template <
class MeshT>
1933 MeshT> &component) {
1935 const MeshT &mesh = component.getMesh();
1937 for (
auto f_it : mesh.faces()) {
1938 component[f_it] = 0;
1941 unsigned int current_component = 0;
1942 for (
auto f_it : mesh.faces()) {
1944 if (component[f_it] != 0)
1947 ++current_component;
1952 std::stack<typename OpenMesh::SmartFaceHandle> dfs;
1955 while (!dfs.empty()) {
1958 component[fh] = current_component;
1964 for (
auto ff_it : fh.
faces()) {
1966 if (component[ff_it] == 0)
1971 std::cout <<
"\x1b[33mmark_components: Mesh has " << current_component
1972 <<
" components.\x1b[0m" << std::endl;
1976template <
class Po
intT>
1977template<
class MeshT,
class SpatialSearchT>
1983 SpatialSearchT &_ssearch) {
1985 typename MeshT::FaceHandle fh;
1986 find_nearest_point(component.getMesh(), pt, fh, _ssearch);
1990 return component[fh];
1993template <
class Po
intT>
1994template <
class MeshT,
class SpatialSearchT>
1997 SpatialSearchT &_ssearch) {
1999 if (points_.empty())
return false;
2003 "component.on_multiple_components.objecttypes.polyline"
2004 ".i8.informatik.rwth-aachen.de");
2007 mark_components(component);
2009 const unsigned int first_component =
2010 component_of(component, points_.front(), _ssearch);
2012 for (
typename std::vector<PointT>::iterator pt_it = ++points_.begin(),
2013 pt_end = points_.end(); pt_it != pt_end; ++pt_it) {
2015 if (first_component != component_of(component, *pt_it, _ssearch))
2022template <
class Po
intT>
2023template <
class MeshT,
class SpatialSearchT>
2026 SpatialSearchT &_ssearch,
2027 std::vector<PolyLineT> &out_polylines) {
2029 if (points_.size() < 2)
return;
2033 "component.split_into_one_per_component.objecttypes.polyline"
2034 ".i8.informatik.rwth-aachen.de");
2036 mark_components(component);
2039 current_polyLine.
add_point(points_.front());
2040 unsigned int current_component =
2041 component_of(component, points_.front(), _ssearch);
2043 for (
typename std::vector<PointT>::iterator pt_it = ++points_.begin(),
2044 pt_end = points_.end(); pt_it != pt_end; ++pt_it) {
2050 const unsigned int next_comp = component_of(component, *pt_it, _ssearch);
2051 if (next_comp == current_component) {
2061 PointT p0 = current_polyLine.
back();
2062 const PointT p1 = *pt_it;
2063 unsigned int comp = next_comp;
2066 const double dist = (p0 - p1).norm();
2068 double firstOut = 1;
2073 static const double EPSILON = 1e-12;
2074 while ((firstOut - lastIn) * dist > EPSILON) {
2075 const double new_pos = .5 * (lastIn + firstOut);
2076 const PointT new_pt = p0 * (1.0 - new_pos) + p1 * new_pos;
2077 const unsigned int new_comp =
2078 component_of(component, new_pt, _ssearch);
2080 if (new_comp == current_component) {
2089 current_polyLine.
add_point(p0 * (1.0 - lastIn) + p1 * lastIn);
2091 out_polylines.push_back(current_polyLine);
2092 current_polyLine.
clear();
2093 current_polyLine.
add_point(p0 * (1.0 - firstOut) + p1 * firstOut);
2094 current_component = comp;
2097 p0 = p0 * (1.0 - firstOut) + p1 * firstOut;
2098 }
while (comp != next_comp);
2100 if (current_polyLine.
back() != *pt_it)
2105 out_polylines.push_back(current_polyLine);
2108 if(out_polylines.size() <= 1)
2110 out_polylines.clear();
2111 out_polylines.push_back(*
this);
2115template <
class Po
intT>
2117 size_t n = cprop_enum.size();
2118 for (
int i = 0; i < n; ++i)
2119 if (cprop_enum[i] == _prop)
2124template <
class Po
intT>
2125typename PolyLineT<PointT>::CustomProperty* PolyLineT<PointT>::custom_prop(CustomPropertyHandle _handle) {
2126 return (_handle >= 0 && _handle <
int(get_num_custom_properties()) ? cprop_enum[_handle] : NULL);
2129template <
class Po
intT>
2130const typename PolyLineT<PointT>::CustomProperty* PolyLineT<PointT>::custom_prop(CustomPropertyHandle _handle)
const {
2131 return (_handle >= 0 && _handle <
int(get_num_custom_properties()) ? cprop_enum[_handle] : NULL);
2134template <
class Po
intT>
2135typename PolyLineT<PointT>::CustomPropertyHandle PolyLineT<PointT>::
2136 request_custom_property(
const std::string& _name,
2137 unsigned int _prop_size) {
2139 CustomPropertyHandle h = get_custom_property_handle(_name);
2140 CustomProperty* pcontainer = custom_prop(h);
2145 pcontainer =
new CustomProperty;
2147 pcontainer->name = _name;
2148 pcontainer->ref_count = 1;
2149 pcontainer->prop_size = _prop_size;
2151 pcontainer->datatype = 0;
2153 pcontainer->prop_data.resize(n_vertices() * _prop_size, 0);
2155 custom_properties[_name] = pcontainer;
2157 cprop_enum.push_back(pcontainer);
2160 if (++pcontainer->ref_count < 1)
2161 pcontainer->ref_count = 1;
2164 return custom_prop_handle(pcontainer);
2167template <
class Po
intT>
2168void PolyLineT<PointT>::
2169 release_custom_property(CustomPropertyHandle _prop_handle) {
2171 CustomProperty* p = custom_prop(_prop_handle);
2173 if (p && --(p->ref_count) <= 0)
2174 p->prop_data.clear();
2177template <
class Po
intT>
2178void PolyLineT<PointT>::
2179 release_custom_property(
const std::string& _name) {
2181 CustomPropertyHandle h = get_custom_property_handle(_name);
2182 release_custom_property(h);
2185template <
class Po
intT>
2186typename PolyLineT<PointT>::CustomPropertyHandle PolyLineT<PointT>::
2187 get_custom_property_handle(
const std::string& _name)
const {
2189 typename CustomPropertyMap::const_iterator it = custom_properties.find(_name);
2191 if (it == custom_properties.end())
2194 return custom_prop_handle(it->second);
2197template <
class Po
intT>
2198const std::string PolyLineT<PointT>::
2199 get_custom_property_name(CustomPropertyHandle _property_handle)
const {
2201 const CustomProperty* p = custom_prop(_property_handle);
2206 std::cerr <<
"PolyLineT::get_custom_property_name - invalid handle" << std::endl;
2212template <
class Po
intT>
2213void PolyLineT<PointT>::
2214 set_custom_property(CustomPropertyHandle _property_handle,
2216 const void* _data) {
2219 std::cerr <<
"PolyLineT::set_custom_property - invalid data" << std::endl;
2223 CustomProperty* p = custom_prop(_property_handle);
2226 unsigned int offset = p->prop_size * _i;
2229 if (offset + p->prop_size > p->prop_data.size()) {
2230 std::cerr <<
"PolyLineT::set_custom_property - out of range access" << std::endl;
2236 memcpy(p->buffer() + offset, _data, p->prop_size);
2239 std::cerr <<
"PolyLineT::set_custom_property - invalid handle" << std::endl;
2242template <
class Po
intT>
2243void PolyLineT<PointT>::
2244 set_custom_property(
const std::string& _name,
2246 const void* _data) {
2248 CustomPropertyHandle h = get_custom_property_handle(_name);
2249 set_custom_property(h, _i, _data);
2252template <
class Po
intT>
2253void PolyLineT<PointT>::
2254 get_custom_property(CustomPropertyHandle _property_handle,
2259 std::cerr <<
"PolyLineT::get_custom_property - invalid destination address" << std::endl;
2263 const CustomProperty* p = custom_prop(_property_handle);
2267 unsigned int offset = p->prop_size * _i;
2270 if (offset + p->prop_size > p->prop_data.size()) {
2271 std::cerr <<
"PolyLineT::get_custom_property - out of range access" << std::endl;
2276 memcpy(_dst, p->buffer() + offset, p->prop_size);
2279 std::cerr <<
"PolyLineT::get_custom_property - invalid handle" << std::endl;
2282template <
class Po
intT>
2283void PolyLineT<PointT>::
2284 get_custom_property(
const std::string& _name,
2286 void* _data)
const {
2288 CustomPropertyHandle h = get_custom_property_handle(_name);
2289 get_custom_property(h, _i, _data);
2293template <
class Po
intT>
2294bool PolyLineT<PointT>::
2295 custom_property_available(CustomPropertyHandle _property_handle)
const {
2297 const CustomProperty* p = custom_prop(_property_handle);
2300 return p->ref_count > 0;
2306template <
class Po
intT>
2307bool PolyLineT<PointT>::
2308 custom_property_available(
const std::string& _name)
const {
2310 CustomPropertyHandle h = get_custom_property_handle(_name);
2311 return custom_property_available(h);
2315template <
class Po
intT>
2323 p->datatype = _datatype;
2324 p->shader_binding = _shader_input_name;
2327 std::cerr <<
"PolyLineT::bind_custom_property_to_shader - invalid handle" << std::endl;
2331template <
class Po
intT>
2340 *_propsize = p->prop_size;
2343 *_input_name = p->shader_binding.c_str();
2346 *_datatype = p->datatype;
2348 return !p->shader_binding.empty() && p->datatype;
2351 std::cerr <<
"PolyLineT::get_custom_property_shader_binding - invalid handle" << std::endl;
2356template <
class Po
intT>
2360 const CustomProperty* p = custom_prop(_property_handle);
2365 std::cerr <<
"PolyLineT::get_custom_property_buffer - invalid handle" << std::endl;
2370template <
class Po
intT>
2371unsigned int PolyLineT<PointT>::
2372 get_num_custom_properties()
const {
2373 return custom_properties.size();
2376template <
class Po
intT>
2377typename PolyLineT<PointT>::CustomPropertyHandle PolyLineT<PointT>::
2378 enumerate_custom_property_handles(
unsigned int _i)
const {
2380 if (_i < get_num_custom_properties())
2381 return CustomPropertyHandle(_i);
size_t n_vertices() const
Get number of vertices.
void split_closed(unsigned int _split_idx)
Split closed polyline at vertex with index _split_idx.
void smooth_uniform_laplace()
Laplacian smoothing.
void insert_point(int _idx, const Point &_p)
insert _p at _idx into polyline
bool on_multiple_components(MeshT &_mesh, SpatialSearchT &_ssearch)
void set_closed(const bool _c)
Set if the polyline should be closed and therefore forms a loop.
void bind_custom_property_to_shader(CustomPropertyHandle _property_handle, const std::string &_shader_input_name, unsigned int _datatype)
Binding to vertex shader (optional)
void print() const
Print information string to cerr.
void mark_components(OpenMesh::PropertyManager< OpenMesh::FPropHandleT< unsigned int >, MeshT > &component)
Point position_arclength(const Scalar _t) const
Same as position but with an arclength parameterization in [0,length()].
LineNodeT * get_line_node(LineNodeT *&_line_node, int _mode=0)
Conversion PolyLine <-> LineNode.
void remove_subsequent_identical_points(const bool _keep_edge_vertices=false, const double _epsilon=1e-6)
remove points which are subsequent and lie at the same position
Point & point(unsigned int _i)
Get a point of the polyline.
Point find_nearest_point(const MeshT &_mesh, const Point &_point, typename MeshT::FaceHandle &_fh, SpatialSearchT *_ssearch=0, double *_dbest=0)
unsigned int component_of(const OpenMesh::PropertyManager< OpenMesh::FPropHandleT< unsigned int >, MeshT > &component, const PointT &pt, SpatialSearchT &_ssearch)
bool get_custom_property_shader_binding(CustomPropertyHandle _property_handle, unsigned int *_propsize, const char **_input_name, unsigned int *_datatype) const
Get shader binding information.
Point position(const Scalar _t) const
Provide linear paremterization of the polyline in [0,1].
size_t n_edges() const
Get number of edges.
PolyLineT(bool _closed=false)
Constructor.
void resample_arclength_uniform(const unsigned int _n)
Perform an uniform arclength resampling while maintaining the start and end point.
void delete_point(int _idx)
Delete point at _idx.
void resize(unsigned int _n)
Resize current polyline.
void collapse(Scalar _smallest)
Collapse polyline.
void smooth_uniform_laplace2()
Squared laplacian smoothing.
void prepend(const PolyLineT< PointT > &_pl)
Prepend second polyline _pl to polyline.
void invert()
Invert polyline that first vertex becomes last.
void project_to_mesh(const MeshT &_mesh, SpatialSearchT *_ssearch=0)
Project polyline points to nearest surface points (use spatial search!!!)
void smooth_uniform_laplace3()
Cubic laplacian smoothing.
void subdivide(Scalar _largest)
Subdivide polyline.
bool is_closed() const
Check if the polyline is marked as closed.
void split(unsigned int _split_idx, PolyLineT< PointT > &_new_pl)
Split closed polyline at vertex with index _split_idx.
Scalar length() const
Compute the length of the polyline (in future cached method)
void clear()
Clear the current polyline.
void set_line_node(LineNodeT *&_line_node, int _mode=0)
Takes a line node and sets the points of this polyline to the points of the node.
void set_to_circle(const PointT _center, const PointT _normal, double _radius, unsigned int _n_samples=100)
creating a circle with center _center and radius _radius lying in tangent plane specified by _normal
void add_point(const Point &_p)
Append a point to the polyline.
bool plane_line_intersection(const IPoint &_p_plane, const IPoint &_n_plane, const IPoint &_p0, const IPoint &_p1, IPoint &_p_int)
Scalar total_gaussian_curvature()
compute total gaussian curvature of enclosed surface (via Gauss-Bonnet)
void append(const PolyLineT< PointT > &_pl)
Append second polyline _pl to this one.
void split_into_one_per_component(MeshT &_mesh, SpatialSearchT &_ssearch, std::vector< PolyLineT > &out_polylines)
Point & back()
Get last point of the polyline ( no range check!!!)
static HalfEdgeHandle halfedge_handle(EdgeHandle _h, const unsigned char _subIdx)
Conversion function.
static EdgeHandle edge_handle(HalfEdgeHandle _h)
Handle conversion.
VertexHandle from_vertex_handle(HalfEdgeHandle _h) const
Get the vertex the halfedge starts from.
VertexHandle to_vertex_handle(HalfEdgeHandle _h) const
Get the vertex the halfedge points to.
VectorT< Scalar, 3 > perpendicular(const VectorT< Scalar, 3 > &v)
find a vector that's perpendicular to _v
Namespace providing different geometric functions concerning angles.
PolyConnectivity::ConstFaceFaceRange faces() const
Returns a range adjacent faces of the face (PolyConnectivity::ff_range())