/******************************************************************************** * * * This file is part of IfcOpenShell. * * * * IfcOpenShell is free software: you can redistribute it and/or modify * * it under the terms of the Lesser GNU General Public License as published by * * the Free Software Foundation, either version 3.0 of the License, or * * (at your option) any later version. * * * * IfcOpenShell is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * Lesser GNU General Public License for more details. * * * * You should have received a copy of the Lesser GNU General Public License * * along with this program. If not, see . * * * ********************************************************************************/ #ifndef IFCGEOM_H #define IFCGEOM_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../../../ifcgeom/AbstractKernel.h" #include "../../../ifcgeom/IfcGeomElement.h" #include "../../../ifcgeom/IfcGeomRepresentation.h" #include "../../../ifcgeom/ConversionResult.h" #include "../../../ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h" #include "../../../ifcgeom/kernels/ifc_geomlibrary_api.h" #include "../../../ifcgeom/taxonomy.h" #include "../../../ifcgeom/ConversionSettings.h" namespace { template bool handle_occt_exception(Fn&& fn) { try { return std::forward(fn)(); } catch (const Standard_Failure& e) { if (e.GetMessageString() && strlen(e.GetMessageString())) { throw std::runtime_error(e.GetMessageString()); } else { throw std::runtime_error("Unknown error creating geometry"); } } } } namespace IfcGeom { class IFC_GEOMLIBRARY_API OpenCascadeKernel : public ifcopenshell::geometry::kernels::AbstractKernel { private: /* faceset_helper traverses the forward instance references of IfcConnectedFaceSet and then provides a mapping M of (IfcCartesianPoint, IfcCartesianPoint) -> TopoDS_Edge, where M(a, b) is a partner of M(b, a), ie share the same underlying edge but with orientation reversed. This then later speeds op the process of creating a manifold Shell / Solid from this set of faces. Only IfcPolyLoop instances are used. Points within the tolerance threshiold are merged, so consider points a, b, c, distance(a, b) < eps then M(a, b) = Null, M(a, b) = M(a, c). */ class faceset_helper { private: OpenCascadeKernel* kernel_; std::set duplicates_; std::map vertex_mapping_; std::map, TopoDS_Edge> edges_; double eps_; bool non_manifold_; void loop_(const ifcopenshell::geometry::taxonomy::loop::ptr ps, const std::function& callback); public: faceset_helper(OpenCascadeKernel* kernel, const ifcopenshell::geometry::taxonomy::shell::ptr l); ~faceset_helper(); bool non_manifold() const { return non_manifold_; } bool& non_manifold() { return non_manifold_; } double epsilon() const { return eps_; } bool edge(int A, int B, TopoDS_Edge& e); bool wire(const ifcopenshell::geometry::taxonomy::loop::ptr loop, TopoDS_Wire& wire); bool wires(const ifcopenshell::geometry::taxonomy::loop::ptr loop, TopTools_ListOfShape& wires); }; faceset_helper* faceset_helper_; double precision_; public: OpenCascadeKernel(const ifcopenshell::geometry::Settings& settings, Logger& logger = Logger::Root()) : AbstractKernel("opencascade", settings, logger) , faceset_helper_(nullptr) , precision_(settings.get().get()) {} virtual AbstractKernel* clone() const { return new OpenCascadeKernel(settings(), logger()); } virtual bool supports_boolean_operations() const { return true; } bool convert(const ifcopenshell::geometry::taxonomy::extrusion::ptr, TopoDS_Shape&); bool convert(const ifcopenshell::geometry::taxonomy::face::ptr, TopoDS_Shape&, bool reversed_surface = false); bool convert(const ifcopenshell::geometry::taxonomy::loop::ptr, TopoDS_Wire&); bool convert(const ifcopenshell::geometry::taxonomy::matrix4::ptr, gp_GTrsf&); bool convert(const ifcopenshell::geometry::taxonomy::shell::ptr, TopoDS_Shape&); bool convert(const ifcopenshell::geometry::taxonomy::solid::ptr, TopoDS_Shape&); bool convert(const ifcopenshell::geometry::taxonomy::loft::ptr, TopoDS_Shape&); bool convert(const ifcopenshell::geometry::taxonomy::bspline_surface::ptr bs, Handle(Geom_Surface) surf); bool convert(const ifcopenshell::geometry::taxonomy::sweep_along_curve::ptr, TopoDS_Shape&); virtual bool convert_impl(const ifcopenshell::geometry::taxonomy::edge::ptr, IfcGeom::ConversionResults&); virtual bool convert_impl(const ifcopenshell::geometry::taxonomy::loop::ptr, IfcGeom::ConversionResults&); virtual bool convert_impl(const ifcopenshell::geometry::taxonomy::face::ptr, IfcGeom::ConversionResults&); virtual bool convert_impl(const ifcopenshell::geometry::taxonomy::solid::ptr, IfcGeom::ConversionResults&); virtual bool convert_impl(const ifcopenshell::geometry::taxonomy::shell::ptr, IfcGeom::ConversionResults&); virtual bool convert_impl(const ifcopenshell::geometry::taxonomy::extrusion::ptr, IfcGeom::ConversionResults&); virtual bool convert_impl(const ifcopenshell::geometry::taxonomy::revolve::ptr, IfcGeom::ConversionResults&); virtual bool convert_impl(const ifcopenshell::geometry::taxonomy::boolean_result::ptr, IfcGeom::ConversionResults&); virtual bool convert_impl(const ifcopenshell::geometry::taxonomy::loft::ptr, IfcGeom::ConversionResults&); virtual bool convert_impl(const ifcopenshell::geometry::taxonomy::sweep_along_curve::ptr, IfcGeom::ConversionResults&); virtual bool convert_openings(const IfcUtil::IfcBaseEntity* entity, const std::vector>& openings, const IfcGeom::ConversionResults& entity_shapes, const ifcopenshell::geometry::taxonomy::matrix4& entity_trsf, IfcGeom::ConversionResults& cut_shapes); virtual bool unify_shapes(const IfcGeom::ConversionResults& input, IfcGeom::ConversionResults& output); typedef boost::variant curve_creation_visitor_result_type; curve_creation_visitor_result_type convert_curve(const ifcopenshell::geometry::taxonomy::ptr); Handle(Geom_Surface) convert_surface(const ifcopenshell::geometry::taxonomy::ptr); template static T convert_xyz(const U& u) { const auto& vs = u.ccomponents(); return T(vs(0), vs(1), vs(2)); } // @todo eliminate template static T convert_xyz2(const U& vs) { return T(vs(0), vs(1), vs(2)); } }; IfcUtil::IfcBaseClass* POSTFIX_SCHEMA(tesselate_)(const TopoDS_Shape& shape, double deflection); IfcUtil::IfcBaseClass* POSTFIX_SCHEMA(serialise_)(const TopoDS_Shape& shape, bool advanced); } #endif