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 + -
显示快捷键?