mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +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 {
|
||||
return dispatch_conversion<0>::dispatch(this, item->kind(), item, results);
|
||||
} catch (std::exception& e) {
|
||||
Logger::Error(e, item->instance);
|
||||
return false;
|
||||
std::string prev_exception = std::string(e.what());
|
||||
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 (...) {
|
||||
// @todo we can't log OCCT exceptions here, can we do some reraising to solve this?
|
||||
return false;
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace {
|
||||
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) {
|
||||
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);
|
||||
} else {
|
||||
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>
|
||||
struct TupleTypeIndex;
|
||||
|
||||
|
||||
@@ -34,5 +34,6 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCircle* inst) {
|
||||
auto c = taxonomy::make<taxonomy::circle>();
|
||||
c->radius = r;
|
||||
c->matrix = taxonomy::cast<taxonomy::matrix4>(map(placement));
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -594,3 +594,160 @@ void ifcopenshell::geometry::taxonomy::extrusion::print(std::ostream& o, int ind
|
||||
direction->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<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<edge, loop, face, piecewise_function> UpgradesTuple;
|
||||
}
|
||||
|
||||
struct type_by_kind {
|
||||
@@ -1058,6 +1059,14 @@ typedef item const* ptr;
|
||||
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>
|
||||
class loop_to_face_upgrade {
|
||||
private:
|
||||
@@ -1065,15 +1074,7 @@ typedef item const* ptr;
|
||||
public:
|
||||
loop_to_face_upgrade(taxonomy::ptr item) {
|
||||
if constexpr (std::is_same_v<T, face>) {
|
||||
auto loop = taxonomy::dcast<taxonomy::loop>(item);
|
||||
if (loop) {
|
||||
loop->external = true;
|
||||
|
||||
face_ = taxonomy::make<taxonomy::face>();
|
||||
(*face_)->instance = loop->instance;
|
||||
(*face_)->matrix = loop->matrix;
|
||||
(*face_)->children = { taxonomy::clone(loop) };
|
||||
}
|
||||
face_ = loop_to_face_upgrade_impl(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1091,6 +1092,7 @@ typedef item const* ptr;
|
||||
}
|
||||
};
|
||||
|
||||
boost::optional<edge::ptr> curve_to_edge_upgrade_impl(ptr item);
|
||||
template <typename T>
|
||||
class curve_to_edge_upgrade {
|
||||
private:
|
||||
@@ -1098,28 +1100,7 @@ typedef item const* ptr;
|
||||
public:
|
||||
curve_to_edge_upgrade(taxonomy::ptr item) {
|
||||
if constexpr (std::is_same_v<T, edge>) {
|
||||
auto circle = taxonomy::dcast<taxonomy::circle>(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>();
|
||||
}
|
||||
}
|
||||
edge_ = taxonomy::curve_to_edge_upgrade_impl(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1137,7 +1118,7 @@ typedef item const* ptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
boost::optional<loop::ptr> curve_to_loop_upgrade_impl(ptr item);
|
||||
template <typename T>
|
||||
class curve_to_loop_upgrade {
|
||||
private:
|
||||
@@ -1145,31 +1126,7 @@ typedef item const* ptr;
|
||||
public:
|
||||
curve_to_loop_upgrade(taxonomy::ptr item) {
|
||||
if constexpr (std::is_same_v<T, loop>) {
|
||||
auto circle = taxonomy::dcast<taxonomy::circle>(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);
|
||||
}
|
||||
loop_ = curve_to_loop_upgrade_impl(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1187,6 +1144,7 @@ typedef item const* ptr;
|
||||
}
|
||||
};
|
||||
|
||||
boost::optional<loop::ptr> edge_to_loop_upgrade_impl(ptr item);
|
||||
template <typename T>
|
||||
class edge_to_loop_upgrade {
|
||||
private:
|
||||
@@ -1194,11 +1152,7 @@ typedef item const* ptr;
|
||||
public:
|
||||
edge_to_loop_upgrade(taxonomy::ptr item) {
|
||||
if constexpr (std::is_same_v<T, loop>) {
|
||||
auto edge = taxonomy::dcast<taxonomy::edge>(item);
|
||||
if (edge) {
|
||||
loop_ = taxonomy::make<taxonomy::loop>();
|
||||
(*loop_)->children.push_back(edge);
|
||||
}
|
||||
loop_ = edge_to_loop_upgrade_impl(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1216,7 +1170,7 @@ typedef item const* ptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
boost::optional<face::ptr> curve_to_face_upgrade_impl(ptr item);
|
||||
template <typename T>
|
||||
class curve_to_face_upgrade {
|
||||
private:
|
||||
@@ -1224,36 +1178,7 @@ typedef item const* ptr;
|
||||
public:
|
||||
curve_to_face_upgrade(taxonomy::ptr item) {
|
||||
if constexpr (std::is_same_v<T, edge>) {
|
||||
auto circle = taxonomy::dcast<taxonomy::circle>(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) };
|
||||
}
|
||||
face_ = curve_to_face_upgrade_impl(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1271,6 +1196,7 @@ typedef item const* ptr;
|
||||
}
|
||||
};
|
||||
|
||||
boost::optional<piecewise_function::ptr> loop_to_piecewise_function_upgrade_impl(ptr item);
|
||||
template <typename T>
|
||||
class loop_to_piecewise_function_upgrade {
|
||||
private:
|
||||
@@ -1279,36 +1205,7 @@ typedef item const* ptr;
|
||||
public:
|
||||
loop_to_piecewise_function_upgrade(taxonomy::ptr item) {
|
||||
if constexpr (std::is_same_v<T, piecewise_function>) {
|
||||
auto loop = taxonomy::dcast<taxonomy::loop>(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_;
|
||||
}
|
||||
}
|
||||
pwf_ = loop_to_piecewise_function_upgrade_impl(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1342,13 +1239,13 @@ typedef item const* ptr;
|
||||
}
|
||||
}
|
||||
{
|
||||
edge_to_loop_upgrade<T> upg(u);
|
||||
curve_to_face_upgrade<T> upg(u);
|
||||
if (upg) {
|
||||
return upg;
|
||||
}
|
||||
}
|
||||
{
|
||||
curve_to_face_upgrade<T> upg(u);
|
||||
edge_to_loop_upgrade<T> upg(u);
|
||||
if (upg) {
|
||||
return upg;
|
||||
}
|
||||
@@ -1379,6 +1276,12 @@ typedef item const* ptr;
|
||||
return upg;
|
||||
}
|
||||
}
|
||||
{
|
||||
curve_to_loop_upgrade<T> upg(u);
|
||||
if (upg) {
|
||||
return upg;
|
||||
}
|
||||
}
|
||||
{
|
||||
curve_to_face_upgrade<T> upg(u);
|
||||
if (upg) {
|
||||
|
||||
@@ -228,10 +228,8 @@ class ShapeBuilder:
|
||||
:return: IfcCircle
|
||||
: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)
|
||||
|
||||
# self.file_file.createIfcAxis2Placement2D(tool.Ifc.get().createIfcCartesianPoint(center[0:2]))
|
||||
return ifc_curve
|
||||
|
||||
def plane(
|
||||
@@ -324,9 +322,7 @@ class ShapeBuilder:
|
||||
for further extrusion.
|
||||
"""
|
||||
direction = self.file.createIfcDirection(ref_x_direction)
|
||||
ifc_position = self.file.createIfcAxis2Placement2D(
|
||||
self.file.createIfcCartesianPoint(position), RefDirection=direction
|
||||
)
|
||||
ifc_position = self.create_axis2_placement_2d(position, direction)
|
||||
ifc_ellipse = self.file.createIfcEllipse(
|
||||
Position=ifc_position, SemiAxis1=x_axis_radius, SemiAxis2=y_axis_radius
|
||||
)
|
||||
@@ -373,6 +369,9 @@ class ShapeBuilder:
|
||||
"OuterCurve": outer_curve,
|
||||
}
|
||||
|
||||
if self.file.schema == "IFC2X3":
|
||||
kwargs["Position"] = self.create_axis2_placement_2d()
|
||||
|
||||
if inner_curves:
|
||||
if not isinstance(inner_curves, collections.abc.Iterable):
|
||||
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()
|
||||
)
|
||||
|
||||
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(
|
||||
self,
|
||||
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