mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-06 07:51:47 +00:00
Brand new implementation of IfcFace(Surface)
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* Example that generates various forms of IfcFace *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "../ifcparse/Ifc2x3.h"
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcHierarchyHelper.h"
|
||||
|
||||
typedef std::string S;
|
||||
typedef IfcParse::IfcGlobalId guid;
|
||||
boost::none_t const null = (static_cast<boost::none_t>(0));
|
||||
|
||||
static int x = 0;
|
||||
|
||||
void create_testcase(IfcHierarchyHelper& file, IfcSchema::IfcFace* face, const std::string& name) {
|
||||
IfcSchema::IfcFace::list::ptr faces(new IfcSchema::IfcFace::list);
|
||||
faces->push(face);
|
||||
IfcSchema::IfcOpenShell* shell = new IfcSchema::IfcOpenShell(faces);
|
||||
|
||||
IfcSchema::IfcConnectedFaceSet::list::ptr shells(new IfcSchema::IfcConnectedFaceSet::list);
|
||||
shells->push(shell);
|
||||
IfcSchema::IfcFaceBasedSurfaceModel* model = new IfcSchema::IfcFaceBasedSurfaceModel(shells);
|
||||
|
||||
IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
|
||||
guid(), 0, name, null, null, 0, 0, null, null);
|
||||
file.addBuildingProduct(product);
|
||||
product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
|
||||
|
||||
product->setObjectPlacement(file.addLocalPlacement(0, 1000 * x++, 0));
|
||||
|
||||
IfcSchema::IfcRepresentation::list::ptr reps (new IfcSchema::IfcRepresentation::list);
|
||||
IfcSchema::IfcRepresentationItem::list::ptr items (new IfcSchema::IfcRepresentationItem::list);
|
||||
|
||||
items->push(model);
|
||||
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
|
||||
file.getRepresentationContext("Model"), S("Body"), S("SurfaceModel"), items);
|
||||
reps->push(rep);
|
||||
|
||||
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
|
||||
file.addEntity(shape);
|
||||
|
||||
product->setRepresentation(shape);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
IfcHierarchyHelper file;
|
||||
{
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points (new IfcSchema::IfcCartesianPoint::list);
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, -400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, -400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, +400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, +400, 0));
|
||||
IfcSchema::IfcPolyLoop* loop = new IfcSchema::IfcPolyLoop(points);
|
||||
IfcSchema::IfcFaceOuterBound* bound = new IfcSchema::IfcFaceOuterBound(loop, true);
|
||||
|
||||
IfcSchema::IfcFaceBound::list::ptr bounds (new IfcSchema::IfcFaceBound::list);
|
||||
bounds->push(bound);
|
||||
IfcSchema::IfcFace* face = new IfcSchema::IfcFace(bounds);
|
||||
create_testcase(file, face, "polyloop");
|
||||
}
|
||||
{
|
||||
IfcSchema::IfcCartesianPoint* point1 = file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, 0., 0.);
|
||||
IfcSchema::IfcCartesianPoint* point2 = file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, 0., 0.);
|
||||
IfcSchema::IfcVertexPoint* vertex1 = new IfcSchema::IfcVertexPoint(point1);
|
||||
IfcSchema::IfcVertexPoint* vertex2 = new IfcSchema::IfcVertexPoint(point2);
|
||||
IfcSchema::IfcCircle* circle = new IfcSchema::IfcCircle(file.addPlacement2d(), 400.);
|
||||
IfcSchema::IfcEdgeCurve* edge1 = new IfcSchema::IfcEdgeCurve(vertex1, vertex2, circle, true);
|
||||
IfcSchema::IfcEdgeCurve* edge2 = new IfcSchema::IfcEdgeCurve(vertex2, vertex1, circle, true);
|
||||
IfcSchema::IfcOrientedEdge* oriented_edge1 = new IfcSchema::IfcOrientedEdge(edge1, true);
|
||||
IfcSchema::IfcOrientedEdge* oriented_edge2 = new IfcSchema::IfcOrientedEdge(edge2, true);
|
||||
IfcSchema::IfcOrientedEdge::list::ptr edges(new IfcSchema::IfcOrientedEdge::list);
|
||||
edges->push(oriented_edge1);
|
||||
edges->push(oriented_edge2);
|
||||
IfcSchema::IfcEdgeLoop* loop = new IfcSchema::IfcEdgeLoop(edges);
|
||||
IfcSchema::IfcFaceOuterBound* bound = new IfcSchema::IfcFaceOuterBound(loop, true);
|
||||
|
||||
IfcSchema::IfcFaceBound::list::ptr bounds (new IfcSchema::IfcFaceBound::list);
|
||||
bounds->push(bound);
|
||||
IfcSchema::IfcFace* face = new IfcSchema::IfcFace(bounds);
|
||||
create_testcase(file, face, "circle");
|
||||
}
|
||||
{
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points (new IfcSchema::IfcCartesianPoint::list);
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, -400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, -400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, +400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, +400, 0));
|
||||
IfcSchema::IfcPolyLoop* loop = new IfcSchema::IfcPolyLoop(points);
|
||||
IfcSchema::IfcFaceOuterBound* outer_bound = new IfcSchema::IfcFaceOuterBound(loop, true);
|
||||
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points2 (new IfcSchema::IfcCartesianPoint::list);
|
||||
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-300, -300, 0));
|
||||
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-100, -300, 0));
|
||||
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-100, +300, 0));
|
||||
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-300, +300, 0));
|
||||
IfcSchema::IfcPolyLoop* loop2 = new IfcSchema::IfcPolyLoop(points2);
|
||||
IfcSchema::IfcFaceBound* inner_bound1 = new IfcSchema::IfcFaceBound(loop2, false);
|
||||
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points3 (new IfcSchema::IfcCartesianPoint::list);
|
||||
points3->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+100, +300, 0));
|
||||
points3->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+300, +300, 0));
|
||||
points3->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+300, -300, 0));
|
||||
points3->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+100, -300, 0));
|
||||
IfcSchema::IfcPolyLoop* loop3 = new IfcSchema::IfcPolyLoop(points3);
|
||||
IfcSchema::IfcFaceBound* inner_bound2 = new IfcSchema::IfcFaceBound(loop3, true);
|
||||
|
||||
IfcSchema::IfcFaceBound::list::ptr bounds (new IfcSchema::IfcFaceBound::list);
|
||||
bounds->push(inner_bound1);
|
||||
bounds->push(outer_bound);
|
||||
bounds->push(inner_bound2);
|
||||
IfcSchema::IfcFace* face = new IfcSchema::IfcFace(bounds);
|
||||
create_testcase(file, face, "polyloop with holes");
|
||||
}
|
||||
{
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points (new IfcSchema::IfcCartesianPoint::list);
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, -400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-100, -400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-100, +400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, +400, 0));
|
||||
IfcSchema::IfcPolyLoop* loop = new IfcSchema::IfcPolyLoop(points);
|
||||
IfcSchema::IfcFaceOuterBound* bound1 = new IfcSchema::IfcFaceOuterBound(loop, true);
|
||||
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points2 (new IfcSchema::IfcCartesianPoint::list);
|
||||
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+100, +400, 0));
|
||||
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, +400, 0));
|
||||
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, -400, 0));
|
||||
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+100, -400, 0));
|
||||
IfcSchema::IfcPolyLoop* loop2 = new IfcSchema::IfcPolyLoop(points2);
|
||||
IfcSchema::IfcFaceOuterBound* bound2 = new IfcSchema::IfcFaceOuterBound(loop2, false);
|
||||
|
||||
IfcSchema::IfcFaceBound::list::ptr bounds (new IfcSchema::IfcFaceBound::list);
|
||||
bounds->push(bound1);
|
||||
bounds->push(bound2);
|
||||
IfcSchema::IfcFace* face = new IfcSchema::IfcFace(bounds);
|
||||
create_testcase(file, face, "multiple outer boundaries (invalid)");
|
||||
}
|
||||
{
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points (new IfcSchema::IfcCartesianPoint::list);
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, -400, 1e-6));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, -400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, +400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, +400, 0));
|
||||
IfcSchema::IfcPolyLoop* loop = new IfcSchema::IfcPolyLoop(points);
|
||||
IfcSchema::IfcFaceOuterBound* bound = new IfcSchema::IfcFaceOuterBound(loop, true);
|
||||
|
||||
IfcSchema::IfcFaceBound::list::ptr bounds (new IfcSchema::IfcFaceBound::list);
|
||||
bounds->push(bound);
|
||||
IfcSchema::IfcFace* face = new IfcSchema::IfcFace(bounds);
|
||||
create_testcase(file, face, "imprecise polyloop");
|
||||
}
|
||||
const std::string filename = "faces.ifc";
|
||||
file.header().file_name().name(filename);
|
||||
std::ofstream f(filename.c_str());
|
||||
f << file;
|
||||
}
|
||||
@@ -120,10 +120,6 @@ int main(int argc, char** argv) {
|
||||
"operand before applying the subtraction operation. This may "
|
||||
"introduce a performance improvement at the risk of failing, in "
|
||||
"which case the subtraction is applied one-by-one.")
|
||||
("force-ccw-face-orientation",
|
||||
"Recompute topological face normals using Newell's Method to "
|
||||
"guarantee that face vertices are defined in a Counter Clock "
|
||||
"Wise order, even if the faces are not part of a closed shell.")
|
||||
("disable-opening-subtractions",
|
||||
"Specifies whether to disable the boolean subtraction of "
|
||||
"IfcOpeningElement Representations from their RelatingElements.")
|
||||
@@ -173,7 +169,6 @@ int main(int argc, char** argv) {
|
||||
const bool convert_back_units = vmap.count("convert-back-units") != 0;
|
||||
const bool sew_shells = vmap.count("sew-shells") != 0;
|
||||
const bool merge_boolean_operands = vmap.count("merge-boolean-operands") != 0;
|
||||
const bool force_ccw_face_orientation = vmap.count("force-ccw-face-orientation") != 0;
|
||||
const bool disable_opening_subtractions = vmap.count("disable-opening-subtractions") != 0;
|
||||
const bool include_entities = vmap.count("include") != 0;
|
||||
const bool include_plan = vmap.count("plan") != 0;
|
||||
@@ -240,7 +235,6 @@ int main(int argc, char** argv) {
|
||||
settings.set(IfcGeom::IteratorSettings::SEW_SHELLS, sew_shells);
|
||||
settings.set(IfcGeom::IteratorSettings::CONVERT_BACK_UNITS, convert_back_units);
|
||||
settings.set(IfcGeom::IteratorSettings::FASTER_BOOLEANS, merge_boolean_operands);
|
||||
settings.set(IfcGeom::IteratorSettings::FORCE_CCW_FACE_ORIENTATION, force_ccw_face_orientation);
|
||||
settings.set(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS, disable_opening_subtractions);
|
||||
settings.set(IfcGeom::IteratorSettings::INCLUDE_CURVES, include_plan);
|
||||
settings.set(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES, !include_model);
|
||||
|
||||
@@ -81,9 +81,6 @@ public:
|
||||
// that consist of many faces is really detrimental for the performance.
|
||||
// Default: 1000
|
||||
GV_MAX_FACES_TO_SEW,
|
||||
// By default singular faces have no explicitly defined orientation, to
|
||||
// force faces to be defined CounterClockWise, set this value greater than zero.
|
||||
GV_FORCE_CCW_FACE_ORIENTATION,
|
||||
// The length unit used the creation of TopoDS_Shapes, primarily affects the
|
||||
// interpretation of IfcCartesianPoints and IfcVector magnitudes
|
||||
// DefaultL 1.0
|
||||
|
||||
+171
-105
@@ -47,6 +47,7 @@
|
||||
#include <TColStd_Array1OfReal.hxx>
|
||||
#include <TColStd_Array1OfInteger.hxx>
|
||||
#include <Geom_Line.hxx>
|
||||
#include <Geom_Plane.hxx>
|
||||
#include <Geom_Circle.hxx>
|
||||
#include <Geom_Ellipse.hxx>
|
||||
#include <Geom_TrimmedCurve.hxx>
|
||||
@@ -70,6 +71,7 @@
|
||||
#include <TopoDS_Wire.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS_Iterator.hxx>
|
||||
|
||||
#include <BRepAlgoAPI_Cut.hxx>
|
||||
|
||||
@@ -91,7 +93,6 @@
|
||||
#include <TColStd_Array1OfReal.hxx>
|
||||
#include <TColStd_Array1OfInteger.hxx>
|
||||
|
||||
#include <Geom_Plane.hxx>
|
||||
#include <BRepCheck_Face.hxx>
|
||||
#endif
|
||||
|
||||
@@ -99,116 +100,181 @@
|
||||
|
||||
bool IfcGeom::Kernel::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) {
|
||||
IfcSchema::IfcFaceBound::list::ptr bounds = l->Bounds();
|
||||
IfcSchema::IfcFaceBound::list::it it = bounds->begin();
|
||||
IfcSchema::IfcLoop* loop = (*it)->Bound();
|
||||
// FIXME: The assumption that the first bound is
|
||||
// the outer bound is not necessarily correct.
|
||||
TopoDS_Wire outer_wire;
|
||||
if ( ! convert_wire(loop,outer_wire) ) return false;
|
||||
BRepBuilderAPI_MakeFace mf (outer_wire);
|
||||
BRepBuilderAPI_FaceError er = mf.Error();
|
||||
if ( er == BRepBuilderAPI_NotPlanar ) {
|
||||
ShapeFix_ShapeTolerance FTol;
|
||||
FTol.SetTolerance(outer_wire, 0.01, TopAbs_WIRE);
|
||||
mf.~BRepBuilderAPI_MakeFace();
|
||||
new (&mf) BRepBuilderAPI_MakeFace(outer_wire);
|
||||
er = mf.Error();
|
||||
}
|
||||
if ( er != BRepBuilderAPI_FaceDone ) return false;
|
||||
if ( bounds->size() == 1 ) {
|
||||
face = mf.Face();
|
||||
} else {
|
||||
for( ++it; it != bounds->end(); ++ it) {
|
||||
IfcSchema::IfcLoop* loop = (*it)->Bound();
|
||||
TopoDS_Wire wire;
|
||||
if ( ! convert_wire(loop,wire) ) return false;
|
||||
mf.Add(wire);
|
||||
}
|
||||
if ( mf.IsDone() ) {
|
||||
ShapeFix_Shape sfs(mf.Face());
|
||||
sfs.Perform();
|
||||
TopoDS_Shape sfs_shape = sfs.Shape();
|
||||
bool is_face = sfs_shape.ShapeType() == TopAbs_FACE;
|
||||
// This assertion is not strictly necessary. The schema
|
||||
// does suggest there to be only one outer bound, but
|
||||
// not all models comply with this.
|
||||
if ( is_face ) {
|
||||
face = TopoDS::Face(sfs_shape);
|
||||
} else {
|
||||
face = sfs_shape;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( getValue(GV_FORCE_CCW_FACE_ORIENTATION)>0 ) {
|
||||
// Check the orientation of the face by comparing the
|
||||
// normal of the topological surface to the Newell's Method's
|
||||
// normal. Newell's Method is used for the normal calculation
|
||||
// as a simple edge cross product can give opposite results
|
||||
// for a concave face boundary.
|
||||
// Reference: Graphics Gems III p. 231
|
||||
BRepGProp_Face prop(TopoDS::Face(face));
|
||||
gp_Vec normal_direction;
|
||||
gp_Pnt center;
|
||||
double u1,u2,v1,v2;
|
||||
prop.Bounds(u1,u2,v1,v2);
|
||||
prop.Normal((u1+u2)/2.0,(v1+v2)/2.0,center,normal_direction);
|
||||
gp_Dir face_normal1 = gp_Dir(normal_direction.XYZ());
|
||||
Handle(Geom_Surface) face_surface;
|
||||
bool reversed_face_surface = false;
|
||||
const bool is_face_surface = l->is(IfcSchema::Type::IfcFaceSurface);
|
||||
|
||||
double x = 0, y = 0, z = 0;
|
||||
gp_Pnt current, previous, first;
|
||||
int n = 0;
|
||||
// Iterate over the vertices of the outer wire (discarding
|
||||
// any potential holes)
|
||||
for ( TopExp_Explorer exp(outer_wire,TopAbs_VERTEX);; exp.Next()) {
|
||||
unsigned has_more = exp.More();
|
||||
if ( has_more ) {
|
||||
const TopoDS_Vertex& v = TopoDS::Vertex(exp.Current());
|
||||
current = BRep_Tool::Pnt(v);
|
||||
} else {
|
||||
current = first;
|
||||
}
|
||||
if ( n ) {
|
||||
const double& xn = previous.X();
|
||||
const double& yn = previous.Y();
|
||||
const double& zn = previous.Z();
|
||||
const double& xn1 = current.X();
|
||||
const double& yn1 = current.Y();
|
||||
const double& zn1 = current.Z();
|
||||
x += (yn-yn1)*(zn+zn1);
|
||||
y += (xn+xn1)*(zn-zn1);
|
||||
z += (xn-xn1)*(yn+yn1);
|
||||
} else {
|
||||
first = current;
|
||||
}
|
||||
if ( !has_more ) {
|
||||
break;
|
||||
}
|
||||
previous = current;
|
||||
++n;
|
||||
}
|
||||
if (is_face_surface) {
|
||||
IfcSchema::IfcFaceSurface* fs = (IfcSchema::IfcFaceSurface*) l;
|
||||
fs->FaceSurface();
|
||||
// FIXME: Surfaces are interpreted as a TopoDS_Shape
|
||||
TopoDS_Shape surface_shape;
|
||||
if (!convert_shape(fs->FaceSurface(), surface_shape)) return false;
|
||||
|
||||
// If Newell's normal does not point in the same direction
|
||||
// as the topological face normal the face orientation is
|
||||
// reversed
|
||||
gp_Vec face_normal2(x,y,z);
|
||||
// FIXME: Assert this obtaines the only face
|
||||
TopExp_Explorer exp(surface_shape, TopAbs_FACE);
|
||||
if (!exp.More()) return false;
|
||||
|
||||
if (face_normal2.Magnitude() > ALMOST_ZERO) {
|
||||
if ( face_normal1.Dot(face_normal2) < 0 ) {
|
||||
TopAbs_Orientation o = face.Orientation();
|
||||
face.Orientation(o == TopAbs_FORWARD ? TopAbs_REVERSED : TopAbs_FORWARD);
|
||||
}
|
||||
}
|
||||
TopoDS_Face surface = TopoDS::Face(exp.Current());
|
||||
face_surface = BRep_Tool::Surface(surface);
|
||||
}
|
||||
|
||||
// It might be a good idea to globally discard faces
|
||||
// smaller than a certain treshold value. But for now
|
||||
// only when processing IfcConnectedFacesets the small
|
||||
// faces are skipped.
|
||||
// return face_area(face) > 0.0001;
|
||||
return true;
|
||||
const int num_bounds = bounds->size();
|
||||
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 ++;
|
||||
}
|
||||
|
||||
// The number of outer bounds should be one according to the schema. Also Open Cascade
|
||||
// expects this, but it is not strictly checked. Regardless, if the number is greater,
|
||||
// the face will still be processed as long as there are no holes. A compound of faces
|
||||
// is returned in that case.
|
||||
if (num_bounds > 1 && num_outer_bounds > 1 && num_bounds != num_outer_bounds) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Invalid configuration of boundaries for:", l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
TopoDS_Compound compound;
|
||||
BRep_Builder builder;
|
||||
if (num_outer_bounds > 1) {
|
||||
builder.MakeCompound(compound);
|
||||
}
|
||||
|
||||
// The builder is initialized on the heap because of the various different moments
|
||||
// of initialization depending on the configuration of surfaces and boundaries.
|
||||
BRepBuilderAPI_MakeFace* mf = 0;
|
||||
|
||||
bool success = false;
|
||||
int processed = 0;
|
||||
|
||||
for (int process_interior = 0; process_interior <= 1; ++process_interior) {
|
||||
for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) {
|
||||
IfcSchema::IfcFaceBound* bound = *it;
|
||||
IfcSchema::IfcLoop* loop = bound->Bound();
|
||||
|
||||
const bool same_sense = bound->Orientation();
|
||||
const bool is_interior =
|
||||
!bound->is(IfcSchema::Type::IfcFaceOuterBound) &&
|
||||
(num_bounds > 1) &&
|
||||
(num_outer_bounds < num_bounds);
|
||||
|
||||
// The exterior face boundary is processed first
|
||||
if (is_interior == !process_interior) continue;
|
||||
|
||||
TopoDS_Wire wire;
|
||||
if (!convert_wire(loop, wire)) break;
|
||||
|
||||
/*
|
||||
The approach below does not result in a significant speed-up
|
||||
if (loop->is(IfcSchema::Type::IfcPolyLoop) && processed == 0 && face_surface.IsNull()) {
|
||||
IfcSchema::IfcPolyLoop* polyloop = (IfcSchema::IfcPolyLoop*) loop;
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points = polyloop->Polygon();
|
||||
|
||||
if (points->size() == 3) {
|
||||
// Help Open Cascade by finding the plane more efficiently
|
||||
IfcSchema::IfcCartesianPoint::list::it point_iterator = points->begin();
|
||||
gp_Pnt a, b, c;
|
||||
convert(*point_iterator++, a);
|
||||
convert(*point_iterator++, b);
|
||||
convert(*point_iterator++, c);
|
||||
const gp_XYZ ab = (b.XYZ() - a.XYZ());
|
||||
const gp_XYZ ac = (c.XYZ() - a.XYZ());
|
||||
const gp_Vec cross = ab.Crossed(ac);
|
||||
if (cross.SquareMagnitude() > ALMOST_ZERO) {
|
||||
const gp_Dir n = cross;
|
||||
face_surface = new Geom_Plane(a, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (!same_sense) {
|
||||
wire.Reverse();
|
||||
}
|
||||
|
||||
ShapeFix_ShapeTolerance FTol;
|
||||
FTol.SetTolerance(wire, getValue(GV_PRECISION), TopAbs_WIRE);
|
||||
|
||||
if (!mf) {
|
||||
if (face_surface.IsNull()) {
|
||||
mf = new BRepBuilderAPI_MakeFace(wire);
|
||||
} else {
|
||||
mf = new BRepBuilderAPI_MakeFace(face_surface, wire);
|
||||
}
|
||||
|
||||
/* BRepBuilderAPI_FaceError er = mf->Error();
|
||||
if (er == BRepBuilderAPI_NotPlanar) {
|
||||
ShapeFix_ShapeTolerance FTol;
|
||||
FTol.SetTolerance(wire, getValue(GV_PRECISION), TopAbs_WIRE);
|
||||
delete mf;
|
||||
mf = new BRepBuilderAPI_MakeFace(wire);
|
||||
} */
|
||||
|
||||
if (mf->IsDone()) {
|
||||
TopoDS_Face outer_face_bound = mf->Face();
|
||||
|
||||
// If the wires are reversed the face needs to be reversed as well in order
|
||||
// to maintain the counter-clock-wise ordering of the bounding wire's vertices.
|
||||
bool all_reversed = true;
|
||||
TopoDS_Iterator it(outer_face_bound, false);
|
||||
for (; it.More(); it.Next()) {
|
||||
const TopoDS_Wire& w = TopoDS::Wire(it.Value());
|
||||
if ((w.Orientation() != TopAbs_REVERSED) == same_sense) {
|
||||
all_reversed = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_reversed) {
|
||||
outer_face_bound.Reverse();
|
||||
}
|
||||
|
||||
if (num_outer_bounds > 1) {
|
||||
builder.Add(compound, outer_face_bound);
|
||||
delete mf; mf = 0;
|
||||
} else if (num_bounds > 1) {
|
||||
// Reinitialize the builder to the outer face
|
||||
// bound in order to add holes more robustly.
|
||||
delete mf;
|
||||
mf = new BRepBuilderAPI_MakeFace(outer_face_bound);
|
||||
} else {
|
||||
face = outer_face_bound;
|
||||
success = true;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
mf->Add(wire);
|
||||
}
|
||||
processed ++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
success = processed == num_bounds;
|
||||
if (success) {
|
||||
if (num_outer_bounds > 1) {
|
||||
face = compound;
|
||||
} else {
|
||||
success = success && mf->IsDone();
|
||||
if (success) {
|
||||
face = mf->Face();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
ShapeFix_ShapeTolerance FTol;
|
||||
FTol.SetTolerance(face, getValue(GV_PRECISION), TopAbs_FACE);
|
||||
}
|
||||
|
||||
delete mf;
|
||||
return success;
|
||||
}
|
||||
|
||||
bool IfcGeom::Kernel::convert(const IfcSchema::IfcArbitraryClosedProfileDef* l, TopoDS_Shape& face) {
|
||||
|
||||
@@ -503,7 +503,6 @@ static double point_equality_tolerance = 0.00001;
|
||||
static double max_faces_to_sew = -1.0;
|
||||
static double ifc_length_unit = 1.0;
|
||||
static double ifc_planeangle_unit = -1.0;
|
||||
static double force_ccw_face_orientation = -1.0;
|
||||
static double modelling_precision = 0.00001;
|
||||
static double dimensionality = 1;
|
||||
|
||||
@@ -530,9 +529,6 @@ void IfcGeom::Kernel::setValue(GeomValue var, double value) {
|
||||
case GV_PLANEANGLE_UNIT:
|
||||
ifc_planeangle_unit = value;
|
||||
break;
|
||||
case GV_FORCE_CCW_FACE_ORIENTATION:
|
||||
force_ccw_face_orientation = value;
|
||||
break;
|
||||
case GV_PRECISION:
|
||||
modelling_precision = value;
|
||||
break;
|
||||
@@ -562,9 +558,6 @@ double IfcGeom::Kernel::getValue(GeomValue var) {
|
||||
case GV_PLANEANGLE_UNIT:
|
||||
return ifc_planeangle_unit;
|
||||
break;
|
||||
case GV_FORCE_CCW_FACE_ORIENTATION:
|
||||
return force_ccw_face_orientation;
|
||||
break;
|
||||
case GV_PRECISION:
|
||||
return modelling_precision;
|
||||
break;
|
||||
|
||||
@@ -450,7 +450,6 @@ namespace IfcGeom {
|
||||
unit_magnitude = 1.f;
|
||||
|
||||
kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.sew_shells() ? 1000 : -1);
|
||||
kernel.setValue(IfcGeom::Kernel::GV_FORCE_CCW_FACE_ORIENTATION, settings.force_ccw_face_orientation() ? 1 : -1);
|
||||
kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.include_curves() ? (settings.exclude_solids_and_surfaces() ? -1. : 0.) : +1.));
|
||||
}
|
||||
public:
|
||||
|
||||
@@ -55,9 +55,6 @@ namespace IfcGeom {
|
||||
// Specifies whether to compose IfcOpeningElements into a single compound
|
||||
// in order to speed up the processing of opening subtractions.
|
||||
static const int FASTER_BOOLEANS = 6;
|
||||
// By default singular faces have no explicitly defined orientation, to
|
||||
// force faces to be defined CounterClockWise set this to true.
|
||||
static const int FORCE_CCW_FACE_ORIENTATION = 7;
|
||||
// Disables the subtraction of IfcOpeningElement representations from
|
||||
// the related building element representations.
|
||||
static const int DISABLE_OPENING_SUBTRACTIONS = 8;
|
||||
@@ -74,7 +71,7 @@ namespace IfcGeom {
|
||||
// End of settings enumeration.
|
||||
|
||||
private:
|
||||
bool _weld_vertices, _use_world_coords, _convert_back_units, _use_brep_data, _sew_shells, _faster_booleans, _force_ccw_face_orientation, _disable_opening_subtractions, _disable_triangulation, _apply_default_materials, _include_curves, _exclude_solids_and_surfaces;
|
||||
bool _weld_vertices, _use_world_coords, _convert_back_units, _use_brep_data, _sew_shells, _faster_booleans, _disable_opening_subtractions, _disable_triangulation, _apply_default_materials, _include_curves, _exclude_solids_and_surfaces;
|
||||
double _deflection_tolerance;
|
||||
public:
|
||||
IteratorSettings()
|
||||
@@ -84,7 +81,6 @@ namespace IfcGeom {
|
||||
, _use_brep_data(false)
|
||||
, _sew_shells(false)
|
||||
, _faster_booleans(false)
|
||||
, _force_ccw_face_orientation(false)
|
||||
, _disable_opening_subtractions(false)
|
||||
, _disable_triangulation(false)
|
||||
, _apply_default_materials(false)
|
||||
@@ -107,8 +103,6 @@ namespace IfcGeom {
|
||||
bool& sew_shells() { return _sew_shells; }
|
||||
const bool& faster_booleans() const { return _faster_booleans; }
|
||||
bool& faster_booleans() { return _faster_booleans; }
|
||||
const bool& force_ccw_face_orientation() const { return _force_ccw_face_orientation; }
|
||||
bool& force_ccw_face_orientation() { return _force_ccw_face_orientation; }
|
||||
const bool& disable_opening_subtractions() const { return _disable_opening_subtractions; }
|
||||
bool& disable_opening_subtractions() { return _disable_opening_subtractions; }
|
||||
const bool& disable_triangulation() const { return _disable_triangulation; }
|
||||
@@ -143,9 +137,6 @@ namespace IfcGeom {
|
||||
case SEW_SHELLS:
|
||||
_sew_shells = value;
|
||||
break;
|
||||
case FORCE_CCW_FACE_ORIENTATION:
|
||||
_force_ccw_face_orientation = value;
|
||||
break;
|
||||
case DISABLE_OPENING_SUBTRACTIONS:
|
||||
_disable_opening_subtractions = value;
|
||||
break;
|
||||
|
||||
@@ -408,30 +408,15 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdgeLoop* l, TopoDS_Wire& resu
|
||||
IfcSchema::IfcOrientedEdge::list::ptr li = l->EdgeList();
|
||||
BRepBuilderAPI_MakeWire mw;
|
||||
for (IfcSchema::IfcOrientedEdge::list::it it = li->begin(); it != li->end(); ++it) {
|
||||
IfcSchema::IfcOrientedEdge* e = *it;
|
||||
|
||||
IfcSchema::IfcPoint* pnt1 = ((IfcSchema::IfcVertexPoint*) e->EdgeStart())->VertexGeometry();
|
||||
IfcSchema::IfcPoint* pnt2 = ((IfcSchema::IfcVertexPoint*) e->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;
|
||||
}
|
||||
|
||||
gp_Pnt p1, p2;
|
||||
if (!IfcGeom::Kernel::convert(((IfcSchema::IfcCartesianPoint*)pnt1), p1) ||
|
||||
!IfcGeom::Kernel::convert(((IfcSchema::IfcCartesianPoint*)pnt2), p2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mw.Add(BRepBuilderAPI_MakeEdge(p1, p2));
|
||||
continue;
|
||||
|
||||
IfcSchema::IfcEdge* base = e->EdgeElement();
|
||||
TopoDS_Wire w;
|
||||
if (convert_wire(e->EdgeElement(), w)) {
|
||||
if (!e->Orientation()) w.Reverse();
|
||||
mw.Add(w);
|
||||
if (convert_wire(*it, w)) {
|
||||
if (!(*it)->Orientation()) w.Reverse();
|
||||
TopoDS_Iterator it(w, false);
|
||||
for (; it.More(); it.Next()) {
|
||||
const TopoDS_Edge& e = TopoDS::Edge(it.Value());
|
||||
mw.Add(e);
|
||||
}
|
||||
// mw.Add(w);
|
||||
}
|
||||
}
|
||||
result = mw;
|
||||
@@ -466,7 +451,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdge* l, TopoDS_Wire& result)
|
||||
}
|
||||
|
||||
bool IfcGeom::Kernel::convert(const IfcSchema::IfcOrientedEdge* l, TopoDS_Wire& result) {
|
||||
if (convert(l->EdgeElement(), result)) {
|
||||
if (convert_wire(l->EdgeElement(), result)) {
|
||||
if (!l->Orientation()) {
|
||||
result.Reverse();
|
||||
}
|
||||
@@ -478,7 +463,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcOrientedEdge* l, TopoDS_Wire&
|
||||
|
||||
bool IfcGeom::Kernel::convert(const IfcSchema::IfcSubedge* l, TopoDS_Wire& result) {
|
||||
TopoDS_Wire temp;
|
||||
if (convert(l->ParentEdge(), result) && convert((IfcSchema::IfcEdge*) l, temp)) {
|
||||
if (convert_wire(l->ParentEdge(), result) && convert((IfcSchema::IfcEdge*) l, temp)) {
|
||||
TopExp_Explorer exp(result, TopAbs_EDGE);
|
||||
TopoDS_Edge edge = TopoDS::Edge(exp.Current());
|
||||
Standard_Real u1, u2;
|
||||
|
||||
@@ -93,6 +93,7 @@ FACE(IfcEllipseProfileDef);
|
||||
FACE(IfcCenterLineProfileDef);
|
||||
FACE(IfcCompositeProfileDef);
|
||||
FACE(IfcDerivedProfileDef);
|
||||
// IfcFaceSurface included
|
||||
FACE(IfcFace);
|
||||
|
||||
WIRE(IfcEdgeCurve);
|
||||
|
||||
@@ -321,7 +321,6 @@ int main (int argc, char** argv) {
|
||||
settings.use_world_coords() = false;
|
||||
settings.weld_vertices() = false;
|
||||
settings.convert_back_units() = true;
|
||||
settings.force_ccw_face_orientation() = true;
|
||||
settings.include_curves() = true;
|
||||
|
||||
iterator = new IfcGeom::Iterator<float>(settings, data, len);
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
|
||||
%extend IfcGeom::IteratorSettings {
|
||||
%pythoncode %{
|
||||
attrs = ("convert_back_units", "deflection_tolerance", "disable_opening_subtractions", "disable_triangulation", "faster_booleans", "force_ccw_face_orientation", "sew_shells", "use_brep_data", "use_world_coords", "weld_vertices")
|
||||
attrs = ("convert_back_units", "deflection_tolerance", "disable_opening_subtractions", "disable_triangulation", "faster_booleans", "sew_shells", "use_brep_data", "use_world_coords", "weld_vertices")
|
||||
def __repr__(self):
|
||||
return "%s(%s)"%(self.__class__.__name__, ",".join(tuple("%s=%r"%(a, getattr(self, a)()) for a in self.attrs)))
|
||||
%}
|
||||
@@ -218,7 +218,6 @@
|
||||
|
||||
IfcGeom::Kernel kernel;
|
||||
kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.sew_shells() ? 1000 : -1);
|
||||
kernel.setValue(IfcGeom::Kernel::GV_FORCE_CCW_FACE_ORIENTATION, settings.force_ccw_face_orientation() ? 1 : -1);
|
||||
kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.include_curves() ? (settings.exclude_solids_and_surfaces() ? -1. : 0.) : +1.));
|
||||
|
||||
IfcSchema::IfcProduct* product = (IfcSchema::IfcProduct*) instance;
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
ISO-10303-21;
|
||||
HEADER;
|
||||
FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
|
||||
FILE_NAME('faces.ifc','2015-05-20T10:50:06',(),(),'IfcOpenShell 0.5.0-dev','IfcOpenShell 0.5.0-dev','');
|
||||
FILE_SCHEMA(('IFC2X3'));
|
||||
ENDSEC;
|
||||
DATA;
|
||||
#1=IFCCARTESIANPOINT((-400.,-400.,0.));
|
||||
#2=IFCCARTESIANPOINT((400.,-400.,0.));
|
||||
#3=IFCCARTESIANPOINT((400.,400.,0.));
|
||||
#4=IFCCARTESIANPOINT((-400.,400.,0.));
|
||||
#5=IFCPERSON($,$,'',$,$,$,$,$);
|
||||
#6=IFCORGANIZATION($,'IfcOpenShell',$,$,$);
|
||||
#7=IFCPERSONANDORGANIZATION(#5,#6,$);
|
||||
#8=IFCAPPLICATION(#6,'0.5.0-dev','IfcOpenShell','IfcOpenShell');
|
||||
#9=IFCOWNERHISTORY(#7,#8,$,.ADDED.,1432111806,#7,#8,1432111806);
|
||||
#10=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0);
|
||||
#11=IFCSIUNIT(*,.LENGTHUNIT.,.MILLI.,.METRE.);
|
||||
#12=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.);
|
||||
#14=IFCMEASUREWITHUNIT(IFCPLANEANGLEMEASURE(0.017453293),#12);
|
||||
#15=IFCCONVERSIONBASEDUNIT(#10,.PLANEANGLEUNIT.,'Degrees',#14);
|
||||
#16=IFCUNITASSIGNMENT((#11,#15));
|
||||
#17=IFCPROJECT('1HQX190X58kvRECR6voyfc',#9,$,$,$,$,$,(#51),#16);
|
||||
#18=IFCDIRECTION((1.,0.,0.));
|
||||
#19=IFCDIRECTION((0.,0.,1.));
|
||||
#20=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#21=IFCAXIS2PLACEMENT3D(#20,#19,#18);
|
||||
#22=IFCLOCALPLACEMENT($,#21);
|
||||
#23=IFCSITE('0eyqmWf4z3dANo5Kaef3tu',#9,$,$,$,#22,$,$,.ELEMENT.,$,$,$,$,$);
|
||||
#24=IFCRELAGGREGATES('18QNJy24z3FB9H1omtBuo_',#9,$,$,#17,(#23));
|
||||
#25=IFCDIRECTION((1.,0.,0.));
|
||||
#26=IFCDIRECTION((0.,0.,1.));
|
||||
#27=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#28=IFCAXIS2PLACEMENT3D(#27,#26,#25);
|
||||
#29=IFCLOCALPLACEMENT(#22,#28);
|
||||
#30=IFCBUILDING('3jWWZTz7n64v5lXI7dcOG2',#9,$,$,$,#29,$,$,.ELEMENT.,$,$,$);
|
||||
#31=IFCRELAGGREGATES('3I_AMlVAjD7AJyIfSH193g',#9,$,$,#23,(#30));
|
||||
#32=IFCDIRECTION((1.,0.,0.));
|
||||
#33=IFCDIRECTION((0.,0.,1.));
|
||||
#34=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#35=IFCAXIS2PLACEMENT3D(#34,#33,#32);
|
||||
#36=IFCLOCALPLACEMENT(#29,#35);
|
||||
#37=IFCBUILDINGSTOREY('1_ImA5b7HELAI8raWFYphY',#9,$,$,$,#36,$,$,.ELEMENT.,$);
|
||||
#38=IFCRELAGGREGATES('29hL9yBXj6lvk6BXb$wnMF',#9,$,$,#30,(#37));
|
||||
#39=IFCBUILDINGELEMENTPROXY('344_rTMFT6RuKWcRH19W6g',#9,'polyloop',$,$,#45,#58,$,$);
|
||||
#40=IFCRELCONTAINEDINSPATIALSTRUCTURE('2RQ$SfpKfBYuSRATxRwC0V',#9,$,$,(#39),#37);
|
||||
#41=IFCDIRECTION((1.,0.,0.));
|
||||
#42=IFCDIRECTION((0.,0.,1.));
|
||||
#43=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#44=IFCAXIS2PLACEMENT3D(#43,#42,#41);
|
||||
#45=IFCLOCALPLACEMENT($,#44);
|
||||
#46=IFCDIRECTION((0.,1.));
|
||||
#47=IFCDIRECTION((1.,0.,0.));
|
||||
#48=IFCDIRECTION((0.,0.,1.));
|
||||
#49=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#50=IFCAXIS2PLACEMENT3D(#49,#48,#47);
|
||||
#51=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-005,#50,#46);
|
||||
#52=IFCPOLYLOOP((#1,#2,#3,#4));
|
||||
#53=IFCFACEOUTERBOUND(#52,.T.);
|
||||
#54=IFCFACE((#53));
|
||||
#55=IFCOPENSHELL((#54));
|
||||
#56=IFCFACEBASEDSURFACEMODEL((#55));
|
||||
#57=IFCSHAPEREPRESENTATION(#51,'Body','SurfaceModel',(#56));
|
||||
#58=IFCPRODUCTDEFINITIONSHAPE($,$,(#57));
|
||||
#59=IFCCARTESIANPOINT((400.,0.,0.));
|
||||
#60=IFCCARTESIANPOINT((-400.,0.,0.));
|
||||
#61=IFCDIRECTION((1.,0.));
|
||||
#62=IFCCARTESIANPOINT((0.,0.));
|
||||
#63=IFCAXIS2PLACEMENT2D(#62,#61);
|
||||
#64=IFCBUILDINGELEMENTPROXY('35crzRJnnE9Akf8211DDa3',#9,'circle',$,$,#70,#84,$,$);
|
||||
#65=IFCRELCONTAINEDINSPATIALSTRUCTURE('3gBsuCqwb3me5EkC8o3Mpn',#9,$,$,(#64),#37);
|
||||
#66=IFCDIRECTION((1.,0.,0.));
|
||||
#67=IFCDIRECTION((0.,0.,1.));
|
||||
#68=IFCCARTESIANPOINT((1000.,0.,0.));
|
||||
#69=IFCAXIS2PLACEMENT3D(#68,#67,#66);
|
||||
#70=IFCLOCALPLACEMENT($,#69);
|
||||
#71=IFCVERTEXPOINT(#59);
|
||||
#72=IFCVERTEXPOINT(#60);
|
||||
#73=IFCCIRCLE(#63,400.);
|
||||
#74=IFCEDGECURVE(#71,#72,#73,.T.);
|
||||
#75=IFCORIENTEDEDGE(*,*,#74,.T.);
|
||||
#76=IFCEDGECURVE(#72,#71,#73,.T.);
|
||||
#77=IFCORIENTEDEDGE(*,*,#76,.T.);
|
||||
#78=IFCEDGELOOP((#75,#77));
|
||||
#79=IFCFACEOUTERBOUND(#78,.T.);
|
||||
#80=IFCFACE((#79));
|
||||
#81=IFCOPENSHELL((#80));
|
||||
#82=IFCFACEBASEDSURFACEMODEL((#81));
|
||||
#83=IFCSHAPEREPRESENTATION(#51,'Body','SurfaceModel',(#82));
|
||||
#84=IFCPRODUCTDEFINITIONSHAPE($,$,(#83));
|
||||
#85=IFCCARTESIANPOINT((-400.,-400.,0.));
|
||||
#86=IFCCARTESIANPOINT((400.,-400.,0.));
|
||||
#87=IFCCARTESIANPOINT((400.,400.,0.));
|
||||
#88=IFCCARTESIANPOINT((-400.,400.,0.));
|
||||
#89=IFCCARTESIANPOINT((-300.,-300.,0.));
|
||||
#90=IFCCARTESIANPOINT((-100.,-300.,0.));
|
||||
#91=IFCCARTESIANPOINT((-100.,300.,0.));
|
||||
#92=IFCCARTESIANPOINT((-300.,300.,0.));
|
||||
#93=IFCCARTESIANPOINT((100.,300.,0.));
|
||||
#94=IFCCARTESIANPOINT((300.,300.,0.));
|
||||
#95=IFCCARTESIANPOINT((300.,-300.,0.));
|
||||
#96=IFCCARTESIANPOINT((100.,-300.,0.));
|
||||
#97=IFCBUILDINGELEMENTPROXY('3w09rKcILCYAnKVxlLSjOP',#9,'polyloop with holes',$,$,#103,#114,$,$);
|
||||
#98=IFCRELCONTAINEDINSPATIALSTRUCTURE('2QRyhTXwH8WPAUUlchhb7x',#9,$,$,(#97),#37);
|
||||
#99=IFCDIRECTION((1.,0.,0.));
|
||||
#100=IFCDIRECTION((0.,0.,1.));
|
||||
#101=IFCCARTESIANPOINT((2000.,0.,0.));
|
||||
#102=IFCAXIS2PLACEMENT3D(#101,#100,#99);
|
||||
#103=IFCLOCALPLACEMENT($,#102);
|
||||
#104=IFCPOLYLOOP((#89,#90,#91,#92));
|
||||
#105=IFCFACEBOUND(#104,.F.);
|
||||
#106=IFCPOLYLOOP((#85,#86,#87,#88));
|
||||
#107=IFCFACEOUTERBOUND(#106,.T.);
|
||||
#108=IFCPOLYLOOP((#93,#94,#95,#96));
|
||||
#109=IFCFACEBOUND(#108,.T.);
|
||||
#110=IFCFACE((#105,#107,#109));
|
||||
#111=IFCOPENSHELL((#110));
|
||||
#112=IFCFACEBASEDSURFACEMODEL((#111));
|
||||
#113=IFCSHAPEREPRESENTATION(#51,'Body','SurfaceModel',(#112));
|
||||
#114=IFCPRODUCTDEFINITIONSHAPE($,$,(#113));
|
||||
#115=IFCCARTESIANPOINT((-400.,-400.,0.));
|
||||
#116=IFCCARTESIANPOINT((-100.,-400.,0.));
|
||||
#117=IFCCARTESIANPOINT((-100.,400.,0.));
|
||||
#118=IFCCARTESIANPOINT((-400.,400.,0.));
|
||||
#119=IFCCARTESIANPOINT((100.,400.,0.));
|
||||
#120=IFCCARTESIANPOINT((400.,400.,0.));
|
||||
#121=IFCCARTESIANPOINT((400.,-400.,0.));
|
||||
#122=IFCCARTESIANPOINT((100.,-400.,0.));
|
||||
#123=IFCBUILDINGELEMENTPROXY('0cxEkTWf97T8imCiw2hTqD',#9,'multiple outer boundaries (invalid)',$,$,#129,#138,$,$);
|
||||
#124=IFCRELCONTAINEDINSPATIALSTRUCTURE('0$orfSvG18vfnhm9zOB5l5',#9,$,$,(#123),#37);
|
||||
#125=IFCDIRECTION((1.,0.,0.));
|
||||
#126=IFCDIRECTION((0.,0.,1.));
|
||||
#127=IFCCARTESIANPOINT((3000.,0.,0.));
|
||||
#128=IFCAXIS2PLACEMENT3D(#127,#126,#125);
|
||||
#129=IFCLOCALPLACEMENT($,#128);
|
||||
#130=IFCPOLYLOOP((#115,#116,#117,#118));
|
||||
#131=IFCFACEOUTERBOUND(#130,.T.);
|
||||
#132=IFCPOLYLOOP((#119,#120,#121,#122));
|
||||
#133=IFCFACEOUTERBOUND(#132,.F.);
|
||||
#134=IFCFACE((#131,#133));
|
||||
#135=IFCOPENSHELL((#134));
|
||||
#136=IFCFACEBASEDSURFACEMODEL((#135));
|
||||
#137=IFCSHAPEREPRESENTATION(#51,'Body','SurfaceModel',(#136));
|
||||
#138=IFCPRODUCTDEFINITIONSHAPE($,$,(#137));
|
||||
#139=IFCCARTESIANPOINT((-400.,-400.,1.E-006));
|
||||
#140=IFCCARTESIANPOINT((400.,-400.,0.));
|
||||
#141=IFCCARTESIANPOINT((400.,400.,0.));
|
||||
#142=IFCCARTESIANPOINT((-400.,400.,0.));
|
||||
#143=IFCBUILDINGELEMENTPROXY('1u73lgHiH3IesmFCYzbd$l',#9,'imprecise polyloop',$,$,#149,#156,$,$);
|
||||
#144=IFCRELCONTAINEDINSPATIALSTRUCTURE('0AV1k6Kl19x9ot0jkkQV8h',#9,$,$,(#143),#37);
|
||||
#145=IFCDIRECTION((1.,0.,0.));
|
||||
#146=IFCDIRECTION((0.,0.,1.));
|
||||
#147=IFCCARTESIANPOINT((4000.,0.,0.));
|
||||
#148=IFCAXIS2PLACEMENT3D(#147,#146,#145);
|
||||
#149=IFCLOCALPLACEMENT($,#148);
|
||||
#150=IFCPOLYLOOP((#139,#140,#141,#142));
|
||||
#151=IFCFACEOUTERBOUND(#150,.T.);
|
||||
#152=IFCFACE((#151));
|
||||
#153=IFCOPENSHELL((#152));
|
||||
#154=IFCFACEBASEDSURFACEMODEL((#153));
|
||||
#155=IFCSHAPEREPRESENTATION(#51,'Body','SurfaceModel',(#154));
|
||||
#156=IFCPRODUCTDEFINITIONSHAPE($,$,(#155));
|
||||
ENDSEC;
|
||||
END-ISO-10303-21;
|
||||
Reference in New Issue
Block a user