mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-26 02:07:36 +00:00
Emit surface genus for representation items
This commit is contained in:
@@ -270,7 +270,8 @@ int main(int argc, char** argv)
|
|||||||
"Not guaranteed to work properly if used with --weld-vertices.")
|
"Not guaranteed to work properly if used with --weld-vertices.")
|
||||||
("default-material-file", po::value<std::string>(&default_material_filename),
|
("default-material-file", po::value<std::string>(&default_material_filename),
|
||||||
"Specifies a material file that describes the material object types will have"
|
"Specifies a material file that describes the material object types will have"
|
||||||
"if an object does not have any specified material in the IFC file.");
|
"if an object does not have any specified material in the IFC file.")
|
||||||
|
("validate", "Checks whether geometrical output conforms to the included explicit quantities.");
|
||||||
|
|
||||||
std::string bounds, offset_str;
|
std::string bounds, offset_str;
|
||||||
#ifdef HAVE_ICU
|
#ifdef HAVE_ICU
|
||||||
@@ -501,6 +502,7 @@ int main(int argc, char** argv)
|
|||||||
fix_quantities(*ifc_file, no_progress, quiet, stderr_progress);
|
fix_quantities(*ifc_file, no_progress, quiet, stderr_progress);
|
||||||
}
|
}
|
||||||
fs << *ifc_file;
|
fs << *ifc_file;
|
||||||
|
exit_code = EXIT_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
Logger::Error("Unable to open output file for writing");
|
Logger::Error("Unable to open output file for writing");
|
||||||
}
|
}
|
||||||
@@ -1087,15 +1089,18 @@ void fix_quantities(IfcParse::IfcFile& f, bool no_progress, bool quiet, bool std
|
|||||||
// Capture relationship nodes
|
// Capture relationship nodes
|
||||||
std::vector<IfcUtil::IfcBaseClass*> relationships;
|
std::vector<IfcUtil::IfcBaseClass*> relationships;
|
||||||
auto IfcRelDefinesByProperties = f.schema()->declaration_by_name("IfcRelDefinesByProperties");
|
auto IfcRelDefinesByProperties = f.schema()->declaration_by_name("IfcRelDefinesByProperties");
|
||||||
for (auto& eq : *element_quantities) {
|
if (element_quantities) {
|
||||||
auto rels = eq->data().getInverse(IfcRelDefinesByProperties, -1);
|
for (auto& eq : *element_quantities) {
|
||||||
for (auto& rel : *rels) {
|
auto rels = eq->data().getInverse(IfcRelDefinesByProperties, -1);
|
||||||
relationships.push_back(rel);
|
for (auto& rel : *rels) {
|
||||||
|
relationships.push_back(rel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete element quantities
|
||||||
|
delete_reversed(element_quantities);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete element quantities
|
|
||||||
delete_reversed(element_quantities);
|
|
||||||
|
|
||||||
// Delete relationship nodes
|
// Delete relationship nodes
|
||||||
for (auto& rel : relationships) {
|
for (auto& rel : relationships) {
|
||||||
@@ -1183,6 +1188,27 @@ void fix_quantities(IfcParse::IfcFile& f, bool no_progress, bool quiet, bool std
|
|||||||
quantities->push(quantity_area);
|
quantities->push(quantity_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto& part : geom_object->geometry()) {
|
||||||
|
auto quantity_complex = latebound_access::create(f, "IfcPhysicalComplexQuantity");
|
||||||
|
latebound_access::set(quantity_complex, "Name", std::string("Shape validation properties"));
|
||||||
|
latebound_access::set(quantity_complex, "Discrimination", '#' + boost::lexical_cast<std::string>(part.ItemId()));
|
||||||
|
|
||||||
|
IfcEntityList::ptr quantities_2(new IfcEntityList);
|
||||||
|
|
||||||
|
int nv = IfcGeom::Kernel::count(part.Shape(), TopAbs_VERTEX, true);
|
||||||
|
int ne = IfcGeom::Kernel::count(part.Shape(), TopAbs_EDGE, true);
|
||||||
|
int nf = IfcGeom::Kernel::count(part.Shape(), TopAbs_FACE, true);
|
||||||
|
|
||||||
|
const int euler = nv - ne + nf;
|
||||||
|
const int genus = (2 - euler) / 2;
|
||||||
|
|
||||||
|
auto quantity_area = latebound_access::create(f, "IfcQuantityCount");
|
||||||
|
latebound_access::set(quantity_area, "Name", std::string("Surface genus"));
|
||||||
|
latebound_access::set(quantity_area, "CountValue", genus);
|
||||||
|
|
||||||
|
latebound_access::set(quantity_complex, "HasQuantities", quantities_2);
|
||||||
|
}
|
||||||
|
|
||||||
if (quantities->size()) {
|
if (quantities->size()) {
|
||||||
quantity = latebound_access::create(f, "IfcElementQuantity");
|
quantity = latebound_access::create(f, "IfcElementQuantity");
|
||||||
latebound_access::set(quantity, "OwnerHistory", ownerhist);
|
latebound_access::set(quantity, "OwnerHistory", ownerhist);
|
||||||
@@ -1213,4 +1239,19 @@ void fix_quantities(IfcParse::IfcFile& f, bool no_progress, bool quiet, bool std
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (++num_created, context_iterator.next());
|
} while (++num_created, context_iterator.next());
|
||||||
|
|
||||||
|
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 writing quantities for " + boost::lexical_cast<std::string>(num_created) +
|
||||||
|
" objects ");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -661,7 +661,7 @@ bool IfcGeom::Kernel::convert_openings(const IfcSchema::IfcProduct* entity, cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(entity_shape, &it3->Style()));
|
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(it3->ItemId(), it3->Placement(), entity_shape, &it3->Style()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -735,7 +735,7 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity,
|
|||||||
BRepCheck_Analyzer analyser(brep_cut_result);
|
BRepCheck_Analyzer analyser(brep_cut_result);
|
||||||
is_valid = analyser.IsValid() != 0;
|
is_valid = analyser.IsValid() != 0;
|
||||||
if ( is_valid ) {
|
if ( is_valid ) {
|
||||||
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(brep_cut_result, &it3->Style()));
|
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(it3->ItemId(), brep_cut_result, &it3->Style()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( !is_valid ) {
|
if ( !is_valid ) {
|
||||||
@@ -847,7 +847,7 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(result, &it3->Style()));
|
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(it3->ItemId(), result, &it3->Style()));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2442,8 +2442,8 @@ bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& i
|
|||||||
for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) {
|
for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) {
|
||||||
TopoDS_Shape a,b;
|
TopoDS_Shape a,b;
|
||||||
if (split_solid_by_shell(it->Shape(), shells[0], a, b)) {
|
if (split_solid_by_shell(it->Shape(), shells[0], a, b)) {
|
||||||
result.push_back(IfcRepresentationShapeItem(it->Placement(), b, styles[0] ? styles[0] : &it->Style()));
|
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), b, styles[0] ? styles[0] : &it->Style()));
|
||||||
result.push_back(IfcRepresentationShapeItem(it->Placement(), a, styles[1] ? styles[1] : &it->Style()));
|
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), a, styles[1] ? styles[1] : &it->Style()));
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -2485,7 +2485,7 @@ bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& i
|
|||||||
for(; it1 != items.end(); ++it1, ++it2) {
|
for(; it1 != items.end(); ++it1, ++it2) {
|
||||||
std::vector<const SurfaceStyle*>::const_iterator it4 = styles.begin();
|
std::vector<const SurfaceStyle*>::const_iterator it4 = styles.begin();
|
||||||
for (temp_t::value_type::const_iterator it3 = it2->begin(); it3 != it2->end(); ++it3, ++it4) {
|
for (temp_t::value_type::const_iterator it3 = it2->begin(); it3 != it2->end(); ++it3, ++it4) {
|
||||||
result.push_back(IfcRepresentationShapeItem(it1->Placement(), *it3, (*it4) ? (*it4) : &it1->Style()));
|
result.push_back(IfcRepresentationShapeItem(it1->ItemId(), it1->Placement(), *it3, (*it4) ? (*it4) : &it1->Style()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2505,8 +2505,8 @@ bool IfcGeom::Kernel::apply_layerset(const IfcRepresentationShapeItems& items, c
|
|||||||
for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) {
|
for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) {
|
||||||
TopoDS_Shape a,b;
|
TopoDS_Shape a,b;
|
||||||
if (split_solid_by_surface(it->Shape(), surfaces[1], a, b)) {
|
if (split_solid_by_surface(it->Shape(), surfaces[1], a, b)) {
|
||||||
result.push_back(IfcRepresentationShapeItem(it->Placement(), b, styles[0] ? styles[0] : &it->Style()));
|
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), b, styles[0] ? styles[0] : &it->Style()));
|
||||||
result.push_back(IfcRepresentationShapeItem(it->Placement(), a, styles[1] ? styles[1] : &it->Style()));
|
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), a, styles[1] ? styles[1] : &it->Style()));
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -2578,7 +2578,7 @@ bool IfcGeom::Kernel::apply_layerset(const IfcRepresentationShapeItems& items, c
|
|||||||
for(; it1 != items.end(); ++it1, ++it2) {
|
for(; it1 != items.end(); ++it1, ++it2) {
|
||||||
std::vector<const SurfaceStyle*>::const_iterator it4 = styles.begin();
|
std::vector<const SurfaceStyle*>::const_iterator it4 = styles.begin();
|
||||||
for (temp_t::value_type::const_iterator it3 = it2->begin(); it3 != it2->end(); ++it3, ++it4) {
|
for (temp_t::value_type::const_iterator it3 = it2->begin(); it3 != it2->end(); ++it3, ++it4) {
|
||||||
result.push_back(IfcRepresentationShapeItem(it1->Placement(), *it3, (*it4) ? (*it4) : &it1->Style()));
|
result.push_back(IfcRepresentationShapeItem(it1->ItemId(), it1->Placement(), *it3, (*it4) ? (*it4) : &it1->Style()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -391,7 +391,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, IfcRepre
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shape.push_back(IfcRepresentationShapeItem(s, indiv_style ? indiv_style : collective_style));
|
shape.push_back(IfcRepresentationShapeItem(l->data().id(), s, indiv_style ? indiv_style : collective_style));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -405,7 +405,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcFaceBasedSurfaceModel* l, IfcR
|
|||||||
TopoDS_Shape s;
|
TopoDS_Shape s;
|
||||||
const SurfaceStyle* shell_style = get_style(*it);
|
const SurfaceStyle* shell_style = get_style(*it);
|
||||||
if (convert_shape(*it,s)) {
|
if (convert_shape(*it,s)) {
|
||||||
shapes.push_back(IfcRepresentationShapeItem(s, shell_style ? shell_style : collective_style));
|
shapes.push_back(IfcRepresentationShapeItem(l->data().id(), s, shell_style ? shell_style : collective_style));
|
||||||
part_success |= true;
|
part_success |= true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -469,7 +469,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, Ifc
|
|||||||
shell_style = get_style((IfcSchema::IfcRepresentationItem*)*it);
|
shell_style = get_style((IfcSchema::IfcRepresentationItem*)*it);
|
||||||
}
|
}
|
||||||
if (convert_shape(*it,s)) {
|
if (convert_shape(*it,s)) {
|
||||||
shapes.push_back(IfcRepresentationShapeItem(s, shell_style ? shell_style : collective_style));
|
shapes.push_back(IfcRepresentationShapeItem(l->data().id(), s, shell_style ? shell_style : collective_style));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -725,7 +725,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRepresentation* l, IfcRepresen
|
|||||||
} else {
|
} else {
|
||||||
TopoDS_Shape s;
|
TopoDS_Shape s;
|
||||||
if (convert_shape(representation_item,s)) {
|
if (convert_shape(representation_item,s)) {
|
||||||
shapes.push_back(IfcRepresentationShapeItem(s, get_style(representation_item)));
|
shapes.push_back(IfcRepresentationShapeItem(l->data().id(), s, get_style(representation_item)));
|
||||||
part_succes |= true;
|
part_succes |= true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -752,7 +752,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcGeometricSet* l, IfcRepresenta
|
|||||||
} else if (element->declaration().is(IfcSchema::IfcSurface::Class())) {
|
} else if (element->declaration().is(IfcSchema::IfcSurface::Class())) {
|
||||||
style = get_style((IfcSchema::IfcSurface*) element);
|
style = get_style((IfcSchema::IfcSurface*) element);
|
||||||
}
|
}
|
||||||
shapes.push_back(IfcRepresentationShapeItem(s, style ? style : parent_style));
|
shapes.push_back(IfcRepresentationShapeItem(l->data().id(), s, style ? style : parent_style));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return part_succes;
|
return part_succes;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ bool IfcGeom::Kernel::convert_shapes(const IfcBaseClass* l, IfcRepresentationSha
|
|||||||
if (shape_type(l) != ST_SHAPELIST) {
|
if (shape_type(l) != ST_SHAPELIST) {
|
||||||
TopoDS_Shape shp;
|
TopoDS_Shape shp;
|
||||||
if (convert_shape(l, shp)) {
|
if (convert_shape(l, shp)) {
|
||||||
r.push_back(IfcGeom::IfcRepresentationShapeItem(shp, get_style(l->as<IfcSchema::IfcRepresentationItem>())));
|
r.push_back(IfcGeom::IfcRepresentationShapeItem(l->data().id(), shp, get_style(l->as<IfcSchema::IfcRepresentationItem>())));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -31,15 +31,16 @@ namespace IfcGeom {
|
|||||||
gp_GTrsf placement;
|
gp_GTrsf placement;
|
||||||
TopoDS_Shape shape;
|
TopoDS_Shape shape;
|
||||||
const SurfaceStyle* style;
|
const SurfaceStyle* style;
|
||||||
|
int id;
|
||||||
public:
|
public:
|
||||||
IfcRepresentationShapeItem(const gp_GTrsf& placement, const TopoDS_Shape& shape, const SurfaceStyle* style)
|
IfcRepresentationShapeItem(int id, const gp_GTrsf& placement, const TopoDS_Shape& shape, const SurfaceStyle* style)
|
||||||
: placement(placement), shape(shape), style(style) {}
|
: id(id), placement(placement), shape(shape), style(style) {}
|
||||||
IfcRepresentationShapeItem(const gp_GTrsf& placement, const TopoDS_Shape& shape)
|
IfcRepresentationShapeItem(int id, const gp_GTrsf& placement, const TopoDS_Shape& shape)
|
||||||
: placement(placement), shape(shape), style(0) {}
|
: id(id), placement(placement), shape(shape), style(0) {}
|
||||||
IfcRepresentationShapeItem(const TopoDS_Shape& shape, const SurfaceStyle* style)
|
IfcRepresentationShapeItem(int id, const TopoDS_Shape& shape, const SurfaceStyle* style)
|
||||||
: shape(shape), style(style) {}
|
: id(id), shape(shape), style(style) {}
|
||||||
IfcRepresentationShapeItem(const TopoDS_Shape& shape)
|
IfcRepresentationShapeItem(int id, const TopoDS_Shape& shape)
|
||||||
: shape(shape), style(0) {}
|
: id(id), shape(shape), style(0) {}
|
||||||
void append(const gp_GTrsf& trsf) { placement.Multiply(trsf); }
|
void append(const gp_GTrsf& trsf) { placement.Multiply(trsf); }
|
||||||
void prepend(const gp_GTrsf& trsf) { placement.PreMultiply(trsf); }
|
void prepend(const gp_GTrsf& trsf) { placement.PreMultiply(trsf); }
|
||||||
const TopoDS_Shape& Shape() const { return shape; }
|
const TopoDS_Shape& Shape() const { return shape; }
|
||||||
@@ -47,6 +48,7 @@ namespace IfcGeom {
|
|||||||
bool hasStyle() const { return style != 0; }
|
bool hasStyle() const { return style != 0; }
|
||||||
const SurfaceStyle& Style() const { return *style; }
|
const SurfaceStyle& Style() const { return *style; }
|
||||||
void setStyle(const SurfaceStyle* style) { this->style = style; }
|
void setStyle(const SurfaceStyle* style) { this->style = style; }
|
||||||
|
int ItemId() const { return id; }
|
||||||
};
|
};
|
||||||
typedef std::vector<IfcRepresentationShapeItem> IfcRepresentationShapeItems;
|
typedef std::vector<IfcRepresentationShapeItem> IfcRepresentationShapeItems;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,13 +15,19 @@ IfcGeom::Kernel::Kernel(IfcParse::IfcFile* file) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int IfcGeom::Kernel::count(const TopoDS_Shape& s, TopAbs_ShapeEnum t) {
|
int IfcGeom::Kernel::count(const TopoDS_Shape& s, TopAbs_ShapeEnum t, bool unique) {
|
||||||
int i = 0;
|
if (unique) {
|
||||||
TopExp_Explorer exp(s, t);
|
TopTools_IndexedMapOfShape map;
|
||||||
for (; exp.More(); exp.Next()) {
|
TopExp::MapShapes(s, t, map);
|
||||||
++i;
|
return map.Extent();
|
||||||
|
} else {
|
||||||
|
int i = 0;
|
||||||
|
TopExp_Explorer exp(s, t);
|
||||||
|
for (; exp.More(); exp.Next()) {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcGeom::impl::KernelFactoryImplementation& IfcGeom::impl::kernel_implementations() {
|
IfcGeom::impl::KernelFactoryImplementation& IfcGeom::impl::kernel_implementations() {
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ namespace IfcGeom {
|
|||||||
return implementation_->convert_placement(item, trsf);
|
return implementation_->convert_placement(item, trsf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int count(const TopoDS_Shape&, TopAbs_ShapeEnum);
|
static int count(const TopoDS_Shape&, TopAbs_ShapeEnum, bool unique=false);
|
||||||
|
|
||||||
static bool is_manifold(const TopoDS_Shape& a);
|
static bool is_manifold(const TopoDS_Shape& a);
|
||||||
static IfcUtil::IfcBaseEntity* get_decomposing_entity(IfcUtil::IfcBaseEntity*);
|
static IfcUtil::IfcBaseEntity* get_decomposing_entity(IfcUtil::IfcBaseEntity*);
|
||||||
|
|||||||
Reference in New Issue
Block a user