Skip to content

Commit

Permalink
MCIndexSegmentSetMutualIntersector: Allow usage from multiple threads
Browse files Browse the repository at this point in the history
  • Loading branch information
dbaston committed Feb 16, 2023
1 parent 9123c56 commit 09bdab4
Show file tree
Hide file tree
Showing 16 changed files with 82 additions and 105 deletions.
3 changes: 1 addition & 2 deletions include/geos/index/chain/MonotoneChain.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,12 @@ class GEOS_DLL MonotoneChain {
/// Ownership left to caller, this class holds a reference.
///
MonotoneChain(const geom::CoordinateSequence& pts,
std::size_t start, std::size_t end, void* context);
std::size_t start, std::size_t end, void* context, double expansionDistance);

~MonotoneChain() = default;

/// Returned envelope is owned by this class
const geom::Envelope& getEnvelope() const;
const geom::Envelope& getEnvelope(double expansionDistance) const;

size_t
getStartIndex() const
Expand Down
1 change: 1 addition & 0 deletions include/geos/index/chain/MonotoneChainBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class GEOS_DLL MonotoneChainBuilder {
*/
static void getChains(const geom::CoordinateSequence* pts,
void* context,
double expansionDistance,
std::vector<MonotoneChain>& mcList);

/**
Expand Down
5 changes: 2 additions & 3 deletions include/geos/noding/FastSegmentSetIntersectionFinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ namespace noding { // geos::noding
*/
class FastSegmentSetIntersectionFinder {
private:
std::unique_ptr<MCIndexSegmentSetMutualIntersector> segSetMutInt;
std::unique_ptr<geos::algorithm::LineIntersector> lineIntersector;
MCIndexSegmentSetMutualIntersector segSetMutInt;

protected:
public:
Expand All @@ -67,7 +66,7 @@ class FastSegmentSetIntersectionFinder {
const SegmentSetMutualIntersector*
getSegmentSetIntersector() const
{
return segSetMutInt.get();
return &segSetMutInt;
}

bool intersects(SegmentString::ConstVect* segStrings);
Expand Down
28 changes: 8 additions & 20 deletions include/geos/noding/MCIndexSegmentSetMutualIntersector.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ class SegmentIntersector;
}
}

//using namespace geos::index::strtree;

namespace geos {
namespace noding { // geos::noding

Expand All @@ -45,12 +43,7 @@ class MCIndexSegmentSetMutualIntersector : public SegmentSetMutualIntersector {
public:

MCIndexSegmentSetMutualIntersector(double p_tolerance)
: monoChains()
, indexCounter(0)
, processCounter(0)
, nOverlaps(0)
, overlapTolerance(p_tolerance)
, indexBuilt(false)
: overlapTolerance(p_tolerance)
{}

MCIndexSegmentSetMutualIntersector()
Expand All @@ -68,9 +61,10 @@ class MCIndexSegmentSetMutualIntersector : public SegmentSetMutualIntersector {

void setBaseSegments(SegmentString::ConstVect* segStrings) override;

// NOTE: re-populates the MonotoneChain vector with newly created chains
void process(SegmentString::ConstVect* segStrings) override;

void process(SegmentString::ConstVect* segStrings, SegmentIntersector* si);

class SegmentOverlapAction : public index::chain::MonotoneChainOverlapAction {
private:
SegmentIntersector& si;
Expand Down Expand Up @@ -98,31 +92,25 @@ class MCIndexSegmentSetMutualIntersector : public SegmentSetMutualIntersector {
private:

typedef std::vector<index::chain::MonotoneChain> MonoChains;
MonoChains monoChains;

/*
* The index::SpatialIndex used should be something that supports
* envelope (range) queries efficiently (such as a index::quadtree::Quadtree
* or index::strtree::STRtree).
*/
index::strtree::TemplateSTRtree<const index::chain::MonotoneChain*> index;
int indexCounter;
int processCounter;
// statistics
int nOverlaps;
double overlapTolerance;

const double overlapTolerance;

/* memory management helper, holds MonotoneChain objects used
* in the SpatialIndex. It's cleared when the SpatialIndex is
*/
bool indexBuilt;
std::once_flag indexBuilt;
MonoChains indexChains;

void addToIndex(SegmentString* segStr);

void intersectChains();
void intersectChains(const MonoChains& chains, SegmentIntersector& segmentIntersector);

void addToMonoChains(SegmentString* segStr);
void addChains(const SegmentString* segStr, MonoChains& chains) const;

};

Expand Down
6 changes: 2 additions & 4 deletions include/geos/noding/SegmentIntersectionDetector.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ namespace noding { // geos::noding
*/
class SegmentIntersectionDetector : public SegmentIntersector {
private:
algorithm::LineIntersector* li;
algorithm::LineIntersector li;

bool findProper;
bool findAllTypes;
Expand All @@ -54,9 +54,8 @@ class SegmentIntersectionDetector : public SegmentIntersector {

protected:
public:
SegmentIntersectionDetector(algorithm::LineIntersector* p_li)
SegmentIntersectionDetector()
:
li(p_li),
findProper(false),
findAllTypes(false),
_hasIntersection(false),
Expand All @@ -68,7 +67,6 @@ class SegmentIntersectionDetector : public SegmentIntersector {

~SegmentIntersectionDetector() override
{
//delete intPt;
delete intSegments;
}

Expand Down
4 changes: 1 addition & 3 deletions src/geom/prep/AbstractPreparedPolygonContains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,7 @@ AbstractPreparedPolygonContains::findAndClassifyIntersections(const geom::Geomet
noding::SegmentString::ConstVect lineSegStr;
noding::SegmentStringUtil::extractSegmentStrings(geom, lineSegStr);

algorithm::LineIntersector li;

noding::SegmentIntersectionDetector intDetector(&li);
noding::SegmentIntersectionDetector intDetector;

intDetector.setFindAllIntersectionTypes(true);
prepPoly->getIntersectionFinder()->intersects(&lineSegStr, &intDetector);
Expand Down
21 changes: 7 additions & 14 deletions src/index/chain/MonotoneChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,29 +32,22 @@ namespace index { // geos.index
namespace chain { // geos.index.chain

MonotoneChain::MonotoneChain(const geom::CoordinateSequence& newPts,
std::size_t nstart, std::size_t nend, void* nContext)
std::size_t nstart, std::size_t nend, void* nContext,
double expansionDistance)
: pts(&newPts)
, context(nContext)
, start(nstart)
, end(nend)
, env()
{}

const Envelope&
MonotoneChain::getEnvelope() const
, env(pts->getAt<CoordinateXY>(start), pts->getAt<CoordinateXY>(end))
{
return getEnvelope(0.0);
if (expansionDistance > 0.0) {
env.expandBy(expansionDistance);
}
}

const Envelope&
MonotoneChain::getEnvelope(double expansionDistance) const
MonotoneChain::getEnvelope() const
{
if (env.isNull()) {
env.init(pts->getAt<CoordinateXY>(start), pts->getAt<CoordinateXY>(end));
if (expansionDistance > 0.0) {
env.expandBy(expansionDistance);
}
}
return env;
}

Expand Down
9 changes: 6 additions & 3 deletions src/index/chain/MonotoneChainBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,14 @@ namespace chain { // geos.index.chain
*/
class ChainBuilder : public CoordinateFilter {
public:
ChainBuilder(const CoordinateSequence* pts, void* context, std::vector<MonotoneChain> & list) :
ChainBuilder(const CoordinateSequence* pts, void* context, double expansionDistance, std::vector<MonotoneChain> & list) :
m_prev(nullptr),
m_i(0),
m_quadrant(-1),
m_start(0),
m_seq(pts),
m_context(context),
m_distance(expansionDistance),
m_list(list) {}

void filter_ro(const CoordinateXY* c) override {
Expand All @@ -72,7 +73,7 @@ class ChainBuilder : public CoordinateFilter {
void finishChain() {
if ( m_i == 0 ) return;
std::size_t chainEnd = m_i - 1;
m_list.emplace_back(*m_seq, m_start, chainEnd, m_context);
m_list.emplace_back(*m_seq, m_start, chainEnd, m_context, m_distance);
m_start = chainEnd;
}

Expand All @@ -99,15 +100,17 @@ class ChainBuilder : public CoordinateFilter {
std::size_t m_start;
const CoordinateSequence* m_seq;
void* m_context;
double m_distance;
std::vector<MonotoneChain>& m_list;
};


/* static public */
void
MonotoneChainBuilder::getChains(const CoordinateSequence* pts, void* context,
double expansionDistance,
std::vector<MonotoneChain>& mcList) {
ChainBuilder builder(pts, context, mcList);
ChainBuilder builder(pts, context, expansionDistance, mcList);
pts->apply_ro(&builder);
builder.finish();
}
Expand Down
9 changes: 3 additions & 6 deletions src/noding/FastSegmentSetIntersectionFinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,15 @@ namespace noding { // geos::noding
*/
FastSegmentSetIntersectionFinder::
FastSegmentSetIntersectionFinder(noding::SegmentString::ConstVect* baseSegStrings)
: segSetMutInt(new MCIndexSegmentSetMutualIntersector()),
lineIntersector(new algorithm::LineIntersector())
{
segSetMutInt->setBaseSegments(baseSegStrings);
segSetMutInt.setBaseSegments(baseSegStrings);
}

bool
FastSegmentSetIntersectionFinder::
intersects(noding::SegmentString::ConstVect* segStrings)
{
SegmentIntersectionDetector intFinder(lineIntersector.get());
SegmentIntersectionDetector intFinder;

return this->intersects(segStrings, &intFinder);
}
Expand All @@ -59,8 +57,7 @@ FastSegmentSetIntersectionFinder::
intersects(noding::SegmentString::ConstVect* segStrings,
SegmentIntersectionDetector* intDetector)
{
segSetMutInt->setSegmentIntersector(intDetector);
segSetMutInt->process(segStrings);
segSetMutInt.process(segStrings, intDetector);

return intDetector->hasIntersection();
}
Expand Down
4 changes: 2 additions & 2 deletions src/noding/MCIndexNoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ MCIndexNoder::computeNodes(SegmentString::NonConstVect* inputSegStrings)

if (!indexBuilt) {
for(const auto& mc : monoChains) {
index.insert(mc.getEnvelope(overlapTolerance), &mc);
index.insert(mc.getEnvelope(), &mc);
}
indexBuilt = true;
}
Expand Down Expand Up @@ -84,7 +84,7 @@ MCIndexNoder::add(SegmentString* segStr)

// segChains will contain newly allocated MonotoneChain objects
MonotoneChainBuilder::getChains(segStr->getCoordinates(),
segStr, monoChains);
segStr, overlapTolerance, monoChains);

}

Expand Down
63 changes: 25 additions & 38 deletions src/noding/MCIndexSegmentSetMutualIntersector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,11 @@
**********************************************************************/

#include <geos/noding/MCIndexSegmentSetMutualIntersector.h>
#include <geos/noding/SegmentSetMutualIntersector.h>
#include <geos/noding/SegmentString.h>
#include <geos/noding/SegmentIntersector.h>
#include <geos/index/SpatialIndex.h>
#include <geos/index/chain/MonotoneChain.h>
#include <geos/index/chain/MonotoneChainBuilder.h>
#include <geos/index/chain/MonotoneChainOverlapAction.h>
#include <geos/index/strtree/SimpleSTRtree.h>

// std
#include <cstddef>
Expand All @@ -33,37 +30,26 @@ namespace noding { // geos::noding

/*private*/
void
MCIndexSegmentSetMutualIntersector::addToIndex(SegmentString* segStr)
{
MonotoneChainBuilder::getChains(segStr->getCoordinates(),
segStr, indexChains);

}


/*private*/
void
MCIndexSegmentSetMutualIntersector::addToMonoChains(SegmentString* segStr)
MCIndexSegmentSetMutualIntersector::addChains(const SegmentString* segStr, MonoChains& chains) const
{
if (segStr->size() == 0)
return;
MonotoneChainBuilder::getChains(segStr->getCoordinates(),
segStr, monoChains);
(void*) segStr, overlapTolerance, chains);
}


/*private*/
void
MCIndexSegmentSetMutualIntersector::intersectChains()
MCIndexSegmentSetMutualIntersector::intersectChains(const MonoChains& chains, SegmentIntersector& segmentIntersector)
{
MCIndexSegmentSetMutualIntersector::SegmentOverlapAction overlapAction(*segInt);
MCIndexSegmentSetMutualIntersector::SegmentOverlapAction overlapAction(segmentIntersector);

for(auto& queryChain : monoChains) {
index.query(queryChain.getEnvelope(overlapTolerance), [&queryChain, &overlapAction, this](const MonotoneChain* testChain) -> bool {
for(auto& queryChain : chains) {
index.query(queryChain.getEnvelope(), [&queryChain, &overlapAction, &segmentIntersector, this](const MonotoneChain* testChain) -> bool {
queryChain.computeOverlaps(testChain, overlapTolerance, &overlapAction);
nOverlaps++;

return !segInt->isDone(); // abort early if segInt->isDone()
return !segmentIntersector.isDone(); // abort early if segmentIntersector->isDone()
});
}
}
Expand All @@ -73,37 +59,38 @@ MCIndexSegmentSetMutualIntersector::intersectChains()
void
MCIndexSegmentSetMutualIntersector::setBaseSegments(SegmentString::ConstVect* segStrings)
{
// NOTE - mloskot: const qualifier is removed silently, dirty.

for(const SegmentString* css: *segStrings) {
if (css->size() == 0)
continue;
SegmentString* ss = const_cast<SegmentString*>(css);
addToIndex(ss);
addChains(css, indexChains);
}
}

/*public*/
void
MCIndexSegmentSetMutualIntersector::process(SegmentString::ConstVect* segStrings)
{
if (!indexBuilt) {
process(segStrings, segInt);
}

/*public*/
void
MCIndexSegmentSetMutualIntersector::process(SegmentString::ConstVect* segStrings,
SegmentIntersector* segmentIntersector)
{
std::call_once(indexBuilt, [this]() {
for (auto& mc: indexChains) {
index.insert(&(mc.getEnvelope(overlapTolerance)), &mc);
index.insert(&(mc.getEnvelope()), &mc);
}
indexBuilt = true;
}

// Reset counters for new inputs
monoChains.clear();
processCounter = indexCounter + 1;
nOverlaps = 0;
});

// TODO: Rework MonotoneChain extraction to take a callback, so we can pass the chains
// to intersectChains as they are identified.
MonoChains monoChains;
for(const SegmentString* css: *segStrings) {
SegmentString* ss = const_cast<SegmentString*>(css);
addToMonoChains(ss);
addChains(ss, monoChains);
}
intersectChains();

intersectChains(monoChains, *segmentIntersector);
}


Expand Down
Loading

0 comments on commit 09bdab4

Please sign in to comment.