try to reduce memory footprint

This commit is contained in:
Thomas Krijnen
2020-09-30 13:52:57 +02:00
parent 3fb822b07b
commit 7b26d6d541
21 changed files with 354 additions and 281 deletions
+1 -1
View File
@@ -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<taxonomy::point3>(edge->start);
auto p4 = *((taxonomy::geom_item*)item)->matrix.components * p3.components->homogeneous();
auto p4 = ((taxonomy::geom_item*)item)->matrix.ccomponents() * p3.ccomponents().homogeneous();
Kernel_::Point_3 P(p4(0), p4(1), p4(2));
elem_to_space_boundary_coords[{g1, g2}].emplace_back(P);
}
@@ -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().ccomponents();
const auto& n = geom_object->transformation().data().ccomponents();
const cgal_placement_t trsf(
m(0, 0), m(0, 1), m(0, 2), m(0, 3),
@@ -123,8 +123,8 @@ void fix_wallconnectivity(IfcParse::IfcFile& f, bool no_progress, bool quiet, bo
auto p0 = boost::get<taxonomy::point3>(first_vertex);
auto p1 = boost::get<taxonomy::point3>(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.ccomponents() * p0.ccomponents().homogeneous();
auto v1 = ((taxonomy::geom_item*)item)->matrix.ccomponents() * p1.ccomponents().homogeneous();
auto P0 = Kernel_::Point_3(v0(0), v0(1), v0(2));
auto P1 = Kernel_::Point_3(v1(0), v1(1), v1(2));
+2 -2
View File
@@ -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().ccomponents();
const auto& n = geom_object->transformation().data().ccomponents();
const cgal_placement_t trsf(
m(0, 0), m(0, 1), m(0, 2), m(0, 3),
@@ -8,8 +8,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.is_identity()) {
const auto& m = place.ccomponents();
// @todo check
const cgal_placement_t trsf(
+33 -44
View File
@@ -171,7 +171,7 @@ bool CgalKernel::convert(const taxonomy::shell* l, cgal_shape_t& shape) {
);
size_t num_points = 0;
visit<taxonomy::point3>(l, [&minmax, &num_points](const taxonomy::point3* p) {
auto& c = *p->components;
auto& c = p->ccomponents();
++num_points;
for (int i = 0; i < 3; ++i) {
if (c(i) < minmax.first(i)) {
@@ -271,11 +271,11 @@ namespace {
if (true || e->basis == nullptr) {
if (builder.empty()) {
const auto& p = boost::get<taxonomy::point3>(e->start);
cgal_point_t pnt((*p.components)(0), (*p.components)(1), (*p.components)(2));
cgal_point_t pnt(p.ccomponents()(0), p.ccomponents()(1), p.ccomponents()(2));
builder.push_back(pnt);
}
const auto& p = boost::get<taxonomy::point3>(e->end);
cgal_point_t pnt((*p.components)(0), (*p.components)(1), (*p.components)(2));
cgal_point_t pnt(p.ccomponents()(0), p.ccomponents()(1), p.ccomponents()(2));
builder.push_back(pnt);
} else if (e->basis->kind() == taxonomy::CIRCLE) {
// @todo
@@ -305,32 +305,32 @@ namespace {
void evaluate_curve(const taxonomy::line& c, double u, taxonomy::point3& p) {
Eigen::Vector4d xy{ u, 0, 0, 1. };
*p.components = (*c.matrix.components * xy).head<3>();
p.components() = (c.matrix.ccomponents() * xy).head<3>();
}
void evaluate_curve(const taxonomy::circle& c, double u, taxonomy::point3& p) {
Eigen::Vector4d xy{ c.radius * std::cos(u), c.radius * std::sin(u), 0, 1. };
*p.components = (*c.matrix.components * xy).head<3>();
p.components() = (c.matrix.ccomponents() * xy).head<3>();
}
void evaluate_curve(const taxonomy::ellipse& c, double u, taxonomy::point3& p) {
Eigen::Vector4d xy{ c.radius * std::cos(u), c.radius2 * std::sin(u), 0, 1. };
*p.components = (*c.matrix.components * xy).head<3>();
p.components() = (c.matrix.ccomponents() * xy).head<3>();
}
// ----
void project_onto_curve(const taxonomy::line& c, const taxonomy::point3& p, double& u) {
u = (c.matrix.components->inverse() * p.components->homogeneous())(0);
u = (c.matrix.ccomponents().inverse() * p.ccomponents().homogeneous())(0);
}
void project_onto_curve(const taxonomy::circle& c, const taxonomy::point3& p, double& u) {
Eigen::Vector2d xy = (c.matrix.components->inverse() * p.components->homogeneous()).head<2>();
Eigen::Vector2d xy = (c.matrix.ccomponents().inverse() * p.ccomponents().homogeneous()).head<2>();
u = std::atan2(xy(1), xy(0));
}
void project_onto_curve(const taxonomy::ellipse& c, const taxonomy::point3& p, double& u) {
Eigen::Vector2d xy = (c.matrix.components->inverse() * p.components->homogeneous()).head<2>();
Eigen::Vector2d xy = (c.matrix.ccomponents().inverse() * p.ccomponents().homogeneous()).head<2>();
u = std::atan2(xy(1), xy(0));
}
@@ -468,7 +468,7 @@ namespace {
if (b.empty()) {
return;
}
double d = (*a.back().components - *b.front().components).norm();
double d = (a.back().ccomponents() - b.front().ccomponents()).norm();
size_t offset = d < 1.e-5 ? 1 : 0;
a.insert(a.end(), b.begin() + offset, b.end());
}
@@ -553,7 +553,7 @@ namespace {
auto edges = loop->children_as<taxonomy::edge>();
for (auto& e : edges) {
auto& p = boost::get<taxonomy::point3>(e->start);
CGAL::Point_2<Kernel_> pnt((*p.components)(0), (*p.components)(1));
CGAL::Point_2<Kernel_> pnt(p.ccomponents()(0), p.ccomponents()(1));
polygon.push_back(pnt);
}
return polygon;
@@ -667,7 +667,7 @@ bool CgalKernel::convert(const taxonomy::loop* loop, cgal_wire_t& result) {
if (points.size() >= 2) {
// the edges -> <p0, ... pn> conversion left us with a duplicate global begin,end point.
double d = (*points.back().components - *points.front().components).norm();
double d = (points.back().ccomponents() - points.front().ccomponents()).norm();
if (d < 1.e-5) {
points.erase(points.end() - 1);
} else {
@@ -678,7 +678,7 @@ bool CgalKernel::convert(const taxonomy::loop* loop, cgal_wire_t& result) {
// Parse and store the points in a sequence
cgal_wire_t polygon = std::vector<Kernel_::Point_3>();
for (auto& p : points) {
cgal_point_t pnt((*p.components)(0), (*p.components)(1), (*p.components)(2));
cgal_point_t pnt(p.ccomponents()(0), p.ccomponents()(1), p.ccomponents()(2));
polygon.push_back(pnt);
}
@@ -854,7 +854,7 @@ bool CgalKernel::process_extrusion(const cgal_face_t& bottom_face, const taxonom
face_list.push_back(cgal_face_t{ w });
auto& fs = *direction.components;
auto& fs = direction.ccomponents();
cgal_direction_t dir(fs(0), fs(1), fs(2));
int si = 0;
@@ -1155,7 +1155,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.ccomponents();
// @todo check
trsf = cgal_placement_t(
@@ -1190,14 +1190,14 @@ bool CgalKernel::process_as_2d_polygon(const taxonomy::boolean_result* br, std::
if (op->kind() != taxonomy::COLLECTION) return nptr;
auto cl = (taxonomy::collection*) op;
if ((cl)->children.size() != 1) return nptr;
m4 = new Eigen::Matrix4d(*cl->matrix.components);
m4 = new Eigen::Matrix4d(cl->matrix.ccomponents());
if (cl->children[0]->kind() == taxonomy::COLLECTION) {
cl = (taxonomy::collection*) cl->children[0];
if ((cl)->children.size() != 1) {
delete m4;
return nptr;
}
(*m4) = (*m4) * *cl->matrix.components;
(*m4) = (*m4) * cl->matrix.ccomponents();
}
if (cl->children[0]->kind() != taxonomy::EXTRUSION) {
delete m4;
@@ -1218,7 +1218,7 @@ bool CgalKernel::process_as_2d_polygon(const taxonomy::boolean_result* br, std::
if (std::find_if(extrusions.begin(), extrusions.end(), [&Z](extrusion_pair& p) {
// @todo factor in p.first;
auto ex = p.second;
auto& m = *ex->matrix.components;
auto& m = ex->matrix.ccomponents();
return std::abs(1. - std::abs(m.col(2).head<3>().dot(Z))) > 1.e-5;
}) != extrusions.end()) {
return false;
@@ -1227,8 +1227,8 @@ bool CgalKernel::process_as_2d_polygon(const taxonomy::boolean_result* br, std::
// | op[i].matrix[2,0:3] . op[i].direction | = 1
if (std::find_if(extrusions.begin(), extrusions.end(), [](extrusion_pair& p) {
auto ex = p.second;
auto& d = *ex->direction.components;
auto& m = *ex->matrix.components;
auto& d = ex->direction.ccomponents();
auto& m = ex->matrix.ccomponents();
return std::abs(1. - std::abs(m.col(2).head<3>().dot(d))) > 1.e-5;
}) != extrusions.end()) {
return false;
@@ -1243,10 +1243,10 @@ bool CgalKernel::process_as_2d_polygon(const taxonomy::boolean_result* br, std::
return false;
}
const auto& op_0_matrix_2_3 = (*extrusions[0].second->matrix.components)(2, 3);
const auto& op_0_matrix_2_3 = extrusions[0].second->matrix.ccomponents()(2, 3);
if (std::find_if(extrusions.begin() + 1, extrusions.end(), [&op_0_matrix_2_3](extrusion_pair& p) {
auto ex = p.second;
return op_0_matrix_2_3 < (*ex->matrix.components)(2, 3);
return op_0_matrix_2_3 < ex->matrix.components()(2, 3);
}) != extrusions.end()) {
return false;
}
@@ -1295,9 +1295,9 @@ bool CgalKernel::process_as_2d_polygon(const taxonomy::boolean_result* br, std::
loops.clear();
std::transform(wires.begin(), wires.end(), std::back_inserter(loops), wire_to_polygon_2);
auto& op_0_matrix = *extrusions[0].second->matrix.components;
auto& op_0_matrix = extrusions[0].second->matrix.ccomponents();
Eigen::Vector4d op_0_dir;
op_0_dir << (*extrusions[0].second->direction.components), 0;
op_0_dir << extrusions[0].second->direction.ccomponents(), 0;
op_0_dir = op_0_matrix * op_0_dir;
z0 = op_0_matrix_2_3;
z1 = z0 + extrusions[0].second->depth * op_0_dir(2);
@@ -1423,7 +1423,7 @@ bool CgalKernel::process_as_2d_polygon(const std::list<std::list<std::pair<const
namespace {
template <typename It, typename Fn>
void project_onto_plane(const taxonomy::plane& p, It i, It j, Fn fn) {
auto mi = p.matrix.components->inverse();
auto mi = p.matrix.ccomponents().inverse();
Eigen::Vector4d v;
std::for_each(i, j, [&mi, &v, &fn](const cgal_shape_t& shp) {
for (auto& vv : vertices(shp)) {
@@ -1444,11 +1444,11 @@ bool CgalKernel::convert_impl(const taxonomy::boolean_result* br, ifcopenshell::
std::list<CGAL::Polygon_2<Kernel_>> loops;
if (process_as_2d_polygon(br, loops, z0, z1)) {
taxonomy::style first_item_style;
taxonomy::style* first_item_style = nullptr;
{
auto gi = dynamic_cast<const taxonomy::geom_item*>(br->children[0]);
while (gi) {
if (gi->surface_style.diffuse) {
if (gi->surface_style) {
first_item_style = gi->surface_style;
break;
}
@@ -1524,7 +1524,7 @@ bool CgalKernel::convert_impl(const taxonomy::boolean_result* br, ifcopenshell::
br->instance->data().id(),
br->matrix,
new CgalShape(shp),
br->surface_style.diffuse ? br->surface_style : first_item_style
br->surface_style ? br->surface_style : first_item_style
);
});
@@ -1541,7 +1541,7 @@ bool CgalKernel::convert_impl(const taxonomy::boolean_result* br, ifcopenshell::
CGAL::Nef_nary_union_3<CGAL::Nef_polyhedron_3<Kernel_>> second_operand_collector;
size_t second_operand_collector_size = 0;
taxonomy::style first_item_style;
taxonomy::style* first_item_style = nullptr;
std::list<std::pair<const IfcUtil::IfcBaseClass*, std::list<cgal_shape_t>>> operands;
@@ -1627,7 +1627,8 @@ bool CgalKernel::convert_impl(const taxonomy::boolean_result* br, ifcopenshell::
if (first && br->operation == taxonomy::boolean_result::SUBTRACTION) {
first_item_style = ((taxonomy::geom_item*)c)->surface_style;
if (!first_item_style.diffuse && c->kind() == taxonomy::COLLECTION) {
if (!first_item_style && c->kind() == taxonomy::COLLECTION) {
// @todo recursively right?
first_item_style = ((taxonomy::geom_item*) ((taxonomy::collection*)c)->children[0])->surface_style;
}
}
@@ -1635,23 +1636,11 @@ 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().is_identity()) {
cgal_placement_t trsf;
convert_placement(it->Placement(), trsf);
for (auto &vertex : vertices(entity_shape)) {
if (false) {
auto x = CGAL::to_double(vertex->point().x());
auto y = CGAL::to_double(vertex->point().y());
auto z = CGAL::to_double(vertex->point().z());
std::wcout << x << " " << y << " " << z << std::endl;
}
vertex->point() = vertex->point().transform(trsf);
if (false) {
auto x = CGAL::to_double(vertex->point().x());
auto y = CGAL::to_double(vertex->point().y());
auto z = CGAL::to_double(vertex->point().z());
std::wcout << x << " " << y << " " << z << std::endl;
}
}
}
operands.back().second.push_back(entity_shape);
@@ -1720,7 +1709,7 @@ bool CgalKernel::convert_impl(const taxonomy::boolean_result* br, ifcopenshell::
br->instance->data().id(),
br->matrix,
new CgalShape(a_poly),
br->surface_style.diffuse ? br->surface_style : first_item_style
br->surface_style ? br->surface_style : first_item_style
));
return true;
}
@@ -134,7 +134,7 @@ bool OpenCascadeKernel::convert(const taxonomy::extrusion* extrusion, TopoDS_Sha
auto trsf = gtrsf.Trsf();
*/
const auto& fs = *extrusion->direction.components;
const auto& fs = extrusion->direction.ccomponents();
gp_Dir dir(fs(0), fs(1), fs(2));
shape.Nullify();
@@ -514,7 +514,7 @@ bool OpenCascadeKernel::convert(const taxonomy::face* face, TopoDS_Shape& result
namespace {
template <typename T, typename U>
T convert_xyz(const U& u) {
const auto& vs = *u.components;
const auto& vs = u.ccomponents();
return T(vs(0), vs(1), vs(2));
}
@@ -536,17 +536,17 @@ namespace {
}
curve_creation_visitor_result_type operator()(const taxonomy::line& l) {
const auto& m = *l.matrix.components;
const auto& m = l.matrix.ccomponents();
return result = Handle(Geom_Curve)(new Geom_Line(convert_xyz2<gp_Pnt>(m.col(3)), convert_xyz2<gp_Dir>(m.col(0))));
}
curve_creation_visitor_result_type operator()(const taxonomy::circle& c) {
const auto& m = *c.matrix.components;
const auto& m = c.matrix.ccomponents();
return result = Handle(Geom_Curve)(new Geom_Circle(gp_Ax2(convert_xyz2<gp_Pnt>(m.col(3)), convert_xyz2<gp_Dir>(m.col(2)), convert_xyz2<gp_Dir>(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.ccomponents();
return result = Handle(Geom_Curve)(new Geom_Ellipse(gp_Ax2(convert_xyz2<gp_Pnt>(m.col(3)), convert_xyz2<gp_Dir>(m.col(2)), convert_xyz2<gp_Dir>(m.col(0))), e.radius, e.radius2));
}
@@ -926,7 +926,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::shell *shell, ifcopenshell:
bool OpenCascadeKernel::convert(const taxonomy::matrix4* matrix, gp_GTrsf& trsf) {
// @todo check
const auto& m = *matrix->components;
const auto& m = matrix->ccomponents();
gp_Mat mat(
m(0, 0), m(0, 1), m(0, 2),
m(1, 0), m(1, 1), m(1, 2),
@@ -2134,7 +2134,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result* br, ifcopen
TopoDS_Shape a;
TopTools_ListOfShape b;
taxonomy::style first_item_style;
taxonomy::style* first_item_style = nullptr;
for (auto& c : br->children) {
// AbstractKernel::convert(c, results);
@@ -2147,7 +2147,8 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result* br, ifcopen
// @todo A will be null on union/intersection, intended?
flatten_shape_list(cr, a, false);
first_item_style = ((taxonomy::geom_item*)c)->surface_style;
if (!first_item_style.diffuse && c->kind() == taxonomy::COLLECTION) {
if (!first_item_style && c->kind() == taxonomy::COLLECTION) {
// @todo recursively right?
first_item_style = ((taxonomy::geom_item*) ((taxonomy::collection*)c)->children[0])->surface_style;
}
} else {
@@ -2188,7 +2189,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result* br, ifcopen
br->instance->data().id(),
br->matrix,
new OpenCascadeShape(r),
br->surface_style.diffuse ? br->surface_style : first_item_style
br->surface_style ? br->surface_style : first_item_style
));
return true;
}
@@ -2268,7 +2269,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.is_identity()) {
return s;
} else {
gp_GTrsf trsf;
@@ -2311,7 +2312,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.ccomponents();
gp_Pln pln(convert_xyz2<gp_Pnt>(m.col(3)), convert_xyz2<gp_Dir>(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();
@@ -10,11 +10,13 @@
namespace {
// We bypass the conversion to gp_GTrsf, because it does not work
void taxonomy_transform(const Eigen::Matrix4d* m, gp_XYZ& xyz) {
Eigen::Vector4d v(xyz.X(), xyz.Y(), xyz.Z(), 1.0);
auto v2 = (*m * v).eval();
xyz.ChangeData()[0] = v2(0);
xyz.ChangeData()[1] = v2(1);
xyz.ChangeData()[2] = v2(2);
if (m) {
Eigen::Vector4d v(xyz.X(), xyz.Y(), xyz.Z(), 1.0);
auto v2 = (*m * v).eval();
xyz.ChangeData()[0] = v2(0);
xyz.ChangeData()[1] = v2(1);
xyz.ChangeData()[2] = v2(2);
}
}
}
@@ -23,14 +25,17 @@ void ifcopenshell::geometry::OpenCascadeShape::Triangulate(const settings& setti
// @todo remove duplication with OpenCascadeKernel::convert(const taxonomy::matrix4* matrix, gp_GTrsf& trsf);
// above can be static?
const auto& m = *place.components;
// A 3x3 matrix to rotate the vertex normals
gp_Mat rotation_matrix(
m(0, 0), m(0, 1), m(0, 2),
m(1, 0), m(1, 1), m(1, 2),
m(2, 0), m(2, 1), m(2, 2)
);
boost::optional<gp_Mat> rotation_matrix;
if (place.components_) {
const auto& m = *place.components_;
rotation_matrix.emplace(
m(0, 0), m(0, 1), m(0, 2),
m(1, 0), m(1, 1), m(1, 2),
m(2, 0), m(2, 1), m(2, 2)
);
}
// Triangulate the shape
try {
@@ -70,7 +75,7 @@ void ifcopenshell::geometry::OpenCascadeShape::Triangulate(const settings& setti
for (int i = 1; i <= nodes.Length(); ++i) {
coords.push_back(nodes(i).Transformed(loc).XYZ());
taxonomy_transform(place.components, *coords.rbegin());
taxonomy_transform(place.components_, *coords.rbegin());
const gp_XYZ& last = *coords.rbegin();
dict[i] = t->addVertex(surface_style_id, last.X(), last.Y(), last.Z());
@@ -81,7 +86,11 @@ void ifcopenshell::geometry::OpenCascadeShape::Triangulate(const settings& setti
prop.Normal(uv.X(), uv.Y(), p, normal_direction);
gp_Vec normal(0., 0., 0.);
if (normal_direction.Magnitude() > 1.e-9) {
normal = gp_Dir(normal_direction.XYZ() * rotation_matrix);
if (rotation_matrix) {
normal = gp_Dir(normal_direction.XYZ() * *rotation_matrix);
} else {
normal = normal_direction;
}
}
t->addNormal(normal.X(), normal.Y(), normal.Z());
}
+1 -1
View File
@@ -12,7 +12,7 @@
if (l->as<IfcSchema::IfcRepresentationItem>() && !l->as<IfcSchema::IfcStyledItem>()) { \
auto style = find_style(l->as<IfcSchema::IfcRepresentationItem>()); \
if (style) { \
((taxonomy::geom_item*)item)->surface_style = as<taxonomy::style>(map(style)); \
((taxonomy::geom_item*)item)->surface_style = (taxonomy::style*) map(style); \
} \
} \
} catch (const std::exception& e) { \
+56 -47
View File
@@ -368,19 +368,25 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcProduct* inst) {
if (single_material) {
auto material_style = map(single_material);
if (material_style) {
c->surface_style = as<taxonomy::style>(material_style);
c->surface_style = (taxonomy::style*) material_style;
}
}
if (openings->size() && !settings_.get(settings::DISABLE_OPENING_SUBTRACTIONS) && use_body) {
auto ci = c->matrix.components->inverse();
Eigen::Matrix4d ci;
if (c->matrix.components_) {
ci = c->matrix.components_->inverse();
} else {
ci.setIdentity();
}
IfcEntityList::ptr operands(new IfcEntityList);
operands->push(body);
operands->push(openings);
auto n = map_to_collection<taxonomy::boolean_result>(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.ccomponents();
});
n->operation = taxonomy::boolean_result::SUBTRACTION;
// @todo one indirection too many
@@ -403,7 +409,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<taxonomy::point3>(map(inst->Location()));
o = *v.components;
o = *v.components_;
}
const bool hasAxis = inst->hasAxis();
const bool hasRef = inst->hasRefDirection();
@@ -414,12 +420,12 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcAxis2Placement3D* inst) {
if (hasAxis) {
taxonomy::direction3 v = as<taxonomy::direction3>(map(inst->Axis()));
axis = *v.components;
axis = *v.components_;
}
if (hasRef) {
taxonomy::direction3 v = as<taxonomy::direction3>(map(inst->RefDirection()));
refDirection = *v.components;
refDirection = *v.components_;
} else {
if (acos(axis.dot(X)) > 1.e-5) {
refDirection = { 1., 0., 0. };
@@ -437,12 +443,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<taxonomy::point3>(map(inst->Location()));
P = *v.components;
P = *v.components_;
}
const bool hasRef = inst->hasRefDirection();
if (hasRef) {
taxonomy::direction3 v = as<taxonomy::direction3>(map(inst->RefDirection()));
V = *v.components;
V = *v.components_;
}
return new taxonomy::matrix4(P, axis, V);
}
@@ -453,15 +459,15 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcCartesianTransformationOpe
Eigen::Vector4d origin, axis1(1.0, 0.0, 0.0, 0.0), axis2(0.0, 1.0, 0.0, 0.0), axis3(0.0, 0.0, 1.0, 0.0);
taxonomy::point3 O = as<taxonomy::point3>(map(inst->LocalOrigin()));
origin << *O.components, 1.0;
origin << *O.components_, 1.0;
if (inst->hasAxis1()) {
taxonomy::direction3 ax1 = as<taxonomy::direction3>(map(inst->Axis1()));
axis1 << *ax1.components, 0.0;
axis1 << *ax1.components_, 0.0;
}
if (inst->hasAxis2()) {
taxonomy::direction3 ax2 = as<taxonomy::direction3>(map(inst->Axis1()));
axis2 << *ax2.components, 0.0;
axis2 << *ax2.components_, 0.0;
}
double scale1, scale2;
@@ -475,13 +481,13 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcCartesianTransformationOpe
scale2 = nu->hasScale2() ? nu->Scale2() : scale1;
}
*m->components <<
m->components() <<
axis1 * scale1,
axis2 * scale2,
axis3,
origin;
m->components->transposeInPlace();
m->components().transposeInPlace();
return m;
}
@@ -495,19 +501,19 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcCartesianTransformationOpe
Eigen::Vector4d axis3(0., 0., 1., 0.);
taxonomy::point3 O = as<taxonomy::point3>(map(inst->LocalOrigin()));
origin << *O.components, 1.0;
origin << *O.components_, 1.0;
if (inst->hasAxis1()) {
taxonomy::direction3 ax1 = as<taxonomy::direction3>(map(inst->Axis1()));
axis1 << *ax1.components, 0.0;
axis1 << *ax1.components_, 0.0;
}
if (inst->hasAxis2()) {
taxonomy::direction3 ax2 = as<taxonomy::direction3>(map(inst->Axis2()));
axis2 << *ax2.components, 0.0;
axis2 << *ax2.components_, 0.0;
}
if (inst->hasAxis3()) {
taxonomy::direction3 ax3 = as<taxonomy::direction3>(map(inst->Axis3()));
axis3 << *ax3.components, 0.0;
axis3 << *ax3.components_, 0.0;
}
double scale1, scale2, scale3;
@@ -529,8 +535,8 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcCartesianTransformationOpe
axis3 * scale3,
origin;
*m->components = tmp.inverse();
m->components->transposeInPlace();
m->components() = tmp.inverse();
m->components().transposeInPlace();
// @todo tag identity?
@@ -545,7 +551,7 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcLocalPlacement* inst) {
if (relplacement->declaration().is(IfcSchema::IfcAxis2Placement3D::Class())) {
taxonomy::matrix4 trsf2 = as<taxonomy::matrix4>(map(relplacement));
// @todo check
*m4->components = *trsf2.components * *m4->components;
m4->components() = trsf2.ccomponents() * m4->ccomponents();
}
if (current->hasPlacementRelTo()) {
IfcSchema::IfcObjectPlacement* parent = current->PlacementRelTo();
@@ -594,14 +600,14 @@ IfcSchema::IfcProduct::list::ptr mapping::products_represented_by(const IfcSchem
if (maps->size() == 1) {
IfcSchema::IfcRepresentationMap* rmap = *maps->begin();
taxonomy::matrix4 origin = as<taxonomy::matrix4>(map(rmap->MappingOrigin()));
if (origin.components->isIdentity()) {
if (origin.is_identity()) {
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<taxonomy::matrix4>(map(item->MappingTarget()));
if (target.components->isIdentity()) {
if (target.is_identity()) {
continue;
}
@@ -845,10 +851,10 @@ IfcSchema::IfcRepresentation* mapping::representation_mapped_to(const IfcSchema:
if (item->StyledByItem()->size() == 0) {
IfcSchema::IfcMappedItem* mapped_item = item->as<IfcSchema::IfcMappedItem>();
taxonomy::matrix4 target = as<taxonomy::matrix4>(map(mapped_item->MappingTarget()));
if (target.components->isIdentity()) {
if (target.is_identity()) {
IfcSchema::IfcRepresentationMap* rmap = mapped_item->MappingSource();
taxonomy::matrix4 origin = as<taxonomy::matrix4>(map(rmap->MappingOrigin()));
if (origin.components->isIdentity()) {
if (origin.is_identity()) {
representation_mapped_to = rmap->MappedRepresentation();
}
}
@@ -1008,14 +1014,14 @@ 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<IfcSchema::IfcSurfaceStyleRendering>()) {
if (rendering_style->hasDiffuseColour() && process_colour(rendering_style->DiffuseColour(), rgb)) {
const taxonomy::colour& old_diffuse = surface_style->diffuse.get_value_or(white);
surface_style->diffuse.reset(taxonomy::colour(old_diffuse.r() * rgb[0], old_diffuse.g() * rgb[1], old_diffuse.b() * rgb[2]));
// @todo
// const taxonomy::colour& old_diffuse = surface_style->diffuse; // .get_value_or(white);
// surface_style->diffuse.reset(taxonomy::colour(old_diffuse.r() * rgb[0], old_diffuse.g() * rgb[1], old_diffuse.b() * rgb[2]));
}
if (rendering_style->hasDiffuseTransmissionColour()) {
// Not supported
@@ -1024,17 +1030,17 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcStyledItem* inst) {
// Not supported
}
if (rendering_style->hasSpecularColour() && process_colour(rendering_style->SpecularColour(), rgb)) {
surface_style->specular.reset(taxonomy::colour(rgb[0], rgb[1], rgb[2]));
surface_style->specular.components() << rgb[0], rgb[1], rgb[2];
}
if (rendering_style->hasSpecularHighlight()) {
IfcSchema::IfcSpecularHighlightSelect* highlight = rendering_style->SpecularHighlight();
if (highlight->declaration().is(IfcSchema::IfcSpecularRoughness::Class())) {
double roughness = *((IfcSchema::IfcSpecularRoughness*)highlight);
if (roughness >= 1e-9) {
surface_style->specularity.reset(1.0 / roughness);
surface_style->specularity = 1.0 / roughness;
}
} else if (highlight->declaration().is(IfcSchema::IfcSpecularExponent::Class())) {
surface_style->specularity.reset(*((IfcSchema::IfcSpecularExponent*)highlight));
surface_style->specularity = *((IfcSchema::IfcSpecularExponent*)highlight);
}
}
if (rendering_style->hasTransmissionColour()) {
@@ -1042,7 +1048,7 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcStyledItem* inst) {
}
if (rendering_style->hasTransparency()) {
const double d = rendering_style->Transparency();
surface_style->transparency.reset(d);
surface_style->transparency = d;
}
}
@@ -1276,7 +1282,7 @@ namespace {
#endif
if (has_position) {
taxonomy::matrix4 m = as<taxonomy::matrix4>(self->map(inst->Position()));
m4 = *m.components;
m4 = m.ccomponents();
}
// @todo precision
@@ -1310,10 +1316,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<taxonomy::point3>(p.previous->start).components->head<2>();
auto p1a = boost::get<taxonomy::point3>(p.previous->end).components->head<2>();
auto p2 = boost::get<taxonomy::point3>(p.next->end).components->head<2>();
auto p1b = boost::get<taxonomy::point3>(p.next->start).components->head<2>();
auto p0 = boost::get<taxonomy::point3>(p.previous->start).components_->head<2>();
auto p1a = boost::get<taxonomy::point3>(p.previous->end).components_->head<2>();
auto p2 = boost::get<taxonomy::point3>(p.next->end).components_->head<2>();
auto p1b = boost::get<taxonomy::point3>(p.next->start).components_->head<2>();
auto ba_ = p0 - p1a;
auto bc_ = p2 - p1b;
@@ -1324,8 +1330,8 @@ namespace {
const double angle = std::acos(ba.dot(bc));
const double inset = *p.radius / std::tan(angle / 2.);
boost::get<taxonomy::point3>(p.previous->end).components->head<2>() += ba * inset;
boost::get<taxonomy::point3>(p.next->start).components->head<2>() += bc * inset;
boost::get<taxonomy::point3>(p.previous->end).components_->head<2>() += ba * inset;
boost::get<taxonomy::point3>(p.next->start).components_->head<2>() += bc * inset;
auto e = new taxonomy::edge;
e->start = p.previous->end;
@@ -1335,10 +1341,10 @@ namespace {
double sign = ab.head<2>().dot(bc) > 0 ? 1. : -1.;
auto O = boost::get<taxonomy::point3>(p.previous->end).components->head<3>() + ab * *p.radius * sign;
auto O = boost::get<taxonomy::point3>(p.previous->end).ccomponents().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.reset(sign == -1.);
@@ -1446,7 +1452,9 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcCircleProfileDef* inst) {
#endif
if (has_position) {
taxonomy::matrix4 m = as<taxonomy::matrix4>(map(inst->Position()));
c->matrix = *m.components;
if (m.components_) {
c->matrix = *m.components_;
}
}
auto e = new taxonomy::edge;
@@ -1547,7 +1555,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
@@ -1576,7 +1584,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) {
@@ -1599,7 +1607,8 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcMappedItem* inst) {
IfcSchema::IfcRepresentationMap* rmap = inst->MappingSource();
IfcSchema::IfcAxis2Placement* placement = rmap->MappingOrigin();
taxonomy::matrix4 trsf2 = as<taxonomy::matrix4>(map(placement));
*gtrsf.components = *gtrsf.components * *trsf2.components;
// Cannot be nullptr here
*gtrsf.components_ = *gtrsf.components_ * *trsf2.components_;
// @todo immutable for caching?
// @todo allow for multiple levels of matrix?
@@ -1610,7 +1619,7 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcMappedItem* inst) {
auto collection = new taxonomy::collection;
collection->children.push_back(shapes);
collection->matrix = *gtrsf.components;
collection->matrix = *gtrsf.components_;
if (shapes != nullptr) {
for (auto& c : ((taxonomy::collection*)shapes)->children) {
@@ -1698,7 +1707,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;
}
@@ -67,31 +67,31 @@ namespace ifcopenshell { namespace geometry {
int id;
ifcopenshell::geometry::taxonomy::matrix4 placement;
ConversionResultShape* shape;
ifcopenshell::geometry::taxonomy::style style;
const ifcopenshell::geometry::taxonomy::style* style;
public:
ConversionResult(int id, const ifcopenshell::geometry::taxonomy::matrix4& placement, const ConversionResultShape* shape, const ifcopenshell::geometry::taxonomy::style& style)
ConversionResult(int id, const ifcopenshell::geometry::taxonomy::matrix4& placement, const ConversionResultShape* shape, const ifcopenshell::geometry::taxonomy::style* style)
: id(id), placement(placement), shape(shape->clone()), style(style) {}
ConversionResult(int id, const ifcopenshell::geometry::taxonomy::matrix4& placement, const ConversionResultShape* shape)
: id(id), placement(placement), shape(shape->clone()) {}
ConversionResult(int id, const ConversionResultShape* shape, const ifcopenshell::geometry::taxonomy::style& style)
ConversionResult(int id, const ConversionResultShape* shape, const ifcopenshell::geometry::taxonomy::style* style)
: id(id), shape(shape->clone()), style(style) {}
ConversionResult(int id, const ConversionResultShape* shape)
: 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.ccomponents() * trsf.ccomponents();
}
void prepend(const ifcopenshell::geometry::taxonomy::matrix4& trsf) {
// @todo verify order
*placement.components = *trsf.components * *placement.components;
placement.components() = trsf.ccomponents() * placement.ccomponents();
}
const ConversionResultShape* Shape() const { return shape; }
ConversionResultShape* Shape() { return shape; }
const ifcopenshell::geometry::taxonomy::matrix4& Placement() const { return placement; }
// @todo
bool hasStyle() const { return style.diffuse.is_initialized(); }
const ifcopenshell::geometry::taxonomy::style& Style() const { return style; }
void setStyle(const ifcopenshell::geometry::taxonomy::style& newStyle) { style = newStyle; }
bool hasStyle() const { return style != nullptr; }
const ifcopenshell::geometry::taxonomy::style& Style() const { return *style; }
void setStyle(const ifcopenshell::geometry::taxonomy::style* newStyle) { style = newStyle; }
int ItemId() const { return id; }
};
+1 -1
View File
@@ -49,7 +49,7 @@ 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();
}
}
}
@@ -39,8 +39,8 @@ ifcopenshell::geometry::Representation::Serialization::Serialization(const BRep&
delete shape;
for (ifcopenshell::geometry::ConversionResults::const_iterator it = brep.begin(); it != brep.end(); ++ it) {
if (it->hasStyle() && it->Style().diffuse) {
const auto& clr = *it->Style().diffuse.get().components;
if (it->hasStyle()) {
const auto& clr = it->Style().diffuse.ccomponents();
surface_styles_.push_back(clr(0));
surface_styles_.push_back(clr(1));
surface_styles_.push_back(clr(2));
@@ -49,8 +49,8 @@ ifcopenshell::geometry::Representation::Serialization::Serialization(const BRep&
surface_styles_.push_back(-1.);
surface_styles_.push_back(-1.);
}
if (it->hasStyle() && it->Style().transparency) {
surface_styles_.push_back(1. - *it->Style().transparency);
if (it->hasStyle() && it->Style().has_transparency()) {
surface_styles_.push_back(1. - it->Style().transparency);
} else {
surface_styles_.push_back(1.);
}
@@ -95,14 +95,16 @@ ifcopenshell::geometry::ConversionResultShape* ifcopenshell::geometry::Represent
// @todo, check
gp_GTrsf trsf;
gp_Trsf tr;
const auto& m = *it->Placement().components;
tr.SetValues(
m(0, 0), m(0, 1), m(0, 2), m(0, 3),
m(1, 0), m(1, 1), m(1, 2), m(1, 3),
m(2, 0), m(2, 1), m(2, 2), m(2, 3)
);
trsf = tr;
if (it->Placement().components_) {
gp_Trsf tr;
const auto& m = it->Placement().ccomponents();
tr.SetValues(
m(0, 0), m(0, 1), m(0, 2), m(0, 3),
m(1, 0), m(1, 1), m(1, 2), m(1, 3),
m(2, 0), m(2, 1), m(2, 2), m(2, 3)
);
trsf = tr;
}
if (!force_meters && settings().get(ifcopenshell::geometry::settings::CONVERT_BACK_UNITS)) {
gp_Trsf scale;
@@ -243,14 +245,17 @@ bool ifcopenshell::geometry::Representation::BRep::calculate_projected_surface_a
try {
// @todo check
gp_GTrsf trsf;
gp_Trsf tr;
const auto& m = *place.components;
tr.SetValues(
m(0, 0), m(0, 1), m(0, 2), m(0, 3),
m(1, 0), m(1, 1), m(1, 2), m(1, 3),
m(2, 0), m(2, 1), m(2, 2), m(2, 3)
);
trsf = tr;
if (place.components_) {
gp_Trsf tr;
const auto& m = place.ccomponents();
tr.SetValues(
m(0, 0), m(0, 1), m(0, 2), m(0, 3),
m(1, 0), m(1, 1), m(1, 2), m(1, 3),
m(2, 0), m(2, 1), m(2, 2), m(2, 3)
);
trsf = tr;
}
gp_Mat mat = trsf.Trsf().HVectorialPart();
gp_Ax3 ax(trsf.TranslationPart(), mat.Column(3), mat.Column(1));
+18 -16
View File
@@ -13,45 +13,46 @@ static bool default_materials_initialized = false;
void InitDefaultMaterials() {
default_materials.insert(std::make_pair("IfcSite", ifcopenshell::geometry::taxonomy::style("IfcSite")));
default_materials["IfcSite"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(0.75, 0.8, 0.65));
default_materials["IfcSite"].diffuse = ifcopenshell::geometry::taxonomy::colour(0.75, 0.8, 0.65);
default_materials.insert(std::make_pair("IfcSlab", ifcopenshell::geometry::taxonomy::style("IfcSlab")));
default_materials["IfcSlab"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(0.4, 0.4, 0.4));
default_materials["IfcSlab"].diffuse = ifcopenshell::geometry::taxonomy::colour(0.4, 0.4, 0.4);
default_materials.insert(std::make_pair("IfcWallStandardCase", ifcopenshell::geometry::taxonomy::style("IfcWallStandardCase")));
default_materials["IfcWallStandardCase"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(0.9, 0.9, 0.9));
default_materials["IfcWallStandardCase"].diffuse = ifcopenshell::geometry::taxonomy::colour(0.9, 0.9, 0.9);
default_materials.insert(std::make_pair("IfcWall", ifcopenshell::geometry::taxonomy::style("IfcWall")));
default_materials["IfcWall"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(0.9, 0.9, 0.9));
default_materials["IfcWall"].diffuse = ifcopenshell::geometry::taxonomy::colour(0.9, 0.9, 0.9);
default_materials.insert(std::make_pair("IfcWindow", ifcopenshell::geometry::taxonomy::style("IfcWindow")));
default_materials["IfcWindow"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(0.75, 0.8, 0.75));
default_materials["IfcWindow"].transparency.reset(0.3);
default_materials["IfcWindow"].diffuse = ifcopenshell::geometry::taxonomy::colour(0.75, 0.8, 0.75);
default_materials["IfcWindow"].transparency = 0.3;
default_materials.insert(std::make_pair("IfcDoor", ifcopenshell::geometry::taxonomy::style("IfcDoor")));
default_materials["IfcDoor"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(0.55, 0.3, 0.15));
default_materials["IfcDoor"].diffuse = ifcopenshell::geometry::taxonomy::colour(0.55, 0.3, 0.15);
default_materials.insert(std::make_pair("IfcBeam", ifcopenshell::geometry::taxonomy::style("IfcBeam")));
default_materials["IfcBeam"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(0.75, 0.7, 0.7));
default_materials["IfcBeam"].diffuse = ifcopenshell::geometry::taxonomy::colour(0.75, 0.7, 0.7);
default_materials.insert(std::make_pair("IfcRailing", ifcopenshell::geometry::taxonomy::style("IfcRailing")));
default_materials["IfcRailing"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(0.65, 0.6, 0.6));
default_materials["IfcRailing"].diffuse = ifcopenshell::geometry::taxonomy::colour(0.65, 0.6, 0.6);
default_materials.insert(std::make_pair("IfcMember", ifcopenshell::geometry::taxonomy::style("IfcMember")));
default_materials["IfcMember"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(0.65, 0.6, 0.6));
default_materials["IfcMember"].diffuse = ifcopenshell::geometry::taxonomy::colour(0.65, 0.6, 0.6);
default_materials.insert(std::make_pair("IfcPlate", ifcopenshell::geometry::taxonomy::style("IfcPlate")));
default_materials["IfcPlate"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(0.8, 0.8, 0.8));
default_materials["IfcPlate"].diffuse = ifcopenshell::geometry::taxonomy::colour(0.8, 0.8, 0.8);
default_material = ifcopenshell::geometry::taxonomy::style("DefaultMaterial");
default_material.diffuse.reset(ifcopenshell::geometry::taxonomy::colour(0.7, 0.7, 0.7));
default_material.diffuse = ifcopenshell::geometry::taxonomy::colour(0.7, 0.7, 0.7);
default_materials_initialized = true;
}
boost::optional<ifcopenshell::geometry::taxonomy::colour> read_colour_component(const boost::optional<pt::ptree&> list) {
ifcopenshell::geometry::taxonomy::colour read_colour_component(const boost::optional<pt::ptree&> list) {
ifcopenshell::geometry::taxonomy::colour clr;
if (!list) {
return boost::none;
return clr;
}
double rgb[3];
int i = 0;
@@ -65,7 +66,8 @@ boost::optional<ifcopenshell::geometry::taxonomy::colour> read_colour_component(
if (i != 3) {
throw std::runtime_error("rgb array less than 3 elements large (was " + std::to_string(i) + ")");
}
return ifcopenshell::geometry::taxonomy::colour(rgb[0], rgb[1], rgb[2]);
clr.components() << rgb[0], rgb[1], rgb[2];
return clr;
}
void IfcGeom::set_default_style_file(const std::string& json_file) {
@@ -88,7 +90,7 @@ void IfcGeom::set_default_style_file(const std::string& json_file) {
default_materials[name].specular = read_colour_component(specular);
if (material.get_child_optional("specular-roughness")) {
default_materials[name].specularity.reset(1.0 / material.get<double>("specular-roughness"));
default_materials[name].specularity = 1.0 / material.get<double>("specular-roughness");
}
if (material.get_child_optional("transparency")) {
default_materials[name].transparency = material.get<double>("transparency");
+27 -10
View File
@@ -9,11 +9,19 @@ namespace {
template <typename T>
bool compare(const eigen_base<T>& t, const eigen_base<T>& u) {
auto t_begin = t.components->data();
auto t_end = t.components->data() + t.components->size();
if (t.components_ == nullptr && u.components_ == nullptr) {
return false;
} else if (t.components_ == nullptr && u.components_ != nullptr) {
return true;
} else if (t.components_ != nullptr && u.components_ == nullptr) {
return false;
}
auto u_begin = u.components->data();
auto u_end = u.components->data() + u.components->size();
auto t_begin = t.components_->data();
auto t_end = t.components_->data() + t.components_->size();
auto u_begin = u.components_->data();
auto u_end = u.components_->data() + u.components_->size();
return std::lexicographical_compare(t_begin, t_end, u_begin, u_end);
}
@@ -108,11 +116,11 @@ namespace {
bool compare(const style& a, const style& b) {
const int order[5] = {
less_to_order_optional(a.name, b.name),
less_to_order_optional(a.diffuse, b.diffuse),
less_to_order_optional(a.specular, b.specular),
less_to_order_optional(a.specularity, b.specularity),
less_to_order_optional(a.transparency, b.transparency)
less_to_order(a.name, b.name),
less_to_order(a.diffuse, b.diffuse),
less_to_order(a.specular, b.specular),
less_to_order(a.specularity, b.specularity),
less_to_order(a.transparency, b.transparency)
};
auto it = std::find_if(std::begin(order), std::end(order), [](int x) { return x; });
if (it == std::end(order)) return false;
@@ -221,7 +229,16 @@ namespace {
// Vectors equal, compare matrix (in case of mapped items).
int matrix_order = less_to_order(a.matrix, b.matrix);
if (matrix_order == 0) {
return compare(a.surface_style, b.surface_style);
if (a.surface_style == nullptr && b.surface_style == nullptr) {
return false;
} else if (a.surface_style == nullptr && b.surface_style != nullptr) {
return true;
} else if (a.surface_style != nullptr && b.surface_style == nullptr) {
return false;
}
return compare(*a.surface_style, *b.surface_style);
} else {
return matrix_order == -1;
}
+94 -44
View File
@@ -28,6 +28,9 @@ enum kinds { MATRIX4, POINT3, DIRECTION3, LINE, CIRCLE, ELLIPSE, BSPLINE_CURVE,
struct item {
const IfcUtil::IfcBaseClass* instance;
boost::optional<bool> orientation;
virtual item* clone() const = 0;
virtual kinds kind() const = 0;
virtual void print(std::ostream&, int indent=0) const = 0;
@@ -44,40 +47,76 @@ struct less_functor {
}
};
namespace {
template <typename T>
const T& eigen_defaults();
template <>
const Eigen::Vector3d& eigen_defaults<Eigen::Vector3d>() {
static Eigen::Vector3d identity = Eigen::Vector3d::Zero();
return identity;
}
template <>
const Eigen::Matrix4d& eigen_defaults<Eigen::Matrix4d>() {
static Eigen::Matrix4d identity = Eigen::Matrix4d::Identity();
return identity;
}
}
template <typename T>
struct eigen_base {
T* components;
T* components_;
eigen_base() {
components = new T;
components_ = nullptr;
}
eigen_base(const eigen_base& other) {
this->components = new T(*other.components);
this->components_ = other.components_ ? new T(*other.components_) : nullptr;
}
eigen_base(const T& other) {
this->components = new T(other);
this->components_ = new T(other);
}
eigen_base& operator=(const eigen_base& other) {
if (this != &other) {
this->components = new T(*other.components);
this->components_ = other.components_ ? new T(*other.components_) : nullptr;
}
return *this;
}
void print_impl(std::ostream& o, const std::string& class_name, int indent = 0) const {
o << std::string(indent, ' ') << class_name;
int n = T::RowsAtCompileTime * T::ColsAtCompileTime;
for (size_t i = 0; i < n; ++i) {
o << " " << (*components)(i);
if (this->components_) {
int n = T::RowsAtCompileTime * T::ColsAtCompileTime;
for (size_t i = 0; i < n; ++i) {
o << " " << (*components_)(i);
}
}
o << std::endl;
}
~eigen_base() {
delete this->components;
delete this->components_;
}
const T& ccomponents() const {
if (this->components_) {
return *this->components_;
} else {
return eigen_defaults<T>();
}
}
T& components() {
if (!this->components_) {
this->components_ = new T;
}
return *this->components_;
}
};
@@ -87,20 +126,24 @@ struct matrix4 : public item, public eigen_base<Eigen::Matrix4d> {
};
tag_t tag;
matrix4() : eigen_base(Eigen::Matrix4d::Identity()), tag(IDENTITY) {}
matrix4() : eigen_base(), 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 = new Eigen::Matrix4d;
(*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.;
}
bool is_identity() const {
return !components_ || components_->isIdentity();
}
void print(std::ostream& o, int indent = 0) const {
print_impl(o, "matrix4", indent);
}
@@ -117,33 +160,30 @@ struct colour : public item, public eigen_base<Eigen::Vector3d> {
virtual item* clone() const { return new colour(*this); }
virtual kinds kind() const { return COLOUR; }
colour() : eigen_base(Eigen::Vector3d::Zero()) {}
colour(double r, double g, double b) { (*components) << r, g, b; }
colour() : eigen_base() {}
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 ccomponents()[0]; }
const double& g() const { return ccomponents()[1]; }
const double& b() const { return ccomponents()[2]; }
};
struct style : public item {
// @todo this is not very efficient wrt alignment
boost::optional<std::string> name;
boost::optional<colour> diffuse;
boost::optional<colour> specular;
boost::optional<double> specularity, transparency;
std::string name;
colour diffuse;
colour specular;
double 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;
o << std::string(indent, ' ') << " " << "name" << (name) << std::endl;
if (diffuse.components_) {
o << std::string(indent, ' ') << " " << "diffuse" << (name) << std::endl;
diffuse.print(o, indent + 5 + 7);
}
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);
if (specular.components_) {
o << std::string(indent, ' ') << " " << "specular" << (name) << std::endl;
specular.print(o, indent + 5 + 8);
}
// @todo
}
@@ -154,23 +194,31 @@ struct style : public item {
// @todo equality implementation based on values?
bool operator==(const style& other) const { return instance == other.instance; }
style() {}
style(const std::string& name) : name(name) {}
style() : specularity(std::numeric_limits<double>::quiet_NaN()), transparency(std::numeric_limits<double>::quiet_NaN()) {}
style(const std::string& name) : name(name), specularity(std::numeric_limits<double>::quiet_NaN()), transparency(std::numeric_limits<double>::quiet_NaN()) {}
bool has_specularity() const {
return !std::isnan(specularity);
}
bool has_transparency() const {
return !std::isnan(transparency);
}
};
struct geom_item : public item {
style surface_style;
style* surface_style;
matrix4 matrix;
boost::optional<bool> orientation;
geom_item(const IfcUtil::IfcBaseClass* instance = nullptr) : item(instance) {}
geom_item(const IfcUtil::IfcBaseClass* instance, matrix4 m) : item(instance), matrix(m) {}
geom_item(matrix4 m) : matrix(m) {}
geom_item(const IfcUtil::IfcBaseClass* instance = nullptr) : item(instance), surface_style(nullptr) {}
geom_item(const IfcUtil::IfcBaseClass* instance, matrix4 m) : item(instance), surface_style(nullptr), matrix(m) {}
geom_item(matrix4 m) : surface_style(nullptr), matrix(m) {}
};
// @todo make 4d for easier multiplication
template <size_t N>
struct cartesian_base : public geom_item, public eigen_base<Eigen::Vector3d> {
cartesian_base() : eigen_base(Eigen::Vector3d::Zero()) {}
struct cartesian_base : public item, public eigen_base<Eigen::Vector3d> {
cartesian_base() : eigen_base() {}
cartesian_base(double x, double y, double z = 0.) : eigen_base(Eigen::Vector3d(x, y, z)) {}
};
@@ -182,7 +230,8 @@ struct point3 : public cartesian_base<3> {
print_impl(o, "point3", indent);
}
point3(double x = 0., double y = 0., double z = 0.) : cartesian_base(x, y, z) {}
point3() : cartesian_base() {}
point3(double x, double y, double z = 0.) : cartesian_base(x, y, z) {}
};
struct direction3 : public cartesian_base<3> {
@@ -193,7 +242,8 @@ struct direction3 : public cartesian_base<3> {
print_impl(o, "direction3", indent);
}
direction3(double x = 0., double y = 0., double z = 0.) : cartesian_base(x, y, z) {}
direction3() : cartesian_base() {}
direction3(double x, double y, double z = 0.) : cartesian_base(x, y, z) {}
};
struct curve : public geom_item {
@@ -243,7 +293,7 @@ struct bspline_curve : public curve {
}
};
struct trimmed_curve : public curve {
struct trimmed_curve : public item {
// @todo The copy constructor of point3 within the variant fails on the avx instruction
// on the default gcc in Ubuntu 18.04 and a recent AMD Ryzen. Probably due to allignment.
boost::variant<point3, double> start, end;
@@ -316,7 +366,7 @@ struct collection : public geom_item {
void print(std::ostream& o, int indent = 0) const {
o << std::string(indent, ' ') << "collection" << std::endl;
if (!matrix.components->isIdentity()) {
if (!matrix.components_->isIdentity()) {
matrix.print(o, indent + 4);
}
for (auto& c : children) {
+22 -24
View File
@@ -197,20 +197,20 @@ 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().ccomponents() * transformation.data().ccomponents());
relative_trsf = new ifcopenshell::geometry::Transformation(transformation.settings(), m4);
transformation_towrite = relative_trsf;
}
// @todo verify
const double* m = transformation_towrite->data().components->data();
const auto& m = transformation_towrite->data().ccomponents();
double matrix_array[4][4] = {
{ m[0], m[4], m[8], m[12] },
{ m[1], m[5], m[9], m[13] },
{ m[2], m[6], m[10], m[14] },
{ m[3], m[7], m[11], m[15] }
{ m(0), m(4), m(8), m(12) },
{ m(1), m(5), m(9), m(13) },
{ m(2), m(6), m(10), m(14) },
{ m(3), m(7), m(11), m(15) }
};
/// @todo: TFK: Rather than applying this offset to all leafs (which might be undesirable) should this offset be applied to a node higher up in the hierarchy?
@@ -251,19 +251,19 @@ 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().ccomponents() * parent_trsf.data().ccomponents());
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 auto& parentMatrix = transformation_towrite->data().ccomponents();
double matrix_array[4][4] = {
{ (double)parentMatrix[0], (double)parentMatrix[3], (double)parentMatrix[6], (double)parentMatrix[9] },
{ (double)parentMatrix[1], (double)parentMatrix[4], (double)parentMatrix[7], (double)parentMatrix[10] },
{ (double)parentMatrix[2], (double)parentMatrix[5], (double)parentMatrix[8], (double)parentMatrix[11] },
{ (double)parentMatrix(0), (double)parentMatrix(3), (double)parentMatrix(6), (double)parentMatrix(9) },
{ (double)parentMatrix(1), (double)parentMatrix(4), (double)parentMatrix(7), (double)parentMatrix(10) },
{ (double)parentMatrix(2), (double)parentMatrix(5), (double)parentMatrix(8), (double)parentMatrix(11) },
{ 0, 0, 0, 1 }
};
@@ -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().ccomponents().inverse())));
parentNodes.push(current_node);
serializer->parentStackId.push(parent.id());
}
@@ -319,19 +319,17 @@ void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::write
openEffect(material_uri + "-fx");
COLLADASW::EffectProfile effect(mSW);
effect.setShaderType(COLLADASW::EffectProfile::LAMBERT);
if (material.diffuse) {
const auto& diffuse = *material.diffuse.get().components;
effect.setDiffuse(COLLADASW::ColorOrTexture(COLLADASW::Color(diffuse[0],diffuse[1],diffuse[2])));
}
if (material.specular) {
const auto& specular = *material.specular.get().components;
const auto& diffuse = material.diffuse.ccomponents();
effect.setDiffuse(COLLADASW::ColorOrTexture(COLLADASW::Color(diffuse[0],diffuse[1],diffuse[2])));
if (material.specular.components_) {
const auto& specular = material.specular.ccomponents();
effect.setSpecular(COLLADASW::ColorOrTexture(COLLADASW::Color(specular[0],specular[1],specular[2])));
}
if (material.specularity) {
effect.setShininess(*material.specularity);
if (material.has_specularity()) {
effect.setShininess(material.specularity);
}
if (material.transparency) {
const double transparency = *material.transparency;
if (material.has_transparency()) {
const double transparency = material.transparency;
if (transparency > 0) {
// The default opacity mode for Collada is A_ONE, which apparently indicates a
// transparency value of 1 to be fully opaque. Hence transparency is inverted.
@@ -352,10 +350,10 @@ void ColladaSerializer::ColladaExporter::ColladaMaterials::add(const ifcopenshel
// @todo apparently material.name is unitialized in some cases now.
std::string material_name = material.name.get_value_or("missing-material");
std::string material_name = material.name;
if (material_name.empty()) {
material_name = "missing-material-" + *material.name;
material_name = "missing-material-" + material.name;
}
collada_id(material_name);
+11 -13
View File
@@ -80,7 +80,7 @@ void GltfSerializer::writeHeader() {
int GltfSerializer::writeMaterial(const ifcopenshell::geometry::taxonomy::style& style) {
// @todo is it safe to always dereference this optional?
const std::string& name = *style.name;
const std::string& name = style.name;
auto it = materials_.find(name);
if (it != materials_.end()) {
@@ -92,18 +92,16 @@ int GltfSerializer::writeMaterial(const ifcopenshell::geometry::taxonomy::style&
std::array<double, 4> base;
base.fill(1.0);
if (style.diffuse) {
for (int i = 0; i < 3; ++i) {
base[i] = (*style.diffuse->components)[i];
}
for (int i = 0; i < 3; ++i) {
base[i] = style.diffuse.ccomponents()(i);
}
if (style.transparency) {
base[3] = 1. - *style.transparency;
if (style.has_transparency()) {
base[3] = 1. - style.transparency;
}
json_["materials"].push_back({ {"pbrMetallicRoughness", {{"baseColorFactor", base}, {"metallicFactor", 0}}} });
if (style.transparency && *style.transparency > 1.e-9) {
if (style.has_transparency() && style.transparency > 1.e-9) {
json_["materials"].back()["alphaMode"] = "BLEND";
}
@@ -167,14 +165,14 @@ void GltfSerializer::write(const ifcopenshell::geometry::TriangulationElement* o
node_array_.push_back(json_["nodes"].size());
const double* m = o->transformation().data().components->data();
const auto& m = o->transformation().data().ccomponents();
// nb: note that this applies the Y-UP transform.
const std::array<double, 16> matrix_flat = {
m[ 0], m[ 2], -m[ 1], m[ 3],
m[ 4], m[ 6], -m[ 5], m[ 7],
m[ 8], m[10], -m[ 9], m[11],
m[12], m[14], -m[13], m[15]
m( 0), m( 2), -m( 1), m( 3),
m( 4), m( 6), -m( 5), m( 7),
m( 8), m(10), -m( 9), m(11),
m(12), m(14), -m(13), m(15)
};
static const std::array<double, 16> identity_matrix = {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
+1 -1
View File
@@ -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->ccomponents()(3, 2);
setSectionHeight(Z + 1.);
Logger::Warning("No building storeys encountered, used for reference:", product);
return;
+12 -17
View File
@@ -61,24 +61,21 @@ void WaveFrontOBJSerializer::writeHeader() {
void WaveFrontOBJSerializer::writeMaterial(const ifcopenshell::geometry::taxonomy::style& style)
{
// @todo original_name
std::string material_name = *(settings().get(SerializerSettings::USE_MATERIAL_NAMES)
? style.name : style.name);
std::string material_name = style.name;
IfcUtil::sanitate_material_name(material_name);
mtl_stream << "newmtl " << material_name << "\n";
if (style.diffuse) {
auto diffuse = style.diffuse->components;
mtl_stream << "Kd " << diffuse[0] << " " << diffuse[1] << " " << diffuse[2] << "\n";
const auto& diffuse = style.diffuse.ccomponents();
mtl_stream << "Kd " << diffuse(0) << " " << diffuse(1) << " " << diffuse(2) << "\n";
if (style.specular.components_) {
const auto& specular = style.specular.ccomponents();
mtl_stream << "Ks " << specular(0) << " " << specular(1) << " " << specular(2) << "\n";
}
if (style.specular) {
auto specular = style.specular->components;
mtl_stream << "Ks " << specular[0] << " " << specular[1] << " " << specular[2] << "\n";
if (style.has_specularity()) {
mtl_stream << "Ns " << style.specularity << "\n";
}
if (style.specularity) {
mtl_stream << "Ns " << *style.specularity << "\n";
}
if (style.transparency) {
const double transparency = 1.0 - *style.transparency;
if (style.has_transparency()) {
const double transparency = 1.0 - style.transparency;
if (transparency < 1) {
mtl_stream << "d " << transparency << "\n";
}
@@ -124,8 +121,7 @@ void WaveFrontOBJSerializer::write(const ifcopenshell::geometry::TriangulationEl
if (material_id != previous_material_id) {
const ifcopenshell::geometry::taxonomy::style& material = mesh.materials()[material_id];
// @todo original_name
std::string material_name = *(settings().get(SerializerSettings::USE_MATERIAL_NAMES)
? material.name : material.name);
std::string material_name = material.name;
IfcUtil::sanitate_material_name(material_name);
obj_stream << "usemtl " << material_name << "\n";
if (materials.find(material_name) == materials.end()) {
@@ -169,8 +165,7 @@ void WaveFrontOBJSerializer::write(const ifcopenshell::geometry::TriangulationEl
if (material_id != previous_material_id) {
const ifcopenshell::geometry::taxonomy::style& material = mesh.materials()[material_id];
// @todo original_name
std::string material_name = *(settings().get(SerializerSettings::USE_MATERIAL_NAMES)
? material.name : material.name);
std::string material_name = material.name;
IfcUtil::sanitate_material_name(material_name);
obj_stream << "usemtl " << material_name << "\n";
if (materials.find(material_name) == materials.end()) {
@@ -131,7 +131,7 @@ boost::optional<std::string> 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->ccomponents()(j, i);
stream << trsf_value;
if (i < 3 && j < 3) {
stream << " ";