mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-19 06:39:13 +00:00
Removed assert, added Logger::Warning and Logger::Error. Made treatment of unexpected data more permissive
This commit is contained in:
committed by
Thomas Krijnen
parent
94b567a25b
commit
2a53911c52
@@ -137,11 +137,13 @@ public:
|
|||||||
m.col(1) = Eigen::Vector4d(0, 1, 0, 0);
|
m.col(1) = Eigen::Vector4d(0, 1, 0, 0);
|
||||||
m.col(2) = Eigen::Vector4d(-dy, 0, dx, 0);
|
m.col(2) = Eigen::Vector4d(-dy, 0, dx, 0);
|
||||||
m.col(3) = Eigen::Vector4d(0, 0, y, 1.0); // y is an elevation so store it as z
|
m.col(3) = Eigen::Vector4d(0, 0, y, 1.0); // y is an elevation so store it as z
|
||||||
|
} else if (segment_type == ST_CANT) {
|
||||||
|
Logger::Warning(std::runtime_error("Use of IfcSpiral for cant is not supported"));
|
||||||
} else {
|
} else {
|
||||||
assert(segment_type == ST_CANT); // if it isn't cant, is there a new segment type?
|
Logger::Error(std::runtime_error("Unexpected segment type encountered"));
|
||||||
assert(false); // not expecting cant
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Eigen::Matrix4d result = transformation_matrix * m;
|
Eigen::Matrix4d result = transformation_matrix * m;
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
@@ -263,7 +265,6 @@ public:
|
|||||||
|
|
||||||
auto dx = cos(angle);
|
auto dx = cos(angle);
|
||||||
auto dy = sin(angle);
|
auto dy = sin(angle);
|
||||||
auto dz = 1.0;
|
|
||||||
|
|
||||||
auto x = R * dx;
|
auto x = R * dx;
|
||||||
auto y = R * dy;
|
auto y = R * dy;
|
||||||
@@ -281,11 +282,13 @@ public:
|
|||||||
m.col(1) = Eigen::Vector4d(0, 1, 0, 0);
|
m.col(1) = Eigen::Vector4d(0, 1, 0, 0);
|
||||||
m.col(2) = Eigen::Vector4d(-dy, 0, dx, 0);
|
m.col(2) = Eigen::Vector4d(-dy, 0, dx, 0);
|
||||||
m.col(3) = Eigen::Vector4d(0, 0, y, 1.0); // y is an elevation so store it as z
|
m.col(3) = Eigen::Vector4d(0, 0, y, 1.0); // y is an elevation so store it as z
|
||||||
|
} else if (segment_type == ST_CANT) {
|
||||||
|
Logger::Warning(std::runtime_error("Use of IfcCircle for cant is not supported"));
|
||||||
} else {
|
} else {
|
||||||
assert(segment_type == ST_CANT); // if it isn't cant, is there a new segment type?
|
Logger::Error(std::runtime_error("Unexpected segment type encountered"));
|
||||||
assert(false); // not expecting cant
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Eigen::Matrix4d result = transformation_matrix * m;
|
Eigen::Matrix4d result = transformation_matrix * m;
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
@@ -313,12 +316,15 @@ public:
|
|||||||
auto std_compare = [](double u_start, double u, double u_end) {return u_start <= u && u < u_end; };
|
auto std_compare = [](double u_start, double u, double u_end) {return u_start <= u && u < u_end; };
|
||||||
auto end_compare = [](double u_start, double u, double u_end) {return u_start <= u && u <= (u_end + 0.001); };
|
auto end_compare = [](double u_start, double u, double u_end) {return u_start <= u && u <= (u_end + 0.001); };
|
||||||
|
|
||||||
auto iter = p->begin();
|
auto begin = p->begin();
|
||||||
|
auto iter = begin;
|
||||||
auto end = p->end();
|
auto end = p->end();
|
||||||
auto last = std::prev(end);
|
auto last = std::prev(end);
|
||||||
auto p1 = *(iter++);
|
auto p1 = *(iter++);
|
||||||
assert(p1->Coordinates().size() == 2); // expecting the polyline to be planar
|
|
||||||
auto u = 0.0;
|
if (p1->Coordinates().size() != 2) Logger::Warning("Expected IfcPolyline.Points to be 2D",pl);
|
||||||
|
|
||||||
|
auto u = 0.0;
|
||||||
for (; iter != end; iter++)
|
for (; iter != end; iter++)
|
||||||
{
|
{
|
||||||
auto p2 = *iter;
|
auto p2 = *iter;
|
||||||
@@ -332,10 +338,13 @@ public:
|
|||||||
auto dx = p2x - p1x;
|
auto dx = p2x - p1x;
|
||||||
auto dy = p2y - p1y;
|
auto dy = p2y - p1y;
|
||||||
auto l = sqrt(dx * dx + dy * dy);
|
auto l = sqrt(dx * dx + dy * dy);
|
||||||
if (l == 0.0)
|
|
||||||
|
if (l < mapping_->conversion_settings().getValue(ConversionSettings::GV_PRECISION))
|
||||||
{
|
{
|
||||||
// @todo: rb use closeness tolerance instead of absolute 0.0
|
std::ostringstream os;
|
||||||
throw std::runtime_error("invalid polyline - points must not be coincident");
|
os << "Coincident IfcPolyline.Points are not expected. Skipping point " << std::distance(iter, begin) << std::endl;
|
||||||
|
Logger::Warning(os.str(), pl);
|
||||||
|
continue; // go to next point
|
||||||
}
|
}
|
||||||
|
|
||||||
dx /= l;
|
dx /= l;
|
||||||
@@ -360,9 +369,10 @@ public:
|
|||||||
m.col(1) = Eigen::Vector4d(0, 1, 0, 0);
|
m.col(1) = Eigen::Vector4d(0, 1, 0, 0);
|
||||||
m.col(2) = Eigen::Vector4d(-dy, 0, dx, 0);
|
m.col(2) = Eigen::Vector4d(-dy, 0, dx, 0);
|
||||||
m.col(3) = Eigen::Vector4d(0, 0, y, 1.0); // y is an elevation so store it as z
|
m.col(3) = Eigen::Vector4d(0, 0, y, 1.0); // y is an elevation so store it as z
|
||||||
|
} else if (segment_type == ST_CANT) {
|
||||||
|
Logger::Warning(std::runtime_error("Use of IfcPolyline for cant is not supported"));
|
||||||
} else {
|
} else {
|
||||||
assert(segment_type == ST_CANT); // if it isn't cant, is there a new segment type?
|
Logger::Error(std::runtime_error("Unexpected segment type encountered"));
|
||||||
assert(false); // not expecting cant
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
@@ -381,10 +391,11 @@ public:
|
|||||||
return compare(u_start, u, u_end);
|
return compare(u_start, u, u_end);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (iter == fns.end()) throw std::runtime_error("invalid distance from start"); // this should never happen, but just in case it does
|
if (iter == fns.end()) throw std::runtime_error("invalid distance from start"); // this should never happen, but just in case it does, throw an exception so the problem gets automatically detected
|
||||||
|
|
||||||
auto [u_start, u_end, compare] = iter->first;
|
const auto& [u_start, u_end, compare] = iter->first;
|
||||||
auto m = (iter->second)(u - u_start); // (u - u_start) is distance from start of this segment of the polyline
|
const auto& fn = iter->second;
|
||||||
|
Eigen::Matrix4d m = fn(u - u_start); // (u - u_start) is distance from start of this segment of the polyline
|
||||||
return m;
|
return m;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -420,7 +431,6 @@ public:
|
|||||||
eval_ = [px, py, dx, dy](double u) {
|
eval_ = [px, py, dx, dy](double u) {
|
||||||
// https://standards.buildingsmart.org/IFC/RELEASE/IFC4_3/HTML/lexical/IfcGradientCurve.htm
|
// https://standards.buildingsmart.org/IFC/RELEASE/IFC4_3/HTML/lexical/IfcGradientCurve.htm
|
||||||
// the parameter, u, is the parameter of the BaseCurve (u = plan view distance along base curve)
|
// the parameter, u, is the parameter of the BaseCurve (u = plan view distance along base curve)
|
||||||
auto x = px + u;
|
|
||||||
|
|
||||||
// dx and dy are normalized so u needs to be scaled by dy/dx
|
// dx and dy are normalized so u needs to be scaled by dy/dx
|
||||||
// Consider a 5% uphill grade defined by dr[0] = 1 and dr[1] = 0.05.
|
// Consider a 5% uphill grade defined by dr[0] = 1 and dr[1] = 0.05.
|
||||||
@@ -438,10 +448,12 @@ public:
|
|||||||
return m;
|
return m;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
else if(segment_type_ == ST_CANT) {
|
||||||
|
Logger::Warning(std::runtime_error("Use of IfcLine for cant is not supported"), l);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
assert(segment_type_ == ST_CANT); // if it isn't cant, is there a new segment type?
|
Logger::Error(std::runtime_error("Unexpected segment type encountered"), l);
|
||||||
assert(false); // not expecting cant
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(IfcSchema::IfcPolynomialCurve* p) {
|
void operator()(IfcSchema::IfcPolynomialCurve* p) {
|
||||||
@@ -449,7 +461,7 @@ public:
|
|||||||
auto coeffX = p->CoefficientsX().get_value_or(std::vector<double>());
|
auto coeffX = p->CoefficientsX().get_value_or(std::vector<double>());
|
||||||
auto coeffY = p->CoefficientsY().get_value_or(std::vector<double>());
|
auto coeffY = p->CoefficientsY().get_value_or(std::vector<double>());
|
||||||
auto coeffZ = p->CoefficientsZ().get_value_or(std::vector<double>());
|
auto coeffZ = p->CoefficientsZ().get_value_or(std::vector<double>());
|
||||||
assert(coeffZ.size() == 0); // expecting the curve to by in the XY Plane (ST_HORIZONTAL) or the UZ Plane (ST_VERTICAL)
|
Logger::Warning("Expected IfcPolynomialCurve.CoefficientsZ to be undefined for alignment geometry", p);
|
||||||
|
|
||||||
auto transformation_matrix = taxonomy::cast<taxonomy::matrix4>(mapping_->map(p->Position()))->ccomponents();
|
auto transformation_matrix = taxonomy::cast<taxonomy::matrix4>(mapping_->map(p->Position()))->ccomponents();
|
||||||
|
|
||||||
@@ -493,13 +505,13 @@ public:
|
|||||||
m.col(1) = Eigen::Vector4d(0, 1, 0, 0);
|
m.col(1) = Eigen::Vector4d(0, 1, 0, 0);
|
||||||
m.col(2) = Eigen::Vector4d(dy, 0, dx, 0);
|
m.col(2) = Eigen::Vector4d(dy, 0, dx, 0);
|
||||||
m.col(3) = Eigen::Vector4d(0, 0, y, 1.0); // y is an elevation so store it as z
|
m.col(3) = Eigen::Vector4d(0, 0, y, 1.0); // y is an elevation so store it as z
|
||||||
}
|
} else if (segment_type == ST_CANT) {
|
||||||
else
|
Logger::Warning(std::runtime_error("Use of IfcPolynomialCurve for cant is not supported"));
|
||||||
{
|
} else {
|
||||||
assert(segment_type == ST_CANT); // if it isn't cant, is there a new segment type?
|
Logger::Error(std::runtime_error("Unexpected segment type encountered"));
|
||||||
assert(false); // not expecting cant
|
}
|
||||||
}
|
|
||||||
return m;
|
return m;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,23 +25,15 @@ using namespace ifcopenshell::geometry;
|
|||||||
|
|
||||||
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcLinearPlacement* inst) {
|
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcLinearPlacement* inst) {
|
||||||
|
|
||||||
// The IFC specification does not provided a description of the optional
|
// IfcLinearPlacement was added in IFC 4.1 but it had an Orientation attribute of type IfcOrientationExpression, which when combined with other
|
||||||
// CartesianPosition attribute. It is assumed to be a pre-computed IfcAxis2Placement3D
|
// attributes was similar to IfcAxis2PlacementLinear. IFC 4.1 and IFC 4.2 have been withdrawn so I'm not going to try to implement linear placement for them.
|
||||||
// to be used by software that don't support IfcLinearPlacement. In this case,
|
// For this reason the preprocessor skips this code if SCHEMA_HAS_IfcAxis2PlacementLinear is not defined
|
||||||
// we will simply use the intended CartesianPosition provided by the IFC model
|
|
||||||
if (inst->CartesianPosition()) {
|
|
||||||
return map(inst->CartesianPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
// the following is taken from IfcLocalPlacement and tweaked a little
|
|
||||||
// assumes that PlacementRelTo is relative to another IfcLinearPlacement
|
|
||||||
IfcSchema::IfcLinearPlacement* current = (IfcSchema::IfcLinearPlacement*)inst;
|
|
||||||
auto m4 = taxonomy::make<taxonomy::matrix4>();
|
|
||||||
|
|
||||||
#if defined SCHEMA_HAS_IfcAxis2PlacementLinear
|
#if defined SCHEMA_HAS_IfcAxis2PlacementLinear
|
||||||
// IfcLinearPlacement was added in IFC 4.1 but it had an Orientation attribute of type IfcOrientationExpression, which when combined with other
|
// the following is taken from IfcLocalPlacement and tweaked a little
|
||||||
// attributes was similar to IfcAxis2PlacementLinear. IFC 4.1 and IFC 4.2 have been withdrawn so I'm not going to try to implement linear placement for them.
|
// assumes that PlacementRelTo is relative to another IfcLinearPlacement
|
||||||
// For this reason the preprocessor skips this code if SCHEMA_HAS_IfcAxix2PlacementLinear is not defined
|
IfcSchema::IfcLinearPlacement* current = (IfcSchema::IfcLinearPlacement*)inst;
|
||||||
|
auto m4 = taxonomy::make<taxonomy::matrix4>();
|
||||||
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
IfcSchema::IfcAxis2PlacementLinear* relplacement = current->RelativePlacement();
|
IfcSchema::IfcAxis2PlacementLinear* relplacement = current->RelativePlacement();
|
||||||
@@ -76,12 +68,34 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcLinearPlacement* inst) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The IFC specification does not provided a description of the optional
|
||||||
|
// CartesianPosition attribute. It is assumed to be a pre-computed IfcAxis2Placement3D
|
||||||
|
// to be used by software that don't support IfcLinearPlacement. Check that the
|
||||||
|
// provided cartesian position is the same as the one determined by linear placement
|
||||||
|
if (inst->CartesianPosition()) {
|
||||||
|
auto m_fallback = taxonomy::cast<taxonomy::matrix4>(map(inst->CartesianPosition()));
|
||||||
|
if (m4 != m_fallback) {
|
||||||
|
Logger::Warning("IfcLinearPlacement.CartesianPosition is different than the computed placement", inst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @todo: rb - not sure what this means... it came from IfcLocalPlacement
|
||||||
|
// m4->components() = offset_and_rotation_ * m4->components();
|
||||||
|
|
||||||
|
return m4;
|
||||||
|
|
||||||
|
#else
|
||||||
|
// The IFC specification does not provided a description of the optional
|
||||||
|
// CartesianPosition attribute. It is assumed to be a pre-computed IfcAxis2Placement3D
|
||||||
|
// to be used by software that don't support IfcLinearPlacement. In this case,
|
||||||
|
// we will simply use the intended CartesianPosition provided by the IFC model
|
||||||
|
if (inst->CartesianPosition()) {
|
||||||
|
return map(inst->CartesianPosition());
|
||||||
|
} else {
|
||||||
|
Logger::Error("Unsupported");
|
||||||
|
}
|
||||||
#endif // SCHEMA_HAS_IfcAxis2PlacementLinear
|
#endif // SCHEMA_HAS_IfcAxis2PlacementLinear
|
||||||
|
|
||||||
// @todo: rb - not sure what this means... it came from IfcLocalPlacement
|
|
||||||
// m4->components() = offset_and_rotation_ * m4->components();
|
|
||||||
|
|
||||||
return m4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user