diff --git a/src/ifcconvert/validate_space_boundaries.cpp b/src/ifcconvert/validate_space_boundaries.cpp index 94ea7bbb6a..0f660e5901 100644 --- a/src/ifcconvert/validate_space_boundaries.cpp +++ b/src/ifcconvert/validate_space_boundaries.cpp @@ -72,7 +72,7 @@ void fix_spaceboundaries(IfcParse::IfcFile& f, bool no_progress, bool quiet, boo for (auto& e : wire->children) { auto edge = (taxonomy::edge*) e; auto p3 = boost::get(edge->start); - auto p4 = ((taxonomy::geom_item*)item)->matrix.components * p3.components.homogeneous(); + auto p4 = *((taxonomy::geom_item*)item)->matrix.components * p3.components->homogeneous(); Kernel_::Point_3 P(p4(0), p4(1), p4(2)); elem_to_space_boundary_coords[{g1, g2}].emplace_back(P); } diff --git a/src/ifcconvert/validate_storey_containment.cpp b/src/ifcconvert/validate_storey_containment.cpp index 64596f68cf..c003291230 100644 --- a/src/ifcconvert/validate_storey_containment.cpp +++ b/src/ifcconvert/validate_storey_containment.cpp @@ -132,8 +132,8 @@ void fix_storeycontainment(IfcParse::IfcFile& f, bool no_progress, bool quiet, b for (auto& g : geom_object->geometry()) { auto s = ((ifcopenshell::geometry::CgalShape*) g.Shape())->shape(); - const auto& m = g.Placement().components; - const auto& n = geom_object->transformation().data().components; + const auto& m = *g.Placement().components; + const auto& n = *geom_object->transformation().data().components; const cgal_placement_t trsf( m(0, 0), m(0, 1), m(0, 2), m(0, 3), diff --git a/src/ifcconvert/validate_wall_connectivity.cpp b/src/ifcconvert/validate_wall_connectivity.cpp index a80360c266..28de1f22e3 100644 --- a/src/ifcconvert/validate_wall_connectivity.cpp +++ b/src/ifcconvert/validate_wall_connectivity.cpp @@ -123,8 +123,8 @@ void fix_wallconnectivity(IfcParse::IfcFile& f, bool no_progress, bool quiet, bo auto p0 = boost::get(first_vertex); auto p1 = boost::get(last_vertex); - auto v0 = ((taxonomy::geom_item*)item)->matrix.components * p0.components.homogeneous(); - auto v1 = ((taxonomy::geom_item*)item)->matrix.components * p1.components.homogeneous(); + auto v0 = *((taxonomy::geom_item*)item)->matrix.components * p0.components->homogeneous(); + auto v1 = *((taxonomy::geom_item*)item)->matrix.components * p1.components->homogeneous(); auto P0 = Kernel_::Point_3(v0(0), v0(1), v0(2)); auto P1 = Kernel_::Point_3(v1(0), v1(1), v1(2)); diff --git a/src/ifcconvert/validation_utils.h b/src/ifcconvert/validation_utils.h index bc33063eb2..ecf4a876a4 100644 --- a/src/ifcconvert/validation_utils.h +++ b/src/ifcconvert/validation_utils.h @@ -475,8 +475,8 @@ struct intersection_validator { for (auto& g : geom_object->geometry()) { auto s = ((ifcopenshell::geometry::CgalShape*) g.Shape())->shape(); - const auto& m = g.Placement().components; - const auto& n = geom_object->transformation().data().components; + const auto& m = *g.Placement().components; + const auto& n = *geom_object->transformation().data().components; const cgal_placement_t trsf( m(0, 0), m(0, 1), m(0, 2), m(0, 3), diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index 5bbfb2537c..f0217c9c0e 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -7,8 +7,8 @@ void ifcopenshell::geometry::CgalShape::Triangulate(const settings& settings, co // Copy is made because triangulate_faces() does not accept a const argument cgal_shape_t s = shape_; - if (!place.components.isIdentity()) { - const auto& m = place.components; + if (!place.components->isIdentity()) { + const auto& m = *place.components; // @todo check const cgal_placement_t trsf( diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.cpp b/src/ifcgeom/kernels/cgal/CgalKernel.cpp index 391f1b26ea..972476b3e4 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.cpp +++ b/src/ifcgeom/kernels/cgal/CgalKernel.cpp @@ -183,17 +183,18 @@ bool CgalKernel::convert(const taxonomy::face* face, cgal_face_t& result) { } namespace { + // @todo obsolete? bool convert_curve(CgalKernel* kernel, const taxonomy::item* curve, cgal_wire_t& builder) { if (curve->kind() == taxonomy::EDGE) { auto e = (taxonomy::edge*) curve; if (true || e->basis == nullptr) { if (builder.empty()) { const auto& p = boost::get(e->start); - cgal_point_t pnt(p.components(0), p.components(1), p.components(2)); + cgal_point_t pnt((*p.components)(0), (*p.components)(1), (*p.components)(2)); builder.push_back(pnt); } const auto& p = boost::get(e->end); - cgal_point_t pnt(p.components(0), p.components(1), p.components(2)); + cgal_point_t pnt((*p.components)(0), (*p.components)(1), (*p.components)(2)); builder.push_back(pnt); } else if (e->basis->kind() == taxonomy::CIRCLE) { // @todo @@ -308,7 +309,7 @@ bool CgalKernel::convert(const taxonomy::extrusion* extrusion, cgal_shape_t &sha } // std::cout << "Face vertices: " << face.outer.size() << std::endl; - auto fs = extrusion->direction.components; + auto fs = *extrusion->direction.components; cgal_direction_t dir(fs(0), fs(1), fs(2)); // std::cout << "Direction: " << dir << std::endl; @@ -584,7 +585,7 @@ bool CgalKernel::preprocess_boolean_operand(const IfcUtil::IfcBaseClass* log_ref namespace { bool convert_placement(const ifcopenshell::geometry::taxonomy::matrix4& place, cgal_placement_t& trsf) { - const auto& m = place.components; + const auto& m = *place.components; // @todo check trsf = cgal_placement_t( @@ -623,7 +624,7 @@ bool CgalKernel::convert_impl(const taxonomy::boolean_result* br, ifcopenshell:: for (auto it = cr.begin(); it != cr.end(); ++it) { const cgal_shape_t& entity_shape_unlocated(((CgalShape*)it->Shape())->shape()); cgal_shape_t entity_shape(entity_shape_unlocated); - if (!it->Placement().components.isIdentity()) { + if (!it->Placement().components->isIdentity()) { cgal_placement_t trsf; convert_placement(it->Placement(), trsf); for (auto &vertex : vertices(entity_shape)) { diff --git a/src/ifcgeom/kernels/opencascade/IfcGeomShapes.cpp b/src/ifcgeom/kernels/opencascade/IfcGeomShapes.cpp index f8a69b0d29..f8ab8d2e41 100644 --- a/src/ifcgeom/kernels/opencascade/IfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/opencascade/IfcGeomShapes.cpp @@ -134,8 +134,8 @@ bool OpenCascadeKernel::convert(const taxonomy::extrusion* extrusion, TopoDS_Sha auto trsf = gtrsf.Trsf(); */ - auto fs = extrusion->direction.components.data(); - gp_Dir dir(fs[0], fs[1], fs[2]); + const auto& fs = *extrusion->direction.components; + gp_Dir dir(fs(0), fs(1), fs(2)); shape.Nullify(); @@ -559,17 +559,17 @@ namespace { } curve_creation_visitor_result_type operator()(const taxonomy::line& l) { - const auto& m = l.matrix.components; + const auto& m = *l.matrix.components; return result = Handle(Geom_Curve)(new Geom_Line(convert_xyz2(m.col(3)), convert_xyz2(m.col(0)))); } curve_creation_visitor_result_type operator()(const taxonomy::circle& c) { - const auto& m = c.matrix.components; + const auto& m = *c.matrix.components; return result = Handle(Geom_Curve)(new Geom_Circle(gp_Ax2(convert_xyz2(m.col(3)), convert_xyz2(m.col(2)), convert_xyz2(m.col(0))), c.radius)); } curve_creation_visitor_result_type operator()(const taxonomy::ellipse& e) { - const auto& m = e.matrix.components; + const auto& m = *e.matrix.components; return result = Handle(Geom_Curve)(new Geom_Ellipse(gp_Ax2(convert_xyz2(m.col(3)), convert_xyz2(m.col(2)), convert_xyz2(m.col(0))), e.radius, e.radius2)); } @@ -2251,7 +2251,7 @@ bool OpenCascadeKernel::flatten_shape_list(const ifcopenshell::geometry::Convers } TopoDS_Shape OpenCascadeKernel::apply_transformation(const TopoDS_Shape& s, const taxonomy::matrix4& t) { - if (t.components.isIdentity()) { + if (t.components->isIdentity()) { return s; } else { gp_GTrsf trsf; @@ -2294,7 +2294,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::face* face, ifcopenshell::g } // @todo boundary - const auto& m = ((taxonomy::geom_item*)face->basis)->matrix.components; + const auto& m = *((taxonomy::geom_item*)face->basis)->matrix.components; gp_Pln pln(convert_xyz2(m.col(3)), convert_xyz2(m.col(2))); const gp_Pnt pnt = pln.Location().Translated(face->orientation.get_value_or(false) ? -pln.Axis().Direction() : pln.Axis().Direction()); TopoDS_Shape shape = BRepPrimAPI_MakeHalfSpace(BRepBuilderAPI_MakeFace(pln), pnt).Solid(); diff --git a/src/ifcgeom/schema/mapping.cpp b/src/ifcgeom/schema/mapping.cpp index 715741d00c..3c038fb791 100644 --- a/src/ifcgeom/schema/mapping.cpp +++ b/src/ifcgeom/schema/mapping.cpp @@ -343,14 +343,14 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcProduct* inst) { c->matrix = as(map(inst->ObjectPlacement())); if (openings->size() && !settings_.get(settings::DISABLE_OPENING_SUBTRACTIONS) && use_body) { - auto ci = c->matrix.components.inverse(); + auto ci = c->matrix.components->inverse(); IfcEntityList::ptr operands(new IfcEntityList); operands->push(body); operands->push(openings); auto n = map_to_collection(this, operands); std::for_each(n->children.begin() + 1, n->children.end(), [&ci](taxonomy::item* i) { - ((taxonomy::geom_item*)i)->matrix.components = ci * ((taxonomy::geom_item*)i)->matrix.components; + *((taxonomy::geom_item*)i)->matrix.components = ci * *((taxonomy::geom_item*)i)->matrix.components; }); n->operation = taxonomy::boolean_result::SUBTRACTION; // @todo one indirection too many @@ -372,7 +372,7 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcAxis2Placement3D* inst) { Eigen::Vector3d o, axis(0, 0, 1), refDirection, X(1, 0, 0); { taxonomy::point3 v = as(map(inst->Location())); - o = v.components; + o = *v.components; } const bool hasAxis = inst->hasAxis(); const bool hasRef = inst->hasRefDirection(); @@ -383,12 +383,12 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcAxis2Placement3D* inst) { if (hasAxis) { taxonomy::direction3 v = as(map(inst->Axis())); - axis = v.components; + axis = *v.components; } if (hasRef) { taxonomy::direction3 v = as(map(inst->RefDirection())); - refDirection = v.components; + refDirection = *v.components; } else { if (acos(axis.dot(X)) > 1.e-5) { refDirection = { 1., 0., 0. }; @@ -406,12 +406,12 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcAxis2Placement2D* inst) { Eigen::Vector3d P, axis(0, 0, 1), V(1, 0, 0); { taxonomy::point3 v = as(map(inst->Location())); - P = v.components; + P = *v.components; } const bool hasRef = inst->hasRefDirection(); if (hasRef) { taxonomy::direction3 v = as(map(inst->RefDirection())); - V = v.components; + V = *v.components; } return new taxonomy::matrix4(P, axis, V); } @@ -444,7 +444,7 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcLocalPlacement* inst) { if (relplacement->declaration().is(IfcSchema::IfcAxis2Placement3D::Class())) { taxonomy::matrix4 trsf2 = as(map(relplacement)); // @todo check - m4->components = trsf2.components * m4->components; + *m4->components = *trsf2.components * *m4->components; } if (current->hasPlacementRelTo()) { IfcSchema::IfcObjectPlacement* parent = current->PlacementRelTo(); @@ -489,14 +489,14 @@ IfcSchema::IfcProduct::list::ptr mapping::products_represented_by(const IfcSchem if (maps->size() == 1) { IfcSchema::IfcRepresentationMap* rmap = *maps->begin(); taxonomy::matrix4 origin = as(map(rmap->MappingOrigin())); - if (origin.components.isIdentity()) { + if (origin.components->isIdentity()) { IfcSchema::IfcMappedItem::list::ptr items = rmap->MapUsage(); for (IfcSchema::IfcMappedItem::list::it it = items->begin(); it != items->end(); ++it) { IfcSchema::IfcMappedItem* item = *it; if (item->StyledByItem()->size() != 0) continue; taxonomy::matrix4 target = as(map(item->MappingTarget())); - if (target.components.isIdentity()) { + if (target.components->isIdentity()) { continue; } @@ -770,10 +770,10 @@ IfcSchema::IfcRepresentation* mapping::representation_mapped_to(const IfcSchema: if (item->StyledByItem()->size() == 0) { IfcSchema::IfcMappedItem* mapped_item = item->as(); taxonomy::matrix4 target = as(map(mapped_item->MappingTarget())); - if (target.components.isIdentity()) { + if (target.components->isIdentity()) { IfcSchema::IfcRepresentationMap* rmap = mapped_item->MappingSource(); taxonomy::matrix4 origin = as(map(rmap->MappingOrigin())); - if (origin.components.isIdentity()) { + if (origin.components->isIdentity()) { representation_mapped_to = rmap->MappedRepresentation(); } } @@ -927,7 +927,7 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcStyledItem* inst) { double rgb[3]; if (process_colour(shading->SurfaceColour(), rgb)) { surface_style->diffuse.emplace(); - (*surface_style->diffuse).components << rgb[0], rgb[1], rgb[2]; + (*(*surface_style->diffuse).components) << rgb[0], rgb[1], rgb[2]; } if (auto rendering_style = shading->as()) { @@ -1194,7 +1194,7 @@ namespace { #endif if (has_position) { taxonomy::matrix4 m = as(self->map(inst->Position())); - m4 = m.components; + m4 = *m.components; } // @todo precision @@ -1228,10 +1228,10 @@ namespace { const auto& p = pps[i]; if (p.radius && *p.radius > 0.) { // Position is a IfcAxis2Placement2D, so should remain 2d points - auto p0 = boost::get(p.previous->start).components.head<2>(); - auto p1a = boost::get(p.previous->end).components.head<2>(); - auto p2 = boost::get(p.next->end).components.head<2>(); - auto p1b = boost::get(p.next->start).components.head<2>(); + auto p0 = boost::get(p.previous->start).components->head<2>(); + auto p1a = boost::get(p.previous->end).components->head<2>(); + auto p2 = boost::get(p.next->end).components->head<2>(); + auto p1b = boost::get(p.next->start).components->head<2>(); auto ba_ = p0 - p1a; auto bc_ = p2 - p1b; @@ -1242,8 +1242,8 @@ namespace { const double angle = std::acos(ba.dot(bc)); const double inset = *p.radius / std::tan(angle / 2.); - boost::get(p.previous->end).components.head<2>() += ba * inset; - boost::get(p.next->start).components.head<2>() += bc * inset; + boost::get(p.previous->end).components->head<2>() += ba * inset; + boost::get(p.next->start).components->head<2>() += bc * inset; auto e = new taxonomy::edge; e->start = p.previous->end; @@ -1253,10 +1253,10 @@ namespace { double sign = ab.head<2>().dot(bc) > 0 ? 1. : -1.; - auto O = boost::get(p.previous->end).components.head<3>() + ab * *p.radius * sign; + auto O = boost::get(p.previous->end).components->head<3>() + ab * *p.radius * sign; auto c = new taxonomy::circle; - c->matrix.components = Eigen::Affine3d(Eigen::Translation3d(O)).matrix(); + *c->matrix.components = Eigen::Affine3d(Eigen::Translation3d(O)).matrix(); c->radius = *p.radius; e->basis = c; c->orientation = sign == -1.; @@ -1364,7 +1364,7 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcCircleProfileDef* inst) { #endif if (has_position) { taxonomy::matrix4 m = as(map(inst->Position())); - c->matrix = m.components; + c->matrix = *m.components; } auto e = new taxonomy::edge; @@ -1465,7 +1465,7 @@ namespace { for (int i = 1; i <= n; ++i) { // wrap around to the first point in case of a closed loop int j = (i % polygon.size()) + 1; - double dist = (polygon.at(i - 1).components - polygon.at(j - 1).components).squaredNorm(); + double dist = (*polygon.at(i - 1).components - *polygon.at(j - 1).components).squaredNorm(); if (dist < tol) { // do not remove the first or last point to // maintain connectivity with other wires @@ -1494,7 +1494,7 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcPolyline* inst) { }); const double eps = precision_ * 10; - const bool closed_by_proximity = polygon.size() >= 3 && (polygon.front().components - polygon.back().components).norm() < eps; + const bool closed_by_proximity = polygon.size() >= 3 && (*polygon.front().components - *polygon.back().components).norm() < eps; // @todo this removes the end point, since it's identical to the beginning. if (closed_by_proximity) { @@ -1517,18 +1517,26 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcMappedItem* inst) { IfcSchema::IfcRepresentationMap* rmap = inst->MappingSource(); IfcSchema::IfcAxis2Placement* placement = rmap->MappingOrigin(); taxonomy::matrix4 trsf2 = as(map(placement)); - gtrsf.components = gtrsf.components * trsf2.components; + *gtrsf.components = *gtrsf.components * *trsf2.components; // @todo immutable for caching? // @todo allow for multiple levels of matrix? auto shapes = map(rmap->MappedRepresentation()); - for (auto& c : ((taxonomy::collection*)shapes)->children) { - auto item = ((taxonomy::geom_item*)c); - item->matrix.components = gtrsf.components * item->matrix.components; - // @todo previously style was also copied. + if (shapes == nullptr) { + return shapes; } - return shapes; + auto collection = new taxonomy::collection; + collection->children.push_back(shapes); + collection->matrix = *gtrsf.components; + + if (shapes != nullptr) { + for (auto& c : ((taxonomy::collection*)shapes)->children) { + // @todo previously style was also copied. + } + } + + return collection; } taxonomy::item* mapping::map_impl(const IfcSchema::IfcCompositeCurve* inst) { @@ -1596,7 +1604,7 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcTrimmedCurve* inst) { trim_cartesian &= has_pnts[0] && has_pnts[1]; if (trim_cartesian) { - if ((pnts[0].components - pnts[1].components).norm() < (2 * precision_)) { + if ((*pnts[0].components - *pnts[1].components).norm() < (2 * precision_)) { Logger::Message(Logger::LOG_WARNING, "Skipping segment with length below tolerance level:", inst); return nullptr; } diff --git a/src/ifcgeom/schema_agnostic/ConversionResult.h b/src/ifcgeom/schema_agnostic/ConversionResult.h index 0ccae1ccf0..d82cdd952b 100644 --- a/src/ifcgeom/schema_agnostic/ConversionResult.h +++ b/src/ifcgeom/schema_agnostic/ConversionResult.h @@ -75,11 +75,11 @@ namespace ifcopenshell { namespace geometry { : id(id), shape(shape->clone()) {} void append(const ifcopenshell::geometry::taxonomy::matrix4& trsf) { // @todo verify order - placement.components = placement.components * trsf.components; + *placement.components = *placement.components * *trsf.components; } void prepend(const ifcopenshell::geometry::taxonomy::matrix4& trsf) { // @todo verify order - placement.components = trsf.components * placement.components; + *placement.components = *trsf.components * *placement.components; } const ConversionResultShape* Shape() const { return shape; } const ifcopenshell::geometry::taxonomy::matrix4& Placement() const { return placement; } diff --git a/src/ifcgeom/schema_agnostic/IfcGeomElement.h b/src/ifcgeom/schema_agnostic/IfcGeomElement.h index a21db0ede1..3c1229844e 100644 --- a/src/ifcgeom/schema_agnostic/IfcGeomElement.h +++ b/src/ifcgeom/schema_agnostic/IfcGeomElement.h @@ -49,14 +49,12 @@ namespace ifcopenshell { namespace geometry { // internally in IfcOpenShell everything is measured in meters. if (settings.get(settings::CONVERT_BACK_UNITS)) { for (int i = 0; i <= 2; ++i) { - matrix_.components(3, i) /= settings.unit_magnitude(); + (*matrix_.components)(3, i) /= settings.unit_magnitude(); } } } const ifcopenshell::geometry::taxonomy::matrix4& data() const { return matrix_; } const element_settings& settings() const { return settings_; } - - EIGEN_MAKE_ALIGNED_OPERATOR_NEW }; class Element { @@ -136,8 +134,6 @@ namespace ifcopenshell { namespace geometry { } virtual ~Element() {} - - EIGEN_MAKE_ALIGNED_OPERATOR_NEW }; class NativeElement : public Element { diff --git a/src/ifcgeom/taxonomy.h b/src/ifcgeom/taxonomy.h index bb9613c2b0..22d4738cb2 100644 --- a/src/ifcgeom/taxonomy.h +++ b/src/ifcgeom/taxonomy.h @@ -31,50 +31,90 @@ struct item { const IfcUtil::IfcBaseClass* instance; virtual item* clone() const = 0; virtual kinds kind() const = 0; + virtual void print(std::ostream&, int indent=0) const = 0; virtual void reverse() { throw taxonomy::topology_error(); } item(const IfcUtil::IfcBaseClass* instance = nullptr) : instance(instance) {} - - EIGEN_MAKE_ALIGNED_OPERATOR_NEW }; -struct matrix4 : public item { +template +struct eigen_base { + T* components; + + eigen_base() { + components = new T; + } + + eigen_base(const eigen_base& other) { + this->components = new T(*other.components); + } + + eigen_base(const T& other) { + this->components = new T(other); + } + + eigen_base& operator=(const eigen_base& other) { + if (this != &other) { + this->components = new T(*other.components); + } + return *this; + } + + void print_impl(std::ostream& o, const std::string& class_name, int indent = 0) const { + o << std::string(indent, ' ') << class_name; + for (size_t i = 0; i < 16; ++i) { + o << " " << (*components)(i); + } + o << std::endl; + } + + ~eigen_base() { + delete this->components; + } +}; + +struct matrix4 : public item, public eigen_base { enum tag_t { IDENTITY, AFFINE_WO_SCALE, AFFINE_W_UNIFORM_SCALE, AFFINE_W_NONUNIFORM_SCALE, OTHER }; tag_t tag; - - Eigen::Matrix4d components; - matrix4() : components(Eigen::Matrix4d::Identity()), tag(IDENTITY) {} - matrix4(const Eigen::Matrix4d& c) : components(c), tag(OTHER) {} + matrix4() : eigen_base(Eigen::Matrix4d::Identity()), tag(IDENTITY) {} + matrix4(const Eigen::Matrix4d& c) : eigen_base(c), tag(OTHER) {} matrix4(const Eigen::Vector3d& o, const Eigen::Vector3d& z, const Eigen::Vector3d& x) : tag(AFFINE_WO_SCALE) { auto X = x.normalized(); auto Y = z.cross(x).normalized(); auto Z = z.normalized(); - components << + components = new Eigen::Matrix4d; + (*components) << X(0), Y(0), Z(0), o(0), X(1), Y(1), Z(1), o(1), X(2), Y(2), Z(2), o(2), 0, 0, 0, 1.; } + void print(std::ostream& o, int indent = 0) const { + print_impl(o, "matrix4", indent); + } + virtual item* clone() const { return new matrix4(*this); } virtual kinds kind() const { return MATRIX4; } }; -struct colour : public item { - Eigen::Vector3d components; +struct colour : public item, public eigen_base { + void print(std::ostream& o, int indent = 0) const { + print_impl(o, "colour", indent); + } virtual item* clone() const { return new colour(*this); } virtual kinds kind() const { return COLOUR; } - colour() : components(Eigen::Vector3d::Zero()) {} - colour(double r, double g, double b) { components << r, g, b; } + colour() : eigen_base(Eigen::Vector3d::Zero()) {} + colour(double r, double g, double b) { (*components) << r, g, b; } - const double& r() const { return components[0]; } - const double& g() const { return components[1]; } - const double& b() const { return components[2]; } + const double& r() const { return (*components)[0]; } + const double& g() const { return (*components)[1]; } + const double& b() const { return (*components)[2]; } }; struct style : public item { @@ -84,6 +124,22 @@ struct style : public item { boost::optional specular; boost::optional specularity, transparency; + void print(std::ostream& o, int indent = 0) const { + o << std::string(indent, ' ') << "style" << std::endl; + if (name) { + o << std::string(indent, ' ') << " " << "name" << (*name) << std::endl; + } + if (diffuse) { + o << std::string(indent, ' ') << " " << "diffuse" << (*name) << std::endl; + diffuse->print(o, indent + 5 + 7); + } + if (diffuse) { + o << std::string(indent, ' ') << " " << "specular" << (*name) << std::endl; + diffuse->print(o, indent + 5 + 8); + } + // @todo + } + virtual item* clone() const { return new style(*this); } virtual kinds kind() const { return STYLE; } @@ -105,17 +161,19 @@ struct geom_item : public item { }; template -struct cartesian_base : public geom_item { - Eigen::Vector3d components; - - cartesian_base() : components(Eigen::Vector3d::Zero()) {} - cartesian_base(double x, double y, double z = 0.) { components << x, y, z; } +struct cartesian_base : public geom_item, public eigen_base { + cartesian_base() : eigen_base(Eigen::Vector3d::Zero()) {} + cartesian_base(double x, double y, double z = 0.) : eigen_base(Eigen::Vector3d(x, y, z)) {} }; struct point3 : public cartesian_base<3> { virtual item* clone() const { return new point3(*this); } virtual kinds kind() const { return POINT3; } + void print(std::ostream& o, int indent = 0) const { + print_impl(o, "point3", indent); + } + point3(double x = 0., double y = 0., double z = 0.) : cartesian_base(x, y, z) {} }; @@ -123,6 +181,10 @@ struct direction3 : public cartesian_base<3> { virtual item* clone() const { return new direction3(*this); } virtual kinds kind() const { return DIRECTION3; } + void print(std::ostream& o, int indent = 0) const { + print_impl(o, "direction3", indent); + } + direction3(double x = 0., double y = 0., double z = 0.) : cartesian_base(x, y, z) {} }; @@ -131,6 +193,10 @@ struct curve : public geom_item {}; struct line : public curve { virtual item* clone() const { return new line(*this); } virtual kinds kind() const { return LINE; } + + void print(std::ostream& o, int indent = 0) const { + o << "not implemented"; + } }; struct circle : public curve { @@ -138,6 +204,10 @@ struct circle : public curve { virtual item* clone() const { return new circle(*this); } virtual kinds kind() const { return CIRCLE; } + + void print(std::ostream& o, int indent = 0) const { + o << "not implemented"; + } }; struct ellipse : public circle { @@ -145,11 +215,19 @@ struct ellipse : public circle { virtual item* clone() const { return new ellipse(*this); } virtual kinds kind() const { return ELLIPSE; } + + void print(std::ostream& o, int indent = 0) const { + o << "not implemented"; + } }; struct bspline_curve : public curve { virtual item* clone() const { return new bspline_curve(*this); } virtual kinds kind() const { return BSPLINE_CURVE; } + + void print(std::ostream& o, int indent = 0) const { + o << "not implemented"; + } }; struct trimmed_curve : public curve { @@ -167,6 +245,13 @@ struct trimmed_curve : public curve { // std::swap(start, end); orientation = !orientation; } + + void print(std::ostream& o, int indent = 0) const { + o << std::string(indent, ' ') << "trimmed_curve" << std::endl; + if (basis) { + basis->print(o, indent + 4); + } + } }; struct edge : public trimmed_curve { @@ -199,6 +284,13 @@ struct collection : public geom_item { child->reverse(); } } + + void print(std::ostream& o, int indent = 0) const { + o << std::string(indent, ' ') << "collection" << std::endl; + for (auto& c : children) { + c->print(o, indent + 4); + } + } }; struct shell : public collection { @@ -213,6 +305,10 @@ struct surface : public geom_item {}; struct plane : public surface { virtual item* clone() const { return new plane(*this); } virtual kinds kind() const { return PLANE; } + + void print(std::ostream& o, int indent = 0) const { + o << "not implemented"; + } }; struct face : public collection { @@ -244,6 +340,12 @@ struct extrusion : public sweep { virtual kinds kind() const { return EXTRUSION; } extrusion(matrix4 m, face basis, direction3 dir, double d) : sweep(m, basis), direction(dir), depth(d) {} + + void print(std::ostream& o, int indent = 0) const { + o << std::string(indent, ' ') << "extrusion " << depth << std::endl; + direction.print(o, indent + 4); + basis.print(o, indent + 4); + } }; struct node : public collection { diff --git a/src/serializers/ColladaSerializer.cpp b/src/serializers/ColladaSerializer.cpp index 4267ed7f3b..19df0e2959 100644 --- a/src/serializers/ColladaSerializer.cpp +++ b/src/serializers/ColladaSerializer.cpp @@ -197,14 +197,14 @@ void ColladaSerializer::ColladaExporter::ColladaScene::add( // If this is not the first parent, get the relative placement if (parentNodes.size() > 0) { - auto m4 = ifcopenshell::geometry::taxonomy::matrix4(matrixStack.top().data().components * transformation.data().components); + auto m4 = ifcopenshell::geometry::taxonomy::matrix4(*matrixStack.top().data().components * *transformation.data().components); relative_trsf = new ifcopenshell::geometry::Transformation(transformation.settings(), m4); transformation_towrite = relative_trsf; } // @todo verify - const double* m = transformation_towrite->data().components.data(); + const double* m = transformation_towrite->data().components->data(); double matrix_array[4][4] = { { m[0], m[4], m[8], m[12] }, @@ -251,14 +251,14 @@ void ColladaSerializer::ColladaExporter::ColladaScene::addParent(const ifcopensh // If this is not the first parent, get the relative placement if (parentNodes.size() > 0) { - auto m4 = ifcopenshell::geometry::taxonomy::matrix4(matrixStack.top().data().components * parent_trsf.data().components); + auto m4 = ifcopenshell::geometry::taxonomy::matrix4(*matrixStack.top().data().components * *parent_trsf.data().components); relative_trsf = new ifcopenshell::geometry::Transformation(parent_trsf.settings(), m4); transformation_towrite = relative_trsf; } // @todo verify - const double* parentMatrix = transformation_towrite->data().components.data(); + const double* parentMatrix = transformation_towrite->data().components->data(); double matrix_array[4][4] = { { (double)parentMatrix[0], (double)parentMatrix[3], (double)parentMatrix[6], (double)parentMatrix[9] }, @@ -280,7 +280,7 @@ void ColladaSerializer::ColladaExporter::ColladaScene::addParent(const ifcopensh current_node->addMatrix(matrix_array); // Add the node to the parent stack - matrixStack.push(ifcopenshell::geometry::Transformation(parent_trsf.settings(), ifcopenshell::geometry::taxonomy::matrix4(parent_trsf.data().components.inverse()))); + matrixStack.push(ifcopenshell::geometry::Transformation(parent_trsf.settings(), ifcopenshell::geometry::taxonomy::matrix4(parent_trsf.data().components->inverse()))); parentNodes.push(current_node); serializer->parentStackId.push(parent.id()); } @@ -320,11 +320,11 @@ void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::write COLLADASW::EffectProfile effect(mSW); effect.setShaderType(COLLADASW::EffectProfile::LAMBERT); if (material.diffuse) { - auto diffuse = material.diffuse.get().components; + const auto& diffuse = *material.diffuse.get().components; effect.setDiffuse(COLLADASW::ColorOrTexture(COLLADASW::Color(diffuse[0],diffuse[1],diffuse[2]))); } if (material.specular) { - auto specular = material.specular.get().components; + const auto& specular = *material.specular.get().components; effect.setSpecular(COLLADASW::ColorOrTexture(COLLADASW::Color(specular[0],specular[1],specular[2]))); } if (material.specularity) { @@ -348,9 +348,11 @@ void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::close void ColladaSerializer::ColladaExporter::ColladaMaterials::add(const ifcopenshell::geometry::taxonomy::style& material) { if (!contains(material)) { - // @todo original_name - std::string material_name = *(serializer->settings().get(SerializerSettings::USE_MATERIAL_NAMES) - ? material.name : material.name); + // @todo original_name? + + // @todo apparently material.name is unitialized in some cases now. + + std::string material_name = material.name.get_value_or("missing-material"); if (material_name.empty()) { material_name = "missing-material-" + *material.name; diff --git a/src/serializers/GltfSerializer.cpp b/src/serializers/GltfSerializer.cpp index 9f80d5b4f1..77454d82b4 100644 --- a/src/serializers/GltfSerializer.cpp +++ b/src/serializers/GltfSerializer.cpp @@ -94,7 +94,7 @@ int GltfSerializer::writeMaterial(const ifcopenshell::geometry::taxonomy::style& base.fill(1.0); if (style.diffuse) { for (int i = 0; i < 3; ++i) { - base[i] = style.diffuse->components[i]; + base[i] = (*style.diffuse->components)[i]; } } if (style.transparency) { @@ -167,7 +167,7 @@ void GltfSerializer::write(const ifcopenshell::geometry::TriangulationElement* o node_array_.push_back(json_["nodes"].size()); - const double* m = o->transformation().data().components.data(); + const double* m = o->transformation().data().components->data(); // nb: note that this applies the Y-UP transform. const std::array matrix_flat = { diff --git a/src/serializers/SvgSerializer.cpp b/src/serializers/SvgSerializer.cpp index 85cda03eda..40fd128216 100644 --- a/src/serializers/SvgSerializer.cpp +++ b/src/serializers/SvgSerializer.cpp @@ -490,7 +490,7 @@ void SvgSerializer::setFile(IfcParse::IfcFile* f) { auto item = mapping_->map(*product->get("ObjectPlacement")); if (item) { auto matrix = (ifcopenshell::geometry::taxonomy::matrix4*) item; - const double& Z = matrix->components(3, 2); + const double& Z = (*matrix->components)(3, 2); setSectionHeight(Z + 1.); Logger::Warning("No building storeys encountered, used for reference:", product); return; diff --git a/src/serializers/schema_dependent/XmlSerializer.cpp b/src/serializers/schema_dependent/XmlSerializer.cpp index ddc174b027..2b388b6c68 100644 --- a/src/serializers/schema_dependent/XmlSerializer.cpp +++ b/src/serializers/schema_dependent/XmlSerializer.cpp @@ -131,7 +131,7 @@ boost::optional format_attribute(ifcopenshell::geometry::abstract_m std::stringstream stream; for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { - const double trsf_value = matrix->components(j, i); + const double trsf_value = (*matrix->components)(j, i); stream << trsf_value; if (i < 3 && j < 3) { stream << " ";