mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-14 19:34:34 +00:00
Merge branch 'master' into v0.6.0
# Conflicts: # src/ifcconvert/IfcConvert.cpp # src/ifcgeom/IfcGeomShapes.cpp # src/serializers/ColladaSerializer.cpp # src/serializers/schema_dependent/XmlSerializer.cpp
This commit is contained in:
@@ -164,6 +164,7 @@ int main(int argc, char** argv)
|
||||
("version", "display version information")
|
||||
("verbose,v", "more verbose log messages")
|
||||
("quiet,q", "less status and progress output")
|
||||
("stderr-progress", "output progress to stderr stream")
|
||||
("yes,y", "answer 'yes' automatically to possible confirmation queries (e.g. overwriting an existing output file)")
|
||||
("no-progress", "suppress possible progress bar type of prints that use carriage return")
|
||||
("log-format", po::value<std::string>(&log_format), "log format: plain or json");
|
||||
@@ -305,7 +306,7 @@ int main(int argc, char** argv)
|
||||
"Applicable for DAE output.")
|
||||
("center-model",
|
||||
"Centers the elements upon serialization by applying the center point of "
|
||||
"all placements as an offset. Applicable for OBJ and DAE output.")
|
||||
"all placements as an offset. Applicable for OBJ and DAE output. Can take several minutes on large models.")
|
||||
("model-offset", po::value<std::string>(&offset_str),
|
||||
"Applies an arbitrary offset of form 'x;y;z' to all placements. Applicable for OBJ and DAE output.")
|
||||
("site-local-placement",
|
||||
@@ -353,6 +354,7 @@ int main(int argc, char** argv)
|
||||
const bool verbose = vmap.count("verbose") != 0;
|
||||
const bool no_progress = vmap.count("no-progress") != 0;
|
||||
const bool quiet = vmap.count("quiet") != 0;
|
||||
const bool stderr_progress = vmap.count("stderr-progress") != 0;
|
||||
const bool weld_vertices = vmap.count("weld-vertices") != 0;
|
||||
const bool use_world_coords = vmap.count("use-world-coords") != 0;
|
||||
const bool convert_back_units = vmap.count("convert-back-units") != 0;
|
||||
@@ -650,7 +652,7 @@ int main(int argc, char** argv)
|
||||
|
||||
int old_progress = quiet ? 0 : -1;
|
||||
|
||||
if (center_model || model_offset) {
|
||||
if (is_tesselated && (center_model || model_offset)) {
|
||||
double* offset = serializer->settings().offset;
|
||||
if (center_model) {
|
||||
if (site_local_placement || building_local_placement) {
|
||||
@@ -658,8 +660,14 @@ int main(int argc, char** argv)
|
||||
delete serializer;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
throw std::runtime_error("needs more work");
|
||||
|
||||
/*
|
||||
if (!quiet) Logger::Status("Computing bounds...");
|
||||
context_iterator.compute_bounds();
|
||||
if (!quiet) Logger::Status("Done!");
|
||||
|
||||
gp_XYZ center = (context_iterator.bounds_min() + context_iterator.bounds_max()) * 0.5;
|
||||
offset[0] = -center.X();
|
||||
offset[1] = -center.Y();
|
||||
@@ -713,8 +721,12 @@ int main(int argc, char** argv)
|
||||
const int progress = context_iterator.progress();
|
||||
for (; old_progress < progress; ++old_progress) {
|
||||
std::cout << ".";
|
||||
if (stderr_progress)
|
||||
std::cerr << ".";
|
||||
}
|
||||
std::cout << std::flush;
|
||||
if (stderr_progress)
|
||||
std::cerr << std::flush;
|
||||
} else {
|
||||
const int progress = context_iterator.progress() / 2;
|
||||
if (old_progress != progress) Logger::ProgressBar(progress);
|
||||
@@ -726,7 +738,12 @@ int main(int argc, char** argv)
|
||||
if (!no_progress && quiet) {
|
||||
for (; old_progress < 100; ++old_progress) {
|
||||
std::cout << ".";
|
||||
if (stderr_progress)
|
||||
std::cerr << ".";
|
||||
}
|
||||
std::cout << std::flush;
|
||||
if (stderr_progress)
|
||||
std::cerr << std::flush;
|
||||
} else {
|
||||
Logger::Status("\rDone creating geometry (" + boost::lexical_cast<std::string>(num_created) +
|
||||
" objects) ");
|
||||
|
||||
@@ -169,6 +169,8 @@ public:
|
||||
bool boolean_operation(const TopoDS_Shape&, const TopoDS_Shape&, BOPAlgo_Operation, TopoDS_Shape&, double fuzziness = -1.);
|
||||
#endif
|
||||
|
||||
bool fit_halfspace(const TopoDS_Shape& a, const TopoDS_Shape& b, TopoDS_Shape& box, double& height);
|
||||
|
||||
const Handle_Geom_Curve intersect(const Handle_Geom_Surface&, const Handle_Geom_Surface&);
|
||||
const Handle_Geom_Curve intersect(const Handle_Geom_Surface&, const TopoDS_Face&);
|
||||
const Handle_Geom_Curve intersect(const TopoDS_Face&, const Handle_Geom_Surface&);
|
||||
|
||||
@@ -135,6 +135,9 @@
|
||||
|
||||
#include <GeomAPI_ExtremaCurveCurve.hxx>
|
||||
|
||||
#include <Extrema_ExtPC.hxx>
|
||||
#include <BRepAdaptor_Curve.hxx>
|
||||
|
||||
#include <Standard_Version.hxx>
|
||||
|
||||
#include "../ifcparse/macros.h"
|
||||
@@ -691,8 +694,27 @@ bool IfcGeom::Kernel::convert_wire_to_face(const TopoDS_Wire& w, TopoDS_Face& fa
|
||||
select_largest(results, wire);
|
||||
}
|
||||
|
||||
ShapeFix_ShapeTolerance FTol;
|
||||
FTol.SetTolerance(wire, getValue(GV_PRECISION), TopAbs_WIRE);
|
||||
bool is_2d = true;
|
||||
TopExp_Explorer exp(wire, TopAbs_EDGE);
|
||||
for (; exp.More(); exp.Next()) {
|
||||
double a, b;
|
||||
Handle(Geom_Curve) crv = BRep_Tool::Curve(TopoDS::Edge(exp.Current()), a, b);
|
||||
if (crv->DynamicType() != STANDARD_TYPE(Geom_Line)) {
|
||||
is_2d = false;
|
||||
break;
|
||||
}
|
||||
Handle(Geom_Line) line = Handle(Geom_Line)::DownCast(crv);
|
||||
if (line->Lin().Direction().Z() > ALMOST_ZERO) {
|
||||
is_2d = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_2d) {
|
||||
// For 2d wires (e.g. profiles) a higher tolerance for plane fitting is never required.
|
||||
ShapeFix_ShapeTolerance FTol;
|
||||
FTol.SetTolerance(wire, getValue(GV_PRECISION), TopAbs_WIRE);
|
||||
}
|
||||
|
||||
BRepBuilderAPI_MakeFace mf(wire, false);
|
||||
BRepBuilderAPI_FaceError er = mf.Error();
|
||||
@@ -2899,7 +2921,7 @@ bool IfcGeom::Kernel::wire_intersections(const TopoDS_Wire& wire, TopTools_ListO
|
||||
if (i == n - 1 && j == 0) continue;
|
||||
|
||||
bool unbounded_intersects;
|
||||
const double eps = getValue(GV_PRECISION) * 2.;
|
||||
const double eps = getValue(GV_PRECISION) * 10.;
|
||||
|
||||
double u11, u12, u21, u22, U1, U2;
|
||||
GeomAPI_ExtremaCurveCurve ecc(
|
||||
@@ -3035,6 +3057,99 @@ void IfcGeom::Kernel::select_largest(const TopTools_ListOfShape& shapes, TopoDS_
|
||||
}
|
||||
}
|
||||
|
||||
bool IfcGeom::Kernel::fit_halfspace(const TopoDS_Shape& a, const TopoDS_Shape& b, TopoDS_Shape& box, double& height) {
|
||||
TopExp_Explorer exp(b, TopAbs_FACE);
|
||||
if (!exp.More()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TopoDS_Face face = TopoDS::Face(exp.Current());
|
||||
exp.Next();
|
||||
|
||||
if (exp.More()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
|
||||
|
||||
// const gp_XYZ xyz = a.Location().Transformation().TranslationPart();
|
||||
// std::cout << "dz " << xyz.Z() << std::endl;
|
||||
|
||||
if (surf->DynamicType() != STANDARD_TYPE(Geom_Plane)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Bnd_Box bb;
|
||||
BRepBndLib::Add(a, bb);
|
||||
|
||||
double xs[2], ys[2], zs[2];
|
||||
bb.Get(xs[0], ys[0], zs[0], xs[1], ys[1], zs[1]);
|
||||
|
||||
gp_Pln pln = Handle(Geom_Plane)::DownCast(surf)->Pln();
|
||||
|
||||
gp_Pnt P = pln.Position().Location();
|
||||
gp_Vec z = pln.Position().Direction();
|
||||
gp_Vec x = pln.Position().XDirection();
|
||||
gp_Vec y = pln.Position().YDirection();
|
||||
|
||||
if (face.Orientation() != TopAbs_REVERSED) {
|
||||
z.Reverse();
|
||||
}
|
||||
|
||||
double D, Umin, Umax, Vmin, Vmax;
|
||||
D = 0.;
|
||||
Umin = Vmin = +std::numeric_limits<double>::infinity();
|
||||
Umax = Vmax = -std::numeric_limits<double>::infinity();
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
for (int j = 0; j < 2; ++j) {
|
||||
for (int k = 0; k < 2; ++k) {
|
||||
gp_Pnt p(xs[i], ys[j], zs[k]);
|
||||
|
||||
gp_Vec d = p.XYZ() - P.XYZ();
|
||||
const double u = d.Dot(x);
|
||||
const double v = d.Dot(y);
|
||||
const double w = d.Dot(z);
|
||||
|
||||
if (w > D) {
|
||||
D = w;
|
||||
}
|
||||
if (u < Umin) {
|
||||
Umin = u;
|
||||
}
|
||||
if (u > Umax) {
|
||||
Umax = u;
|
||||
}
|
||||
if (v < Vmin) {
|
||||
Vmin = v;
|
||||
}
|
||||
if (v > Vmax) {
|
||||
Vmax = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const double eps = getValue(GV_PRECISION) * 2.;
|
||||
|
||||
BRepBuilderAPI_MakePolygon poly;
|
||||
poly.Add(P.XYZ() + x.XYZ() * (Umin + eps) + y.XYZ() * (Vmin + eps));
|
||||
poly.Add(P.XYZ() + x.XYZ() * (Umax + eps) + y.XYZ() * (Vmin + eps));
|
||||
poly.Add(P.XYZ() + x.XYZ() * (Umax + eps) + y.XYZ() * (Vmax + eps));
|
||||
poly.Add(P.XYZ() + x.XYZ() * (Umin + eps) + y.XYZ() * (Vmax + eps));
|
||||
poly.Close();
|
||||
|
||||
BRepBuilderAPI_MakeFace mf(surf, poly.Wire(), true);
|
||||
|
||||
gp_Vec vec = gp_Vec(z.XYZ() * (D + eps));
|
||||
|
||||
BRepPrimAPI_MakePrism mp(mf.Face(), vec);
|
||||
box = mp.Shape();
|
||||
|
||||
height = D;
|
||||
return true;
|
||||
}
|
||||
|
||||
#if OCC_VERSION_HEX < 0x60900
|
||||
bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopTools_ListOfShape& b, BOPAlgo_Operation op, TopoDS_Shape& result) {
|
||||
result = a;
|
||||
@@ -3132,6 +3247,48 @@ namespace {
|
||||
}
|
||||
return min_edge_len;
|
||||
}
|
||||
|
||||
double min_vertex_edge_distance(const TopoDS_Shape& a, double t) {
|
||||
TopExp_Explorer exp(a, TopAbs_VERTEX);
|
||||
|
||||
double M = std::numeric_limits<double>::infinity();
|
||||
|
||||
for (; exp.More(); exp.Next()) {
|
||||
if (exp.Current().Orientation() != TopAbs_FORWARD) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const TopoDS_Vertex& v = TopoDS::Vertex(exp.Current());
|
||||
gp_Pnt p = BRep_Tool::Pnt(v);
|
||||
|
||||
TopExp_Explorer exp2(a, TopAbs_EDGE);
|
||||
for (; exp2.More(); exp2.Next()) {
|
||||
const TopoDS_Edge& e = TopoDS::Edge(exp2.Current());
|
||||
TopoDS_Vertex v1, v2;
|
||||
TopExp::Vertices(e, v1, v2);
|
||||
|
||||
if (v.IsEqual(v1) || v.IsEqual(v2)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BRepAdaptor_Curve crv(e);
|
||||
Extrema_ExtPC ext(p, crv);
|
||||
if (!ext.IsDone()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= ext.NbExt(); ++i) {
|
||||
const double m = sqrt(ext.SquareDistance(i));
|
||||
if (m < M && m > t) {
|
||||
M = m;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return M;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopTools_ListOfShape& b, BOPAlgo_Operation op, TopoDS_Shape& result, double fuzziness) {
|
||||
@@ -3150,8 +3307,20 @@ bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopTools_Li
|
||||
fuzziness = getValue(GV_PRECISION);
|
||||
}
|
||||
|
||||
const double min_edge_len = min_edge_length(a);
|
||||
const double fuzz = (std::min)(min_edge_len / 3., fuzziness);
|
||||
double min_len = (std::min)(min_edge_length(a), min_vertex_edge_distance(a, getValue(GV_PRECISION)));
|
||||
TopTools_ListIteratorOfListOfShape it(b);
|
||||
for (; it.More(); it.Next()) {
|
||||
double d = min_edge_length(it.Value());
|
||||
if (d < min_len) {
|
||||
min_len = d;
|
||||
}
|
||||
d = min_vertex_edge_distance(it.Value(), getValue(GV_PRECISION));
|
||||
if (d < min_len) {
|
||||
min_len = d;
|
||||
}
|
||||
}
|
||||
|
||||
const double fuzz = (std::min)(min_len / 10., fuzziness);
|
||||
|
||||
TopTools_ListOfShape s1s;
|
||||
s1s.Append(copy_operand(a));
|
||||
@@ -3185,7 +3354,7 @@ bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopTools_Li
|
||||
delete builder;
|
||||
if (!success) {
|
||||
const double new_fuzziness = fuzziness * 10.;
|
||||
if (new_fuzziness + 1e-15 <= getValue(GV_PRECISION) * 1000. && new_fuzziness < min_edge_len) {
|
||||
if (new_fuzziness + 1e-15 <= getValue(GV_PRECISION) * 1000. && new_fuzziness < min_len) {
|
||||
return boolean_operation(a, b, op, result, new_fuzziness);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,6 +291,13 @@ namespace IfcGeom {
|
||||
done = 0;
|
||||
total = representations->size();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Computes model's bounding box (bounds_min and bounds_max).
|
||||
/// @note Can take several minutes for large files.
|
||||
void compute_bounds()
|
||||
{
|
||||
for (int i = 1; i < 4; ++i) {
|
||||
bounds_min_.SetCoord(i, std::numeric_limits<double>::infinity());
|
||||
bounds_max_.SetCoord(i, -std::numeric_limits<double>::infinity());
|
||||
@@ -300,21 +307,21 @@ namespace IfcGeom {
|
||||
for (IfcSchema::IfcProduct::list::it iter = products->begin(); iter != products->end(); ++iter) {
|
||||
IfcSchema::IfcProduct* product = *iter;
|
||||
if (product->hasObjectPlacement()) {
|
||||
// Use a fresh trsf every time in order to prevent the result to be concatenated
|
||||
// Use a fresh trsf every time in order to prevent the result to be concatenated
|
||||
gp_Trsf trsf;
|
||||
bool success = false;
|
||||
|
||||
try {
|
||||
success = kernel.convert(product->ObjectPlacement(), trsf);
|
||||
} catch (const std::exception& e) {
|
||||
Logger::Error(e);
|
||||
} catch (...) {
|
||||
Logger::Error("Failed to construct placement");
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
continue;
|
||||
}
|
||||
bool success = false;
|
||||
|
||||
try {
|
||||
success = kernel.convert(product->ObjectPlacement(), trsf);
|
||||
} catch (const std::exception& e) {
|
||||
Logger::Error(e);
|
||||
} catch (...) {
|
||||
Logger::Error("Failed to construct placement");
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const gp_XYZ& pos = trsf.TranslationPart();
|
||||
bounds_min_.SetX(std::min(bounds_min_.X(), pos.X()));
|
||||
@@ -325,9 +332,7 @@ namespace IfcGeom {
|
||||
bounds_max_.SetZ(std::max(bounds_max_.Z(), pos.Z()));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int progress() const { return 100 * done / total; }
|
||||
|
||||
|
||||
@@ -481,6 +481,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape
|
||||
IfcSchema::IfcBooleanOperand* operand1 = l->FirstOperand();
|
||||
IfcSchema::IfcBooleanOperand* operand2 = l->SecondOperand();
|
||||
bool is_halfspace = operand2->declaration().is(IfcSchema::IfcHalfSpaceSolid::Class());
|
||||
bool is_unbounded_halfspace = is_halfspace && !operand2->declaration().is(IfcSchema::IfcPolygonalBoundedHalfSpace::Class());
|
||||
|
||||
if ( shape_type(operand1) == ST_SHAPELIST ) {
|
||||
if (!(convert_shapes(operand1, items1) && flatten_shape_list(items1, s1, true))) {
|
||||
@@ -526,6 +527,20 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape
|
||||
Logger::Message(Logger::LOG_WARNING,"Empty solid for:",operand2);
|
||||
}
|
||||
|
||||
if (is_unbounded_halfspace) {
|
||||
TopoDS_Shape temp;
|
||||
double d;
|
||||
if (fit_halfspace(s1, s2, temp, d)) {
|
||||
if (d < getValue(GV_PRECISION)) {
|
||||
Logger::Message(Logger::LOG_WARNING, "Subtraction yields unchanged volume:", l);
|
||||
shape = s1;
|
||||
return true;
|
||||
} else {
|
||||
s2 = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const IfcSchema::IfcBooleanOperator::Value op = l->Operator();
|
||||
|
||||
/*
|
||||
|
||||
@@ -1810,7 +1810,7 @@ void IfcFile::removeEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
entities_by_ref_t::iterator byref_it = byref.find(name);
|
||||
if (byref_it != byref.end()) {
|
||||
std::vector<unsigned>& ids = byref_it->second;
|
||||
std::remove(ids.begin(), ids.end(), name);
|
||||
ids.erase(std::remove(ids.begin(), ids.end(), id), ids.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,20 +263,13 @@ void ColladaSerializer::ColladaExporter::ColladaScene::addParent(const IfcGeom::
|
||||
{ 0, 0, 0, 1 }
|
||||
};
|
||||
|
||||
// Chose a name of the parent object
|
||||
std::string name = "";
|
||||
if (serializer->settings().get(SerializerSettings::USE_ELEMENT_TYPES)) {
|
||||
name = parent.type() + " " + parent.name();
|
||||
} else {
|
||||
name = parent.unique_id();
|
||||
}
|
||||
std::string name = serializer->object_id(&parent);
|
||||
collada_id(name);
|
||||
|
||||
const std::string& id = name;
|
||||
|
||||
COLLADASW::Node *current_node;
|
||||
current_node = new COLLADASW::Node(mSW);
|
||||
current_node->setNodeId(id);
|
||||
current_node->setNodeId(name);
|
||||
/// @todo redundant information using ID as both ID and Name, maybe omit Name or allow specifying what would be used as the name
|
||||
current_node->setNodeName(name);
|
||||
current_node->setType(COLLADASW::Node::NODE);
|
||||
current_node->start();
|
||||
@@ -391,19 +384,7 @@ void ColladaSerializer::ColladaExporter::write(const IfcGeom::TriangulationEleme
|
||||
{
|
||||
const IfcGeom::Representation::Triangulation<real_t>& mesh = o->geometry();
|
||||
|
||||
std::string slabSuffix = "";
|
||||
if (o->type() == "IfcSlab")
|
||||
{
|
||||
slabSuffix = differentiateSlabTypes(o);
|
||||
}
|
||||
|
||||
std::string name = serializer->settings().get(SerializerSettings::USE_ELEMENT_GUIDS)
|
||||
? o->guid()
|
||||
: (serializer->settings().get(SerializerSettings::USE_ELEMENT_NAMES)
|
||||
? o->name()
|
||||
: (serializer->settings().get(SerializerSettings::USE_ELEMENT_TYPES)
|
||||
? (o->type() + slabSuffix)
|
||||
: o->unique_id()));
|
||||
std::string name = serializer->object_id(o);
|
||||
collada_id(name);
|
||||
|
||||
std::string representation_id = "representation-" + o->geometry().id();
|
||||
@@ -430,26 +411,50 @@ void ColladaSerializer::ColladaExporter::write(const IfcGeom::TriangulationEleme
|
||||
deferreds.push_back(deferred);
|
||||
}
|
||||
|
||||
std::string ColladaSerializer::ColladaExporter::differentiateSlabTypes(const IfcGeom::TriangulationElement<real_t>* o) {
|
||||
std::string ColladaSerializer::differentiateSlabTypes(const IfcUtil::IfcBaseEntity* slab)
|
||||
{
|
||||
auto value = slab->get("PredefinedType");
|
||||
|
||||
if (value->isNull()) {
|
||||
return "_Unknown";
|
||||
}
|
||||
|
||||
const std::string str_value = *value;
|
||||
std::string result;
|
||||
|
||||
if (!o->product()->get("ObjectType")->isNull()) {
|
||||
const std::string object_type = *o->product()->get("ObjectType");
|
||||
result = "_" + object_type;
|
||||
if (str_value == "FLOOR") {
|
||||
result = "_Floor";
|
||||
} else if (str_value == "ROOF") {
|
||||
result = "_Roof";
|
||||
} else if (str_value == "LANDING") {
|
||||
result = "_Landing";
|
||||
} else if (str_value == "BASESLAB") {
|
||||
result = "_BaseSlab";
|
||||
} else if (str_value == "NOTDEFINED") {
|
||||
result = "_NotDefined";
|
||||
} else {
|
||||
result = "_Unknown";
|
||||
auto otype = slab->get("ObjectType");
|
||||
if (otype->isNull()) {
|
||||
result = "_Unknown";
|
||||
} else {
|
||||
result = *otype;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string slabtype = *o->product()->get("PredefinedType");
|
||||
if (slabtype != "NOTDEFINED" && slabtype != "USERDEFINED") {
|
||||
result = "_" + slabtype;
|
||||
}
|
||||
|
||||
collada_id(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string ColladaSerializer::object_id(const IfcGeom::Element<real_t>* o) /*override*/
|
||||
{
|
||||
if (settings_.get(SerializerSettings::USE_ELEMENT_TYPES)) {
|
||||
const std::string slabSuffix = (o->product() && o->product()->declaration().name() == "IfcSlab")
|
||||
? differentiateSlabTypes(o->product())
|
||||
: "";
|
||||
return o->type() + slabSuffix;
|
||||
}
|
||||
return GeometrySerializer::object_id(o);
|
||||
}
|
||||
|
||||
void ColladaSerializer::ColladaExporter::endDocument() {
|
||||
// In fact due the XML based nature of Collada and its dependency on library nodes,
|
||||
// only at this point all objects are written to the stream.
|
||||
|
||||
@@ -189,7 +189,6 @@ private:
|
||||
COLLADABU::NativeString filename;
|
||||
COLLADASW::StreamWriter stream;
|
||||
ColladaScene scene;
|
||||
std::string differentiateSlabTypes(const IfcGeom::TriangulationElement<real_t>* o);
|
||||
public:
|
||||
/// @param double_precision Whether to use "double precision" (up to 16 decimals) or not (6 or 7 decimals).
|
||||
ColladaExporter(const std::string& scene_name, const std::string& fn, ColladaSerializer *_serializer,
|
||||
@@ -235,6 +234,11 @@ public:
|
||||
unit_magnitude = magnitude;
|
||||
}
|
||||
void setFile(IfcParse::IfcFile*) {}
|
||||
|
||||
std::string object_id(const IfcGeom::Element<real_t>* o) /*override*/;
|
||||
|
||||
private:
|
||||
static std::string differentiateSlabTypes(const IfcUtil::IfcBaseEntity* slab);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -83,6 +83,14 @@ public:
|
||||
const SerializerSettings& settings() const { return settings_; }
|
||||
SerializerSettings& settings() { return settings_; }
|
||||
|
||||
/// Returns ID for the object depending on the used setting.
|
||||
virtual std::string object_id(const IfcGeom::Element<real_t>* o)
|
||||
{
|
||||
if (settings_.get(SerializerSettings::USE_ELEMENT_GUIDS)) return o->guid();
|
||||
if (settings_.get(SerializerSettings::USE_ELEMENT_NAMES)) return o->name();
|
||||
return o->unique_id();
|
||||
}
|
||||
|
||||
protected:
|
||||
SerializerSettings settings_;
|
||||
};
|
||||
|
||||
@@ -474,9 +474,7 @@ std::string SvgSerializer::nameElement(const IfcGeom::Element<real_t>* elem)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
const std::string type = "product";
|
||||
const std::string name = (settings().get(SerializerSettings::USE_ELEMENT_GUIDS)
|
||||
? elem->guid() : (settings().get(SerializerSettings::USE_ELEMENT_NAMES)
|
||||
? elem->name() : elem->unique_id()));
|
||||
const std::string name = object_id(elem);
|
||||
oss << "id=\"" << type << "-" << name<< "\"";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -73,10 +73,7 @@ void WaveFrontOBJSerializer::writeMaterial(const IfcGeom::Material& style)
|
||||
|
||||
void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement<real_t>* o)
|
||||
{
|
||||
const std::string name = (settings().get(SerializerSettings::USE_ELEMENT_GUIDS)
|
||||
? o->guid() : (settings().get(SerializerSettings::USE_ELEMENT_NAMES)
|
||||
? o->name() : o->unique_id()));
|
||||
obj_stream << "g " << name << "\n";
|
||||
obj_stream << "g " << object_id(o) << "\n";
|
||||
obj_stream << "s 1" << "\n";
|
||||
|
||||
const IfcGeom::Representation::Triangulation<real_t>& mesh = o->geometry();
|
||||
|
||||
@@ -153,6 +153,12 @@ boost::optional<std::string> format_attribute(const Argument* argument, IfcUtil:
|
||||
ptree& format_entity_instance(IfcUtil::IfcBaseEntity* instance, ptree& child, ptree& tree, bool as_link = false) {
|
||||
const unsigned n = instance->declaration().attribute_count();
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
try {
|
||||
instance->data().getArgument(i);
|
||||
} catch (const std::exception&) {
|
||||
Logger::Error("Expected " + boost::lexical_cast<std::string>(n) + " attributes for:", instance);
|
||||
break;
|
||||
}
|
||||
const Argument* argument = instance->data().getArgument(i);
|
||||
if (argument->isNull()) continue;
|
||||
|
||||
@@ -343,7 +349,11 @@ void format_properties(IfcSchema::IfcProperty::list::ptr properties, ptree& node
|
||||
void format_quantities(IfcSchema::IfcPhysicalQuantity::list::ptr quantities, ptree& node) {
|
||||
for (IfcSchema::IfcPhysicalQuantity::list::it it = quantities->begin(); it != quantities->end(); ++it) {
|
||||
IfcSchema::IfcPhysicalQuantity* p = *it;
|
||||
format_entity_instance(p, node);
|
||||
ptree& node2 = format_entity_instance(p, node);
|
||||
if (p->declaration().is(IfcSchema::IfcPhysicalComplexQuantity::Class())) {
|
||||
IfcSchema::IfcPhysicalComplexQuantity* complex = (IfcSchema::IfcPhysicalComplexQuantity*)p;
|
||||
format_quantities(complex->HasQuantities(), node2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -374,13 +384,55 @@ void MAKE_TYPE_NAME(XmlSerializer)::finalize() {
|
||||
BOOST_FOREACH(const std::string& s, file->header().file_schema().schema_identifiers()) {
|
||||
header.add_child("file_schema.schema_identifiers", ptree(s));
|
||||
}
|
||||
header.put("file_description.implementation_level", file->header().file_description().implementation_level());
|
||||
header.put("file_name.name", file->header().file_name().name());
|
||||
header.put("file_name.time_stamp", file->header().file_name().time_stamp());
|
||||
header.put("file_name.preprocessor_version", file->header().file_name().preprocessor_version());
|
||||
header.put("file_name.originating_system", file->header().file_name().originating_system());
|
||||
header.put("file_name.authorization", file->header().file_name().authorization());
|
||||
|
||||
try {
|
||||
header.put("file_description.implementation_level", file->header().file_description().implementation_level());
|
||||
}
|
||||
catch (const IfcParse::IfcException& ex) {
|
||||
std::stringstream ss;
|
||||
ss << "Failed to get ifc file header file_description implementation_level, error: '" << ex.what() << "'";
|
||||
Logger::Message(Logger::LOG_ERROR, ss.str());
|
||||
}
|
||||
try {
|
||||
header.put("file_name.name", file->header().file_name().name());
|
||||
}
|
||||
catch (const IfcParse::IfcException& ex) {
|
||||
std::stringstream ss;
|
||||
ss << "Failed to get ifc file header file_name name, error: '" << ex.what() << "'";
|
||||
Logger::Message(Logger::LOG_ERROR, ss.str());
|
||||
}
|
||||
try {
|
||||
header.put("file_name.time_stamp", file->header().file_name().time_stamp());
|
||||
}
|
||||
catch (const IfcParse::IfcException& ex) {
|
||||
std::stringstream ss;
|
||||
ss << "Failed to get ifc file header file_name time_stamp, error: '" << ex.what() << "'";
|
||||
Logger::Message(Logger::LOG_ERROR, ss.str());
|
||||
}
|
||||
try {
|
||||
header.put("file_name.preprocessor_version", file->header().file_name().preprocessor_version());
|
||||
}
|
||||
catch (const IfcParse::IfcException& ex) {
|
||||
std::stringstream ss;
|
||||
ss << "Failed to get ifc file header file_name preprocessor_version, error: '" << ex.what() << "'";
|
||||
Logger::Message(Logger::LOG_ERROR, ss.str());
|
||||
}
|
||||
try {
|
||||
header.put("file_name.originating_system", file->header().file_name().originating_system());
|
||||
}
|
||||
catch (const IfcParse::IfcException& ex) {
|
||||
std::stringstream ss;
|
||||
ss << "Failed to get ifc file header file_name originating_system, error: '" << ex.what() << "'";
|
||||
Logger::Message(Logger::LOG_ERROR, ss.str());
|
||||
}
|
||||
try {
|
||||
header.put("file_name.authorization", file->header().file_name().authorization());
|
||||
}
|
||||
catch (const IfcParse::IfcException& ex) {
|
||||
std::stringstream ss;
|
||||
ss << "Failed to get ifc file header file_name authorization, error: '" << ex.what() << "'";
|
||||
Logger::Message(Logger::LOG_ERROR, ss.str());
|
||||
}
|
||||
|
||||
// Descend into the decomposition structure of the IFC file.
|
||||
descend(project, decomposition);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user