offsetcurvebuilder.cpp

来自「一个很好的vc底层代码」· C++ 代码 · 共 510 行 · 第 1/2 页

CPP
510
字号
			* This case should ONLY happen for LineStrings, so the orientation is always CW.			* (Polygons can never have two consecutive segments which are parallel but reversed,			* because that would be a self intersection.			*/			addFillet(s1, offset0->p1, offset1->p0, CGAlgorithms::CLOCKWISE, distance);		}	} else if (outsideTurn) {		// add a fillet to connect the endpoints of the offset segments		if (addStartPoint) addPt(offset0->p1);		// TESTING-comment out to produce beveled joins		addFillet(s1, offset0->p1, offset1->p0, orientation, distance);		addPt(offset1->p0);	} else { // inside turn		/**		* add intersection point of offset segments (if any)		*/		li->computeIntersection( offset0->p0, offset0->p1,offset1->p0, offset1->p1);		if (li->hasIntersection()) {			addPt(li->getIntersection(0));		} else {			/**			* If no intersection, it means the angle is so small and/or the offset so large			* that the offsets segments don't intersect.			* In this case we must add a offset joining curve to make sure the buffer line			* is continuous and tracks the buffer correctly around the corner.			* Note that the joining curve won't appear in the final buffer.			*			* The intersection test above is vulnerable to robustness errors;			* i.e. it may be that the offsets should intersect very close to their			* endpoints, but don't due to rounding.  To handle this situation			* appropriately, we use the following test:			* If the offset points are very close, don't add a joining curve			* but simply use one of the offset points			*/			if (offset0->p1.distance(offset1->p0)<distance / 1000.0) {				addPt(offset0->p1);			} else {				// add endpoint of this segment offset				addPt(offset0->p1);				// <FIX> MD-add in centre point of corner, to make sure offset closer lines have correct topology				addPt(s1);				addPt(offset1->p0);			}		}	}}/*** Add last offset point*/void OffsetCurveBuilder::addLastSegment() {	addPt(offset1->p1);}/*** Compute an offset segment for an input segment on a given side and at a given distance.* The offset points are computed in full double precision, for accuracy.** @param seg the segment to offset* @param side the side of the segment the offset lies on* @param distance the offset distance* @param offset the points computed for the offset segment*/void OffsetCurveBuilder::computeOffsetSegment(LineSegment *seg, int side, double distance, LineSegment *offset){	int sideSign=side==Position::LEFT ? 1 : -1;	double dx=seg->p1.x-seg->p0.x;	double dy=seg->p1.y-seg->p0.y;	double len=sqrt(dx*dx+dy*dy);	// u is the vector that is the length of the offset, in the direction of the segment	double ux=sideSign*distance*dx / len;	double uy=sideSign*distance*dy / len;	offset->p0.x=seg->p0.x-uy;	offset->p0.y=seg->p0.y+ux;	offset->p1.x=seg->p1.x-uy;	offset->p1.y=seg->p1.y+ux;}/*** Add an end cap around point p1, terminating a line segment coming from p0*/voidOffsetCurveBuilder::addLineEndCap(const Coordinate &p0,const Coordinate &p1){	LineSegment *seg=new LineSegment(p0, p1);	LineSegment *offsetL=new LineSegment();	computeOffsetSegment(seg, Position::LEFT, distance, offsetL);	LineSegment *offsetR=new LineSegment();	computeOffsetSegment(seg, Position::RIGHT, distance, offsetR);	double dx=p1.x-p0.x;	double dy=p1.y-p0.y;	double angle=atan2(dy, dx);	switch (endCapStyle) {		case BufferOp::CAP_ROUND:			// add offset seg points with a fillet between them			addPt(offsetL->p1);			addFillet(p1, angle+PI_OVER_2,angle-PI_OVER_2, CGAlgorithms::CLOCKWISE, distance);			addPt(offsetR->p1);			break;		case BufferOp::CAP_BUTT:			// only offset segment points are added			addPt(offsetL->p1);			addPt(offsetR->p1);			break;		case BufferOp::CAP_SQUARE:			// add a square defined by extensions of the offset segment endpoints			Coordinate *squareCapSideOffset=new Coordinate();			squareCapSideOffset->x=fabs(distance)*cos(angle);			squareCapSideOffset->y=fabs(distance)*sin(angle);			Coordinate *squareCapLOffset=new Coordinate(offsetL->p1.x+squareCapSideOffset->x, offsetL->p1.y+squareCapSideOffset->y);			Coordinate *squareCapROffset=new Coordinate(offsetR->p1.x+squareCapSideOffset->x, offsetR->p1.y+squareCapSideOffset->y);			addPt(*squareCapLOffset);			addPt(*squareCapROffset);			delete squareCapSideOffset;			delete squareCapLOffset;			delete squareCapROffset;			break;	}	delete seg;	delete offsetL;	delete offsetR;}/*** @param p base point of curve* @param p0 start point of fillet curve* @param p1 endpoint of fillet curve*/void OffsetCurveBuilder::addFillet(const Coordinate &p,const Coordinate &p0,const Coordinate &p1, int direction, double distance){	double dx0=p0.x-p.x;	double dy0=p0.y-p.y;	double startAngle=atan2(dy0, dx0);	double dx1=p1.x-p.x;	double dy1=p1.y-p.y;	double endAngle=atan2(dy1, dx1);	if (direction==CGAlgorithms::CLOCKWISE) {		if (startAngle<= endAngle) startAngle += 2.0*3.1415926535;	} else {    // direction==COUNTERCLOCKWISE		if (startAngle>=endAngle) startAngle-=2.0*3.1415926535;	}	addPt(p0);	addFillet(p, startAngle, endAngle, direction, distance);	addPt(p1);}/*** Adds points for a fillet->  The start and end point for the fillet are not added -* the caller must add them if required->** @param direction is -1 for a CW angle, 1 for a CCW angle*/void OffsetCurveBuilder::addFillet(const Coordinate &p, double startAngle, double endAngle, int direction, double distance){	int directionFactor=direction==CGAlgorithms::CLOCKWISE ? -1 : 1;	double totalAngle=fabs(startAngle-endAngle);	int nSegs=(int) (totalAngle / filletAngleQuantum+0.5);	if (nSegs<1) return;   // no segments because angle is less than increment-nothing to do!	double initAngle, currAngleInc;	// choose angle increment so that each segment has equal length	initAngle=0.0;	currAngleInc=totalAngle / nSegs;	double currAngle=initAngle;	Coordinate pt;	while (currAngle<totalAngle) {		double angle=startAngle+directionFactor*currAngle;		pt.x=p.x+distance*cos(angle);		pt.y=p.y+distance*sin(angle);		addPt(pt);		currAngle += currAngleInc;	}}/*** Adds a CW circle around a point*/void OffsetCurveBuilder::addCircle(const Coordinate &p, double distance){	// add start point	Coordinate pt(p);	pt.x+=distance;	addPt(pt);	addFillet(p, 0.0, 2.0*3.1415926535, -1, distance);}/*** Adds a CW square around a point*/void OffsetCurveBuilder::addSquare(const Coordinate &p, double distance){	// add start point	addPt(*(new Coordinate(p.x+distance, p.y+distance)));	addPt(*(new Coordinate(p.x+distance, p.y-distance)));	addPt(*(new Coordinate(p.x-distance, p.y-distance)));	addPt(*(new Coordinate(p.x-distance, p.y+distance)));	addPt(*(new Coordinate(p.x+distance, p.y+distance)));}} // namespace geos/********************************************************************** * $Log: OffsetCurveBuilder.cpp,v $ * Revision 1.15.2.1  2005/05/23 16:03:37  strk * back-ported memleak plug in getRingCurve() * * Revision 1.15  2004/12/08 13:54:44  strk * gcc warnings checked and fixed, general cleanups. * * Revision 1.14  2004/11/04 19:08:07  strk * Cleanups, initializers list, profiling. * * Revision 1.13  2004/07/13 08:33:53  strk * Added missing virtual destructor to virtual classes. * Fixed implicit unsigned int -> int casts * * Revision 1.12  2004/07/08 19:34:49  strk * Mirrored JTS interface of CoordinateSequence, factory and * default implementations. * Added DefaultCoordinateSequenceFactory::instance() function. * * Revision 1.11  2004/07/02 13:28:27  strk * Fixed all #include lines to reflect headers layout change. * Added client application build tips in README. * * Revision 1.10  2004/05/27 08:37:16  strk * Fixed a bug preventing OffsetCurveBuilder point list from being reset. * * Revision 1.9  2004/05/26 19:48:19  strk * Changed abs() to fabs() when working with doubles. * Used dynamic_cast<> instead of typeid() when JTS uses instanceof. * * Revision 1.8  2004/05/19 13:40:49  strk * Fixed bug in ::addCircle * * Revision 1.7  2004/05/05 13:08:01  strk * Leaks fixed, explicit allocations/deallocations reduced. * * Revision 1.6  2004/04/20 10:58:04  strk * More memory leaks removed. * * Revision 1.5  2004/04/19 16:14:52  strk * Some memory leaks plugged in noding algorithms. * * Revision 1.4  2004/04/19 15:14:46  strk * Added missing virtual destructor in SpatialIndex class. * Memory leaks fixes. Const and throw specifications added. * * Revision 1.3  2004/04/16 13:03:17  strk * More leaks fixed * * Revision 1.2  2004/04/16 12:48:07  strk * Leak fixes. * * Revision 1.1  2004/04/10 08:40:01  ybychkov * "operation/buffer" upgraded to JTS 1.4 * * **********************************************************************/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?