This commit is contained in:
aothms
2015-11-10 11:16:00 +01:00
parent d076fa588b
commit 579d3713fd
10 changed files with 875 additions and 10 deletions
+17
View File
@@ -61,6 +61,7 @@ void printUsage(const boost::program_options::options_description& generic_optio
<< " .igs IGES Initial Graphics Exchange Specification" << std::endl << " .igs IGES Initial Graphics Exchange Specification" << std::endl
<< " .xml XML Property definitions and decomposition tree" << std::endl << " .xml XML Property definitions and decomposition tree" << std::endl
<< " .svg SVG Scalable Vector Graphics (2d floor plan)" << std::endl << " .svg SVG Scalable Vector Graphics (2d floor plan)" << std::endl
<< " .hdf HDF5 Efficient binary IFC serialization" << std::endl
<< std::endl << std::endl
<< "Command line options" << std::endl << generic_options << std::endl << "Command line options" << std::endl << generic_options << std::endl
<< "Advanced options" << std::endl << geom_options << std::endl; << "Advanced options" << std::endl << geom_options << std::endl;
@@ -131,6 +132,8 @@ int main(int argc, char** argv) {
("bounds", boost::program_options::value<std::string>(&bounds), ("bounds", boost::program_options::value<std::string>(&bounds),
"Specifies the bounding rectangle, for example 512x512, to which the " "Specifies the bounding rectangle, for example 512x512, to which the "
"output will be scaled. Only used when converting to SVG.") "output will be scaled. Only used when converting to SVG.")
("compress",
"Compress HDF5.")
("include", ("include",
"Specifies that the entities listed after --entities are to be included") "Specifies that the entities listed after --entities are to be included")
("exclude", ("exclude",
@@ -250,6 +253,20 @@ int main(int argc, char** argv) {
} catch (...) {} } catch (...) {}
write_log(); write_log();
return exit_code; return exit_code;
} else if (output_extension == ".hdf") {
int exit_code = 1;
// try {
IfcParse::IfcFile f;
if (!f.Init(input_filename)) {
Logger::Message(Logger::LOG_ERROR, "Unable to parse .ifc file");
} else {
f.write_hdf5(output_filename, vmap.count("compress") != 0);
exit_code = 0;
}
// } catch (...) {}
write_log();
// std::cin.get();
return exit_code;
} }
IfcGeom::IteratorSettings settings; IfcGeom::IteratorSettings settings;
+8
View File
@@ -65,6 +65,10 @@ class SchemaClass:
for name in collection.keys(): for name in collection.keys():
statements.append('%(cpp_type)s* %(name)s_type = 0;' % locals()) statements.append('%(cpp_type)s* %(name)s_type = 0;' % locals())
statements.append('#ifdef _MSC_VER' )
statements.append('#pragma optimize("", off)')
statements.append('#endif' )
statements.append('schema_definition* populate_schema() {') statements.append('schema_definition* populate_schema() {')
emitted_types = set() emitted_types = set()
@@ -145,6 +149,10 @@ class SchemaClass:
statements.extend(('}','')) statements.extend(('}',''))
statements.append('#ifdef _MSC_VER' )
statements.append('#pragma optimize("", on)')
statements.append('#endif' )
statements.extend(('const schema_definition& get_schema() {', statements.extend(('const schema_definition& get_schema() {',
'', '',
' static const schema_definition* s = populate_schema();', ' static const schema_definition* s = populate_schema();',
+9
View File
@@ -1009,6 +1009,11 @@ enumeration_type* IfcWindowPanelPositionEnum_type = 0;
enumeration_type* IfcWindowStyleConstructionEnum_type = 0; enumeration_type* IfcWindowStyleConstructionEnum_type = 0;
enumeration_type* IfcWindowStyleOperationEnum_type = 0; enumeration_type* IfcWindowStyleOperationEnum_type = 0;
enumeration_type* IfcWorkControlTypeEnum_type = 0; enumeration_type* IfcWorkControlTypeEnum_type = 0;
#ifdef _MSC_VER
# pragma optimize( "", off )
#endif
schema_definition* populate_schema() { schema_definition* populate_schema() {
IfcAbsorbedDoseMeasure_type = new type_declaration(IfcSchema::Type::IfcAbsorbedDoseMeasure, new simple_type(simple_type::real_type)); IfcAbsorbedDoseMeasure_type = new type_declaration(IfcSchema::Type::IfcAbsorbedDoseMeasure, new simple_type(simple_type::real_type));
IfcAccelerationMeasure_type = new type_declaration(IfcSchema::Type::IfcAccelerationMeasure, new simple_type(simple_type::real_type)); IfcAccelerationMeasure_type = new type_declaration(IfcSchema::Type::IfcAccelerationMeasure, new simple_type(simple_type::real_type));
@@ -10374,6 +10379,10 @@ schema_definition* populate_schema() {
return new schema_definition("IFC2X3", declarations, true); return new schema_definition("IFC2X3", declarations, true);
} }
#ifdef _MSC_VER
# pragma optimize( "", on )
#endif
const schema_definition& get_schema() { const schema_definition& get_schema() {
static const schema_definition* s = populate_schema(); static const schema_definition* s = populate_schema();
+2
View File
@@ -135,6 +135,8 @@ public:
std::pair<IfcSchema::IfcNamedUnit*, double> getUnit(IfcSchema::IfcUnitEnum::IfcUnitEnum); std::pair<IfcSchema::IfcNamedUnit*, double> getUnit(IfcSchema::IfcUnitEnum::IfcUnitEnum);
const schema_definition* schema() const { return schema_; } const schema_definition* schema() const { return schema_; }
void write_hdf5(const std::string&, bool compress) const;
}; };
} }
+671
View File
@@ -0,0 +1,671 @@
#include "IfcHdf5File.h"
#include "H5pubconf.h"
#ifndef H5_HAVE_FILTER_DEFLATE
#pragma message("warning: HDF5 compression support is recommended")
#endif
class UnmetDependencyException : public std::exception {};
H5::DataType* IfcParse::IfcHdf5File::map_type(const IfcParse::parameter_type* pt) {
H5::DataType* h5_dt;
if (pt->as_aggregation_type()) {
h5_dt = new H5::VarLenType(map_type(pt->as_aggregation_type()->type_of_element()));
} else if (pt->as_named_type()) {
if (pt->as_named_type()->declared_type()->as_entity()) {
h5_dt = new H5::DataType();
h5_dt->copy(*instance_reference);
} else {
IfcSchema::Type::Enum ty = pt->as_named_type()->declared_type()->type();
if (declared_types.find(ty) == declared_types.end()) {
throw UnmetDependencyException();
} else {
h5_dt = new H5::DataType();
h5_dt->copy(*declared_types[ty]);
}
}
} else if (pt->as_simple_type()) {
const H5::DataType* orig = default_types[pt->as_simple_type()->declared_type()];
h5_dt = new H5::DataType();
h5_dt->copy(*orig);
} else {
throw UnmetDependencyException();
}
return h5_dt;
}
H5::CompType* create_compound(const std::vector< IfcParse::IfcHdf5File::compound_member >& members) {
size_t s = 0, o = 0;
for (auto it = members.begin(); it != members.end(); ++it) {
s += it->second->getSize();
}
H5::CompType* h5_dt = new H5::CompType(s);
for (auto it = members.begin(); it != members.end(); ++it) {
h5_dt->insertMember(it->first, o, *it->second);
o += it->second->getSize();
}
return h5_dt;
}
H5::EnumType* create_enumeration(const std::vector<std::string>& items, int offset = 0) {
size_t numbytes = 0;
size_t size = items.size();
while (size != 0) {
size >>= 8;
numbytes ++;
}
int i = offset;
H5::EnumType* h5_enum = new H5::EnumType(numbytes);
for (auto it = items.begin(); it != items.end(); ++it, ++i) {
h5_enum->insert(it->c_str(), &i);
}
return h5_enum;
}
H5::EnumType* map_enumeration(const IfcParse::enumeration_type* en) {
return create_enumeration(en->enumeration_items());
}
H5::DataType* IfcParse::IfcHdf5File::commit(H5::DataType* dt, const std::string& name) {
dt->commit(schema_group, name);
return dt;
}
H5::CompType* IfcParse::IfcHdf5File::map_entity(const IfcParse::entity* e) {
std::vector<const IfcParse::entity::attribute*> attributes = e->all_attributes();
std::vector< IfcParse::IfcHdf5File::compound_member > h5_attributes;
h5_attributes.reserve(attributes.size() + 2);
h5_attributes.push_back(std::make_pair(std::string("set_unset_bitmap"), &H5::PredType::NATIVE_INT16));
h5_attributes.push_back(std::make_pair(std::string("Entity-Instance-Identifier"), &H5::PredType::NATIVE_INT32));
const std::vector<bool>& attributes_derived_in_subtype = e->derived();
auto jt = attributes_derived_in_subtype.begin();
for (auto it = attributes.begin(); it != attributes.end(); ++it, ++jt) {
if (*jt) {
continue;
}
const std::string& name = (*it)->name();
const bool is_optional = (*it)->optional();
H5::DataType* type = map_type((*it)->type_of_attribute());
h5_attributes.push_back(std::make_pair(name, type));
}
return create_compound(h5_attributes);
}
void IfcParse::IfcHdf5File::init_default_types() {
{
std::vector< compound_member > members;
members.push_back( std::make_pair(std::string("_HDF5_dataset_index_"), new H5::PredType(H5::PredType::NATIVE_INT16)) );
members.push_back( std::make_pair(std::string("_HDF5_instance_index_"), new H5::PredType(H5::PredType::NATIVE_INT32)) );
instance_reference = static_cast<H5::CompType*>(commit(create_compound(members), "_HDF_INSTANCE_REFERENCE_HANDLE_"));
}
object_reference_type = &H5::PredType::STD_REF_OBJ;
{
std::vector<std::string> names;
names.push_back("BOOLEAN-FALSE");
names.push_back("BOOLEAN-TRUE");
default_types[simple_type::boolean_type] = create_enumeration(names);
}
{
std::vector<std::string> names;
names.push_back("LOGICAL-UNKNOWN");
names.push_back("LOGICAL-FALSE");
names.push_back("LOGICAL-TRUE");
default_types[simple_type::logical_type] = create_enumeration(names, -1);
}
default_types[simple_type::binary_type] = &H5::PredType::NATIVE_OPAQUE; // vlen?
default_types[simple_type::real_type] = &H5::PredType::NATIVE_DOUBLE;
default_types[simple_type::number_type] = &H5::PredType::NATIVE_DOUBLE;
default_types[simple_type::string_type] = new H5::StrType(H5::PredType::C_S1, H5T_VARIABLE);
default_types[simple_type::integer_type] = &H5::PredType::NATIVE_INT;
default_type_names[simple_type::logical_type] = "logical";
default_type_names[simple_type::boolean_type] = "boolean";
default_type_names[simple_type::binary_type] = "binary";
default_type_names[simple_type::real_type] = "real";
default_type_names[simple_type::number_type] = "number";
default_type_names[simple_type::string_type] = "string";
default_type_names[simple_type::integer_type] = "integer";
default_cpp_type_names[IfcUtil::Argument_BOOL] = "boolean";
default_cpp_type_names[IfcUtil::Argument_DOUBLE] = "real";
default_cpp_type_names[IfcUtil::Argument_STRING] = "string";
default_cpp_type_names[IfcUtil::Argument_INT] = "integer";
}
void IfcParse::IfcHdf5File::visit_select(const IfcParse::select_type* pt, std::set<const IfcParse::declaration*>& leafs) {
for (auto it = pt->select_list().begin(); it != pt->select_list().end(); ++it) {
if ((*it)->as_select_type()) {
visit_select((*it)->as_select_type(), leafs);
} else {
leafs.insert(*it);
}
}
}
std::string IfcParse::IfcHdf5File::flatten_aggregate_name(const IfcParse::parameter_type* at) const {
if (at->as_aggregation_type()) {
return std::string("aggregate-of-") + flatten_aggregate_name(at->as_aggregation_type()->type_of_element());
} else if (at->as_simple_type()) {
return default_type_names.find(at->as_simple_type()->declared_type())->second;
} else if (at->as_named_type()) {
// TODO: Unwind type name
return at->as_named_type()->declared_type()->name();
} else {
throw;
}
}
H5::DataType* IfcParse::IfcHdf5File::map_select(const IfcParse::select_type* pt) {
std::set<const IfcParse::declaration*> leafs;
visit_select(pt, leafs);
bool all_entity_instance_refs = true;
for (auto it = leafs.begin(); it != leafs.end(); ++it) {
if (!(*it)->as_entity()) {
all_entity_instance_refs = false;
break;
}
}
if (all_entity_instance_refs) {
return 0;
} else {
std::set<std::string> member_names;
std::vector<compound_member> h5_attributes;
h5_attributes.push_back(std::make_pair(std::string("select_bitmap"), &H5::PredType::NATIVE_INT8));
h5_attributes.push_back(std::make_pair(std::string("type_path"), default_types[simple_type::string_type]));
for (auto it = leafs.begin(); it != leafs.end(); ++it) {
std::string name;
const H5::DataType* dt = 0;
const IfcParse::declaration* decl = (*it);
if ((*it)->as_type_declaration()) {
while (decl->as_type_declaration()) {
const IfcParse::parameter_type* pt = decl->as_type_declaration()->declared_type();
const IfcParse::named_type* nt = pt->as_named_type();
const IfcParse::simple_type* st = pt->as_simple_type();
const IfcParse::aggregation_type* at = pt->as_aggregation_type();
if (nt) {
decl = nt->declared_type();
} else if (st) {
name = default_type_names[st->declared_type()];
dt = default_types[st->declared_type()];
break;
} else if (at) {
name = flatten_aggregate_name(at);
dt = map_type(at);
break;
}
}
}
if (!dt) {
if ((*it)->as_entity()) {
name = "instance";
dt = instance_reference;
} else if ((*it)->as_enumeration_type()) {
name = (*it)->name();
dt = declared_types[(*it)->type()];
} else {
throw;
}
}
if (member_names.find(name) != member_names.end()) {
continue;
}
member_names.insert(name);
name += "-value";
h5_attributes.push_back(std::make_pair(name, dt));
}
return create_compound(h5_attributes);
}
}
void IfcParse::IfcHdf5File::advance(void*& ptr, size_t n) const {
ptr = ( uint8_t*) ptr + n;
}
template <typename T>
void IfcParse::IfcHdf5File::write(void*& ptr, const T& t) const {
*((T*)ptr) = t;
advance(ptr, sizeof(T));
}
template <>
void IfcParse::IfcHdf5File::write(void*& ptr, const std::string& s) const {
char* c = new(allocator.allocate(s.size()+1)) char [s.size()+1];
strcpy(c, s.c_str());
write(ptr, c);
}
template <unsigned int T> struct uint_of_size {};
template <> struct uint_of_size <1> { typedef uint8_t type; };
template <> struct uint_of_size <2> { typedef uint16_t type; };
template <> struct uint_of_size <4> { typedef uint32_t type; };
template <> struct uint_of_size <8> { typedef uint64_t type; };
template <unsigned int T> struct int_of_size {};
template <> struct int_of_size <1> { typedef int8_t type; };
template <> struct int_of_size <2> { typedef int16_t type; };
template <> struct int_of_size <4> { typedef int32_t type; };
template <> struct int_of_size <8> { typedef int64_t type; };
template <unsigned int T> struct float_of_size {};
template <> struct float_of_size <4> { typedef float type; };
template <> struct float_of_size <8> { typedef double type; };
template <typename T>
void IfcParse::IfcHdf5File::write_number_of_size(void*& ptr, size_t n, T i) const {
if (!std::numeric_limits<T>::is_integer) {
if (n == 4) {
write(ptr, static_cast< float_of_size<4>::type > (i));
} else if (n == 8) {
write(ptr, static_cast< float_of_size<8>::type > (i));
}
} else if (std::numeric_limits<T>::is_signed) {
if (n == 1) {
write(ptr, static_cast< int_of_size<1>::type > (i));
} else if (n == 2) {
write(ptr, static_cast< int_of_size<2>::type > (i));
} else if (n == 4) {
write(ptr, static_cast< int_of_size<4>::type > (i));
} else if (n == 8) {
write(ptr, static_cast< int_of_size<8>::type > (i));
}
} else {
if (n == 1) {
write(ptr, static_cast< uint_of_size<1>::type > (i));
} else if (n == 2) {
write(ptr, static_cast< uint_of_size<2>::type > (i));
} else if (n == 4) {
write(ptr, static_cast< uint_of_size<4>::type > (i));
} else if (n == 8) {
write(ptr, static_cast< uint_of_size<8>::type > (i));
}
}
}
void IfcParse::IfcHdf5File::write_vlen_t(void*& ptr, size_t n_elements, void* vlen_data) const {
advance(ptr, HOFFSET(hvl_t, len));
void* temp_ptr;
write_number_of_size(temp_ptr = ptr, sizeof(size_t), n_elements);
advance(ptr, HOFFSET(hvl_t, p));
write(ptr, vlen_data);
}
template <typename T>
void IfcParse::IfcHdf5File::write_aggregate(void*& ptr, const T& ts) const {
size_t elem_size = get_datatype<typename T::value_type>()->getSize();
size_t n_elements = ts.size();
size_t size_in_bytes = elem_size * n_elements;
void* aggr_data = allocator.allocate(size_in_bytes);
void* aggr_ptr = aggr_data;
for (T::const_iterator it = ts.begin(); it != ts.end(); ++it) {
write_number_of_size(aggr_ptr, elem_size, *it);
}
write_vlen_t(ptr, n_elements, aggr_data);
}
template <>
void IfcParse::IfcHdf5File::write_aggregate(void*& ptr, const std::vector<std::string>& ts) const {
size_t elem_size = sizeof(char*);
size_t n_elements = ts.size();
size_t size_in_bytes = elem_size * n_elements;
void* aggr_data = allocator.allocate(size_in_bytes);
void* aggr_ptr = aggr_data;
for (std::vector<std::string>::const_iterator it = ts.begin(); it != ts.end(); ++it) {
write(aggr_ptr, *it);
}
write_vlen_t(ptr, n_elements, aggr_data);
}
template <>
void IfcParse::IfcHdf5File::write_aggregate(void*& ptr, const IfcEntityList::ptr& ts) const {
size_t elem_size = instance_reference->getSize();
size_t n_elements = ts->size();
size_t size_in_bytes = elem_size * n_elements;
void* aggr_data = allocator.allocate(size_in_bytes);
void* aggr_ptr = aggr_data;
for (IfcEntityList::it it = ts->begin(); it != ts->end(); ++it) {
auto ref = make_instance_reference(*it);
write_number_of_size(aggr_ptr, instance_reference->getMemberDataType(0).getSize(), ref.first);
write_number_of_size(aggr_ptr, instance_reference->getMemberDataType(1).getSize(), ref.second);
}
write_vlen_t(ptr, n_elements, aggr_data);
}
void IfcParse::IfcHdf5File::write_schema(const IfcParse::schema_definition& schema) {
// From h5ex_g_compact.c
// Compact groups?
H5::FileAccPropList* plist = new H5::FileAccPropList();
plist->setLibverBounds(H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
// H5::FileCreatPropList* plist2 = new H5::FileCreatPropList();
// H5Pset_file_space(plist2->getId(), H5F_FILE_SPACE_VFD, (hsize_t)0);
file = new H5::H5File(name_, H5F_ACC_TRUNC, H5::FileCreatPropList::DEFAULT, *plist);
schema_group = file->createGroup(schema.name() + "_encoding");
population_group = file->createGroup("population");
init_default_types();
for (auto it = schema.enumeration_types().begin(); it != schema.enumeration_types().end(); ++it) {
declared_types[(*it)->type()] = commit(map_enumeration((*it)), (*it)->name());
}
const std::vector<const type_declaration*>& ts = schema.type_declarations();
std::set<const type_declaration*> processed;
while (processed.size() < ts.size()) {
for (auto it = ts.begin(); it != ts.end(); ++it) {
const std::string& name = (*it)->name();
if (processed.find(*it) != processed.end()) continue;
try {
declared_types[(*it)->type()] = commit(map_type((*it)->declared_type()), (*it)->name());
processed.insert(*it);
} catch(const UnmetDependencyException&) {}
auto pt = (*it)->declared_type();
}
}
for (auto it = schema.select_types().begin(); it != schema.select_types().end(); ++it) {
H5::DataType* dt = map_select(*it);
if (dt) {
declared_types[(*it)->type()] = commit(dt, (*it)->name());
} else {
declared_types[(*it)->type()] = instance_reference;
}
}
for (auto it = schema.entities().begin(); it != schema.entities().end(); ++it) {
declared_types[(*it)->type()] = commit(map_entity(*it), (*it)->name());
}
};
std::pair<size_t, size_t> IfcParse::IfcHdf5File::make_instance_reference(const IfcUtil::IfcBaseClass* instance) const {
const std::vector<IfcUtil::IfcBaseClass*>& es = sorted_entities.find(instance->declaration().type())->second;
auto dataset_id = std::lower_bound(dataset_names.begin(), dataset_names.end(), instance->declaration().type());
auto instance_id = std::lower_bound(es.begin(), es.end(), instance); // TODO: << make a vector of ids to make sure pointers are stable
size_t dataset_offset = std::distance(dataset_names.begin(), dataset_id);
size_t instance_offset = std::distance(es.begin(), instance_id);
return std::make_pair(dataset_offset, instance_offset);
}
void IfcParse::IfcHdf5File::write_select(void*& ptr, IfcUtil::IfcBaseClass* instance, const H5::CompType* datatype) const {
int member_index = -1;
if (instance->declaration().as_entity()) {
member_index = datatype->getMemberIndex("instance-value");
size_t offset = datatype->getMemberOffset(member_index);
auto ref = make_instance_reference(instance);
void* ptr_member = (uint8_t*) ptr + offset;
write_number_of_size(ptr_member, instance_reference->getMemberDataType(0).getSize(), ref.first);
write_number_of_size(ptr_member, instance_reference->getMemberDataType(1).getSize(), ref.second);
} else {
Argument& wrapped_data = *instance->data().getArgument(0);
IfcUtil::ArgumentType ty = wrapped_data.type();
if (default_cpp_type_names.find(ty) == default_cpp_type_names.end()) {
Logger::Message(Logger::LOG_ERROR, "Unsupported select valuation encountered", instance);
} else {
std::string member_name = default_cpp_type_names.find(ty)->second + "-value";
member_index = datatype->getMemberIndex(member_name);
size_t offset = datatype->getMemberOffset(member_index);
size_t member_size = datatype->getMemberDataType(member_index).getSize();
void* ptr_member = (uint8_t*) ptr + offset;
switch(wrapped_data.type()) {
case IfcUtil::Argument_BOOL: {
bool instance = wrapped_data;
write_number_of_size(ptr_member, member_size, static_cast<uint8_t>(instance ? 1 : 0));
break; }
case IfcUtil::Argument_DOUBLE: {
double d = wrapped_data;
write_number_of_size(ptr_member, member_size, d);
break; }
case IfcUtil::Argument_STRING: {
std::string s = wrapped_data;
write(ptr_member, s);
break; }
case IfcUtil::Argument_INT: {
int i = wrapped_data;
write_number_of_size(ptr_member, member_size, i);
break; }
default:
Logger::Message(Logger::LOG_ERROR, "Unsupported select valuation encountered", instance);
break;
}
}
}
if (member_index == -1) {
member_index = 0;
} else {
member_index -= 2; // select_bitmap, type_path
}
void* temp_ptr = ptr;
write_number_of_size(temp_ptr, H5::PredType::NATIVE_INT8.getSize(), member_index);
write(temp_ptr, instance->declaration().name());
// TODO: Should string be set to "", or keep as null?
// std::cout << datatype->getMemberIndex("string-value") << std::endl;
advance(ptr, datatype->getSize());
}
void IfcParse::IfcHdf5File::write_population(const IfcFile& f, bool compress) {
std::set<IfcSchema::Type::Enum> tys;
for (auto it = f.begin(); it != f.end(); ++it) {
IfcSchema::Type::Enum ty = it->second->declaration().type();
tys.insert(ty);
// This already is sorted on entity instance name
sorted_entities[ty].push_back(it->second);
}
dataset_names.assign(tys.begin(), tys.end());
std::sort(dataset_names.begin(), dataset_names.end());
for (auto it = dataset_names.begin(); it != dataset_names.end(); ++it) {
const std::vector<IfcUtil::IfcBaseClass*>& es = sorted_entities.find(*it)->second;
hsize_t dims = es.size();
// don't chunk too small
// hsize_t chunk = (std::min)(std::max(es.size() / 64, (size_t)8), es.size());
// hsize_t chunk = (std::min)( (std::max)(es.size() / 8, (size_t) 128 ) , es.size());
hsize_t chunk = dims;
const H5::DSetCreatPropList* plist;
// H5O_MESG_MAX_SIZE = 65536
const bool compact = es.size() * declared_types[*it]->getSize() < (1 << 15);
if (compress && !compact) {
H5::DSetCreatPropList* plist_ = new H5::DSetCreatPropList;
plist_->setChunk(1, &chunk);
// D'oh. Order is significant, according to h5ex_d_shuffle.c
plist_->setShuffle();
plist_->setDeflate(9);
plist = plist_;
} else if (compact) {
H5::DSetCreatPropList* plist_ = new H5::DSetCreatPropList;
// Set compact according to h5ex_d_compact.c
plist_->setLayout(H5D_COMPACT);
plist = plist_;
} else {
plist = &H5::DSetCreatPropList::DEFAULT;
}
H5::DataSet ds = population_group.createDataSet(IfcSchema::Type::ToString(*it) + "_instances", *declared_types[*it], H5::DataSpace(1, &dims), *plist);
void* data = allocator.allocate(declared_types[*it]->getSize() * static_cast<size_t>(dims));
void* ptr = data;
const H5::CompType* dt = (H5::CompType*) declared_types[*it];
int ind = 0;
for (auto jt = es.begin(); jt != es.end(); ++jt, ++ind) {
int member_idx = 0;
H5::DataType member_type;
IfcAbstractEntity& dat = (*jt)->data();
const declaration& decl = (*jt)->declaration();
std::vector<const IfcParse::entity::attribute*> attributes = decl.as_entity()->all_attributes();
const std::vector<bool>& attributes_derived_in_subtype = decl.as_entity()->derived();
std::vector<bool>::const_iterator is_derived = attributes_derived_in_subtype.begin();
member_type = dt->getMemberDataType(member_idx++);
uint32_t set_unset_mask = 0;
void* set_unset_ptr = ptr;
size_t set_unset_size = member_type.getSize();
// skip for now write later
advance(ptr, set_unset_size);
member_type = dt->getMemberDataType(member_idx++);
write_number_of_size(ptr, member_type.getSize(), static_cast<unsigned int>(dat.id()));
for (unsigned i = 0; i < dat.getArgumentCount(); ++i, ++is_derived) {
if (*is_derived) {
continue;
}
const IfcParse::entity::attribute* schema_attr = attributes[i];
Argument& attr_value = *dat.getArgument(i);
member_type = dt->getMemberDataType(member_idx++);
if (attr_value.isNull()) {
if (member_type == *default_types[simple_type::string_type]) {
// HDF5 otherwise crashes on derefencing a zero pointer for the string type
write(ptr, new(allocator.allocate(1)) char(0));
} else {
memset(ptr, 0, member_type.getSize());
advance(ptr, member_type.getSize());
}
} else {
set_unset_mask |= 1 << i;
if (member_type == *instance_reference) {
IfcUtil::IfcBaseClass* v = attr_value;
auto ref = make_instance_reference(v);
write_number_of_size(ptr, instance_reference->getMemberDataType(0).getSize(), ref.first);
write_number_of_size(ptr, instance_reference->getMemberDataType(1).getSize(), ref.second);
} else if (member_type == *default_types[simple_type::real_type]) {
double d = attr_value;
write_number_of_size(ptr, member_type.getSize(), d);
} else if (member_type == *default_types[simple_type::string_type]) {
std::string s = attr_value;
write(ptr, s);
} else if (member_type == *default_types[simple_type::integer_type]) {
int i = attr_value;
write_number_of_size(ptr, member_type.getSize(), i);
} else if (member_type == *default_types[simple_type::boolean_type] ||
member_type == *default_types[simple_type::logical_type])
{
bool b = attr_value;
write_number_of_size(ptr, member_type.getSize(), static_cast<uint8_t>(b ? 1 : 0));
} else if (member_type.getClass() == H5T_ENUM) {
// NB: Note that boolean and logical are also enums
// NB2: In IfcOpenShell an enum value can be read as a string
std::string s = attr_value;
const std::vector<std::string>& enum_values = schema_attr->type_of_attribute()->as_named_type()->declared_type()->as_enumeration_type()->enumeration_items();
size_t d = std::distance(enum_values.begin(), std::find(enum_values.begin(), enum_values.end(), s));
write_number_of_size(ptr, member_type.getSize(), d);
} else if (member_type.getClass() == H5T_VLEN) {
const parameter_type* pt = schema_attr->type_of_attribute();
while (pt->as_named_type()) {
pt = pt->as_named_type()->declared_type()->as_type_declaration()->declared_type();
}
const named_type* nt = pt->as_aggregation_type()->type_of_element()->as_named_type();
if (nt && nt->declared_type()->as_select_type()) {
const H5::DataType* datatype = declared_types[nt->declared_type()->type()];
IfcEntityList::ptr es = attr_value;
if (datatype == instance_reference) {
// For a SELECTs with only ENTITY leaves, a blind instance reference type is used
write_aggregate(ptr, es);
} else {
size_t size_in_bytes = datatype->getSize();
size_t num_elements = es->size();
void* buffer_ptr;
// void* buffer = buffer_ptr = new uint8_t[size_in_bytes * num_elements];
void* buffer = buffer_ptr = allocator.allocate(size_in_bytes * num_elements);
for (auto it = es->begin(); it != es->end(); ++it) {
write_select(buffer_ptr, *it, static_cast<const H5::CompType*>(datatype));
}
write_vlen_t(ptr, num_elements, buffer);
}
} else {
if (sizeof(hvl_t) != member_type.getSize()) throw;
switch(attr_value.type()) {
case IfcUtil::Argument_AGGREGATE_OF_INT: {
std::vector<int> ds = attr_value;
write_aggregate(ptr, ds);
break; }
case IfcUtil::Argument_AGGREGATE_OF_DOUBLE: {
std::vector<double> ds = attr_value;
write_aggregate(ptr, ds);
break; }
case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: {
IfcEntityList::ptr es = attr_value;
write_aggregate(ptr, es);
break; }
case IfcUtil::Argument_AGGREGATE_OF_STRING: {
std::vector<std::string> ss = attr_value;
write_aggregate(ptr, ss);
break; }
default:
// Can be an empty list in which case parser does not know type
if (attr_value.size() > 0) {
Logger::Message(Logger::LOG_ERROR, "Unsupported aggregate encountered", *jt);
}
memset(ptr, 0, member_type.getSize());
ptr = (uint8_t*) ptr + member_type.getSize();
}
}
} else if (member_type.getClass() == H5T_COMPOUND) {
memset(ptr, 0, member_type.getSize());
IfcUtil::ArgumentType ty = attr_value.type();
if (ty != IfcUtil::Argument_ENTITY_INSTANCE) throw;
IfcUtil::IfcBaseClass* b = attr_value;
write_select(ptr, attr_value, static_cast<H5::CompType*>(&member_type));
}
}
}
write_number_of_size(set_unset_ptr, set_unset_size, set_unset_mask);
}
ds.write(data, *declared_types[*it]);
ds.close();
allocator.free();
for (auto it = es.begin(); it != es.end(); ++it) {
static_cast<IfcParse::Entity*>(&(**it).data())->Unload();
}
}
}
+122
View File
@@ -0,0 +1,122 @@
/********************************************************************************
* *
* 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/>. *
* *
********************************************************************************/
#ifndef IFCHDF5FILE_H
#define IFCHDF5FILE_H
#include "H5Cpp.h"
#include "../ifcparse/IfcUtil.h"
#include "../ifcparse/IfcFile.h"
namespace IfcParse {
class IfcHdf5File {
private:
class allocator_t {
private:
// TODO: Change this?
mutable std::vector<uint8_t*> buffers;
public:
void* allocate(size_t n) const {
return new uint8_t[n];
}
void free() {
std::vector<uint8_t*>::const_iterator it;
for (it = buffers.begin(); it != buffers.end(); ++it) {
delete[] *it;
}
buffers.clear();
}
~allocator_t() {
free();
}
};
allocator_t allocator;
std::string name_;
schema_definition schema_;
H5::H5File* file;
H5::Group schema_group;
H5::Group population_group;
// TODO: const
H5::CompType* instance_reference;
const H5::DataType* object_reference_type;
std::map<IfcSchema::Type::Enum, H5::DataType*> declared_types;
// TODO: why? get_datatype()
std::map<IfcParse::simple_type::data_type, const H5::DataType*> default_types;
std::map<IfcParse::simple_type::data_type, std::string> default_type_names;
std::map<IfcUtil::ArgumentType, std::string> default_cpp_type_names;
std::map<IfcSchema::Type::Enum, std::vector<IfcUtil::IfcBaseClass*> > sorted_entities;
std::vector<IfcSchema::Type::Enum> dataset_names;
H5::DataType* map_type(const IfcParse::parameter_type* pt);
H5::CompType* map_entity(const IfcParse::entity* e);
H5::DataType* map_select(const IfcParse::select_type* pt);
H5::DataType* commit(H5::DataType* dt, const std::string& name);
void init_default_types();
void visit_select(const IfcParse::select_type* pt, std::set<const IfcParse::declaration*>& leafs);
std::string flatten_aggregate_name(const IfcParse::parameter_type* at) const;
std::pair<size_t, size_t> make_instance_reference(const IfcUtil::IfcBaseClass* instance) const;
void write_select(void*& ptr, IfcUtil::IfcBaseClass* instance, const H5::CompType* datatype) const;
void write_schema(const schema_definition& schema);
void write_population(const IfcFile& f, bool compress);
template <typename T>
const H5::DataType* get_datatype() const {
return default_types.find(IfcUtil::cpp_to_schema_type<T>::schema_type)->second;
}
void advance(void*& ptr, size_t n) const;
template <typename T>
void write(void*& ptr, const T& t) const;
template <>
void write(void*& ptr, const std::string& s) const;
void write_vlen_t(void*& ptr, size_t n_elements, void* vlen_data) const;
template <typename T>
void write_number_of_size(void*& ptr, size_t n, T i) const;
template <typename T>
void write_aggregate(void*& ptr, const T& ts) const;
public:
typedef std::pair<std::string, const H5::DataType*> compound_member;
IfcHdf5File(const IfcFile* f, const std::string& name, bool compress)
: name_(name)
, schema_(*f->schema())
{
write_schema(*f->schema());
write_population(*f, compress);
};
};
}
#endif
+10
View File
@@ -38,6 +38,7 @@
#include "../ifcparse/IfcFile.h" #include "../ifcparse/IfcFile.h"
#include "../ifcparse/IfcSIPrefix.h" #include "../ifcparse/IfcSIPrefix.h"
#include "../ifcparse/IfcSchema.h" #include "../ifcparse/IfcSchema.h"
#include "../ifcparse/IfcHdf5File.h"
using namespace IfcParse; using namespace IfcParse;
@@ -830,6 +831,11 @@ void Entity::Load(std::vector<unsigned int>& ids, bool seek) const {
if ( ! TokenFunc::isOperator(semilocon,';') ) file->tokens->stream->Seek(old_offset); if ( ! TokenFunc::isOperator(semilocon,';') ) file->tokens->stream->Seek(old_offset);
} }
void Entity::Unload() {
delete args;
args = 0;
}
IfcSchema::Type::Enum Entity::type() const { IfcSchema::Type::Enum Entity::type() const {
return _type; return _type;
} }
@@ -1536,3 +1542,7 @@ std::pair<IfcSchema::IfcNamedUnit*, double> IfcFile::getUnit(IfcSchema::IfcUnitE
} }
return return_value; return return_value;
} }
void IfcFile::write_hdf5(const std::string& name, bool compress) const {
IfcHdf5File(this, name, compress);
}
+3 -2
View File
@@ -130,7 +130,7 @@ namespace IfcParse {
std::vector<Argument*> list; std::vector<Argument*> list;
void push(Argument* l); void push(Argument* l);
public: public:
~ArgumentList(); virtual ~ArgumentList();
void read(IfcSpfLexer* t, std::vector<unsigned int>& ids); void read(IfcSpfLexer* t, std::vector<unsigned int>& ids);
@@ -206,7 +206,7 @@ namespace IfcParse {
IfcUtil::IfcBaseClass* entity; IfcUtil::IfcBaseClass* entity;
public: public:
EntityArgument(const Token& t); EntityArgument(const Token& t);
~EntityArgument(); virtual ~EntityArgument();
IfcUtil::ArgumentType type() const; IfcUtil::ArgumentType type() const;
@@ -251,6 +251,7 @@ namespace IfcParse {
~Entity(); ~Entity();
IfcEntityList::ptr getInverse(IfcSchema::Type::Enum type, int attribute_index); IfcEntityList::ptr getInverse(IfcSchema::Type::Enum type, int attribute_index);
void Load(std::vector<unsigned int>& ids, bool seek=false) const; void Load(std::vector<unsigned int>& ids, bool seek=false) const;
void Unload();
Argument* getArgument (unsigned int i); Argument* getArgument (unsigned int i);
unsigned int getArgumentCount() const; unsigned int getArgumentCount() const;
std::string toString(bool upper=false) const; std::string toString(bool upper=false) const;
+15 -7
View File
@@ -23,6 +23,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include <iterator>
#ifdef USE_IFC4 #ifdef USE_IFC4
#include "../ifcparse/Ifc4enum.h" #include "../ifcparse/Ifc4enum.h"
@@ -243,12 +244,14 @@ namespace IfcParse {
const std::vector<const attribute*> all_attributes() const { const std::vector<const attribute*> all_attributes() const {
std::vector<const attribute*> attrs; std::vector<const attribute*> attrs;
attrs.reserve(derived_.size()); attrs.reserve(derived_.size());
std::vector<const attribute*>::iterator it = attrs.begin(); // std::vector<const attribute*>::iterator it = attrs.begin();
if (supertype_) { if (supertype_) {
const std::vector<const attribute*> supertype_attrs = supertype_->all_attributes(); const std::vector<const attribute*> supertype_attrs = supertype_->all_attributes();
it = std::copy(supertype_attrs.begin(), supertype_attrs.end(), it); // it = std::copy(supertype_attrs.begin(), supertype_attrs.end(), it);
std::copy(supertype_attrs.begin(), supertype_attrs.end(), std::back_inserter(attrs));
} }
std::copy(attributes_.begin(), attributes_.end(), it); // std::copy(attributes_.begin(), attributes_.end(), it);
std::copy(attributes_.begin(), attributes_.end(), std::back_inserter(attrs));
return attrs; return attrs;
} }
@@ -266,6 +269,7 @@ namespace IfcParse {
std::vector<const type_declaration*> type_declarations_; std::vector<const type_declaration*> type_declarations_;
std::vector<const select_type*> select_types_; std::vector<const select_type*> select_types_;
std::vector<const enumeration_type*> enumeration_types_; std::vector<const enumeration_type*> enumeration_types_;
std::vector<const entity*> entities_;
class declaration_by_name_cmp : public std::binary_function<const declaration*, const std::string&, bool> { class declaration_by_name_cmp : public std::binary_function<const declaration*, const std::string&, bool> {
public: public:
@@ -284,6 +288,7 @@ namespace IfcParse {
if ((**it).as_type_declaration()) type_declarations_.push_back((**it).as_type_declaration()); if ((**it).as_type_declaration()) type_declarations_.push_back((**it).as_type_declaration());
if ((**it).as_select_type()) select_types_.push_back((**it).as_select_type()); if ((**it).as_select_type()) select_types_.push_back((**it).as_select_type());
if ((**it).as_enumeration_type()) enumeration_types_.push_back((**it).as_enumeration_type()); if ((**it).as_enumeration_type()) enumeration_types_.push_back((**it).as_enumeration_type());
if ((**it).as_entity()) entities_.push_back((**it).as_entity());
} }
} }
@@ -307,10 +312,13 @@ namespace IfcParse {
return declaration_by_name(IfcSchema::Type::ToString(name)); return declaration_by_name(IfcSchema::Type::ToString(name));
} }
const std::vector<const declaration*>& declarations() { return declarations_; } const std::vector<const declaration*>& declarations() const { return declarations_; }
const std::vector<const type_declaration*>& type_declarations() { return type_declarations_; } const std::vector<const type_declaration*>& type_declarations() const { return type_declarations_; }
const std::vector<const select_type*>& select_types() { return select_types_; } const std::vector<const select_type*>& select_types() const { return select_types_; }
const std::vector<const enumeration_type*>& enumeration_types() { return enumeration_types_; } const std::vector<const enumeration_type*>& enumeration_types() const { return enumeration_types_; }
const std::vector<const entity*>& entities() const { return entities_; }
const std::string& name() const { return name_; }
}; };
} }
+17
View File
@@ -130,6 +130,23 @@ namespace IfcUtil {
}; };
bool valid_binary_string(const std::string& s); bool valid_binary_string(const std::string& s);
template <typename T> struct cpp_to_schema_type;
template <> struct cpp_to_schema_type < boost::dynamic_bitset<> > { static const IfcParse::simple_type::data_type schema_type = IfcParse::simple_type::binary_type; };
template <> struct cpp_to_schema_type < bool > { static const IfcParse::simple_type::data_type schema_type = IfcParse::simple_type::boolean_type; };
template <> struct cpp_to_schema_type < int > { static const IfcParse::simple_type::data_type schema_type = IfcParse::simple_type::integer_type; };
template <> struct cpp_to_schema_type < double > { static const IfcParse::simple_type::data_type schema_type = IfcParse::simple_type::real_type; };
template <> struct cpp_to_schema_type < std::string > { static const IfcParse::simple_type::data_type schema_type = IfcParse::simple_type::string_type; };
template <IfcParse::simple_type::data_type T>
struct schema_to_cpp_type;
template <> struct schema_to_cpp_type < IfcParse::simple_type::binary_type > { typedef boost::dynamic_bitset<> cpp_type; };
template <> struct schema_to_cpp_type < IfcParse::simple_type::boolean_type > { typedef bool cpp_type; };
template <> struct schema_to_cpp_type < IfcParse::simple_type::integer_type > { typedef int cpp_type; };
template <> struct schema_to_cpp_type < IfcParse::simple_type::logical_type > { typedef bool cpp_type; };
template <> struct schema_to_cpp_type < IfcParse::simple_type::number_type > { typedef double cpp_type; };
template <> struct schema_to_cpp_type < IfcParse::simple_type::real_type > { typedef double cpp_type; };
template <> struct schema_to_cpp_type < IfcParse::simple_type::string_type > { typedef std::string cpp_type; };
} }
template <class T> template <class T>