Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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>
96 PolyLineT<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>
121 PolyLineT<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
186 PolyLineT<PointT>::
187 clear()
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
216 PolyLineT<PointT>::n_edges() const
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
230 PolyLineT<PointT>::
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
287 PolyLineT<PointT>::
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
351 PolyLineT<PointT>::
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
416 PolyLineT<PointT>::
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
483 PolyLineT<PointT>::
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
514 PolyLineT<PointT>::
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
527 PolyLineT<PointT>::
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
579 PolyLineT<PointT>::
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
618 PolyLineT<PointT>::
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
671 PolyLineT<PointT>::
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
737 PolyLineT<PointT>::
738 smooth_uniform_laplace()
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
791 PolyLineT<PointT>::
792 smooth_uniform_laplace2()
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
848 PolyLineT<PointT>::
849 smooth_uniform_laplace3()
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
910 PolyLineT<PointT>::
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
936 PolyLineT<PointT>::
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
957 PolyLineT<PointT>::
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
1005 PolyLineT<PointT>::
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*
1079 PolyLineT<PointT>::
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
1142 PolyLineT<PointT>::
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
1192 PolyLineT<PointT>::
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
1209 PolyLineT<PointT>::
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
1356 PolyLineT<PointT>::
1357 invert()
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
1386 PolyLineT<PointT>::
1387 append(const PolyLineT<PointT>& _pl)
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
1415 PolyLineT<PointT>::
1416 prepend(const PolyLineT<PointT>& _pl)
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
1430 PolyLineT<PointT>::
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
1462 PolyLineT<PointT>::
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
1492 PolyLineT<PointT>::
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
1526 PolyLineT<PointT>::
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
1758 PolyLineT<PointT>::
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
1840 PolyLineT<PointT>::
1841 total_gaussian_curvature()
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>
1935 void PolyLineT<PointT>::mark_components(
1936 OpenMesh::PropertyManager<
1937 OpenMesh::FPropHandleT<unsigned int>,
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>
1987 unsigned int PolyLineT<PointT>::component_of(
1988 const OpenMesh::PropertyManager<
1989 OpenMesh::FPropHandleT<unsigned int>,
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>
2004 bool PolyLineT<PointT>::
2005 on_multiple_components(MeshT &_mesh,
2006 SpatialSearchT &_ssearch) {
2007
2008 if (points_.empty()) return false;
2009
2010 OpenMesh::PropertyManager<OpenMesh::FPropHandleT<unsigned int>, MeshT>
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>
2033 void PolyLineT<PointT>::
2034 split_into_one_per_component(MeshT &_mesh,
2035 SpatialSearchT &_ssearch,
2036 std::vector<PolyLineT> &out_polylines) {
2037
2038 if (points_.size() < 2) return;
2039
2040 OpenMesh::PropertyManager<OpenMesh::FPropHandleT<unsigned int>, MeshT>
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>
2325 void PolyLineT<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>
2341 bool PolyLineT<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 //=============================================================================
ACG::PolyLineT::smooth_uniform_laplace
void smooth_uniform_laplace()
Laplacian smoothing.
Definition: PolyLineT.cc:738
ACG::PolyLineT::invert
void invert()
Invert polyline that first vertex becomes last.
Definition: PolyLineT.cc:1357
ACG::Geometry::perpendicular
VectorT< Scalar, 3 > perpendicular(const VectorT< Scalar, 3 > &v)
find a vector that's perpendicular to _v
Definition: Algorithms.cc:1162
ACG::PolyLineT::get_line_node
LineNodeT * get_line_node(LineNodeT *&_line_node, int _mode=0)
Conversion PolyLine <-> LineNode.
Definition: PolyLineT.cc:1080
ACG::PolyLineT::total_gaussian_curvature
Scalar total_gaussian_curvature()
compute total gaussian curvature of enclosed surface (via Gauss-Bonnet)
Definition: PolyLineT.cc:1841
ACG::PolyLineT::n_vertices
size_t n_vertices() const
Get number of vertices.
Definition: PolyLineT.hh:122
ACG::PolyLineT::on_multiple_components
bool on_multiple_components(MeshT &_mesh, SpatialSearchT &_ssearch)
Definition: PolyLineT.cc:2005
ACG::PolyLineT::points_
std::vector< Point > points_
List of points in the polyline.
Definition: PolyLineT.hh:653
ACG
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
ACG::PolyLineT::remove_subsequent_identical_points
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
ACG::PolyLineT::smooth_uniform_laplace3
void smooth_uniform_laplace3()
Cubic laplacian smoothing.
Definition: PolyLineT.cc:849
ACG::PolyLineT::split_into_one_per_component
void split_into_one_per_component(MeshT &_mesh, SpatialSearchT &_ssearch, std::vector< PolyLineT > &out_polylines)
Definition: PolyLineT.cc:2034
ACG::PolyLineT::mark_components
void mark_components(OpenMesh::PropertyManager< OpenMesh::FPropHandleT< unsigned int >, MeshT > &component)
Definition: PolyLineT.cc:1935
ACG::PolyLineT::component_of
unsigned int component_of(const OpenMesh::PropertyManager< OpenMesh::FPropHandleT< unsigned int >, MeshT > &component, const PointT &pt, SpatialSearchT &_ssearch)
Definition: PolyLineT.cc:1987
ACG::PolyLineT
Definition: PolyLineT.hh:90
ACG::PolyLineT::closed_
bool closed_
Connect first and last point?
Definition: PolyLineT.hh:656
ACG::PolyLineT::clear
void clear()
Clear the current polyline.
Definition: PolyLineT.cc:187
ACG::PolyLineT::project_to_mesh
void project_to_mesh(const MeshT &_mesh, SpatialSearchT *_ssearch=0)
Project polyline points to nearest surface points (use spatial search!!!)
Definition: PolyLineT.cc:937
ACG::PolyLineT::n_edges
size_t n_edges() const
Get number of edges.
Definition: PolyLineT.cc:216
ACG::PolyLineT::is_closed
bool is_closed() const
Check if the polyline is marked as closed.
Definition: PolyLineT.hh:113
OpenMesh::PropertyManager
Definition: PropertyManager.hh:94
ACG::PolyLineT::delete_point
void delete_point(int _idx)
Delete point at _idx.
Definition: PolyLineT.cc:417
ACG::PolyLineT::find_nearest_point
Point find_nearest_point(const MeshT &_mesh, const Point &_point, typename MeshT::FaceHandle &_fh, SpatialSearchT *_ssearch=0, double *_dbest=0)
Definition: PolyLineT.cc:1006
ACG::PolyLineT::smooth_uniform_laplace2
void smooth_uniform_laplace2()
Squared laplacian smoothing.
Definition: PolyLineT.cc:792
ACG::PolyLineT::subdivide
void subdivide(Scalar _largest)
Subdivide polyline.
Definition: PolyLineT.cc:619
ACG::PolyLineT::position_arclength
Point position_arclength(const Scalar _t) const
Same as position but with an arclength parameterization in [0,length()].
Definition: PolyLineT.cc:528
ACG::PolyLineT::plane_line_intersection
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
ACG::PolyLineT::bind_custom_property_to_shader
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
ACG::PolyLineT::split
void split(unsigned int _split_idx, PolyLineT< PointT > &_new_pl)
Split closed polyline at vertex with index _split_idx.
Definition: PolyLineT.cc:1463
OpenMesh::VectorT< float, 4 >
ACG::PolyLineT::resize
void resize(unsigned int _n)
Resize current polyline.
Definition: PolyLineT.cc:231
ACG::PolyLineT::set_closed
void set_closed(const bool _c)
Set if the polyline should be closed and therefore forms a loop.
Definition: PolyLineT.hh:119
ACG::PolyLineT::length
Scalar length() const
Compute the length of the polyline (in future cached method)
Definition: PolyLineT.cc:484
ACG::PolyLineT::set_to_circle
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
ACG::PolyLineT::PolyLineT
PolyLineT(bool _closed=false)
Constructor.
Definition: PolyLineT.cc:97
OpenMesh::FPropHandleT< unsigned int >
ACG::PolyLineT::get_custom_property_shader_binding
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
ACG::PolyLineT::split_closed
void split_closed(unsigned int _split_idx)
Split closed polyline at vertex with index _split_idx.
Definition: PolyLineT.cc:1431
ACG::PolyLineT::add_point
void add_point(const Point &_p)
Append a point to the polyline.
Definition: PolyLineT.cc:288
ACG::PolyLineT::point
Point & point(unsigned int _i)
Get a point of the polyline.
Definition: PolyLineT.hh:148
ACG::PolyLineT::resample_arclength_uniform
void resample_arclength_uniform(const unsigned int _n)
Perform an uniform arclength resampling while maintaining the start and end point.
Definition: PolyLineT.cc:580
ACG::PolyLineT::back
Point & back()
Get last point of the polyline ( no range check!!!)
Definition: PolyLineT.hh:166
ACG::PolyLineT::append
void append(const PolyLineT< PointT > &_pl)
Append second polyline _pl to this one.
Definition: PolyLineT.cc:1387
ACG::PolyLineT::set_line_node
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
ACG::PolyLineT::print
void print() const
Print information string to cerr.
Definition: PolyLineT.cc:1193
ACG::PolyLineT::insert_point
void insert_point(int _idx, const Point &_p)
insert _p at _idx into polyline
Definition: PolyLineT.cc:352
ACG::PolyLineT::prepend
void prepend(const PolyLineT< PointT > &_pl)
Prepend second polyline _pl to polyline.
Definition: PolyLineT.cc:1416
ACG::PolyLineT::collapse
void collapse(Scalar _smallest)
Collapse polyline.
Definition: PolyLineT.cc:672
ACG::PolyLineT::position
Point position(const Scalar _t) const
Provide linear paremterization of the polyline in [0,1].
Definition: PolyLineT.cc:515
ACG::PolyLineT::CustomProperty
Definition: PolyLineT.hh:702