mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-10 06:00:51 +00:00
Merge remote-tracking branch 'origin/v0.8.0' into datamodel-v1.0
This commit is contained in:
@@ -452,6 +452,12 @@ namespace ifcopenshell {
|
||||
static constexpr bool defaultvalue = false;
|
||||
};
|
||||
|
||||
struct MakeVolume : public SettingBase<MakeVolume, bool> {
|
||||
static constexpr const char* const name = "make-volume";
|
||||
static constexpr const char* const description = "Try to isolate and fix a valid volume from non-manifold elements prior to opening subtraction";
|
||||
static constexpr bool defaultvalue = false;
|
||||
};
|
||||
|
||||
struct DeferProcessingFirstElement : public SettingBase<DeferProcessingFirstElement, bool, true> {
|
||||
static constexpr const char* const name = "defer-processing-first-element";
|
||||
static constexpr const char* const description = "Don't process first element in Iterator::initialize call()";
|
||||
@@ -647,7 +653,7 @@ namespace ifcopenshell {
|
||||
};
|
||||
|
||||
class Settings : public SettingsContainer<
|
||||
std::tuple<MesherLinearDeflection, MesherAngularDeflection, ReorientShells, LengthUnit, PlaneUnit, Precision, OutputDimensionality, LayersetFirst, DisableBooleanResult, NoWireIntersectionCheck, NoWireIntersectionTolerance, PrecisionFactor, DebugBooleanOperations, BooleanAttempt2d, SurfaceColour, WeldVertices, UseWorldCoords, UnifyShapes, UseMaterialNames, ConvertBackUnits, ContextIds, ContextTypes, ContextIdentifiers, IteratorOutput, DisableOpeningSubtractions, ApplyDefaultMaterials, DontEmitNormals, GenerateUvs, ApplyLayerSets, UseElementHierarchy, ValidateQuantities, EdgeArrows, BuildingLocalPlacement, SiteLocalPlacement, ForceSpaceTransparency, CircleSegments, CgalSmoothAngleDegrees, KeepBoundingBoxes, ComputeCurvature, FunctionStepType, FunctionStepParam, NoParallelMapping, PermissiveShapeReuse, ModelOffset, ModelRotation, TriangulationType, CgalEmitOriginalEdges, OcctNoCleanTriangulation, CacheShapes, DeferProcessingFirstElement, MaxOffset, MaxOffsetDeviation, ApplyOffset>
|
||||
std::tuple<MesherLinearDeflection, MesherAngularDeflection, ReorientShells, LengthUnit, PlaneUnit, Precision, OutputDimensionality, LayersetFirst, DisableBooleanResult, NoWireIntersectionCheck, NoWireIntersectionTolerance, PrecisionFactor, DebugBooleanOperations, BooleanAttempt2d, SurfaceColour, WeldVertices, UseWorldCoords, UnifyShapes, UseMaterialNames, ConvertBackUnits, ContextIds, ContextTypes, ContextIdentifiers, IteratorOutput, DisableOpeningSubtractions, ApplyDefaultMaterials, DontEmitNormals, GenerateUvs, ApplyLayerSets, UseElementHierarchy, ValidateQuantities, EdgeArrows, BuildingLocalPlacement, SiteLocalPlacement, ForceSpaceTransparency, CircleSegments, CgalSmoothAngleDegrees, KeepBoundingBoxes, ComputeCurvature, FunctionStepType, FunctionStepParam, NoParallelMapping, PermissiveShapeReuse, ModelOffset, ModelRotation, TriangulationType, CgalEmitOriginalEdges, OcctNoCleanTriangulation, CacheShapes, DeferProcessingFirstElement, MaxOffset, MaxOffsetDeviation, ApplyOffset, MakeVolume>
|
||||
>
|
||||
{};
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -91,7 +91,7 @@ bool IfcGeom::Representation::BRep::calculate_volume(double& volume) const {
|
||||
volume = 0.;
|
||||
return false;
|
||||
}
|
||||
volume = s->area()->to_double();
|
||||
volume = s->volume()->to_double();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1835,6 +1835,9 @@ bool CgalKernel::convert_impl(const taxonomy::boolean_result::ptr br, Conversion
|
||||
CGAL::Polygon_with_holes_2<Kernel_> pwh(p, ++it, loops.end());
|
||||
CGAL::Gps_segment_traits_2<Kernel_> traits;
|
||||
if (!CGAL::are_holes_and_boundary_pairwise_disjoint(pwh, traits)) {
|
||||
#ifdef IFOPSH_SIMPLE_KERNEL
|
||||
throw std::runtime_error("Holes are not disjoint - use a different geometry kernel");
|
||||
#else
|
||||
// this is very slow.
|
||||
// the check is also slow...
|
||||
|
||||
@@ -1851,6 +1854,7 @@ bool CgalKernel::convert_impl(const taxonomy::boolean_result::ptr br, Conversion
|
||||
result.difference(*it);
|
||||
}
|
||||
result.polygons_with_holes(std::back_inserter(pwhs));
|
||||
#endif
|
||||
} else {
|
||||
pwhs.push_back(pwh);
|
||||
}
|
||||
|
||||
@@ -1773,6 +1773,10 @@ namespace IfcGeom {
|
||||
auto& vs = elem->geometry().verts();
|
||||
auto& fs = elem->geometry().faces();
|
||||
|
||||
if (vs.empty() || fs.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
gp_Trsf tr;
|
||||
tr.SetValues(
|
||||
m(0, 0), m(0, 1), m(0, 2), m(0, 3),
|
||||
@@ -1840,23 +1844,36 @@ namespace IfcGeom {
|
||||
candidates.push_back({ std::abs(Z.Dot(ref)), ref });
|
||||
}
|
||||
|
||||
if (candidates.empty()) {
|
||||
{
|
||||
gp_XYZ ref(0, 0, 1);
|
||||
candidates.push_back({ std::abs(Z.Dot(ref)), ref });
|
||||
gp_Ax3 ax3;
|
||||
gp_Trsf trsf2;
|
||||
|
||||
for (size_t attempt = 0; attempt < 2; ++attempt) {
|
||||
|
||||
if (candidates.empty() || attempt == 1) {
|
||||
{
|
||||
gp_XYZ ref(0, 0, 1);
|
||||
candidates.push_back({std::abs(Z.Dot(ref)), ref});
|
||||
}
|
||||
{
|
||||
gp_XYZ ref(1, 0, 0);
|
||||
candidates.push_back({std::abs(Z.Dot(ref)), ref});
|
||||
}
|
||||
}
|
||||
|
||||
auto X = std::min_element(candidates.begin(), candidates.end(), [](auto& p1, auto& p2) { return p1.first < p2.first; })->second;
|
||||
|
||||
{
|
||||
gp_XYZ ref(1, 0, 0);
|
||||
candidates.push_back({ std::abs(Z.Dot(ref)), ref });
|
||||
try {
|
||||
ax3 = gp_Ax3(gp::Origin(), Z, X);
|
||||
trsf2.SetTransformation(gp::XOY(), ax3);
|
||||
} catch (Standard_ConstructionError&) {
|
||||
// Try again, likely we have all identical normals in candidates so
|
||||
// we cannot find a suitable candidate and need the two default axes
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto X = std::min_element(candidates.begin(), candidates.end(), [](auto& p1, auto& p2) { return p1.first < p2.first; })->second;
|
||||
|
||||
gp_Trsf trsf2;
|
||||
gp_Ax3 ax3(gp::Origin(), Z, X);
|
||||
trsf2.SetTransformation(gp::XOY(), ax3);
|
||||
|
||||
Bnd_Box tmp;
|
||||
|
||||
for (auto& p : vs_transformed) {
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "boolean_utils.h"
|
||||
#include "base_utils.h"
|
||||
|
||||
#include <BOPAlgo_MakerVolume.hxx>
|
||||
#include <BRepPrimAPI_MakeRevol.hxx>
|
||||
|
||||
namespace {
|
||||
@@ -136,7 +137,20 @@ bool IfcGeom::OpenCascadeKernel::convert_openings(const express::Base& entity, c
|
||||
bool is_manifold = util::is_manifold(entity_part);
|
||||
|
||||
if (!is_manifold) {
|
||||
logger::warning("Non-manifold first operand");
|
||||
if (settings_.get<settings::MakeVolume>().get()) {
|
||||
BOPAlgo_MakerVolume mv;
|
||||
mv.AddArgument(entity_part);
|
||||
mv.Perform();
|
||||
if (mv.HasErrors()) {
|
||||
logger::warning("Non-manifold first operand, --make-volume failed");
|
||||
} else {
|
||||
entity_part = mv.Shape();
|
||||
is_manifold = util::is_manifold(entity_part);
|
||||
}
|
||||
}
|
||||
if (!is_manifold) {
|
||||
logger::warning("Non-manifold first operand, use --make-volume to try and make manifold");
|
||||
}
|
||||
}
|
||||
|
||||
TopoDS_Shape entity_part_result;
|
||||
@@ -1363,4 +1377,4 @@ bool IfcGeom::OpenCascadeKernel::convert_impl(const taxonomy::revolve::ptr r, If
|
||||
// if (IfcGeom::util::apply_layerset(r, const std::vector<ifcopenshell::geometry::taxonomy::style>&, ConversionResults& r2, double tol)) {
|
||||
// std::swap(r, r2)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -56,6 +56,21 @@
|
||||
#include "../../../ifcgeom/taxonomy.h"
|
||||
#include "../../../ifcgeom/ConversionSettings.h"
|
||||
|
||||
namespace {
|
||||
template <typename Fn>
|
||||
bool handle_occt_exception(Fn&& fn) {
|
||||
try {
|
||||
return std::forward<Fn>(fn)();
|
||||
} catch (const Standard_Failure& e) {
|
||||
if (e.GetMessageString() && strlen(e.GetMessageString())) {
|
||||
throw std::runtime_error(e.GetMessageString());
|
||||
} else {
|
||||
throw std::runtime_error("Unknown error creating geometry");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace IfcGeom {
|
||||
|
||||
class IFC_GEOMLIBRARY_API OpenCascadeKernel : public ifcopenshell::geometry::kernels::AbstractKernel {
|
||||
|
||||
@@ -84,6 +84,7 @@ namespace {
|
||||
}
|
||||
|
||||
bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result::ptr br, ConversionResults& results) {
|
||||
return handle_occt_exception([&]() -> bool {
|
||||
bool valid_result = false;
|
||||
bool first = true;
|
||||
const double tol = settings_.get<settings::Precision>().get();
|
||||
@@ -196,4 +197,5 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result::ptr br, Con
|
||||
));
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1134,6 +1134,8 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
|
||||
#endif
|
||||
builder->SetFuzzyValue(fuzz);
|
||||
builder->SetArguments(s1s);
|
||||
// We use our own multi-threading in ifcopenshell on a per-product basis
|
||||
builder->SetRunParallel(false);
|
||||
copy_operand(b, b_tmp);
|
||||
std::swap(b, b_tmp);
|
||||
builder->SetTools(b);
|
||||
|
||||
@@ -72,6 +72,8 @@ bool OpenCascadeKernel::convert(const taxonomy::extrusion::ptr extrusion, TopoDS
|
||||
}
|
||||
|
||||
bool OpenCascadeKernel::convert_impl(const taxonomy::extrusion::ptr extrusion, IfcGeom::ConversionResults& results) {
|
||||
return handle_occt_exception([&]() -> bool {
|
||||
|
||||
TopoDS_Shape shape;
|
||||
if (!convert(extrusion, shape)) {
|
||||
return false;
|
||||
@@ -84,4 +86,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::extrusion::ptr extrusion, I
|
||||
extrusion->surface_style
|
||||
));
|
||||
return true;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -599,6 +599,8 @@ bool OpenCascadeKernel::convert(const taxonomy::face::ptr face, TopoDS_Shape& re
|
||||
}
|
||||
|
||||
bool OpenCascadeKernel::convert_impl(const taxonomy::face::ptr face, IfcGeom::ConversionResults& results) {
|
||||
return handle_occt_exception([&]() -> bool {
|
||||
|
||||
TopoDS_Shape shape;
|
||||
if (!convert(face, shape)) {
|
||||
return false;
|
||||
@@ -609,4 +611,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::face::ptr face, IfcGeom::Co
|
||||
face->surface_style
|
||||
));
|
||||
return true;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -107,6 +107,8 @@ bool OpenCascadeKernel::convert(const taxonomy::shell::ptr l, TopoDS_Shape& shap
|
||||
}
|
||||
|
||||
bool OpenCascadeKernel::convert_impl(const taxonomy::shell::ptr shell, IfcGeom::ConversionResults& results) {
|
||||
return handle_occt_exception([&]() -> bool {
|
||||
|
||||
TopoDS_Shape shape;
|
||||
if (!convert(shell, shape)) {
|
||||
return false;
|
||||
@@ -118,4 +120,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::shell::ptr shell, IfcGeom::
|
||||
shell->surface_style
|
||||
));
|
||||
return true;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -102,6 +102,8 @@ bool OpenCascadeKernel::convert(const taxonomy::solid::ptr solid, TopoDS_Shape&
|
||||
}
|
||||
|
||||
bool OpenCascadeKernel::convert_impl(const taxonomy::solid::ptr solid, IfcGeom::ConversionResults& results) {
|
||||
return handle_occt_exception([&]() -> bool {
|
||||
|
||||
TopoDS_Shape shape;
|
||||
if (!convert(solid, shape)) {
|
||||
return false;
|
||||
@@ -113,4 +115,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::solid::ptr solid, IfcGeom::
|
||||
solid->surface_style
|
||||
));
|
||||
return true;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -308,6 +308,8 @@ bool OpenCascadeKernel::convert(const taxonomy::sweep_along_curve::ptr scs, Topo
|
||||
}
|
||||
|
||||
bool OpenCascadeKernel::convert_impl(const taxonomy::sweep_along_curve::ptr scs, IfcGeom::ConversionResults& results) {
|
||||
return handle_occt_exception([&]() -> bool {
|
||||
|
||||
TopoDS_Shape shape;
|
||||
// For tiny radii occt will fail building the sweep, in which case we enlarge the inputs to occt, and add a scale matrix to the output
|
||||
bool enlarged = false;
|
||||
@@ -352,4 +354,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::sweep_along_curve::ptr scs,
|
||||
scs->surface_style
|
||||
));
|
||||
return true;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcObjectPlacement& inst) {
|
||||
|
||||
if (fallback) {
|
||||
auto mapped_fallback = taxonomy::cast<taxonomy::matrix4>(map(fallback));
|
||||
if (mapped_fallback != result) {
|
||||
if (!result->ccomponents().isApprox(mapped_fallback->ccomponents())) {
|
||||
logger::warning("Computed placement differs from fallback", inst);
|
||||
}
|
||||
}
|
||||
@@ -229,4 +229,4 @@ if (gridp = inst.as<IfcSchema::IfcGridPlacement>()) {
|
||||
|
||||
trsf.PreMultiply(grid_position);
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
||||
@@ -24,16 +24,11 @@ using namespace ifcopenshell::geometry;
|
||||
#ifdef SCHEMA_HAS_IfcToroidalSurface
|
||||
|
||||
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcToroidalSurface& inst) {
|
||||
return nullptr;
|
||||
|
||||
/*
|
||||
gp_Trsf trsf;
|
||||
IfcGeom::Kernel::convert(inst.Position(), trsf);
|
||||
|
||||
// IfcElementarySurface.Position has unit scale factor
|
||||
face = BRepBuilderAPI_MakeFace(new Geom_ToroidalSurface(gp::XOY(), inst.MajorRadius() * length_unit_, inst.MinorRadius() * length_unit_), getValue(GV_PRECISION)).Face().Moved(trsf);
|
||||
return true;
|
||||
*/
|
||||
auto torus = taxonomy::make<taxonomy::torus>();
|
||||
torus->radius1 = inst.MajorRadius() * length_unit_;
|
||||
torus->radius2 = inst.MinorRadius() * length_unit_;
|
||||
torus->matrix = taxonomy::cast<taxonomy::matrix4>(map(inst.Position()));
|
||||
return torus;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user