/*private*/ void ConvexHull::cleanRing(const Coordinate::ConstVect &original, Coordinate::ConstVect &cleaned) { size_t npts=original.size(); const Coordinate *last = original[npts-1]; //util::Assert::equals(*(original[0]), *last); assert(last); assert(original[0]->equals2D(*last)); const Coordinate *prev = NULL; for (size_t i=0; i<npts-1; ++i) { const Coordinate *curr = original[i]; const Coordinate *next = original[i+1]; // skip consecutive equal coordinates if (curr->equals2D(*next)) continue; if ( prev != NULL && isBetween(*prev, *curr, *next) ) { continue; } cleaned.push_back(curr); prev=curr; } cleaned.push_back(last); }
/* private */ void ConvexHull::reduce(Coordinate::ConstVect &pts) { Coordinate::ConstVect polyPts; if ( ! computeOctRing(pts, polyPts) ) { // unable to compute interior polygon for some reason return; } // add points defining polygon Coordinate::ConstSet reducedSet; reducedSet.insert(polyPts.begin(), polyPts.end()); /** * Add all unique points not in the interior poly. * CGAlgorithms.isPointInRing is not defined for points * actually on the ring, but this doesn't matter since * the points of the interior polygon are forced to be * in the reduced set. * * @@TIP: there should be a std::algo for this */ for (size_t i=0, n=pts.size(); i<n; ++i) { if ( !CGAlgorithms::isPointInRing(*(pts[i]), polyPts) ) { reducedSet.insert(pts[i]); } } inputPts.assign(reducedSet.begin(), reducedSet.end()); if ( inputPts.size() < 3 ) padArray3(inputPts); }
/* private */ Geometry* ConvexHull::lineOrPolygon(const Coordinate::ConstVect &input) { Coordinate::ConstVect cleaned; cleanRing(input, cleaned); if (cleaned.size()==3) { // shouldn't this be 2 ?? cleaned.resize(2); CoordinateSequence *cl1=toCoordinateSequence(cleaned); LineString *ret = geomFactory->createLineString(cl1); return ret; } CoordinateSequence *cl2=toCoordinateSequence(cleaned); LinearRing *linearRing=geomFactory->createLinearRing(cl2); return geomFactory->createPolygon(linearRing,NULL); }
/*private*/ Coordinate::ConstVect::const_iterator LineStringSnapper::findSnapForVertex(const Coordinate& pt, const Coordinate::ConstVect& snapPts) { Coordinate::ConstVect::const_iterator end = snapPts.end(); Coordinate::ConstVect::const_iterator candidate = end; double minDist = snapTolerance; // TODO: use std::find_if for ( Coordinate::ConstVect::const_iterator it=snapPts.begin(); it != end; ++it) { assert(*it); const Coordinate& snapPt = *(*it); if ( snapPt.equals2D(pt) ) { #if GEOS_DEBUG cerr << " points are equal, returning not-found " << endl; #endif return end; } double dist = snapPt.distance(pt); #if GEOS_DEBUG cerr << " distance from snap point " << snapPt << ": " << dist << endl; #endif if ( dist < minDist ) { minDist = dist; candidate = it; } } #if GEOS_DEBUG if ( candidate == end ) { cerr << " no snap point within distance, returning not-found" << endl; } #endif return candidate; }
/* private */ void ConvexHull::preSort(Coordinate::ConstVect &pts) { // find the lowest point in the set. If two or more points have // the same minimum y coordinate choose the one with the minimum x. // This focal point is put in array location pts[0]. for(size_t i=1, n=pts.size(); i<n; ++i) { const Coordinate *p0=pts[0]; // this will change const Coordinate *pi=pts[i]; if ( (pi->y<p0->y) || ((pi->y==p0->y) && (pi->x<p0->x)) ) { const Coordinate *t=p0; pts[0]=pi; pts[i]=t; } } // sort the points radially around the focal point. std::sort(pts.begin(), pts.end(), RadiallyLessThen(pts[0])); }
/* static */ bool LineSequencer::isSequenced(const Geometry* geom) { const MultiLineString *mls; if ( nullptr == (mls=dynamic_cast<const MultiLineString *>(geom)) ) { return true; } // the nodes in all subgraphs which have been completely scanned Coordinate::ConstSet prevSubgraphNodes; Coordinate::ConstVect currNodes; const Coordinate* lastNode = nullptr; for (std::size_t i=0, n=mls->getNumGeometries(); i<n; ++i) { const LineString* lineptr = \ dynamic_cast<const LineString*>(mls->getGeometryN(i)); assert(lineptr); const LineString& line = *lineptr; const Coordinate* startNode = &(line.getCoordinateN(0)); const Coordinate* endNode = &(line.getCoordinateN(line.getNumPoints() - 1)); /** * If this linestring is connected to a previous subgraph, * geom is not sequenced */ if (prevSubgraphNodes.find(startNode) != prevSubgraphNodes.end()) { return false; } if (prevSubgraphNodes.find(endNode) != prevSubgraphNodes.end()) { return false; } if (lastNode != nullptr) { if (! startNode->equals2D(*lastNode)) { // start new connected sequence prevSubgraphNodes.insert(currNodes.begin(), currNodes.end()); currNodes.clear(); } } currNodes.push_back(startNode); currNodes.push_back(endNode); lastNode = endNode; } return true; }
/* private */ void ConvexHull::computeOctPts(const Coordinate::ConstVect &inputPts, Coordinate::ConstVect &pts) { // Initialize all slots with first input coordinate pts = Coordinate::ConstVect(8, inputPts[0]); for (size_t i=1, n=inputPts.size(); i<n; ++i) { if (inputPts[i]->x < pts[0]->x) { pts[0] = inputPts[i]; } if (inputPts[i]->x - inputPts[i]->y < pts[1]->x - pts[1]->y) { pts[1] = inputPts[i]; } if (inputPts[i]->y > pts[2]->y) { pts[2] = inputPts[i]; } if (inputPts[i]->x + inputPts[i]->y > pts[3]->x + pts[3]->y) { pts[3] = inputPts[i]; } if (inputPts[i]->x > pts[4]->x) { pts[4] = inputPts[i]; } if (inputPts[i]->x - inputPts[i]->y > pts[5]->x - pts[5]->y) { pts[5] = inputPts[i]; } if (inputPts[i]->y < pts[6]->y) { pts[6] = inputPts[i]; } if (inputPts[i]->x + inputPts[i]->y < pts[7]->x + pts[7]->y) { pts[7] = inputPts[i]; } } }
/* private */ bool ConvexHull::computeOctRing(const Coordinate::ConstVect &inputPts, Coordinate::ConstVect &dest) { computeOctPts(inputPts, dest); // Remove consecutive equal Coordinates // unique() returns an iterator to the end of the resulting // sequence, we erase from there to the end. dest.erase( std::unique(dest.begin(),dest.end()), dest.end() ); // points must all lie in a line if ( dest.size() < 3 ) return false; // close ring dest.push_back(dest[0]); return true; }
void object::test<1>() { using geos::geom::Coordinate; // Create geometry from WKT const Coordinate::ConstVect::size_type size5 = 5; const std::string wkt("MULTIPOINT(10 10, 20 20, 30 30, 20 20, 10 10)"); GeometryPtr geo(reader_.read(wkt)); ensure_equals( geo->getGeometryTypeId(), geos::geom::GEOS_MULTIPOINT ); std::auto_ptr<geos::geom::CoordinateSequence> cs; cs.reset(geo->getCoordinates()); ensure_equals(cs->getSize(), size5 ); // Create collection buffer for filtered coordinates const Coordinate::ConstVect::size_type size0 = 0; Coordinate::ConstVect coords; // Create filtering object geos::util::UniqueCoordinateArrayFilter filter(coords); ensure_equals( coords.size(), size0 ); // Apply filter const Coordinate::ConstVect::size_type size3 = 3; geo->apply_ro(&filter); cs.reset(geo->getCoordinates()); ensure_equals( cs->getSize(), size5 ); ensure_equals( coords.size(), size3 ); ensure_equals( coords.at(0)->x, 10 ); ensure_equals( coords.at(0)->y, 10 ); ensure_equals( coords.at(1)->x, 20 ); ensure_equals( coords.at(1)->y, 20 ); ensure_equals( coords.at(2)->x, 30 ); ensure_equals( coords.at(2)->y, 30 ); }
/*private*/ void ConvexHull::grahamScan(const Coordinate::ConstVect &c, Coordinate::ConstVect &ps) { ps.push_back(c[0]); ps.push_back(c[1]); ps.push_back(c[2]); for(size_t i=3, n=c.size(); i<n; ++i) { const Coordinate *p = ps.back(); ps.pop_back(); while (!ps.empty() && CGAlgorithms::computeOrientation( *(ps.back()), *p, *(c[i])) > 0) { p = ps.back(); ps.pop_back(); } ps.push_back(p); ps.push_back(c[i]); } ps.push_back(c[0]); }