Skip to content

Commit 09bdab4

Browse files
committed
MCIndexSegmentSetMutualIntersector: Allow usage from multiple threads
1 parent 9123c56 commit 09bdab4

16 files changed

+82
-105
lines changed

include/geos/index/chain/MonotoneChain.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,12 @@ class GEOS_DLL MonotoneChain {
9696
/// Ownership left to caller, this class holds a reference.
9797
///
9898
MonotoneChain(const geom::CoordinateSequence& pts,
99-
std::size_t start, std::size_t end, void* context);
99+
std::size_t start, std::size_t end, void* context, double expansionDistance);
100100

101101
~MonotoneChain() = default;
102102

103103
/// Returned envelope is owned by this class
104104
const geom::Envelope& getEnvelope() const;
105-
const geom::Envelope& getEnvelope(double expansionDistance) const;
106105

107106
size_t
108107
getStartIndex() const

include/geos/index/chain/MonotoneChainBuilder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class GEOS_DLL MonotoneChainBuilder {
5858
*/
5959
static void getChains(const geom::CoordinateSequence* pts,
6060
void* context,
61+
double expansionDistance,
6162
std::vector<MonotoneChain>& mcList);
6263

6364
/**

include/geos/noding/FastSegmentSetIntersectionFinder.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ namespace noding { // geos::noding
4949
*/
5050
class FastSegmentSetIntersectionFinder {
5151
private:
52-
std::unique_ptr<MCIndexSegmentSetMutualIntersector> segSetMutInt;
53-
std::unique_ptr<geos::algorithm::LineIntersector> lineIntersector;
52+
MCIndexSegmentSetMutualIntersector segSetMutInt;
5453

5554
protected:
5655
public:
@@ -67,7 +66,7 @@ class FastSegmentSetIntersectionFinder {
6766
const SegmentSetMutualIntersector*
6867
getSegmentSetIntersector() const
6968
{
70-
return segSetMutInt.get();
69+
return &segSetMutInt;
7170
}
7271

7372
bool intersects(SegmentString::ConstVect* segStrings);

include/geos/noding/MCIndexSegmentSetMutualIntersector.h

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ class SegmentIntersector;
2929
}
3030
}
3131

32-
//using namespace geos::index::strtree;
33-
3432
namespace geos {
3533
namespace noding { // geos::noding
3634

@@ -45,12 +43,7 @@ class MCIndexSegmentSetMutualIntersector : public SegmentSetMutualIntersector {
4543
public:
4644

4745
MCIndexSegmentSetMutualIntersector(double p_tolerance)
48-
: monoChains()
49-
, indexCounter(0)
50-
, processCounter(0)
51-
, nOverlaps(0)
52-
, overlapTolerance(p_tolerance)
53-
, indexBuilt(false)
46+
: overlapTolerance(p_tolerance)
5447
{}
5548

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

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

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

66+
void process(SegmentString::ConstVect* segStrings, SegmentIntersector* si);
67+
7468
class SegmentOverlapAction : public index::chain::MonotoneChainOverlapAction {
7569
private:
7670
SegmentIntersector& si;
@@ -98,31 +92,25 @@ class MCIndexSegmentSetMutualIntersector : public SegmentSetMutualIntersector {
9892
private:
9993

10094
typedef std::vector<index::chain::MonotoneChain> MonoChains;
101-
MonoChains monoChains;
10295

10396
/*
10497
* The index::SpatialIndex used should be something that supports
10598
* envelope (range) queries efficiently (such as a index::quadtree::Quadtree
10699
* or index::strtree::STRtree).
107100
*/
108101
index::strtree::TemplateSTRtree<const index::chain::MonotoneChain*> index;
109-
int indexCounter;
110-
int processCounter;
111-
// statistics
112-
int nOverlaps;
113-
double overlapTolerance;
102+
103+
const double overlapTolerance;
114104

115105
/* memory management helper, holds MonotoneChain objects used
116106
* in the SpatialIndex. It's cleared when the SpatialIndex is
117107
*/
118-
bool indexBuilt;
108+
std::once_flag indexBuilt;
119109
MonoChains indexChains;
120110

121-
void addToIndex(SegmentString* segStr);
122-
123-
void intersectChains();
111+
void intersectChains(const MonoChains& chains, SegmentIntersector& segmentIntersector);
124112

125-
void addToMonoChains(SegmentString* segStr);
113+
void addChains(const SegmentString* segStr, MonoChains& chains) const;
126114

127115
};
128116

include/geos/noding/SegmentIntersectionDetector.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ namespace noding { // geos::noding
4040
*/
4141
class SegmentIntersectionDetector : public SegmentIntersector {
4242
private:
43-
algorithm::LineIntersector* li;
43+
algorithm::LineIntersector li;
4444

4545
bool findProper;
4646
bool findAllTypes;
@@ -54,9 +54,8 @@ class SegmentIntersectionDetector : public SegmentIntersector {
5454

5555
protected:
5656
public:
57-
SegmentIntersectionDetector(algorithm::LineIntersector* p_li)
57+
SegmentIntersectionDetector()
5858
:
59-
li(p_li),
6059
findProper(false),
6160
findAllTypes(false),
6261
_hasIntersection(false),
@@ -68,7 +67,6 @@ class SegmentIntersectionDetector : public SegmentIntersector {
6867

6968
~SegmentIntersectionDetector() override
7069
{
71-
//delete intPt;
7270
delete intSegments;
7371
}
7472

src/geom/prep/AbstractPreparedPolygonContains.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,7 @@ AbstractPreparedPolygonContains::findAndClassifyIntersections(const geom::Geomet
8383
noding::SegmentString::ConstVect lineSegStr;
8484
noding::SegmentStringUtil::extractSegmentStrings(geom, lineSegStr);
8585

86-
algorithm::LineIntersector li;
87-
88-
noding::SegmentIntersectionDetector intDetector(&li);
86+
noding::SegmentIntersectionDetector intDetector;
8987

9088
intDetector.setFindAllIntersectionTypes(true);
9189
prepPoly->getIntersectionFinder()->intersects(&lineSegStr, &intDetector);

src/index/chain/MonotoneChain.cpp

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,29 +32,22 @@ namespace index { // geos.index
3232
namespace chain { // geos.index.chain
3333

3434
MonotoneChain::MonotoneChain(const geom::CoordinateSequence& newPts,
35-
std::size_t nstart, std::size_t nend, void* nContext)
35+
std::size_t nstart, std::size_t nend, void* nContext,
36+
double expansionDistance)
3637
: pts(&newPts)
3738
, context(nContext)
3839
, start(nstart)
3940
, end(nend)
40-
, env()
41-
{}
42-
43-
const Envelope&
44-
MonotoneChain::getEnvelope() const
41+
, env(pts->getAt<CoordinateXY>(start), pts->getAt<CoordinateXY>(end))
4542
{
46-
return getEnvelope(0.0);
43+
if (expansionDistance > 0.0) {
44+
env.expandBy(expansionDistance);
45+
}
4746
}
4847

4948
const Envelope&
50-
MonotoneChain::getEnvelope(double expansionDistance) const
49+
MonotoneChain::getEnvelope() const
5150
{
52-
if (env.isNull()) {
53-
env.init(pts->getAt<CoordinateXY>(start), pts->getAt<CoordinateXY>(end));
54-
if (expansionDistance > 0.0) {
55-
env.expandBy(expansionDistance);
56-
}
57-
}
5851
return env;
5952
}
6053

src/index/chain/MonotoneChainBuilder.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,14 @@ namespace chain { // geos.index.chain
4848
*/
4949
class ChainBuilder : public CoordinateFilter {
5050
public:
51-
ChainBuilder(const CoordinateSequence* pts, void* context, std::vector<MonotoneChain> & list) :
51+
ChainBuilder(const CoordinateSequence* pts, void* context, double expansionDistance, std::vector<MonotoneChain> & list) :
5252
m_prev(nullptr),
5353
m_i(0),
5454
m_quadrant(-1),
5555
m_start(0),
5656
m_seq(pts),
5757
m_context(context),
58+
m_distance(expansionDistance),
5859
m_list(list) {}
5960

6061
void filter_ro(const CoordinateXY* c) override {
@@ -72,7 +73,7 @@ class ChainBuilder : public CoordinateFilter {
7273
void finishChain() {
7374
if ( m_i == 0 ) return;
7475
std::size_t chainEnd = m_i - 1;
75-
m_list.emplace_back(*m_seq, m_start, chainEnd, m_context);
76+
m_list.emplace_back(*m_seq, m_start, chainEnd, m_context, m_distance);
7677
m_start = chainEnd;
7778
}
7879

@@ -99,15 +100,17 @@ class ChainBuilder : public CoordinateFilter {
99100
std::size_t m_start;
100101
const CoordinateSequence* m_seq;
101102
void* m_context;
103+
double m_distance;
102104
std::vector<MonotoneChain>& m_list;
103105
};
104106

105107

106108
/* static public */
107109
void
108110
MonotoneChainBuilder::getChains(const CoordinateSequence* pts, void* context,
111+
double expansionDistance,
109112
std::vector<MonotoneChain>& mcList) {
110-
ChainBuilder builder(pts, context, mcList);
113+
ChainBuilder builder(pts, context, expansionDistance, mcList);
111114
pts->apply_ro(&builder);
112115
builder.finish();
113116
}

src/noding/FastSegmentSetIntersectionFinder.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,15 @@ namespace noding { // geos::noding
3939
*/
4040
FastSegmentSetIntersectionFinder::
4141
FastSegmentSetIntersectionFinder(noding::SegmentString::ConstVect* baseSegStrings)
42-
: segSetMutInt(new MCIndexSegmentSetMutualIntersector()),
43-
lineIntersector(new algorithm::LineIntersector())
4442
{
45-
segSetMutInt->setBaseSegments(baseSegStrings);
43+
segSetMutInt.setBaseSegments(baseSegStrings);
4644
}
4745

4846
bool
4947
FastSegmentSetIntersectionFinder::
5048
intersects(noding::SegmentString::ConstVect* segStrings)
5149
{
52-
SegmentIntersectionDetector intFinder(lineIntersector.get());
50+
SegmentIntersectionDetector intFinder;
5351

5452
return this->intersects(segStrings, &intFinder);
5553
}
@@ -59,8 +57,7 @@ FastSegmentSetIntersectionFinder::
5957
intersects(noding::SegmentString::ConstVect* segStrings,
6058
SegmentIntersectionDetector* intDetector)
6159
{
62-
segSetMutInt->setSegmentIntersector(intDetector);
63-
segSetMutInt->process(segStrings);
60+
segSetMutInt.process(segStrings, intDetector);
6461

6562
return intDetector->hasIntersection();
6663
}

src/noding/MCIndexNoder.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ MCIndexNoder::computeNodes(SegmentString::NonConstVect* inputSegStrings)
5151

5252
if (!indexBuilt) {
5353
for(const auto& mc : monoChains) {
54-
index.insert(mc.getEnvelope(overlapTolerance), &mc);
54+
index.insert(mc.getEnvelope(), &mc);
5555
}
5656
indexBuilt = true;
5757
}
@@ -84,7 +84,7 @@ MCIndexNoder::add(SegmentString* segStr)
8484

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

8989
}
9090

src/noding/MCIndexSegmentSetMutualIntersector.cpp

Lines changed: 25 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,11 @@
1313
**********************************************************************/
1414

1515
#include <geos/noding/MCIndexSegmentSetMutualIntersector.h>
16-
#include <geos/noding/SegmentSetMutualIntersector.h>
1716
#include <geos/noding/SegmentString.h>
1817
#include <geos/noding/SegmentIntersector.h>
19-
#include <geos/index/SpatialIndex.h>
2018
#include <geos/index/chain/MonotoneChain.h>
2119
#include <geos/index/chain/MonotoneChainBuilder.h>
2220
#include <geos/index/chain/MonotoneChainOverlapAction.h>
23-
#include <geos/index/strtree/SimpleSTRtree.h>
2421

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

3431
/*private*/
3532
void
36-
MCIndexSegmentSetMutualIntersector::addToIndex(SegmentString* segStr)
37-
{
38-
MonotoneChainBuilder::getChains(segStr->getCoordinates(),
39-
segStr, indexChains);
40-
41-
}
42-
43-
44-
/*private*/
45-
void
46-
MCIndexSegmentSetMutualIntersector::addToMonoChains(SegmentString* segStr)
33+
MCIndexSegmentSetMutualIntersector::addChains(const SegmentString* segStr, MonoChains& chains) const
4734
{
4835
if (segStr->size() == 0)
4936
return;
5037
MonotoneChainBuilder::getChains(segStr->getCoordinates(),
51-
segStr, monoChains);
38+
(void*) segStr, overlapTolerance, chains);
5239
}
5340

5441

5542
/*private*/
5643
void
57-
MCIndexSegmentSetMutualIntersector::intersectChains()
44+
MCIndexSegmentSetMutualIntersector::intersectChains(const MonoChains& chains, SegmentIntersector& segmentIntersector)
5845
{
59-
MCIndexSegmentSetMutualIntersector::SegmentOverlapAction overlapAction(*segInt);
46+
MCIndexSegmentSetMutualIntersector::SegmentOverlapAction overlapAction(segmentIntersector);
6047

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

66-
return !segInt->isDone(); // abort early if segInt->isDone()
52+
return !segmentIntersector.isDone(); // abort early if segmentIntersector->isDone()
6753
});
6854
}
6955
}
@@ -73,37 +59,38 @@ MCIndexSegmentSetMutualIntersector::intersectChains()
7359
void
7460
MCIndexSegmentSetMutualIntersector::setBaseSegments(SegmentString::ConstVect* segStrings)
7561
{
76-
// NOTE - mloskot: const qualifier is removed silently, dirty.
77-
7862
for(const SegmentString* css: *segStrings) {
79-
if (css->size() == 0)
80-
continue;
81-
SegmentString* ss = const_cast<SegmentString*>(css);
82-
addToIndex(ss);
63+
addChains(css, indexChains);
8364
}
8465
}
8566

8667
/*public*/
8768
void
8869
MCIndexSegmentSetMutualIntersector::process(SegmentString::ConstVect* segStrings)
8970
{
90-
if (!indexBuilt) {
71+
process(segStrings, segInt);
72+
}
73+
74+
/*public*/
75+
void
76+
MCIndexSegmentSetMutualIntersector::process(SegmentString::ConstVect* segStrings,
77+
SegmentIntersector* segmentIntersector)
78+
{
79+
std::call_once(indexBuilt, [this]() {
9180
for (auto& mc: indexChains) {
92-
index.insert(&(mc.getEnvelope(overlapTolerance)), &mc);
81+
index.insert(&(mc.getEnvelope()), &mc);
9382
}
94-
indexBuilt = true;
95-
}
96-
97-
// Reset counters for new inputs
98-
monoChains.clear();
99-
processCounter = indexCounter + 1;
100-
nOverlaps = 0;
83+
});
10184

85+
// TODO: Rework MonotoneChain extraction to take a callback, so we can pass the chains
86+
// to intersectChains as they are identified.
87+
MonoChains monoChains;
10288
for(const SegmentString* css: *segStrings) {
10389
SegmentString* ss = const_cast<SegmentString*>(css);
104-
addToMonoChains(ss);
90+
addChains(ss, monoChains);
10591
}
106-
intersectChains();
92+
93+
intersectChains(monoChains, *segmentIntersector);
10794
}
10895

10996

0 commit comments

Comments
 (0)