Move print() to header, distinguish properly between curve_sense and edge orientation, unwrap trimmed curves as edge bases, don't mutated cached edge in oriented edge processing, etc. #4895

This commit is contained in:
Thomas Krijnen
2024-06-24 21:56:27 +02:00
parent 278524ee3e
commit 8da68f599b
9 changed files with 189 additions and 111 deletions
+4 -1
View File
@@ -650,7 +650,7 @@ bool CgalKernel::convert(const taxonomy::loop::ptr loop, cgal_wire_t& result) {
std::vector<taxonomy::point3> 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<taxonomy::point3::ptr>(e->end)
};
}
if (!e->orientation.get_value_or(true)) {
std::reverse(edge.begin(), edge.end());
}
extend_wire(points, edge);
}
+7
View File
@@ -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 */
@@ -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<ifcopenshell::geometry::taxonomy::point3::ptr>(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);
}
+27 -13
View File
@@ -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<taxonomy::edge>(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<Handle(Geom_Curve)>(crv_or_wire);
@@ -131,27 +137,23 @@ namespace {
curve = approx.Curve();
}
const bool reversed = !taxonomy::cast<taxonomy::geom_item>(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<gp_Pnt>(*boost::get<taxonomy::point3::ptr>(e->start));
auto p2 = OpenCascadeKernel::convert_xyz<gp_Pnt>(*boost::get<taxonomy::point3::ptr>(e->end));
if (reversed) {
std::swap(p1, p2);
}
E = BRepBuilderAPI_MakeEdge(curve, p1, p2).Edge();
} else {
auto v1 = boost::get<double>(e->start);
auto v2 = boost::get<double>(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();
}
+2 -2
View File
@@ -45,7 +45,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCompositeCurve* inst) {
e->basis = map(segment->as<IfcSchema::IfcCompositeCurveSegment>()->ParentCurve());
e->start = u0;
e->end = u1;
e->orientation_2.reset(segment->as<IfcSchema::IfcCompositeCurveSegment>()->SameSense());
e->curve_sense.reset(segment->as<IfcSchema::IfcCompositeCurveSegment>()->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<taxonomy::edge>(crv);
ecrv->orientation_2.reset(segment->as<IfcSchema::IfcCompositeCurveSegment>()->SameSense());
ecrv->curve_sense.reset(segment->as<IfcSchema::IfcCompositeCurveSegment>()->SameSense());
loop->children.push_back(ecrv);
}
else if (crv->kind() == taxonomy::LOOP) {
+1 -1
View File
@@ -41,7 +41,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcEdge* inst) {
if (inst->as<IfcSchema::IfcEdgeCurve>()) {
e->basis = map(inst->as<IfcSchema::IfcEdgeCurve>()->EdgeGeometry());
e->orientation = inst->as<IfcSchema::IfcEdgeCurve>()->SameSense();
e->curve_sense = inst->as<IfcSchema::IfcEdgeCurve>()->SameSense();
}
return e;
+1
View File
@@ -23,6 +23,7 @@ using namespace ifcopenshell::geometry;
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOrientedEdge* inst) {
auto e = taxonomy::cast<taxonomy::edge>(map(inst->EdgeElement()));
e.reset(e->clone_());
if (!inst->Orientation()) {
e->reverse();
}
+118 -1
View File
@@ -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);
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<point3::ptr, double>* 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<point3::ptr>(*start_end[i])->print(o, indent + 4);
} else if (start_end[i]->which() == 1) {
o << std::string(indent + 4, ' ') << "parameter " << boost::get<double>(*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;
}
+26 -92
View File
@@ -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<Eigen::Vector3d> {
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<decltype(v)>{}(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<decltype(v)>{}(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<decltype(v)>{}(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<decltype(v)>{}(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<decltype(v)>{}(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<std::vector<double>> 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<decltype(v)>{}(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<bool> orientation_2;
boost::optional<bool> 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<point3::ptr, double>* 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<point3::ptr>(*start_end[i])->print(o, indent + 4);
}
else if (start_end[i]->which() == 1) {
o << std::string(indent + 4, ' ') << "parameter " << boost::get<double>(*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<size_t>(EDGE), start, end, basis ? basis->hash() : size_t(0), orientation_2 ? *orientation_2 ? 2 : 1 : 0);
auto v = std::make_tuple(static_cast<size_t>(EDGE), start, end, basis ? basis->hash() : size_t(0), curve_sense ? *curve_sense ? 2 : 1 : 0);
return boost::hash<decltype(v)>{}(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<size_t>(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<size_t>(CYLINDER), matrix->hash_components());
return boost::hash<decltype(v)>{}(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<size_t>(SPHERE), matrix->hash_components());
return boost::hash<decltype(v)>{}(v);
@@ -971,9 +915,7 @@ typedef item const* ptr;
boost::optional<std::vector<std::vector<double>>> weights;
std::array<int, 2> 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<size_t>(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<double>& 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<size_t>(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<size_t>(SURFACE_CURVE_SWEEP), matrix->hash_components(), basis->calc_hash(), surface->calc_hash(), curve->calc_hash());