diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.cpp b/src/ifcgeom/kernels/cgal/CgalKernel.cpp index dee865c460..d1d99fb85d 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.cpp +++ b/src/ifcgeom/kernels/cgal/CgalKernel.cpp @@ -650,7 +650,7 @@ bool CgalKernel::convert(const taxonomy::loop::ptr loop, cgal_wire_t& result) { std::vector edge; if (e->basis) { convert_curve(settings_, e, edge); - if (!e->orientation_2.get_value_or(true)) { + if (!e->curve_sense.get_value_or(true)) { std::reverse(edge.begin(), edge.end()); } } else { @@ -659,6 +659,9 @@ bool CgalKernel::convert(const taxonomy::loop::ptr loop, cgal_wire_t& result) { *boost::get(e->end) }; } + if (!e->orientation.get_value_or(true)) { + std::reverse(edge.begin(), edge.end()); + } extend_wire(points, edge); } diff --git a/src/ifcgeom/kernels/opencascade/face.cpp b/src/ifcgeom/kernels/opencascade/face.cpp index 8986dcd6b1..ee78c120fa 100644 --- a/src/ifcgeom/kernels/opencascade/face.cpp +++ b/src/ifcgeom/kernels/opencascade/face.cpp @@ -49,6 +49,13 @@ using namespace IfcGeom; using namespace IfcGeom::util; bool OpenCascadeKernel::convert(const taxonomy::face::ptr face, TopoDS_Shape& result) { +#ifdef IFOPSH_DEBUG + std::ostringstream oss; + face->print(oss); + auto osss = oss.str(); + std::wcout << osss.c_str() << std::endl; +#endif + face_definition fd; const bool is_face_surface = false; /* todo */ diff --git a/src/ifcgeom/kernels/opencascade/faceset_helper.cpp b/src/ifcgeom/kernels/opencascade/faceset_helper.cpp index e518bc9ef6..adc60798d2 100644 --- a/src/ifcgeom/kernels/opencascade/faceset_helper.cpp +++ b/src/ifcgeom/kernels/opencascade/faceset_helper.cpp @@ -155,7 +155,6 @@ IfcGeom::OpenCascadeKernel::faceset_helper::faceset_helper( if (edge_sets.find(segment_set) != edge_sets.end()) { duplicate_faces++; - // @todo does this work with tesselated face sets, will they have an associated instance? Guess not. duplicates_.insert(loop->identity()); continue; } @@ -203,6 +202,9 @@ void IfcGeom::OpenCascadeKernel::faceset_helper::loop_(const ifcopenshell::geome auto B = boost::get(b->start)->identity(); auto C = vertex_mapping_[A], D = vertex_mapping_[B]; bool fwd = C < D; + if (!b->orientation) { + fwd = !fwd; + } if (!fwd) { std::swap(C, D); } diff --git a/src/ifcgeom/kernels/opencascade/loop.cpp b/src/ifcgeom/kernels/opencascade/loop.cpp index ee263fcef1..2c4992611b 100644 --- a/src/ifcgeom/kernels/opencascade/loop.cpp +++ b/src/ifcgeom/kernels/opencascade/loop.cpp @@ -110,8 +110,14 @@ namespace { } TopoDS_Edge E; - if (e->basis) { - auto crv_or_wire = convert_curve(kernel, e->basis); + auto e_basis = e->basis; + if (e_basis) { + while (e_basis->kind() == taxonomy::EDGE && e_basis->instance && e_basis->instance->declaration().name() == "IfcTrimmedCurve") { + // @todo we still might have something to wrt orientation on periodic curves + // to make sure we select the correct arc later on. + e_basis = taxonomy::cast(e_basis)->basis; + } + auto crv_or_wire = convert_curve(kernel, e_basis); Handle(Geom_Curve) curve; if (crv_or_wire.which() == 0) { curve = boost::get(crv_or_wire); @@ -131,27 +137,23 @@ namespace { curve = approx.Curve(); } - const bool reversed = !taxonomy::cast(e->basis)->orientation.get_value_or(true); - const bool is_conic = e->basis->kind() == taxonomy::ELLIPSE || e->basis->kind() == taxonomy::CIRCLE; + const bool reversed = !e->orientation.get_value_or(true); + const bool is_conic = e_basis->kind() == taxonomy::ELLIPSE || e_basis->kind() == taxonomy::CIRCLE; + + if (!e->curve_sense) { + curve->Reverse(); + } // @todo, copy over logic from previous IfcTrimmedCurve handling if (e->start.which() == 0) { auto p1 = OpenCascadeKernel::convert_xyz(*boost::get(e->start)); auto p2 = OpenCascadeKernel::convert_xyz(*boost::get(e->end)); - if (reversed) { - std::swap(p1, p2); - } - E = BRepBuilderAPI_MakeEdge(curve, p1, p2).Edge(); } else { auto v1 = boost::get(e->start); auto v2 = boost::get(e->end); - if (reversed) { - std::swap(v1, v2); - } - if (is_conic && ALMOST_THE_SAME(fmod(v2 - v1, M_PI*2.), 0.)) { E = BRepBuilderAPI_MakeEdge(curve).Edge(); } else { @@ -171,6 +173,18 @@ namespace { E = BRepBuilderAPI_MakeEdge(p1, p2).Edge(); } + +#ifdef IFOPSH_DEBUG + std::ostringstream oss; + e->print(oss); + TopoDS_Vertex v0, v1; + TopExp::Vertices(E, v0, v1, true); + BRep_Tool::Pnt(v0).DumpJson(oss); + BRep_Tool::Pnt(v1).DumpJson(oss); + auto osss = oss.str(); + std::wcout << osss.c_str() << std::endl; +#endif + BRep_Builder B; TopoDS_Wire W; B.MakeWire(W); @@ -221,7 +235,7 @@ bool OpenCascadeKernel::convert(const taxonomy::loop::ptr loop, TopoDS_Wire& wir std::wcout << o_str.c_str() << std::endl; #endif - if (!segment->orientation_2.get_value_or(true)) { + if (!segment->curve_sense.get_value_or(true)) { segment_wire.Reverse(); } diff --git a/src/ifcgeom/mapping/IfcCompositeCurve.cpp b/src/ifcgeom/mapping/IfcCompositeCurve.cpp index b2c4637743..70230da556 100644 --- a/src/ifcgeom/mapping/IfcCompositeCurve.cpp +++ b/src/ifcgeom/mapping/IfcCompositeCurve.cpp @@ -45,7 +45,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCompositeCurve* inst) { e->basis = map(segment->as()->ParentCurve()); e->start = u0; e->end = u1; - e->orientation_2.reset(segment->as()->SameSense()); + e->curve_sense.reset(segment->as()->SameSense()); loop->children.push_back(e); } @@ -54,7 +54,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCompositeCurve* inst) { if (crv) { if (crv->kind() == taxonomy::EDGE) { auto ecrv = taxonomy::cast(crv); - ecrv->orientation_2.reset(segment->as()->SameSense()); + ecrv->curve_sense.reset(segment->as()->SameSense()); loop->children.push_back(ecrv); } else if (crv->kind() == taxonomy::LOOP) { diff --git a/src/ifcgeom/mapping/IfcEdge.cpp b/src/ifcgeom/mapping/IfcEdge.cpp index cffc491839..fdb6538cd9 100644 --- a/src/ifcgeom/mapping/IfcEdge.cpp +++ b/src/ifcgeom/mapping/IfcEdge.cpp @@ -41,7 +41,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcEdge* inst) { if (inst->as()) { e->basis = map(inst->as()->EdgeGeometry()); - e->orientation = inst->as()->SameSense(); + e->curve_sense = inst->as()->SameSense(); } return e; diff --git a/src/ifcgeom/mapping/IfcOrientedEdge.cpp b/src/ifcgeom/mapping/IfcOrientedEdge.cpp index 81c8e1c09d..769a8870ee 100644 --- a/src/ifcgeom/mapping/IfcOrientedEdge.cpp +++ b/src/ifcgeom/mapping/IfcOrientedEdge.cpp @@ -23,6 +23,7 @@ using namespace ifcopenshell::geometry; taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOrientedEdge* inst) { auto e = taxonomy::cast(map(inst->EdgeElement())); + e.reset(e->clone_()); if (!inst->Orientation()) { e->reverse(); } diff --git a/src/ifcgeom/taxonomy.cpp b/src/ifcgeom/taxonomy.cpp index 25fbfced5d..38a70f9733 100644 --- a/src/ifcgeom/taxonomy.cpp +++ b/src/ifcgeom/taxonomy.cpp @@ -558,4 +558,121 @@ const std::string& ifcopenshell::geometry::taxonomy::kind_to_string(kinds k) { return values[k]; } -std::atomic_uint32_t item::counter_(0); \ No newline at end of file +std::atomic_uint32_t item::counter_(0); + +void ifcopenshell::geometry::taxonomy::piecewise_function::print(std::ostream& o, int) const { + o << "piecewise_function" << std::endl; +} + +void ifcopenshell::geometry::taxonomy::matrix4::print(std::ostream& o, int indent) const { + print_impl(o, "matrix4", indent); +} + +void ifcopenshell::geometry::taxonomy::colour::print(std::ostream& o, int indent) const { + print_impl(o, "colour", indent); +} + + +void ifcopenshell::geometry::taxonomy::style::print(std::ostream& o, int indent) const { + o << std::string(indent, ' ') << "style" << std::endl; + o << std::string(indent, ' ') << " " << "name" << (name) << std::endl; + if (diffuse.components_) { + o << std::string(indent, ' ') << " " << "diffuse" << (name) << std::endl; + diffuse.print(o, indent + 5 + 7); + } + if (specular.components_) { + o << std::string(indent, ' ') << " " << "specular" << (name) << std::endl; + specular.print(o, indent + 5 + 8); + } + // @todo +} + +void ifcopenshell::geometry::taxonomy::point3::print(std::ostream& o, int indent) const { + print_impl(o, "point3", indent); +} + +void ifcopenshell::geometry::taxonomy::direction3::print(std::ostream& o, int indent) const { + print_impl(o, "direction3", indent); +} + +void ifcopenshell::geometry::taxonomy::line::print(std::ostream& o, int indent) const { + print_impl(o, "line", indent); +} + +void ifcopenshell::geometry::taxonomy::circle::print(std::ostream& o, int indent) const { + print_impl(o, "circle", indent); +} + +void ifcopenshell::geometry::taxonomy::ellipse::print(std::ostream& o, int indent) const { + print_impl(o, "ellipse", indent); +} + +void ifcopenshell::geometry::taxonomy::bspline_curve::print(std::ostream& o, int indent) const { + o << std::string(indent, ' ') << "bspline curve" << std::endl; +} + +void ifcopenshell::geometry::taxonomy::offset_curve::print(std::ostream& o, int indent) const { + o << std::string(indent, ' ') << "offset_curve" << std::endl; +} + +void ifcopenshell::geometry::taxonomy::trimmed_curve::print(std::ostream& o, int indent) const { + o << std::string(indent, ' ') << "trimmed_curve"; + if (!this->orientation.get_value_or(true)) { + o << " [R]"; + } else { + o << " [ ]"; + } + if (!this->curve_sense.get_value_or(true)) { + o << " [R]"; + } else { + o << " [ ]"; + } + o << std::endl; + if (basis) { + basis->print(o, indent + 4); + } + + const boost::variant* const start_end[2] = { &start, &end }; + for (int i = 0; i < 2; ++i) { + o << std::string(indent + 4, ' ') << (i == 0 ? "start" : "end") << std::endl; + if (start_end[i]->which() == 0) { + boost::get(*start_end[i])->print(o, indent + 4); + } else if (start_end[i]->which() == 1) { + o << std::string(indent + 4, ' ') << "parameter " << boost::get(*start_end[i]) << std::endl; + } + } + + if (this->instance) { + o << std::string(indent, ' ') << this->instance->data().toString() << std::endl; + } +} + +void ifcopenshell::geometry::taxonomy::plane::print(std::ostream& o, int indent) const { + o << "not implemented"; +} + +void ifcopenshell::geometry::taxonomy::cylinder::print(std::ostream& o, int indent) const { + o << "not implemented"; +} + +void ifcopenshell::geometry::taxonomy::sphere::print(std::ostream& o, int indent) const { + o << "not implemented"; +} + +void ifcopenshell::geometry::taxonomy::bspline_surface::print(std::ostream& o, int indent) const { + o << "not implemented"; +} + +void ifcopenshell::geometry::taxonomy::extrusion::print(std::ostream& o, int indent) const { + o << std::string(indent, ' ') << "extrusion " << depth << std::endl; + direction->print(o, indent + 4); + basis->print(o, indent + 4); +} + +void ifcopenshell::geometry::taxonomy::revolve::print(std::ostream& o, int indent) const { + o << std::string(indent, ' ') << "revolve" << std::endl; +} + +void ifcopenshell::geometry::taxonomy::surface_curve_sweep::print(std::ostream& o, int indent) const { + o << std::string(indent, ' ') << "surface_curve_sweep" << std::endl; +} \ No newline at end of file diff --git a/src/ifcgeom/taxonomy.h b/src/ifcgeom/taxonomy.h index 6c569944c8..8efffae7cc 100644 --- a/src/ifcgeom/taxonomy.h +++ b/src/ifcgeom/taxonomy.h @@ -165,9 +165,7 @@ typedef item const* ptr; return *length_; } - void print(std::ostream& o, int = 0) const { - o << "piecewise_function" << std::endl; - } + void print(std::ostream& o, int = 0) const; virtual piecewise_function* clone_() const { return new piecewise_function(*this); } virtual kinds kind() const { return PIECEWISE_FUNCTION; } @@ -376,9 +374,7 @@ typedef item const* ptr; return !components_ || components_->isIdentity(); } - void print(std::ostream& o, int indent = 0) const { - print_impl(o, "matrix4", indent); - } + void print(std::ostream& o, int indent = 0) const; virtual matrix4* clone_() const { return new matrix4(*this); } virtual kinds kind() const { return MATRIX4; } @@ -394,9 +390,7 @@ typedef item const* ptr; struct colour : public item, public eigen_base { DECLARE_PTR(colour) - void print(std::ostream& o, int indent = 0) const { - print_impl(o, "colour", indent); - } + void print(std::ostream& o, int indent = 0) const; virtual colour* clone_() const { return new colour(*this); } virtual kinds kind() const { return COLOUR; } @@ -422,19 +416,7 @@ typedef item const* ptr; colour specular; double specularity, transparency; - void print(std::ostream& o, int indent = 0) const { - o << std::string(indent, ' ') << "style" << std::endl; - o << std::string(indent, ' ') << " " << "name" << (name) << std::endl; - if (diffuse.components_) { - o << std::string(indent, ' ') << " " << "diffuse" << (name) << std::endl; - diffuse.print(o, indent + 5 + 7); - } - if (specular.components_) { - o << std::string(indent, ' ') << " " << "specular" << (name) << std::endl; - specular.print(o, indent + 5 + 8); - } - // @todo - } + void print(std::ostream& o, int indent = 0) const; virtual style* clone_() const { return new style(*this); } virtual kinds kind() const { return STYLE; } @@ -489,9 +471,7 @@ typedef item const* ptr; return boost::hash{}(v); } - void print(std::ostream& o, int indent = 0) const { - print_impl(o, "point3", indent); - } + void print(std::ostream& o, int indent = 0) const; point3() : cartesian_base() {} point3(const Eigen::Vector3d& c) : cartesian_base(c) {} @@ -509,9 +489,7 @@ typedef item const* ptr; return boost::hash{}(v); } - void print(std::ostream& o, int indent = 0) const { - print_impl(o, "direction3", indent); - } + void print(std::ostream& o, int indent = 0) const; direction3() : cartesian_base() {} direction3(const Eigen::Vector3d& c) : cartesian_base(c) {} @@ -536,9 +514,7 @@ typedef item const* ptr; return boost::hash{}(v); } - void print(std::ostream& o, int indent = 0) const { - print_impl(o, "line", indent); - } + void print(std::ostream& o, int indent = 0) const; }; struct circle : public curve { @@ -554,9 +530,7 @@ typedef item const* ptr; return boost::hash{}(v); } - void print(std::ostream& o, int indent = 0) const { - print_impl(o, "circle", indent); - } + void print(std::ostream& o, int indent = 0) const; static circle::ptr from_3_points(const Eigen::Vector3d& p1, const Eigen::Vector3d& p2, const Eigen::Vector3d& p3) { Eigen::Vector3d t = p2 - p1; @@ -600,9 +574,7 @@ typedef item const* ptr; return boost::hash{}(v); } - void print(std::ostream& o, int indent = 0) const { - print_impl(o, "ellipse", indent); - } + void print(std::ostream& o, int indent = 0) const; }; struct bspline_curve : public curve { @@ -637,9 +609,7 @@ typedef item const* ptr; boost::optional> weights; int degree; - void print(std::ostream& o, int indent = 0) const { - o << std::string(indent, ' ') << "bspline curve" << std::endl; - } + void print(std::ostream& o, int indent = 0) const; }; struct offset_curve : public curve { @@ -657,9 +627,7 @@ typedef item const* ptr; return boost::hash{}(v); } - void print(std::ostream& o, int indent = 0) const { - o << std::string(indent, ' ') << "offset_curve" << std::endl; - } + void print(std::ostream& o, int indent = 0) const; }; struct trimmed_curve : public item { @@ -673,37 +641,17 @@ typedef item const* ptr; item::ptr basis; // @todo does this make sense? this is to accommodate for the fact that orientation is defined on both TrimmedCurve as well CompCurveSegment - boost::optional orientation_2; + boost::optional curve_sense; - trimmed_curve() : basis(nullptr), orientation_2(true) {} + trimmed_curve() : basis(nullptr), curve_sense(true) {} trimmed_curve(const point3::ptr& a, const point3::ptr& b) : start(a), end(b), basis(nullptr) {} virtual void reverse() { // std::swap(start, end); - orientation = !orientation; + orientation = !orientation.get_value_or(true); } - void print(std::ostream& o, int indent = 0) const { - o << std::string(indent, ' ') << "trimmed_curve" << std::endl; - if (basis) { - basis->print(o, indent + 4); - } - - const boost::variant* const start_end[2] = { &start, &end }; - for (int i = 0; i < 2; ++i) { - o << std::string(indent + 4, ' ') << (i == 0 ? "start" : "end") << std::endl; - if (start_end[i]->which() == 0) { - boost::get(*start_end[i])->print(o, indent + 4); - } - else if (start_end[i]->which() == 1) { - o << std::string(indent + 4, ' ') << "parameter " << boost::get(*start_end[i]) << std::endl; - } - } - - if (this->instance) { - o << std::string(indent, ' ') << this->instance->data().toString() << std::endl; - } - } + void print(std::ostream& o, int indent = 0) const; }; struct edge : public trimmed_curve { @@ -717,7 +665,7 @@ typedef item const* ptr; virtual kinds kind() const { return EDGE; } virtual size_t calc_hash() const { - auto v = std::make_tuple(static_cast(EDGE), start, end, basis ? basis->hash() : size_t(0), orientation_2 ? *orientation_2 ? 2 : 1 : 0); + auto v = std::make_tuple(static_cast(EDGE), start, end, basis ? basis->hash() : size_t(0), curve_sense ? *curve_sense ? 2 : 1 : 0); return boost::hash{}(v); } }; @@ -758,7 +706,7 @@ typedef item const* ptr; void print(std::ostream& o, int indent = 0) const { o << std::string(indent, ' ') << kind_to_string(kind()) << std::endl; - if (!matrix->is_identity()) { + if (matrix && !matrix->is_identity()) { matrix->print(o, indent + 4); } for (auto& c : children) { @@ -885,9 +833,7 @@ typedef item const* ptr; virtual plane* clone_() const { return new plane(*this); } virtual kinds kind() const { return PLANE; } - void print(std::ostream& o, int) const { - o << "not implemented"; - } + void print(std::ostream& o, int) const; virtual size_t calc_hash() const { auto v = std::make_tuple(static_cast(PLANE), matrix->hash_components()); @@ -903,9 +849,8 @@ typedef item const* ptr; virtual cylinder* clone_() const { return new cylinder(*this); } virtual kinds kind() const { return CYLINDER; } - void print(std::ostream& o, int) const { - o << "not implemented"; - } + void print(std::ostream& o, int) const; + virtual size_t calc_hash() const { auto v = std::make_tuple(static_cast(CYLINDER), matrix->hash_components()); return boost::hash{}(v); @@ -920,9 +865,8 @@ typedef item const* ptr; virtual sphere* clone_() const { return new sphere(*this); } virtual kinds kind() const { return SPHERE; } - void print(std::ostream& o, int) const { - o << "not implemented"; - } + void print(std::ostream& o, int) const; + virtual size_t calc_hash() const { auto v = std::make_tuple(static_cast(SPHERE), matrix->hash_components()); return boost::hash{}(v); @@ -971,9 +915,7 @@ typedef item const* ptr; boost::optional>> weights; std::array degree; - void print(std::ostream& o, int) const { - o << "not implemented"; - } + void print(std::ostream& o, int) const; }; struct sweep : public geom_item { @@ -996,11 +938,7 @@ typedef item const* ptr; extrusion(matrix4::ptr m, face::ptr basis, direction3::ptr dir, double d) : sweep(m, basis), direction(dir), depth(d) {} - void print(std::ostream& o, int indent = 0) const { - o << std::string(indent, ' ') << "extrusion " << depth << std::endl; - direction->print(o, indent + 4); - basis->print(o, indent + 4); - } + void print(std::ostream& o, int indent = 0) const; virtual size_t calc_hash() const { auto v = std::make_tuple(static_cast(EXTRUSION), matrix->hash_components(), basis->calc_hash(), direction->hash_components(), depth); @@ -1020,9 +958,7 @@ typedef item const* ptr; revolve(matrix4::ptr m, face::ptr basis, point3::ptr pnt, direction3::ptr dir, const boost::optional& a) : sweep(m, basis), axis_origin(pnt), direction(dir), angle(a) {} - void print(std::ostream& o, int indent = 0) const { - o << std::string(indent, ' ') << "revolve" << std::endl; - } + void print(std::ostream& o, int indent = 0) const; virtual size_t calc_hash() const { auto v = std::make_tuple(static_cast(REVOLVE), matrix->hash_components(), basis->calc_hash(), axis_origin->hash_components(), direction->hash_components(), angle ? *angle : 1000.); @@ -1041,9 +977,7 @@ typedef item const* ptr; surface_curve_sweep(matrix4::ptr m, face::ptr basis, item::ptr surf, item::ptr crv) : sweep(m, basis), surface(surf), curve(crv) {} - void print(std::ostream& o, int indent = 0) const { - o << std::string(indent, ' ') << "surface_curve_sweep" << std::endl; - } + void print(std::ostream& o, int indent = 0) const; virtual size_t calc_hash() const { auto v = std::make_tuple(static_cast(SURFACE_CURVE_SWEEP), matrix->hash_components(), basis->calc_hash(), surface->calc_hash(), curve->calc_hash());