Skip to content

Commit

Permalink
Add CoveragePolygonValidator section performance optimization (#1099)
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-jts committed May 23, 2024
1 parent 2d854e0 commit ac8b32f
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 90 deletions.
57 changes: 57 additions & 0 deletions include/geos/coverage/CoveragePolygon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**********************************************************************
*
* GEOS - Geometry Engine Open Source
* http://geos.osgeo.org
*
* Copyright (C) 2024 Martin Davis <[email protected]>
*
* 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.
*
**********************************************************************/

#pragma once

#include <geos/algorithm/locate/IndexedPointInAreaLocator.h>

// Forward declarations
namespace geos {
namespace geom {
class Coordinate;
class Envelope;
class Polygon;
}
}

using geos::geom::CoordinateXY;
using geos::geom::Envelope;
using geos::geom::Polygon;
using geos::algorithm::locate::IndexedPointInAreaLocator;

namespace geos { // geos
namespace coverage { // geos::coverage

class GEOS_DLL CoveragePolygon {

// Members
const Polygon* m_polygon;
Envelope polyEnv;
mutable std::unique_ptr<IndexedPointInAreaLocator> m_locator;

public:
CoveragePolygon(const Polygon* poly);

bool intersectsEnv(const Envelope& env) const;
bool intersectsEnv(const CoordinateXY& p) const;
bool contains(const CoordinateXY& p) const;

private:
IndexedPointInAreaLocator& getLocator() const;

};

} // namespace geos::coverage
} // namespace geos

38 changes: 16 additions & 22 deletions include/geos/coverage/CoveragePolygonValidator.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <geos/noding/BasicSegmentString.h>
#include <geos/geom/LineSegment.h>
#include <geos/algorithm/locate/IndexedPointInAreaLocator.h>
#include <geos/coverage/CoveragePolygon.h>
#include <geos/coverage/CoverageRing.h>

#include <unordered_map>
Expand Down Expand Up @@ -195,11 +196,10 @@ class GEOS_DLL CoveragePolygonValidator {
// Members
const Geometry* targetGeom;
std::vector<const Geometry*> adjGeoms;
std::vector<const Polygon*> m_adjPolygons;
//std::vector<const Polygon*> m_adjPolygons;
const GeometryFactory* geomFactory;
double gapWidth = 0.0;
std::map<std::size_t, std::unique_ptr<IndexedPointInAreaLocator>> adjPolygonLocators;
// std::vector<std::unique_ptr<CoverageRing>> coverageRingStore;
std::vector<std::unique_ptr<CoveragePolygon>> m_adjCovPolygons;
std::deque<CoverageRing> coverageRingStore;
std::vector<std::unique_ptr<CoordinateSequence>> localCoordinateSequences;
std::deque<CoverageRingSegment> coverageRingSegmentStore;
Expand Down Expand Up @@ -273,6 +273,8 @@ class GEOS_DLL CoveragePolygonValidator {

private:

static std::vector<std::unique_ptr<CoveragePolygon>>
toCoveragePolygons(const std::vector<const Polygon*> polygons);
static std::vector<const Polygon*> extractPolygons(std::vector<const Geometry*>& geoms);

/* private */
Expand Down Expand Up @@ -336,34 +338,26 @@ class GEOS_DLL CoveragePolygonValidator {
* to an adjacent polygon.
*
* @param targetRings the rings with segments to test
* @param adjPolygons the adjacent polygons
* @param adjCovPolygons the adjacent polygons
*/
void markInvalidInteriorSegments(
std::vector<CoverageRing*>& targetRings,
std::vector<const Polygon*>& adjPolygons);
std::vector<std::unique_ptr<CoveragePolygon>>& adjCovPolygons);

void markInvalidInteriorSection(
CoverageRing& ring,
std::size_t iStart,
std::size_t iEnd,
std::vector<std::unique_ptr<CoveragePolygon>>& adjCovPolygons );

void markInvalidInteriorSegment(
CoverageRing& ring, std::size_t i, CoveragePolygon* adjPoly);

void checkTargetRings(
std::vector<CoverageRing*>& targetRings,
std::vector<CoverageRing*>& adjRngs,
const Envelope& targetEnv);

/**
* Tests if a coordinate is in the interior of some adjacent polygon.
* Uses the cached Point-In-Polygon indexed locators, for performance.
*
* @param p the coordinate to test
* @param adjPolygons the list of polygons
* @return true if the point is in the interior
*/
bool isInteriorVertex(const Coordinate& p,
std::vector<const Polygon*>& adjPolygons);


bool polygonContainsPoint(std::size_t index,
const Polygon* poly, const Coordinate& pt);

IndexedPointInAreaLocator* getLocator(std::size_t index, const Polygon* poly);

std::unique_ptr<Geometry> createInvalidLines(std::vector<CoverageRing*>& rings);

std::vector<CoverageRing*> createRings(const Geometry* geom);
Expand Down
2 changes: 2 additions & 0 deletions include/geos/coverage/CoverageRing.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ class GEOS_DLL CoverageRing : public noding::BasicSegmentString {

CoverageRing(const LinearRing* ring, bool isShell);

geom::Envelope getEnvelope(std::size_t start, std::size_t end);

/**
* Tests if all rings have known status (matched or invalid)
* for all segments.
Expand Down
76 changes: 76 additions & 0 deletions src/coverage/CoveragePolygon.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**********************************************************************
*
* GEOS - Geometry Engine Open Source
* http://geos.osgeo.org
*
* Copyright (C) 2024 Martin Davis <[email protected]>
*
* 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/coverage/CoveragePolygon.h>

#include <geos/geom/Coordinate.h>
#include <geos/geom/Envelope.h>
#include <geos/geom/Location.h>
#include <geos/geom/Polygon.h>

using geos::algorithm::locate::IndexedPointInAreaLocator;
using geos::geom::CoordinateXY;
using geos::geom::Envelope;
using geos::geom::Location;
using geos::geom::Polygon;

namespace geos { // geos
namespace coverage { // geos.coverage

/* public */
CoveragePolygon::CoveragePolygon(const Polygon* poly)
: m_polygon(poly)
{
//-- cache polygon envelope for maximum performance
polyEnv = *(poly->getEnvelopeInternal());
}

/* public */
bool
CoveragePolygon::intersectsEnv(const Envelope& env) const
{
return polyEnv.intersects(env);
}

/* public */
bool
CoveragePolygon::intersectsEnv(const CoordinateXY& p) const
{
return polyEnv.intersects(p);
}

/* public */
bool
CoveragePolygon::contains(const CoordinateXY& p) const
{
if (! intersectsEnv(p))
return false;
IndexedPointInAreaLocator& pia = getLocator();
return Location::INTERIOR == pia.locate(&p);
}

/* private */
IndexedPointInAreaLocator&
CoveragePolygon::getLocator() const
{
if (m_locator == nullptr) {
m_locator = std::make_unique<IndexedPointInAreaLocator>(*m_polygon);
}
return *m_locator;
}

} // namespace geos.coverage
} // namespace geos


Loading

0 comments on commit ac8b32f

Please sign in to comment.