Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
PolyLineT.cc
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43  * *
44  * $Revision$ *
45  * $Author$ *
46  * $Date$ *
47  * *
48 \*===========================================================================*/
49 
50 
51 
52 //=============================================================================
53 //
54 // CLASS PolyLineT - IMPLEMENTATION
55 //
56 //=============================================================================
57 
58 #define ACG_POLYLINET_C
59 
60 //== INCLUDES =================================================================
61 
62 #include <OpenMesh/Core/Geometry/VectorT.hh>
63 
64 #include <iostream>
65 #include <fstream>
66 #include <map>
67 #include <stack>
68 
69 #include "PolyLineT.hh"
70 
71 #include <cfloat>
72 #include <ACG/Geometry/Algorithms.hh>
73 #include <ACG/Utils/VSToolsT.hh>
74 
75 #ifndef WIN32
76 #include <cstdlib>
77 #endif
78 
79 #include <cstring>
80 
81 #ifdef USE_OPENMP
82 #include <omp.h>
83 #endif
84 
85 //== NAMESPACES ===============================================================
86 
87 namespace ACG {
88 
89 //== IMPLEMENTATION ==========================================================
90 
91 //-----------------------------------------------------------------------------
92 
93 
95 template <class PointT>
97  PolyLineT( bool _closed )
98  : closed_(_closed),
99  vertex_radius_(0.01),
100  edge_radius_(0.01),
101  ref_count_vnormals_(0),
102  ref_count_vbinormals_(0),
103  ref_count_vcolors_(0),
104  ref_count_vscalars_(0),
105  ref_count_vselections_(0),
106  ref_count_vvhandles_(0),
107  ref_count_vehandles_(0),
108  ref_count_vfhandles_(0),
109  ref_count_enormals_(0),
110  ref_count_ecolors_(0),
111  ref_count_escalars_(0),
112  ref_count_eselections_(0),
113  ref_count_epreimage_direction_(0)
114 {
115 }
116 
117 //-----------------------------------------------------------------------------
118 
120 template <class PointT>
122  PolyLineT( const PolyLineT& _line )
123 {
124  closed_ = _line.closed_;
125 
126  //copy points
127  points_ = _line.points_;
128 
129  //copy vertex properties
130  vnormals_ = _line.vnormals_;
131  vbinormals_ = _line.vbinormals_;
132  vcolors_ = _line.vcolors_;
133  vscalars_ = _line.vscalars_;
134  vselections_ = _line.vselections_;
135  vvhandles_ = _line.vvhandles_;
136  vehandles_ = _line.vehandles_;
137  vfhandles_ = _line.vfhandles_;
138 
139  //copy edge properties
140  enormals_ = _line.enormals_;
141  ecolors_ = _line.ecolors_;
142  escalars_ = _line.escalars_;
143  eselections_ = _line.eselections_;
144  epreimage_direction_ = _line.epreimage_direction_;
145 
146  // property reference counter
147  ref_count_vnormals_ = _line.ref_count_vnormals_;
148  ref_count_vbinormals_ = _line.ref_count_vbinormals_;
149  ref_count_vcolors_ = _line.ref_count_vcolors_;
150  ref_count_vscalars_ = _line.ref_count_vscalars_;
151  ref_count_vselections_ = _line.ref_count_vselections_;
152  ref_count_vvhandles_ = _line.ref_count_vvhandles_;
153  ref_count_vehandles_ = _line.ref_count_vehandles_;
154  ref_count_vfhandles_ = _line.ref_count_vfhandles_;
155 
156  ref_count_enormals_ = _line.ref_count_enormals_;
157  ref_count_ecolors_ = _line.ref_count_ecolors_;
158  ref_count_escalars_ = _line.ref_count_escalars_;
159  ref_count_eselections_ = _line.ref_count_eselections_;
160  ref_count_epreimage_direction_ = _line.ref_count_epreimage_direction_;
161 
162 
163  // copy custom properties
164  for (typename CustomPropertyMap::const_iterator it = _line.custom_properties.begin(); it != _line.custom_properties.end(); ++it) {
165 
166  const CustomProperty* src = it->second;
167  CustomProperty* dst = new CustomProperty;
168 
169  dst->name = src->name;
170  dst->ref_count = src->ref_count;
171  dst->prop_size = src->prop_size;
172  dst->prop_data = src->prop_data;
173 
174  dst->datatype = src->datatype;
175  dst->shader_binding = src->shader_binding;
176 
177  custom_properties[it->first] = dst;
178  }
179 }
180 
181 //-----------------------------------------------------------------------------
182 
183 
184 template <class PointT>
185 void
188 {
189  points_.clear();
190 
191  // clear propertiy vectors
192  vnormals_.clear();
193  vbinormals_.clear();
194  vcolors_.clear();
195  vscalars_.clear();
196  vselections_.clear();
197  vvhandles_.clear();
198  vehandles_.clear();
199  vfhandles_.clear();
200 
201  enormals_.clear();
202  ecolors_.clear();
203  escalars_.clear();
204  eselections_.clear();
205  epreimage_direction_.clear();
206 
207  for (typename CustomPropertyMap::iterator it = custom_properties.begin(); it != custom_properties.end(); ++it)
208  delete it->second;
209  custom_properties.clear();
210 }
211 
212 //-----------------------------------------------------------------------------
213 
214 template <class PointT>
215 size_t
217 {
218  if (n_vertices() <= 1)
219  return 0;
220  else
221  return n_vertices() - 1 + (unsigned int) closed_;
222 }
223 
224 
225 //-----------------------------------------------------------------------------
226 
227 
228 template <class PointT>
229 void
231 resize( unsigned int _n)
232 {
233  if( _n < n_vertices())
234  {
235 
236  points_.resize( _n);
237 
238  // clear propertiy vectors
239  if( vertex_normals_available() )
240  vnormals_.resize( _n);
241  if( vertex_binormals_available() )
242  vbinormals_.resize( _n);
243  if( vertex_colors_available())
244  vcolors_.resize( _n);
245  if( vertex_scalars_available())
246  vscalars_.resize( _n);
247  if( vertex_selections_available())
248  vselections_.resize( _n);
249  if( vertex_vhandles_available())
250  vvhandles_.resize( _n);
251  if( vertex_ehandles_available())
252  vehandles_.resize( _n);
253  if( vertex_fhandles_available())
254  vfhandles_.resize( _n);
255 
256  if( edge_normals_available())
257  enormals_.resize( _n);
258  if( edge_colors_available())
259  ecolors_.resize( _n);
260  if( edge_scalars_available())
261  escalars_.resize( _n);
262  if( edge_preimage_directions_available())
263  epreimage_direction_.resize( _n);
264 
265 
266  for (typename CustomPropertyMap::iterator it = custom_properties.begin(); it != custom_properties.end(); ++it) {
267 
268  CustomProperty* p = it->second;
269 
270  p->prop_data.resize(p->prop_size * _n);
271  }
272 
273  }
274  else
275  {
276  while( n_vertices() < _n)
277  add_point( Point());
278  }
279 }
280 
281 
282 //-----------------------------------------------------------------------------
283 
284 
285 template <class PointT>
286 void
288 add_point(const Point& _p)
289 {
290  // add new point
291  points_.push_back( _p );
292 
293  // add available properties
294  if( vertex_normals_available() )
295  vnormals_.push_back( Point(0,0,0));
296 
297  if( vertex_binormals_available() )
298  vbinormals_.push_back( Point(0,0,0));
299 
300  if( vertex_colors_available())
301  vcolors_.push_back( Point(1,0,1));
302 
303  if( vertex_scalars_available())
304  vscalars_.push_back( 0.0 );
305 
306  if( vertex_selections_available())
307  vselections_.push_back( false);
308 
309  if( vertex_vhandles_available())
310  vvhandles_.push_back(-1);
311 
312  if( vertex_ehandles_available())
313  vehandles_.push_back(-1);
314 
315  if( vertex_fhandles_available())
316  vfhandles_.push_back(-1);
317 
318  if( edge_normals_available())
319  enormals_.push_back( Point(0,0,0));
320 
321  if( edge_colors_available())
322  ecolors_.push_back( Point(1,0,1));
323 
324  if( edge_scalars_available())
325  escalars_.push_back( 0.0);
326 
327  if( edge_selections_available())
328  eselections_.push_back(false);
329 
330  if( edge_preimage_directions_available())
331  epreimage_direction_.push_back(Point(0,0,0));
332 
333 
334  for (typename CustomPropertyMap::iterator it = custom_properties.begin(); it != custom_properties.end(); ++it) {
335 
336  CustomProperty* p = it->second;
337 
338  size_t cur_size = p->prop_data.size();
339 
340  p->prop_data.resize(cur_size + p->prop_size);
341 
342  if (p->buffer())
343  memset(p->buffer() + cur_size, 0, p->prop_size);
344  }
345 }
346 
347 //-----------------------------------------------------------------------------
348 
349 template <class PointT>
350 void
352 insert_point(int _idx, const Point& _p)
353 {
354  assert(_idx < (int)n_vertices() );
355 
356  // insert new point
357  points_.insert(points_.begin()+_idx, _p);
358 
359  // insert available properties
360  if( vertex_normals_available() )
361  vnormals_.insert(vnormals_.begin()+_idx, Point(0,0,0));
362 
363  if( vertex_binormals_available() )
364  vbinormals_.insert(vbinormals_.begin()+_idx, Point(0,0,0));
365 
366  if( vertex_colors_available())
367  vcolors_.insert(vcolors_.begin()+_idx, Point(1,0,1));
368 
369  if( vertex_scalars_available())
370  vscalars_.insert(vscalars_.begin()+_idx, 0.0 );
371 
372  if( vertex_selections_available())
373  vselections_.insert(vselections_.begin()+_idx, false);
374 
375  if( vertex_vhandles_available())
376  vvhandles_.insert(vvhandles_.begin()+_idx, -1);
377 
378  if( vertex_ehandles_available())
379  vehandles_.insert(vehandles_.begin()+_idx, -1);
380 
381  if( vertex_fhandles_available())
382  vfhandles_.insert(vfhandles_.begin()+_idx, -1);
383 
384  if( edge_normals_available())
385  enormals_.insert(enormals_.begin()+_idx, Point(0,0,0));
386 
387  if( edge_colors_available())
388  ecolors_.insert(ecolors_.begin()+_idx, Point(1,0,1));
389 
390  if( edge_scalars_available())
391  escalars_.insert(escalars_.begin()+_idx, 0.0);
392 
393  if( edge_selections_available())
394  eselections_.insert(eselections_.begin()+_idx, false);
395 
396  if( edge_preimage_directions_available())
397  epreimage_direction_.insert(epreimage_direction_.begin()+_idx, Point(0,0,0));
398 
399  // custom properties: insert byte-wise
400  for (typename CustomPropertyMap::iterator it = custom_properties.begin(); it != custom_properties.end(); ++it) {
401 
402  CustomProperty* p = it->second;
403  unsigned int offset = p->prop_size * _idx;
404 
405  for (unsigned int i = 0; i < p->prop_size; ++i)
406  p->prop_data.insert(p->prop_data.begin() + offset, 0);
407  }
408 }
409 
410 
411 //-----------------------------------------------------------------------------
412 
413 
414 template <class PointT>
415 void
417 delete_point(int _idx)
418 {
419  assert(_idx < (int)n_vertices() );
420 
421  // delete point at given index
422  points_.erase(points_.begin()+_idx);
423 
424 
425  // delete available properties
426  if( vertex_normals_available() )
427  vnormals_.erase(vnormals_.begin()+_idx);
428 
429  if( vertex_binormals_available() )
430  vbinormals_.erase(vbinormals_.begin()+_idx);
431 
432  if( vertex_colors_available())
433  vcolors_.erase(vcolors_.begin()+_idx);
434 
435  if( vertex_scalars_available())
436  vscalars_.erase(vscalars_.begin()+_idx);
437 
438  if( vertex_selections_available())
439  vselections_.erase(vselections_.begin()+_idx);
440 
441  if( vertex_vhandles_available())
442  vvhandles_.erase(vvhandles_.begin()+_idx);
443 
444  if( vertex_ehandles_available())
445  vehandles_.erase(vehandles_.begin()+_idx);
446 
447  if( vertex_fhandles_available())
448  vfhandles_.erase(vfhandles_.begin()+_idx);
449 
450  if( edge_normals_available())
451  enormals_.erase(enormals_.begin()+_idx);
452 
453  if( edge_colors_available())
454  ecolors_.erase(ecolors_.begin()+_idx);
455 
456  if( edge_scalars_available())
457  escalars_.erase(escalars_.begin()+_idx);
458 
459  if( edge_selections_available())
460  eselections_.erase(eselections_.begin()+_idx);
461 
462  if( edge_preimage_directions_available())
463  epreimage_direction_.erase(epreimage_direction_.begin()+_idx);
464 
465 
466  // custom properties: delete byte-wise
467  for (typename CustomPropertyMap::iterator it = custom_properties.begin(); it != custom_properties.end(); ++it) {
468 
469  CustomProperty* p = it->second;
470  unsigned int offset = p->prop_size * _idx;
471 
472  for (unsigned int i = 0; i < p->prop_size; ++i)
473  p->prop_data.erase(p->prop_data.begin() + offset);
474  }
475 }
476 
477 
478 //-----------------------------------------------------------------------------
479 
480 
481 template <class PointT>
482 typename PolyLineT<PointT>::Scalar
484 length() const
485 {
486  Scalar l = 0;
487 
488  unsigned int n = points_.size();
489 
490  if(!closed_)
491  {
492  for(unsigned int i=0; i<n-1; ++i)
493  {
494  l += (points_[(i+1)]-points_[i]).norm();
495  }
496  }
497  else
498  {
499  for(unsigned int i=0; i<n; ++i)
500  {
501  l += (points_[(i+1)%n]-points_[i]).norm();
502  }
503  }
504 
505  return l;
506 }
507 
508 
509 //-----------------------------------------------------------------------------
510 
511 
512 template <class PointT>
513 typename PolyLineT<PointT>::Point
515 position(const Scalar _t) const
516 {
517  assert(_t >=0.0 && _t<=1.0);
518  return position_arclength(_t*this->length());
519 }
520 
521 
522 //-----------------------------------------------------------------------------
523 
524 
525 template <class PointT>
526 typename PolyLineT<PointT>::Point
528 position_arclength(const Scalar _t) const
529 {
530  // handle degenerate polyline cases
531  if(this->n_vertices() < 2)
532  {
533  if(this->n_vertices() == 1)
534  return this->front();
535  else
536  {
537  std::cerr << "Warning: called position_arclength on emptu PolyLine!!!" << std::endl;
538  return Point(0,0,0);
539  }
540  }
541 
542  // return beginning of curve for negative parameter value
543  if(_t < 0.0)
544  return this->front();
545 
546  unsigned int nv = this->n_vertices();
547  unsigned int ne = this->n_edges();
548 
549  Scalar l = 0;
550 
551  for(unsigned int i=0; i<ne; ++i)
552  {
553  Scalar dl = (points_[(i+1)%nv]-points_[i]).norm();
554 
555  if(l <= _t && _t <= (l+dl))
556  {
557  Scalar tl = (_t-l)/dl;
558  if(!std::isfinite(tl))
559  tl = 0.0;
560  return (tl*points_[(i+1)%nv] + (1.0-tl)*points_[i]);
561  }
562 
563  l += dl;
564  }
565 
566  // return end of curve for too large parameter values
567  if(!closed_)
568  return this->back();
569  else
570  return this->front();
571 }
572 
573 
574 //-----------------------------------------------------------------------------
575 
576 
577 template <class PointT>
578 void
580 resample_arclength_uniform(const unsigned int _n)
581 {
582  unsigned int n = std::max((unsigned int)(2),_n);
583  Scalar l = this->length();
584 
585  // add new polyline with similar properties
586  PolyLineT<PointT> new_pl = *this;
587  // copy first point
588  new_pl.resize(n);
589  new_pl.copy_vertex_complete(*this, 0, 0);
590 
591  if(!closed_)
592  {
593  Scalar s = l/Scalar(n-1);
594  for(unsigned int i=1; i<n-1; ++i)
595  new_pl.point(i) = this->position_arclength(i*s);
596  }
597  else
598  {
599  Scalar s = l/Scalar(n);
600  for(unsigned int i=1; i<n; ++i)
601  new_pl.point(i) = this->position_arclength(i*s);
602  }
603 
604  // copy last point
605  if(!closed_)
606  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));
607 
608  // update polyline
609  *this = new_pl;
610 }
611 
612 
613 //-----------------------------------------------------------------------------
614 
615 
616 template <class PointT>
617 void
619 subdivide(Scalar _largest)
620 {
621  // check validity
622  if (!n_vertices())
623  return;
624 
625  unsigned int n_subdivisions = 1;
626 
627  while (n_subdivisions != 0) {
628 
629  n_subdivisions = 0;
630 
631  // add new polyline and add first point
632  PolyLineT<PointT> new_pl = *this;
633  new_pl.resize(1);
634  new_pl.copy_vertex_complete(*this, 0, 0);
635 
636  // squared maximal length
637  Scalar l2 = _largest * _largest;
638 
639  for (unsigned int i = 1; i < points_.size(); ++i) {
640  if ((new_pl.point(new_pl.n_vertices() - 1) - points_[i]).sqrnorm() > l2) {
641  Point mid_point = (new_pl.point(new_pl.n_vertices() - 1) + points_[i]) * 0.5;
642 
643  new_pl.add_point(mid_point);
644  ++n_subdivisions;
645  }
646 
647  // copy vertex
648  new_pl.resize(new_pl.n_vertices() + 1);
649  new_pl.copy_vertex_complete(*this, i, new_pl.n_vertices() - 1);
650  }
651 
652  // last interval for closed polyline
653  if (closed_) {
654  if ((new_pl.point(new_pl.n_vertices() - 1) - points_[0]).sqrnorm() > l2) {
655  Point mid_point = (new_pl.point(new_pl.n_vertices() - 1) + points_[0]) * 0.5;
656  new_pl.add_point(mid_point);
657  ++n_subdivisions;
658  }
659  }
660 
661  // update points
662  *this = new_pl;
663  }
664 }
665 
666 //-----------------------------------------------------------------------------
667 
668 
669 template <class PointT>
670 void
672 collapse(Scalar _smallest)
673 {
674  // check validity
675  if(!n_vertices()) return;
676 
677  unsigned int n_collapses = 1;
678 
679  unsigned int n_iter = 0;
680 
681  while( n_collapses != 0 && n_iter < 5)
682  {
683  ++n_iter;
684  n_collapses = 0;
685 
686  // create new PolyLine (with all properties) and insert first point
687  PolyLineT<PointT> new_pl = *this;
688  new_pl.resize(1);
689  new_pl.copy_vertex_complete( *this, 0, 0);
690 
691  // squared maximal length
692  Scalar l2 = _smallest*_smallest;
693 
694  for(unsigned int i=1; i<points_.size(); ++i)
695  {
696  // check whether vertex is selected
697  bool vertex_selected = false;
698  if( vertex_selections_available() && vertex_selection(i))
699  vertex_selected = true;
700 
701  if( (new_pl.point(new_pl.n_vertices()-1) - points_[i]).sqrnorm() >= l2 ||
702  vertex_selected ||
703  (!closed_ && i==points_.size()-1) )
704  {
705  // copy next point
706  new_pl.resize( new_pl.n_vertices()+1);
707  new_pl.copy_vertex_complete( *this, i, new_pl.n_vertices()-1);
708  }
709  else ++n_collapses;
710  }
711 
712  // last interval for closed polyline
713  if( closed_)
714  {
715  // check whether vertex is selected
716  bool vertex_selected = false;
717  if( vertex_selections_available() && vertex_selection(points_.size()-1))
718  vertex_selected = true;
719 
720  if( (new_pl.point(new_pl.n_vertices()-1) - points_[0]).sqrnorm() < l2 && !vertex_selected)
721  {
722  new_pl.resize( new_pl.n_vertices()-1);
723  }
724  else ++n_collapses;
725  }
726 
727  // update points
728  *this = new_pl;
729  }
730 }
731 
732 
733 //-----------------------------------------------------------------------------
734 
735 template <class PointT>
736 void
739 {
740  // copy point positions
741  std::vector<Point> points_old( points_ );
742 
743  int n = points_.size();
744 
745  int is = 0;
746  int ie = n;
747 
748  if( !closed_ )
749  {
750  ++is;
751  --ie;
752  }
753 
754  if( vertex_selections_available())
755  {
756  #ifdef USE_OPENMP
757  #pragma omp parallel for
758  #endif
759  for( int i=is; i<ie; ++i)
760  {
761  // only smooth not selected vertices
762  if( !vertex_selection(i))
763  // laplace stencil 1,-2,1
764  points_[i] = (points_old[ (i-1+n)%n ] +
765  points_old[ (i+n )%n ]*2.0 +
766  points_old[ (i+1 )%n ] )*0.25;
767 
768  }
769  }
770  else
771  {
772  #ifdef USE_OPENMP
773  #pragma omp parallel for
774  #endif
775  for( int i=is; i<ie; ++i)
776  {
777  // laplace stencil 1,-2,1
778  points_[i] = (points_old[ (i-1+n)%n ] +
779  points_old[ (i+n )%n ] * 2.0 +
780  points_old[ (i+1 )%n ] )*0.25;
781  }
782  }
783 }
784 
785 
786 //-----------------------------------------------------------------------------
787 
788 
789 template <class PointT>
790 void
793 {
794  // copy point positions
795  std::vector<Point> points_old( points_ );
796 
797  int n = points_.size();
798 
799  int is = 0;
800  int ie = n;
801 
802  if( !closed_ )
803  {
804  is+=2;
805  ie-=2;
806  }
807 
808  if( vertex_selections_available())
809  {
810  #ifdef USE_OPENMP
811  #pragma omp parallel for
812  #endif
813  for(int i=is; i<ie; ++i)
814  {
815  // only smooth not selected vertices
816  if( !vertex_selection(i))
817  // laplace^2 stencil 1,-4,6,-4,1
818  points_[i] -= (points_old[ (i-2+2*n)%n ] +
819  points_old[ (i-1+2*n)%n ]*-4.0 +
820  points_old[ (i )%n ]* 6.0 +
821  points_old[ (i+1 )%n ]*-4.0 +
822  points_old[ (i+2 )%n ] )/(16.0*2.0);
823  }
824  }
825  else
826  {
827  #ifdef USE_OPENMP
828  #pragma omp parallel for
829  #endif
830  for(int i=is; i<ie; ++i)
831  {
832  // laplace^2 stencil 1,-4,6,-4,1
833  points_[i] -= (points_old[ (i-2+2*n)%n ] +
834  points_old[ (i-1+2*n)%n ]*-4.0 +
835  points_old[ (i )%n ]* 6.0 +
836  points_old[ (i+1 )%n ]*-4.0 +
837  points_old[ (i+2 )%n ] )/(16.0*2.0);
838  }
839  }
840 }
841 
842 
843 //-----------------------------------------------------------------------------
844 
845 
846 template <class PointT>
847 void
850 {
851  // copy point positions
852  std::vector<Point> points_old( points_ );
853 
854  int n = points_.size();
855 
856  int is = 0;
857  int ie = n;
858 
859  if( !closed_ )
860  {
861  is+=3;
862  ie-=3;
863  }
864 
865  if( vertex_selections_available())
866  {
867  #ifdef USE_OPENMP
868  #pragma omp parallel for
869  #endif
870  for( int i=is; i<ie; ++i)
871  {
872  // only smooth not selected vertices
873  if( !vertex_selection(i))
874  // laplace^3 stencil 1,-6,15,-20,15,-6,1
875  points_[i] = (points_old[ (i-3+3*n)%n ] +
876  points_old[ (i-2+3*n)%n ]*(-6.0) +
877  points_old[ (i-1+3*n)%n ]*15.0 +
878  points_old[ (i ) ]*(44.0) +
879  points_old[ (i+1 )%n ]*15.0 +
880  points_old[ (i+2 )%n ]*(-6.0) +
881  points_old[ (i+3 )%n ] )/64.0;
882 
883  }
884  }
885  else
886  {
887  #ifdef USE_OPENMP
888  #pragma omp parallel for
889  #endif
890  for( int i=is; i<ie; ++i)
891  {
892  // laplace^3 stencil 1,-6,15,-20,15,-6,1
893  points_[i] = (points_old[ (i-3+3*n)%n ] +
894  points_old[ (i-2+3*n)%n ]*(-6.0) +
895  points_old[ (i-1+3*n)%n ]*15.0 +
896  points_old[ (i ) ]*(44.0) +
897  points_old[ (i+1 )%n ]*15.0 +
898  points_old[ (i+2 )%n ]*(-6.0) +
899  points_old[ (i+3 )%n ] )/64.0;
900  }
901  }
902 }
903 
904 
905 //-----------------------------------------------------------------------------
906 
907 
908 template <class PointT>
909 void
911 set_to_circle(const PointT _center, const PointT _normal, double _radius, unsigned int _n_samples)
912 {
913  this->clear();
914  this->set_closed(true);
915 
916  // get local basis vectors
917  PointT n = _normal; n.normalize();
918  PointT u = ACG::Geometry::perpendicular(_normal); u*=_radius/u.norm();
919  PointT v = n % u;
920 
921  for(unsigned int i=0; i<_n_samples; ++i)
922  {
923  double alpha = double(i)*2.0*M_PI/double(_n_samples);
924 
925  this->add_point(_center + u*cos(alpha) + v*sin(alpha));
926  }
927 }
928 
929 
930 //-----------------------------------------------------------------------------
931 
932 
933 template <class PointT>
934 template <class MeshT, class SpatialSearchT>
935 void
937 project_to_mesh( const MeshT& _mesh, SpatialSearchT * _ssearch)
938 {
939  typename MeshT::FaceHandle fh;
940 
941  #ifdef USE_OPENMP
942  #pragma omp parallel for
943  #endif
944  for(unsigned int i=0; i<points_.size(); ++i)
945  {
946  points_[i] = find_nearest_point( _mesh, points_[i], fh, _ssearch);
947  }
948 }
949 
950 
951 //-----------------------------------------------------------------------------
952 
953 
954 template <class PointT>
955 template <class MeshT, class SpatialSearchT>
956 void
958 project_to_mesh( const std::vector<MeshT*>& _mesh,
959  std::vector<SpatialSearchT*>* _ssearch)
960 {
961  typename MeshT::FaceHandle fh;
962 
963  #ifdef USE_OPENMP
964  #pragma omp parallel for
965  #endif
966  for(int i=0; i< (int)points_.size(); ++i)
967  {
968  // init d_best
969  typename MeshT::Scalar d_best = -1;
970 
971  // best point
972  Point p_best(0,0,0);
973 
974  // iterate over all possible meshes
975  for(unsigned int j=0; j<_mesh.size(); ++j)
976  {
977  double d_new(-1);
978 
979  Point p_new;
980  if(_ssearch != 0)
981  p_new = find_nearest_point( *(_mesh[j]), points_[i], fh, ((*_ssearch)[j]), &d_new);
982  else
983  p_new = find_nearest_point( *(_mesh[j]), points_[i], fh, (SpatialSearchT*)0, &d_new);
984 
985  // store best result
986  if( d_new < d_best || d_best == -1)
987  {
988  p_best = p_new;
989  d_best = d_new;
990  }
991  }
992 
993  if( d_best != -1)
994  points_[i] = p_best;
995  }
996 }
997 
998 
999 //-----------------------------------------------------------------------------
1000 
1001 
1002 template <class PointT>
1003 template <class MeshT, class SpatialSearchT>
1004 typename PolyLineT<PointT>::Point
1006 find_nearest_point( const MeshT& _mesh,
1007  const Point& _point,
1008  typename MeshT::FaceHandle& _fh,
1009  SpatialSearchT * _ssearch,
1010  double* _dbest)
1011 {
1012  typename MeshT::Point p0 = (typename MeshT::Point) _point;
1013 
1014  typename MeshT::Point p_best = _mesh.point(_mesh.vertex_handle(0));
1015  typename MeshT::Scalar d_best = (p0 - p_best).sqrnorm();
1016 
1017  typename MeshT::FaceHandle fh_best;
1018 
1019  if (_ssearch == 0) {
1020  // exhaustive search
1021  typename MeshT::ConstFaceIter cf_it = _mesh.faces_begin();
1022  typename MeshT::ConstFaceIter cf_end = _mesh.faces_end();
1023 
1024  for (; cf_it != cf_end; ++cf_it) {
1025  typename MeshT::ConstFaceVertexIter cfv_it = _mesh.cfv_iter(*cf_it);
1026 
1027  const typename MeshT::Point& pt0 = _mesh.point(*cfv_it);
1028  const typename MeshT::Point& pt1 = _mesh.point(*(++cfv_it));
1029  const typename MeshT::Point& pt2 = _mesh.point(*(++cfv_it));
1030 
1031  typename MeshT::Point ptn;
1032 
1033  typename MeshT::Scalar d = Geometry::distPointTriangleSquared(p0, pt0, pt1, pt2, ptn);
1034 
1035  if (d < d_best) {
1036  d_best = d;
1037  p_best = ptn;
1038 
1039  fh_best = *cf_it;
1040  }
1041  }
1042 
1043  // return face handle
1044  _fh = fh_best;
1045 
1046  // return distance
1047  if (_dbest)
1048  *_dbest = sqrt(d_best);
1049 
1050  return (Point) p_best;
1051  } else {
1052  typename MeshT::FaceHandle fh = _ssearch->nearest(p0).handle;
1053  typename MeshT::CFVIter fv_it = _mesh.cfv_iter(fh);
1054 
1055  const typename MeshT::Point& pt0 = _mesh.point(*fv_it);
1056  const typename MeshT::Point& pt1 = _mesh.point(*(++fv_it));
1057  const typename MeshT::Point& pt2 = _mesh.point(*(++fv_it));
1058 
1059  // project
1060  d_best = Geometry::distPointTriangleSquared(p0, pt0, pt1, pt2, p_best);
1061 
1062  // return facehandle
1063  _fh = fh;
1064 
1065  // return distance
1066  if (_dbest)
1067  *_dbest = sqrt(d_best);
1068 
1069  return (Point) p_best;
1070  }
1071 }
1072 
1073 //-----------------------------------------------------------------------------
1074 
1075 
1076 template <class PointT>
1077 template <class LineNodeT>
1078 LineNodeT*
1080 get_line_node(LineNodeT*& _line_node, int _mode)
1081 {
1082  typedef typename LineNodeT::value_type Vec3fL;
1083 
1084  if (_mode == 0) {
1085  // LineSegmentsMode
1086 
1087  // create LineNode
1088  _line_node = new LineNodeT(LineNodeT::LineSegmentsMode, 0, "PolyLine");
1089  _line_node->set_line_width(5.0);
1090  // _line_node->set_base_color(Vec4f(0,1,0,0));
1091  _line_node->set_base_color(
1092  OpenMesh::Vec4f(0.2 + double(rand()) / double(RAND_MAX) * 0.8, 0.2 + double(rand()) / double(RAND_MAX) * 0.8,
1093  0.2 + double(rand()) / double(RAND_MAX) * 0.8, 1.0));
1094 
1095  _line_node->show();
1096 
1097  // add line node
1098  for (unsigned int i = 0; i < this->points().size() - 1; ++i) {
1099  _line_node->add_line((Vec3fL) this->points()[i], (Vec3fL) this->points()[i + 1]);
1100  }
1101 
1102  // close loop
1103  if (closed_)
1104  if (!this->points().empty()) {
1105  _line_node->add_point((Vec3fL) this->points()[0]);
1106  }
1107 
1108  return _line_node;
1109  } else {
1110  // create LineNode
1111  _line_node = new LineNodeT(LineNodeT::PolygonMode, 0, "PolyLine");
1112  _line_node->set_line_width(5.0);
1113  // _line_node->set_base_color(Vec4f(0,1,0,0));
1114  _line_node->set_base_color(
1115  OpenMesh::Vec4f(0.2 + double(rand()) / double(RAND_MAX) * 0.8, 0.2 + double(rand()) / double(RAND_MAX) * 0.8,
1116  0.2 + double(rand()) / double(RAND_MAX) * 0.8, 1.0));
1117 
1118  _line_node->show();
1119 
1120  // add line node
1121  for (unsigned int i = 0; i < this->points().size(); ++i) {
1122  _line_node->add_point((Vec3fL) this->points()[i]);
1123  }
1124 
1125  // close loop
1126  if (closed_)
1127  if (!this->points().empty()) {
1128  _line_node->add_point((Vec3fL) this->points()[0]);
1129  }
1130 
1131  return _line_node;
1132  }
1133 }
1134 
1135 
1136 //-----------------------------------------------------------------------------
1137 
1138 
1139 template <class PointT>
1140 template <class LineNodeT>
1141 void
1143 set_line_node(LineNodeT*& _line_node, int _mode)
1144 {
1145  // typedef typename LineNodeT::value_type Vec3fL;
1146 
1147  // clear old values
1148  clear();
1149 
1150  if (_mode == 0) {
1151  // assume LineSegmentsMode
1152 
1153  const typename LineNodeT::PointVector& ln_points = _line_node->points();
1154 
1155  for (unsigned int i = 0; i < ln_points.size();) {
1156  if (i != ln_points.size() - 1)
1157  add_point((Point) ln_points[i]);
1158  else {
1159  // last point
1160  if ((ln_points[ln_points.size() - 1] - ln_points[0]).sqrnorm() == 0) {
1161  closed_ = true;
1162  } else {
1163  closed_ = false;
1164  add_point((Point) ln_points[i]);
1165  }
1166  }
1167 
1168  // increase counter
1169  if (i == 0)
1170  i += 1;
1171  else
1172  i += 2;
1173  }
1174  } else {
1175  // assume PolygonMode
1176  closed_ = true;
1177 
1178  const typename LineNodeT::PointVector& ln_points(_line_node->points());
1179 
1180  for (unsigned int i = 0; i < ln_points.size(); ++i) {
1181  add_point((Point) ln_points[i]);
1182  }
1183  }
1184 }
1185 
1186 
1187 //-----------------------------------------------------------------------------
1188 
1189 
1190 template <class PointT>
1191 void
1193 print() const
1194 {
1195  std::cerr << "****** PolyInfo ******\n";
1196  std::cerr << "closed : " << closed_ << std::endl;
1197  std::cerr << "#points: " << points_.size() << std::endl;
1198  for(unsigned int i=0; i<points_.size(); ++i)
1199  std::cerr << points_[i] << std::endl;
1200 }
1201 
1202 
1203 //-----------------------------------------------------------------------------
1204 
1205 
1206 template <class PointT>
1207 template <class PropT>
1208 void
1210 request_prop( unsigned int& _ref_count, PropT& _prop)
1211 {
1212  if(_ref_count == 0)
1213  {
1214  _ref_count = 1;
1215  // always use vertex size!!!
1216  _prop.resize(n_vertices());
1217  }
1218  else ++_ref_count;
1219 }
1220 
1221 
1222 //-----------------------------------------------------------------------------
1223 
1224 
1225 template <class PointT>
1226 template <class PropT>
1227 void
1228 PolyLineT<PointT>::
1229 release_prop( unsigned int& _ref_count, PropT& _prop)
1230 {
1231  if( _ref_count <= 1)
1232  {
1233  _ref_count = 0;
1234  _prop.clear();
1235  }
1236  else --_ref_count;
1237 }
1238 
1239 
1240 //-----------------------------------------------------------------------------
1241 
1242 
1243 template <class PointT>
1244 void
1245 PolyLineT<PointT>::
1246 copy_vertex_complete(const PolyLineT<PointT>& _pl, unsigned int _i, unsigned int _j)
1247 {
1248  // check range
1249  if( n_vertices() <= _j || _pl.n_vertices() <= _i)
1250  {
1251  std::cerr << "Warning: invalid range in PolyLine::copy_vertex_complete ( "
1252  << _i << " " << _j << " ) " << std::endl;
1253  return;
1254  }
1255 
1256  // copy point position
1257  point(_j) = _pl.point(_i);
1258 
1259  // copy properties if available
1260 
1261  // vertex normal
1262  if( _pl.vertex_normals_available())
1263  if( vertex_normals_available())
1264  vertex_normal(_j) = _pl.vertex_normal(_i);
1265 
1266  if( _pl.vertex_binormals_available())
1267  if( vertex_binormals_available())
1268  vertex_binormal(_j) = _pl.vertex_binormal(_i);
1269 
1270  // vertex colors
1271  if( _pl.vertex_colors_available())
1272  if( vertex_colors_available())
1273  vertex_color(_j) = _pl.vertex_color(_i);
1274 
1275  // vertex scalar
1276  if( _pl.vertex_scalars_available())
1277  if( vertex_scalars_available())
1278  vertex_scalar(_j) = _pl.vertex_scalar(_i);
1279 
1280  // vertex selection
1281  if( _pl.vertex_selections_available())
1282  if( vertex_selections_available())
1283  vertex_selection(_j) = _pl.vertex_selection(_i);
1284 
1285  // vertex vhandle
1286  if( _pl.vertex_vhandles_available())
1287  if( vertex_vhandles_available())
1288  vertex_vhandle(_j) = _pl.vertex_vhandle(_i);
1289 
1290  // vertex ehandle
1291  if( _pl.vertex_ehandles_available())
1292  if( vertex_ehandles_available())
1293  vertex_ehandle(_j) = _pl.vertex_ehandle(_i);
1294 
1295  // vertex vhandle
1296  if( _pl.vertex_ehandles_available())
1297  if( vertex_ehandles_available())
1298  vertex_ehandle(_j) = _pl.vertex_ehandle(_i);
1299 }
1300 
1301 
1302 //-----------------------------------------------------------------------------
1303 
1304 
1305 template <class PointT>
1306 void
1307 PolyLineT<PointT>::
1308 copy_edge_complete(const PolyLineT<PointT>& _pl, unsigned int _i, unsigned int _j)
1309 {
1310  // check range
1311  if( n_edges() <= _j || _pl.n_edges() <= _i)
1312  {
1313  std::cerr << "Warning: invalid range in PolyLine::copy_edge_complete ( "
1314  << _i << " " << _j << " ) " << std::endl;
1315  return;
1316  }
1317 
1318  // edge normal
1319  if( _pl.edge_selections_available())
1320  if( edge_selections_available())
1321  edge_selection(_j) = _pl.edge_selection(_i);
1322 
1323 
1324  // edge normal
1325  if( _pl.edge_normals_available())
1326  if( edge_normals_available())
1327  edge_normal(_j) = _pl.edge_normal(_i);
1328 
1329  // edge color
1330  if( _pl.edge_colors_available())
1331  if( edge_colors_available())
1332  edge_color(_j) = _pl.edge_color(_i);
1333 
1334  // edge scalar
1335  if( _pl.edge_scalars_available())
1336  if( edge_scalars_available())
1337  edge_scalar(_j) = _pl.edge_scalar(_i);
1338 
1339  // edge normal
1340  if( _pl.edge_selections_available())
1341  if( edge_selections_available())
1342  edge_selection(_j) = _pl.edge_selection(_i);
1343 
1344  // edge selection
1345  if( _pl.edge_selections_available())
1346  if( edge_selections_available())
1347  edge_selection(_j) = _pl.edge_selection(_i);
1348 }
1349 
1350 
1351 //-----------------------------------------------------------------------------
1352 
1353 
1354 template <class PointT>
1355 void
1358 {
1359  // inversion is only supported for open polylines
1360  if(is_closed())
1361  {
1362  std::cerr << "Warning: inversion for closed polylines is not supported!!!\n";
1363  return;
1364  }
1365 
1366  PolyLineT<PointT> pl_temp = *this;
1367 
1368  // copy vertices in reverse order
1369  for(unsigned int i=0; i<n_vertices(); ++i)
1370  pl_temp.copy_vertex_complete( *this, n_vertices()-1-i, i);
1371 
1372  // copy edges in reverse order
1373  for(unsigned int i=0; i<n_edges(); ++i)
1374  pl_temp.copy_edge_complete( *this, n_edges()-1-i, i);
1375 
1376  // save inverted polyline
1377  *this = pl_temp;
1378 }
1379 
1380 
1381 //-----------------------------------------------------------------------------
1382 
1383 
1384 template <class PointT>
1385 void
1388 {
1389  // operation not supported for closed polylines
1390  if( is_closed() || _pl.is_closed())
1391  {
1392  std::cerr << is_closed() << " " << _pl.is_closed() << std::endl;
1393  std::cerr << "Warning: appending not supported for closed polylines!!!\n";
1394  return;
1395  }
1396 
1397  unsigned int old_nv = n_vertices();
1398  unsigned int old_ne = n_edges();
1399 
1400  resize( n_vertices() + _pl.n_vertices());
1401 
1402  for( unsigned int i=0; i<_pl.n_vertices(); ++i)
1403  copy_vertex_complete( _pl, i, i+old_nv);
1404 
1405  for( unsigned int i=0; i<_pl.n_edges(); ++i)
1406  copy_edge_complete( _pl, i, i+old_ne+1);
1407 }
1408 
1409 
1410 //-----------------------------------------------------------------------------
1411 
1412 
1413 template <class PointT>
1414 void
1417 {
1418  PolyLineT<PointT> pl_temp = _pl;
1419 
1420  pl_temp.append(*this);
1421  *this = pl_temp;
1422 }
1423 
1424 
1425 //-----------------------------------------------------------------------------
1426 
1427 
1428 template <class PointT>
1429 void
1431 split_closed( unsigned int _split_idx)
1432 {
1433  if(!is_closed())
1434  {
1435  std::cerr << "Warning: split_closed was called for open polyline!\n";
1436  return;
1437  }
1438 
1439  // prepare new polyline
1440  PolyLineT<PointT> pl_temp = *this;
1441  pl_temp.resize(n_vertices()+1);
1442  pl_temp.set_closed( false);
1443 
1444 
1445  // splitted polyline has n+1 vertices
1446  for(unsigned int i=0; i<n_vertices()+1; ++i)
1447  pl_temp.copy_vertex_complete( *this, (i+_split_idx)%n_vertices(),i);
1448 
1449  for(unsigned int i=0; i<n_edges(); ++i)
1450  pl_temp.copy_edge_complete( *this, (i+_split_idx)%n_edges(),i);
1451 
1452  // copy updated polyline
1453  *this = pl_temp;
1454 }
1455 
1456 
1457 //-----------------------------------------------------------------------------
1458 
1459 
1460 template <class PointT>
1461 void
1463 split( unsigned int _split_idx, PolyLineT<PointT>& _new_pl)
1464 {
1465  if( is_closed() ) split_closed( _split_idx);
1466  else
1467  {
1468  // copy properties
1469  _new_pl = *this;
1470 
1471  _new_pl.resize( n_vertices() - _split_idx);
1472 
1473  // copy vertex data
1474  for(unsigned int i=_split_idx; i<n_vertices(); ++i)
1475  _new_pl.copy_vertex_complete(*this, i, i-_split_idx);
1476  // copy edge data
1477  for(unsigned int i=_split_idx; i<n_edges(); ++i)
1478  _new_pl.copy_edge_complete(*this, i, i-_split_idx);
1479 
1480  // cut copied part
1481  resize(_split_idx+1);
1482  }
1483 }
1484 
1485 
1486 //-----------------------------------------------------------------------------
1487 
1488 
1489 template <class PointT>
1490 template <class IPoint>
1491 bool
1493 plane_line_intersection( const IPoint& _p_plane,
1494  const IPoint& _n_plane,
1495  const IPoint& _p0,
1496  const IPoint& _p1,
1497  IPoint& _p_int)
1498 {
1499  double a = (_n_plane | (_p_plane - _p0));
1500  double b = (_n_plane | (_p1 - _p0));
1501 
1502  if (fabs(b) > 1e-9) {
1503  double s = a / b;
1504 
1505  if (s >= 0.0 && s <= 1.0) {
1506  _p_int = _p0 + (_p1 - _p0) * s;
1507 
1508  // TEST Intersection Point
1509  if (fabs((_n_plane | (_p_int - _p_plane))) > 1e-9)
1510  std::cerr << "WARNING: wrong intersection point!!!\n";
1511 
1512  return true;
1513  } else
1514  return false;
1515  } else
1516  return false;
1517 }
1518 
1519 
1520 //-----------------------------------------------------------------------------
1521 
1522 
1523 template <class PointT>
1524 template<class MeshT>
1525 void
1527 edge_points_in_segment( const MeshT& _mesh,
1528  const Point& _p0,
1529  const Point& _p1,
1530  const typename MeshT::FaceHandle _fh0,
1531  const typename MeshT::FaceHandle _fh1,
1532  std::vector<Point> & _points,
1533  std::vector<typename MeshT::EdgeHandle>& _ehandles )
1534 {
1535  // initialize
1536  _points.clear();
1537  _ehandles.clear();
1538 
1539  Point p_start = _p0;
1540  Point p_end = _p1;
1541 
1542  typename MeshT::FaceHandle fh_start = _fh0;
1543  typename MeshT::FaceHandle fh_end = _fh1;
1544 
1545  if( fh_start == fh_end)
1546  return;
1547 
1548  // vectors for new points
1549  std::vector<Point> new_points0, new_points1;
1550 
1551  // vector for new edgehandle
1552  std::vector<typename MeshT::EdgeHandle> new_eh0, new_eh1;
1553 
1554 // // insert first point
1555 // new_points0.push_back( p_start);
1556 // new_points1.push_back( p_start);
1557 
1558  // construct cut plane
1559  // get first normal
1560  typename MeshT::HalfedgeHandle heh = _mesh.halfedge_handle(fh_start);
1561  Point p0 = (Point)_mesh.point(_mesh.to_vertex_handle( heh ));
1562  Point p1 = (Point)_mesh.point(_mesh.to_vertex_handle( heh = _mesh.next_halfedge_handle(heh) ));
1563  Point p2 = (Point)_mesh.point(_mesh.to_vertex_handle( heh = _mesh.next_halfedge_handle(heh) ));
1564  Point n_start = ((p1-p0)%(p2-p0)).normalize();
1565 
1566  // get second normal
1567  heh = _mesh.halfedge_handle(fh_end);
1568  p0 = _mesh.point(_mesh.to_vertex_handle( heh ));
1569  p1 = _mesh.point(_mesh.to_vertex_handle( heh = _mesh.next_halfedge_handle(heh) ));
1570  p2 = _mesh.point(_mesh.to_vertex_handle( heh = _mesh.next_halfedge_handle(heh) ));
1571  Point n_end = ((p1-p0)%(p2-p0)).normalize();
1572 
1573  // get average normal
1574  Point n_avg = n_start + n_end;
1575  if( n_avg.sqrnorm() < 1e-7) n_avg = n_start - n_end;
1576  n_avg.normalize();
1577 
1578  // get plane data
1579  Point n_plane = n_avg % (p_start-p_end).normalize();
1580  if( n_plane.sqrnorm() > 1e-9) n_plane.normalize();
1581  else std::cerr << "WARNING: Edge Resampling -> not possible to construct stable cut plane!!!\n";
1582  Point p_plane = (p_start + p_end)*0.5;
1583 
1584  // get intersection halfedges of start triangle
1585  std::vector<typename MeshT::HalfedgeHandle > start_hehs;
1586  std::vector<Point> start_ps;
1587  heh = _mesh.halfedge_handle(fh_start);
1588  Point p_int;
1589  for(unsigned int i=0; i<3; ++i)
1590  {
1591  // edge endpoints
1592  p0 = (Point) _mesh.point(_mesh.from_vertex_handle(heh));
1593  p1 = (Point) _mesh.point(_mesh.to_vertex_handle (heh));
1594 
1595  // intersection ?
1596  if( plane_line_intersection( p_plane, n_plane, p0, p1, p_int))
1597  {
1598  start_hehs.push_back( heh );
1599  start_ps.push_back(p_int);
1600  }
1601  // move to next halfedge handle
1602  heh = _mesh.next_halfedge_handle(heh);
1603  }
1604 
1605  // DEBUG
1606  // get intersection halfedges of end triangle
1607  std::vector<typename MeshT::HalfedgeHandle > end_hehs;
1608  std::vector<Point> end_ps;
1609  heh = _mesh.halfedge_handle(fh_end);
1610  for(unsigned int i=0; i<3; ++i)
1611  {
1612  // edge endpoints
1613  p0 = (Point) _mesh.point(_mesh.from_vertex_handle(heh));
1614  p1 = (Point) _mesh.point(_mesh.to_vertex_handle (heh));
1615 
1616  // intersection ?
1617  if( plane_line_intersection( p_plane, n_plane, p0, p1, p_int))
1618  {
1619  end_hehs.push_back( heh );
1620  end_ps.push_back(p_int);
1621  }
1622  // move to next halfedge handle
1623  heh = _mesh.next_halfedge_handle(heh);
1624  }
1625  // END DEBUG
1626 
1627  // hack: debug hints
1628  if( start_hehs.size() != 2 || end_hehs.size() != 2)
1629  {
1630  std::cerr << "PolyLineResampling ERROR: wrong number of intersections... ";
1631  std::cerr << start_hehs.size() << " ";
1632  std::cerr << end_hehs.size() << std::endl;
1633  }
1634  // else std::cerr << "SUPI!!!\n";
1635  // end hack
1636 
1637 
1638  if( start_hehs.size() == 2 && end_hehs.size() == 2)
1639  {
1640  // initialize start points
1641  typename MeshT::HalfedgeHandle cur_heh0 = start_hehs[0];
1642  typename MeshT::HalfedgeHandle cur_heh1 = start_hehs[1];
1643 
1644  // store points and edge handles
1645  new_points0.push_back( start_ps[0]);
1646  new_eh0.push_back( _mesh.edge_handle( cur_heh0));
1647 
1648  new_points1.push_back( start_ps[1]);
1649  new_eh1.push_back( _mesh.edge_handle( cur_heh1));
1650 
1651  unsigned int count = 0;
1652 
1653  while( _mesh.face_handle(_mesh.opposite_halfedge_handle(cur_heh0)) != fh_end &&
1654  _mesh.face_handle(_mesh.opposite_halfedge_handle(cur_heh1)) != fh_end &&
1655  count < 1000 )
1656  {
1657  ++count;
1658 
1659  // move into first direction
1660  cur_heh0 = _mesh.opposite_halfedge_handle( cur_heh0);
1661 
1662  // test for boundary
1663  if( _mesh.is_boundary(cur_heh0))
1664  {
1665  std::cerr << "ERROR: found boundary in traversal!!!\n";
1666  cur_heh0 = _mesh.opposite_halfedge_handle( cur_heh0);
1667  } else {
1668 
1669  unsigned int old_size = new_points0.size();
1670 
1671  for(unsigned int i=0; i<2; ++i)
1672  {
1673  // move to next halfedge handle
1674  cur_heh0 = _mesh.next_halfedge_handle(cur_heh0);
1675 
1676  // edge endpoints
1677  p0 = (Point) _mesh.point(_mesh.from_vertex_handle(cur_heh0));
1678  p1 = (Point) _mesh.point(_mesh.to_vertex_handle (cur_heh0));
1679 
1680  // intersection ?
1681  if( plane_line_intersection( p_plane, n_plane, p0, p1, p_int))
1682  {
1683  new_points0.push_back(p_int);
1684  new_eh0.push_back( _mesh.edge_handle( cur_heh0));
1685  break;
1686  }
1687  }
1688 
1689  // debug helper
1690  if( new_points0.size() != old_size + 1)
1691  std::cerr << "WARNING: could not find new point!!!\n";
1692  }
1693 
1694  // move into second direction
1695  cur_heh1 = _mesh.opposite_halfedge_handle( cur_heh1);
1696 
1697  // test for boundary
1698  if( _mesh.is_boundary(cur_heh1))
1699  {
1700  std::cerr << "ERROR: found boundary in traversal!!!\n";
1701  cur_heh1 = _mesh.opposite_halfedge_handle( cur_heh1);
1702  } else {
1703 
1704  unsigned int old_size = new_points1.size();
1705 
1706  for(unsigned int i=0; i<2; ++i)
1707  {
1708  // move to next halfedge handle
1709  cur_heh1 = _mesh.next_halfedge_handle(cur_heh1);
1710 
1711  // edge endpoints
1712  p0 = (Point) _mesh.point(_mesh.from_vertex_handle(cur_heh1));
1713  p1 = (Point) _mesh.point(_mesh.to_vertex_handle (cur_heh1));
1714 
1715  // intersection ?
1716  if( plane_line_intersection( p_plane, n_plane, p0, p1, p_int))
1717  {
1718  new_points1.push_back(p_int);
1719  new_eh1.push_back( _mesh.edge_handle( cur_heh1));
1720  break;
1721  }
1722  }
1723 
1724  // debug helper
1725  if( new_points1.size() != old_size + 1)
1726  std::cerr << "WARNING: could not find new point!!!\n";
1727  }
1728 
1729  }
1730 
1731 // // add end points
1732 // new_points0.push_back( p_end );
1733 // new_points1.push_back( p_start );
1734 
1735  // set new points, test which direction converged first
1736  if(_mesh.face_handle(_mesh.opposite_halfedge_handle(cur_heh0)) == fh_end )
1737  {
1738  // return values
1739  _points = new_points0;
1740  _ehandles = new_eh0;
1741  }
1742  else
1743  if (_mesh.face_handle(_mesh.opposite_halfedge_handle(cur_heh1)) == fh_end)
1744  {
1745  // return values
1746  _points = new_points1;
1747  _ehandles = new_eh1;
1748  }
1749  }
1750 }
1751 
1752 
1753 //-----------------------------------------------------------------------------
1754 
1755 
1756 template <class PointT>
1757 void
1759 remove_subsequent_identical_points(const bool _keep_edge_vertices, const double _epsilon )
1760 {
1761  if(is_closed())
1762  {
1763  for( int i=0; i<int(n_vertices()); ++i)
1764  {
1765  int i_next = (i+1) % int(n_vertices());
1766 
1767  if( (point(i) - point(i_next)).norm() < _epsilon)
1768  {
1769  if( vertex_ehandles_available())
1770  {
1771  if( !_keep_edge_vertices || vertex_ehandle(i_next) == -1)
1772  {
1773  delete_point(i_next);
1774  --i;
1775  }
1776  else
1777  if( vertex_ehandle(i) == -1)
1778  {
1779  delete_point(i);
1780  --i;
1781  }
1782  }
1783  else // simply delete i_next
1784  {
1785  delete_point(i_next);
1786  --i;
1787  }
1788  }
1789  }
1790  }
1791  else
1792  {
1793  for( int i=0; i<int(n_vertices())-1; ++i)
1794  {
1795  int i_next = (i+1) % int(n_vertices());
1796 
1797  if( (point(i) - point(i_next)).norm() < _epsilon)
1798  {
1799  if( vertex_ehandles_available())
1800  {
1801  if( !_keep_edge_vertices || vertex_ehandle(i_next) == -1)
1802  {
1803  if(i_next != int(n_vertices())-1)
1804  {
1805  delete_point(i_next);
1806  --i;
1807  }
1808  else delete_point(i);
1809  }
1810  else
1811  if( vertex_ehandle(i) == -1)
1812  {
1813  if(i != 0)
1814  {
1815  delete_point(i);
1816  --i;
1817  }
1818  }
1819  }
1820  else // simply delete i_next
1821  {
1822  if(i_next != int(n_vertices())-1)
1823  {
1824  delete_point(i_next);
1825  --i;
1826  }
1827  else delete_point(i);
1828  }
1829  }
1830  }
1831  }
1832 }
1833 
1834 
1835 //-----------------------------------------------------------------------------
1836 
1837 
1838 template <class PointT>
1839 typename PolyLineT<PointT>::Scalar
1842 {
1843  // total gaussian curvature
1844  Scalar gcurv = 0.0;
1845 
1846  if (!edge_normals_available() || !is_closed()) {
1847  std::cerr << "Warning: PolyLineT::total_gaussian_curvature requires a closed loop and edge normals!!!\n";
1848  } else // closed and edge normals available
1849  {
1850  // sum over boundary
1851  for (unsigned int i = 0; i < n_edges(); ++i) {
1852  // get two consecutive edge vectors and corresponding normals
1853  Point e0 = edge_vector(i);
1854  Point n0 = edge_normal(i);
1855  Point e1 = edge_vector((i + 1) % n_edges());
1856  Point n1 = edge_normal((i + 1) % n_edges());
1857 
1858  // normalize edges
1859  if (e0.norm() > 1e-8)
1860  e0.normalize();
1861  else {
1862  std::cerr << "Warning: e0 is undefined...\n";
1863  continue;
1864  }
1865  if (e1.norm() > 1e-8)
1866  e1.normalize();
1867  else {
1868  std::cerr << "Warning: e1 is undefined...\n";
1869  continue;
1870  }
1871 
1872  // normalize normals
1873  if (n0.norm() > 1e-4)
1874  n0.normalize();
1875  else {
1876  std::cerr << "Warning: n0 is undefined...\n";
1877  continue;
1878  }
1879  if (n1.norm() > 1e-4)
1880  n1.normalize();
1881  else {
1882  std::cerr << "Warning: n1 is undefined...\n";
1883  continue;
1884  }
1885 
1886  // compute binormals
1887  Point b0 = n0 % e0;
1888  // Point b1 = n1%e0;
1889 
1890  // normalize binormals
1891  if (b0.norm() > 1e-8)
1892  b0.normalize();
1893  else {
1894  std::cerr << "Warning: b0 is undefined...\n";
1895  continue;
1896  }
1897  // if( b1.norm() > 1e-4) b1.normalize();
1898  // else std::cerr << "Warning: b1 is undefined...\n";
1899 
1900  // compute intersection of tangent planes
1901  Point d = n0 % n1;
1902  if ((d | b0) < 0) // reorientation necessary?
1903  d *= -1.0;
1904 
1905  // both in same tangent plane?
1906  if (d.norm() < 1e-3)
1907  d = b0;
1908  else
1909  d.normalize();
1910 
1911  // add both angles
1912  double dp = (-e0 | d);
1913  dp = std::max(-1.0, dp);
1914  dp = std::min(1.0, dp);
1915 
1916  // compute first boundary angle
1917  double boundary_angle = acos(dp);
1918 
1919  dp = (e1 | d);
1920  dp = std::max(-1.0, dp);
1921  dp = std::min(1.0, dp);
1922 
1923  // add second angle
1924  boundary_angle += acos(dp);
1925 
1926  gcurv += M_PI - boundary_angle;
1927  }
1928  }
1929  // return total gaussian curvature
1930  return (2.0 * M_PI - gcurv);
1931 }
1932 
1933 template <class PointT>
1934 template <class MeshT>
1938  MeshT> &component) {
1939 
1940  MeshT &mesh = component.getMesh();
1941 
1942  for (typename MeshT::FaceIter
1943  f_it = mesh.faces_begin(), f_end = mesh.faces_end();
1944  f_it != f_end; ++f_it) {
1945  component[*f_it] = 0;
1946  }
1947 
1948  unsigned int current_component = 0;
1949  for (typename MeshT::FaceIter f_it = mesh.faces_begin(),
1950  f_end = mesh.faces_end(); f_it != f_end; ++f_it) {
1951 
1952  if (component[*f_it] != 0)
1953  continue;
1954 
1955  ++current_component;
1956 
1957  /*
1958  * Flood fill component.
1959  */
1960  std::stack<typename MeshT::FaceHandle> dfs;
1961  dfs.push(*f_it);
1962 
1963  while (!dfs.empty()) {
1964  const typename MeshT::FaceHandle fh = dfs.top(); dfs.pop();
1965 
1966  component[fh] = current_component;
1967 
1968  /*
1969  * Visit neighbors, push them onto stack if they
1970  * haven't been visited yet.
1971  */
1972  for (typename MeshT::FFIter ff_it = mesh.ff_begin(fh),
1973  ff_end = mesh.ff_end(fh); ff_it != ff_end; ++ff_it) {
1974 
1975  if (component[*ff_it] == 0)
1976  dfs.push(*ff_it);
1977  }
1978  }
1979  }
1980  std::cout << "\x1b[33mmark_components: Mesh has " << current_component
1981  << " components.\x1b[0m" << std::endl;
1982 
1983 }
1984 
1985 template <class PointT>
1986 template<class MeshT, class SpatialSearchT>
1990  MeshT> &component,
1991  const PointT &pt,
1992  SpatialSearchT &_ssearch) {
1993 
1994  typename MeshT::FaceHandle fh;
1995  find_nearest_point(component.getMesh(), pt, fh, _ssearch);
1996 //#ifndef NDEBUG
1997 // std::cout << "Point(" << pt << ") on fh " << fh.idx() << std::endl;
1998 //#endif
1999  return component[fh];
2000 }
2001 
2002 template <class PointT>
2003 template <class MeshT, class SpatialSearchT>
2006  SpatialSearchT &_ssearch) {
2007 
2008  if (points_.empty()) return false;
2009 
2011  component(_mesh,
2012  "component.on_multiple_components.objecttypes.polyline"
2013  ".i8.informatik.rwth-aachen.de");
2014 
2015 
2016  mark_components(component);
2017 
2018  const unsigned int first_component =
2019  component_of(component, points_.front(), _ssearch);
2020 
2021  for (typename std::vector<PointT>::iterator pt_it = ++points_.begin(),
2022  pt_end = points_.end(); pt_it != pt_end; ++pt_it) {
2023 
2024  if (first_component != component_of(component, *pt_it, _ssearch))
2025  return true;
2026  }
2027 
2028  return false;
2029 }
2030 
2031 template <class PointT>
2032 template <class MeshT, class SpatialSearchT>
2035  SpatialSearchT &_ssearch,
2036  std::vector<PolyLineT> &out_polylines) {
2037 
2038  if (points_.size() < 2) return;
2039 
2041  component(_mesh,
2042  "component.split_into_one_per_component.objecttypes.polyline"
2043  ".i8.informatik.rwth-aachen.de");
2044 
2045  mark_components(component);
2046 
2047  PolyLineT<PointT> current_polyLine;
2048  current_polyLine.add_point(points_.front());
2049  unsigned int current_component =
2050  component_of(component, points_.front(), _ssearch);
2051 
2052  for (typename std::vector<PointT>::iterator pt_it = ++points_.begin(),
2053  pt_end = points_.end(); pt_it != pt_end; ++pt_it) {
2054 
2055  /*
2056  * The easy case: next point is on the same component as
2057  * the previous one.
2058  */
2059  const unsigned int next_comp = component_of(component, *pt_it, _ssearch);
2060  if (next_comp == current_component) {
2061  current_polyLine.add_point(*pt_it);
2062  continue;
2063  }
2064 
2065  /*
2066  * The hard case: next point is on different component
2067  * than the previous one.
2068  */
2069 
2070  PointT p0 = current_polyLine.back();
2071  const PointT p1 = *pt_it;
2072  unsigned int comp = next_comp;
2073 
2074  do {
2075  const double dist = (p0 - p1).norm();
2076  double lastIn = 0;
2077  double firstOut = 1;
2078 
2079  /*
2080  * Perform binary search to determine reasonable lastIn and firstOut.
2081  */
2082  static const double EPSILON = 1e-12;
2083  while ((firstOut - lastIn) * dist > EPSILON) {
2084  const double new_pos = .5 * (lastIn + firstOut);
2085  const PointT new_pt = p0 * (1.0 - new_pos) + p1 * new_pos;
2086  const unsigned int new_comp =
2087  component_of(component, new_pt, _ssearch);
2088 
2089  if (new_comp == current_component) {
2090  lastIn = new_pos;
2091  } else {
2092  firstOut = new_pos;
2093  comp = new_comp;
2094  }
2095  }
2096 
2097  if (lastIn != 0)
2098  current_polyLine.add_point(p0 * (1.0 - lastIn) + p1 * lastIn);
2099  if (current_polyLine.n_vertices() >= 2)
2100  out_polylines.push_back(current_polyLine);
2101  current_polyLine.clear();
2102  current_polyLine.add_point(p0 * (1.0 - firstOut) + p1 * firstOut);
2103  current_component = comp;
2104 
2105  // Update
2106  p0 = p0 * (1.0 - firstOut) + p1 * firstOut;
2107  } while (comp != next_comp);
2108 
2109  if (current_polyLine.back() != *pt_it)
2110  current_polyLine.add_point(*pt_it);
2111  }
2112 
2113  if (current_polyLine.n_vertices() >= 2)
2114  out_polylines.push_back(current_polyLine);
2115 
2116  // hack! if no splitting return original polyline
2117  if(out_polylines.size() <= 1)
2118  {
2119  out_polylines.clear();
2120  out_polylines.push_back(*this);
2121  }
2122 }
2123 
2124 template <class PointT>
2125 typename PolyLineT<PointT>::CustomPropertyHandle PolyLineT<PointT>::custom_prop_handle(const CustomProperty* _prop) const {
2126  size_t n = cprop_enum.size();
2127  for (int i = 0; i < n; ++i)
2128  if (cprop_enum[i] == _prop)
2129  return i;
2130  return -1;
2131 }
2132 
2133 template <class PointT>
2134 typename PolyLineT<PointT>::CustomProperty* PolyLineT<PointT>::custom_prop(CustomPropertyHandle _handle) {
2135  return (_handle >= 0 && _handle < int(get_num_custom_properties()) ? cprop_enum[_handle] : NULL);
2136 }
2137 
2138 template <class PointT>
2139 const typename PolyLineT<PointT>::CustomProperty* PolyLineT<PointT>::custom_prop(CustomPropertyHandle _handle) const {
2140  return (_handle >= 0 && _handle < int(get_num_custom_properties()) ? cprop_enum[_handle] : NULL);
2141 }
2142 
2143 template <class PointT>
2144 typename PolyLineT<PointT>::CustomPropertyHandle PolyLineT<PointT>::
2145  request_custom_property(const std::string& _name,
2146  unsigned int _prop_size) {
2147 
2148  CustomPropertyHandle h = get_custom_property_handle(_name);
2149  CustomProperty* pcontainer = custom_prop(h);
2150 
2151  if (!pcontainer) {
2152 
2153  // create new property container
2154  pcontainer = new CustomProperty;
2155 
2156  pcontainer->name = _name;
2157  pcontainer->ref_count = 1;
2158  pcontainer->prop_size = _prop_size;
2159 
2160  pcontainer->datatype = 0;
2161 
2162  pcontainer->prop_data.resize(n_vertices() * _prop_size, 0);
2163 
2164  custom_properties[_name] = pcontainer;
2165 
2166  cprop_enum.push_back(pcontainer);
2167  } else {
2168 
2169  if (++pcontainer->ref_count < 1)
2170  pcontainer->ref_count = 1;
2171  }
2172 
2173  return custom_prop_handle(pcontainer);
2174 }
2175 
2176 template <class PointT>
2177 void PolyLineT<PointT>::
2178  release_custom_property(CustomPropertyHandle _prop_handle) {
2179 
2180  CustomProperty* p = custom_prop(_prop_handle);
2181 
2182  if (p && --(p->ref_count) <= 0)
2183  p->prop_data.clear();
2184 }
2185 
2186 template <class PointT>
2187 void PolyLineT<PointT>::
2188  release_custom_property(const std::string& _name) {
2189 
2190  CustomPropertyHandle h = get_custom_property_handle(_name);
2191  release_custom_property(h);
2192 }
2193 
2194 template <class PointT>
2195 typename PolyLineT<PointT>::CustomPropertyHandle PolyLineT<PointT>::
2196  get_custom_property_handle(const std::string& _name) const {
2197 
2198  typename CustomPropertyMap::const_iterator it = custom_properties.find(_name);
2199 
2200  if (it == custom_properties.end())
2201  return -1;
2202 
2203  return custom_prop_handle(it->second);
2204 }
2205 
2206 template <class PointT>
2207 const std::string PolyLineT<PointT>::
2208  get_custom_property_name(CustomPropertyHandle _property_handle) const {
2209 
2210  const CustomProperty* p = custom_prop(_property_handle);
2211 
2212  if (p)
2213  return p->name;
2214 
2215  std::cerr << "PolyLineT::get_custom_property_name - invalid handle" << std::endl;
2216 
2217  return "";
2218 }
2219 
2220 
2221 template <class PointT>
2222 void PolyLineT<PointT>::
2223  set_custom_property(CustomPropertyHandle _property_handle,
2224  unsigned int _i,
2225  const void* _data) {
2226 
2227  if (!_data) {
2228  std::cerr << "PolyLineT::set_custom_property - invalid data" << std::endl;
2229  return;
2230  }
2231 
2232  CustomProperty* p = custom_prop(_property_handle);
2233 
2234  if (p) {
2235  unsigned int offset = p->prop_size * _i;
2236 
2237  // check out of range
2238  if (offset + p->prop_size > p->prop_data.size()) {
2239  std::cerr << "PolyLineT::set_custom_property - out of range access" << std::endl;
2240  return;
2241  }
2242 
2243 
2244  // copy data byte-wise
2245  memcpy(p->buffer() + offset, _data, p->prop_size);
2246  }
2247  else
2248  std::cerr << "PolyLineT::set_custom_property - invalid handle" << std::endl;
2249 }
2250 
2251 template <class PointT>
2252 void PolyLineT<PointT>::
2253  set_custom_property(const std::string& _name,
2254  unsigned int _i,
2255  const void* _data) {
2256 
2257  CustomPropertyHandle h = get_custom_property_handle(_name);
2258  set_custom_property(h, _i, _data);
2259 }
2260 
2261 template <class PointT>
2262 void PolyLineT<PointT>::
2263  get_custom_property(CustomPropertyHandle _property_handle,
2264  unsigned int _i,
2265  void* _dst) const {
2266 
2267  if (!_dst) {
2268  std::cerr << "PolyLineT::get_custom_property - invalid destination address" << std::endl;
2269  return;
2270  }
2271 
2272  const CustomProperty* p = custom_prop(_property_handle);
2273 
2274  if (p) {
2275 
2276  unsigned int offset = p->prop_size * _i;
2277 
2278  // check out of range
2279  if (offset + p->prop_size >= p->prop_data.size()) {
2280  std::cerr << "PolyLineT::get_custom_property - out of range access" << std::endl;
2281  return;
2282  }
2283 
2284  // copy data byte-wise
2285  memcpy(_dst, p->buffer() + offset, p->prop_size);
2286  }
2287  else
2288  std::cerr << "PolyLineT::get_custom_property - invalid handle" << std::endl;
2289 }
2290 
2291 template <class PointT>
2292 void PolyLineT<PointT>::
2293  get_custom_property(const std::string& _name,
2294  unsigned int _i,
2295  void* _data) const {
2296 
2297  CustomPropertyHandle h = get_custom_property_handle(_name);
2298  get_custom_property(h, _i, _data);
2299 }
2300 
2301 
2302 template <class PointT>
2303 bool PolyLineT<PointT>::
2304  custom_property_available(CustomPropertyHandle _property_handle) const {
2305 
2306  const CustomProperty* p = custom_prop(_property_handle);
2307 
2308  if (p)
2309  return p->ref_count > 0;
2310 
2311  return false;
2312 }
2313 
2314 
2315 template <class PointT>
2316 bool PolyLineT<PointT>::
2317  custom_property_available(const std::string& _name) const {
2318 
2319  CustomPropertyHandle h = get_custom_property_handle(_name);
2320  return custom_property_available(h);
2321 }
2322 
2323 
2324 template <class PointT>
2326  bind_custom_property_to_shader(CustomPropertyHandle _property_handle, const std::string& _shader_input_name, unsigned int _datatype) {
2327 
2328  CustomProperty* p = custom_prop(_property_handle);
2329 
2330  if (p) {
2331 
2332  p->datatype = _datatype;
2333  p->shader_binding = _shader_input_name;
2334 
2335  } else
2336  std::cerr << "PolyLineT::bind_custom_property_to_shader - invalid handle" << std::endl;
2337 }
2338 
2339 
2340 template <class PointT>
2342  get_custom_property_shader_binding(CustomPropertyHandle _property_handle, unsigned int* _propsize, const char** _input_name, unsigned int* _datatype) const {
2343 
2344  const CustomProperty* p = custom_prop(_property_handle);
2345 
2346  if (p) {
2347 
2348  if (_propsize)
2349  *_propsize = p->prop_size;
2350 
2351  if (_input_name)
2352  *_input_name = p->shader_binding.c_str();
2353 
2354  if (_datatype)
2355  *_datatype = p->datatype;
2356 
2357  return !p->shader_binding.empty() && p->datatype;
2358  }
2359  else
2360  std::cerr << "PolyLineT::get_custom_property_shader_binding - invalid handle" << std::endl;
2361 
2362  return false;
2363 }
2364 
2365 template <class PointT>
2366 const void* PolyLineT<PointT>::
2367  get_custom_property_buffer(CustomPropertyHandle _property_handle) const {
2368 
2369  const CustomProperty* p = custom_prop(_property_handle);
2370 
2371  if (p)
2372  return p->buffer();
2373  else
2374  std::cerr << "PolyLineT::get_custom_property_buffer - invalid handle" << std::endl;
2375 
2376  return NULL;
2377 }
2378 
2379 template <class PointT>
2380 unsigned int PolyLineT<PointT>::
2381  get_num_custom_properties() const {
2382  return custom_properties.size();
2383 }
2384 
2385 template <class PointT>
2386 typename PolyLineT<PointT>::CustomPropertyHandle PolyLineT<PointT>::
2387  enumerate_custom_property_handles(unsigned int _i) const {
2388 
2389  if (_i < get_num_custom_properties())
2390  return CustomPropertyHandle(_i);
2391  else
2392  return -1;
2393 }
2394 
2395 //=============================================================================
2396 } // namespace ACG
2397 //=============================================================================
void smooth_uniform_laplace()
Laplacian smoothing.
Definition: PolyLineT.cc:738
void invert()
Invert polyline that first vertex becomes last.
Definition: PolyLineT.cc:1357
VectorT< Scalar, 3 > perpendicular(const VectorT< Scalar, 3 > &v)
find a vector that's perpendicular to _v
Definition: Algorithms.cc:1162
LineNodeT * get_line_node(LineNodeT *&_line_node, int _mode=0)
Conversion PolyLine <-> LineNode.
Definition: PolyLineT.cc:1080
Scalar total_gaussian_curvature()
compute total gaussian curvature of enclosed surface (via Gauss-Bonnet)
Definition: PolyLineT.cc:1841
size_t n_vertices() const
Get number of vertices.
Definition: PolyLineT.hh:122
bool on_multiple_components(MeshT &_mesh, SpatialSearchT &_ssearch)
Definition: PolyLineT.cc:2005
std::vector< Point > points_
List of points in the polyline.
Definition: PolyLineT.hh:653
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
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
Definition: PolyLineT.cc:1759
void smooth_uniform_laplace3()
Cubic laplacian smoothing.
Definition: PolyLineT.cc:849
void split_into_one_per_component(MeshT &_mesh, SpatialSearchT &_ssearch, std::vector< PolyLineT > &out_polylines)
Definition: PolyLineT.cc:2034
void mark_components(OpenMesh::PropertyManager< OpenMesh::FPropHandleT< unsigned int >, MeshT > &component)
Definition: PolyLineT.cc:1935
unsigned int component_of(const OpenMesh::PropertyManager< OpenMesh::FPropHandleT< unsigned int >, MeshT > &component, const PointT &pt, SpatialSearchT &_ssearch)
Definition: PolyLineT.cc:1987
bool closed_
Connect first and last point?
Definition: PolyLineT.hh:656
void clear()
Clear the current polyline.
Definition: PolyLineT.cc:187
void project_to_mesh(const MeshT &_mesh, SpatialSearchT *_ssearch=0)
Project polyline points to nearest surface points (use spatial search!!!)
Definition: PolyLineT.cc:937
size_t n_edges() const
Get number of edges.
Definition: PolyLineT.cc:216
bool is_closed() const
Check if the polyline is marked as closed.
Definition: PolyLineT.hh:113
void delete_point(int _idx)
Delete point at _idx.
Definition: PolyLineT.cc:417
Point find_nearest_point(const MeshT &_mesh, const Point &_point, typename MeshT::FaceHandle &_fh, SpatialSearchT *_ssearch=0, double *_dbest=0)
Definition: PolyLineT.cc:1006
void smooth_uniform_laplace2()
Squared laplacian smoothing.
Definition: PolyLineT.cc:792
void subdivide(Scalar _largest)
Subdivide polyline.
Definition: PolyLineT.cc:619
Point position_arclength(const Scalar _t) const
Same as position but with an arclength parameterization in [0,length()].
Definition: PolyLineT.cc:528
bool plane_line_intersection(const IPoint &_p_plane, const IPoint &_n_plane, const IPoint &_p0, const IPoint &_p1, IPoint &_p_int)
Definition: PolyLineT.cc:1493
void bind_custom_property_to_shader(CustomPropertyHandle _property_handle, const std::string &_shader_input_name, unsigned int _datatype)
Binding to vertex shader (optional)
Definition: PolyLineT.cc:2326
void split(unsigned int _split_idx, PolyLineT< PointT > &_new_pl)
Split closed polyline at vertex with index _split_idx.
Definition: PolyLineT.cc:1463
void resize(unsigned int _n)
Resize current polyline.
Definition: PolyLineT.cc:231
void set_closed(const bool _c)
Set if the polyline should be closed and therefore forms a loop.
Definition: PolyLineT.hh:119
Scalar length() const
Compute the length of the polyline (in future cached method)
Definition: PolyLineT.cc:484
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 ...
Definition: PolyLineT.cc:911
PolyLineT(bool _closed=false)
Constructor.
Definition: PolyLineT.cc:97
bool get_custom_property_shader_binding(CustomPropertyHandle _property_handle, unsigned int *_propsize, const char **_input_name, unsigned int *_datatype) const
Get shader binding information.
Definition: PolyLineT.cc:2342
void split_closed(unsigned int _split_idx)
Split closed polyline at vertex with index _split_idx.
Definition: PolyLineT.cc:1431
void add_point(const Point &_p)
Append a point to the polyline.
Definition: PolyLineT.cc:288
Point & point(unsigned int _i)
Get a point of the polyline.
Definition: PolyLineT.hh:148
void resample_arclength_uniform(const unsigned int _n)
Perform an uniform arclength resampling while maintaining the start and end point.
Definition: PolyLineT.cc:580
Point & back()
Get last point of the polyline ( no range check!!!)
Definition: PolyLineT.hh:166
void append(const PolyLineT< PointT > &_pl)
Append second polyline _pl to this one.
Definition: PolyLineT.cc:1387
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. ...
Definition: PolyLineT.cc:1143
void print() const
Print information string to cerr.
Definition: PolyLineT.cc:1193
void insert_point(int _idx, const Point &_p)
insert _p at _idx into polyline
Definition: PolyLineT.cc:352
void prepend(const PolyLineT< PointT > &_pl)
Prepend second polyline _pl to polyline.
Definition: PolyLineT.cc:1416
void collapse(Scalar _smallest)
Collapse polyline.
Definition: PolyLineT.cc:672
Point position(const Scalar _t) const
Provide linear paremterization of the polyline in [0,1].
Definition: PolyLineT.cc:515