mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
Merge remote-tracking branch 'cgal/cgal' into v0.7.0
This commit is contained in:
+15
-7
@@ -264,15 +264,23 @@ ENDIF()
|
||||
FIND_LIBRARY(libCGAL NAMES CGAL PATHS ${CGAL_LIBRARY_DIR} NO_DEFAULT_PATH)
|
||||
IF(libCGAL)
|
||||
MESSAGE(STATUS "CGAL library files found")
|
||||
foreach(lib ${CGAL_LIBRARY_NAMES})
|
||||
string(REPLACE libCGAL "${lib}" lib_path "${libCGAL}")
|
||||
list(APPEND CGAL_LIBRARIES "${lib_path}")
|
||||
endforeach()
|
||||
ELSE()
|
||||
MESSAGE(FATAL_ERROR "Unable to find CGAL library files, aborting")
|
||||
FILE(GLOB CGAL_LIBRARIES ${CGAL_LIBRARY_DIR}/CGAL*.lib)
|
||||
LIST(LENGTH CGAL_LIBRARY_NAMES num_cgal_library_names)
|
||||
LIST(LENGTH CGAL_LIBRARIES num_cgal_libraries)
|
||||
LINK_DIRECTORIES("${CGAL_LIBRARY_DIR}")
|
||||
if(NOT "${num_cgal_library_names}" STREQUAL "${num_cgal_library_names}")
|
||||
MESSAGE(FATAL_ERROR "Unable to find CGAL library files, aborting")
|
||||
endif()
|
||||
MESSAGE(STATUS "CGAL library files found")
|
||||
ENDIF()
|
||||
foreach(lib ${CGAL_LIBRARY_NAMES})
|
||||
string(REPLACE libCGAL "${lib}" lib_path "${libCGAL}")
|
||||
list(APPEND CGAL_LIBRARIES "${lib_path}")
|
||||
endforeach()
|
||||
FIND_LIBRARY(libGMP NAMES gmp PATHS ${GMP_LIBRARY_DIR} NO_DEFAULT_PATH)
|
||||
FIND_LIBRARY(libMPFR NAMES mpfr PATHS ${MPFR_LIBRARY_DIR} NO_DEFAULT_PATH)
|
||||
# TODO: Remove hardcoded version numbers for windows
|
||||
FIND_LIBRARY(libGMP NAMES gmp "libgmp-10" PATHS ${GMP_LIBRARY_DIR} NO_DEFAULT_PATH)
|
||||
FIND_LIBRARY(libMPFR NAMES mpfr "libmpfr-4" PATHS ${MPFR_LIBRARY_DIR} NO_DEFAULT_PATH)
|
||||
IF(NOT libGMP)
|
||||
MESSAGE(FATAL_ERROR "Unable to find GMP library files, aborting")
|
||||
ENDIF()
|
||||
|
||||
@@ -1,241 +1,115 @@
|
||||
#include "CgalKernel.h"
|
||||
#include "../../../ifcgeom/schema_agnostic/cgal/CgalConversionResult.h"
|
||||
|
||||
#define CgalKernel MAKE_TYPE_NAME(CgalKernel)
|
||||
|
||||
// @todo two distinct uses of the word Kernel is getting confusing
|
||||
typedef Kernel Kernel_;
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRepresentation* l, ConversionResults& shapes) {
|
||||
IfcSchema::IfcRepresentationItem::list::ptr items = l->Items();
|
||||
bool part_succes = false;
|
||||
if (items->size()) {
|
||||
for (IfcSchema::IfcRepresentationItem::list::it it = items->begin(); it != items->end(); ++it) {
|
||||
IfcSchema::IfcRepresentationItem* representation_item = *it;
|
||||
if (shape_type(representation_item) == ST_SHAPELIST) {
|
||||
part_succes |= convert_shapes(*it, shapes);
|
||||
} else {
|
||||
cgal_shape_t s;
|
||||
if (convert_shape(representation_item, s)) {
|
||||
shapes.push_back(ConversionResult(representation_item->data().id(), new CgalShape(s)));
|
||||
part_succes |= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return part_succes;
|
||||
bool IfcGeom::CgalKernel::convert_wire_to_face(const cgal_wire_t& wire, cgal_face_t& face) {
|
||||
face.outer = wire;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal_shape_t &shape) {
|
||||
const double height = l->Depth() * getValue(GV_LENGTH_UNIT);
|
||||
if (height < getValue(GV_PRECISION)) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Non-positive extrusion height encountered for:", l);
|
||||
return false;
|
||||
void IfcGeom::CgalKernel::remove_duplicate_points_from_loop(cgal_wire_t& polygon) {
|
||||
std::set<cgal_point_t> points;
|
||||
for (int i = 0; i < polygon.size(); ++i) {
|
||||
if (points.count(polygon[i])) {
|
||||
polygon.erase(polygon.begin()+i);
|
||||
--i;
|
||||
} else points.insert(polygon[i]);
|
||||
}
|
||||
|
||||
cgal_face_t face;
|
||||
if ( !convert_face(l->SweptArea(),face) ) return false;
|
||||
}
|
||||
|
||||
cgal_placement_t trsf;
|
||||
bool has_position = true;
|
||||
#ifdef USE_IFC4
|
||||
has_position = l->hasPosition();
|
||||
#endif
|
||||
if (has_position) {
|
||||
IfcGeom::CgalKernel::convert(l->Position(), trsf);
|
||||
}
|
||||
|
||||
cgal_direction_t dir;
|
||||
convert(l->ExtrudedDirection(),dir);
|
||||
// std::cout << "Direction: " << dir << std::endl;
|
||||
|
||||
std::list<cgal_face_t> face_list;
|
||||
face_list.push_back(face);
|
||||
|
||||
for (std::vector<Kernel_::Point_3>::const_iterator current_vertex = face.outer.begin();
|
||||
current_vertex != face.outer.end();
|
||||
++current_vertex) {
|
||||
std::vector<Kernel_::Point_3>::const_iterator next_vertex = current_vertex;
|
||||
++next_vertex;
|
||||
if (next_vertex == face.outer.end()) {
|
||||
next_vertex = face.outer.begin();
|
||||
} cgal_face_t side_face;
|
||||
side_face.outer.push_back(*next_vertex);
|
||||
side_face.outer.push_back(*current_vertex);
|
||||
side_face.outer.push_back(*current_vertex+height*dir);
|
||||
side_face.outer.push_back(*next_vertex+height*dir);
|
||||
face_list.push_back(side_face);
|
||||
}
|
||||
|
||||
cgal_face_t top_face;
|
||||
for (std::vector<Kernel_::Point_3>::const_reverse_iterator vertex = face.outer.rbegin();
|
||||
vertex != face.outer.rend();
|
||||
++vertex) {
|
||||
top_face.outer.push_back(*vertex+height*dir);
|
||||
} face_list.push_back(top_face);
|
||||
CGAL::Polyhedron_3<Kernel> IfcGeom::CgalKernel::create_polyhedron(std::list<cgal_face_t> &face_list) {
|
||||
|
||||
// Naive creation
|
||||
cgal_shape_t polyhedron = CGAL::Polyhedron_3<Kernel_>();
|
||||
CGAL::Polyhedron_3<Kernel> polyhedron;
|
||||
PolyhedronBuilder builder(&face_list);
|
||||
polyhedron.delegate(builder);
|
||||
|
||||
// Stitch edges
|
||||
// std::cout << "Before: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl;
|
||||
// std::cout << "Before: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl;
|
||||
CGAL::Polygon_mesh_processing::stitch_borders(polyhedron);
|
||||
if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) {
|
||||
CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron);
|
||||
}
|
||||
// std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl;
|
||||
|
||||
shape = polyhedron;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianPoint* l, cgal_point_t& point) {
|
||||
std::vector<double> xyz = l->Coordinates();
|
||||
if (xyz.size() == 3) {
|
||||
point = Kernel_::Point_3(xyz.size() ? (xyz[0]*getValue(GV_LENGTH_UNIT)) : 0.0f,
|
||||
xyz.size() > 1 ? (xyz[1]*getValue(GV_LENGTH_UNIT)) : 0.0f,
|
||||
xyz.size() > 2 ? (xyz[2]*getValue(GV_LENGTH_UNIT)) : 0.0f);
|
||||
// std::cout << "Converted Point(" << point << ")" << std::endl;
|
||||
return true;
|
||||
} else {
|
||||
throw std::runtime_error("Point without 3 coordinates");
|
||||
}
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcDirection* l, cgal_direction_t& dir) {
|
||||
// IN_CACHE(IfcDirection,l,cgal_direction_t,dir)
|
||||
std::vector<double> xyz = l->DirectionRatios();
|
||||
dir = Kernel_::Vector_3(xyz.size() ? xyz[0] : 0.0f,
|
||||
xyz.size() > 1 ? xyz[1] : 0.0f,
|
||||
xyz.size() > 2 ? xyz[2] : 0.0f);
|
||||
// CACHE(IfcDirection,l,dir)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement2D* l, cgal_placement_t& trsf) {
|
||||
// IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf)
|
||||
cgal_point_t o;
|
||||
cgal_direction_t axis = Kernel_::Vector_3(0,0,1);
|
||||
cgal_direction_t refDirection = Kernel_::Vector_3(1,0,0); // TODO: Put identity for now. Check?
|
||||
IfcGeom::CgalKernel::convert(l->Location(),o);
|
||||
bool hasRef = l->hasRefDirection();
|
||||
if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection);
|
||||
|
||||
// TODO: From Thomas' email. Should be checked.
|
||||
Kernel_::Vector_3 y = CGAL::cross_product(Kernel_::Vector_3(0.0, 0.0, 1.0), refDirection);
|
||||
trsf = Kernel_::Aff_transformation_3(refDirection.cartesian(0), y.cartesian(0), 0.0, o.cartesian(0),
|
||||
refDirection.cartesian(1), y.cartesian(1), 0.0, o.cartesian(1),
|
||||
0.0, y.cartesian(2), 1.0, 0.0);
|
||||
|
||||
// CACHE(IfcAxis2Placement3D,l,trsf)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement3D* l, cgal_placement_t& trsf) {
|
||||
// IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf)
|
||||
cgal_point_t o;
|
||||
cgal_direction_t axis = Kernel_::Vector_3(0,0,1);
|
||||
cgal_direction_t refDirection = Kernel_::Vector_3(1,0,0); // TODO: Put identity for now. Check?
|
||||
IfcGeom::CgalKernel::convert(l->Location(),o);
|
||||
bool hasRef = l->hasRefDirection();
|
||||
if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(),axis);
|
||||
if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection);
|
||||
|
||||
// std::cout << "Ref direction: " << refDirection << std::endl;
|
||||
// std::cout << "Axis: " << axis << std::endl;
|
||||
// std::cout << "Origin: " << o << std::endl;
|
||||
|
||||
// TODO: From Thomas' email. Should be checked.
|
||||
Kernel_::Vector_3 y = CGAL::cross_product(axis, refDirection);
|
||||
trsf = Kernel_::Aff_transformation_3(refDirection.cartesian(0), y.cartesian(0), axis.cartesian(0), o.cartesian(0),
|
||||
refDirection.cartesian(1), y.cartesian(1), axis.cartesian(1), o.cartesian(1),
|
||||
refDirection.cartesian(2), y.cartesian(2), axis.cartesian(2), o.cartesian(2));
|
||||
|
||||
// for (int i = 0; i < 3; ++i) {
|
||||
// for (int j = 0; j < 4; ++j) {
|
||||
// std::cout << trsf.cartesian(i, j) << " ";
|
||||
// } std::cout << std::endl;
|
||||
// }
|
||||
|
||||
// CACHE(IfcAxis2Placement3D,l,trsf)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcObjectPlacement* l, cgal_placement_t& trsf) {
|
||||
// TODO: These macros don't work for the CGAL types. Need to check why.
|
||||
// IN_CACHE(IfcObjectPlacement,l,cgal_placement_t,trsf)
|
||||
if ( ! l->as<IfcSchema::IfcLocalPlacement>() ) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Unsupported IfcObjectPlacement:", l);
|
||||
return false;
|
||||
}
|
||||
|
||||
// std::cout << "initial trsf (identity?)" << std::endl;
|
||||
// for (int i = 0; i < 3; ++i) {
|
||||
// for (int j = 0; j < 4; ++j) {
|
||||
// std::cout << trsf.cartesian(i, j) << " ";
|
||||
// } std::cout << std::endl;
|
||||
// }
|
||||
|
||||
IfcSchema::IfcLocalPlacement* current = (IfcSchema::IfcLocalPlacement*)l;
|
||||
for (;;) {
|
||||
cgal_placement_t trsf2;
|
||||
|
||||
IfcSchema::IfcAxis2Placement* relplacement = current->RelativePlacement();
|
||||
if ( relplacement->as<IfcSchema::IfcAxis2Placement3D>() ) {
|
||||
IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement3D*)relplacement,trsf2);
|
||||
|
||||
// std::cout << "trsf2" << std::endl;
|
||||
// for (int i = 0; i < 3; ++i) {
|
||||
// for (int j = 0; j < 4; ++j) {
|
||||
// std::cout << trsf2.cartesian(i, j) << " ";
|
||||
// } std::cout << std::endl;
|
||||
// }
|
||||
|
||||
trsf = trsf * trsf2; // TODO: I think it's fine, but maybe should it be the other way around?
|
||||
|
||||
// std::cout << "trsf (after multiplication)" << std::endl;
|
||||
// for (int i = 0; i < 3; ++i) {
|
||||
// for (int j = 0; j < 4; ++j) {
|
||||
// std::cout << trsf.cartesian(i, j) << " ";
|
||||
// } std::cout << std::endl;
|
||||
// }
|
||||
if (!polyhedron.is_valid()) {
|
||||
Logger::Message(Logger::LOG_ERROR, "create_polyhedron: Polyhedron not valid!");
|
||||
// std::ofstream fresult;
|
||||
// fresult.open("/Users/ken/Desktop/invalid.off");
|
||||
// fresult << polyhedron << std::endl;
|
||||
// fresult.close();
|
||||
return CGAL::Polyhedron_3<Kernel>();
|
||||
} if (polyhedron.is_closed()) {
|
||||
if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) {
|
||||
CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron);
|
||||
}
|
||||
if ( current->hasPlacementRelTo() ) {
|
||||
IfcSchema::IfcObjectPlacement* relto = current->PlacementRelTo();
|
||||
if ( relto->as<IfcSchema::IfcLocalPlacement>() )
|
||||
current = (IfcSchema::IfcLocalPlacement*)current->PlacementRelTo();
|
||||
else break;
|
||||
} else break;
|
||||
}
|
||||
// CACHE(IfcObjectPlacement,l,trsf)
|
||||
return true;
|
||||
|
||||
// std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl;
|
||||
|
||||
return polyhedron;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangleProfileDef* l, cgal_face_t& face) {
|
||||
const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
|
||||
if ( x < ALMOST_ZERO || y < ALMOST_ZERO ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l);
|
||||
return false;
|
||||
CGAL::Polyhedron_3<Kernel> IfcGeom::CgalKernel::create_polyhedron(CGAL::Nef_polyhedron_3<Kernel> &nef_polyhedron) {
|
||||
if (nef_polyhedron.is_simple()) {
|
||||
try {
|
||||
CGAL::Polyhedron_3<Kernel> polyhedron;
|
||||
nef_polyhedron.convert_to_polyhedron(polyhedron);
|
||||
return polyhedron;
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Conversion from Nef to polyhedron failed!");
|
||||
return CGAL::Polyhedron_3<Kernel>();
|
||||
}
|
||||
} else {
|
||||
Logger::Message(Logger::LOG_ERROR, "Nef polyhedron not simple: cannot create polyhedron!");
|
||||
return CGAL::Polyhedron_3<Kernel>();
|
||||
}
|
||||
|
||||
cgal_placement_t trsf2d;
|
||||
bool has_position = true;
|
||||
#ifdef USE_IFC4
|
||||
has_position = l->hasPosition();
|
||||
#endif
|
||||
if (has_position) {
|
||||
IfcGeom::CgalKernel::convert(l->Position(), trsf2d);
|
||||
}
|
||||
|
||||
face = cgal_face_t();
|
||||
face.outer.push_back(Kernel_::Point_3(-x, -y, 0.0));
|
||||
face.outer.push_back(Kernel_::Point_3( x, -y, 0.0));
|
||||
face.outer.push_back(Kernel_::Point_3( x, y, 0.0));
|
||||
face.outer.push_back(Kernel_::Point_3(-x, y, 0.0));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CGAL::Nef_polyhedron_3<Kernel> IfcGeom::CgalKernel::create_nef_polyhedron(std::list<cgal_face_t> &face_list) {
|
||||
CGAL::Polyhedron_3<Kernel> polyhedron = create_polyhedron(face_list);
|
||||
CGAL::Polygon_mesh_processing::triangulate_faces(polyhedron);
|
||||
CGAL::Nef_polyhedron_3<Kernel> nef_polyhedron;
|
||||
try {
|
||||
nef_polyhedron = CGAL::Nef_polyhedron_3<Kernel>(polyhedron);
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Conversion to Nef polyhedron failed!");
|
||||
return nef_polyhedron;
|
||||
} return nef_polyhedron;
|
||||
}
|
||||
|
||||
CGAL::Nef_polyhedron_3<Kernel> IfcGeom::CgalKernel::create_nef_polyhedron(CGAL::Polyhedron_3<Kernel> &polyhedron) {
|
||||
if (polyhedron.is_valid()) {
|
||||
CGAL::Polygon_mesh_processing::triangulate_faces(polyhedron);
|
||||
CGAL::Nef_polyhedron_3<Kernel> nef_polyhedron;
|
||||
try {
|
||||
nef_polyhedron = CGAL::Nef_polyhedron_3<Kernel>(polyhedron);
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Conversion to Nef polyhedron failed!");
|
||||
return nef_polyhedron;
|
||||
} return nef_polyhedron;
|
||||
} else {
|
||||
Logger::Message(Logger::LOG_ERROR, "Polyhedron not valid: cannot create Nef polyhedron!");
|
||||
return CGAL::Nef_polyhedron_3<Kernel>();
|
||||
}
|
||||
}
|
||||
|
||||
//CGAL::Polyhedron_3<Kernel> IfcGeom::CgalKernel::triangulate_faces(CGAL::Polyhedron_3<Kernel> &polyhedron) {
|
||||
// std::list<cgal_face_t> face_list;
|
||||
//
|
||||
// for (CGAL::Polyhedron_3<Kernel>::Facet_const_iterator current_facet = polyhedron.facets_begin();
|
||||
// current_facet != polyhedron.facets_end();
|
||||
// ++current_facet) {
|
||||
//
|
||||
// // Triangle
|
||||
// if (current_facet->is_triangle()) {
|
||||
// face_list.push_back(cgal_face_t());
|
||||
// CGAL::Polyhedron_3<Kernel>::Halfedge_around_facet_const_circulator current_halfedge = current_facet->facet_begin();
|
||||
// do {
|
||||
// face_list.back().outer.push_back(current_halfedge->vertex()->point());
|
||||
// ++current_halfedge;
|
||||
// } while (current_halfedge != current_facet->facet_begin());
|
||||
// }
|
||||
//
|
||||
// // Polygon
|
||||
// else {
|
||||
// std::list<Kernel::Point_3> points_in_polygon;
|
||||
//
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return create_polyhedron(face_list);
|
||||
//}
|
||||
|
||||
@@ -17,27 +17,28 @@
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "../../../ifcgeom/IfcGeomShapeType.h"
|
||||
#include "../../../ifcgeom/IfcGeom.h"
|
||||
|
||||
#include "CgalKernel.h"
|
||||
#include "CgalConversionResult.h"
|
||||
|
||||
#define CgalKernel MAKE_TYPE_NAME(CgalKernel)
|
||||
|
||||
// @todo two distinct uses of the word Kernel is getting confusing
|
||||
typedef Kernel Kernel_;
|
||||
|
||||
using namespace IfcSchema;
|
||||
using namespace IfcUtil;
|
||||
|
||||
|
||||
bool IfcGeom::CgalKernel::convert_shapes(const IfcBaseClass* l, ConversionResults& r) {
|
||||
if (shape_type(l) != ST_SHAPELIST) {
|
||||
cgal_shape_t shp;
|
||||
if (convert_shape(l, shp)) {
|
||||
r.push_back(IfcGeom::ConversionResult(l->data().id(), new CgalShape(shp)));
|
||||
r.push_back(IfcGeom::ConversionResult(new CgalShape(shp), get_style(l->as<IfcSchema::IfcRepresentationItem>())));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#include "CgalEntityMappingShapes.h"
|
||||
Logger::Message(Logger::LOG_ERROR,"No operation defined for:", l);
|
||||
Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -47,7 +48,7 @@ IfcGeom::ShapeType IfcGeom::CgalKernel::shape_type(const IfcBaseClass* l) {
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert_shape(const IfcBaseClass* l, cgal_shape_t& r) {
|
||||
const unsigned int id = l->data().id();
|
||||
const unsigned int id = l->entity->id();
|
||||
bool success = false;
|
||||
bool processed = false;
|
||||
bool ignored = false;
|
||||
@@ -75,186 +76,25 @@ bool IfcGeom::CgalKernel::convert_shape(const IfcBaseClass* l, cgal_shape_t& r)
|
||||
const char* const msg = processed
|
||||
? "Failed to convert:"
|
||||
: "No operation defined for:";
|
||||
Logger::Message(Logger::LOG_ERROR, msg, l);
|
||||
Logger::Message(Logger::LOG_ERROR, msg, l->entity);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, ConversionResults& shape) {
|
||||
cgal_shape_t s;
|
||||
const SurfaceStyle* collective_style = get_style(l);
|
||||
if (convert_shape(l->Outer(),s) ) {
|
||||
const SurfaceStyle* indiv_style = get_style(l->Outer());
|
||||
|
||||
IfcSchema::IfcClosedShell::list::ptr voids(new IfcSchema::IfcClosedShell::list);
|
||||
if (l->as<IfcSchema::IfcFacetedBrepWithVoids>()) {
|
||||
voids = l->as<IfcSchema::IfcFacetedBrepWithVoids>()->Voids();
|
||||
}
|
||||
#ifdef USE_IFC4
|
||||
if (l->as<IfcSchema::IfcAdvancedBrepWithVoids>()) {
|
||||
voids = l->as<IfcSchema::IfcAdvancedBrepWithVoids>()->Voids();
|
||||
}
|
||||
#endif
|
||||
|
||||
for (IfcSchema::IfcClosedShell::list::it it = voids->begin(); it != voids->end(); ++it) {
|
||||
// TopoDS_Shape s2;
|
||||
// /// @todo No extensive shapefixing since shells should be disjoint.
|
||||
// /// @todo Awaiting generalized boolean ops module with appropriate checking
|
||||
// if (convert_shape(l->Outer(), s2)) {
|
||||
// s = BRepAlgoAPI_Cut(s, s2).Shape();
|
||||
// }
|
||||
}
|
||||
|
||||
shape.push_back(ConversionResult(l->data().id(), new CgalShape(s), indiv_style ? indiv_style : collective_style));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_shape_t& shape) {
|
||||
IfcSchema::IfcFace::list::ptr faces = l->CfsFaces();
|
||||
|
||||
std::list<cgal_face_t> face_list;
|
||||
for (IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++it) {
|
||||
bool success = false;
|
||||
cgal_face_t face;
|
||||
|
||||
try {
|
||||
success = convert_face(*it, face);
|
||||
} catch (...) {}
|
||||
|
||||
if (!success) {
|
||||
Logger::Message(Logger::LOG_WARNING, "Failed to convert face:", *it);
|
||||
continue;
|
||||
}
|
||||
|
||||
// std::cout << "Face in ConnectedFaceSet: " << std::endl;
|
||||
// for (auto &point: face.outer) {
|
||||
// std::cout << "\tPoint(" << point << ")" << std::endl;
|
||||
// }
|
||||
|
||||
face_list.push_back(face);
|
||||
}
|
||||
|
||||
// Naive creation
|
||||
cgal_shape_t polyhedron = CGAL::Polyhedron_3<Kernel_>();
|
||||
PolyhedronBuilder builder(&face_list);
|
||||
polyhedron.delegate(builder);
|
||||
|
||||
// Stitch edges
|
||||
// std::cout << "Before: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl;
|
||||
CGAL::Polygon_mesh_processing::stitch_borders(polyhedron);
|
||||
if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) {
|
||||
CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron);
|
||||
}
|
||||
// std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl;
|
||||
|
||||
shape = polyhedron;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert_wire(const IfcBaseClass* l, cgal_wire_t& r) {
|
||||
#include "CgalEntityMappingWire.h"
|
||||
Logger::Message(Logger::LOG_ERROR,"No operation defined for:", l);
|
||||
Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert_face(const IfcBaseClass* l, cgal_face_t& r) {
|
||||
#include "CgalEntityMappingFace.h"
|
||||
Logger::Message(Logger::LOG_ERROR,"No operation defined for:", l);
|
||||
Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcFace* l, cgal_face_t& face) {
|
||||
IfcSchema::IfcFaceBound::list::ptr bounds = l->Bounds();
|
||||
|
||||
int num_outer_bounds = 0;
|
||||
|
||||
for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) {
|
||||
IfcSchema::IfcFaceBound* bound = *it;
|
||||
if (bound->as<IfcSchema::IfcFaceOuterBound>()) num_outer_bounds ++;
|
||||
}
|
||||
|
||||
if (num_outer_bounds != 1) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Invalid configuration of boundaries for:", l);
|
||||
return false;
|
||||
}
|
||||
|
||||
cgal_face_t mf;
|
||||
|
||||
for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) {
|
||||
IfcSchema::IfcFaceBound* bound = *it;
|
||||
IfcSchema::IfcLoop* loop = bound->Bound();
|
||||
|
||||
const bool is_interior = !bound->as<IfcSchema::IfcFaceOuterBound>();
|
||||
|
||||
cgal_wire_t wire;
|
||||
if (!convert_wire(loop, wire)) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary loop", loop);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_interior) {
|
||||
mf.outer = wire;
|
||||
} else {
|
||||
mf.inner.push_back(wire);
|
||||
}
|
||||
}
|
||||
|
||||
face = mf;
|
||||
|
||||
// std::cout << "Face: " << std::endl;
|
||||
// for (auto &point: face.outer) {
|
||||
// std::cout << "\tPoint(" << point << ")" << std::endl;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& result) {
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points = l->Polygon();
|
||||
|
||||
// Parse and store the points in a sequence
|
||||
cgal_wire_t polygon = std::vector<Kernel_::Point_3>();
|
||||
for(IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it) {
|
||||
cgal_point_t pnt;
|
||||
IfcGeom::CgalKernel::convert(*it, pnt);
|
||||
polygon.push_back(pnt);
|
||||
}
|
||||
|
||||
// A loop should consist of at least three vertices
|
||||
std::size_t original_count = polygon.size();
|
||||
if (original_count < 3) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l);
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Remove repeated points (and points that are too close to one another?)
|
||||
// remove_duplicate_points_from_loop(polygon, true);
|
||||
|
||||
std::size_t count = polygon.size();
|
||||
if (original_count - count != 0) {
|
||||
std::stringstream ss; ss << (original_count - count) << " edges removed for:";
|
||||
Logger::Message(Logger::LOG_WARNING, ss.str(), l);
|
||||
}
|
||||
|
||||
if (count < 3) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l);
|
||||
return false;
|
||||
}
|
||||
|
||||
result = polygon;
|
||||
|
||||
// std::cout << "PolyLoop: " << std::endl;
|
||||
// for (auto &point: polygon) {
|
||||
// std::cout << "\tPoint(" << point << ")" << std::endl;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert_curve(const IfcBaseClass* l, cgal_curve_t& r) {
|
||||
#include "CgalEntityMappingCurve.h"
|
||||
Logger::Message(Logger::LOG_ERROR,"No operation defined for:", l);
|
||||
Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -27,23 +27,95 @@
|
||||
|
||||
#include "../../../ifcparse/IfcParse.h"
|
||||
|
||||
SHAPES(IfcShellBasedSurfaceModel);
|
||||
SHAPES(IfcFaceBasedSurfaceModel);
|
||||
SHAPES(IfcRepresentation);
|
||||
SHAPES(IfcMappedItem);
|
||||
// IfcFacetedBrep included
|
||||
// IfcAdvancedBrep included
|
||||
// IfcFacetedBrepWithVoids included
|
||||
// IfcAdvancedBrepWithVoids included
|
||||
SHAPES(IfcManifoldSolidBrep);
|
||||
SHAPES(IfcGeometricSet);
|
||||
|
||||
#ifdef USE_IFC4
|
||||
//SHAPE(IfcCylindricalSurface);
|
||||
//SHAPE(IfcAdvancedBrep);
|
||||
//SHAPE(IfcBSplineSurfaceWithKnots);
|
||||
SHAPE(IfcTriangulatedFaceSet);
|
||||
SHAPE(IfcExtrudedAreaSolidTapered);
|
||||
#endif
|
||||
//SHAPE(IfcPlane);
|
||||
SHAPE(IfcExtrudedAreaSolid);
|
||||
//SHAPE(IfcRevolvedAreaSolid);
|
||||
SHAPE(IfcConnectedFaceSet);
|
||||
SHAPE(IfcBooleanResult);
|
||||
//SHAPE(IfcPolygonalBoundedHalfSpace);
|
||||
SHAPE(IfcHalfSpaceSolid);
|
||||
//SHAPE(IfcSurfaceOfLinearExtrusion);
|
||||
//SHAPE(IfcSurfaceOfRevolution);
|
||||
SHAPE(IfcBlock);
|
||||
SHAPE(IfcRectangularPyramid);
|
||||
SHAPE(IfcRightCircularCylinder);
|
||||
SHAPE(IfcRightCircularCone);
|
||||
SHAPE(IfcSphere);
|
||||
SHAPE(IfcCsgSolid);
|
||||
//SHAPE(IfcCurveBoundedPlane);
|
||||
//SHAPE(IfcRectangularTrimmedSurface);
|
||||
//SHAPE(IfcSurfaceCurveSweptAreaSolid);
|
||||
//SHAPE(IfcSweptDiskSolid);
|
||||
|
||||
FACE(IfcFace);
|
||||
FACE(IfcArbitraryProfileDefWithVoids);
|
||||
FACE(IfcArbitraryClosedProfileDef);
|
||||
FACE(IfcRoundedRectangleProfileDef);
|
||||
FACE(IfcRectangleHollowProfileDef);
|
||||
FACE(IfcRectangleProfileDef);
|
||||
FACE(IfcTrapeziumProfileDef)
|
||||
FACE(IfcCShapeProfileDef);
|
||||
// IfcAsymmetricIShapeProfileDef included
|
||||
FACE(IfcIShapeProfileDef);
|
||||
FACE(IfcLShapeProfileDef);
|
||||
FACE(IfcTShapeProfileDef);
|
||||
FACE(IfcUShapeProfileDef);
|
||||
FACE(IfcZShapeProfileDef);
|
||||
FACE(IfcCircleHollowProfileDef);
|
||||
FACE(IfcCircleProfileDef);
|
||||
FACE(IfcEllipseProfileDef);
|
||||
//FACE(IfcCenterLineProfileDef);
|
||||
//FACE(IfcCompositeProfileDef);
|
||||
FACE(IfcDerivedProfileDef);
|
||||
// IfcFaceSurface included
|
||||
// IfcAdvancedFace included in case of IFC4
|
||||
FACE(IfcFace);
|
||||
|
||||
//WIRE(IfcEdgeCurve);
|
||||
//WIRE(IfcSubedge);
|
||||
WIRE(IfcOrientedEdge);
|
||||
WIRE(IfcEdge);
|
||||
WIRE(IfcEdgeLoop);
|
||||
WIRE(IfcPolyline);
|
||||
WIRE(IfcPolyLoop);
|
||||
WIRE(IfcCompositeCurve);
|
||||
WIRE(IfcTrimmedCurve);
|
||||
//WIRE(IfcArbitraryOpenProfileDef);
|
||||
|
||||
CURVE(IfcCircle);
|
||||
CURVE(IfcEllipse);
|
||||
CURVE(IfcLine);
|
||||
#ifdef USE_IFC4
|
||||
// IfcRationalBSplineCurveWithKnots included
|
||||
//CURVE(IfcBSplineCurveWithKnots);
|
||||
#endif
|
||||
|
||||
CLASS(IfcCartesianPoint,cgal_point_t);
|
||||
CLASS(IfcDirection,cgal_direction_t);
|
||||
CLASS(IfcAxis2Placement2D,cgal_placement_t);
|
||||
CLASS(IfcAxis2Placement3D,cgal_placement_t);
|
||||
CLASS(IfcAxis1Placement,cgal_placement_t);
|
||||
CLASS(IfcCartesianTransformationOperator2DnonUniform,cgal_placement_t);
|
||||
CLASS(IfcCartesianTransformationOperator3DnonUniform,cgal_placement_t);
|
||||
CLASS(IfcCartesianTransformationOperator2D,cgal_placement_t);
|
||||
CLASS(IfcCartesianTransformationOperator3D,cgal_placement_t);
|
||||
CLASS(IfcObjectPlacement,cgal_placement_t);
|
||||
CLASS(IfcVector,cgal_vector_t);
|
||||
CLASS(IfcPlane,cgal_plane_t);
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
#include "CgalKernel.h"
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCircle* l, cgal_curve_t& curve) {
|
||||
const double r = l->Radius() * getValue(GV_LENGTH_UNIT);
|
||||
if ( r < ALMOST_ZERO ) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Radius not greater than zero for:", l->entity);
|
||||
return false;
|
||||
}
|
||||
cgal_placement_t trsf;
|
||||
IfcSchema::IfcAxis2Placement* placement = l->Position();
|
||||
if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) {
|
||||
IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf);
|
||||
} else {
|
||||
cgal_placement_t trsf2d;
|
||||
IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf2d);
|
||||
trsf = trsf2d;
|
||||
}
|
||||
|
||||
const int segments = 12;
|
||||
|
||||
curve = cgal_curve_t();
|
||||
for (int current_segment = 0; current_segment < segments; ++current_segment) {
|
||||
double current_angle = current_segment*2.0*3.141592653589793/((double)segments);
|
||||
curve.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0));
|
||||
}
|
||||
|
||||
for (auto &vertex: curve) {
|
||||
vertex = vertex.transform(trsf);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcEllipse* l, cgal_curve_t& curve) {
|
||||
double x = l->SemiAxis1() * getValue(GV_LENGTH_UNIT);
|
||||
double y = l->SemiAxis2() * getValue(GV_LENGTH_UNIT);
|
||||
if (x < ALMOST_ZERO || y < ALMOST_ZERO) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Radius not greater than zero for:", l->entity);
|
||||
return false;
|
||||
}
|
||||
cgal_placement_t trsf;
|
||||
IfcSchema::IfcAxis2Placement* placement = l->Position();
|
||||
if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) {
|
||||
convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf);
|
||||
} else {
|
||||
cgal_placement_t trsf2d;
|
||||
convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf2d);
|
||||
trsf = trsf2d;
|
||||
}
|
||||
|
||||
const int segments = 12;
|
||||
|
||||
curve = cgal_curve_t();
|
||||
for (int current_segment = 0; current_segment < segments; ++current_segment) {
|
||||
double current_angle = current_segment*2.0*3.141592653589793/((double)segments);
|
||||
curve.push_back(Kernel::Point_3(x*cos(current_angle), y*sin(current_angle), 0));
|
||||
}
|
||||
|
||||
for (auto &vertex: curve) {
|
||||
vertex = vertex.transform(trsf);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcLine* l, cgal_curve_t& curve) {
|
||||
cgal_point_t pnt;
|
||||
cgal_direction_t vec;
|
||||
convert(l->Pnt(),pnt);
|
||||
convert(l->Dir(),vec);
|
||||
curve = cgal_curve_t();
|
||||
curve.push_back(pnt);
|
||||
curve.push_back(pnt+vec);
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,988 @@
|
||||
#include "CgalKernel.h"
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcArbitraryClosedProfileDef* l, cgal_face_t& face) {
|
||||
cgal_wire_t wire;
|
||||
if ( ! convert_wire(l->OuterCurve(),wire) ) return false;
|
||||
|
||||
cgal_face_t f;
|
||||
bool success = convert_wire_to_face(wire, f);
|
||||
if (success) face = f;
|
||||
return success;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcArbitraryProfileDefWithVoids* l, cgal_face_t& face) {
|
||||
cgal_wire_t profile;
|
||||
if ( ! convert_wire(l->OuterCurve(),profile) ) return false;
|
||||
cgal_face_t mf;
|
||||
mf.outer = profile;
|
||||
IfcSchema::IfcCurve::list::ptr voids = l->InnerCurves();
|
||||
for( IfcSchema::IfcCurve::list::it it = voids->begin(); it != voids->end(); ++ it ) {
|
||||
cgal_wire_t hole;
|
||||
if ( convert_wire(*it,hole) ) {
|
||||
mf.inner.push_back(hole);
|
||||
}
|
||||
} face = mf;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangleProfileDef* l, cgal_face_t& face) {
|
||||
const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
|
||||
if ( x < ALMOST_ZERO || y < ALMOST_ZERO ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
cgal_placement_t trsf2d;
|
||||
bool has_position = true;
|
||||
#ifdef USE_IFC4
|
||||
has_position = l->hasPosition();
|
||||
#endif
|
||||
|
||||
face = cgal_face_t();
|
||||
face.outer.push_back(Kernel::Point_3(-x, -y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3( x, -y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3( x, y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(-x, y, 0.0));
|
||||
|
||||
if (has_position) {
|
||||
IfcGeom::CgalKernel::convert(l->Position(), trsf2d);
|
||||
for (auto &vertex: face.outer) {
|
||||
vertex = vertex.transform(trsf2d);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef* l, cgal_face_t& face) {
|
||||
const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double r = l->RoundingRadius() * getValue(GV_LENGTH_UNIT);
|
||||
|
||||
if ( x < ALMOST_ZERO || y < ALMOST_ZERO || r < ALMOST_ZERO ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
cgal_placement_t trsf2d;
|
||||
bool has_position = true;
|
||||
#ifdef USE_IFC4
|
||||
has_position = l->hasPosition();
|
||||
#endif
|
||||
|
||||
const int segments = 3;
|
||||
|
||||
if (r == 0.0) {
|
||||
face = cgal_face_t();
|
||||
face.outer.push_back(Kernel::Point_3(-x, -y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3( x, -y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3( x, y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(-x, y, 0.0));
|
||||
}
|
||||
|
||||
else {
|
||||
face = cgal_face_t();
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), y-r+r*sin(current_angle), 0));
|
||||
}
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(-x+r+r*cos(current_angle), y-r+r*sin(current_angle), 0));
|
||||
}
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(-x+r+r*cos(current_angle), -y+r+r*sin(current_angle), 0));
|
||||
}
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), -y+r+r*sin(current_angle), 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (has_position) {
|
||||
IfcGeom::CgalKernel::convert(l->Position(), trsf2d);
|
||||
for (auto &vertex: face.outer) {
|
||||
vertex = vertex.transform(trsf2d);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangleHollowProfileDef* l, cgal_face_t& face) {
|
||||
const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double d = l->WallThickness() * getValue(GV_LENGTH_UNIT);
|
||||
|
||||
const bool fr1 = l->hasOuterFilletRadius();
|
||||
const bool fr2 = l->hasInnerFilletRadius();
|
||||
|
||||
const double r1 = fr1 ? l->OuterFilletRadius() * getValue(GV_LENGTH_UNIT) : 0.;
|
||||
const double r2 = fr2 ? l->InnerFilletRadius() * getValue(GV_LENGTH_UNIT) : 0.;
|
||||
|
||||
if ( x < ALMOST_ZERO || y < ALMOST_ZERO ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
cgal_placement_t trsf2d;
|
||||
bool has_position = true;
|
||||
#ifdef USE_IFC4
|
||||
has_position = l->hasPosition();
|
||||
#endif
|
||||
|
||||
const int segments = 3;
|
||||
|
||||
if (!fr1 || r1 == 0.0) {
|
||||
face = cgal_face_t();
|
||||
face.outer.push_back(Kernel::Point_3(-x, -y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3( x, -y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3( x, y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(-x, y, 0.0));
|
||||
}
|
||||
|
||||
else {
|
||||
face = cgal_face_t();
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(x-r1+r1*cos(current_angle), y-r1+r1*sin(current_angle), 0));
|
||||
}
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(-x+r1+r1*cos(current_angle), y-r1+r1*sin(current_angle), 0));
|
||||
}
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(-x+r1+r1*cos(current_angle), -y+r1+r1*sin(current_angle), 0));
|
||||
}
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(x-r1+r1*cos(current_angle), -y+r1+r1*sin(current_angle), 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (!fr2 || r2 == 0.0) {
|
||||
face.inner.push_back(cgal_wire_t());
|
||||
face.inner.back().push_back(Kernel::Point_3(-x+d, -y+d, 0.0));
|
||||
face.inner.back().push_back(Kernel::Point_3( x-d, -y+d, 0.0));
|
||||
face.inner.back().push_back(Kernel::Point_3( x-d, y-d, 0.0));
|
||||
face.inner.back().push_back(Kernel::Point_3(-x+d, y-d, 0.0));
|
||||
}
|
||||
|
||||
else {
|
||||
face.inner.push_back(cgal_wire_t());
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.inner.back().push_back(Kernel::Point_3(x-d-r1+r1*cos(current_angle), y-d-r1+r1*sin(current_angle), 0));
|
||||
}
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.inner.back().push_back(Kernel::Point_3(-x+d+r1+r1*cos(current_angle), y-d-r1+r1*sin(current_angle), 0));
|
||||
}
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.inner.back().push_back(Kernel::Point_3(-x+d+r1+r1*cos(current_angle), -y+d+r1+r1*sin(current_angle), 0));
|
||||
}
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.inner.back().push_back(Kernel::Point_3(x-d-r1+r1*cos(current_angle), -y+d+r1+r1*sin(current_angle), 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (has_position) {
|
||||
IfcGeom::CgalKernel::convert(l->Position(), trsf2d);
|
||||
for (auto &vertex: face.outer) {
|
||||
vertex = vertex.transform(trsf2d);
|
||||
} for (auto &inner: face.inner) {
|
||||
for (auto &vertex: inner) {
|
||||
vertex = vertex.transform(trsf2d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTrapeziumProfileDef* l, cgal_face_t& face) {
|
||||
const double x1 = l->BottomXDim() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double w = l->TopXDim() * getValue(GV_LENGTH_UNIT);
|
||||
const double dx = l->TopXOffset() * getValue(GV_LENGTH_UNIT);
|
||||
const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
|
||||
if ( x1 < ALMOST_ZERO || w < ALMOST_ZERO || y < ALMOST_ZERO ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
cgal_placement_t trsf2d;
|
||||
bool has_position = true;
|
||||
#ifdef USE_IFC4
|
||||
has_position = l->hasPosition();
|
||||
#endif
|
||||
|
||||
face = cgal_face_t();
|
||||
face.outer.push_back(Kernel::Point_3(-x1, -y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(x1, -y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(dx+w-x1, y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(dx-x1, y, 0.0));
|
||||
|
||||
if (has_position) {
|
||||
IfcGeom::CgalKernel::convert(l->Position(), trsf2d);
|
||||
for (auto &vertex: face.outer) {
|
||||
vertex = vertex.transform(trsf2d);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCircleProfileDef* l, cgal_face_t& face) {
|
||||
const double r = l->Radius() * getValue(GV_LENGTH_UNIT);
|
||||
if ( r == 0.0f ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
cgal_placement_t trsf2d;
|
||||
bool has_position = true;
|
||||
#ifdef USE_IFC4
|
||||
has_position = l->hasPosition();
|
||||
#endif
|
||||
|
||||
const int segments = 12;
|
||||
|
||||
face = cgal_face_t();
|
||||
for (int current_segment = 0; current_segment < segments; ++current_segment) {
|
||||
double current_angle = current_segment*2.0*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0));
|
||||
}
|
||||
|
||||
if (has_position) {
|
||||
IfcGeom::CgalKernel::convert(l->Position(), trsf2d);
|
||||
for (auto &vertex: face.outer) {
|
||||
vertex = vertex.transform(trsf2d);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCircleHollowProfileDef* l, cgal_face_t& face) {
|
||||
const double r = l->Radius() * getValue(GV_LENGTH_UNIT);
|
||||
const double t = l->WallThickness() * getValue(GV_LENGTH_UNIT);
|
||||
|
||||
if ( r == 0.0f || t == 0.0f ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
cgal_placement_t trsf2d;
|
||||
bool has_position = true;
|
||||
#ifdef USE_IFC4
|
||||
has_position = l->hasPosition();
|
||||
#endif
|
||||
|
||||
const int segments = 12;
|
||||
|
||||
face = cgal_face_t();
|
||||
for (int current_segment = 0; current_segment < segments; ++current_segment) {
|
||||
double current_angle = current_segment*2.0*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0));
|
||||
}
|
||||
|
||||
face.inner.push_back(cgal_wire_t());
|
||||
for (int current_segment = 0; current_segment < segments; ++current_segment) {
|
||||
double current_angle = current_segment*2.0*3.141592653589793/((double)segments);
|
||||
face.inner.back().push_back(Kernel::Point_3((r-t)*cos(current_angle), (r-t)*sin(current_angle), 0));
|
||||
}
|
||||
|
||||
if (has_position) {
|
||||
IfcGeom::CgalKernel::convert(l->Position(), trsf2d);
|
||||
for (auto &vertex: face.outer) {
|
||||
vertex = vertex.transform(trsf2d);
|
||||
} for (auto &inner: face.inner) {
|
||||
for (auto &vertex: inner) {
|
||||
vertex = vertex.transform(trsf2d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcEllipseProfileDef* l, cgal_face_t& face) {
|
||||
double rx = l->SemiAxis1() * getValue(GV_LENGTH_UNIT);
|
||||
double ry = l->SemiAxis2() * getValue(GV_LENGTH_UNIT);
|
||||
|
||||
if ( rx < ALMOST_ZERO || ry < ALMOST_ZERO ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
cgal_placement_t trsf2d;
|
||||
bool has_position = true;
|
||||
#ifdef USE_IFC4
|
||||
has_position = l->hasPosition();
|
||||
#endif
|
||||
|
||||
const int segments = 12;
|
||||
|
||||
face = cgal_face_t();
|
||||
for (int current_segment = 0; current_segment < segments; ++current_segment) {
|
||||
double current_angle = current_segment*2.0*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(rx*cos(current_angle), ry*sin(current_angle), 0));
|
||||
}
|
||||
|
||||
if (has_position) {
|
||||
IfcGeom::CgalKernel::convert(l->Position(), trsf2d);
|
||||
for (auto &vertex: face.outer) {
|
||||
vertex = vertex.transform(trsf2d);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcFace* l, cgal_face_t& face) {
|
||||
IfcSchema::IfcFaceBound::list::ptr bounds = l->Bounds();
|
||||
|
||||
int num_outer_bounds = 0;
|
||||
|
||||
for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) {
|
||||
IfcSchema::IfcFaceBound* bound = *it;
|
||||
if (bound->is(IfcSchema::Type::IfcFaceOuterBound)) num_outer_bounds ++;
|
||||
}
|
||||
|
||||
if (num_outer_bounds != 1) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Invalid configuration of boundaries for:", l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
cgal_face_t mf;
|
||||
|
||||
for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) {
|
||||
IfcSchema::IfcFaceBound* bound = *it;
|
||||
IfcSchema::IfcLoop* loop = bound->Bound();
|
||||
|
||||
const bool is_interior = !bound->is(IfcSchema::Type::IfcFaceOuterBound);
|
||||
|
||||
cgal_wire_t wire;
|
||||
if (!convert_wire(loop, wire)) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary loop", loop->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_interior) {
|
||||
mf.outer = wire;
|
||||
} else {
|
||||
mf.inner.push_back(wire);
|
||||
}
|
||||
}
|
||||
|
||||
face = mf;
|
||||
|
||||
// std::cout << "Face: " << std::endl;
|
||||
// for (auto &point: face.outer) {
|
||||
// std::cout << "\tPoint(" << point << ")" << std::endl;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCShapeProfileDef* l, cgal_face_t& face) {
|
||||
const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double x = l->Width() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double d1 = l->WallThickness() * getValue(GV_LENGTH_UNIT);
|
||||
const double d2 = l->Girth() * getValue(GV_LENGTH_UNIT);
|
||||
bool doFillet = l->hasInternalFilletRadius();
|
||||
double f1 = 0;
|
||||
double f2 = 0;
|
||||
if ( doFillet ) {
|
||||
f1 = l->InternalFilletRadius() * getValue(GV_LENGTH_UNIT);
|
||||
f2 = f1 + d1;
|
||||
}
|
||||
|
||||
if ( x < ALMOST_ZERO || y < ALMOST_ZERO || d1 < ALMOST_ZERO || d2 < ALMOST_ZERO ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
cgal_placement_t trsf2d;
|
||||
bool has_position = true;
|
||||
#ifdef USE_IFC4
|
||||
has_position = l->hasPosition();
|
||||
#endif
|
||||
|
||||
const int segments = 3;
|
||||
|
||||
if (!doFillet || f1 == 0.0) {
|
||||
face = cgal_face_t();
|
||||
face.outer.push_back(Kernel::Point_3(-x, -y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(x, -y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(x, -y+d2, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(x-d1, -y+d2, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(x-d1, -y+d1, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(-x+d1, -y+d1, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(-x+d1, y-d1, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(x-d1, y-d1, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(x-d1, y-d2, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(x, y-d2, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(x, y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(-x, y, 0.0));
|
||||
}
|
||||
|
||||
else {
|
||||
face = cgal_face_t();
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(-x+f2+f2*cos(current_angle), -y+f2+f2*sin(current_angle), 0));
|
||||
}
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(x-f2+f2*cos(current_angle), -y+f2+f2*sin(current_angle), 0));
|
||||
}
|
||||
face.outer.push_back(Kernel::Point_3(x, -y+d2, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(x-d1, -y+d2, 0.0));
|
||||
for (int current_segment = segments; current_segment >= 0; --current_segment) {
|
||||
double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(x-f2+f1*cos(current_angle), -y+f2+f1*sin(current_angle), 0));
|
||||
}
|
||||
for (int current_segment = segments; current_segment >= 0; --current_segment) {
|
||||
double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(-x+f2+f1*cos(current_angle), -y+f2+f1*sin(current_angle), 0));
|
||||
}
|
||||
for (int current_segment = segments; current_segment >= 0; --current_segment) {
|
||||
double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(-x+f2+f1*cos(current_angle), y-f2+f1*sin(current_angle), 0));
|
||||
}
|
||||
for (int current_segment = segments; current_segment >= 0; --current_segment) {
|
||||
double current_angle = current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(x-f2+f1*cos(current_angle), y-f2+f1*sin(current_angle), 0));
|
||||
}
|
||||
face.outer.push_back(Kernel::Point_3(x-d1, y-d2, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(x, y-d2, 0.0));
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(x-f2+f2*cos(current_angle), y-f2+f2*sin(current_angle), 0));
|
||||
}
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(-x+f2+f2*cos(current_angle), y-f2+f2*sin(current_angle), 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (has_position) {
|
||||
IfcGeom::CgalKernel::convert(l->Position(), trsf2d);
|
||||
for (auto &vertex: face.outer) {
|
||||
vertex = vertex.transform(trsf2d);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcLShapeProfileDef* l, cgal_face_t& face) {
|
||||
const bool hasSlope = l->hasLegSlope();
|
||||
const bool doEdgeFillet = l->hasEdgeRadius();
|
||||
const bool doFillet = l->hasFilletRadius();
|
||||
|
||||
const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double x = (l->hasWidth() ? l->Width() : l->Depth()) / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double d = l->Thickness() * getValue(GV_LENGTH_UNIT);
|
||||
const double slope = hasSlope ? (l->LegSlope() * getValue(GV_PLANEANGLE_UNIT)) : 0.;
|
||||
|
||||
double f1 = 0.0f;
|
||||
double f2 = 0.0f;
|
||||
if (doFillet) {
|
||||
f1 = l->FilletRadius() * getValue(GV_LENGTH_UNIT);
|
||||
}
|
||||
if ( doEdgeFillet) {
|
||||
f2 = l->EdgeRadius() * getValue(GV_LENGTH_UNIT);
|
||||
}
|
||||
|
||||
if ( x < ALMOST_ZERO || y < ALMOST_ZERO || d < ALMOST_ZERO ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
double xx = -x+d;
|
||||
double xy = -y+d;
|
||||
double dy1 = 0.;
|
||||
double dy2 = 0.;
|
||||
double dx1 = 0.;
|
||||
double dx2 = 0.;
|
||||
if (hasSlope) {
|
||||
dy1 = tan(slope) * x;
|
||||
dy2 = tan(slope) * (x - d);
|
||||
dx1 = tan(slope) * y;
|
||||
dx2 = tan(slope) * (y - d);
|
||||
|
||||
const double x1s = x; const double y1s = -y + d - dy1;
|
||||
const double x1e = -x + d; const double y1e = -y + d + dy2;
|
||||
const double x2s = -x + d - dx1; const double y2s = y;
|
||||
const double x2e = -x + d + dx2; const double y2e = -y + d;
|
||||
|
||||
const double a1 = y1e - y1s;
|
||||
const double b1 = x1s - x1e;
|
||||
const double c1 = a1*x1s + b1*y1s;
|
||||
|
||||
const double a2 = y2e - y2s;
|
||||
const double b2 = x2s - x2e;
|
||||
const double c2 = a2*x2s + b2*y2s;
|
||||
|
||||
const double det = a1*b2 - a2*b1;
|
||||
|
||||
if (ALMOST_THE_SAME(det, 0.)) {
|
||||
Logger::Message(Logger::LOG_NOTICE, "Legs do not intersect for:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
xx = (b2*c1 - b1*c2) / det;
|
||||
xy = (a1*c2 - a2*c1) / det;
|
||||
}
|
||||
|
||||
cgal_placement_t trsf2d;
|
||||
bool has_position = true;
|
||||
#ifdef USE_IFC4
|
||||
has_position = l->hasPosition();
|
||||
#endif
|
||||
|
||||
const int segments = 3;
|
||||
|
||||
face = cgal_face_t();
|
||||
face.outer.push_back(Kernel::Point_3(-x, -y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(x, -y, 0.0));
|
||||
if (f2 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(x, -y+d-dy1, 0.0));
|
||||
} else {
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(x-f2+f2*cos(current_angle), -y+d-dy1-f2+f2*sin(current_angle), 0));
|
||||
}
|
||||
} if (f1 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(xx, xy, 0.0));
|
||||
} else {
|
||||
for (int current_segment = segments; current_segment >= 0; --current_segment) {
|
||||
double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(xx+f1+f1*cos(current_angle), xy+f1+f1*sin(current_angle), 0));
|
||||
}
|
||||
} if (f2 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(-x+d-dx1, y, 0.0));
|
||||
} else {
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(-x+d-dx1-f2+f2*cos(current_angle), y-f2+f2*sin(current_angle), 0));
|
||||
}
|
||||
} face.outer.push_back(Kernel::Point_3(-x, y, 0.0));
|
||||
|
||||
if (has_position) {
|
||||
IfcGeom::CgalKernel::convert(l->Position(), trsf2d);
|
||||
for (auto &vertex: face.outer) {
|
||||
vertex = vertex.transform(trsf2d);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Untested
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcIShapeProfileDef* l, cgal_face_t& face) {
|
||||
const double x1 = l->OverallWidth() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double y = l->OverallDepth() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double d1 = l->WebThickness() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double dy1 = l->FlangeThickness() * getValue(GV_LENGTH_UNIT);
|
||||
|
||||
bool doFillet1 = l->hasFilletRadius();
|
||||
double f1 = 0.;
|
||||
if ( doFillet1 ) {
|
||||
f1 = l->FilletRadius() * getValue(GV_LENGTH_UNIT);
|
||||
}
|
||||
|
||||
bool doFillet2 = doFillet1;
|
||||
double x2 = x1, dy2 = dy1, f2 = f1;
|
||||
|
||||
if (l->is(IfcSchema::Type::IfcAsymmetricIShapeProfileDef)) {
|
||||
IfcSchema::IfcAsymmetricIShapeProfileDef* assym = (IfcSchema::IfcAsymmetricIShapeProfileDef*) l;
|
||||
x2 = assym->TopFlangeWidth() / 2. * getValue(GV_LENGTH_UNIT);
|
||||
doFillet2 = assym->hasTopFlangeFilletRadius();
|
||||
if (doFillet2) {
|
||||
f2 = assym->TopFlangeFilletRadius() * getValue(GV_LENGTH_UNIT);
|
||||
}
|
||||
if (assym->hasTopFlangeThickness()) {
|
||||
dy2 = assym->TopFlangeThickness() * getValue(GV_LENGTH_UNIT);
|
||||
}
|
||||
}
|
||||
|
||||
if ( x1 < ALMOST_ZERO || x2 < ALMOST_ZERO || y < ALMOST_ZERO || d1 < ALMOST_ZERO || dy1 < ALMOST_ZERO || dy2 < ALMOST_ZERO ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
cgal_placement_t trsf2d;
|
||||
bool has_position = true;
|
||||
#ifdef USE_IFC4
|
||||
has_position = l->hasPosition();
|
||||
#endif
|
||||
|
||||
const int segments = 3;
|
||||
|
||||
face = cgal_face_t();
|
||||
face.outer.push_back(Kernel::Point_3(-x1, -y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(x1, -y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(x1, -y+dy1, 0.0));
|
||||
if (f1 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(d1, -y+dy1, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(d1, y-dy2, 0.0));
|
||||
} else {
|
||||
for (int current_segment = segments; current_segment >= 0; --current_segment) {
|
||||
double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(d1+f1+f1*cos(current_angle), -y+dy1+f1+f1*sin(current_angle), 0));
|
||||
} for (int current_segment = segments; current_segment >= 0; --current_segment) {
|
||||
double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(d1+f1+f1*cos(current_angle), y-dy2-f1+f1*sin(current_angle), 0));
|
||||
}
|
||||
} face.outer.push_back(Kernel::Point_3(x2, y-dy2, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(x2, y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(-x2, y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(-x2, y-dy2, 0.0));
|
||||
if (f2 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(-d1, y-dy2, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(-d1, -y+dy1, 0.0));
|
||||
} else {
|
||||
for (int current_segment = segments; current_segment >= 0; --current_segment) {
|
||||
double current_angle = current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(-d1-f2+f2*cos(current_angle), y-dy2-f2+f2*sin(current_angle), 0));
|
||||
} for (int current_segment = segments; current_segment >= 0; --current_segment) {
|
||||
double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(-d1-f2+f2*cos(current_angle), -y+dy1+f2+f2*sin(current_angle), 0));
|
||||
}
|
||||
} face.outer.push_back(Kernel::Point_3(-x1, -y+dy1, 0.0));
|
||||
|
||||
if (has_position) {
|
||||
IfcGeom::CgalKernel::convert(l->Position(), trsf2d);
|
||||
for (auto &vertex: face.outer) {
|
||||
vertex = vertex.transform(trsf2d);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTShapeProfileDef* l, cgal_face_t& face) {
|
||||
const bool doFlangeEdgeFillet = l->hasFlangeEdgeRadius();
|
||||
const bool doWebEdgeFillet = l->hasWebEdgeRadius();
|
||||
const bool doFillet = l->hasFilletRadius();
|
||||
const bool hasFlangeSlope = l->hasFlangeSlope();
|
||||
const bool hasWebSlope = l->hasWebSlope();
|
||||
|
||||
const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double x = l->FlangeWidth() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double d1 = l->WebThickness() * getValue(GV_LENGTH_UNIT);
|
||||
const double d2 = l->FlangeThickness() * getValue(GV_LENGTH_UNIT);
|
||||
const double flangeSlope = hasFlangeSlope ? (l->FlangeSlope() * getValue(GV_PLANEANGLE_UNIT)) : 0.;
|
||||
const double webSlope = hasWebSlope ? (l->WebSlope() * getValue(GV_PLANEANGLE_UNIT)) : 0.;
|
||||
|
||||
if ( x < ALMOST_ZERO || y < ALMOST_ZERO || d1 < ALMOST_ZERO || d2 < ALMOST_ZERO ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
double dy1 = 0.0f;
|
||||
double dy2 = 0.0f;
|
||||
double dx1 = 0.0f;
|
||||
double dx2 = 0.0f;
|
||||
double f1 = 0.0f;
|
||||
double f2 = 0.0f;
|
||||
double f3 = 0.0f;
|
||||
|
||||
if (doFillet) {
|
||||
f1 = l->FilletRadius() * getValue(GV_LENGTH_UNIT);
|
||||
}
|
||||
if (doWebEdgeFillet) {
|
||||
f2 = l->WebEdgeRadius() * getValue(GV_LENGTH_UNIT);
|
||||
}
|
||||
if (doFlangeEdgeFillet) {
|
||||
f3 = l->FlangeEdgeRadius() * getValue(GV_LENGTH_UNIT);
|
||||
}
|
||||
|
||||
double xx, xy;
|
||||
if (hasFlangeSlope) {
|
||||
dy1 = (x / 2. - d1) * tan(flangeSlope);
|
||||
dy2 = x / 2. * tan(flangeSlope);
|
||||
}
|
||||
if (hasWebSlope) {
|
||||
dx1 = (y - d2) * tan(webSlope);
|
||||
dx2 = y * tan(webSlope);
|
||||
}
|
||||
if (hasWebSlope || hasFlangeSlope) {
|
||||
const double x1s = d1/2. - dx2; const double y1s = -y;
|
||||
const double x1e = d1/2. + dx1; const double y1e = y - d2;
|
||||
const double x2s = x; const double y2s = y - d2 + dy2;
|
||||
const double x2e = d1/2.; const double y2e = y - d2 - dy1;
|
||||
|
||||
const double a1 = y1e - y1s;
|
||||
const double b1 = x1s - x1e;
|
||||
const double c1 = a1*x1s + b1*y1s;
|
||||
|
||||
const double a2 = y2e - y2s;
|
||||
const double b2 = x2s - x2e;
|
||||
const double c2 = a2*x2s + b2*y2s;
|
||||
|
||||
const double det = a1*b2 - a2*b1;
|
||||
|
||||
if (ALMOST_THE_SAME(det, 0.)) {
|
||||
Logger::Message(Logger::LOG_NOTICE, "Web and flange do not intersect for:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
xx = (b2*c1 - b1*c2) / det;
|
||||
xy = (a1*c2 - a2*c1) / det;
|
||||
} else {
|
||||
xx = d1 / 2;
|
||||
xy = y - d2;
|
||||
}
|
||||
|
||||
cgal_placement_t trsf2d;
|
||||
bool has_position = true;
|
||||
#ifdef USE_IFC4
|
||||
has_position = l->hasPosition();
|
||||
#endif
|
||||
|
||||
const int segments = 3;
|
||||
|
||||
face = cgal_face_t();
|
||||
if (f2 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(d1/2.-dx2, -y, 0.0));
|
||||
} else {
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(d1/2.-dx2-f2+f2*cos(current_angle), -y+f2+f2*sin(current_angle), 0));
|
||||
}
|
||||
} if (f1 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(xx, xy, 0.0));
|
||||
} else {
|
||||
for (int current_segment = segments; current_segment >= 0; --current_segment) {
|
||||
double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(xx+f1+f1*cos(current_angle), xy-f1+f1*sin(current_angle), 0));
|
||||
}
|
||||
} if (f3 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(x, y-d2+dy2, 0.0));
|
||||
} else {
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(x-f3+f3*cos(current_angle), y-d2+dy2+f3+f3*sin(current_angle), 0));
|
||||
}
|
||||
} face.outer.push_back(Kernel::Point_3(x, y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(-x, y, 0.0));
|
||||
if (f3 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(-x, y-d2+dy2, 0.0));
|
||||
} else {
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(-x+f3+f3*cos(current_angle), y-d2+dy2+f3+f3*sin(current_angle), 0));
|
||||
}
|
||||
} if (f1 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(-xx, xy, 0.0));
|
||||
} else {
|
||||
for (int current_segment = segments; current_segment >= 0; --current_segment) {
|
||||
double current_angle = current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(-xx-f1+f1*cos(current_angle), xy-f1+f1*sin(current_angle), 0));
|
||||
}
|
||||
} if (f2 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(-d1/2.+dx2, -y, 0.0));
|
||||
} else {
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(-d1/2.+dx2+f2+f2*cos(current_angle), -y+f2+f2*sin(current_angle), 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (has_position) {
|
||||
IfcGeom::CgalKernel::convert(l->Position(), trsf2d);
|
||||
for (auto &vertex: face.outer) {
|
||||
vertex = vertex.transform(trsf2d);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcUShapeProfileDef* l, cgal_face_t& face) {
|
||||
const bool doEdgeFillet = l->hasEdgeRadius();
|
||||
const bool doFillet = l->hasFilletRadius();
|
||||
const bool hasSlope = l->hasFlangeSlope();
|
||||
|
||||
const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double x = l->FlangeWidth() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double d1 = l->WebThickness() * getValue(GV_LENGTH_UNIT);
|
||||
const double d2 = l->FlangeThickness() * getValue(GV_LENGTH_UNIT);
|
||||
const double slope = hasSlope ? (l->FlangeSlope() * getValue(GV_PLANEANGLE_UNIT)) : 0.;
|
||||
|
||||
double dy1 = 0.0f;
|
||||
double dy2 = 0.0f;
|
||||
double f1 = 0.0f;
|
||||
double f2 = 0.0f;
|
||||
|
||||
if (doFillet) {
|
||||
f1 = l->FilletRadius() * getValue(GV_LENGTH_UNIT);
|
||||
}
|
||||
if (doEdgeFillet) {
|
||||
f2 = l->EdgeRadius() * getValue(GV_LENGTH_UNIT);
|
||||
}
|
||||
|
||||
if (hasSlope) {
|
||||
dy1 = (x - d1) * tan(slope);
|
||||
dy2 = x * tan(slope);
|
||||
}
|
||||
|
||||
if ( x < ALMOST_ZERO || y < ALMOST_ZERO || d1 < ALMOST_ZERO || d2 < ALMOST_ZERO ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
cgal_placement_t trsf2d;
|
||||
bool has_position = true;
|
||||
#ifdef USE_IFC4
|
||||
has_position = l->hasPosition();
|
||||
#endif
|
||||
|
||||
const int segments = 3;
|
||||
|
||||
face = cgal_face_t();
|
||||
face.outer.push_back(Kernel::Point_3(-x, -y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(x, -y, 0.0));
|
||||
if (f2 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(x, -y+d2-dy2, 0.0));
|
||||
} else {
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(x-f2+f2*cos(current_angle), -y+d2-dy2-f2+f2*sin(current_angle), 0));
|
||||
}
|
||||
} if (f1 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(-x+d1, -y+d2+dy1, 0.0));
|
||||
} else {
|
||||
for (int current_segment = segments; current_segment >= 0; --current_segment) {
|
||||
double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(-x+d1+f1+f1*cos(current_angle), -y+d2+dy1+f1+f1*sin(current_angle), 0));
|
||||
}
|
||||
} if (f1 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(-x+d1, y-d2-dy1, 0.0));
|
||||
} else {
|
||||
for (int current_segment = segments; current_segment >= 0; --current_segment) {
|
||||
double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(-x+d1+f1+f1*cos(current_angle), y-d2-dy1-f1+f1*sin(current_angle), 0));
|
||||
}
|
||||
} if (f2 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(x,y-d2+dy2, 0.0));
|
||||
} else {
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(x-f2+f2*cos(current_angle), y-d2+dy2+f2+f2*sin(current_angle), 0));
|
||||
}
|
||||
} face.outer.push_back(Kernel::Point_3(x,y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(-x,y, 0.0));
|
||||
|
||||
if (has_position) {
|
||||
IfcGeom::CgalKernel::convert(l->Position(), trsf2d);
|
||||
for (auto &vertex: face.outer) {
|
||||
vertex = vertex.transform(trsf2d);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcZShapeProfileDef* l, cgal_face_t& face) {
|
||||
const double x = l->FlangeWidth() * getValue(GV_LENGTH_UNIT);
|
||||
const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double dx = l->WebThickness() / 2.0f * getValue(GV_LENGTH_UNIT);
|
||||
const double dy = l->FlangeThickness() * getValue(GV_LENGTH_UNIT);
|
||||
|
||||
bool doFillet = l->hasFilletRadius();
|
||||
bool doEdgeFillet = l->hasEdgeRadius();
|
||||
|
||||
double f1 = 0.;
|
||||
double f2 = 0.;
|
||||
|
||||
if ( doFillet ) {
|
||||
f1 = l->FilletRadius() * getValue(GV_LENGTH_UNIT);
|
||||
}
|
||||
if ( doEdgeFillet ) {
|
||||
f2 = l->EdgeRadius() * getValue(GV_LENGTH_UNIT);
|
||||
}
|
||||
|
||||
if ( x == 0.0f || y == 0.0f || dx == 0.0f || dy == 0.0f ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
cgal_placement_t trsf2d;
|
||||
bool has_position = true;
|
||||
#ifdef USE_IFC4
|
||||
has_position = l->hasPosition();
|
||||
#endif
|
||||
|
||||
const int segments = 3;
|
||||
|
||||
face = cgal_face_t();
|
||||
face.outer.push_back(Kernel::Point_3(-dx, -y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(x, -y, 0.0));
|
||||
if (f2 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(x, -y+dy, 0.0));
|
||||
} else {
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(x-f2+f2*cos(current_angle), -y+dy-f2+f2*sin(current_angle), 0));
|
||||
}
|
||||
} if (f1 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(dx, -y+dy, 0.0));
|
||||
} else {
|
||||
for (int current_segment = segments; current_segment >= 0; --current_segment) {
|
||||
double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(dx+f1+f1*cos(current_angle), -y+dy+f1+f1*sin(current_angle), 0));
|
||||
}
|
||||
} face.outer.push_back(Kernel::Point_3(dx, y, 0.0));
|
||||
face.outer.push_back(Kernel::Point_3(-x, y, 0.0));
|
||||
if (f2 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(-x, y-dy, 0.0));
|
||||
} else {
|
||||
for (int current_segment = 0; current_segment <= segments; ++current_segment) {
|
||||
double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(-x+f2+f2*cos(current_angle), y-dy+f2+f2*sin(current_angle), 0));
|
||||
}
|
||||
} if (f1 == 0.0) {
|
||||
face.outer.push_back(Kernel::Point_3(-dx, y-dy, 0.0));
|
||||
} else {
|
||||
for (int current_segment = segments; current_segment >= 0; --current_segment) {
|
||||
double current_angle = current_segment*0.5*3.141592653589793/((double)segments);
|
||||
face.outer.push_back(Kernel::Point_3(-dx-f1+f1*cos(current_angle), y-dy-f1+f1*sin(current_angle), 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (has_position) {
|
||||
IfcGeom::CgalKernel::convert(l->Position(), trsf2d);
|
||||
for (auto &vertex: face.outer) {
|
||||
vertex = vertex.transform(trsf2d);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcDerivedProfileDef* l, cgal_face_t& face) {
|
||||
cgal_face_t f;
|
||||
cgal_placement_t trsf2d;
|
||||
if (convert_face(l->ParentProfile(), f) && IfcGeom::CgalKernel::convert(l->Operator(), trsf2d)) {
|
||||
cgal_placement_t trsf = trsf2d;
|
||||
for (auto &vertex: f.outer) vertex = vertex.transform(trsf);
|
||||
for (auto &ring: f.inner) {
|
||||
for (auto &vertex: ring) vertex = vertex.transform(trsf);
|
||||
} face = f;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
#include "CgalKernel.h"
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianPoint* l, cgal_point_t& point) {
|
||||
std::vector<double> xyz = l->Coordinates();
|
||||
point = Kernel::Point_3(xyz.size() ? (xyz[0]*getValue(GV_LENGTH_UNIT)) : 0.0f,
|
||||
xyz.size() > 1 ? (xyz[1]*getValue(GV_LENGTH_UNIT)) : 0.0f,
|
||||
xyz.size() > 2 ? (xyz[2]*getValue(GV_LENGTH_UNIT)) : 0.0f);
|
||||
// std::cout << "Converted Point(" << point << ")" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcDirection* l, cgal_direction_t& dir) {
|
||||
// IN_CACHE(IfcDirection,l,cgal_direction_t,dir)
|
||||
std::vector<double> xyz = l->DirectionRatios();
|
||||
dir = Kernel::Vector_3(xyz.size() ? xyz[0] : 0.0f,
|
||||
xyz.size() > 1 ? xyz[1] : 0.0f,
|
||||
xyz.size() > 2 ? xyz[2] : 0.0f);
|
||||
// CACHE(IfcDirection,l,dir)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcVector* l, cgal_vector_t& v) {
|
||||
// IN_CACHE(IfcVector,l,cgal_vector_t,v)
|
||||
cgal_direction_t d;
|
||||
IfcGeom::CgalKernel::convert(l->Orientation(),d);
|
||||
v = l->Magnitude() * getValue(GV_LENGTH_UNIT) * d;
|
||||
// CACHE(IfcVector,l,v)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPlane* pln, cgal_plane_t& plane) {
|
||||
// IN_CACHE(IfcPlane,pln,gp_Pln,plane)
|
||||
IfcSchema::IfcAxis2Placement3D* l = pln->Position();
|
||||
cgal_point_t o;
|
||||
cgal_direction_t axis = Kernel::Vector_3(0,0,1);
|
||||
cgal_direction_t refDirection = Kernel::Vector_3(1,0,0);
|
||||
IfcGeom::CgalKernel::convert(l->Location(),o);
|
||||
bool hasRef = l->hasRefDirection();
|
||||
if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(),axis);
|
||||
if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection);
|
||||
Kernel::Vector_3 y = CGAL::cross_product(axis, refDirection);
|
||||
Kernel::Vector_3 x = CGAL::cross_product(y, axis);
|
||||
|
||||
cgal_plane_t ax3;
|
||||
if ( hasRef ) ax3 = Kernel::Plane_3(o,o+x,o+y);
|
||||
else ax3 = Kernel::Plane_3(o,axis);
|
||||
plane = ax3;
|
||||
|
||||
// std::cout << "IfcPlane C = " << o << std::endl;
|
||||
// std::cout << "IfcPlane z (axis, exact) = " << axis << std::endl;
|
||||
// std::cout << "IfcPlane x (refDirection, approximate) = " << refDirection << std::endl;
|
||||
// std::cout << "IfcPlane y (computed, exact) = " << y << std::endl;
|
||||
// std::cout << "IfcPlane x (computed, exact) = " << x << std::endl;
|
||||
//
|
||||
// std::cout << "Plane_3 o = " << o << std::endl;
|
||||
// std::cout << "Plane_3 o+x = " << o+x << std::endl;
|
||||
// std::cout << "Plane_3 o+y = " << o+y << std::endl;
|
||||
|
||||
// ax + by + cz + d = 0
|
||||
// std::cout << "Plane: a = " << plane.a() << ", b = " << plane.b() << ", c = " << plane.c() << ", d = " << plane.d() << std::endl;
|
||||
|
||||
// std::ofstream fresult;
|
||||
// fresult.open("/Users/ken/Desktop/plane.obj");
|
||||
// // x = -5, y = -5, z = (5a +5b -d)/c
|
||||
// fresult << "v -5 -5 " << (5.0*CGAL::to_double(plane.a())+5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl;
|
||||
// // x = -5, y = +5, z = (5a -5b -d)/c
|
||||
// fresult << "v -5 5 " << (5.0*CGAL::to_double(plane.a())-5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl;
|
||||
// // x = 5, y = -5, z = (-5a +5b -d)/c
|
||||
// fresult << "v 5 -5 " << (-5.0*CGAL::to_double(plane.a())+5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl;
|
||||
// // x = 5, y = +5, z = (-5a -5b -d)/c
|
||||
// fresult << "v 5 5 " << (-5.0*CGAL::to_double(plane.a())-5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl;
|
||||
// fresult << "f 1 2 3" << std::endl;
|
||||
// fresult << "f 4 3 2" << std::endl;
|
||||
// fresult.close();
|
||||
|
||||
// CACHE(IfcPlane,pln,plane)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement2D* l, cgal_placement_t& trsf) {
|
||||
// IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf)
|
||||
cgal_point_t o;
|
||||
cgal_direction_t refDirection = Kernel::Vector_3(1,0,0);
|
||||
IfcGeom::CgalKernel::convert(l->Location(),o);
|
||||
bool hasRef = l->hasRefDirection();
|
||||
if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection);
|
||||
cgal_direction_t y = Kernel::Vector_3(-refDirection.y(), refDirection.x(), 0.0);
|
||||
|
||||
const double tolerance = 0.01;
|
||||
if (refDirection.squared_length() < 1.0-tolerance || refDirection.squared_length() > 1.0+tolerance ||
|
||||
y.squared_length() < 1.0-tolerance || y.squared_length() > 1.0+tolerance) {
|
||||
std::cout << "Ref direction (x): " << refDirection << " squared length: " << refDirection.squared_length() << std::endl;
|
||||
std::cout << "y: " << y << " squared length: " << y.squared_length() << std::endl;
|
||||
std::cout << "Origin: " << o << std::endl;
|
||||
}
|
||||
|
||||
// TODO: Should be checked.
|
||||
trsf = Kernel::Aff_transformation_3(refDirection.cartesian(0), y.cartesian(0), 0.0, o.cartesian(0),
|
||||
refDirection.cartesian(1), y.cartesian(1), 0.0, o.cartesian(1),
|
||||
0.0, 0.0, 1.0, 0.0);
|
||||
|
||||
// CACHE(IfcAxis2Placement3D,l,trsf)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement3D* l, cgal_placement_t& trsf) {
|
||||
// IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf)
|
||||
cgal_point_t o;
|
||||
cgal_direction_t axis = Kernel::Vector_3(0,0,1);
|
||||
cgal_direction_t refDirection = Kernel::Vector_3(1,0,0);
|
||||
IfcGeom::CgalKernel::convert(l->Location(),o);
|
||||
bool hasRef = l->hasRefDirection();
|
||||
if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(),axis);
|
||||
if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection);
|
||||
Kernel::Vector_3 y = CGAL::cross_product(axis, refDirection);
|
||||
Kernel::Vector_3 x = CGAL::cross_product(y, axis);
|
||||
|
||||
const double tolerance = 0.01;
|
||||
if (x.squared_length() < 1.0-tolerance || x.squared_length() > 1.0+tolerance ||
|
||||
y.squared_length() < 1.0-tolerance || y.squared_length() > 1.0+tolerance ||
|
||||
axis.squared_length() < 1.0-tolerance || axis.squared_length() > 1.0+tolerance) {
|
||||
std::cout << "Ref direction: " << refDirection << " squared length: " << refDirection.squared_length() << std::endl;
|
||||
std::cout << "Axis (z): " << axis << " squared length: " << axis.squared_length() << std::endl;
|
||||
std::cout << "y: " << y << " squared length: " << y.squared_length() << std::endl;
|
||||
std::cout << "x: " << x << " squared length: " << x.squared_length() << std::endl;
|
||||
std::cout << "Origin: " << o << std::endl;
|
||||
}
|
||||
|
||||
// TODO: Should be checked.
|
||||
trsf = Kernel::Aff_transformation_3(x.cartesian(0), y.cartesian(0), axis.cartesian(0), o.cartesian(0),
|
||||
x.cartesian(1), y.cartesian(1), axis.cartesian(1), o.cartesian(1),
|
||||
x.cartesian(2), y.cartesian(2), axis.cartesian(2), o.cartesian(2));
|
||||
|
||||
// for (int i = 0; i < 3; ++i) {
|
||||
// for (int j = 0; j < 4; ++j) {
|
||||
// std::cout << trsf.cartesian(i, j) << " ";
|
||||
// } std::cout << std::endl;
|
||||
// }
|
||||
|
||||
// CACHE(IfcAxis2Placement3D,l,trsf)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis1Placement* l, cgal_placement_t& ax) {
|
||||
// IN_CACHE(IfcAxis1Placement,l,gp_Ax1,ax)
|
||||
cgal_point_t o;
|
||||
cgal_direction_t axis = Kernel::Vector_3(0,0,1);
|
||||
IfcGeom::CgalKernel::convert(l->Location(),o);
|
||||
if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(), axis);
|
||||
|
||||
const double tolerance = 0.01;
|
||||
if (axis.squared_length() < 1.0-tolerance || axis.squared_length() > 1.0+tolerance) {
|
||||
std::cout << "Axis (z): " << axis << " squared length: " << axis.squared_length() << std::endl;
|
||||
std::cout << "Origin: " << o << std::endl;
|
||||
}
|
||||
|
||||
// TODO: Should be checked.
|
||||
ax = Kernel::Aff_transformation_3(1.0, 0.0, axis.cartesian(0), o.cartesian(0),
|
||||
0.0, 1.0, axis.cartesian(1), o.cartesian(1),
|
||||
0.0, 0.0, axis.cartesian(2), o.cartesian(2));
|
||||
|
||||
// CACHE(IfcAxis1Placement,l,ax)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcObjectPlacement* l, cgal_placement_t& trsf) {
|
||||
// IN_CACHE(IfcObjectPlacement,l,cgal_placement_t,trsf)
|
||||
if ( ! l->is(IfcSchema::Type::IfcLocalPlacement) ) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Unsupported IfcObjectPlacement:", l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
// std::cout << "initial trsf (identity?)" << std::endl;
|
||||
// for (int i = 0; i < 3; ++i) {
|
||||
// for (int j = 0; j < 4; ++j) {
|
||||
// std::cout << trsf.cartesian(i, j) << " ";
|
||||
// } std::cout << std::endl;
|
||||
// }
|
||||
|
||||
IfcSchema::IfcLocalPlacement* current = (IfcSchema::IfcLocalPlacement*)l;
|
||||
for (;;) {
|
||||
cgal_placement_t trsf2;
|
||||
|
||||
IfcSchema::IfcAxis2Placement* relplacement = current->RelativePlacement();
|
||||
if ( relplacement->is(IfcSchema::Type::IfcAxis2Placement3D) ) {
|
||||
IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement3D*)relplacement,trsf2);
|
||||
|
||||
// std::cout << "trsf2" << std::endl;
|
||||
// for (int i = 0; i < 3; ++i) {
|
||||
// for (int j = 0; j < 4; ++j) {
|
||||
// std::cout << trsf2.cartesian(i, j) << " ";
|
||||
// } std::cout << std::endl;
|
||||
// }
|
||||
|
||||
trsf = trsf2 * trsf;
|
||||
|
||||
// std::cout << "trsf (after multiplication)" << std::endl;
|
||||
// for (int i = 0; i < 3; ++i) {
|
||||
// for (int j = 0; j < 4; ++j) {
|
||||
// std::cout << trsf.cartesian(i, j) << " ";
|
||||
// } std::cout << std::endl;
|
||||
// }
|
||||
}
|
||||
if ( current->hasPlacementRelTo() ) {
|
||||
IfcSchema::IfcObjectPlacement* relto = current->PlacementRelTo();
|
||||
if ( relto->is(IfcSchema::Type::IfcLocalPlacement) )
|
||||
current = (IfcSchema::IfcLocalPlacement*)current->PlacementRelTo();
|
||||
else break;
|
||||
} else break;
|
||||
}
|
||||
// CACHE(IfcObjectPlacement,l,trsf)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator2D* l, cgal_placement_t& trsf) {
|
||||
// IN_CACHE(IfcCartesianTransformationOperator2D,l,cgal_placement_t,trsf)
|
||||
|
||||
cgal_point_t origin;
|
||||
cgal_direction_t axis1 (1.,0.,0.);
|
||||
cgal_direction_t axis2 (0.,1.,0.);
|
||||
|
||||
IfcGeom::CgalKernel::convert(l->LocalOrigin(),origin);
|
||||
if ( l->hasAxis1() ) IfcGeom::CgalKernel::convert(l->Axis1(),axis1);
|
||||
if ( l->hasAxis2() ) IfcGeom::CgalKernel::convert(l->Axis2(),axis2);
|
||||
double scale = 1.0;
|
||||
if (l->hasScale()) {
|
||||
scale = l->Scale();
|
||||
}
|
||||
|
||||
// TODO: Untested
|
||||
trsf = Kernel::Aff_transformation_3(scale*axis1.cartesian(0), axis2.cartesian(0), 0.0, origin.cartesian(0),
|
||||
axis1.cartesian(1), scale*axis2.cartesian(1), 0.0, origin.cartesian(1),
|
||||
0.0, 0.0, 1.0, 0.0);
|
||||
|
||||
// CACHE(IfcCartesianTransformationOperator2D,l,trsf)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator2DnonUniform* l, cgal_placement_t& trsf) {
|
||||
// IN_CACHE(IfcCartesianTransformationOperator2DnonUniform,l,cgal_placement_t,gtrsf)
|
||||
|
||||
cgal_point_t origin;
|
||||
cgal_direction_t axis1 (1.,0.,0.);
|
||||
cgal_direction_t axis2 (0.,1.,0.);
|
||||
|
||||
IfcGeom::CgalKernel::convert(l->LocalOrigin(),origin);
|
||||
if ( l->hasAxis1() ) IfcGeom::CgalKernel::convert(l->Axis1(),axis1);
|
||||
if ( l->hasAxis2() ) IfcGeom::CgalKernel::convert(l->Axis2(),axis2);
|
||||
|
||||
const double scale1 = l->hasScale() ? l->Scale() : 1.0f;
|
||||
const double scale2 = l->hasScale2() ? l->Scale2() : scale1;
|
||||
|
||||
// TODO: Untested
|
||||
trsf = Kernel::Aff_transformation_3(scale1*axis1.cartesian(0), axis2.cartesian(0), 0.0, origin.cartesian(0),
|
||||
axis1.cartesian(1), scale2*axis2.cartesian(1), 0.0, origin.cartesian(1),
|
||||
0.0, 0.0, 1.0, 0.0);
|
||||
|
||||
// CACHE(IfcCartesianTransformationOperator2DnonUniform,l,gtrsf)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator3D* l, cgal_placement_t& trsf) {
|
||||
// IN_CACHE(IfcCartesianTransformationOperator3D,l,gp_Trsf,trsf)
|
||||
cgal_point_t origin;
|
||||
IfcGeom::CgalKernel::convert(l->LocalOrigin(),origin);
|
||||
cgal_direction_t axis1 (1.,0.,0.);
|
||||
cgal_direction_t axis2 (0.,1.,0.);
|
||||
cgal_direction_t axis3 (0.,0.,1.);
|
||||
if ( l->hasAxis1() ) IfcGeom::CgalKernel::convert(l->Axis1(),axis1);
|
||||
if ( l->hasAxis2() ) IfcGeom::CgalKernel::convert(l->Axis2(),axis2);
|
||||
if ( l->hasAxis3() ) IfcGeom::CgalKernel::convert(l->Axis3(),axis3);
|
||||
double scale = 1.0;
|
||||
if (l->hasScale()) {
|
||||
scale = l->Scale();
|
||||
}
|
||||
|
||||
// TODO: Untested
|
||||
trsf = Kernel::Aff_transformation_3(scale*axis1.cartesian(0), axis2.cartesian(0), axis3.cartesian(0), origin.cartesian(0),
|
||||
axis1.cartesian(1), scale*axis2.cartesian(1), axis3.cartesian(1), origin.cartesian(1),
|
||||
axis1.cartesian(2), axis2.cartesian(2), scale*axis3.cartesian(2), origin.cartesian(2));
|
||||
|
||||
// std::cout << std::endl;
|
||||
// for (int i = 0; i < 3; ++i) {
|
||||
// for (int j = 0; j < 4; ++j) {
|
||||
// std::cout << trsf.cartesian(i, j) << " ";
|
||||
// } std::cout << std::endl;
|
||||
// }
|
||||
|
||||
// CACHE(IfcCartesianTransformationOperator3D,l,trsf)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator3DnonUniform* l, cgal_placement_t& gtrsf) {
|
||||
// IN_CACHE(IfcCartesianTransformationOperator3DnonUniform,l,gp_GTrsf,gtrsf)
|
||||
cgal_point_t origin;
|
||||
IfcGeom::CgalKernel::convert(l->LocalOrigin(),origin);
|
||||
cgal_direction_t axis1 (1.,0.,0.);
|
||||
cgal_direction_t axis2 (0.,1.,0.);
|
||||
cgal_direction_t axis3 (0.,0.,1.);
|
||||
if ( l->hasAxis1() ) IfcGeom::CgalKernel::convert(l->Axis1(),axis1);
|
||||
if ( l->hasAxis2() ) IfcGeom::CgalKernel::convert(l->Axis2(),axis2);
|
||||
if ( l->hasAxis3() ) IfcGeom::CgalKernel::convert(l->Axis3(),axis3);
|
||||
const double scale1 = l->hasScale() ? l->Scale() : 1.0f;
|
||||
const double scale2 = l->hasScale2() ? l->Scale2() : scale1;
|
||||
const double scale3 = l->hasScale3() ? l->Scale3() : scale1;
|
||||
|
||||
// TODO: Untested
|
||||
gtrsf = Kernel::Aff_transformation_3(scale1*axis1.cartesian(0), axis2.cartesian(0), axis3.cartesian(0), origin.cartesian(0),
|
||||
axis1.cartesian(1), scale2*axis2.cartesian(1), axis3.cartesian(1), origin.cartesian(1),
|
||||
axis1.cartesian(2), axis2.cartesian(2), scale3*axis3.cartesian(2), origin.cartesian(2));
|
||||
|
||||
// for (int i = 0; i < 3; ++i) {
|
||||
// for (int j = 0; j < 4; ++j) {
|
||||
// std::cout << gtrsf.cartesian(i, j) << " ";
|
||||
// } std::cout << std::endl;
|
||||
// }
|
||||
|
||||
// CACHE(IfcCartesianTransformationOperator3DnonUniform,l,gtrsf)
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,916 @@
|
||||
#include "CgalKernel.h"
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal_shape_t &shape) {
|
||||
const double height = l->Depth() * getValue(GV_LENGTH_UNIT);
|
||||
if (height < getValue(GV_PRECISION)) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Non-positive extrusion height encountered for:", l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Outer
|
||||
cgal_face_t bottom_face;
|
||||
if ( !convert_face(l->SweptArea(),bottom_face) ) return false;
|
||||
// std::cout << "Face vertices: " << face.outer.size() << std::endl;
|
||||
|
||||
cgal_placement_t trsf;
|
||||
bool has_position = true;
|
||||
#ifdef USE_IFC4
|
||||
has_position = l->hasPosition();
|
||||
#endif
|
||||
if (has_position) {
|
||||
IfcGeom::CgalKernel::convert(l->Position(), trsf);
|
||||
}
|
||||
|
||||
cgal_direction_t dir;
|
||||
convert(l->ExtrudedDirection(),dir);
|
||||
// std::cout << "Direction: " << dir << std::endl;
|
||||
|
||||
std::list<cgal_face_t> face_list;
|
||||
face_list.push_back(bottom_face);
|
||||
|
||||
for (std::vector<Kernel::Point_3>::const_iterator current_vertex = bottom_face.outer.begin();
|
||||
current_vertex != bottom_face.outer.end();
|
||||
++current_vertex) {
|
||||
std::vector<Kernel::Point_3>::const_iterator next_vertex = current_vertex;
|
||||
++next_vertex;
|
||||
if (next_vertex == bottom_face.outer.end()) {
|
||||
next_vertex = bottom_face.outer.begin();
|
||||
} cgal_face_t side_face;
|
||||
side_face.outer.push_back(*next_vertex);
|
||||
side_face.outer.push_back(*current_vertex);
|
||||
side_face.outer.push_back(*current_vertex+height*dir);
|
||||
side_face.outer.push_back(*next_vertex+height*dir);
|
||||
face_list.push_back(side_face);
|
||||
}
|
||||
|
||||
cgal_face_t top_face;
|
||||
for (std::vector<Kernel::Point_3>::const_reverse_iterator vertex = bottom_face.outer.rbegin();
|
||||
vertex != bottom_face.outer.rend();
|
||||
++vertex) {
|
||||
top_face.outer.push_back(*vertex+height*dir);
|
||||
} face_list.push_back(top_face);
|
||||
|
||||
if (bottom_face.inner.empty()) {
|
||||
shape = create_polyhedron(face_list);
|
||||
if (has_position) for (auto &vertex: vertices(shape)) vertex->point() = vertex->point().transform(trsf);
|
||||
return true;
|
||||
}
|
||||
|
||||
CGAL::Nef_polyhedron_3<Kernel> nef_shape = create_nef_polyhedron(face_list);
|
||||
|
||||
// Inner
|
||||
// TODO: Would be faster to triangulate top/bottom face template rather than use Nef polyhedra for subtraction
|
||||
for (auto &inner: bottom_face.inner) {
|
||||
// std::cout << "Inner wire" << std::endl;
|
||||
face_list.clear();
|
||||
|
||||
cgal_face_t hole_bottom_face;
|
||||
hole_bottom_face.outer = inner;
|
||||
remove_duplicate_points_from_loop(hole_bottom_face.outer);
|
||||
face_list.push_back(hole_bottom_face);
|
||||
|
||||
for (std::vector<Kernel::Point_3>::const_iterator current_vertex = inner.begin();
|
||||
current_vertex != inner.end();
|
||||
++current_vertex) {
|
||||
std::vector<Kernel::Point_3>::const_iterator next_vertex = current_vertex;
|
||||
++next_vertex;
|
||||
if (next_vertex == inner.end()) {
|
||||
next_vertex = inner.begin();
|
||||
} cgal_face_t hole_side_face;
|
||||
hole_side_face.outer.push_back(*next_vertex);
|
||||
hole_side_face.outer.push_back(*current_vertex);
|
||||
hole_side_face.outer.push_back(*current_vertex+height*dir);
|
||||
hole_side_face.outer.push_back(*next_vertex+height*dir);
|
||||
face_list.push_back(hole_side_face);
|
||||
}
|
||||
|
||||
cgal_face_t hole_top_face;
|
||||
for (std::vector<Kernel::Point_3>::const_reverse_iterator vertex = inner.rbegin();
|
||||
vertex != inner.rend();
|
||||
++vertex) {
|
||||
hole_top_face.outer.push_back(*vertex+height*dir);
|
||||
} face_list.push_back(hole_top_face);
|
||||
|
||||
try {
|
||||
nef_shape -= create_nef_polyhedron(face_list);
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_ERROR, "IfcExtrudedAreaSolid: cannot subtract opening for:", l->entity);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_position) {
|
||||
// IfcSweptAreaSolid.Position (trsf) is an IfcAxis2Placement3D
|
||||
// and therefore has a unit scale factor
|
||||
nef_shape.transform(trsf);
|
||||
}
|
||||
|
||||
try {
|
||||
nef_shape.convert_to_polyhedron(shape);
|
||||
return true;
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_ERROR, "IfcExtrudedAreaSolid: cannot convert Nef to polyhedron for:", l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef USE_IFC4
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolidTapered* l, cgal_shape_t& shape) {
|
||||
const double height = l->Depth() * getValue(GV_LENGTH_UNIT);
|
||||
if (height < getValue(GV_PRECISION)) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Non-positive extrusion height encountered for:", l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
cgal_face_t face1, face2;
|
||||
if (!convert_face(l->SweptArea(), face1)) return false;
|
||||
if (!convert_face(l->EndSweptArea(), face2)) return false;
|
||||
|
||||
cgal_placement_t trsf;
|
||||
bool has_position = true;
|
||||
#ifdef USE_IFC4
|
||||
has_position = l->hasPosition();
|
||||
#endif
|
||||
if (has_position) {
|
||||
IfcGeom::CgalKernel::convert(l->Position(), trsf);
|
||||
}
|
||||
|
||||
cgal_direction_t dir;
|
||||
convert(l->ExtrudedDirection(), dir);
|
||||
|
||||
for (auto &vertex: face2.outer) vertex = vertex + height*dir;
|
||||
for (auto &ring: face2.inner) {
|
||||
for (auto &vertex: ring) vertex = vertex + height*dir;
|
||||
}
|
||||
|
||||
// Outer
|
||||
std::list<cgal_face_t> face_list;
|
||||
face_list.push_back(face1);
|
||||
|
||||
std::vector<Kernel::Point_3>::const_iterator current_face1_vertex = face1.outer.begin();
|
||||
std::vector<Kernel::Point_3>::const_iterator current_face2_vertex = face2.outer.begin();
|
||||
while (current_face1_vertex != face1.outer.end() &&
|
||||
current_face2_vertex != face2.outer.end()) {
|
||||
std::vector<Kernel::Point_3>::const_iterator next_face1_vertex = current_face1_vertex;
|
||||
std::vector<Kernel::Point_3>::const_iterator next_face2_vertex = current_face2_vertex;
|
||||
++next_face1_vertex;
|
||||
++next_face2_vertex;
|
||||
if (next_face1_vertex == face1.outer.end()) next_face1_vertex = face1.outer.begin();
|
||||
if (next_face2_vertex == face2.outer.end()) next_face2_vertex = face2.outer.begin();
|
||||
cgal_face_t side_face;
|
||||
side_face.outer.push_back(*next_face1_vertex);
|
||||
side_face.outer.push_back(*current_face1_vertex);
|
||||
side_face.outer.push_back(*current_face2_vertex);
|
||||
side_face.outer.push_back(*next_face2_vertex);
|
||||
face_list.push_back(side_face);
|
||||
++current_face1_vertex;
|
||||
++current_face2_vertex;
|
||||
}
|
||||
|
||||
cgal_face_t top_face;
|
||||
for (std::vector<Kernel::Point_3>::const_reverse_iterator vertex = face2.outer.rbegin();
|
||||
vertex != face2.outer.rend();
|
||||
++vertex) {
|
||||
top_face.outer.push_back(*vertex);
|
||||
} face_list.push_back(top_face);
|
||||
|
||||
if (face1.inner.empty() || face2.inner.empty()) {
|
||||
shape = create_polyhedron(face_list);
|
||||
if (has_position) for (auto &vertex: vertices(shape)) vertex->point() = vertex->point().transform(trsf);
|
||||
return true;
|
||||
}
|
||||
|
||||
// std::ofstream f1;
|
||||
// CGAL::Polyhedron_3<Kernel> outer_polyhedron;
|
||||
// PolyhedronBuilder builder(&face_list);
|
||||
// outer_polyhedron.delegate(builder);
|
||||
// f1.open("/Users/ken/Desktop/outer.off");
|
||||
// f1 << outer_polyhedron << std::endl;
|
||||
// f1.close();
|
||||
|
||||
CGAL::Nef_polyhedron_3<Kernel> nef_shape = create_nef_polyhedron(face_list);
|
||||
|
||||
// Inner
|
||||
// TODO: Would be faster to triangulate top/bottom face template rather than use Nef polyhedra for subtraction
|
||||
std::vector<cgal_wire_t>::iterator inner_face1 = face1.inner.begin();
|
||||
std::vector<cgal_wire_t>::iterator inner_face2 = face2.inner.begin();
|
||||
while (inner_face1 != face1.inner.end() &&
|
||||
inner_face2 != face2.inner.end()) {
|
||||
face_list.clear();
|
||||
|
||||
cgal_face_t hole_face1;
|
||||
hole_face1.outer = *inner_face1;
|
||||
remove_duplicate_points_from_loop(hole_face1.outer);
|
||||
face_list.push_back(hole_face1);
|
||||
|
||||
cgal_face_t hole_face2;
|
||||
hole_face2.outer = *inner_face2;
|
||||
remove_duplicate_points_from_loop(hole_face2.outer);
|
||||
|
||||
current_face1_vertex = hole_face1.outer.begin();
|
||||
current_face2_vertex = hole_face2.outer.begin();
|
||||
while (current_face1_vertex != hole_face1.outer.end() &&
|
||||
current_face2_vertex != hole_face2.outer.end()) {
|
||||
std::vector<Kernel::Point_3>::const_iterator next_face1_vertex = current_face1_vertex;
|
||||
std::vector<Kernel::Point_3>::const_iterator next_face2_vertex = current_face2_vertex;
|
||||
++next_face1_vertex;
|
||||
++next_face2_vertex;
|
||||
if (next_face1_vertex == hole_face1.outer.end()) next_face1_vertex = hole_face1.outer.begin();
|
||||
if (next_face2_vertex == hole_face2.outer.end()) next_face2_vertex = hole_face2.outer.begin();
|
||||
cgal_face_t side_face;
|
||||
side_face.outer.push_back(*next_face1_vertex);
|
||||
side_face.outer.push_back(*current_face1_vertex);
|
||||
side_face.outer.push_back(*current_face2_vertex);
|
||||
side_face.outer.push_back(*next_face2_vertex);
|
||||
face_list.push_back(side_face);
|
||||
++current_face1_vertex;
|
||||
++current_face2_vertex;
|
||||
}
|
||||
|
||||
cgal_face_t top_hole_face;
|
||||
for (std::vector<Kernel::Point_3>::const_reverse_iterator vertex = hole_face2.outer.rbegin();
|
||||
vertex != hole_face2.outer.rend();
|
||||
++vertex) {
|
||||
top_hole_face.outer.push_back(*vertex);
|
||||
} face_list.push_back(top_hole_face);
|
||||
|
||||
// std::ofstream f2;
|
||||
// CGAL::Polyhedron_3<Kernel> inner_polyhedron;
|
||||
// PolyhedronBuilder builder(&face_list);
|
||||
// inner_polyhedron.delegate(builder);
|
||||
// f2.open("/Users/ken/Desktop/inner.off");
|
||||
// f2 << inner_polyhedron << std::endl;
|
||||
// f2.close();
|
||||
|
||||
try {
|
||||
nef_shape -= create_nef_polyhedron(face_list);
|
||||
} catch (...) {
|
||||
std::cout << "IfcExtrudedAreaSolidTapered: cannot subtract opening for:" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
++inner_face1;
|
||||
++inner_face2;
|
||||
}
|
||||
|
||||
if (has_position) {
|
||||
// IfcSweptAreaSolid.Position (trsf) is an IfcAxis2Placement3D
|
||||
// and therefore has a unit scale factor
|
||||
nef_shape.transform(trsf);
|
||||
}
|
||||
|
||||
try {
|
||||
nef_shape.convert_to_polyhedron(shape);
|
||||
return true;
|
||||
} catch (...) {
|
||||
std::cout << "IfcExtrudedAreaSolidTapered: cannot convert Nef to polyhedron!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_shape_t& shape) {
|
||||
IfcSchema::IfcFace::list::ptr faces = l->CfsFaces();
|
||||
|
||||
std::list<cgal_face_t> face_list;
|
||||
for (IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++it) {
|
||||
bool success = false;
|
||||
cgal_face_t face;
|
||||
|
||||
try {
|
||||
success = convert_face(*it, face);
|
||||
} catch (...) {}
|
||||
|
||||
if (!success) {
|
||||
Logger::Message(Logger::LOG_WARNING, "Failed to convert face:", (*it)->entity);
|
||||
continue;
|
||||
}
|
||||
|
||||
// std::cout << "Face in ConnectedFaceSet: " << std::endl;
|
||||
// for (auto &point: face.outer) {
|
||||
// std::cout << "\tPoint(" << point << ")" << std::endl;
|
||||
// }
|
||||
|
||||
face_list.push_back(face);
|
||||
}
|
||||
|
||||
shape = create_polyhedron(face_list);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCsgSolid* l, cgal_shape_t& shape) {
|
||||
return convert_shape(l->TreeRootExpression(), shape);
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBlock* l, cgal_shape_t& shape) {
|
||||
const double dx = l->XLength() * getValue(GV_LENGTH_UNIT);
|
||||
const double dy = l->YLength() * getValue(GV_LENGTH_UNIT);
|
||||
const double dz = l->ZLength() * getValue(GV_LENGTH_UNIT);
|
||||
|
||||
std::list<cgal_face_t> face_list;
|
||||
|
||||
// x = 0
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, 0, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, dy, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, dy, dz));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, 0, dz));
|
||||
|
||||
// x = dx
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(Kernel::Point_3(dx, 0, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(dx, 0, dz));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(dx, dy, dz));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(dx, dy, 0));
|
||||
|
||||
// y = 0
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, 0, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, 0, dz));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(dx, 0, dz));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(dx, 0, 0));
|
||||
|
||||
// y = dy
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, dy, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(dx, dy, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(dx, dy, dz));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, dy, dz));
|
||||
|
||||
// z = 0
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, 0, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(dx, 0, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(dx, dy, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, dy, 0));
|
||||
|
||||
// z = dz
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, 0, dz));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, dy, dz));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(dx, dy, dz));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(dx, 0, dz));
|
||||
|
||||
cgal_placement_t trsf;
|
||||
IfcGeom::CgalKernel::convert(l->Position(),trsf);
|
||||
|
||||
shape = create_polyhedron(face_list);
|
||||
for (auto &vertex: vertices(shape)) vertex->point() = vertex->point().transform(trsf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_shape_t& shape) {
|
||||
|
||||
cgal_shape_t s1, s2;
|
||||
ConversionResults items1, items2;
|
||||
cgal_wire_t boundary_wire;
|
||||
IfcSchema::IfcBooleanOperand* operand1 = l->FirstOperand();
|
||||
IfcSchema::IfcBooleanOperand* operand2 = l->SecondOperand();
|
||||
bool is_halfspace = operand2->is(IfcSchema::Type::IfcHalfSpaceSolid);
|
||||
|
||||
if ( shape_type(operand1) == ST_SHAPELIST ) {
|
||||
Logger::Message(Logger::LOG_ERROR, "s1: ST_SHAPELIST Unsupported", operand1->entity);
|
||||
// if (!(convert_shapes(operand1, items1) && flatten_shape_list(items1, s1, true))) {
|
||||
return false;
|
||||
// }
|
||||
} else if ( shape_type(operand1) == ST_SHAPE ) {
|
||||
if (!convert_shape(operand1, s1) ) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
Logger::Message(Logger::LOG_ERROR, "s1: Invalid representation item for boolean operation", operand1->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
// const double first_operand_volume = shape_volume(s1);
|
||||
// if ( first_operand_volume <= ALMOST_ZERO )
|
||||
// Logger::Message(Logger::LOG_WARNING,"Empty solid for:",l->FirstOperand()->entity);
|
||||
|
||||
bool shape2_processed = false;
|
||||
if ( shape_type(operand2) == ST_SHAPELIST ) {
|
||||
Logger::Message(Logger::LOG_ERROR, "s2: ST_SHAPELIST Unsupported", operand1->entity);
|
||||
// shape2_processed = convert_shapes(operand2, items2) && flatten_shape_list(items2, s2, true);
|
||||
} else if ( shape_type(operand2) == ST_SHAPE ) {
|
||||
shape2_processed = convert_shape(operand2,s2);
|
||||
} else {
|
||||
Logger::Message(Logger::LOG_ERROR, "s2: Invalid representation item for boolean operation", operand2->entity);
|
||||
}
|
||||
|
||||
if (!shape2_processed) {
|
||||
shape = s1;
|
||||
Logger::Message(Logger::LOG_ERROR,"Failed to convert SecondOperand of:",l->entity);
|
||||
return true;
|
||||
}
|
||||
|
||||
// if (!is_halfspace) {
|
||||
// const double second_operand_volume = shape_volume(s2);
|
||||
// if ( second_operand_volume <= ALMOST_ZERO )
|
||||
// Logger::Message(Logger::LOG_WARNING,"Empty solid for:",operand2->entity);
|
||||
// }
|
||||
|
||||
const IfcSchema::IfcBooleanOperator::IfcBooleanOperator op = l->Operator();
|
||||
|
||||
if (!s1.is_valid()) {
|
||||
Logger::Message(Logger::LOG_ERROR, "s1: Not valid?", operand1->entity);
|
||||
return false;
|
||||
} else {
|
||||
// std::ofstream f1;
|
||||
// CGAL::Polyhedron_3<Kernel> p1;
|
||||
// s1.convert_to_Polyhedron(p1);
|
||||
// f1.open("/Users/ken/Desktop/s1.off");
|
||||
// f1 << p1 << std::endl;
|
||||
// f1.close();
|
||||
}
|
||||
|
||||
bool is_plane = false;
|
||||
cgal_plane_t plane;
|
||||
if (!s2.is_valid()) {
|
||||
Logger::Message(Logger::LOG_ERROR, "s2: Not valid?", operand2->entity);
|
||||
return false;
|
||||
} else if (is_halfspace) {
|
||||
// std::cout << "s2: halfspace" << std::endl;
|
||||
IfcSchema::IfcHalfSpaceSolid *hss = static_cast<IfcSchema::IfcHalfSpaceSolid *>(operand2);
|
||||
IfcSchema::IfcSurface* surface = hss->BaseSurface();
|
||||
if (surface->is(IfcSchema::Type::IfcPlane) ) {
|
||||
is_plane = true;
|
||||
IfcGeom::CgalKernel::convert((IfcSchema::IfcPlane *)surface, plane);
|
||||
if (hss->AgreementFlag()) plane = plane.opposite();
|
||||
// std::ofstream fresult;
|
||||
// fresult.open("/Users/ken/Desktop/s2.off");
|
||||
// fresult << "OFF" << std::endl << "4 2 4" << std::endl;
|
||||
// // x = -5, y = -5, z = (5a +5b -d)/c
|
||||
// fresult << "-5 -5 " << (5.0*CGAL::to_double(plane.a())+5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl;
|
||||
// // x = -5, y = +5, z = (5a -5b -d)/c
|
||||
// fresult << "-5 5 " << (5.0*CGAL::to_double(plane.a())-5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl;
|
||||
// // x = 5, y = -5, z = (-5a +5b -d)/c
|
||||
// fresult << "5 -5 " << (-5.0*CGAL::to_double(plane.a())+5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl;
|
||||
// // x = 5, y = +5, z = (-5a -5b -d)/c
|
||||
// fresult << "5 5 " << (-5.0*CGAL::to_double(plane.a())-5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl;
|
||||
// fresult << "3 0 1 2" << std::endl;
|
||||
// fresult << "3 3 2 1" << std::endl;
|
||||
// fresult.close();
|
||||
}
|
||||
} else {
|
||||
// std::ofstream f2;
|
||||
// CGAL::Polyhedron_3<Kernel> p2;
|
||||
// s2.convert_to_Polyhedron(p2);
|
||||
// f2.open("/Users/ken/Desktop/s2.off");
|
||||
// f2 << p2 << std::endl;
|
||||
// f2.close();
|
||||
}
|
||||
|
||||
if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE) {
|
||||
|
||||
// std::cout << "Difference" << std::endl;
|
||||
CGAL::Nef_polyhedron_3<Kernel> nef_result;
|
||||
try {
|
||||
nef_result = CGAL::Nef_polyhedron_3<Kernel>(s1);
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_ERROR, "s1: cannot convert to Nef?", operand1->entity);
|
||||
return false;
|
||||
} if (is_halfspace) {
|
||||
if (is_plane) nef_result = nef_result.intersection(plane, CGAL::Nef_polyhedron_3<Kernel>::Intersection_mode::CLOSED_HALFSPACE);
|
||||
} else {
|
||||
CGAL::Nef_polyhedron_3<Kernel> nef_s2;
|
||||
try {
|
||||
nef_s2 = CGAL::Nef_polyhedron_3<Kernel>(s2);
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_ERROR, "s2: cannot convert to Nef?", operand2->entity);
|
||||
} nef_result -= nef_s2;
|
||||
}
|
||||
if (!nef_result.is_simple()) {
|
||||
Logger::Message(Logger::LOG_ERROR, "s2: not simple?", operand2->entity);
|
||||
return false;
|
||||
} else {
|
||||
// CGAL::Polyhedron_3<Kernel> result;
|
||||
// nef_result.convert_to_polyhedron(result);
|
||||
// std::ofstream fresult;
|
||||
// fresult.open("/Users/ken/Desktop/result.off");
|
||||
// fresult << result << std::endl;
|
||||
// fresult.close();
|
||||
} try {
|
||||
nef_result.convert_to_polyhedron(shape);
|
||||
return true;
|
||||
} catch (...) {
|
||||
std::cout << "IfcBooleanResult: cannot convert Nef to polyhedron!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_UNION) {
|
||||
|
||||
// std::cout << "Union" << std::endl;
|
||||
CGAL::Nef_polyhedron_3<Kernel> nef_result = CGAL::Nef_polyhedron_3<Kernel>(s1)+CGAL::Nef_polyhedron_3<Kernel>(s2);
|
||||
if (!nef_result.is_simple()) {
|
||||
std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl;
|
||||
return false;
|
||||
} else {
|
||||
// CGAL::Polyhedron_3<Kernel> result;
|
||||
// nef_result.convert_to_polyhedron(result);
|
||||
// std::ofstream fresult;
|
||||
// fresult.open("/Users/ken/Desktop/result.off");
|
||||
// fresult << result << std::endl;
|
||||
// fresult.close();
|
||||
} try {
|
||||
nef_result.convert_to_polyhedron(shape);
|
||||
return true;
|
||||
} catch (...) {
|
||||
std::cout << "IfcBooleanResult: cannot convert Nef to polyhedron!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_INTERSECTION) {
|
||||
|
||||
// std::cout << "Intersection" << std::endl;
|
||||
CGAL::Nef_polyhedron_3<Kernel> nef_result = CGAL::Nef_polyhedron_3<Kernel>(s1)*CGAL::Nef_polyhedron_3<Kernel>(s2);
|
||||
if (!nef_result.is_simple()) {
|
||||
std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl;
|
||||
return false;
|
||||
} else {
|
||||
// CGAL::Polyhedron_3<Kernel> result;
|
||||
// nef_result.convert_to_polyhedron(result);
|
||||
// std::ofstream fresult;
|
||||
// fresult.open("/Users/ken/Desktop/result.off");
|
||||
// fresult << result << std::endl;
|
||||
// fresult.close();
|
||||
} try {
|
||||
nef_result.convert_to_polyhedron(shape);
|
||||
return true;
|
||||
} catch (...) {
|
||||
std::cout << "IfcBooleanResult: cannot convert Nef to polyhedron!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
} return false;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcSphere* l, cgal_shape_t& shape) {
|
||||
const double r = l->Radius() * getValue(GV_LENGTH_UNIT);
|
||||
|
||||
// Make icosahedron
|
||||
float golden_ratio = (1.0+sqrtf(5.0))/2.0;
|
||||
float normalising_factor = sqrtf(golden_ratio*golden_ratio+1.0);
|
||||
std::vector<Kernel::Point_3> icosahedron_vertices;
|
||||
icosahedron_vertices.push_back(Kernel::Point_3(-1.0/normalising_factor, golden_ratio/normalising_factor, 0.0));
|
||||
icosahedron_vertices.push_back(Kernel::Point_3( 1.0/normalising_factor, golden_ratio/normalising_factor, 0.0));
|
||||
icosahedron_vertices.push_back(Kernel::Point_3(-1.0/normalising_factor, -golden_ratio/normalising_factor, 0.0));
|
||||
icosahedron_vertices.push_back(Kernel::Point_3( 1.0/normalising_factor, -golden_ratio/normalising_factor, 0.0));
|
||||
icosahedron_vertices.push_back(Kernel::Point_3(0.0, -1.0/normalising_factor, golden_ratio/normalising_factor));
|
||||
icosahedron_vertices.push_back(Kernel::Point_3(0.0, 1.0/normalising_factor, golden_ratio/normalising_factor));
|
||||
icosahedron_vertices.push_back(Kernel::Point_3(0.0, -1.0/normalising_factor, -golden_ratio/normalising_factor));
|
||||
icosahedron_vertices.push_back(Kernel::Point_3(0.0, 1.0/normalising_factor, -golden_ratio/normalising_factor));
|
||||
icosahedron_vertices.push_back(Kernel::Point_3( golden_ratio/normalising_factor, 0.0, -1.0/normalising_factor));
|
||||
icosahedron_vertices.push_back(Kernel::Point_3( golden_ratio/normalising_factor, 0.0, 1.0/normalising_factor));
|
||||
icosahedron_vertices.push_back(Kernel::Point_3(-golden_ratio/normalising_factor, 0.0, -1.0/normalising_factor));
|
||||
icosahedron_vertices.push_back(Kernel::Point_3(-golden_ratio/normalising_factor, 0.0, 1.0/normalising_factor));
|
||||
|
||||
std::list<cgal_face_t> face_list;
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[0]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[11]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[5]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[0]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[5]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[1]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[0]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[1]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[7]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[0]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[7]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[10]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[0]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[10]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[11]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[1]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[5]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[9]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[5]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[11]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[4]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[11]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[10]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[2]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[10]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[7]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[6]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[7]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[1]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[8]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[3]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[9]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[4]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[3]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[4]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[2]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[3]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[2]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[6]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[3]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[6]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[8]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[3]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[8]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[9]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[4]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[9]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[5]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[2]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[4]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[11]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[6]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[2]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[10]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[8]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[6]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[7]);
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(icosahedron_vertices[9]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[8]);
|
||||
face_list.back().outer.push_back(icosahedron_vertices[1]);
|
||||
|
||||
const unsigned int refinements = 2;
|
||||
for (unsigned int current_refinement = 0; current_refinement < refinements; ++current_refinement) {
|
||||
std::list<cgal_face_t> refined_face_list;
|
||||
for (auto &face: face_list) {
|
||||
Kernel::Point_3 vertex0 = face.outer[0];
|
||||
Kernel::Point_3 vertex1 = face.outer[1];
|
||||
Kernel::Point_3 vertex2 = face.outer[2];
|
||||
|
||||
Kernel::Point_3 midpoint01 = CGAL::midpoint(vertex0, vertex1);
|
||||
Kernel::Point_3 midpoint12 = CGAL::midpoint(vertex1, vertex2);
|
||||
Kernel::Point_3 midpoint20 = CGAL::midpoint(vertex2, vertex0);
|
||||
|
||||
double midpoint01_distance_to_origin = sqrt(CGAL::to_double(CGAL::squared_distance(midpoint01, Kernel::Point_3(0, 0, 0))));
|
||||
midpoint01 = Kernel::Point_3(midpoint01.x()/midpoint01_distance_to_origin,
|
||||
midpoint01.y()/midpoint01_distance_to_origin,
|
||||
midpoint01.z()/midpoint01_distance_to_origin);
|
||||
double midpoint12_distance_to_origin = sqrt(CGAL::to_double(CGAL::squared_distance(midpoint12, Kernel::Point_3(0, 0, 0))));
|
||||
midpoint12 = Kernel::Point_3(midpoint12.x()/midpoint12_distance_to_origin,
|
||||
midpoint12.y()/midpoint12_distance_to_origin,
|
||||
midpoint12.z()/midpoint12_distance_to_origin);
|
||||
double midpoint20_distance_to_origin = sqrt(CGAL::to_double(CGAL::squared_distance(midpoint20, Kernel::Point_3(0, 0, 0))));
|
||||
midpoint20 = Kernel::Point_3(midpoint20.x()/midpoint20_distance_to_origin,
|
||||
midpoint20.y()/midpoint20_distance_to_origin,
|
||||
midpoint20.z()/midpoint20_distance_to_origin);
|
||||
|
||||
refined_face_list.push_back(cgal_face_t());
|
||||
refined_face_list.back().outer.push_back(vertex0);
|
||||
refined_face_list.back().outer.push_back(midpoint01);
|
||||
refined_face_list.back().outer.push_back(midpoint20);
|
||||
|
||||
refined_face_list.push_back(cgal_face_t());
|
||||
refined_face_list.back().outer.push_back(vertex1);
|
||||
refined_face_list.back().outer.push_back(midpoint12);
|
||||
refined_face_list.back().outer.push_back(midpoint01);
|
||||
|
||||
refined_face_list.push_back(cgal_face_t());
|
||||
refined_face_list.back().outer.push_back(vertex2);
|
||||
refined_face_list.back().outer.push_back(midpoint20);
|
||||
refined_face_list.back().outer.push_back(midpoint12);
|
||||
|
||||
refined_face_list.push_back(cgal_face_t());
|
||||
refined_face_list.back().outer.push_back(midpoint01);
|
||||
refined_face_list.back().outer.push_back(midpoint12);
|
||||
refined_face_list.back().outer.push_back(midpoint20);
|
||||
} face_list = refined_face_list;
|
||||
}
|
||||
|
||||
cgal_placement_t trsf;
|
||||
IfcGeom::CgalKernel::convert(l->Position(),trsf);
|
||||
|
||||
shape = create_polyhedron(face_list);
|
||||
for (auto &vertex: vertices(shape)) {
|
||||
vertex->point() = Kernel::Point_3(r*vertex->point().x(),
|
||||
r*vertex->point().y(),
|
||||
r*vertex->point().z());
|
||||
vertex->point() = vertex->point().transform(trsf);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangularPyramid* l, cgal_shape_t& shape) {
|
||||
const double dx = l->XLength() * getValue(GV_LENGTH_UNIT);
|
||||
const double dy = l->YLength() * getValue(GV_LENGTH_UNIT);
|
||||
const double dz = l->Height() * getValue(GV_LENGTH_UNIT);
|
||||
|
||||
std::list<cgal_face_t> face_list;
|
||||
|
||||
// Base
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, 0, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(dx, 0, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(dx, dy, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, dy, 0));
|
||||
|
||||
// Lateral faces
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, 0, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, dy, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0.5*dx, 0.5*dy, dz));
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, dy, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(dx, dy, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0.5*dx, 0.5*dy, dz));
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(Kernel::Point_3(dx, dy, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(dx, 0, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0.5*dx, 0.5*dy, dz));
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(Kernel::Point_3(dx, 0, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, 0, 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0.5*dx, 0.5*dy, dz));
|
||||
|
||||
cgal_placement_t trsf;
|
||||
IfcGeom::CgalKernel::convert(l->Position(),trsf);
|
||||
|
||||
shape = create_polyhedron(face_list);
|
||||
for (auto &vertex: vertices(shape)) vertex->point() = vertex->point().transform(trsf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCylinder* l, cgal_shape_t& shape) {
|
||||
const double r = l->Radius() * getValue(GV_LENGTH_UNIT);
|
||||
const double h = l->Height() * getValue(GV_LENGTH_UNIT);
|
||||
|
||||
std::list<cgal_face_t> face_list;
|
||||
|
||||
const int segments = 12;
|
||||
|
||||
// Base
|
||||
face_list.push_back(cgal_face_t());
|
||||
for (int current_segment = 0; current_segment < segments; ++current_segment) {
|
||||
double current_angle = current_segment*2.0*3.141592653589793/((double)segments);
|
||||
face_list.back().outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0));
|
||||
}
|
||||
|
||||
// Side faces
|
||||
for (int current_segment = 0; current_segment < segments; ++current_segment) {
|
||||
double current_angle = current_segment*2.0*3.141592653589793/((double)segments);
|
||||
int next_segment = (current_segment+1)%segments;
|
||||
double next_angle = next_segment*2.0*3.141592653589793/((double)segments);
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(Kernel::Point_3(r*cos(next_angle), r*sin(next_angle), 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), h));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(r*cos(next_angle), r*sin(next_angle), h));
|
||||
}
|
||||
|
||||
// Top
|
||||
face_list.push_back(cgal_face_t());
|
||||
for (int current_segment = segments-1; current_segment >= 0; --current_segment) {
|
||||
double current_angle = current_segment*2.0*3.141592653589793/((double)segments);
|
||||
face_list.back().outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), h));
|
||||
}
|
||||
|
||||
cgal_placement_t trsf;
|
||||
IfcGeom::CgalKernel::convert(l->Position(),trsf);
|
||||
|
||||
shape = create_polyhedron(face_list);
|
||||
for (auto &vertex: vertices(shape)) vertex->point() = vertex->point().transform(trsf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCone* l, cgal_shape_t& shape) {
|
||||
const double r = l->BottomRadius() * getValue(GV_LENGTH_UNIT);
|
||||
const double h = l->Height() * getValue(GV_LENGTH_UNIT);
|
||||
|
||||
std::list<cgal_face_t> face_list;
|
||||
|
||||
const int segments = 12;
|
||||
|
||||
// Base
|
||||
face_list.push_back(cgal_face_t());
|
||||
for (int current_segment = 0; current_segment < segments; ++current_segment) {
|
||||
double current_angle = current_segment*2.0*3.141592653589793/((double)segments);
|
||||
face_list.back().outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0));
|
||||
}
|
||||
|
||||
// Side faces
|
||||
for (int current_segment = 0; current_segment < segments; ++current_segment) {
|
||||
double current_angle = current_segment*2.0*3.141592653589793/((double)segments);
|
||||
int next_segment = (current_segment+1)%segments;
|
||||
double next_angle = next_segment*2.0*3.141592653589793/((double)segments);
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(Kernel::Point_3(r*cos(next_angle), r*sin(next_angle), 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0));
|
||||
face_list.back().outer.push_back(Kernel::Point_3(0, 0, h));
|
||||
}
|
||||
|
||||
cgal_placement_t trsf;
|
||||
IfcGeom::CgalKernel::convert(l->Position(),trsf);
|
||||
|
||||
shape = create_polyhedron(face_list);
|
||||
for (auto &vertex: vertices(shape)) vertex->point() = vertex->point().transform(trsf);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_IFC4
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTriangulatedFaceSet* l, cgal_shape_t& shape) {
|
||||
IfcSchema::IfcCartesianPointList3D* point_list = l->Coordinates();
|
||||
const std::vector< std::vector<double> > coordinates = point_list->CoordList();
|
||||
std::vector<cgal_point_t> points;
|
||||
points.reserve(coordinates.size());
|
||||
for (std::vector< std::vector<double> >::const_iterator it = coordinates.begin(); it != coordinates.end(); ++it) {
|
||||
const std::vector<double>& coords = *it;
|
||||
if (coords.size() != 3) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Invalid dimensions encountered on Coordinates", l->entity);
|
||||
return false;
|
||||
}
|
||||
points.push_back(Kernel::Point_3(coords[0] * getValue(GV_LENGTH_UNIT),
|
||||
coords[1] * getValue(GV_LENGTH_UNIT),
|
||||
coords[2] * getValue(GV_LENGTH_UNIT)));
|
||||
}
|
||||
|
||||
std::vector< std::vector<int> > indices = l->CoordIndex();
|
||||
|
||||
std::list<cgal_face_t> face_list;
|
||||
|
||||
for(std::vector< std::vector<int> >::const_iterator it = indices.begin(); it != indices.end(); ++ it) {
|
||||
const std::vector<int>& tri = *it;
|
||||
if (tri.size() != 3) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Invalid dimensions encountered on CoordIndex", l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
const int min_index = *std::min_element(tri.begin(), tri.end());
|
||||
const int max_index = *std::max_element(tri.begin(), tri.end());
|
||||
|
||||
if (min_index < 1 || max_index > (int) points.size()) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Contents of CoordIndex out of bounds", l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
const Kernel::Point_3& a = points[tri[0] - 1]; // account for zero- vs
|
||||
const Kernel::Point_3& b = points[tri[1] - 1]; // one-based indices in
|
||||
const Kernel::Point_3& c = points[tri[2] - 1]; // c++ and express
|
||||
|
||||
face_list.push_back(cgal_face_t());
|
||||
face_list.back().outer.push_back(a);
|
||||
face_list.back().outer.push_back(b);
|
||||
face_list.back().outer.push_back(c);
|
||||
}
|
||||
|
||||
shape = create_polyhedron(face_list);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcHalfSpaceSolid* l, cgal_shape_t& shape) {
|
||||
IfcSchema::IfcSurface* surface = l->BaseSurface();
|
||||
if ( ! surface->is(IfcSchema::Type::IfcPlane) ) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Unsupported BaseSurface:", surface->entity);
|
||||
return false;
|
||||
}
|
||||
cgal_plane_t pln;
|
||||
IfcGeom::CgalKernel::convert((IfcSchema::IfcPlane*)surface,pln);
|
||||
|
||||
// TODO: Don't fully understand the logic here. Might be incorrect.
|
||||
if (l->AgreementFlag()) pln = pln.opposite();
|
||||
// const gp_Pnt pnt = pln.Location().Translated( l->AgreementFlag() ? -pln.Axis().Direction() : pln.Axis().Direction());
|
||||
// shape = BRepPrimAPI_MakeHalfSpace(BRepBuilderAPI_MakeFace(pln),pnt).Solid();
|
||||
|
||||
// TODO: For now we do nothing and process halfspaces in IfcBooleanResult, which likely doesn't capture all cases.
|
||||
// Find a better solution later (with an abstract shape class?)
|
||||
shape = CGAL::Polyhedron_3<Kernel>();
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
#include "CgalKernel.h"
|
||||
#include "CgalConversionResult.h"
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRepresentation* l, ConversionResults& shapes) {
|
||||
IfcSchema::IfcRepresentationItem::list::ptr items = l->Items();
|
||||
bool part_succes = false;
|
||||
if (items->size()) {
|
||||
for (IfcSchema::IfcRepresentationItem::list::it it = items->begin(); it != items->end(); ++it) {
|
||||
IfcSchema::IfcRepresentationItem* representation_item = *it;
|
||||
if (shape_type(representation_item) == ST_SHAPELIST) {
|
||||
part_succes |= convert_shapes(*it, shapes);
|
||||
} else {
|
||||
cgal_shape_t s;
|
||||
if (convert_shape(representation_item, s)) {
|
||||
shapes.push_back(ConversionResult(new CgalShape(s), get_style(representation_item)));
|
||||
part_succes |= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return part_succes;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcGeometricSet* l, ConversionResults& shapes) {
|
||||
IfcEntityList::ptr elements = l->Elements();
|
||||
if ( !elements->size() ) return false;
|
||||
bool part_succes = false;
|
||||
const IfcGeom::SurfaceStyle* parent_style = get_style(l);
|
||||
for ( IfcEntityList::it it = elements->begin(); it != elements->end(); ++ it ) {
|
||||
IfcSchema::IfcGeometricSetSelect* element = *it;
|
||||
cgal_shape_t s;
|
||||
if (convert_shape(element, s)) {
|
||||
part_succes = true;
|
||||
const IfcGeom::SurfaceStyle* style = 0;
|
||||
if (element->is(IfcSchema::Type::IfcPoint)) {
|
||||
style = get_style((IfcSchema::IfcPoint*) element);
|
||||
} else if (element->is(IfcSchema::Type::IfcCurve)) {
|
||||
style = get_style((IfcSchema::IfcCurve*) element);
|
||||
} else if (element->is(IfcSchema::Type::IfcSurface)) {
|
||||
style = get_style((IfcSchema::IfcSurface*) element);
|
||||
}
|
||||
shapes.push_back(ConversionResult(new CgalShape(s), style ? style : parent_style));
|
||||
}
|
||||
}
|
||||
return part_succes;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::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 ) {
|
||||
cgal_shape_t s;
|
||||
const SurfaceStyle* shell_style = 0;
|
||||
if ((*it)->is(IfcSchema::Type::IfcRepresentationItem)) {
|
||||
shell_style = get_style((IfcSchema::IfcRepresentationItem*)*it);
|
||||
}
|
||||
if (convert_shape(*it,s)) {
|
||||
shapes.push_back(ConversionResult(new CgalShape(s), shell_style ? shell_style : collective_style));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, ConversionResults& shape) {
|
||||
cgal_shape_t s;
|
||||
const SurfaceStyle* collective_style = get_style(l);
|
||||
if (convert_shape(l->Outer(),s) ) {
|
||||
CGAL::Nef_polyhedron_3<Kernel> nef_s = create_nef_polyhedron(s);
|
||||
const SurfaceStyle* indiv_style = get_style(l->Outer());
|
||||
|
||||
IfcSchema::IfcClosedShell::list::ptr voids(new IfcSchema::IfcClosedShell::list);
|
||||
if (l->is(IfcSchema::Type::IfcFacetedBrepWithVoids)) {
|
||||
voids = l->as<IfcSchema::IfcFacetedBrepWithVoids>()->Voids();
|
||||
}
|
||||
#ifdef USE_IFC4
|
||||
if (l->is(IfcSchema::Type::IfcAdvancedBrepWithVoids)) {
|
||||
voids = l->as<IfcSchema::IfcAdvancedBrepWithVoids>()->Voids();
|
||||
}
|
||||
#endif
|
||||
|
||||
for (IfcSchema::IfcClosedShell::list::it it = voids->begin(); it != voids->end(); ++it) {
|
||||
cgal_shape_t s2;
|
||||
// TODO: This looks weird. Aren't we removing the outer shell again and again?
|
||||
// Maybe it should be
|
||||
// if (convert_shape(*it, s2)) {
|
||||
if (convert_shape(l->Outer(), s2)) {
|
||||
nef_s -= CGAL::Nef_polyhedron_3<Kernel>(s2);
|
||||
}
|
||||
}
|
||||
|
||||
s = create_polyhedron(nef_s);
|
||||
shape.push_back(ConversionResult(new CgalShape(s), indiv_style ? indiv_style : collective_style));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcMappedItem* l, ConversionResults& shapes) {
|
||||
cgal_placement_t gtrsf;
|
||||
IfcSchema::IfcCartesianTransformationOperator* transform = l->MappingTarget();
|
||||
if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3DnonUniform) ) {
|
||||
IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3DnonUniform*)transform,gtrsf);
|
||||
} else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2DnonUniform) ) {
|
||||
IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator2DnonUniform*)transform,gtrsf);
|
||||
} else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3D) ) {
|
||||
IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3D*)transform,gtrsf);
|
||||
} else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2D) ) {
|
||||
IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator2D*)transform,gtrsf);
|
||||
}
|
||||
IfcSchema::IfcRepresentationMap* map = l->MappingSource();
|
||||
IfcSchema::IfcAxis2Placement* placement = map->MappingOrigin();
|
||||
cgal_placement_t trsf;
|
||||
if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) {
|
||||
IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf);
|
||||
} else {
|
||||
cgal_placement_t trsf_2d;
|
||||
IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf_2d);
|
||||
trsf = trsf_2d;
|
||||
}
|
||||
|
||||
// TODO: Check
|
||||
gtrsf = trsf * gtrsf;
|
||||
|
||||
// std::cout << std::endl;
|
||||
// for (int i = 0; i < 3; ++i) {
|
||||
// for (int j = 0; j < 4; ++j) {
|
||||
// std::cout << gtrsf.cartesian(i, j) << " ";
|
||||
// } std::cout << std::endl;
|
||||
// }
|
||||
|
||||
const IfcGeom::SurfaceStyle* mapped_item_style = get_style(l);
|
||||
|
||||
const size_t previous_size = shapes.size();
|
||||
bool b = convert_shapes(map->MappedRepresentation(), shapes);
|
||||
|
||||
for (size_t i = previous_size; i < shapes.size(); ++ i ) {
|
||||
IfcGeom::CgalPlacement place(gtrsf);
|
||||
shapes[i].prepend(&place);
|
||||
|
||||
// Apply styles assigned to the mapped item only if on
|
||||
// a more granular level no styles have been applied
|
||||
if (!shapes[i].hasStyle()) {
|
||||
shapes[i].setStyle(mapped_item_style);
|
||||
}
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::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);
|
||||
for( IfcSchema::IfcConnectedFaceSet::list::it it = facesets->begin(); it != facesets->end(); ++ it ) {
|
||||
cgal_shape_t s;
|
||||
const SurfaceStyle* shell_style = get_style(*it);
|
||||
if (convert_shape(*it,s)) {
|
||||
shapes.push_back(ConversionResult(new CgalShape(s), shell_style ? shell_style : collective_style));
|
||||
part_success |= true;
|
||||
}
|
||||
}
|
||||
return part_success;
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
// For MSVC to have M_PI
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <cmath>
|
||||
|
||||
#include "CgalKernel.h"
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& result) {
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points = l->Polygon();
|
||||
|
||||
// Parse and store the points in a sequence
|
||||
cgal_wire_t polygon = std::vector<Kernel::Point_3>();
|
||||
for(IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it) {
|
||||
cgal_point_t pnt;
|
||||
IfcGeom::CgalKernel::convert(*it, pnt);
|
||||
polygon.push_back(pnt);
|
||||
}
|
||||
|
||||
// A loop should consist of at least three vertices
|
||||
std::size_t original_count = polygon.size();
|
||||
if (original_count < 3) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove points that are too close to one another
|
||||
remove_duplicate_points_from_loop(polygon);
|
||||
|
||||
std::size_t count = polygon.size();
|
||||
if (original_count - count != 0) {
|
||||
std::stringstream ss; ss << (original_count - count) << " edges removed for:";
|
||||
Logger::Message(Logger::LOG_WARNING, ss.str(), l->entity);
|
||||
}
|
||||
|
||||
if (count < 3) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
result = polygon;
|
||||
|
||||
// std::cout << "PolyLoop: " << std::endl;
|
||||
// for (auto &point: polygon) {
|
||||
// std::cout << "\tPoint(" << point << ")" << std::endl;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyline* l, cgal_wire_t& result) {
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points = l->Points();
|
||||
|
||||
// Parse and store the points in a sequence
|
||||
cgal_wire_t polygon = std::vector<Kernel::Point_3>();
|
||||
for(IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it) {
|
||||
cgal_point_t pnt;
|
||||
IfcGeom::CgalKernel::convert(*it, pnt);
|
||||
polygon.push_back(pnt);
|
||||
}
|
||||
|
||||
// Remove points that are too close to one another
|
||||
remove_duplicate_points_from_loop(polygon);
|
||||
|
||||
result = polygon;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcEdgeLoop* l, cgal_wire_t& result) {
|
||||
IfcSchema::IfcOrientedEdge::list::ptr li = l->EdgeList();
|
||||
cgal_wire_t mw;
|
||||
for (IfcSchema::IfcOrientedEdge::list::it it = li->begin(); it != li->end(); ++it) {
|
||||
cgal_wire_t w;
|
||||
if (convert_wire(*it, w)) {
|
||||
// TODO: What to do here? Add some points only?
|
||||
// mw.Add(TopoDS::Edge(TopoDS_Iterator(w).Value()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
result = mw;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcOrientedEdge* l, cgal_wire_t& result) {
|
||||
if (convert_wire(l->EdgeElement(), result)) {
|
||||
if (!l->Orientation()) {
|
||||
std::reverse(result.begin(),result.end());
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcEdge* l, cgal_wire_t& result) {
|
||||
if (!l->EdgeStart()->is(IfcSchema::Type::IfcVertexPoint) || !l->EdgeEnd()->is(IfcSchema::Type::IfcVertexPoint)) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Only IfcVertexPoints are supported for EdgeStart and -End", l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
IfcSchema::IfcPoint* pnt1 = ((IfcSchema::IfcVertexPoint*) l->EdgeStart())->VertexGeometry();
|
||||
IfcSchema::IfcPoint* pnt2 = ((IfcSchema::IfcVertexPoint*) l->EdgeEnd())->VertexGeometry();
|
||||
if (!pnt1->is(IfcSchema::Type::IfcCartesianPoint) || !pnt2->is(IfcSchema::Type::IfcCartesianPoint)) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Only IfcCartesianPoints are supported for VertexGeometry", l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
cgal_point_t p1, p2;
|
||||
if (!convert(((IfcSchema::IfcCartesianPoint*)pnt1), p1) ||
|
||||
!convert(((IfcSchema::IfcCartesianPoint*)pnt2), p2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
cgal_wire_t mw;
|
||||
mw.push_back(p1);
|
||||
mw.push_back(p2);
|
||||
|
||||
result = mw;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCompositeCurve* l, cgal_wire_t& wire) {
|
||||
if ( getValue(GV_PLANEANGLE_UNIT)<0 ) {
|
||||
Logger::Message(Logger::LOG_WARNING,"Creating a composite curve without unit information:",l->entity);
|
||||
|
||||
// Temporarily pretend we do have unit information
|
||||
setValue(GV_PLANEANGLE_UNIT,1.0);
|
||||
|
||||
bool succes_radians = false;
|
||||
bool succes_degrees = false;
|
||||
bool use_radians = false;
|
||||
bool use_degrees = false;
|
||||
|
||||
// First try radians
|
||||
cgal_wire_t wire_radians, wire_degrees;
|
||||
try {
|
||||
succes_radians = IfcGeom::CgalKernel::convert(l,wire_radians);
|
||||
} catch (...) {}
|
||||
|
||||
// Now try degrees
|
||||
setValue(GV_PLANEANGLE_UNIT,0.0174532925199433);
|
||||
try {
|
||||
succes_degrees = IfcGeom::CgalKernel::convert(l,wire_degrees);
|
||||
} catch (...) {}
|
||||
|
||||
// Restore to unknown unit state
|
||||
setValue(GV_PLANEANGLE_UNIT,-1.0);
|
||||
|
||||
if ( succes_degrees && ! succes_radians ) {
|
||||
use_degrees = true;
|
||||
} else if ( succes_radians && ! succes_degrees ) {
|
||||
use_radians = true;
|
||||
} else if ( succes_radians && succes_degrees ) {
|
||||
if ( wire_degrees.back() == wire_degrees.front() && wire_radians.back() != wire_radians.front() ) {
|
||||
use_degrees = true;
|
||||
} else if ( wire_radians.back() == wire_radians.front() && wire_degrees.back() != wire_degrees.front() ) {
|
||||
use_radians = true;
|
||||
} else {
|
||||
// No heuristic left to prefer the one over the other,
|
||||
// apparently both variants are equally succesful.
|
||||
// The curve might be composed of only straight segments.
|
||||
// Let's go with the wire created using radians as that
|
||||
// at least is a SI unit.
|
||||
use_radians = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( use_radians ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Used radians to create composite curve");
|
||||
wire = wire_radians;
|
||||
} else if ( use_degrees ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Used degrees to create composite curve");
|
||||
wire = wire_degrees;
|
||||
}
|
||||
|
||||
return use_radians || use_degrees;
|
||||
}
|
||||
IfcSchema::IfcCompositeCurveSegment::list::ptr segments = l->Segments();
|
||||
cgal_wire_t w;
|
||||
//TopoDS_Vertex last_vertex;
|
||||
for( IfcSchema::IfcCompositeCurveSegment::list::it it = segments->begin(); it != segments->end(); ++ it ) {
|
||||
IfcSchema::IfcCurve* curve = (*it)->ParentCurve();
|
||||
cgal_wire_t wire2;
|
||||
if ( !convert_wire(curve,wire2) ) {
|
||||
Logger::Message(Logger::LOG_ERROR,"Failed to convert curve:",curve->entity);
|
||||
continue;
|
||||
}
|
||||
if ( ! (*it)->SameSense() ) std::reverse(wire2.begin(),wire2.end());
|
||||
|
||||
if (wire2.empty()) {
|
||||
continue;
|
||||
} else if (w.empty()) {
|
||||
w = wire2;
|
||||
} else if (w.back() == w.front()) {
|
||||
std::vector<Kernel::Point_3>::const_iterator vertex = wire2.begin();
|
||||
++vertex;
|
||||
while (vertex != wire2.end()) {
|
||||
w.push_back(*vertex);
|
||||
++vertex;
|
||||
}
|
||||
} else {
|
||||
for (auto &vertex: wire2) w.push_back(vertex);
|
||||
}
|
||||
}
|
||||
|
||||
remove_duplicate_points_from_loop(w);
|
||||
|
||||
wire = w;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTrimmedCurve* l, cgal_wire_t& wire) {
|
||||
IfcSchema::IfcCurve* basis_curve = l->BasisCurve();
|
||||
bool isConic = basis_curve->is(IfcSchema::Type::IfcConic);
|
||||
double parameterFactor = isConic ? getValue(GV_PLANEANGLE_UNIT) : getValue(GV_LENGTH_UNIT);
|
||||
cgal_curve_t curve;
|
||||
if ( !convert_curve(basis_curve,curve) ) return false;
|
||||
bool trim_cartesian = l->MasterRepresentation() == IfcSchema::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN;
|
||||
IfcEntityList::ptr trims1 = l->Trim1();
|
||||
IfcEntityList::ptr trims2 = l->Trim2();
|
||||
unsigned sense_agreement = l->SenseAgreement() ? 0 : 1;
|
||||
double flts[2];
|
||||
cgal_point_t pnts[2];
|
||||
bool has_flts[2] = {false,false};
|
||||
bool has_pnts[2] = {false,false};
|
||||
cgal_wire_t w;
|
||||
for ( IfcEntityList::it it = trims1->begin(); it != trims1->end(); it ++ ) {
|
||||
IfcUtil::IfcBaseClass* i = *it;
|
||||
if ( i->is(IfcSchema::Type::IfcCartesianPoint) ) {
|
||||
IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianPoint*)i, pnts[sense_agreement] );
|
||||
has_pnts[sense_agreement] = true;
|
||||
} else if ( i->is(IfcSchema::Type::IfcParameterValue) ) {
|
||||
const double value = *((IfcSchema::IfcParameterValue*)i);
|
||||
flts[sense_agreement] = value * parameterFactor;
|
||||
has_flts[sense_agreement] = true;
|
||||
}
|
||||
}
|
||||
for ( IfcEntityList::it it = trims2->begin(); it != trims2->end(); it ++ ) {
|
||||
IfcUtil::IfcBaseClass* i = *it;
|
||||
if ( i->is(IfcSchema::Type::IfcCartesianPoint) ) {
|
||||
IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianPoint*)i, pnts[1-sense_agreement] );
|
||||
has_pnts[1-sense_agreement] = true;
|
||||
} else if ( i->is(IfcSchema::Type::IfcParameterValue) ) {
|
||||
const double value = *((IfcSchema::IfcParameterValue*)i);
|
||||
flts[1-sense_agreement] = value * parameterFactor;
|
||||
has_flts[1-sense_agreement] = true;
|
||||
}
|
||||
}
|
||||
trim_cartesian &= has_pnts[0] && has_pnts[1];
|
||||
bool trim_cartesian_failed = !trim_cartesian;
|
||||
if ( trim_cartesian ) {
|
||||
// TODO: Project points to closest point in curve?
|
||||
if ( CGAL::squared_distance(pnts[0], pnts[1]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE) ) {
|
||||
Logger::Message(Logger::LOG_WARNING,"Skipping segment with length below tolerance level:",l->entity);
|
||||
return false;
|
||||
}
|
||||
if (l->SenseAgreement()) {
|
||||
bool found = false;
|
||||
int loops_to_go = 2;
|
||||
std::vector<Kernel::Point_3>::const_iterator point = curve.begin();
|
||||
do {
|
||||
if (!found) {
|
||||
if (CGAL::squared_distance(*point, pnts[0]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE)) {
|
||||
found = true;
|
||||
w.push_back(*point);
|
||||
}
|
||||
} else {
|
||||
w.push_back(*point);
|
||||
if (CGAL::squared_distance(*point, pnts[1]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE)) {
|
||||
break;
|
||||
}
|
||||
} ++point;
|
||||
if (point == curve.end()) {
|
||||
point = curve.begin();
|
||||
--loops_to_go;
|
||||
}
|
||||
} while (point != curve.begin() && loops_to_go > 0);
|
||||
} else {
|
||||
bool found = false;
|
||||
int loops_to_go = 2;
|
||||
std::vector<Kernel::Point_3>::const_reverse_iterator point = curve.rbegin();
|
||||
do {
|
||||
if (!found) {
|
||||
if (CGAL::squared_distance(*point, pnts[0]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE)) {
|
||||
found = true;
|
||||
w.push_back(*point);
|
||||
}
|
||||
} else {
|
||||
w.push_back(*point);
|
||||
if (CGAL::squared_distance(*point, pnts[1]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE)) {
|
||||
break;
|
||||
}
|
||||
} ++point;
|
||||
if (point == curve.rend() && loops_to_go > 0) point = curve.rbegin();
|
||||
} while (point != curve.rbegin());
|
||||
}
|
||||
}
|
||||
if ( (!trim_cartesian || trim_cartesian_failed) && (has_flts[0] && has_flts[1]) ) {
|
||||
// The Geom_Line is constructed from a gp_Pnt and gp_Dir, whereas the IfcLine
|
||||
// is defined by an IfcCartesianPoint and an IfcVector with Magnitude. Because
|
||||
// the vector is normalised when passed to Geom_Line constructor the magnitude
|
||||
// needs to be factored in with the IfcParameterValue here.
|
||||
if ( basis_curve->is(IfcSchema::Type::IfcLine) ) {
|
||||
IfcSchema::IfcLine* line = static_cast<IfcSchema::IfcLine*>(basis_curve);
|
||||
const double magnitude = line->Dir()->Magnitude();
|
||||
flts[0] *= magnitude; flts[1] *= magnitude;
|
||||
}
|
||||
if ( isConic && ALMOST_THE_SAME(fmod(flts[1]-flts[0],M_PI*2.),0.) ) {
|
||||
for (auto &point: curve) w.push_back(point);
|
||||
} else {
|
||||
const int segments_of_full_curve = 12;
|
||||
double segment_angle = 2.0*3.141592653589793/segments_of_full_curve;
|
||||
if ( basis_curve->is(IfcSchema::Type::IfcEllipse) ) {
|
||||
IfcSchema::IfcEllipse* ellipse = static_cast<IfcSchema::IfcEllipse*>(basis_curve);
|
||||
double x = ellipse->SemiAxis1() * getValue(GV_LENGTH_UNIT);
|
||||
double y = ellipse->SemiAxis2() * getValue(GV_LENGTH_UNIT);
|
||||
for (double current_angle = flts[0]; current_angle < flts[1]; current_angle += segment_angle) {
|
||||
w.push_back(Kernel::Point_3(x*cos(current_angle), y*sin(current_angle), 0));
|
||||
} w.push_back(Kernel::Point_3(x*cos(flts[1]), y*sin(flts[1]), 0));
|
||||
} if ( basis_curve->is(IfcSchema::Type::IfcCircle) ) {
|
||||
IfcSchema::IfcCircle* circle = static_cast<IfcSchema::IfcCircle*>(basis_curve);
|
||||
double r = circle->Radius() * getValue(GV_LENGTH_UNIT);
|
||||
for (double current_angle = flts[0]; current_angle < flts[1]; current_angle += segment_angle) {
|
||||
w.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0));
|
||||
} w.push_back(Kernel::Point_3(r*cos(flts[1]), r*sin(flts[1]), 0));
|
||||
}
|
||||
}
|
||||
} else if ( trim_cartesian_failed && (has_pnts[0] && has_pnts[1]) ) {
|
||||
w.push_back(pnts[0]);
|
||||
w.push_back(pnts[1]);
|
||||
}
|
||||
wire = w;
|
||||
return true;
|
||||
}
|
||||
@@ -89,6 +89,167 @@ bool IfcGeom::CgalKernel::validate_quantities(const IfcSchema::IfcProduct* produ
|
||||
}
|
||||
|
||||
bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* product, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const IfcGeom::ConversionResults& shapes, const IfcGeom::ConversionResultPlacement* trsf, IfcGeom::ConversionResults& opened_shapes) {
|
||||
throw std::runtime_error("not implemented");
|
||||
std::list<cgal_shape_t> opening_shapelist;
|
||||
|
||||
for ( IfcSchema::IfcRelVoidsElement::list::it it = openings->begin(); it != openings->end(); ++ it ) {
|
||||
IfcSchema::IfcRelVoidsElement* v = *it;
|
||||
IfcSchema::IfcFeatureElementSubtraction* fes = v->RelatedOpeningElement();
|
||||
if ( fes->is(IfcSchema::Type::IfcOpeningElement) ) {
|
||||
if (!fes->hasRepresentation()) continue;
|
||||
|
||||
// Convert the IfcRepresentation of the IfcOpeningElement
|
||||
cgal_placement_t opening_trsf;
|
||||
if (fes->hasObjectPlacement()) {
|
||||
try {
|
||||
convert(fes->ObjectPlacement(),opening_trsf);
|
||||
} catch (...) {}
|
||||
}
|
||||
|
||||
// Move the opening into the coordinate system of the IfcProduct
|
||||
opening_trsf = entity_trsf.inverse() * opening_trsf;
|
||||
|
||||
IfcSchema::IfcProductRepresentation* prodrep = fes->Representation();
|
||||
IfcSchema::IfcRepresentation::list::ptr reps = prodrep->Representations();
|
||||
|
||||
IfcGeom::ConversionResults opening_shapes;
|
||||
|
||||
for ( IfcSchema::IfcRepresentation::list::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) {
|
||||
convert_shapes(*it2,opening_shapes);
|
||||
}
|
||||
|
||||
for ( unsigned int i = 0; i < opening_shapes.size(); ++ i ) {
|
||||
cgal_placement_t gtrsf;
|
||||
if (opening_shapes[i].Placement()) {
|
||||
gtrsf = *(CgalPlacement*)opening_shapes[i].Placement();
|
||||
}
|
||||
gtrsf = opening_trsf * gtrsf;
|
||||
cgal_shape_t opening_shape(((CgalShape*)opening_shapes[i].Shape())->shape());
|
||||
for (auto &vertex: vertices(opening_shape)) vertex->point() = vertex->point().transform(gtrsf);
|
||||
opening_shapelist.push_back(opening_shape);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate over the shapes of the IfcProduct
|
||||
for ( IfcGeom::ConversionResults::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) {
|
||||
const cgal_shape_t& entity_shape_unlocated(((CgalShape*)it3->Shape())->shape());
|
||||
cgal_shape_t entity_shape(entity_shape_unlocated);
|
||||
if (it3->Placement()) {
|
||||
const cgal_placement_t& entity_shape_gtrsf = *(CgalPlacement*)it3->Placement();
|
||||
for (auto &vertex: vertices(entity_shape)) vertex->point() = vertex->point().transform(entity_shape_gtrsf);
|
||||
}
|
||||
|
||||
cgal_shape_t original_entity_shape(entity_shape);
|
||||
|
||||
if (!entity_shape.is_valid()) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Conversion to Nef will fail. Invalid entity:", entity->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!entity_shape.is_closed()) {
|
||||
// TODO: There can be substractions to remove parts of non-volumetric objects. Maybe iterate over all faces of an entity and put them in a Nef_polyhedron_3 through Boolean union? Highly inefficient but maybe desirable...
|
||||
Logger::Message(Logger::LOG_ERROR, "Subtraction of openings not supported for non-closed entity:", entity->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
|
||||
try {
|
||||
success = CGAL::Polygon_mesh_processing::triangulate_faces(entity_shape);
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Triangulation of entity crashed:", entity->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Triangulation of entity failed:", entity->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CGAL::Polygon_mesh_processing::does_self_intersect(entity_shape)) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Conversion to Nef will fail. Self-intersecting entity:", entity->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
CGAL::Nef_polyhedron_3<Kernel> nef_brep_cut_result;
|
||||
|
||||
try {
|
||||
nef_brep_cut_result = CGAL::Nef_polyhedron_3<Kernel>(entity_shape);
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Could not convert entity to Nef:", entity->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
cgal_shape_t brep_cut_result;
|
||||
nef_brep_cut_result.convert_to_polyhedron(brep_cut_result);
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_WARNING, "Final conversion will likely fail. Could not convert entity from Nef:", entity->entity);
|
||||
}
|
||||
|
||||
for (auto &opening: opening_shapelist) {
|
||||
|
||||
cgal_shape_t original_opening_shape(opening);
|
||||
if (!opening.is_valid()) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Conversion to Nef will fail. Invalid opening in entity:", entity->entity);
|
||||
return false;
|
||||
} if (!opening.is_closed()) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Subtraction of opening makes no sense. Not closed opening in entity:", entity->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
success = false;
|
||||
|
||||
try {
|
||||
success = CGAL::Polygon_mesh_processing::triangulate_faces(opening);
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Triangulation of opening of entity crashed:", entity->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Triangulation of opening of entity failed:", entity->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CGAL::Polygon_mesh_processing::does_self_intersect(entity_shape)) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Conversion to Nef will fail. Self-intersecting opening of entity:", entity->entity);
|
||||
}
|
||||
|
||||
CGAL::Nef_polyhedron_3<Kernel> nef_opening;
|
||||
|
||||
try {
|
||||
nef_opening = CGAL::Nef_polyhedron_3<Kernel>(opening);
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Could not convert opening of entity to Nef:", entity->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
cgal_shape_t opening_shape;
|
||||
nef_opening.convert_to_polyhedron(opening_shape);
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_WARNING, "Final conversion will likely fail. Could not convert opening of entity from Nef:", entity->entity);
|
||||
// return false;
|
||||
}
|
||||
|
||||
try {
|
||||
nef_brep_cut_result -= nef_opening;
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Could not subtract Nef opening of entity:", entity->entity);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
nef_brep_cut_result.convert_to_polyhedron(entity_shape);
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Could not convert entity with openings from Nef:", entity->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
cut_shapes.push_back(IfcGeom::ConversionResult(new CgalShape(entity_shape), &it3->Style()));
|
||||
|
||||
} return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -120,8 +120,18 @@ namespace IfcGeom {
|
||||
bool convert_wire(const IfcUtil::IfcBaseClass* L, cgal_wire_t& result);
|
||||
bool convert_curve(const IfcUtil::IfcBaseClass* L, cgal_curve_t& result);
|
||||
bool convert_face(const IfcUtil::IfcBaseClass* L, cgal_face_t& result);
|
||||
|
||||
bool convert_wire_to_face(const cgal_wire_t& wire, cgal_face_t& face);
|
||||
|
||||
void remove_duplicate_points_from_loop(cgal_wire_t& polygon);
|
||||
|
||||
// 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(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const cgal_placement_t& entity_trsf, ConversionResults& cut_shapes);
|
||||
|
||||
// CGAL::Polyhedron_3<Kernel> triangulate_faces(CGAL::Polyhedron_3<Kernel> &polyhedron);
|
||||
CGAL::Polyhedron_3<Kernel> create_polyhedron(std::list<cgal_face_t> &face_list);
|
||||
CGAL::Polyhedron_3<Kernel> create_polyhedron(CGAL::Nef_polyhedron_3<Kernel> &nef_polyhedron);
|
||||
CGAL::Nef_polyhedron_3<Kernel> create_nef_polyhedron(std::list<cgal_face_t> &face_list);
|
||||
CGAL::Nef_polyhedron_3<Kernel> create_nef_polyhedron(CGAL::Polyhedron_3<Kernel> &polyhedron);
|
||||
|
||||
void purge_cache() {
|
||||
// Rather hack-ish, but a stopgap solution to keep memory under control
|
||||
|
||||
@@ -17,24 +17,44 @@ void triangulate_helper(const cgal_shape_t& shape_const, const IfcGeom::Iterator
|
||||
vertex->point() = vertex->point().transform(trsf);
|
||||
}
|
||||
|
||||
if (!s.is_valid()) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Invalid Polyhedron_3 in object (before triangulation)");
|
||||
return;
|
||||
}
|
||||
|
||||
// Triangulate the shape and compute the normals
|
||||
std::map<cgal_vertex_descriptor_t, Kernel::Vector_3> vertex_normals;
|
||||
boost::associative_property_map<std::map<cgal_vertex_descriptor_t, Kernel::Vector_3>> vertex_normals_map(vertex_normals);
|
||||
// std::map<cgal_vertex_descriptor_t, Kernel::Vector_3> vertex_normals;
|
||||
// boost::associative_property_map<std::map<cgal_vertex_descriptor_t, Kernel::Vector_3>> vertex_normals_map(vertex_normals);
|
||||
std::map<cgal_face_descriptor_t, Kernel::Vector_3> face_normals;
|
||||
boost::associative_property_map<std::map<cgal_face_descriptor_t, Kernel::Vector_3>> face_normals_map(face_normals);
|
||||
|
||||
if (CGAL::Polygon_mesh_processing::triangulate_faces(s)) {
|
||||
// std::cout << "Triangulated model: " << s.size_of_facets() << " facets and " << s.size_of_vertices() << " vertices" << std::endl;
|
||||
} else {
|
||||
Logger::Message(Logger::LOG_ERROR, "Failed to triangulate shape");
|
||||
bool success = false;
|
||||
try {
|
||||
success = CGAL::Polygon_mesh_processing::triangulate_faces(s);
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Triangulation crashed");
|
||||
return;
|
||||
}
|
||||
|
||||
CGAL::Polygon_mesh_processing::compute_normals(s, vertex_normals_map, face_normals_map);
|
||||
|
||||
// Iterates over the faces of the shape
|
||||
int num_faces = 0, num_vertices = 0;
|
||||
|
||||
if (!success) {
|
||||
Logger::Message(Logger::LOG_ERROR, return;
|
||||
"Triangulation failed");
|
||||
}
|
||||
// std::cout << "Triangulated model: " << s.size_of_facets() << " facets and " << s.size_of_vertices() << " vertices" << std::endl;
|
||||
|
||||
if (!s.is_valid()) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Invalid Polyhedron_3 in object (after triangulation)");
|
||||
return;
|
||||
}
|
||||
|
||||
// CGAL::Polygon_mesh_processing::compute_normals(s, vertex_normals_map, face_normals_map);
|
||||
CGAL::Polygon_mesh_processing::compute_face_normals(s, face_normals_map);
|
||||
|
||||
for (auto &face: faces(s)) {
|
||||
if (!face->is_triangle()) {
|
||||
std::cout << "Warning: non-triangular face!" << std::endl;
|
||||
continue;
|
||||
}
|
||||
CGAL::Polyhedron_3<Kernel>::Halfedge_around_facet_const_circulator current_halfedge = face->facet_begin();
|
||||
do {
|
||||
t->addVertex(surface_style_id,
|
||||
|
||||
@@ -20,6 +20,13 @@
|
||||
#ifndef CGALCONVERSIONRESULT_H
|
||||
#define CGALCONVERSIONRESULT_H
|
||||
|
||||
#include "../../../ifcgeom/schema_agnostic/Kernel.h"
|
||||
#include "../../../ifcgeom/schema_agnostic/IfcGeomElement.h"
|
||||
#include "../../../ifcgeom/schema_agnostic/cgal/CgalConversionResult.h"
|
||||
|
||||
// @todo create separate shapetype enum?
|
||||
#include "../../../ifcgeom/kernels/opencascade/IfcGeomShapeType.h"
|
||||
|
||||
#include <boost/property_map/property_map.hpp>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Polyhedron_3.h>
|
||||
@@ -28,12 +35,16 @@
|
||||
#include <CGAL/Polygon_mesh_processing/orientation.h>
|
||||
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
|
||||
#include <CGAL/Polygon_mesh_processing/compute_normal.h>
|
||||
#include <CGAL/Polygon_mesh_processing/self_intersections.h>
|
||||
#include <CGAL/Nef_polyhedron_3.h>
|
||||
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::Aff_transformation_3 cgal_placement_t;
|
||||
typedef Kernel::Point_3 cgal_point_t;
|
||||
typedef Kernel::Vector_3 cgal_direction_t;
|
||||
typedef Kernel::Vector_3 cgal_vector_t;
|
||||
typedef Kernel::Plane_3 cgal_plane_t;
|
||||
typedef std::vector<Kernel::Point_3> cgal_curve_t;
|
||||
typedef std::vector<Kernel::Point_3> cgal_wire_t;
|
||||
|
||||
@@ -60,19 +71,15 @@ namespace IfcGeom {
|
||||
operator const cgal_placement_t& () { return trsf_; }
|
||||
|
||||
virtual double Value(int i, int j) const {
|
||||
// TODO: Check
|
||||
// std::cout << "Getting CgalPlacement with i = " << i << " and j = " << j << std::endl;
|
||||
return CGAL::to_double(trsf_.cartesian(i-1, j-1));
|
||||
return CGAL::to_double(trsf_.cartesian(i-1, j-1));
|
||||
}
|
||||
|
||||
virtual void Multiply(const ConversionResultPlacement* other) {
|
||||
// TODO: Check
|
||||
trsf_ = ((CgalPlacement *)other)->trsf_ * trsf_;
|
||||
trsf_ = trsf_ * ((CgalPlacement *)other)->trsf_;
|
||||
}
|
||||
|
||||
virtual void PreMultiply(const ConversionResultPlacement* other) {
|
||||
// TODO: Check
|
||||
trsf_ = trsf_ * ((CgalPlacement *)other)->trsf_;
|
||||
trsf_ = ((CgalPlacement *)other)->trsf_ * trsf_;
|
||||
}
|
||||
|
||||
virtual ConversionResultPlacement* clone() const {
|
||||
|
||||
Reference in New Issue
Block a user