// Copyright (c) 2006-2008 Fernando Luis Cacciola Carballal. All rights reserved. // // This file is part of CGAL (www.cgal.org). // // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // Author(s) : Fernando Cacciola // #ifndef CGAL_CREATE_OFFSET_POLYGONS_2_H #define CGAL_CREATE_OFFSET_POLYGONS_2_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace CGAL { namespace CGAL_SS_i { template std::shared_ptr< Straight_skeleton_2 > create_partial_interior_straight_skeleton_2 ( FT const& aMaxTime , PointIterator aOuterContour_VerticesBegin , PointIterator aOuterContour_VerticesEnd , HoleIterator aHolesBegin , HoleIterator aHolesEnd , K const& // aka 'SK' ) { CGAL_precondition( aMaxTime > static_cast(0) ) ; typedef Straight_skeleton_2 Ss ; typedef Straight_skeleton_builder_traits_2 SsBuilderTraits; typedef Straight_skeleton_builder_2 SsBuilder; typedef typename K::FT KFT ; typedef typename std::iterator_traits::value_type InputPoint ; typedef typename Kernel_traits::Kernel InputKernel ; Cartesian_converter conv ; typename InputKernel::FT lMaxTime = aMaxTime; std::optional lOptMaxTime(conv(lMaxTime)) ; SsBuilder ssb( lOptMaxTime ) ; ssb.enter_contour( aOuterContour_VerticesBegin, aOuterContour_VerticesEnd, conv ) ; for ( HoleIterator hi = aHolesBegin ; hi != aHolesEnd ; ++ hi ) ssb.enter_contour( CGAL_SS_i::vertices_begin(*hi), CGAL_SS_i::vertices_end(*hi), conv ) ; return ssb.construct_skeleton(); } template std::shared_ptr< Straight_skeleton_2 > create_partial_exterior_straight_skeleton_2 ( FT const& aMaxOffset , PointIterator aVerticesBegin , PointIterator aVerticesEnd , K const& k // aka 'SK' ) { CGAL_precondition( aMaxOffset > 0 ) ; typedef typename std::iterator_traits::value_type Point_2; typedef typename Kernel_traits::Kernel IK; typedef typename IK::FT IFT; std::shared_ptr > rSkeleton; // That's because we might not have FT == IK::FT (e.g. `double` and `Core`) // Note that we can also have IK != K (e.g. `Simple_cartesian` and `EPICK`) IFT lOffset = aMaxOffset; // @todo This likely should be done in the kernel K rather than the input kernel (i.e. the same // converter stuff that is done in `create_partial_exterior_straight_skeleton_2`?). std::optional margin = compute_outer_frame_margin(aVerticesBegin, aVerticesEnd, lOffset); if ( margin ) { const IFT lm = *margin; const Bbox_2 bbox = bbox_2(aVerticesBegin, aVerticesEnd); const IFT fxmin = IFT(bbox.xmin()) - lm ; const IFT fxmax = IFT(bbox.xmax()) + lm ; const IFT fymin = IFT(bbox.ymin()) - lm ; const IFT fymax = IFT(bbox.ymax()) + lm ; Point_2 frame[4] ; frame[0] = Point_2(fxmin,fymin) ; frame[1] = Point_2(fxmax,fymin) ; frame[2] = Point_2(fxmax,fymax) ; frame[3] = Point_2(fxmin,fymax) ; typedef std::vector Hole ; Hole lPoly(aVerticesBegin, aVerticesEnd); std::reverse(lPoly.begin(), lPoly.end()); std::vector holes ; holes.push_back(lPoly) ; rSkeleton = create_partial_interior_straight_skeleton_2(aMaxOffset, frame, frame+4, holes.begin(), holes.end(), k ) ; } return rSkeleton ; } // // Kernel != Skeleton::kernel. The skeleton is converted to Straight_skeleton_2 // template std::vector< std::shared_ptr > create_offset_polygons_2 ( FT const& aOffset, Skeleton const& aSs, K const& , Tag_false ) { static_assert(!(std::is_same::value)); typedef std::shared_ptr OutPolygonPtr ; typedef std::vector OutPolygonPtrVector ; typedef Straight_skeleton_2 OfSkeleton ; typedef Polygon_offset_builder_traits_2 OffsetBuilderTraits; typedef Polygon_offset_builder_2 OffsetBuilder; OutPolygonPtrVector rR ; std::shared_ptr lConvertedSs = convert_straight_skeleton_2(aSs); OffsetBuilder ob( *lConvertedSs ); ob.construct_offset_contours(aOffset, std::back_inserter(rR) ) ; return rR ; } // // Kernel == Skeleton::kernel, no conversion // template std::vector< std::shared_ptr > create_offset_polygons_2 ( FT const& aOffset, Skeleton const& aSs, K const& /*k*/, Tag_true ) { static_assert(!(std::is_same::value)); typedef std::shared_ptr OutPolygonPtr ; typedef std::vector OutPolygonPtrVector ; typedef Polygon_offset_builder_traits_2 OffsetBuilderTraits; typedef Polygon_offset_builder_2 OffsetBuilder; OffsetBuilder ob(aSs); typename K::FT lOffset = aOffset; OutPolygonPtrVector rR ; ob.construct_offset_contours(lOffset, std::back_inserter(rR) ) ; return rR ; } // Allow failure due to invalid straight skeletons to go through the users template Skeleton const& dereference ( std::shared_ptr const& ss ) { CGAL_precondition(ss.get() != 0); return *ss; } } // namespace CGAL_SS_i template std::vector > inline create_offset_polygons_2(const FT& aOffset, const Skeleton& aSs, const K& k = K()) { typename CGAL_SS_i::Is_same_type::type same_kernel; return CGAL_SS_i::create_offset_polygons_2(aOffset, aSs, k, same_kernel); } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// /// INTERIOR template std::vector > > inline create_interior_skeleton_and_offset_polygons_2(const FT& aOffset, const APolygon& aOuterBoundary, HoleIterator aHolesBegin, HoleIterator aHolesEnd, const OfK& ofk = OfK(), const SsK& ssk = SsK(), std::enable_if_t::value>* = 0) { using OutPolygon = CGAL_SS_i::Polygon_return_type; return create_offset_polygons_2( aOffset, CGAL_SS_i::dereference( CGAL_SS_i::create_partial_interior_straight_skeleton_2( aOffset, CGAL_SS_i::vertices_begin(aOuterBoundary), CGAL_SS_i::vertices_end (aOuterBoundary), aHolesBegin, aHolesEnd, ssk)), ofk); } // Overload where APolygon is a simple polygon (no holes) template std::vector > > inline create_interior_skeleton_and_offset_polygons_2(const FT& aOffset, const APolygon& aPoly, const OfK& ofk = OfK(), const SsK& ssk = SsK(), std::enable_if_t< ! CGAL_SS_i::has_Hole_const_iterator::value>* = nullptr) { using OutPolygon = CGAL_SS_i::Polygon_return_type; std::vector no_holes; return create_interior_skeleton_and_offset_polygons_2(aOffset, aPoly, no_holes.begin(), no_holes.end(), ofk, ssk); } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// /// EXTERIOR /*! create_exterior_skeleton_and_offset_polygons_2 (no sorting of the result) */ // Overload where Polygon actually is a simple polygon (no holes) template std::vector > > inline create_exterior_skeleton_and_offset_polygons_2(const FT& aOffset, const APolygon& aPoly, const OfK& ofk = OfK(), const SsK& ssk = SsK(), std::enable_if_t< ! CGAL_SS_i::has_Hole_const_iterator::value>* = nullptr) { using OutPolygon = CGAL_SS_i::Polygon_return_type; return create_offset_polygons_2( aOffset, CGAL_SS_i::dereference( CGAL_SS_i::create_partial_exterior_straight_skeleton_2( aOffset, CGAL_SS_i::vertices_begin(aPoly), CGAL_SS_i::vertices_end (aPoly), ssk)), ofk); } } // namespace CGAL #endif // CGAL_CREATE_OFFSET_POLYGONS_2_H