mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-20 15:08:51 +00:00
Merge pull request #5362 from IfcOpenShell/fix-ifccircle-ifcellipse-processing
Fix error processing IfcCircle/IfcEllipse #5352
This commit is contained in:
@@ -30,8 +30,15 @@ bool ifcopenshell::geometry::kernels::AbstractKernel::convert(const taxonomy::pt
|
|||||||
try {
|
try {
|
||||||
return dispatch_conversion<0>::dispatch(this, item->kind(), item, results);
|
return dispatch_conversion<0>::dispatch(this, item->kind(), item, results);
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
Logger::Error(e, item->instance);
|
std::string prev_exception = std::string(e.what());
|
||||||
return false;
|
try {
|
||||||
|
return dispatch_with_upgrade<0>::dispatch(this, item, results);
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
Logger::Error(prev_exception + " Conversion for upgraded element failed with: " + std::string(e.what()), item->instance);
|
||||||
|
return false;
|
||||||
|
} catch (...) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// @todo we can't log OCCT exceptions here, can we do some reraising to solve this?
|
// @todo we can't log OCCT exceptions here, can we do some reraising to solve this?
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ namespace {
|
|||||||
struct dispatch_conversion {
|
struct dispatch_conversion {
|
||||||
static bool dispatch(ifcopenshell::geometry::kernels::AbstractKernel* kernel, ifcopenshell::geometry::taxonomy::kinds item_kind, const ifcopenshell::geometry::taxonomy::ptr item, IfcGeom::ConversionResults& results) {
|
static bool dispatch(ifcopenshell::geometry::kernels::AbstractKernel* kernel, ifcopenshell::geometry::taxonomy::kinds item_kind, const ifcopenshell::geometry::taxonomy::ptr item, IfcGeom::ConversionResults& results) {
|
||||||
if (N == item_kind) {
|
if (N == item_kind) {
|
||||||
auto concrete_item = ifcopenshell::geometry::taxonomy::template cast<ifcopenshell::geometry::taxonomy::type_by_kind::type<N>>(item);
|
auto concrete_item = std::static_pointer_cast<ifcopenshell::geometry::taxonomy::type_by_kind::type<N>>(item);
|
||||||
return kernel->convert_impl(concrete_item, results);
|
return kernel->convert_impl(concrete_item, results);
|
||||||
} else {
|
} else {
|
||||||
return dispatch_conversion<N + 1>::dispatch(kernel, item_kind, item, results);
|
return dispatch_conversion<N + 1>::dispatch(kernel, item_kind, item, results);
|
||||||
@@ -102,6 +102,26 @@ namespace {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
struct dispatch_with_upgrade {
|
||||||
|
static bool dispatch(ifcopenshell::geometry::kernels::AbstractKernel* kernel, const ifcopenshell::geometry::taxonomy::ptr item, IfcGeom::ConversionResults& results) {
|
||||||
|
auto concrete_item = ifcopenshell::geometry::taxonomy::template dcast<ifcopenshell::geometry::taxonomy::upgrades::type<N>>(item);
|
||||||
|
if (concrete_item) {
|
||||||
|
return kernel->convert_impl(concrete_item, results);
|
||||||
|
} else {
|
||||||
|
return dispatch_with_upgrade<N + 1>::dispatch(kernel, item, results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct dispatch_with_upgrade<ifcopenshell::geometry::taxonomy::upgrades::max> {
|
||||||
|
static bool dispatch(ifcopenshell::geometry::kernels::AbstractKernel*, const ifcopenshell::geometry::taxonomy::ptr item, IfcGeom::ConversionResults&) {
|
||||||
|
Logger::Error("No conversion with upgrade for " + std::to_string(item->kind()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <class T, class Tuple>
|
template <class T, class Tuple>
|
||||||
struct TupleTypeIndex;
|
struct TupleTypeIndex;
|
||||||
|
|
||||||
|
|||||||
@@ -34,5 +34,6 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCircle* inst) {
|
|||||||
auto c = taxonomy::make<taxonomy::circle>();
|
auto c = taxonomy::make<taxonomy::circle>();
|
||||||
c->radius = r;
|
c->radius = r;
|
||||||
c->matrix = taxonomy::cast<taxonomy::matrix4>(map(placement));
|
c->matrix = taxonomy::cast<taxonomy::matrix4>(map(placement));
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -594,3 +594,160 @@ void ifcopenshell::geometry::taxonomy::extrusion::print(std::ostream& o, int ind
|
|||||||
direction->print(o, indent + 4);
|
direction->print(o, indent + 4);
|
||||||
basis->print(o, indent + 4);
|
basis->print(o, indent + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::optional<face::ptr> ifcopenshell::geometry::taxonomy::loop_to_face_upgrade_impl(ptr item) {
|
||||||
|
boost::optional<face::ptr> face_;
|
||||||
|
auto loop_ = dcast<loop>(item);
|
||||||
|
if (loop_) {
|
||||||
|
loop_->external = true;
|
||||||
|
|
||||||
|
face_ = make<face>();
|
||||||
|
(*face_)->instance = loop_->instance;
|
||||||
|
(*face_)->matrix = loop_->matrix;
|
||||||
|
(*face_)->children = { clone(loop_) };
|
||||||
|
}
|
||||||
|
return face_;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<edge::ptr> ifcopenshell::geometry::taxonomy::curve_to_edge_upgrade_impl(ptr item) {
|
||||||
|
boost::optional<edge::ptr> edge_;
|
||||||
|
auto circle_ = dcast<circle>(item);
|
||||||
|
auto ellipse_ = dcast<ellipse>(item);
|
||||||
|
auto line_ = dcast<line>(item);
|
||||||
|
auto bspline_curve_ = dcast<bspline_curve>(item);
|
||||||
|
if (circle_ || ellipse_ || line_ || bspline_curve_) {
|
||||||
|
edge_ = make<edge>();
|
||||||
|
if (circle_) {
|
||||||
|
(*edge_)->basis = circle_;
|
||||||
|
(*edge_)->instance = circle_->instance;
|
||||||
|
} else if (ellipse_) {
|
||||||
|
(*edge_)->basis = ellipse_;
|
||||||
|
(*edge_)->instance = ellipse_->instance;
|
||||||
|
} else if (line_) {
|
||||||
|
(*edge_)->basis = line_;
|
||||||
|
(*edge_)->instance = line_->instance;
|
||||||
|
} else if (bspline_curve_) {
|
||||||
|
(*edge_)->basis = bspline_curve_;
|
||||||
|
(*edge_)->instance = bspline_curve_->instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (circle_ || ellipse_) {
|
||||||
|
// @todo
|
||||||
|
(*edge_)->start = 0.;
|
||||||
|
(*edge_)->end = 2 * boost::math::constants::pi<double>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return edge_;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<loop::ptr> ifcopenshell::geometry::taxonomy::curve_to_loop_upgrade_impl(ptr item) {
|
||||||
|
boost::optional<loop::ptr> loop_;
|
||||||
|
auto circle_ = dcast<circle>(item);
|
||||||
|
auto ellipse_ = dcast<ellipse>(item);
|
||||||
|
auto line_ = dcast<line>(item);
|
||||||
|
auto bspline_curve_ = dcast<bspline_curve>(item);
|
||||||
|
if (circle_ || ellipse_ || line_ || bspline_curve_) {
|
||||||
|
auto edge_ = make<edge>();
|
||||||
|
if (circle_) {
|
||||||
|
edge_->basis = circle_;
|
||||||
|
} else if (ellipse_) {
|
||||||
|
edge_->basis = ellipse_;
|
||||||
|
} else if (line_) {
|
||||||
|
edge_->basis = line_;
|
||||||
|
} else if (bspline_curve_) {
|
||||||
|
edge_->basis = bspline_curve_;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (circle_ || ellipse_) {
|
||||||
|
// @todo
|
||||||
|
edge_->start = 0.;
|
||||||
|
edge_->end = 2 * boost::math::constants::pi<double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
loop_ = make<loop>();
|
||||||
|
(*loop_)->children.push_back(edge_);
|
||||||
|
}
|
||||||
|
return loop_;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<loop::ptr> ifcopenshell::geometry::taxonomy::edge_to_loop_upgrade_impl(ptr item) {
|
||||||
|
boost::optional<loop::ptr> loop_;
|
||||||
|
auto edge_ = dcast<edge>(item);
|
||||||
|
if (edge_) {
|
||||||
|
loop_ = make<loop>();
|
||||||
|
(*loop_)->children.push_back(edge_);
|
||||||
|
}
|
||||||
|
return loop_;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<face::ptr> ifcopenshell::geometry::taxonomy::curve_to_face_upgrade_impl(ptr item) {
|
||||||
|
boost::optional<face::ptr> face_;
|
||||||
|
auto circle_ = dcast<circle>(item);
|
||||||
|
auto ellipse_ = dcast<ellipse>(item);
|
||||||
|
auto line_ = dcast<line>(item);
|
||||||
|
auto bspline_curve_ = dcast<bspline_curve>(item);
|
||||||
|
|
||||||
|
if (circle_ || ellipse_ || line_ || bspline_curve_) {
|
||||||
|
auto edge_ = make<edge>();
|
||||||
|
if (circle_) {
|
||||||
|
edge_->basis = circle_;
|
||||||
|
} else if (ellipse_) {
|
||||||
|
edge_->basis = ellipse_;
|
||||||
|
} else if (line_) {
|
||||||
|
edge_->basis = line_;
|
||||||
|
} else if (bspline_curve_) {
|
||||||
|
edge_->basis = bspline_curve_;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (circle_ || ellipse_) {
|
||||||
|
// @todo
|
||||||
|
edge_->start = 0.;
|
||||||
|
edge_->end = 2 * boost::math::constants::pi<double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto loop_ = make<loop>();
|
||||||
|
loop_->children.push_back(edge_);
|
||||||
|
|
||||||
|
face_ = make<face>();
|
||||||
|
(*face_)->instance = loop_->instance;
|
||||||
|
(*face_)->matrix = loop_->matrix;
|
||||||
|
(*face_)->children = { clone(loop_) };
|
||||||
|
}
|
||||||
|
return face_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
boost::optional<piecewise_function::ptr> ifcopenshell::geometry::taxonomy::loop_to_piecewise_function_upgrade_impl(ptr item) {
|
||||||
|
boost::optional<piecewise_function::ptr> pwf_;
|
||||||
|
auto loop_ = dcast<loop>(item);
|
||||||
|
if (loop_) {
|
||||||
|
if (loop_->pwf.is_initialized()) {
|
||||||
|
pwf_ = loop_->pwf;
|
||||||
|
} else {
|
||||||
|
piecewise_function::spans_t spans;
|
||||||
|
spans.reserve(loop_->children.size());
|
||||||
|
for (auto& edge_ : loop_->children) {
|
||||||
|
// the edge could be an arc or trimmed circle in the case of IfcIndexPolyCurve - support for this isn't implemented yet
|
||||||
|
if (edge_->basis) {
|
||||||
|
Logger::Message(Logger::Severity::LOG_NOTICE, "Shape of basis curve ignored - edge is treated as a straight line edge");
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& s = boost::get<point3::ptr>(edge_->start)->ccomponents();
|
||||||
|
const auto& e = boost::get<point3::ptr>(edge_->end)->ccomponents();
|
||||||
|
Eigen::Vector3d v = e - s;
|
||||||
|
auto l = v.norm(); // the norm of a vector is a measure of its length
|
||||||
|
v.normalize(); // normalize the vector so that it is a unit direction vector
|
||||||
|
std::function<Eigen::Matrix4d(double)> fn = [s, v](double u) {
|
||||||
|
Eigen::Vector3d o(s + u * v), axis(0, 0, 1), refDirection(v);
|
||||||
|
auto Y = axis.cross(refDirection).normalized();
|
||||||
|
axis = refDirection.cross(Y).normalized();
|
||||||
|
return make<matrix4>(o, axis, refDirection)->components();
|
||||||
|
};
|
||||||
|
spans.emplace_back(l, fn);
|
||||||
|
}
|
||||||
|
pwf_ = make<piecewise_function>(0.0,spans);
|
||||||
|
loop_->pwf = pwf_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pwf_;
|
||||||
|
}
|
||||||
|
|||||||
+28
-125
@@ -1035,6 +1035,7 @@ typedef item const* ptr;
|
|||||||
typedef std::tuple<matrix4, point3, direction3, line, circle, ellipse, bspline_curve, offset_curve, plane, cylinder, sphere, torus, bspline_surface, edge, loop, face, shell, solid, loft, extrusion, revolve, sweep_along_curve, node, collection, boolean_result, piecewise_function> KindsTuple;
|
typedef std::tuple<matrix4, point3, direction3, line, circle, ellipse, bspline_curve, offset_curve, plane, cylinder, sphere, torus, bspline_surface, edge, loop, face, shell, solid, loft, extrusion, revolve, sweep_along_curve, node, collection, boolean_result, piecewise_function> KindsTuple;
|
||||||
typedef std::tuple<line, circle, ellipse, bspline_curve, offset_curve, loop, edge> CurvesTuple;
|
typedef std::tuple<line, circle, ellipse, bspline_curve, offset_curve, loop, edge> CurvesTuple;
|
||||||
typedef std::tuple<plane, cylinder, sphere, torus, bspline_surface, extrusion, revolve> SurfacesTuple;
|
typedef std::tuple<plane, cylinder, sphere, torus, bspline_surface, extrusion, revolve> SurfacesTuple;
|
||||||
|
typedef std::tuple<edge, loop, face, piecewise_function> UpgradesTuple;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct type_by_kind {
|
struct type_by_kind {
|
||||||
@@ -1058,6 +1059,14 @@ typedef item const* ptr;
|
|||||||
static const size_t max = std::tuple_size<impl::SurfacesTuple>::value;
|
static const size_t max = std::tuple_size<impl::SurfacesTuple>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct upgrades {
|
||||||
|
template <std::size_t N>
|
||||||
|
using type = typename std::tuple_element<N, impl::UpgradesTuple>::type;
|
||||||
|
|
||||||
|
static const size_t max = std::tuple_size<impl::UpgradesTuple>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
boost::optional<face::ptr> loop_to_face_upgrade_impl(ptr item);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class loop_to_face_upgrade {
|
class loop_to_face_upgrade {
|
||||||
private:
|
private:
|
||||||
@@ -1065,15 +1074,7 @@ typedef item const* ptr;
|
|||||||
public:
|
public:
|
||||||
loop_to_face_upgrade(taxonomy::ptr item) {
|
loop_to_face_upgrade(taxonomy::ptr item) {
|
||||||
if constexpr (std::is_same_v<T, face>) {
|
if constexpr (std::is_same_v<T, face>) {
|
||||||
auto loop = taxonomy::dcast<taxonomy::loop>(item);
|
face_ = loop_to_face_upgrade_impl(item);
|
||||||
if (loop) {
|
|
||||||
loop->external = true;
|
|
||||||
|
|
||||||
face_ = taxonomy::make<taxonomy::face>();
|
|
||||||
(*face_)->instance = loop->instance;
|
|
||||||
(*face_)->matrix = loop->matrix;
|
|
||||||
(*face_)->children = { taxonomy::clone(loop) };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1091,6 +1092,7 @@ typedef item const* ptr;
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
boost::optional<edge::ptr> curve_to_edge_upgrade_impl(ptr item);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class curve_to_edge_upgrade {
|
class curve_to_edge_upgrade {
|
||||||
private:
|
private:
|
||||||
@@ -1098,28 +1100,7 @@ typedef item const* ptr;
|
|||||||
public:
|
public:
|
||||||
curve_to_edge_upgrade(taxonomy::ptr item) {
|
curve_to_edge_upgrade(taxonomy::ptr item) {
|
||||||
if constexpr (std::is_same_v<T, edge>) {
|
if constexpr (std::is_same_v<T, edge>) {
|
||||||
auto circle = taxonomy::dcast<taxonomy::circle>(item);
|
edge_ = taxonomy::curve_to_edge_upgrade_impl(item);
|
||||||
auto ellipse = taxonomy::dcast<taxonomy::ellipse>(item);
|
|
||||||
auto line = taxonomy::dcast<taxonomy::line>(item);
|
|
||||||
auto bspline_curve = taxonomy::dcast<taxonomy::bspline_curve>(item);
|
|
||||||
if (circle || ellipse || line || bspline_curve) {
|
|
||||||
edge_ = taxonomy::make<taxonomy::edge>();
|
|
||||||
if (circle) {
|
|
||||||
(*edge_)->basis = circle;
|
|
||||||
} else if (ellipse) {
|
|
||||||
(*edge_)->basis = ellipse;
|
|
||||||
} else if (line) {
|
|
||||||
(*edge_)->basis = line;
|
|
||||||
} else if (bspline_curve) {
|
|
||||||
(*edge_)->basis = bspline_curve;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (circle || ellipse) {
|
|
||||||
// @todo
|
|
||||||
(*edge_)->start = 0.;
|
|
||||||
(*edge_)->end = 2 * boost::math::constants::pi<double>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1137,7 +1118,7 @@ typedef item const* ptr;
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
boost::optional<loop::ptr> curve_to_loop_upgrade_impl(ptr item);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class curve_to_loop_upgrade {
|
class curve_to_loop_upgrade {
|
||||||
private:
|
private:
|
||||||
@@ -1145,31 +1126,7 @@ typedef item const* ptr;
|
|||||||
public:
|
public:
|
||||||
curve_to_loop_upgrade(taxonomy::ptr item) {
|
curve_to_loop_upgrade(taxonomy::ptr item) {
|
||||||
if constexpr (std::is_same_v<T, loop>) {
|
if constexpr (std::is_same_v<T, loop>) {
|
||||||
auto circle = taxonomy::dcast<taxonomy::circle>(item);
|
loop_ = curve_to_loop_upgrade_impl(item);
|
||||||
auto ellipse = taxonomy::dcast<taxonomy::ellipse>(item);
|
|
||||||
auto line = taxonomy::dcast<taxonomy::line>(item);
|
|
||||||
auto bspline_curve = taxonomy::dcast<taxonomy::bspline_curve>(item);
|
|
||||||
if (circle || ellipse || line || bspline_curve) {
|
|
||||||
auto edge = taxonomy::make<taxonomy::edge>();
|
|
||||||
if (circle) {
|
|
||||||
edge->basis = circle;
|
|
||||||
} else if (ellipse) {
|
|
||||||
edge->basis = ellipse;
|
|
||||||
} else if (line) {
|
|
||||||
edge->basis = line;
|
|
||||||
} else if (bspline_curve) {
|
|
||||||
edge->basis = bspline_curve;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (circle || ellipse) {
|
|
||||||
// @todo
|
|
||||||
edge->start = 0.;
|
|
||||||
edge->end = 2 * boost::math::constants::pi<double>();
|
|
||||||
}
|
|
||||||
|
|
||||||
loop_ = taxonomy::make<taxonomy::loop>();
|
|
||||||
(*loop_)->children.push_back(edge);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1187,6 +1144,7 @@ typedef item const* ptr;
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
boost::optional<loop::ptr> edge_to_loop_upgrade_impl(ptr item);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class edge_to_loop_upgrade {
|
class edge_to_loop_upgrade {
|
||||||
private:
|
private:
|
||||||
@@ -1194,11 +1152,7 @@ typedef item const* ptr;
|
|||||||
public:
|
public:
|
||||||
edge_to_loop_upgrade(taxonomy::ptr item) {
|
edge_to_loop_upgrade(taxonomy::ptr item) {
|
||||||
if constexpr (std::is_same_v<T, loop>) {
|
if constexpr (std::is_same_v<T, loop>) {
|
||||||
auto edge = taxonomy::dcast<taxonomy::edge>(item);
|
loop_ = edge_to_loop_upgrade_impl(item);
|
||||||
if (edge) {
|
|
||||||
loop_ = taxonomy::make<taxonomy::loop>();
|
|
||||||
(*loop_)->children.push_back(edge);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1216,7 +1170,7 @@ typedef item const* ptr;
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
boost::optional<face::ptr> curve_to_face_upgrade_impl(ptr item);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class curve_to_face_upgrade {
|
class curve_to_face_upgrade {
|
||||||
private:
|
private:
|
||||||
@@ -1224,36 +1178,7 @@ typedef item const* ptr;
|
|||||||
public:
|
public:
|
||||||
curve_to_face_upgrade(taxonomy::ptr item) {
|
curve_to_face_upgrade(taxonomy::ptr item) {
|
||||||
if constexpr (std::is_same_v<T, edge>) {
|
if constexpr (std::is_same_v<T, edge>) {
|
||||||
auto circle = taxonomy::dcast<taxonomy::circle>(item);
|
face_ = curve_to_face_upgrade_impl(item);
|
||||||
auto ellipse = taxonomy::dcast<taxonomy::ellipse>(item);
|
|
||||||
auto line = taxonomy::dcast<taxonomy::line>(item);
|
|
||||||
auto bspline_curve = taxonomy::dcast<taxonomy::bspline_curve>(item);
|
|
||||||
if (circle || ellipse || line || bspline_curve) {
|
|
||||||
auto edge = taxonomy::make<taxonomy::edge>();
|
|
||||||
if (circle) {
|
|
||||||
edge->basis = circle;
|
|
||||||
} else if (ellipse) {
|
|
||||||
edge->basis = ellipse;
|
|
||||||
} else if (line) {
|
|
||||||
edge->basis = line;
|
|
||||||
} else if (bspline_curve) {
|
|
||||||
edge->basis = bspline_curve;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (circle || ellipse) {
|
|
||||||
// @todo
|
|
||||||
edge->start = 0.;
|
|
||||||
edge->end = 2 * boost::math::constants::pi<double>();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto loop = taxonomy::make<taxonomy::loop>();
|
|
||||||
loop->children.push_back(edge);
|
|
||||||
|
|
||||||
face_ = taxonomy::make<taxonomy::face>();
|
|
||||||
(*face_)->instance = loop->instance;
|
|
||||||
(*face_)->matrix = loop->matrix;
|
|
||||||
(*face_)->children = { taxonomy::clone(loop) };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1271,6 +1196,7 @@ typedef item const* ptr;
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
boost::optional<piecewise_function::ptr> loop_to_piecewise_function_upgrade_impl(ptr item);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class loop_to_piecewise_function_upgrade {
|
class loop_to_piecewise_function_upgrade {
|
||||||
private:
|
private:
|
||||||
@@ -1279,36 +1205,7 @@ typedef item const* ptr;
|
|||||||
public:
|
public:
|
||||||
loop_to_piecewise_function_upgrade(taxonomy::ptr item) {
|
loop_to_piecewise_function_upgrade(taxonomy::ptr item) {
|
||||||
if constexpr (std::is_same_v<T, piecewise_function>) {
|
if constexpr (std::is_same_v<T, piecewise_function>) {
|
||||||
auto loop = taxonomy::dcast<taxonomy::loop>(item);
|
pwf_ = loop_to_piecewise_function_upgrade_impl(item);
|
||||||
if (loop) {
|
|
||||||
if (loop->pwf.is_initialized()) {
|
|
||||||
pwf_ = loop->pwf;
|
|
||||||
} else {
|
|
||||||
taxonomy::piecewise_function::spans_t spans;
|
|
||||||
spans.reserve(loop->children.size());
|
|
||||||
for (auto& edge : loop->children) {
|
|
||||||
// the edge could be an arc or trimmed circle in the case of IfcIndexPolyCurve - support for this isn't implemented yet
|
|
||||||
if (edge->basis) {
|
|
||||||
Logger::Message(Logger::Severity::LOG_NOTICE, "Shape of basis curve ignored - edge is treated as a straight line edge");
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& s = boost::get<taxonomy::point3::ptr>(edge->start)->ccomponents();
|
|
||||||
const auto& e = boost::get<taxonomy::point3::ptr>(edge->end)->ccomponents();
|
|
||||||
Eigen::Vector3d v = e - s;
|
|
||||||
auto l = v.norm(); // the norm of a vector is a measure of its length
|
|
||||||
v.normalize(); // normalize the vector so that it is a unit direction vector
|
|
||||||
std::function<Eigen::Matrix4d(double)> fn = [s, v](double u) {
|
|
||||||
Eigen::Vector3d o(s + u * v), axis(0, 0, 1), refDirection(v);
|
|
||||||
auto Y = axis.cross(refDirection).normalized();
|
|
||||||
axis = refDirection.cross(Y).normalized();
|
|
||||||
return taxonomy::make<taxonomy::matrix4>(o, axis, refDirection)->components();
|
|
||||||
};
|
|
||||||
spans.emplace_back(l, fn);
|
|
||||||
}
|
|
||||||
pwf_ = taxonomy::make<taxonomy::piecewise_function>(0.0,spans);
|
|
||||||
loop->pwf = pwf_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1342,13 +1239,13 @@ typedef item const* ptr;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
edge_to_loop_upgrade<T> upg(u);
|
curve_to_face_upgrade<T> upg(u);
|
||||||
if (upg) {
|
if (upg) {
|
||||||
return upg;
|
return upg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
curve_to_face_upgrade<T> upg(u);
|
edge_to_loop_upgrade<T> upg(u);
|
||||||
if (upg) {
|
if (upg) {
|
||||||
return upg;
|
return upg;
|
||||||
}
|
}
|
||||||
@@ -1379,6 +1276,12 @@ typedef item const* ptr;
|
|||||||
return upg;
|
return upg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
curve_to_loop_upgrade<T> upg(u);
|
||||||
|
if (upg) {
|
||||||
|
return upg;
|
||||||
|
}
|
||||||
|
}
|
||||||
{
|
{
|
||||||
curve_to_face_upgrade<T> upg(u);
|
curve_to_face_upgrade<T> upg(u);
|
||||||
if (upg) {
|
if (upg) {
|
||||||
|
|||||||
@@ -228,10 +228,8 @@ class ShapeBuilder:
|
|||||||
:return: IfcCircle
|
:return: IfcCircle
|
||||||
:rtype: ifcopenshell.entity_instance
|
:rtype: ifcopenshell.entity_instance
|
||||||
"""
|
"""
|
||||||
ifc_center = self.file.createIfcAxis2Placement2D(self.file.createIfcCartesianPoint(center))
|
ifc_center = self.create_axis2_placement_2d(center)
|
||||||
ifc_curve = self.file.createIfcCircle(ifc_center, radius)
|
ifc_curve = self.file.createIfcCircle(ifc_center, radius)
|
||||||
|
|
||||||
# self.file_file.createIfcAxis2Placement2D(tool.Ifc.get().createIfcCartesianPoint(center[0:2]))
|
|
||||||
return ifc_curve
|
return ifc_curve
|
||||||
|
|
||||||
def plane(
|
def plane(
|
||||||
@@ -324,9 +322,7 @@ class ShapeBuilder:
|
|||||||
for further extrusion.
|
for further extrusion.
|
||||||
"""
|
"""
|
||||||
direction = self.file.createIfcDirection(ref_x_direction)
|
direction = self.file.createIfcDirection(ref_x_direction)
|
||||||
ifc_position = self.file.createIfcAxis2Placement2D(
|
ifc_position = self.create_axis2_placement_2d(position, direction)
|
||||||
self.file.createIfcCartesianPoint(position), RefDirection=direction
|
|
||||||
)
|
|
||||||
ifc_ellipse = self.file.createIfcEllipse(
|
ifc_ellipse = self.file.createIfcEllipse(
|
||||||
Position=ifc_position, SemiAxis1=x_axis_radius, SemiAxis2=y_axis_radius
|
Position=ifc_position, SemiAxis1=x_axis_radius, SemiAxis2=y_axis_radius
|
||||||
)
|
)
|
||||||
@@ -373,6 +369,9 @@ class ShapeBuilder:
|
|||||||
"OuterCurve": outer_curve,
|
"OuterCurve": outer_curve,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.file.schema == "IFC2X3":
|
||||||
|
kwargs["Position"] = self.create_axis2_placement_2d()
|
||||||
|
|
||||||
if inner_curves:
|
if inner_curves:
|
||||||
if not isinstance(inner_curves, collections.abc.Iterable):
|
if not isinstance(inner_curves, collections.abc.Iterable):
|
||||||
inner_curves = [inner_curves]
|
inner_curves = [inner_curves]
|
||||||
@@ -580,6 +579,17 @@ class ShapeBuilder:
|
|||||||
position=matrix[:, 3][:3].tolist(), z_axis=matrix[:, 2][:3].tolist(), x_axis=matrix[:, 0][:3].tolist()
|
position=matrix[:, 3][:3].tolist(), z_axis=matrix[:, 2][:3].tolist(), x_axis=matrix[:, 0][:3].tolist()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def create_axis2_placement_2d(
|
||||||
|
self, position: VectorTuple = (0.0, 0.0), x_direction: Optional[VectorTuple] = None
|
||||||
|
) -> ifcopenshell.entity_instance:
|
||||||
|
"""Create IfcAxis2Placement2D."""
|
||||||
|
ref_direction = self.file.create_entity("IfcDirection", x_direction) if x_direction else None
|
||||||
|
return self.file.create_entity(
|
||||||
|
"IfcAxis2Placement2D",
|
||||||
|
Location=self.file.create_entity("IfcCartesianPoint", position),
|
||||||
|
RefDirection=ref_direction,
|
||||||
|
)
|
||||||
|
|
||||||
def mirror(
|
def mirror(
|
||||||
self,
|
self,
|
||||||
curve_or_item: Union[ifcopenshell.entity_instance, list[ifcopenshell.entity_instance]],
|
curve_or_item: Union[ifcopenshell.entity_instance, list[ifcopenshell.entity_instance]],
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
# IfcOpenShell - IFC toolkit and geometry engine
|
||||||
|
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||||
|
#
|
||||||
|
# This file is part of IfcOpenShell.
|
||||||
|
#
|
||||||
|
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import ifcopenshell
|
||||||
|
import ifcopenshell.geom
|
||||||
|
import test.bootstrap
|
||||||
|
from ifcopenshell.util.shape_builder import ShapeBuilder, V
|
||||||
|
|
||||||
|
|
||||||
|
class TestCreatingShapes(test.bootstrap.IFC4):
|
||||||
|
def test_create_IfcCirle(self):
|
||||||
|
builder = ShapeBuilder(self.file)
|
||||||
|
item = builder.circle(radius=1.0)
|
||||||
|
settings = ifcopenshell.geom.settings()
|
||||||
|
shape = ifcopenshell.geom.create_shape(settings, item)
|
||||||
|
assert shape.verts
|
||||||
|
|
||||||
|
def test_create_IfcEllipse(self):
|
||||||
|
builder = ShapeBuilder(self.file)
|
||||||
|
item = self.file.create_entity(
|
||||||
|
"IfcEllipse", Position=builder.create_axis2_placement_2d(), SemiAxis1=1.0, SemiAxis2=0.5
|
||||||
|
)
|
||||||
|
settings = ifcopenshell.geom.settings()
|
||||||
|
shape = ifcopenshell.geom.create_shape(settings, item)
|
||||||
|
assert shape.verts
|
||||||
|
|
||||||
|
def test_create_IfcLine(self):
|
||||||
|
item = self.file.create_entity(
|
||||||
|
"IfcLine",
|
||||||
|
Pnt=self.file.create_entity("IfcCartesianPoint", (0.0, 0.0)),
|
||||||
|
Dir=self.file.create_entity(
|
||||||
|
"IfcVector", Orientation=self.file.create_entity("IfcDirection", (1.0, 0.0)), Magnitude=1.0
|
||||||
|
),
|
||||||
|
)
|
||||||
|
settings = ifcopenshell.geom.settings()
|
||||||
|
shape = ifcopenshell.geom.create_shape(settings, item)
|
||||||
|
assert shape.verts
|
||||||
|
|
||||||
|
def test_create_IfcBSplineCurve(self):
|
||||||
|
points = [
|
||||||
|
(6.4062, 19.4575766757, 13.352536093),
|
||||||
|
(5.8477429418, 19.9080686796, 14.1328111323),
|
||||||
|
(3.6139147091, 20.3256826827, 14.8561398035),
|
||||||
|
(1.1790137971e-05, 20.2853841412, 14.7863406821),
|
||||||
|
(1.1790137971e-05, 18.5102818197, 11.7117732726),
|
||||||
|
(1.16078600148, 18.0665062393, 10.9431314203),
|
||||||
|
]
|
||||||
|
item = self.file.create_entity(
|
||||||
|
"IfcBSplineCurveWithKnots",
|
||||||
|
Degree=3,
|
||||||
|
ControlPointsList=[self.file.create_entity("IfcCartesianPoint", p) for p in points],
|
||||||
|
KnotMultiplicities=(4, 1, 1, 4),
|
||||||
|
Knots=(0.0, 1 / 3, 2 / 3, 1.0),
|
||||||
|
)
|
||||||
|
settings = ifcopenshell.geom.settings()
|
||||||
|
shape = ifcopenshell.geom.create_shape(settings, item)
|
||||||
|
assert shape.verts
|
||||||
Reference in New Issue
Block a user