mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 10:33:20 +00:00
Proceed with merge
This commit is contained in:
@@ -21,7 +21,8 @@
|
||||
|
||||
#include "HdfSerializer.h"
|
||||
|
||||
#include "../ifcgeom_schema_agnostic/IfcGeomRenderStyles.h"
|
||||
#include "../ifcgeom/IfcGeomRenderStyles.h"
|
||||
#include "../ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h"
|
||||
|
||||
#include "../ifcparse/utils.h"
|
||||
|
||||
@@ -232,28 +233,19 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
void HdfSerializer::read_surface_style(surface_style_serialization& s, std::shared_ptr<IfcGeom::SurfaceStyle>& style_ptr) {
|
||||
void HdfSerializer::read_surface_style(surface_style_serialization& s, ifcopenshell::geometry::taxonomy::style& gss) {
|
||||
if (strlen(s.name) || s.id) {
|
||||
if (strlen(s.name) && s.id) {
|
||||
style_ptr = std::make_shared<IfcGeom::SurfaceStyle>(s.id, s.name);
|
||||
} else if (strlen(s.name)) {
|
||||
style_ptr = std::make_shared<IfcGeom::SurfaceStyle>(s.name);
|
||||
} else if (s.id) {
|
||||
style_ptr = std::make_shared<IfcGeom::SurfaceStyle>(s.id);
|
||||
}
|
||||
auto& gss = *style_ptr;
|
||||
|
||||
if (s.diffuse[0] == s.diffuse[0]) {
|
||||
gss.Diffuse().emplace(s.diffuse[0], s.diffuse[1], s.diffuse[2]);
|
||||
gss.diffuse = ifcopenshell::geometry::taxonomy::colour(s.diffuse[0], s.diffuse[1], s.diffuse[2]);
|
||||
}
|
||||
if (s.specular[0] == s.specular[0]) {
|
||||
gss.Specular().emplace(s.specular[0], s.specular[1], s.specular[2]);
|
||||
gss.specular = ifcopenshell::geometry::taxonomy::colour(s.specular[0], s.specular[1], s.specular[2]);
|
||||
}
|
||||
if (s.transparency == s.transparency) {
|
||||
gss.Transparency() = s.transparency;
|
||||
gss.transparency = s.transparency;
|
||||
}
|
||||
if (s.specularity == s.specularity) {
|
||||
gss.Specularity() = s.specularity;
|
||||
gss.specularity = s.specularity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,15 +274,12 @@ IfcGeom::Element* HdfSerializer::read(IfcParse::IfcFile& f, const std::string& g
|
||||
std::string context = read_scalar_attribute<std::string>(element_group, "context");
|
||||
std::string unique_id = read_scalar_attribute<std::string>(element_group, "unique_id");
|
||||
|
||||
gp_Trsf trsf;
|
||||
ifcopenshell::geometry::taxonomy::matrix4 trsf;
|
||||
auto placeds = element_group.openDataSet(DATASET_NAME_PLACEMENT);
|
||||
double m44[4][4];
|
||||
placeds.read(m44, H5::PredType::NATIVE_DOUBLE);
|
||||
trsf.SetValues(
|
||||
m44[0][0], m44[0][1], m44[0][2], m44[0][3],
|
||||
m44[1][0], m44[1][1], m44[1][2], m44[1][3],
|
||||
m44[2][0], m44[2][1], m44[2][2], m44[2][3]
|
||||
);
|
||||
// @todo check
|
||||
trsf.components() << Eigen::Map<Eigen::Matrix4d>(&m44[0][0]);
|
||||
|
||||
auto representation_group = element_group.openGroup(representation_id_str);
|
||||
std::string geom_id = read_scalar_attribute<std::string>(representation_group, "geom_id");
|
||||
@@ -353,66 +342,27 @@ IfcGeom::Element* HdfSerializer::read(IfcParse::IfcFile& f, const std::string& g
|
||||
brepDataset.read(parts.data(), compound);
|
||||
}
|
||||
|
||||
IfcGeom::IfcRepresentationShapeItems shapes;
|
||||
IfcGeom::ConversionResults shapes;
|
||||
|
||||
for (auto& part : parts) {
|
||||
TopoDS_Shape shp = read_shape(part.shape_serialization);
|
||||
|
||||
// The gp_GTrsf(Mat, V) constructor isn't very smart in that
|
||||
// it sets the Form to gp_Other. This, in turn, then means that
|
||||
// in IfcOpenShell when the BRepElement is cast to a TopoDS_Compound
|
||||
// (happens e.g in SVG and Python), and the trsf is multiplied into
|
||||
// the shape, it is automatically converted to a Nurbs object.
|
||||
// For this reason we do a quick identity check so that we in that
|
||||
// case can keep the Form at gp_Identity. Better yet would be to
|
||||
// do a full decomposition of the matrix in Translation Rotation and
|
||||
// Scale components and use the OCCT APIs to reconstruct the Trsf
|
||||
// from that.
|
||||
// @todo check
|
||||
ifcopenshell::geometry::taxonomy::matrix4 matrix;
|
||||
matrix.components() << Eigen::Map<Eigen::Matrix4d>(&part.matrix[0][0]);
|
||||
|
||||
gp_Mat M(
|
||||
part.matrix[0][0], part.matrix[0][1], part.matrix[0][2],
|
||||
part.matrix[1][0], part.matrix[1][1], part.matrix[1][2],
|
||||
part.matrix[2][0], part.matrix[2][1], part.matrix[2][2]
|
||||
);
|
||||
|
||||
bool is_identity = true;
|
||||
|
||||
// quick identity test
|
||||
|
||||
for (int i = 1; i < 4; ++i) {
|
||||
for (int j = 1; j < 4; ++j) {
|
||||
if (std::fabs(M.Row(i).Coord(j) - ((i == j) ? 1.0 : 0.0)) > 1.e-9) {
|
||||
is_identity = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gp_XYZ V(
|
||||
part.matrix[3][0], part.matrix[3][1], part.matrix[3][2]
|
||||
);
|
||||
|
||||
if (gp_Pnt(V).Distance(gp::Origin()) > 1.e-9) {
|
||||
is_identity = false;
|
||||
}
|
||||
|
||||
gp_GTrsf trsf;
|
||||
auto style_ptr = new ifcopenshell::geometry::taxonomy::style;
|
||||
read_surface_style(part.surface_style, *style_ptr);
|
||||
|
||||
if (!is_identity) {
|
||||
trsf = gp_GTrsf(M, V);
|
||||
trsf.SetForm();
|
||||
}
|
||||
|
||||
std::shared_ptr<IfcGeom::SurfaceStyle> style_ptr;
|
||||
read_surface_style(part.surface_style, style_ptr);
|
||||
|
||||
shapes.push_back(IfcGeom::IfcRepresentationShapeItem(part.id, trsf, shp, style_ptr));
|
||||
shapes.push_back(IfcGeom::ConversionResult(part.id, matrix, new ifcopenshell::geometry::OpenCascadeShape(shp), style_ptr));
|
||||
}
|
||||
|
||||
// World coordinates can be applied post-hoc
|
||||
if (settings_.get(IfcGeom::IteratorSettings::USE_WORLD_COORDS) && !(stored_settings & IfcGeom::IteratorSettings::USE_WORLD_COORDS)) {
|
||||
for (IfcGeom::IfcRepresentationShapeItems::iterator it = shapes.begin(); it != shapes.end(); ++it) {
|
||||
for (IfcGeom::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++it) {
|
||||
it->prepend(trsf);
|
||||
}
|
||||
trsf = gp_Trsf();
|
||||
trsf = ifcopenshell::geometry::taxonomy::matrix4();
|
||||
}
|
||||
|
||||
brep_geometry = boost::shared_ptr<IfcGeom::Representation::BRep>(new IfcGeom::Representation::BRep(element_settings, geom_id, shapes));
|
||||
@@ -456,7 +406,7 @@ IfcGeom::Element* HdfSerializer::read(IfcParse::IfcFile& f, const std::string& g
|
||||
ds.read(surface_styles.data(), style_compound);
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<IfcGeom::SurfaceStyle>> surface_style_ptrs(surface_styles.size());
|
||||
std::vector<ifcopenshell::geometry::taxonomy::style> surface_style_ptrs(surface_styles.size());
|
||||
|
||||
for (size_t i = 0; i < surface_styles.size(); ++i) {
|
||||
read_surface_style(surface_styles[i], surface_style_ptrs[i]);
|
||||
@@ -497,21 +447,6 @@ IfcGeom::Element* HdfSerializer::read(IfcParse::IfcFile& f, const std::string& g
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::array<std::array<double, 4>, 4> gtrsf_to_matrix(const gp_GTrsf& trsf) {
|
||||
std::array<std::array<double, 4>, 4> arr;
|
||||
|
||||
for (int i = 1; i < 5; ++i) {
|
||||
for (int j = 1; j < 4; ++j) {
|
||||
arr[i-1][j-1] = trsf.Value(j, i);
|
||||
}
|
||||
arr[i - 1][3] = i == 4 ? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
|
||||
H5::Group HdfSerializer::write(const IfcGeom::Element* o) {
|
||||
try {
|
||||
return file.openGroup(o->guid());
|
||||
@@ -552,12 +487,13 @@ H5::Group HdfSerializer::write(const IfcGeom::Element* o) {
|
||||
H5::DataSpace dataspace_4x4(2, dims_4x4);
|
||||
|
||||
auto placement_dataset = element_group.createDataSet(DATASET_NAME_PLACEMENT, H5::PredType::NATIVE_DOUBLE, dataspace_4x4);
|
||||
const std::vector<double>& m43 = o->transformation().matrix().data();
|
||||
const auto& m = o->transformation().data().ccomponents();
|
||||
// @todo check, is this needed, can we use the storage of Eigen?
|
||||
double m44[4][4] = {
|
||||
{ m43[0], m43[3], m43[6], m43[9] },
|
||||
{ m43[1], m43[4], m43[7], m43[10] },
|
||||
{ m43[2], m43[5], m43[8], m43[11] },
|
||||
{ 0, 0, 0, 1 }
|
||||
{ m(0,0), m(1,0), m(2,0), m(3,0) },
|
||||
{ m(0,1), m(1,1), m(2,1), m(3,1) },
|
||||
{ m(0,2), m(1,2), m(2,2), m(3,2) },
|
||||
{ m(0,3), m(1,3), m(2,3), m(3,3) }
|
||||
};
|
||||
placement_dataset.write(m44, H5::PredType::NATIVE_DOUBLE);
|
||||
|
||||
@@ -588,25 +524,26 @@ H5::Group HdfSerializer::createRepresentationGroup(const H5::Group& element_grou
|
||||
return representation_group;
|
||||
}
|
||||
|
||||
void HdfSerializer::write_style(surface_style_serialization& data, const IfcGeom::SurfaceStyle& s) {
|
||||
data.name = s.Name().c_str();
|
||||
data.original_name = s.original_name().c_str();
|
||||
data.id = s.Id().get_value_or(0);
|
||||
if (s.Diffuse()) {
|
||||
data.diffuse[0] = s.Diffuse()->R();
|
||||
data.diffuse[1] = s.Diffuse()->G();
|
||||
data.diffuse[2] = s.Diffuse()->B();
|
||||
void HdfSerializer::write_style(surface_style_serialization& data, const ifcopenshell::geometry::taxonomy::style& s) {
|
||||
data.name = s.name.c_str();
|
||||
// @todo
|
||||
data.original_name = s.name.c_str();
|
||||
data.id = s.instance->data().id();
|
||||
if (s.diffuse) {
|
||||
data.diffuse[0] = s.diffuse.ccomponents()(0);
|
||||
data.diffuse[1] = s.diffuse.ccomponents()(1);
|
||||
data.diffuse[2] = s.diffuse.ccomponents()(2);
|
||||
}
|
||||
if (s.Specular()) {
|
||||
data.specular[0] = s.Specular()->R();
|
||||
data.specular[1] = s.Specular()->G();
|
||||
data.specular[2] = s.Specular()->B();
|
||||
if (s.specular) {
|
||||
data.specular[0] = s.specular.ccomponents()(0);
|
||||
data.specular[1] = s.specular.ccomponents()(1);
|
||||
data.specular[2] = s.specular.ccomponents()(2);
|
||||
}
|
||||
if (s.Transparency()) {
|
||||
data.transparency = *s.Transparency();
|
||||
if (s.transparency == s.transparency) {
|
||||
data.transparency = s.transparency;
|
||||
}
|
||||
if (s.Specularity()) {
|
||||
data.specularity = *s.Specularity();
|
||||
if (s.specularity == s.specularity) {
|
||||
data.specularity = s.specularity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -636,13 +573,20 @@ void HdfSerializer::write(const IfcGeom::BRepElement* o) {
|
||||
size_t i = 0;
|
||||
for (auto it = o->geometry().begin(); it != o->geometry().end(); ++it, ++i) {
|
||||
parts[i].id = it->ItemId();
|
||||
std::array<std::array<double, 4>, 4> arr = gtrsf_to_matrix(it->Placement());
|
||||
const auto& m = o->transformation().data().ccomponents();
|
||||
// @todo check, is this needed, can we use the storage of Eigen?
|
||||
std::array<std::array<double, 4>, 4> arr = { {
|
||||
{ { m(0,0), m(1,0), m(2,0), m(3,0) } },
|
||||
{ { m(0,1), m(1,1), m(2,1), m(3,1) } },
|
||||
{ { m(0,2), m(1,2), m(2,2), m(3,2) } },
|
||||
{ { m(0,3), m(1,3), m(2,3), m(3,3) } }
|
||||
} };
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
std::copy(arr[j].begin(), arr[j].end(), parts[i].matrix[j]);
|
||||
}
|
||||
|
||||
brep_strings.emplace_back();
|
||||
write_shape(it->Shape(), brep_strings.back());
|
||||
write_shape(((ifcopenshell::geometry::OpenCascadeShape*)it->Shape())->shape(), brep_strings.back());
|
||||
|
||||
parts[i].surface_style = { "", "", 0, {nan,nan,nan}, {nan,nan,nan}, nan, nan };
|
||||
if (it->hasStyle()) {
|
||||
@@ -710,7 +654,7 @@ void HdfSerializer::write(const IfcGeom::TriangulationElement* o) {
|
||||
data.reserve(ts.size());
|
||||
for (auto& m : ts) {
|
||||
data.emplace_back();
|
||||
write_style(data.back(), m.get_style());
|
||||
write_style(data.back(), m);
|
||||
}
|
||||
|
||||
auto ds = meshGroup.createDataSet(DATASET_NAME_MATERIALS, dt, dataspace);
|
||||
|
||||
Reference in New Issue
Block a user