From 4d12bf7e8df4bd144526eeb5994802d308b40297 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Mon, 16 Jan 2017 14:04:31 +0100 Subject: [PATCH] Cgal kernel skeleton (#3) Cgal kernel skeleton --- src/ifcconvert/IfcConvert.cpp | 67 ++++--- src/ifcgeom/IfcGeomAbstractKernel.cpp | 3 +- src/ifcgeom/IfcGeomIterator.h | 20 +- src/ifcgeom/IfcGeomIteratorSettings.h | 1 + .../kernels/cgal/CgalConversionFunctions.cpp | 28 +++ .../kernels/cgal/CgalConversionResult.cpp | 6 + .../kernels/cgal/CgalConversionResult.h | 77 ++++++++ .../kernels/cgal/CgalEntityMapping.cpp | 100 ++++++++++ src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 35 ++++ .../cgal/CgalEntityMappingCreateCache.h | 6 + .../kernels/cgal/CgalEntityMappingCurve.h | 6 + .../cgal/CgalEntityMappingDeclaration.h | 10 + .../kernels/cgal/CgalEntityMappingDefine.h | 18 ++ .../kernels/cgal/CgalEntityMappingFace.h | 6 + .../cgal/CgalEntityMappingPurgeCache.h | 6 + .../kernels/cgal/CgalEntityMappingShape.h | 20 ++ .../kernels/cgal/CgalEntityMappingShapeType.h | 14 ++ .../kernels/cgal/CgalEntityMappingShapes.h | 13 ++ .../kernels/cgal/CgalEntityMappingUndefine.h | 18 ++ .../kernels/cgal/CgalEntityMappingWire.h | 6 + src/ifcgeom/kernels/cgal/CgalKernel.cpp | 171 ++++++++++++++++++ src/ifcgeom/kernels/cgal/CgalKernel.h | 93 ++++++++++ 22 files changed, 688 insertions(+), 36 deletions(-) create mode 100644 src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp create mode 100644 src/ifcgeom/kernels/cgal/CgalConversionResult.cpp create mode 100644 src/ifcgeom/kernels/cgal/CgalConversionResult.h create mode 100644 src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp create mode 100644 src/ifcgeom/kernels/cgal/CgalEntityMapping.h create mode 100644 src/ifcgeom/kernels/cgal/CgalEntityMappingCreateCache.h create mode 100644 src/ifcgeom/kernels/cgal/CgalEntityMappingCurve.h create mode 100644 src/ifcgeom/kernels/cgal/CgalEntityMappingDeclaration.h create mode 100644 src/ifcgeom/kernels/cgal/CgalEntityMappingDefine.h create mode 100644 src/ifcgeom/kernels/cgal/CgalEntityMappingFace.h create mode 100644 src/ifcgeom/kernels/cgal/CgalEntityMappingPurgeCache.h create mode 100644 src/ifcgeom/kernels/cgal/CgalEntityMappingShape.h create mode 100644 src/ifcgeom/kernels/cgal/CgalEntityMappingShapeType.h create mode 100644 src/ifcgeom/kernels/cgal/CgalEntityMappingShapes.h create mode 100644 src/ifcgeom/kernels/cgal/CgalEntityMappingUndefine.h create mode 100644 src/ifcgeom/kernels/cgal/CgalEntityMappingWire.h create mode 100644 src/ifcgeom/kernels/cgal/CgalKernel.cpp create mode 100644 src/ifcgeom/kernels/cgal/CgalKernel.h diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 7015190a78..5b9057a73b 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -129,6 +129,7 @@ int main(int argc, char** argv) { std::vector entity_vector, names; double deflection_tolerance; + std::string kernel; boost::program_options::options_description geom_options("Geometry options"); geom_options.add_options() ("plan", @@ -143,7 +144,7 @@ int main(int argc, char** argv) { "vector will only contain unique xyz-triplets. This results in a " "manifold mesh which is useful for modelling applications, but might " "result in unwanted shading artefacts in rendering applications.") - ("use-world-coords", + ("use-world-coords", "Specifies whether to apply the local placements of building elements " "directly to the coordinates of the representation mesh rather than " "to represent the local placement in the 4x3 matrix, which will in that " @@ -152,7 +153,7 @@ int main(int argc, char** argv) { "Specifies whether to convert back geometrical output back to the " "unit of measure in which it is defined in the IFC file. Default is " "to use meters.") - ("sew-shells", + ("sew-shells", "Specifies whether to sew the faces of IfcConnectedFaceSets together. " "This is a potentially time consuming operation, but guarantees a " "consistent orientation of surface normals, even if the faces are not " @@ -162,45 +163,46 @@ int main(int argc, char** argv) { // arguments where not introduced yet and a work-around was implemented to // subtract multiple openings as a single compound. This hack is obsolete // for newer versions of Open CASCADE. - ("merge-boolean-operands", + ("merge-boolean-operands", "Specifies whether to merge all IfcOpeningElement operands into a single " "operand before applying the subtraction operation. This may " "introduce a performance improvement at the risk of failing, in " "which case the subtraction is applied one-by-one.") #endif - ("disable-opening-subtractions", + ("disable-opening-subtractions", "Specifies whether to disable the boolean subtraction of " "IfcOpeningElement Representations from their RelatingElements.") - ("enable-layerset-slicing", + ("enable-layerset-slicing", "Specifies whether to enable the slicing of products according " "to their associated IfcMaterialLayerSet.") - ("include", - "Specifies that the entities and/or names listed after --entities and/or --names are to be included") - ("exclude", - "Specifies that the entities and/or names listed after --entities and/or --names are to be excluded") + ("include", + "Specifies that the entities and/or names listed after --entities and/or --names are to be included") + ("exclude", + "Specifies that the entities and/or names listed after --entities and/or --names are to be excluded") ("entities", boost::program_options::value< std::vector >(&entity_vector)->multitoken(), "A list of entities that should be included in or excluded from the " "geometrical output, depending on whether --exclude or --include is specified. " - "Defaults to IfcOpeningElement and IfcSpace to be excluded. SVG output defaults " - "to IfcSpace to be included." - "The names are handled case-insensitively. Cannot be placed right before input file argument.") - ("names", boost::program_options::value< std::vector >(&names)->multitoken(), - "A list of names or wildcard patterns that should be included in or excluded from the " - "geometrical output, depending on whether --exclude or --include is specified. " - "The names are handled case-sensitively. Cannot be placed right before input file argument.") - ("no-normals", - "Disables computation of normals. Saves time and file size and is useful " - "in instances where you're going to recompute normals for the exported " - "model in other modelling application in any case.") - ("deflection-tolerance", boost::program_options::value(&deflection_tolerance), - "Sets the deflection tolerance of the mesher, 1e-3 by default if not specified.") - ("generate-uvs", - "Generates UVs (texture coordinates) by using simple box projection. Requires normals. " - "Not guaranteed to work properly if used with --weld-vertices.") - ("traverse", - "Applies --include or --exclude also to the decomposition and/or containment (IsDecomposedBy, " - "HasOpenings, FillsVoid, ContainedInStructure) of the filtered entity, e.g. " - "--include --traverse --names \"Level 1\" includes entity with name \"Level 1\" and all of its children."); + "Defaults to IfcOpeningElement and IfcSpace to be excluded. SVG output defaults " + "to IfcSpace to be included." + "The names are handled case-insensitively. Cannot be placed right before input file argument.") + ("names", boost::program_options::value< std::vector >(&names)->multitoken(), + "A list of names or wildcard patterns that should be included in or excluded from the " + "geometrical output, depending on whether --exclude or --include is specified. " + "The names are handled case-sensitively. Cannot be placed right before input file argument.") + ("no-normals", + "Disables computation of normals. Saves time and file size and is useful " + "in instances where you're going to recompute normals for the exported " + "model in other modelling application in any case.") + ("deflection-tolerance", boost::program_options::value(&deflection_tolerance), + "Sets the deflection tolerance of the mesher, 1e-3 by default if not specified.") + ("generate-uvs", + "Generates UVs (texture coordinates) by using simple box projection. Requires normals. " + "Not guaranteed to work properly if used with --weld-vertices.") + ("traverse", + "Applies --include or --exclude also to the decomposition and/or containment (IsDecomposedBy, " + "HasOpenings, FillsVoid, ContainedInStructure) of the filtered entity, e.g. " + "--include --traverse --names \"Level 1\" includes entity with name \"Level 1\" and all of its children.") + ("kernel", "Geometry kernel to use ('opencascade' or 'cgal'). Defaults to 'cgal'."); std::string bounds; boost::program_options::options_description serializer_options("Serialization options"); @@ -284,6 +286,11 @@ int main(int argc, char** argv) { const bool traverse = vmap.count("traverse") != 0; const bool deflection_tolerance_specified = vmap.count("deflection-tolerance") != 0 ; + if (vmap.count("kernel") == 0) { + std::cerr << "Using default CGAL based kernel" << std::endl; + kernel = "cgal"; + } + int bounding_width = -1, bounding_height = -1; if (vmap.count("bounds") == 1) { int w, h; @@ -434,7 +441,7 @@ int main(int argc, char** argv) { settings.set(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION, true); } - IfcGeom::Iterator context_iterator(settings, input_filename); + IfcGeom::Iterator context_iterator(settings, input_filename, kernel.c_str()); try { if (include_entities) { diff --git a/src/ifcgeom/IfcGeomAbstractKernel.cpp b/src/ifcgeom/IfcGeomAbstractKernel.cpp index a5669d44f6..76d49892c2 100644 --- a/src/ifcgeom/IfcGeomAbstractKernel.cpp +++ b/src/ifcgeom/IfcGeomAbstractKernel.cpp @@ -2,6 +2,7 @@ #include "IfcGeom.h" #include "kernels/opencascade/OpenCascadeKernel.h" +#include "kernels/cgal/CgalKernel.h" void IfcGeom::AbstractKernel::setValue(GeomValue var, double value) { switch (var) { @@ -241,7 +242,7 @@ IfcGeom::AbstractKernel* IfcGeom::AbstractKernel::kernel_by_name(const std::stri if (name == "opencascade") { return new OpenCascadeKernel(); } else if (name == "cgal") { - throw std::runtime_error("Not implemented"); + return new CgalKernel(); } else { throw std::runtime_error("No kernel named " + name); } diff --git a/src/ifcgeom/IfcGeomIterator.h b/src/ifcgeom/IfcGeomIterator.h index 150c6899f7..2ada29a2cf 100644 --- a/src/ifcgeom/IfcGeomIterator.h +++ b/src/ifcgeom/IfcGeomIterator.h @@ -737,6 +737,8 @@ namespace IfcGeom { return success; } private: + const char* const kernel_name_; + void _initialize() { current_triangulation = 0; current_shape_model = 0; @@ -750,7 +752,11 @@ namespace IfcGeom { unit_name = "METER"; unit_magnitude = 1.f; - kernel = IfcGeom::AbstractKernel::kernel_by_name("opencascade"); + const char* kn = kernel_name_; + if (kn == 0) { + kn = "cgal"; + } + kernel = IfcGeom::AbstractKernel::kernel_by_name(kn); kernel->setValue(IfcGeom::AbstractKernel::GV_MAX_FACES_TO_SEW, settings.get(IteratorSettings::SEW_SHELLS) ? 1000 : -1); kernel->setValue(IfcGeom::AbstractKernel::GV_DIMENSIONALITY, (settings.get(IteratorSettings::INCLUDE_CURVES) @@ -759,33 +765,37 @@ namespace IfcGeom { bool owns_ifc_file; public: - Iterator(const IteratorSettings& settings, IfcParse::IfcFile* file) + Iterator(const IteratorSettings& settings, IfcParse::IfcFile* file, const char* const kernel_name=0) : settings(settings) , ifc_file(file) , owns_ifc_file(false) + , kernel_name_(kernel_name) { _initialize(); } - Iterator(const IteratorSettings& settings, const std::string& filename) + Iterator(const IteratorSettings& settings, const std::string& filename, const char* const kernel_name = 0) : settings(settings) , ifc_file(new IfcParse::IfcFile) , owns_ifc_file(true) + , kernel_name_(kernel_name) { ifc_file->Init(filename); _initialize(); } - Iterator(const IteratorSettings& settings, void* data, int length) + Iterator(const IteratorSettings& settings, void* data, int length, const char* const kernel_name = 0) : settings(settings) , ifc_file(new IfcParse::IfcFile) , owns_ifc_file(true) + , kernel_name_(kernel_name) { ifc_file->Init(data, length); _initialize(); } - Iterator(const IteratorSettings& settings, std::istream& filestream, int length) + Iterator(const IteratorSettings& settings, std::istream& filestream, int length, const char* const kernel_name = 0) : settings(settings) , ifc_file(new IfcParse::IfcFile) , owns_ifc_file(true) + , kernel_name_(kernel_name) { ifc_file->Init(filestream, length); _initialize(); diff --git a/src/ifcgeom/IfcGeomIteratorSettings.h b/src/ifcgeom/IfcGeomIteratorSettings.h index e3fcd353b9..ebd21af247 100644 --- a/src/ifcgeom/IfcGeomIteratorSettings.h +++ b/src/ifcgeom/IfcGeomIteratorSettings.h @@ -23,6 +23,7 @@ #include "ifc_geom_api.h" #include "../ifcparse/IfcException.h" #include "../ifcparse/IfcUtil.h" +#include "../ifcparse/IfcLogger.h" namespace IfcGeom { diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp new file mode 100644 index 0000000000..68d9224029 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -0,0 +1,28 @@ +#include "../../../ifcparse/IfcParse.h" + +#include "CgalKernel.h" +#include "CgalConversionResult.h" + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRepresentation* l, ConversionResults& shapes) { + IfcSchema::IfcRepresentationItem::list::ptr items = l->Items(); + bool part_succes = false; + if (items->size()) { + for (IfcSchema::IfcRepresentationItem::list::it it = items->begin(); it != items->end(); ++it) { + IfcSchema::IfcRepresentationItem* representation_item = *it; + if (shape_type(representation_item) == ST_SHAPELIST) { + part_succes |= convert_shapes(*it, shapes); + } else { + cgal_shape_t s; + if (convert_shape(representation_item, s)) { + shapes.push_back(ConversionResult(new CgalShape(s), get_style(representation_item))); + part_succes |= true; + } + } + } + } + return part_succes; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid*, cgal_shape_t&) { + throw std::runtime_error("Not implemented IfcExtrudedAreaSolid"); +} diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp new file mode 100644 index 0000000000..e2da8ecd97 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -0,0 +1,6 @@ +#include "CgalKernel.h" +#include "CgalConversionResult.h" + +void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement * place, IfcGeom::Representation::Triangulation* t, int surface_style_id) const { + throw std::runtime_error("Not implemented Triangulate()"); +} diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.h b/src/ifcgeom/kernels/cgal/CgalConversionResult.h new file mode 100644 index 0000000000..3fb4bb7e67 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.h @@ -0,0 +1,77 @@ +/******************************************************************************** +* * +* 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 CGALCONVERSIONRESULT_H +#define CGALCONVERSIONRESULT_H + +#include "../../../ifcgeom/ConversionResult.h" + +namespace IfcGeom { + + class CgalPlacement : public ConversionResultPlacement { + public: + CgalPlacement(const cgal_placement_t& trsf) + : trsf_(trsf) + {} + + const cgal_placement_t& trsf() const { return trsf_; } + operator const cgal_placement_t& () { return trsf_; } + + virtual double Value(int i, int j) const { + // Get cell from placement as 4x3 matrix as implemented in OCCT. We'll have to check exact semantics. + throw std::runtime_error("Not implemented"); + } + virtual void Multiply(const ConversionResultPlacement* other) { + // Multiply matrix as implemented in OCCT. We'll have to check exact semantics. + throw std::runtime_error("Not implemented"); + } + virtual void PreMultiply(const ConversionResultPlacement* other) { + // PreMultiply matrix as implemented in OCCT. We'll have to check exact semantics. + throw std::runtime_error("Not implemented"); + } + virtual ConversionResultPlacement* clone() const { + return new CgalPlacement(trsf_); + } + private: + cgal_placement_t trsf_; + }; + + class CgalShape : public ConversionResultShape { + public: + CgalShape(const cgal_shape_t& shape) + : shape_(shape) + {} + + const cgal_shape_t& shape() const { return shape_; } + operator const cgal_shape_t& () { return shape_; } + + virtual void Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement * place, IfcGeom::Representation::Triangulation* t, int surface_style_id) const; + virtual void Serialize(std::string&) const { + throw std::runtime_error("Not implemented"); + } + virtual ConversionResultShape* clone() const { + return new CgalShape(shape_); + } + private: + cgal_shape_t shape_; + }; + +} + +#endif \ No newline at end of file diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp new file mode 100644 index 0000000000..f3002292d4 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp @@ -0,0 +1,100 @@ +/******************************************************************************** +* * +* 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 . * +* * +********************************************************************************/ + +#include "../../../ifcgeom/IfcGeomShapeType.h" +#include "../../../ifcgeom/IfcGeom.h" + +#include "CgalKernel.h" +#include "CgalConversionResult.h" + +using namespace IfcSchema; +using namespace IfcUtil; + + +bool IfcGeom::CgalKernel::convert_shapes(const IfcBaseClass* l, ConversionResults& r) { + if (shape_type(l) != ST_SHAPELIST) { + cgal_shape_t shp; + if (convert_shape(l, shp)) { + r.push_back(IfcGeom::ConversionResult(new CgalShape(shp), get_style(l->as()))); + return true; + } + return false; + } + +#include "CgalEntityMappingShapes.h" + Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity); + return false; +} + +IfcGeom::ShapeType IfcGeom::CgalKernel::shape_type(const IfcBaseClass* l) { +#include "CgalEntityMappingShapeType.h" + return ST_OTHER; +} + +bool IfcGeom::CgalKernel::convert_shape(const IfcBaseClass* l, cgal_shape_t& r) { + const unsigned int id = l->entity->id(); + bool success = false; + bool processed = false; + bool ignored = false; + +#ifndef NO_CACHE + std::map::const_iterator it = cache.Shape.find(id); + if ( it != cache.Shape.end() ) { r = it->second; return true; } +#endif + const bool include_curves = getValue(GV_DIMENSIONALITY) != +1; + const bool include_solids_and_surfaces = getValue(GV_DIMENSIONALITY) != -1; + + IfcGeom::ShapeType st = shape_type(l); + ignored = (!include_solids_and_surfaces && (st == ST_SHAPE || st == ST_FACE)) || (!include_curves && (st == ST_WIRE || st == ST_CURVE)); + if (st == ST_SHAPE && include_solids_and_surfaces) { +#include "CgalEntityMappingShape.h" + } + + if ( processed && success ) { + const double precision = getValue(GV_PRECISION); + // apply_tolerance(r, precision); +#ifndef NO_CACHE + cache.Shape[id] = r; +#endif + } else if (!ignored) { + const char* const msg = processed + ? "Failed to convert:" + : "No operation defined for:"; + Logger::Message(Logger::LOG_ERROR, msg, l->entity); + } + return success; +} + +bool IfcGeom::CgalKernel::convert_wire(const IfcBaseClass* l, cgal_wire_t& r) { +#include "CgalEntityMappingWire.h" + Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity); + return false; +} + +bool IfcGeom::CgalKernel::convert_face(const IfcBaseClass* l, cgal_face_t& r) { +#include "CgalEntityMappingFace.h" + Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity); + return false; +} + +bool IfcGeom::CgalKernel::convert_curve(const IfcBaseClass* l, cgal_curve_t& r) { +#include "CgalEntityMappingCurve.h" + Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity); + return false; +} diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h new file mode 100644 index 0000000000..eb2ecedf38 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -0,0 +1,35 @@ +/******************************************************************************** +* * +* 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 . * +* * +********************************************************************************/ + +/******************************************************************************** + * * + * This file registers function prototypes for all supported IFC geometrical * + * entities. For entities of type CLASS an std::map is also created to cache * + * the output of the conversion functions * + * * + ********************************************************************************/ + +#include "../../../ifcparse/IfcUtil.h" +#include "../../../ifcparse/IfcParse.h" + +SHAPES(IfcRepresentation); + +SHAPE(IfcExtrudedAreaSolid); + +CLASS(IfcCartesianPoint,cgal_point_t); diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMappingCreateCache.h b/src/ifcgeom/kernels/cgal/CgalEntityMappingCreateCache.h new file mode 100644 index 0000000000..ebfb8daca7 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalEntityMappingCreateCache.h @@ -0,0 +1,6 @@ +#include "CgalEntityMappingUndefine.h" +#define CLASS(T,V) \ + std::map T; +#include "CgalEntityMappingDefine.h" + +#include "CgalEntityMapping.h" diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMappingCurve.h b/src/ifcgeom/kernels/cgal/CgalEntityMappingCurve.h new file mode 100644 index 0000000000..ac6736626a --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalEntityMappingCurve.h @@ -0,0 +1,6 @@ +#include "CgalEntityMappingUndefine.h" +#define CURVE(T) \ + if ( l->is(T::Class()) ) return convert((T*)l,r); +#include "CgalEntityMappingDefine.h" + +#include "CgalEntityMapping.h" \ No newline at end of file diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMappingDeclaration.h b/src/ifcgeom/kernels/cgal/CgalEntityMappingDeclaration.h new file mode 100644 index 0000000000..7101613c26 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalEntityMappingDeclaration.h @@ -0,0 +1,10 @@ +#include "CgalEntityMappingUndefine.h" +#define CLASS(T,V) bool convert(const IfcSchema::T* L, V& r); +#define SHAPES(T) CLASS(T,ConversionResults) +#define SHAPE(T) CLASS(T,cgal_shape_t) +#define WIRE(T) CLASS(T,cgal_wire_t) +#define FACE(T) CLASS(T,cgal_face_t) +#define CURVE(T) CLASS(T,cgal_curve_t) +#include "CgalEntityMappingDefine.h" + +#include "CgalEntityMapping.h" \ No newline at end of file diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMappingDefine.h b/src/ifcgeom/kernels/cgal/CgalEntityMappingDefine.h new file mode 100644 index 0000000000..65f8704a81 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalEntityMappingDefine.h @@ -0,0 +1,18 @@ +#ifndef SHAPES +#define SHAPES(T) +#endif +#ifndef SHAPE +#define SHAPE(T) +#endif +#ifndef WIRE +#define WIRE(T) +#endif +#ifndef FACE +#define FACE(T) +#endif +#ifndef CURVE +#define CURVE(T) +#endif +#ifndef CLASS +#define CLASS(T,V) +#endif \ No newline at end of file diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMappingFace.h b/src/ifcgeom/kernels/cgal/CgalEntityMappingFace.h new file mode 100644 index 0000000000..ccebad4e33 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalEntityMappingFace.h @@ -0,0 +1,6 @@ +#include "CgalEntityMappingUndefine.h" +#define FACE(T) \ + if ( l->is(T::Class()) ) return convert((T*)l,r); +#include "CgalEntityMappingDefine.h" + +#include "CgalEntityMapping.h" \ No newline at end of file diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMappingPurgeCache.h b/src/ifcgeom/kernels/cgal/CgalEntityMappingPurgeCache.h new file mode 100644 index 0000000000..ea8c2c2554 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalEntityMappingPurgeCache.h @@ -0,0 +1,6 @@ +#include "CgalEntityMappingUndefine.h" +#define CLASS(T,V) \ + T.clear(); +#include "CgalEntityMappingDefine.h" + +#include "CgalEntityMapping.h" \ No newline at end of file diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMappingShape.h b/src/ifcgeom/kernels/cgal/CgalEntityMappingShape.h new file mode 100644 index 0000000000..736df52c62 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalEntityMappingShape.h @@ -0,0 +1,20 @@ +#include "CgalEntityMappingUndefine.h" +#define SHAPE(T) \ + if ( !processed && l->is(T::Class()) ) { \ + processed = true; \ + try { \ + if ( convert((T*)l,r) ) { \ + success = true; \ + } \ + } catch (const std::exception& e) { \ + Logger::Message(Logger::LOG_ERROR, std::string(e.what()) + "\nFailed to convert:", l->entity); \ + return false; \ + } \ + if (!success) { \ + Logger::Message(Logger::LOG_ERROR,"Failed to convert:",l->entity); \ + return false; \ + } \ + } +#include "CgalEntityMappingDefine.h" + +#include "CgalEntityMapping.h" \ No newline at end of file diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMappingShapeType.h b/src/ifcgeom/kernels/cgal/CgalEntityMappingShapeType.h new file mode 100644 index 0000000000..21e6a0cd31 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalEntityMappingShapeType.h @@ -0,0 +1,14 @@ +#include "CgalEntityMappingUndefine.h" +#define SHAPES(T) \ + if ( l->is(T::Class()) ) return ST_SHAPELIST; +#define SHAPE(T) \ + if ( l->is(T::Class()) ) return ST_SHAPE; +#define WIRE(T) \ + if ( l->is(T::Class()) ) return ST_WIRE; +#define FACE(T) \ + if ( l->is(T::Class()) ) return ST_FACE; +#define CURVE(T) \ + if ( l->is(T::Class()) ) return ST_CURVE; +#include "CgalEntityMappingDefine.h" + +#include "CgalEntityMapping.h" diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMappingShapes.h b/src/ifcgeom/kernels/cgal/CgalEntityMappingShapes.h new file mode 100644 index 0000000000..778a5399ac --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalEntityMappingShapes.h @@ -0,0 +1,13 @@ +#include "CgalEntityMappingUndefine.h" +#define SHAPES(T) \ + if ( l->is(T::Class()) ) { \ + try { \ + return convert((T*)l,r); \ + } catch (const std::exception& e) { \ + Logger::Message(Logger::LOG_ERROR, std::string(e.what()) + "\nFailed to convert:", l->entity); \ + } \ + return false; \ + } +#include "CgalEntityMappingDefine.h" + +#include "CgalEntityMapping.h" diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMappingUndefine.h b/src/ifcgeom/kernels/cgal/CgalEntityMappingUndefine.h new file mode 100644 index 0000000000..d2d537a073 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalEntityMappingUndefine.h @@ -0,0 +1,18 @@ +#ifdef SHAPES +#undef SHAPES +#endif +#ifdef SHAPE +#undef SHAPE +#endif +#ifdef WIRE +#undef WIRE +#endif +#ifdef FACE +#undef FACE +#endif +#ifdef CURVE +#undef CURVE +#endif +#ifdef CLASS +#undef CLASS +#endif \ No newline at end of file diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMappingWire.h b/src/ifcgeom/kernels/cgal/CgalEntityMappingWire.h new file mode 100644 index 0000000000..ed5461ba75 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalEntityMappingWire.h @@ -0,0 +1,6 @@ +#include "CgalEntityMappingUndefine.h" +#define WIRE(T) \ + if ( l->is(T::Class()) ) return convert((T*)l,r); +#include "CgalEntityMappingDefine.h" + +#include "CgalEntityMapping.h" diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.cpp b/src/ifcgeom/kernels/cgal/CgalKernel.cpp new file mode 100644 index 0000000000..f4f830cbee --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalKernel.cpp @@ -0,0 +1,171 @@ +/******************************************************************************** +* * +* 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 . * +* * +********************************************************************************/ + +#include "../../../ifcgeom/IfcGeomShapeType.h" +#include "../../../ifcgeom/IfcGeom.h" + +#include "CgalKernel.h" +#include "CgalConversionResult.h" + +bool IfcGeom::CgalKernel::is_identity_transform(IfcUtil::IfcBaseClass* l) { + Logger::Message(Logger::LOG_ERROR, "Not implemented is_identity_transform()"); + return false; + /* + // OpenCascade kernel code below + + IfcSchema::IfcAxis2Placement2D* ax2d; + IfcSchema::IfcAxis2Placement3D* ax3d; + + IfcSchema::IfcCartesianTransformationOperator2D* op2d; + IfcSchema::IfcCartesianTransformationOperator3D* op3d; + IfcSchema::IfcCartesianTransformationOperator2DnonUniform* op2dnonu; + IfcSchema::IfcCartesianTransformationOperator3DnonUniform* op3dnonu; + + if ((op2dnonu = l->as()) != 0) { + gp_GTrsf2d gtrsf2d; + convert(op2dnonu, gtrsf2d); + return gtrsf2d.Form() == gp_Identity; + } else if ((op2d = l->as()) != 0) { + gp_Trsf2d trsf2d; + convert(op2d, trsf2d); + return trsf2d.Form() == gp_Identity; + } else if ((op3dnonu = l->as()) != 0) { + gp_GTrsf gtrsf; + convert(op3dnonu, gtrsf); + return gtrsf.Form() == gp_Identity; + } else if ((op3d = l->as()) != 0) { + gp_Trsf trsf; + convert(op3d, trsf); + return trsf.Form() == gp_Identity; + } else if ((ax2d = l->as()) != 0) { + gp_Trsf2d trsf2d; + convert(ax2d, trsf2d); + return trsf2d.Form() == gp_Identity; + } else if ((ax3d = l->as()) != 0) { + gp_Trsf trsf; + convert(ax3d, trsf); + return trsf.Form() == gp_Identity; + } else { + throw IfcParse::IfcException("Invalid valuation for IfcAxis2Placement / IfcCartesianTransformationOperator"); + } + */ +} + +IfcGeom::NativeElement* IfcGeom::CgalKernel::create_brep_for_representation_and_product( + const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product) +{ + IfcGeom::Representation::Native* shape; + IfcGeom::ConversionResults shapes, shapes2; + + if (!convert_shapes(representation, shapes)) { + return 0; + } + + if (settings.get(IteratorSettings::APPLY_LAYERSETS)) { + Logger::Message(Logger::LOG_ERROR, "Not implemented APPLY_LAYERSETS"); + } + + int parent_id = -1; + try { + IfcSchema::IfcObjectDefinition* parent_object = get_decomposing_entity(product); + if (parent_object) { + parent_id = parent_object->entity->id(); + } + } catch (...) {} + + const std::string name = product->hasName() ? product->Name() : ""; + const std::string guid = product->GlobalId(); + + cgal_placement_t trsf; + try { + // convert(product->ObjectPlacement(), trsf); + } catch (...) {} + + // Does the IfcElement have any IfcOpenings? + // Note that openings for IfcOpeningElements are not processed + IfcSchema::IfcRelVoidsElement::list::ptr openings = find_openings(product); + + const std::string product_type = IfcSchema::Type::ToString(product->type()); + ElementSettings element_settings(settings, getValue(GV_LENGTH_UNIT), product_type); + + if (!settings.get(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS) && openings && openings->size()) { + Logger::Message(Logger::LOG_ERROR, "Not implemented opening subtractions"); + } + + shape = new IfcGeom::Representation::Native(element_settings, representation->entity->id(), shapes); + + std::string context_string = ""; + if (representation->hasRepresentationIdentifier()) { + context_string = representation->RepresentationIdentifier(); + } else if (representation->ContextOfItems()->hasContextType()) { + context_string = representation->ContextOfItems()->ContextType(); + } + + return new NativeElement( + product->entity->id(), + parent_id, + name, + product_type, + guid, + context_string, + new CgalPlacement(trsf), + boost::shared_ptr(shape) + ); +} + +IfcGeom::NativeElement* IfcGeom::CgalKernel::create_brep_for_processed_representation( + const IteratorSettings& /*settings*/, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, + IfcGeom::NativeElement* brep) +{ + int parent_id = -1; + try { + IfcSchema::IfcObjectDefinition* parent_object = get_decomposing_entity(product); + if (parent_object) { + parent_id = parent_object->entity->id(); + } + } catch (...) {} + + const std::string name = product->hasName() ? product->Name() : ""; + const std::string guid = product->GlobalId(); + + cgal_placement_t trsf; + try { + // convert(product->ObjectPlacement(), trsf); + } catch (...) {} + + std::string context_string = ""; + if (representation->hasRepresentationIdentifier()) { + context_string = representation->RepresentationIdentifier(); + } else if (representation->ContextOfItems()->hasContextType()) { + context_string = representation->ContextOfItems()->ContextType(); + } + + const std::string product_type = IfcSchema::Type::ToString(product->type()); + + return new NativeElement( + product->entity->id(), + parent_id, + name, + product_type, + guid, + context_string, + new CgalPlacement(trsf), + brep->geometry_pointer() + ); +} diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h new file mode 100644 index 0000000000..a3e7167624 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -0,0 +1,93 @@ +/******************************************************************************** +* * +* 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 CGAL_KERNEL_H +#define CGAL_KERNEL_H + +/* +#ifdef NO_CACHE + +#define IN_CACHE(T,E,t,e) +#define CACHE(T,E,e) + +#else + +#define IN_CACHE(T,E,t,e) std::map::const_iterator it = cache.T.find(E->entity->id());\ +if ( it != cache.T.end() ) { e = it->second; return true; } +#define CACHE(T,E,e) cache.T[E->entity->id()] = e; + +#endif +*/ + +#include "../../../ifcgeom/IfcGeom.h" + +typedef void* cgal_shape_t; +typedef void* cgal_face_t; +typedef void* cgal_wire_t; +typedef void* cgal_curve_t; +typedef void* cgal_placement_t; +typedef void* cgal_point_t; + +namespace IfcGeom { + + class IFC_GEOM_API CgalCache { + public: +#include "CgalEntityMappingCreateCache.h" + std::map Shape; + }; + + class IFC_GEOM_API CgalKernel : public AbstractKernel { + public: + +#ifndef NO_CACHE + CgalCache cache; +#endif + + IfcGeom::ShapeType shape_type(const IfcUtil::IfcBaseClass* L); + + bool convert_shapes(const IfcUtil::IfcBaseClass* L, ConversionResults& result); + bool convert_shape(const IfcUtil::IfcBaseClass* L, cgal_shape_t& result); + bool convert_wire(const IfcUtil::IfcBaseClass* L, cgal_wire_t& result); + bool convert_curve(const IfcUtil::IfcBaseClass* L, cgal_curve_t& result); + bool convert_face(const IfcUtil::IfcBaseClass* L, cgal_face_t& result); + + // bool convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, ConversionResults& cut_shapes); + + void purge_cache() { + // Rather hack-ish, but a stopgap solution to keep memory under control + // for large files. SurfaceStyles need to be kept at all costs, as they + // are read later on when serializing Collada files. +#ifndef NO_CACHE + cache = CgalCache(); +#endif + } + + virtual bool is_identity_transform(IfcUtil::IfcBaseClass*); + virtual IfcGeom::NativeElement* create_brep_for_representation_and_product( + const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*); + virtual IfcGeom::NativeElement* create_brep_for_processed_representation( + const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*, IfcGeom::NativeElement*); + +#include "CgalEntityMappingDeclaration.h" + + }; + +} + +#endif \ No newline at end of file