Polygon* GeometryEditor::editPolygon(const Polygon *polygon,GeometryEditorOperation *operation) { Polygon* newPolygon=(Polygon*) operation->edit(polygon, factory); if (newPolygon->isEmpty()) { //RemoveSelectedPlugIn relies on this behaviour. [Jon Aquino] return newPolygon; } LinearRing* shell = (LinearRing*) edit(newPolygon->getExteriorRing(),operation); if (shell->isEmpty()) { //RemoveSelectedPlugIn relies on this behaviour. [Jon Aquino] delete shell; delete newPolygon; return factory->createPolygon(NULL,NULL); } vector<Geometry*> *holes=new vector<Geometry*>; for (int i=0;i<newPolygon->getNumInteriorRing(); i++) { LinearRing *hole =(LinearRing*) edit(newPolygon->getInteriorRingN(i),operation); if (hole->isEmpty()) { continue; } holes->push_back(hole); } delete newPolygon; return factory->createPolygon(shell,holes); }
TEST(TileCover, DISABLED_FuzzPoly) { while(1) { std::srand (time(NULL)); std::size_t len = std::rand() % 10000 + 3; Polygon<double> polygon; std::size_t num_rings = 1; num_rings += std::rand() % 5; while (num_rings > 0) { LinearRing<double> ring; for (std::size_t i = 0; i < len; ++i) { double x = std::rand() % 180; double y = std::rand() % 90; ring.push_back({x,y}); } polygon.emplace_back(ring); --num_rings; } std::clog << "."; util::TileCover tc(polygon, 5); while(tc.next()) { }; } }
void Polygon::apply_rw(const CoordinateFilter *filter) { shell->apply_rw(filter); for(size_t i=0, n=holes->size(); i<n; ++i) { LinearRing* lr = dynamic_cast<LinearRing *>((*holes)[i]); lr->apply_rw(filter); } }
/*public*/ EdgeRing* EdgeRing::findEdgeRingContaining(EdgeRing* testEr, vector<EdgeRing*>* shellList) { const LinearRing* testRing = testEr->getRingInternal(); if(! testRing) { return nullptr; } const Envelope* testEnv = testRing->getEnvelopeInternal(); Coordinate testPt = testRing->getCoordinateN(0); EdgeRing* minShell = nullptr; const Envelope* minEnv = nullptr; typedef std::vector<EdgeRing*> ERList; for(ERList::size_type i = 0, e = shellList->size(); i < e; ++i) { EdgeRing* tryShell = (*shellList)[i]; LinearRing* tryRing = tryShell->getRingInternal(); const Envelope* tryEnv = tryRing->getEnvelopeInternal(); if(minShell != nullptr) { minEnv = minShell->getRingInternal()->getEnvelopeInternal(); } bool isContained = false; // the hole envelope cannot equal the shell envelope if(tryEnv->equals(testEnv)) { continue; } const CoordinateSequence* tryCoords = tryRing->getCoordinatesRO(); if(tryEnv->contains(testEnv)) { // TODO: don't copy testPt ! testPt = ptNotInList(testRing->getCoordinatesRO(), tryCoords); if(PointLocation::isInRing(testPt, tryCoords)) { isContained = true; } } // check if this new containing ring is smaller // than the current minimum ring if(isContained) { if(minShell == nullptr || minEnv->contains(tryEnv)) { minShell = tryShell; } } } return minShell; }
/* * Returns the area of this <code>Polygon</code> * * @return the area of the polygon */ double Polygon::getArea() const { double area=0.0; area+=fabs(algorithm::CGAlgorithms::signedArea(shell->getCoordinatesRO())); for(size_t i=0, n=holes->size(); i<n; ++i) { LinearRing *lr = static_cast<LinearRing *>((*holes)[i]); const CoordinateSequence *h=lr->getCoordinatesRO(); area-=fabs(algorithm::CGAlgorithms::signedArea(h)); } return area; }
bool QuadtreeNestedRingTester::isNonNested() { buildQuadtree(); for(size_t i = 0, ni = rings.size(); i < ni; ++i) { const LinearRing* innerRing = rings[i]; const CoordinateSequence* innerRingPts = innerRing->getCoordinatesRO(); const Envelope* envi = innerRing->getEnvelopeInternal(); vector<void*> results; qt->query(envi, results); for(size_t j = 0, nj = results.size(); j < nj; ++j) { LinearRing* searchRing = (LinearRing*)results[j]; const CoordinateSequence* searchRingPts = searchRing->getCoordinatesRO(); if(innerRing == searchRing) { continue; } const Envelope* e1 = innerRing->getEnvelopeInternal(); const Envelope* e2 = searchRing->getEnvelopeInternal(); if(!e1->intersects(e2)) { continue; } const Coordinate* innerRingPt = IsValidOp::findPtNotNode(innerRingPts, searchRing, graph); // Unable to find a ring point not a node of the search ring assert(innerRingPt != nullptr); bool isInside = PointLocation::isInRing(*innerRingPt, searchRingPts); if(isInside) { /* * innerRingPt is const just because the input * CoordinateSequence is const. If the input * Polygon survives lifetime of this object * we are safe. */ nestedPt = const_cast<Coordinate*>(innerRingPt); return false; } } } return true; }
void updateNonClosedRing(LinearRing& ring) { CoordinateSequence& pts = *(const_cast<CoordinateSequence*>( ring.getCoordinatesRO() )); Coordinate c = pts[0]; c.x += 0.0001; pts.setAt(c, 0); }
Polygon* GeometryEditor::editPolygon(const Polygon *polygon,GeometryEditorOperation *operation) { Polygon* newPolygon= dynamic_cast<Polygon*>( operation->edit(polygon, factory) ); if (newPolygon->isEmpty()) { //RemoveSelectedPlugIn relies on this behaviour. [Jon Aquino] return newPolygon; } Geometry* editResult = edit(newPolygon->getExteriorRing(),operation); LinearRing* shell = dynamic_cast<LinearRing*>(editResult); if (shell->isEmpty()) { //RemoveSelectedPlugIn relies on this behaviour. [Jon Aquino] delete shell; delete newPolygon; return factory->createPolygon(NULL,NULL); } vector<Geometry*> *holes=new vector<Geometry*>; for (size_t i=0, n=newPolygon->getNumInteriorRing(); i<n; ++i) { Geometry *hole_geom = edit(newPolygon->getInteriorRingN(i), operation); LinearRing *hole = dynamic_cast<LinearRing*>(hole_geom); assert(hole); if (hole->isEmpty()) { continue; } holes->push_back(hole); } delete newPolygon; return factory->createPolygon(shell,holes); }
void Polygon::AddGeometry(Geometry *pGeometry) { LinearRing *pring = dynamic_cast<LinearRing*>(pGeometry); if(pring ==NULL) { return; } //如果环是不闭合的,并且不是一个空环,则不能加入到多边形中 if(!pring->isClosed() && !pring->isEmpty()) { return; } //当外环为空时,将这个环替换外环 if(shell->isEmpty()) { delete shell; shell =pring; return; } holes->push_back(pring); }
bool TextureCoordinates::targets(const LinearRing& ring) const { return m_targetID == ring.getId(); }
static Feature::geometry_type convertGeometry(const GeometryTileFeature& geometryTileFeature, const CanonicalTileID& tileID) { const double size = util::EXTENT * std::pow(2, tileID.z); const double x0 = util::EXTENT * tileID.x; const double y0 = util::EXTENT * tileID.y; auto tileCoordinatesToLatLng = [&] (const Point<int16_t>& p) { double y2 = 180 - (p.y + y0) * 360 / size; return Point<double>( (p.x + x0) * 360 / size - 180, 360.0 / M_PI * std::atan(std::exp(y2 * M_PI / 180)) - 90.0 ); }; GeometryCollection geometries = geometryTileFeature.getGeometries(); switch (geometryTileFeature.getType()) { case FeatureType::Unknown: { assert(false); return Point<double>(NAN, NAN); } case FeatureType::Point: { MultiPoint<double> multiPoint; for (const auto& p : geometries.at(0)) { multiPoint.push_back(tileCoordinatesToLatLng(p)); } if (multiPoint.size() == 1) { return multiPoint[0]; } else { return multiPoint; } } case FeatureType::LineString: { MultiLineString<double> multiLineString; for (const auto& g : geometries) { LineString<double> lineString; for (const auto& p : g) { lineString.push_back(tileCoordinatesToLatLng(p)); } multiLineString.push_back(std::move(lineString)); } if (multiLineString.size() == 1) { return multiLineString[0]; } else { return multiLineString; } } case FeatureType::Polygon: { MultiPolygon<double> multiPolygon; for (const auto& pg : classifyRings(geometries)) { Polygon<double> polygon; for (const auto& r : pg) { LinearRing<double> linearRing; for (const auto& p : r) { linearRing.push_back(tileCoordinatesToLatLng(p)); } polygon.push_back(std::move(linearRing)); } multiPolygon.push_back(std::move(polygon)); } if (multiPolygon.size() == 1) { return multiPolygon[0]; } else { return multiPolygon; } } } // Unreachable, but placate GCC. return Point<double>(); }