WKT footprint massaging

This commit is contained in:
Thomas Krijnen
2025-11-07 10:59:33 +01:00
parent 6dd34b1fa4
commit 7db2f66685
+54 -12
View File
@@ -31,6 +31,10 @@
#include <TopoDS.hxx> #include <TopoDS.hxx>
#include <Bnd_Box.hxx> #include <Bnd_Box.hxx>
#include <gp_Pln.hxx> #include <gp_Pln.hxx>
#include <TopoDS_Wire.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <GProp_GProps.hxx>
#include <BRepGProp.hxx>
#endif #endif
@@ -396,7 +400,14 @@ void TtlWktSerializer::write(const IfcGeom::BRepElement* brep_obj) {
filename_.stream << ttl_object_id(brep_obj) << " geo:hasMetricLength " << height << " .\n\n"; filename_.stream << ttl_object_id(brep_obj) << " geo:hasMetricLength " << height << " .\n\n";
gp_Pln pln(gp_Pnt(0, 0, zmin + section_height), gp::DZ()); std::map<double, std::string> polygons_by_area;
double rectangle_area = (x2 - x1) * (y2 - y1);
bool emitted_warning = false;
for (int iter = 0; iter < 10; ++iter) {
gp_Pln pln(gp_Pnt(0, 0, zmin + section_height + iter * (height - 1.) / 10.), gp::DZ());
Handle(TopTools_HSequenceOfShape) wires = new TopTools_HSequenceOfShape(); Handle(TopTools_HSequenceOfShape) wires = new TopTools_HSequenceOfShape();
@@ -417,6 +428,21 @@ void TtlWktSerializer::write(const IfcGeom::BRepElement* brep_obj) {
ShapeAnalysis_FreeBounds::ConnectEdgesToWires(edges, 1e-4, false, wires); ShapeAnalysis_FreeBounds::ConnectEdgesToWires(edges, 1e-4, false, wires);
for (int i = 1; i <= wires->Length(); ++i) { for (int i = 1; i <= wires->Length(); ++i) {
const TopoDS_Wire& wire = TopoDS::Wire(wires->Value(i)); const TopoDS_Wire& wire = TopoDS::Wire(wires->Value(i));
if (!wire.Closed()) {
continue;
}
BRepBuilderAPI_MakeFace mf(wire);
if (!mf.IsDone()) {
continue;
}
auto face = mf.Face();
// calculate face area
GProp_GProps props;
BRepGProp::SurfaceProperties(face, props);
auto area = props.Mass();
BRepTools_WireExplorer it(wire); BRepTools_WireExplorer it(wire);
std::vector<double> loop_coords; std::vector<double> loop_coords;
for (; it.More(); it.Next()) { for (; it.More(); it.Next()) {
@@ -433,19 +459,35 @@ void TtlWktSerializer::write(const IfcGeom::BRepElement* brep_obj) {
std::string postfix = "_section_geometry_" + std::to_string(N++); std::string postfix = "_section_geometry_" + std::to_string(N++);
filename_.stream << ttl_object_id(brep_obj) << " geo:hasGeometry " << ttl_object_id(brep_obj, postfix.c_str()) << " .\n\n"; std::ostringstream oss;
filename_.stream << ttl_object_id(brep_obj, postfix.c_str()) << " a geo:Geometry ;\n";
filename_.stream << " geo:asWKT " << escape_for_turtle( oss << ttl_object_id(brep_obj) << " geo:hasGeometry " << ttl_object_id(brep_obj, postfix.c_str()) << " .\n\n";
IfcUtil::convert_utf8( oss << ttl_object_id(brep_obj, postfix.c_str()) << " a geo:Geometry ;\n";
capture_output( oss << " geo:asWKT " << escape_for_turtle(IfcUtil::convert_utf8(capture_output(emit_line_component, loop_coords, loop_idxs, true, POLYGON))) << "^^geo:wktLiteral .\n\n";
emit_line_component,
loop_coords, polygons_by_area[area] = oss.str();
loop_idxs,
true,
POLYGON))
) << "^^geo:wktLiteral .\n\n";
} }
} }
if (polygons_by_area.size() > 0) {
if ((polygons_by_area.rbegin()->first > (0.6 * rectangle_area)) || (height < (1. + 1.e-5))) {
// Found sufficiently large polygon
if (emitted_warning) {
Logger::Warning("Found larger polygon area (" + std::to_string(polygons_by_area.rbegin()->first) + ").");
}
break;
} else if (!emitted_warning) {
Logger::Warning("Section polygon area is small compared to bounding box area (" + std::to_string(polygons_by_area.rbegin()->first) + " < " + std::to_string(0.6 * rectangle_area) + "). Trying again with different section height.");
emitted_warning = true;
}
}
}
if (polygons_by_area.size() > 0) {
// Emit polygon with largest area
auto it = polygons_by_area.rbegin();
filename_.stream << it->second;
}
#endif #endif
} }