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
+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;
}