to_string() option, no shared_ptr in OpaqueCoord, add ConvResShape::vertices(), newell instead of simple cross product, create_epeck(double/str)

This commit is contained in:
Thomas Krijnen
2023-12-13 16:43:33 +01:00
parent 14e924cd8c
commit 6ed91d3ea4
8 changed files with 219 additions and 94 deletions
+117 -55
View File
@@ -21,8 +21,12 @@ using ifcopenshell::geometry::NumberEpeck;
ifcopenshell::geometry::CgalShape::CgalShape(const cgal_shape_t & shape) {
shape_ = shape;
CGAL::Polygon_mesh_processing::triangulate_faces(*shape_);
CGAL::Polygon_mesh_processing::remove_degenerate_faces(*shape_);
if (shape.size_of_facets() != 1) {
// this is for handling the specical case of storing a single point in a polyhedron,
// @todo come up with a proper variant for storing lower dimensional entities
CGAL::Polygon_mesh_processing::triangulate_faces(*shape_);
CGAL::Polygon_mesh_processing::remove_degenerate_faces(*shape_);
}
}
#ifndef IFOPSH_SIMPLE_KERNEL
@@ -63,7 +67,7 @@ void ifcopenshell::geometry::CgalShape::Triangulate(ifcopenshell::geometry::Sett
m(2, 0), m(2, 1), m(2, 2), m(2, 3));
// Apply transformation
for (auto &vertex : vertices(s)) {
for (auto &vertex : s.vertex_handles()) {
vertex->point() = vertex->point().transform(trsf);
}
}
@@ -185,7 +189,7 @@ void ifcopenshell::geometry::CgalShape::Serialize(const ifcopenshell::geometry::
m(2, 0), m(2, 1), m(2, 2), m(2, 3));
// Apply transformation
for (auto &vertex : vertices(s)) {
for (auto &vertex : s.vertex_handles()) {
vertex->point() = vertex->point().transform(trsf);
}
}
@@ -255,7 +259,7 @@ int ifcopenshell::geometry::CgalShape::num_faces() const
}
}
std::shared_ptr<OpaqueNumber> ifcopenshell::geometry::CgalShape::CgalShape::length()
OpaqueNumber* ifcopenshell::geometry::CgalShape::CgalShape::length()
{
to_poly();
Kernel_::FT len = 0;
@@ -265,19 +269,19 @@ std::shared_ptr<OpaqueNumber> ifcopenshell::geometry::CgalShape::CgalShape::leng
it->next()->vertex()->point()
).squared_length());
}
return std::make_shared<NumberType>(len);
return new NumberType(len);
}
std::shared_ptr<OpaqueNumber> ifcopenshell::geometry::CgalShape::area()
OpaqueNumber* ifcopenshell::geometry::CgalShape::area()
{
to_poly();
return std::make_shared<NumberType>(CGAL::Polygon_mesh_processing::area(*shape_));
return new NumberType(CGAL::Polygon_mesh_processing::area(*shape_));
}
std::shared_ptr<OpaqueNumber> ifcopenshell::geometry::CgalShape::volume()
OpaqueNumber* ifcopenshell::geometry::CgalShape::volume()
{
to_poly();
return std::make_shared<NumberType>(CGAL::Polygon_mesh_processing::volume(*shape_));
return new NumberType(CGAL::Polygon_mesh_processing::volume(*shape_));
}
OpaqueCoordinate<3> ifcopenshell::geometry::CgalShape::position()
@@ -297,9 +301,9 @@ OpaqueCoordinate<3> ifcopenshell::geometry::CgalShape::position()
p[i] /= N;
}
return OpaqueCoordinate<3>(
std::make_shared<NumberType>(p[0]),
std::make_shared<NumberType>(p[1]),
std::make_shared<NumberType>(p[2])
new NumberType(p[0]),
new NumberType(p[1]),
new NumberType(p[2])
);
} else {
throw std::runtime_error("Invalid shape type");
@@ -307,15 +311,25 @@ OpaqueCoordinate<3> ifcopenshell::geometry::CgalShape::position()
}
namespace {
template <typename Facet>
CGAL::Direction_3<Kernel_> newell(Facet& face) {
typename Kernel_::FT a(0), b(0), c(0);
CGAL::Polyhedron_3<Kernel_>::Halfedge_around_facet_const_circulator current_halfedge = face.facet_begin();
do {
auto& curr = current_halfedge->vertex()->point();
auto& next = current_halfedge->next()->vertex()->point();
a += (curr.y() - next.y()) * (curr.z() + next.z());
b += (curr.z() - next.z()) * (curr.x() + next.x());
c += (curr.x() - next.x()) * (curr.y() + next.y());
} while (++current_halfedge != face.facet_begin());
return CGAL::Direction_3<Kernel_>(a, b, c);
}
struct Plane_equation {
template <class Facet>
typename Facet::Plane_3 operator()(Facet& f) {
// @todo from the docs, but better use Newell's method
typename Facet::Halfedge_handle h = f.halfedge();
typedef typename Facet::Plane_3 Plane;
return Plane(h->vertex()->point(),
h->next()->vertex()->point(),
h->next()->next()->vertex()->point());
template <typename Facet>
typename Facet::Plane_3 operator()(Facet& face) {
typename Facet::Halfedge_handle h = face.halfedge();
return typename Facet::Plane_3(h->vertex()->point(), newell(face));
}
};
}
@@ -331,9 +345,9 @@ OpaqueCoordinate<3> ifcopenshell::geometry::CgalShape::axis()
auto maxval = ((-*minel) > *maxel) ? (-*minel) : *maxel;
return OpaqueCoordinate<3>(
std::make_shared<NumberType>(pl.a() / maxval),
std::make_shared<NumberType>(pl.b() / maxval),
std::make_shared<NumberType>(pl.c() / maxval)
new NumberType(pl.a() / maxval),
new NumberType(pl.b() / maxval),
new NumberType(pl.c() / maxval)
);
} else {
throw std::runtime_error("Invalid shape type");
@@ -390,9 +404,52 @@ ConversionResultShape * ifcopenshell::geometry::CgalShape::box()
throw std::runtime_error("Not implemented");
}
std::vector<ConversionResultShape*> ifcopenshell::geometry::CgalShape::vertices()
{
// @todo this is ridiculous
to_poly();
std::vector<ConversionResultShape*> result;
for (auto& p : shape_->points()) {
std::vector<cgal_point_t> ps = {
p, p, p
};
std::vector<std::vector<size_t>> ids(1);
ids.front().push_back(0);
ids.front().push_back(1);
ids.front().push_back(2);
cgal_shape_t poly;
CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh(ps, ids, poly);
result.push_back(new CgalShape(poly));
}
return result;
}
std::vector<ConversionResultShape*> ifcopenshell::geometry::CgalShape::edges()
{
throw std::runtime_error("Not implemented");
// @todo this is ridiculous
to_poly();
std::vector<ConversionResultShape*> result;
for (auto& ed : shape_->edges()) {
std::vector<cgal_point_t> ps = {
ed.vertex()->point(),
ed.vertex()->point(),
ed.next()->vertex()->point()
};
std::vector<std::vector<size_t>> ids(1);
ids.front().push_back(0);
ids.front().push_back(1);
ids.front().push_back(2);
cgal_shape_t poly;
CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh(ps, ids, poly);
result.push_back(new CgalShape(poly));
}
return result;
}
std::vector<ConversionResultShape*> ifcopenshell::geometry::CgalShape::facets()
@@ -463,7 +520,7 @@ ConversionResultShape* ifcopenshell::geometry::CgalShape::moved(ifcopenshell::ge
m(2, 0), m(2, 1), m(2, 2), m(2, 3));
// Apply transformation
for (auto &vertex : vertices(s)) {
for (auto &vertex : s.vertex_handles()) {
vertex->point() = vertex->point().transform(trsf);
}
}
@@ -515,17 +572,17 @@ int ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::num_faces() const
throw std::runtime_error("Not implemented");
}
std::shared_ptr<OpaqueNumber> ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::CgalShapeHalfSpaceDecomposition::length()
OpaqueNumber* ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::CgalShapeHalfSpaceDecomposition::length()
{
throw std::runtime_error("Not implemented");
}
std::shared_ptr<OpaqueNumber> ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::area()
OpaqueNumber* ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::area()
{
throw std::runtime_error("Not implemented");
}
std::shared_ptr<OpaqueNumber> ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::volume()
OpaqueNumber* ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::volume()
{
throw std::runtime_error("Not implemented");
}
@@ -535,9 +592,9 @@ OpaqueCoordinate<3> ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::pos
if (planes_.size() == 1) {
auto xyz = CGAL::ORIGIN + planes_.front().d() * CGAL::Vector_3<Kernel_>(planes_.front().a(), planes_.front().b(), planes_.front().c());
return OpaqueCoordinate<3>(
std::make_shared<NumberType>(xyz.cartesian(0)),
std::make_shared<NumberType>(xyz.cartesian(1)),
std::make_shared<NumberType>(xyz.cartesian(2))
new NumberType(xyz.cartesian(0)),
new NumberType(xyz.cartesian(1)),
new NumberType(xyz.cartesian(2))
);
} else {
throw std::runtime_error("Invalid shape type");
@@ -552,9 +609,9 @@ OpaqueCoordinate<3> ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::axi
auto maxel = std::max_element(abc.begin(), abc.end());
auto maxval = ((-*minel) > *maxel) ? (-*minel) : *maxel;
return OpaqueCoordinate<3>(
std::make_shared<NumberType>(planes_.front().a() / maxval),
std::make_shared<NumberType>(planes_.front().b() / maxval),
std::make_shared<NumberType>(planes_.front().c() / maxval)
new NumberType(planes_.front().a() / maxval),
new NumberType(planes_.front().b() / maxval),
new NumberType(planes_.front().c() / maxval)
);
} else {
throw std::runtime_error("Invalid shape type");
@@ -569,10 +626,10 @@ OpaqueCoordinate<4> ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::pla
auto maxel = std::max_element(abc.begin(), abc.end());
auto maxval = ((-*minel) > *maxel) ? (-*minel) : *maxel;
return OpaqueCoordinate<4>(
std::make_shared<NumberType>(planes_.front().a() / maxval),
std::make_shared<NumberType>(planes_.front().b() / maxval),
std::make_shared<NumberType>(planes_.front().c() / maxval),
std::make_shared<NumberType>(planes_.front().d() / maxval)
new NumberType(planes_.front().a() / maxval),
new NumberType(planes_.front().b() / maxval),
new NumberType(planes_.front().c() / maxval),
new NumberType(planes_.front().d() / maxval)
);
} else {
throw std::runtime_error("Invalid shape type");
@@ -599,6 +656,11 @@ ConversionResultShape * ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition:
throw std::runtime_error("Not implemented");
}
std::vector<ConversionResultShape*> ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::vertices()
{
throw std::runtime_error("Not implemented");
}
std::vector<ConversionResultShape*> ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::edges()
{
throw std::runtime_error("Not implemented");
@@ -646,16 +708,16 @@ void ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::map(OpaqueCoordina
plane_map<Kernel_> mp;
mp.insert({
CGAL::Plane_3<Kernel_>(
std::static_pointer_cast<NumberEpeck>(from.values[0])->value(),
std::static_pointer_cast<NumberEpeck>(from.values[1])->value(),
std::static_pointer_cast<NumberEpeck>(from.values[2])->value(),
std::static_pointer_cast<NumberEpeck>(from.values[3])->value()
static_cast<NumberEpeck*>(from.values[0])->value(),
static_cast<NumberEpeck*>(from.values[1])->value(),
static_cast<NumberEpeck*>(from.values[2])->value(),
static_cast<NumberEpeck*>(from.values[3])->value()
),
CGAL::Plane_3<Kernel_>(
std::static_pointer_cast<NumberEpeck>(to.values[0])->value(),
std::static_pointer_cast<NumberEpeck>(to.values[1])->value(),
std::static_pointer_cast<NumberEpeck>(to.values[2])->value(),
std::static_pointer_cast<NumberEpeck>(to.values[3])->value()
static_cast<NumberEpeck*>(to.values[0])->value(),
static_cast<NumberEpeck*>(to.values[1])->value(),
static_cast<NumberEpeck*>(to.values[2])->value(),
static_cast<NumberEpeck*>(to.values[3])->value()
)
});
auto nw = shape_->map(mp);
@@ -674,16 +736,16 @@ void ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::map(const std::vec
auto& to = *jt;
mp.insert({
CGAL::Plane_3<Kernel_>(
std::static_pointer_cast<NumberEpeck>(from.values[0])->value(),
std::static_pointer_cast<NumberEpeck>(from.values[1])->value(),
std::static_pointer_cast<NumberEpeck>(from.values[2])->value(),
std::static_pointer_cast<NumberEpeck>(from.values[3])->value()
static_cast<NumberEpeck*>(from.values[0])->value(),
static_cast<NumberEpeck*>(from.values[1])->value(),
static_cast<NumberEpeck*>(from.values[2])->value(),
static_cast<NumberEpeck*>(from.values[3])->value()
),
CGAL::Plane_3<Kernel_>(
std::static_pointer_cast<NumberEpeck>(to.values[0])->value(),
std::static_pointer_cast<NumberEpeck>(to.values[1])->value(),
std::static_pointer_cast<NumberEpeck>(to.values[2])->value(),
std::static_pointer_cast<NumberEpeck>(to.values[3])->value()
static_cast<NumberEpeck*>(to.values[0])->value(),
static_cast<NumberEpeck*>(to.values[1])->value(),
static_cast<NumberEpeck*>(to.values[2])->value(),
static_cast<NumberEpeck*>(to.values[3])->value()
)
});
}