// Begin License: // Copyright (C) 2006-2008 Tobias Sargeant (tobias.sargeant@gmail.com). // All rights reserved. // // This file is part of the Carve CSG Library (http://carve-csg.com/) // // This file may be used under the terms of the GNU General Public // License version 2.0 as published by the Free Software Foundation // and appearing in the file LICENSE.GPL2 included in the packaging of // this file. // // This file is provided "AS IS" with NO WARRANTY OF ANY KIND, // INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE. // End: #pragma once #include #include #include #include #include #include #include #include #include #include #include namespace carve { namespace csg { class VertexPool { const static unsigned blocksize = 1024; typedef std::list > pool_t; pool_t pool; public: void reset(); carve::poly::Polyhedron::vertex_t *get(const carve::geom3d::Vector &v = carve::geom3d::Vector::ZERO()); bool inPool(const carve::poly::Polyhedron::vertex_t *v) const; VertexPool(); ~VertexPool(); }; namespace detail { struct Data; class LoopEdges; } /** * \class CSG * \brief The class responsible for the computation of CSG operations. * */ class CSG { private: public: struct Hook { /** * \class Hook * \brief Provides API access to intermediate steps in CSG calculation. * */ virtual void intersectionVertex(const carve::poly::Polyhedron::vertex_t *vertex, const IObjPairSet &intersections) { } virtual void processOutputFace(std::vector &faces, const carve::poly::Polyhedron::face_t *orig_face, bool flipped) { } virtual void resultFace(const carve::poly::Polyhedron::face_t *new_face, const carve::poly::Polyhedron::face_t *orig_face, bool flipped) { } virtual ~Hook() { } }; /** * \class Hooks * \brief Management of API hooks. * */ class Hooks { public: enum { RESULT_FACE_HOOK = 0, PROCESS_OUTPUT_FACE_HOOK = 1, INTERSECTION_VERTEX_HOOK = 2, HOOK_MAX = 3, RESULT_FACE_BIT = 0x0001, PROCESS_OUTPUT_FACE_BIT = 0x0002, INTERSECTION_VERTEX_BIT = 0x0004 }; std::vector > hooks; bool hasHook(unsigned hook_num); void intersectionVertex(const carve::poly::Polyhedron::vertex_t *vertex, const IObjPairSet &intersections); void processOutputFace(std::vector &faces, const carve::poly::Polyhedron::face_t *orig_face, bool flipped); void resultFace(const carve::poly::Polyhedron::face_t *new_face, const carve::poly::Polyhedron::face_t *orig_face, bool flipped); void registerHook(Hook *hook, unsigned hook_bits); void unregisterHook(Hook *hook); void reset(); Hooks(); ~Hooks(); }; /** * \class Collector * \brief Base class for objects responsible for selecting result from which form the result polyhedron. * */ class Collector { Collector(const Collector &); Collector &operator=(const Collector &); protected: public: virtual void collect(FaceLoopGroup *group, CSG::Hooks &) =0; virtual carve::poly::Polyhedron *done(CSG::Hooks &) =0; Collector() {} virtual ~Collector() {} }; private: /// The computed intersection data. Intersections intersections; /// A map from intersection point to a set of intersections /// represented by pairs of intersection objects. VertexIntersections vertex_intersections; /// A pool from which temporary vertices are allocated. Also /// provides testing for pool membership. VertexPool vertex_pool; void init(); void makeVertexIntersections(); void groupIntersections(); void determinePotentiallyInteractingOctreeNodes( const carve::poly::Polyhedron *a, const carve::poly::Polyhedron *b); void generateVertexEdgeIntersections( const carve::poly::Polyhedron *a, const carve::poly::Polyhedron *b); /** * \brief Generate vertex-vertex, vertex-edge and edge-edge intersections between poly \a a and poly \a b. * * @param a Polyhedron a. * @param b Polyhedron b. */ void generateEdgeEdgeIntersections( const carve::poly::Polyhedron *a, const carve::poly::Polyhedron *b); /** * \brief Generate vertex-face and edge-face intersections between poly \a a and poly \a b. * * @param a Polyhedron a. * @param b Polyhedron b. */ void generateEdgeFaceIntersections( const carve::poly::Polyhedron *a, const carve::poly::Polyhedron *b); /** * \brief Compute all points of intersection between poly \a a and poly \a b * * @param a Polyhedron a. * @param b Polyhedron b. */ void generateIntersections( const carve::poly::Polyhedron *a, const carve::poly::Polyhedron *b); /** * \brief Generate tables of intersecting pairs of faces. * * @param[out] data Internal data-structure holding intersection info. */ void intersectingFacePairs(detail::Data &data); /** * \brief Divide edges in \a edges that are intersected by polyhedron \a poly * * @param edges The edges to divide. * @param[in] poly The polyhedron to divide against. * @param[in,out] data Intersection information. */ void divideEdges( const std::vector &edges, const carve::poly::Polyhedron *poly, detail::Data &data); void divideIntersectedEdges(detail::Data &data); /** * \brief From the intersection points of pairs of intersecting faces, compute intersection edges. * * @param[out] eclass Classification information about created edges. * @param[in,out] data Intersection information. */ void makeFaceEdges( EdgeClassification &eclass, detail::Data &data); friend void classifyEasyFaces( FaceLoopList &face_loops, VertexClassification &vclass, const carve::poly::Polyhedron *other_poly, int other_poly_num, CSG &csg, CSG::Collector &collector); size_t generateFaceLoops( const carve::poly::Polyhedron *poly, const detail::Data &data, FaceLoopList &face_loops_out); // intersect_group.cpp /** * \brief Build a loop edge mapping from a list of face loops. * * @param[in] loops A list of face loops. * @param[in] edge_count A hint as to the number of edges in \a loops. * @param[out] edge_map The calculated map of edges to loops. */ void makeEdgeMap( const FaceLoopList &loops, size_t edge_count, detail::LoopEdges &edge_map); /** * \brief Divide a list of face loops into groups that are connected by at least one edge not present in \a no_cross. * * @param[in,out] face_loops The list of loops (will be emptied as a side effect) * @param[in] loop_edges A loop edge map used for traversing connected loops. * @param[in] no_cross A set of edges not to cross. * @param[out] out_loops A list of grouped face loops. */ void groupFaceLoops( FaceLoopList &face_loops, const detail::LoopEdges &loop_edges, const V2Set &no_cross, FLGroupList &out_loops); /** * \brief Find the set of edges shared between two edge maps. * * @param[in] edge_map_a The first edge map. * @param[in] edge_map_b The second edge map. * @param[out] shared_edges The resulting set of common edges. */ void findSharedEdges( const detail::LoopEdges &edge_map_a, const detail::LoopEdges &edge_map_b, V2Set &shared_edges); // intersect_classify_edge.cpp /** * * * @param shared_edges * @param vclass * @param poly_a * @param a_loops_grouped * @param a_edge_map * @param poly_b * @param b_loops_grouped * @param b_edge_map * @param collector */ void classifyFaceGroupsEdge( const V2Set &shared_edges, VertexClassification &vclass, const carve::poly::Polyhedron *poly_a, FLGroupList &a_loops_grouped, const detail::LoopEdges &a_edge_map, const carve::poly::Polyhedron *poly_b, FLGroupList &b_loops_grouped, const detail::LoopEdges &b_edge_map, CSG::Collector &collector); // intersect_classify_group.cpp /** * * * @param shared_edges * @param vclass * @param poly_a * @param a_loops_grouped * @param a_edge_map * @param poly_b * @param b_loops_grouped * @param b_edge_map * @param collector */ void classifyFaceGroups( const V2Set &shared_edges, VertexClassification &vclass, const carve::poly::Polyhedron *poly_a, FLGroupList &a_loops_grouped, const detail::LoopEdges &a_edge_map, const carve::poly::Polyhedron *poly_b, FLGroupList &b_loops_grouped, const detail::LoopEdges &b_edge_map, CSG::Collector &collector); // intersect_half_classify_group.cpp /** * * * @param shared_edges * @param vclass * @param poly_a * @param a_loops_grouped * @param a_edge_map * @param poly_b * @param b_loops_grouped * @param b_edge_map * @param FaceClass * @param b_out */ void halfClassifyFaceGroups( const V2Set &shared_edges, VertexClassification &vclass, const carve::poly::Polyhedron *poly_a, FLGroupList &a_loops_grouped, const detail::LoopEdges &a_edge_map, const carve::poly::Polyhedron *poly_b, FLGroupList &b_loops_grouped, const detail::LoopEdges &b_edge_map, std::list > &b_out); // intersect.cpp /** * \brief The main calculation method for CSG. * * @param[in] a Polyhedron a * @param[in] b Polyhedron b * @param[out] vclass * @param[out] eclass * @param[out] a_face_loops * @param[out] b_face_loops * @param[out] a_edge_count * @param[out] b_edge_count */ void calc( const carve::poly::Polyhedron *a, const carve::poly::Polyhedron *b, VertexClassification &vclass, EdgeClassification &eclass, FaceLoopList &a_face_loops, FaceLoopList &b_face_loops, size_t &a_edge_count, size_t &b_edge_count); public: /** * \enum OP * \brief Enumeration of the supported CSG operations. */ enum OP { UNION, /**< in a or b. */ INTERSECTION, /**< in a and b. */ A_MINUS_B, /**< in a, but not b. */ B_MINUS_A, /**< in b, but not a. */ SYMMETRIC_DIFFERENCE, /**< in a or b, but not both. */ ALL /**< all split faces from a and b */ }; /** * \enum CLASSIFY_TYPE * \brief The type of classification algorithm to use. */ enum CLASSIFY_TYPE { CLASSIFY_NORMAL, /**< Normal (group) classifier. */ CLASSIFY_EDGE /**< Edge classifier. */ }; CSG::Hooks hooks; /**< The manager for calculation hooks. */ CSG(); ~CSG(); /** * \brief Compute a CSG operation between two polyhedra, \a a and \a b. * * @param a Polyhedron a * @param b Polyhedron b * @param collector The collector (determines the CSG operation performed) * @param shared_edges A pointer to a set that will be populated with shared edges (if not NULL). * @param classify_type The type of classifier to use. * * @return */ carve::poly::Polyhedron *compute( const carve::poly::Polyhedron *a, const carve::poly::Polyhedron *b, CSG::Collector &collector, V2Set *shared_edges = NULL, CLASSIFY_TYPE classify_type = CLASSIFY_NORMAL); /** * \brief Compute a CSG operation between two closed polyhedra, \a a and \a b. * * @param a Polyhedron a * @param b Polyhedron b * @param op The CSG operation (A collector is created automatically). * @param shared_edges A pointer to a set that will be populated with shared edges (if not NULL). * @param classify_type The type of classifier to use. * * @return */ carve::poly::Polyhedron *compute( const carve::poly::Polyhedron *a, const carve::poly::Polyhedron *b, OP op, V2Set *shared_edges = NULL, CLASSIFY_TYPE classify_type = CLASSIFY_NORMAL); void slice( const carve::poly::Polyhedron *a, const carve::poly::Polyhedron *b, std::list &a_sliced, std::list &b_sliced, V2Set *shared_edges = NULL); bool sliceAndClassify( const carve::poly::Polyhedron *closed, const carve::poly::Polyhedron *open, std::list > &result, V2Set *shared_edges = NULL); }; } }