Work on serializers

This commit is contained in:
Thomas Krijnen
2017-12-20 12:40:15 +01:00
parent 830a03ffcd
commit d46dfb6061
9 changed files with 146 additions and 129 deletions
+13 -24
View File
@@ -32,8 +32,6 @@
#include <string> #include <string>
#include <cmath> #include <cmath>
using namespace IfcSchema;
static std::string& collada_id(std::string& s) static std::string& collada_id(std::string& s)
{ {
IfcUtil::sanitate_material_name(s); IfcUtil::sanitate_material_name(s);
@@ -431,31 +429,22 @@ void ColladaSerializer::ColladaExporter::write(const IfcGeom::TriangulationEleme
} }
std::string ColladaSerializer::ColladaExporter::differentiateSlabTypes(const IfcGeom::TriangulationElement<real_t>* o) { std::string ColladaSerializer::ColladaExporter::differentiateSlabTypes(const IfcGeom::TriangulationElement<real_t>* o) {
IfcSlab* slab = (IfcSlab*)o->product();
std::string result; std::string result;
switch (slab->PredefinedType())
{ if (!o->product()->get("ObjectType")->isNull()) {
case (IfcSlabTypeEnum::IfcSlabType_FLOOR): const std::string object_type = *o->product()->get("ObjectType");
result = "_Floor"; result = "_" + object_type;
break; } else {
case (IfcSlabTypeEnum::IfcSlabType_ROOF): result = "_Unknown";
result = "_Roof";
break;
case (IfcSlabTypeEnum::IfcSlabType_LANDING):
result = "_Landing";
break;
case (IfcSlabTypeEnum::IfcSlabType_BASESLAB):
result = "_BaseSlab";
break;
case (IfcSlabTypeEnum::IfcSlabType_NOTDEFINED):
result = "_NotDefined";
break;
default:
if (slab->hasObjectType()) { result = "_" + slab->ObjectType(); }
else { result = "_Unknown"; }
break;
} }
const std::string slabtype = *o->product()->get("PredefinedType");
if (slabtype != "NOTDEFINED" && slabtype != "USERDEFINED") {
result = "_" + slabtype;
}
collada_id(result); collada_id(result);
return result; return result;
} }
+66 -50
View File
@@ -56,7 +56,7 @@ namespace po = boost::program_options;
void print_version() void print_version()
{ {
std::cout << "IfcOpenShell " << IfcSchema::Identifier << " IfcConvert " << IFCOPENSHELL_VERSION << " (OCC " << OCC_VERSION_STRING_EXT << ")\n"; std::cout << "IfcOpenShell " << " IfcConvert " << IFCOPENSHELL_VERSION << " (OCC " << OCC_VERSION_STRING_EXT << ")\n";
} }
void print_usage(bool suggest_help = true) void print_usage(bool suggest_help = true)
@@ -116,6 +116,7 @@ static std::stringstream log_stream;
void write_log(); void write_log();
/// @todo make the filters non-global /// @todo make the filters non-global
/*
IfcGeom::entity_filter entity_filter; // Entity filter is used always by default. IfcGeom::entity_filter entity_filter; // Entity filter is used always by default.
IfcGeom::layer_filter layer_filter; IfcGeom::layer_filter layer_filter;
const std::string NAME_ARG = "Name", GUID_ARG = "GlobalId", DESC_ARG = "Description", TAG_ARG = "Tag"; const std::string NAME_ARG = "Name", GUID_ARG = "GlobalId", DESC_ARG = "Description", TAG_ARG = "Tag";
@@ -147,6 +148,7 @@ struct exclusion_traverse_filter : public geom_filter { exclusion_traverse_filte
size_t read_filters_from_file(const std::string&, inclusion_filter&, inclusion_traverse_filter&, exclusion_filter&, exclusion_traverse_filter&); size_t read_filters_from_file(const std::string&, inclusion_filter&, inclusion_traverse_filter&, exclusion_filter&, exclusion_traverse_filter&);
void parse_filter(geom_filter &, const std::vector<std::string>&); void parse_filter(geom_filter &, const std::vector<std::string>&);
std::vector<IfcGeom::filter_t> setup_filters(const std::vector<geom_filter>&, const std::string&); std::vector<IfcGeom::filter_t> setup_filters(const std::vector<geom_filter>&, const std::string&);
*/
bool init_input_file(const std::string& filename, IfcParse::IfcFile& ifc_file, bool no_progress, bool mmap); bool init_input_file(const std::string& filename, IfcParse::IfcFile& ifc_file, bool no_progress, bool mmap);
@@ -170,11 +172,13 @@ int main(int argc, char** argv)
double deflection_tolerance; double deflection_tolerance;
inclusion_filter include_filter; /*
inclusion_filter include_filter;
inclusion_traverse_filter include_traverse_filter; inclusion_traverse_filter include_traverse_filter;
exclusion_filter exclude_filter; exclusion_filter exclude_filter;
exclusion_traverse_filter exclude_traverse_filter; exclusion_traverse_filter exclude_traverse_filter;
std::string filter_filename; std::string filter_filename;
*/
po::options_description geom_options("Geometry options"); po::options_description geom_options("Geometry options");
geom_options.add_options() geom_options.add_options()
@@ -190,7 +194,7 @@ int main(int argc, char** argv)
"vector will only contain unique xyz-triplets. This results in a " "vector will only contain unique xyz-triplets. This results in a "
"manifold mesh which is useful for modelling applications, but might " "manifold mesh which is useful for modelling applications, but might "
"result in unwanted shading artefacts in rendering applications.") "result in unwanted shading artefacts in rendering applications.")
("use-world-coords", ("use-world-coords",
"Specifies whether to apply the local placements of building elements " "Specifies whether to apply the local placements of building elements "
"directly to the coordinates of the representation mesh rather than " "directly to the coordinates of the representation mesh rather than "
"to represent the local placement in the 4x3 matrix, which will in that " "to represent the local placement in the 4x3 matrix, which will in that "
@@ -199,7 +203,7 @@ int main(int argc, char** argv)
"Specifies whether to convert back geometrical output back to the " "Specifies whether to convert back geometrical output back to the "
"unit of measure in which it is defined in the IFC file. Default is " "unit of measure in which it is defined in the IFC file. Default is "
"to use meters.") "to use meters.")
("sew-shells", ("sew-shells",
"Specifies whether to sew the faces of IfcConnectedFaceSets together. " "Specifies whether to sew the faces of IfcConnectedFaceSets together. "
"This is a potentially time consuming operation, but guarantees a " "This is a potentially time consuming operation, but guarantees a "
"consistent orientation of surface normals, even if the faces are not " "consistent orientation of surface normals, even if the faces are not "
@@ -209,53 +213,56 @@ int main(int argc, char** argv)
// arguments where not introduced yet and a work-around was implemented to // arguments where not introduced yet and a work-around was implemented to
// subtract multiple openings as a single compound. This hack is obsolete // subtract multiple openings as a single compound. This hack is obsolete
// for newer versions of Open CASCADE. // for newer versions of Open CASCADE.
("merge-boolean-operands", ("merge-boolean-operands",
"Specifies whether to merge all IfcOpeningElement operands into a single " "Specifies whether to merge all IfcOpeningElement operands into a single "
"operand before applying the subtraction operation. This may " "operand before applying the subtraction operation. This may "
"introduce a performance improvement at the risk of failing, in " "introduce a performance improvement at the risk of failing, in "
"which case the subtraction is applied one-by-one.") "which case the subtraction is applied one-by-one.")
#endif #endif
("disable-opening-subtractions", ("disable-opening-subtractions",
"Specifies whether to disable the boolean subtraction of " "Specifies whether to disable the boolean subtraction of "
"IfcOpeningElement Representations from their RelatingElements.") "IfcOpeningElement Representations from their RelatingElements.")
("enable-layerset-slicing", ("enable-layerset-slicing",
"Specifies whether to enable the slicing of products according " "Specifies whether to enable the slicing of products according "
"to their associated IfcMaterialLayerSet.") "to their associated IfcMaterialLayerSet.")
("include", po::value<inclusion_filter>(&include_filter)->multitoken(), /*
"Specifies that the entities that match a specific filtering criteria are to be included in the geometrical output:\n" ("include", po::value<inclusion_filter>(&include_filter)->multitoken(),
"1) 'entities': the following list of types should be included. SVG output defaults " "Specifies that the entities that match a specific filtering criteria are to be included in the geometrical output:\n"
"to IfcSpace to be included. The entity names are handled case-insensitively.\n" "1) 'entities': the following list of types should be included. SVG output defaults "
"2) 'layers': the entities that are assigned to presentation layers of which names " "to IfcSpace to be included. The entity names are handled case-insensitively.\n"
"match the given values should be included.\n" "2) 'layers': the entities that are assigned to presentation layers of which names "
"3) 'arg <ArgumentName>': the following list of values for that specific argument should be included. " "match the given values should be included.\n"
"Currently supported arguments are GlobalId, Name, Description, and Tag.\n\n" "3) 'arg <ArgumentName>': the following list of values for that specific argument should be included. "
"The values for 'layers' and 'arg' are handled case-sensitively (wildcards supported)." "Currently supported arguments are GlobalId, Name, Description, and Tag.\n\n"
"--include and --exclude cannot be placed right before input file argument and " "The values for 'layers' and 'arg' are handled case-sensitively (wildcards supported)."
"only single of each argument supported for now. See also --exclude.") "--include and --exclude cannot be placed right before input file argument and "
("include+", po::value<inclusion_traverse_filter>(&include_traverse_filter)->multitoken(), "only single of each argument supported for now. See also --exclude.")
"Same as --include but applies filtering also to the decomposition and/or containment (IsDecomposedBy, " ("include+", po::value<inclusion_traverse_filter>(&include_traverse_filter)->multitoken(),
"HasOpenings, FillsVoid, ContainedInStructure) of the filtered entity, e.g. --include+=arg Name \"Level 1\" " "Same as --include but applies filtering also to the decomposition and/or containment (IsDecomposedBy, "
"includes entity with name \"Level 1\" and all of its children. See --include for more information. ") "HasOpenings, FillsVoid, ContainedInStructure) of the filtered entity, e.g. --include+=arg Name \"Level 1\" "
("exclude", po::value<exclusion_filter>(&exclude_filter)->multitoken(), "includes entity with name \"Level 1\" and all of its children. See --include for more information. ")
"Specifies that the entities that match a specific filtering criteria are to be excluded in the geometrical output." ("exclude", po::value<exclusion_filter>(&exclude_filter)->multitoken(),
"See --include for syntax and more details. The default value is '--exclude=entities IfcOpeningElement IfcSpace'.") "Specifies that the entities that match a specific filtering criteria are to be excluded in the geometrical output."
("exclude+", po::value<exclusion_traverse_filter>(&exclude_traverse_filter)->multitoken(), "See --include for syntax and more details. The default value is '--exclude=entities IfcOpeningElement IfcSpace'.")
"Same as --exclude but applies filtering also to the decomposition and/or containment " ("exclude+", po::value<exclusion_traverse_filter>(&exclude_traverse_filter)->multitoken(),
"of the filtered entity. See --include+ for more details.") "Same as --exclude but applies filtering also to the decomposition and/or containment "
("no-normals", "of the filtered entity. See --include+ for more details.")
"Disables computation of normals. Saves time and file size and is useful " ("filter-file", po::value<std::string>(&filter_filename),
"in instances where you're going to recompute normals for the exported " "Specifies a filter file that describes the used filtering criteria. Supported formats "
"model in other modelling application in any case.") "are '--include=arg GlobalId ...' and 'include arg GlobalId ...'. Spaces and tabs can be used as delimeters."
("deflection-tolerance", po::value<double>(&deflection_tolerance)->default_value(1e-3), "Multiple filters of same type with different values can be inserted on their own lines. "
"Sets the deflection tolerance of the mesher, 1e-3 by default if not specified.") "See --include, --include+, --exclude, and --exclude+ for more details.");
("generate-uvs", */
"Generates UVs (texture coordinates) by using simple box projection. Requires normals. " ("no-normals",
"Not guaranteed to work properly if used with --weld-vertices.") "Disables computation of normals. Saves time and file size and is useful "
("filter-file", po::value<std::string>(&filter_filename), "in instances where you're going to recompute normals for the exported "
"Specifies a filter file that describes the used filtering criteria. Supported formats " "model in other modelling application in any case.")
"are '--include=arg GlobalId ...' and 'include arg GlobalId ...'. Spaces and tabs can be used as delimeters." ("deflection-tolerance", po::value<double>(&deflection_tolerance)->default_value(1e-3),
"Multiple filters of same type with different values can be inserted on their own lines. " "Sets the deflection tolerance of the mesher, 1e-3 by default if not specified.")
"See --include, --include+, --exclude, and --exclude+ for more details."); ("generate-uvs",
"Generates UVs (texture coordinates) by using simple box projection. Requires normals. "
"Not guaranteed to work properly if used with --weld-vertices.");
std::string bounds, offset_str; std::string bounds, offset_str;
#ifdef HAVE_ICU #ifdef HAVE_ICU
@@ -456,6 +463,7 @@ int main(int argc, char** argv)
return exit_code; return exit_code;
} }
/*
if (!filter_filename.empty()) { if (!filter_filename.empty()) {
size_t num_filters = read_filters_from_file(filter_filename, include_filter, include_traverse_filter, exclude_filter, exclude_traverse_filter); size_t num_filters = read_filters_from_file(filter_filename, include_filter, include_traverse_filter, exclude_filter, exclude_traverse_filter);
if (num_filters) { if (num_filters) {
@@ -465,7 +473,7 @@ int main(int argc, char** argv)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
/// @todo Clean up this filter code further. /// @todo Clean up this filter code further.
std::vector<geom_filter> used_filters; std::vector<geom_filter> used_filters;
if (include_filter.type != geom_filter::UNUSED) { used_filters.push_back(include_filter); } if (include_filter.type != geom_filter::UNUSED) { used_filters.push_back(include_filter); }
@@ -485,6 +493,7 @@ int main(int argc, char** argv)
if (!name_filter.values.empty()) { name_filter.update_description(); Logger::Notice(name_filter.description); } if (!name_filter.values.empty()) { name_filter.update_description(); Logger::Notice(name_filter.description); }
if (!desc_filter.values.empty()) { desc_filter.update_description(); Logger::Notice(desc_filter.description); } if (!desc_filter.values.empty()) { desc_filter.update_description(); Logger::Notice(desc_filter.description); }
if (!tag_filter.values.empty()) { tag_filter.update_description(); Logger::Notice(tag_filter.description); } if (!tag_filter.values.empty()) { tag_filter.update_description(); Logger::Notice(tag_filter.description); }
*/
SerializerSettings settings; SerializerSettings settings;
/// @todo Make APPLY_DEFAULT_MATERIALS configurable? Quickly tested setting this to false and using obj exporter caused the program to crash and burn. /// @todo Make APPLY_DEFAULT_MATERIALS configurable? Quickly tested setting this to false and using obj exporter caused the program to crash and burn.
@@ -588,7 +597,7 @@ int main(int argc, char** argv)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
IfcGeom::Iterator<real_t> context_iterator(settings, &ifc_file, filter_funcs); IfcGeom::Iterator<real_t> context_iterator(settings, &ifc_file);
if (!context_iterator.initialize()) { if (!context_iterator.initialize()) {
/// @todo It would be nice to know and print separate error prints for a case where we found no entities /// @todo It would be nice to know and print separate error prints for a case where we found no entities
/// and for a case we found no entities that satisfy our filtering criteria. /// and for a case we found no entities that satisfy our filtering criteria.
@@ -599,10 +608,10 @@ int main(int argc, char** argv)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
serializer->setFile(context_iterator.getFile()); serializer->setFile(context_iterator.file());
if (convert_back_units) { if (convert_back_units) {
serializer->setUnitNameAndMagnitude(context_iterator.getUnitName(), static_cast<float>(context_iterator.getUnitMagnitude())); serializer->setUnitNameAndMagnitude(context_iterator.unit_name(), static_cast<float>(context_iterator.unit_magnitude()));
} else { } else {
serializer->setUnitNameAndMagnitude("METER", 1.0f); serializer->setUnitNameAndMagnitude("METER", 1.0f);
} }
@@ -619,10 +628,13 @@ int main(int argc, char** argv)
delete serializer; delete serializer;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
throw std::runtime_error("needs more work");
/*
gp_XYZ center = (context_iterator.bounds_min() + context_iterator.bounds_max()) * 0.5; gp_XYZ center = (context_iterator.bounds_min() + context_iterator.bounds_max()) * 0.5;
offset[0] = -center.X(); offset[0] = -center.X();
offset[1] = -center.Y(); offset[1] = -center.Y();
offset[2] = -center.Z(); offset[2] = -center.Z();
*/
} else { } else {
if (sscanf(offset_str.c_str(), "%lf;%lf;%lf", &offset[0], &offset[1], &offset[2]) != 3) { if (sscanf(offset_str.c_str(), "%lf;%lf;%lf", &offset[0], &offset[1], &offset[2]) != 3) {
std::cerr << "[Error] Invalid use of --model-offset\n"; std::cerr << "[Error] Invalid use of --model-offset\n";
@@ -716,16 +728,17 @@ void write_log() {
} }
} }
bool init_input_file(const std::string &filename, IfcParse::IfcFile &ifc_file, bool no_progress, bool mmap) bool init_input_file(const std::string& filename, IfcParse::IfcFile* ifc_file, bool no_progress, bool mmap) {
{
// Prevent IfcFile::Init() prints by setting output to null temporarily // Prevent IfcFile::Init() prints by setting output to null temporarily
if (no_progress) { Logger::SetOutput(NULL, &log_stream); } if (no_progress) { Logger::SetOutput(NULL, &log_stream); }
#ifdef USE_MMAP #ifdef USE_MMAP
if (!ifc_file.Init(filename, mmap)) { ifc_file = new IfcParse::IfcFile(filename, mmap);
#else #else
(void)mmap; (void)mmap;
if (!ifc_file.Init(filename)) { ifc_file = new IfcParse::IfcFile(filename);
if (!ifc_file->good()) {
#endif #endif
Logger::Error("Unable to parse input file '" + filename + "'"); Logger::Error("Unable to parse input file '" + filename + "'");
return false; return false;
@@ -734,8 +747,10 @@ bool init_input_file(const std::string &filename, IfcParse::IfcFile &ifc_file, b
if (no_progress) { Logger::SetOutput(&std::cout, &log_stream); } if (no_progress) { Logger::SetOutput(&std::cout, &log_stream); }
return true; return true;
} }
/*
bool append_filter(const std::string& type, const std::vector<std::string>& values, geom_filter& filter) bool append_filter(const std::string& type, const std::vector<std::string>& values, geom_filter& filter)
{ {
geom_filter temp; geom_filter temp;
@@ -928,3 +943,4 @@ std::vector<IfcGeom::filter_t> setup_filters(const std::vector<geom_filter>& fil
return filter_funcs; return filter_funcs;
} }
*/
+8 -14
View File
@@ -22,6 +22,7 @@
#include <cstdio> #include <cstdio>
#include <Standard_Version.hxx> #include <Standard_Version.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include "OpenCascadeBasedSerializer.h" #include "OpenCascadeBasedSerializer.h"
@@ -34,23 +35,16 @@ bool OpenCascadeBasedSerializer::ready() {
} }
void OpenCascadeBasedSerializer::write(const IfcGeom::BRepElement<real_t>* o) { void OpenCascadeBasedSerializer::write(const IfcGeom::BRepElement<real_t>* o) {
for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = o->geometry().begin(); it != o->geometry().end(); ++ it) { TopoDS_Shape compound = o->geometry().as_compound();
gp_GTrsf gtrsf = it->Placement();
const gp_Trsf& o_trsf = o->transformation().data(); if (o->geometry().settings().get(IfcGeom::IteratorSettings::CONVERT_BACK_UNITS)) {
gtrsf.PreMultiply(o_trsf); gp_Trsf scale;
scale.SetScaleFactor(1.0 / o->geometry().settings().unit_magnitude());
if (o->geometry().settings().get(IfcGeom::IteratorSettings::CONVERT_BACK_UNITS)) {
gp_Trsf scale;
scale.SetScaleFactor(1.0 / o->geometry().settings().unit_magnitude());
gtrsf.PreMultiply(scale);
}
const TopoDS_Shape& s = it->Shape(); compound = BRepBuilderAPI_Transform(compound, scale, true).Shape();
const TopoDS_Shape moved_shape = IfcGeom::Kernel::apply_transformation(s, gtrsf);
writeShape(moved_shape);
} }
writeShape(compound);
} }
#define RATHER_SMALL (1e-3) #define RATHER_SMALL (1e-3)
+39 -22
View File
@@ -50,6 +50,7 @@
#include <gp_Ax22d.hxx> #include <gp_Ax22d.hxx>
#include <Standard_Version.hxx> #include <Standard_Version.hxx>
#include <GeomAPI.hxx> #include <GeomAPI.hxx>
#include <TopoDS_Wire.hxx>
#include "../ifcparse/IfcGlobalId.h" #include "../ifcparse/IfcGlobalId.h"
@@ -103,7 +104,9 @@ void SvgSerializer::write(path_object& p, const TopoDS_Wire& wire) {
Handle(Standard_Type) ty = curve->DynamicType(); Handle(Standard_Type) ty = curve->DynamicType();
bool conical = (ty == STANDARD_TYPE(Geom_Circle) || ty == STANDARD_TYPE(Geom_Ellipse)); bool conical = (ty == STANDARD_TYPE(Geom_Circle) || ty == STANDARD_TYPE(Geom_Ellipse));
bool closed = ALMOST_THE_SAME(u1 + PI2, u2);
// TODO: ALMOST_THE_SAME utilities in separate header
bool closed = fabs((u1 + PI2) - u2) < 1.e-9;
if (conical && closed) { if (conical && closed) {
if (first) { if (first) {
@@ -274,7 +277,7 @@ void SvgSerializer::write(path_object& p, const TopoDS_Wire& wire) {
p.second.push_back(path); p.second.push_back(path);
} }
SvgSerializer::path_object& SvgSerializer::start_path(IfcSchema::IfcBuildingStorey* storey, const std::string& id) { SvgSerializer::path_object& SvgSerializer::start_path(IfcUtil::IfcBaseEntity* storey, const std::string& id) {
SvgSerializer::path_object& p = paths.insert(std::make_pair(storey, path_object()))->second; SvgSerializer::path_object& p = paths.insert(std::make_pair(storey, path_object()))->second;
p.first = id; p.first = id;
return p; return p;
@@ -282,8 +285,13 @@ SvgSerializer::path_object& SvgSerializer::start_path(IfcSchema::IfcBuildingStor
void SvgSerializer::write(const IfcGeom::BRepElement<real_t>* o) void SvgSerializer::write(const IfcGeom::BRepElement<real_t>* o)
{ {
IfcSchema::IfcBuildingStorey* storey = storey_; IfcUtil::IfcBaseEntity* storey = storey_;
boost::optional<double> storey_elevation = boost::none; boost::optional<double> storey_elevation = boost::none;
/*
TODO: based on BRepElement::parent()
IfcSchema::IfcObjectDefinition* obdef = static_cast<IfcSchema::IfcObjectDefinition*>(file->entityById(o->id())); IfcSchema::IfcObjectDefinition* obdef = static_cast<IfcSchema::IfcObjectDefinition*>(file->entityById(o->id()));
#ifndef USE_IFC4 #ifndef USE_IFC4
@@ -327,25 +335,25 @@ void SvgSerializer::write(const IfcGeom::BRepElement<real_t>* o)
break; break;
} }
} }
*/
// With a global section height, building storeys are not a requirement. // With a global section height, building storeys are not a requirement.
if (!storey && !section_height) return; if (!storey && !section_height) return;
path_object& p = start_path(storey, nameElement(o)); path_object& p = start_path(storey, nameElement(o));
for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = o->geometry().begin(); it != o->geometry().end(); ++ it) { TopoDS_Shape compound = o->geometry().as_compound();
gp_GTrsf gtrsf = it->Placement(); TopoDS_Iterator it(compound);
const gp_Trsf& o_trsf = o->transformation().data(); // Iterate over components of compound to have better chance of matching section edges to closed wires
gtrsf.PreMultiply(o_trsf); for (; it.More(); it.Next()) {
const TopoDS_Shape& subshape = it.Value();
const TopoDS_Shape& s = it->Shape();
const TopoDS_Shape moved_shape = IfcGeom::Kernel::apply_transformation(s, gtrsf);
const double inf = std::numeric_limits<double>::infinity(); const double inf = std::numeric_limits<double>::infinity();
double zmin = inf; double zmin = inf;
double zmax = -inf; double zmax = -inf;
{TopExp_Explorer exp(moved_shape, TopAbs_VERTEX); {TopExp_Explorer exp(subshape, TopAbs_VERTEX);
for (; exp.More(); exp.Next()) { for (; exp.More(); exp.Next()) {
const TopoDS_Vertex& vertex = TopoDS::Vertex(exp.Current()); const TopoDS_Vertex& vertex = TopoDS::Vertex(exp.Current());
gp_Pnt pnt = BRep_Tool::Pnt(vertex); gp_Pnt pnt = BRep_Tool::Pnt(vertex);
@@ -373,13 +381,13 @@ void SvgSerializer::write(const IfcGeom::BRepElement<real_t>* o)
} }
// Create a horizontal cross section 1 meter above the bottom point of the shape // Create a horizontal cross section 1 meter above the bottom point of the shape
TopoDS_Shape result = BRepAlgoAPI_Section(moved_shape, gp_Pln(gp_Pnt(0, 0, cut_z), gp::DZ())); TopoDS_Shape result = BRepAlgoAPI_Section(subshape, gp_Pln(gp_Pnt(0, 0, cut_z), gp::DZ()));
Handle(TopTools_HSequenceOfShape) edges = new TopTools_HSequenceOfShape(); Handle(TopTools_HSequenceOfShape) edges = new TopTools_HSequenceOfShape();
Handle(TopTools_HSequenceOfShape) wires = new TopTools_HSequenceOfShape(); Handle(TopTools_HSequenceOfShape) wires = new TopTools_HSequenceOfShape();
{TopExp_Explorer exp(result, TopAbs_EDGE); {TopExp_Explorer exp(result, TopAbs_EDGE);
for (; exp.More(); exp.Next()) { for (; exp.More(); exp.Next()) {
edges->Append(exp.Current()); edges->Append(exp.Current());
}} }}
ShapeAnalysis_FreeBounds::ConnectEdgesToWires(edges, 1e-5, false, wires); ShapeAnalysis_FreeBounds::ConnectEdgesToWires(edges, 1e-5, false, wires);
@@ -389,7 +397,7 @@ void SvgSerializer::write(const IfcGeom::BRepElement<real_t>* o)
const TopoDS_Wire& wire = TopoDS::Wire(wires->Value(i)); const TopoDS_Wire& wire = TopoDS::Wire(wires->Value(i));
write(p, wire); write(p, wire);
} }
} }
} }
void SvgSerializer::setBoundingRectangle(double width, double height) { void SvgSerializer::setBoundingRectangle(double width, double height) {
@@ -430,9 +438,9 @@ void SvgSerializer::finalize() {
}} }}
} }
std::multimap<IfcSchema::IfcBuildingStorey*, path_object>::const_iterator it; std::multimap<IfcUtil::IfcBaseEntity*, path_object>::const_iterator it;
IfcSchema::IfcBuildingStorey* previous = 0; IfcUtil::IfcBaseEntity* previous = 0;
bool first = true; bool first = true;
for (it = paths.begin(); it != paths.end(); ++it) { for (it = paths.begin(); it != paths.end(); ++it) {
if (it->first != previous || first) { if (it->first != previous || first) {
@@ -473,19 +481,27 @@ std::string SvgSerializer::nameElement(const IfcGeom::Element<real_t>* elem)
return oss.str(); return oss.str();
} }
std::string SvgSerializer::nameElement(const IfcSchema::IfcProduct* elem) { std::string SvgSerializer::nameElement(const IfcUtil::IfcBaseEntity* elem) {
if (elem == 0) { return ""; } if (elem == 0) { return ""; }
std::ostringstream oss; std::ostringstream oss;
const std::string type = elem->declaration().is(IfcSchema::Type::IfcBuildingStorey) ? "storey" : "product"; const std::string type = elem->declaration().is("IfcBuildingStorey") ? "storey" : "product";
const std::string name = (settings().get(SerializerSettings::USE_ELEMENT_GUIDS)
? elem->GlobalId() : (settings().get(SerializerSettings::USE_ELEMENT_NAMES) const std::string name =
? elem->Name() : IfcParse::IfcGlobalId(elem->GlobalId()).formatted())); (settings().get(SerializerSettings::USE_ELEMENT_GUIDS)
? static_cast<std::string>(*elem->get("GlobalId"))
: ((settings().get(SerializerSettings::USE_ELEMENT_NAMES) && !elem->get("Name")->isNull()))
? static_cast<std::string>(*elem->get("Name"))
: IfcParse::IfcGlobalId(*elem->get("GlobalId")).formatted());
oss << "id=\"" << type << "-" << name << "\""; oss << "id=\"" << type << "-" << name << "\"";
return oss.str(); return oss.str();
} }
void SvgSerializer::setFile(IfcParse::IfcFile* f) { void SvgSerializer::setFile(IfcParse::IfcFile* f) {
throw std::runtime_error("todo");
/*
file = f; file = f;
IfcSchema::IfcBuildingStorey::list::ptr storeys = f->entitiesByType<IfcSchema::IfcBuildingStorey>(); IfcSchema::IfcBuildingStorey::list::ptr storeys = f->entitiesByType<IfcSchema::IfcBuildingStorey>();
if (!storeys || storeys->size() == 0) { if (!storeys || storeys->size() == 0) {
@@ -526,4 +542,5 @@ void SvgSerializer::setFile(IfcParse::IfcFile* f) {
Logger::Error("No building storeys encountered, output might be invalid or missing"); Logger::Error("No building storeys encountered, output might be invalid or missing");
} }
*/
} }
+5 -5
View File
@@ -37,12 +37,12 @@ protected:
double xmin, ymin, xmax, ymax, width, height; double xmin, ymin, xmax, ymax, width, height;
boost::optional<double> section_height; boost::optional<double> section_height;
bool rescale; bool rescale;
std::multimap<IfcSchema::IfcBuildingStorey*, path_object> paths; std::multimap<IfcUtil::IfcBaseEntity*, path_object> paths;
std::vector< boost::shared_ptr<util::string_buffer::float_item> > xcoords; std::vector< boost::shared_ptr<util::string_buffer::float_item> > xcoords;
std::vector< boost::shared_ptr<util::string_buffer::float_item> > ycoords; std::vector< boost::shared_ptr<util::string_buffer::float_item> > ycoords;
std::vector< boost::shared_ptr<util::string_buffer::float_item> > radii; std::vector< boost::shared_ptr<util::string_buffer::float_item> > radii;
IfcParse::IfcFile* file; IfcParse::IfcFile* file;
IfcSchema::IfcBuildingStorey* storey_; IfcUtil::IfcBaseEntity* storey_;
public: public:
SvgSerializer(const std::string& out_filename, const SerializerSettings& settings) SvgSerializer(const std::string& out_filename, const SerializerSettings& settings)
: GeometrySerializer(settings) : GeometrySerializer(settings)
@@ -64,15 +64,15 @@ public:
void write(const IfcGeom::TriangulationElement<real_t>* /*o*/) {} void write(const IfcGeom::TriangulationElement<real_t>* /*o*/) {}
void write(const IfcGeom::BRepElement<real_t>* o); void write(const IfcGeom::BRepElement<real_t>* o);
void write(path_object& p, const TopoDS_Wire& wire); void write(path_object& p, const TopoDS_Wire& wire);
path_object& start_path(IfcSchema::IfcBuildingStorey* storey, const std::string& id); path_object& start_path(IfcUtil::IfcBaseEntity* storey, const std::string& id);
bool isTesselated() const { return false; } bool isTesselated() const { return false; }
void finalize(); void finalize();
void setUnitNameAndMagnitude(const std::string& /*name*/, float /*magnitude*/) {} void setUnitNameAndMagnitude(const std::string& /*name*/, float /*magnitude*/) {}
void setFile(IfcParse::IfcFile* f); void setFile(IfcParse::IfcFile* f);
void setBoundingRectangle(double width, double height); void setBoundingRectangle(double width, double height);
void setSectionHeight(double h, IfcSchema::IfcBuildingStorey* storey = 0) { section_height = h; storey_ = storey; } void setSectionHeight(double h, IfcUtil::IfcBaseEntity* storey = 0) { section_height = h; storey_ = storey; }
std::string nameElement(const IfcGeom::Element<real_t>* elem); std::string nameElement(const IfcGeom::Element<real_t>* elem);
std::string nameElement(const IfcSchema::IfcProduct* elem); std::string nameElement(const IfcUtil::IfcBaseEntity* elem);
}; };
#endif #endif
+3 -2
View File
@@ -28,10 +28,11 @@
#include <algorithm> #include <algorithm>
#include "../ifcparse/IfcSIPrefix.h" #include "../ifcparse/IfcSIPrefix.h"
#include "../ifcgeom/IfcGeom.h" // #include "../ifcgeom/IfcGeom.h"
using boost::property_tree::ptree; using boost::property_tree::ptree;
using namespace IfcSchema;
// using namespace IfcSchema;
namespace { namespace {
+7 -7
View File
@@ -90,7 +90,7 @@ namespace IfcGeom {
std::string _context; std::string _context;
std::string _unique_id; std::string _unique_id;
Transformation<P> _transformation; Transformation<P> _transformation;
IfcUtil::IfcBaseClass* product_; IfcUtil::IfcBaseEntity* product_;
std::vector<const IfcGeom::Element<P>*> _parents; std::vector<const IfcGeom::Element<P>*> _parents;
public: public:
@@ -101,9 +101,9 @@ namespace IfcGeom {
// Use the id to compare, or the elevation is the elements are IfcBuildingStoreys and the elevation is set // Use the id to compare, or the elevation is the elements are IfcBuildingStoreys and the elevation is set
friend bool operator < (const Element<P> & element1, const Element<P> & element2) { friend bool operator < (const Element<P> & element1, const Element<P> & element2) {
if (element1.type() == "IfcBuildingStorey" && element2.type() == "IfcBuildingStorey") { if (element1.type() == "IfcBuildingStorey" && element2.type() == "IfcBuildingStorey") {
size_t attr_index = product_->declaration().as_entity->attribute_index("Elevation"); size_t attr_index = element1.product()->declaration().attribute_index("Elevation");
Argument* elev_attr1 = storey1->data().getArgument(attr_index); Argument* elev_attr1 = element1.product()->data().getArgument(attr_index);
Argument* elev_attr2 = storey2->data().getArgument(attr_index); Argument* elev_attr2 = element2.product()->data().getArgument(attr_index);
if (!elev_attr1->isNull() && !elev_attr2->isNull()) { if (!elev_attr1->isNull() && !elev_attr2->isNull()) {
double elev1 = *elev_attr1; double elev1 = *elev_attr1;
@@ -124,12 +124,12 @@ namespace IfcGeom {
const std::string& context() const { return _context; } const std::string& context() const { return _context; }
const std::string& unique_id() const { return _unique_id; } const std::string& unique_id() const { return _unique_id; }
const Transformation<P>& transformation() const { return _transformation; } const Transformation<P>& transformation() const { return _transformation; }
IfcUtil::IfcBaseClass* product() const { return product_; } IfcUtil::IfcBaseEntity* product() const { return product_; }
const std::vector<const IfcGeom::Element<P>*> parents() const { return _parents; } const std::vector<const IfcGeom::Element<P>*> parents() const { return _parents; }
void SetParents(std::vector<const IfcGeom::Element<P>*> newparents) { _parents = newparents; } void SetParents(std::vector<const IfcGeom::Element<P>*> newparents) { _parents = newparents; }
Element(const ElementSettings& settings, int id, int parent_id, const std::string& name, const std::string& type, Element(const ElementSettings& settings, int id, int parent_id, const std::string& name, const std::string& type,
const std::string& guid, const std::string& context, const gp_Trsf& trsf, IfcUtil::IfcBaseClass* product) const std::string& guid, const std::string& context, const gp_Trsf& trsf, IfcUtil::IfcBaseEntity* product)
: _id(id), _parent_id(parent_id), _name(name), _type(type), _guid(guid), _context(context), _transformation(settings, trsf) : _id(id), _parent_id(parent_id), _name(name), _type(type), _guid(guid), _context(context), _transformation(settings, trsf)
, product_(product) , product_(product)
{ {
@@ -167,7 +167,7 @@ namespace IfcGeom {
const Representation::BRep& geometry() const { return *_geometry; } const Representation::BRep& geometry() const { return *_geometry; }
BRepElement(int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid, BRepElement(int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid,
const std::string& context, const gp_Trsf& trsf, const boost::shared_ptr<Representation::BRep>& geometry, const std::string& context, const gp_Trsf& trsf, const boost::shared_ptr<Representation::BRep>& geometry,
IfcUtil::IfcBaseClass* product) IfcUtil::IfcBaseEntity* product)
: Element<P>(geometry->settings() ,id, parent_id, name, type, guid, context, trsf, product) : Element<P>(geometry->settings() ,id, parent_id, name, type, guid, context, trsf, product)
, _geometry(geometry) , _geometry(geometry)
{} {}
+1 -1
View File
@@ -72,7 +72,7 @@ namespace IfcUtil {
virtual const IfcParse::entity& declaration() const = 0; virtual const IfcParse::entity& declaration() const = 0;
Argument* getArgumentByName(const std::string& name) const; Argument* get(const std::string& name) const;
}; };
// TODO: Investigate whether these should be template classes instead // TODO: Investigate whether these should be template classes instead
+4 -4
View File
@@ -78,14 +78,14 @@ namespace IfcGeom {
IfcParse::IfcFile* file_; IfcParse::IfcFile* file_;
IfcGeom::IteratorSettings settings_; IfcGeom::IteratorSettings settings_;
IteratorImplementation* implementation_; IteratorImplementation<P>* implementation_;
public: public:
Iterator(const IfcGeom::IteratorSettings& settings, IfcParse::IfcFile* file) Iterator(const IfcGeom::IteratorSettings& settings, IfcParse::IfcFile* file)
: file_(file) : file_(file)
, settings_(settings) , settings_(settings)
{ {
implementation_ = iterator_implementations().construct(file_->schema()->name()); implementation_ = iterator_implementations<P>().construct(file_->schema()->name(), settings, file);
} }
bool initialize() { bool initialize() {
@@ -94,11 +94,11 @@ namespace IfcGeom {
int progress() const { return implementation_->progress(); } int progress() const { return implementation_->progress(); }
std::string& unit_name() const { return implementation_->getUnitName(); } const std::string& unit_name() const { return implementation_->getUnitName(); }
double unit_magnitude() const { return implementation_->getUnitMagnitude(); } double unit_magnitude() const { return implementation_->getUnitMagnitude(); }
IfcParse::IfcFile* file() const { return implementation_->getFile(); } IfcParse::IfcFile* file() const { return implementation_->file(); }
IfcUtil::IfcBaseClass* next() const { return implementation_->next(); } IfcUtil::IfcBaseClass* next() const { return implementation_->next(); }