From a4264f31433eee1553b4c08f6f6c4f9a8272aae4 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Fri, 27 Jan 2017 15:31:22 -0600 Subject: [PATCH 01/25] Replaced macros, added basic CGAL definitions --- src/ifcconvert/ColladaSerializer.cpp | 6 +++--- src/ifcconvert/XmlSerializer.cpp | 8 ++++---- src/ifcgeom/IfcGeomIterator.h | 14 +++++++------- src/ifcgeom/kernels/cgal/CgalKernel.h | 23 +++++++++++++++-------- src/ifcparse/IfcUtil.h | 2 +- 5 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/ifcconvert/ColladaSerializer.cpp b/src/ifcconvert/ColladaSerializer.cpp index c8272aba64..e9108f6e80 100644 --- a/src/ifcconvert/ColladaSerializer.cpp +++ b/src/ifcconvert/ColladaSerializer.cpp @@ -208,7 +208,7 @@ void ColladaSerializer::ColladaExporter::ColladaScene::add( node.addMatrix(matrix_array); COLLADASW::InstanceGeometry instanceGeometry(mSW); instanceGeometry.setUrl ("#" + geom_name); - foreach(std::string material_name, material_ids) { + for (std::string material_name: material_ids) { /// @todo This is done 6 times in this file, try to perform this once and be done with the material naming for the export. collada_id(material_name); COLLADASW::InstanceMaterial material (material_name, "#" + material_name); @@ -276,7 +276,7 @@ bool ColladaSerializer::ColladaExporter::ColladaMaterials::contains(const IfcGeo void ColladaSerializer::ColladaExporter::ColladaMaterials::write() { effects.close(); - foreach(const IfcGeom::Material& material, materials) { + for (const IfcGeom::Material& material: materials) { std::string material_name = (serializer->settings().get(IfcGeom::IteratorSettings::USE_MATERIAL_NAMES) ? material.original_name() : material.name()); std::string material_name_unescaped = material_name; // workaround double-escaping that would occur in addInstanceEffect() @@ -307,7 +307,7 @@ void ColladaSerializer::ColladaExporter::write(const IfcGeom::TriangulationEleme const std::string representation_id = "representation-" + boost::lexical_cast(o->geometry().id()); std::vector material_references; - foreach(const IfcGeom::Material& material, mesh.materials()) { + for (const IfcGeom::Material& material: mesh.materials()) { if (!materials.contains(material)) { materials.add(material); } diff --git a/src/ifcconvert/XmlSerializer.cpp b/src/ifcconvert/XmlSerializer.cpp index dcb574e0cd..b6cdec851d 100644 --- a/src/ifcconvert/XmlSerializer.cpp +++ b/src/ifcconvert/XmlSerializer.cpp @@ -341,16 +341,16 @@ void XmlSerializer::finalize() { ptree root, header, units, decomposition, properties, types, layers; // Write the SPF header as XML nodes. - foreach(const std::string& s, file->header().file_description().description()) { + for (const std::string& s: file->header().file_description().description()) { header.add_child("file_description.description", ptree(s)); } - foreach(const std::string& s, file->header().file_name().author()) { + for (const std::string& s: file->header().file_name().author()) { header.add_child("file_name.author", ptree(s)); } - foreach(const std::string& s, file->header().file_name().organization()) { + for (const std::string& s: file->header().file_name().organization()) { header.add_child("file_name.organization", ptree(s)); } - foreach(const std::string& s, file->header().file_schema().schema_identifiers()) { + for (const std::string& s: file->header().file_schema().schema_identifiers()) { header.add_child("file_schema.schema_identifiers", ptree(s)); } header.put("file_description.implementation_level", file->header().file_description().implementation_level()); diff --git a/src/ifcgeom/IfcGeomIterator.h b/src/ifcgeom/IfcGeomIterator.h index 2ada29a2cf..2d2c8fe312 100644 --- a/src/ifcgeom/IfcGeomIterator.h +++ b/src/ifcgeom/IfcGeomIterator.h @@ -329,7 +329,7 @@ namespace IfcGeom { void include_entity_names(const std::vector& names) { names_to_include_or_exclude.clear(); - foreach(const std::string &name, names) + for (const std::string &name: names) names_to_include_or_exclude.insert(wildcard_string_to_regex(name)); include_names_in_processing_ = true; } @@ -338,7 +338,7 @@ namespace IfcGeom { void exclude_entity_names(const std::vector& names) { names_to_include_or_exclude.clear(); - foreach(const std::string &name, names) + for (const std::string &name: names) names_to_include_or_exclude.insert(wildcard_string_to_regex(name)); include_names_in_processing_ = false; } @@ -347,7 +347,7 @@ namespace IfcGeom { { // Escape all non-"*?" regex special chars std::string special_chars = "\\^.$|()[]+/"; - foreach(char c, special_chars) { + for (char c: special_chars) { std::string char_str(1, c); boost::replace_all(str, char_str, "\\" + char_str); } @@ -540,7 +540,7 @@ namespace IfcGeom { IfcSchema::IfcProduct* prod = *jt; bool type_found = false; // The set is iterated over to able to filter on subtypes. - foreach(IfcSchema::Type::Enum type, entities_to_include_or_exclude) { + for (IfcSchema::Type::Enum type: entities_to_include_or_exclude) { if (prod->is(type)) { type_found = true; break; @@ -548,7 +548,7 @@ namespace IfcGeom { } if (!type_found && traverse) { - foreach(IfcSchema::Type::Enum type, entities_to_include_or_exclude) { + for (IfcSchema::Type::Enum type: entities_to_include_or_exclude) { IfcSchema::IfcProduct* parent, * current = prod; while ((parent = static_cast(kernel->get_decomposing_entity(current))) != 0) { if (parent->is(type)) { @@ -564,7 +564,7 @@ namespace IfcGeom { } bool name_found = false; - foreach(const boost::regex& r, names_to_include_or_exclude) { + for (const boost::regex& r: names_to_include_or_exclude) { if (prod->hasName() && boost::regex_match(prod->Name(), r)) { name_found = true; break; @@ -572,7 +572,7 @@ namespace IfcGeom { } if (!name_found && traverse) { - foreach(const boost::regex& r, names_to_include_or_exclude) { + for (const boost::regex& r: names_to_include_or_exclude) { IfcSchema::IfcProduct* parent, *current = prod; while ((parent = static_cast(kernel->get_decomposing_entity(current))) != 0) { if (parent->hasName() && boost::regex_match(parent->Name(), r)) { diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index a3e7167624..5a9fe325a8 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -1,4 +1,4 @@ -/******************************************************************************** +/******************************************************************************** * * * This file is part of IfcOpenShell. * * * @@ -37,12 +37,19 @@ if ( it != cache.T.end() ) { e = it->second; return true; } #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; +#undef Handle + +#include +#include + +typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; + +typedef CGAL::Nef_polyhedron_3 *cgal_shape_t; +typedef std::vector *cgal_face_t; +typedef std::vector *cgal_wire_t; +typedef std::vector *cgal_curve_t; +typedef Kernel::Aff_transformation_3 *cgal_placement_t; +typedef Kernel::Point_3 *cgal_point_t; namespace IfcGeom { @@ -90,4 +97,4 @@ namespace IfcGeom { } -#endif \ No newline at end of file +#endif diff --git a/src/ifcparse/IfcUtil.h b/src/ifcparse/IfcUtil.h index 13eeb4a134..8b5259b111 100644 --- a/src/ifcparse/IfcUtil.h +++ b/src/ifcparse/IfcUtil.h @@ -38,7 +38,7 @@ #include #include -#define foreach BOOST_FOREACH +//#define foreach BOOST_FOREACH #define rforeach BOOST_REVERSE_FOREACH class Argument; From cac9c91c56397ee6ad0791abf489b9f9bb17b51c Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Fri, 27 Jan 2017 15:31:37 -0600 Subject: [PATCH 02/25] Mac metadata --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c8a6b575ee..f7b2047913 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ __pycache__ # Visual Studio Code files .vscode +.DS_Store From 0821dd4702d554bfe9a441ab2a6da8e69d4bf5e3 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Fri, 27 Jan 2017 18:40:38 -0600 Subject: [PATCH 03/25] Skeleton for IfcManifoldSolidBrep and IfcConnectedFaceSet --- .../kernels/cgal/CgalEntityMapping.cpp | 74 +++++++++++++++++++ src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 7 ++ 2 files changed, 81 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp index f3002292d4..ea7e417a15 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp @@ -81,6 +81,80 @@ bool IfcGeom::CgalKernel::convert_shape(const IfcBaseClass* l, cgal_shape_t& r) return success; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, ConversionResults& shape) { + cgal_shape_t s; + const SurfaceStyle* collective_style = get_style(l); + if (convert_shape(l->Outer(),s) ) { +// const SurfaceStyle* indiv_style = get_style(l->Outer()); +// +// IfcSchema::IfcClosedShell::list::ptr voids(new IfcSchema::IfcClosedShell::list); +// if (l->is(IfcSchema::Type::IfcFacetedBrepWithVoids)) { +// voids = l->as()->Voids(); +// } +//#ifdef USE_IFC4 +// if (l->is(IfcSchema::Type::IfcAdvancedBrepWithVoids)) { +// voids = l->as()->Voids(); +// } +//#endif +// +// for (IfcSchema::IfcClosedShell::list::it it = voids->begin(); it != voids->end(); ++it) { +// TopoDS_Shape s2; +// /// @todo No extensive shapefixing since shells should be disjoint. +// /// @todo Awaiting generalized boolean ops module with appropriate checking +// if (convert_shape(l->Outer(), s2)) { +// s = BRepAlgoAPI_Cut(s, s2).Shape(); +// } +// } +// +// shape.push_back(ConversionResult(new OpenCascadeShape(s), indiv_style ? indiv_style : collective_style)); +// return true; + } + return false; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_shape_t& shape) { + IfcSchema::IfcFace::list::ptr faces = l->CfsFaces(); + +// TopTools_ListOfShape face_list; + for (IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++it) { + bool success = false; + cgal_face_t face; + + try { + success = convert_face(*it, face); + } catch (...) {} + + if (!success) { + Logger::Message(Logger::LOG_WARNING, "Failed to convert face:", (*it)->entity); + continue; + } + +// if (face_area(face) > getValue(GV_MINIMAL_FACE_AREA)) { +// face_list.Append(face); +// } else { +// Logger::Message(Logger::LOG_WARNING, "Invalid face:", (*it)->entity); +// } + } +// +// if (face_list.Extent() == 0) { +// return false; +// } +// +// if (face_list.Extent() > getValue(GV_MAX_FACES_TO_SEW) || !create_solid_from_faces(face_list, shape)) { +// TopoDS_Compound compound; +// BRep_Builder builder; +// builder.MakeCompound(compound); +// +// TopTools_ListIteratorOfListOfShape face_iterator; +// for (face_iterator.Initialize(face_list); face_iterator.More(); face_iterator.Next()) { +// builder.Add(compound, face_iterator.Value()); +// } +// shape = compound; +// } + + return true; +} + 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); diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index eb2ecedf38..d8760aa233 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -31,5 +31,12 @@ SHAPES(IfcRepresentation); SHAPE(IfcExtrudedAreaSolid); +// IfcFacetedBrep included +// IfcAdvancedBrep included +// IfcFacetedBrepWithVoids included +// IfcAdvancedBrepWithVoids included +SHAPES(IfcManifoldSolidBrep); + +SHAPE(IfcConnectedFaceSet); CLASS(IfcCartesianPoint,cgal_point_t); From 9c21e0518454087d45fd44d3d423953494113df6 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 31 Jan 2017 18:53:00 -0600 Subject: [PATCH 04/25] Skeleton reaching all the way up to points, to be filled in --- .../kernels/cgal/CgalConversionFunctions.cpp | 12 + .../kernels/cgal/CgalEntityMapping.cpp | 264 +++++++++++++++++- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 9 +- 3 files changed, 281 insertions(+), 4 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 68d9224029..f226d7c9e4 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -26,3 +26,15 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRepresentation* l, Convers bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid*, cgal_shape_t&) { throw std::runtime_error("Not implemented IfcExtrudedAreaSolid"); } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianPoint* l, cgal_point_t& point) { +// IN_CACHE(IfcCartesianPoint,l,gp_Pnt,point) +// std::vector xyz = l->Coordinates(); +// point = gp_Pnt( +// xyz.size() ? (xyz[0]*getValue(GV_LENGTH_UNIT)) : 0.0f, +// xyz.size() > 1 ? (xyz[1]*getValue(GV_LENGTH_UNIT)) : 0.0f, +// xyz.size() > 2 ? (xyz[2]*getValue(GV_LENGTH_UNIT)) : 0.0f +// ); +// CACHE(IfcCartesianPoint,l,point) + return true; +} diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp index ea7e417a15..c04005e65d 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp @@ -1,4 +1,4 @@ -/******************************************************************************** +/******************************************************************************** * * * This file is part of IfcOpenShell. * * * @@ -167,6 +167,268 @@ bool IfcGeom::CgalKernel::convert_face(const IfcBaseClass* l, cgal_face_t& r) { return false; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcFace* l, cgal_face_t& face) { + IfcSchema::IfcFaceBound::list::ptr bounds = l->Bounds(); + +// Handle(Geom_Surface) face_surface; +// const bool is_face_surface = l->is(IfcSchema::Type::IfcFaceSurface); +// +// if (is_face_surface) { +// IfcSchema::IfcFaceSurface* fs = (IfcSchema::IfcFaceSurface*) l; +// fs->FaceSurface(); +// // FIXME: Surfaces are interpreted as a TopoDS_Shape +// TopoDS_Shape surface_shape; +// if (!convert_shape(fs->FaceSurface(), surface_shape)) return false; +// +// // FIXME: Assert this obtaines the only face +// TopExp_Explorer exp(surface_shape, TopAbs_FACE); +// if (!exp.More()) return false; +// +// TopoDS_Face surface = TopoDS::Face(exp.Current()); +// face_surface = BRep_Tool::Surface(surface); +// } +// +// const int num_bounds = bounds->size(); +// int num_outer_bounds = 0; +// +// for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) { +// IfcSchema::IfcFaceBound* bound = *it; +// if (bound->is(IfcSchema::Type::IfcFaceOuterBound)) num_outer_bounds ++; +// } +// +// // The number of outer bounds should be one according to the schema. Also Open Cascade +// // expects this, but it is not strictly checked. Regardless, if the number is greater, +// // the face will still be processed as long as there are no holes. A compound of faces +// // is returned in that case. +// if (num_bounds > 1 && num_outer_bounds > 1 && num_bounds != num_outer_bounds) { +// Logger::Message(Logger::LOG_ERROR, "Invalid configuration of boundaries for:", l->entity); +// return false; +// } +// +// TopoDS_Compound compound; +// BRep_Builder builder; +// if (num_outer_bounds > 1) { +// builder.MakeCompound(compound); +// } +// +// TopTools_DataMapOfShapeInteger wire_senses; +// +// // The builder is initialized on the heap because of the various different moments +// // of initialization depending on the configuration of surfaces and boundaries. +// BRepBuilderAPI_MakeFace* mf = 0; +// +// bool success = false; +// int processed = 0; +// +// for (int process_interior = 0; process_interior <= 1; ++process_interior) { + for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) { + IfcSchema::IfcFaceBound* bound = *it; + IfcSchema::IfcLoop* loop = bound->Bound(); + +// bool same_sense = bound->Orientation(); +// const bool is_interior = +// !bound->is(IfcSchema::Type::IfcFaceOuterBound) && +// (num_bounds > 1) && +// (num_outer_bounds < num_bounds); +// +// // The exterior face boundary is processed first +// if (is_interior == !process_interior) continue; +// + cgal_wire_t wire; + if (!convert_wire(loop, wire)) { +// Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary loop", loop->entity); +// delete mf; +// return false; + } +// +// if (!same_sense) { +// wire.Reverse(); +// } +// +// wire_senses.Bind(wire.Oriented(TopAbs_FORWARD), same_sense ? TopAbs_FORWARD : TopAbs_REVERSED); +// +// bool flattened_wire = false; +// +// if (!mf) { +// process_wire: +// +// if (face_surface.IsNull()) { +// mf = new BRepBuilderAPI_MakeFace(wire); +// } else { +// /// @todo check necessity of false here +// mf = new BRepBuilderAPI_MakeFace(face_surface, wire, false); +// } +// +// /* BRepBuilderAPI_FaceError er = mf->Error(); +// if (er == BRepBuilderAPI_NotPlanar) { +// ShapeFix_ShapeTolerance FTol; +// FTol.SetTolerance(wire, getValue(GV_PRECISION), TopAbs_WIRE); +// delete mf; +// mf = new BRepBuilderAPI_MakeFace(wire); +// } */ +// +// if (mf->IsDone()) { +// TopoDS_Face outer_face_bound = mf->Face(); +// +// // In case of (non-planar) face surface, p-curves need to be computed. +// // For planar faces, Open Cascade generates p-curves on the fly. +// if (!face_surface.IsNull()) { +// TopExp_Explorer exp(outer_face_bound, TopAbs_EDGE); +// for (; exp.More(); exp.Next()) { +// const TopoDS_Edge& edge = TopoDS::Edge(exp.Current()); +// ShapeFix_Edge fix_edge; +// fix_edge.FixAddPCurve(edge, outer_face_bound, false, getValue(GV_PRECISION)); +// } +// } +// +// if (BRepCheck_Face(outer_face_bound).OrientationOfWires() == BRepCheck_BadOrientationOfSubshape) { +// wire.Reverse(); +// same_sense = !same_sense; +// delete mf; +// if (face_surface.IsNull()) { +// mf = new BRepBuilderAPI_MakeFace(wire); +// } else { +// mf = new BRepBuilderAPI_MakeFace(face_surface, wire); +// } +// ShapeFix_Face fix(mf->Face()); +// fix.FixOrientation(); +// outer_face_bound = fix.Face(); +// } +// +// if (num_outer_bounds > 1) { +// builder.Add(compound, outer_face_bound); +// delete mf; mf = 0; +// } else if (num_bounds > 1) { +// // Reinitialize the builder to the outer face +// // bound in order to add holes more robustly. +// delete mf; +// // TODO: What about the face_surface? +// mf = new BRepBuilderAPI_MakeFace(outer_face_bound); +// } else { +// face = outer_face_bound; +// success = true; +// } +// } else { +// const bool non_planar = mf->Error() == BRepBuilderAPI_NotPlanar; +// delete mf; +// if (!non_planar || flattened_wire || !flatten_wire(wire)) { +// Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary", bound->entity); +// return false; +// } else { +// Logger::Message(Logger::LOG_ERROR, "Flattening face boundary", bound->entity); +// flattened_wire = true; +// goto process_wire; +// } +// } +// +// } else { +// mf->Add(wire); +// } +// processed ++; + } +// } +// +// if (!success) { +// success = processed == num_bounds; +// if (success) { +// if (num_outer_bounds > 1) { +// face = compound; +// } else { +// success = success && mf->IsDone(); +// if (success) { +// face = mf->Face(); +// } +// +// ShapeFix_Face sfs(TopoDS::Face(face)); +// TopTools_DataMapOfShapeListOfShape wire_map; +// sfs.FixOrientation(wire_map); +// +// TopoDS_Iterator jt(face, false); +// for (; jt.More(); jt.Next()) { +// const TopoDS_Wire& w = TopoDS::Wire(jt.Value()); +// if (wire_map.IsBound(w)) { +// const TopTools_ListOfShape& shapes = wire_map.Find(w); +// TopTools_ListIteratorOfListOfShape it(shapes); +// for (; it.More(); it.Next()) { +// // Apparently the wire got reversed, so register it with opposite orientation in the map +// wire_senses.Bind(it.Value(), wire_senses.Find(w) == TopAbs_FORWARD ? TopAbs_REVERSED : TopAbs_FORWARD); +// } +// } +// } +// +// face = TopoDS::Face(sfs.Face()); +// } +// } +// } +// +// if (success) { +// // If the wires are reversed the face needs to be reversed as well in order +// // to maintain the counter-clock-wise ordering of the bounding wire's vertices. +// if (num_bounds == 1 || true) { +// bool all_reversed = true; +// TopoDS_Iterator jt(face, false); +// for (; jt.More(); jt.Next()) { +// const TopoDS_Wire& w = TopoDS::Wire(jt.Value()); +// if (!wire_senses.IsBound(w.Oriented(TopAbs_FORWARD)) || (w.Orientation() == wire_senses.Find(w.Oriented(TopAbs_FORWARD)))) { +// all_reversed = false; +// } +// } +// +// if (all_reversed) { +// face.Reverse(); +// } +// } +// +// ShapeFix_ShapeTolerance FTol; +// FTol.SetTolerance(face, getValue(GV_PRECISION), TopAbs_FACE); +// } +// +// delete mf; + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& result) { + IfcSchema::IfcCartesianPoint::list::ptr points = l->Polygon(); + +// // Parse and store the points in a sequence +// TColgp_SequenceOfPnt polygon; + for(IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it) { + cgal_point_t pnt; + IfcGeom::CgalKernel::convert(*it, pnt); +// polygon.Append(pnt); + } +// +// // A loop should consist of at least three vertices +// int original_count = polygon.Length(); +// if (original_count < 3) { +// Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity); +// return false; +// } +// +// // Remove points that are too close to one another +// remove_duplicate_points_from_loop(polygon, true); +// +// int count = polygon.Length(); +// if (original_count - count != 0) { +// std::stringstream ss; ss << (original_count - count) << " edges removed for:"; +// Logger::Message(Logger::LOG_WARNING, ss.str(), l->entity); +// } +// +// if (count < 3) { +// Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity); +// return false; +// } +// +// BRepBuilderAPI_MakePolygon w; +// for (int i = 1; i <= polygon.Length(); ++i) { +// w.Add(polygon.Value(i)); +// } +// w.Close(); +// +// result = w.Wire(); + return true; +} + 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); diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index d8760aa233..e720796002 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -1,4 +1,4 @@ -/******************************************************************************** +/******************************************************************************** * * * This file is part of IfcOpenShell. * * * @@ -29,14 +29,17 @@ #include "../../../ifcparse/IfcParse.h" SHAPES(IfcRepresentation); - -SHAPE(IfcExtrudedAreaSolid); // IfcFacetedBrep included // IfcAdvancedBrep included // IfcFacetedBrepWithVoids included // IfcAdvancedBrepWithVoids included SHAPES(IfcManifoldSolidBrep); +SHAPE(IfcExtrudedAreaSolid); SHAPE(IfcConnectedFaceSet); +FACE(IfcFace); + +WIRE(IfcPolyLoop); + CLASS(IfcCartesianPoint,cgal_point_t); From 233aaeaca2de096d4388f1759905e8114a3c9d49 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 31 Jan 2017 19:03:15 -0600 Subject: [PATCH 05/25] Points and wires --- .../kernels/cgal/CgalConversionFunctions.cpp | 19 ++++++++++--------- .../kernels/cgal/CgalEntityMapping.cpp | 10 +++++----- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index f226d7c9e4..53336e0da5 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -28,13 +28,14 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid*, cgal_s } bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianPoint* l, cgal_point_t& point) { -// IN_CACHE(IfcCartesianPoint,l,gp_Pnt,point) -// std::vector xyz = l->Coordinates(); -// point = gp_Pnt( -// xyz.size() ? (xyz[0]*getValue(GV_LENGTH_UNIT)) : 0.0f, -// xyz.size() > 1 ? (xyz[1]*getValue(GV_LENGTH_UNIT)) : 0.0f, -// xyz.size() > 2 ? (xyz[2]*getValue(GV_LENGTH_UNIT)) : 0.0f -// ); -// CACHE(IfcCartesianPoint,l,point) - return true; + std::vector xyz = l->Coordinates(); +// for (const double &coordinate: xyz) std::cout << coordinate << " "; +// std::cout << std::endl; + if (xyz.size() == 3) { + point = new Kernel::Point_3(xyz[0], xyz[1], xyz[2]); + return true; + } else { + point = new Kernel::Point_3(); + return false; + } } diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp index c04005e65d..b093aa2679 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp @@ -390,14 +390,14 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcFace* l, cgal_face_t& face bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& result) { IfcSchema::IfcCartesianPoint::list::ptr points = l->Polygon(); -// // Parse and store the points in a sequence -// TColgp_SequenceOfPnt polygon; + // Parse and store the points in a sequence + cgal_wire_t polygon; for(IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it) { cgal_point_t pnt; IfcGeom::CgalKernel::convert(*it, pnt); -// polygon.Append(pnt); + polygon->push_back(*pnt); } -// + // // A loop should consist of at least three vertices // int original_count = polygon.Length(); // if (original_count < 3) { @@ -425,7 +425,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& // } // w.Close(); // -// result = w.Wire(); + result = polygon; return true; } From f2a45b705704c739dcc182b0d096d7c4241c205e Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Wed, 1 Feb 2017 15:57:25 -0600 Subject: [PATCH 06/25] Fixed pointer bug, wires seem okay now --- .../kernels/cgal/CgalConversionFunctions.cpp | 1 + .../kernels/cgal/CgalEntityMapping.cpp | 41 +++++++------------ src/ifcgeom/kernels/cgal/CgalKernel.h | 4 +- 3 files changed, 17 insertions(+), 29 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 53336e0da5..9f80843bb6 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -33,6 +33,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianPoint* l, cgal_po // std::cout << std::endl; if (xyz.size() == 3) { point = new Kernel::Point_3(xyz[0], xyz[1], xyz[2]); +// std::cout << *point << std::endl; return true; } else { point = new Kernel::Point_3(); diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp index b093aa2679..08577a7866 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp @@ -236,15 +236,15 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcFace* l, cgal_face_t& face // cgal_wire_t wire; if (!convert_wire(loop, wire)) { -// Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary loop", loop->entity); + Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary loop", loop->entity); // delete mf; -// return false; + return false; } -// + // if (!same_sense) { // wire.Reverse(); // } -// +// // wire_senses.Bind(wire.Oriented(TopAbs_FORWARD), same_sense ? TopAbs_FORWARD : TopAbs_REVERSED); // // bool flattened_wire = false; @@ -259,14 +259,6 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcFace* l, cgal_face_t& face // mf = new BRepBuilderAPI_MakeFace(face_surface, wire, false); // } // -// /* BRepBuilderAPI_FaceError er = mf->Error(); -// if (er == BRepBuilderAPI_NotPlanar) { -// ShapeFix_ShapeTolerance FTol; -// FTol.SetTolerance(wire, getValue(GV_PRECISION), TopAbs_WIRE); -// delete mf; -// mf = new BRepBuilderAPI_MakeFace(wire); -// } */ -// // if (mf->IsDone()) { // TopoDS_Face outer_face_bound = mf->Face(); // @@ -391,20 +383,21 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& IfcSchema::IfcCartesianPoint::list::ptr points = l->Polygon(); // Parse and store the points in a sequence - cgal_wire_t polygon; + cgal_wire_t polygon = new std::vector(); for(IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it) { cgal_point_t pnt; IfcGeom::CgalKernel::convert(*it, pnt); +// std::cout << *pnt << std::endl; polygon->push_back(*pnt); } -// // A loop should consist of at least three vertices -// int original_count = polygon.Length(); -// if (original_count < 3) { -// Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity); -// return false; -// } -// + // A loop should consist of at least three vertices + int original_count = polygon->size(); + if (original_count < 3) { + Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity); + return false; + } + // // Remove points that are too close to one another // remove_duplicate_points_from_loop(polygon, true); // @@ -418,13 +411,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& // Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity); // return false; // } -// -// BRepBuilderAPI_MakePolygon w; -// for (int i = 1; i <= polygon.Length(); ++i) { -// w.Add(polygon.Value(i)); -// } -// w.Close(); -// + result = polygon; return true; } diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index 5a9fe325a8..377a2687fb 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -40,11 +40,11 @@ if ( it != cache.T.end() ) { e = it->second; return true; } #undef Handle #include -#include +#include typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; -typedef CGAL::Nef_polyhedron_3 *cgal_shape_t; +typedef CGAL::Polyhedron_3 *cgal_shape_t; typedef std::vector *cgal_face_t; typedef std::vector *cgal_wire_t; typedef std::vector *cgal_curve_t; From 5724e1ac348ebbc7fd6dc3cb2c2a92d548d76c87 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Wed, 1 Feb 2017 17:53:12 -0600 Subject: [PATCH 07/25] Face from IfcFace --- .../kernels/cgal/CgalConversionFunctions.cpp | 6 +- .../kernels/cgal/CgalEntityMapping.cpp | 262 +++--------------- src/ifcgeom/kernels/cgal/CgalKernel.h | 14 +- 3 files changed, 56 insertions(+), 226 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 9f80843bb6..93947879ea 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -29,14 +29,10 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid*, cgal_s bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianPoint* l, cgal_point_t& point) { std::vector xyz = l->Coordinates(); -// for (const double &coordinate: xyz) std::cout << coordinate << " "; -// std::cout << std::endl; if (xyz.size() == 3) { point = new Kernel::Point_3(xyz[0], xyz[1], xyz[2]); -// std::cout << *point << std::endl; return true; } else { - point = new Kernel::Point_3(); - return false; + throw std::runtime_error("Point without 3 coordinates"); } } diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp index 08577a7866..73232096a5 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp @@ -169,213 +169,42 @@ bool IfcGeom::CgalKernel::convert_face(const IfcBaseClass* l, cgal_face_t& r) { bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcFace* l, cgal_face_t& face) { IfcSchema::IfcFaceBound::list::ptr bounds = l->Bounds(); + + int num_outer_bounds = 0; + + for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) { + IfcSchema::IfcFaceBound* bound = *it; + if (bound->is(IfcSchema::Type::IfcFaceOuterBound)) num_outer_bounds ++; + } -// Handle(Geom_Surface) face_surface; -// const bool is_face_surface = l->is(IfcSchema::Type::IfcFaceSurface); -// -// if (is_face_surface) { -// IfcSchema::IfcFaceSurface* fs = (IfcSchema::IfcFaceSurface*) l; -// fs->FaceSurface(); -// // FIXME: Surfaces are interpreted as a TopoDS_Shape -// TopoDS_Shape surface_shape; -// if (!convert_shape(fs->FaceSurface(), surface_shape)) return false; -// -// // FIXME: Assert this obtaines the only face -// TopExp_Explorer exp(surface_shape, TopAbs_FACE); -// if (!exp.More()) return false; -// -// TopoDS_Face surface = TopoDS::Face(exp.Current()); -// face_surface = BRep_Tool::Surface(surface); -// } -// -// const int num_bounds = bounds->size(); -// int num_outer_bounds = 0; -// -// for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) { -// IfcSchema::IfcFaceBound* bound = *it; -// if (bound->is(IfcSchema::Type::IfcFaceOuterBound)) num_outer_bounds ++; -// } -// -// // The number of outer bounds should be one according to the schema. Also Open Cascade -// // expects this, but it is not strictly checked. Regardless, if the number is greater, -// // the face will still be processed as long as there are no holes. A compound of faces -// // is returned in that case. -// if (num_bounds > 1 && num_outer_bounds > 1 && num_bounds != num_outer_bounds) { -// Logger::Message(Logger::LOG_ERROR, "Invalid configuration of boundaries for:", l->entity); -// return false; -// } -// -// TopoDS_Compound compound; -// BRep_Builder builder; -// if (num_outer_bounds > 1) { -// builder.MakeCompound(compound); -// } -// -// TopTools_DataMapOfShapeInteger wire_senses; -// -// // The builder is initialized on the heap because of the various different moments -// // of initialization depending on the configuration of surfaces and boundaries. -// BRepBuilderAPI_MakeFace* mf = 0; -// -// bool success = false; -// int processed = 0; -// -// for (int process_interior = 0; process_interior <= 1; ++process_interior) { - for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) { - IfcSchema::IfcFaceBound* bound = *it; - IfcSchema::IfcLoop* loop = bound->Bound(); + if (num_outer_bounds != 1) { + Logger::Message(Logger::LOG_ERROR, "Invalid configuration of boundaries for:", l->entity); + return false; + } + + cgal_face_t mf = new CgalFace(); -// bool same_sense = bound->Orientation(); -// const bool is_interior = -// !bound->is(IfcSchema::Type::IfcFaceOuterBound) && -// (num_bounds > 1) && -// (num_outer_bounds < num_bounds); -// -// // The exterior face boundary is processed first -// if (is_interior == !process_interior) continue; -// - cgal_wire_t wire; - if (!convert_wire(loop, wire)) { - Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary loop", loop->entity); -// delete mf; - return false; - } + for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) { + IfcSchema::IfcFaceBound* bound = *it; + IfcSchema::IfcLoop* loop = bound->Bound(); -// if (!same_sense) { -// wire.Reverse(); -// } -// -// wire_senses.Bind(wire.Oriented(TopAbs_FORWARD), same_sense ? TopAbs_FORWARD : TopAbs_REVERSED); -// -// bool flattened_wire = false; -// -// if (!mf) { -// process_wire: -// -// if (face_surface.IsNull()) { -// mf = new BRepBuilderAPI_MakeFace(wire); -// } else { -// /// @todo check necessity of false here -// mf = new BRepBuilderAPI_MakeFace(face_surface, wire, false); -// } -// -// if (mf->IsDone()) { -// TopoDS_Face outer_face_bound = mf->Face(); -// -// // In case of (non-planar) face surface, p-curves need to be computed. -// // For planar faces, Open Cascade generates p-curves on the fly. -// if (!face_surface.IsNull()) { -// TopExp_Explorer exp(outer_face_bound, TopAbs_EDGE); -// for (; exp.More(); exp.Next()) { -// const TopoDS_Edge& edge = TopoDS::Edge(exp.Current()); -// ShapeFix_Edge fix_edge; -// fix_edge.FixAddPCurve(edge, outer_face_bound, false, getValue(GV_PRECISION)); -// } -// } -// -// if (BRepCheck_Face(outer_face_bound).OrientationOfWires() == BRepCheck_BadOrientationOfSubshape) { -// wire.Reverse(); -// same_sense = !same_sense; -// delete mf; -// if (face_surface.IsNull()) { -// mf = new BRepBuilderAPI_MakeFace(wire); -// } else { -// mf = new BRepBuilderAPI_MakeFace(face_surface, wire); -// } -// ShapeFix_Face fix(mf->Face()); -// fix.FixOrientation(); -// outer_face_bound = fix.Face(); -// } -// -// if (num_outer_bounds > 1) { -// builder.Add(compound, outer_face_bound); -// delete mf; mf = 0; -// } else if (num_bounds > 1) { -// // Reinitialize the builder to the outer face -// // bound in order to add holes more robustly. -// delete mf; -// // TODO: What about the face_surface? -// mf = new BRepBuilderAPI_MakeFace(outer_face_bound); -// } else { -// face = outer_face_bound; -// success = true; -// } -// } else { -// const bool non_planar = mf->Error() == BRepBuilderAPI_NotPlanar; -// delete mf; -// if (!non_planar || flattened_wire || !flatten_wire(wire)) { -// Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary", bound->entity); -// return false; -// } else { -// Logger::Message(Logger::LOG_ERROR, "Flattening face boundary", bound->entity); -// flattened_wire = true; -// goto process_wire; -// } -// } -// -// } else { -// mf->Add(wire); -// } -// processed ++; + const bool is_interior = !bound->is(IfcSchema::Type::IfcFaceOuterBound); + + cgal_wire_t wire; + if (!convert_wire(loop, wire)) { + Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary loop", loop->entity); + delete mf; + return false; } -// } -// -// if (!success) { -// success = processed == num_bounds; -// if (success) { -// if (num_outer_bounds > 1) { -// face = compound; -// } else { -// success = success && mf->IsDone(); -// if (success) { -// face = mf->Face(); -// } -// -// ShapeFix_Face sfs(TopoDS::Face(face)); -// TopTools_DataMapOfShapeListOfShape wire_map; -// sfs.FixOrientation(wire_map); -// -// TopoDS_Iterator jt(face, false); -// for (; jt.More(); jt.Next()) { -// const TopoDS_Wire& w = TopoDS::Wire(jt.Value()); -// if (wire_map.IsBound(w)) { -// const TopTools_ListOfShape& shapes = wire_map.Find(w); -// TopTools_ListIteratorOfListOfShape it(shapes); -// for (; it.More(); it.Next()) { -// // Apparently the wire got reversed, so register it with opposite orientation in the map -// wire_senses.Bind(it.Value(), wire_senses.Find(w) == TopAbs_FORWARD ? TopAbs_REVERSED : TopAbs_FORWARD); -// } -// } -// } -// -// face = TopoDS::Face(sfs.Face()); -// } -// } -// } -// -// if (success) { -// // If the wires are reversed the face needs to be reversed as well in order -// // to maintain the counter-clock-wise ordering of the bounding wire's vertices. -// if (num_bounds == 1 || true) { -// bool all_reversed = true; -// TopoDS_Iterator jt(face, false); -// for (; jt.More(); jt.Next()) { -// const TopoDS_Wire& w = TopoDS::Wire(jt.Value()); -// if (!wire_senses.IsBound(w.Oriented(TopAbs_FORWARD)) || (w.Orientation() == wire_senses.Find(w.Oriented(TopAbs_FORWARD)))) { -// all_reversed = false; -// } -// } -// -// if (all_reversed) { -// face.Reverse(); -// } -// } -// -// ShapeFix_ShapeTolerance FTol; -// FTol.SetTolerance(face, getValue(GV_PRECISION), TopAbs_FACE); -// } -// -// delete mf; + + if (!is_interior) { + mf->outer = wire; + } else { + mf->inner.push_back(wire); + } + } + + face = mf; return true; } @@ -387,30 +216,29 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& for(IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it) { cgal_point_t pnt; IfcGeom::CgalKernel::convert(*it, pnt); -// std::cout << *pnt << std::endl; polygon->push_back(*pnt); } // A loop should consist of at least three vertices - int original_count = polygon->size(); + std::size_t original_count = polygon->size(); if (original_count < 3) { Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity); return false; } -// // Remove points that are too close to one another + // TODO: Remove repeated points (and points that are too close to one another?) // remove_duplicate_points_from_loop(polygon, true); -// -// int count = polygon.Length(); -// if (original_count - count != 0) { -// std::stringstream ss; ss << (original_count - count) << " edges removed for:"; -// Logger::Message(Logger::LOG_WARNING, ss.str(), l->entity); -// } -// -// if (count < 3) { -// Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity); -// return false; -// } + + std::size_t count = polygon->size(); + if (original_count - count != 0) { + std::stringstream ss; ss << (original_count - count) << " edges removed for:"; + Logger::Message(Logger::LOG_WARNING, ss.str(), l->entity); + } + + if (count < 3) { + Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity); + return false; + } result = polygon; return true; diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index 377a2687fb..dc3cdbd9b7 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -44,12 +44,18 @@ if ( it != cache.T.end() ) { e = it->second; return true; } typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; -typedef CGAL::Polyhedron_3 *cgal_shape_t; -typedef std::vector *cgal_face_t; -typedef std::vector *cgal_wire_t; -typedef std::vector *cgal_curve_t; typedef Kernel::Aff_transformation_3 *cgal_placement_t; typedef Kernel::Point_3 *cgal_point_t; +typedef std::vector *cgal_curve_t; +typedef std::vector *cgal_wire_t; + +struct CgalFace { + cgal_wire_t outer; + std::vector inner; +}; + +typedef CgalFace *cgal_face_t; +typedef CGAL::Polyhedron_3 *cgal_shape_t; namespace IfcGeom { From 1525cf6bfc615571c0907effbdceb00dd04bd87a Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 2 Feb 2017 14:29:26 -0600 Subject: [PATCH 08/25] Polyhedra built with the incremental builder, IfcConvert crashes --- .../kernels/cgal/CgalEntityMapping.cpp | 45 +++++++++--------- src/ifcgeom/kernels/cgal/CgalKernel.h | 47 +++++++++++++++++++ 2 files changed, 69 insertions(+), 23 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp index 73232096a5..4509a8de7e 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp @@ -115,7 +115,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, Conv bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_shape_t& shape) { IfcSchema::IfcFace::list::ptr faces = l->CfsFaces(); -// TopTools_ListOfShape face_list; + std::list face_list; for (IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++it) { bool success = false; cgal_face_t face; @@ -128,30 +128,29 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_ Logger::Message(Logger::LOG_WARNING, "Failed to convert face:", (*it)->entity); continue; } - -// if (face_area(face) > getValue(GV_MINIMAL_FACE_AREA)) { -// face_list.Append(face); -// } else { -// Logger::Message(Logger::LOG_WARNING, "Invalid face:", (*it)->entity); -// } + + face_list.push_back(face); } -// -// if (face_list.Extent() == 0) { -// return false; -// } -// -// if (face_list.Extent() > getValue(GV_MAX_FACES_TO_SEW) || !create_solid_from_faces(face_list, shape)) { -// TopoDS_Compound compound; -// BRep_Builder builder; -// builder.MakeCompound(compound); -// -// TopTools_ListIteratorOfListOfShape face_iterator; -// for (face_iterator.Initialize(face_list); face_iterator.More(); face_iterator.Next()) { -// builder.Add(compound, face_iterator.Value()); -// } -// shape = compound; -// } + for (auto const &face : face_list) { + std::cout << "Face" << std::endl; + std::cout << "\touter: "; + for (auto const &point: *face->outer) { + std::cout << "(" << point << ") "; + } std::cout << std::endl; + for (auto const &inner: face->inner) { + std::cout << "\tinner: "; + for (auto const &point: *inner) { + std::cout << "(" << point << ") "; + } std::cout << std::endl; + } + } + + cgal_shape_t polyhedron = new CGAL::Polyhedron_3(); + PolyhedronBuilder builder(&face_list); + polyhedron->delegate(builder); + + shape = polyhedron; return true; } diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index dc3cdbd9b7..b32435793d 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -57,6 +57,53 @@ struct CgalFace { typedef CgalFace *cgal_face_t; typedef CGAL::Polyhedron_3 *cgal_shape_t; +struct PolyhedronBuilder : public CGAL::Modifier_base::HalfedgeDS> { +private: + std::list *face_list; +public: + PolyhedronBuilder(std::list *face_list) { + this->face_list = face_list; + } + + void operator()(CGAL::Polyhedron_3::HalfedgeDS &hds) { + std::map points_map; + std::list> facet_vertices; + CGAL::Polyhedron_incremental_builder_3::HalfedgeDS> builder(hds, true); + + for (auto const &face: *face_list) { + facet_vertices.push_back(std::list()); + for (auto const &point: *face->outer) { + if (points_map.count(point) == 0) { + facet_vertices.back().push_back(points_map.size()); + points_map[point] = points_map.size(); + } else { + facet_vertices.back().push_back(points_map[point]); + } + } + } + + builder.begin_surface(points_map.size(), facet_vertices.size()); + + for (auto const &point: points_map) { + std::cout << "Adding point " << point.first << std::endl; + builder.add_vertex(point.first); + } + + for (auto const &facet: facet_vertices) { + builder.begin_facet(); + std::cout << "Adding facet "; + for (auto const &vertex: facet) { + std::cout << vertex << " "; + builder.add_vertex_to_facet(vertex); + } + std::cout << std::endl; + builder.end_facet(); + } + + builder.end_surface(); + } +}; + namespace IfcGeom { class IFC_GEOM_API CgalCache { From 6aff3d0f3d1f1fb76ada0505cbc0af0bf2474753 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Feb 2017 16:22:36 -0600 Subject: [PATCH 09/25] Conversion result for breps --- .../kernels/cgal/CgalEntityMapping.cpp | 60 +++++++++---------- src/ifcgeom/kernels/cgal/CgalKernel.h | 8 +-- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp index 4509a8de7e..dea961cf7c 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp @@ -85,29 +85,29 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, Conv cgal_shape_t s; const SurfaceStyle* collective_style = get_style(l); if (convert_shape(l->Outer(),s) ) { -// const SurfaceStyle* indiv_style = get_style(l->Outer()); -// -// IfcSchema::IfcClosedShell::list::ptr voids(new IfcSchema::IfcClosedShell::list); -// if (l->is(IfcSchema::Type::IfcFacetedBrepWithVoids)) { -// voids = l->as()->Voids(); -// } -//#ifdef USE_IFC4 -// if (l->is(IfcSchema::Type::IfcAdvancedBrepWithVoids)) { -// voids = l->as()->Voids(); -// } -//#endif -// -// for (IfcSchema::IfcClosedShell::list::it it = voids->begin(); it != voids->end(); ++it) { + const SurfaceStyle* indiv_style = get_style(l->Outer()); + + IfcSchema::IfcClosedShell::list::ptr voids(new IfcSchema::IfcClosedShell::list); + if (l->is(IfcSchema::Type::IfcFacetedBrepWithVoids)) { + voids = l->as()->Voids(); + } +#ifdef USE_IFC4 + if (l->is(IfcSchema::Type::IfcAdvancedBrepWithVoids)) { + voids = l->as()->Voids(); + } +#endif + + for (IfcSchema::IfcClosedShell::list::it it = voids->begin(); it != voids->end(); ++it) { // TopoDS_Shape s2; // /// @todo No extensive shapefixing since shells should be disjoint. // /// @todo Awaiting generalized boolean ops module with appropriate checking // if (convert_shape(l->Outer(), s2)) { // s = BRepAlgoAPI_Cut(s, s2).Shape(); // } -// } -// -// shape.push_back(ConversionResult(new OpenCascadeShape(s), indiv_style ? indiv_style : collective_style)); -// return true; + } + + shape.push_back(ConversionResult(new CgalShape(s), indiv_style ? indiv_style : collective_style)); + return true; } return false; } @@ -132,19 +132,19 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_ face_list.push_back(face); } - for (auto const &face : face_list) { - std::cout << "Face" << std::endl; - std::cout << "\touter: "; - for (auto const &point: *face->outer) { - std::cout << "(" << point << ") "; - } std::cout << std::endl; - for (auto const &inner: face->inner) { - std::cout << "\tinner: "; - for (auto const &point: *inner) { - std::cout << "(" << point << ") "; - } std::cout << std::endl; - } - } +// for (auto const &face : face_list) { +// std::cout << "Face" << std::endl; +// std::cout << "\touter: "; +// for (auto const &point: *face->outer) { +// std::cout << "(" << point << ") "; +// } std::cout << std::endl; +// for (auto const &inner: face->inner) { +// std::cout << "\tinner: "; +// for (auto const &point: *inner) { +// std::cout << "(" << point << ") "; +// } std::cout << std::endl; +// } +// } cgal_shape_t polyhedron = new CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index b32435793d..b6a042770d 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -85,18 +85,18 @@ public: builder.begin_surface(points_map.size(), facet_vertices.size()); for (auto const &point: points_map) { - std::cout << "Adding point " << point.first << std::endl; +// std::cout << "Adding point " << point.first << std::endl; builder.add_vertex(point.first); } for (auto const &facet: facet_vertices) { builder.begin_facet(); - std::cout << "Adding facet "; +// std::cout << "Adding facet "; for (auto const &vertex: facet) { - std::cout << vertex << " "; +// std::cout << vertex << " "; builder.add_vertex_to_facet(vertex); } - std::cout << std::endl; +// std::cout << std::endl; builder.end_facet(); } From e1702fc0cf12efd43118d434c7d0898287ad6994 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Feb 2017 16:22:54 -0600 Subject: [PATCH 10/25] =?UTF-8?q?Return=20value=20for=20transformation,=20?= =?UTF-8?q?still=20needs=20to=20be=20initialised=20somewhere=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ifcgeom/kernels/cgal/CgalConversionResult.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.h b/src/ifcgeom/kernels/cgal/CgalConversionResult.h index 3fb4bb7e67..92c80dc32a 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.h +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.h @@ -35,7 +35,7 @@ namespace IfcGeom { 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"); + return CGAL::to_double(trsf_->cartesian(i, j)); } virtual void Multiply(const ConversionResultPlacement* other) { // Multiply matrix as implemented in OCCT. We'll have to check exact semantics. From bae84b675383655ee10f2afd8dec6c1fa59a3479 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 7 Feb 2017 19:50:51 -0600 Subject: [PATCH 11/25] Directions as CGAL Vector_3, more robust points --- .../kernels/cgal/CgalConversionFunctions.cpp | 15 ++++++++++++++- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalKernel.h | 1 + 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 93947879ea..9e66c5def6 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -30,9 +30,22 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid*, cgal_s bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianPoint* l, cgal_point_t& point) { std::vector xyz = l->Coordinates(); if (xyz.size() == 3) { - point = new Kernel::Point_3(xyz[0], xyz[1], xyz[2]); + point = new Kernel::Point_3(xyz.size() ? (xyz[0]*getValue(GV_LENGTH_UNIT)) : 0.0f, + xyz.size() > 1 ? (xyz[1]*getValue(GV_LENGTH_UNIT)) : 0.0f, + xyz.size() > 2 ? (xyz[2]*getValue(GV_LENGTH_UNIT)) : 0.0f); return true; } else { throw std::runtime_error("Point without 3 coordinates"); } } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcDirection* l, cgal_direction_t& dir) { +// IN_CACHE(IfcDirection,l,cgal_direction_t,dir) + std::vector xyz = l->DirectionRatios(); + dir = new Kernel::Vector_3(xyz.size() ? xyz[0] : 0.0f, + xyz.size() > 1 ? xyz[1] : 0.0f, + xyz.size() > 2 ? xyz[2] : 0.0f); +// CACHE(IfcDirection,l,dir) + return true; +} + diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index e720796002..d8e39626d2 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -43,3 +43,4 @@ FACE(IfcFace); WIRE(IfcPolyLoop); CLASS(IfcCartesianPoint,cgal_point_t); +CLASS(IfcDirection,cgal_direction_t); diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index b6a042770d..638344c7d8 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -46,6 +46,7 @@ typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; typedef Kernel::Aff_transformation_3 *cgal_placement_t; typedef Kernel::Point_3 *cgal_point_t; +typedef Kernel::Vector_3 *cgal_direction_t; typedef std::vector *cgal_curve_t; typedef std::vector *cgal_wire_t; From 96e9c8ecc160d26138c1bd13a428e8b146b8ced4 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 7 Feb 2017 19:51:16 -0600 Subject: [PATCH 12/25] Skeleton for IfcObjectPlacement and IfcAxis2Placement3D --- .../kernels/cgal/CgalConversionFunctions.cpp | 43 +++++++++++++++++++ src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 3 ++ src/ifcgeom/kernels/cgal/CgalKernel.cpp | 4 +- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 9e66c5def6..3320c606e0 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -49,3 +49,46 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcDirection* l, cgal_directi return true; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement3D* l, cgal_placement_t& trsf) { +// IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf) +// cgal_point_t o;cgal_direction_t axis = new Kernel::Vector_3(0,0,1);cgal_direction_t refDirection; +// IfcGeom::OpenCascadeKernel::convert(l->Location(),o); +// bool hasRef = l->hasRefDirection(); +// if ( l->hasAxis() ) IfcGeom::OpenCascadeKernel::convert(l->Axis(),axis); +// if ( hasRef ) IfcGeom::OpenCascadeKernel::convert(l->RefDirection(),refDirection); +// gp_Ax3 ax3; +// if ( hasRef ) ax3 = gp_Ax3(o,axis,refDirection); +// else ax3 = gp_Ax3(o,axis); +// +// if (!axis_equal(ax3, (gp_Ax3) gp::XOY(), getValue(GV_PRECISION))) { +// trsf.SetTransformation(ax3, gp::XOY()); +// } +// +// CACHE(IfcAxis2Placement3D,l,trsf) + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcObjectPlacement* l, cgal_placement_t& trsf) { +// IN_CACHE(IfcObjectPlacement,l,cgal_placement_t,trsf) + if ( ! l->is(IfcSchema::Type::IfcLocalPlacement) ) { + Logger::Message(Logger::LOG_ERROR, "Unsupported IfcObjectPlacement:", l->entity); + return false; + } + IfcSchema::IfcLocalPlacement* current = (IfcSchema::IfcLocalPlacement*)l; + for (;;) { + cgal_placement_t trsf2; + IfcSchema::IfcAxis2Placement* relplacement = current->RelativePlacement(); + if ( relplacement->is(IfcSchema::Type::IfcAxis2Placement3D) ) { + IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement3D*)relplacement,trsf2); + *trsf = *trsf * *trsf2; // TODO: Or should it be the other way around? + } + if ( current->hasPlacementRelTo() ) { + IfcSchema::IfcObjectPlacement* relto = current->PlacementRelTo(); + if ( relto->is(IfcSchema::Type::IfcLocalPlacement) ) + current = (IfcSchema::IfcLocalPlacement*)current->PlacementRelTo(); + else break; + } else break; + } +// CACHE(IfcObjectPlacement,l,trsf) + return true; +} diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index d8e39626d2..a3c68c56ea 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -44,3 +44,6 @@ WIRE(IfcPolyLoop); CLASS(IfcCartesianPoint,cgal_point_t); CLASS(IfcDirection,cgal_direction_t); +//CLASS(IfcAxis2Placement2D,cgal_placement_t); +CLASS(IfcAxis2Placement3D,cgal_placement_t); +CLASS(IfcObjectPlacement,cgal_placement_t); diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.cpp b/src/ifcgeom/kernels/cgal/CgalKernel.cpp index f4f830cbee..73f9bd761e 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.cpp +++ b/src/ifcgeom/kernels/cgal/CgalKernel.cpp @@ -94,7 +94,7 @@ IfcGeom::NativeElement* IfcGeom::CgalKernel::create_brep_for_representat cgal_placement_t trsf; try { - // convert(product->ObjectPlacement(), trsf); + convert(product->ObjectPlacement(), trsf); } catch (...) {} // Does the IfcElement have any IfcOpenings? @@ -146,7 +146,7 @@ IfcGeom::NativeElement* IfcGeom::CgalKernel::create_brep_for_processed_r cgal_placement_t trsf; try { - // convert(product->ObjectPlacement(), trsf); + convert(product->ObjectPlacement(), trsf); } catch (...) {} std::string context_string = ""; From 42b512960b32c39427ed4c395b5688e216625bce Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 7 Feb 2017 20:25:04 -0600 Subject: [PATCH 13/25] Filling in most of the placement code. To check. --- .../kernels/cgal/CgalConversionFunctions.cpp | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 3320c606e0..94f694dcdd 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -51,24 +51,25 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcDirection* l, cgal_directi bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement3D* l, cgal_placement_t& trsf) { // IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf) -// cgal_point_t o;cgal_direction_t axis = new Kernel::Vector_3(0,0,1);cgal_direction_t refDirection; -// IfcGeom::OpenCascadeKernel::convert(l->Location(),o); -// bool hasRef = l->hasRefDirection(); -// if ( l->hasAxis() ) IfcGeom::OpenCascadeKernel::convert(l->Axis(),axis); -// if ( hasRef ) IfcGeom::OpenCascadeKernel::convert(l->RefDirection(),refDirection); -// gp_Ax3 ax3; -// if ( hasRef ) ax3 = gp_Ax3(o,axis,refDirection); -// else ax3 = gp_Ax3(o,axis); -// -// if (!axis_equal(ax3, (gp_Ax3) gp::XOY(), getValue(GV_PRECISION))) { -// trsf.SetTransformation(ax3, gp::XOY()); -// } -// + cgal_point_t o; + cgal_direction_t axis = new Kernel::Vector_3(0,0,1); + cgal_direction_t refDirection = new Kernel::Vector_3(1,0,0); // TODO: Put identity for now. Check? + IfcGeom::CgalKernel::convert(l->Location(),o); + bool hasRef = l->hasRefDirection(); + if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(),axis); + if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection); + + // TODO: From Thomas' email. Should be checked. + trsf = new Kernel::Aff_transformation_3(refDirection->cartesian(0), axis->cartesian(0)*refDirection->cartesian(0), axis->cartesian(0), o->cartesian(0), + refDirection->cartesian(1), axis->cartesian(1)*refDirection->cartesian(1), axis->cartesian(1), o->cartesian(1), + refDirection->cartesian(2), axis->cartesian(2)*refDirection->cartesian(2), axis->cartesian(2), o->cartesian(2)); + // CACHE(IfcAxis2Placement3D,l,trsf) return true; } bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcObjectPlacement* l, cgal_placement_t& trsf) { + // TODO: These macros don't work for the CGAL types. Need to check why. // IN_CACHE(IfcObjectPlacement,l,cgal_placement_t,trsf) if ( ! l->is(IfcSchema::Type::IfcLocalPlacement) ) { Logger::Message(Logger::LOG_ERROR, "Unsupported IfcObjectPlacement:", l->entity); @@ -80,7 +81,13 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcObjectPlacement* l, cgal_p IfcSchema::IfcAxis2Placement* relplacement = current->RelativePlacement(); if ( relplacement->is(IfcSchema::Type::IfcAxis2Placement3D) ) { IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement3D*)relplacement,trsf2); - *trsf = *trsf * *trsf2; // TODO: Or should it be the other way around? + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + std::cout << "trsf " << trsf->m(i, j) << std::endl; + } + } +// std::cout << "trsf2" << trsf2 << std::endl; + *trsf = *trsf * *trsf2; // TODO: I think it's fine, but maybe should it be the other way around? } if ( current->hasPlacementRelTo() ) { IfcSchema::IfcObjectPlacement* relto = current->PlacementRelTo(); From 2894b0cb92f45d332ac013f8d68a5136fc4fb541 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 7 Feb 2017 20:37:47 -0600 Subject: [PATCH 14/25] =?UTF-8?q?Nothing=20is=20a=20pointer=20now.=20Initi?= =?UTF-8?q?alisation=20is=20easier=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kernels/cgal/CgalConversionFunctions.cpp | 30 ++++++++----------- .../kernels/cgal/CgalConversionResult.h | 4 +-- .../kernels/cgal/CgalEntityMapping.cpp | 19 ++++++------ src/ifcgeom/kernels/cgal/CgalKernel.h | 17 +++++------ 4 files changed, 31 insertions(+), 39 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 94f694dcdd..10b2bc49ec 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -30,9 +30,9 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid*, cgal_s bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianPoint* l, cgal_point_t& point) { std::vector xyz = l->Coordinates(); if (xyz.size() == 3) { - point = new Kernel::Point_3(xyz.size() ? (xyz[0]*getValue(GV_LENGTH_UNIT)) : 0.0f, - xyz.size() > 1 ? (xyz[1]*getValue(GV_LENGTH_UNIT)) : 0.0f, - xyz.size() > 2 ? (xyz[2]*getValue(GV_LENGTH_UNIT)) : 0.0f); + point = Kernel::Point_3(xyz.size() ? (xyz[0]*getValue(GV_LENGTH_UNIT)) : 0.0f, + xyz.size() > 1 ? (xyz[1]*getValue(GV_LENGTH_UNIT)) : 0.0f, + xyz.size() > 2 ? (xyz[2]*getValue(GV_LENGTH_UNIT)) : 0.0f); return true; } else { throw std::runtime_error("Point without 3 coordinates"); @@ -42,9 +42,9 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianPoint* l, cgal_po bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcDirection* l, cgal_direction_t& dir) { // IN_CACHE(IfcDirection,l,cgal_direction_t,dir) std::vector xyz = l->DirectionRatios(); - dir = new Kernel::Vector_3(xyz.size() ? xyz[0] : 0.0f, - xyz.size() > 1 ? xyz[1] : 0.0f, - xyz.size() > 2 ? xyz[2] : 0.0f); + dir = Kernel::Vector_3(xyz.size() ? xyz[0] : 0.0f, + xyz.size() > 1 ? xyz[1] : 0.0f, + xyz.size() > 2 ? xyz[2] : 0.0f); // CACHE(IfcDirection,l,dir) return true; } @@ -52,17 +52,17 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcDirection* l, cgal_directi bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement3D* l, cgal_placement_t& trsf) { // IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf) cgal_point_t o; - cgal_direction_t axis = new Kernel::Vector_3(0,0,1); - cgal_direction_t refDirection = new Kernel::Vector_3(1,0,0); // TODO: Put identity for now. Check? + cgal_direction_t axis = Kernel::Vector_3(0,0,1); + cgal_direction_t refDirection = Kernel::Vector_3(1,0,0); // TODO: Put identity for now. Check? IfcGeom::CgalKernel::convert(l->Location(),o); bool hasRef = l->hasRefDirection(); if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(),axis); if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection); // TODO: From Thomas' email. Should be checked. - trsf = new Kernel::Aff_transformation_3(refDirection->cartesian(0), axis->cartesian(0)*refDirection->cartesian(0), axis->cartesian(0), o->cartesian(0), - refDirection->cartesian(1), axis->cartesian(1)*refDirection->cartesian(1), axis->cartesian(1), o->cartesian(1), - refDirection->cartesian(2), axis->cartesian(2)*refDirection->cartesian(2), axis->cartesian(2), o->cartesian(2)); + trsf = Kernel::Aff_transformation_3(refDirection.cartesian(0), axis.cartesian(0)*refDirection.cartesian(0), axis.cartesian(0), o.cartesian(0), + refDirection.cartesian(1), axis.cartesian(1)*refDirection.cartesian(1), axis.cartesian(1), o.cartesian(1), + refDirection.cartesian(2), axis.cartesian(2)*refDirection.cartesian(2), axis.cartesian(2), o.cartesian(2)); // CACHE(IfcAxis2Placement3D,l,trsf) return true; @@ -81,13 +81,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcObjectPlacement* l, cgal_p IfcSchema::IfcAxis2Placement* relplacement = current->RelativePlacement(); if ( relplacement->is(IfcSchema::Type::IfcAxis2Placement3D) ) { IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement3D*)relplacement,trsf2); - for (int i = 0; i < 3; ++i) { - for (int j = 0; j < 3; ++j) { - std::cout << "trsf " << trsf->m(i, j) << std::endl; - } - } -// std::cout << "trsf2" << trsf2 << std::endl; - *trsf = *trsf * *trsf2; // TODO: I think it's fine, but maybe should it be the other way around? + trsf = trsf * trsf2; // TODO: I think it's fine, but maybe should it be the other way around? } if ( current->hasPlacementRelTo() ) { IfcSchema::IfcObjectPlacement* relto = current->PlacementRelTo(); diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.h b/src/ifcgeom/kernels/cgal/CgalConversionResult.h index 92c80dc32a..b20c8c8858 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.h +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.h @@ -35,7 +35,7 @@ namespace IfcGeom { 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. - return CGAL::to_double(trsf_->cartesian(i, j)); + return CGAL::to_double(trsf_.cartesian(i, j)); } virtual void Multiply(const ConversionResultPlacement* other) { // Multiply matrix as implemented in OCCT. We'll have to check exact semantics. @@ -74,4 +74,4 @@ namespace IfcGeom { } -#endif \ No newline at end of file +#endif diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp index dea961cf7c..6366590c8d 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp @@ -146,9 +146,9 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_ // } // } - cgal_shape_t polyhedron = new CGAL::Polyhedron_3(); + cgal_shape_t polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); - polyhedron->delegate(builder); + polyhedron.delegate(builder); shape = polyhedron; return true; @@ -181,7 +181,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcFace* l, cgal_face_t& face return false; } - cgal_face_t mf = new CgalFace(); + cgal_face_t mf; for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) { IfcSchema::IfcFaceBound* bound = *it; @@ -192,14 +192,13 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcFace* l, cgal_face_t& face cgal_wire_t wire; if (!convert_wire(loop, wire)) { Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary loop", loop->entity); - delete mf; return false; } if (!is_interior) { - mf->outer = wire; + mf.outer = wire; } else { - mf->inner.push_back(wire); + mf.inner.push_back(wire); } } @@ -211,15 +210,15 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& IfcSchema::IfcCartesianPoint::list::ptr points = l->Polygon(); // Parse and store the points in a sequence - cgal_wire_t polygon = new std::vector(); + cgal_wire_t polygon = std::vector(); for(IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it) { cgal_point_t pnt; IfcGeom::CgalKernel::convert(*it, pnt); - polygon->push_back(*pnt); + polygon.push_back(pnt); } // A loop should consist of at least three vertices - std::size_t original_count = polygon->size(); + std::size_t original_count = polygon.size(); if (original_count < 3) { Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity); return false; @@ -228,7 +227,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& // TODO: Remove repeated points (and points that are too close to one another?) // remove_duplicate_points_from_loop(polygon, true); - std::size_t count = polygon->size(); + std::size_t count = polygon.size(); if (original_count - count != 0) { std::stringstream ss; ss << (original_count - count) << " edges removed for:"; Logger::Message(Logger::LOG_WARNING, ss.str(), l->entity); diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index 638344c7d8..48d7aea233 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -44,19 +44,18 @@ if ( it != cache.T.end() ) { e = it->second; return true; } typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; -typedef Kernel::Aff_transformation_3 *cgal_placement_t; -typedef Kernel::Point_3 *cgal_point_t; -typedef Kernel::Vector_3 *cgal_direction_t; -typedef std::vector *cgal_curve_t; -typedef std::vector *cgal_wire_t; +typedef Kernel::Aff_transformation_3 cgal_placement_t; +typedef Kernel::Point_3 cgal_point_t; +typedef Kernel::Vector_3 cgal_direction_t; +typedef std::vector cgal_curve_t; +typedef std::vector cgal_wire_t; -struct CgalFace { +struct cgal_face_t { cgal_wire_t outer; std::vector inner; }; -typedef CgalFace *cgal_face_t; -typedef CGAL::Polyhedron_3 *cgal_shape_t; +typedef CGAL::Polyhedron_3 cgal_shape_t; struct PolyhedronBuilder : public CGAL::Modifier_base::HalfedgeDS> { private: @@ -73,7 +72,7 @@ public: for (auto const &face: *face_list) { facet_vertices.push_back(std::list()); - for (auto const &point: *face->outer) { + for (auto const &point: face.outer) { if (points_map.count(point) == 0) { facet_vertices.back().push_back(points_map.size()); points_map[point] = points_map.size(); From 7051104bc7f564e35da81f134079fa48ac925865 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Wed, 8 Feb 2017 16:12:19 -0600 Subject: [PATCH 15/25] Basic code to output triangulation, something goes wrong when getting materials... --- .../kernels/cgal/CgalConversionResult.cpp | 179 +++++++++++++++++- .../kernels/cgal/CgalEntityMapping.cpp | 14 -- src/ifcgeom/kernels/cgal/CgalKernel.h | 16 +- 3 files changed, 189 insertions(+), 20 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index e2da8ecd97..81fd474622 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -2,5 +2,182 @@ #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()"); + cgal_shape_t s = shape_; + const cgal_placement_t& trsf = dynamic_cast(place)->trsf(); + + // Triangulate the shape and compute the normals + std::map vertex_normals; + boost::associative_property_map> vertex_normals_map(vertex_normals); + std::map face_normals; + boost::associative_property_map> face_normals_map(face_normals); + try { + CGAL::Polygon_mesh_processing::triangulate_faces(s); + CGAL::Polygon_mesh_processing::compute_normals(s, vertex_normals_map, face_normals_map); + } catch (...) { + + // TODO: Catch outside + // Logger::Message(Logger::LOG_ERROR,"Failed to triangulate shape:",ifc_file->entityById(_id)->entity); + Logger::Message(Logger::LOG_ERROR, "Failed to triangulate shape"); + return; + } + + // Iterates over the faces of the shape + int num_faces = 0, num_vertices = 0; +// TopExp_Explorer exp; + for (auto &face: faces(s)) { + CGAL::Polyhedron_3::Halfedge_around_facet_const_circulator current_halfedge = face->facet_begin(); + do { + t->addVertex(surface_style_id, + CGAL::to_double(current_halfedge->vertex()->point().cartesian(0)), + CGAL::to_double(current_halfedge->vertex()->point().cartesian(1)), + CGAL::to_double(current_halfedge->vertex()->point().cartesian(2))); + for (int i = 0; i < 3; ++i) t->normals().push_back(CGAL::to_double(face_normals_map[face].cartesian(i))); + t->faces().push_back(num_vertices); + ++num_vertices; + ++current_halfedge; + } while (current_halfedge != face->facet_begin()); + t->material_ids().push_back(surface_style_id); + ++num_faces; + +// TopLoc_Location loc; +// Handle_Poly_Triangulation tri = BRep_Tool::Triangulation(face, loc); +// +// if (!tri.IsNull()) { +// +// // A 3x3 matrix to rotate the vertex normals +// const gp_Mat rotation_matrix = trsf.VectorialPart(); +// +// // Keep track of the number of times an edge is used +// // Manifold edges (i.e. edges used twice) are deemed invisible +// std::map, int> edgecount; +// std::vector > edges_temp; +// +// const TColgp_Array1OfPnt& nodes = tri->Nodes(); +// const TColgp_Array1OfPnt2d& uvs = tri->UVNodes(); +// std::vector coords; +// BRepGProp_Face prop(face); +// std::map dict; +// +// // Vertex normals are only calculated if vertices are not welded and calculation is not disable explicitly. +// const bool calculate_normals = !settings.get(IteratorSettings::WELD_VERTICES) && +// !settings.get(IteratorSettings::NO_NORMALS); +// +// for (int i = 1; i <= nodes.Length(); ++i) { +// coords.push_back(nodes(i).Transformed(loc).XYZ()); +// trsf.Transforms(*coords.rbegin()); +// const gp_XYZ& last = *coords.rbegin(); +// dict[i] = t->addVertex(surface_style_id, last.X(), last.Y(), last.Z()); +// +// if (calculate_normals) { +// const gp_Pnt2d& uv = uvs(i); +// gp_Pnt p; +// gp_Vec normal_direction; +// prop.Normal(uv.X(), uv.Y(), p, normal_direction); +// gp_Vec normal(0., 0., 0.); +// if (normal_direction.Magnitude() > ALMOST_ZERO) { +// normal = gp_Dir(normal_direction.XYZ() * rotation_matrix); +// } +// t->normals().push_back(static_cast(normal.X())); +// t->normals().push_back(static_cast(normal.Y())); +// t->normals().push_back(static_cast(normal.Z())); +// } +// } +// +// const Poly_Array1OfTriangle& triangles = tri->Triangles(); +// for (int i = 1; i <= triangles.Length(); ++i) { +// int n1, n2, n3; +// if (face.Orientation() == TopAbs_REVERSED) +// triangles(i).Get(n3, n2, n1); +// else triangles(i).Get(n1, n2, n3); +// +// t->faces().push_back(dict[n1]); +// t->faces().push_back(dict[n2]); +// t->faces().push_back(dict[n3]); +// +// t->material_ids().push_back(surface_style_id); +// +// t->addEdge(dict[n1], dict[n2], edgecount, edges_temp); +// t->addEdge(dict[n2], dict[n3], edgecount, edges_temp); +// t->addEdge(dict[n3], dict[n1], edgecount, edges_temp); +// } +// for (std::vector >::const_iterator jt = edges_temp.begin(); jt != edges_temp.end(); ++jt) { +// if (edgecount[*jt] == 1) { +// // non manifold edge, face boundary +// t->edges().push_back(jt->first); +// t->edges().push_back(jt->second); +// } +// } +// } + } +// +// if (num_faces == 0) { +// // Edges are only emitted if there are no faces. A mixed representation of faces +// // and loose edges is discouraged by the standard. An alternative would be to use +// // TopExp_Explorer texp(s, TopAbs_EDGE, TopAbs_FACE) to find edges that do not +// // belong to any face. +// for (TopExp_Explorer texp(s, TopAbs_EDGE); texp.More(); texp.Next()) { +// BRepAdaptor_Curve crv(TopoDS::Edge(texp.Current())); +// GCPnts_QuasiUniformDeflection tessellater(crv, settings.deflection_tolerance()); +// int n = tessellater.NbPoints(); +// int start = (int)t->verts().size() / 3; +// for (int i = 1; i <= n; ++i) { +// gp_XYZ p = tessellater.Value(i).XYZ(); +// +// /* +// // In case you want direction arrows on your edges +// double u = tessellater.Parameter(i); +// gp_XYZ p2, p3; +// gp_Pnt tmp; +// gp_Vec tmp2; +// crv.D1(u, tmp, tmp2); +// gp_Dir d1, d2, d3, d4; +// d1 = tmp2; +// if (texp.Current().Orientation() == TopAbs_REVERSED) { +// d1 = -d1; +// } +// if (fabs(d1.Z()) < 0.5) { +// d2 = d1.Crossed(gp::DZ()); +// } else { +// d2 = d1.Crossed(gp::DY()); +// } +// d3 = d1.XYZ() + d2.XYZ(); +// d4 = d1.XYZ() - d2.XYZ(); +// p2 = p - d3.XYZ() / 10.; +// p3 = p - d4.XYZ() / 10.; +// trsf.Transforms(p2); +// trsf.Transforms(p3); +// _material_ids.push_back(surface_style_id); +// _material_ids.push_back(surface_style_id); +// _verts.push_back(static_cast

(p2.X())); +// _verts.push_back(static_cast

(p2.Y())); +// _verts.push_back(static_cast

(p2.Z())); +// _verts.push_back(static_cast

