mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 09:48:32 +00:00
Merge pull request #7 from kenohori/cgal
Composite curves, some profiles (C, I, L)
This commit is contained in:
@@ -49,6 +49,18 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcDirection* l, cgal_directi
|
||||
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);
|
||||
IfcGeom::CgalKernel::convert(l->Location(),o);
|
||||
if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(),axis);
|
||||
plane = Kernel::Plane_3(o, axis);
|
||||
// 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;
|
||||
@@ -173,6 +185,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOpe
|
||||
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) << " ";
|
||||
@@ -183,6 +196,35 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOpe
|
||||
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;
|
||||
}
|
||||
|
||||
void IfcGeom::CgalKernel::remove_duplicate_points_from_loop(cgal_wire_t& polygon, bool closed, double tol) {
|
||||
if (tol <= 0.) tol = getValue(GV_PRECISION);
|
||||
tol *= tol;
|
||||
|
||||
@@ -47,6 +47,7 @@ SHAPE(IfcRectangularPyramid);
|
||||
SHAPE(IfcRightCircularCylinder);
|
||||
SHAPE(IfcRightCircularCone);
|
||||
SHAPE(IfcTriangulatedFaceSet);
|
||||
SHAPE(IfcHalfSpaceSolid);
|
||||
|
||||
FACE(IfcArbitraryClosedProfileDef);
|
||||
FACE(IfcCircleHollowProfileDef);
|
||||
@@ -57,15 +58,21 @@ FACE(IfcRectangleHollowProfileDef);
|
||||
FACE(IfcRectangleProfileDef);
|
||||
FACE(IfcTrapeziumProfileDef);
|
||||
FACE(IfcEllipseProfileDef);
|
||||
FACE(IfcCShapeProfileDef);
|
||||
FACE(IfcIShapeProfileDef);
|
||||
FACE(IfcLShapeProfileDef);
|
||||
|
||||
WIRE(IfcEdgeLoop);
|
||||
WIRE(IfcOrientedEdge);
|
||||
WIRE(IfcPolyLoop);
|
||||
WIRE(IfcPolyline);
|
||||
WIRE(IfcCompositeCurve);
|
||||
|
||||
CLASS(IfcCartesianPoint,cgal_point_t);
|
||||
CLASS(IfcDirection,cgal_direction_t);
|
||||
CLASS(IfcPlane,cgal_plane_t);
|
||||
CLASS(IfcAxis2Placement2D,cgal_placement_t);
|
||||
CLASS(IfcAxis2Placement3D,cgal_placement_t);
|
||||
CLASS(IfcObjectPlacement,cgal_placement_t);
|
||||
CLASS(IfcCartesianTransformationOperator3D,cgal_placement_t);
|
||||
CLASS(IfcCartesianTransformationOperator3DnonUniform,cgal_placement_t);
|
||||
|
||||
@@ -376,3 +376,282 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcFace* l, cgal_face_t& face
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -36,8 +36,9 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcMappedItem* l, ConversionR
|
||||
cgal_placement_t gtrsf;
|
||||
IfcSchema::IfcCartesianTransformationOperator* transform = l->MappingTarget();
|
||||
if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3DnonUniform) ) {
|
||||
IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3DnonUniform*)transform,gtrsf);
|
||||
Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity);
|
||||
// IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3DnonUniform*)transform,gtrsf);
|
||||
return false;
|
||||
} else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2DnonUniform) ) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity);
|
||||
return false;
|
||||
@@ -45,6 +46,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcMappedItem* l, ConversionR
|
||||
cgal_placement_t trsf;
|
||||
IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3D*)transform,trsf);
|
||||
gtrsf = trsf;
|
||||
// Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity);
|
||||
// return false;
|
||||
} else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2D) ) {
|
||||
cgal_placement_t trsf_2d;
|
||||
Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity);
|
||||
@@ -61,9 +64,17 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcMappedItem* l, ConversionR
|
||||
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();
|
||||
@@ -127,7 +138,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal
|
||||
face_list.push_back(bottom_face);
|
||||
|
||||
// if (true) {
|
||||
// cgal_shape_t polyhedron = CGAL::Polyhedron_3<Kernel>();
|
||||
// CGAL::Polyhedron_3<Kernel> polyhedron;
|
||||
// PolyhedronBuilder builder(&face_list);
|
||||
// polyhedron.delegate(builder);
|
||||
//
|
||||
@@ -166,12 +177,13 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal
|
||||
|
||||
// Stitch edges
|
||||
// std::cout << "Before: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl;
|
||||
CGAL::Polyhedron_3<Kernel> old_polyhedron(polyhedron);
|
||||
CGAL::Polygon_mesh_processing::stitch_borders(polyhedron);
|
||||
if (!polyhedron.is_valid()) {
|
||||
std::cout << "Invalid polyhedron!" << std::endl;
|
||||
std::ofstream fresult;
|
||||
fresult.open("/Users/ken/Desktop/invalid.off");
|
||||
fresult << polyhedron << std::endl;
|
||||
fresult << old_polyhedron << std::endl;
|
||||
fresult.close();
|
||||
}
|
||||
|
||||
@@ -925,3 +937,21 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTriangulatedFaceSet* l, cg
|
||||
shape = CGAL::Nef_polyhedron_3<Kernel>(polyhedron);
|
||||
return true;
|
||||
}
|
||||
|
||||
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: This might be the other way around?
|
||||
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();
|
||||
|
||||
shape = CGAL::Nef_polyhedron_3<Kernel>(pln);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -85,3 +85,93 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcOrientedEdge* l, cgal_wire
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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, false);
|
||||
|
||||
wire = w;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ 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::Plane_3 cgal_plane_t;
|
||||
typedef std::vector<Kernel::Point_3> cgal_curve_t;
|
||||
typedef std::vector<Kernel::Point_3> cgal_wire_t;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user