Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0

This commit is contained in:
Dion Moult
2020-06-18 11:50:54 +10:00
29 changed files with 90505 additions and 147 deletions
+1 -1
View File
@@ -459,7 +459,7 @@ function(files_for_ifc_version IFC_VERSION RESULT_NAME)
)
endfunction()
set(SCHEMA_VERSIONS "2x3" "4" "4x1" "4x2")
set(SCHEMA_VERSIONS "2x3" "4" "4x1" "4x2" "4x3_rc1")
if(COMPILE_SCHEMA)
# @todo, this appears to be untested at the moment
+61 -37
View File
@@ -221,6 +221,7 @@ int main(int argc, char** argv) {
"based on an interpretation of the geometry when exporting IFC");
int num_threads;
std::string offset_str, rotation_str;
po::options_description geom_options("Geometry options");
geom_options.add_options()
@@ -252,6 +253,13 @@ int main(int argc, char** argv) {
"This is a potentially time consuming operation, but guarantees a "
"consistent orientation of surface normals, even if the faces are not "
"properly oriented in the IFC file.")
("center-model",
"Centers the elements by applying the center point of all placements as an offset."
"Can take several minutes on large models.")
("model-offset", po::value<std::string>(&offset_str),
"Applies an arbitrary offset of form 'x;y;z' to all placements.")
("model-rotation", po::value<std::string>(&rotation_str),
"Applies an arbitrary quaternion rotation of form 'x;y;z;w' to all placements.")
#if OCC_VERSION_HEX < 0x60900
// In Open CASCADE version prior to 6.9.0 boolean operations with multiple
// arguments where not introduced yet and a work-around was implemented to
@@ -311,7 +319,7 @@ int main(int argc, char** argv) {
"if an object does not have any specified material in the IFC file.")
("validate", "Checks whether geometrical output conforms to the included explicit quantities.");
std::string bounds, offset_str;
std::string bounds;
#ifdef HAVE_ICU
std::string unicode_mode;
#endif
@@ -344,11 +352,6 @@ int main(int argc, char** argv) {
("use-element-hierarchy",
"Order the elements using their IfcBuildingStorey parent. "
"Applicable for DAE output.")
("center-model",
"Centers the elements upon serialization by applying the center point of "
"all placements as an offset. Applicable for OBJ and DAE output. Can take several minutes on large models.")
("model-offset", po::value<std::string>(&offset_str),
"Applies an arbitrary offset of form 'x;y;z' to all placements. Applicable for OBJ and DAE output.")
("site-local-placement",
"Place elements locally in the IfcSite coordinate system, instead of placing "
"them in the IFC global coords. Applicable for OBJ and DAE output.")
@@ -360,7 +363,9 @@ int main(int argc, char** argv) {
"Applicable for OBJ and DAE output. For DAE output, value >= 15 means that up to 16 decimals are used, "
" and any other value means that 6 or 7 decimals are used.")
("print-space-names", "Prints IfcSpace LongName and Name in the geometry output. Applicable for SVG output")
("print-space-areas", "Prints calculated IfcSpace areas in square meters. Applicable for SVG output");
("print-space-areas", "Prints calculated IfcSpace areas in square meters. Applicable for SVG output")
("edge-arrows", "Adds arrow heads to edge segments to signify edge direction")
;
po::options_description cmdline_options;
cmdline_options.add(generic_options).add(fileio_options).add(geom_options).add(ifc_options).add(serializer_options);
@@ -417,10 +422,12 @@ int main(int argc, char** argv) {
const bool no_normals = vmap.count("no-normals") != 0;
const bool center_model = vmap.count("center-model") != 0;
const bool model_offset = vmap.count("model-offset") != 0;
const bool model_rotation = vmap.count("model-rotation") != 0;
const bool site_local_placement = vmap.count("site-local-placement") != 0;
const bool building_local_placement = vmap.count("building-local-placement") != 0;
const bool generate_uvs = vmap.count("generate-uvs") != 0;
const bool validate = vmap.count("validate") != 0;
const bool edge_arrows = vmap.count("edge-arrows") != 0;
if (!quiet || vmap.count("version")) {
print_version();
@@ -650,6 +657,7 @@ int main(int argc, char** argv) {
settings.set(IfcGeom::IteratorSettings::LAYERSET_FIRST, layerset_first);
settings.set(IfcGeom::IteratorSettings::NO_NORMALS, no_normals);
settings.set(IfcGeom::IteratorSettings::GENERATE_UVS, generate_uvs);
settings.set(IfcGeom::IteratorSettings::EDGE_ARROWS, edge_arrows);
settings.set(IfcGeom::IteratorSettings::SEARCH_FLOOR, use_element_hierarchy || output_extension == SVG);
settings.set(IfcGeom::IteratorSettings::SITE_LOCAL_PLACEMENT, site_local_placement);
settings.set(IfcGeom::IteratorSettings::BUILDING_LOCAL_PLACEMENT, building_local_placement);
@@ -758,6 +766,52 @@ int main(int argc, char** argv) {
Logger::SetOutput(quiet ? nullptr : &cout_, &log_stream);
if (model_rotation) {
std::array<double, 4> &rotation = settings.rotation;
if (sscanf(rotation_str.c_str(), "%lf;%lf;%lf;%lf", &rotation[0], &rotation[1], &rotation[2], &rotation[3]) != 4) {
cerr_ << "[Error] Invalid use of --model-rotation\n";
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename));
print_options(serializer_options);
return EXIT_FAILURE;
}
std::stringstream msg;
msg << "Using model rotation (" << rotation[0] << "," << rotation[1] << "," << rotation[2] << "," << rotation[3] << ")";
Logger::Notice(msg.str());
}
if (is_tesselated && (center_model || model_offset)) {
std::array<double, 3> &offset = settings.offset;
if (center_model) {
if (site_local_placement || building_local_placement) {
Logger::Error("Cannot use --center-model together with --{site,building}-local-placement");
return EXIT_FAILURE;
}
IfcGeom::Iterator<real_t> tmp_context_iterator(settings, ifc_file, filter_funcs, num_threads);
if (!quiet) Logger::Status("Computing bounds...");
tmp_context_iterator.compute_bounds();
if (!quiet) Logger::Status("Done!");
gp_XYZ center = (tmp_context_iterator.bounds_min() + tmp_context_iterator.bounds_max()) * 0.5;
offset[0] = -center.X();
offset[1] = -center.Y();
offset[2] = -center.Z();
} else {
if (sscanf(offset_str.c_str(), "%lf;%lf;%lf", &offset[0], &offset[1], &offset[2]) != 3) {
cerr_ << "[Error] Invalid use of --model-offset\n";
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename));
print_options(serializer_options);
return EXIT_FAILURE;
}
}
std::stringstream msg;
msg << "Using model offset (" << offset[0] << "," << offset[1] << "," << offset[2] << ")";
Logger::Notice(msg.str());
}
IfcGeom::Iterator<real_t> context_iterator(settings, ifc_file, filter_funcs, num_threads);
if (!context_iterator.initialize()) {
/// @todo It would be nice to know and print separate error prints for a case where we found no entities
@@ -781,36 +835,6 @@ int main(int argc, char** argv) {
int old_progress = quiet ? 0 : -1;
if (is_tesselated && (center_model || model_offset)) {
double* offset = serializer->settings().offset;
if (center_model) {
if (site_local_placement || building_local_placement) {
Logger::Error("Cannot use --center-model together with --{site,building}-local-placement");
return EXIT_FAILURE;
}
if (!quiet) Logger::Status("Computing bounds...");
context_iterator.compute_bounds();
if (!quiet) Logger::Status("Done!");
gp_XYZ center = (context_iterator.bounds_min() + context_iterator.bounds_max()) * 0.5;
offset[0] = -center.X();
offset[1] = -center.Y();
offset[2] = -center.Z();
} else {
if (sscanf(offset_str.c_str(), "%lf;%lf;%lf", &offset[0], &offset[1], &offset[2]) != 3) {
cerr_ << "[Error] Invalid use of --model-offset\n";
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename));
print_options(serializer_options);
return EXIT_FAILURE;
}
}
std::stringstream msg;
msg << "Using model offset (" << offset[0] << "," << offset[1] << "," << offset[2] << ")";
Logger::Notice(msg.str());
}
if (!quiet) {
if (num_threads == 1) {
Logger::Status("Creating geometry...");
+34 -10
View File
@@ -21,6 +21,7 @@
#define IFCGEOM_H
#include <cmath>
#include <array>
static const double ALMOST_ZERO = 1.e-9;
@@ -37,6 +38,7 @@ inline static bool ALMOST_THE_SAME(const T& a, const T& b, double tolerance=ALMO
#include <gp_GTrsf2d.hxx>
#include <gp_Trsf.hxx>
#include <gp_Trsf2d.hxx>
#include <gp_Quaternion.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Wire.hxx>
#include <TopoDS_Face.hxx>
@@ -222,6 +224,9 @@ private:
double modelling_precision;
double dimensionality;
double layerset_first;
gp_Vec offset = gp_Vec{0.0, 0.0, 0.0};
gp_Quaternion rotation = gp_Quaternion{};
gp_Trsf offset_and_rotation = gp_Trsf();
#ifndef NO_CACHE
MAKE_TYPE_NAME(Cache) cache;
@@ -245,25 +250,44 @@ public:
, ifc_planeangle_unit(-1.0)
, modelling_precision(0.00001)
, dimensionality(1.)
, placement_rel_to(0)
, placement_rel_to(nullptr)
, faceset_helper_(nullptr)
{}
MAKE_TYPE_NAME(Kernel)(const MAKE_TYPE_NAME(Kernel)& other) : IfcGeom::Kernel(0) {
*this = other;
MAKE_TYPE_NAME(Kernel)(const MAKE_TYPE_NAME(Kernel)& other)
: IfcGeom::Kernel(0)
, deflection_tolerance(other.deflection_tolerance)
, max_faces_to_orient(other.max_faces_to_orient)
, ifc_length_unit(other.ifc_length_unit)
, ifc_planeangle_unit(other.ifc_planeangle_unit)
, modelling_precision(other.modelling_precision)
, dimensionality(other.dimensionality)
, placement_rel_to(other.placement_rel_to)
// @nb faceset_helper_ always initialized to 0
, faceset_helper_(nullptr)
, offset(other.offset)
, rotation(other.rotation)
, offset_and_rotation(other.offset_and_rotation)
{
}
MAKE_TYPE_NAME(Kernel)& operator=(const MAKE_TYPE_NAME(Kernel)& other) {
setValue(GV_DEFLECTION_TOLERANCE, other.getValue(GV_DEFLECTION_TOLERANCE));
setValue(GV_MAX_FACES_TO_ORIENT, other.getValue(GV_MAX_FACES_TO_ORIENT));
setValue(GV_LENGTH_UNIT, other.getValue(GV_LENGTH_UNIT));
setValue(GV_PLANEANGLE_UNIT, other.getValue(GV_PLANEANGLE_UNIT));
setValue(GV_PRECISION, other.getValue(GV_PRECISION));
setValue(GV_DIMENSIONALITY, other.getValue(GV_DIMENSIONALITY));
setValue(GV_LAYERSET_FIRST, other.getValue(GV_LAYERSET_FIRST));
deflection_tolerance = other.deflection_tolerance;
max_faces_to_orient = other.max_faces_to_orient;
ifc_length_unit = other.ifc_length_unit;
ifc_planeangle_unit = other.ifc_planeangle_unit;
modelling_precision = other.modelling_precision;
dimensionality = other.dimensionality;
placement_rel_to = other.placement_rel_to;
offset = other.offset;
rotation = other.rotation;
offset_and_rotation = other.offset_and_rotation;
return *this;
}
void set_offset(const std::array<double, 3>& offset);
void set_rotation(const std::array<double, 4>& rotation);
bool convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face);
bool convert_curve_to_wire(const Handle(Geom_Curve)& curve, TopoDS_Wire& wire);
bool convert_shapes(const IfcUtil::IfcBaseClass* L, IfcRepresentationShapeItems& result);
+24 -2
View File
@@ -505,6 +505,28 @@ namespace {
usd.Build();
return usd.Shape();
}
gp_Trsf combine_offset_and_rotation(const gp_Vec &offset, const gp_Quaternion& rotation) {
auto offset_transform = gp_Trsf{};
offset_transform.SetTranslation(offset);
auto rotation_transform = gp_Trsf{};
rotation_transform.SetRotation(rotation);
return rotation_transform * offset_transform;
}
}
void IfcGeom::Kernel::set_offset(const std::array<double, 3> &p_offset) {
offset = gp_Vec(p_offset[0], p_offset[1], p_offset[2]);
offset_and_rotation = combine_offset_and_rotation(offset, rotation);
}
void IfcGeom::Kernel::set_rotation(const std::array<double, 4> &p_rotation) {
rotation = gp_Quaternion(p_rotation[0], p_rotation[1], p_rotation[2], p_rotation[3]);
offset_and_rotation = combine_offset_and_rotation(offset, rotation);
}
bool IfcGeom::Kernel::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) {
@@ -4369,8 +4391,8 @@ IfcGeom::Kernel::faceset_helper::faceset_helper(Kernel* kernel, const IfcSchema:
edge_set_t segment_set;
loop_(ps, [&segments, &segment_set](int C, int D, bool) {
segment_set.insert({ { C, D } });
segments.push_back({ C, D });
segment_set.insert(edge_t{C,D});
segments.push_back(std::make_pair(C, D));
});
if (edge_sets.find(segment_set) != edge_sets.end()) {
+3
View File
@@ -418,6 +418,9 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& t
else break;
} else break;
}
trsf.PreMultiply(offset_and_rotation);
CACHE(IfcObjectPlacement,l,trsf)
return true;
}
@@ -985,6 +985,8 @@ namespace IfcGeom {
} else if (settings.get(IteratorSettings::SITE_LOCAL_PLACEMENT)) {
kernel.set_conversion_placement_rel_to(&IfcSchema::IfcSite::Class());
}
kernel.set_offset(settings.offset);
kernel.set_rotation(settings.rotation);
}
public:
+10 -1
View File
@@ -20,6 +20,8 @@
#ifndef IFCGEOMITERATORSETTINGS_H
#define IFCGEOMITERATORSETTINGS_H
#include <array>
#include "ifc_geom_api.h"
#include "../ifcparse/IfcException.h"
#include "../ifcparse/IfcBaseClass.h"
@@ -88,8 +90,10 @@ namespace IfcGeom
VALIDATE_QUANTITIES = 1 << 17,
/// Assigns the first layer material to the entire product
LAYERSET_FIRST = 1 << 18,
/// Adds arrow heads to edge segments to signify edge direction
EDGE_ARROWS = 1 << 19,
/// Number of different setting flags.
NUM_SETTINGS = 18
NUM_SETTINGS = 19
};
/// Used to store logical OR combination of setting flags.
typedef unsigned SettingField;
@@ -132,6 +136,11 @@ namespace IfcGeom
}
}
/// Optional offset that is applied to serialized objects, (0,0,0) by default.
std::array<double,3> offset = std::array<double,3>{0.0, 0.0, 0.0};
/// Optional rotation that is applied to serialized objects, (0,0,0,1) by default.
std::array<double,4> rotation = std::array<double,4>{0.0, 0.0, 0.0, 1.0};
protected:
SettingField settings_;
double deflection_tolerance_;
+39 -44
View File
@@ -290,57 +290,52 @@ namespace IfcGeom {
for (int i = 1; i <= n; ++i) {
gp_XYZ p = tessellater.Value(i).XYZ();
/*
// In case you want direction arrows on your edges
double u = tessellater.Parameter(i);
gp_XYZ p2, p3;
gp_Pnt tmp;
gp_Vec tmp2;
crv.D1(u, tmp, tmp2);
gp_Dir d1, d2, d3, d4;
d1 = tmp2;
if (texp.Current().Orientation() == TopAbs_REVERSED) {
d1 = -d1;
}
if (fabs(d1.Z()) < 0.5) {
d2 = d1.Crossed(gp::DZ());
} else {
d2 = d1.Crossed(gp::DY());
}
d3 = d1.XYZ() + d2.XYZ();
d4 = d1.XYZ() - d2.XYZ();
p2 = p - d3.XYZ() / 10.;
p3 = p - d4.XYZ() / 10.;
trsf.Transforms(p2);
trsf.Transforms(p3);
_material_ids.push_back(surface_style_id);
_material_ids.push_back(surface_style_id);
_verts.push_back(static_cast<P>(p2.X()));
_verts.push_back(static_cast<P>(p2.Y()));
_verts.push_back(static_cast<P>(p2.Z()));
_verts.push_back(static_cast<P>(p3.X()));
_verts.push_back(static_cast<P>(p3.Y()));
_verts.push_back(static_cast<P>(p3.Z()));
*/
trsf.Transforms(p);
int current = addVertex(surface_style_id, p);
std::vector<std::pair<int, int>> segments;
if (i > 1) {
_edges.push_back(previous);
_edges.push_back(current);
segments.push_back(std::make_pair(previous, current));
}
if (settings().get(IfcGeom::IteratorSettings::EDGE_ARROWS)) {
// In case you want direction arrows on your edges
double u = tessellater.Parameter(i);
gp_XYZ p2, p3;
gp_Pnt tmp;
gp_Vec tmp2;
crv.D1(u, tmp, tmp2);
gp_Dir d1, d2, d3, d4;
d1 = tmp2;
if (texp.Current().Orientation() == TopAbs_REVERSED) {
d1 = -d1;
}
if (fabs(d1.Z()) < 0.5) {
d2 = d1.Crossed(gp::DZ());
} else {
d2 = d1.Crossed(gp::DY());
}
d3 = d1.XYZ() + d2.XYZ();
d4 = d1.XYZ() - d2.XYZ();
p2 = p - d3.XYZ() / 10.;
p3 = p - d4.XYZ() / 10.;
trsf.Transforms(p2);
trsf.Transforms(p3);
trsf.Transforms(p);
int left = addVertex(surface_style_id, p2);
int right = addVertex(surface_style_id, p3);
segments.push_back(std::make_pair(left, current));
segments.push_back(std::make_pair(right, current));
}
for (auto& s : segments) {
_edges.push_back(s.first);
_edges.push_back(s.second);
_material_ids.push_back(surface_style_id);
// _edges.push_back(start + 3 * (i - 2) + 2);
// _edges.push_back(start + 3 * (i - 1) + 2);
}
previous = current;
// _edges.push_back(start + 3 * (i - 1) + 0);
// _edges.push_back(start + 3 * (i - 1) + 2);
// _edges.push_back(start + 3 * (i - 1) + 1);
// _edges.push_back(start + 3 * (i - 1) + 2);
}
}
}
+11 -9
View File
@@ -75,16 +75,18 @@ void opencascade_array_to_vector2(T& t, std::vector< std::vector<U> >& u) {
}
#ifdef SCHEMA_HAS_IfcRationalBSplineSurfaceWithKnots
IfcSchema::IfcKnotType::Value opencascade_knotspec_to_ifc(GeomAbs_BSplKnotDistribution bspline_knot_spec) {
IfcSchema::IfcKnotType::Value knot_spec = IfcSchema::IfcKnotType::IfcKnotType_UNSPECIFIED;
if (bspline_knot_spec == GeomAbs_Uniform) {
knot_spec = IfcSchema::IfcKnotType::IfcKnotType_UNIFORM_KNOTS;
} else if (bspline_knot_spec == GeomAbs_QuasiUniform) {
knot_spec = IfcSchema::IfcKnotType::IfcKnotType_QUASI_UNIFORM_KNOTS;
} else if (bspline_knot_spec == GeomAbs_PiecewiseBezier) {
knot_spec = IfcSchema::IfcKnotType::IfcKnotType_PIECEWISE_BEZIER_KNOTS;
namespace {
IfcSchema::IfcKnotType::Value opencascade_knotspec_to_ifc(GeomAbs_BSplKnotDistribution bspline_knot_spec) {
IfcSchema::IfcKnotType::Value knot_spec = IfcSchema::IfcKnotType::IfcKnotType_UNSPECIFIED;
if (bspline_knot_spec == GeomAbs_Uniform) {
knot_spec = IfcSchema::IfcKnotType::IfcKnotType_UNIFORM_KNOTS;
} else if (bspline_knot_spec == GeomAbs_QuasiUniform) {
knot_spec = IfcSchema::IfcKnotType::IfcKnotType_QUASI_UNIFORM_KNOTS;
} else if (bspline_knot_spec == GeomAbs_PiecewiseBezier) {
knot_spec = IfcSchema::IfcKnotType::IfcKnotType_PIECEWISE_BEZIER_KNOTS;
}
return knot_spec;
}
return knot_spec;
}
#endif
+64 -16
View File
@@ -708,6 +708,60 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcArbitraryOpenProfileDef* l, To
return convert_wire(l->Curve(), result);
}
#include <Extrema_ExtPC.hxx>
namespace {
bool create_edge_over_curve_with_log_messages(const Handle_Geom_Curve& crv, const double eps, const gp_Pnt& p1, const gp_Pnt& p2, TopoDS_Edge& result) {
if (crv->IsClosed() && p1.Distance(p2) <= eps) {
BRepBuilderAPI_MakeEdge me(crv);
if (me.IsDone()) {
result = me.Edge();
return true;
} else {
return false;
}
}
BRep_Builder builder;
TopoDS_Vertex v1, v2;
/// @todo project first and emit warnings accordingly
builder.MakeVertex(v1, p1, eps);
builder.MakeVertex(v2, p2, eps);
BRepBuilderAPI_MakeEdge me(crv, v1, v2);
if (!me.IsDone()) {
const double eps2 = eps * eps;
if (me.Error() == BRepLib_PointProjectionFailed) {
GeomAdaptor_Curve GAC(crv);
const gp_Pnt* ps[2] = { &p1, &p2 };
for (int i = 0; i < 2; ++i) {
Extrema_ExtPC extrema(*ps[i], GAC);
if (extrema.IsDone()) {
int n = extrema.NbExt();
double dmin = std::numeric_limits<double>::infinity();
for (int j = 1; j <= n; j++) {
const double d = extrema.SquareDistance(j);
if (d < dmin) {
dmin = d;
}
}
if (dmin == std::numeric_limits<double>::infinity()) {
Logger::Error("No extrema for point");
} else if (dmin > eps2) {
Logger::Error("Distance of " + boost::lexical_cast<std::string>(std::sqrt(dmin)) + " exceeds tolerance");
}
} else {
Logger::Error("Failed to calculate extrema for point");
}
}
}
return false;
}
result = me.Edge();
return true;
}
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdgeCurve* l, TopoDS_Wire& result) {
IfcSchema::IfcPoint* pnt1 = ((IfcSchema::IfcVertexPoint*) l->EdgeStart())->VertexGeometry();
IfcSchema::IfcPoint* pnt2 = ((IfcSchema::IfcVertexPoint*) l->EdgeEnd())->VertexGeometry();
@@ -734,13 +788,14 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdgeCurve* l, TopoDS_Wire& res
const bool is_bounded = l->EdgeGeometry()->declaration().is(IfcSchema::IfcBoundedCurve::Class());
if (!is_bounded && convert_curve(l->EdgeGeometry(), crv)) {
BRepBuilderAPI_MakeEdge me(crv, p1, p2);
if (!me.IsDone()) {
TopoDS_Edge e;
if (create_edge_over_curve_with_log_messages(crv, getValue(GV_PRECISION), p1, p2, e)) {
mw.Add(e);
result = mw;
return true;
} else {
return false;
}
mw.Add(me.Edge());
result = mw;
return true;
} else if (is_bounded && convert_wire(l->EdgeGeometry(), result)) {
if (!l->SameSense()) {
result.Reverse();
@@ -777,18 +832,11 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdgeCurve* l, TopoDS_Wire& res
continue;
}
if (ecrv->IsClosed() && a.Distance(b) < getValue(GV_PRECISION)) {
// When vertices are close enough and the curve is closed,
// use the entire curve.
mw.Add(BRepBuilderAPI_MakeEdge(ecrv));
TopoDS_Edge e;
if (create_edge_over_curve_with_log_messages(ecrv, getValue(GV_PRECISION), a, b, e)) {
mw.Add(e);
} else {
BRep_Builder builder;
TopoDS_Vertex v1, v2;
/// @todo project first and emit warnings accordingly
builder.MakeVertex(v1, a, getValue(GV_PRECISION));
builder.MakeVertex(v2, b, getValue(GV_PRECISION));
mw.Add(BRepBuilderAPI_MakeEdge(ecrv, v1, v2));
return false;
}
first = false;
@@ -18,10 +18,22 @@ extern void init_IteratorImplementation_Ifc2x3(IteratorFactoryImplementation<P,
template <typename P, typename PP>
extern void init_IteratorImplementation_Ifc4(IteratorFactoryImplementation<P, PP>*);
template <typename P, typename PP>
extern void init_IteratorImplementation_Ifc4x1(IteratorFactoryImplementation<P, PP>*);
template <typename P, typename PP>
extern void init_IteratorImplementation_Ifc4x2(IteratorFactoryImplementation<P, PP>*);
template <typename P, typename PP>
extern void init_IteratorImplementation_Ifc4x3_rc1(IteratorFactoryImplementation<P, PP>*);
template <typename P, typename PP>
IteratorFactoryImplementation<P, PP>::IteratorFactoryImplementation() {
init_IteratorImplementation_Ifc2x3(this);
init_IteratorImplementation_Ifc4(this);
init_IteratorImplementation_Ifc4x1(this);
init_IteratorImplementation_Ifc4x2(this);
init_IteratorImplementation_Ifc4x3_rc1(this);
}
template <typename P, typename PP>
+45
View File
@@ -50,10 +50,16 @@ IfcGeom::impl::KernelFactoryImplementation& IfcGeom::impl::kernel_implementation
extern void init_KernelImplementation_Ifc2x3(IfcGeom::impl::KernelFactoryImplementation*);
extern void init_KernelImplementation_Ifc4(IfcGeom::impl::KernelFactoryImplementation*);
extern void init_KernelImplementation_Ifc4x1(IfcGeom::impl::KernelFactoryImplementation*);
extern void init_KernelImplementation_Ifc4x2(IfcGeom::impl::KernelFactoryImplementation*);
extern void init_KernelImplementation_Ifc4x3_rc1(IfcGeom::impl::KernelFactoryImplementation*);
IfcGeom::impl::KernelFactoryImplementation::KernelFactoryImplementation() {
init_KernelImplementation_Ifc2x3(this);
init_KernelImplementation_Ifc4(this);
init_KernelImplementation_Ifc4x1(this);
init_KernelImplementation_Ifc4x2(this);
init_KernelImplementation_Ifc4x3_rc1(this);
}
void IfcGeom::impl::KernelFactoryImplementation::bind(const std::string& schema_name, IfcGeom::impl::kernel_fn fn) {
@@ -131,6 +137,30 @@ namespace {
}
return nullptr;
}
IfcUtil::IfcBaseEntity* get_RelatingObject(Ifc4x1::IfcRelDecomposes* decompose) {
Ifc4x1::IfcRelAggregates* aggr = decompose->as<Ifc4x1::IfcRelAggregates>();
if (aggr != nullptr) {
return aggr->RelatingObject();
}
return nullptr;
}
IfcUtil::IfcBaseEntity* get_RelatingObject(Ifc4x2::IfcRelDecomposes* decompose) {
Ifc4x2::IfcRelAggregates* aggr = decompose->as<Ifc4x2::IfcRelAggregates>();
if (aggr != nullptr) {
return aggr->RelatingObject();
}
return nullptr;
}
IfcUtil::IfcBaseEntity* get_RelatingObject(Ifc4x3_rc1::IfcRelDecomposes* decompose) {
Ifc4x3_rc1::IfcRelAggregates* aggr = decompose->as<Ifc4x3_rc1::IfcRelAggregates>();
if (aggr != nullptr) {
return aggr->RelatingObject();
}
return nullptr;
}
IfcUtil::IfcBaseEntity* get_RelatingObject(Ifc2x3::IfcRelDecomposes* decompose) {
return decompose->RelatingObject();
@@ -138,6 +168,9 @@ namespace {
CREATE_GET_DECOMPOSING_ENTITY(Ifc2x3);
CREATE_GET_DECOMPOSING_ENTITY(Ifc4);
CREATE_GET_DECOMPOSING_ENTITY(Ifc4x1);
CREATE_GET_DECOMPOSING_ENTITY(Ifc4x2);
CREATE_GET_DECOMPOSING_ENTITY(Ifc4x3_rc1);
}
IfcUtil::IfcBaseEntity* IfcGeom::Kernel::get_decomposing_entity(IfcUtil::IfcBaseEntity* inst, bool include_openings) {
@@ -145,6 +178,12 @@ IfcUtil::IfcBaseEntity* IfcGeom::Kernel::get_decomposing_entity(IfcUtil::IfcBase
return get_decomposing_entity_impl(inst->as<Ifc2x3::IfcProduct>(), include_openings);
} else if (inst->as<Ifc4::IfcProduct>()) {
return get_decomposing_entity_impl(inst->as<Ifc4::IfcProduct>(), include_openings);
} else if (inst->as<Ifc4x1::IfcProduct>()) {
return get_decomposing_entity_impl(inst->as<Ifc4x1::IfcProduct>(), include_openings);
} else if (inst->as<Ifc4x2::IfcProduct>()) {
return get_decomposing_entity_impl(inst->as<Ifc4x2::IfcProduct>(), include_openings);
} else if (inst->as<Ifc4x3_rc1::IfcProduct>()) {
return get_decomposing_entity_impl(inst->as<Ifc4x3_rc1::IfcProduct>(), include_openings);
} else if (inst->declaration().name() == "IfcProject") {
return nullptr;
} else {
@@ -175,6 +214,12 @@ std::map<std::string, IfcUtil::IfcBaseEntity*> IfcGeom::Kernel::get_layers(IfcUt
return get_layers_impl<Ifc2x3>(inst->as<Ifc2x3::IfcProduct>());
} else if (inst->as<Ifc4::IfcProduct>()) {
return get_layers_impl<Ifc4>(inst->as<Ifc4::IfcProduct>());
} else if (inst->as<Ifc4x1::IfcProduct>()) {
return get_layers_impl<Ifc4x1>(inst->as<Ifc4x1::IfcProduct>());
} else if (inst->as<Ifc4x2::IfcProduct>()) {
return get_layers_impl<Ifc4x2>(inst->as<Ifc4x2::IfcProduct>());
} else if (inst->as<Ifc4x3_rc1::IfcProduct>()) {
return get_layers_impl<Ifc4x3_rc1>(inst->as<Ifc4x3_rc1::IfcProduct>());
} else {
throw IfcParse::IfcException("Unexpected entity " + inst->declaration().name());
}
+3
View File
@@ -7,6 +7,9 @@
#include "../ifcparse/Ifc2x3.h"
#include "../ifcparse/Ifc4.h"
#include "../ifcparse/Ifc4x1.h"
#include "../ifcparse/Ifc4x2.h"
#include "../ifcparse/Ifc4x3_rc1.h"
#include <boost/function.hpp>
+30 -5
View File
@@ -5,12 +5,19 @@
namespace IfcGeom {
extern IfcUtil::IfcBaseClass* tesselate_Ifc2x3(const TopoDS_Shape& shape, double deflection);
extern IfcUtil::IfcBaseClass* tesselate_Ifc4(const TopoDS_Shape& shape, double deflection);
extern IfcUtil::IfcBaseClass* tesselate_Ifc4x1(const TopoDS_Shape& shape, double deflection);
extern IfcUtil::IfcBaseClass* tesselate_Ifc4x2(const TopoDS_Shape& shape, double deflection);
extern IfcUtil::IfcBaseClass* tesselate_Ifc4x3_rc1(const TopoDS_Shape& shape, double deflection);
extern IfcUtil::IfcBaseClass* serialise_Ifc2x3(const TopoDS_Shape& shape, bool advanced);
extern IfcUtil::IfcBaseClass* serialise_Ifc4(const TopoDS_Shape& shape, bool advanced);
extern IfcUtil::IfcBaseClass* serialise_Ifc4x1(const TopoDS_Shape& shape, bool advanced);
extern IfcUtil::IfcBaseClass* serialise_Ifc4x2(const TopoDS_Shape& shape, bool advanced);
extern IfcUtil::IfcBaseClass* serialise_Ifc4x3_rc1(const TopoDS_Shape& shape, bool advanced);
}
template <typename Fn, typename T>
IfcUtil::IfcBaseClass* execute_based_on_schema(Fn fn1, Fn fn2, const std::string& schema_name, const TopoDS_Shape& shape, T t) {
IfcUtil::IfcBaseClass* execute_based_on_schema(Fn fn_2x3, Fn fn_4, Fn fn_4x1, Fn fn_4x2, Fn fn_4x3_rc1, const std::string& schema_name, const TopoDS_Shape& shape, T t) {
// @todo an ugly hack to guarantee schemas are initialised.
try {
IfcParse::schema_by_name("IFC2X3");
@@ -19,18 +26,36 @@ IfcUtil::IfcBaseClass* execute_based_on_schema(Fn fn1, Fn fn2, const std::string
const std::string schema_name_lower = boost::to_lower_copy(schema_name);
if (schema_name_lower == "ifc2x3") {
return fn1(shape, t);
return fn_2x3(shape, t);
} else if (schema_name_lower == "ifc4") {
return fn2(shape, t);
return fn_4(shape, t);
} else if (schema_name_lower == "ifc4x1") {
return fn_4x1(shape, t);
} else if (schema_name_lower == "ifc4x2") {
return fn_4x2(shape, t);
} else if (schema_name_lower == "ifc4x3_rc1") {
return fn_4x3_rc1(shape, t);
} else {
throw IfcParse::IfcException("No geometry serialization available for " + schema_name);
}
}
IfcUtil::IfcBaseClass* IfcGeom::tesselate(const std::string& schema_name, const TopoDS_Shape& shape, double deflection) {
return execute_based_on_schema(IfcGeom::tesselate_Ifc2x3, IfcGeom::tesselate_Ifc4, schema_name, shape, deflection);
return execute_based_on_schema(
IfcGeom::tesselate_Ifc2x3,
IfcGeom::tesselate_Ifc4,
IfcGeom::tesselate_Ifc4x1,
IfcGeom::tesselate_Ifc4x2,
IfcGeom::tesselate_Ifc4x3_rc1,
schema_name, shape, deflection);
}
IfcUtil::IfcBaseClass* IfcGeom::serialise(const std::string& schema_name, const TopoDS_Shape& shape, bool advanced) {
return execute_based_on_schema(IfcGeom::serialise_Ifc2x3, IfcGeom::serialise_Ifc4, schema_name, shape, advanced);
return execute_based_on_schema(
IfcGeom::serialise_Ifc2x3,
IfcGeom::serialise_Ifc4,
IfcGeom::serialise_Ifc4x1,
IfcGeom::serialise_Ifc4x2,
IfcGeom::serialise_Ifc4x3_rc1,
schema_name, shape, advanced);
}
@@ -29,8 +29,10 @@ from collections import namedtuple, Iterable
try:
from OCC.Core import V3d, TopoDS, gp, AIS, Quantity, BRepTools, Graphic3d
USE_OCCT_HANDLE = False
except ImportError:
from OCC import V3d, TopoDS, gp, AIS, Quantity, BRepTools, Graphic3d
USE_OCCT_HANDLE = True
shape_tuple = namedtuple('shape_tuple', ('data', 'geometry', 'styles'))
@@ -76,10 +78,15 @@ def initialize_display():
for l in lights:
viewer.DelLight(l)
for dir in [V3d.V3d_TypeOfOrientation_Yup_AxoRight, V3d.V3d_TypeOfOrientation_Zup_AxoRight]:
if hasattr(V3d, 'V3d_TypeOfOrientation_Yup_AxoRight'):
dirs = [[V3d.V3d_TypeOfOrientation_Yup_AxoRight], [V3d.V3d_TypeOfOrientation_Zup_AxoRight]]
else:
dirs = [(3, 2, 1), (-1, -2, -3)]
for dir in dirs:
light = V3d.V3d_DirectionalLight(viewer_handle)
light.SetDirection(dir)
viewer.SetLightOn(light)
light.SetDirection(*dir)
viewer.SetLightOn(light.GetHandle() if USE_OCCT_HANDLE else light)
setup()
return handle
@@ -177,14 +184,14 @@ def display_shape(shape, clr=None, viewer_handle=None):
clr = Quantity.Quantity_Color(r(), r(), r(), Quantity.Quantity_TOC_RGB)
ais.SetColor(clr)
ais_handle = ais
ais_handle = ais.GetHandle() if USE_OCCT_HANDLE else ais
viewer_handle.Context.Display(ais_handle, False)
return ais_handle
def set_shape_transparency(ais, t, update_viewer=True):
handle.Context.SetTransparency(ais, t, update_viewer)
def set_shape_transparency(ais, t):
handle.Context.SetTransparency(ais, t)
def get_bounding_box_center(bbox):
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+8
View File
@@ -477,6 +477,13 @@ Ifc4x2::IfcStyledItem* create_styled_item(Ifc4x2::IfcRepresentationItem* item, I
style_assignments->push(style_assignment);
return new Ifc4x2::IfcStyledItem(item, style_assignments, boost::none);
}
Ifc4x3_rc1::IfcStyledItem* create_styled_item(Ifc4x3_rc1::IfcRepresentationItem* item, Ifc4x3_rc1::IfcPresentationStyleAssignment* style_assignment) {
IfcEntityList::ptr style_assignments(new IfcEntityList);
style_assignments->push(style_assignment);
return new Ifc4x3_rc1::IfcStyledItem(item, style_assignments, boost::none);
}
template <typename Schema>
void IfcHierarchyHelper<Schema>::setSurfaceColour(typename Schema::IfcRepresentation* rep,
typename Schema::IfcPresentationStyleAssignment* style_assignment)
@@ -573,3 +580,4 @@ template IFC_PARSE_API class IfcHierarchyHelper<Ifc2x3>;
template IFC_PARSE_API class IfcHierarchyHelper<Ifc4>;
template IFC_PARSE_API class IfcHierarchyHelper<Ifc4x1>;
template IFC_PARSE_API class IfcHierarchyHelper<Ifc4x2>;
template IFC_PARSE_API class IfcHierarchyHelper<Ifc4x3_rc1>;
+14
View File
@@ -36,6 +36,7 @@
#include "../ifcparse/Ifc4.h"
#include "../ifcparse/Ifc4x1.h"
#include "../ifcparse/Ifc4x2.h"
#include "../ifcparse/Ifc4x3_rc1.h"
#include "../ifcparse/IfcFile.h"
@@ -65,6 +66,10 @@ namespace {
return t->RelatingStructure();
}
Ifc4x3_rc1::IfcObjectDefinition* get_parent_of_relation(Ifc4x3_rc1::IfcRelContainedInSpatialStructure* t) {
return t->RelatingStructure();
}
IfcEntityList::ptr get_children_of_relation(IfcUtil::IfcBaseClass* t) {
return *t->data().getArgument(
t->declaration().as_entity()->attribute_index("RelatedElements")
@@ -86,6 +91,11 @@ namespace {
IfcEntityList::ptr get_children_of_relation(Ifc4x2::IfcRelContainedInSpatialStructure* t) {
return t->RelatedElements()->generalize();
}
IfcEntityList::ptr get_children_of_relation(Ifc4x3_rc1::IfcRelContainedInSpatialStructure* t) {
return t->RelatedElements()->generalize();
}
void set_children_of_relation(IfcUtil::IfcBaseClass* t, IfcEntityList::ptr& cs) {
IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument;
attr->set(cs);
@@ -110,6 +120,10 @@ namespace {
void set_children_of_relation(Ifc4x2::IfcRelContainedInSpatialStructure* t, IfcEntityList::ptr& cs) {
t->setRelatedElements(cs->as<Ifc4x2::IfcProduct>());
}
void set_children_of_relation(Ifc4x3_rc1::IfcRelContainedInSpatialStructure* t, IfcEntityList::ptr& cs) {
t->setRelatedElements(cs->as<Ifc4x3_rc1::IfcProduct>());
}
}
template <typename Schema>
class IFC_PARSE_API IfcHierarchyHelper : public IfcParse::IfcFile {
+2
View File
@@ -23,6 +23,7 @@
#include "../ifcparse/Ifc4.h"
#include "../ifcparse/Ifc4x1.h"
#include "../ifcparse/Ifc4x2.h"
#include "../ifcparse/Ifc4x3_rc1.h"
double IfcParse::IfcSIPrefixToValue(const std::string& v) {
if ( v == "EXA" ) return 1.e18;
@@ -76,3 +77,4 @@ template double IfcParse::get_SI_equivalent<Ifc2x3>(typename Ifc2x3::IfcNamedUni
template double IfcParse::get_SI_equivalent<Ifc4>(typename Ifc4::IfcNamedUnit* named_unit);
template double IfcParse::get_SI_equivalent<Ifc4x1>(typename Ifc4x1::IfcNamedUnit* named_unit);
template double IfcParse::get_SI_equivalent<Ifc4x2>(typename Ifc4x2::IfcNamedUnit* named_unit);
template double IfcParse::get_SI_equivalent<Ifc4x3_rc1>(typename Ifc4x3_rc1::IfcNamedUnit* named_unit);
+2
View File
@@ -66,6 +66,7 @@ IfcParse::schema_definition::~schema_definition() {
#include "../ifcparse/Ifc4.h"
#include "../ifcparse/Ifc4x1.h"
#include "../ifcparse/Ifc4x2.h"
#include "../ifcparse/Ifc4x3_rc1.h"
const IfcParse::schema_definition* IfcParse::schema_by_name(const std::string& name) {
// TODO: initialize automatically somehow
@@ -73,6 +74,7 @@ const IfcParse::schema_definition* IfcParse::schema_by_name(const std::string& n
Ifc4::get_schema();
Ifc4x1::get_schema();
Ifc4x2::get_schema();
Ifc4x3_rc1::get_schema();
std::map<std::string, const IfcParse::schema_definition*>::const_iterator it = schemas.find(name);
if (it == schemas.end()) {
+7 -1
View File
@@ -326,7 +326,7 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_ORIENT, settings.get(IfcGeom::IteratorSettings::SEW_SHELLS) ? std::numeric_limits<double>::infinity() : -1);
kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.get(IfcGeom::IteratorSettings::INCLUDE_CURVES) ? (settings.get(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES) ? -1. : 0.) : +1.));
kernel.setValue(IfcGeom::Kernel::GV_LAYERSET_FIRST,
settings.get(IteratorSettings::LAYERSET_FIRST)
settings.get(IfcGeom::IteratorSettings::LAYERSET_FIRST)
? +1.0
: -1.0
);
@@ -456,6 +456,12 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
return helper_fn_create_shape<Ifc2x3>(settings, instance, representation);
} else if (schema_name == "IFC4") {
return helper_fn_create_shape<Ifc4>(settings, instance, representation);
} else if (schema_name == "IFC4X1") {
return helper_fn_create_shape<Ifc4x1>(settings, instance, representation);
} else if (schema_name == "IFC4X2") {
return helper_fn_create_shape<Ifc4x2>(settings, instance, representation);
} else if (schema_name == "IFC4X3_RC1") {
return helper_fn_create_shape<Ifc4x3_rc1>(settings, instance, representation);
} else {
throw IfcParse::IfcException("No geometry support for " + schema_name);
}
+3
View File
@@ -76,6 +76,9 @@
#include "../ifcparse/Ifc2x3.h"
#include "../ifcparse/Ifc4.h"
#include "../ifcparse/Ifc4x1.h"
#include "../ifcparse/Ifc4x2.h"
#include "../ifcparse/Ifc4x3_rc1.h"
#include "../ifcparse/IfcBaseClass.h"
#include "../ifcparse/IfcFile.h"
#include "../ifcparse/IfcSchema.h"
-5
View File
@@ -212,11 +212,6 @@ void ColladaSerializer::ColladaExporter::ColladaScene::add(
{ (double)posmatrix[2], (double)posmatrix[5], (double)posmatrix[8], (double)posmatrix[11] },
{ 0, 0, 0, 1 }
};
/// @todo: TFK: Rather than applying this offset to all leafs (which might be undesirable) should this offset be applied to a node higher up in the hierarchy?
matrix_array[0][3] += serializer->settings().offset[0];
matrix_array[1][3] += serializer->settings().offset[1];
matrix_array[2][3] += serializer->settings().offset[2];
delete relative_trsf;
+1 -7
View File
@@ -55,13 +55,7 @@ public:
};
SerializerSettings()
: precision(DEFAULT_PRECISION)
{
memset(offset, 0, sizeof(offset));
}
/// Optional offset that is applied to serialized objects, (0,0,0) by default.
double offset[3];
: precision(DEFAULT_PRECISION) { }
/// Sets the precision used to format floating-point values, 15 by default.
/// Use a negative value to use the system's default precision (should be 6 typically).
+3 -3
View File
@@ -93,9 +93,9 @@ void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement<real_t>*
const int vcount = (int)mesh.verts().size() / 3;
for ( std::vector<real_t>::const_iterator it = mesh.verts().begin(); it != mesh.verts().end(); ) {
const real_t x = *(it++) + (real_t)settings().offset[0];
const real_t y = *(it++) + (real_t)settings().offset[1];
const real_t z = *(it++) + (real_t)settings().offset[2];
const real_t x = *(it++);
const real_t y = *(it++);
const real_t z = *(it++);
obj_stream << "v " << x << " " << y << " " << z << "\n";
}
+2
View File
@@ -4,12 +4,14 @@ extern void init_XmlSerializerIfc2x3(XmlSerializerFactory::Factory*);
extern void init_XmlSerializerIfc4(XmlSerializerFactory::Factory*);
extern void init_XmlSerializerIfc4x1(XmlSerializerFactory::Factory*);
extern void init_XmlSerializerIfc4x2(XmlSerializerFactory::Factory*);
extern void init_XmlSerializerIfc4x3_rc1(XmlSerializerFactory::Factory*);
XmlSerializerFactory::Factory::Factory() {
init_XmlSerializerIfc2x3(this);
init_XmlSerializerIfc4(this);
init_XmlSerializerIfc4x1(this);
init_XmlSerializerIfc4x2(this);
init_XmlSerializerIfc4x3_rc1(this);
}
void XmlSerializerFactory::Factory::bind(const std::string& schema_name, fn f) {