Skip to content

Commit 1b126d3

Browse files
committed
[pal] Use GEOS for point in polygon test, also use prepared GEOS
geometries where possible
1 parent cb249c3 commit 1b126d3

File tree

8 files changed

+60
-43
lines changed

8 files changed

+60
-43
lines changed

src/core/pal/costcalculator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ namespace pal
5959
{
6060
case PolygonInterior:
6161
// n ranges from 0 -> 12
62-
n = lp->getNumPointsInPolygon( obstacle->getNumPoints(), obstacle->x, obstacle->y );
62+
n = lp->getNumPointsInPolygon( obstacle );
6363
break;
6464
case PolygonBoundary:
6565
// penalty may need tweaking, given that interior mode ranges up to 12

src/core/pal/feature.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,8 +1061,7 @@ namespace pal
10611061
{
10621062
for ( ry = py, j = 0; j < 2; ry = ry + 2 * yrm, j++ )
10631063
{
1064-
// TODO should test with the polyone insteand of the bbox
1065-
if ( !isPointInPolygon( 4, box->x, box->y, rx, ry ) )
1064+
if ( !mapShape->containsPoint( rx, ry ) )
10661065
{
10671066
enoughPlace = false;
10681067
break;
@@ -1130,7 +1129,7 @@ namespace pal
11301129
ry += box->y[0];
11311130

11321131
// Only accept candidate that center is in the polygon
1133-
if ( isPointInPolygon( mapShape->nbPoints, mapShape->x, mapShape->y, rx, ry ) )
1132+
if ( mapShape->containsPoint( rx, ry ) )
11341133
{
11351134
// cost is set to minimal value, evaluated later
11361135
positions.append( new LabelPosition( id++, rx - dlx, ry - dly, xrm, yrm, alpha, 0.0001, this ) ); // Polygon
@@ -1336,13 +1335,10 @@ namespace pal
13361335

13371336
bool FeaturePart::isConnected( FeaturePart* p2 )
13381337
{
1339-
if ( !mGeos )
1340-
createGeosGeom();
1341-
13421338
if ( !p2->mGeos )
13431339
p2->createGeosGeom();
13441340

1345-
return ( GEOSTouches_r( geosContext(), mGeos, p2->mGeos ) == 1 );
1341+
return ( GEOSPreparedTouches_r( geosContext(), preparedGeom(), p2->mGeos ) == 1 );
13461342
}
13471343

13481344
bool FeaturePart::mergeWithFeaturePart( FeaturePart* other )

src/core/pal/geomfunction.cpp

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -378,25 +378,6 @@ namespace pal
378378

379379
}
380380

381-
382-
bool isPointInPolygon( int npol, double *xp, double *yp, double x, double y )
383-
{
384-
// code from Randolph Franklin (found at http://local.wasp.uwa.edu.au/~pbourke/geometry/insidepoly/)
385-
int i, j;
386-
bool c = false;
387-
388-
for ( i = 0, j = npol - 1; i < npol; j = i++ )
389-
{
390-
if (((( yp[i] <= y ) && ( y < yp[j] ) ) ||
391-
(( yp[j] <= y ) && ( y < yp[i] ) ) )
392-
&& ( x < ( xp[j] - xp[i] ) *( y - yp[i] ) / ( yp[j] - yp[i] ) + xp[i] ) )
393-
{
394-
c = !c;
395-
}
396-
}
397-
return c;
398-
}
399-
400381
void findLineCircleIntersection( double cx, double cy, double radius,
401382
double x1, double y1, double x2, double y2,
402383
double& xRes, double& yRes )

src/core/pal/geomfunction.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@ namespace pal
5959
return ( x2 - x1 ) *( x2 - x1 ) + ( y2 - y1 ) *( y2 - y1 );
6060
}
6161

62-
bool isPointInPolygon( int npol, double *xp, double *yp, double x, double y );
63-
6462
void findLineCircleIntersection( double cx, double cy, double radius,
6563
double x1, double y1, double x2, double y2,
6664
double& xRes, double& yRes );

src/core/pal/labelposition.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -586,20 +586,20 @@ namespace pal
586586
return false;
587587
}
588588

589-
int LabelPosition::getNumPointsInPolygon( int npol, double *xp, double *yp )
589+
int LabelPosition::getNumPointsInPolygon( PointSet *polygon ) const
590590
{
591591
int a, k, count = 0;
592592
double px, py;
593593

594-
// cheack each corner
594+
// check each corner
595595
for ( k = 0; k < 4; k++ )
596596
{
597597
px = x[k];
598598
py = y[k];
599599

600600
for ( a = 0; a < 2; a++ ) // and each middle of segment
601601
{
602-
if ( isPointInPolygon( npol, xp, yp, px, py ) )
602+
if ( polygon->containsPoint( px, py ) )
603603
count++;
604604
px = ( x[k] + x[( k+1 ) %4] ) / 2.0;
605605
py = ( y[k] + y[( k+1 ) %4] ) / 2.0;
@@ -610,7 +610,7 @@ namespace pal
610610
py = ( y[0] + y[2] ) / 2.0;
611611

612612
// and the label center
613-
if ( isPointInPolygon( npol, xp, yp, px, py ) )
613+
if ( polygon->containsPoint( px, py ) )
614614
count += 4; // virtually 4 points
615615

616616
// TODO: count with nextFeature

src/core/pal/labelposition.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ namespace pal
132132
bool isBorderCrossingLine( PointSet* feat );
133133

134134
/** Returns number of intersections with polygon (testing border and center) */
135-
int getNumPointsInPolygon( int npol, double *xp, double *yp );
135+
int getNumPointsInPolygon( PointSet* polygon ) const;
136136

137137
/** Shift the label by specified offset */
138138
void offsetPosition( double xOffset, double yOffset );

src/core/pal/pointset.cpp

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
namespace pal
4444
{
4545

46-
4746
PointSet::PointSet()
4847
: mGeos( 0 )
4948
, mOwnsGeom( false )
@@ -53,6 +52,7 @@ namespace pal
5352
, xmax( -DBL_MAX )
5453
, ymin( DBL_MAX )
5554
, ymax( -DBL_MAX )
55+
, mPreparedGeom( 0 )
5656
{
5757
nbPoints = cHullSize = 0;
5858
x = NULL;
@@ -71,6 +71,7 @@ namespace pal
7171
, xmax( -DBL_MAX )
7272
, ymin( DBL_MAX )
7373
, ymax( -DBL_MAX )
74+
, mPreparedGeom( 0 )
7475
{
7576
this->nbPoints = nbPoints;
7677
this->x = new double[nbPoints];
@@ -93,6 +94,7 @@ namespace pal
9394
, xmax( aY )
9495
, ymin( aX )
9596
, ymax( aY )
97+
, mPreparedGeom( 0 )
9698
{
9799
nbPoints = cHullSize = 1;
98100
x = new double[1];
@@ -115,6 +117,7 @@ namespace pal
115117
, xmax( -DBL_MAX )
116118
, ymin( DBL_MAX )
117119
, ymax( -DBL_MAX )
120+
, mPreparedGeom( 0 )
118121
{
119122
int i;
120123

@@ -148,7 +151,7 @@ namespace pal
148151
holeOf = ps.holeOf;
149152
}
150153

151-
void PointSet::createGeosGeom()
154+
void PointSet::createGeosGeom() const
152155
{
153156
GEOSContextHandle_t geosctxt = geosContext();
154157
GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt, nbPoints, 2 );
@@ -161,13 +164,28 @@ namespace pal
161164
mOwnsGeom = true;
162165
}
163166

167+
const GEOSPreparedGeometry *PointSet::preparedGeom() const
168+
{
169+
if ( !mGeos )
170+
createGeosGeom();
171+
172+
if ( !mPreparedGeom )
173+
{
174+
mPreparedGeom = GEOSPrepare_r( geosContext(), mGeos );
175+
}
176+
return mPreparedGeom;
177+
}
178+
164179
PointSet::~PointSet()
165180
{
181+
GEOSContextHandle_t geosctxt = geosContext();
182+
166183
if ( mOwnsGeom )
167184
{
168-
GEOSGeom_destroy_r( geosContext(), mGeos );
185+
GEOSGeom_destroy_r( geosctxt, mGeos );
169186
mGeos = NULL;
170187
}
188+
GEOSPreparedGeom_destroy_r( geosctxt, mPreparedGeom );
171189

172190
deleteCoords();
173191

@@ -230,6 +248,18 @@ namespace pal
230248
return newShape;
231249
}
232250

251+
bool PointSet::containsPoint( double x, double y ) const
252+
{
253+
GEOSContextHandle_t geosctxt = geosContext();
254+
GEOSCoordSequence* seq = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
255+
GEOSCoordSeq_setX_r( geosctxt, seq, 0, x );
256+
GEOSCoordSeq_setY_r( geosctxt, seq, 0, y );
257+
GEOSGeometry* point = GEOSGeom_createPoint_r( geosctxt, seq );
258+
259+
bool result = ( GEOSPreparedContains_r( geosctxt, preparedGeom(), point ) == 1 );
260+
GEOSGeom_destroy_r( geosctxt, point );
261+
return result;
262+
}
233263

234264
void PointSet::splitPolygons( QLinkedList<PointSet*> &shapes_toProcess,
235265
QLinkedList<PointSet*> &shapes_final,
@@ -868,7 +898,7 @@ namespace pal
868898
}
869899

870900

871-
void PointSet::getCentroid( double &px, double &py, bool forceInside )
901+
void PointSet::getCentroid( double &px, double &py, bool forceInside ) const
872902
{
873903
if ( !mGeos )
874904
createGeosGeom();
@@ -886,7 +916,7 @@ namespace pal
886916
}
887917

888918
// check if centroid inside in polygon
889-
if ( forceInside && !isPointInPolygon( nbPoints, x, y, px, py ) )
919+
if ( forceInside && !containsPoint( px, py ) )
890920
{
891921
GEOSGeometry *pointGeom = GEOSPointOnSurface_r( geosctxt, mGeos );
892922

src/core/pal/pointset.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,13 @@ namespace pal
101101

102102
PointSet* extractShape( int nbPtSh, int imin, int imax, int fps, int fpe, double fptx, double fpty );
103103

104+
/** Tests whether point set contains a specified point.
105+
* @param x x-coordinate of point
106+
* @param y y-coordinate of point
107+
* @returns true if point set contains a specified point
108+
*/
109+
bool containsPoint( double x, double y ) const;
110+
104111
PointSet* createProblemSpecificPointSet( double bbmin[2], double bbmax[2], bool *inside );
105112

106113
CHullBox * compute_chull_bbox();
@@ -123,7 +130,7 @@ namespace pal
123130
*/
124131
double getDist( double px, double py, double *rx, double *ry );
125132

126-
void getCentroid( double &px, double &py, bool forceInside = false );
133+
void getCentroid( double &px, double &py, bool forceInside = false ) const;
127134

128135
int getGeosType() const { return type; }
129136

@@ -189,8 +196,8 @@ namespace pal
189196
}
190197

191198
protected:
192-
GEOSGeometry *mGeos;
193-
bool mOwnsGeom;
199+
mutable GEOSGeometry *mGeos;
200+
mutable bool mOwnsGeom;
194201

195202
int nbPoints;
196203
double *x;
@@ -209,13 +216,18 @@ namespace pal
209216
PointSet( PointSet &ps );
210217

211218
void deleteCoords();
212-
void createGeosGeom();
219+
void createGeosGeom() const;
220+
const GEOSPreparedGeometry* preparedGeom() const;
213221

214222
double xmin;
215223
double xmax;
216224
double ymin;
217225
double ymax;
218226

227+
private:
228+
229+
mutable const GEOSPreparedGeometry* mPreparedGeom;
230+
219231
};
220232

221233
} // namespace pal

0 commit comments

Comments
 (0)