Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'xs/src/libnest2d/libnest2d/boost_alg.hpp')
-rw-r--r--xs/src/libnest2d/libnest2d/boost_alg.hpp518
1 files changed, 518 insertions, 0 deletions
diff --git a/xs/src/libnest2d/libnest2d/boost_alg.hpp b/xs/src/libnest2d/libnest2d/boost_alg.hpp
new file mode 100644
index 000000000..bb0403b06
--- /dev/null
+++ b/xs/src/libnest2d/libnest2d/boost_alg.hpp
@@ -0,0 +1,518 @@
+#ifndef BOOST_ALG_HPP
+#define BOOST_ALG_HPP
+
+#ifndef DISABLE_BOOST_SERIALIZE
+ #include <sstream>
+#endif
+
+#ifdef __clang__
+#undef _MSC_EXTENSIONS
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4244)
+#pragma warning(disable: 4267)
+#endif
+#include <boost/geometry.hpp>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+// this should be removed to not confuse the compiler
+// #include <libnest2d.h>
+
+namespace bp2d {
+
+using libnest2d::TCoord;
+using libnest2d::PointImpl;
+using Coord = TCoord<PointImpl>;
+using libnest2d::PolygonImpl;
+using libnest2d::PathImpl;
+using libnest2d::Orientation;
+using libnest2d::OrientationType;
+using libnest2d::getX;
+using libnest2d::getY;
+using libnest2d::setX;
+using libnest2d::setY;
+using Box = libnest2d::_Box<PointImpl>;
+using Segment = libnest2d::_Segment<PointImpl>;
+using Shapes = libnest2d::nfp::Shapes<PolygonImpl>;
+
+}
+
+/**
+ * We have to make all the libnest2d geometry types available to boost. The real
+ * models of the geometries remain the same if a conforming model for libnest2d
+ * was defined by the library client. Boost is used only as an optional
+ * implementer of some algorithms that can be implemented by the model itself
+ * if a faster alternative exists.
+ *
+ * However, boost has its own type traits and we have to define the needed
+ * specializations to be able to use boost::geometry. This can be done with the
+ * already provided model.
+ */
+namespace boost {
+namespace geometry {
+namespace traits {
+
+/* ************************************************************************** */
+/* Point concept adaptaion ************************************************** */
+/* ************************************************************************** */
+
+template<> struct tag<bp2d::PointImpl> {
+ using type = point_tag;
+};
+
+template<> struct coordinate_type<bp2d::PointImpl> {
+ using type = bp2d::Coord;
+};
+
+template<> struct coordinate_system<bp2d::PointImpl> {
+ using type = cs::cartesian;
+};
+
+template<> struct dimension<bp2d::PointImpl>: boost::mpl::int_<2> {};
+
+template<>
+struct access<bp2d::PointImpl, 0 > {
+ static inline bp2d::Coord get(bp2d::PointImpl const& a) {
+ return libnest2d::getX(a);
+ }
+
+ static inline void set(bp2d::PointImpl& a,
+ bp2d::Coord const& value) {
+ libnest2d::setX(a, value);
+ }
+};
+
+template<>
+struct access<bp2d::PointImpl, 1 > {
+ static inline bp2d::Coord get(bp2d::PointImpl const& a) {
+ return libnest2d::getY(a);
+ }
+
+ static inline void set(bp2d::PointImpl& a,
+ bp2d::Coord const& value) {
+ libnest2d::setY(a, value);
+ }
+};
+
+
+/* ************************************************************************** */
+/* Box concept adaptaion **************************************************** */
+/* ************************************************************************** */
+
+template<> struct tag<bp2d::Box> {
+ using type = box_tag;
+};
+
+template<> struct point_type<bp2d::Box> {
+ using type = bp2d::PointImpl;
+};
+
+template<> struct indexed_access<bp2d::Box, min_corner, 0> {
+ static inline bp2d::Coord get(bp2d::Box const& box) {
+ return bp2d::getX(box.minCorner());
+ }
+ static inline void set(bp2d::Box &box, bp2d::Coord const& coord) {
+ bp2d::setX(box.minCorner(), coord);
+ }
+};
+
+template<> struct indexed_access<bp2d::Box, min_corner, 1> {
+ static inline bp2d::Coord get(bp2d::Box const& box) {
+ return bp2d::getY(box.minCorner());
+ }
+ static inline void set(bp2d::Box &box, bp2d::Coord const& coord) {
+ bp2d::setY(box.minCorner(), coord);
+ }
+};
+
+template<> struct indexed_access<bp2d::Box, max_corner, 0> {
+ static inline bp2d::Coord get(bp2d::Box const& box) {
+ return bp2d::getX(box.maxCorner());
+ }
+ static inline void set(bp2d::Box &box, bp2d::Coord const& coord) {
+ bp2d::setX(box.maxCorner(), coord);
+ }
+};
+
+template<> struct indexed_access<bp2d::Box, max_corner, 1> {
+ static inline bp2d::Coord get(bp2d::Box const& box) {
+ return bp2d::getY(box.maxCorner());
+ }
+ static inline void set(bp2d::Box &box, bp2d::Coord const& coord) {
+ bp2d::setY(box.maxCorner(), coord);
+ }
+};
+
+/* ************************************************************************** */
+/* Segment concept adaptaion ************************************************ */
+/* ************************************************************************** */
+
+template<> struct tag<bp2d::Segment> {
+ using type = segment_tag;
+};
+
+template<> struct point_type<bp2d::Segment> {
+ using type = bp2d::PointImpl;
+};
+
+template<> struct indexed_access<bp2d::Segment, 0, 0> {
+ static inline bp2d::Coord get(bp2d::Segment const& seg) {
+ return bp2d::getX(seg.first());
+ }
+ static inline void set(bp2d::Segment &seg, bp2d::Coord const& coord) {
+ auto p = seg.first(); bp2d::setX(p, coord); seg.first(p);
+ }
+};
+
+template<> struct indexed_access<bp2d::Segment, 0, 1> {
+ static inline bp2d::Coord get(bp2d::Segment const& seg) {
+ return bp2d::getY(seg.first());
+ }
+ static inline void set(bp2d::Segment &seg, bp2d::Coord const& coord) {
+ auto p = seg.first(); bp2d::setY(p, coord); seg.first(p);
+ }
+};
+
+template<> struct indexed_access<bp2d::Segment, 1, 0> {
+ static inline bp2d::Coord get(bp2d::Segment const& seg) {
+ return bp2d::getX(seg.second());
+ }
+ static inline void set(bp2d::Segment &seg, bp2d::Coord const& coord) {
+ auto p = seg.second(); bp2d::setX(p, coord); seg.second(p);
+ }
+};
+
+template<> struct indexed_access<bp2d::Segment, 1, 1> {
+ static inline bp2d::Coord get(bp2d::Segment const& seg) {
+ return bp2d::getY(seg.second());
+ }
+ static inline void set(bp2d::Segment &seg, bp2d::Coord const& coord) {
+ auto p = seg.second(); bp2d::setY(p, coord); seg.second(p);
+ }
+};
+
+
+/* ************************************************************************** */
+/* Polygon concept adaptation *********************************************** */
+/* ************************************************************************** */
+
+// Connversion between libnest2d::Orientation and order_selector ///////////////
+
+template<bp2d::Orientation> struct ToBoostOrienation {};
+
+template<>
+struct ToBoostOrienation<bp2d::Orientation::CLOCKWISE> {
+ static const order_selector Value = clockwise;
+};
+
+template<>
+struct ToBoostOrienation<bp2d::Orientation::COUNTER_CLOCKWISE> {
+ static const order_selector Value = counterclockwise;
+};
+
+static const bp2d::Orientation RealOrientation =
+ bp2d::OrientationType<bp2d::PolygonImpl>::Value;
+
+// Ring implementation /////////////////////////////////////////////////////////
+
+// Boost would refer to ClipperLib::Path (alias bp2d::PolygonImpl) as a ring
+template<> struct tag<bp2d::PathImpl> {
+ using type = ring_tag;
+};
+
+template<> struct point_order<bp2d::PathImpl> {
+ static const order_selector value =
+ ToBoostOrienation<RealOrientation>::Value;
+};
+
+// All our Paths should be closed for the bin packing application
+template<> struct closure<bp2d::PathImpl> {
+ static const closure_selector value = closed;
+};
+
+// Polygon implementation //////////////////////////////////////////////////////
+
+template<> struct tag<bp2d::PolygonImpl> {
+ using type = polygon_tag;
+};
+
+template<> struct exterior_ring<bp2d::PolygonImpl> {
+ static inline bp2d::PathImpl& get(bp2d::PolygonImpl& p) {
+ return libnest2d::shapelike::getContour(p);
+ }
+
+ static inline bp2d::PathImpl const& get(bp2d::PolygonImpl const& p) {
+ return libnest2d::shapelike::getContour(p);
+ }
+};
+
+template<> struct ring_const_type<bp2d::PolygonImpl> {
+ using type = const bp2d::PathImpl&;
+};
+
+template<> struct ring_mutable_type<bp2d::PolygonImpl> {
+ using type = bp2d::PathImpl&;
+};
+
+template<> struct interior_const_type<bp2d::PolygonImpl> {
+ using type = const libnest2d::THolesContainer<bp2d::PolygonImpl>&;
+};
+
+template<> struct interior_mutable_type<bp2d::PolygonImpl> {
+ using type = libnest2d::THolesContainer<bp2d::PolygonImpl>&;
+};
+
+template<>
+struct interior_rings<bp2d::PolygonImpl> {
+
+ static inline libnest2d::THolesContainer<bp2d::PolygonImpl>& get(
+ bp2d::PolygonImpl& p)
+ {
+ return libnest2d::shapelike::holes(p);
+ }
+
+ static inline const libnest2d::THolesContainer<bp2d::PolygonImpl>& get(
+ bp2d::PolygonImpl const& p)
+ {
+ return libnest2d::shapelike::holes(p);
+ }
+};
+
+/* ************************************************************************** */
+/* MultiPolygon concept adaptation ****************************************** */
+/* ************************************************************************** */
+
+template<> struct tag<bp2d::Shapes> {
+ using type = multi_polygon_tag;
+};
+
+} // traits
+} // geometry
+
+// This is an addition to the ring implementation of Polygon concept
+template<>
+struct range_value<bp2d::PathImpl> {
+ using type = bp2d::PointImpl;
+};
+
+template<>
+struct range_value<bp2d::Shapes> {
+ using type = bp2d::PolygonImpl;
+};
+
+} // boost
+
+/* ************************************************************************** */
+/* Algorithms *************************************************************** */
+/* ************************************************************************** */
+
+namespace libnest2d { // Now the algorithms that boost can provide...
+
+namespace pointlike {
+template<>
+inline double distance(const PointImpl& p1, const PointImpl& p2 )
+{
+ return boost::geometry::distance(p1, p2);
+}
+
+template<>
+inline double distance(const PointImpl& p, const bp2d::Segment& seg )
+{
+ return boost::geometry::distance(p, seg);
+}
+}
+
+namespace shapelike {
+// Tell libnest2d how to make string out of a ClipperPolygon object
+template<>
+inline bool intersects(const PathImpl& sh1, const PathImpl& sh2)
+{
+ return boost::geometry::intersects(sh1, sh2);
+}
+
+// Tell libnest2d how to make string out of a ClipperPolygon object
+template<>
+inline bool intersects(const PolygonImpl& sh1, const PolygonImpl& sh2)
+{
+ return boost::geometry::intersects(sh1, sh2);
+}
+
+// Tell libnest2d how to make string out of a ClipperPolygon object
+template<>
+inline bool intersects(const bp2d::Segment& s1, const bp2d::Segment& s2)
+{
+ return boost::geometry::intersects(s1, s2);
+}
+
+#ifndef DISABLE_BOOST_AREA
+template<>
+inline double area(const PolygonImpl& shape, const PolygonTag&)
+{
+ return boost::geometry::area(shape);
+}
+#endif
+
+template<>
+inline bool isInside(const PointImpl& point, const PolygonImpl& shape)
+{
+ return boost::geometry::within(point, shape);
+}
+
+template<>
+inline bool isInside(const PolygonImpl& sh1, const PolygonImpl& sh2)
+{
+ return boost::geometry::within(sh1, sh2);
+}
+
+template<>
+inline bool touches(const PolygonImpl& sh1, const PolygonImpl& sh2)
+{
+ return boost::geometry::touches(sh1, sh2);
+}
+
+template<>
+inline bool touches( const PointImpl& point, const PolygonImpl& shape)
+{
+ return boost::geometry::touches(point, shape);
+}
+
+#ifndef DISABLE_BOOST_BOUNDING_BOX
+template<>
+inline bp2d::Box boundingBox(const PolygonImpl& sh, const PolygonTag&)
+{
+ bp2d::Box b;
+ boost::geometry::envelope(sh, b);
+ return b;
+}
+
+template<>
+inline bp2d::Box boundingBox<bp2d::Shapes>(const bp2d::Shapes& shapes,
+ const MultiPolygonTag&)
+{
+ bp2d::Box b;
+ boost::geometry::envelope(shapes, b);
+ return b;
+}
+#endif
+
+#ifndef DISABLE_BOOST_CONVEX_HULL
+template<>
+inline PolygonImpl convexHull(const PolygonImpl& sh, const PolygonTag&)
+{
+ PolygonImpl ret;
+ boost::geometry::convex_hull(sh, ret);
+ return ret;
+}
+
+template<>
+inline PolygonImpl convexHull(const TMultiShape<PolygonImpl>& shapes,
+ const MultiPolygonTag&)
+{
+ PolygonImpl ret;
+ boost::geometry::convex_hull(shapes, ret);
+ return ret;
+}
+#endif
+
+#ifndef DISABLE_BOOST_OFFSET
+template<>
+inline void offset(PolygonImpl& sh, bp2d::Coord distance)
+{
+ PolygonImpl cpy = sh;
+ boost::geometry::buffer(cpy, sh, distance);
+}
+#endif
+
+#ifndef DISABLE_BOOST_SERIALIZE
+template<> inline std::string serialize<libnest2d::Formats::SVG>(
+ const PolygonImpl& sh, double scale)
+{
+ std::stringstream ss;
+ std::string style = "fill: none; stroke: black; stroke-width: 1px;";
+
+ using namespace boost::geometry;
+ using Pointf = model::point<double, 2, cs::cartesian>;
+ using Polygonf = model::polygon<Pointf>;
+
+ Polygonf::ring_type ring;
+ Polygonf::inner_container_type holes;
+ ring.reserve(shapelike::contourVertexCount(sh));
+
+ for(auto it = shapelike::cbegin(sh); it != shapelike::cend(sh); it++) {
+ auto& v = *it;
+ ring.emplace_back(getX(v)*scale, getY(v)*scale);
+ };
+
+ auto H = shapelike::holes(sh);
+ for(PathImpl& h : H ) {
+ Polygonf::ring_type hf;
+ for(auto it = h.begin(); it != h.end(); it++) {
+ auto& v = *it;
+ hf.emplace_back(getX(v)*scale, getY(v)*scale);
+ };
+ holes.push_back(hf);
+ }
+
+ Polygonf poly;
+ poly.outer() = ring;
+ poly.inners() = holes;
+ auto svg_data = boost::geometry::svg(poly, style);
+
+ ss << svg_data << std::endl;
+
+ return ss.str();
+}
+#endif
+
+#ifndef DISABLE_BOOST_UNSERIALIZE
+template<>
+inline void unserialize<libnest2d::Formats::SVG>(
+ PolygonImpl& sh,
+ const std::string& str)
+{
+}
+#endif
+
+template<> inline std::pair<bool, std::string> isValid(const PolygonImpl& sh)
+{
+ std::string message;
+ bool ret = boost::geometry::is_valid(sh, message);
+
+ return {ret, message};
+}
+}
+
+namespace nfp {
+
+#ifndef DISABLE_BOOST_NFP_MERGE
+
+// Warning: I could not get boost union_ to work. Geometries will overlap.
+template<>
+inline bp2d::Shapes nfp::merge(const bp2d::Shapes& shapes,
+ const PolygonImpl& sh)
+{
+ bp2d::Shapes retv;
+ boost::geometry::union_(shapes, sh, retv);
+ return retv;
+}
+
+template<>
+inline bp2d::Shapes nfp::merge(const bp2d::Shapes& shapes)
+{
+ bp2d::Shapes retv;
+ boost::geometry::union_(shapes, shapes.back(), retv);
+ return retv;
+}
+#endif
+
+}
+
+
+}
+
+
+
+#endif // BOOST_ALG_HPP