2021-02-12 17:32:43 +01:00
|
|
|
/********************************************************************************
|
|
|
|
|
* *
|
|
|
|
|
* This file is part of IfcOpenShell. *
|
|
|
|
|
* *
|
|
|
|
|
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
|
|
|
|
* it under the terms of the Lesser GNU General Public License as published by *
|
|
|
|
|
* the Free Software Foundation, either version 3.0 of the License, or *
|
|
|
|
|
* (at your option) any later version. *
|
|
|
|
|
* *
|
|
|
|
|
* IfcOpenShell is distributed in the hope that it will be useful, *
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
|
* Lesser GNU General Public License for more details. *
|
|
|
|
|
* *
|
|
|
|
|
* You should have received a copy of the Lesser GNU General Public License *
|
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
|
|
|
|
* *
|
|
|
|
|
********************************************************************************/
|
|
|
|
|
|
2023-03-22 11:17:14 +01:00
|
|
|
#if defined(WITH_HDF5) && defined(IFOPSH_WITH_OPENCASCADE)
|
2021-02-12 17:32:43 +01:00
|
|
|
|
|
|
|
|
#include "HdfSerializer.h"
|
|
|
|
|
|
2023-03-21 20:15:01 +01:00
|
|
|
#include "../ifcgeom/IfcGeomRenderStyles.h"
|
|
|
|
|
#include "../ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h"
|
2021-02-12 17:32:43 +01:00
|
|
|
|
|
|
|
|
#include "../ifcparse/utils.h"
|
|
|
|
|
|
2021-10-08 15:38:46 +02:00
|
|
|
#include <BRepTools_ShapeSet.hxx>
|
|
|
|
|
#include <BinTools_ShapeSet.hxx>
|
2021-02-12 17:32:43 +01:00
|
|
|
#include <boost/lexical_cast.hpp>
|
2021-02-14 12:23:43 +01:00
|
|
|
|
2021-10-08 15:38:46 +02:00
|
|
|
#include <iomanip>
|
|
|
|
|
#include <numeric>
|
|
|
|
|
#include <functional>
|
2025-08-08 16:34:59 +05:00
|
|
|
#include <cmath>
|
2026-06-04 22:23:19 +01:00
|
|
|
#include <cstdint>
|
2021-10-08 15:38:46 +02:00
|
|
|
|
|
|
|
|
#ifdef USE_BINARY
|
|
|
|
|
#define write_shape write_binary
|
|
|
|
|
#define read_shape read_binary
|
|
|
|
|
#else
|
|
|
|
|
#define write_shape write_text
|
|
|
|
|
#define read_shape read_text
|
|
|
|
|
#endif
|
|
|
|
|
|
2021-11-02 11:39:49 +01:00
|
|
|
herr_t print_stack(hid_t /*estack*/, void*) {
|
2021-10-08 15:38:46 +02:00
|
|
|
// For debugging: when using IfcConvert on Windows with wcout,
|
|
|
|
|
// it's difficult to get console output of HDF5 stack traces.
|
2021-11-02 11:39:49 +01:00
|
|
|
/*
|
2021-10-08 15:38:46 +02:00
|
|
|
auto f = fopen("temp.txt", "w");
|
|
|
|
|
H5Eprint(estack, f);
|
|
|
|
|
fclose(f);
|
|
|
|
|
*/
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2021-02-14 12:23:43 +01:00
|
|
|
|
2026-07-16 16:21:28 +05:00
|
|
|
HdfSerializer::HdfSerializer(const std::string& hdf_filename, const ifcopenshell::geometry::Settings& geometry_settings, const ifcopenshell::geometry::SerializerSettings& settings, bool read_only, Logger* logger)
|
|
|
|
|
: GeometrySerializer(geometry_settings, settings, logger_or_root(logger))
|
2021-02-19 17:03:41 +01:00
|
|
|
, hdf_filename(hdf_filename)
|
2021-10-08 15:38:46 +02:00
|
|
|
, settings_(settings)
|
2021-02-12 17:32:43 +01:00
|
|
|
{
|
2021-10-08 15:38:46 +02:00
|
|
|
H5E_auto2_t fn = &print_stack;
|
|
|
|
|
H5::Exception::setAutoPrint(fn, nullptr);
|
2021-11-28 19:33:45 +00:00
|
|
|
|
2021-10-08 15:38:46 +02:00
|
|
|
try {
|
2021-11-28 19:33:45 +00:00
|
|
|
file = H5::H5File(hdf_filename, read_only
|
|
|
|
|
? H5F_ACC_RDONLY
|
|
|
|
|
: (H5F_ACC_RDWR | H5F_ACC_CREAT));
|
|
|
|
|
} catch (H5::Exception& e) {
|
|
|
|
|
throw IfcParse::IfcException(e.getDetailMsg());
|
2021-10-08 15:38:46 +02:00
|
|
|
}
|
2021-11-28 19:33:45 +00:00
|
|
|
|
2021-10-08 15:38:46 +02:00
|
|
|
str_type = H5::StrType(H5::PredType::C_S1, H5T_VARIABLE);
|
|
|
|
|
|
|
|
|
|
#ifdef USE_BINARY
|
|
|
|
|
auto uint_type = H5::PredType::NATIVE_UINT8;
|
|
|
|
|
shape_type = H5::VarLenType(&uint_type);
|
|
|
|
|
#else
|
|
|
|
|
shape_type = str_type;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
hsize_t dims_3[1]{ 3 };
|
|
|
|
|
double3 = H5::ArrayType(H5::PredType::NATIVE_DOUBLE, 1, dims_3);
|
|
|
|
|
|
|
|
|
|
style_compound = H5::CompType(sizeof(surface_style_serialization));
|
|
|
|
|
style_compound.insertMember("name", HOFFSET(surface_style_serialization, name), str_type);
|
|
|
|
|
style_compound.insertMember("original_name", HOFFSET(surface_style_serialization, original_name), str_type);
|
|
|
|
|
style_compound.insertMember("id", HOFFSET(surface_style_serialization, id), H5::PredType::NATIVE_INT);
|
|
|
|
|
style_compound.insertMember("diffuse", HOFFSET(surface_style_serialization, diffuse), double3);
|
|
|
|
|
style_compound.insertMember("specular", HOFFSET(surface_style_serialization, specular), double3);
|
|
|
|
|
style_compound.insertMember("transparency", HOFFSET(surface_style_serialization, transparency), H5::PredType::NATIVE_DOUBLE);
|
|
|
|
|
style_compound.insertMember("specularity", HOFFSET(surface_style_serialization, specularity), H5::PredType::NATIVE_DOUBLE);
|
|
|
|
|
|
|
|
|
|
hsize_t dims_4x4[2]{ 4, 4 };
|
|
|
|
|
double4x4 = H5::ArrayType(H5::PredType::NATIVE_DOUBLE, 2, dims_4x4);
|
|
|
|
|
|
|
|
|
|
compound = H5::CompType(sizeof(brep_element));
|
|
|
|
|
compound.insertMember("id", HOFFSET(brep_element, id), H5::PredType::NATIVE_INT);
|
|
|
|
|
compound.insertMember("matrix", HOFFSET(brep_element, matrix), double4x4);
|
|
|
|
|
compound.insertMember("shape_serialization", HOFFSET(brep_element, shape_serialization), shape_type);
|
|
|
|
|
compound.insertMember("surface_style_id", HOFFSET(brep_element, surface_style), style_compound);
|
|
|
|
|
}
|
2021-02-15 21:17:35 +01:00
|
|
|
|
2021-02-12 17:32:43 +01:00
|
|
|
bool HdfSerializer::ready() {
|
2021-02-17 17:20:03 +01:00
|
|
|
return true;
|
2021-02-12 17:32:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void HdfSerializer::writeHeader() {
|
2021-10-08 15:38:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
template <typename T>
|
|
|
|
|
H5::DataType h5_datatype_for_cpp();
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
H5::DataType h5_datatype_for_cpp<int>() {
|
|
|
|
|
return H5::PredType::NATIVE_INT;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-07 19:23:48 +01:00
|
|
|
template <>
|
|
|
|
|
H5::DataType h5_datatype_for_cpp<uint64_t>() {
|
|
|
|
|
return H5::PredType::NATIVE_UINT64;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-08 15:38:46 +02:00
|
|
|
template <>
|
|
|
|
|
H5::DataType h5_datatype_for_cpp<double>() {
|
|
|
|
|
return H5::PredType::NATIVE_DOUBLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
H5::DataType h5_datatype_for_cpp<std::string>() {
|
|
|
|
|
return H5::StrType(H5::PredType::C_S1, H5T_VARIABLE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
void do_read(H5::Attribute& attr, T& val) {
|
|
|
|
|
attr.read(h5_datatype_for_cpp<T>(), &val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
void do_read(H5::Attribute& attr, std::string& val) {
|
|
|
|
|
attr.read(h5_datatype_for_cpp<std::string>(), val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
T read_scalar_attribute(H5::H5Object& l, const std::string& name) {
|
|
|
|
|
auto attr = l.openAttribute(name);
|
|
|
|
|
auto space = attr.getSpace();
|
|
|
|
|
int rank = space.getSimpleExtentNdims();
|
|
|
|
|
// A scalar dataspace, H5S_SCALAR, has a single element, though that
|
|
|
|
|
// element may be of a complex datatype, such as a compound or array
|
|
|
|
|
// datatype. By convention, the rank of a scalar dataspace is always
|
|
|
|
|
// 0 (zero);
|
|
|
|
|
if (rank != 0) {
|
|
|
|
|
throw std::runtime_error("Invalid");
|
|
|
|
|
}
|
|
|
|
|
T val;
|
|
|
|
|
do_read<T>(attr, val);
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#include <BinTools.hxx>
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
// https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/Part/App/TopoShape.cpp
|
|
|
|
|
TopoDS_Shape read_binary(const hvl_t& vlen) {
|
|
|
|
|
std::string s((char*)vlen.p, (size_t)vlen.len);
|
|
|
|
|
std::istringstream str(s);
|
|
|
|
|
BinTools_ShapeSet theShapeSet;
|
|
|
|
|
theShapeSet.Read(str);
|
|
|
|
|
Standard_Integer shapeId = 0, locId = 0, orient = 0;
|
|
|
|
|
BinTools::GetInteger(str, shapeId);
|
|
|
|
|
if (shapeId <= 0 || shapeId > theShapeSet.NbShapes()) {
|
|
|
|
|
throw std::runtime_error("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BinTools::GetInteger(str, locId);
|
|
|
|
|
BinTools::GetInteger(str, orient);
|
|
|
|
|
TopAbs_Orientation anOrient = static_cast<TopAbs_Orientation>(orient);
|
|
|
|
|
|
|
|
|
|
TopoDS_Shape shp = theShapeSet.Shape(shapeId);
|
|
|
|
|
shp.Location(theShapeSet.Locations().Location(locId));
|
|
|
|
|
shp.Orientation(anOrient);
|
|
|
|
|
|
|
|
|
|
return shp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/Part/App/TopoShape.cpp
|
|
|
|
|
void write_binary(TopoDS_Shape shp, std::string& s) {
|
|
|
|
|
std::ostringstream out;
|
|
|
|
|
|
|
|
|
|
BinTools_ShapeSet theShapeSet;
|
|
|
|
|
|
|
|
|
|
Standard_Integer shapeId = theShapeSet.Add(shp);
|
|
|
|
|
Standard_Integer locId = theShapeSet.Locations().Index(shp.Location());
|
|
|
|
|
Standard_Integer orient = static_cast<int>(shp.Orientation());
|
|
|
|
|
|
|
|
|
|
theShapeSet.Write(out);
|
|
|
|
|
BinTools::PutInteger(out, shapeId);
|
|
|
|
|
BinTools::PutInteger(out, locId);
|
|
|
|
|
BinTools::PutInteger(out, orient);
|
|
|
|
|
|
|
|
|
|
s = out.str();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TopoDS_Shape read_text(const std::string& s) {
|
|
|
|
|
std::stringstream stream(s);
|
|
|
|
|
BRep_Builder B;
|
|
|
|
|
TopoDS_Shape shp;
|
|
|
|
|
BRepTools::Read(shp, stream, B);
|
|
|
|
|
return shp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void write_text(TopoDS_Shape shp, std::string& out) {
|
|
|
|
|
std::stringstream sstream;
|
|
|
|
|
BRepTools::Write(shp, sstream);
|
|
|
|
|
out = sstream.str();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
template <typename T>
|
|
|
|
|
std::vector<T> read_dataset(const H5::Group& group, const std::string& name) {
|
|
|
|
|
auto ds = group.openDataSet(name);
|
|
|
|
|
auto space = ds.getSpace();
|
|
|
|
|
int rank = space.getSimpleExtentNdims();
|
|
|
|
|
std::vector<hsize_t> dims(rank);
|
|
|
|
|
space.getSimpleExtentDims(dims.data(), NULL);
|
|
|
|
|
const hsize_t total = std::accumulate(dims.begin(), dims.end(), 1U, std::multiplies<hsize_t>());
|
|
|
|
|
std::vector<T> result(total);
|
|
|
|
|
ds.read(result.data(), h5_datatype_for_cpp<T>());
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-07 21:01:18 +05:00
|
|
|
void HdfSerializer::read_surface_style(const surface_style_serialization& s,
|
|
|
|
|
ifcopenshell::geometry::taxonomy::style& gss,
|
|
|
|
|
IfcParse::IfcFile& f) {
|
2021-10-08 15:38:46 +02:00
|
|
|
if (strlen(s.name) || s.id) {
|
2025-08-08 16:34:59 +05:00
|
|
|
if (!std::isnan(s.diffuse[0])) {
|
2023-03-21 20:15:01 +01:00
|
|
|
gss.diffuse = ifcopenshell::geometry::taxonomy::colour(s.diffuse[0], s.diffuse[1], s.diffuse[2]);
|
2021-10-08 15:38:46 +02:00
|
|
|
}
|
2025-08-08 16:34:59 +05:00
|
|
|
if (!std::isnan(s.specular[0])) {
|
2023-03-21 20:15:01 +01:00
|
|
|
gss.specular = ifcopenshell::geometry::taxonomy::colour(s.specular[0], s.specular[1], s.specular[2]);
|
2021-10-08 15:38:46 +02:00
|
|
|
}
|
2025-08-08 16:34:59 +05:00
|
|
|
if (!std::isnan(s.transparency)) {
|
2023-03-21 20:15:01 +01:00
|
|
|
gss.transparency = s.transparency;
|
2021-10-08 15:38:46 +02:00
|
|
|
}
|
2025-08-08 16:34:59 +05:00
|
|
|
if (!std::isnan(s.specularity)) {
|
2023-03-21 20:15:01 +01:00
|
|
|
gss.specularity = s.specularity;
|
2021-10-08 15:38:46 +02:00
|
|
|
}
|
2025-08-07 21:01:18 +05:00
|
|
|
if (s.id != 0) {
|
|
|
|
|
gss.instance = f.instance_by_id(s.id)->as<IfcUtil::IfcBaseEntity>();
|
|
|
|
|
}
|
2021-10-08 15:38:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-29 10:41:21 +02:00
|
|
|
void HdfSerializer::remove(const std::string& guid) {
|
|
|
|
|
if (H5Lexists(file.getId(), guid.c_str(), H5P_DEFAULT)) {
|
|
|
|
|
file.unlink(guid);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-10-08 15:38:46 +02:00
|
|
|
|
2021-11-02 11:39:49 +01:00
|
|
|
IfcGeom::Element* HdfSerializer::read(IfcParse::IfcFile& f, const std::string& guid, const std::string& representation_id_str, read_type rt) {
|
2021-10-08 15:38:46 +02:00
|
|
|
if (!H5Lexists(file.getId(), guid.c_str(), H5P_DEFAULT)) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto element_group = file.openGroup(guid);
|
|
|
|
|
if (!H5Lexists(element_group.getId(), representation_id_str.c_str(), H5P_DEFAULT)) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int id = read_scalar_attribute<int>(element_group, "id");
|
|
|
|
|
int parent_id = read_scalar_attribute<int>(element_group, "parent_id");
|
|
|
|
|
std::string type = read_scalar_attribute<std::string>(element_group, "type");
|
|
|
|
|
std::string name = read_scalar_attribute<std::string>(element_group, "name");
|
|
|
|
|
std::string context = read_scalar_attribute<std::string>(element_group, "context");
|
|
|
|
|
std::string unique_id = read_scalar_attribute<std::string>(element_group, "unique_id");
|
|
|
|
|
|
2023-07-27 16:42:06 +08:00
|
|
|
auto trsf = ifcopenshell::geometry::taxonomy::make<ifcopenshell::geometry::taxonomy::matrix4>();
|
2021-10-08 15:38:46 +02:00
|
|
|
auto placeds = element_group.openDataSet(DATASET_NAME_PLACEMENT);
|
|
|
|
|
double m44[4][4];
|
|
|
|
|
placeds.read(m44, H5::PredType::NATIVE_DOUBLE);
|
2023-03-21 20:15:01 +01:00
|
|
|
// @todo check
|
2023-07-27 16:42:06 +08:00
|
|
|
trsf->components() << Eigen::Map<Eigen::Matrix4d>(&m44[0][0]);
|
2021-10-08 15:38:46 +02:00
|
|
|
|
2021-11-02 11:39:49 +01:00
|
|
|
auto representation_group = element_group.openGroup(representation_id_str);
|
2021-10-08 15:38:46 +02:00
|
|
|
std::string geom_id = read_scalar_attribute<std::string>(representation_group, "geom_id");
|
|
|
|
|
|
|
|
|
|
auto inst = f.instance_by_id(id)->as<IfcUtil::IfcBaseEntity>();
|
|
|
|
|
|
2021-11-06 13:16:13 +01:00
|
|
|
boost::shared_ptr<IfcGeom::Representation::BRep> brep_geometry;
|
|
|
|
|
boost::shared_ptr<IfcGeom::Representation::Triangulation> triangulation_geometry;
|
|
|
|
|
|
2021-10-08 15:38:46 +02:00
|
|
|
if (rt == READ_BREP) {
|
2021-11-06 13:16:13 +01:00
|
|
|
auto it = brep_cache_.find(representation_id_str);
|
|
|
|
|
if (it != brep_cache_.end()) {
|
|
|
|
|
brep_geometry = it->second;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
auto it = triangulation_cache_.find(representation_id_str);
|
|
|
|
|
if (it != triangulation_cache_.end()) {
|
|
|
|
|
triangulation_geometry = it->second;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rt == READ_BREP && !brep_geometry) {
|
2021-10-08 15:38:46 +02:00
|
|
|
auto brepDataset = representation_group.openDataSet(DATASET_NAME_OCCT);
|
2021-11-08 10:59:49 +01:00
|
|
|
|
2023-11-15 10:32:20 +01:00
|
|
|
/*
|
|
|
|
|
// @todo
|
|
|
|
|
|
2021-11-08 10:59:49 +01:00
|
|
|
static const auto ignored_settings =
|
|
|
|
|
// Settings that do not affect storage of brep data
|
|
|
|
|
IfcGeom::IteratorSettings::DISABLE_TRIANGULATION | IfcGeom::IteratorSettings::USE_BREP_DATA |
|
|
|
|
|
// Settings that affect which representation is considered, but cache does not need to be complete
|
|
|
|
|
IfcGeom::IteratorSettings::INCLUDE_CURVES | IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES |
|
|
|
|
|
// Only affects triangulation
|
|
|
|
|
IfcGeom::IteratorSettings::WELD_VERTICES | IfcGeom::IteratorSettings::NO_NORMALS |
|
|
|
|
|
IfcGeom::IteratorSettings::GENERATE_UVS | IfcGeom::IteratorSettings::EDGE_ARROWS |
|
|
|
|
|
// Is applied in the serializer
|
2021-12-18 16:16:44 +01:00
|
|
|
IfcGeom::IteratorSettings::ELEMENT_HIERARCHY;
|
2021-11-08 10:59:49 +01:00
|
|
|
|
2021-11-07 19:23:48 +01:00
|
|
|
auto stored_settings = read_scalar_attribute<uint64_t>(brepDataset, "settings");
|
2021-11-08 10:59:49 +01:00
|
|
|
auto requested_settings = settings_.get_raw();
|
|
|
|
|
stored_settings &= ~ignored_settings;
|
|
|
|
|
requested_settings &= ~ignored_settings;
|
|
|
|
|
|
|
|
|
|
// World coordinates can be applied post hoc
|
|
|
|
|
if (stored_settings != requested_settings && (stored_settings | IfcGeom::IteratorSettings::USE_WORLD_COORDS) != requested_settings) {
|
2021-11-07 19:23:48 +01:00
|
|
|
throw std::runtime_error("Settings mismatch");
|
|
|
|
|
}
|
2023-11-15 10:32:20 +01:00
|
|
|
*/
|
2021-10-08 15:38:46 +02:00
|
|
|
|
|
|
|
|
std::vector<brep_element> parts;
|
|
|
|
|
{
|
|
|
|
|
auto space = brepDataset.getSpace();
|
|
|
|
|
int rank = space.getSimpleExtentNdims();
|
|
|
|
|
|
|
|
|
|
if (rank != 1) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<hsize_t> dims(rank);
|
|
|
|
|
space.getSimpleExtentDims(dims.data(), NULL);
|
|
|
|
|
|
|
|
|
|
parts.resize(dims[0]);
|
|
|
|
|
brepDataset.read(parts.data(), compound);
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-21 20:15:01 +01:00
|
|
|
IfcGeom::ConversionResults shapes;
|
|
|
|
|
|
2021-10-08 15:38:46 +02:00
|
|
|
for (auto& part : parts) {
|
|
|
|
|
TopoDS_Shape shp = read_shape(part.shape_serialization);
|
|
|
|
|
|
2023-03-21 20:15:01 +01:00
|
|
|
// @todo check
|
2023-07-27 16:42:06 +08:00
|
|
|
auto matrix = ifcopenshell::geometry::taxonomy::make<ifcopenshell::geometry::taxonomy::matrix4>();
|
|
|
|
|
matrix->components() << Eigen::Map<Eigen::Matrix4d>(&part.matrix[0][0]);
|
2021-10-08 15:38:46 +02:00
|
|
|
|
2023-07-27 16:42:06 +08:00
|
|
|
auto style_ptr = ifcopenshell::geometry::taxonomy::make<ifcopenshell::geometry::taxonomy::style>();
|
2025-08-07 21:01:18 +05:00
|
|
|
read_surface_style(part.surface_style, *style_ptr, f);
|
2021-10-08 15:38:46 +02:00
|
|
|
|
2023-03-21 20:15:01 +01:00
|
|
|
shapes.push_back(IfcGeom::ConversionResult(part.id, matrix, new ifcopenshell::geometry::OpenCascadeShape(shp), style_ptr));
|
2021-10-08 15:38:46 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-15 10:32:20 +01:00
|
|
|
/*
|
|
|
|
|
// @todo
|
|
|
|
|
|
2021-11-08 10:59:49 +01:00
|
|
|
// World coordinates can be applied post-hoc
|
2021-11-07 19:23:48 +01:00
|
|
|
if (settings_.get(IfcGeom::IteratorSettings::USE_WORLD_COORDS) && !(stored_settings & IfcGeom::IteratorSettings::USE_WORLD_COORDS)) {
|
2023-03-21 20:15:01 +01:00
|
|
|
for (IfcGeom::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++it) {
|
2021-11-07 19:23:48 +01:00
|
|
|
it->prepend(trsf);
|
|
|
|
|
}
|
2023-07-27 16:42:06 +08:00
|
|
|
trsf = ifcopenshell::geometry::taxonomy::make<ifcopenshell::geometry::taxonomy::matrix4>();
|
2021-11-07 19:23:48 +01:00
|
|
|
}
|
2023-11-15 10:32:20 +01:00
|
|
|
*/
|
2021-11-07 19:23:48 +01:00
|
|
|
|
2023-11-15 10:32:20 +01:00
|
|
|
brep_geometry = boost::shared_ptr<IfcGeom::Representation::BRep>(new IfcGeom::Representation::BRep(geometry_settings(), type, geom_id, shapes));
|
2021-11-07 19:23:48 +01:00
|
|
|
|
2023-11-15 10:32:20 +01:00
|
|
|
/*
|
|
|
|
|
// @todo
|
2021-11-07 19:23:48 +01:00
|
|
|
if (!settings_.get(IfcGeom::IteratorSettings::USE_WORLD_COORDS)) {
|
|
|
|
|
brep_cache_.insert({ representation_id_str, brep_geometry });
|
|
|
|
|
}
|
2023-11-15 10:32:20 +01:00
|
|
|
*/
|
2021-11-06 13:16:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rt == READ_TRIANGULATION && !triangulation_geometry) {
|
2021-10-08 15:38:46 +02:00
|
|
|
H5::Group meshGroup;
|
|
|
|
|
try {
|
|
|
|
|
meshGroup = representation_group.openGroup(GROUP_NAME_MESH);
|
|
|
|
|
} catch (H5::Exception&) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto verts = read_dataset<double>(meshGroup, DATASET_NAME_POSITIONS);
|
|
|
|
|
auto faces = read_dataset<int>(meshGroup, DATASET_NAME_INDICES);
|
|
|
|
|
auto edges = read_dataset<int>(meshGroup, DATASET_NAME_EDGES);
|
|
|
|
|
auto normals = read_dataset<double>(meshGroup, DATASET_NAME_NORMALS);
|
|
|
|
|
auto uvcoords = read_dataset<double>(meshGroup, DATASET_NAME_UVCOORDS);
|
|
|
|
|
auto material_ids = read_dataset<int>(meshGroup, DATASET_NAME_MATERIAL_IDS);
|
2023-06-19 13:47:45 +02:00
|
|
|
auto item_ids = read_dataset<int>(meshGroup, DATASET_NAME_ITEM_IDS);
|
2024-09-25 15:15:47 +05:00
|
|
|
auto edges_item_ids = read_dataset<int>(meshGroup, DATASET_NAME_EDGES_ITEM_IDS);
|
2021-10-08 15:38:46 +02:00
|
|
|
|
|
|
|
|
std::vector<surface_style_serialization> surface_styles;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
auto ds = meshGroup.openDataSet(DATASET_NAME_MATERIALS);
|
|
|
|
|
auto space = ds.getSpace();
|
|
|
|
|
int rank = space.getSimpleExtentNdims();
|
|
|
|
|
|
|
|
|
|
if (rank != 1) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<hsize_t> dims(rank);
|
|
|
|
|
space.getSimpleExtentDims(dims.data(), NULL);
|
|
|
|
|
|
|
|
|
|
surface_styles.resize(dims[0]);
|
|
|
|
|
ds.read(surface_styles.data(), style_compound);
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-10 20:11:24 +02:00
|
|
|
std::vector<ifcopenshell::geometry::taxonomy::style::ptr> surface_style_ptrs(surface_styles.size());
|
2021-10-08 15:38:46 +02:00
|
|
|
|
|
|
|
|
for (size_t i = 0; i < surface_styles.size(); ++i) {
|
2025-08-07 20:24:13 +05:00
|
|
|
surface_style_ptrs[i] = ifcopenshell::geometry::taxonomy::make<ifcopenshell::geometry::taxonomy::style>();
|
2025-08-07 21:01:18 +05:00
|
|
|
read_surface_style(surface_styles[i], *surface_style_ptrs[i], f);
|
2021-10-08 15:38:46 +02:00
|
|
|
}
|
|
|
|
|
|
2021-11-06 13:16:13 +01:00
|
|
|
triangulation_geometry = boost::shared_ptr<IfcGeom::Representation::Triangulation>(new IfcGeom::Representation::Triangulation(
|
2023-11-15 10:32:20 +01:00
|
|
|
geometry_settings_,
|
|
|
|
|
type,
|
2021-10-08 15:38:46 +02:00
|
|
|
geom_id,
|
|
|
|
|
verts,
|
|
|
|
|
faces,
|
|
|
|
|
edges,
|
|
|
|
|
normals,
|
|
|
|
|
uvcoords,
|
|
|
|
|
material_ids,
|
2023-06-19 13:47:45 +02:00
|
|
|
surface_style_ptrs,
|
|
|
|
|
item_ids
|
2024-09-25 15:15:47 +05:00
|
|
|
, edges_item_ids
|
2021-10-08 15:38:46 +02:00
|
|
|
));
|
|
|
|
|
|
2021-11-06 13:16:13 +01:00
|
|
|
triangulation_cache_.insert({ representation_id_str, triangulation_geometry });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rt == READ_BREP) {
|
|
|
|
|
return new IfcGeom::BRepElement(id, parent_id, name, type, guid, context, trsf, brep_geometry, inst);
|
|
|
|
|
} else {
|
2021-10-08 15:38:46 +02:00
|
|
|
return new IfcGeom::TriangulationElement(
|
|
|
|
|
IfcGeom::Element(
|
2023-11-15 10:32:20 +01:00
|
|
|
geometry_settings_,
|
2021-10-08 15:38:46 +02:00
|
|
|
id,
|
|
|
|
|
parent_id,
|
|
|
|
|
name,
|
|
|
|
|
type,
|
|
|
|
|
guid,
|
|
|
|
|
context,
|
|
|
|
|
trsf,
|
|
|
|
|
inst
|
|
|
|
|
),
|
2021-11-06 13:16:13 +01:00
|
|
|
triangulation_geometry
|
|
|
|
|
);
|
2021-10-08 15:38:46 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
H5::Group HdfSerializer::write(const IfcGeom::Element* o) {
|
|
|
|
|
try {
|
|
|
|
|
return file.openGroup(o->guid());
|
|
|
|
|
} catch (H5::Exception&) {}
|
|
|
|
|
|
|
|
|
|
H5::Group element_group = file.createGroup(o->guid());
|
|
|
|
|
|
|
|
|
|
typedef std::string const & (IfcGeom::Element::*string_member_fun)(void) const;
|
|
|
|
|
typedef int (IfcGeom::Element::*int_member_fun)(void) const;
|
|
|
|
|
|
|
|
|
|
static const std::vector<std::pair<const char* const, string_member_fun>> data_pairs_string = {
|
|
|
|
|
{"type", &IfcGeom::Element::type},
|
|
|
|
|
{"name", &IfcGeom::Element::name },
|
|
|
|
|
{"guid", &IfcGeom::Element::guid },
|
|
|
|
|
{"context", &IfcGeom::Element::context },
|
|
|
|
|
{"unique_id", &IfcGeom::Element::unique_id }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const std::vector<std::pair<const char* const, int_member_fun>> data_pairs_int = {
|
|
|
|
|
{"id", &IfcGeom::Element::id},
|
|
|
|
|
{"parent_id", &IfcGeom::Element::parent_id },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
H5::DataSpace attrdspace(H5S_SCALAR);
|
|
|
|
|
|
|
|
|
|
for (auto& p : data_pairs_string) {
|
|
|
|
|
H5::Attribute att = element_group.createAttribute(p.first, str_type, attrdspace);
|
|
|
|
|
att.write(str_type, ((*o).*(p.second))());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto& p : data_pairs_int) {
|
|
|
|
|
H5::Attribute att = element_group.createAttribute(p.first, H5::PredType::NATIVE_INT, attrdspace);
|
|
|
|
|
int value = ((*o).*(p.second))();
|
|
|
|
|
att.write(H5::PredType::NATIVE_INT, &value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hsize_t dims_4x4[2]{ 4, 4 };
|
|
|
|
|
H5::DataSpace dataspace_4x4(2, dims_4x4);
|
|
|
|
|
|
|
|
|
|
auto placement_dataset = element_group.createDataSet(DATASET_NAME_PLACEMENT, H5::PredType::NATIVE_DOUBLE, dataspace_4x4);
|
2023-07-27 16:42:06 +08:00
|
|
|
const auto& m = o->transformation().data()->ccomponents();
|
2023-03-21 20:15:01 +01:00
|
|
|
// @todo check, is this needed, can we use the storage of Eigen?
|
2021-10-08 15:38:46 +02:00
|
|
|
double m44[4][4] = {
|
2023-03-21 20:15:01 +01:00
|
|
|
{ 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) }
|
2021-10-08 15:38:46 +02:00
|
|
|
};
|
|
|
|
|
placement_dataset.write(m44, H5::PredType::NATIVE_DOUBLE);
|
|
|
|
|
|
|
|
|
|
return element_group;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
H5::Group HdfSerializer::createRepresentationGroup(const H5::Group& element_group, const std::string& gid) {
|
|
|
|
|
// the part before the hyphen is the representation id
|
|
|
|
|
auto gid2 = gid;
|
|
|
|
|
auto hyphen = gid2.find("-");
|
|
|
|
|
if (hyphen != std::string::npos) {
|
|
|
|
|
gid2 = gid2.substr(0, hyphen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
H5::Group representation_group;
|
|
|
|
|
try {
|
|
|
|
|
representation_group = element_group.openGroup(gid2);
|
|
|
|
|
} catch (H5::Exception&) {
|
|
|
|
|
representation_group = element_group.createGroup(gid2);
|
|
|
|
|
|
|
|
|
|
H5::DataSpace attrdspace(H5S_SCALAR);
|
|
|
|
|
{
|
|
|
|
|
H5::Attribute att = representation_group.createAttribute("geom_id", str_type, attrdspace);
|
|
|
|
|
std::string value = gid;
|
|
|
|
|
att.write(str_type, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return representation_group;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-10 20:11:24 +02:00
|
|
|
void HdfSerializer::write_style(surface_style_serialization& data, const ifcopenshell::geometry::taxonomy::style::ptr& sptr) {
|
|
|
|
|
auto& s = *sptr;
|
2023-03-21 20:15:01 +01:00
|
|
|
data.name = s.name.c_str();
|
|
|
|
|
// @todo
|
|
|
|
|
data.original_name = s.name.c_str();
|
2025-04-11 16:15:08 +01:00
|
|
|
auto instance = s.instance->as<IfcUtil::IfcBaseClass>();
|
|
|
|
|
data.id = instance ? instance->id() : 0;
|
2023-03-21 20:15:01 +01:00
|
|
|
if (s.diffuse) {
|
|
|
|
|
data.diffuse[0] = s.diffuse.ccomponents()(0);
|
|
|
|
|
data.diffuse[1] = s.diffuse.ccomponents()(1);
|
|
|
|
|
data.diffuse[2] = s.diffuse.ccomponents()(2);
|
2021-10-08 15:38:46 +02:00
|
|
|
}
|
2023-03-21 20:15:01 +01:00
|
|
|
if (s.specular) {
|
|
|
|
|
data.specular[0] = s.specular.ccomponents()(0);
|
|
|
|
|
data.specular[1] = s.specular.ccomponents()(1);
|
|
|
|
|
data.specular[2] = s.specular.ccomponents()(2);
|
2021-10-08 15:38:46 +02:00
|
|
|
}
|
2023-03-21 20:15:01 +01:00
|
|
|
if (s.transparency == s.transparency) {
|
|
|
|
|
data.transparency = s.transparency;
|
2021-10-08 15:38:46 +02:00
|
|
|
}
|
2023-03-21 20:15:01 +01:00
|
|
|
if (s.specularity == s.specularity) {
|
|
|
|
|
data.specularity = s.specularity;
|
2021-10-08 15:38:46 +02:00
|
|
|
}
|
2021-02-12 17:32:43 +01:00
|
|
|
}
|
|
|
|
|
|
2021-02-18 10:12:29 +01:00
|
|
|
|
2021-07-11 15:00:59 +02:00
|
|
|
void HdfSerializer::write(const IfcGeom::BRepElement* o) {
|
2025-08-07 19:17:16 +05:00
|
|
|
// Currenly we only support OpenCascade shapes.
|
|
|
|
|
for (auto it = o->geometry().begin(); it != o->geometry().end(); ++it) {
|
|
|
|
|
auto shape_ptr = std::dynamic_pointer_cast<ifcopenshell::geometry::OpenCascadeShape>(it->Shape());
|
|
|
|
|
if (shape_ptr == nullptr) {
|
|
|
|
|
std::cerr << "WARNING. Only OpenCascade shapes support caching. "
|
|
|
|
|
<< "Skipping caching for item #" << it->ItemId() << "." << std::endl;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-08 15:38:46 +02:00
|
|
|
static auto nan = std::numeric_limits<double>::quiet_NaN();
|
|
|
|
|
|
2021-11-06 13:16:13 +01:00
|
|
|
auto element_group = write((const IfcGeom::Element*)o);
|
|
|
|
|
|
2023-01-13 12:10:52 +01:00
|
|
|
/*
|
|
|
|
|
// For now we disable softlinks, as it can't be safely used with delete()
|
|
|
|
|
// @todo we can still cache the serialization or read it from the file probably for a comparible speedup.
|
|
|
|
|
|
2021-11-06 13:16:13 +01:00
|
|
|
auto it = group_cache_.find(o->geometry().id());
|
|
|
|
|
if (it != group_cache_.end()) {
|
|
|
|
|
H5Lcreate_soft(it->second.c_str(), element_group.getLocId(), o->geometry().id().c_str(), H5P_DEFAULT, H5P_DEFAULT);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-01-13 12:10:52 +01:00
|
|
|
*/
|
2021-02-15 21:17:35 +01:00
|
|
|
|
2021-10-08 15:38:46 +02:00
|
|
|
H5::Group representation_group = createRepresentationGroup(element_group, o->geometry().id());
|
|
|
|
|
|
2023-01-13 12:10:52 +01:00
|
|
|
/*
|
2021-11-06 13:16:13 +01:00
|
|
|
const size_t len = H5Iget_name(representation_group.getId(), NULL, 0);
|
|
|
|
|
char* name_buffer = new char[len];
|
|
|
|
|
H5Iget_name(representation_group.getId(), name_buffer, len + 1);
|
|
|
|
|
group_cache_.insert(it, { o->geometry().id(), name_buffer });
|
|
|
|
|
delete[] name_buffer;
|
2023-01-13 12:10:52 +01:00
|
|
|
*/
|
2021-11-06 13:16:13 +01:00
|
|
|
|
2021-10-08 15:38:46 +02:00
|
|
|
std::list<std::string> brep_strings;
|
|
|
|
|
size_t num_parts = std::distance(o->geometry().begin(), o->geometry().end());
|
|
|
|
|
brep_element* parts = new brep_element[num_parts];
|
|
|
|
|
size_t i = 0;
|
|
|
|
|
for (auto it = o->geometry().begin(); it != o->geometry().end(); ++it, ++i) {
|
|
|
|
|
parts[i].id = it->ItemId();
|
2023-07-27 16:42:06 +08:00
|
|
|
const auto& m = o->transformation().data()->ccomponents();
|
2023-03-21 20:15:01 +01:00
|
|
|
// @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) } }
|
|
|
|
|
} };
|
2021-10-08 15:38:46 +02:00
|
|
|
for (int j = 0; j < 4; ++j) {
|
|
|
|
|
std::copy(arr[j].begin(), arr[j].end(), parts[i].matrix[j]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
brep_strings.emplace_back();
|
2025-08-07 19:17:16 +05:00
|
|
|
// OpenCascadeShape type ensured by the check at the method start.
|
2023-11-02 09:04:34 +01:00
|
|
|
write_shape(std::static_pointer_cast<ifcopenshell::geometry::OpenCascadeShape>(it->Shape())->shape(), brep_strings.back());
|
2021-02-18 10:41:54 +01:00
|
|
|
|
2021-10-08 15:38:46 +02:00
|
|
|
parts[i].surface_style = { "", "", 0, {nan,nan,nan}, {nan,nan,nan}, nan, nan };
|
|
|
|
|
if (it->hasStyle()) {
|
2024-06-10 20:11:24 +02:00
|
|
|
auto s = it->StylePtr();
|
2021-10-08 15:38:46 +02:00
|
|
|
write_style(parts[i].surface_style, s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef USE_BINARY
|
|
|
|
|
const auto& s = brep_strings.back();
|
|
|
|
|
parts[i].shape_serialization.p = new char[s.size()];
|
|
|
|
|
memcpy(parts[i].shape_serialization.p, s.c_str(), s.size());
|
|
|
|
|
parts[i].shape_serialization.len = s.size();
|
|
|
|
|
#else
|
|
|
|
|
parts[i].shape_serialization = brep_strings.back().c_str();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2021-02-14 12:23:43 +01:00
|
|
|
|
2021-10-08 15:38:46 +02:00
|
|
|
hsize_t dimsp[1]{ num_parts };
|
|
|
|
|
H5::DataSpace dataspace_parts(1, dimsp);
|
2021-02-12 17:32:43 +01:00
|
|
|
|
2021-10-08 15:38:46 +02:00
|
|
|
auto brepDataset = representation_group.createDataSet(DATASET_NAME_OCCT, compound, dataspace_parts);
|
|
|
|
|
brepDataset.write(parts, compound);
|
2021-11-07 19:23:48 +01:00
|
|
|
|
|
|
|
|
H5::DataSpace attrdspace(H5S_SCALAR);
|
|
|
|
|
H5::Attribute att = brepDataset.createAttribute("settings", H5::PredType::NATIVE_UINT64, attrdspace);
|
2023-11-15 10:32:20 +01:00
|
|
|
/*
|
|
|
|
|
// @todo
|
2021-11-07 19:23:48 +01:00
|
|
|
uint64_t value = o->geometry().settings().get_raw();
|
2023-11-15 10:32:20 +01:00
|
|
|
*/
|
|
|
|
|
uint64_t value = 0;
|
2021-11-07 19:23:48 +01:00
|
|
|
att.write(H5::PredType::NATIVE_UINT64, &value);
|
2021-10-08 15:38:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
void write_dataset(const H5::Group& group, const std::string& name, const std::vector<T>& ts, size_t stride) {
|
|
|
|
|
hsize_t d[2]{ ts.size() / stride, stride };
|
|
|
|
|
H5::DataSpace dataspace(stride == 1 ? 1 : 2, d);
|
|
|
|
|
auto dt = h5_datatype_for_cpp<T>();
|
|
|
|
|
|
|
|
|
|
auto ds = group.createDataSet(name, dt, dataspace);
|
|
|
|
|
ds.write(ts.data(), dt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void HdfSerializer::write(const IfcGeom::TriangulationElement* o) {
|
|
|
|
|
auto element_group = write((const IfcGeom::Element*)o);
|
|
|
|
|
|
|
|
|
|
const auto& mesh = o->geometry();
|
|
|
|
|
H5::Group representation_group = createRepresentationGroup(element_group, o->geometry().id());
|
|
|
|
|
H5::Group meshGroup = representation_group.createGroup(GROUP_NAME_MESH);
|
|
|
|
|
|
|
|
|
|
write_dataset(meshGroup, DATASET_NAME_POSITIONS, mesh.verts(), 3);
|
|
|
|
|
write_dataset(meshGroup, DATASET_NAME_INDICES, mesh.faces(), 3);
|
|
|
|
|
write_dataset(meshGroup, DATASET_NAME_EDGES, mesh.edges(), 2);
|
|
|
|
|
write_dataset(meshGroup, DATASET_NAME_NORMALS, mesh.normals(), 2);
|
|
|
|
|
write_dataset(meshGroup, DATASET_NAME_UVCOORDS, mesh.uvs(), 2);
|
|
|
|
|
write_dataset(meshGroup, DATASET_NAME_MATERIAL_IDS, mesh.material_ids(), 1);
|
2023-06-19 13:47:45 +02:00
|
|
|
write_dataset(meshGroup, DATASET_NAME_ITEM_IDS, mesh.item_ids(), 1);
|
2025-08-07 19:23:38 +05:00
|
|
|
write_dataset(meshGroup, DATASET_NAME_EDGES_ITEM_IDS, mesh.edges_item_ids(), 1);
|
2021-10-08 15:38:46 +02:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
auto& ts = mesh.materials();
|
|
|
|
|
hsize_t d[2] { ts.size() };
|
|
|
|
|
H5::DataSpace dataspace(1, d);
|
|
|
|
|
const auto& dt = style_compound;
|
|
|
|
|
|
|
|
|
|
std::vector<surface_style_serialization> data;
|
|
|
|
|
data.reserve(ts.size());
|
|
|
|
|
for (auto& m : ts) {
|
|
|
|
|
data.emplace_back();
|
2023-03-21 20:15:01 +01:00
|
|
|
write_style(data.back(), m);
|
2021-10-08 15:38:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto ds = meshGroup.createDataSet(DATASET_NAME_MATERIALS, dt, dataspace);
|
|
|
|
|
ds.write(data.data(), dt);
|
2021-02-18 10:12:29 +01:00
|
|
|
}
|
2021-02-12 17:32:43 +01:00
|
|
|
}
|
2021-08-31 11:03:28 +02:00
|
|
|
|
2021-10-08 15:38:46 +02:00
|
|
|
|
|
|
|
|
const H5std_string HdfSerializer::DATASET_NAME_POSITIONS = "positions";
|
|
|
|
|
const H5std_string HdfSerializer::DATASET_NAME_UVCOORDS = "uvcoords";
|
|
|
|
|
const H5std_string HdfSerializer::DATASET_NAME_NORMALS = "normals";
|
|
|
|
|
const H5std_string HdfSerializer::DATASET_NAME_INDICES = "indices";
|
|
|
|
|
const H5std_string HdfSerializer::DATASET_NAME_EDGES = "edges";
|
|
|
|
|
const H5std_string HdfSerializer::DATASET_NAME_MATERIAL_IDS = "material_ids";
|
2023-06-19 13:47:45 +02:00
|
|
|
const H5std_string HdfSerializer::DATASET_NAME_ITEM_IDS = "item_ids";
|
2024-09-25 15:15:47 +05:00
|
|
|
const H5std_string HdfSerializer::DATASET_NAME_EDGES_ITEM_IDS = "edges_item_ids";
|
2021-10-08 15:38:46 +02:00
|
|
|
const H5std_string HdfSerializer::DATASET_NAME_MATERIALS = "materials";
|
|
|
|
|
const H5std_string HdfSerializer::DATASET_NAME_OCCT = "brep";
|
|
|
|
|
const H5std_string HdfSerializer::DATASET_NAME_PLACEMENT = "placement";
|
|
|
|
|
|
|
|
|
|
const H5std_string HdfSerializer::GROUP_NAME_MESH = "mesh";
|
|
|
|
|
|
|
|
|
|
|
2026-06-10 18:30:54 +02:00
|
|
|
#endif
|