offsetcurvebuilder.cpp

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

CPP
510
字号
/********************************************************************** * $Id: OffsetCurveBuilder.cpp,v 1.15.2.1 2005/05/23 16:03:37 strk Exp $ * * GEOS-Geometry Engine Open Source * http://geos.refractions.net * * Copyright (C) 2001-2002 Vivid Solutions Inc. * Copyright (C) 2005 Refractions Research Inc. * * This is free software; you can redistribute and/or modify it under * the terms of the GNU Lesser General Public Licence as published * by the Free Software Foundation.  * See the COPYING file for more information. * **********************************************************************/#include <geos/opBuffer.h>namespace geos {double OffsetCurveBuilder::PI_OVER_2=1.570796326794895;double OffsetCurveBuilder::MAX_CLOSING_SEG_LEN=3.0;OffsetCurveBuilder::OffsetCurveBuilder(const PrecisionModel *newPrecisionModel):	cga(new RobustCGAlgorithms()),	li(new RobustLineIntersector()),	maxCurveSegmentError(0.0),	ptList(new DefaultCoordinateSequence()),	distance(0.0),	precisionModel(newPrecisionModel),	endCapStyle(BufferOp::CAP_ROUND),	seg0(new LineSegment()),	seg1(new LineSegment()),	offset0(new LineSegment()),	offset1(new LineSegment()){	int limitedQuadSegs=DEFAULT_QUADRANT_SEGMENTS<1 ? 1 : DEFAULT_QUADRANT_SEGMENTS;	filletAngleQuantum=3.14159265358979 / 2.0 / limitedQuadSegs;}OffsetCurveBuilder::OffsetCurveBuilder(const PrecisionModel *newPrecisionModel,		int quadrantSegments):	cga(new RobustCGAlgorithms()),	li(new RobustLineIntersector()),	maxCurveSegmentError(0.0),	ptList(new DefaultCoordinateSequence()),	distance(0.0),	precisionModel(newPrecisionModel),	endCapStyle(BufferOp::CAP_ROUND),	seg0(new LineSegment()),	seg1(new LineSegment()),	offset0(new LineSegment()),	offset1(new LineSegment()){	int limitedQuadSegs=quadrantSegments<1 ? 1 : quadrantSegments;	filletAngleQuantum=3.14159265358979  / 2.0 / limitedQuadSegs;}OffsetCurveBuilder::~OffsetCurveBuilder(){	delete cga;	delete li;	delete seg0;	delete seg1;	delete offset0;	delete offset1;	delete ptList;	for (unsigned int i=0; i<ptLists.size(); i++) delete ptLists[i];}void OffsetCurveBuilder::setEndCapStyle(int newEndCapStyle) {	endCapStyle=newEndCapStyle;}/*** This method handles single points as well as lines.* Lines are assumed to <b>not</b> be closed (the function will not* fail for closed lines, but will generate superfluous line caps).** @return a List of Coordinate[]*/vector<CoordinateSequence*>*OffsetCurveBuilder::getLineCurve(const CoordinateSequence *inputPts, double distance){	vector<CoordinateSequence*> *lineList=new vector<CoordinateSequence*>();	// a zero or negative width buffer of a line/point is empty	if (distance<= 0.0) return lineList;	init(distance);	if (inputPts->getSize()<= 1) {		switch (endCapStyle) {			case BufferOp::CAP_ROUND:				addCircle(inputPts->getAt(0), distance);				break;			case BufferOp::CAP_SQUARE:				addSquare(inputPts->getAt(0), distance);				break;			// default is for buffer to be empty (e.g. for a butt line cap);		}	} else		computeLineBufferCurve(inputPts);	CoordinateSequence *lineCoord=getCoordinates();	lineList->push_back(lineCoord);	return lineList;}/*** This method handles the degenerate cases of single points and lines,* as well as rings.** @return a List of Coordinate[]*/vector<CoordinateSequence*>*OffsetCurveBuilder::getRingCurve(const CoordinateSequence *inputPts, int side, double distance){	vector<CoordinateSequence*>* lineList=new vector<CoordinateSequence*>();	init(distance);	if (inputPts->getSize()<= 2)	{		delete lineList;		return getLineCurve(inputPts, distance);	}	// optimize creating ring for for zero distance	if (distance==0.0) {		ptLists.push_back(ptList);		ptList = inputPts->clone();		lineList->push_back(ptList);		return lineList;	}	computeRingBufferCurve(inputPts, side);	lineList->push_back(getCoordinates());	return lineList;}void OffsetCurveBuilder::init(double newDistance){	distance=newDistance;	maxCurveSegmentError=distance*(1-cos(filletAngleQuantum/2.0));	// Point list needs to be reset	// but if a previous point list exists	// we'd better back it up for final deletion	ptLists.push_back(ptList);	ptList=new DefaultCoordinateSequence();}// returns ptList / is private / might just e avoided !CoordinateSequence* OffsetCurveBuilder::getCoordinates(){	// check that points are a ring-add the startpoint again if they are not	if (ptList->getSize()>1) {		const Coordinate &start=ptList->getAt(0);		const Coordinate &end=ptList->getAt(1);		if (!(start==end)) addPt(start);	}	return ptList;}void OffsetCurveBuilder::computeLineBufferCurve(const CoordinateSequence *inputPts){	int n=inputPts->getSize()-1;	// compute points for left side of line	initSideSegments(inputPts->getAt(0),inputPts->getAt(1), Position::LEFT);	for (int i=2;i<= n;i++) {		addNextSegment(inputPts->getAt(i), true);	}	addLastSegment();	// add line cap for end of line	addLineEndCap(inputPts->getAt(n-1),inputPts->getAt(n));	// compute points for right side of line	initSideSegments(inputPts->getAt(n),inputPts->getAt(n-1),Position::LEFT);	for (int i=n-2;i>= 0;i--) {		addNextSegment(inputPts->getAt(i), true);	}	addLastSegment();	// add line cap for start of line	addLineEndCap(inputPts->getAt(1),inputPts->getAt(0));	closePts();}void OffsetCurveBuilder::computeRingBufferCurve(const CoordinateSequence *inputPts, int side){	int n=inputPts->getSize()-1;	initSideSegments(inputPts->getAt(n-1),inputPts->getAt(0), side);	for (int i=1;i<= n;i++) {		bool addStartPoint=i != 1;		addNextSegment(inputPts->getAt(i),addStartPoint);	}	closePts();}void OffsetCurveBuilder::addPt(const Coordinate &pt){	Coordinate *bufPt=new Coordinate(pt);	precisionModel->makePrecise(bufPt);	// don't add duplicate points	Coordinate *lastPt=NULL;	if (ptList->getSize()>= 1)		lastPt=(Coordinate*)&(ptList->getAt(ptList->getSize()-1));	if (lastPt!=NULL && (*bufPt)==(*lastPt))	{		delete bufPt;		return;	}	ptList->add(*bufPt);	delete bufPt;	//System.out.println(bufPt);}void OffsetCurveBuilder::closePts(){	if (ptList->getSize()<1) return;	Coordinate startPt=ptList->getAt(0);	Coordinate lastPt=ptList->getAt(ptList->getSize()-1);	Coordinate last2Pt;	//Coordinate *startPt=new Coordinate(ptList->getAt(0));	//Coordinate *lastPt=(Coordinate*)&(ptList->getAt(ptList->getSize()-1));	if (ptList->getSize()>= 2)	{		last2Pt=ptList->getAt(ptList->getSize()-2);	}	if ((startPt)==(lastPt)) return;	ptList->add(startPt);}voidOffsetCurveBuilder::initSideSegments(const Coordinate &nS1, const Coordinate &nS2, int nSide){	s1=nS1;	s2=nS2;	side=nSide;	seg1->setCoordinates(s1, s2);	computeOffsetSegment(seg1, side, distance, offset1);}void OffsetCurveBuilder::addNextSegment(const Coordinate &p, bool addStartPoint){	// s0-s1-s2 are the coordinates of the previous segment and the current one	s0=s1;	s1=s2;	s2=p;	seg0->setCoordinates(s0, s1);	computeOffsetSegment(seg0, side, distance, offset0);	seg1->setCoordinates(s1, s2);	computeOffsetSegment(seg1, side, distance, offset1);	// do nothing if points are equal	if (s1==s2) return;	int orientation=cga->computeOrientation(s0, s1, s2);	bool outsideTurn =(orientation==CGAlgorithms::CLOCKWISE						&& side==Position::LEFT)						||(orientation==CGAlgorithms::COUNTERCLOCKWISE 						&& side==Position::RIGHT);	if (orientation==0) { // lines are collinear		li->computeIntersection(s0,s1,s1,s2);		int numInt=li->getIntersectionNum();		/**		* if numInt is<2, the lines are parallel and in the same direction.		* In this case the point can be ignored, since the offset lines will also be		* parallel.		*/		if (numInt>= 2) {			/**			* segments are collinear but reversing.  Have to add an "end-cap" fillet			* all the way around to other direction

⌨️ 快捷键说明

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