(p3.X())); +// _verts.push_back(static_cast

(p3.Y())); +// _verts.push_back(static_cast

(p3.Z())); +// */ +// +// trsf.Transforms(p); +// +// t->material_ids().push_back(surface_style_id); +// +// t->verts().push_back(static_cast(p.X())); +// t->verts().push_back(static_cast(p.Y())); +// t->verts().push_back(static_cast(p.Z())); +// +// if (i > 1) { +// t->edges().push_back(start + i - 2); +// t->edges().push_back(start + i - 1); +// // _edges.push_back(start + 3 * (i - 2) + 2); +// // _edges.push_back(start + 3 * (i - 1) + 2); +// } +// +// // _edges.push_back(start + 3 * (i - 1) + 0); +// // _edges.push_back(start + 3 * (i - 1) + 2); +// // _edges.push_back(start + 3 * (i - 1) + 1); +// // _edges.push_back(start + 3 * (i - 1) + 2); +// } +// } +// } +// +// BRepTools::Clean(s); } diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp index 6366590c8d..996926c978 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp @@ -132,20 +132,6 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_ face_list.push_back(face); } -// for (auto const &face : face_list) { -// std::cout << "Face" << std::endl; -// std::cout << "\touter: "; -// for (auto const &point: *face->outer) { -// std::cout << "(" << point << ") "; -// } std::cout << std::endl; -// for (auto const &inner: face->inner) { -// std::cout << "\tinner: "; -// for (auto const &point: *inner) { -// std::cout << "(" << point << ") "; -// } std::cout << std::endl; -// } -// } - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index 48d7aea233..596fcacf4e 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -39,8 +39,12 @@ if ( it != cache.T.end() ) { e = it->second; return true; } #undef Handle +#include #include #include +#include +#include +#include typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; @@ -56,6 +60,8 @@ struct cgal_face_t { }; typedef CGAL::Polyhedron_3 cgal_shape_t; +typedef boost::graph_traits>::vertex_descriptor cgal_vertex_descriptor_t; +typedef boost::graph_traits>::face_descriptor cgal_face_descriptor_t; struct PolyhedronBuilder : public CGAL::Modifier_base::HalfedgeDS> { private: @@ -70,9 +76,9 @@ public: std::list> facet_vertices; CGAL::Polyhedron_incremental_builder_3::HalfedgeDS> builder(hds, true); - for (auto const &face: *face_list) { + for (auto &face: *face_list) { facet_vertices.push_back(std::list()); - for (auto const &point: face.outer) { + for (auto &point: face.outer) { if (points_map.count(point) == 0) { facet_vertices.back().push_back(points_map.size()); points_map[point] = points_map.size(); @@ -84,15 +90,15 @@ public: builder.begin_surface(points_map.size(), facet_vertices.size()); - for (auto const &point: points_map) { + for (auto &point: points_map) { // std::cout << "Adding point " << point.first << std::endl; builder.add_vertex(point.first); } - for (auto const &facet: facet_vertices) { + for (auto &facet: facet_vertices) { builder.begin_facet(); // std::cout << "Adding facet "; - for (auto const &vertex: facet) { + for (auto &vertex: facet) { // std::cout << vertex << " "; builder.add_vertex_to_facet(vertex); } From 1755752ab75860679dab3f022e43f6e64e1dd4b9 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Wed, 8 Feb 2017 16:56:59 -0600 Subject: [PATCH 16/25] IfcAxis2Placement2D --- .../kernels/cgal/CgalConversionFunctions.cpp | 26 ++- .../kernels/cgal/CgalConversionResult.cpp | 151 +----------------- .../kernels/cgal/CgalConversionResult.h | 10 +- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 2 +- 4 files changed, 37 insertions(+), 152 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 10b2bc49ec..1a488a274a 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -49,6 +49,25 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcDirection* l, cgal_directi return true; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement2D* l, cgal_placement_t& trsf) { + // IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf) + cgal_point_t o; + cgal_direction_t axis = Kernel::Vector_3(0,0,1); + cgal_direction_t refDirection = Kernel::Vector_3(1,0,0); // TODO: Put identity for now. Check? + IfcGeom::CgalKernel::convert(l->Location(),o); + bool hasRef = l->hasRefDirection(); + if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection); + + // TODO: From Thomas' email. Should be checked. + Kernel::Vector_3 y = CGAL::cross_product(Kernel::Vector_3(0.0, 0.0, 1.0), refDirection); + trsf = Kernel::Aff_transformation_3(refDirection.cartesian(0), y.cartesian(0), 0.0, o.cartesian(0), + refDirection.cartesian(1), y.cartesian(1), 0.0, o.cartesian(1), + 0.0, y.cartesian(2), 1.0, 0.0); + + // CACHE(IfcAxis2Placement3D,l,trsf) + return true; +} + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement3D* l, cgal_placement_t& trsf) { // IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf) cgal_point_t o; @@ -60,9 +79,10 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement3D* l, cgal_ if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection); // TODO: From Thomas' email. Should be checked. - trsf = Kernel::Aff_transformation_3(refDirection.cartesian(0), axis.cartesian(0)*refDirection.cartesian(0), axis.cartesian(0), o.cartesian(0), - refDirection.cartesian(1), axis.cartesian(1)*refDirection.cartesian(1), axis.cartesian(1), o.cartesian(1), - refDirection.cartesian(2), axis.cartesian(2)*refDirection.cartesian(2), axis.cartesian(2), o.cartesian(2)); + Kernel::Vector_3 y = CGAL::cross_product(axis, refDirection); + trsf = Kernel::Aff_transformation_3(refDirection.cartesian(0), y.cartesian(0), axis.cartesian(0), o.cartesian(0), + refDirection.cartesian(1), y.cartesian(1), axis.cartesian(1), o.cartesian(1), + refDirection.cartesian(2), y.cartesian(2), axis.cartesian(2), o.cartesian(2)); // CACHE(IfcAxis2Placement3D,l,trsf) return true; diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index 81fd474622..529e692abb 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -5,6 +5,11 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, cgal_shape_t s = shape_; const cgal_placement_t& trsf = dynamic_cast(place)->trsf(); + // Apply transformation + for (auto &vertex: vertices(s)) { + vertex->point() = vertex->point().transform(trsf); + } + // Triangulate the shape and compute the normals std::map vertex_normals; boost::associative_property_map> vertex_normals_map(vertex_normals); @@ -23,7 +28,6 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, // Iterates over the faces of the shape int num_faces = 0, num_vertices = 0; -// TopExp_Explorer exp; for (auto &face: faces(s)) { CGAL::Polyhedron_3::Halfedge_around_facet_const_circulator current_halfedge = face->facet_begin(); do { @@ -32,152 +36,11 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, CGAL::to_double(current_halfedge->vertex()->point().cartesian(1)), CGAL::to_double(current_halfedge->vertex()->point().cartesian(2))); for (int i = 0; i < 3; ++i) t->normals().push_back(CGAL::to_double(face_normals_map[face].cartesian(i))); - t->faces().push_back(num_vertices); +// t->faces().push_back(num_vertices); ++num_vertices; ++current_halfedge; } while (current_halfedge != face->facet_begin()); - t->material_ids().push_back(surface_style_id); +// t->material_ids().push_back(surface_style_id); ++num_faces; - -// TopLoc_Location loc; -// Handle_Poly_Triangulation tri = BRep_Tool::Triangulation(face, loc); -// -// if (!tri.IsNull()) { -// -// // A 3x3 matrix to rotate the vertex normals -// const gp_Mat rotation_matrix = trsf.VectorialPart(); -// -// // Keep track of the number of times an edge is used -// // Manifold edges (i.e. edges used twice) are deemed invisible -// std::map, int> edgecount; -// std::vector > edges_temp; -// -// const TColgp_Array1OfPnt& nodes = tri->Nodes(); -// const TColgp_Array1OfPnt2d& uvs = tri->UVNodes(); -// std::vector coords; -// BRepGProp_Face prop(face); -// std::map dict; -// -// // Vertex normals are only calculated if vertices are not welded and calculation is not disable explicitly. -// const bool calculate_normals = !settings.get(IteratorSettings::WELD_VERTICES) && -// !settings.get(IteratorSettings::NO_NORMALS); -// -// for (int i = 1; i <= nodes.Length(); ++i) { -// coords.push_back(nodes(i).Transformed(loc).XYZ()); -// trsf.Transforms(*coords.rbegin()); -// const gp_XYZ& last = *coords.rbegin(); -// dict[i] = t->addVertex(surface_style_id, last.X(), last.Y(), last.Z()); -// -// if (calculate_normals) { -// const gp_Pnt2d& uv = uvs(i); -// gp_Pnt p; -// gp_Vec normal_direction; -// prop.Normal(uv.X(), uv.Y(), p, normal_direction); -// gp_Vec normal(0., 0., 0.); -// if (normal_direction.Magnitude() > ALMOST_ZERO) { -// normal = gp_Dir(normal_direction.XYZ() * rotation_matrix); -// } -// t->normals().push_back(static_cast(normal.X())); -// t->normals().push_back(static_cast(normal.Y())); -// t->normals().push_back(static_cast(normal.Z())); -// } -// } -// -// const Poly_Array1OfTriangle& triangles = tri->Triangles(); -// for (int i = 1; i <= triangles.Length(); ++i) { -// int n1, n2, n3; -// if (face.Orientation() == TopAbs_REVERSED) -// triangles(i).Get(n3, n2, n1); -// else triangles(i).Get(n1, n2, n3); -// -// t->faces().push_back(dict[n1]); -// t->faces().push_back(dict[n2]); -// t->faces().push_back(dict[n3]); -// -// t->material_ids().push_back(surface_style_id); -// -// t->addEdge(dict[n1], dict[n2], edgecount, edges_temp); -// t->addEdge(dict[n2], dict[n3], edgecount, edges_temp); -// t->addEdge(dict[n3], dict[n1], edgecount, edges_temp); -// } -// for (std::vector >::const_iterator jt = edges_temp.begin(); jt != edges_temp.end(); ++jt) { -// if (edgecount[*jt] == 1) { -// // non manifold edge, face boundary -// t->edges().push_back(jt->first); -// t->edges().push_back(jt->second); -// } -// } -// } } -// -// if (num_faces == 0) { -// // Edges are only emitted if there are no faces. A mixed representation of faces -// // and loose edges is discouraged by the standard. An alternative would be to use -// // TopExp_Explorer texp(s, TopAbs_EDGE, TopAbs_FACE) to find edges that do not -// // belong to any face. -// for (TopExp_Explorer texp(s, TopAbs_EDGE); texp.More(); texp.Next()) { -// BRepAdaptor_Curve crv(TopoDS::Edge(texp.Current())); -// GCPnts_QuasiUniformDeflection tessellater(crv, settings.deflection_tolerance()); -// int n = tessellater.NbPoints(); -// int start = (int)t->verts().size() / 3; -// for (int i = 1; i <= n; ++i) { -// gp_XYZ p = tessellater.Value(i).XYZ(); -// -// /* -// // In case you want direction arrows on your edges -// double u = tessellater.Parameter(i); -// gp_XYZ p2, p3; -// gp_Pnt tmp; -// gp_Vec tmp2; -// crv.D1(u, tmp, tmp2); -// gp_Dir d1, d2, d3, d4; -// d1 = tmp2; -// if (texp.Current().Orientation() == TopAbs_REVERSED) { -// d1 = -d1; -// } -// if (fabs(d1.Z()) < 0.5) { -// d2 = d1.Crossed(gp::DZ()); -// } else { -// d2 = d1.Crossed(gp::DY()); -// } -// d3 = d1.XYZ() + d2.XYZ(); -// d4 = d1.XYZ() - d2.XYZ(); -// p2 = p - d3.XYZ() / 10.; -// p3 = p - d4.XYZ() / 10.; -// trsf.Transforms(p2); -// trsf.Transforms(p3); -// _material_ids.push_back(surface_style_id); -// _material_ids.push_back(surface_style_id); -// _verts.push_back(static_cast

