mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-27 18:57:17 +00:00
Further work on profiles
This commit is contained in:
@@ -505,7 +505,7 @@ namespace {
|
|||||||
/* A compile-time for loop over the curve kinds */
|
/* A compile-time for loop over the curve kinds */
|
||||||
template <typename T, size_t N=0>
|
template <typename T, size_t N=0>
|
||||||
struct dispatch_curve_creation {
|
struct dispatch_curve_creation {
|
||||||
static bool dispatch(const ifcopenshell::geometry::taxonomy::item* item, T visitor) {
|
static bool dispatch(const ifcopenshell::geometry::taxonomy::item* item, T& visitor) {
|
||||||
// @todo it should be possible to eliminate this dynamic_cast when there is a static equivalent to kind()
|
// @todo it should be possible to eliminate this dynamic_cast when there is a static equivalent to kind()
|
||||||
const ifcopenshell::geometry::taxonomy::curves::type<N>* v = dynamic_cast<const ifcopenshell::geometry::taxonomy::curves::type<N>*>(item);
|
const ifcopenshell::geometry::taxonomy::curves::type<N>* v = dynamic_cast<const ifcopenshell::geometry::taxonomy::curves::type<N>*>(item);
|
||||||
if (v) {
|
if (v) {
|
||||||
@@ -519,7 +519,7 @@ namespace {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct dispatch_curve_creation<T, ifcopenshell::geometry::taxonomy::curves::max> {
|
struct dispatch_curve_creation<T, ifcopenshell::geometry::taxonomy::curves::max> {
|
||||||
static bool dispatch(const ifcopenshell::geometry::taxonomy::item* item, T visitor) {
|
static bool dispatch(const ifcopenshell::geometry::taxonomy::item* item, T& visitor) {
|
||||||
Logger::Error("No conversion for " + std::to_string(item->kind()));
|
Logger::Error("No conversion for " + std::to_string(item->kind()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -532,6 +532,7 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct curve_creation_visitor {
|
struct curve_creation_visitor {
|
||||||
|
OpenCascadeKernel* kernel;
|
||||||
typedef boost::variant<Handle(Geom_Curve), TopoDS_Wire> result_type;
|
typedef boost::variant<Handle(Geom_Curve), TopoDS_Wire> result_type;
|
||||||
result_type result;
|
result_type result;
|
||||||
|
|
||||||
@@ -550,10 +551,32 @@ namespace {
|
|||||||
result_type operator()(const taxonomy::ellipse& e) {
|
result_type operator()(const taxonomy::ellipse& e) {
|
||||||
return result = Handle(Geom_Curve)(new Geom_Ellipse(gp_Ax2(convert_xyz<gp_Pnt>(e.origin), convert_xyz<gp_Dir>(e.z), convert_xyz<gp_Dir>(e.x)), e.radius, e.radius2));
|
return result = Handle(Geom_Curve)(new Geom_Ellipse(gp_Ax2(convert_xyz<gp_Pnt>(e.origin), convert_xyz<gp_Dir>(e.z), convert_xyz<gp_Dir>(e.x)), e.radius, e.radius2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result_type operator()(const taxonomy::loop& l) {
|
||||||
|
TopoDS_Wire wire;
|
||||||
|
kernel->convert(&l, wire);
|
||||||
|
return result = wire;
|
||||||
|
}
|
||||||
|
|
||||||
|
result_type operator()(const taxonomy::edge& e) {
|
||||||
|
if (e.basis == nullptr) {
|
||||||
|
// @todo we should probably construct edges based on correct oriented TopoDS_Vertex instead.
|
||||||
|
auto p1 = convert_xyz<gp_Pnt>(boost::get<taxonomy::point3>(e.start));
|
||||||
|
auto p2 = convert_xyz<gp_Pnt>(boost::get<taxonomy::point3>(e.end));
|
||||||
|
TopoDS_Edge e = BRepBuilderAPI_MakeEdge(p1, p2).Edge();
|
||||||
|
BRep_Builder B;
|
||||||
|
TopoDS_Wire W;
|
||||||
|
B.MakeWire(W);
|
||||||
|
B.Add(W, e);
|
||||||
|
return result = W;
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("not implemented");
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
curve_creation_visitor::result_type convert_curve(const taxonomy::item* curve) {
|
curve_creation_visitor::result_type convert_curve(OpenCascadeKernel* kernel, const taxonomy::item* curve) {
|
||||||
curve_creation_visitor v;
|
curve_creation_visitor v{ kernel };
|
||||||
if (dispatch_curve_creation<curve_creation_visitor, 0>::dispatch(curve, v)) {
|
if (dispatch_curve_creation<curve_creation_visitor, 0>::dispatch(curve, v)) {
|
||||||
return v.result;
|
return v.result;
|
||||||
} else {
|
} else {
|
||||||
@@ -771,7 +794,7 @@ bool OpenCascadeKernel::convert(const taxonomy::loop* loop, TopoDS_Wire& wire) {
|
|||||||
TopTools_ListOfShape converted_segments;
|
TopTools_ListOfShape converted_segments;
|
||||||
|
|
||||||
for (auto& segment : segments) {
|
for (auto& segment : segments) {
|
||||||
TopoDS_Wire segment_wire = boost::get<TopoDS_Wire>(convert_curve(segment));
|
auto segment_wire = boost::get<TopoDS_Wire>(convert_curve(this, segment));
|
||||||
|
|
||||||
if (!segment->orientation) {
|
if (!segment->orientation) {
|
||||||
segment_wire.Reverse();
|
segment_wire.Reverse();
|
||||||
@@ -837,11 +860,13 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::shell *shell, ifcopenshell:
|
|||||||
|
|
||||||
bool OpenCascadeKernel::convert(const taxonomy::matrix4* matrix, gp_GTrsf& trsf) {
|
bool OpenCascadeKernel::convert(const taxonomy::matrix4* matrix, gp_GTrsf& trsf) {
|
||||||
// @todo check
|
// @todo check
|
||||||
for (int i = 0; i < 3; ++i) {
|
gp_Trsf t;
|
||||||
for (int j = 0; j < 4; ++j) {
|
t.SetValues(
|
||||||
trsf.SetValue(i + 1, j + 1, matrix->components(i, j));
|
matrix->components(0, 0), matrix->components(1, 0), matrix->components(2, 0), matrix->components(3, 0),
|
||||||
}
|
matrix->components(0, 1), matrix->components(1, 1), matrix->components(2, 1), matrix->components(3, 1),
|
||||||
}
|
matrix->components(0, 2), matrix->components(1, 2), matrix->components(2, 2), matrix->components(3, 2)
|
||||||
|
);
|
||||||
|
trsf = t;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
if (item != nullptr) { \
|
if (item != nullptr) { \
|
||||||
item->instance = l; \
|
item->instance = l; \
|
||||||
try { \
|
try { \
|
||||||
if (l->as<IfcSchema::IfcRepresentationItem>()) { \
|
if (l->as<IfcSchema::IfcRepresentationItem>() && !l->as<IfcSchema::IfcStyledItem>()) { \
|
||||||
auto style = find_style(l->as<IfcSchema::IfcRepresentationItem>()); \
|
auto style = find_style(l->as<IfcSchema::IfcRepresentationItem>()); \
|
||||||
if (style) { \
|
if (style) { \
|
||||||
((taxonomy::geom_item*)item)->surface_style = as<taxonomy::style>(map(style)); \
|
((taxonomy::geom_item*)item)->surface_style = as<taxonomy::style>(map(style)); \
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ namespace {
|
|||||||
as(taxonomy::item* item) : item_(item) {}
|
as(taxonomy::item* item) : item_(item) {}
|
||||||
operator T() const {
|
operator T() const {
|
||||||
if (!item_) {
|
if (!item_) {
|
||||||
throw taxonomy::topology_error();
|
throw taxonomy::topology_error("item was nullptr");
|
||||||
}
|
}
|
||||||
T* t = dynamic_cast<T*>(item_);
|
T* t = dynamic_cast<T*>(item_);
|
||||||
if (t) {
|
if (t) {
|
||||||
@@ -118,7 +118,7 @@ namespace {
|
|||||||
return upgrade;
|
return upgrade;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw taxonomy::topology_error();
|
throw taxonomy::topology_error("item does not match type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
~as() {
|
~as() {
|
||||||
@@ -145,12 +145,11 @@ namespace {
|
|||||||
};
|
};
|
||||||
|
|
||||||
taxonomy::item* mapping::map_impl(const IfcSchema::IfcExtrudedAreaSolid* inst) {
|
taxonomy::item* mapping::map_impl(const IfcSchema::IfcExtrudedAreaSolid* inst) {
|
||||||
// @todo length unit
|
|
||||||
return new taxonomy::extrusion(
|
return new taxonomy::extrusion(
|
||||||
as<taxonomy::matrix4>(map(inst->Position())),
|
as<taxonomy::matrix4>(map(inst->Position())),
|
||||||
as<taxonomy::face>(map(inst->SweptArea())),
|
as<taxonomy::face>(map(inst->SweptArea())),
|
||||||
as<taxonomy::direction3>(map(inst->ExtrudedDirection())),
|
as<taxonomy::direction3>(map(inst->ExtrudedDirection())),
|
||||||
inst->Depth()
|
inst->Depth() * length_unit_
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,12 +264,12 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcAxis2Placement3D* inst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hasAxis) {
|
if (hasAxis) {
|
||||||
taxonomy::point3 v = as<taxonomy::point3>(map(inst->Axis()));
|
taxonomy::direction3 v = as<taxonomy::direction3>(map(inst->Axis()));
|
||||||
axis = v.components;
|
axis = v.components;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasRef) {
|
if (hasRef) {
|
||||||
taxonomy::point3 v = as<taxonomy::point3>(map(inst->RefDirection()));
|
taxonomy::direction3 v = as<taxonomy::direction3>(map(inst->RefDirection()));
|
||||||
refDirection = v.components;
|
refDirection = v.components;
|
||||||
} else {
|
} else {
|
||||||
if (acos(axis.dot(X)) > 1.e-5) {
|
if (acos(axis.dot(X)) > 1.e-5) {
|
||||||
@@ -285,6 +284,20 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcAxis2Placement3D* inst) {
|
|||||||
return new taxonomy::matrix4(o, axis, refDirection);
|
return new taxonomy::matrix4(o, axis, refDirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
taxonomy::item* mapping::map_impl(const IfcSchema::IfcAxis2Placement2D* inst) {
|
||||||
|
Eigen::Vector3d P, axis(0, 0, 1), V(1, 0, 0);
|
||||||
|
{
|
||||||
|
taxonomy::point3 v = as<taxonomy::point3>(map(inst->Location()));
|
||||||
|
P = v.components;
|
||||||
|
}
|
||||||
|
const bool hasRef = inst->hasRefDirection();
|
||||||
|
if (hasRef) {
|
||||||
|
taxonomy::direction3 v = as<taxonomy::direction3>(map(inst->RefDirection()));
|
||||||
|
V = v.components;
|
||||||
|
}
|
||||||
|
return new taxonomy::matrix4(P, axis, V);
|
||||||
|
}
|
||||||
|
|
||||||
taxonomy::item* mapping::map_impl(const IfcSchema::IfcCartesianTransformationOperator2DnonUniform* inst) {
|
taxonomy::item* mapping::map_impl(const IfcSchema::IfcCartesianTransformationOperator2DnonUniform* inst) {
|
||||||
// @todo
|
// @todo
|
||||||
return new taxonomy::matrix4();
|
return new taxonomy::matrix4();
|
||||||
@@ -756,8 +769,8 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcMaterial* material) {
|
|||||||
for (IfcSchema::IfcRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) {
|
for (IfcSchema::IfcRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) {
|
||||||
styles->push((**it).Items()->as<IfcSchema::IfcStyledItem>());
|
styles->push((**it).Items()->as<IfcSchema::IfcStyledItem>());
|
||||||
}
|
}
|
||||||
for (IfcSchema::IfcStyledItem::list::it it = styles->begin(); it != styles->end(); ++it) {
|
if (styles->size() == 1) {
|
||||||
return map(*it);
|
return map(*styles->begin());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -829,6 +842,7 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcStyledItem* inst) {
|
|||||||
|
|
||||||
|
|
||||||
taxonomy::item* mapping::map(const IfcBaseClass* l) {
|
taxonomy::item* mapping::map(const IfcBaseClass* l) {
|
||||||
|
// std::wcout << l->data().toString().c_str() << std::endl;
|
||||||
#include "bind_convert_impl.i"
|
#include "bind_convert_impl.i"
|
||||||
Logger::Message(Logger::LOG_ERROR, "No operation defined for:", l);
|
Logger::Message(Logger::LOG_ERROR, "No operation defined for:", l);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -983,3 +997,120 @@ void mapping::initialize_units_() {
|
|||||||
Logger::Warning("No plane angle unit encountered");
|
Logger::Warning("No plane angle unit encountered");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct profile_point {
|
||||||
|
std::array<double, 2> xy;
|
||||||
|
boost::optional<double> radius;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct profile_point_with_neighbours {
|
||||||
|
std::array<double, 2> xy;
|
||||||
|
boost::optional<double> radius;
|
||||||
|
profile_point* previous, *next;
|
||||||
|
};
|
||||||
|
taxonomy::loop* profile_helper(mapping* self, const IfcSchema::IfcParameterizedProfileDef* inst, const std::vector<profile_point>& points) {
|
||||||
|
|
||||||
|
/* TopoDS_Vertex* vertices = new TopoDS_Vertex[numVerts];
|
||||||
|
|
||||||
|
for (int i = 0; i < numVerts; i++) {
|
||||||
|
gp_XY xy(verts[2 * i], verts[2 * i + 1]);
|
||||||
|
trsf.Transforms(xy);
|
||||||
|
vertices[i] = BRepBuilderAPI_MakeVertex(gp_Pnt(xy.X(), xy.Y(), 0.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
BRepBuilderAPI_MakeWire w;
|
||||||
|
for (int i = 0; i < numVerts; i++)
|
||||||
|
w.Add(BRepBuilderAPI_MakeEdge(vertices[i], vertices[(i + 1) % numVerts]));
|
||||||
|
|
||||||
|
TopoDS_Face face;
|
||||||
|
convert_wire_to_face(w.Wire(), face);
|
||||||
|
|
||||||
|
if (numFillets && *std::max_element(filletRadii, filletRadii + numFillets) > ALMOST_ZERO) {
|
||||||
|
BRepFilletAPI_MakeFillet2d fillet(face);
|
||||||
|
for (int i = 0; i < numFillets; i++) {
|
||||||
|
const double radius = filletRadii[i];
|
||||||
|
if (radius <= ALMOST_ZERO) continue;
|
||||||
|
fillet.AddFillet(vertices[filletIndices[i]], radius);
|
||||||
|
}
|
||||||
|
fillet.Build();
|
||||||
|
if (fillet.IsDone()) {
|
||||||
|
face = TopoDS::Face(fillet.Shape());
|
||||||
|
} else {
|
||||||
|
Logger::Error("Failed to process profile fillets");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Eigen::Matrix4d m4;
|
||||||
|
|
||||||
|
bool has_position = true;
|
||||||
|
#ifdef SCHEMA_IfcParameterizedProfileDef_Position_IS_OPTIONAL
|
||||||
|
has_position = inst->hasPosition();
|
||||||
|
#endif
|
||||||
|
if (has_position) {
|
||||||
|
taxonomy::matrix4 m = as<taxonomy::matrix4>(self->map(inst->Position()));
|
||||||
|
m4 = m.components;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @todo precision
|
||||||
|
if (m4.isIdentity()) {
|
||||||
|
has_position = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<taxonomy::point3> ps;
|
||||||
|
ps.reserve(points.size());
|
||||||
|
std::transform(points.begin(), points.end(), std::back_inserter(ps), [&has_position, &m4](const profile_point& p) {
|
||||||
|
if (has_position) {
|
||||||
|
Eigen::Vector4d v(p.xy[0], p.xy[1], 0., 1.);
|
||||||
|
v = m4 * v;
|
||||||
|
return taxonomy::point3(v(0), v(1), 0.);
|
||||||
|
} else {
|
||||||
|
return taxonomy::point3(p.xy[0], p.xy[1], 0.);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
auto loop = new taxonomy::loop();
|
||||||
|
auto previous = ps.back();
|
||||||
|
for (auto& p : ps) {
|
||||||
|
auto e = new taxonomy::edge;
|
||||||
|
e->start = previous;
|
||||||
|
e->end = p;
|
||||||
|
previous = p;
|
||||||
|
loop->children.push_back(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
taxonomy::item* mapping::map_impl(const IfcSchema::IfcRectangleProfileDef* inst) {
|
||||||
|
const double x = inst->XDim() / 2.0f * length_unit_;
|
||||||
|
const double y = inst->YDim() / 2.0f * length_unit_;
|
||||||
|
|
||||||
|
// @todo
|
||||||
|
const double precision_ = 1.e-5;
|
||||||
|
|
||||||
|
if (x < precision_ || y < precision_) {
|
||||||
|
Logger::Message(Logger::LOG_NOTICE, "Skipping zero sized profile:", inst);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return profile_helper(this, inst, {
|
||||||
|
{{-x, -y}},
|
||||||
|
{{+x, -y}},
|
||||||
|
{{+x, +y}},
|
||||||
|
{{-x, +y}},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
taxonomy::item* mapping::map_impl(const IfcSchema::IfcArbitraryClosedProfileDef* l) {
|
||||||
|
auto loop = map(l->OuterCurve());
|
||||||
|
if (loop) {
|
||||||
|
auto face = new taxonomy::face;
|
||||||
|
face->children = { loop };
|
||||||
|
return face;
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -73,10 +73,10 @@ BIND(IfcConnectedFaceSet);
|
|||||||
// BIND(IfcSweptDiskSolid);
|
// BIND(IfcSweptDiskSolid);
|
||||||
|
|
||||||
// BIND(IfcArbitraryProfileDefWithVoids);
|
// BIND(IfcArbitraryProfileDefWithVoids);
|
||||||
// BIND(IfcArbitraryClosedProfileDef);
|
BIND(IfcArbitraryClosedProfileDef);
|
||||||
// BIND(IfcRoundedRectangleProfileDef);
|
// BIND(IfcRoundedRectangleProfileDef);
|
||||||
// BIND(IfcRectangleHollowProfileDef);
|
// BIND(IfcRectangleHollowProfileDef);
|
||||||
// BIND(IfcRectangleProfileDef);
|
BIND(IfcRectangleProfileDef);
|
||||||
// BIND(IfcTrapeziumProfileDef)
|
// BIND(IfcTrapeziumProfileDef)
|
||||||
// BIND(IfcCShapeProfileDef);
|
// BIND(IfcCShapeProfileDef);
|
||||||
// IfcAsymmetricIShapeProfileDef included
|
// IfcAsymmetricIShapeProfileDef included
|
||||||
@@ -119,7 +119,7 @@ BIND(IfcPolyLoop);
|
|||||||
|
|
||||||
BIND(IfcCartesianPoint);
|
BIND(IfcCartesianPoint);
|
||||||
BIND(IfcDirection);
|
BIND(IfcDirection);
|
||||||
// BIND(IfcAxis2Placement2D);
|
BIND(IfcAxis2Placement2D);
|
||||||
BIND(IfcAxis2Placement3D);
|
BIND(IfcAxis2Placement3D);
|
||||||
// BIND(IfcAxis1Placement);
|
// BIND(IfcAxis1Placement);
|
||||||
BIND(IfcCartesianTransformationOperator2DnonUniform);
|
BIND(IfcCartesianTransformationOperator2DnonUniform);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ namespace taxonomy {
|
|||||||
class topology_error : public std::runtime_error {
|
class topology_error : public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
topology_error() : std::runtime_error("Generic topology error") {}
|
topology_error() : std::runtime_error("Generic topology error") {}
|
||||||
|
topology_error(const char* const s) : std::runtime_error(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum kinds { MATRIX4, POINT3, DIRECTION3, LINE, CIRCLE, ELLIPSE, BSPLINE_CURVE, EDGE, LOOP, FACE, SHELL, EXTRUSION, NODE, COLLECTION, COLOUR, STYLE };
|
enum kinds { MATRIX4, POINT3, DIRECTION3, LINE, CIRCLE, ELLIPSE, BSPLINE_CURVE, EDGE, LOOP, FACE, SHELL, EXTRUSION, NODE, COLLECTION, COLOUR, STYLE };
|
||||||
@@ -248,7 +249,7 @@ struct node : public geom_item {
|
|||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
typedef std::tuple<matrix4, point3, direction3, line, circle, ellipse, bspline_curve, edge, loop, face, shell, extrusion, node, collection> KindsTuple;
|
typedef std::tuple<matrix4, point3, direction3, line, circle, ellipse, bspline_curve, edge, loop, face, shell, extrusion, node, collection> KindsTuple;
|
||||||
typedef std::tuple<line, circle, ellipse, bspline_curve> CurvesTuple;
|
typedef std::tuple<line, circle, ellipse, bspline_curve, loop, edge> CurvesTuple;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct type_by_kind {
|
struct type_by_kind {
|
||||||
|
|||||||
Reference in New Issue
Block a user