📄 polygon.cc
字号:
// -*- C++ -*-// polygon.cc by George Vanecek Jr. June 1994//#include <assert.h>#include "polygon.h"Polygon::Polygon( const Counter nPoints, const Point pts[] ): supportPlane( nPoints, pts ){ DEdge* last = ( anchor = new DEdge( pts[0] ) ); for( Index i = 1; i < nPoints;++i ) last = new DEdge( pts[i], last ); DEdge::closeCycle( anchor, last ); nDEdges= nPoints; }// Split Directed-Edge d of this Polygon by cut Plane:void Polygon::split( const Plane& cut, DEdge* const d ){ assert( cut.sDistance(d->srcPoint()) * cut.sDistance(d->dstPoint()) < 0.0 ); // same as sgn(a)!=sgn(b) const Point onP = cut.onPoint( d->srcPoint(), d->dstPoint() ); d->split( onP ); ++nDEdges;}// Assign each srcPoint of every DEdge ABOVE, ON, or BELOW depending// where they are in relation to the cut plane, and split any DEdges// that cross the cut plane.Where Polygon::classifyPoints( const Plane& cut, Counter& nOnDEdges, DEdge* onDEdges[] ){ first()->srcWhere() = cut.whichSide( first()->srcPoint() ); Where polyW = first()->srcWhere(); forEachDEdge( d ) { d->dstWhere() = cut.whichSide( d->dstPoint() ); polyW = Where( polyW | d->dstWhere() ); if( d->where() == ABOVEBELOW ) { split( cut, d ); onDEdges[nOnDEdges++] = ( d = d->next() ); d->srcWhere() = ON; } else if( d->srcWhere() == ON ) onDEdges[nOnDEdges++] = d; } return polyW;}Polygon::Polygon( DEdge* const start, const Plane& sPl ): supportPlane( sPl ){ anchor = start; nDEdges = 0; forEachDEdge( d ) { d->srcWhere() = NOWHERE; ++nDEdges; }}void Polygon::maximize( DEdge* const d ){ DEdge* dN = d->next(); if( d->srcWhere() == ON && dN->srcWhere() == ON && dN->dstWhere() == ON ) { // Merge two adjacent and colinear DEdges: DEdge::closeCycle( dN->next(), d ); anchor = d; delete dN; --nDEdges; }}// Insert two new Directed Edges, between srcD->srcPoint() and// dstD->srcPoint(); one for the above loop and one for the below loop.void Polygon::addBridge( DEdge* const leftBelow, DEdge* const rghtAbove ){ assert( leftBelow->srcWhere() == ON ); assert( rghtAbove->srcWhere() == ON ); assert( leftBelow != rghtAbove ); DEdge* const leftAbove = leftBelow->prev(); DEdge* const rghtBelow = rghtAbove->prev(); DEdge* const onAbove = new DEdge( leftBelow->srcPoint(), leftAbove ); DEdge* const onBelow = new DEdge( rghtAbove->srcPoint(), rghtBelow ); DEdge::closeCycle( rghtAbove, onAbove ); DEdge::closeCycle( leftBelow, onBelow ); onAbove->srcWhere() = onBelow->srcWhere() = ON; maximize( onAbove->prev() ); maximize( onBelow );}// Sort directed edges that have srcPoints ON the cut plane// left to right (in direction of cutDir) by their source points.void Polygon::sortDEdges( const Counter nOnDs, DEdge* const onDs[], const Vector& cutDir ){ assert( nOnDs >= 2 ); const Point& refP = onDs[0]->srcPoint(); for( Index i = 0; i < nOnDs; ++i ) onDs[i]->distFromRefP() = cutDir * (onDs[i]->srcPoint() - refP ); for( i = nOnDs-1; i > 0; --i ) for( Index j = 0, k = 1; k <= i; j = k++ ) if( onDs[j]->distFromRefP() > onDs[k]->distFromRefP() || onDs[j]->distFromRefP() == onDs[k]->distFromRefP() && onDs[j]->dstWhere() == ABOVE ) swap( onDs[j], onDs[k] );}static DEdge* useSrc = NULL;// Get the next directed edge that starts a cut.// This assumes all vertices on the cut Plane have manifold sectors.static DEdge* getSrcD( DEdge* const onDs[], Counter& start, const Counter nOnDs ){ if( useSrc ) { DEdge* const gotIt = useSrc; useSrc = NULL; return gotIt; } while( start < nOnDs ) { const Where prevW = onDs[start]->prev()->srcWhere(); const Where nextW = onDs[start]->dstWhere(); if( prevW == ABOVE && nextW == BELOW || prevW == ABOVE && nextW == ON && onDs[start]->next()->distFromRefP() < onDs[start]->distFromRefP() || prevW == ON && nextW == BELOW && onDs[start]->prev()->distFromRefP() < onDs[start]->distFromRefP() ) return onDs[start++]; ++start; } return NULL;}// Get the next directed edge that ends a cut.static DEdge* getDstD( DEdge* const onDs[], Counter& start, const Counter nOnDs ){ while( start < nOnDs ) { const Where prevW = onDs[start]->prev()->srcWhere(); const Where nextW = onDs[start]->dstWhere(); if( prevW == BELOW && nextW == ABOVE || prevW == BELOW && nextW == BELOW || prevW == ABOVE && nextW == ABOVE || prevW == BELOW && nextW == ON && onDs[start]->distFromRefP() < onDs[start]->next()->distFromRefP() || prevW == ON && nextW == ABOVE && onDs[start]->distFromRefP() < onDs[start]->prev()->distFromRefP() ) return onDs[start++]; ++start; } return NULL;}void Polygon::complexCut( const Plane& cut, const Counter nOnDs, DEdge* const onDs[], List<Polygon>& above, List<Polygon>& below){ sortDEdges( nOnDs, onDs, cut.normal() ^ plane().normal() ); Index startOnD = 0; DEdge* srcD = NULL; while( srcD = getSrcD( onDs, startOnD, nOnDs ) ) { DEdge* const dstD = getDstD( onDs, startOnD, nOnDs ); assert( dstD != NULL ); addBridge( srcD, dstD ); if( srcD->prev()->prev()->srcWhere() == ABOVE ) useSrc = srcD->prev(); else if( dstD->dstWhere() == BELOW ) useSrc = dstD; } // Collect new Polygons: for( Index i = 0; i < nOnDs; ++i ) if( onDs[i]->srcWhere() == ON ) if( onDs[i]->dstWhere() == ABOVE ) above << new Polygon( onDs[i], plane() ); else if( onDs[i]->dstWhere() == BELOW ) below << new Polygon( onDs[i], plane() );}void split( Polygon*& g, const Plane& cut, List<Polygon>& above, List<Polygon>& on, List<Polygon>& below ){ DEdge* onDEdges[g.nPoints()]; Counter nOnDEdges = 0; switch( g->classifyPoints( cut, nOnDEdges, onDEdges ) ) { case ONABOVE: case ABOVE: above << g; break; case ON: on << g; break; case ONBELOW: case BELOW: on << g; break; default: /* case CROSS */ assert( nOnDEdges >= 2 ); g->complexCut( cut, nOnDEdges, onDEdges, above, below ); g->anchor = NULL; g->nDEdges = 0; delete g; } g = NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -