2222#include " ../shapely/geometry/geometrycollection.h"
2323
2424#include < array>
25- #include < cmath>
2625#include < cstring>
2726#include < tuple>
2827#include < vector>
@@ -67,20 +66,6 @@ inline void ensure_c_contiguous(const py::buffer_info& buf) {
6766 }
6867}
6968
70- // / Validate coordinate buffer — reject NaN/Inf before they reach GEOS.
71- // / Throws std::invalid_argument with the index of the first offending value.
72- template <typename T>
73- inline void ensure_no_nan_inf (const T* data, size_t count, const char * label = " coords" ) {
74- for (size_t i = 0 ; i < count; ++i) {
75- if (std::isnan (data[i]))
76- throw std::invalid_argument (
77- std::string (label) + " contains NaN at index " + std::to_string (i));
78- if (std::isinf (data[i]))
79- throw std::invalid_argument (
80- std::string (label) + " contains Inf at index " + std::to_string (i));
81- }
82- }
83-
8469// / Convert any py::array coordinate buffer to std::vector<double>.
8570// / Extracts the first 2 columns per row — safe for (N,2) and (N,≥3) arrays.
8671// / dtype double → direct copy; float32/other → cast & widen to double.
@@ -111,8 +96,6 @@ inline std::vector<double> array_to_double_vec(const py::array& arr) {
11196 tmp[r * 2 + 1 ] = static_cast <double >(src[base + 1 ]);
11297 }
11398 }
114- // Validate AFTER conversion: reject NaN/Inf before GEOS
115- ensure_no_nan_inf (tmp.data (), rows * 2 , " coords" );
11699 return tmp;
117100}
118101
@@ -121,65 +104,45 @@ inline std::vector<double> array_to_double_vec(const py::array& arr) {
121104// ============================================================================
122105
123106// -- Point: scalar (x,y) + array ([x,y]) forms --
124- inline Point<double > point (double x, double y) {
125- if (std::isnan (x) || std::isnan (y))
126- throw std::invalid_argument (" point coords contains NaN" );
127- if (std::isinf (x) || std::isinf (y))
128- throw std::invalid_argument (" point coords contains Inf" );
129- return Point<double >(x, y);
130- }
107+ inline Point<double > point (double x, double y) { return Point<double >(x, y); }
131108inline Point<float > point (float x, float y) { return Point<float >(x, y); }
132109
133110inline Point<double > point (const py::array_t <double >& arr) {
134111 auto buf = arr.request ();
135112 ensure_c_contiguous (buf);
136113 const double * p = static_cast <const double *>(buf.ptr );
137- ensure_no_nan_inf (p, buf.size , " point coords" );
138114 return Point<double >(buf.size > 0 ? p[0 ] : 0 , buf.size > 1 ? p[1 ] : 0 );
139115}
140116// float32 auto-upcast: prevent GEOS precision mismatch vs Python shapely
141117inline Point<double > point (const py::array_t <float >& arr) {
142118 auto buf = arr.request ();
143119 ensure_c_contiguous (buf);
144120 const float * p = static_cast <const float *>(buf.ptr );
145- double x = buf.size > 0 ? static_cast <double >(p[0 ]) : 0 ;
146- double y = buf.size > 1 ? static_cast <double >(p[1 ]) : 0 ;
147- if (std::isnan (x) || std::isnan (y))
148- throw std::invalid_argument (" point coords contains NaN" );
149- if (std::isinf (x) || std::isinf (y))
150- throw std::invalid_argument (" point coords contains Inf" );
151- return Point<double >(x, y);
121+ return Point<double >(buf.size > 0 ? static_cast <double >(p[0 ]) : 0 ,
122+ buf.size > 1 ? static_cast <double >(p[1 ]) : 0 );
152123}
153124// auto-double: accept any dtype (int, unknown), always produce Point<double>
154125// Handles 1D [x,y] and 2D (N,≥2) arrays — takes first 2 elements.
155126inline Point<double > point (const py::array& arr) {
156127 auto buf = arr.request ();
157128 ensure_c_contiguous (buf);
158129 if (buf.size < 2 ) return Point<double >(0 , 0 );
159- double x, y;
160130 if (arr.dtype ().is (py::dtype::of<double >())) {
161131 const double * p = static_cast <const double *>(buf.ptr );
162- x = p[0 ]; y = p[1 ];
132+ return Point< double >( p[0 ], p[1 ]) ;
163133 } else {
164134 // float32 or int/other → cast through pybind11 to float32, then widen
165135 auto f32 = py::cast<py::array_t <float >>(arr);
166136 auto fbuf = f32 .request ();
167137 const float * p = static_cast <const float *>(fbuf.ptr );
168- x = static_cast <double >(p[0 ]);
169- y = static_cast <double >(p[1 ]);
138+ return Point<double >(static_cast <double >(p[0 ]), static_cast <double >(p[1 ]));
170139 }
171- if (std::isnan (x) || std::isnan (y))
172- throw std::invalid_argument (" point coords contains NaN" );
173- if (std::isinf (x) || std::isinf (y))
174- throw std::invalid_argument (" point coords contains Inf" );
175- return Point<double >(x, y);
176140}
177141
178142// -- LineString --
179143inline LineString<double > linestring (const py::array_t <double >& arr) {
180144 auto buf = arr.request ();
181145 ensure_c_contiguous (buf);
182- ensure_no_nan_inf (static_cast <const double *>(buf.ptr ), buf.size , " linestring coords" );
183146 return LineString<double >(static_cast <const double *>(buf.ptr ), buf.shape [0 ], buf.shape [1 ]);
184147}
185148// float32 auto-upcast: prevent GEOS precision mismatch vs Python shapely
@@ -204,15 +167,13 @@ inline LineString<double> linestring(const std::vector<std::array<double, 2>>& p
204167 flat[i * 2 ] = pts[i][0 ];
205168 flat[i * 2 + 1 ] = pts[i][1 ];
206169 }
207- ensure_no_nan_inf (flat.data (), pts.size () * 2 , " linestring coords" );
208170 return LineString<double >(flat.data (), pts.size (), 2 );
209171}
210172
211173// -- Polygon --
212174inline Polygon<double > polygon (const py::array_t <double >& arr) {
213175 auto buf = arr.request ();
214176 ensure_c_contiguous (buf);
215- ensure_no_nan_inf (static_cast <const double *>(buf.ptr ), buf.size , " polygon coords" );
216177 return Polygon<double >(static_cast <const double *>(buf.ptr ), buf.shape [0 ], buf.shape [1 ]);
217178}
218179// float32 auto-upcast: prevent GEOS precision mismatch vs Python shapely
@@ -231,7 +192,6 @@ inline Polygon<double> polygon(const py::array& arr) {
231192inline LinearRing<double > linearring (const py::array_t <double >& arr) {
232193 auto buf = arr.request ();
233194 ensure_c_contiguous (buf);
234- ensure_no_nan_inf (static_cast <const double *>(buf.ptr ), buf.size , " linearring coords" );
235195 return LinearRing<double >(static_cast <const double *>(buf.ptr ), buf.shape [0 ], buf.shape [1 ]);
236196}
237197inline LinearRing<double > linearring (const py::array& arr) {
@@ -244,7 +204,6 @@ inline LinearRing<double> linearring(const py::array& arr) {
244204inline MultiPoint<double > multipoint (const py::array_t <double >& arr) {
245205 auto buf = arr.request ();
246206 ensure_c_contiguous (buf);
247- ensure_no_nan_inf (static_cast <const double *>(buf.ptr ), buf.size , " multipoint coords" );
248207 return MultiPoint<double >(static_cast <const double *>(buf.ptr ), buf.shape [0 ], buf.shape [1 ]);
249208}
250209// float32 auto-upcast: prevent GEOS precision mismatch vs Python shapely
@@ -265,7 +224,6 @@ inline MultiLineString<double> multilinestring(const std::vector<py::array_t<dou
265224 for (auto & arr : arrays) {
266225 auto buf = arr.request ();
267226 ensure_c_contiguous (buf);
268- ensure_no_nan_inf (static_cast <const double *>(buf.ptr ), buf.size , " multilinestring coords" );
269227 mls.add_line (static_cast <const double *>(buf.ptr ), buf.shape [0 ], buf.shape [1 ]);
270228 }
271229 return mls;
@@ -296,7 +254,6 @@ inline MultiPolygon<double> multipolygon(const std::vector<py::array_t<double>>&
296254 for (auto & arr : arrays) {
297255 auto buf = arr.request ();
298256 ensure_c_contiguous (buf);
299- ensure_no_nan_inf (static_cast <const double *>(buf.ptr ), buf.size , " multipolygon coords" );
300257 mp.add_polygon (static_cast <const double *>(buf.ptr ), buf.shape [0 ], buf.shape [1 ]);
301258 }
302259 return mp;
0 commit comments