1 /**
2 * SFCGAL
3 *
4 * Copyright (C) 2012-2013 Oslandia <infos@oslandia.com>
5 * Copyright (C) 2012-2013 IGN (http://www.ign.fr)
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21
22 #include <SFCGAL/Geometry.h>
23 #include <SFCGAL/version.h>
24 #include <SFCGAL/Point.h>
25 #include <SFCGAL/LineString.h>
26 #include <SFCGAL/Triangle.h>
27 #include <SFCGAL/Polygon.h>
28 #include <SFCGAL/Solid.h>
29 #include <SFCGAL/MultiPoint.h>
30 #include <SFCGAL/MultiLineString.h>
31 #include <SFCGAL/MultiPolygon.h>
32 #include <SFCGAL/GeometryCollection.h>
33 #include <SFCGAL/PolyhedralSurface.h>
34 #include <SFCGAL/TriangulatedSurface.h>
35 #include <SFCGAL/PreparedGeometry.h>
36
37 #include <SFCGAL/capi/sfcgal_c.h>
38
39 #include <SFCGAL/io/wkt.h>
40 #include <SFCGAL/io/ewkt.h>
41 #include <SFCGAL/detail/io/Serialization.h>
42
43 #include <SFCGAL/algorithm/isValid.h>
44 #include <SFCGAL/algorithm/intersects.h>
45 #include <SFCGAL/algorithm/covers.h>
46 #include <SFCGAL/algorithm/intersection.h>
47 #include <SFCGAL/algorithm/difference.h>
48 #include <SFCGAL/algorithm/union.h>
49 #include <SFCGAL/algorithm/convexHull.h>
50 #include <SFCGAL/algorithm/distance.h>
51 #include <SFCGAL/algorithm/distance3d.h>
52 #include <SFCGAL/algorithm/lineSubstring.h>
53 #include <SFCGAL/algorithm/plane.h>
54 #include <SFCGAL/algorithm/volume.h>
55 #include <SFCGAL/algorithm/area.h>
56 #include <SFCGAL/algorithm/extrude.h>
57 #include <SFCGAL/algorithm/tesselate.h>
58 #include <SFCGAL/triangulate/triangulate2DZ.h>
59 #include <SFCGAL/algorithm/minkowskiSum.h>
60 #include <SFCGAL/algorithm/offset.h>
61 #include <SFCGAL/algorithm/straightSkeleton.h>
62
63 #include <SFCGAL/detail/transform/ForceZOrderPoints.h>
64 #include <SFCGAL/detail/transform/ForceOrderPoints.h>
65 #include <SFCGAL/detail/transform/RoundTransform.h>
66
67 //
68 // Note about sfcgal_geometry_t pointers: they are basically void* pointers that represent
69 // pointers to a SFCGAL::Geometry.
70 // In order to support multiple inheritance:
71 // every input or output sfcgal_geometry_t* is a pointer to the *base class* SFCGAL::Geometry.
72 // If a function wants to return a sub-class, it must be up casted before returned (static_cast)
73 // If a function wants to use a sub-class from a parameter, it must also be down casted.
74 // For instance, static_cast<SFCGAL::Point*>(reinterpret_cast<SFCGAL::Geometry*>(p))
75 //
76 // SFCGAL::PreparedGeometry has no vtable and can thus be manipuled through reinterpret_cast without
77 // problem
78
79 static sfcgal_error_handler_t __sfcgal_warning_handler = printf;
80 static sfcgal_error_handler_t __sfcgal_error_handler = printf;
81
82 #define SFCGAL_WARNING __sfcgal_warning_handler
83 #define SFCGAL_ERROR __sfcgal_error_handler
84
85 #define SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR( call ) \
86 try {call}\
87 catch( std::exception& e ) { SFCGAL_ERROR( "%s", e.what() ); return 0; }
88
89 #define SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR_NO_RET( call ) \
90 try {call}\
91 catch( std::exception& e ) { SFCGAL_ERROR( "%s", e.what() ); }
92
93 template <class T>
down_cast(sfcgal_geometry_t * p)94 inline T* down_cast( sfcgal_geometry_t* p )
95 {
96 T* q = dynamic_cast<T*>( reinterpret_cast<SFCGAL::Geometry*>( p ) );
97
98 if ( !q ) {
99 BOOST_THROW_EXCEPTION( SFCGAL::Exception( "wrong geometry type" ) );
100 }
101
102 return q;
103 }
104
105 template <class T>
down_const_cast(const sfcgal_geometry_t * p)106 inline const T* down_const_cast( const sfcgal_geometry_t* p )
107 {
108 const T* q = dynamic_cast<const T*>( reinterpret_cast<const SFCGAL::Geometry*>( p ) );
109
110 if ( !q ) {
111 BOOST_THROW_EXCEPTION( SFCGAL::Exception( "wrong geometry type" ) );
112 }
113
114 return q;
115 }
116
sfcgal_set_error_handlers(sfcgal_error_handler_t warning_handler,sfcgal_error_handler_t error_handler)117 extern "C" void sfcgal_set_error_handlers( sfcgal_error_handler_t warning_handler, sfcgal_error_handler_t error_handler )
118 {
119 __sfcgal_warning_handler = warning_handler;
120 __sfcgal_error_handler = error_handler;
121 }
122
123 static sfcgal_alloc_handler_t __sfcgal_alloc_handler = malloc;
124 static sfcgal_free_handler_t __sfcgal_free_handler = free;
125
sfcgal_set_alloc_handlers(sfcgal_alloc_handler_t alloc_handler,sfcgal_free_handler_t free_handler)126 extern "C" void sfcgal_set_alloc_handlers( sfcgal_alloc_handler_t alloc_handler, sfcgal_free_handler_t free_handler )
127 {
128 __sfcgal_alloc_handler = alloc_handler;
129 __sfcgal_free_handler = free_handler;
130 }
131
sfcgal_init()132 extern "C" void sfcgal_init()
133 {
134 // Empty for now
135 }
136
sfcgal_version()137 extern "C" const char* sfcgal_version()
138 {
139 return SFCGAL::Version();
140 }
141
sfcgal_full_version()142 extern "C" const char* sfcgal_full_version()
143 {
144 return SFCGAL::Full_Version();
145 }
146
sfcgal_set_geometry_validation(int)147 extern "C" void sfcgal_set_geometry_validation( int /*enabled*/ )
148 {
149 }
150
sfcgal_geometry_type_id(const sfcgal_geometry_t * geom)151 extern "C" sfcgal_geometry_type_t sfcgal_geometry_type_id( const sfcgal_geometry_t* geom )
152 {
153
154 try {
155 return ( sfcgal_geometry_type_t )reinterpret_cast<const SFCGAL::Geometry*>( geom )->geometryTypeId();
156 }
157 catch( std::exception& e ) {
158 SFCGAL_ERROR( "%s", e.what() );
159 return SFCGAL_TYPE_POINT; // to avoid warning
160 }
161 }
162
sfcgal_geometry_is_valid(const sfcgal_geometry_t * geom)163 extern "C" int sfcgal_geometry_is_valid( const sfcgal_geometry_t* geom )
164 {
165 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
166 return ( int )bool( SFCGAL::algorithm::isValid( *reinterpret_cast<const SFCGAL::Geometry*>( geom ) ) );
167 )
168 }
169
sfcgal_geometry_is_valid_detail(const sfcgal_geometry_t * geom,char ** invalidity_reason,sfcgal_geometry_t ** invalidity_location)170 extern "C" int sfcgal_geometry_is_valid_detail( const sfcgal_geometry_t* geom, char** invalidity_reason, sfcgal_geometry_t** invalidity_location )
171 {
172 // invalidity location is not supported for now
173 if ( invalidity_location )
174 *invalidity_location = 0;
175 // set to null for now
176 if ( invalidity_reason )
177 *invalidity_reason = 0;
178
179 const SFCGAL::Geometry* g = reinterpret_cast<const SFCGAL::Geometry*>( geom );
180 if ( g->hasValidityFlag() )
181 return true;
182 bool is_valid = false;
183 try
184 {
185 SFCGAL::Validity validity = SFCGAL::algorithm::isValid( *g );
186 is_valid = validity;
187 if ( !is_valid && invalidity_reason ) {
188 *invalidity_reason = strdup( validity.reason().c_str() );
189 }
190 }
191 catch ( SFCGAL::Exception& e )
192 {
193 if ( invalidity_reason ) {
194 *invalidity_reason = strdup( e.what() );
195 }
196 }
197 return is_valid;
198 }
199
sfcgal_geometry_is_3d(const sfcgal_geometry_t * geom)200 extern "C" int sfcgal_geometry_is_3d( const sfcgal_geometry_t* geom )
201 {
202 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
203 return ( int )reinterpret_cast<const SFCGAL::Geometry*>( geom )->is3D();
204 )
205 }
206
sfcgal_geometry_is_measured(const sfcgal_geometry_t * geom)207 extern "C" int sfcgal_geometry_is_measured( const sfcgal_geometry_t* geom )
208 {
209 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
210 return ( int )reinterpret_cast<const SFCGAL::Geometry*>( geom )->isMeasured();
211 )
212 }
213
sfcgal_geometry_is_empty(const sfcgal_geometry_t * geom)214 extern "C" int sfcgal_geometry_is_empty( const sfcgal_geometry_t* geom )
215 {
216 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
217 return ( int )reinterpret_cast<const SFCGAL::Geometry*>( geom )->isEmpty();
218 )
219 }
220
sfcgal_geometry_clone(const sfcgal_geometry_t * geom)221 extern "C" sfcgal_geometry_t* sfcgal_geometry_clone( const sfcgal_geometry_t* geom )
222 {
223 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
224 return reinterpret_cast<const SFCGAL::Geometry*>( geom )->clone();
225 )
226 }
227
sfcgal_geometry_delete(sfcgal_geometry_t * geom)228 extern "C" void sfcgal_geometry_delete( sfcgal_geometry_t* geom )
229 {
230 delete reinterpret_cast<SFCGAL::Geometry*>( geom );
231 }
232
sfcgal_geometry_as_text(const sfcgal_geometry_t * pgeom,char ** buffer,size_t * len)233 extern "C" void sfcgal_geometry_as_text( const sfcgal_geometry_t* pgeom, char** buffer, size_t* len )
234 {
235 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR_NO_RET(
236 std::string wkt = reinterpret_cast<const SFCGAL::Geometry*>( pgeom )->asText();
237 *buffer = ( char* )__sfcgal_alloc_handler( wkt.size() + 1 );
238 *len = wkt.size();
239 strncpy( *buffer, wkt.c_str(), *len );
240 )
241 }
242
sfcgal_geometry_as_text_decim(const sfcgal_geometry_t * pgeom,int numDecimals,char ** buffer,size_t * len)243 extern "C" void sfcgal_geometry_as_text_decim( const sfcgal_geometry_t* pgeom, int numDecimals, char** buffer, size_t* len )
244 {
245 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR_NO_RET(
246 std::string wkt = reinterpret_cast<const SFCGAL::Geometry*>( pgeom )->asText( numDecimals );
247 *buffer = ( char* )__sfcgal_alloc_handler( wkt.size() + 1 );
248 *len = wkt.size();
249 strncpy( *buffer, wkt.c_str(), *len );
250 )
251 }
252
253 /**
254 * Point
255 */
sfcgal_point_create()256 extern "C" sfcgal_geometry_t* sfcgal_point_create()
257 {
258 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
259 return static_cast<SFCGAL::Geometry*>( new SFCGAL::Point() );
260 )
261 }
262
sfcgal_point_create_from_xy(double x,double y)263 extern "C" sfcgal_geometry_t* sfcgal_point_create_from_xy( double x, double y )
264 {
265 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
266 return static_cast<SFCGAL::Geometry*>( new SFCGAL::Point( x, y ) );
267 )
268 }
sfcgal_point_create_from_xyz(double x,double y,double z)269 extern "C" sfcgal_geometry_t* sfcgal_point_create_from_xyz( double x, double y, double z )
270 {
271 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
272 return static_cast<SFCGAL::Geometry*>( new SFCGAL::Point( x, y, z ) );
273 )
274 }
275
sfcgal_point_x(const sfcgal_geometry_t * geom)276 extern "C" double sfcgal_point_x( const sfcgal_geometry_t* geom )
277 {
278 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
279 return CGAL::to_double( down_const_cast<SFCGAL::Point>( geom )->x() );
280 )
281 }
282
sfcgal_point_y(const sfcgal_geometry_t * geom)283 extern "C" double sfcgal_point_y( const sfcgal_geometry_t* geom )
284 {
285 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
286 return CGAL::to_double( down_const_cast<SFCGAL::Point>( geom )->y() );
287 )
288 }
289
sfcgal_point_z(const sfcgal_geometry_t * geom)290 extern "C" double sfcgal_point_z( const sfcgal_geometry_t* geom )
291 {
292 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
293 return CGAL::to_double( down_const_cast<SFCGAL::Point>( geom )->z() );
294 )
295 }
296
sfcgal_point_m(const sfcgal_geometry_t * geom)297 extern "C" double sfcgal_point_m( const sfcgal_geometry_t* geom )
298 {
299 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
300 return CGAL::to_double( down_const_cast<SFCGAL::Point>( geom )->m() );
301 )
302 }
303
304 /**
305 * LineString
306 */
sfcgal_linestring_create()307 extern "C" sfcgal_geometry_t* sfcgal_linestring_create()
308 {
309 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
310 return static_cast<SFCGAL::Geometry*>( new SFCGAL::LineString() );
311 )
312 }
313
sfcgal_linestring_num_points(const sfcgal_geometry_t * geom)314 extern "C" size_t sfcgal_linestring_num_points( const sfcgal_geometry_t* geom )
315 {
316 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
317 return down_const_cast<SFCGAL::LineString>( geom )->numPoints();
318 )
319 }
320
sfcgal_linestring_point_n(const sfcgal_geometry_t * geom,size_t i)321 extern "C" const sfcgal_geometry_t* sfcgal_linestring_point_n( const sfcgal_geometry_t* geom, size_t i )
322 {
323 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
324 return static_cast<const SFCGAL::Geometry*>( &( down_const_cast<SFCGAL::LineString>( geom )->pointN( i ) ) );
325 )
326 }
327
sfcgal_linestring_add_point(sfcgal_geometry_t * geom,sfcgal_geometry_t * point)328 extern "C" void sfcgal_linestring_add_point( sfcgal_geometry_t* geom, sfcgal_geometry_t* point )
329 {
330 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR_NO_RET(
331 down_cast<SFCGAL::LineString>( geom )->addPoint( down_cast<SFCGAL::Point>( point ) );
332 )
333 }
334
335 /**
336 * Triangle
337 */
sfcgal_triangle_create()338 extern "C" sfcgal_geometry_t* sfcgal_triangle_create()
339 {
340 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
341 return static_cast<SFCGAL::Geometry*>( new SFCGAL::Triangle() );
342 )
343 }
344
sfcgal_triangle_create_from_points(const sfcgal_geometry_t * pa,const sfcgal_geometry_t * pb,const sfcgal_geometry_t * pc)345 extern "C" sfcgal_geometry_t* sfcgal_triangle_create_from_points( const sfcgal_geometry_t* pa,
346 const sfcgal_geometry_t* pb,
347 const sfcgal_geometry_t* pc )
348 {
349 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
350 return static_cast<SFCGAL::Geometry*>( new SFCGAL::Triangle( *down_const_cast<SFCGAL::Point>( pa ),
351 *down_const_cast<SFCGAL::Point>( pb ),
352 *down_const_cast<SFCGAL::Point>( pc ) ) );
353 )
354 }
355
356
sfcgal_triangle_vertex(const sfcgal_geometry_t * geom,int i)357 extern "C" const sfcgal_geometry_t* sfcgal_triangle_vertex( const sfcgal_geometry_t* geom, int i )
358 {
359 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
360 return static_cast<const SFCGAL::Geometry*>( &down_const_cast<SFCGAL::Triangle>( geom )->vertex( i ) );
361 )
362 }
363
sfcgal_triangle_set_vertex(sfcgal_geometry_t * geom,int i,const sfcgal_geometry_t * point)364 extern "C" void sfcgal_triangle_set_vertex( sfcgal_geometry_t* geom, int i, const sfcgal_geometry_t* point )
365 {
366 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR_NO_RET(
367 down_cast<SFCGAL::Triangle>( geom )->vertex( i ) = *down_const_cast<const SFCGAL::Point>( point );
368 )
369 }
370
sfcgal_triangle_set_vertex_from_xy(sfcgal_geometry_t * geom,int i,double x,double y)371 extern "C" void sfcgal_triangle_set_vertex_from_xy( sfcgal_geometry_t* geom, int i, double x, double y )
372 {
373 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR_NO_RET(
374 down_cast<SFCGAL::Triangle>( geom )->vertex( i ) = SFCGAL::Point( x, y );
375 )
376 }
377
sfcgal_triangle_set_vertex_from_xyz(sfcgal_geometry_t * geom,int i,double x,double y,double z)378 extern "C" void sfcgal_triangle_set_vertex_from_xyz( sfcgal_geometry_t* geom, int i, double x, double y, double z )
379 {
380 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR_NO_RET(
381 down_cast<SFCGAL::Triangle>( geom )->vertex( i ) = SFCGAL::Point( x, y, z );
382 )
383 }
384
385 /**
386 * Polygon
387 */
sfcgal_polygon_create()388 extern "C" sfcgal_geometry_t* sfcgal_polygon_create()
389 {
390 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
391 return static_cast<SFCGAL::Geometry*>( new SFCGAL::Polygon() );
392 )
393 }
394
sfcgal_polygon_create_from_exterior_ring(sfcgal_geometry_t * ring)395 extern "C" sfcgal_geometry_t* sfcgal_polygon_create_from_exterior_ring( sfcgal_geometry_t* ring )
396 {
397 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
398 return static_cast<SFCGAL::Geometry*>( new SFCGAL::Polygon( down_cast<SFCGAL::LineString>( ring ) ) );
399 )
400 }
401
sfcgal_polygon_exterior_ring(const sfcgal_geometry_t * geom)402 extern "C" const sfcgal_geometry_t* sfcgal_polygon_exterior_ring( const sfcgal_geometry_t* geom )
403 {
404 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
405 return static_cast<const SFCGAL::Geometry*>( &down_const_cast<SFCGAL::Polygon>( geom )->exteriorRing() );
406 )
407 }
408
sfcgal_polygon_num_interior_rings(const sfcgal_geometry_t * geom)409 extern "C" size_t sfcgal_polygon_num_interior_rings( const sfcgal_geometry_t* geom )
410 {
411 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
412 return down_const_cast<SFCGAL::Polygon>( geom )->numInteriorRings();
413 )
414 }
415
sfcgal_polygon_interior_ring_n(const sfcgal_geometry_t * geom,size_t i)416 extern "C" const sfcgal_geometry_t* sfcgal_polygon_interior_ring_n( const sfcgal_geometry_t* geom, size_t i )
417 {
418 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
419 return static_cast<const SFCGAL::Geometry*>( &down_const_cast<SFCGAL::Polygon>( geom )->interiorRingN( i ) );
420 )
421 }
422
sfcgal_polygon_add_interior_ring(sfcgal_geometry_t * geom,sfcgal_geometry_t * ring)423 extern "C" void sfcgal_polygon_add_interior_ring( sfcgal_geometry_t* geom, sfcgal_geometry_t* ring )
424 {
425 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR_NO_RET(
426 down_cast<SFCGAL::Polygon>( geom )->addRing( down_cast<SFCGAL::LineString>( ring ) );
427 )
428 }
429
430 /**
431 * Geometry collection
432 */
433
sfcgal_geometry_collection_create()434 extern "C" sfcgal_geometry_t* sfcgal_geometry_collection_create()
435 {
436 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
437 return static_cast<SFCGAL::Geometry*>( new SFCGAL::GeometryCollection() );
438 )
439 }
440
sfcgal_geometry_collection_num_geometries(const sfcgal_geometry_t * geom)441 extern "C" size_t sfcgal_geometry_collection_num_geometries( const sfcgal_geometry_t* geom )
442 {
443 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
444 return down_const_cast<SFCGAL::GeometryCollection>( geom )->numGeometries();
445 )
446 }
447
sfcgal_geometry_collection_geometry_n(const sfcgal_geometry_t * geom,size_t i)448 extern "C" const sfcgal_geometry_t* sfcgal_geometry_collection_geometry_n( const sfcgal_geometry_t* geom, size_t i )
449 {
450 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
451 const SFCGAL::GeometryCollection* g = down_const_cast<SFCGAL::GeometryCollection>( geom );
452 return static_cast<const SFCGAL::Geometry*>( &g->geometryN( i ) );
453 )
454 }
455
sfcgal_geometry_collection_add_geometry(sfcgal_geometry_t * geom,sfcgal_geometry_t * ngeom)456 extern "C" void sfcgal_geometry_collection_add_geometry( sfcgal_geometry_t* geom, sfcgal_geometry_t* ngeom )
457 {
458 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR_NO_RET(
459 down_cast<SFCGAL::GeometryCollection>( geom )->addGeometry( reinterpret_cast<SFCGAL::Geometry*>( ngeom ) );
460 )
461 }
462
463 /**
464 * Multi-*
465 */
sfcgal_multi_point_create()466 extern "C" sfcgal_geometry_t* sfcgal_multi_point_create()
467 {
468 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
469 return static_cast<SFCGAL::Geometry*>( new SFCGAL::MultiPoint() );
470 )
471 }
472
sfcgal_multi_linestring_create()473 extern "C" sfcgal_geometry_t* sfcgal_multi_linestring_create()
474 {
475 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
476 return static_cast<SFCGAL::Geometry*>( new SFCGAL::MultiLineString() );
477 )
478 }
479
sfcgal_multi_polygon_create()480 extern "C" sfcgal_geometry_t* sfcgal_multi_polygon_create()
481 {
482 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
483 return static_cast<SFCGAL::Geometry*>( new SFCGAL::MultiPolygon() );
484 )
485 }
486
487 /**
488 * Polyhedral surface
489 */
490
sfcgal_polyhedral_surface_create()491 extern "C" sfcgal_geometry_t* sfcgal_polyhedral_surface_create()
492 {
493 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
494 return static_cast<SFCGAL::Geometry*>( new SFCGAL::PolyhedralSurface() );
495 )
496 }
497
sfcgal_polyhedral_surface_num_polygons(const sfcgal_geometry_t * geom)498 extern "C" size_t sfcgal_polyhedral_surface_num_polygons( const sfcgal_geometry_t* geom )
499 {
500 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
501 return down_const_cast<SFCGAL::PolyhedralSurface>( geom )->numPolygons();
502 )
503 }
504
sfcgal_polyhedral_surface_polygon_n(const sfcgal_geometry_t * geom,size_t i)505 extern "C" const sfcgal_geometry_t* sfcgal_polyhedral_surface_polygon_n( const sfcgal_geometry_t* geom, size_t i )
506 {
507 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
508 return static_cast<const SFCGAL::Geometry*>( &down_const_cast<SFCGAL::PolyhedralSurface>( geom )->polygonN( i ) );
509 )
510 }
511
sfcgal_polyhedral_surface_add_polygon(sfcgal_geometry_t * geom,sfcgal_geometry_t * poly)512 extern "C" void sfcgal_polyhedral_surface_add_polygon( sfcgal_geometry_t* geom, sfcgal_geometry_t* poly )
513 {
514 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR_NO_RET(
515 return down_cast<SFCGAL::PolyhedralSurface>( geom )->addPolygon( down_cast<SFCGAL::Polygon>( poly ) );
516 )
517 }
518
519 /**
520 * Triangulated surface
521 */
522
sfcgal_triangulated_surface_create()523 extern "C" sfcgal_geometry_t* sfcgal_triangulated_surface_create()
524 {
525 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
526 return static_cast<SFCGAL::Geometry*>( new SFCGAL::TriangulatedSurface() );
527 )
528 }
529
sfcgal_triangulated_surface_num_triangles(const sfcgal_geometry_t * geom)530 extern "C" size_t sfcgal_triangulated_surface_num_triangles( const sfcgal_geometry_t* geom )
531 {
532 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
533 return down_const_cast<SFCGAL::TriangulatedSurface>( geom )->numTriangles();
534 )
535 }
536
sfcgal_triangulated_surface_triangle_n(const sfcgal_geometry_t * geom,size_t i)537 extern "C" const sfcgal_geometry_t* sfcgal_triangulated_surface_triangle_n( const sfcgal_geometry_t* geom, size_t i )
538 {
539 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
540 return static_cast<const SFCGAL::Geometry*>( &down_const_cast<SFCGAL::TriangulatedSurface>( geom )->triangleN( i ) );
541 )
542 }
543
sfcgal_triangulated_surface_add_triangle(sfcgal_geometry_t * geom,sfcgal_geometry_t * triangle)544 extern "C" void sfcgal_triangulated_surface_add_triangle( sfcgal_geometry_t* geom, sfcgal_geometry_t* triangle )
545 {
546 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR_NO_RET(
547 down_cast<SFCGAL::TriangulatedSurface>( geom )->addTriangle( down_cast<SFCGAL::Triangle>( triangle ) );
548 )
549 }
550
551 /**
552 * Solid
553 */
554
sfcgal_solid_create()555 extern "C" sfcgal_geometry_t* sfcgal_solid_create()
556 {
557 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
558 return static_cast<SFCGAL::Geometry*>( new SFCGAL::Solid() );
559 )
560 }
561
sfcgal_solid_create_from_exterior_shell(sfcgal_geometry_t * shell)562 extern "C" sfcgal_geometry_t* sfcgal_solid_create_from_exterior_shell( sfcgal_geometry_t* shell )
563 {
564 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
565 return static_cast<SFCGAL::Geometry*>( new SFCGAL::Solid( down_cast<SFCGAL::PolyhedralSurface>( shell ) ) );
566 )
567 }
568
sfcgal_solid_num_shells(const sfcgal_geometry_t * geom)569 extern "C" size_t sfcgal_solid_num_shells( const sfcgal_geometry_t* geom )
570 {
571 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
572 return down_const_cast<SFCGAL::Solid>( geom )->numShells();
573 )
574 }
575
sfcgal_solid_shell_n(const sfcgal_geometry_t * geom,size_t i)576 extern "C" const sfcgal_geometry_t* sfcgal_solid_shell_n( const sfcgal_geometry_t* geom, size_t i )
577 {
578 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
579 return static_cast<const SFCGAL::Geometry*>( &down_const_cast<SFCGAL::Solid>( geom )->shellN( i ) );
580 )
581 }
582
sfcgal_solid_add_interior_shell(sfcgal_geometry_t * geom,sfcgal_geometry_t * shell)583 extern "C" void sfcgal_solid_add_interior_shell( sfcgal_geometry_t* geom , sfcgal_geometry_t* shell )
584 {
585 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR_NO_RET(
586 down_cast<SFCGAL::Solid>( geom )->addInteriorShell( down_cast<SFCGAL::PolyhedralSurface>( shell ) );
587 )
588 }
589
sfcgal_prepared_geometry_create()590 extern "C" sfcgal_prepared_geometry_t* sfcgal_prepared_geometry_create()
591 {
592 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
593 return new SFCGAL::PreparedGeometry();
594 )
595 }
596
sfcgal_prepared_geometry_create_from_geometry(sfcgal_geometry_t * geom,srid_t srid)597 extern "C" sfcgal_prepared_geometry_t* sfcgal_prepared_geometry_create_from_geometry( sfcgal_geometry_t* geom, srid_t srid )
598 {
599 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
600 return new SFCGAL::PreparedGeometry( reinterpret_cast<SFCGAL::Geometry*>( geom ), srid );
601 )
602 }
603
sfcgal_prepared_geometry_delete(sfcgal_prepared_geometry_t * pgeom)604 extern "C" void sfcgal_prepared_geometry_delete( sfcgal_prepared_geometry_t* pgeom )
605 {
606 delete reinterpret_cast<SFCGAL::PreparedGeometry*>( pgeom );
607 }
608
sfcgal_prepared_geometry_geometry(const sfcgal_prepared_geometry_t * pgeom)609 extern "C" const sfcgal_geometry_t* sfcgal_prepared_geometry_geometry( const sfcgal_prepared_geometry_t* pgeom )
610 {
611 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
612 return &reinterpret_cast<const SFCGAL::PreparedGeometry*>( pgeom )->geometry();
613 )
614 }
615
sfcgal_prepared_geometry_set_geometry(sfcgal_prepared_geometry_t * pgeom,sfcgal_geometry_t * geom)616 extern "C" void sfcgal_prepared_geometry_set_geometry( sfcgal_prepared_geometry_t* pgeom, sfcgal_geometry_t* geom )
617 {
618 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR_NO_RET(
619 reinterpret_cast<SFCGAL::PreparedGeometry*>( pgeom )->resetGeometry( reinterpret_cast<SFCGAL::Geometry*>( geom ) );
620 )
621 }
622
sfcgal_prepared_geometry_srid(const sfcgal_prepared_geometry_t * pgeom)623 extern "C" srid_t sfcgal_prepared_geometry_srid( const sfcgal_prepared_geometry_t* pgeom )
624 {
625 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
626 return reinterpret_cast<const SFCGAL::PreparedGeometry*>( pgeom )->SRID();
627 )
628 }
629
sfcgal_prepared_geometry_set_srid(sfcgal_prepared_geometry_t * pgeom,srid_t srid)630 extern "C" void sfcgal_prepared_geometry_set_srid( sfcgal_prepared_geometry_t* pgeom, srid_t srid )
631 {
632 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR_NO_RET(
633 reinterpret_cast<SFCGAL::PreparedGeometry*>( pgeom )->SRID() = srid;
634 )
635 }
636
sfcgal_prepared_geometry_as_ewkt(const sfcgal_prepared_geometry_t * pgeom,int num_decimals,char ** buffer,size_t * len)637 extern "C" void sfcgal_prepared_geometry_as_ewkt( const sfcgal_prepared_geometry_t* pgeom, int num_decimals, char** buffer, size_t* len )
638 {
639 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR_NO_RET(
640 std::string ewkt = reinterpret_cast<const SFCGAL::PreparedGeometry*>( pgeom )->asEWKT( num_decimals );
641 *buffer = ( char* )__sfcgal_alloc_handler( ewkt.size() + 1 );
642 *len = ewkt.size();
643 strncpy( *buffer, ewkt.c_str(), *len );
644 )
645 }
646
sfcgal_io_read_wkt(const char * str,size_t len)647 extern "C" sfcgal_geometry_t* sfcgal_io_read_wkt( const char* str, size_t len )
648 {
649 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR(
650 return SFCGAL::io::readWkt( str, len ).release();
651 )
652 }
653
sfcgal_io_write_binary_prepared(const sfcgal_prepared_geometry_t * geom,char ** buffer,size_t * len)654 extern "C" void sfcgal_io_write_binary_prepared( const sfcgal_prepared_geometry_t* geom, char** buffer, size_t* len )
655 {
656 SFCGAL_GEOMETRY_CONVERT_CATCH_TO_ERROR_NO_RET(
657 const SFCGAL::PreparedGeometry* g = reinterpret_cast<const SFCGAL::PreparedGeometry*>( geom );
658 std::string str = SFCGAL::io::writeBinaryPrepared( *g );
659 *buffer = ( char* )__sfcgal_alloc_handler( str.size() + 1 );
660 *len = str.size();
661 memcpy( *buffer, str.c_str(), *len );
662 )
663 }
664
sfcgal_io_read_binary_prepared(const char * str,size_t len)665 extern "C" sfcgal_prepared_geometry_t* sfcgal_io_read_binary_prepared( const char* str, size_t len )
666 {
667 std::string sstr( str, len );
668 std::unique_ptr<SFCGAL::PreparedGeometry> g;
669
670 try {
671 g = SFCGAL::io::readBinaryPrepared( sstr );
672 }
673 catch ( std::exception& e ) {
674 SFCGAL_WARNING( "During read_binary_prepared" );
675 SFCGAL_ERROR( "%s", e.what() );
676 return 0;
677 }
678
679 return g.release();
680 }
681
sfcgal_io_read_ewkt(const char * str,size_t len)682 extern "C" sfcgal_prepared_geometry_t* sfcgal_io_read_ewkt( const char* str, size_t len )
683 {
684 std::unique_ptr<SFCGAL::PreparedGeometry> g;
685
686 try {
687 g = SFCGAL::io::readEwkt( str, len );
688 }
689 catch ( std::exception& e ) {
690 SFCGAL_ERROR( "%s", e.what() );
691 return 0;
692 }
693
694 SFCGAL::PreparedGeometry* pg = g.release();
695 return pg;
696 }
697
698 // Functions that take two geometries and return a scalar
699 //
700 // name: C function name
701 // ret_type: C function return type
702 // sfcgal_function: C++ SFCGAL method to call
703 // cpp_type: C++ return type (might be different than ret_type)
704 // fail_value: returned value on failure
705 #define SFCGAL_GEOMETRY_FUNCTION_BINARY_SCALAR( name, sfcgal_function, ret_type, cpp_type, fail_value ) \
706 extern "C" ret_type sfcgal_geometry_##name( const sfcgal_geometry_t* ga, const sfcgal_geometry_t* gb ) \
707 { \
708 cpp_type r; \
709 try \
710 { \
711 r = sfcgal_function( *(const SFCGAL::Geometry*)(ga), *(const SFCGAL::Geometry*)(gb) ); \
712 } \
713 catch ( std::exception& e ) \
714 { \
715 SFCGAL_WARNING( "During " #name "(A,B) :" ); \
716 SFCGAL_WARNING( " with A: %s", ((const SFCGAL::Geometry*)(ga))->asText().c_str() ); \
717 SFCGAL_WARNING( " and B: %s", ((const SFCGAL::Geometry*)(gb))->asText().c_str() ); \
718 SFCGAL_ERROR( "%s", e.what() ); \
719 return fail_value; \
720 } \
721 return r; \
722 }
723
724 #define SFCGAL_GEOMETRY_FUNCTION_BINARY_PREDICATE( name, sfcgal_function ) \
725 SFCGAL_GEOMETRY_FUNCTION_BINARY_SCALAR( name, sfcgal_function, int, bool, -1 )
726
SFCGAL_GEOMETRY_FUNCTION_BINARY_PREDICATE(covers,SFCGAL::algorithm::covers)727 SFCGAL_GEOMETRY_FUNCTION_BINARY_PREDICATE( covers, SFCGAL::algorithm::covers )
728 SFCGAL_GEOMETRY_FUNCTION_BINARY_PREDICATE( covers_3d, SFCGAL::algorithm::covers3D )
729
730 SFCGAL_GEOMETRY_FUNCTION_BINARY_PREDICATE( intersects, SFCGAL::algorithm::intersects )
731 SFCGAL_GEOMETRY_FUNCTION_BINARY_PREDICATE( intersects_3d, SFCGAL::algorithm::intersects3D )
732
733 #define SFCGAL_GEOMETRY_FUNCTION_BINARY_MEASURE( name, sfcgal_function ) \
734 SFCGAL_GEOMETRY_FUNCTION_BINARY_SCALAR( name, sfcgal_function, double, double, -1.0 )
735
736 SFCGAL_GEOMETRY_FUNCTION_BINARY_MEASURE( distance, SFCGAL::algorithm::distance )
737 SFCGAL_GEOMETRY_FUNCTION_BINARY_MEASURE( distance_3d, SFCGAL::algorithm::distance3D )
738
739
740 #define SFCGAL_GEOMETRY_FUNCTION_BINARY_CONSTRUCTION( name, sfcgal_function ) \
741 extern "C" sfcgal_geometry_t* sfcgal_geometry_##name( const sfcgal_geometry_t* ga, const sfcgal_geometry_t* gb ) \
742 { \
743 std::unique_ptr<SFCGAL::Geometry> result; \
744 try \
745 { \
746 result = sfcgal_function( *(const SFCGAL::Geometry*)(ga), *(const SFCGAL::Geometry*)(gb) ); \
747 } \
748 catch ( std::exception& e ) \
749 { \
750 SFCGAL_WARNING( "During " #name "(A,B) :" ); \
751 SFCGAL_WARNING( " with A: %s", ((const SFCGAL::Geometry*)(ga))->asText().c_str() ); \
752 SFCGAL_WARNING( " and B: %s", ((const SFCGAL::Geometry*)(gb))->asText().c_str() ); \
753 SFCGAL_ERROR( "%s", e.what() ); \
754 return 0; \
755 } \
756 return result.release(); \
757 }
758
759 SFCGAL_GEOMETRY_FUNCTION_BINARY_CONSTRUCTION( intersection, SFCGAL::algorithm::intersection )
760 SFCGAL_GEOMETRY_FUNCTION_BINARY_CONSTRUCTION( intersection_3d, SFCGAL::algorithm::intersection3D )
761 SFCGAL_GEOMETRY_FUNCTION_BINARY_CONSTRUCTION( difference, SFCGAL::algorithm::difference )
762 SFCGAL_GEOMETRY_FUNCTION_BINARY_CONSTRUCTION( difference_3d, SFCGAL::algorithm::difference3D )
763 SFCGAL_GEOMETRY_FUNCTION_BINARY_CONSTRUCTION( union, SFCGAL::algorithm::union_ )
764 SFCGAL_GEOMETRY_FUNCTION_BINARY_CONSTRUCTION( union_3d, SFCGAL::algorithm::union3D )
765
766 #define SFCGAL_GEOMETRY_FUNCTION_UNARY_CONSTRUCTION( name, sfcgal_function ) \
767 extern "C" sfcgal_geometry_t* sfcgal_geometry_##name( const sfcgal_geometry_t* ga ) \
768 { \
769 std::unique_ptr<SFCGAL::Geometry> result; \
770 try \
771 { \
772 result = sfcgal_function( *(const SFCGAL::Geometry*)(ga) ); \
773 } \
774 catch ( std::exception& e ) \
775 { \
776 SFCGAL_WARNING( "During " #name "(A) :" ); \
777 SFCGAL_WARNING( " with A: %s", ((const SFCGAL::Geometry*)(ga))->asText().c_str() ); \
778 SFCGAL_ERROR( "%s", e.what() ); \
779 return 0; \
780 } \
781 return result.release(); \
782 }
783
784 SFCGAL_GEOMETRY_FUNCTION_UNARY_CONSTRUCTION( convexhull, SFCGAL::algorithm::convexHull )
785 SFCGAL_GEOMETRY_FUNCTION_UNARY_CONSTRUCTION( convexhull_3d, SFCGAL::algorithm::convexHull3D )
786 SFCGAL_GEOMETRY_FUNCTION_UNARY_CONSTRUCTION( straight_skeleton, SFCGAL::algorithm::straightSkeleton )
787 SFCGAL_GEOMETRY_FUNCTION_UNARY_CONSTRUCTION( approximate_medial_axis, SFCGAL::algorithm::approximateMedialAxis )
788 SFCGAL_GEOMETRY_FUNCTION_UNARY_CONSTRUCTION( tesselate, SFCGAL::algorithm::tesselate )
789
790 #define SFCGAL_GEOMETRY_FUNCTION_UNARY_MEASURE( name, sfcgal_function ) \
791 extern "C" double sfcgal_geometry_##name( const sfcgal_geometry_t* ga ) \
792 { \
793 double r; \
794 try \
795 { \
796 r = sfcgal_function( *(const SFCGAL::Geometry*)(ga) ); \
797 } \
798 catch ( std::exception& e ) \
799 { \
800 SFCGAL_WARNING( "During " #name "(A) :" ); \
801 SFCGAL_WARNING( " with A: %s", ((const SFCGAL::Geometry*)(ga))->asText().c_str() ); \
802 SFCGAL_ERROR( "%s", e.what() ); \
803 return -1.0; \
804 } \
805 return r; \
806 }
807
808 extern "C" double sfcgal_geometry_volume( const sfcgal_geometry_t* ga )
809 {
810 double r;
811
812 try {
813 r = CGAL::to_double( SFCGAL::algorithm::volume( *( const SFCGAL::Geometry* )( ga ) ) );
814 }
815 catch ( std::exception& e ) {
816 SFCGAL_WARNING( "During volume(A) :" );
817 SFCGAL_WARNING( " with A: %s", ( ( const SFCGAL::Geometry* )( ga ) )->asText().c_str() );
818 SFCGAL_ERROR( "%s", e.what() );
819 return -1.0;
820 }
821
822 return r;
823 }
824
SFCGAL_GEOMETRY_FUNCTION_UNARY_MEASURE(area,SFCGAL::algorithm::area)825 SFCGAL_GEOMETRY_FUNCTION_UNARY_MEASURE( area, SFCGAL::algorithm::area )
826 SFCGAL_GEOMETRY_FUNCTION_UNARY_MEASURE( area_3d, SFCGAL::algorithm::area3D )
827
828 extern "C" int sfcgal_geometry_is_planar( const sfcgal_geometry_t* ga )
829 {
830 const SFCGAL::Geometry* g = reinterpret_cast<const SFCGAL::Geometry*>( ga );
831
832 if ( g->geometryTypeId() != SFCGAL::TYPE_POLYGON ) {
833 SFCGAL_ERROR( "is_planar() only applies to polygons" );
834 return -1;
835 }
836
837 bool r;
838
839 try {
840 r = SFCGAL::algorithm::isPlane3D< SFCGAL::Kernel >( g->as<const SFCGAL::Polygon >(), 1e-9 );
841 }
842 catch ( std::exception& e ) {
843 SFCGAL_WARNING( "During is_planar(A) :" );
844 SFCGAL_WARNING( " with A: %s", ( ( const SFCGAL::Geometry* )( ga ) )->asText().c_str() );
845 SFCGAL_ERROR( "%s", e.what() );
846 return -1.0;
847 }
848
849 return r ? 1 : 0;
850 }
851
852 /**
853 * Get geometry orientation.
854 * Returns:
855 * -1 for a counter clock wise orientation,
856 * 1 for a clock wise orientation,
857 * 0 for invalid or undetermined orientation
858 */
sfcgal_geometry_orientation(const sfcgal_geometry_t * ga)859 extern "C" int sfcgal_geometry_orientation( const sfcgal_geometry_t* ga )
860 {
861 const SFCGAL::Geometry* g = reinterpret_cast<const SFCGAL::Geometry*>( ga );
862
863 if ( g->geometryTypeId() != SFCGAL::TYPE_POLYGON ) {
864 SFCGAL_ERROR( "orientation() only applies to polygons" );
865 return 0;
866 }
867
868 bool r;
869
870 try {
871 r = g->as<const SFCGAL::Polygon>().isCounterClockWiseOriented();
872 }
873 catch ( std::exception& e ) {
874 SFCGAL_WARNING( "During orientation(A) :" );
875 SFCGAL_WARNING( " with A: %s", ( ( const SFCGAL::Geometry* )( ga ) )->asText().c_str() );
876 SFCGAL_ERROR( "%s", e.what() );
877 return -1.0;
878 }
879
880 return r ? -1 : 1;
881 }
882
sfcgal_geometry_make_solid(const sfcgal_geometry_t * ga)883 extern "C" sfcgal_geometry_t* sfcgal_geometry_make_solid( const sfcgal_geometry_t* ga )
884 {
885 const SFCGAL::Geometry* g = reinterpret_cast<const SFCGAL::Geometry*>( ga );
886
887 if ( g->geometryTypeId() != SFCGAL::TYPE_POLYHEDRALSURFACE ) {
888 SFCGAL_ERROR( "make_solid() only applies to polyhedral surfaces" );
889 return 0;
890 }
891
892 return static_cast<SFCGAL::Geometry*>( new SFCGAL::Solid( g->as<const SFCGAL::PolyhedralSurface>() ) );
893 }
894
sfcgal_geometry_force_lhr(const sfcgal_geometry_t * ga)895 extern "C" sfcgal_geometry_t* sfcgal_geometry_force_lhr( const sfcgal_geometry_t* ga )
896 {
897 const SFCGAL::Geometry* g = reinterpret_cast<const SFCGAL::Geometry*>( ga );
898 SFCGAL::Geometry* gb = g->clone();
899 SFCGAL::transform::ForceOrderPoints force( /* ccw */ true );
900
901 try {
902 gb->accept( force );
903 }
904 catch ( std::exception& e ) {
905 SFCGAL_WARNING( "During force_lhr(A) :" );
906 SFCGAL_WARNING( " with A: %s", ( ( const SFCGAL::Geometry* )( ga ) )->asText().c_str() );
907 SFCGAL_ERROR( "%s", e.what() );
908 return 0;
909 }
910
911 return gb;
912 }
913
sfcgal_geometry_force_rhr(const sfcgal_geometry_t * ga)914 extern "C" sfcgal_geometry_t* sfcgal_geometry_force_rhr( const sfcgal_geometry_t* ga )
915 {
916 const SFCGAL::Geometry* g = reinterpret_cast<const SFCGAL::Geometry*>( ga );
917 SFCGAL::Geometry* gb = g->clone();
918 SFCGAL::transform::ForceOrderPoints force( /* ccw */ false );
919
920 try {
921 gb->accept( force );
922 }
923 catch ( std::exception& e ) {
924 SFCGAL_WARNING( "During force_rhr(A) :" );
925 SFCGAL_WARNING( " with A: %s", ( ( const SFCGAL::Geometry* )( ga ) )->asText().c_str() );
926 SFCGAL_ERROR( "%s", e.what() );
927 return 0;
928 }
929
930 return gb;
931 }
932
sfcgal_geometry_triangulate_2dz(const sfcgal_geometry_t * ga)933 extern "C" sfcgal_geometry_t* sfcgal_geometry_triangulate_2dz( const sfcgal_geometry_t* ga )
934 {
935 const SFCGAL::Geometry* g = reinterpret_cast<const SFCGAL::Geometry*>( ga );
936 SFCGAL::TriangulatedSurface* surf = new SFCGAL::TriangulatedSurface;
937
938 try {
939 SFCGAL::triangulate::ConstraintDelaunayTriangulation cdt;
940 SFCGAL::triangulate::triangulate2DZ( *g, cdt );
941 cdt.getTriangles( *surf );
942 }
943 catch ( std::exception& e ) {
944 SFCGAL_WARNING( "During triangulate_2d(A) :" );
945 SFCGAL_WARNING( " with A: %s", ( ( const SFCGAL::Geometry* )( ga ) )->asText().c_str() );
946 SFCGAL_ERROR( "%s", e.what() );
947 return 0;
948 }
949
950 return static_cast<SFCGAL::Geometry*>( surf );
951 }
952
sfcgal_geometry_extrude(const sfcgal_geometry_t * ga,double x,double y,double z)953 extern "C" sfcgal_geometry_t* sfcgal_geometry_extrude( const sfcgal_geometry_t* ga, double x, double y, double z )
954 {
955 const SFCGAL::Geometry* g = reinterpret_cast<const SFCGAL::Geometry*>( ga );
956 std::unique_ptr<SFCGAL::Geometry> gb( g->clone() );
957 SFCGAL::transform::ForceZOrderPoints forceZ;
958 std::unique_ptr<SFCGAL::Geometry> result;
959
960 try {
961 gb->accept( forceZ );
962 result = SFCGAL::algorithm::extrude( *gb, x, y, z );
963 }
964 catch ( std::exception& e ) {
965 SFCGAL_WARNING( "During extrude(A, %g, %g, %g) :", x, y, z );
966 SFCGAL_WARNING( " with A: %s", ( ( const SFCGAL::Geometry* )( ga ) )->asText().c_str() );
967 SFCGAL_ERROR( "%s", e.what() );
968 return 0;
969 }
970
971 return result.release();
972 }
973
sfcgal_geometry_round(const sfcgal_geometry_t * ga,int scale)974 extern "C" sfcgal_geometry_t* sfcgal_geometry_round( const sfcgal_geometry_t* ga, int scale )
975 {
976 const SFCGAL::Geometry* g = reinterpret_cast<const SFCGAL::Geometry*>( ga );
977 SFCGAL::Geometry* gb = g->clone();
978 // SFCGAL_WARNING( "geom: %s %s", gb->asText().c_str(), typeid(g).name() );
979
980 SFCGAL::transform::RoundTransform roundT( scale );
981
982 try {
983 gb->accept( roundT );
984 }
985 catch ( std::exception& e ) {
986 SFCGAL_WARNING( "During round(A):" );
987 SFCGAL_WARNING( " with A: %s", ( ( const SFCGAL::Geometry* )( ga ) )->asText().c_str() );
988 SFCGAL_ERROR( "%s", e.what() );
989 return 0;
990 }
991
992 // SFCGAL_WARNING( "processed geom: %s", gb->asText().c_str() );
993 return gb;
994 }
995
sfcgal_geometry_minkowski_sum(const sfcgal_geometry_t * ga,const sfcgal_geometry_t * gb)996 extern "C" sfcgal_geometry_t* sfcgal_geometry_minkowski_sum( const sfcgal_geometry_t* ga, const sfcgal_geometry_t* gb )
997 {
998 const SFCGAL::Geometry* g1 = reinterpret_cast<const SFCGAL::Geometry*>( ga );
999 const SFCGAL::Geometry* g2 = reinterpret_cast<const SFCGAL::Geometry*>( gb );
1000
1001 if ( g2->geometryTypeId() != SFCGAL::TYPE_POLYGON ) {
1002 SFCGAL_ERROR( "minkowski_sum(): the second argument must be a polygon" );
1003 return 0;
1004 }
1005
1006 std::unique_ptr<SFCGAL::Geometry> sum;
1007
1008 try {
1009 sum = SFCGAL::algorithm::minkowskiSum( *g1, g2->as<const SFCGAL::Polygon>() );
1010 }
1011 catch ( std::exception& e ) {
1012 SFCGAL_WARNING( "During minkowski_sum(A,B):" );
1013 SFCGAL_WARNING( " with A: %s", ( ( const SFCGAL::Geometry* )( ga ) )->asText().c_str() );
1014 SFCGAL_WARNING( " and B: %s", ( ( const SFCGAL::Geometry* )( gb ) )->asText().c_str() );
1015 SFCGAL_ERROR( "%s", e.what() );
1016 return 0;
1017 }
1018
1019 return sum.release();
1020 }
1021
sfcgal_geometry_offset_polygon(const sfcgal_geometry_t * ga,double offset)1022 extern "C" sfcgal_geometry_t* sfcgal_geometry_offset_polygon( const sfcgal_geometry_t* ga, double offset )
1023 {
1024 const SFCGAL::Geometry* g1 = reinterpret_cast<const SFCGAL::Geometry*>( ga );
1025 std::unique_ptr<SFCGAL::MultiPolygon> mp;
1026
1027 try {
1028 mp = SFCGAL::algorithm::offset( *g1, offset );
1029 }
1030 catch ( std::exception& e ) {
1031 SFCGAL_WARNING( "During offset(A,%g):", offset );
1032 SFCGAL_WARNING( " with A: %s", ( ( const SFCGAL::Geometry* )( ga ) )->asText().c_str() );
1033 SFCGAL_ERROR( "%s", e.what() );
1034 return 0;
1035 }
1036
1037 return mp.release();
1038 }
1039
sfcgal_geometry_force_valid(sfcgal_geometry_t * geom,int valid)1040 extern "C" void sfcgal_geometry_force_valid( sfcgal_geometry_t* geom, int valid )
1041 {
1042 SFCGAL::Geometry* g1 = reinterpret_cast<SFCGAL::Geometry*>( geom );
1043 SFCGAL::algorithm::propagateValidityFlag( *g1, valid != 0 );
1044 }
1045
sfcgal_geometry_has_validity_flag(const sfcgal_geometry_t * geom)1046 extern "C" int sfcgal_geometry_has_validity_flag( const sfcgal_geometry_t* geom )
1047 {
1048 const SFCGAL::Geometry* g1 = reinterpret_cast<const SFCGAL::Geometry*>( geom );
1049 return g1->hasValidityFlag() ? 1 : 0;
1050 }
1051
sfcgal_geometry_straight_skeleton_distance_in_m(const sfcgal_geometry_t * geom)1052 extern "C" sfcgal_geometry_t* sfcgal_geometry_straight_skeleton_distance_in_m( const sfcgal_geometry_t* geom )
1053 {
1054 const SFCGAL::Geometry* g1 = reinterpret_cast<const SFCGAL::Geometry*>( geom );
1055 std::unique_ptr<SFCGAL::MultiLineString> mls;
1056
1057 try {
1058 mls = SFCGAL::algorithm::straightSkeleton( *g1, /*autoOrientation*/ true, /*innerOnly*/ false, /*outputDistanceInM*/ true );
1059 }
1060 catch ( std::exception& e ) {
1061 SFCGAL_WARNING( "During straight_skeleton_distance_in_m(A):" );
1062 SFCGAL_WARNING( " with A: %s", ( ( const SFCGAL::Geometry* )( geom ) )->asText().c_str() );
1063 SFCGAL_ERROR( "%s", e.what() );
1064 return 0;
1065 }
1066
1067 return mls.release();
1068 }
1069
sfcgal_geometry_line_sub_string(const sfcgal_geometry_t * geom,double start,double end)1070 extern "C" sfcgal_geometry_t* sfcgal_geometry_line_sub_string( const sfcgal_geometry_t* geom, double start, double end )
1071 {
1072 const SFCGAL::Geometry* g1 = reinterpret_cast<const SFCGAL::Geometry*>( geom );
1073 if ( g1->geometryTypeId() != SFCGAL::TYPE_LINESTRING ) {
1074 SFCGAL_ERROR( "line_sub_string(): the first argument must be a lineString" );
1075 return 0;
1076 }
1077 std::unique_ptr<SFCGAL::LineString> ls;
1078 try {
1079 ls = SFCGAL::algorithm::lineSubstring( g1->as<const SFCGAL::LineString>(), start, end );
1080 }
1081 catch ( std::exception& e ) {
1082 SFCGAL_WARNING( "During line_sub_string(A, %g, %g):", start, end );
1083 SFCGAL_WARNING( " with A: %s", ( ( const SFCGAL::Geometry* )( geom ) )->asText().c_str() );
1084 SFCGAL_ERROR( "%s", e.what() );
1085 return 0;
1086 }
1087
1088 return ls.release();
1089 }
1090