(p2.X())); -// _verts.push_back(static_cast

(p2.Y())); -// _verts.push_back(static_cast

(p2.Z())); -// _verts.push_back(static_cast

(p3.X())); -// _verts.push_back(static_cast

(p3.Y())); -// _verts.push_back(static_cast

(p3.Z())); -// */ -// -// trsf.Transforms(p); -// -// t->material_ids().push_back(surface_style_id); -// -// t->verts().push_back(static_cast(p.X())); -// t->verts().push_back(static_cast(p.Y())); -// t->verts().push_back(static_cast(p.Z())); -// -// if (i > 1) { -// t->edges().push_back(start + i - 2); -// t->edges().push_back(start + i - 1); -// // _edges.push_back(start + 3 * (i - 2) + 2); -// // _edges.push_back(start + 3 * (i - 1) + 2); -// } -// -// // _edges.push_back(start + 3 * (i - 1) + 0); -// // _edges.push_back(start + 3 * (i - 1) + 2); -// // _edges.push_back(start + 3 * (i - 1) + 1); -// // _edges.push_back(start + 3 * (i - 1) + 2); -// } -// } -// } -// -// BRepTools::Clean(s); } diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.h b/src/ifcgeom/kernels/cgal/CgalConversionResult.h index b20c8c8858..6a6e6157e8 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.h +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.h @@ -1,4 +1,4 @@ -/******************************************************************************** +/******************************************************************************** * * * This file is part of IfcOpenShell. * * * @@ -34,15 +34,17 @@ namespace IfcGeom { 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. + // TODO: Check return CGAL::to_double(trsf_.cartesian(i, j)); } virtual void Multiply(const ConversionResultPlacement* other) { - // Multiply matrix as implemented in OCCT. We'll have to check exact semantics. + // TODO: Check + trsf_ = ((CgalPlacement *)other)->trsf_ * trsf_; 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. + // TODO: Check + trsf_ = trsf_ * ((CgalPlacement *)other)->trsf_; throw std::runtime_error("Not implemented"); } virtual ConversionResultPlacement* clone() const { diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index a3c68c56ea..ddfab3fc5a 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -44,6 +44,6 @@ WIRE(IfcPolyLoop); CLASS(IfcCartesianPoint,cgal_point_t); CLASS(IfcDirection,cgal_direction_t); -//CLASS(IfcAxis2Placement2D,cgal_placement_t); +CLASS(IfcAxis2Placement2D,cgal_placement_t); CLASS(IfcAxis2Placement3D,cgal_placement_t); CLASS(IfcObjectPlacement,cgal_placement_t); From 44634eb42dbef7ffe41504ae88529d04b691f7d3 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Wed, 8 Feb 2017 17:12:56 -0600 Subject: [PATCH 17/25] Remove implemented throws, add faces and materials --- src/ifcgeom/kernels/cgal/CgalConversionResult.cpp | 10 +++++----- src/ifcgeom/kernels/cgal/CgalConversionResult.h | 2 -- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index 529e692abb..7f16e43073 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -6,9 +6,9 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, const cgal_placement_t& trsf = dynamic_cast(place)->trsf(); // Apply transformation - for (auto &vertex: vertices(s)) { - vertex->point() = vertex->point().transform(trsf); - } +// for (auto &vertex: vertices(s)) { +// vertex->point() = vertex->point().transform(trsf); +// } // Triangulate the shape and compute the normals std::map vertex_normals; @@ -36,11 +36,11 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, CGAL::to_double(current_halfedge->vertex()->point().cartesian(1)), CGAL::to_double(current_halfedge->vertex()->point().cartesian(2))); for (int i = 0; i < 3; ++i) t->normals().push_back(CGAL::to_double(face_normals_map[face].cartesian(i))); -// t->faces().push_back(num_vertices); + t->faces().push_back(num_vertices); ++num_vertices; ++current_halfedge; } while (current_halfedge != face->facet_begin()); -// t->material_ids().push_back(surface_style_id); + t->material_ids().push_back(surface_style_id); ++num_faces; } } diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.h b/src/ifcgeom/kernels/cgal/CgalConversionResult.h index 6a6e6157e8..940a598b67 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.h +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.h @@ -40,12 +40,10 @@ namespace IfcGeom { virtual void Multiply(const ConversionResultPlacement* other) { // TODO: Check trsf_ = ((CgalPlacement *)other)->trsf_ * trsf_; - throw std::runtime_error("Not implemented"); } virtual void PreMultiply(const ConversionResultPlacement* other) { // TODO: Check trsf_ = trsf_ * ((CgalPlacement *)other)->trsf_; - throw std::runtime_error("Not implemented"); } virtual ConversionResultPlacement* clone() const { return new CgalPlacement(trsf_); From b463dfe88a3327bba89c31b32800ec2d68742db6 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 9 Feb 2017 14:46:02 -0600 Subject: [PATCH 18/25] Changed --kernel parameter to --opencascade. Was conflicting with positional options for input. --- src/ifcconvert/IfcConvert.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 5b9057a73b..b64e8b508f 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -202,7 +202,8 @@ int main(int argc, char** argv) { "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'."); +// ("kernel", "Geometry kernel to use ('opencascade' or 'cgal'). Defaults to 'cgal'.") + ("opencascade", "Use opencascade kernel rather than cgal."); std::string bounds; boost::program_options::options_description serializer_options("Serialization options"); @@ -286,10 +287,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"; - } + if (vmap.count("opencascade") == 1) { + kernel = "opencascade"; + } else { + kernel = "cgal"; + } int bounding_width = -1, bounding_height = -1; if (vmap.count("bounds") == 1) { From f4274e4b465406e39c86b91fbbfe987a9d8ce97b Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 13 Feb 2017 11:12:04 -0600 Subject: [PATCH 19/25] Skeleton for IfcExtrudedAreaSolid --- .../kernels/cgal/CgalConversionFunctions.cpp | 80 ++++++++++++++++++- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 1a488a274a..60404f6828 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -23,8 +23,57 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRepresentation* l, Convers return part_succes; } -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid*, cgal_shape_t&) { - throw std::runtime_error("Not implemented IfcExtrudedAreaSolid"); +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal_shape_t &shape) { + const double height = l->Depth() * getValue(GV_LENGTH_UNIT); + if (height < getValue(GV_PRECISION)) { + Logger::Message(Logger::LOG_ERROR, "Non-positive extrusion height encountered for:", l->entity); + return false; + } + + cgal_face_t face; + if ( !convert_face(l->SweptArea(),face) ) return false; + + cgal_placement_t trsf; + bool has_position = true; +#ifdef USE_IFC4 + has_position = l->hasPosition(); +#endif + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf); + } + + cgal_direction_t dir; + convert(l->ExtrudedDirection(),dir); + + std::list face_list; + face_list.push_back(face); + + cgal_face_t top_face; + for (auto const &vertex: face.outer) { + top_face.outer.push_back(vertex+dir); + } face_list.push_back(top_face); + + for (std::vector::const_iterator current_vertex = face.outer.begin(); + current_vertex != face.outer.end(); + ++current_vertex) { + std::vector::const_iterator next_vertex = current_vertex; + ++next_vertex; + if (next_vertex == face.outer.end()) { + next_vertex = face.outer.begin(); + } cgal_face_t side_face; + side_face.outer.push_back(*current_vertex); + side_face.outer.push_back(*next_vertex); + side_face.outer.push_back(*next_vertex+dir); + side_face.outer.push_back(*current_vertex+dir); + face_list.push_back(side_face); + } + + cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + PolyhedronBuilder builder(&face_list); + polyhedron.delegate(builder); + + shape = polyhedron; + return true; } bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianPoint* l, cgal_point_t& point) { @@ -113,3 +162,30 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcObjectPlacement* l, cgal_p // CACHE(IfcObjectPlacement,l,trsf) return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangleProfileDef* l, cgal_face_t& face) { + const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT); + const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT); + + if ( x < ALMOST_ZERO || y < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + cgal_placement_t trsf2d; + bool has_position = true; +#ifdef USE_IFC4 + has_position = l->hasPosition(); +#endif + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + } + + face = cgal_face_t(); + face.outer.push_back(Kernel::Point_3(-x, -y, 0.0)); + face.outer.push_back(Kernel::Point_3( x, -y, 0.0)); + face.outer.push_back(Kernel::Point_3( x, y, 0.0)); + face.outer.push_back(Kernel::Point_3(-x, y, 0.0)); + + return true; +} diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index ddfab3fc5a..b163696066 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -39,6 +39,7 @@ SHAPE(IfcExtrudedAreaSolid); SHAPE(IfcConnectedFaceSet); FACE(IfcFace); +FACE(IfcRectangleProfileDef); WIRE(IfcPolyLoop); From d9d5f17725ba0f848f79560533031a7b9181ce4c Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 13 Feb 2017 11:45:17 -0600 Subject: [PATCH 20/25] Should be working now --- .../kernels/cgal/CgalConversionFunctions.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 60404f6828..6919a9319f 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -48,11 +48,6 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal std::list face_list; face_list.push_back(face); - cgal_face_t top_face; - for (auto const &vertex: face.outer) { - top_face.outer.push_back(vertex+dir); - } face_list.push_back(top_face); - for (std::vector::const_iterator current_vertex = face.outer.begin(); current_vertex != face.outer.end(); ++current_vertex) { @@ -61,13 +56,20 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal if (next_vertex == face.outer.end()) { next_vertex = face.outer.begin(); } cgal_face_t side_face; - side_face.outer.push_back(*current_vertex); side_face.outer.push_back(*next_vertex); - side_face.outer.push_back(*next_vertex+dir); + side_face.outer.push_back(*current_vertex); side_face.outer.push_back(*current_vertex+dir); + side_face.outer.push_back(*next_vertex+dir); face_list.push_back(side_face); } + cgal_face_t top_face; + for (std::vector::const_reverse_iterator vertex = face.outer.rbegin(); + vertex != face.outer.rend(); + ++vertex) { + top_face.outer.push_back(*vertex+dir); + } face_list.push_back(top_face); + cgal_shape_t polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); From 9d4463b73a0c3d84532ac404c7eb463fcb2035c5 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 13 Feb 2017 15:26:06 -0600 Subject: [PATCH 21/25] Check for NULL placement --- src/ifcgeom/kernels/cgal/CgalConversionResult.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index 7f16e43073..ebb7bb9c9c 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -6,9 +6,9 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, const cgal_placement_t& trsf = dynamic_cast(place)->trsf(); // Apply transformation -// for (auto &vertex: vertices(s)) { -// vertex->point() = vertex->point().transform(trsf); -// } + if (place != NULL) for (auto &vertex: vertices(s)) { + vertex->point() = vertex->point().transform(trsf); + } // Triangulate the shape and compute the normals std::map vertex_normals; From e47d128b180afcd9e8c2a084131020aa5a61af00 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 20 Feb 2017 20:14:49 -0600 Subject: [PATCH 22/25] Brep and swept solid working now --- src/ifcconvert/WavefrontObjSerializer.cpp | 1 + .../kernels/cgal/CgalConversionFunctions.cpp | 10 +++++++ .../kernels/cgal/CgalConversionResult.cpp | 16 +++++++----- .../kernels/cgal/CgalEntityMapping.cpp | 26 +++++++++++++++++++ src/ifcgeom/kernels/cgal/CgalKernel.h | 20 +++++++------- 5 files changed, 55 insertions(+), 18 deletions(-) diff --git a/src/ifcconvert/WavefrontObjSerializer.cpp b/src/ifcconvert/WavefrontObjSerializer.cpp index 54fd609265..52881e858f 100644 --- a/src/ifcconvert/WavefrontObjSerializer.cpp +++ b/src/ifcconvert/WavefrontObjSerializer.cpp @@ -108,6 +108,7 @@ void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement* const bool has_uvs = !mesh.uvs().empty(); const bool has_normals = !mesh.normals().empty(); +// std::cout << mesh.faces().size() << " vertices in face mesh" << std::endl; for ( std::vector::const_iterator it = mesh.faces().begin(); it != mesh.faces().end(); ) { const int material_id = *(material_it++); diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 6919a9319f..4121a7c783 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -70,10 +70,19 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal top_face.outer.push_back(*vertex+dir); } face_list.push_back(top_face); + // Naive creation cgal_shape_t polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); + // Stitch edges +// std::cout << "Before: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; + CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); + if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { + CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); + } +// std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; + shape = polyhedron; return true; } @@ -84,6 +93,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianPoint* l, cgal_po point = Kernel::Point_3(xyz.size() ? (xyz[0]*getValue(GV_LENGTH_UNIT)) : 0.0f, xyz.size() > 1 ? (xyz[1]*getValue(GV_LENGTH_UNIT)) : 0.0f, xyz.size() > 2 ? (xyz[2]*getValue(GV_LENGTH_UNIT)) : 0.0f); +// std::cout << "Converted Point(" << point << ")" << std::endl; return true; } else { throw std::runtime_error("Point without 3 coordinates"); diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index ebb7bb9c9c..59225e53f0 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -4,6 +4,8 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement * place, IfcGeom::Representation::Triangulation* t, int surface_style_id) const { cgal_shape_t s = shape_; const cgal_placement_t& trsf = dynamic_cast(place)->trsf(); +// std::cout << "Model: " << s.size_of_facets() << " facets and " << s.size_of_vertices() << " vertices" << std::endl; +// std::cout << "Valid: " << s.is_valid() << std::endl; // Apply transformation if (place != NULL) for (auto &vertex: vertices(s)) { @@ -15,17 +17,15 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, boost::associative_property_map> vertex_normals_map(vertex_normals); std::map face_normals; boost::associative_property_map> face_normals_map(face_normals); - try { - CGAL::Polygon_mesh_processing::triangulate_faces(s); - CGAL::Polygon_mesh_processing::compute_normals(s, vertex_normals_map, face_normals_map); - } catch (...) { - - // TODO: Catch outside - // Logger::Message(Logger::LOG_ERROR,"Failed to triangulate shape:",ifc_file->entityById(_id)->entity); + if (CGAL::Polygon_mesh_processing::triangulate_faces(s)) { +// std::cout << "Triangulated model: " << s.size_of_facets() << " facets and " << s.size_of_vertices() << " vertices" << std::endl; + } else { Logger::Message(Logger::LOG_ERROR, "Failed to triangulate shape"); return; } + CGAL::Polygon_mesh_processing::compute_normals(s, vertex_normals_map, face_normals_map); + // Iterates over the faces of the shape int num_faces = 0, num_vertices = 0; for (auto &face: faces(s)) { @@ -43,4 +43,6 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, t->material_ids().push_back(surface_style_id); ++num_faces; } + +// std::cout << num_faces << " faces" << std::endl; } diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp index 996926c978..802af766c2 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp @@ -129,13 +129,27 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_ continue; } +// std::cout << "Face in ConnectedFaceSet: " << std::endl; +// for (auto &point: face.outer) { +// std::cout << "\tPoint(" << point << ")" << std::endl; +// } + face_list.push_back(face); } + // Naive creation cgal_shape_t polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); + // Stitch edges +// std::cout << "Before: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; + CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); + if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { + CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); + } +// std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; + shape = polyhedron; return true; } @@ -189,6 +203,12 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcFace* l, cgal_face_t& face } face = mf; + +// std::cout << "Face: " << std::endl; +// for (auto &point: face.outer) { +// std::cout << "\tPoint(" << point << ")" << std::endl; +// } + return true; } @@ -225,6 +245,12 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& } result = polygon; + +// std::cout << "PolyLoop: " << std::endl; +// for (auto &point: polygon) { +// std::cout << "\tPoint(" << point << ")" << std::endl; +// } + return true; } diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index 596fcacf4e..4e82272375 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -43,6 +43,8 @@ if ( it != cache.T.end() ) { e = it->second; return true; } #include #include #include +#include +#include #include #include @@ -72,27 +74,23 @@ public: } void operator()(CGAL::Polyhedron_3::HalfedgeDS &hds) { - std::map points_map; + std::list points; std::list> facet_vertices; CGAL::Polyhedron_incremental_builder_3::HalfedgeDS> builder(hds, true); for (auto &face: *face_list) { facet_vertices.push_back(std::list()); for (auto &point: face.outer) { - if (points_map.count(point) == 0) { - facet_vertices.back().push_back(points_map.size()); - points_map[point] = points_map.size(); - } else { - facet_vertices.back().push_back(points_map[point]); - } + facet_vertices.back().push_back(points.size()); + points.push_back(point); } } - builder.begin_surface(points_map.size(), facet_vertices.size()); + builder.begin_surface(points.size(), facet_vertices.size()); - for (auto &point: points_map) { -// std::cout << "Adding point " << point.first << std::endl; - builder.add_vertex(point.first); + for (auto &point: points) { +// std::cout << "Adding point " << point << std::endl; + builder.add_vertex(point); } for (auto &facet: facet_vertices) { From c0732f5197fdb08d55adfeb23a05dfb7b1d93b3a Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 21 Feb 2017 15:37:38 -0600 Subject: [PATCH 23/25] =?UTF-8?q?Trying=20to=20find=20out=20why=20placemen?= =?UTF-8?q?ts=20don=E2=80=99t=20arrive=20at=20Triangulate()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ifcgeom/IfcGeomIterator.h | 7 ++++ .../kernels/cgal/CgalConversionFunctions.cpp | 34 +++++++++++++++++++ .../kernels/cgal/CgalConversionResult.h | 5 +-- src/ifcgeom/kernels/cgal/CgalKernel.cpp | 7 ++++ 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/ifcgeom/IfcGeomIterator.h b/src/ifcgeom/IfcGeomIterator.h index 2d2c8fe312..8a1de806e5 100644 --- a/src/ifcgeom/IfcGeomIterator.h +++ b/src/ifcgeom/IfcGeomIterator.h @@ -702,6 +702,13 @@ namespace IfcGeom { try { next_shape_model = create_shape_model_for_next_entity(); + +// std::cout << "trsf" << std::endl; +// for (int i = 0; i < 3; ++i) { +// for (int j = 0; j < 4; ++j) { +// std::cout << next_shape_model->transformation().matrix().data() << " "; +// } std::cout << std::endl; +// } } catch (...) {} if (next_shape_model) { diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 4121a7c783..80f7457811 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -139,12 +139,22 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement3D* l, cgal_ if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(),axis); if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection); +// std::cout << "Ref direction: " << refDirection << std::endl; +// std::cout << "Axis: " << axis << std::endl; +// std::cout << "Origin: " << o << std::endl; + // TODO: From Thomas' email. Should be checked. Kernel::Vector_3 y = CGAL::cross_product(axis, refDirection); trsf = Kernel::Aff_transformation_3(refDirection.cartesian(0), y.cartesian(0), axis.cartesian(0), o.cartesian(0), refDirection.cartesian(1), y.cartesian(1), axis.cartesian(1), o.cartesian(1), refDirection.cartesian(2), y.cartesian(2), axis.cartesian(2), o.cartesian(2)); +// for (int i = 0; i < 3; ++i) { +// for (int j = 0; j < 4; ++j) { +// std::cout << trsf.cartesian(i, j) << " "; +// } std::cout << std::endl; +// } + // CACHE(IfcAxis2Placement3D,l,trsf) return true; } @@ -156,13 +166,37 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcObjectPlacement* l, cgal_p Logger::Message(Logger::LOG_ERROR, "Unsupported IfcObjectPlacement:", l->entity); return false; } + +// std::cout << "initial trsf (identity?)" << std::endl; +// for (int i = 0; i < 3; ++i) { +// for (int j = 0; j < 4; ++j) { +// std::cout << trsf.cartesian(i, j) << " "; +// } std::cout << std::endl; +// } + IfcSchema::IfcLocalPlacement* current = (IfcSchema::IfcLocalPlacement*)l; for (;;) { cgal_placement_t trsf2; + IfcSchema::IfcAxis2Placement* relplacement = current->RelativePlacement(); if ( relplacement->is(IfcSchema::Type::IfcAxis2Placement3D) ) { IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement3D*)relplacement,trsf2); + +// std::cout << "trsf2" << std::endl; +// for (int i = 0; i < 3; ++i) { +// for (int j = 0; j < 4; ++j) { +// std::cout << trsf2.cartesian(i, j) << " "; +// } std::cout << std::endl; +// } + trsf = trsf * trsf2; // TODO: I think it's fine, but maybe should it be the other way around? + +// std::cout << "trsf (after multiplication)" << std::endl; +// for (int i = 0; i < 3; ++i) { +// for (int j = 0; j < 4; ++j) { +// std::cout << trsf.cartesian(i, j) << " "; +// } std::cout << std::endl; +// } } if ( current->hasPlacementRelTo() ) { IfcSchema::IfcObjectPlacement* relto = current->PlacementRelTo(); diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.h b/src/ifcgeom/kernels/cgal/CgalConversionResult.h index 940a598b67..b02e6e5c95 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.h +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.h @@ -35,7 +35,8 @@ namespace IfcGeom { virtual double Value(int i, int j) const { // TODO: Check - return CGAL::to_double(trsf_.cartesian(i, j)); +// std::cout << "Getting CgalPlacement with i = " << i << " and j = " << j << std::endl; + return CGAL::to_double(trsf_.cartesian(i-1, j-1)); } virtual void Multiply(const ConversionResultPlacement* other) { // TODO: Check @@ -51,7 +52,7 @@ namespace IfcGeom { private: cgal_placement_t trsf_; }; - + class CgalShape : public ConversionResultShape { public: CgalShape(const cgal_shape_t& shape) diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.cpp b/src/ifcgeom/kernels/cgal/CgalKernel.cpp index 73f9bd761e..7d346c93fc 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.cpp +++ b/src/ifcgeom/kernels/cgal/CgalKernel.cpp @@ -96,6 +96,13 @@ IfcGeom::NativeElement* IfcGeom::CgalKernel::create_brep_for_representat try { convert(product->ObjectPlacement(), trsf); } catch (...) {} + + std::cout << "trsf" << std::endl; + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 4; ++j) { + std::cout << trsf.cartesian(i, j) << " "; + } std::cout << std::endl; + } // Does the IfcElement have any IfcOpenings? // Note that openings for IfcOpeningElements are not processed From 64eb7079960ab8ac6ad98bb6f59cca319cae2e82 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 21 Feb 2017 18:40:27 -0600 Subject: [PATCH 24/25] Fixed issue with transformations? --- src/ifcgeom/IfcGeomIterator.h | 3 +- .../kernels/cgal/CgalEntityMapping.cpp | 2 +- src/ifcgeom/kernels/cgal/CgalKernel.cpp | 33 ++++++++++++++----- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/ifcgeom/IfcGeomIterator.h b/src/ifcgeom/IfcGeomIterator.h index 8a1de806e5..f85c056ae6 100644 --- a/src/ifcgeom/IfcGeomIterator.h +++ b/src/ifcgeom/IfcGeomIterator.h @@ -704,9 +704,10 @@ namespace IfcGeom { next_shape_model = create_shape_model_for_next_entity(); // std::cout << "trsf" << std::endl; +// IfcGeom::CgalPlacement *trsf = next_shape_model->transformation().data(); // for (int i = 0; i < 3; ++i) { // for (int j = 0; j < 4; ++j) { -// std::cout << next_shape_model->transformation().matrix().data() << " "; +// std::cout << << " "; // } std::cout << std::endl; // } } catch (...) {} diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp index 802af766c2..d7c576a4e7 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp @@ -67,7 +67,7 @@ bool IfcGeom::CgalKernel::convert_shape(const IfcBaseClass* l, cgal_shape_t& r) } if ( processed && success ) { - const double precision = getValue(GV_PRECISION); +// const double precision = getValue(GV_PRECISION); // apply_tolerance(r, precision); #ifndef NO_CACHE cache.Shape[id] = r; diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.cpp b/src/ifcgeom/kernels/cgal/CgalKernel.cpp index 7d346c93fc..e67be1c390 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.cpp +++ b/src/ifcgeom/kernels/cgal/CgalKernel.cpp @@ -97,12 +97,12 @@ IfcGeom::NativeElement* IfcGeom::CgalKernel::create_brep_for_representat convert(product->ObjectPlacement(), trsf); } catch (...) {} - std::cout << "trsf" << std::endl; - for (int i = 0; i < 3; ++i) { - for (int j = 0; j < 4; ++j) { - std::cout << trsf.cartesian(i, j) << " "; - } std::cout << std::endl; - } +// std::cout << "trsf" << std::endl; +// for (int i = 0; i < 3; ++i) { +// for (int j = 0; j < 4; ++j) { +// std::cout << trsf.cartesian(i, j) << " "; +// } std::cout << std::endl; +// } // Does the IfcElement have any IfcOpenings? // Note that openings for IfcOpeningElements are not processed @@ -114,9 +114,24 @@ IfcGeom::NativeElement* IfcGeom::CgalKernel::create_brep_for_representat 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); - + + if (settings.get(IteratorSettings::USE_WORLD_COORDS)) { + // TODO: OpenCascade code uses opened_shapes. Check why. + for ( IfcGeom::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++ it ) { + it->prepend(new CgalPlacement(trsf)); + } + trsf = Kernel::Aff_transformation_3(); + shape = new IfcGeom::Representation::Native(element_settings, representation->entity->id(), shapes); + } else if (settings.get(IteratorSettings::USE_WORLD_COORDS)) { + for ( IfcGeom::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++ it ) { + it->prepend(new CgalPlacement(trsf)); + } + trsf = Kernel::Aff_transformation_3(); + shape = new IfcGeom::Representation::Native(element_settings, representation->entity->id(), shapes); + } else { + shape = new IfcGeom::Representation::Native(element_settings, representation->entity->id(), shapes); + } + std::string context_string = ""; if (representation->hasRepresentationIdentifier()) { context_string = representation->RepresentationIdentifier(); From b893f5a3f08f065de6f889c71dc5a1dfd8a693e4 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Wed, 22 Feb 2017 18:15:27 -0600 Subject: [PATCH 25/25] Take into account extrusion height --- src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 80f7457811..063b4d8abf 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -44,6 +44,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal cgal_direction_t dir; convert(l->ExtrudedDirection(),dir); +// std::cout << "Direction: " << dir << std::endl; std::list face_list; face_list.push_back(face); @@ -58,8 +59,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal } cgal_face_t side_face; side_face.outer.push_back(*next_vertex); side_face.outer.push_back(*current_vertex); - side_face.outer.push_back(*current_vertex+dir); - side_face.outer.push_back(*next_vertex+dir); + side_face.outer.push_back(*current_vertex+height*dir); + side_face.outer.push_back(*next_vertex+height*dir); face_list.push_back(side_face); } @@ -67,7 +68,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal for (std::vector::const_reverse_iterator vertex = face.outer.rbegin(); vertex != face.outer.rend(); ++vertex) { - top_face.outer.push_back(*vertex+dir); + top_face.outer.push_back(*vertex+height*dir); } face_list.push_back(top_face); // Naive creation