mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
Work towards trimmed curves
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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; }
|
||||
|
||||
Reference in New Issue
Block a user