xBimTeam / XbimGeometry

XbimGeometry contains the CLR interop libraries and the c++ engine used to compute the 3D geometry of models.
https://xbimteam.github.io/
Other
255 stars 128 forks source link

[QUESTION] How to create IFCBuildingElements by a Mesh? #117

Open lucasaue opened 6 years ago

lucasaue commented 6 years ago

Hi,

I'm working with XBim a few months and in my software project, the user can build your Architetural Project. To creates entities like walls, doors, windows, stairs every thing works so fine, but I have a problem with some families from a imported IFC files.

The imported file work so well, but I need to recreate this model from some 3D data, with Mesh (vertex, TriangleIndices...) when the user edit this model. I'm working with IFC2x3, because has more interoperability with the third softwares and I know that the IFC 2x3 there aren't IfcTriangulatedFaceSet, so I need to create my model using IFCClosedShells or IfcFaceBasedSurfaceModels.

I've been studing and I know there are some hard implementation rules to create this geometries, like for example to create a ClosedShell, you have these rules:

My question is? Is there some simple way to convert a mesh to a IFC2x3 Geometry? Is there something the I'm missing?

bekraft commented 5 years ago

Hi, indeed the use of Ifc2x3 and already triangulated surfaces is a worst-case scenario. But Ifc2x3 provides several alternative approaches to declare the boundaries of faces (edge-wise or point-vertex-wise). The basic question is: Is the given mesh (triangles) topologically correct? Means: Are all triangles oriented in the same direction (normals pointing in/out) and does the mesh have no gaps (open edges/faces)?

If you're not sure about this, you'll have to check it by yourself. Otherwise you're able to transform the triangulation into a connected face set directly.

Create a list of IfcCartesianPoint (having some 3D points as IEnumerable<double[]>:

var list = new List<IfcCartesianPoint>();
foreach (var coordinates in points.Select(p => p.Select(x => new IfcLengthMeasure(x))))
{
    var point = ifcStore.Instances.New<IfcCartesianPoint>();
    point.Coordinates.AddRange(coordinates);
    list.Add(point);
}

and generate a connected faceset out of this list with the help of the triangle-face indexes:

var faceSet = ifcStore.Instances.New<IfcConnectedFaceSet>();
var points = ... // list of IfcCartesianPoint
var indexes = ... // IEnumerable<int[]> 

foreach (var t in indexes)
{
    // Create face loop by given boundary points
    var polyLoop = ifcStore.Instances.New<IfcPolyLoop>();
    polyLoop.Polygon.AddRange(t.Select(k => points[k]));

    // Create bounds
    var bound = ifcStore.Instances.New<IfcFaceOuterBound>();
    bound.Bound = polyLoop;
    // Create face
    var face = ifcStore.Instances.New<IfcFace>();
    face.Bounds.Add(bound);
    // Add face to outer shell
    faceSet.CfsFaces.Add(face);
}

Finally you can plug this set into a new IfcFaceBasedSurfaceModel.