/*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); }
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 */ 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 */ 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; }
/* 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])); }
/*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]); }
/* 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]; } } }