Work towards trimmed curves

This commit is contained in:
Thomas Krijnen
2019-09-16 19:30:11 +02:00
parent 3731c95728
commit a447dc6208
4 changed files with 145 additions and 16 deletions
@@ -533,8 +533,14 @@ namespace {
template <typename T, typename U>
T convert_xyz(const U& u) {
const double* vs = u.components.data();
return T(vs[0], vs[1], vs[2]);
const auto& vs = u.components;
return T(vs(0), vs(1), vs(2));
}
// @todo eliminate
template <typename T, typename U>
T convert_xyz2(const U& vs) {
return T(vs(0), vs(1), vs(2));
}
struct curve_creation_visitor {
@@ -547,15 +553,18 @@ namespace {
}
result_type operator()(const taxonomy::line& l) {
return result = Handle(Geom_Curve)(new Geom_Line(convert_xyz<gp_Pnt>(l.origin), convert_xyz<gp_Dir>(l.direction)));
const auto& m = l.matrix.components;
return result = Handle(Geom_Curve)(new Geom_Line(convert_xyz2<gp_Pnt>(m.row(3)), convert_xyz2<gp_Dir>(m.row(0))));
}
result_type operator()(const taxonomy::circle& c) {
return result = Handle(Geom_Curve)(new Geom_Circle(gp_Ax2(convert_xyz<gp_Pnt>(c.origin), convert_xyz<gp_Dir>(c.z), convert_xyz<gp_Dir>(c.x)), c.radius));
const auto& m = c.matrix.components;
return result = Handle(Geom_Curve)(new Geom_Circle(gp_Ax2(convert_xyz2<gp_Pnt>(m.row(3)), convert_xyz2<gp_Dir>(m.row(2)), convert_xyz2<gp_Dir>(m.row(0))), c.radius));
}
result_type operator()(const taxonomy::ellipse& e) {
return result = Handle(Geom_Curve)(new Geom_Ellipse(gp_Ax2(convert_xyz<gp_Pnt>(e.origin), convert_xyz<gp_Dir>(e.z), convert_xyz<gp_Dir>(e.x)), e.radius, e.radius2));
const auto& m = e.matrix.components;
return result = Handle(Geom_Curve)(new Geom_Ellipse(gp_Ax2(convert_xyz2<gp_Pnt>(m.row(3)), convert_xyz2<gp_Dir>(m.row(2)), convert_xyz2<gp_Dir>(m.row(0))), e.radius, e.radius2));
}
result_type operator()(const taxonomy::loop& l) {
+125
View File
@@ -1190,3 +1190,128 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcMappedItem* inst) {
return shapes;
}
taxonomy::item* mapping::map_impl(const IfcSchema::IfcCompositeCurve* inst) {
auto loop = new taxonomy::loop;
auto segments = inst->Segments();
for (auto& segment : *segments) {
auto crv = map(segment->ParentCurve());
if (crv) {
((taxonomy::geom_item*)crv)->orientation = segment->SameSense();
loop->children.push_back(crv);
}
}
IfcEntityList::ptr profile = inst->data().getInverse(&IfcSchema::IfcProfileDef::Class(), -1);
const bool force_close = profile && profile->size() > 0;
loop->closed = force_close;
return loop;
}
taxonomy::item* mapping::map_impl(const IfcSchema::IfcTrimmedCurve* inst) {
IfcSchema::IfcCurve* basis_curve = inst->BasisCurve();
bool isConic = basis_curve->declaration().is(IfcSchema::IfcConic::Class());
double parameterFactor = isConic ? angle_unit_ : length_unit_;
auto tc = new taxonomy::edge;
tc->basis = map(inst->BasisCurve());
bool trim_cartesian = inst->MasterRepresentation() != IfcSchema::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER;
IfcEntityList::ptr trims1 = inst->Trim1();
IfcEntityList::ptr trims2 = inst->Trim2();
unsigned sense_agreement = inst->SenseAgreement() ? 0 : 1;
double flts[2];
taxonomy::point3 pnts[2];
bool has_flts[2] = { false,false };
bool has_pnts[2] = { false,false };
tc->orientation = sense_agreement != 0;
for (IfcEntityList::it it = trims1->begin(); it != trims1->end(); it++) {
IfcUtil::IfcBaseClass* i = *it;
if (i->declaration().is(IfcSchema::IfcCartesianPoint::Class())) {
pnts[sense_agreement] = as<taxonomy::point3>(map(i));
has_pnts[sense_agreement] = true;
} else if (i->declaration().is(IfcSchema::IfcParameterValue::Class())) {
const double value = *((IfcSchema::IfcParameterValue*)i);
flts[sense_agreement] = value * parameterFactor;
has_flts[sense_agreement] = true;
}
}
for (IfcEntityList::it it = trims2->begin(); it != trims2->end(); it++) {
IfcUtil::IfcBaseClass* i = *it;
if (i->declaration().is(IfcSchema::IfcCartesianPoint::Class())) {
pnts[1 - sense_agreement] = as<taxonomy::point3>(map(i));
has_pnts[1 - sense_agreement] = true;
} else if (i->declaration().is(IfcSchema::IfcParameterValue::Class())) {
const double value = *((IfcSchema::IfcParameterValue*)i);
flts[1 - sense_agreement] = value * parameterFactor;
has_flts[1 - sense_agreement] = true;
}
}
// @todo
const double precision_ = 1.e-5;
const double M_PI = 3.141592653;
trim_cartesian &= has_pnts[0] && has_pnts[1];
if (trim_cartesian) {
if ((pnts[0].components - pnts[1].components).norm() < (2 * precision_)) {
Logger::Message(Logger::LOG_WARNING, "Skipping segment with length below tolerance level:", inst);
return false;
}
} else if (has_flts[0] && has_flts[1]) {
// The Geom_Line is constructed from a gp_Pnt and gp_Dir, whereas the IfcLine
// is defined by an IfcCartesianPoint and an IfcVector with Magnitude. Because
// the vector is normalised when passed to Geom_Line constructor the magnitude
// needs to be factored in with the IfcParameterValue here.
if (basis_curve->declaration().is(IfcSchema::IfcLine::Class())) {
IfcSchema::IfcLine* line = static_cast<IfcSchema::IfcLine*>(basis_curve);
const double magnitude = line->Dir()->Magnitude();
flts[0] *= magnitude; flts[1] *= magnitude;
}
if (basis_curve->declaration().is(IfcSchema::IfcEllipse::Class())) {
IfcSchema::IfcEllipse* ellipse = static_cast<IfcSchema::IfcEllipse*>(basis_curve);
double x = ellipse->SemiAxis1() * length_unit_;
double y = ellipse->SemiAxis2() * length_unit_;
const bool rotated = y > x;
if (rotated) {
flts[0] -= M_PI / 2.;
flts[1] -= M_PI / 2.;
}
}
}
/*
// @todo
if (isConic) {
// Tiny circle segnments can cause issues later on, for example
// when the comp curve is used as the sweeping directrix.
double a, b;
Handle(Geom_Curve) crv = BRep_Tool::Curve(e, a, b);
double radius = -1.;
if (crv->DynamicType() == STANDARD_TYPE(Geom_Circle)) {
radius = Handle(Geom_Circle)::DownCast(crv)->Radius();
} else if (crv->DynamicType() == STANDARD_TYPE(Geom_Ellipse)) {
// The formula above is for circles, but probably good enough
radius = Handle(Geom_Ellipse)::DownCast(crv)->MajorRadius();
}
if (radius > 0. && deflection_for_approximating_circle(radius, b - a) < getValue(GV_PRECISION)) {
TopoDS_Vertex v0, v1;
TopExp::Vertices(e, v0, v1);
e = TopoDS::Edge(BRepBuilderAPI_MakeEdge(v0, v1).Edge().Oriented(e.Orientation()));
Logger::Warning("Subsituted edge with linear approximation", l);
}
}
*/
return tc;
}
taxonomy::item* mapping::map_impl(const IfcSchema::IfcCircle* inst) {
auto c = new taxonomy::circle;
c->matrix = as<taxonomy::matrix4>(map(inst->Position()));
c->radius = inst->Radius();
return c;
}
+3 -3
View File
@@ -102,14 +102,14 @@ BIND(IfcFace);
// BIND(IfcEdgeLoop);
BIND(IfcPolyline);
BIND(IfcPolyLoop);
// BIND(IfcCompositeCurve);
// BIND(IfcTrimmedCurve);
BIND(IfcCompositeCurve);
BIND(IfcTrimmedCurve);
// BIND(IfcArbitraryOpenProfileDef);
#ifdef SCHEMA_HAS_IfcIndexedPolyCurve
// BIND(IfcIndexedPolyCurve)
#endif
// BIND(IfcCircle);
BIND(IfcCircle);
// BIND(IfcEllipse);
// BIND(IfcLine);
#ifdef SCHEMA_HAS_IfcBSplineCurveWithKnots
+3 -8
View File
@@ -97,6 +97,7 @@ struct style : public item {
struct geom_item : public item {
style surface_style;
matrix4 matrix;
boost::optional<bool> orientation;
geom_item(const IfcUtil::IfcBaseClass* instance = nullptr) : item(instance) {}
geom_item(const IfcUtil::IfcBaseClass* instance, matrix4 m) : item(instance), matrix(m) {}
@@ -128,17 +129,11 @@ struct direction3 : public cartesian_base<3> {
struct curve : public geom_item {};
struct line : public curve {
point3 origin;
direction3 direction;
virtual item* clone() const { return new line(*this); }
virtual kinds kind() const { return LINE; }
};
struct circle : public curve {
point3 origin;
direction3 x;
direction3 z;
double radius;
virtual item* clone() const { return new circle(*this); }
@@ -160,7 +155,7 @@ struct bspline_curve : public curve {
struct trimmed_curve : public curve {
boost::variant<point3, double> start, end;
// @todo somehow account for the fact that curve in IFC can be trimmed curve, polyline and composite curve as well.
curve* basis;
item* basis;
bool orientation;
trimmed_curve() : basis(nullptr), orientation(true) {}
@@ -216,7 +211,7 @@ struct face : public collection {
};
struct loop : public collection {
boost::optional<bool> external;
boost::optional<bool> external, closed;
virtual item* clone() const { return new loop(*this); }
virtual kinds kind() const { return LOOP; }