Major update to halfspace algorithm, conversion result shape analysis

This commit is contained in:
Thomas Krijnen
2023-11-02 09:04:34 +01:00
parent 559de7d4cd
commit 809668c015
21 changed files with 1385 additions and 133 deletions
@@ -1,13 +1,22 @@
#include "OpenCascadeConversionResult.h"
#include <map>
#include <TopoDS.hxx>
#include <TopExp.hxx>
#include <BRepGProp.hxx>
#include <GProp_GProps.hxx>
#include <Geom_SphericalSurface.hxx>
#include "OpenCascadeConversionResult.h"
#include "../../../ifcparse/IfcLogger.h"
#include "../../../ifcgeom/IfcGeomRepresentation.h"
#include "base_utils.h"
#include "boolean_utils.h"
#include <TopoDS.hxx>
#include <Geom_SphericalSurface.hxx>
#include <map>
using IfcGeom::OpaqueNumber;
using IfcGeom::OpaqueCoordinate;
using IfcGeom::NumberNativeDouble;
using IfcGeom::ConversionResultShape;
namespace {
// We bypass the conversion to gp_GTrsf, because it does not work
@@ -226,9 +235,190 @@ void ifcopenshell::geometry::OpenCascadeShape::Serialize(const ifcopenshell::geo
}
int ifcopenshell::geometry::OpenCascadeShape::surface_genus() const {
throw std::runtime_error("Not implemented");
return IfcGeom::util::surface_genus(shape_);
}
bool ifcopenshell::geometry::OpenCascadeShape::is_manifold() const {
return IfcGeom::util::is_manifold(shape_);
}
int ifcopenshell::geometry::OpenCascadeShape::num_vertices() const
{
return IfcGeom::util::count(shape_, TopAbs_VERTEX);
}
int ifcopenshell::geometry::OpenCascadeShape::num_edges() const
{
return IfcGeom::util::count(shape_, TopAbs_EDGE);
}
int ifcopenshell::geometry::OpenCascadeShape::num_faces() const
{
return IfcGeom::util::count(shape_, TopAbs_FACE);
}
std::shared_ptr<OpaqueNumber> ifcopenshell::geometry::OpenCascadeShape::OpenCascadeShape::length()
{
GProp_GProps prop;
BRepGProp::LinearProperties(shape_, prop);
double l = prop.Mass();
return std::make_shared<NumberNativeDouble>(l);
}
std::shared_ptr<OpaqueNumber> ifcopenshell::geometry::OpenCascadeShape::area()
{
GProp_GProps prop;
BRepGProp::SurfaceProperties(shape_, prop);
double l = prop.Mass();
return std::make_shared<NumberNativeDouble>(l);
}
std::shared_ptr<OpaqueNumber> ifcopenshell::geometry::OpenCascadeShape::volume()
{
GProp_GProps prop;
BRepGProp::VolumeProperties(shape_, prop);
double l = prop.Mass();
return std::make_shared<NumberNativeDouble>(l);
}
#include <Geom_Plane.hxx>
OpaqueCoordinate<3> ifcopenshell::geometry::OpenCascadeShape::position()
{
if (shape_.ShapeType() == TopAbs_FACE) {
auto surf = BRep_Tool::Surface(TopoDS::Face(shape_));
auto plane = Handle(Geom_Plane)::DownCast(surf);
if (plane) {
auto loc = plane->Location();
return OpaqueCoordinate<3>(
std::make_shared<NumberNativeDouble>(loc.X()),
std::make_shared<NumberNativeDouble>(loc.Y()),
std::make_shared<NumberNativeDouble>(loc.Z())
);
}
}
throw std::runtime_error("Invalid shape type");
}
OpaqueCoordinate<3> ifcopenshell::geometry::OpenCascadeShape::axis()
{
if (shape_.ShapeType() == TopAbs_FACE) {
auto surf = BRep_Tool::Surface(TopoDS::Face(shape_));
auto plane = Handle(Geom_Plane)::DownCast(surf);
if (plane) {
auto dir = plane->Axis().Direction();
return OpaqueCoordinate<3>(
std::make_shared<NumberNativeDouble>(dir.X()),
std::make_shared<NumberNativeDouble>(dir.Y()),
std::make_shared<NumberNativeDouble>(dir.Z())
);
}
}
throw std::runtime_error("Invalid shape type");
}
OpaqueCoordinate<4> ifcopenshell::geometry::OpenCascadeShape::plane_equation()
{
if (shape_.ShapeType() == TopAbs_FACE) {
auto surf = BRep_Tool::Surface(TopoDS::Face(shape_));
auto plane = Handle(Geom_Plane)::DownCast(surf);
if (plane) {
double a, b, c, d;
plane->Pln().Coefficients(a, b, c, d);
return OpaqueCoordinate<4>(
std::make_shared<NumberNativeDouble>(a),
std::make_shared<NumberNativeDouble>(b),
std::make_shared<NumberNativeDouble>(c),
std::make_shared<NumberNativeDouble>(d)
);
}
}
throw std::runtime_error("Invalid shape type");
}
std::vector<ConversionResultShape*> ifcopenshell::geometry::OpenCascadeShape::convex_decomposition()
{
throw std::runtime_error("Not implemented");
}
}
ConversionResultShape * ifcopenshell::geometry::OpenCascadeShape::halfspaces()
{
throw std::runtime_error("Not implemented");
}
ConversionResultShape* ifcopenshell::geometry::OpenCascadeShape::solid()
{
throw std::runtime_error("Not implemented");
}
ConversionResultShape * ifcopenshell::geometry::OpenCascadeShape::box()
{
throw std::runtime_error("Not implemented");
}
std::vector<ConversionResultShape*> ifcopenshell::geometry::OpenCascadeShape::edges()
{
TopTools_IndexedMapOfShape map;
TopExp::MapShapes(shape_, TopAbs_EDGE, map);
std::vector<ConversionResultShape*> vec;
for (int i = 1; i <= map.Extent(); ++i) {
vec.push_back(new OpenCascadeShape(map.FindKey(i)));
}
return vec;
}
std::vector<ConversionResultShape*> ifcopenshell::geometry::OpenCascadeShape::facets()
{
TopTools_IndexedMapOfShape map;
TopExp::MapShapes(shape_, TopAbs_FACE, map);
std::vector<ConversionResultShape*> vec;
for (int i = 1; i <= map.Extent(); ++i) {
vec.push_back(new OpenCascadeShape(map.FindKey(i)));
}
return vec;
}
namespace {
ConversionResultShape* boolean_op(BOPAlgo_Operation op, const TopoDS_Shape& shape_, const TopoDS_Shape& other_shape) {
IfcGeom::util::boolean_settings st;
st.attempt_2d = true;
st.debug = false;
st.precision = 1.e-5;
TopoDS_Shape result;
if (IfcGeom::util::boolean_operation(st, shape_, other_shape, op, result)) {
return new ifcopenshell::geometry::OpenCascadeShape(result);
} else {
throw std::runtime_error("Failed to process boolean operation");
}
}
}
ConversionResultShape* ifcopenshell::geometry::OpenCascadeShape::add(ConversionResultShape* other)
{
return boolean_op(BOPAlgo_FUSE, shape_, ((ifcopenshell::geometry::OpenCascadeShape*)other)->shape_);
}
ConversionResultShape* ifcopenshell::geometry::OpenCascadeShape::subtract(ConversionResultShape* other)
{
return boolean_op(BOPAlgo_CUT, shape_, ((ifcopenshell::geometry::OpenCascadeShape*)other)->shape_);
}
ConversionResultShape* ifcopenshell::geometry::OpenCascadeShape::intersect(ConversionResultShape* other)
{
return boolean_op(BOPAlgo_COMMON, shape_, ((ifcopenshell::geometry::OpenCascadeShape*)other)->shape_);
}
std::pair<OpaqueCoordinate<3>, OpaqueCoordinate<3>> ifcopenshell::geometry::OpenCascadeShape::bounding_box() const
{
throw std::runtime_error("Not implemented");
}
ConversionResultShape* ifcopenshell::geometry::OpenCascadeShape::moved(ifcopenshell::geometry::taxonomy::matrix4::ptr t) const
{
return new OpenCascadeShape(IfcGeom::util::apply_transformation(shape_, *t));
}
void ifcopenshell::geometry::OpenCascadeShape::map(OpaqueCoordinate<4>& from, OpaqueCoordinate<4>& to) {
throw std::runtime_error("Not implemented");
}
@@ -39,6 +39,9 @@
namespace ifcopenshell {
namespace geometry {
using IfcGeom::OpaqueCoordinate;
using IfcGeom::OpaqueNumber;
class OpenCascadeShape : public IfcGeom::ConversionResultShape {
public:
OpenCascadeShape(const TopoDS_Shape& shape)
@@ -48,28 +51,51 @@ namespace ifcopenshell {
operator const TopoDS_Shape& () { return shape_; }
virtual void Triangulate(const IfcGeom::IteratorSettings& settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int surface_style_id) const;
virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const;
virtual IfcGeom::ConversionResultShape* clone() const {
return new OpenCascadeShape(shape_);
}
virtual bool is_manifold() const;
virtual double bounding_box(void*&) const {
throw std::runtime_error("Not implemented");
}
virtual int num_vertices() const {
throw std::runtime_error("Not implemented");
}
virtual void set_box(void*) {
throw std::runtime_error("Not implemented");
}
virtual int surface_genus() const;
virtual bool is_manifold() const;
virtual int num_vertices() const;
virtual int num_edges() const;
virtual int num_faces() const;
// @todo this must be something with a virtual dtor so that we can delete it.
virtual std::pair<OpaqueCoordinate<3>, OpaqueCoordinate<3>> bounding_box() const;
virtual std::shared_ptr<OpaqueNumber> length();
virtual std::shared_ptr<OpaqueNumber> area();
virtual std::shared_ptr<OpaqueNumber> volume();
virtual OpaqueCoordinate<3> position();
virtual OpaqueCoordinate<3> axis();
virtual OpaqueCoordinate<4> plane_equation();
virtual std::vector<ConversionResultShape*> convex_decomposition();
virtual ConversionResultShape* halfspaces();
virtual ConversionResultShape* solid();
virtual ConversionResultShape* box();
virtual std::vector<ConversionResultShape*> edges();
virtual std::vector<ConversionResultShape*> facets();
virtual ConversionResultShape* add(ConversionResultShape*);
virtual ConversionResultShape* subtract(ConversionResultShape*);
virtual ConversionResultShape* intersect(ConversionResultShape*);
virtual void map(OpaqueCoordinate<4>& from, OpaqueCoordinate<4>& to);
virtual ConversionResultShape* moved(ifcopenshell::geometry::taxonomy::matrix4::ptr) const;
private:
TopoDS_Shape shape_;
};
@@ -247,7 +247,7 @@ bool IfcGeom::OpenCascadeKernel::convert_openings(const IfcUtil::IfcBaseEntity*
for (unsigned int i = 0; i < opening_shapes.size(); ++i) {
TopoDS_Shape opening_shape_solid;
auto opening_shape_i = ((OpenCascadeShape*)opening_shapes[i].Shape())->shape();
auto opening_shape_i = std::static_pointer_cast<OpenCascadeShape>(opening_shapes[i].Shape())->shape();
const TopoDS_Shape& opening_shape_unlocated = util::ensure_fit_for_subtraction(opening_shape_i, opening_shape_solid, conv_settings_.getValue(ConversionSettings::GV_PRECISION));
auto gtrsf = opening_shapes[i].Placement();
@@ -277,7 +277,7 @@ bool IfcGeom::OpenCascadeKernel::convert_openings(const IfcUtil::IfcBaseEntity*
std::list<TopoDS_Shape> parts;
auto it3_shape = ((OpenCascadeShape*)it3->Shape())->shape();
auto it3_shape = std::static_pointer_cast<OpenCascadeShape>(it3->Shape())->shape();
bool is_multiple = it3_shape.ShapeType() == TopAbs_COMPOUND && TopoDS_Iterator(it3_shape).More() && util::is_nested_compound_of_solid(it3_shape);
@@ -769,7 +769,7 @@ bool IfcGeom::util::flatten_shape_list(const IfcGeom::ConversionResults& shapes,
for (IfcGeom::ConversionResults::const_iterator it = shapes.begin(); it != shapes.end(); ++it) {
TopoDS_Shape merged;
const TopoDS_Shape& s = ((ifcopenshell::geometry::OpenCascadeShape*)it->Shape())->shape();
const TopoDS_Shape& s = std::static_pointer_cast<ifcopenshell::geometry::OpenCascadeShape>(it->Shape())->shape();
if (fuse) {
util::ensure_fit_for_subtraction(s, merged, tol);
} else {
@@ -82,7 +82,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result::ptr br, Con
} else {
for (auto& r : cr) {
auto S = ((OpenCascadeShape*)r.Shape())->shape();
auto S = std::static_pointer_cast<OpenCascadeShape>(r.Shape())->shape();
gp_GTrsf trsf;
convert(r.Placement(), trsf);
// @todo it really confuses me why I cannot use Moved() here instead
+4 -4
View File
@@ -248,7 +248,7 @@ bool IfcGeom::util::apply_folded_layerset(const ConversionResults& items, const
for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) {
TopoDS_Shape a, b;
if (split_solid_by_shell(((OpenCascadeShape*)it->Shape())->shape(), shells.First(), a, b, tol)) {
if (split_solid_by_shell(std::static_pointer_cast<OpenCascadeShape>(it->Shape())->shape(), shells.First(), a, b, tol)) {
result.push_back(ConversionResult(it->ItemId(), it->Placement(), new OpenCascadeShape(b), (!!styles[0] ? styles[0] : it->StylePtr())));
result.push_back(ConversionResult(it->ItemId(), it->Placement(), new OpenCascadeShape(a), (!!styles[1] ? styles[1] : it->StylePtr())));
} else {
@@ -262,7 +262,7 @@ bool IfcGeom::util::apply_folded_layerset(const ConversionResults& items, const
for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) {
const TopoDS_Shape& s = ((OpenCascadeShape*)it->Shape())->shape();
const TopoDS_Shape& s = std::static_pointer_cast<OpenCascadeShape>(it->Shape())->shape();
TopoDS_Solid sld;
ensure_fit_for_subtraction(s, sld, tol);
@@ -291,7 +291,7 @@ bool IfcGeom::util::apply_layerset(const ConversionResults& items, const std::ve
for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) {
TopoDS_Shape a, b;
if (split_solid_by_surface(((OpenCascadeShape*)it->Shape())->shape(), surfaces[1], a, b, tol)) {
if (split_solid_by_surface(std::static_pointer_cast<OpenCascadeShape>(it->Shape())->shape(), surfaces[1], a, b, tol)) {
result.push_back(ConversionResult(it->ItemId(), it->Placement(),new OpenCascadeShape(b), (!!styles[0] ? styles[0] : it->StylePtr())));
result.push_back(ConversionResult(it->ItemId(), it->Placement(),new OpenCascadeShape(a), (!!styles[1] ? styles[1] : it->StylePtr())));
} else {
@@ -334,7 +334,7 @@ bool IfcGeom::util::apply_layerset(const ConversionResults& items, const std::ve
for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) {
const TopoDS_Shape& s = ((OpenCascadeShape*)it->Shape())->shape();
const TopoDS_Shape& s = std::static_pointer_cast<OpenCascadeShape>(it->Shape())->shape();
TopoDS_Solid sld;
ensure_fit_for_subtraction(s, sld, tol);