diff --git a/src/capi/sfcgal_c.cpp b/src/capi/sfcgal_c.cpp index 350bbf4c..51466b3e 100644 --- a/src/capi/sfcgal_c.cpp +++ b/src/capi/sfcgal_c.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -1334,3 +1335,76 @@ sfcgal_optimal_convex_partition_2(const sfcgal_geometry_t *geom) return result.release(); } + + +extern "C" sfcgal_geometry_t * +sfcgal_visibility_point(const sfcgal_geometry_t *polygon, const sfcgal_geometry_t *point) +{ + + const auto *poly = reinterpret_cast(polygon); + const auto *pt = reinterpret_cast(point); + std::unique_ptr result; + + if (poly->geometryTypeId() != SFCGAL::TYPE_POLYGON) { + SFCGAL_ERROR("visibility() only applies to polygons"); + return result.release(); + } + + if (pt->geometryTypeId() != SFCGAL::TYPE_POINT) { + SFCGAL_ERROR("second argument must be a point"); + return result.release(); + } + + try { + result = SFCGAL::algorithm::visibility( + poly->as(), pt->as()); + } catch (std::exception &e) { + SFCGAL_WARNING("During visibility(A, B) :"); + SFCGAL_WARNING(" with A: %s", + poly->asText().c_str()); + SFCGAL_WARNING(" and B: %s", + pt->asText().c_str()); + SFCGAL_ERROR("%s", e.what()); + return result.release(); + } + + return result.release(); +} + +extern "C" sfcgal_geometry_t * +sfcgal_visibility_segment(const sfcgal_geometry_t *polygon, const sfcgal_geometry_t *pointA, const sfcgal_geometry_t *pointB) +{ + const auto *poly = reinterpret_cast(polygon); + const auto *ptA = reinterpret_cast(pointA); + const auto *ptB = reinterpret_cast(pointB); + std::unique_ptr result; + + if (poly->geometryTypeId() != SFCGAL::TYPE_POLYGON) { + SFCGAL_ERROR("visibility() only applies to polygons"); + return result.release(); + } + + if ( (ptA->geometryTypeId() != SFCGAL::TYPE_POINT) || (ptB->geometryTypeId() != SFCGAL::TYPE_POINT) ) { + SFCGAL_ERROR("second and third argument must be a point"); + return result.release(); + } + + try { + result = SFCGAL::algorithm::visibility( + poly->as(), ptA->as(), ptB->as()); + } catch (std::exception &e) { + SFCGAL_WARNING("During visibility(A, B, C) :"); + SFCGAL_WARNING(" with A: %s", + poly->asText().c_str()); + SFCGAL_WARNING(" and B: %s", + ptA->asText().c_str()); + SFCGAL_WARNING(" and C: %s", + ptB->asText().c_str()); + SFCGAL_ERROR("%s", e.what()); + return result.release(); + } + + return result.release(); +} + + diff --git a/src/capi/sfcgal_c.h b/src/capi/sfcgal_c.h index 5d386425..b6f8c541 100644 --- a/src/capi/sfcgal_c.h +++ b/src/capi/sfcgal_c.h @@ -1081,6 +1081,31 @@ sfcgal_greene_approx_convex_partition_2(const sfcgal_geometry_t *geom); SFCGAL_API sfcgal_geometry_t * sfcgal_optimal_convex_partition_2(const sfcgal_geometry_t *geom); +/** + * Returns the visibility polygon of a Point inside a Polygon + * @param polygon input geometry + * @param point input geometry + * @ingroup capi + * @pre polygon is a valid geometry + * @pre point must be inside polygon or on the boundary + */ +SFCGAL_API sfcgal_geometry_t * +sfcgal_visibility_point(const sfcgal_geometry_t *polygon, const sfcgal_geometry_t *point); + +/** + * @brief build the visibility polygon of the segment [pointA ; pointB] on a + * Polygon + * @param polygon input geometry + * @param pointA input geometry + * @param pointB input geometry + * @ingroup public_api + * @pre polygon is a valid geometry + * @pre pointA and pointB must be vertices of poly, adjacents and respect the + * direction + */ +SFCGAL_API sfcgal_geometry_t * +sfcgal_visibility_segment(const sfcgal_geometry_t *polygon, const sfcgal_geometry_t *pointA, const sfcgal_geometry_t *pointB); + /*--------------------------------------------------------------------------------------* * * Error handling