Files
IfcOpenShell/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp
T

471 lines
18 KiB
C++
Raw Normal View History

#include "CgalKernel.h"
2017-03-02 17:11:58 -06:00
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::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;
}
2017-03-06 11:12:06 -06:00
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;
2017-03-06 15:03:57 -06:00
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));
2017-03-06 11:12:06 -06:00
}
2017-03-06 15:03:57 -06:00
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);
2017-03-06 15:03:57 -06:00
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);
2017-03-06 15:03:57 -06:00
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);
2017-03-06 15:03:57 -06:00
face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), -y+r+r*sin(current_angle), 0));
}
2017-03-06 11:12:06 -06:00
}
if (has_position) {
IfcGeom::CgalKernel::convert(l->Position(), trsf2d);
for (auto &vertex: face.outer) {
vertex = vertex.transform(trsf2d);
}
}
return true;
}
2017-03-07 13:52:29 -06:00
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;
}
2017-03-06 11:18:51 -06:00
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;
}
2017-03-07 13:04:22 -06:00
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);
2017-03-07 13:52:29 -06:00
} for (auto &inner: face.inner) {
for (auto &vertex: inner) {
vertex = vertex.transform(trsf2d);
}
2017-03-07 13:04:22 -06:00
}
}
return true;
}
2017-03-06 11:23:37 -06:00
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;
}
2017-03-08 19:38:25 -06:00
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;
}