Isolate (most of the) geometry processing code into separate opencascade kernel

This commit is contained in:
Thomas Krijnen
2019-01-18 11:23:19 +01:00
parent 0072e1f247
commit ad24b6be0f
38 changed files with 678 additions and 491 deletions
+11 -20
View File
@@ -536,7 +536,7 @@ if(NOT Boost_VERSION LESS 105800)
add_definitions(-DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE)
endif()
set(IFCOPENSHELL_LIBRARIES IfcParse IfcGeom IfcGeom IfcGeom_CGAL Serializers Serializers)
set(IFCOPENSHELL_LIBRARIES IfcParse IfcGeom Serializers)
# IfcParse
file(GLOB IFCPARSE_H_FILES ../src/ifcparse/*.h)
@@ -561,11 +561,6 @@ file(GLOB IFCGEOM_H_FILES ../src/ifcgeom/*.h)
file(GLOB IFCGEOM_CPP_FILES ../src/ifcgeom/*.cpp)
set(IFCGEOM_FILES ${IFCGEOM_CPP_FILES} ${IFCGEOM_H_FILES})
# IfcGeom, schema agnostic, OCCT
file(GLOB SCHEMA_AGNOSTIC_H_FILES ../src/ifcgeom_schema_agnostic/*.h)
file(GLOB SCHEMA_AGNOSTIC_CPP_FILES ../src/ifcgeom_schema_agnostic/*.cpp)
set(SCHEMA_AGNOSTIC_FILES ${SCHEMA_AGNOSTIC_H_FILES} ${SCHEMA_AGNOSTIC_CPP_FILES})
foreach(schema 2x3 4)
add_library(IfcGeom_ifc${schema} ${IFCGEOM_FILES})
set_target_properties(IfcGeom_ifc${schema} PROPERTIES COMPILE_FLAGS "-DIFC_GEOM_EXPORTS -DIfcSchema=Ifc${schema} -DUSE_IFC${schema}")
@@ -573,32 +568,28 @@ TARGET_LINK_LIBRARIES(IfcGeom_ifc${schema} IfcParse ${OPENCASCADE_LIBRARIES})
list(APPEND IfcGeom_libraries IfcGeom_ifc${schema})
endforeach()
add_library(IfcGeom ${SCHEMA_AGNOSTIC_FILES})
set_target_properties(IfcGeom PROPERTIES COMPILE_FLAGS -DIFC_GEOM_EXPORTS)
TARGET_LINK_LIBRARIES(IfcGeom ${IfcGeom_libraries})
### CGAL
# IfcGeom, schema dependent, OCCT
# IfcGeom, schema dependent, CGAL
file(GLOB IFCGEOM_H_FILES ../src/ifcgeom/kernels/cgal/*.h)
file(GLOB IFCGEOM_CPP_FILES ../src/ifcgeom/kernels/cgal/*.cpp)
set(IFCGEOM_FILES ${IFCGEOM_CPP_FILES} ${IFCGEOM_H_FILES})
# IfcGeom, schema agnostic, OCCT
file(GLOB SCHEMA_AGNOSTIC_H_FILES ../src/ifcgeom_schema_agnostic_cgal/*.h)
file(GLOB SCHEMA_AGNOSTIC_CPP_FILES ../src/ifcgeom_schema_agnostic_cgal/*.cpp)
set(SCHEMA_AGNOSTIC_FILES ${SCHEMA_AGNOSTIC_H_FILES} ${SCHEMA_AGNOSTIC_CPP_FILES})
foreach(schema 2x3 4)
add_library(IfcGeom_ifc${schema} ${IFCGEOM_FILES})
add_library(IfcGeom_CGAL_ifc${schema} ${IFCGEOM_FILES})
set_target_properties(IfcGeom_CGAL_ifc${schema} PROPERTIES COMPILE_FLAGS "-DIFC_GEOM_EXPORTS -DIfcSchema=Ifc${schema} -DUSE_IFC${schema}")
TARGET_LINK_LIBRARIES(IfcGeom_CGAL_ifc${schema} IfcParse ${OPENCASCADE_LIBRARIES})
list(APPEND IfcGeom_CGAL_libraries IfcGeom_CGAL_ifc${schema})
endforeach()
add_library(IfcGeom_CGAL ${SCHEMA_AGNOSTIC_FILES})
set_target_properties(IfcGeom_CGAL PROPERTIES COMPILE_FLAGS -DIFC_GEOM_EXPORTS)
TARGET_LINK_LIBRARIES(IfcGeom_CGAL ${IfcGeom_CGAL_libraries})
# IfcGeom, schema and kernel agnostic
file(GLOB SCHEMA_AGNOSTIC_H_FILES ../src/ifcgeom_schema_agnostic/*.h)
file(GLOB SCHEMA_AGNOSTIC_CPP_FILES ../src/ifcgeom_schema_agnostic/*.cpp)
set(SCHEMA_AGNOSTIC_FILES ${SCHEMA_AGNOSTIC_H_FILES} ${SCHEMA_AGNOSTIC_CPP_FILES})
add_library(IfcGeom ${SCHEMA_AGNOSTIC_FILES})
set_target_properties(IfcGeom PROPERTIES COMPILE_FLAGS -DIFC_GEOM_EXPORTS)
TARGET_LINK_LIBRARIES(IfcGeom ${IfcGeom_libraries})
endif(BUILD_IFCGEOM)
+4 -4
View File
@@ -711,7 +711,7 @@ int main(int argc, char** argv)
// The functions IfcGeom::Iterator::get() and IfcGeom::Iterator::next()
// wrap an iterator of all geometrical products in the Ifc file.
// IfcGeom::Iterator::get() returns an IfcGeom::TriangulationElement or
// -BRepElement pointer, based on current settings. (see IfcGeomIterator.h
// -NativeElement pointer, based on current settings. (see IfcGeomIterator.h
// for definition) IfcGeom::Iterator::next() is used to poll whether more
// geometrical entities are available. None of these functions throw
// exceptions, neither for parsing errors or geometrical errors. Upon
@@ -729,7 +729,7 @@ int main(int argc, char** argv)
}
else
{
serializer->write(static_cast<const IfcGeom::BRepElement<real_t>*>(geom_object));
serializer->write(static_cast<const IfcGeom::NativeElement<real_t>*>(geom_object));
}
if (!no_progress) {
@@ -1152,7 +1152,7 @@ void fix_quantities(IfcParse::IfcFile& f, bool no_progress, bool quiet, bool std
if (num_created) {
has_more = context_iterator.next();
}
IfcGeom::BRepElement<double>* geom_object = nullptr;
IfcGeom::NativeElement<double>* geom_object = nullptr;
if (has_more) {
geom_object = context_iterator.get_native();
}
@@ -1205,7 +1205,7 @@ void fix_quantities(IfcParse::IfcFile& f, bool no_progress, bool quiet, bool std
auto quantity_count = latebound_access::create(f, "IfcQuantityCount");
latebound_access::set(quantity_count, "Name", std::string("Surface Genus"));
latebound_access::set(quantity_count, "Description", '#' + boost::lexical_cast<std::string>(part.ItemId()));
latebound_access::set(quantity_count, "CountValue", IfcGeom::Kernel::surface_genus(part.Shape()));
latebound_access::set(quantity_count, "CountValue", part.Shape()->surface_genus());
quantities_2->push(quantity_count);
}
+19 -17
View File
@@ -52,14 +52,15 @@ inline static bool ALMOST_THE_SAME(const T& a, const T& b, double tolerance=ALMO
#include "../ifcparse/IfcParse.h"
#include "../ifcparse/IfcBaseClass.h"
#include "../ifcgeom/IfcGeomElement.h"
#include "../ifcgeom/IfcGeomRepresentation.h"
#include "../ifcgeom/IfcRepresentationShapeItem.h"
#include "../ifcgeom_schema_agnostic/IfcGeomElement.h"
#include "../ifcgeom_schema_agnostic/IfcGeomRepresentation.h"
#include "../ifcgeom_schema_agnostic/ConversionResult.h"
#include "../ifcgeom/IfcGeomShapeType.h"
#include "../ifcgeom_schema_agnostic/Kernel.h"
#include "OpenCascadeConversionResult.h"
#include "ifc_geom_api.h"
#include "../ifcgeom_schema_agnostic/ifc_geom_api.h"
// Define this in case you want to conserve memory usage at all cost. This has been
// benchmarked extensively: https://github.com/IfcOpenShell/IfcOpenShell/pull/47
@@ -258,21 +259,21 @@ public:
bool convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face);
bool convert_curve_to_wire(const Handle(Geom_Curve)& curve, TopoDS_Wire& wire);
bool convert_shapes(const IfcUtil::IfcBaseClass* L, IfcRepresentationShapeItems& result);
bool convert_shapes(const IfcUtil::IfcBaseClass* L, ConversionResults& result);
IfcGeom::ShapeType shape_type(const IfcUtil::IfcBaseClass* L);
bool convert_shape(const IfcUtil::IfcBaseClass* L, TopoDS_Shape& result);
bool flatten_shape_list(const IfcGeom::IfcRepresentationShapeItems& shapes, TopoDS_Shape& result, bool fuse);
bool flatten_shape_list(const IfcGeom::ConversionResults& shapes, TopoDS_Shape& result, bool fuse);
bool convert_wire(const IfcUtil::IfcBaseClass* L, TopoDS_Wire& result);
bool convert_curve(const IfcUtil::IfcBaseClass* L, Handle(Geom_Curve)& result);
bool convert_face(const IfcUtil::IfcBaseClass* L, TopoDS_Shape& result);
bool convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcRepresentationShapeItems& cut_shapes);
bool convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcRepresentationShapeItems& cut_shapes);
bool convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, ConversionResults& cut_shapes);
bool convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, ConversionResults& cut_shapes);
void assert_closed_wire(TopoDS_Wire& wire);
bool convert_layerset(const IfcSchema::IfcProduct*, std::vector<Handle_Geom_Surface>&, std::vector<const SurfaceStyle*>&, std::vector<double>&);
bool apply_layerset(const IfcRepresentationShapeItems&, const std::vector<Handle_Geom_Surface>&, const std::vector<const SurfaceStyle*>&, IfcRepresentationShapeItems&);
bool apply_folded_layerset(const IfcRepresentationShapeItems&, const std::vector< std::vector<Handle_Geom_Surface> >&, const std::vector<const SurfaceStyle*>&, IfcRepresentationShapeItems&);
bool fold_layers(const IfcSchema::IfcWall*, const IfcRepresentationShapeItems&, const std::vector<Handle_Geom_Surface>&, const std::vector<double>&, std::vector< std::vector<Handle_Geom_Surface> >&);
bool apply_layerset(const ConversionResults&, const std::vector<Handle_Geom_Surface>&, const std::vector<const SurfaceStyle*>&, ConversionResults&);
bool apply_folded_layerset(const ConversionResults&, const std::vector< std::vector<Handle_Geom_Surface> >&, const std::vector<const SurfaceStyle*>&, ConversionResults&);
bool fold_layers(const IfcSchema::IfcWall*, const ConversionResults&, const std::vector<Handle_Geom_Surface>&, const std::vector<double>&, std::vector< std::vector<Handle_Geom_Surface> >&);
bool split_solid_by_surface(const TopoDS_Shape&, const Handle_Geom_Surface&, TopoDS_Shape&, TopoDS_Shape&);
bool split_solid_by_shell(const TopoDS_Shape&, const TopoDS_Shape& s, TopoDS_Shape&, TopoDS_Shape&);
@@ -326,6 +327,7 @@ public:
static double shape_volume(const TopoDS_Shape& s);
static double face_area(const TopoDS_Face& f);
static TopoDS_Shape apply_transformation(const TopoDS_Shape&, const OpenCascadePlacement*);
static TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_Trsf&);
static TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_GTrsf&);
@@ -338,12 +340,12 @@ public:
std::pair<std::string, double> initializeUnits(IfcSchema::IfcUnitAssignment*);
template <typename P, typename PP>
IfcGeom::BRepElement<P, PP>* create_brep_for_representation_and_product(
IfcGeom::NativeElement<P, PP>* create_brep_for_representation_and_product(
const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*);
template <typename P, typename PP>
IfcGeom::BRepElement<P, PP>* create_brep_for_processed_representation(
const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*, IfcGeom::BRepElement<P, PP>*);
IfcGeom::NativeElement<P, PP>* create_brep_for_processed_representation(
const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*, IfcGeom::NativeElement<P, PP>*);
const IfcSchema::IfcMaterial* get_single_material_association(const IfcSchema::IfcProduct*);
IfcSchema::IfcRepresentation* representation_mapped_to(const IfcSchema::IfcRepresentation* representation);
@@ -416,15 +418,15 @@ public:
virtual void setValue(GeomValue var, double value);
virtual double getValue(GeomValue var) const;
virtual IfcGeom::BRepElement<double>* convert(
virtual IfcGeom::NativeElement<double>* convert(
const IteratorSettings& settings, IfcUtil::IfcBaseClass* representation,
IfcUtil::IfcBaseClass* product)
{
return create_brep_for_representation_and_product<double, double>(settings, (IfcSchema::IfcRepresentation*) representation, (IfcSchema::IfcProduct*) product);
}
virtual IfcRepresentationShapeItems convert(IfcUtil::IfcBaseClass* item) {
IfcRepresentationShapeItems items;
virtual ConversionResults convert(IfcUtil::IfcBaseClass* item) {
ConversionResults items;
bool success = convert_shapes(item, items);
if (!success) {
throw IfcParse::IfcException("Failed to process representation item");
+96 -94
View File
@@ -507,13 +507,13 @@ const TopoDS_Shape& IfcGeom::Kernel::ensure_fit_for_subtraction(const TopoDS_Sha
}
bool IfcGeom::Kernel::convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings,
const IfcGeom::IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::IfcRepresentationShapeItems& cut_shapes) {
const IfcGeom::ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::ConversionResults& cut_shapes) {
// TODO: Refactor convert_openings() convert_openings_fast() and convert(IfcBooleanResult) to use
// the same code base and conform to the same checks and logging messages.
// Iterate over IfcOpeningElements
IfcGeom::IfcRepresentationShapeItems opening_shapes;
IfcGeom::ConversionResults opening_shapes;
unsigned int last_size = 0;
for ( IfcSchema::IfcRelVoidsElement::list::it it = openings->begin(); it != openings->end(); ++ it ) {
IfcSchema::IfcRelVoidsElement* v = *it;
@@ -545,30 +545,26 @@ bool IfcGeom::Kernel::convert_openings(const IfcSchema::IfcProduct* entity, cons
const unsigned int current_size = (const unsigned int) opening_shapes.size();
for ( unsigned int i = last_size; i < current_size; ++ i ) {
opening_shapes[i].prepend(opening_trsf);
OpenCascadePlacement p((gp_GTrsf)opening_trsf);
opening_shapes[i].prepend(&p);
}
last_size = current_size;
}
}
// Iterate over the shapes of the IfcProduct
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) {
for ( IfcGeom::ConversionResults::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) {
TopoDS_Shape entity_shape_solid;
const TopoDS_Shape& entity_shape_unlocated = ensure_fit_for_subtraction(it3->Shape(),entity_shape_solid);
const gp_GTrsf& entity_shape_gtrsf = it3->Placement();
if ( entity_shape_gtrsf.Form() == gp_Other ) {
Logger::Message(Logger::LOG_WARNING, "Applying non uniform transformation to:", entity);
}
const TopoDS_Shape& entity_shape_unlocated = ensure_fit_for_subtraction(*(OpenCascadeShape*) it3->Shape(), entity_shape_solid);
const OpenCascadePlacement* entity_shape_gtrsf = (OpenCascadePlacement*) it3->Placement();
TopoDS_Shape entity_shape = apply_transformation(entity_shape_unlocated, entity_shape_gtrsf);
// Iterate over the shapes of the IfcOpeningElements
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it4 = opening_shapes.begin(); it4 != opening_shapes.end(); ++ it4 ) {
for ( IfcGeom::ConversionResults::const_iterator it4 = opening_shapes.begin(); it4 != opening_shapes.end(); ++ it4 ) {
TopoDS_Shape opening_shape_solid;
const TopoDS_Shape& opening_shape_unlocated = ensure_fit_for_subtraction(it4->Shape(),opening_shape_solid);
const gp_GTrsf& opening_shape_gtrsf = it4->Placement();
if ( opening_shape_gtrsf.Form() == gp_Other ) {
Logger::Message(Logger::LOG_WARNING,"Applying non uniform transformation to opening of:",entity);
}
const TopoDS_Shape& opening_shape_unlocated = ensure_fit_for_subtraction(*(OpenCascadeShape*) it4->Shape(),opening_shape_solid);
const OpenCascadePlacement* opening_shape_gtrsf = (OpenCascadePlacement*)it4->Placement();
TopoDS_Shape opening_shape = apply_transformation(opening_shape_unlocated, opening_shape_gtrsf);
double opening_volume;
@@ -673,7 +669,7 @@ bool IfcGeom::Kernel::convert_openings(const IfcSchema::IfcProduct* entity, cons
}
}
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(it3->ItemId(), it3->Placement(), entity_shape, &it3->Style()));
cut_shapes.push_back(IfcGeom::ConversionResult(it3->ItemId(), it3->Placement()->clone(), new OpenCascadeShape(entity_shape), &it3->Style()));
}
return true;
@@ -681,7 +677,7 @@ bool IfcGeom::Kernel::convert_openings(const IfcSchema::IfcProduct* entity, cons
#if OCC_VERSION_HEX < 0x60900
bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings,
const IfcGeom::IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::IfcRepresentationShapeItems& cut_shapes) {
const IfcGeom::ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::ConversionResults& cut_shapes) {
// Create a compound of all opening shapes in order to speed up the boolean operations
TopoDS_Compound opening_compound;
@@ -712,7 +708,7 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity,
IfcSchema::IfcProductRepresentation* prodrep = fes->Representation();
IfcSchema::IfcRepresentation::list::ptr reps = prodrep->Representations();
IfcGeom::IfcRepresentationShapeItems opening_shapes;
IfcGeom::ConversionResults opening_shapes;
for ( IfcSchema::IfcRepresentation::list::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) {
convert_shapes(*it2,opening_shapes);
@@ -729,7 +725,7 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity,
}
// Iterate over the shapes of the IfcProduct
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) {
for ( IfcGeom::ConversionResults::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) {
TopoDS_Shape entity_shape_solid;
const TopoDS_Shape& entity_shape_unlocated = ensure_fit_for_subtraction(it3->Shape(),entity_shape_solid);
const gp_GTrsf& entity_shape_gtrsf = it3->Placement();
@@ -747,7 +743,7 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity,
BRepCheck_Analyzer analyser(brep_cut_result);
is_valid = analyser.IsValid() != 0;
if ( is_valid ) {
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(it3->ItemId(), brep_cut_result, &it3->Style()));
cut_shapes.push_back(IfcGeom::ConversionResult(it3->ItemId(), brep_cut_result, &it3->Style()));
}
}
if ( !is_valid ) {
@@ -772,7 +768,7 @@ namespace {
}
bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings,
const IfcGeom::IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::IfcRepresentationShapeItems& cut_shapes) {
const IfcGeom::ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::ConversionResults& cut_shapes) {
std::vector< std::pair<double, TopoDS_Shape> > opening_vector;
@@ -800,7 +796,7 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity,
IfcSchema::IfcProductRepresentation* prodrep = fes->Representation();
IfcSchema::IfcRepresentation::list::ptr reps = prodrep->Representations();
IfcGeom::IfcRepresentationShapeItems opening_shapes;
IfcGeom::ConversionResults opening_shapes;
for (IfcSchema::IfcRepresentation::list::it it2 = reps->begin(); it2 != reps->end(); ++it2) {
convert_shapes(*it2, opening_shapes);
@@ -808,9 +804,12 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity,
for (unsigned int i = 0; i < opening_shapes.size(); ++i) {
TopoDS_Shape opening_shape_solid;
const TopoDS_Shape& opening_shape_unlocated = ensure_fit_for_subtraction(opening_shapes[i].Shape(), opening_shape_solid);
const TopoDS_Shape& opening_shape_unlocated = ensure_fit_for_subtraction(*(OpenCascadeShape*)opening_shapes[i].Shape(), opening_shape_solid);
gp_GTrsf gtrsf = opening_shapes[i].Placement();
gp_GTrsf gtrsf;
if (opening_shapes[i].Placement()) {
gtrsf = ((OpenCascadePlacement*)opening_shapes[i].Placement())->trsf();
}
gtrsf.PreMultiply(opening_trsf);
TopoDS_Shape opening_shape = apply_transformation(opening_shape_unlocated, gtrsf);
opening_vector.push_back(std::make_pair(min_edge_length(opening_shape), opening_shape));
@@ -822,13 +821,10 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity,
std::sort(opening_vector.begin(), opening_vector.end(), opening_sorter());
// Iterate over the shapes of the IfcProduct
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) {
for ( IfcGeom::ConversionResults::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) {
TopoDS_Shape entity_shape_solid;
const TopoDS_Shape& entity_shape_unlocated = ensure_fit_for_subtraction(it3->Shape(),entity_shape_solid);
const gp_GTrsf& entity_shape_gtrsf = it3->Placement();
if (entity_shape_gtrsf.Form() == gp_Other) {
Logger::Message(Logger::LOG_WARNING, "Applying non uniform transformation to:", entity);
}
const TopoDS_Shape& entity_shape_unlocated = ensure_fit_for_subtraction(*(OpenCascadeShape*) it3->Shape(),entity_shape_solid);
const OpenCascadePlacement* entity_shape_gtrsf = (OpenCascadePlacement*)it3->Placement();
TopoDS_Shape entity_shape = apply_transformation(entity_shape_unlocated, entity_shape_gtrsf);
TopoDS_Shape result = entity_shape;
@@ -859,7 +855,7 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity,
}
}
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(it3->ItemId(), result, &it3->Style()));
cut_shapes.push_back(IfcGeom::ConversionResult(it3->ItemId(), new OpenCascadeShape(result), &it3->Style()));
}
return true;
}
@@ -1263,22 +1259,22 @@ bool IfcGeom::Kernel::fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& sha
return true;
}
bool IfcGeom::Kernel::flatten_shape_list(const IfcGeom::IfcRepresentationShapeItems& shapes, TopoDS_Shape& result, bool fuse) {
bool IfcGeom::Kernel::flatten_shape_list(const IfcGeom::ConversionResults& shapes, TopoDS_Shape& result, bool fuse) {
TopoDS_Compound compound;
BRep_Builder builder;
builder.MakeCompound(compound);
result = TopoDS_Shape();
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
for ( IfcGeom::ConversionResults::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
TopoDS_Shape merged;
const TopoDS_Shape& s = it->Shape();
const TopoDS_Shape& s = *(OpenCascadeShape*)it->Shape();
if (fuse) {
ensure_fit_for_subtraction(s, merged);
} else {
merged = s;
}
const gp_GTrsf& trsf = it->Placement();
const OpenCascadePlacement* trsf = (const OpenCascadePlacement*) it->Placement();
const TopoDS_Shape moved_shape = apply_transformation(merged, trsf);
if (shapes.size() == 1) {
@@ -1463,7 +1459,7 @@ const IfcSchema::IfcMaterial* IfcGeom::Kernel::get_single_material_association(c
}
template <typename P, typename PP>
IfcGeom::BRepElement<P, PP>* IfcGeom::Kernel::create_brep_for_representation_and_product(
IfcGeom::NativeElement<P, PP>* IfcGeom::Kernel::create_brep_for_representation_and_product(
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product)
{
std::stringstream representation_id_builder;
@@ -1471,7 +1467,7 @@ IfcGeom::BRepElement<P, PP>* IfcGeom::Kernel::create_brep_for_representation_and
representation_id_builder << representation->data().id();
IfcGeom::Representation::BRep* shape;
IfcGeom::IfcRepresentationShapeItems shapes, shapes2;
IfcGeom::ConversionResults shapes, shapes2;
if ( !convert_shapes(representation, shapes) ) {
return 0;
@@ -1526,7 +1522,7 @@ IfcGeom::BRepElement<P, PP>* IfcGeom::Kernel::create_brep_for_representation_and
const IfcSchema::IfcMaterial* single_material = get_single_material_association(product);
if (single_material) {
const IfcGeom::SurfaceStyle* s = get_style(single_material);
for (IfcGeom::IfcRepresentationShapeItems::iterator it = shapes.begin(); it != shapes.end(); ++it) {
for (IfcGeom::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++it) {
if (!it->hasStyle() && s) {
it->setStyle(s);
material_style_applied = true;
@@ -1534,7 +1530,7 @@ IfcGeom::BRepElement<P, PP>* IfcGeom::Kernel::create_brep_for_representation_and
}
} else {
bool some_items_without_style = false;
for (IfcGeom::IfcRepresentationShapeItems::iterator it = shapes.begin(); it != shapes.end(); ++it) {
for (IfcGeom::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++it) {
if (!it->hasStyle()) {
some_items_without_style = true;
break;
@@ -1584,7 +1580,7 @@ IfcGeom::BRepElement<P, PP>* IfcGeom::Kernel::create_brep_for_representation_and
representation_id_builder << "-" << (*it)->data().id();
}
IfcGeom::IfcRepresentationShapeItems opened_shapes;
IfcGeom::ConversionResults opened_shapes;
bool caught_error = false;
try {
#if OCC_VERSION_HEX < 0x60900
@@ -1617,16 +1613,18 @@ IfcGeom::BRepElement<P, PP>* IfcGeom::Kernel::create_brep_for_representation_and
}
if (settings.get(IteratorSettings::USE_WORLD_COORDS)) {
for ( IfcGeom::IfcRepresentationShapeItems::iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) {
it->prepend(trsf);
for ( IfcGeom::ConversionResults::iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) {
OpenCascadePlacement p(trsf);
it->prepend(&p);
}
trsf = gp_Trsf();
representation_id_builder << "-world-coords";
}
shape = new IfcGeom::Representation::BRep(element_settings, representation_id_builder.str(), opened_shapes);
} else if (settings.get(IteratorSettings::USE_WORLD_COORDS)) {
for ( IfcGeom::IfcRepresentationShapeItems::iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
it->prepend(trsf);
for ( IfcGeom::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
OpenCascadePlacement p(trsf);
it->prepend(&p);
}
trsf = gp_Trsf();
representation_id_builder << "-world-coords";
@@ -1642,14 +1640,14 @@ IfcGeom::BRepElement<P, PP>* IfcGeom::Kernel::create_brep_for_representation_and
context_string = representation->ContextOfItems()->ContextType();
}
auto elem = new BRepElement<P, PP>(
auto elem = new NativeElement<P, PP>(
product->data().id(),
parent_id,
name,
product_type,
guid,
context_string,
trsf,
new OpenCascadePlacement(trsf),
boost::shared_ptr<IfcGeom::Representation::BRep>(shape),
product
);
@@ -1703,7 +1701,7 @@ IfcGeom::BRepElement<P, PP>* IfcGeom::Kernel::create_brep_for_representation_and
int genus = q2->as<IfcSchema::IfcQuantityCount>()->CountValue();
for (auto& part : elem->geometry()) {
if (part.ItemId() == item_id) {
if (surface_genus(part.Shape()) != genus) {
if (surface_genus(*(OpenCascadeShape*)part.Shape()) != genus) {
all_succeeded = false;
}
}
@@ -1792,9 +1790,9 @@ IfcSchema::IfcProduct::list::ptr IfcGeom::Kernel::products_represented_by(const
}
template <typename P, typename PP>
IfcGeom::BRepElement<P, PP>* IfcGeom::Kernel::create_brep_for_processed_representation(
IfcGeom::NativeElement<P, PP>* IfcGeom::Kernel::create_brep_for_processed_representation(
const IteratorSettings& /*settings*/, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product,
IfcGeom::BRepElement<P, PP>* brep)
IfcGeom::NativeElement<P, PP>* brep)
{
int parent_id = -1;
try {
@@ -1827,32 +1825,32 @@ IfcGeom::BRepElement<P, PP>* IfcGeom::Kernel::create_brep_for_processed_represen
const std::string product_type = product->declaration().name();
return new BRepElement<P, PP>(
return new NativeElement<P, PP>(
product->data().id(),
parent_id,
name,
product_type,
guid,
context_string,
trsf,
new OpenCascadePlacement(trsf),
brep->geometry_pointer(),
product
);
}
template IFC_GEOM_API IfcGeom::BRepElement<float, float>* IfcGeom::Kernel::create_brep_for_representation_and_product<float, float>(
template IFC_GEOM_API IfcGeom::NativeElement<float, float>* IfcGeom::Kernel::create_brep_for_representation_and_product<float, float>(
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
template IFC_GEOM_API IfcGeom::BRepElement<float, double>* IfcGeom::Kernel::create_brep_for_representation_and_product<float, double>(
template IFC_GEOM_API IfcGeom::NativeElement<float, double>* IfcGeom::Kernel::create_brep_for_representation_and_product<float, double>(
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
template IFC_GEOM_API IfcGeom::BRepElement<double, double>* IfcGeom::Kernel::create_brep_for_representation_and_product<double, double>(
template IFC_GEOM_API IfcGeom::NativeElement<double, double>* IfcGeom::Kernel::create_brep_for_representation_and_product<double, double>(
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
template IFC_GEOM_API IfcGeom::BRepElement<float, float>* IfcGeom::Kernel::create_brep_for_processed_representation<float, float>(
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::BRepElement<float, float>* brep);
template IFC_GEOM_API IfcGeom::BRepElement<float, double>* IfcGeom::Kernel::create_brep_for_processed_representation<float, double>(
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::BRepElement<float, double>* brep);
template IFC_GEOM_API IfcGeom::BRepElement<double, double>* IfcGeom::Kernel::create_brep_for_processed_representation<double, double>(
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::BRepElement<double, double>* brep);
template IFC_GEOM_API IfcGeom::NativeElement<float, float>* IfcGeom::Kernel::create_brep_for_processed_representation<float, float>(
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement<float, float>* brep);
template IFC_GEOM_API IfcGeom::NativeElement<float, double>* IfcGeom::Kernel::create_brep_for_processed_representation<float, double>(
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement<float, double>* brep);
template IFC_GEOM_API IfcGeom::NativeElement<double, double>* IfcGeom::Kernel::create_brep_for_processed_representation<double, double>(
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement<double, double>* brep);
std::pair<std::string, double> IfcGeom::Kernel::initializeUnits(IfcSchema::IfcUnitAssignment* unit_assignment) {
// Set default units, set length to meters, angles to undefined
@@ -1952,7 +1950,7 @@ bool IfcGeom::Kernel::convert_layerset(const IfcSchema::IfcProduct* product, std
return false;
}
IfcRepresentationShapeItems axis_items;
ConversionResults axis_items;
{
Kernel temp = *this;
temp.setValue(GV_DIMENSIONALITY, -1.);
@@ -2144,7 +2142,7 @@ bool IfcGeom::Kernel::find_wall_end_points(const IfcSchema::IfcWall* wall, gp_Pn
return false;
}
IfcRepresentationShapeItems items;
ConversionResults items;
{
Kernel temp = *this;
temp.setValue(GV_DIMENSIONALITY, -1.);
@@ -2152,8 +2150,8 @@ bool IfcGeom::Kernel::find_wall_end_points(const IfcSchema::IfcWall* wall, gp_Pn
}
TopoDS_Vertex a, b;
for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) {
TopExp_Explorer exp(it->Shape(), TopAbs_VERTEX);
for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) {
TopExp_Explorer exp(*(OpenCascadeShape*)it->Shape(), TopAbs_VERTEX);
for (; exp.More(); exp.Next()) {
b = TopoDS::Vertex(exp.Current());
if (a.IsNull()) {
@@ -2172,7 +2170,7 @@ bool IfcGeom::Kernel::find_wall_end_points(const IfcSchema::IfcWall* wall, gp_Pn
return true;
}
bool IfcGeom::Kernel::fold_layers(const IfcSchema::IfcWall* wall, const IfcRepresentationShapeItems& items, const std::vector<Handle_Geom_Surface>& surfaces, const std::vector<double>& thicknesses, std::vector< std::vector<Handle_Geom_Surface> >& result) {
bool IfcGeom::Kernel::fold_layers(const IfcSchema::IfcWall* wall, const ConversionResults& items, const std::vector<Handle_Geom_Surface>& surfaces, const std::vector<double>& thicknesses, std::vector< std::vector<Handle_Geom_Surface> >& result) {
bool folds_made = false;
IfcSchema::IfcRelConnectsPathElements::list::ptr connections(new IfcSchema::IfcRelConnectsPathElements::list);
@@ -2321,7 +2319,7 @@ bool IfcGeom::Kernel::fold_layers(const IfcSchema::IfcWall* wall, const IfcRepre
continue;
}
IfcRepresentationShapeItems axis_items;
ConversionResults axis_items;
{
Kernel temp = *this;
temp.setValue(GV_DIMENSIONALITY, -1.);
@@ -2605,7 +2603,7 @@ namespace {
#endif
}
bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& items, const std::vector< std::vector<Handle_Geom_Surface> >& surfaces, const std::vector<const SurfaceStyle*>& styles, IfcRepresentationShapeItems& result) {
bool IfcGeom::Kernel::apply_folded_layerset(const ConversionResults& items, const std::vector< std::vector<Handle_Geom_Surface> >& surfaces, const std::vector<const SurfaceStyle*>& styles, ConversionResults& result) {
Bnd_Box bb;
TopoDS_Shape input;
flatten_shape_list(items, input, false);
@@ -2681,11 +2679,11 @@ bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& i
} else if (shells.Extent() == 1) {
for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) {
for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) {
TopoDS_Shape a,b;
if (split_solid_by_shell(it->Shape(), shells.First(), a, b)) {
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), b, styles[0] ? styles[0] : &it->Style()));
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), a, styles[1] ? styles[1] : &it->Style()));
if (split_solid_by_shell(*(OpenCascadeShape*)it->Shape(), shells.First(), a, b)) {
result.push_back(ConversionResult(it->ItemId(), it->Placement()->clone(), new OpenCascadeShape(b), styles[0] ? styles[0] : &it->Style()));
result.push_back(ConversionResult(it->ItemId(), it->Placement()->clone(), new OpenCascadeShape(a), styles[1] ? styles[1] : &it->Style()));
} else {
continue;
}
@@ -2695,16 +2693,16 @@ bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& i
} else {
for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) {
for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) {
const TopoDS_Shape& s = it->Shape();
const TopoDS_Shape& s = *(OpenCascadeShape*)it->Shape();
TopoDS_Solid sld;
ensure_fit_for_subtraction(s, sld);
std::vector<TopoDS_Shape> slices;
if (split(*this, it->Shape(), shells, getValue(GV_PRECISION), slices) && slices.size() == styles.size()) {
if (split(*this, *(OpenCascadeShape*)it->Shape(), shells, getValue(GV_PRECISION), slices) && slices.size() == styles.size()) {
for (size_t i = 0; i < slices.size(); ++i) {
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), slices[i], styles[i] ? styles[i] : &it->Style()));
result.push_back(ConversionResult(it->ItemId(), it->Placement()->clone(), new OpenCascadeShape(slices[i]), styles[i] ? styles[i] : &it->Style()));
}
} else {
return false;
@@ -2717,18 +2715,18 @@ bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& i
}
bool IfcGeom::Kernel::apply_layerset(const IfcRepresentationShapeItems& items, const std::vector<Handle_Geom_Surface>& surfaces, const std::vector<const SurfaceStyle*>& styles, IfcRepresentationShapeItems& result) {
bool IfcGeom::Kernel::apply_layerset(const ConversionResults& items, const std::vector<Handle_Geom_Surface>& surfaces, const std::vector<const SurfaceStyle*>& styles, ConversionResults& result) {
if (surfaces.size() < 3) {
return false;
} else if (surfaces.size() == 3) {
for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) {
for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) {
TopoDS_Shape a,b;
if (split_solid_by_surface(it->Shape(), surfaces[1], a, b)) {
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), b, styles[0] ? styles[0] : &it->Style()));
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), a, styles[1] ? styles[1] : &it->Style()));
if (split_solid_by_surface(*(OpenCascadeShape*)it->Shape(), surfaces[1], a, b)) {
result.push_back(ConversionResult(it->ItemId(), it->Placement()->clone(), new OpenCascadeShape(b), styles[0] ? styles[0] : &it->Style()));
result.push_back(ConversionResult(it->ItemId(), it->Placement()->clone(), new OpenCascadeShape(a), styles[1] ? styles[1] : &it->Style()));
} else {
continue;
}
@@ -2742,7 +2740,7 @@ bool IfcGeom::Kernel::apply_layerset(const IfcRepresentationShapeItems& items, c
// Determine whether sequence of surfaces is consistent with surface normal, so that
// layer operations are applied in the correct order. This seems to be always the case.
Bnd_Box bb;
for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) {
for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) {
BRepBndLib::Add(it->Shape(), bb);
}
@@ -2767,9 +2765,9 @@ bool IfcGeom::Kernel::apply_layerset(const IfcRepresentationShapeItems& items, c
mass.ChangeCoord() += n1.XYZ();
*/
for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) {
for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) {
const TopoDS_Shape& s = it->Shape();
const TopoDS_Shape& s = *(OpenCascadeShape*)it->Shape();
TopoDS_Solid sld;
ensure_fit_for_subtraction(s, sld);
@@ -2786,9 +2784,9 @@ bool IfcGeom::Kernel::apply_layerset(const IfcRepresentationShapeItems& items, c
}
std::vector<TopoDS_Shape> slices;
if (split(*this, it->Shape(), operands, getValue(GV_PRECISION), slices) && slices.size() == styles.size()) {
if (split(*this, *(OpenCascadeShape*)it->Shape(), operands, getValue(GV_PRECISION), slices) && slices.size() == styles.size()) {
for (size_t i = 0; i < slices.size(); ++i) {
result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), slices[i], styles[i] ? styles[i] : &it->Style()));
result.push_back(ConversionResult(it->ItemId(), it->Placement()->clone(), new OpenCascadeShape(slices[i]), styles[i] ? styles[i] : &it->Style()));
}
} else {
return false;
@@ -3201,28 +3199,32 @@ bool IfcGeom::Kernel::triangulate_wire(const TopoDS_Wire& wire, TopTools_ListOfS
return true;
}
TopoDS_Shape IfcGeom::Kernel::apply_transformation(const TopoDS_Shape& s, const gp_Trsf& t) {
if (t.Form() == gp_Identity) {
TopoDS_Shape IfcGeom::Kernel::apply_transformation(const TopoDS_Shape& s, const OpenCascadePlacement* t) {
if (t == nullptr) {
return s;
} else {
/// @todo set to 1. and exactly 1. or use epsilon?
if (t.ScaleFactor() != 1.) {
return BRepBuilderAPI_Transform(s, t, true);
} else {
return s.Moved(t);
}
return apply_transformation(s, t->trsf());
}
}
TopoDS_Shape IfcGeom::Kernel::apply_transformation(const TopoDS_Shape& s, const gp_GTrsf& t) {
if (t.Form() == gp_Other) {
Logger::Message(Logger::LOG_WARNING, "Applying non uniform transformation");
return BRepBuilderAPI_GTransform(s, t, true);
} else {
return apply_transformation(s, t.Trsf());
}
}
TopoDS_Shape IfcGeom::Kernel::apply_transformation(const TopoDS_Shape& s, const gp_Trsf& t) {
/// @todo set to 1. and exactly 1. or use epsilon?
if (t.ScaleFactor() != 1.) {
return BRepBuilderAPI_Transform(s, t, true);
} else {
return s.Moved(t);
}
}
namespace {
/*
+9 -9
View File
@@ -76,10 +76,10 @@
#include "../ifcparse/IfcFile.h"
#include "../ifcgeom/IfcGeom.h"
#include "../ifcgeom/IfcGeomElement.h"
#include "../ifcgeom_schema_agnostic/IfcGeomElement.h"
#include "../ifcgeom_schema_agnostic/IfcGeomMaterial.h"
#include "../ifcgeom/IfcGeomIteratorSettings.h"
#include "../ifcgeom/IfcRepresentationShapeItem.h"
#include "../ifcgeom_schema_agnostic/IfcGeomIteratorSettings.h"
#include "../ifcgeom_schema_agnostic/ConversionResult.h"
#include "../ifcgeom_schema_agnostic/IfcGeomFilter.h"
#include "../ifcgeom_schema_agnostic/IteratorImplementation.h"
@@ -112,7 +112,7 @@ namespace IfcGeom {
// The object is fetched beforehand to be sure that get() returns a valid element
TriangulationElement<P, PP>* current_triangulation;
BRepElement<P, PP>* current_shape_model;
NativeElement<P, PP>* current_shape_model;
SerializedElement<P, PP>* current_serialization;
// A container and iterator for IfcBuildingElements for the current IfcRepresentation referenced by *representation_iterator
@@ -403,7 +403,7 @@ namespace IfcGeom {
return associated_single_materials.size() == 1;
}
BRepElement<P, PP>* create_shape_model_for_next_entity() {
NativeElement<P, PP>* create_shape_model_for_next_entity() {
for (;;) {
IfcSchema::IfcRepresentation* representation;
@@ -474,7 +474,7 @@ namespace IfcGeom {
IfcSchema::IfcProduct* product = *ifcproduct_iterator;
Logger::SetProduct(product);
BRepElement<P, PP>* element;
NativeElement<P, PP>* element;
if (ifcproduct_iterator == ifcproducts->begin() || !geometry_reuse_ok_for_current_representation_) {
element = kernel.create_brep_for_representation_and_product<P, PP>(settings, representation, product);
} else {
@@ -588,7 +588,7 @@ namespace IfcGeom {
}
/// Gets the native (Open Cascade) representation of the current geometrical entity.
BRepElement<P, PP>* get_native()
NativeElement<P, PP>* get_native()
{
// TODO: Test settings and throw
return current_shape_model;
@@ -646,12 +646,12 @@ namespace IfcGeom {
ElementSettings element_settings(settings, unit_magnitude, instance_type);
Element<P, PP>* ifc_object = new Element<P, PP>(element_settings, id, parent_id, product_name, instance_type, product_guid, "", trsf, ifc_product);
Element<P, PP>* ifc_object = new Element<P, PP>(element_settings, id, parent_id, product_name, instance_type, product_guid, "", new OpenCascadePlacement(trsf), ifc_product);
return ifc_object;
}
IfcUtil::IfcBaseClass* create() {
IfcGeom::BRepElement<P, PP>* next_shape_model = 0;
IfcGeom::NativeElement<P, PP>* next_shape_model = 0;
IfcGeom::SerializedElement<P, PP>* next_serialization = 0;
IfcGeom::TriangulationElement<P, PP>* next_triangulation = 0;
+14 -13
View File
@@ -366,7 +366,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRevolvedAreaSolid* l, TopoDS_S
return !shape.IsNull();
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, IfcRepresentationShapeItems& shape) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, ConversionResults& shape) {
TopoDS_Shape s;
const SurfaceStyle* collective_style = get_style(l);
if (convert_shape(l->Outer(),s) ) {
@@ -391,13 +391,13 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, IfcRepre
}
}
shape.push_back(IfcRepresentationShapeItem(l->data().id(), s, indiv_style ? indiv_style : collective_style));
shape.push_back(ConversionResult(l->data().id(), new OpenCascadeShape(s), indiv_style ? indiv_style : collective_style));
return true;
}
return false;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcFaceBasedSurfaceModel* l, IfcRepresentationShapeItems& shapes) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcFaceBasedSurfaceModel* l, ConversionResults& shapes) {
bool part_success = false;
IfcSchema::IfcConnectedFaceSet::list::ptr facesets = l->FbsmFaces();
const SurfaceStyle* collective_style = get_style(l);
@@ -405,7 +405,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcFaceBasedSurfaceModel* l, IfcR
TopoDS_Shape s;
const SurfaceStyle* shell_style = get_style(*it);
if (convert_shape(*it,s)) {
shapes.push_back(IfcRepresentationShapeItem(l->data().id(), s, shell_style ? shell_style : collective_style));
shapes.push_back(ConversionResult(l->data().id(), new OpenCascadeShape(s), shell_style ? shell_style : collective_style));
part_success |= true;
}
}
@@ -459,7 +459,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolygonalBoundedHalfSpace* l,
return true;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, IfcRepresentationShapeItems& shapes) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, ConversionResults& shapes) {
IfcEntityList::ptr shells = l->SbsmBoundary();
const SurfaceStyle* collective_style = get_style(l);
for( IfcEntityList::it it = shells->begin(); it != shells->end(); ++ it ) {
@@ -469,7 +469,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, Ifc
shell_style = get_style((IfcSchema::IfcRepresentationItem*)*it);
}
if (convert_shape(*it,s)) {
shapes.push_back(IfcRepresentationShapeItem(l->data().id(), s, shell_style ? shell_style : collective_style));
shapes.push_back(ConversionResult(l->data().id(), new OpenCascadeShape(s), shell_style ? shell_style : collective_style));
}
}
return true;
@@ -478,7 +478,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, Ifc
bool IfcGeom::Kernel::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape& shape) {
TopoDS_Shape s1, s2;
IfcRepresentationShapeItems items1, items2;
ConversionResults items1, items2;
TopoDS_Wire boundary_wire;
IfcSchema::IfcBooleanOperand* operand1 = l->FirstOperand();
IfcSchema::IfcBooleanOperand* operand2 = l->SecondOperand();
@@ -664,7 +664,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Sh
return true;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcMappedItem* l, IfcRepresentationShapeItems& shapes) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcMappedItem* l, ConversionResults& shapes) {
gp_GTrsf gtrsf;
IfcSchema::IfcCartesianTransformationOperator* transform = l->MappingTarget();
if ( transform->declaration().is(IfcSchema::IfcCartesianTransformationOperator3DnonUniform::Class()) ) {
@@ -699,7 +699,8 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcMappedItem* l, IfcRepresentati
bool b = convert_shapes(map->MappedRepresentation(), shapes);
for (size_t i = previous_size; i < shapes.size(); ++ i ) {
shapes[i].prepend(gtrsf);
OpenCascadePlacement p(gtrsf);
shapes[i].prepend(&p);
// Apply styles assigned to the mapped item only if on
// a more granular level no styles have been applied
@@ -711,7 +712,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcMappedItem* l, IfcRepresentati
return b;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcRepresentation* l, IfcRepresentationShapeItems& shapes) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcRepresentation* l, ConversionResults& shapes) {
IfcSchema::IfcRepresentationItem::list::ptr items = l->Items();
bool part_succes = false;
if ( items->size() ) {
@@ -722,7 +723,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRepresentation* l, IfcRepresen
} else {
TopoDS_Shape s;
if (convert_shape(representation_item,s)) {
shapes.push_back(IfcRepresentationShapeItem(representation_item->data().id(), s, get_style(representation_item)));
shapes.push_back(ConversionResult(representation_item->data().id(), new OpenCascadeShape(s), get_style(representation_item)));
part_succes |= true;
}
}
@@ -731,7 +732,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRepresentation* l, IfcRepresen
return part_succes;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcGeometricSet* l, IfcRepresentationShapeItems& shapes) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcGeometricSet* l, ConversionResults& shapes) {
IfcEntityList::ptr elements = l->Elements();
if ( !elements->size() ) return false;
bool part_succes = false;
@@ -749,7 +750,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcGeometricSet* l, IfcRepresenta
} else if (element->declaration().is(IfcSchema::IfcSurface::Class())) {
style = get_style((IfcSchema::IfcSurface*) element);
}
shapes.push_back(IfcRepresentationShapeItem(l->data().id(), s, style ? style : parent_style));
shapes.push_back(ConversionResult(l->data().id(), new OpenCascadeShape(s), style ? style : parent_style));
}
}
return part_succes;
+2 -2
View File
@@ -21,7 +21,7 @@
#define IFCGEOMTREE_H
#include "../ifcparse/IfcFile.h"
#include "../ifcgeom/IfcGeomElement.h"
#include "../ifcgeom_schema_agnostic/IfcGeomElement.h"
#include "../ifcgeom_schema_agnostic/IfcGeomIterator.h"
#include "../ifcgeom_schema_agnostic/Kernel.h"
@@ -267,7 +267,7 @@ namespace IfcGeom {
if (it.initialize()) {
do {
IfcGeom::BRepElement<double>* elem = (IfcGeom::BRepElement<double>*)it.get();
IfcGeom::NativeElement<double>* elem = (IfcGeom::NativeElement<double>*)it.get();
add((IfcUtil::IfcBaseEntity*)f.instance_by_id(elem->id()), elem->geometry().as_compound());
} while (it.next());
}
+3 -3
View File
@@ -24,11 +24,11 @@
using namespace IfcUtil;
bool IfcGeom::Kernel::convert_shapes(const IfcBaseClass* l, IfcRepresentationShapeItems& r) {
bool IfcGeom::Kernel::convert_shapes(const IfcBaseClass* l, ConversionResults& r) {
if (shape_type(l) != ST_SHAPELIST) {
TopoDS_Shape shp;
if (convert_shape(l, shp)) {
r.push_back(IfcGeom::IfcRepresentationShapeItem(l->data().id(), shp, get_style(l->as<IfcSchema::IfcRepresentationItem>())));
r.push_back(IfcGeom::ConversionResult(l->data().id(), new OpenCascadeShape(shp), get_style(l->as<IfcSchema::IfcRepresentationItem>())));
return true;
}
return false;
@@ -61,7 +61,7 @@ bool IfcGeom::Kernel::convert_shape(const IfcBaseClass* l, TopoDS_Shape& r) {
ignored = (!include_solids_and_surfaces && (st == ST_SHAPE || st == ST_FACE)) || (!include_curves && (st == ST_WIRE || st == ST_CURVE));
if (st == ST_SHAPELIST) {
processed = true;
IfcRepresentationShapeItems items;
ConversionResults items;
success = convert_shapes(l, items) && flatten_shape_list(items, r, false);
} else if (st == ST_SHAPE && include_solids_and_surfaces) {
#include "IfcRegisterConvertShape.h"
+1 -1
View File
@@ -1,6 +1,6 @@
#include "IfcRegisterUndef.h"
#define CLASS(T,V) bool convert(const IfcSchema::T* L, V& r);
#define SHAPES(T) CLASS(T,IfcRepresentationShapeItems)
#define SHAPES(T) CLASS(T,ConversionResults)
#define SHAPE(T) CLASS(T,TopoDS_Shape)
#define WIRE(T) CLASS(T,TopoDS_Wire)
#define FACE(T) CLASS(T,TopoDS_Shape)
-55
View File
@@ -1,55 +0,0 @@
/********************************************************************************
* *
* 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 IFCSHAPELIST_H
#define IFCSHAPELIST_H
#include <gp_GTrsf.hxx>
#include <TopoDS_Shape.hxx>
#include "../ifcgeom_schema_agnostic/IfcGeomRenderStyles.h"
namespace IfcGeom {
class IFC_GEOM_API IfcRepresentationShapeItem {
private:
int id;
gp_GTrsf placement;
TopoDS_Shape shape;
const SurfaceStyle* style;
public:
IfcRepresentationShapeItem(int id, const gp_GTrsf& placement, const TopoDS_Shape& shape, const SurfaceStyle* style)
: id(id), placement(placement), shape(shape), style(style) {}
IfcRepresentationShapeItem(int id, const gp_GTrsf& placement, const TopoDS_Shape& shape)
: id(id), placement(placement), shape(shape), style(0) {}
IfcRepresentationShapeItem(int id, const TopoDS_Shape& shape, const SurfaceStyle* style)
: id(id), shape(shape), style(style) {}
IfcRepresentationShapeItem(int id, const TopoDS_Shape& shape)
: id(id), shape(shape), style(0) {}
void append(const gp_GTrsf& trsf) { placement.Multiply(trsf); }
void prepend(const gp_GTrsf& trsf) { placement.PreMultiply(trsf); }
const TopoDS_Shape& Shape() const { return shape; }
const gp_GTrsf& Placement() const { return placement; }
bool hasStyle() const { return style != 0; }
const SurfaceStyle& Style() const { return *style; }
void setStyle(const SurfaceStyle* style) { this->style = style; }
int ItemId() const { return id; }
};
typedef std::vector<IfcRepresentationShapeItem> IfcRepresentationShapeItems;
}
#endif
+104
View File
@@ -0,0 +1,104 @@
/********************************************************************************
* *
* 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 IFCGEOMOPENCASCADEREPRESENTATION_H
#define IFCGEOMOPENCASCADEREPRESENTATION_H
#include <BRepMesh_IncrementalMesh.hxx>
#include <BRepGProp_Face.hxx>
#include <Poly_Triangulation.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <TopExp_Explorer.hxx>
#include <BRepTools.hxx>
#include <gp_GTrsf.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <GCPnts_QuasiUniformDeflection.hxx>
#include "../ifcgeom_schema_agnostic/ConversionResult.h"
namespace IfcGeom {
class OpenCascadePlacement : public ConversionResultPlacement {
public:
OpenCascadePlacement(const gp_GTrsf& trsf)
: trsf_(trsf) {}
const gp_GTrsf& trsf() const { return trsf_; }
operator const gp_GTrsf& () { return trsf_; }
virtual double Value(int i, int j) const {
return trsf_.Value(i, j);
}
virtual void Multiply(const ConversionResultPlacement* other) {
trsf_.Multiply(((OpenCascadePlacement*)other)->trsf_);
}
virtual void PreMultiply(const ConversionResultPlacement* other) {
trsf_.PreMultiply(((OpenCascadePlacement*)other)->trsf_);
}
virtual ConversionResultPlacement* clone() const {
return new OpenCascadePlacement(trsf_);
}
virtual ConversionResultPlacement* inverted() const {
return new OpenCascadePlacement(trsf_.Inverted());
}
virtual ConversionResultPlacement* multiplied(const ConversionResultPlacement* other) const {
return new OpenCascadePlacement(trsf_.Multiplied(((OpenCascadePlacement*)other)->trsf_));
}
private:
gp_GTrsf trsf_;
};
class OpenCascadeShape : public ConversionResultShape {
public:
OpenCascadeShape(const TopoDS_Shape& shape)
: shape_(shape)
{}
const TopoDS_Shape& shape() const { return shape_; }
operator const TopoDS_Shape& () { return shape_; }
virtual void Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement * place, IfcGeom::Representation::Triangulation<float>* t, int surface_style_id) const;
virtual void Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement * place, IfcGeom::Representation::Triangulation<double>* t, int surface_style_id) const;
virtual void Serialize(std::string&) const {
throw std::runtime_error("Not implemented");
}
virtual ConversionResultShape* clone() const {
return new OpenCascadeShape(shape_);
}
virtual int surface_genus() const;
private:
TopoDS_Shape shape_;
};
}
#endif
+202
View File
@@ -0,0 +1,202 @@
#include "OpenCascadeConversionResult.h"
#include "../ifcparse/IfcLogger.h"
#include "../ifcgeom_schema_agnostic/IfcGeomRepresentation.h"
#include "IfcGeom.h"
#include <TopoDS.hxx>
#include <map>
template <typename Precision>
void triangulate_helper(const TopoDS_Shape& s, const IfcGeom::IteratorSettings& settings, const IfcGeom::ConversionResultPlacement* place, IfcGeom::Representation::Triangulation<Precision>* t, int surface_style_id) {
gp_GTrsf trsf;
if (place) {
trsf = dynamic_cast<const IfcGeom::OpenCascadePlacement*>(place)->trsf();
}
// Triangulate the shape
try {
BRepMesh_IncrementalMesh(s, settings.deflection_tolerance());
} catch (...) {
// TODO: Catch outside
// Logger::Message(Logger::LOG_ERROR,"Failed to triangulate shape:",ifc_file->entityById(_id)->entity);
Logger::Message(Logger::LOG_ERROR, "Failed to triangulate shape");
return;
}
// Iterates over the faces of the shape
int num_faces = 0;
TopExp_Explorer exp;
for (exp.Init(s, TopAbs_FACE); exp.More(); exp.Next(), ++num_faces) {
TopoDS_Face face = TopoDS::Face(exp.Current());
TopLoc_Location loc;
Handle_Poly_Triangulation tri = BRep_Tool::Triangulation(face, loc);
if (!tri.IsNull()) {
// A 3x3 matrix to rotate the vertex normals
const gp_Mat rotation_matrix = trsf.VectorialPart();
// Keep track of the number of times an edge is used
// Manifold edges (i.e. edges used twice) are deemed invisible
std::map<std::pair<int, int>, int> edgecount;
std::vector<std::pair<int, int> > edges_temp;
const TColgp_Array1OfPnt& nodes = tri->Nodes();
const TColgp_Array1OfPnt2d& uvs = tri->UVNodes();
std::vector<gp_XYZ> coords;
BRepGProp_Face prop(face);
std::map<int, int> dict;
// Vertex normals are only calculated if vertices are not welded and calculation is not disable explicitly.
const bool calculate_normals = !settings.get(IfcGeom::IteratorSettings::WELD_VERTICES) &&
!settings.get(IfcGeom::IteratorSettings::NO_NORMALS);
for (int i = 1; i <= nodes.Length(); ++i) {
coords.push_back(nodes(i).Transformed(loc).XYZ());
trsf.Transforms(*coords.rbegin());
const gp_XYZ& last = *coords.rbegin();
dict[i] = t->addVertex(surface_style_id, last.X(), last.Y(), last.Z());
if (calculate_normals) {
const gp_Pnt2d& uv = uvs(i);
gp_Pnt p;
gp_Vec normal_direction;
prop.Normal(uv.X(), uv.Y(), p, normal_direction);
gp_Vec normal(0., 0., 0.);
if (normal_direction.Magnitude() > 1.e-9) {
normal = gp_Dir(normal_direction.XYZ() * rotation_matrix);
}
t->addNormal(normal.X(), normal.Y(), normal.Z());
}
}
const Poly_Array1OfTriangle& triangles = tri->Triangles();
for (int i = 1; i <= triangles.Length(); ++i) {
int n1, n2, n3;
if (face.Orientation() == TopAbs_REVERSED)
triangles(i).Get(n3, n2, n1);
else triangles(i).Get(n1, n2, n3);
/* An alternative would be to calculate normals based
* on the coordinates of the mesh vertices */
/*
const gp_XYZ pt1 = coords[n1-1];
const gp_XYZ pt2 = coords[n2-1];
const gp_XYZ pt3 = coords[n3-1];
const gp_XYZ v1 = pt2-pt1;
const gp_XYZ v2 = pt3-pt2;
gp_Dir normal = gp_Dir(v1^v2);
_normals.push_back((float)normal.X());
_normals.push_back((float)normal.Y());
_normals.push_back((float)normal.Z());
*/
t->addFace(surface_style_id, dict[n1], dict[n2], dict[n3]);
t->addEdge(dict[n1], dict[n2], edgecount, edges_temp);
t->addEdge(dict[n2], dict[n3], edgecount, edges_temp);
t->addEdge(dict[n3], dict[n1], edgecount, edges_temp);
}
for (std::vector<std::pair<int, int> >::const_iterator jt = edges_temp.begin(); jt != edges_temp.end(); ++jt) {
if (edgecount[*jt] == 1) {
// non manifold edge, face boundary
t->registerEdge(jt->first, jt->second);
}
}
}
}
/*
TODO: Unimplemented
if (!t.normals().empty() && settings().get(IfcGeom::IteratorSettings::GENERATE_UVS)) {
t.uvs() = box_project_uvs(t.verts(), t.normals());
}
if (num_faces == 0) {
// Edges are only emitted if there are no faces. A mixed representation of faces
// and loose edges is discouraged by the standard. An alternative would be to use
// TopExp_Explorer texp(s, TopAbs_EDGE, TopAbs_FACE) to find edges that do not
// belong to any face.
for (TopExp_Explorer texp(s, TopAbs_EDGE); texp.More(); texp.Next()) {
BRepAdaptor_Curve crv(TopoDS::Edge(texp.Current()));
GCPnts_QuasiUniformDeflection tessellater(crv, settings.deflection_tolerance());
int n = tessellater.NbPoints();
int start = (int)t->verts().size() / 3;
for (int i = 1; i <= n; ++i) {
gp_XYZ p = tessellater.Value(i).XYZ();
// // In case you want direction arrows on your edges
// double u = tessellater.Parameter(i);
// gp_XYZ p2, p3;
// gp_Pnt tmp;
// gp_Vec tmp2;
// crv.D1(u, tmp, tmp2);
// gp_Dir d1, d2, d3, d4;
// d1 = tmp2;
// if (texp.Current().Orientation() == TopAbs_REVERSED) {
// d1 = -d1;
// }
// if (fabs(d1.Z()) < 0.5) {
// d2 = d1.Crossed(gp::DZ());
// } else {
// d2 = d1.Crossed(gp::DY());
// }
// d3 = d1.XYZ() + d2.XYZ();
// d4 = d1.XYZ() - d2.XYZ();
// p2 = p - d3.XYZ() / 10.;
// p3 = p - d4.XYZ() / 10.;
// trsf.Transforms(p2);
// trsf.Transforms(p3);
// _material_ids.push_back(surface_style_id);
// _material_ids.push_back(surface_style_id);
// _verts.push_back(static_cast<P>(p2.X()));
// _verts.push_back(static_cast<P>(p2.Y()));
// _verts.push_back(static_cast<P>(p2.Z()));
// _verts.push_back(static_cast<P>(p3.X()));
// _verts.push_back(static_cast<P>(p3.Y()));
// _verts.push_back(static_cast<P>(p3.Z()));
trsf.Transforms(p);
t->material_ids().push_back(surface_style_id);
t->verts().push_back(static_cast<double>(p.X()));
t->verts().push_back(static_cast<double>(p.Y()));
t->verts().push_back(static_cast<double>(p.Z()));
if (i > 1) {
t->edges().push_back(start + i - 2);
t->edges().push_back(start + i - 1);
// _edges.push_back(start + 3 * (i - 2) + 2);
// _edges.push_back(start + 3 * (i - 1) + 2);
}
// _edges.push_back(start + 3 * (i - 1) + 0);
// _edges.push_back(start + 3 * (i - 1) + 2);
// _edges.push_back(start + 3 * (i - 1) + 1);
// _edges.push_back(start + 3 * (i - 1) + 2);
}
}
}
*/
BRepTools::Clean(s);
}
void IfcGeom::OpenCascadeShape::Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement * place, IfcGeom::Representation::Triangulation<float>* t, int surface_style_id) const {
triangulate_helper(shape_, settings, place, t, surface_style_id);
}
void IfcGeom::OpenCascadeShape::Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement * place, IfcGeom::Representation::Triangulation<double>* t, int surface_style_id) const {
triangulate_helper(shape_, settings, place, t, surface_style_id);
}
int IfcGeom::OpenCascadeShape::surface_genus() const {
return IfcGeom::Kernel::surface_genus(shape_);
}
View File
View File
@@ -0,0 +1,93 @@
/********************************************************************************
* *
* 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 IFCSHAPELIST_H
#define IFCSHAPELIST_H
#include "../ifcgeom_schema_agnostic/IfcGeomRenderStyles.h"
#include "../ifcgeom_schema_agnostic/IfcGeomIteratorSettings.h"
namespace IfcGeom {
namespace Representation {
template <typename P>
class IFC_GEOM_API Triangulation;
}
class IFC_GEOM_API ConversionResultPlacement {
public:
virtual void Multiply(const ConversionResultPlacement*) = 0;
virtual void PreMultiply(const ConversionResultPlacement*) = 0;
virtual ConversionResultPlacement* inverted() const = 0;
virtual ConversionResultPlacement* multiplied(const ConversionResultPlacement*) const = 0;
virtual double Value(int i, int j) const = 0;
virtual ConversionResultPlacement* clone() const = 0;
virtual ~ConversionResultPlacement() {}
};
class IFC_GEOM_API ConversionResultShape {
public:
virtual void Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement* place, IfcGeom::Representation::Triangulation<float>* t, int surface_style_id) const = 0;
virtual void Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement* place, IfcGeom::Representation::Triangulation<double>* t, int surface_style_id) const = 0;
virtual void Serialize(std::string&) const = 0;
virtual ConversionResultShape* clone() const = 0;
virtual int surface_genus() const = 0;
virtual ~ConversionResultShape() {}
};
class IFC_GEOM_API ConversionResult {
private:
int id;
ConversionResultPlacement* placement;
ConversionResultShape* shape;
const SurfaceStyle* style;
public:
ConversionResult(int id, const ConversionResultPlacement* placement, const ConversionResultShape* shape, const SurfaceStyle* style)
: id(id), placement(placement->clone()), shape(shape->clone()), style(style) {}
ConversionResult(int id, const ConversionResultPlacement* placement, const ConversionResultShape* shape)
: id(id), placement(placement->clone()), shape(shape->clone()), style(0) {}
ConversionResult(int id, const ConversionResultShape* shape, const SurfaceStyle* style)
: id(id), placement(0), shape(shape->clone()), style(style) {}
ConversionResult(int id, const ConversionResultShape* shape)
: id(id), placement(0), shape(shape->clone()), style(0) {}
void append(const ConversionResultPlacement* trsf) {
if (placement == 0) {
placement = trsf->clone();
} else {
placement->Multiply(trsf);
}
}
void prepend(const ConversionResultPlacement* trsf) {
if (placement == 0) {
placement = trsf->clone();
} else {
placement->PreMultiply(trsf);
}
}
const ConversionResultShape* Shape() const { return shape; }
const ConversionResultPlacement* Placement() const { return placement; }
bool hasStyle() const { return style != 0; }
const SurfaceStyle& Style() const { return *style; }
void setStyle(const SurfaceStyle* style) { this->style = style; }
int ItemId() const { return id; }
};
typedef std::vector<ConversionResult> ConversionResults;
}
#endif
@@ -25,8 +25,8 @@
#include "../ifcparse/IfcGlobalId.h"
#include "../ifcgeom/IfcGeomRepresentation.h"
#include "../ifcgeom/IfcGeomIteratorSettings.h"
#include "../ifcgeom_schema_agnostic/IfcGeomRepresentation.h"
#include "../ifcgeom_schema_agnostic/IfcGeomIteratorSettings.h"
#include "ifc_geom_api.h"
namespace IfcGeom {
@@ -36,7 +36,7 @@ namespace IfcGeom {
private:
std::vector<P> _data;
public:
Matrix(const ElementSettings& settings, const gp_Trsf& trsf) {
Matrix(const ElementSettings& settings, const ConversionResultPlacement* trsf) {
// Convert the gp_Trsf into a 4x3 Matrix
// Note that in case the CONVERT_BACK_UNITS setting is enabled
// the translation component of the matrix needs to be divided
@@ -44,7 +44,7 @@ namespace IfcGeom {
// internally in IfcOpenShell everything is measured in meters.
for(int i = 1; i < 5; ++i) {
for (int j = 1; j < 4; ++j) {
const double trsf_value = trsf.Value(j,i);
const double trsf_value = trsf->Value(j,i);
const double matrix_value = i == 4 && settings.get(IteratorSettings::CONVERT_BACK_UNITS)
? trsf_value / settings.unit_magnitude()
: trsf_value;
@@ -59,23 +59,23 @@ namespace IfcGeom {
class Transformation {
private:
ElementSettings settings_;
gp_Trsf trsf_;
ConversionResultPlacement* trsf_;
Matrix<P> matrix_;
public:
Transformation(const ElementSettings& settings, const gp_Trsf& trsf)
Transformation(const ElementSettings& settings, const ConversionResultPlacement* trsf)
: settings_(settings)
, trsf_(trsf)
, trsf_(trsf->clone())
, matrix_(settings, trsf)
{}
const gp_Trsf& data() const { return trsf_; }
const ConversionResultPlacement* data() const { return trsf_; }
const Matrix<P>& matrix() const { return matrix_; }
Transformation inverted() const {
return Transformation(settings_, trsf_.Inverted());
return Transformation(settings_, trsf_->inverted());
}
Transformation multiplied(const Transformation& other) const {
return Transformation(settings_, trsf_.Multiplied(other.data()));
return Transformation(settings_, trsf_->multiplied(other.data()));
}
};
@@ -129,7 +129,7 @@ namespace IfcGeom {
void SetParents(std::vector<const IfcGeom::Element<P, PP>*> newparents) { _parents = newparents; }
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::IfcBaseEntity* product)
const std::string& guid, const std::string& context, const ConversionResultPlacement* trsf, IfcUtil::IfcBaseEntity* product)
: _id(id), _parent_id(parent_id), _name(name), _type(type), _guid(guid), _context(context), _transformation(settings, trsf)
, product_(product)
{
@@ -159,28 +159,25 @@ namespace IfcGeom {
};
template <typename P = double, typename PP = P>
class BRepElement : public Element<P, PP> {
class NativeElement : public Element<P, PP> {
private:
boost::shared_ptr<Representation::BRep> _geometry;
public:
const boost::shared_ptr<Representation::BRep>& geometry_pointer() 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,
const std::string& context, const gp_Trsf& trsf, const boost::shared_ptr<Representation::BRep>& geometry,
NativeElement(int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid,
const std::string& context, const ConversionResultPlacement* trsf, const boost::shared_ptr<Representation::BRep>& geometry,
IfcUtil::IfcBaseEntity* product)
: Element<P, PP>(geometry->settings() ,id, parent_id, name, type, guid, context, trsf, product)
, _geometry(geometry)
{}
bool calculate_projected_surface_area(double& along_x, double& along_y, double& along_z) const {
const auto& trsf = this->transformation().data();
const gp_Mat& mat = trsf.HVectorialPart();
gp_Ax3 ax(trsf.TranslationPart(), mat.Column(3), mat.Column(1));
return geometry().calculate_projected_surface_area(ax, along_x, along_y, along_z);
return geometry().calculate_projected_surface_area(this->transformation().data(), along_x, along_y, along_z);
}
private:
BRepElement(const BRepElement& other);
BRepElement& operator=(const BRepElement& other);
NativeElement(const NativeElement& other);
NativeElement& operator=(const NativeElement& other);
};
template <typename P = double, typename PP = P>
@@ -190,7 +187,7 @@ namespace IfcGeom {
public:
const Representation::Triangulation<P>& geometry() const { return *_geometry; }
const boost::shared_ptr< Representation::Triangulation<P> >& geometry_pointer() const { return _geometry; }
TriangulationElement(const BRepElement<P, PP>& shape_model)
TriangulationElement(const NativeElement<P, PP>& shape_model)
: Element<P, PP>(shape_model)
, _geometry(boost::shared_ptr<Representation::Triangulation<P> >(new Representation::Triangulation<P>(shape_model.geometry())))
{}
@@ -209,7 +206,7 @@ namespace IfcGeom {
Representation::Serialization* _geometry;
public:
const Representation::Serialization& geometry() const { return *_geometry; }
SerializedElement(const BRepElement<P, PP>& shape_model)
SerializedElement(const NativeElement<P, PP>& shape_model)
: Element<P, PP>(shape_model)
, _geometry(new Representation::Serialization(shape_model.geometry()))
{}
@@ -119,7 +119,7 @@ namespace IfcGeom {
Element<P, PP>* get() { return implementation_->get(); }
BRepElement<P, PP>* get_native() { return implementation_->get_native(); }
NativeElement<P, PP>* get_native() { return implementation_->get_native(); }
const Element<P, PP>* get_object(int id) { return implementation_->get_object(id); }
@@ -23,6 +23,7 @@
#include "ifc_geom_api.h"
#include "../ifcparse/IfcException.h"
#include "../ifcparse/IfcBaseClass.h"
#include "../ifcparse/IfcLogger.h"
namespace IfcGeom
{
@@ -20,7 +20,7 @@
#ifndef IFCGEOMRENDERSTYLES_H
#define IFCGEOMRENDERSTYLES_H
#include "../ifcgeom/ifc_geom_api.h"
#include "../ifcgeom_schema_agnostic/ifc_geom_api.h"
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/replace.hpp>
@@ -26,16 +26,16 @@
#include <GProp_GProps.hxx>
#include <BRepGProp.hxx>
#include "../ifcgeom/IfcGeom.h"
#include "IfcGeomRepresentation.h"
#include "../ifcgeom/OpenCascadeConversionResult.h"
#include "../ifcgeom_schema_agnostic/Kernel.h"
IfcGeom::Representation::Serialization::Serialization(const BRep& brep)
: Representation(brep.settings())
, id_(brep.id())
{
TopoDS_Compound compound = brep.as_compound();
for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = brep.begin(); it != brep.end(); ++ it) {
for (IfcGeom::ConversionResults::const_iterator it = brep.begin(); it != brep.end(); ++ it) {
if (it->hasStyle() && it->Style().Diffuse()) {
const IfcGeom::SurfaceStyle::ColorComponent& clr = *it->Style().Diffuse();
surface_styles_.push_back(clr.R());
@@ -57,7 +57,7 @@ IfcGeom::Representation::Serialization::Serialization(const BRep& brep)
brep_data_ = sstream.str();
}
// todo copied from kernel
// @todo copied from kernel
#include <BRepBuilderAPI_Transform.hxx>
#include <BRepBuilderAPI_GTransform.hxx>
@@ -86,9 +86,13 @@ TopoDS_Compound IfcGeom::Representation::BRep::as_compound() const {
TopoDS_Compound compound;
BRep_Builder builder;
builder.MakeCompound(compound);
for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = begin(); it != end(); ++it) {
const TopoDS_Shape& s = it->Shape();
gp_GTrsf trsf = it->Placement();
for (IfcGeom::ConversionResults::const_iterator it = begin(); it != end(); ++it) {
const TopoDS_Shape& s = *(OpenCascadeShape*) it->Shape();
gp_GTrsf trsf;
if (it->Placement()) {
trsf = ((OpenCascadePlacement*)it->Placement())->trsf();
}
if (settings().get(IteratorSettings::CONVERT_BACK_UNITS)) {
gp_Trsf scale;
@@ -166,7 +170,7 @@ namespace {
const gp_Vec v2 = pt3 - pt2;
const gp_Vec v3 = pt1 - pt3;
const gp_Vec normal_vector = v1 ^ v2;
if (normal_vector.Magnitude() > ALMOST_ZERO) {
if (normal_vector.Magnitude() > 1.e-9) {
gp_Dir normal = gp_Dir();
double edge_lengths[3] = { v1.Magnitude(), v2.Magnitude(), v3.Magnitude() };
@@ -190,9 +194,9 @@ bool IfcGeom::Representation::BRep::calculate_surface_area(double& area) const {
try {
area = 0.;
for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = begin(); it != end(); ++it) {
for (IfcGeom::ConversionResults::const_iterator it = begin(); it != end(); ++it) {
GProp_GProps prop;
BRepGProp::SurfaceProperties(it->Shape(), prop);
BRepGProp::SurfaceProperties(*(OpenCascadeShape*)it->Shape(), prop);
area += prop.Mass();
}
@@ -207,10 +211,10 @@ bool IfcGeom::Representation::BRep::calculate_volume(double& volume) const {
try {
volume = 0.;
for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = begin(); it != end(); ++it) {
if (Kernel::is_manifold(it->Shape())) {
for (IfcGeom::ConversionResults::const_iterator it = begin(); it != end(); ++it) {
if (Kernel::is_manifold(*(OpenCascadeShape*)it->Shape())) {
GProp_GProps prop;
BRepGProp::VolumeProperties(it->Shape(), prop);
BRepGProp::VolumeProperties(*(OpenCascadeShape*)it->Shape(), prop);
volume += prop.Mass();
} else {
return false;
@@ -224,15 +228,19 @@ bool IfcGeom::Representation::BRep::calculate_volume(double& volume) const {
}
}
bool IfcGeom::Representation::BRep::calculate_projected_surface_area(const gp_Ax3 & ax, double & along_x, double & along_y, double & along_z) const {
bool IfcGeom::Representation::BRep::calculate_projected_surface_area(const ConversionResultPlacement* place, double & along_x, double & along_y, double & along_z) const {
try {
gp_Trsf trsf = ((OpenCascadePlacement*)place)->trsf().Trsf();
gp_Mat mat = trsf.HVectorialPart();
gp_Ax3 ax(trsf.TranslationPart(), mat.Column(3), mat.Column(1));
along_x = along_y = along_z = 0.;
for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = begin(); it != end(); ++it) {
for (IfcGeom::ConversionResults::const_iterator it = begin(); it != end(); ++it) {
double x, y, z;
surface_area_along_direction(settings().deflection_tolerance(), it->Shape(), ax, x, y, z);
surface_area_along_direction(settings().deflection_tolerance(), *(OpenCascadeShape*)it->Shape(), ax, x, y, z);
if (Kernel::is_manifold(it->Shape())) {
if (Kernel::is_manifold(*(OpenCascadeShape*)it->Shape())) {
x /= 2.;
y /= 2.;
z /= 2.;
@@ -35,12 +35,14 @@
#include <GCPnts_QuasiUniformDeflection.hxx>
#include <Geom_SphericalSurface.hxx>
#include "../ifcgeom/IfcGeomIteratorSettings.h"
#include "../ifcgeom_schema_agnostic/IfcGeomIteratorSettings.h"
#include "../ifcgeom_schema_agnostic/IfcGeomMaterial.h"
#include "../ifcgeom/IfcRepresentationShapeItem.h"
#include "../ifcgeom_schema_agnostic/ConversionResult.h"
#include <TopoDS_Compound.hxx>
#include <map>
namespace IfcGeom {
namespace Representation {
@@ -61,25 +63,25 @@ namespace IfcGeom {
class IFC_GEOM_API BRep : public Representation {
private:
std::string id_;
const IfcGeom::IfcRepresentationShapeItems shapes_;
const IfcGeom::ConversionResults shapes_;
BRep(const BRep& other);
BRep& operator=(const BRep& other);
public:
BRep(const ElementSettings& settings, const std::string& id, const IfcGeom::IfcRepresentationShapeItems& shapes)
BRep(const ElementSettings& settings, const std::string& id, const IfcGeom::ConversionResults& shapes)
: Representation(settings)
, id_(id)
, shapes_(shapes)
{}
virtual ~BRep() {}
IfcGeom::IfcRepresentationShapeItems::const_iterator begin() const { return shapes_.begin(); }
IfcGeom::IfcRepresentationShapeItems::const_iterator end() const { return shapes_.end(); }
const IfcGeom::IfcRepresentationShapeItems& shapes() const { return shapes_; }
IfcGeom::ConversionResults::const_iterator begin() const { return shapes_.begin(); }
IfcGeom::ConversionResults::const_iterator end() const { return shapes_.end(); }
const IfcGeom::ConversionResults& shapes() const { return shapes_; }
const std::string& id() const { return id_; }
TopoDS_Compound as_compound() const;
bool calculate_volume(double&) const;
bool calculate_surface_area(double&) const;
bool calculate_projected_surface_area(const gp_Ax3& ax, double& along_x, double& along_y, double& along_z) const;
bool calculate_projected_surface_area(const ConversionResultPlacement* ax, double& along_x, double& along_y, double& along_z) const;
};
class IFC_GEOM_API Serialization : public Representation {
@@ -133,7 +135,7 @@ namespace IfcGeom {
: Representation(shape_model.settings())
, id_(shape_model.id())
{
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator iit = shape_model.begin(); iit != shape_model.end(); ++ iit ) {
for ( IfcGeom::ConversionResults::const_iterator iit = shape_model.begin(); iit != shape_model.end(); ++ iit ) {
int surface_style_id = -1;
if (iit->hasStyle()) {
@@ -158,192 +160,7 @@ namespace IfcGeom {
}
}
const TopoDS_Shape& s = iit->Shape();
const gp_GTrsf& trsf = iit->Placement();
// Triangulate the shape
try {
BRepMesh_IncrementalMesh(s, settings().deflection_tolerance());
} catch(...) {
Logger::Message(Logger::LOG_ERROR, "Failed to triangulate shape");
continue;
}
// Iterates over the faces of the shape
int num_faces = 0;
TopExp_Explorer exp;
for ( exp.Init(s,TopAbs_FACE); exp.More(); exp.Next(), ++num_faces ) {
TopoDS_Face face = TopoDS::Face(exp.Current());
TopLoc_Location loc;
Handle_Poly_Triangulation tri = BRep_Tool::Triangulation(face,loc);
if ( ! tri.IsNull() ) {
// A 3x3 matrix to rotate the vertex normals
const gp_Mat rotation_matrix = trsf.VectorialPart();
// Keep track of the number of times an edge is used
// Manifold edges (i.e. edges used twice) are deemed invisible
std::map<std::pair<int,int>,int> edgecount;
std::vector<std::pair<int,int> > edges_temp;
const TColgp_Array1OfPnt& nodes = tri->Nodes();
const TColgp_Array1OfPnt2d& uvs = tri->UVNodes();
std::vector<gp_XYZ> coords;
BRepGProp_Face prop(face);
std::map<int,int> dict;
// Vertex normals are only calculated if vertices are not welded and calculation is not disable explicitly.
const bool calculate_normals = !settings().get(IteratorSettings::WELD_VERTICES) &&
!settings().get(IteratorSettings::NO_NORMALS);
for( int i = 1; i <= nodes.Length(); ++ i ) {
coords.push_back(nodes(i).Transformed(loc).XYZ());
trsf.Transforms(*coords.rbegin());
dict[i] = addVertex(surface_style_id, *coords.rbegin());
if ( calculate_normals ) {
const gp_Pnt2d& uv = uvs(i);
gp_Pnt p;
gp_Vec normal_direction;
prop.Normal(uv.X(),uv.Y(),p,normal_direction);
gp_Vec normal(0., 0., 0.);
if (normal_direction.Magnitude() > 1.e-9) {
normal = gp_Dir(normal_direction.XYZ() * rotation_matrix);
} else {
Handle_Geom_Surface surf = BRep_Tool::Surface(face);
// Special case the normal at the poles of a spherical surface
if (surf->DynamicType() == STANDARD_TYPE(Geom_SphericalSurface)) {
if (fabs(fabs(uv.Y()) - M_PI / 2.) < 1.e-9) {
const bool is_top = uv.Y() > 0;
const bool is_forward = face.Orientation() == TopAbs_FORWARD;
const double z = (is_top == is_forward) ? 1. : -1.;
normal = gp_Dir(gp_XYZ(0, 0, z) * rotation_matrix);
}
}
// TODO: Do the same for conical surfaces, but they are rare in IFC.
}
_normals.push_back(static_cast<P>(normal.X()));
_normals.push_back(static_cast<P>(normal.Y()));
_normals.push_back(static_cast<P>(normal.Z()));
}
}
const Poly_Array1OfTriangle& triangles = tri->Triangles();
for( int i = 1; i <= triangles.Length(); ++ i ) {
int n1,n2,n3;
if ( face.Orientation() == TopAbs_REVERSED )
triangles(i).Get(n3,n2,n1);
else triangles(i).Get(n1,n2,n3);
/* An alternative would be to calculate normals based
* on the coordinates of the mesh vertices */
/*
const gp_XYZ pt1 = coords[n1-1];
const gp_XYZ pt2 = coords[n2-1];
const gp_XYZ pt3 = coords[n3-1];
const gp_XYZ v1 = pt2-pt1;
const gp_XYZ v2 = pt3-pt2;
gp_Dir normal = gp_Dir(v1^v2);
_normals.push_back((float)normal.X());
_normals.push_back((float)normal.Y());
_normals.push_back((float)normal.Z());
*/
_faces.push_back(dict[n1]);
_faces.push_back(dict[n2]);
_faces.push_back(dict[n3]);
_material_ids.push_back(surface_style_id);
addEdge(dict[n1], dict[n2], edgecount, edges_temp);
addEdge(dict[n2], dict[n3], edgecount, edges_temp);
addEdge(dict[n3], dict[n1], edgecount, edges_temp);
}
for ( std::vector<std::pair<int,int> >::const_iterator jt = edges_temp.begin(); jt != edges_temp.end(); ++jt ) {
if (edgecount[*jt] == 1) {
// non manifold edge, face boundary
_edges.push_back(jt->first);
_edges.push_back(jt->second);
}
}
}
}
if (!_normals.empty() && settings().get(IfcGeom::IteratorSettings::GENERATE_UVS)) {
uvs_ = box_project_uvs(_verts, _normals);
}
if (num_faces == 0) {
// Edges are only emitted if there are no faces. A mixed representation of faces
// and loose edges is discouraged by the standard. An alternative would be to use
// TopExp_Explorer texp(s, TopAbs_EDGE, TopAbs_FACE) to find edges that do not
// belong to any face.
for (TopExp_Explorer texp(s, TopAbs_EDGE); texp.More(); texp.Next()) {
BRepAdaptor_Curve crv(TopoDS::Edge(texp.Current()));
GCPnts_QuasiUniformDeflection tessellater(crv, settings().deflection_tolerance());
int n = tessellater.NbPoints();
int start = (int)_verts.size() / 3;
for (int i = 1; i <= n; ++i) {
gp_XYZ p = tessellater.Value(i).XYZ();
/*
// In case you want direction arrows on your edges
double u = tessellater.Parameter(i);
gp_XYZ p2, p3;
gp_Pnt tmp;
gp_Vec tmp2;
crv.D1(u, tmp, tmp2);
gp_Dir d1, d2, d3, d4;
d1 = tmp2;
if (texp.Current().Orientation() == TopAbs_REVERSED) {
d1 = -d1;
}
if (fabs(d1.Z()) < 0.5) {
d2 = d1.Crossed(gp::DZ());
} else {
d2 = d1.Crossed(gp::DY());
}
d3 = d1.XYZ() + d2.XYZ();
d4 = d1.XYZ() - d2.XYZ();
p2 = p - d3.XYZ() / 10.;
p3 = p - d4.XYZ() / 10.;
trsf.Transforms(p2);
trsf.Transforms(p3);
_material_ids.push_back(surface_style_id);
_material_ids.push_back(surface_style_id);
_verts.push_back(static_cast<P>(p2.X()));
_verts.push_back(static_cast<P>(p2.Y()));
_verts.push_back(static_cast<P>(p2.Z()));
_verts.push_back(static_cast<P>(p3.X()));
_verts.push_back(static_cast<P>(p3.Y()));
_verts.push_back(static_cast<P>(p3.Z()));
*/
trsf.Transforms(p);
_material_ids.push_back(surface_style_id);
_verts.push_back(static_cast<P>(p.X()));
_verts.push_back(static_cast<P>(p.Y()));
_verts.push_back(static_cast<P>(p.Z()));
if (i > 1) {
_edges.push_back(start + i - 2);
_edges.push_back(start + i - 1);
// _edges.push_back(start + 3 * (i - 2) + 2);
// _edges.push_back(start + 3 * (i - 1) + 2);
}
// _edges.push_back(start + 3 * (i - 1) + 0);
// _edges.push_back(start + 3 * (i - 1) + 2);
// _edges.push_back(start + 3 * (i - 1) + 1);
// _edges.push_back(start + 3 * (i - 1) + 2);
}
}
}
BRepTools::Clean(s);
iit->Shape()->Triangulate(settings(), iit->Placement(), this, surface_style_id);
}
}
virtual ~Triangulation() {}
@@ -378,13 +195,14 @@ namespace IfcGeom {
return uvs;
}
private:
public:
// Welds vertices that belong to different faces
int addVertex(int material_index, const gp_XYZ& p) {
int addVertex(int material_index, P X, P Y, P Z) {
const bool convert = settings().get(IteratorSettings::CONVERT_BACK_UNITS);
const P X = static_cast<P>(convert ? (p.X() / settings().unit_magnitude()) : p.X());
const P Y = static_cast<P>(convert ? (p.Y() / settings().unit_magnitude()) : p.Y());
const P Z = static_cast<P>(convert ? (p.Z() / settings().unit_magnitude()) : p.Z());
X = static_cast<P>(convert ? (X / settings().unit_magnitude()) : X);
Y = static_cast<P>(convert ? (Y / settings().unit_magnitude()) : Y);
Z = static_cast<P>(convert ? (Z / settings().unit_magnitude()) : Z);
int i = (int) _verts.size() / 3;
if (settings().get(IteratorSettings::WELD_VERTICES)) {
const VertexKey key = std::make_pair(material_index, std::make_pair(X, std::make_pair(Y, Z)));
@@ -398,12 +216,34 @@ namespace IfcGeom {
_verts.push_back(Z);
return i;
}
inline void addEdge(int n1, int n2, std::map<std::pair<int,int>,int>& edgecount, std::vector<std::pair<int,int> >& edges_temp) {
const Edge e = Edge( (std::min)(n1,n2),(std::max)(n1,n2) );
if ( edgecount.find(e) == edgecount.end() ) edgecount[e] = 1;
else edgecount[e] ++;
edges_temp.push_back(e);
}
inline void addNormal(P X, P Y, P Z) {
_normals.push_back(X);
_normals.push_back(Y);
_normals.push_back(Z);
}
inline void addFace(int style, int i0, int i1, int i2) {
_faces.push_back(i0);
_faces.push_back(i1);
_faces.push_back(i2);
_material_ids.push_back(style);
}
inline void registerEdge(int i0, int i1) {
_edges.push_back(i0);
_edges.push_back(i1);
}
private:
Triangulation();
Triangulation(const Triangulation&);
Triangulation& operator=(const Triangulation&);
@@ -3,7 +3,7 @@
#include "../ifcgeom_schema_agnostic/IfcGeomFilter.h"
#include "../ifcparse/IfcFile.h"
#include "../ifcgeom/IfcGeomIteratorSettings.h"
#include "../ifcgeom_schema_agnostic/IfcGeomIteratorSettings.h"
#include <gp_XYZ.hxx>
@@ -20,7 +20,7 @@ namespace IfcGeom {
class Element;
template <typename P, typename PP>
class BRepElement;
class NativeElement;
}
typedef boost::function3<IfcGeom::IteratorImplementation<float, float>*, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*, const std::vector<IfcGeom::filter_t>&> iterator_float_float_fn;
@@ -71,7 +71,7 @@ namespace IfcGeom {
virtual IfcParse::IfcFile* file() const = 0;
virtual IfcUtil::IfcBaseClass* next() = 0;
virtual Element<P, PP>* get() = 0;
virtual BRepElement<P, PP>* get_native() = 0;
virtual NativeElement<P, PP>* get_native() = 0;
virtual const Element<P, PP>* get_object(int id) = 0;
virtual IfcUtil::IfcBaseClass* create() = 0;
};
+5 -5
View File
@@ -2,8 +2,8 @@
#define ITERATOR_KERNEL_H
#include "../ifcparse/IfcFile.h"
#include "../ifcgeom/IfcGeomIteratorSettings.h"
#include "../ifcgeom/IfcRepresentationShapeItem.h"
#include "../ifcgeom_schema_agnostic/IfcGeomIteratorSettings.h"
#include "../ifcgeom_schema_agnostic/ConversionResult.h"
#include "../ifcparse/Ifc2x3.h"
#include "../ifcparse/Ifc4.h"
@@ -15,7 +15,7 @@
namespace IfcGeom {
template <typename P, typename PP>
class BRepElement;
class NativeElement;
class Kernel {
private:
@@ -64,14 +64,14 @@ namespace IfcGeom {
return implementation_->getValue(var);
}
virtual BRepElement<double, double>* convert(
virtual NativeElement<double, double>* convert(
const IteratorSettings& settings, IfcUtil::IfcBaseClass* representation,
IfcUtil::IfcBaseClass* product)
{
return implementation_->convert(settings, representation, product);
}
virtual IfcRepresentationShapeItems convert(IfcUtil::IfcBaseClass* item) {
virtual ConversionResults convert(IfcUtil::IfcBaseClass* item) {
return implementation_->convert(item);
}
+1 -1
View File
@@ -1,4 +1,4 @@
#include "../ifcgeom/ifc_geom_api.h"
#include "../ifcgeom_schema_agnostic/ifc_geom_api.h"
#include "../ifcparse/IfcBaseClass.h"
#include <TopoDS_Shape.hxx>
+5 -5
View File
@@ -39,7 +39,7 @@
#endif
#include "../ifcgeom_schema_agnostic/IfcGeomIterator.h"
#include "../ifcgeom/IfcGeomElement.h"
#include "../ifcgeom_schema_agnostic/IfcGeomElement.h"
#include "../ifcparse/IfcFile.h"
#include "../ifcparse/IfcLogger.h"
@@ -404,9 +404,9 @@ static const std::string WALKABLE_SURFACE_AREA = "WALKABLE_SURFACE_AREA";
class QuantityWriter_v0 : public EntityExtension {
private:
const IfcGeom::BRepElement<float, double>* elem_;
const IfcGeom::NativeElement<float, double>* elem_;
public:
QuantityWriter_v0(const IfcGeom::BRepElement<float, double>* elem) :
QuantityWriter_v0(const IfcGeom::NativeElement<float, double>* elem) :
elem_(elem)
{
put_json(TOTAL_SURFACE_AREA, 0.);
@@ -419,9 +419,9 @@ public:
class QuantityWriter_v1 : public EntityExtension {
private:
const IfcGeom::BRepElement<float, double>* elem_;
const IfcGeom::NativeElement<float, double>* elem_;
public:
QuantityWriter_v1(const IfcGeom::BRepElement<float, double>* elem) :
QuantityWriter_v1(const IfcGeom::NativeElement<float, double>* elem) :
elem_(elem)
{
double a, b, c;
+2 -2
View File
@@ -369,7 +369,7 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
}
}
IfcGeom::BRepElement<double>* brep = kernel.convert(settings, ifc_representation, product);
IfcGeom::NativeElement<double>* brep = kernel.convert(settings, ifc_representation, product);
if (!brep) {
throw IfcParse::IfcException("Failed to process shape");
}
@@ -387,7 +387,7 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
} else {
if (!representation) {
if (instance->declaration().is(Schema::IfcRepresentationItem::Class()) || instance->declaration().is(Schema::IfcRepresentation::Class())) {
IfcGeom::IfcRepresentationShapeItems shapes = kernel.convert(instance);
IfcGeom::ConversionResults shapes = kernel.convert(instance);
IfcGeom::ElementSettings element_settings(settings, kernel.getValue(IfcGeom::Kernel::GV_LENGTH_UNIT), instance->declaration().name());
IfcGeom::Representation::BRep brep(element_settings, boost::lexical_cast<std::string>(instance->data().id()), shapes);
+1 -1
View File
@@ -230,7 +230,7 @@ public:
bool ready();
void writeHeader();
void write(const IfcGeom::TriangulationElement<real_t>* o);
void write(const IfcGeom::BRepElement<real_t>* /*o*/) {}
void write(const IfcGeom::NativeElement<real_t>* /*o*/) {}
void finalize();
bool isTesselated() const { return true; }
void setUnitNameAndMagnitude(const std::string& name, float magnitude) {
+2 -2
View File
@@ -28,7 +28,7 @@ typedef float real_t;
#include "../serializers/Serializer.h"
#include "../ifcgeom_schema_agnostic/IfcGeomIterator.h"
#include "../ifcgeom/IfcGeomElement.h"
#include "../ifcgeom_schema_agnostic/IfcGeomElement.h"
class SerializerSettings : public IfcGeom::IteratorSettings
{
@@ -77,7 +77,7 @@ public:
virtual bool isTesselated() const = 0;
virtual void write(const IfcGeom::TriangulationElement<real_t>* o) = 0;
virtual void write(const IfcGeom::BRepElement<real_t>* o) = 0;
virtual void write(const IfcGeom::NativeElement<real_t>* o) = 0;
virtual void setUnitNameAndMagnitude(const std::string& name, float magnitude) = 0;
const SerializerSettings& settings() const { return settings_; }
+2 -2
View File
@@ -42,8 +42,8 @@ public:
: OpenCascadeBasedSerializer(out_filename, settings)
{}
virtual ~IgesSerializer() {}
void writeShape(const TopoDS_Shape& shape) {
writer.AddShape(shape);
void writeShape(const IfcGeom::ConversionResultShape* shape) {
writer.AddShape(*(IfcGeom::OpenCascadeShape*)shape);
}
void finalize() {
writer.Write(out_filename.c_str());
@@ -34,7 +34,7 @@ bool OpenCascadeBasedSerializer::ready() {
return succeeded;
}
void OpenCascadeBasedSerializer::write(const IfcGeom::BRepElement<real_t>* o) {
void OpenCascadeBasedSerializer::write(const IfcGeom::NativeElement<real_t>* o) {
TopoDS_Shape compound = o->geometry().as_compound();
if (o->geometry().settings().get(IfcGeom::IteratorSettings::CONVERT_BACK_UNITS)) {
@@ -44,7 +44,8 @@ void OpenCascadeBasedSerializer::write(const IfcGeom::BRepElement<real_t>* o) {
compound = BRepBuilderAPI_Transform(compound, scale, true).Shape();
}
writeShape(compound);
IfcGeom::OpenCascadeShape s(compound);
writeShape(&s);
}
#define RATHER_SMALL (1e-3)
+3 -3
View File
@@ -21,7 +21,7 @@
#define OPENCASCADEBASEDSERIALIZER_H
#include "../ifcgeom_schema_agnostic/IfcGeomIterator.h"
#include "../ifcgeom/OpenCascadeConversionResult.h"
#include "../serializers/GeometrySerializer.h"
class OpenCascadeBasedSerializer : public GeometrySerializer {
@@ -38,9 +38,9 @@ public:
virtual ~OpenCascadeBasedSerializer() {}
void writeHeader() {}
bool ready();
virtual void writeShape(const TopoDS_Shape& shape) = 0;
virtual void writeShape(const IfcGeom::ConversionResultShape* shape) = 0;
void write(const IfcGeom::TriangulationElement<real_t>* /*o*/) {}
void write(const IfcGeom::BRepElement<real_t>* o);
void write(const IfcGeom::NativeElement<real_t>* o);
bool isTesselated() const { return false; }
void setFile(IfcParse::IfcFile*) {}
};
+2 -2
View File
@@ -36,10 +36,10 @@ public:
: OpenCascadeBasedSerializer(out_filename, settings)
{}
virtual ~StepSerializer() {}
void writeShape(const TopoDS_Shape& shape) {
void writeShape(const IfcGeom::ConversionResultShape* shape) {
std::stringstream ss;
std::streambuf *sb = std::cout.rdbuf(ss.rdbuf());
writer.Transfer(shape, STEPControl_AsIs);
writer.Transfer(((IfcGeom::OpenCascadeShape*)shape)->shape(), STEPControl_AsIs);
std::cout.rdbuf(sb);
}
void finalize() {
+2 -2
View File
@@ -283,14 +283,14 @@ SvgSerializer::path_object& SvgSerializer::start_path(IfcUtil::IfcBaseEntity* st
return p;
}
void SvgSerializer::write(const IfcGeom::BRepElement<real_t>* o)
void SvgSerializer::write(const IfcGeom::NativeElement<real_t>* o)
{
IfcUtil::IfcBaseEntity* storey = storey_;
boost::optional<double> storey_elevation = boost::none;
/*
TODO: based on BRepElement::parent()
TODO: based on NativeElement::parent()
IfcSchema::IfcObjectDefinition* obdef = static_cast<IfcSchema::IfcObjectDefinition*>(file->entityById(o->id()));
+1 -1
View File
@@ -62,7 +62,7 @@ public:
void writeHeader();
bool ready();
void write(const IfcGeom::TriangulationElement<real_t>* /*o*/) {}
void write(const IfcGeom::BRepElement<real_t>* o);
void write(const IfcGeom::NativeElement<real_t>* o);
void write(path_object& p, const TopoDS_Wire& wire);
path_object& start_path(IfcUtil::IfcBaseEntity* storey, const std::string& id);
bool isTesselated() const { return false; }
+1 -1
View File
@@ -51,7 +51,7 @@ public:
void writeHeader();
void writeMaterial(const IfcGeom::Material& style);
void write(const IfcGeom::TriangulationElement<real_t>* o);
void write(const IfcGeom::BRepElement<real_t>* /*o*/) {}
void write(const IfcGeom::NativeElement<real_t>* /*o*/) {}
void finalize() {}
bool isTesselated() const { return true; }
void setUnitNameAndMagnitude(const std::string& /*name*/, float /*magnitude*/) {}