diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 98c59d77b6..baeb3409de 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -805,6 +805,10 @@ int main(int argc, char** argv) { IfcGeom::update_default_style("IfcSpace").transparency = geometry_settings.get().get(); } + if (output_extension == OBJ || output_extension == STP || output_extension == IGS) { + geometry_settings.get().value = true; + } + boost::shared_ptr serializer; /**< @todo use std::unique_ptr when possible */ if (output_extension == OBJ) { // Do not use temp file for MTL as it's such a small file. diff --git a/src/ifcgeom/ConversionResult.cpp b/src/ifcgeom/ConversionResult.cpp index da29dc380e..30bed11214 100644 --- a/src/ifcgeom/ConversionResult.cpp +++ b/src/ifcgeom/ConversionResult.cpp @@ -8,3 +8,13 @@ IfcGeom::Representation::Triangulation * IfcGeom::ConversionResultShape::Triangu Triangulate(settings, iden, t, -1); return t; } + +using namespace ifcopenshell::geometry::taxonomy; + +void IfcGeom::ConversionResult::append(ifcopenshell::geometry::taxonomy::matrix4::ptr trsf) { + placement_ = make(placement_->ccomponents() * trsf->ccomponents()); +} + +void IfcGeom::ConversionResult::prepend(ifcopenshell::geometry::taxonomy::matrix4::ptr trsf) { + placement_ = make(trsf->ccomponents() * placement_->ccomponents()); +} diff --git a/src/ifcgeom/ConversionResult.h b/src/ifcgeom/ConversionResult.h index 333b305ec4..1577eb369d 100644 --- a/src/ifcgeom/ConversionResult.h +++ b/src/ifcgeom/ConversionResult.h @@ -245,14 +245,8 @@ namespace IfcGeom { ConversionResult(int id, ConversionResultShape* shape) : id(id), placement_(ifcopenshell::geometry::taxonomy::make()), shape_(shape) {} - void append(ifcopenshell::geometry::taxonomy::matrix4::ptr trsf) { - // @todo verify order - placement_->components() = placement_->ccomponents() * trsf->ccomponents(); - } - void prepend(ifcopenshell::geometry::taxonomy::matrix4::ptr trsf) { - // @todo verify order - placement_->components() = trsf->ccomponents() * placement_->ccomponents(); - } + void append(ifcopenshell::geometry::taxonomy::matrix4::ptr trsf); + void prepend(ifcopenshell::geometry::taxonomy::matrix4::ptr trsf); std::shared_ptr Shape() const { return shape_; } ifcopenshell::geometry::taxonomy::matrix4::ptr Placement() const { return placement_; } bool hasStyle() const { return !!style_; } diff --git a/src/ifcgeom/Iterator.h b/src/ifcgeom/Iterator.h index b5698a570b..9c31ff8948 100644 --- a/src/ifcgeom/Iterator.h +++ b/src/ifcgeom/Iterator.h @@ -185,9 +185,9 @@ namespace IfcGeom { tasks_.push_back(res); } - std::vector products; - for (auto& r : reps) { - std::copy(r.products->begin(), r.products->end(), std::back_inserter(products)); + size_t num_products = 0; + for (auto& r : tasks_) { + num_products += r.products.size(); } /* @@ -220,7 +220,7 @@ namespace IfcGeom { } */ - Logger::Notice("Created " + boost::lexical_cast(tasks_.size()) + " tasks for " + boost::lexical_cast(products.size()) + " products"); + Logger::Notice("Created " + boost::lexical_cast(tasks_.size()) + " tasks for " + boost::lexical_cast(num_products) + " products"); if (tasks_.size() == 0) { Logger::Warning("No representations encountered, aborting"); diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index f29b935501..357741ba92 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -18,6 +18,12 @@ using ifcopenshell::geometry::NumberEpeck; #define NumberType NumberEpeck #endif +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_); +} + #ifndef IFOPSH_SIMPLE_KERNEL void ifcopenshell::geometry::CgalShape::to_poly() const { if (!shape_) { @@ -259,12 +265,62 @@ std::shared_ptr ifcopenshell::geometry::CgalShape::volume() OpaqueCoordinate<3> ifcopenshell::geometry::CgalShape::position() { - throw std::runtime_error("Invalid shape type"); + to_poly(); + if (shape_->size_of_facets() == 1) { + // return centroid; + // CGAL::Vector_3 p; + std::array p; + for (auto it = shape_->points_begin(); it != shape_->points_end(); ++it) { + for (int i = 0; i < 3; ++i) { + p[i] += it->cartesian(i); + } + } + Kernel_::FT N(std::distance(shape_->points_begin(), shape_->points_end())); + for (int i = 0; i < 3; ++i) { + p[i] /= N; + } + return OpaqueCoordinate<3>( + std::make_shared(p[0]), + std::make_shared(p[1]), + std::make_shared(p[2]) + ); + } else { + throw std::runtime_error("Invalid shape type"); + } +} + +namespace { + struct Plane_equation { + template + 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()); + } + }; } OpaqueCoordinate<3> ifcopenshell::geometry::CgalShape::axis() { - throw std::runtime_error("Invalid shape type"); + to_poly(); + if (shape_->size_of_facets() == 1) { + auto pl = Plane_equation()(*shape_->facets_begin()); + std::array abc{ pl.a(), pl.b(), pl.c() }; + auto minel = std::min_element(abc.begin(), abc.end()); + auto maxel = std::max_element(abc.begin(), abc.end()); + auto maxval = ((-*minel) > *maxel) ? (-*minel) : *maxel; + + return OpaqueCoordinate<3>( + std::make_shared(pl.a() / maxval), + std::make_shared(pl.b() / maxval), + std::make_shared(pl.c() / maxval) + ); + } else { + throw std::runtime_error("Invalid shape type"); + } } OpaqueCoordinate<4> ifcopenshell::geometry::CgalShape::plane_equation() @@ -324,7 +380,24 @@ std::vector ifcopenshell::geometry::CgalShape::edges() std::vector ifcopenshell::geometry::CgalShape::facets() { - throw std::runtime_error("Not implemented"); + to_poly(); + std::vector result; + for (auto &face : faces(*shape_)) { + std::vector ps; + std::vector> ids(1); + + auto it = face->facet_begin(); + do { + ps.push_back(it->vertex()->point()); + ids.front().push_back(ids.front().size()); + } while (++it != face->facet_begin()); + + cgal_shape_t poly; + CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh(ps, ids, poly); + + result.push_back(new CgalShape(poly)); + } + return result; } ConversionResultShape* ifcopenshell::geometry::CgalShape::add(ConversionResultShape* other) @@ -453,10 +526,14 @@ OpaqueCoordinate<3> ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::pos OpaqueCoordinate<3> ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::axis() { if (planes_.size() == 1) { + std::array abc{ planes_.front().a(), planes_.front().b(), planes_.front().c() }; + auto minel = std::min_element(abc.begin(), abc.end()); + auto maxel = std::max_element(abc.begin(), abc.end()); + auto maxval = ((-*minel) > *maxel) ? (-*minel) : *maxel; return OpaqueCoordinate<3>( - std::make_shared(planes_.front().a()), - std::make_shared(planes_.front().b()), - std::make_shared(planes_.front().c()) + std::make_shared(planes_.front().a() / maxval), + std::make_shared(planes_.front().b() / maxval), + std::make_shared(planes_.front().c() / maxval) ); } else { throw std::runtime_error("Invalid shape type"); @@ -466,11 +543,15 @@ OpaqueCoordinate<3> ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::axi OpaqueCoordinate<4> ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::plane_equation() { if (planes_.size() == 1) { + std::array abc{ planes_.front().a(), planes_.front().b(), planes_.front().c() }; + auto minel = std::min_element(abc.begin(), abc.end()); + auto maxel = std::max_element(abc.begin(), abc.end()); + auto maxval = ((-*minel) > *maxel) ? (-*minel) : *maxel; return OpaqueCoordinate<4>( - std::make_shared(planes_.front().a()), - std::make_shared(planes_.front().b()), - std::make_shared(planes_.front().c()), - std::make_shared(planes_.front().d()) + std::make_shared(planes_.front().a() / maxval), + std::make_shared(planes_.front().b() / maxval), + std::make_shared(planes_.front().c() / maxval), + std::make_shared(planes_.front().d() / maxval) ); } else { throw std::runtime_error("Invalid shape type"); diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.h b/src/ifcgeom/kernels/cgal/CgalConversionResult.h index b0e3da28c0..0811b1968d 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.h +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.h @@ -171,9 +171,7 @@ namespace ifcopenshell { namespace geometry { mutable boost::optional> nef_; #endif public: - CgalShape(const cgal_shape_t& shape) { - shape_ = shape; - } + CgalShape(const cgal_shape_t& shape); #ifndef IFOPSH_SIMPLE_KERNEL CgalShape(const CGAL::Nef_polyhedron_3& shape) { diff --git a/src/ifcwrap/IfcGeomWrapper.i b/src/ifcwrap/IfcGeomWrapper.i index 4d3808fec8..099615fa18 100644 --- a/src/ifcwrap/IfcGeomWrapper.i +++ b/src/ifcwrap/IfcGeomWrapper.i @@ -631,6 +631,17 @@ struct ShapeRTTI : public boost::static_visitor %template(OpaqueCoordinate_3) IfcGeom::OpaqueCoordinate<3>; %template(OpaqueCoordinate_4) IfcGeom::OpaqueCoordinate<4>; +%{ + #include "../ifcgeom/kernels/cgal/CgalConversionResult.h" +%} + +%inline %{ + std::shared_ptr create_epeck(int i) { + return std::make_shared(i); + } +%} + + %naturalvar svgfill::polygon_2::boundary; %naturalvar svgfill::polygon_2::inner_boundaries; %naturalvar svgfill::polygon_2::point_inside;