mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-26 02:07:36 +00:00
WKT footprint massaging
This commit is contained in:
@@ -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,56 +400,94 @@ 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;
|
||||||
|
|
||||||
Handle(TopTools_HSequenceOfShape) wires = new TopTools_HSequenceOfShape();
|
double rectangle_area = (x2 - x1) * (y2 - y1);
|
||||||
|
bool emitted_warning = false;
|
||||||
|
|
||||||
size_t N = 0;
|
for (int iter = 0; iter < 10; ++iter) {
|
||||||
TopoDS_Iterator it(compound);
|
|
||||||
// Iterate over components of compound to have better chance of matching section edges to closed wires
|
|
||||||
for (; it.More(); it.Next()) {
|
|
||||||
Handle(TopTools_HSequenceOfShape) edges = new TopTools_HSequenceOfShape();
|
|
||||||
TopoDS_Shape result = BRepAlgoAPI_Section(it.Value(), pln);
|
|
||||||
|
|
||||||
{
|
gp_Pln pln(gp_Pnt(0, 0, zmin + section_height + iter * (height - 1.) / 10.), gp::DZ());
|
||||||
TopExp_Explorer exp(result, TopAbs_EDGE);
|
|
||||||
for (; exp.More(); exp.Next()) {
|
|
||||||
edges->Append(exp.Current());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ShapeAnalysis_FreeBounds::ConnectEdgesToWires(edges, 1e-4, false, wires);
|
Handle(TopTools_HSequenceOfShape) wires = new TopTools_HSequenceOfShape();
|
||||||
for (int i = 1; i <= wires->Length(); ++i) {
|
|
||||||
const TopoDS_Wire& wire = TopoDS::Wire(wires->Value(i));
|
|
||||||
BRepTools_WireExplorer it(wire);
|
|
||||||
std::vector<double> loop_coords;
|
|
||||||
for (; it.More(); it.Next()) {
|
|
||||||
const auto& v = it.CurrentVertex();
|
|
||||||
auto pnt = BRep_Tool::Pnt(v);
|
|
||||||
loop_coords.push_back(pnt.X());
|
|
||||||
loop_coords.push_back(pnt.Y());
|
|
||||||
loop_coords.push_back(pnt.Z());
|
|
||||||
}
|
|
||||||
std::vector<int> loop_idxs(loop_coords.size() / 3);
|
|
||||||
for (int i = 0; i < loop_idxs.size(); ++i) {
|
|
||||||
loop_idxs[i] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string postfix = "_section_geometry_" + std::to_string(N++);
|
size_t N = 0;
|
||||||
|
TopoDS_Iterator it(compound);
|
||||||
|
// Iterate over components of compound to have better chance of matching section edges to closed wires
|
||||||
|
for (; it.More(); it.Next()) {
|
||||||
|
Handle(TopTools_HSequenceOfShape) edges = new TopTools_HSequenceOfShape();
|
||||||
|
TopoDS_Shape result = BRepAlgoAPI_Section(it.Value(), pln);
|
||||||
|
|
||||||
filename_.stream << ttl_object_id(brep_obj) << " geo:hasGeometry " << ttl_object_id(brep_obj, postfix.c_str()) << " .\n\n";
|
{
|
||||||
filename_.stream << ttl_object_id(brep_obj, postfix.c_str()) << " a geo:Geometry ;\n";
|
TopExp_Explorer exp(result, TopAbs_EDGE);
|
||||||
filename_.stream << " geo:asWKT " << escape_for_turtle(
|
for (; exp.More(); exp.Next()) {
|
||||||
IfcUtil::convert_utf8(
|
edges->Append(exp.Current());
|
||||||
capture_output(
|
}
|
||||||
emit_line_component,
|
}
|
||||||
loop_coords,
|
|
||||||
loop_idxs,
|
ShapeAnalysis_FreeBounds::ConnectEdgesToWires(edges, 1e-4, false, wires);
|
||||||
true,
|
for (int i = 1; i <= wires->Length(); ++i) {
|
||||||
POLYGON))
|
const TopoDS_Wire& wire = TopoDS::Wire(wires->Value(i));
|
||||||
) << "^^geo:wktLiteral .\n\n";
|
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);
|
||||||
|
std::vector<double> loop_coords;
|
||||||
|
for (; it.More(); it.Next()) {
|
||||||
|
const auto& v = it.CurrentVertex();
|
||||||
|
auto pnt = BRep_Tool::Pnt(v);
|
||||||
|
loop_coords.push_back(pnt.X());
|
||||||
|
loop_coords.push_back(pnt.Y());
|
||||||
|
loop_coords.push_back(pnt.Z());
|
||||||
|
}
|
||||||
|
std::vector<int> loop_idxs(loop_coords.size() / 3);
|
||||||
|
for (int i = 0; i < loop_idxs.size(); ++i) {
|
||||||
|
loop_idxs[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string postfix = "_section_geometry_" + std::to_string(N++);
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
|
||||||
|
oss << ttl_object_id(brep_obj) << " geo:hasGeometry " << ttl_object_id(brep_obj, postfix.c_str()) << " .\n\n";
|
||||||
|
oss << ttl_object_id(brep_obj, postfix.c_str()) << " a geo:Geometry ;\n";
|
||||||
|
oss << " geo:asWKT " << escape_for_turtle(IfcUtil::convert_utf8(capture_output(emit_line_component, loop_coords, loop_idxs, true, POLYGON))) << "^^geo:wktLiteral .\n\n";
|
||||||
|
|
||||||
|
polygons_by_area[area] = oss.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user