mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 18:43:26 +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 */
|
||||
template <typename T, size_t N=0>
|
||||
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()
|
||||
const ifcopenshell::geometry::taxonomy::curves::type<N>* v = dynamic_cast<const ifcopenshell::geometry::taxonomy::curves::type<N>*>(item);
|
||||
if (v) {
|
||||
@@ -519,7 +519,7 @@ namespace {
|
||||
|
||||
template <typename T>
|
||||
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()));
|
||||
return false;
|
||||
}
|
||||
@@ -532,6 +532,7 @@ namespace {
|
||||
}
|
||||
|
||||
struct curve_creation_visitor {
|
||||
OpenCascadeKernel* kernel;
|
||||
typedef boost::variant<Handle(Geom_Curve), TopoDS_Wire> result_type;
|
||||
result_type result;
|
||||
|
||||
@@ -550,10 +551,32 @@ namespace {
|
||||
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));
|
||||
}
|
||||
|
||||
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 v;
|
||||
curve_creation_visitor::result_type convert_curve(OpenCascadeKernel* kernel, const taxonomy::item* curve) {
|
||||
curve_creation_visitor v{ kernel };
|
||||
if (dispatch_curve_creation<curve_creation_visitor, 0>::dispatch(curve, v)) {
|
||||
return v.result;
|
||||
} else {
|
||||
@@ -771,7 +794,7 @@ bool OpenCascadeKernel::convert(const taxonomy::loop* loop, TopoDS_Wire& wire) {
|
||||
TopTools_ListOfShape converted_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) {
|
||||
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) {
|
||||
// @todo check
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
trsf.SetValue(i + 1, j + 1, matrix->components(i, j));
|
||||
}
|
||||
}
|
||||
gp_Trsf t;
|
||||
t.SetValues(
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
if (item != nullptr) { \
|
||||
item->instance = l; \
|
||||
try { \
|
||||
if (l->as<IfcSchema::IfcRepresentationItem>()) { \
|
||||
if (l->as<IfcSchema::IfcRepresentationItem>() && !l->as<IfcSchema::IfcStyledItem>()) { \
|
||||
auto style = find_style(l->as<IfcSchema::IfcRepresentationItem>()); \
|
||||
if (style) { \
|
||||
((taxonomy::geom_item*)item)->surface_style = as<taxonomy::style>(map(style)); \
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace {
|
||||
as(taxonomy::item* item) : item_(item) {}
|
||||
operator T() const {
|
||||
if (!item_) {
|
||||
throw taxonomy::topology_error();
|
||||
throw taxonomy::topology_error("item was nullptr");
|
||||
}
|
||||
T* t = dynamic_cast<T*>(item_);
|
||||
if (t) {
|
||||
@@ -118,7 +118,7 @@ namespace {
|
||||
return upgrade;
|
||||
}
|
||||
}
|
||||
throw taxonomy::topology_error();
|
||||
throw taxonomy::topology_error("item does not match type");
|
||||
}
|
||||
}
|
||||
~as() {
|
||||
@@ -145,12 +145,11 @@ namespace {
|
||||
};
|
||||
|
||||
taxonomy::item* mapping::map_impl(const IfcSchema::IfcExtrudedAreaSolid* inst) {
|
||||
// @todo length unit
|
||||
return new taxonomy::extrusion(
|
||||
as<taxonomy::matrix4>(map(inst->Position())),
|
||||
as<taxonomy::face>(map(inst->SweptArea())),
|
||||
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) {
|
||||
taxonomy::point3 v = as<taxonomy::point3>(map(inst->Axis()));
|
||||
taxonomy::direction3 v = as<taxonomy::direction3>(map(inst->Axis()));
|
||||
axis = v.components;
|
||||
}
|
||||
|
||||
if (hasRef) {
|
||||
taxonomy::point3 v = as<taxonomy::point3>(map(inst->RefDirection()));
|
||||
taxonomy::direction3 v = as<taxonomy::direction3>(map(inst->RefDirection()));
|
||||
refDirection = v.components;
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
// @todo
|
||||
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) {
|
||||
styles->push((**it).Items()->as<IfcSchema::IfcStyledItem>());
|
||||
}
|
||||
for (IfcSchema::IfcStyledItem::list::it it = styles->begin(); it != styles->end(); ++it) {
|
||||
return map(*it);
|
||||
if (styles->size() == 1) {
|
||||
return map(*styles->begin());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -829,6 +842,7 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcStyledItem* inst) {
|
||||
|
||||
|
||||
taxonomy::item* mapping::map(const IfcBaseClass* l) {
|
||||
// std::wcout << l->data().toString().c_str() << std::endl;
|
||||
#include "bind_convert_impl.i"
|
||||
Logger::Message(Logger::LOG_ERROR, "No operation defined for:", l);
|
||||
return nullptr;
|
||||
@@ -983,3 +997,120 @@ void mapping::initialize_units_() {
|
||||
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(IfcArbitraryProfileDefWithVoids);
|
||||
// BIND(IfcArbitraryClosedProfileDef);
|
||||
BIND(IfcArbitraryClosedProfileDef);
|
||||
// BIND(IfcRoundedRectangleProfileDef);
|
||||
// BIND(IfcRectangleHollowProfileDef);
|
||||
// BIND(IfcRectangleProfileDef);
|
||||
BIND(IfcRectangleProfileDef);
|
||||
// BIND(IfcTrapeziumProfileDef)
|
||||
// BIND(IfcCShapeProfileDef);
|
||||
// IfcAsymmetricIShapeProfileDef included
|
||||
@@ -119,7 +119,7 @@ BIND(IfcPolyLoop);
|
||||
|
||||
BIND(IfcCartesianPoint);
|
||||
BIND(IfcDirection);
|
||||
// BIND(IfcAxis2Placement2D);
|
||||
BIND(IfcAxis2Placement2D);
|
||||
BIND(IfcAxis2Placement3D);
|
||||
// BIND(IfcAxis1Placement);
|
||||
BIND(IfcCartesianTransformationOperator2DnonUniform);
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace taxonomy {
|
||||
class topology_error : public std::runtime_error {
|
||||
public:
|
||||
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 };
|
||||
@@ -248,7 +249,7 @@ struct node : public geom_item {
|
||||
|
||||
namespace impl {
|
||||
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 {
|
||||
|
||||
Reference in New Issue
Block a user