mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-16 21:42:19 +00:00
Work towards trimmed curves
This commit is contained in:
@@ -533,8 +533,14 @@ namespace {
|
|||||||
|
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
T convert_xyz(const U& u) {
|
T convert_xyz(const U& u) {
|
||||||
const double* vs = u.components.data();
|
const auto& vs = u.components;
|
||||||
return T(vs[0], vs[1], vs[2]);
|
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 {
|
struct curve_creation_visitor {
|
||||||
@@ -547,15 +553,18 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result_type operator()(const taxonomy::line& l) {
|
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) {
|
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) {
|
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) {
|
result_type operator()(const taxonomy::loop& l) {
|
||||||
|
|||||||
@@ -1190,3 +1190,128 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcMappedItem* inst) {
|
|||||||
|
|
||||||
return shapes;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -102,14 +102,14 @@ BIND(IfcFace);
|
|||||||
// BIND(IfcEdgeLoop);
|
// BIND(IfcEdgeLoop);
|
||||||
BIND(IfcPolyline);
|
BIND(IfcPolyline);
|
||||||
BIND(IfcPolyLoop);
|
BIND(IfcPolyLoop);
|
||||||
// BIND(IfcCompositeCurve);
|
BIND(IfcCompositeCurve);
|
||||||
// BIND(IfcTrimmedCurve);
|
BIND(IfcTrimmedCurve);
|
||||||
// BIND(IfcArbitraryOpenProfileDef);
|
// BIND(IfcArbitraryOpenProfileDef);
|
||||||
#ifdef SCHEMA_HAS_IfcIndexedPolyCurve
|
#ifdef SCHEMA_HAS_IfcIndexedPolyCurve
|
||||||
// BIND(IfcIndexedPolyCurve)
|
// BIND(IfcIndexedPolyCurve)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// BIND(IfcCircle);
|
BIND(IfcCircle);
|
||||||
// BIND(IfcEllipse);
|
// BIND(IfcEllipse);
|
||||||
// BIND(IfcLine);
|
// BIND(IfcLine);
|
||||||
#ifdef SCHEMA_HAS_IfcBSplineCurveWithKnots
|
#ifdef SCHEMA_HAS_IfcBSplineCurveWithKnots
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ struct style : public item {
|
|||||||
struct geom_item : public item {
|
struct geom_item : public item {
|
||||||
style surface_style;
|
style surface_style;
|
||||||
matrix4 matrix;
|
matrix4 matrix;
|
||||||
|
boost::optional<bool> orientation;
|
||||||
|
|
||||||
geom_item(const IfcUtil::IfcBaseClass* instance = nullptr) : item(instance) {}
|
geom_item(const IfcUtil::IfcBaseClass* instance = nullptr) : item(instance) {}
|
||||||
geom_item(const IfcUtil::IfcBaseClass* instance, matrix4 m) : item(instance), matrix(m) {}
|
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 curve : public geom_item {};
|
||||||
|
|
||||||
struct line : public curve {
|
struct line : public curve {
|
||||||
point3 origin;
|
|
||||||
direction3 direction;
|
|
||||||
|
|
||||||
virtual item* clone() const { return new line(*this); }
|
virtual item* clone() const { return new line(*this); }
|
||||||
virtual kinds kind() const { return LINE; }
|
virtual kinds kind() const { return LINE; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct circle : public curve {
|
struct circle : public curve {
|
||||||
point3 origin;
|
|
||||||
direction3 x;
|
|
||||||
direction3 z;
|
|
||||||
double radius;
|
double radius;
|
||||||
|
|
||||||
virtual item* clone() const { return new circle(*this); }
|
virtual item* clone() const { return new circle(*this); }
|
||||||
@@ -160,7 +155,7 @@ struct bspline_curve : public curve {
|
|||||||
struct trimmed_curve : public curve {
|
struct trimmed_curve : public curve {
|
||||||
boost::variant<point3, double> start, end;
|
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.
|
// @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;
|
bool orientation;
|
||||||
|
|
||||||
trimmed_curve() : basis(nullptr), orientation(true) {}
|
trimmed_curve() : basis(nullptr), orientation(true) {}
|
||||||
@@ -216,7 +211,7 @@ struct face : public collection {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct loop : public collection {
|
struct loop : public collection {
|
||||||
boost::optional<bool> external;
|
boost::optional<bool> external, closed;
|
||||||
|
|
||||||
virtual item* clone() const { return new loop(*this); }
|
virtual item* clone() const { return new loop(*this); }
|
||||||
virtual kinds kind() const { return LOOP; }
|
virtual kinds kind() const { return LOOP; }
|
||||||
|
|||||||
Reference in New Issue
Block a user