Skip to content

Commit 592f5f1

Browse files
author
peng.li24
committed
refactor: align C++ API naming with Python shapely
- Rename sym_difference → symmetric_difference (all 7 geometry types) - Add boundary() to Point, LineString, LinearRing - Add minimum_clearance() to Point, LineString, Polygon, LinearRing - Add is_closed() to Point, Polygon - Add is_ring() to Point, Polygon - Add envelope() to LineString, LinearRing - Add representative_point() to LineString, LinearRing - Add project() / interpolate() to Polygon, LinearRing - Expand LinearRing with full Python-equivalent API (buffer, distance, predicates, relates, hausdorff, constructive ops, convex_hull, parallel_offset, etc.) - All 162 tests pass
1 parent eb04172 commit 592f5f1

7 files changed

Lines changed: 403 additions & 22 deletions

File tree

shapely/geometry/geometrycollection.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class GeometryCollection {
4848
GeometryCollection difference(const GeometryCollection& other) const;
4949
GeometryCollection intersection(const GeometryCollection& other) const;
5050
GeometryCollection union_op(const GeometryCollection& other) const;
51-
GeometryCollection sym_difference(const GeometryCollection& other) const;
51+
GeometryCollection symmetric_difference(const GeometryCollection& other) const;
5252
GeometryCollection simplify(double tolerance) const;
5353

5454
// -- Accessors --
@@ -155,7 +155,7 @@ GeometryCollection GeometryCollection::OP(const GeometryCollection& o) const { \
155155
GC_CONSTRUCT(difference, geos_difference)
156156
GC_CONSTRUCT(intersection, geos_intersection)
157157
GC_CONSTRUCT(union_op, geos_union)
158-
GC_CONSTRUCT(sym_difference, geos_sym_difference)
158+
GC_CONSTRUCT(symmetric_difference, geos_sym_difference)
159159
#undef GC_CONSTRUCT
160160

161161
GeometryCollection GeometryCollection::simplify(double tol) const {

shapely/geometry/linestring.h

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,19 @@ class LineString {
119119
Point<double> interpolate(double distance) const;
120120
Point<double> centroid() const;
121121
Polygon<double> buffer(double distance) const;
122+
123+
// -- Boundary (Python: .boundary) --
124+
std::string boundary() const;
125+
126+
// -- Minimum clearance (Python: .minimum_clearance) --
127+
double minimum_clearance() const;
128+
129+
// -- Envelope (Python: .envelope) --
130+
Polygon<double> envelope() const;
131+
132+
// -- Representative point (Python: .representative_point) --
133+
Point<double> representative_point() const;
134+
122135
void normalize();
123136

124137
// -- Constructive operations (Python: difference, union, intersection, sym_difference) --
@@ -131,9 +144,9 @@ class LineString {
131144
std::string union_op(const LineString& other) const;
132145
template <typename U> std::string union_op(const Point<U>& other) const;
133146
template <typename U> std::string union_op(const Polygon<U>& other) const;
134-
std::string sym_difference(const LineString& other) const;
135-
template <typename U> std::string sym_difference(const Point<U>& other) const;
136-
template <typename U> std::string sym_difference(const Polygon<U>& other) const;
147+
std::string symmetric_difference(const LineString& other) const;
148+
template <typename U> std::string symmetric_difference(const Point<U>& other) const;
149+
template <typename U> std::string symmetric_difference(const Polygon<U>& other) const;
137150
std::string simplify(double tolerance) const;
138151
std::string parallel_offset(double distance, int quad_segs = 16) const;
139152
Polygon<double> convex_hull() const;
@@ -372,7 +385,7 @@ template <typename T> template <typename U> std::string LineString<T>::OP(const
372385
LS_CONSTRUCT(difference, geos_difference)
373386
LS_CONSTRUCT(intersection, geos_intersection)
374387
LS_CONSTRUCT(union_op, geos_union)
375-
LS_CONSTRUCT(sym_difference, geos_sym_difference)
388+
LS_CONSTRUCT(symmetric_difference, geos_sym_difference)
376389
#undef LS_CONSTRUCT
377390

378391
// Python: base.py::simplify:L469
@@ -404,6 +417,44 @@ Polygon<double> LineString<T>::convex_hull() const {
404417
return Polygon<double>(c.data(), n, 2);
405418
}
406419

420+
// Python: shapely/geometry/base.py::boundary:L457
421+
template <typename T>
422+
std::string LineString<T>::boundary() const {
423+
auto res = detail::geos_boundary(geos_linestring_.get());
424+
return res ? detail::geos_to_wkt(res.get()) : "GEOMETRYCOLLECTION EMPTY";
425+
}
426+
427+
// Python: shapely/geometry/base.py::minimum_clearance:L734
428+
template <typename T>
429+
double LineString<T>::minimum_clearance() const {
430+
return detail::geos_minimum_clearance(geos_linestring_.get());
431+
}
432+
433+
// Python: shapely/geometry/base.py::envelope:L742
434+
template <typename T>
435+
Polygon<double> LineString<T>::envelope() const {
436+
auto res = detail::geos_envelope(geos_linestring_.get());
437+
if (!res || res->isEmpty()) return Polygon<double>();
438+
auto* gp = dynamic_cast<geos::geom::Polygon*>(res.get());
439+
if (!gp) return Polygon<double>();
440+
auto* cs = gp->getExteriorRing()->getCoordinatesRO();
441+
if (!cs || cs->isEmpty()) return Polygon<double>();
442+
size_t n = cs->getSize();
443+
std::vector<double> c(n*2);
444+
for (size_t i = 0; i < n; ++i) { c[i*2]=cs->getAt(i).x; c[i*2+1]=cs->getAt(i).y; }
445+
return Polygon<double>(c.data(), n, 2);
446+
}
447+
448+
// Python: shapely/geometry/base.py::representative_point:L877
449+
template <typename T>
450+
Point<double> LineString<T>::representative_point() const {
451+
auto res = detail::geos_representative_point(geos_linestring_.get());
452+
if (!res || res->isEmpty()) return Point<double>(0, 0);
453+
auto* pt = dynamic_cast<geos::geom::Point*>(res.get());
454+
if (!pt) return Point<double>(0, 0);
455+
return Point<double>(pt->getX(), pt->getY());
456+
}
457+
407458
// Python: base.py::normalize:L663
408459
template <typename T>
409460
void LineString<T>::normalize() { geos_linestring_->normalize(); }

shapely/geometry/multilinestring.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ class MultiLineString {
9696
MultiLineString<double> difference(const MultiLineString<double>& other) const;
9797
MultiLineString<double> intersection(const MultiLineString<double>& other) const;
9898
MultiLineString<double> union_op(const MultiLineString<double>& other) const;
99-
MultiLineString<double> sym_difference(const MultiLineString<double>& other) const;
99+
MultiLineString<double> symmetric_difference(const MultiLineString<double>& other) const;
100100
MultiLineString<double> simplify(double tolerance) const;
101101

102102
// -- Accessors --
@@ -332,7 +332,7 @@ MultiLineString<double> MultiLineString<T>::union_op(const MultiLineString<doubl
332332
return MultiLineString<double>();
333333
}
334334
template <typename T>
335-
MultiLineString<double> MultiLineString<T>::sym_difference(const MultiLineString<double>& o) const {
335+
MultiLineString<double> MultiLineString<T>::symmetric_difference(const MultiLineString<double>& o) const {
336336
auto res = detail::geos_sym_difference(geos_mls_.get(), o.geos_mls_.get());
337337
if (!res || res->isEmpty()) return MultiLineString<double>();
338338
auto* mls = dynamic_cast<geos::geom::MultiLineString*>(res.get());

shapely/geometry/multipoint.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ class MultiPoint {
8787
template <typename U> Point<double> intersection(const Point<U>& other) const;
8888
MultiPoint<double> union_op(const MultiPoint<double>& other) const;
8989
template <typename U> MultiPoint<double> union_op(const Point<U>& other) const;
90-
MultiPoint<double> sym_difference(const MultiPoint<double>& other) const;
91-
template <typename U> MultiPoint<double> sym_difference(const Point<U>& other) const;
90+
MultiPoint<double> symmetric_difference(const MultiPoint<double>& other) const;
91+
template <typename U> MultiPoint<double> symmetric_difference(const Point<U>& other) const;
9292
MultiPoint<double> simplify(double tolerance) const;
9393

9494
// -- Accessors --
@@ -339,7 +339,7 @@ MultiPoint<double> MultiPoint<T>::union_op(const Point<U>& o) const {
339339
return MultiPoint<double>(c.data(), n, 2);
340340
}
341341
template <typename T>
342-
MultiPoint<double> MultiPoint<T>::sym_difference(const MultiPoint<double>& o) const {
342+
MultiPoint<double> MultiPoint<T>::symmetric_difference(const MultiPoint<double>& o) const {
343343
auto res = detail::geos_sym_difference(geos_multipoint_.get(), o.geos_multipoint_.get());
344344
if (!res || res->isEmpty()) return MultiPoint<double>();
345345
auto* mpt = dynamic_cast<geos::geom::MultiPoint*>(res.get());
@@ -353,7 +353,7 @@ MultiPoint<double> MultiPoint<T>::sym_difference(const MultiPoint<double>& o) co
353353
return MultiPoint<double>(c.data(), n, 2);
354354
}
355355
template <typename T> template <typename U>
356-
MultiPoint<double> MultiPoint<T>::sym_difference(const Point<U>& o) const {
356+
MultiPoint<double> MultiPoint<T>::symmetric_difference(const Point<U>& o) const {
357357
auto res = detail::geos_sym_difference(geos_multipoint_.get(), o.geos_point_.get());
358358
if (!res || res->isEmpty()) return MultiPoint<double>();
359359
auto* mpt = dynamic_cast<geos::geom::MultiPoint*>(res.get());

shapely/geometry/multipolygon.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ class MultiPolygon {
113113
MultiPolygon<double> difference(const MultiPolygon<double>& other) const;
114114
MultiPolygon<double> intersection(const MultiPolygon<double>& other) const;
115115
MultiPolygon<double> union_op(const MultiPolygon<double>& other) const;
116-
MultiPolygon<double> sym_difference(const MultiPolygon<double>& other) const;
116+
MultiPolygon<double> symmetric_difference(const MultiPolygon<double>& other) const;
117117
MultiPolygon<double> simplify(double tolerance) const;
118118

119119
// -- Accessors --
@@ -313,7 +313,7 @@ template <typename T> MultiPolygon<double> MultiPolygon<T>::OP(const MultiPolygo
313313
MPY_CONSTRUCT(difference, geos_difference)
314314
MPY_CONSTRUCT(intersection, geos_intersection)
315315
MPY_CONSTRUCT(union_op, geos_union)
316-
MPY_CONSTRUCT(sym_difference, geos_sym_difference)
316+
MPY_CONSTRUCT(symmetric_difference, geos_sym_difference)
317317
#undef MPY_CONSTRUCT
318318

319319
template <typename T>

shapely/geometry/point.h

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ class Point {
4343
// -- Buffer (Python: buffer) --
4444
Polygon<double> buffer(double distance) const;
4545

46+
// -- Boundary (Python: .boundary) --
47+
std::string boundary() const;
48+
49+
// -- Minimum clearance (Python: .minimum_clearance) --
50+
double minimum_clearance() const;
51+
4652
// -- Predicates (Python: contains, within, ...) --
4753
template <typename U> bool contains(const Point<U>& other) const;
4854
template <typename U> bool contains(const LineString<U>& other) const;
@@ -103,6 +109,8 @@ class Point {
103109
bool is_empty() const;
104110
bool is_simple() const;
105111
bool is_valid() const;
112+
bool is_closed() const;
113+
bool is_ring() const;
106114
double area() const;
107115
double length() const;
108116
std::vector<double> bounds() const;
@@ -117,9 +125,9 @@ class Point {
117125
Point<double> union_op(const Point& other) const;
118126
template <typename U> std::string union_op(const LineString<U>& other) const;
119127
template <typename U> std::string union_op(const Polygon<U>& other) const;
120-
Point<double> sym_difference(const Point& other) const;
121-
template <typename U> std::string sym_difference(const LineString<U>& other) const;
122-
template <typename U> std::string sym_difference(const Polygon<U>& other) const;
128+
Point<double> symmetric_difference(const Point& other) const;
129+
template <typename U> std::string symmetric_difference(const LineString<U>& other) const;
130+
template <typename U> std::string symmetric_difference(const Polygon<U>& other) const;
123131
Point<double> simplify(double tolerance) const;
124132

125133
// -- Topology (Python: convex_hull, boundary, envelope, representative_point) --
@@ -230,6 +238,19 @@ Polygon<double> Point<T>::buffer(double distance) const {
230238
return Polygon<double>(c.data(), n, 2);
231239
}
232240

241+
// Python: shapely/geometry/base.py::boundary:L457
242+
template <typename T>
243+
std::string Point<T>::boundary() const {
244+
// Point has no boundary — returns empty geometry
245+
return "GEOMETRYCOLLECTION EMPTY";
246+
}
247+
248+
// Python: shapely/geometry/base.py::minimum_clearance:L734
249+
template <typename T>
250+
double Point<T>::minimum_clearance() const {
251+
return detail::geos_minimum_clearance(geos_point_.get());
252+
}
253+
233254
// Python: shapely/geometry/base.py predicates L753-L813
234255
// -- Predicates (macros to reduce boilerplate) -------------------------------
235256

@@ -391,7 +412,7 @@ std::string Point<T>::union_op(const Polygon<U>& o) const {
391412
}
392413

393414
template <typename T>
394-
Point<double> Point<T>::sym_difference(const Point& o) const {
415+
Point<double> Point<T>::symmetric_difference(const Point& o) const {
395416
auto res = detail::geos_sym_difference(geos_point_.get(), o.geos_point_.get());
396417
if (!res || res->isEmpty()) return Point<double>(0, 0);
397418
auto* mpt = dynamic_cast<geos::geom::MultiPoint*>(res.get());
@@ -404,12 +425,12 @@ Point<double> Point<T>::sym_difference(const Point& o) const {
404425
return Point<double>(0, 0);
405426
}
406427
template <typename T> template <typename U>
407-
std::string Point<T>::sym_difference(const LineString<U>& o) const {
428+
std::string Point<T>::symmetric_difference(const LineString<U>& o) const {
408429
auto res = detail::geos_sym_difference(geos_point_.get(), o.geos_linestring_.get());
409430
return res ? detail::geos_to_wkt(res.get()) : "GEOMETRYCOLLECTION EMPTY";
410431
}
411432
template <typename T> template <typename U>
412-
std::string Point<T>::sym_difference(const Polygon<U>& o) const {
433+
std::string Point<T>::symmetric_difference(const Polygon<U>& o) const {
413434
auto res = detail::geos_sym_difference(geos_point_.get(), o.geos_polygon_.get());
414435
return res ? detail::geos_to_wkt(res.get()) : "GEOMETRYCOLLECTION EMPTY";
415436
}

0 commit comments

Comments
 (0)