mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-10 14:07:43 +00:00
Use exact topology points at parametric range bounds to guarantee welding #4487
This commit is contained in:
@@ -397,7 +397,10 @@ int IfcGeom::Representation::Triangulation::addVertex(int item_id, int material_
|
|||||||
if (settings().get<ifcopenshell::geometry::settings::WeldVertices>().get()) {
|
if (settings().get<ifcopenshell::geometry::settings::WeldVertices>().get()) {
|
||||||
const VertexKey key = std::make_tuple(item_id, material_index, X, Y, Z);
|
const VertexKey key = std::make_tuple(item_id, material_index, X, Y, Z);
|
||||||
typename VertexKeyMap::const_iterator it = welds.find(key);
|
typename VertexKeyMap::const_iterator it = welds.find(key);
|
||||||
if (it != welds.end()) return it->second;
|
if (it != welds.end()) {
|
||||||
|
// Return index for previously encountered point
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
i = (int)(welds.size() + weld_offset_);
|
i = (int)(welds.size() + weld_offset_);
|
||||||
welds[key] = i;
|
welds[key] = i;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -248,8 +248,34 @@ void ifcopenshell::geometry::OpenCascadeShape::Triangulate(ifcopenshell::geometr
|
|||||||
int previous = -1;
|
int previous = -1;
|
||||||
const bool reversed = texp.Value().Orientation() == TopAbs_REVERSED;
|
const bool reversed = texp.Value().Orientation() == TopAbs_REVERSED;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
|
gp_Pnt p0, p1;
|
||||||
|
double u0 = std::numeric_limits<double>::quiet_NaN(), u1 = std::numeric_limits<double>::quiet_NaN();
|
||||||
|
if (auto crv = BRep_Tool::Curve(TopoDS::Edge(texp.Value()), u0, u1)) {
|
||||||
|
TopoDS_Vertex v0, v1;
|
||||||
|
TopExp::Vertices(TopoDS::Edge(texp.Value()), v0, v1, false);
|
||||||
|
if (!v0.IsNull() && !v1.IsNull()) {
|
||||||
|
p0 = BRep_Tool::Pnt(v0);
|
||||||
|
p1 = BRep_Tool::Pnt(v1);
|
||||||
|
} else {
|
||||||
|
u0 = u1 = std::numeric_limits<double>::quiet_NaN();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = (reversed ? n : 1); reversed ? (i >= 1) : (i <= n); i += reversed ? -1 : 1) {
|
for (int i = (reversed ? n : 1); reversed ? (i >= 1) : (i <= n); i += reversed ? -1 : 1) {
|
||||||
gp_XYZ p = tessellater.Value(i).XYZ();
|
gp_XYZ p;
|
||||||
|
if (std::fabs(tessellater.Parameter(i) - u0) < 1.e-7) {
|
||||||
|
// Use the exact points from the topology when parameter is close to the begin or end of the parametric range
|
||||||
|
// This guarantees points are properly welded, because the GCPnts_QuasiUniformDeflection could otherwise introduce
|
||||||
|
// minor differences between the approximated points from shared vertices.
|
||||||
|
// @todo Using GCPnts_QuasiUniformDeflection on linear edges is pure lazyness
|
||||||
|
p = p0.XYZ();
|
||||||
|
} else if (std::fabs(tessellater.Parameter(i) - u1) < 1.e-7) {
|
||||||
|
p = p1.XYZ();
|
||||||
|
} else {
|
||||||
|
p = tessellater.Value(i).XYZ();
|
||||||
|
}
|
||||||
|
|
||||||
auto p_local = p;
|
auto p_local = p;
|
||||||
taxonomy_transform(place.components_, p);
|
taxonomy_transform(place.components_, p);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user