Merge branch 'v0.8.0' into ifcmax/initial-refresh

This commit is contained in:
Josef Wienerroither
2026-02-11 10:42:12 +01:00
5 changed files with 926 additions and 1005 deletions
+2 -5
View File
@@ -12,11 +12,8 @@ ifcopenshell::geometry::Converter::Converter(std::unique_ptr<ifcopenshell::geome
settings_ = mapping_->settings();
}
ifcopenshell::geometry::Converter::~Converter()
{
if (mapping_ != nullptr) {
delete mapping_;
}
ifcopenshell::geometry::Converter::~Converter() {
delete mapping_;
}
namespace {
+65 -35
View File
@@ -82,49 +82,79 @@ bool OpenCascadeKernel::convert(const taxonomy::loft::ptr loft, TopoDS_Shape& re
}
if (non_polygonal) {
if (loft->children.size() == 2) {
BRep_Builder BB;
TopoDS_Shell comp;
BB.MakeShell(comp);
if (loft->children.size() < 2) {
Logger::Error("Not enough sections to loft");
return false;
}
std::vector<std::vector<TopoDS_Wire>> sections;
sections.reserve(loft->children.size());
TopoDS_Shape f0, f1;
if (!convert(std::static_pointer_cast<taxonomy::face>(loft->children.front()), f0) ||
!convert(std::static_pointer_cast<taxonomy::face>(loft->children.back()), f1))
{
TopoDS_Shape f0, f1;
// Convert all children to vectors of wires
for (const auto& child : loft->children) {
TopoDS_Shape shape;
if (!convert(std::static_pointer_cast<taxonomy::face>(child), shape)) {
return false;
}
if (shape.ShapeType() != TopAbs_FACE) {
return false;
}
// At least make sure to have outer wire consistent, but in reality
// this is probably not a concern given how to build up these faces
auto f = TopoDS::Face(shape);
if (child == loft->children.front()) {
f0 = f;
} else if (child == loft->children.back()) {
f1 = f;
}
auto outer = BRepTools::OuterWire(f);
sections.emplace_back();
sections.back().push_back(outer);
for (TopoDS_Iterator it(f); it.More(); it.Next()) {
if (outer != it.Value()) {
sections.back().push_back(TopoDS::Wire(it.Value()));
}
}
}
auto first_wire_count = sections.front().size();
for (auto& section : sections) {
if (section.size() != first_wire_count) {
Logger::Error("Inconsistent number of wires in sections");
return false;
}
if (f0.ShapeType() != TopAbs_FACE || f1.ShapeType() != TopAbs_FACE) {
}
BRep_Builder BB;
TopoDS_Shell comp;
BB.MakeShell(comp);
for (size_t i = 0; i < first_wire_count; ++i) {
// Rule=True uses linear interpolation.
// This is critical for preventing twists in roads/railings.
BRepOffsetAPI_ThruSections builder(false, true);
for (auto& ws : sections) {
builder.AddWire(ws[i]);
}
builder.Build();
if (!builder.IsDone()) {
return false;
}
TopExp_Explorer exp1(f0, TopAbs_WIRE);
TopExp_Explorer exp2(f1, TopAbs_WIRE);
for (; exp1.More() && exp2.More(); exp1.Next(), exp2.Next()) {
const auto& w1 = TopoDS::Wire(exp1.Current());
const auto& w2 = TopoDS::Wire(exp2.Current());
BRepOffsetAPI_ThruSections builder;
builder.AddWire(w1);
builder.AddWire(w2);
builder.Build();
if (!builder.IsDone()) {
return false;
}
for (TopExp_Explorer exp(builder.Shape(), TopAbs_FACE); exp.More(); exp.Next()) {
BB.Add(comp, exp.Current());
}
for (TopExp_Explorer exp(builder.Shape(), TopAbs_FACE); exp.More(); exp.Next()) {
BB.Add(comp, exp.Current());
}
BB.Add(comp, f0.Reversed());
BB.Add(comp, f1);
result = BRepBuilderAPI_MakeSolid(comp).Solid();
return true;
} else {
Logger::Error("Lofting more than two sections is not supported");
return false;
}
BB.Add(comp, f0.Reversed());
BB.Add(comp, f1);
result = BRepBuilderAPI_MakeSolid(comp).Solid();
return true;
}
TopTools_ListOfShape faces;
@@ -21,7 +21,41 @@
#define mapping POSTFIX_SCHEMA(mapping)
using namespace ifcopenshell::geometry;
#include <deque>
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcObjectPlacement* inst) {
if (placement_rel_to_type_ || placement_rel_to_instance_) {
using QueueItem = std::pair<const IfcUtil::IfcBaseEntity*, int>;
std::deque<QueueItem> q = {{inst, 0}};
while (!q.empty()) {
auto [placement_entity, depth] = q.front();
q.pop_front();
auto placement = placement_entity->as<typename IfcSchema::IfcObjectPlacement>();
if (!placement) {
continue;
}
auto self_places = placement->PlacesObject();
inst->ReferencedByPlacements();
for (auto iter = self_places->begin(); iter != self_places->end(); ++iter) {
if ((placement_rel_to_type_ && (*iter)->declaration().is(*placement_rel_to_type_)) ||
(placement_rel_to_instance_ && (*iter)->as<IfcUtil::IfcBaseEntity>() == placement_rel_to_instance_)) {
return taxonomy::make<taxonomy::matrix4>();
}
}
// Look for two levels deep, we want to know if we're at or *above* the
// element we're ignoring, but we don't want to traverse the entire model.
if (depth < 2) {
auto refs = placement->ReferencedByPlacements();
for (auto& ref : *refs) {
q.emplace_back(ref, depth + 1);
}
}
}
}
const IfcSchema::IfcObjectPlacement* relative_to = nullptr;
const IfcUtil::IfcBaseInterface* transform;
File diff suppressed because it is too large Load Diff
+12
View File
@@ -2,8 +2,10 @@
#define GRAPH_2D_H
#ifdef SVGFILL_DEBUG
#if 0
#include <nlohmann/json.hpp>
#endif
#endif
template <typename Kernel>
class Graph2D {
@@ -334,6 +336,16 @@ public:
return Graph2D(input_adjacency_list);
}
template <typename T>
void to_arrangement(T& arr) {
for (auto it = edges_begin(); it != edges_end(); ++it) {
if (it->first == it->second) {
continue;
}
CGAL::insert(arr, CGAL::Segment_2<Kernel>(it->first, it->second));
}
}
void assert_symmetric() {
#ifdef SVGFILL_DEBUG
#if 0