53#ifndef LASS_GUARDIAN_OF_INCLUSION_SPAT_PLANAR_MESH_H
54#define LASS_GUARDIAN_OF_INCLUSION_SPAT_PLANAR_MESH_H
79 #define TEMPLATE_DEF template< \
81 typename PointHandle, \
82 typename EdgeHandle, \
87 TEMPLATE_DEF
class EdgeToMatlab;
88 TEMPLATE_DEF
class EdgeGatherer;
89 TEMPLATE_DEF
class EdgeMarker;
92 namespace experimental
95 struct ObjectAllocator:
96 private util::AllocatorThrow<
97 util::AllocatorBinned<
98 util::AllocatorSimpleBlock<
100 util::AllocatorFixed<
101 util::AllocatorAlignedAlloc<LASS_SIMD_ALIGNMENT>
105 util::BinnerPadded<LASS_SIMD_ALIGNMENT>,
106 util::AllocatorAlignedAlloc<LASS_SIMD_ALIGNMENT>
110 template <
typename T> T* make(
const T& x)
112 T*
const p =
static_cast<T*
>(allocate(
sizeof(T)));
119 deallocate(p,
sizeof(T));
124 template <
typename T>
void free(T* p)
129 deallocate(p,
sizeof(T));
134 template <
typename T>
138 enum { size = 8 *
sizeof(T) };
139 BitField(T bits = 0x0): bits_(bits) {}
140 bool operator[](
size_t i)
const
142 return bits_ & mask(i) ? true :
false;
148 void set(
size_t i,
bool value)
152 bits_ |= (value ? m : 0);
159 const T mask(
size_t i)
const
161 LASS_ASSERT(i < size);
167 template <
typename T>
168 class ResetableThreadLocalVariable
171 ResetableThreadLocalVariable(
const T& proto = T()):
175 TTls* tls =
reinterpret_cast<TTls*
>(tls_);
176 new (tls) TTls(Impl(
this));
178 ~ResetableThreadLocalVariable()
180 TTls* tls =
reinterpret_cast<TTls*
>(tls_);
185 return *(*
reinterpret_cast<TTls*
>(tls_))->it;
187 const T& operator*()
const
189 return *(*
reinterpret_cast<TTls*
>(tls_))->it;
191 void reset(
const T& proto)
196 std::fill(values_.begin(), values_.end(), proto_);
202 Impl(ResetableThreadLocalVariable* self): self(self)
204 this->self->registerImpl(
this);
206 Impl(
const Impl& other): self(other.self)
208 self->registerImpl(
this);
212 self->unregisterImpl(
this);
214 ResetableThreadLocalVariable* self;
215 typename std::list<T>::iterator it;
218 typedef util::ThreadLocalVariable<Impl> TTls;
220 void registerImpl(Impl* impl)
224 values_.push_back(proto_);
225 impl->it = stde::prev(values_.end());
228 void unregisterImpl(Impl* impl)
232 values_.erase(impl->it);
236 char tls_[
sizeof(TTls)];
237 std::list<T> values_;
239 util::Semaphore mutex_;
245 class PlanarMesh:
private experimental::ObjectAllocator
248 typedef lass::prim::Point2D<T> TPoint2D;
255 typedef experimental::BitField<num::Tuint32> TBitField;
260 stackDepth = TBitField::size - 1,
261 publicMarkIndex = TBitField::size - 1
264 struct ProxyHandle:
private meta::Tuple< typename meta::type_list::Make<PointHandle, EdgeHandle, FaceHandle>::Type >
266 typedef meta::Tuple< typename meta::type_list::Make<PointHandle, EdgeHandle, FaceHandle>::Type > THandles;
269 TBitField internalMark_;
271 ProxyHandle(): point_(NULL), internalMark_(0x00) {}
272 const PointHandle& pointHandle()
const {
return meta::tuple::field<0>(
static_cast<const THandles&
>(*
this)); }
273 const EdgeHandle& edgeHandle()
const {
return meta::tuple::field<1>(
static_cast<const THandles&
>(*
this)); }
274 const FaceHandle& faceHandle()
const {
return meta::tuple::field<2>(
static_cast<const THandles&
>(*
this)); }
275 PointHandle& pointHandle() {
return meta::tuple::field<0>(
static_cast<THandles&
>(*
this)); }
276 EdgeHandle& edgeHandle() {
return meta::tuple::field<1>(
static_cast<THandles&
>(*
this)); }
277 FaceHandle& faceHandle() {
return meta::tuple::field<2>(
static_cast<THandles&
>(*
this)); }
279 class StackIncrementer
282 size_t maxStackDepth_;
283 StackIncrementer() {}
285 StackIncrementer(
size_t* iStackVar,
size_t iMaxStackDepth ) : stackDepth_(iStackVar), maxStackDepth_( iMaxStackDepth )
288 if (*stackDepth_>maxStackDepth_)
291 throw std::runtime_error(
"PlanarMesh: stack overflow");
301 typedef lass::spat::QuadEdge<ProxyHandle> TQuadEdge;
302 typedef typename TQuadEdge::Edge TEdge;
303 typedef std::vector< TQuadEdge* > TQuadEdgeList;
304 typedef std::vector< ProxyHandle* > TProxyHandleList;
305 typedef lass::util::CallbackR1<bool,TEdge*> TEdgeCallback;
306 typedef lass::util::CallbackR3<bool,TEdge*,const TSimplePolygon2D&, FaceHandle> TEdgePolyFaceHandleCallback;
309 PlanarMesh(
const TPoint2D& a,
const TPoint2D& b,
const TPoint2D& c);
310 PlanarMesh(
const TPoint2D& a,
const TPoint2D& b,
const TPoint2D& c,
const TPoint2D& d);
311 PlanarMesh(
const prim::Aabb2D<T>& iAabb );
312 void setTolerance(
const T& iTolerance) {tolerance_ = iTolerance;}
313 const T& tolerance() {
return tolerance_; }
314 void setPointDistanceTolerance(
const T& iPointDistanceTolerance) {pointDistanceTolerance_ = iPointDistanceTolerance;}
315 const T& pointDistanceTolerance() {
return pointDistanceTolerance_; }
316 virtual ~PlanarMesh();
318 TEdge* startEdge()
const;
321 bool forAllPrimaryEdges(
const TEdgeCallback& iCallback );
324 bool forAllDualEdges(
const TEdgeCallback& iCallback );
325 bool forAllEdges(
const TEdgeCallback& iCallback );
326 bool forAllVertices(
const TEdgeCallback& iCallback );
327 bool forAllFaces(
const TEdgeCallback& iCallback );
328 bool forAllFacesCached(
const TEdgeCallback& iCallback );
329 template <
typename InputPolygonIterator,
typename InputFaceHandleIterator>
330 bool forAllPolygonFaces( InputPolygonIterator iFirstPolygon, InputPolygonIterator iLastPolygon, InputFaceHandleIterator iFirstFaceHandle,
const TEdgePolyFaceHandleCallback& iCallback );
333 TEdge*
locate(
const TPoint2D& iPoint, TEdge* iHint=0 )
const;
335 TEdge*
shoot(
const TRay2D& iRay )
const;
336 template <
typename OutputIterator> OutputIterator walk(
const TLineSegment2D& iSegment, OutputIterator oCrossedEdges )
const;
337 template <
typename OutputIterator> OutputIterator walkIntersections(
const TLineSegment2D& iSegment, OutputIterator oIntersections )
const;
338 std::pair<int, TEdge*> walkTillConstrained(
const TRay2D& iRay)
const;
339 TEdge*
insertSite(
const TPoint2D& iPoint,
bool makeDelaunay =
true,
bool forceOnEdge =
false);
340 TEdge*
insertEdge(
const TLineSegment2D& iSegment, EdgeHandle iLeftHandle = EdgeHandle(), EdgeHandle iRightHandle = EdgeHandle(), PointHandle iPointHandle = PointHandle(),
bool forcePointHandle =
false,
bool makeDelaunay =
true);
341 TEdge* insertPolygon(
const TSimplePolygon2D& iSegment, EdgeHandle iLeftHandle = EdgeHandle(), EdgeHandle iRightHandle = EdgeHandle(),
bool makeDelaunay =
true);
342 void markPolygon( TEdge* iStartEdge,
const TSimplePolygon2D& iPolygon, FaceHandle iFaceHandle );
343 template <
typename InputPolygonIterator,
typename InputFaceHandleIterator>
344 void markPolygons( InputPolygonIterator iFirstPolygon, InputPolygonIterator iLastPolygon, InputFaceHandleIterator iFirstFaceHandle);
345 void markPolygons(
const std::vector<TSimplePolygon2D>& iPolygons,
const std::vector<FaceHandle>& iFaceHandles);
349 long edgeCount()
const {
return edgeCount_; }
350 void makeMaximalConvexPolygon(T iMaxSurface=T(-1));
351 void makeRectangular(T minAngle, T maxAngle);
353 static TTriangle2D triangle(
const TEdge* iEdge);
354 static TSimplePolygon2D polygon(
const TEdge* iEdge);
355 static const TPoint2D& org(
const TEdge* iEdge );
356 static const TPoint2D& dest(
const TEdge* iEdge );
357 static const TPoint2D& fastOrg(
const TEdge* iEdge );
358 static const TPoint2D& fastDest(
const TEdge* iEdge );
359 static TPoint2D along(
const TEdge* iEdge,
const T& iParam );
360 static TPoint2D fastAlong(
const TEdge* iEdge,
const T& iParam );
361 static const TVector2D direction(
const TEdge* iEdge );
362 static bool rightOf(
const TPoint2D& iPoint,
const TEdge* iEdge );
363 static bool fastRightOf(
const TPoint2D& iPoint,
const TEdge* iEdge );
364 static bool leftOf(
const TPoint2D& iPoint,
const TEdge* iEdge );
365 static bool fastLeftOf(
const TPoint2D& iPoint,
const TEdge* iEdge );
366 static bool onEdge(
const TPoint2D& iPoint,
const TEdge* iEdge );
367 static bool hasLeftFace(
const TEdge* iEdge );
368 static bool fastHasLeftFace(
const TEdge* iEdge );
369 static bool hasRightFace(
const TEdge* iEdge );
373 static bool inConvexCell(
const TPoint2D& iPoint,
const TEdge* iEdge );
377 TEdge*
makeEdge(
const TPoint2D& a,
const TPoint2D& b,
bool makeConstrained );
380 void swap( TEdge* iEdge );
382 void setTempQuadEdges(
bool iAllocateInTemp);
388 static void setOrg(
const TPoint2D& iOrg, TEdge* iEdge );
389 static void setDest(
const TPoint2D& iDest, TEdge* iEdge );
390 bool moveWithinNeighbourhood( TEdge* iEdge,
const TPoint2D& iNewLocation );
396 bool removeVertex(TEdge* iEdge);
398 static bool inPrimaryMesh(
const TEdge* iEdge );
399 static bool inDualMesh(
const TEdge* iEdge );
400 static bool marking(
const TEdge* iEdge );
401 static void setMarking( TEdge* iEdge,
bool iMark );
402 static PointHandle pointHandle(
const TEdge* iEdge );
403 static EdgeHandle edgeHandle(
const TEdge* iEdge );
404 static FaceHandle faceHandle(
const TEdge* iEdge );
405 static PointHandle& pointHandleRef( TEdge* iEdge );
406 static EdgeHandle& edgeHandleRef( TEdge* iEdge );
407 static FaceHandle& faceHandleRef( TEdge* iEdge );
408 static void setPointHandle( TEdge* iEdge, PointHandle iHandle );
409 static void setEdgeHandle( TEdge* iEdge, EdgeHandle iHandle );
410 static void setFaceHandle( TEdge* iEdge, FaceHandle iHandle );
411 static void setOrientedEdgeHandle( TEdge* iEdge, EdgeHandle iLeftHandle, EdgeHandle iRightHandle,
const TVector2D& iDirection );
413 bool allocateInTemp_;
415 TQuadEdgeList quadEdgeList_;
416 TQuadEdgeList tempQuadEdgeList_;
417 std::vector<TPoint2D> boundingPoints_;
419 T pointDistanceTolerance_;
424 mutable experimental::ResetableThreadLocalVariable<TEdge*> lastLocateEdge_;
425 mutable experimental::ResetableThreadLocalVariable<TEdge*> lastFloodEdge_;
429 void init4(
const TPoint2D& a,
const TPoint2D& b,
const TPoint2D& c,
const TPoint2D& d);
430 void fixEdge( TEdge* e );
431 TEdge* makeEmptyEdge(
bool makeConstrained );
432 void triangulate( TEdge* iEdge );
433 void splitEdge(TEdge *e,
const TPoint2D& iPoint );
434 TEdge* pointShoot(
const TRay2D& iRay )
const;
435 template <
typename OutputIterator> OutputIterator pointWalk(
const TLineSegment2D& iSegment, OutputIterator oCrossedEdges )
const;
436 void safeSplitEdge(TEdge *e,
const TPoint2D& iPoint );
437 TPoint2D snap(
const TPoint2D& a,
const TPoint2D& b,
const TPoint2D& c);
439 TEdge* bruteForceLocate(
const TPoint2D& iPoint )
const;
440 TEdge* bruteForceExactLocate(
const TPoint2D& iPoint )
const;
442 friend class impl::EdgeToMatlab<T, PointHandle, EdgeHandle, FaceHandle>;
443 friend class impl::EdgeGatherer<T, PointHandle, EdgeHandle, FaceHandle>;
444 friend class impl::EdgeMarker<T, PointHandle, EdgeHandle, FaceHandle>;
446 bool internalMarking(
const TEdge* iEdge );
447 bool deletePoint( TEdge* e);
448 void setInternalMarking( TEdge* iEdge,
bool iMark );
449 void setInternalMarkingAroundVertex(
typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TEdge* iEdge,
bool iMark );
450 void setInternalMarkingInFace(
typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TEdge* iEdge,
bool iMark );
452 bool floodPolygon( TEdge* iStartEdge,
const TSimplePolygon2D& iPolygon, FaceHandle iFaceHandle );
453 bool floodPolygonCallback( TEdge* iStartEdge,
const TSimplePolygon2D& iPolygon, FaceHandle iFaceHandle,
const TEdgePolyFaceHandleCallback& iCallback);
456 static unsigned numSetOrientedEdgeHandleCalls;
457 static unsigned numSetOrientedEdgeHandleSwaps;
467 template <
typename T>
469 const lass::prim::Point2D<T>& iC,
const lass::prim::Point2D<T>& iD, lass::prim::Point2D<T>& oP)
475 const T denominator = lass::prim::perpDot(dirA, dirB);
476 const T denominator2= denominator*2.0;
478 if (denominator == denominator2)
486 const T oTa = perpDot(difference, dirB) / denominator;
500 EdgeMarker(
TPlanarMesh* iMesh,
bool iMark ) : mesh_(iMesh), marking_(iMark) {}
503 bool internalMark(
typename TPlanarMesh::TEdge* e )
505 mesh_->setInternalMarking( e, marking_ );
508 bool mark(
typename TPlanarMesh::TEdge* e )
510 TPlanarMesh::setMarking( e, marking_ );
520 typedef PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle> TPlanarMesh;
523 lass::io::MatlabOStream& stream_;
525 EdgeToMatlab( TPlanarMesh* iMesh, lass::io::MatlabOStream& ioOStream ) : mesh_(iMesh), stream_( ioOStream ) {}
526 bool edgeToMatlab(
typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TEdge* iEdge )
528 if (!mesh_->internalMarking( iEdge ))
530 if (iEdge->isConstrained())
531 stream_.setColor(lass::io::mcRed);
533 stream_.setColor(lass::io::mcBlack);
534 stream_ <<
typename TPlanarMesh::TLineSegment2D(
535 TPlanarMesh::org(iEdge), TPlanarMesh::dest(iEdge) );
539 mesh_->setInternalMarking( iEdge,
true );
540 mesh_->setInternalMarking( iEdge->sym(),
true );
543 bool vertexToMatlab(
typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TEdge* iEdge )
545 typedef PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle> TPlanarMesh;
546 if ( !mesh_->internalMarking( iEdge ) )
547 stream_ << TPlanarMesh::org(iEdge);
550 mesh_->setInternalMarkingAroundVertex( iEdge,
true );
558 typedef PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle> TPlanarMesh;
562 typedef std::list< typename TPlanarMesh::TEdge* > TEdgeList;
564 T angleConstraintMin;
565 T angleConstraintMax;
568 EdgeGatherer( TPlanarMesh* iMesh ) : mesh_(iMesh), lastArea_(0) {}
569 virtual ~EdgeGatherer() {}
571 bool makeConvexPolygon(
typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TEdge* e )
573 LASS_ASSERT( TPlanarMesh::inPrimaryMesh( e ) );
574 if ( mesh_->internalMarking( e ) || e->isConstrained())
577 if ( prim::weakCcw( TPlanarMesh::org(e->dNext()), TPlanarMesh::dest(e), TPlanarMesh::dest(e->lNext()))
578 && prim::weakCcw( TPlanarMesh::org(e->sym()->dNext()), TPlanarMesh::org(e), TPlanarMesh::dest(e->sym()->lNext())) )
580 T dArea =
num::abs(prim::doubleTriangleArea( TPlanarMesh::org(e->dNext()), TPlanarMesh::dest(e), TPlanarMesh::dest(e->lNext())))
581 +
num::abs(prim::doubleTriangleArea( TPlanarMesh::org(e->sym()->dNext()), TPlanarMesh::org(e), TPlanarMesh::dest(e->sym()->lNext())));
585 T leftArea = TPlanarMesh::polygon(e).area();
586 T rightArea = TPlanarMesh::polygon(e->sym()).area();
587 if (leftArea+rightArea>maxSurface)
590 if (lastArea_ == T(0))
593 edgeList.push_back( e );
599 edgeList.push_front( e );
603 edgeList.push_back( e );
609 bool makeRectangular(
typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TEdge* e )
611 LASS_ASSERT( TPlanarMesh::inPrimaryMesh( e ) );
612 if ( mesh_->internalMarking( e ) || e->isConstrained())
615 if ( prim::ccw( TPlanarMesh::org(e->dNext()), TPlanarMesh::dest(e), TPlanarMesh::dest(e->lNext()))
616 && prim::ccw( TPlanarMesh::org(e->sym()->dNext()), TPlanarMesh::org(e), TPlanarMesh::dest(e->sym()->lNext())) )
619 typename TPlanarMesh::TVector2D v1 = TPlanarMesh::fastDest(e->lNext())-TPlanarMesh::fastDest(e);
620 typename TPlanarMesh::TVector2D v2 = TPlanarMesh::fastOrg(e)-TPlanarMesh::fastDest(e->lNext());
621 typename TPlanarMesh::TVector2D v3 = TPlanarMesh::fastDest(e->sym()->lNext())-TPlanarMesh::fastOrg(e);
622 typename TPlanarMesh::TVector2D v4 = TPlanarMesh::fastDest(e)-TPlanarMesh::fastDest(e->sym()->lNext());
627 T angle1 = lass::num::acos(lass::prim::dot( v1, v2));
628 T angle2 = lass::num::acos(lass::prim::dot( v2, v3));
629 T angle3 = lass::num::acos(lass::prim::dot( v3, v4));
630 T angle4 = lass::num::acos(lass::prim::dot( v4, v1));
640 edgeList.push_back( e );
652 class BrutePointExactLocator
654 typedef PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle> TPlanarMesh;
655 typename TPlanarMesh::TPoint2D point_;
657 typename TPlanarMesh::TEdge* edge;
658 BrutePointExactLocator(
const typename TPlanarMesh::TPoint2D& iPoint ) : point_(iPoint), edge(NULL) {}
659 bool findPoint(
typename TPlanarMesh::TEdge* e )
661 if (TPlanarMesh::org(e)==point_)
671 class BrutePointLocator
673 typedef PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle> TPlanarMesh;
674 typename TPlanarMesh::TPoint2D point_;
676 typename TPlanarMesh::TEdge* edge;
677 BrutePointLocator(
const typename TPlanarMesh::TPoint2D& iPoint ) : point_(iPoint), edge(NULL) {}
678 bool findEdge(
typename TPlanarMesh::TEdge* e )
680 typename TPlanarMesh::TEdge* ce = e;
681 for (
int i=0;i<3;++i)
683 if (TPlanarMesh::rightOf(point_,ce))
690 if (point_==TPlanarMesh::org(e))
695 if (point_==TPlanarMesh::dest(e))
700 if (point_==TPlanarMesh::dest(e->lNext()))
702 edge = e->lNext()->sym();
706 typename TPlanarMesh::TRay2D R1(TPlanarMesh::org(e), TPlanarMesh::dest(e));
707 typename TPlanarMesh::TPoint2D p1 = R1.point( R1.t( point_ ) );
708 typename TPlanarMesh::TRay2D R2(TPlanarMesh::dest(e), TPlanarMesh::org(e->lPrev()));
709 typename TPlanarMesh::TPoint2D p2 = R2.point( R2.t( point_ ) );
710 typename TPlanarMesh::TRay2D R3(TPlanarMesh::org(e->lPrev()), TPlanarMesh::org(e));
711 typename TPlanarMesh::TPoint2D p3 = R3.point( R3.t( point_ ) );
713 typename TPlanarMesh::TPoint2D::TValue d1 = squaredDistance(point_,p1);
714 typename TPlanarMesh::TPoint2D::TValue d2 = squaredDistance(point_,p2);
715 typename TPlanarMesh::TPoint2D::TValue d3 = squaredDistance(point_,p3);
717 if ((d1<d2) && (d1<d3))
722 if ((d2<d3) && (d2<=d1))
755 class BrutePointLocatorVerbose
757 typedef PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle> TPlanarMesh;
758 typename TPlanarMesh::TPoint2D point_;
760 typename TPlanarMesh::TEdge* edge;
761 std::ofstream stream;
762 BrutePointLocatorVerbose(
const typename TPlanarMesh::TPoint2D& iPoint ) : point_(iPoint), edge(NULL) {}
763 bool findEdge(
typename TPlanarMesh::TEdge* e )
765 typename TPlanarMesh::TEdge* ce = e;
768 stream << std::setprecision(20);
770 for (
int i=0;i<3;++i)
773 stream << TPlanarMesh::org(ce) <<
"-->" << TPlanarMesh::dest(ce) <<
":" << prim::doubleTriangleArea(point_,TPlanarMesh::dest(ce),TPlanarMesh::org(ce)) <<
"\n";
775#pragma LASS_TODO("Get rid of the epsilon!")
776 if (prim::doubleTriangleArea(point_,TPlanarMesh::dest(ce),TPlanarMesh::org(ce))>1e-12)
785 T d1 = squaredDistance(TPlanarMesh::org(e),point_);
786 T d2 = squaredDistance(TPlanarMesh::dest(e),point_);
787 T d3 = squaredDistance(TPlanarMesh::dest(e->lNext()),point_);
794 edge=e->lNext()->sym();
801 edge=e->lNext()->sym();
810 lass::io::MatlabOStream& operator<<( lass::io::MatlabOStream& ioOStream,
const typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TEdge& iEdge )
813 ioOStream <<
typename TPlanarMesh::TLineSegment2D(
814 TPlanarMesh::org(iEdge), TPlanarMesh::dest(iEdge) )
822 typedef impl::EdgeMarker<T, PointHandle, EdgeHandle, FaceHandle> TEdgeMarker;
824 typedef typename TPlanarMesh::TEdgeCallback TEdgeCallback;
825 impl::EdgeToMatlab<T,PointHandle,EdgeHandle,FaceHandle> matlabWriter(&iMesh, ioOStream);
826 TEdgeMarker edgeMarker( &iMesh,
false );
827 iMesh.forAllPrimaryEdges( TEdgeCallback( &edgeMarker, &TEdgeMarker::internalMark ) );
828 iMesh.forAllPrimaryEdges( TEdgeCallback( &matlabWriter,
829 &impl::EdgeToMatlab<T,PointHandle,EdgeHandle,FaceHandle>::edgeToMatlab ) );
830 iMesh.forAllPrimaryEdges( TEdgeCallback( &edgeMarker, &TEdgeMarker::internalMark ) );
831 iMesh.forAllPrimaryEdges( TEdgeCallback( &matlabWriter,
832 &impl::EdgeToMatlab<T,PointHandle,EdgeHandle,FaceHandle>::vertexToMatlab ) );
837 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::makeMaximalConvexPolygon(T iMaxSurface)
839 typedef impl::EdgeGatherer<T, PointHandle, EdgeHandle, FaceHandle> TEdgeGatherer;
840 typedef impl::EdgeMarker<T, PointHandle, EdgeHandle, FaceHandle> TEdgeMarker;
842 TEdgeMarker edgeMarker(
this,
false );
843 forAllPrimaryEdges( TEdgeCallback( &edgeMarker, &TEdgeMarker::internalMark ) );
846 TEdgeGatherer edgeGatherer(
this );
847 edgeGatherer.maxSurface = iMaxSurface;
848 edgeGatherer.edgeList.clear();
849 forAllPrimaryUndirectedEdgesCached( TEdgeCallback( &edgeGatherer, &TEdgeGatherer::makeConvexPolygon) );
850 if (edgeGatherer.edgeList.size()>0)
851 gcDeleteEdge( edgeGatherer.edgeList.front() );
856 std::cout <<
"PlanarMesh GC collected " << gc() <<
" edges" << std::endl;
861 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::makeRectangular(T minAngle, T maxAngle)
863 typedef impl::EdgeGatherer<T, PointHandle, EdgeHandle, FaceHandle> TEdgeGatherer;
864 typedef impl::EdgeMarker<T, PointHandle, EdgeHandle, FaceHandle> TEdgeMarker;
866 TEdgeMarker edgeMarker(
this,
false );
867 forAllPrimaryEdges( TEdgeCallback( &edgeMarker, &TEdgeMarker::internalMark ) );
870 TEdgeGatherer edgeGatherer(
this );
871 edgeGatherer.edgeList.clear();
872 edgeGatherer.angleConstraintMin = minAngle;
873 edgeGatherer.angleConstraintMax = maxAngle;
874 forAllPrimaryUndirectedEdgesCached( TEdgeCallback( &edgeGatherer, &TEdgeGatherer::makeRectangular) );
875 if (edgeGatherer.edgeList.size()==0)
877 if (edgeGatherer.edgeList.size()>0)
879 gcDeleteEdge( edgeGatherer.edgeList.back() );
880 edgeGatherer.edgeList.pop_back();
884 std::cout <<
"PlanarMesh GC collected " << gc() <<
" edges" << std::endl;
890 PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::PlanarMesh(
const TPoint2D& a,
const TPoint2D& b,
const TPoint2D& c)
892 allocateInTemp_ =
false;
894 pointDistanceTolerance_ = 1.0e-8;
895 TEdge* ea = makeEdge(a, b,
true);
896 TEdge* eb = makeEdge(b, c,
true);
897 TEdge* ec = makeEdge(c, a,
true);
900 TQuadEdge::splice(ea->sym(), eb);
901 TQuadEdge::splice(eb->sym(), ec);
902 TQuadEdge::splice(ec->sym(), ea);
905 lastLocateEdge_.reset(startEdge_);
906 lastFloodEdge_.reset(startEdge_);
910 boundingPoints_.push_back(a);
911 boundingPoints_.push_back(b);
912 boundingPoints_.push_back(c);
918 allocateInTemp_ =
false;
919 tolerance_ = T(1.0e-8);
920 pointDistanceTolerance_ = T(1.0e-8);
922 TEdge* ea = makeEdge(a, b,
true);
923 TEdge* eb = makeEdge(b, c,
true);
924 TEdge* ec = makeEdge(c, d,
true);
925 TEdge* ed = makeEdge(d, a,
true);
927 TQuadEdge::splice(ea->sym(), eb);
928 TQuadEdge::splice(eb->sym(), ec);
929 TQuadEdge::splice(ec->sym(), ed);
930 TQuadEdge::splice(ed->sym(), ea);
932 if (prim::inCircle( c,d,a,b ))
938 lastLocateEdge_.reset(startEdge_);
939 lastFloodEdge_.reset(startEdge_);
944 boundingPoints_.push_back(a);
945 boundingPoints_.push_back(b);
946 boundingPoints_.push_back(c);
947 boundingPoints_.push_back(d);
951 PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::PlanarMesh(
const prim::Aabb2D<T>& iAabb )
953 allocateInTemp_ =
false;
954 TPoint2D topleft(iAabb.min().x, iAabb.max().y);
955 TPoint2D topright(iAabb.max().x, iAabb.max().y);
956 TPoint2D bottomleft(iAabb.min().x, iAabb.min().y);
957 TPoint2D bottomright(iAabb.max().x, iAabb.min().y);
958 init4(topleft, bottomleft, bottomright, topright);
964 allocateInTemp_ =
false;
970 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::deletePoint(
typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TEdge* iEdge)
972 if (iEdge->handle().point_)
973 free(iEdge->handle().point_);
974 TEdge* currentEdge = iEdge;
977 currentEdge->handle().point_ = NULL;
978 currentEdge = currentEdge->oNext();
979 }
while ( currentEdge != iEdge );
984 PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::~PlanarMesh( )
986 forAllVertices( TEdgeCallback(
this, &PlanarMesh::deletePoint) );
987 typename TQuadEdgeList::iterator qIt;
988 for (qIt = quadEdgeList_.begin(); qIt != quadEdgeList_.end();++qIt)
990 (*qIt)->edgeDeconstrain();
991 (*qIt)->faceDeconstrain();
997 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::setTempQuadEdges(
bool iAllocateInTemp )
999 allocateInTemp_ = iAllocateInTemp;
1000 if (!allocateInTemp_ )
1002 std::copy(tempQuadEdgeList_.begin(),tempQuadEdgeList_.end(),std::back_inserter(quadEdgeList_));
1003 tempQuadEdgeList_.clear();
1009 typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TEdge* PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::makeEmptyEdge(
bool makeConstrained )
1011 TQuadEdge* qe = make(TQuadEdge(makeConstrained));
1012 if (allocateInTemp_)
1013 tempQuadEdgeList_.push_back( qe );
1015 quadEdgeList_.push_back( qe );
1018 TEdge* e = qe->edges();
1033 FaceHandle fa = faceHandle(a);
1034 FaceHandle fb = faceHandle(b);
1037 LASS_THROW(
"connect of edges would violate face constraint");
1039 PointHandle hADest = pointHandle( a->sym() );
1040 PointHandle hB = pointHandle( b );
1041 TEdge* e =
makeEdge( dest(a), org(b),
false);
1042 TQuadEdge::splice( e, a->lNext() );
1043 TQuadEdge::splice( e->sym(), b );
1045 setFaceHandle( e, fa );
1046 setPointHandle( a->sym(), hADest );
1047 setPointHandle( b, hB );
1054 LASS_ENFORCE(iWhere>T(0) && iWhere<T(1));
1055 splitEdge(iEdge,along(iEdge,iWhere));
1056 return iEdge->lNext();
1074 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::removeVertex( TEdge* iEdge)
1077 int n = vertexOrder(iEdge);
1078 TEdge* currentEdge = iEdge;
1079 for (
int i=0;i<n;++i)
1081 gcDeleteEdge(currentEdge);
1082 currentEdge = currentEdge->oNext();
1089 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::fixEdge(TEdge *e)
1095 if (e->isConstrained())
1097 TEdge *f = e->oPrev();
1098 TEdge *g = e->dNext();
1100 if ( prim::inCircle( dest(e),dest(e->oNext()),org(e),dest(f)) )
1110 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::safeSplitEdge(TEdge *e,
const TPoint2D& iPoint )
1118 TRay2D testRay1(org(e),dest(e));
1119 if (testRay1.t(dest(e))<=testRay1.t(iPoint))
1121 LASS_THROW(
"Inconsistent splitting of constrained edge");
1123 TRay2D testRay2(dest(e),org(e));
1124 if (testRay2.t(org(e))<=testRay2.t(iPoint))
1126 LASS_THROW(
"Inconsistent splitting of constrained edge");
1128 splitEdge(e,iPoint);
1133 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::splitEdge(TEdge *e,
const TPoint2D& iPoint )
1145 const TVector2D dir = direction(e);
1146 PointHandle iE = pointHandle(e);
1147 [[maybe_unused]] PointHandle iES = pointHandle(e->sym());
1148 EdgeHandle iLE = edgeHandle(e);
1149 EdgeHandle iRE = edgeHandle(e->sym());
1152 TEdge* t = e->lNext();
1153 TQuadEdge::splice( e->sym(), t );
1154 setDest( thePoint, e );
1155 setPointHandle(e, iE);
1156 TEdge* ne = connect( e, t );
1157 if (e->isConstrained())
1161 setOrientedEdgeHandle( e, iLE, iRE, dir );
1162 setOrientedEdgeHandle( ne, iLE, iRE, dir );
1163 ne->quadEdge()->edgeConstrain();
1167 LASS_ASSERT( pointHandle(e) == iE );
1168 LASS_ASSERT( pointHandle(e->lNext()->sym()) == iES );
1172 typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TPoint2D PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::snap(
const TPoint2D& x,
const TPoint2D& a,
const TPoint2D& b)
1185 T t1 = dot(x-a,b-a);
1186 T t2 = dot(x-b,a-b);
1188 T t = std::max(t1,t2) / (t1 + t2);
1190 if (prim::doubleTriangleArea(x,a,b)==T(0))
1195 T rx1 = (T(1)-t)*a.x + t*b.x;
1196 T ry1 = (T(1)-t)*a.y + t*b.y;
1200 T rx2 = (T(1)-t)*b.x + t*a.x;
1201 T ry2 = (T(1)-t)*b.y + t*a.y;
1207 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::swap( TEdge* iEdge )
1209 if ( iEdge->isConstrained() )
1211 LASS_THROW(
"cannot swap constrained edge" );
1214 TEdge* a = e->oPrev();
1215 TEdge* b = e->sym()->oPrev();
1225 PointHandle hA = pointHandle(e->oNext()->sym());
1226 [[maybe_unused]] PointHandle hB = pointHandle(e);
1227 [[maybe_unused]] PointHandle hC = pointHandle(e->sym());
1228 PointHandle hD = pointHandle(e->oPrev()->sym());
1230 TQuadEdge::splice( e, a );
1231 TQuadEdge::splice( e->sym(), b );
1232 TQuadEdge::splice( e, a->lNext() );
1233 TQuadEdge::splice( e->sym(), b->lNext() );
1234 setOrg( dest(a), e );
1235 setDest( dest(b), e );
1237 setPointHandle( e, hD );
1238 setPointHandle( e->sym(), hA );
1240 LASS_ASSERT( leftOf( dest(e->lNext()), e ) );
1241 LASS_ASSERT( leftOf( dest(e->lNext()->lNext()), e->lNext() ) );
1242 LASS_ASSERT( leftOf( dest(e->lNext()->lNext()->lNext()), e->lNext()->lNext() ) );
1243 LASS_ASSERT( leftOf( dest(e->sym()->lNext()), e->sym() ) );
1244 LASS_ASSERT( leftOf( dest(e->sym()->lNext()->lNext()), e->sym()->lNext() ) );
1245 LASS_ASSERT( leftOf( dest(e->sym()->lNext()->lNext()->lNext()), e->sym()->lNext()->lNext() ) );
1247 LASS_ASSERT( pointHandle( e->oNext()->sym() ) == hB );
1248 LASS_ASSERT( pointHandle( e->oPrev()->sym() ) == hC );
1254 if ( e->isConstrained() )
1259 while (startEdge_->quadEdge()==e->quadEdge())
1260 startEdge_=e->lNext();
1263 if ( *lastLocateEdge_==e
1264 || *lastLocateEdge_==e->rot()
1265 || *lastLocateEdge_==e->sym()
1266 || *lastLocateEdge_==e->sym()->rot())
1267 lastLocateEdge_.reset(startEdge_);
1268 if ( *lastFloodEdge_==e
1269 || *lastFloodEdge_==e->rot()
1270 || *lastFloodEdge_==e->sym()
1271 || *lastFloodEdge_==e->sym()->rot())
1272 lastFloodEdge_.reset(startEdge_);
1274 TQuadEdge::splice( e, e->oPrev() );
1275 TQuadEdge::splice( e->sym(), e->sym()->oPrev() );
1277 typename TQuadEdgeList::iterator it = std::find(quadEdgeList_.begin(),quadEdgeList_.end(),e->quadEdge());
1278 std::swap(*it, quadEdgeList_.back());
1280 TQuadEdge* qe = quadEdgeList_.back();
1281 qe->edgeDeconstrain();
1282 qe->faceDeconstrain();
1283 quadEdgeList_.pop_back();
1293 if ( e->isConstrained() )
1298 while (startEdge_->quadEdge()==e->quadEdge())
1299 startEdge_=e->lNext();
1301 if ( *lastLocateEdge_==e
1302 || *lastLocateEdge_==e->rot()
1303 || *lastLocateEdge_==e->sym()
1304 || *lastLocateEdge_==e->sym()->rot())
1305 lastLocateEdge_.reset(startEdge_);
1306 if ( *lastFloodEdge_==e
1307 || *lastFloodEdge_==e->rot()
1308 || *lastFloodEdge_==e->sym()
1309 || *lastFloodEdge_==e->sym()->rot())
1310 lastFloodEdge_.reset(startEdge_);
1312 TQuadEdge::splice( e, e->oPrev() );
1313 TQuadEdge::splice( e->sym(), e->sym()->oPrev() );
1315 TQuadEdge* qe = e->quadEdge();
1316 qe->edgeDeconstrain();
1317 qe->faceDeconstrain();
1332 int lastMarker = quadEdgeList_.size()-1;
1333 int startMarker = 0;
1335 int n = quadEdgeList_.size()-1;
1337 while (startMarker<lastMarker)
1340 while (!quadEdgeList_[startMarker]->deleted && startMarker<n)
1343 while (quadEdgeList_[lastMarker]->deleted && lastMarker>0)
1346 if (quadEdgeList_[startMarker]->deleted && !quadEdgeList_[lastMarker]->deleted )
1347 std::swap(quadEdgeList_[startMarker],quadEdgeList_[lastMarker]);
1353 while (quadEdgeList_[lastMarker]->deleted && lastMarker>0)
1356 quadEdgeList_.pop_back();
1364 typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TEdge* PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::bruteForceLocate(
const TPoint2D& iPoint )
const
1367 impl::BrutePointLocator<T, PointHandle, EdgeHandle, FaceHandle> bruteLocator1( iPoint );
1368 const_cast<TPlanarMesh*
>(
this)->forAllFaces( TEdgeCallback( &bruteLocator1, &impl::BrutePointLocator<T, PointHandle, EdgeHandle, FaceHandle>::findEdge ) );
1369 if (bruteLocator1.edge==NULL)
1371 impl::BrutePointLocator<T, PointHandle, EdgeHandle, FaceHandle> bruteLocator2( iPoint );
1372 const_cast<TPlanarMesh*
>(
this)->forAllPrimaryEdges( TEdgeCallback( &bruteLocator2, &impl::BrutePointLocator<T, PointHandle, EdgeHandle, FaceHandle>::findEdge ) );
1374 if (bruteLocator2.edge==NULL)
1376 impl::BrutePointLocatorVerbose<T, PointHandle, EdgeHandle, FaceHandle> bruteLocatorVerbose( iPoint );
1377 bruteLocatorVerbose.stream.open(
"bruteforcelocation.txt");
1378 const_cast<TPlanarMesh*
>(
this)->forAllPrimaryEdges( TEdgeCallback( &bruteLocatorVerbose, &impl::BrutePointLocatorVerbose<T, PointHandle, EdgeHandle, FaceHandle>::findEdge ) );
1379 bruteLocatorVerbose.stream.close();
1380 return bruteLocatorVerbose.edge;
1383 return bruteLocator2.edge;
1385 return bruteLocator1.edge;
1390 typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TEdge* PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::bruteForceExactLocate(
const TPoint2D& iPoint )
const
1393 impl::BrutePointExactLocator<T, PointHandle, EdgeHandle, FaceHandle> brutePointLocator( iPoint );
1394 const_cast<TPlanarMesh*
>(
this)->forAllVertices( TEdgeCallback( &brutePointLocator, &impl::BrutePointExactLocator<T, PointHandle, EdgeHandle, FaceHandle>::findPoint ) );
1395 return brutePointLocator.edge;
1401 size_t length = boundingPoints_.size();
1402 for (
size_t i=0;i<length;++i)
1404 if (boundingPoints_[i]==iPoint)
1416 *lastLocateEdge_ = iHint;
1417 TEdge*& lastLocateEdge = *lastLocateEdge_;
1418 long edgesPassed = 0;
1420 TEdge* e = lastLocateEdge;
1421 while (edgesPassed<(edgeCount_+2))
1425 const TPoint2D& eorg = fastOrg(e);
1426 const TPoint2D& edest = fastDest(e);
1428 if ( eorg == iPoint )
1433 if ( edest == iPoint )
1439 if ( fastRightOf( iPoint, e ) )
1443 bool hasALeftFace =
true;
1445 hasALeftFace = fastHasLeftFace(e);
1455 if ( fastLeftOf( iPoint, e->oNext()) )
1465 for (
int i=0;i<loopOrder;++i)
1467 if ( fastLeftOf( iPoint, ce->dPrev()) )
1470 goto continueSearch;
1475 TRay2D R1(fastOrg(e), fastDest(e));
1476 TPoint2D p1 = R1.
point( R1.
t( iPoint ) );
1477 TRay2D R2(fastDest(e), fastOrg(e->lPrev()));
1478 TPoint2D p2 = R2.
point( R2.
t( iPoint ) );
1479 TRay2D R3(fastOrg(e->lPrev()), fastOrg(e));
1480 TPoint2D p3 = R3.
point( R3.
t( iPoint ) );
1482 typename TPoint2D::TValue d1 = squaredDistance(iPoint,p1);
1483 typename TPoint2D::TValue d2 = squaredDistance(iPoint,p2);
1484 typename TPoint2D::TValue d3 = squaredDistance(iPoint,p3);
1492 if ((d1<d2) && (d1<d3))
1497 if ((d2<d3) && (d2<=d1))
1508 if (onEdge(iPoint,e))
1515 if (rightOf(iPoint, e->oPrev()))
1517 e = e->oPrev()->sym();
1520 if (rightOf(iPoint,e->dNext()))
1522 e = e->dNext()->sym();
1528 e = bruteForceLocate(iPoint);
1536 TEdge*& lastLocateEdge = *lastLocateEdge_;
1537 long edgesPassed = 0;
1539 TEdge* e = lastLocateEdge;
1540 while (edgesPassed<(edgeCount_+2))
1543 if ( org( e ) == iPoint )
1548 if ( dest( e ) == iPoint )
1554 if ( rightOf( iPoint, e ) )
1559 if ( iPoint == org(e->lPrev()) )
1565 if ( leftOf( iPoint, e->oNext()) )
1570 if ( leftOf( iPoint, e->dPrev()) )
1577 if (rightOf(iPoint, e->oPrev()))
1579 e = e->oPrev()->sym();
1582 if (rightOf(iPoint,e->dNext()))
1584 e = e->dNext()->sym();
1589 e = bruteForceExactLocate(iPoint);
1590 LASS_ASSERT(e!=NULL);
1602 TEdge* startEdge = locateEdge;
1606 if (org(startEdge)==iRay.
support())
1608 TEdge* e(startEdge);
1611 for (
int i=0;i<vOrder+1;++i)
1620 && iRay.
t(dest(e)) > T(0) )
1628 TEdge* e(startEdge);
1637 lastSide = currentSide;
1640 while (e!=startEdge);
1641 startEdge = startEdge->oNext();
1642 }
while (startEdge!=locateEdge);
1648 bugMesh.open(
"shoot_ray.m" );
1649 bugMesh << std::setprecision(15);
1650 bugMesh << *const_cast<PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>*>(
this);
1652 bugMesh.open(
"shoot_ray_edges.m" );
1653 bugMesh.setColor(lass::io::mcBlue);
1654 bugMesh << TLineSegment2D(iRay.
support(),iRay.
point(1.0));
1657 TEdge* e(startEdge);
1659 bugMesh.setColor(lass::io::mcRed);
1660 bugMesh << TLineSegment2D(org(startEdge),dest(startEdge));
1663 bugMesh.setColor(lass::io::mcGreen);
1664 bugMesh << TLineSegment2D(org(e),dest(e));
1668 lastSide = currentSide;
1671 while (e!=startEdge);
1672 startEdge = startEdge->oNext();
1673 }
while (startEdge!=locateEdge);
1683 typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TEdge* PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::pointShoot(
const TRay2D& iRay )
const
1685 TEdge* locateEdge = pointLocate(iRay.support());
1686 LASS_ASSERT(isBoundingPoint(org(locateEdge)) || allEqualChainOrder(locateEdge));
1687 TEdge* startEdge = locateEdge;
1692 TEdge* e(startEdge);
1694 int vOrder = vertexOrder(e);
1695 for (
int i=0;i<vOrder+1;++i)
1703 if (
num::abs(prim::doubleTriangleArea(iRay.support(),iRay.point(T(1)),dest(e)))<tolerance_
1704 && iRay.t(dest(e)) > T(0) )
1712 TEdge* e(startEdge);
1719 lastSide = currentSide;
1722 while (e!=startEdge);
1723 startEdge = startEdge->oNext();
1724 }
while (startEdge!=locateEdge);
1726 LASS_THROW(
"pointShoot, could not find suitable triangle");
1733 template <
typename OutputIterator>
1734 OutputIterator PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::walkIntersections(
const TLineSegment2D& iSegment, OutputIterator oIntersections)
const
1736 std::vector<TEdge*> crossedEdges;
1737 walk(iSegment,std::back_inserter(crossedEdges));
1738 const size_t n = crossedEdges.size();
1739 for (
size_t i=0;i<n;++i)
1745 (*oIntersections++) = std::pair<TPoint2D,TEdge*>(fastOrg(crossedEdges[i]),crossedEdges[i]);
1746 if (squaredDistance(fastOrg(crossedEdges[i]),fastDest(crossedEdges[i]))<squaredDistance(iSegment.tail(),iSegment.head()))
1747 (*oIntersections++) = std::pair<TPoint2D,TEdge*>(fastDest(crossedEdges[i]),crossedEdges[i]);
1749 (*oIntersections++) = std::pair<TPoint2D,TEdge*>(iSegment.head(),crossedEdges[i]);
1753 (*oIntersections++) = std::pair<TPoint2D,TEdge*>(intersection,crossedEdges[i]);
1756 return oIntersections;
1762 template <
typename OutputIterator>
1763 OutputIterator PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::walk(
const TLineSegment2D& iSegment, OutputIterator crossedEdges )
const
1766 e = shoot(TRay2D(iSegment.tail(),iSegment.vector()));
1770 LASS_THROW(
"Could not shoot initial ray in walk");
1772 if (inConvexCell(iSegment.head(),e))
1773 return crossedEdges;
1774 if (dest(e)==iSegment.head())
1776 (*crossedEdges++) = e;
1777 return crossedEdges;
1780 while ( !leftOf(iSegment.head(),e)
1781 || ( (
num::abs(prim::doubleTriangleArea(dest(e),iSegment.head(),iSegment.tail()))<tolerance_ )
1782 && (
num::abs(prim::doubleTriangleArea(org(e),iSegment.head(),iSegment.tail()))<tolerance_ ) ) )
1784 (*crossedEdges++) = e;
1792 TEdge* ce = e->sym()->lNext();
1793#pragma LASS_TODO("Optimize")
1797 for (
int i=0;i<chainOrder(e);++i)
1799 if ( weakCcw( iSegment.tail(), iSegment.head(), dest(ce) ) )
1808 LASS_THROW(
"Planarmesh: stuck in walk");
1811 return crossedEdges;
1816 std::pair<int, typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TEdge*> PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::walkTillConstrained(
const TRay2D& iRay)
const
1820 TLineSegment2D segment(iRay.support(),iRay.support()+iRay.direction());
1825 LASS_THROW(
"Could not shoot initial ray in walk");
1827 while ( !e->isConstrained())
1836 TEdge* ce = e->sym()->lNext();
1837#pragma LASS_TODO("Optimize")
1841 int n = chainOrder(e);
1842 for (
int i=0;i<n;++i)
1844 if ( weakCcw( segment.tail(), segment.head(), dest(ce) ) )
1854 LASS_THROW(
"Planarmesh: stuck in walkTillConstrained");
1857 return std::make_pair(nCrossed,e);
1864 template <
typename OutputIterator>
1865 OutputIterator PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::pointWalk(
const TLineSegment2D& iSegment, OutputIterator crossedEdges )
const
1868 e = pointShoot(TRay2D(iSegment.tail(),iSegment.vector()));
1869 LASS_ASSERT(isBoundingPoint(org(e)) || allEqualChainOrder(e));
1872 LASS_THROW(
"Could not shoot initial ray in pointWalk");
1874 if (dest(e)==iSegment.head())
1876 (*crossedEdges++) = e;
1877 return crossedEdges;
1880 while ( !leftOf(iSegment.head(),e)
1881 || ( (
num::abs(prim::doubleTriangleArea(dest(e),iSegment.head(),iSegment.tail()))<tolerance_ )
1882 && (
num::abs(prim::doubleTriangleArea(org(e),iSegment.head(),iSegment.tail()))<tolerance_ ) ) )
1884 (*crossedEdges++) = e;
1892 TEdge* ce = e->sym()->lNext();
1893#pragma LASS_TODO("Optimize")
1896 for (
int i=0;i<chainOrder(e)-1;++i)
1898 if ( weakCcw( iSegment.tail(), iSegment.head(), dest(ce) ) )
1906 return crossedEdges;
1911 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::triangulate( TEdge* iEdge )
1923 TEdge *first = iEdge;
1924 TEdge *a, *b, *e, *t1, *t2, *last = first->lPrev();
1926 while (first->lNext()->lNext() != last)
1933 if (t2 == last && t1 == first)
1935 if (leftOf(dest(e),t1))
1938 t1 = first = connect(e, t1)->sym();
1940 t1 = connect(e, t1)->sym();
1941 a = t1->oPrev(), b = t1->dNext();
1953 a = last->lNext(), b = last->lPrev();
1968 TEdge* e =
locate( iPoint );
1972 LASS_ASSERT( e!=NULL);
1974 T sqDistOrgEP = prim::squaredDistance(org(e),iPoint);
1975 T sqDistDestEP = prim::squaredDistance(dest(e),iPoint);
1977 if (sqDistOrgEP<pointDistanceTolerance_*pointDistanceTolerance_)
1979 if (sqDistDestEP<pointDistanceTolerance_*pointDistanceTolerance_)
1982 bool hasLeft = hasLeftFace(e);
1983 bool hasRight = hasRightFace(e);
1985 if (!hasLeft && !hasRight)
1989 bugMesh.open(
"bugMesh.m" );
1993 throw std::runtime_error(
"insertSite: edge does not have any faces");
1996 bool isOnEdge = onEdge(iPoint, e) || forceOnEdge;
1998 if (!isOnEdge && TLine2D(org(e),dest(e)).squaredDistance(iPoint)<T(1.05)*pointDistanceTolerance_*pointDistanceTolerance_)
2003 TPoint2D x = snap(iPoint, org(e), dest(e));
2007 bool insideLeft = hasLeft && (isOnEdge || leftOf(iPoint, e)) &&
2008 rightOf(iPoint, e->oNext()) && rightOf(iPoint, e->dPrev());
2009 bool insideRight = hasRight && (isOnEdge || rightOf(iPoint, e)) &&
2010 leftOf(iPoint, e->oPrev()) && leftOf(iPoint, e->dNext());
2015 TPoint2D p1 = org(e);
2016 TPoint2D p2 = dest(e);
2017 TPoint2D p3 = dest(e->lNext());
2019 T s1 = prim::doubleTriangleArea(iPoint,p1,p2);
2020 T s2 = prim::doubleTriangleArea(iPoint,p2,p3);
2021 T s3 = prim::doubleTriangleArea(iPoint,p3,p1);
2025 if ( s1*s2 < T(0) || s2*s3 < T(0) || s1*s3 < T(0) )
2027 if (squaredDistance(org(e),iPoint)<squaredDistance(dest(e),iPoint))
2029 if (squaredDistance(org(e),iPoint)<pointDistanceTolerance_*pointDistanceTolerance_)
2035 std::cout <<
"Numerical instability detected in lass::mesh\n";
2040 if (squaredDistance(dest(e),iPoint)<pointDistanceTolerance_*pointDistanceTolerance_)
2041 return insertSite(dest(e),makeDelaunay,
true);
2046 std::cout <<
"Numerical instability detected in lass::mesh\n";
2053 LASS_ASSERT( s1*s2 > T(0) );
2054 LASS_ASSERT( s2*s3 > T(0) );
2055 LASS_ASSERT( s1*s3 > T(0) );
2060 if (insideLeft && iPoint == dest(e->oNext()))
2062 if (insideRight && iPoint == dest(e->oPrev()))
2068 TPoint2D x = snap(iPoint, org(e), dest(e));
2069 T sqDistOrgEX = prim::squaredDistance(org(e),x);
2070 T sqDistDestEX = prim::squaredDistance(dest(e),x);
2072 if (sqDistOrgEX<pointDistanceTolerance_*pointDistanceTolerance_)
2074 if (sqDistDestEX<pointDistanceTolerance_*pointDistanceTolerance_)
2078 if (hasRight && hasLeft)
2081 TEdge *a, *b, *c, *d;
2086 safeSplitEdge(e, x);
2088 connect(e->oPrev(), e->sym());
2099 TEdge *c = e->lNext();
2100 TEdge *d = e->lPrev();
2101 safeSplitEdge(e, x);
2107 LASS_ASSERT(x==dest(e));
2115 PointHandle pH = pointHandle(e);
2116 TEdge* base =
makeEdge(org(e),iPoint,
false);
2117 TQuadEdge::splice(base,e);
2118 setPointHandle(e, pH);
2119 TEdge* startBase = base->sym();
2123 base =
connect( e, base->sym() );
2125 }
while (e->dPrev()!=startBase);
2132 TEdge* t=e->oPrev();
2133 if ( !e->isConstrained() && prim::inCircle(org(e),dest(t),dest(e),iPoint))
2140 if (e->lPrev()==startBase)
2143 e = e->oNext()->lPrev();
2148 LASS_ASSERT(iPoint==dest(base));
2159 typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TEdge*
PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::insertEdge(
const TLineSegment2D& iSegment, EdgeHandle iLeftHandle, EdgeHandle iRightHandle, PointHandle iPointHandle,
bool iForcePointHandle,
bool makeDelaunay )
2162 std::cout <<
"Inserting : " << iSegment <<
"\n";
2163 static int passCountMesh = 0;
2166 sprintf(buf,
"debug_mesh_%d.m",passCountMesh);
2168 debugMesh.open(buf);
2173 TPoint2D aa, bb, fbb, faa;
2174 if (ea =
insertSite(iSegment.tail()),makeDelaunay)
2177 if (iForcePointHandle)
2178 setPointHandle(ea, iPointHandle);
2181 if (eb =
insertSite(iSegment.head()),makeDelaunay)
2184 if (iForcePointHandle)
2185 setPointHandle(eb, iPointHandle);
2190 if (ea == NULL || eb == NULL)
2192 LASS_THROW(
"insertEdge: could not insert endpoints of edge");
2200 LASS_THROW(
"insertEdge: could not locate an endpoint");
2203 if (!(aa == org(ea)))
2205 if (!(aa == org(ea)))
2207 LASS_THROW(
"insertEdge: point a is not an endpoint of ea");
2220 for (
int i=0;i<vOrder;++i)
2224 ce->quadEdge()->edgeConstrain();
2225 setOrientedEdgeHandle( ce, iLeftHandle, iRightHandle, iSegment.
vector() );
2230 if (distance(aa,bb)<pointDistanceTolerance_ )
2232 LASS_THROW(
"insertEdge: both ends map to same vertex within requested numerical precision");
2235 for (
int i=0;i<vOrder;++i)
2238 if ( prim::dot(direction(ce), iSegment.
vector()) > T(0)
2239 &&
num::abs(lass::prim::doubleTriangleArea(dest(ce),faa,fbb))<tolerance_)
2241 ce->quadEdge()->edgeConstrain();
2242 setOrientedEdgeHandle( ce, iLeftHandle, iRightHandle, iSegment.
vector() );
2244 return insertEdge( TLineSegment2D( dest(ce), fbb), iLeftHandle, iRightHandle, iPointHandle, iForcePointHandle, makeDelaunay );
2251 std::vector< TEdge* > insertedEdges;
2252 std::vector< TPoint2D > insertedPoints;
2253 std::vector< TPoint2D > finalInsertedPoints;
2254 std::vector< TEdge* > crossedEdges;
2255 std::vector< TEdge* > filteredEdges;
2260 pointWalk(TLineSegment2D(faa,fbb),std::back_inserter(crossedEdges));
2262 std::cout <<
"Walk returned segments " << crossedEdges.size() <<
"\n";
2263 std::cout << std::setprecision(15);
2267 insertedPoints.push_back(faa);
2268 for (
size_t i=0;i<crossedEdges.size();++i)
2270 bool computeIntersection = (crossedEdges[i]->isConstrained());
2271 TPoint2D eorg = org(crossedEdges[i]);
2272 TPoint2D edest= dest(crossedEdges[i]);
2273 bool noCommonPoints = eorg!=faa && eorg!=fbb && edest!=faa && edest!=fbb;
2274 if ( computeIntersection
2277 TLine2D other(eorg,edest);
2280 if (prim::intersect(TLine2D(aa,bb),other,x)==
prim::rOne)
2283 TPoint2D nx = org(npe);
2289 if (nx!=insertedPoints.back())
2291 insertedPoints.push_back(nx);
2293 std::cout <<
"-> Intersection " << x <<
" filtered to " << nx <<
"\n";
2300 filteredEdges.push_back(crossedEdges[i]);
2302 if (fbb!=insertedPoints.back())
2303 insertedPoints.push_back(fbb);
2306 if (insertedPoints.size()>2)
2310 for (
size_t i=0;i<insertedPoints.size()-1;++i)
2312 ce =
insertEdge( TLineSegment2D(insertedPoints[i],insertedPoints[i+1]), iLeftHandle, iRightHandle, iPointHandle, iForcePointHandle, makeDelaunay );
2316 if ( org(bce) != faa )
2320 LASS_ASSERT( org(bce)==faa);
2325 std::vector< TEdge* > toSwapEdges;
2328 bool madeConstraint =
false;
2330 for (
size_t i=0;i<filteredEdges.size();++i)
2333 TPoint2D a = org(filteredEdges[i]);
2334 TPoint2D b = dest(filteredEdges[i]);
2335 TPoint2D c = dest(filteredEdges[i]->lNext());
2336 TPoint2D d = dest(filteredEdges[i]->sym()->lNext());
2337 bool swappedCcw1 = prim::ccw(d,b,c);
2338 bool swappedCcw2 = prim::ccw(a,d,c);
2339 if (!swappedCcw1 || !swappedCcw2)
2343 bugMesh.open(
"swap_constrained.m" );
2345 for (
int j=0;j<filteredEdges.size();++j)
2347 bugMesh.setColor( lass::io::mcBlue);
2348 bugMesh << TLineSegment2D(org(filteredEdges[j]),dest(filteredEdges[j]));
2350 bugMesh.setColor( lass::io::mcRed );
2351 bugMesh << TLineSegment2D(a,b);
2352 bugMesh.setColor( lass::io::mcGreen );
2353 bugMesh << TLineSegment2D(faa,fbb);
2356 toSwapEdges.push_back(filteredEdges[i]);
2362 if (filteredEdges[i]->quadEdge()->isConstrained())
2364 LASS_THROW(
"found constrained edge where I should not find one!");
2366 swap(filteredEdges[i]);
2367 TPoint2D eorg = org(filteredEdges[i]);
2368 TPoint2D edest = dest(filteredEdges[i]);
2369 T onEdgeOrg =
num::abs(prim::doubleTriangleArea(eorg,edest,faa));
2370 T onEdgeDest =
num::abs(prim::doubleTriangleArea(eorg,edest,fbb));
2373 if (onEdgeOrg<tolerance_ && onEdgeDest<tolerance_)
2375 filteredEdges[i]->quadEdge()->edgeConstrain();
2377 std::cout <<
"@ Constraining " << org(filteredEdges[i]) <<
"-->" << dest(filteredEdges[i]) <<
"\n";
2379 setOrientedEdgeHandle( filteredEdges[i], iLeftHandle, iRightHandle, iSegment.
vector() );
2380 if (toSwapEdges.size()>0)
2382 LASS_THROW(
"edges for delayed swapping found");
2384 madeConstraint =
true;
2390 if (toSwapEdges.size()>0)
2391 return insertEdge( iSegment, iLeftHandle, iRightHandle, iPointHandle, iForcePointHandle, makeDelaunay );
2392 if (!madeConstraint)
2394 LASS_THROW(
"could not force constrained edge");
2396 LASS_ASSERT( org(ea) == faa );
2402 typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TEdge* PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::insertPolygon(
const TSimplePolygon2D& iPolygon, EdgeHandle iLeftHandle, EdgeHandle iRightHandle,
bool )
2405 for (
size_t i=1;i<iPolygon.size();++i)
2407 e=insertEdge(TLineSegment2D(iPolygon[i-1],iPolygon[i]),iLeftHandle,iRightHandle);
2409 e=insertEdge(TLineSegment2D(iPolygon[iPolygon.size()-1],iPolygon[0]),iLeftHandle,iRightHandle);
2417 typedef impl::EdgeMarker<T, PointHandle, EdgeHandle, FaceHandle> TEdgeMarker;
2419 TEdgeMarker edgeMarker(
this,
false );
2420 forAllPrimaryEdges( TEdgeCallback( &edgeMarker, &TEdgeMarker::internalMark ) );
2421#pragma LASS_TODO("do a more efficient marking or allow for multiple marking")
2424 for (
int i=0;i<n;++i)
2426 floodPolygon( iStartEdge->sym(), iPolygon, iFaceHandle );
2427 iStartEdge = iStartEdge->lNext();
2433 template <
typename InputPolygonIterator,
typename InputFaceHandleIterator>
2434 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::markPolygons( InputPolygonIterator iFirstPolygon, InputPolygonIterator iLastPolygon, InputFaceHandleIterator iFirstFaceHandle )
2436 typedef impl::EdgeMarker<T, PointHandle, EdgeHandle, FaceHandle> TEdgeMarker;
2438 TEdgeMarker edgeMarker(
this,
false );
2439 forAllPrimaryEdges( TEdgeCallback( &edgeMarker, &TEdgeMarker::internalMark ) );
2441 while (iFirstPolygon != iLastPolygon)
2443 TEdge* iStartEdge =
locate((*iFirstPolygon)[0]);
2445 for (
int i=0;i<n;++i)
2447 floodPolygon( iStartEdge->sym(), *iFirstPolygon, *iFirstFaceHandle );
2448 iStartEdge = iStartEdge->lNext();
2457 template <
typename InputPolygonIterator,
typename InputFaceHandleIterator>
2458 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::forAllPolygonFaces( InputPolygonIterator iFirstPolygon, InputPolygonIterator iLastPolygon, InputFaceHandleIterator iFirstFaceHandle,
const TEdgePolyFaceHandleCallback& iCallback )
2460 typedef impl::EdgeMarker<T, PointHandle, EdgeHandle, FaceHandle> TEdgeMarker;
2462 TEdgeMarker edgeMarker(
this,
false );
2463 forAllPrimaryEdges( TEdgeCallback( &edgeMarker, &TEdgeMarker::internalMark ) );
2465 while (iFirstPolygon != iLastPolygon)
2467 TEdge* iStartEdge =
locate((*iFirstPolygon)[0],*lastFloodEdge_);
2469 for (
int i=0;i<n;++i)
2471 if (!floodPolygonCallback( iStartEdge->sym(), *iFirstPolygon, *iFirstFaceHandle, iCallback ))
2475 if (!floodPolygonCallback( iStartEdge, *iFirstPolygon, *iFirstFaceHandle, iCallback ))
2479 iStartEdge = iStartEdge->lNext();
2484 std::cout <<
"Out polygon faces true" << std::endl;
2491 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::markPolygons(
const std::vector<TSimplePolygon2D>& iPolygons,
const std::vector<FaceHandle>& iFaceHandles)
2493 if (iPolygons.size()!=iFaceHandles.size())
2495 LASS_THROW(
"markPolygons: list of polygons must fit list of face handles");
2497 markPolygons(iPolygons.begin(), iPolygons.end(), iFaceHandles.begin());
2502 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::floodPolygon( TEdge* iStartEdge,
const TSimplePolygon2D& iPolygon, FaceHandle iFaceHandle)
2504 TPoint2D bary = polygon(iStartEdge).surfaceCentroid().affine();
2505 if (iPolygon.contains(bary) && !internalMarking(iStartEdge))
2507 setInternalMarking( iStartEdge,
true );
2508 setFaceHandle( iStartEdge, iFaceHandle );
2509 int n = chainOrder(iStartEdge);
2510 for (
int i=0;i<n;++i)
2512 if (!floodPolygon( iStartEdge->sym(), iPolygon, iFaceHandle))
2514 iStartEdge = iStartEdge->lNext();
2521 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::floodPolygonCallback( TEdge* iStartEdge,
const TSimplePolygon2D& iPolygon, FaceHandle iFaceHandle,
const TEdgePolyFaceHandleCallback& iCallback )
2523 *lastFloodEdge_ = iStartEdge;
2524 TPoint2D bary = polygon(iStartEdge).surfaceCentroid().affine();
2525 if (iPolygon.contains(bary) && !internalMarking(iStartEdge))
2527 setInternalMarking( iStartEdge,
true );
2529 if (!iCallback(iStartEdge, iPolygon,iFaceHandle))
2533 int n = chainOrder(iStartEdge);
2534 for (
int i=0;i<n;++i)
2536 if (!floodPolygonCallback( iStartEdge->sym(), iPolygon, iFaceHandle, iCallback ))
2540 iStartEdge = iStartEdge->lNext();
2549 TEdge* e(makeEmptyEdge( makeConstrained ));
2551 TPoint2D* na = make(a);
2552 TPoint2D* nb = make(b);
2553 e->handle().point_ = na;
2554 e->sym()->handle().point_ = nb;
2560 typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TEdge* PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::startEdge()
const
2567 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::inPrimaryMesh(
const TEdge* iEdge )
2569 return (iEdge->index() == 2) || (iEdge->index() == 0);
2573 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::inDualMesh(
const TEdge* iEdge )
2575 return !inPrimaryMesh( iEdge );
2579 typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TTriangle2D PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::triangle(
const TEdge* iEdge)
2581 if (!inPrimaryMesh(iEdge))
2583 LASS_THROW(
"PlanarMesh::triangle: edge not in primary mesh");
2585 return TTriangle2D(org(iEdge),dest(iEdge),dest(iEdge->lNext()));
2589 typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TSimplePolygon2D PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::polygon(
const TEdge* iEdge)
2591 if (!inPrimaryMesh(iEdge))
2593 LASS_THROW(
"PlanarMesh::polygon: edge not in primary mesh");
2595 TSimplePolygon2D poly;
2596 const TEdge* cEdge = iEdge;
2599 poly.add(org(cEdge));
2600 cEdge = cEdge->lNext();
2601 }
while (cEdge!=iEdge);
2606 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::inConvexCell(
const TPoint2D& iPoint,
const TEdge* iEdge)
2608 if (!inPrimaryMesh(iEdge))
2610 LASS_THROW(
"PlanarMesh::polygon: edge not in primary mesh");
2612 const TEdge* cEdge = iEdge;
2615 if (rightOf(iPoint, cEdge))
2617 cEdge = cEdge->lNext();
2618 }
while (cEdge!=iEdge);
2623 const typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TPoint2D& PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::org(
const TEdge* iEdge )
2625 if (!inPrimaryMesh( iEdge ))
2627 LASS_THROW(
"PlanarMesh::org: edge not in primary mesh");
2629 return *iEdge->handle().point_;
2633 const typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TPoint2D& PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::fastOrg(
const TEdge* iEdge )
2635 return *iEdge->handle().point_;
2639 typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TPoint2D PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::along(
const TEdge* iEdge,
const T& iParam )
2641 LASS_ASSERT(inPrimaryMesh( iEdge ));
2648 const TPoint2D& eOrg = *iEdge->handle().point_;
2649 const TPoint2D& eDest = *iEdge->sym()->handle().point_;
2650 const T oX = eDest.x*iParam + (T(1)-iParam)*eOrg.x;
2651 const T oY = eDest.y*iParam + (T(1)-iParam)*eOrg.y;
2656 typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TPoint2D PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::fastAlong(
const TEdge* iEdge,
const T& iParam )
2658 const TPoint2D& eOrg = *iEdge->handle()->point_;
2659 const TPoint2D& eDest = *iEdge->sym()->handle()->point_;
2660 const T oX = eDest.x*iParam + (T(1)-iParam)*eOrg.x;
2661 const T oY = eDest.y*iParam + (T(1)-iParam)*eOrg.y;
2667 const typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TPoint2D& PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::dest(
const TEdge* iEdge )
2669 return org( iEdge->sym() );
2673 const typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TPoint2D& PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::fastDest(
const TEdge* iEdge )
2675 return fastOrg( iEdge->sym() );
2679 const typename PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::TVector2D PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::direction(
const TEdge* iEdge )
2681 return dest( iEdge ) - org( iEdge );
2685 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::setOrg(
const TPoint2D& iPoint, TEdge* iEdge )
2687 LASS_ASSERT( inPrimaryMesh( iEdge ) );
2688 *iEdge->handle().point_ = iPoint;
2692 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::setDest(
const TPoint2D& iPoint, TEdge* iEdge )
2694 LASS_ASSERT( inPrimaryMesh( iEdge ) );
2695 *iEdge->sym()->handle().point_ = iPoint;
2699 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::rightOf(
const TPoint2D& iPoint,
const TEdge* iEdge )
2701 return lass::prim::ccw( iPoint, dest(iEdge), org(iEdge) );
2705 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::fastRightOf(
const TPoint2D& iPoint,
const TEdge* iEdge )
2707 return lass::prim::ccw( iPoint, fastDest(iEdge), fastOrg(iEdge) );
2712 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::leftOf(
const TPoint2D& iPoint,
const TEdge* iEdge )
2714 return lass::prim::ccw( iPoint, org(iEdge), dest(iEdge) );
2718 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::fastLeftOf(
const TPoint2D& iPoint,
const TEdge* iEdge )
2720 return lass::prim::ccw( iPoint, fastOrg(iEdge), fastDest(iEdge) );
2724 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::onEdge(
const TPoint2D& iPoint,
const TEdge* iEdge )
2726 if (prim::doubleTriangleArea( iPoint, org(iEdge), dest(iEdge)) == T(0) )
2728 TLineSegment2D eSeg(org(iEdge), dest(iEdge) );
2729 T rt = eSeg.t(iPoint);
2730 return (rt>=T(0)) && (rt<=T(1));
2735 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::hasLeftFace(
const TEdge* e )
2740 return leftOf(dest(e->lNext()), e);
2744 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::fastHasLeftFace(
const TEdge* e )
2749 return fastLeftOf(fastDest(e->lNext()), e);
2753 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::hasRightFace(
const TEdge* iEdge )
2755 return hasLeftFace( iEdge->sym() );
2766 const TEdge* currentEdge = iEdge;
2770 currentEdge = currentEdge->lNext();
2771 }
while (currentEdge!=iEdge);
2785 iEdge = iEdge->oNext();
2800 const TEdge* currentEdge = iEdge;
2804 currentEdge = currentEdge->oNext();
2805 }
while (currentEdge!=iEdge);
2811 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::marking(
const TEdge* iEdge )
2813 return iEdge->handle().internalMark_[publicMarkIndex];
2817 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::internalMarking(
const TEdge* iEdge )
2819 return iEdge->handle().internalMark_[stackDepth_];
2824 PointHandle PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::pointHandle(
const TEdge* iEdge )
2826 return inPrimaryMesh( iEdge ) ? iEdge->handle().pointHandle() : PointHandle();
2830 EdgeHandle PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::edgeHandle(
const TEdge* iEdge )
2832 return inPrimaryMesh( iEdge ) ? iEdge->handle().edgeHandle() : EdgeHandle();
2836 FaceHandle PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::faceHandle(
const TEdge* iEdge )
2838 if ( inPrimaryMesh( iEdge ) )
2840 return iEdge->rot()->handle().faceHandle();
2842 return FaceHandle();
2847 PointHandle& PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::pointHandleRef( TEdge* iEdge )
2849 if (inPrimaryMesh(iEdge))
2850 return iEdge->handle().pointHandle();
2851 LASS_THROW(
"no point handle available");
2855 EdgeHandle& PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::edgeHandleRef( TEdge* iEdge )
2857 if (inPrimaryMesh(iEdge))
2858 return iEdge->handle().edgeHandle();
2859 LASS_THROW(
"no edge handle available");
2863 FaceHandle& PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::faceHandleRef( TEdge* iEdge )
2865 if ( inPrimaryMesh( iEdge ) )
2867 return iEdge->rot()->handle().faceHandle();
2869 LASS_THROW(
"no face handle available");
2873 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::setMarking( TEdge* iEdge,
bool iMark )
2875 iEdge->handle().internalMark_.set(publicMarkIndex, iMark);
2879 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::setInternalMarking( TEdge* iEdge,
bool iMark )
2881 iEdge->handle().internalMark_.set(stackDepth_, iMark);
2885 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::setInternalMarkingAroundVertex( TEdge* iEdge,
bool iMark )
2890 setInternalMarking( e, iMark );
2896 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::setInternalMarkingInFace( TEdge* iEdge,
bool iMark )
2901 setInternalMarking( e, iMark );
2908 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::setPointHandle( TEdge* iEdge, PointHandle iHandle )
2910 if (! inPrimaryMesh( iEdge ) )
2911 throw std::runtime_error(
"setPointHandle : edge not in primary mesh");
2913 TEdge* currentEdge = iEdge;
2916 currentEdge->handle().pointHandle() = iHandle;
2917 currentEdge = currentEdge->oNext();
2918 }
while ( currentEdge != iEdge );
2922 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::setEdgeHandle( TEdge* iEdge, EdgeHandle iHandle )
2924 if (! inPrimaryMesh( iEdge ) )
2925 throw std::runtime_error(
"setEdgeHandle : edge not in primary mesh");
2926 iEdge->handle().edgeHandle() = iHandle;
2930 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::setFaceHandle( TEdge* iEdge, FaceHandle iHandle )
2932 if (! inPrimaryMesh( iEdge ) )
2933 throw std::runtime_error(
"setFaceHandle : edge not in dual mesh");
2935 TEdge* currentEdge = iEdge;
2938 currentEdge->rot()->handle().faceHandle() = iHandle;
2939 if ( faceHandle( currentEdge ) != faceHandle( currentEdge->sym() ) )
2940 currentEdge->quadEdge()->faceConstrain();
2942 currentEdge->quadEdge()->faceDeconstrain();
2943 currentEdge = currentEdge->lNext();
2944 }
while ( currentEdge != iEdge );
2948 void PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::setOrientedEdgeHandle(
2949 TEdge* iEdge, EdgeHandle iLeftHandle, EdgeHandle iRightHandle,
const TVector2D& iOrientation )
2952 ++numSetOrientedEdgeHandleCalls;
2954 if (prim::dot(direction(iEdge), iOrientation) < T(0))
2957 ++numSetOrientedEdgeHandleSwaps;
2959 std::swap(iLeftHandle, iRightHandle);
2961 setEdgeHandle(iEdge, iLeftHandle);
2962 setEdgeHandle(iEdge->sym(), iRightHandle);
2966 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::forAllPrimaryEdges(
const TEdgeCallback& iCallback )
2968 typename TQuadEdgeList::iterator qIt;
2969 for (qIt = quadEdgeList_.begin(); qIt != quadEdgeList_.end();++qIt)
2971 if (!(*qIt)->deleted)
2973 if (inPrimaryMesh( (*qIt)->edges() ) )
2975 if (!iCallback( (*qIt)->edges() ))
return false;
2976 if (!iCallback( (*qIt)->edges()->sym() ))
return false;
2980 if (!iCallback( (*qIt)->edges()->rot() ))
return false;
2981 if (!iCallback( (*qIt)->edges()->invRot() ))
return false;
2992 typename TQuadEdgeList::iterator qIt;
2993 for (qIt = quadEdgeList_.begin(); qIt != quadEdgeList_.end();++qIt)
2995 if (!(*qIt)->deleted)
2997 if (inPrimaryMesh( (*qIt)->edges() ) )
2999 if (!iCallback( (*qIt)->edges() ))
return false;
3003 if (!iCallback( (*qIt)->edges()->rot() ))
return false;
3013 static size_t start = 0;
3014 size_t savedStart = start;
3016 if (savedStart>quadEdgeList_.size()-1)
3022 for (
size_t i = savedStart; i<quadEdgeList_.size();++i)
3024 TQuadEdge* qe = quadEdgeList_[i];
3027 if (inPrimaryMesh( (qe)->edges() ) )
3029 if (!iCallback( (qe)->edges() ))
return false;
3033 if (!iCallback( (qe)->edges()->rot() ))
return false;
3039 for (
size_t i = 0; i<savedStart;++i)
3041 TQuadEdge* qe = quadEdgeList_[i];
3044 if (inPrimaryMesh( (qe)->edges() ) )
3046 if (!iCallback( (qe)->edges() ))
return false;
3050 if (!iCallback( (qe)->edges()->rot() ))
return false;
3059 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::forAllDualEdges(
const TEdgeCallback& iCallback )
3061 typename TQuadEdgeList::iterator qIt;
3062 for (qIt = quadEdgeList_.begin(); qIt != quadEdgeList_.end();++qIt)
3064 if (!(*qIt)->deleted)
3066 if (inDualMesh( (*qIt)->edges() ) )
3068 if (!iCallback( (*qIt)->edges() ))
return false;
3069 if (!iCallback( (*qIt)->edges()->sym() ))
return false;
3073 if (!iCallback( (*qIt)->edges()->rot() ))
return false;
3074 if (!iCallback( (*qIt)->edges()->invRot() ))
return false;
3082 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::forAllEdges(
const TEdgeCallback& iCallback )
3084 typename TQuadEdgeList::iterator qIt;
3085 for (qIt = quadEdgeList_.begin(); qIt != quadEdgeList_.end();++qIt)
3087 if (!(*qIt)->deleted)
3089 if (!iCallback( (*qIt)->edges() ))
return false;
3090 if (!iCallback( (*qIt)->edges()->sym() ))
return false;
3091 if (!iCallback( (*qIt)->edges()->rot() ))
return false;
3092 if (!iCallback( (*qIt)->edges()->invRot() ))
return false;
3099 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::forAllVertices(
const TEdgeCallback& iCallback )
3101 StackIncrementer( &stackDepth_, PLANAR_MESH_STACK_DEPTH );
3102 typedef impl::EdgeMarker<T, PointHandle, EdgeHandle, FaceHandle> TEdgeMarker;
3103 TEdgeMarker edgeMarker(
this,
false );
3104 forAllPrimaryEdges( TEdgeCallback( &edgeMarker, &TEdgeMarker::internalMark ) );
3106 typename TQuadEdgeList::iterator qIt;
3107 for (qIt = quadEdgeList_.begin(); qIt != quadEdgeList_.end();++qIt)
3109 if (!(*qIt)->deleted)
3111 TEdge* baseEdge = (*qIt)->edges();
3112 if (inDualMesh( baseEdge ) )
3113 baseEdge = baseEdge->rot();
3115 TEdge* e = baseEdge;
3116 for (
int i=0;i<2;++i)
3118 if ( !internalMarking( e ) )
3120 if (!iCallback( e ))
3122 setInternalMarkingAroundVertex( e,
true );
3132 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::forAllFacesCached(
const TEdgeCallback& iCallback )
3134 StackIncrementer( &stackDepth_, PLANAR_MESH_STACK_DEPTH );
3135 typedef impl::EdgeMarker<T, PointHandle, EdgeHandle, FaceHandle> TEdgeMarker;
3136 TEdgeMarker edgeMarker(
this,
false );
3137 forAllPrimaryEdges( TEdgeCallback( &edgeMarker, &TEdgeMarker::internalMark ) );
3139 static size_t startFace = 0;
3140 size_t savedStart = startFace;
3142 if (savedStart>quadEdgeList_.size()-1)
3148 for (
size_t i = savedStart; i<quadEdgeList_.size();++i)
3151 TQuadEdge* qe = quadEdgeList_[i];
3154 TEdge* baseEdge = qe->edges();
3155 if (inDualMesh( baseEdge ) )
3156 baseEdge = baseEdge->rot();
3158 TEdge* e = baseEdge;
3159 for (
int i=0;i<2;++i)
3161 if ( !internalMarking( e ) )
3163 if (!iCallback( e ))
3165 setInternalMarkingInFace( e,
true );
3171 for (
size_t i = 0; i<savedStart;++i)
3174 TQuadEdge* qe = quadEdgeList_[i];
3177 TEdge* baseEdge = qe->edges();
3178 if (inDualMesh( baseEdge ) )
3179 baseEdge = baseEdge->rot();
3181 TEdge* e = baseEdge;
3182 for (
int i=0;i<2;++i)
3184 if ( !internalMarking( e ) )
3186 if (!iCallback( e ))
3188 setInternalMarkingInFace( e,
true );
3198 bool PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::forAllFaces(
const TEdgeCallback& iCallback )
3200 StackIncrementer( &stackDepth_, PLANAR_MESH_STACK_DEPTH );
3201 typedef impl::EdgeMarker<T, PointHandle, EdgeHandle, FaceHandle> TEdgeMarker;
3202 TEdgeMarker edgeMarker(
this,
false );
3203 forAllPrimaryEdges( TEdgeCallback( &edgeMarker, &TEdgeMarker::internalMark ) );
3205 typename TQuadEdgeList::iterator qIt;
3206 for (qIt = quadEdgeList_.begin(); qIt != quadEdgeList_.end();++qIt)
3208 if (!(*qIt)->deleted)
3210 TEdge* baseEdge = (*qIt)->edges();
3211 if (inDualMesh( baseEdge ) )
3212 baseEdge = baseEdge->rot();
3214 TEdge* e = baseEdge;
3215 for (
int i=0;i<2;++i)
3217 if ( !internalMarking( e ) )
3219 if (!iCallback( e ))
3221 setInternalMarkingInFace( e,
true );
3232 TEMPLATE_DEF
unsigned PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::numSetOrientedEdgeHandleCalls = 0;
3233 TEMPLATE_DEF
unsigned PlanarMesh<T, PointHandle, EdgeHandle, FaceHandle>::numSetOrientedEdgeHandleSwaps = 0;
Output stream for writing a selection of geometric primitives to matlab M files.
const TVector vector() const
Return vector from tail to head.
const TPoint point(TParam a_t) const
Return point on ray by it's parameter.
const TValue t(const TPoint &iPoint) const
Return parameter of point on the ray that is the projection of the given point.
const TPoint & support() const
return origin of ray.
Side classify(const TPoint &iPoint) const
Return on what side a point is located.
convex or concave polygon in 2D (not selfintersecting, no holes)
A very simple 2D polygon :)
TEdge * insertEdge(const TLineSegment2D &iSegment, EdgeHandle iLeftHandle=EdgeHandle(), EdgeHandle iRightHandle=EdgeHandle(), PointHandle iPointHandle=PointHandle(), bool forcePointHandle=false, bool makeDelaunay=true)
insertEdge.
TEdge * split(TEdge *a, T iWhere)
splits an edge with iWhere in the open interval (0,1) and returns the new edge with as org the splitt...
static int vertexOrder(const TEdge *iEdge)
vertexOrder.
void markPolygon(TEdge *iStartEdge, const TSimplePolygon2D &iPolygon, FaceHandle iFaceHandle)
marks all faces which have their barycentrum inside the given polygon with the provided handle
bool deleteEdge(TEdge *iEdge)
delete edge without using gc
TEdge * locate(const TPoint2D &iPoint, TEdge *iHint=0) const
locate an edge of the triangle containing iPoint
static int chainOrder(const TEdge *iEdge)
chainOrder.
bool gcDeleteEdge(TEdge *iEdge)
delete edge using garbage collector, useful for deletion avalanches
int gc()
do garbage collection after deletion avalanches, returns number of quadedge collected
static bool allEqualChainOrder(const TEdge *iEdge)
allEqualchainOrder.
TEdge * insertSite(const TPoint2D &iPoint, bool makeDelaunay=true, bool forceOnEdge=false)
makeDelaunay: after insertion of the site force a Delaunay triangulation forceOnEdge : points are con...
TEdge * shoot(const TRay2D &iRay) const
locate the edge found by shooting the ray from within the triangle containt the tail of the ray
bool isBoundingPoint(const TPoint2D &iPoint) const
true for points defining the boundary
TEdge * makeEdge(const TPoint2D &a, const TPoint2D &b, bool makeConstrained)
makes a dangling edge, this is really only for ADVANCED usage, you'll have to splice it or it won't b...
TEdge * connect(TEdge *a, TEdge *b)
connects the dest of a with the org of b
TEdge * pointLocate(const TPoint2D &iPoint) const
locate an edge of which the org is the same as iPoint, useful for known degeneracy point location,...
static const int PLANAR_MESH_STACK_DEPTH
bool forAllPrimaryUndirectedEdgesCached(const TEdgeCallback &iCallback)
forAllPrimaryUndirectedEdges.
bool forAllPrimaryUndirectedEdges(const TEdgeCallback &iCallback)
forAllPrimaryUndirectedEdges.
void markPolygons(const std::vector< TSimplePolygon2D > &iPolygons, const std::vector< FaceHandle > &iFaceHandles)
marks all faces which have their barycentrum inside the given polygon with the provided handle
T abs(const T &x)
if x < 0 return -x, else return x.
#define LASS_LOCK(iLock)
Locks a iLock and starts a scope block in which it remains locked.
Side
Different sides of a surface.
@ sSurface
right on the surface
@ sRight
alias for sBack in 2D
Result
meta information on the result you have from an operation like an intersection ...
@ rInvalid
0 is an invalid value, nothing is known.
@ rOne
there's exactly one answer, 1 output argument contains the answer
spatial subdivisions, quadtrees, octrees, meshes in 2D and 3D, triangulators, ...
Library for Assembled Shared Sources.
lass::prim::Result fastIntersect(const lass::prim::Point2D< T > &iA, const lass::prim::Point2D< T > &iB, const lass::prim::Point2D< T > &iC, const lass::prim::Point2D< T > &iD, lass::prim::Point2D< T > &oP)
fastIntersect.