@@ -154,13 +154,29 @@ namespace pal
154
154
void PointSet::createGeosGeom () const
155
155
{
156
156
GEOSContextHandle_t geosctxt = geosContext ();
157
- GEOSCoordSequence *coord = GEOSCoordSeq_create_r ( geosctxt, nbPoints, 2 );
157
+
158
+ bool needClose = false ;
159
+ if ( x[0 ] != x[ nbPoints - 1 ] || y[0 ] != y[ nbPoints - 1 ] )
160
+ {
161
+ needClose = true ;
162
+ }
163
+
164
+ GEOSCoordSequence *coord = GEOSCoordSeq_create_r ( geosctxt, nbPoints + ( needClose ? 1 : 0 ), 2 );
158
165
for ( int i = 0 ; i < nbPoints; ++i )
159
166
{
160
167
GEOSCoordSeq_setX_r ( geosctxt, coord, i, x[i] );
161
168
GEOSCoordSeq_setY_r ( geosctxt, coord, i, y[i] );
162
169
}
170
+
171
+ // close ring if needed
172
+ if ( needClose )
173
+ {
174
+ GEOSCoordSeq_setX_r ( geosctxt, coord, nbPoints, x[0 ] );
175
+ GEOSCoordSeq_setY_r ( geosctxt, coord, nbPoints, y[0 ] );
176
+ }
177
+
163
178
mGeos = GEOSGeom_createPolygon_r ( geosctxt, GEOSGeom_createLinearRing_r ( geosctxt, coord ), 0 , 0 );
179
+
164
180
mOwnsGeom = true ;
165
181
}
166
182
@@ -180,7 +196,7 @@ namespace pal
180
196
{
181
197
GEOSContextHandle_t geosctxt = geosContext ();
182
198
183
- if ( mOwnsGeom )
199
+ if ( mGeos && mOwnsGeom )
184
200
{
185
201
GEOSGeom_destroy_r ( geosctxt, mGeos );
186
202
mGeos = NULL ;
@@ -625,44 +641,6 @@ namespace pal
625
641
}
626
642
}
627
643
628
-
629
- PointSet* PointSet::createProblemSpecificPointSet ( double bbmin[2 ], double bbmax[2 ], bool *inside )
630
- {
631
- #ifdef _DEBUG_FULL_
632
- std::cout << " CreateProblemSpecific:" << std::endl;
633
- #endif
634
- PointSet *shape = new PointSet ();
635
- shape->x = new double [nbPoints];
636
- shape->y = new double [nbPoints];
637
- shape->nbPoints = nbPoints;
638
- shape->type = type;
639
-
640
- shape->xmin = xmin;
641
- shape->xmax = xmax;
642
- shape->ymin = ymin;
643
- shape->ymax = ymax;
644
-
645
- *inside = true ;
646
-
647
- for ( int i = 0 ; i < nbPoints; i++ )
648
- {
649
- shape->x [i] = this ->x [i];
650
- shape->y [i] = this ->y [i];
651
-
652
- // check whether it's not outside
653
- if ( x[i] < bbmin[0 ] || x[i] > bbmax[0 ] || y[i] < bbmin[1 ] || y[i] > bbmax[1 ] )
654
- *inside = false ;
655
- }
656
-
657
- shape->holeOf = NULL ;
658
- shape->parent = NULL ;
659
-
660
- return shape;
661
- }
662
-
663
-
664
-
665
-
666
644
CHullBox * PointSet::compute_chull_bbox ()
667
645
{
668
646
int i;
@@ -830,74 +808,47 @@ namespace pal
830
808
return finalBb;
831
809
}
832
810
833
- double PointSet::getDist ( double px, double py, double *rx, double *ry )
811
+ double PointSet::minDistanceToPoint ( double px, double py, double *rx, double *ry )
834
812
{
835
- if ( nbPoints == 1 || type == GEOS_POINT )
836
- {
837
- if ( rx && ry )
838
- {
839
- *rx = x[0 ];
840
- *ry = y[0 ];
841
- }
842
- return dist_euc2d_sq ( x[0 ], y[0 ], px, py );
843
- }
844
-
845
- int a, b;
846
- int nbP = ( type == GEOS_POLYGON ? nbPoints : nbPoints - 1 );
813
+ if ( !mGeos )
814
+ createGeosGeom ();
847
815
848
- double best_dist = DBL_MAX;
849
- double d ;
816
+ if ( ! mGeos )
817
+ return 0 ;
850
818
851
- for ( a = 0 ; a < nbP; a++ )
852
- {
853
- b = ( a + 1 ) % nbPoints;
854
-
855
- double px2, py2;
856
- px2 = px - y[b] + y[a];
857
- py2 = py + x[b] - x[a];
858
- double ix, iy;
859
-
860
- // (px,py)->(px2,py2) is a line perpendicular to a->b
861
- // Check the line p->p2 cross the segment a->b
862
- if ( computeLineSegIntersection ( px, py, px2, py2,
863
- x[a], y[a], x[b], y[b],
864
- &ix, &iy ) )
865
- {
866
- d = dist_euc2d_sq ( px, py, ix, iy );
867
- }
868
- else
869
- {
870
- double d1 = dist_euc2d_sq ( x[a], y[a], px, py );
871
- double d2 = dist_euc2d_sq ( x[b], y[b], px, py );
872
- if ( d1 < d2 )
873
- {
874
- d = d1;
875
- ix = x[a];
876
- iy = y[a];
877
- }
878
- else
879
- {
880
- d = d2;
881
- ix = x[b];
882
- iy = y[b];
883
- }
884
- }
819
+ GEOSContextHandle_t geosctxt = geosContext ();
885
820
886
- if ( d < best_dist )
887
- {
888
- best_dist = d;
889
- if ( rx && ry )
890
- {
891
- *rx = ix;
892
- *ry = iy;
893
- }
894
- }
895
- } // end for (a in nbPoints)
821
+ GEOSCoordSequence *coord = GEOSCoordSeq_create_r ( geosctxt, 1 , 2 );
822
+ GEOSCoordSeq_setX_r ( geosctxt, coord, 0 , px );
823
+ GEOSCoordSeq_setY_r ( geosctxt, coord, 0 , py );
824
+ GEOSGeometry* geosPt = GEOSGeom_createPoint_r ( geosctxt, coord );
896
825
897
- return best_dist;
826
+ int type = GEOSGeomTypeId_r ( geosctxt, mGeos );
827
+ const GEOSGeometry* extRing = 0 ;
828
+ if ( type != GEOS_POLYGON )
829
+ {
830
+ extRing = mGeos ;
831
+ }
832
+ else
833
+ {
834
+ // for polygons, we want distance to exterior ring (not an interior point)
835
+ extRing = GEOSGetExteriorRing_r ( geosctxt, mGeos );
836
+ }
837
+ GEOSCoordSequence *nearestCoord = GEOSNearestPoints_r ( geosctxt, extRing, geosPt );
838
+ double nx;
839
+ double ny;
840
+ ( void )GEOSCoordSeq_getX_r ( geosctxt, nearestCoord, 0 , &nx );
841
+ ( void )GEOSCoordSeq_getY_r ( geosctxt, nearestCoord, 0 , &ny );
842
+ GEOSGeom_destroy_r ( geosctxt, geosPt );
843
+
844
+ if ( rx )
845
+ *rx = nx;
846
+ if ( ry )
847
+ *ry = ny;
848
+
849
+ return dist_euc2d_sq ( px, py, nx, ny );
898
850
}
899
851
900
-
901
852
void PointSet::getCentroid ( double &px, double &py, bool forceInside ) const
902
853
{
903
854
if ( !mGeos )
@@ -932,6 +883,15 @@ namespace pal
932
883
GEOSGeom_destroy_r ( geosctxt, centroidGeom );
933
884
}
934
885
886
+ const GEOSGeometry *PointSet::geos () const
887
+ {
888
+ if ( !mGeos )
889
+ createGeosGeom ();
890
+
891
+ return mGeos ;
892
+ }
893
+
894
+
935
895
} // end namespace
936
896
937
897
#endif
0 commit comments