XbimGeometry icon indicating copy to clipboard operation
XbimGeometry copied to clipboard

Create IFC file using tessellated data

Open rahulkhandepts opened this issue 4 years ago • 13 comments

Hello Team,

I'm new to XbimGeometry. I need to create IFC file with tessellation data. I found IFC Schema IFC4 supports entity of type IfcTriangulatedFaceSet using which geometries can be created. But unfortunately, I could not sum to get started.

Can I get a working example or guidelines to use the same?

Help will be really appreciated,. Thanks in advance

rahulkhandepts avatar Apr 01 '21 12:04 rahulkhandepts

Hello!

I have the same question. Can you give some code example of creating and filling IfcTriangulatedFaceSet with my custom verticies, indicies, normals and face colors. And also it's interesting, is there any analog of IfcTriangulatedFaceSet in IFC2x3.

Thank you!

GVladislavG avatar Apr 02 '21 12:04 GVladislavG

Here is a minimal example:

private static IfcTriangulatedFaceSet CreateTetrahedron(IModel model)
{
    return model.Instances.New<IfcTriangulatedFaceSet>(tfs => {
        tfs.Closed = true;
        tfs.Coordinates = model.Instances.New<IfcCartesianPointList3D>(pl => {
            pl.CoordList.GetAt(0).AddRange(new IfcLengthMeasure[] { 0, 0, 0 });
            pl.CoordList.GetAt(1).AddRange(new IfcLengthMeasure[] { 1, 0, 0 });
            pl.CoordList.GetAt(2).AddRange(new IfcLengthMeasure[] { 0, 1, 0 });
            pl.CoordList.GetAt(3).AddRange(new IfcLengthMeasure[] { 0, 0, 1 });
        });

        // Indices are 1 based in IFC !!!
        tfs.CoordIndex.GetAt(0).AddRange(new IfcPositiveInteger[] { 1, 3, 2 });
        tfs.CoordIndex.GetAt(1).AddRange(new IfcPositiveInteger[] { 1, 2, 4 });
        tfs.CoordIndex.GetAt(2).AddRange(new IfcPositiveInteger[] { 1, 4, 3 });
        tfs.CoordIndex.GetAt(3).AddRange(new IfcPositiveInteger[] { 2, 3, 4 });
    });
}

Prior to IFC4 you could use IfcClosedShell. But IfcTriangulatedFaceSet is far better for this.

martin1cerny avatar Apr 06 '21 09:04 martin1cerny

So is there no way to write triangulated mesh in IFC2x3? I just looked in IfcClosedShell and there are no vericies, indicies, etc.

GVladislavG avatar Apr 06 '21 15:04 GVladislavG

You would have to create IfcClosedShell (or open shell) where your triangles would become faces (CfsFaces). This is far from being optimal but it is what BIM tools do when they export triangulated mesh as IFC2x3.

martin1cerny avatar Apr 06 '21 15:04 martin1cerny

Is there any code example like for IfcTriangulatedFaceSet? Thanks!

GVladislavG avatar Apr 09 '21 19:04 GVladislavG

All you need is in the documentation. Start at Alphabetical listing -> Entities -> IfcClosedShell.

martin1cerny avatar Apr 12 '21 07:04 martin1cerny

I got one more question. How can I represent element like this? Забор Can I add some representation of lines and curves to IfcProduct with IfcTriangulatedFaceSet?

Thanks!

GVladislavG avatar Apr 13 '21 15:04 GVladislavG

Yes, you can add it as another representation (not IfcTriangulatedFaceSet). But many tools (including xbim UI components) will not show it as things need to be 3D in 3D view.

martin1cerny avatar Apr 13 '21 15:04 martin1cerny

What class do I need to use as representation for this lines(curves)? Do I understand correctly, that I can use two representations for one IfcProduct? One for IfcTriangulatedFaceSet for the footings and one for the grid?

GVladislavG avatar Apr 13 '21 18:04 GVladislavG

Maybe IfcLine for lines and IfcCurve for curves? You should read IFC documentation to identify the best fit for your data. The rest of your question depends on the structure of your data.

martin1cerny avatar Apr 14 '21 07:04 martin1cerny

Hello! I try to create and fill IfcClosedShell according to documentation. Use this code:

var ifcClosedShell = model.Instances.New<Xbim.Ifc2x3.TopologyResource.IfcClosedShell>(cs =>
{
      foreach (var meshTuple in meshList)
      {                            
            var csMesh = m_Meshes[meshTuple.Item1];                            
            for (int i = 0; i < csMesh.Faces; i++)
            {
                  var face = model.Instances.New<Xbim.Ifc2x3.TopologyResource.IfcFace>(fc =>
                  {
                        var edgeLoop = model.Instances.New<Xbim.Ifc2x3.TopologyResource.IfcEdgeLoop>(loop =>
                        {
                              var edge1 = model.Instances.New<Xbim.Ifc2x3.TopologyResource.IfcOrientedEdge>();
                              //edge1.EdgeStart =
                              //edge1.EdgeEnd =

                              var edge2 = model.Instances.New<Xbim.Ifc2x3.TopologyResource.IfcOrientedEdge>();
                              //edge2.EdgeStart =
                              //edge2.EdgeEnd =

                              var edge3 = model.Instances.New<Xbim.Ifc2x3.TopologyResource.IfcOrientedEdge>();
                              //edge3.EdgeStart =
                              //edge3.EdgeEnd =

                              loop.EdgeList.Add(edge1); loop.EdgeList.Add(edge2); loop.EdgeList.Add(edge3);
                         });
                         var faceBound = model.Instances.New<Xbim.Ifc2x3.TopologyResource.IfcFaceBound>();
                         faceBound.Bound = edgeLoop;
                         fc.Bounds.Add(faceBound);
                   });   
                   cs.CfsFaces.Add(face);                                                            
            }
      }
 });

But I can't understand how to set EdgeStart and EdgeEnd verticies with coordinates... Thanks!

GVladislavG avatar Apr 17 '21 13:04 GVladislavG

As you can see from the documentation, these EdgeStart and EdgeEnd are derived properties, so you can't set them to anything:

ENTITY IfcOrientedEdge
 SUBTYPE OF (IfcEdge);
  EdgeElement : IfcEdge;
  Orientation : IfcBoolean;
 DERIVE
  SELF\IfcEdge.EdgeStart : IfcVertex := IfcBooleanChoose (Orientation, EdgeElement.EdgeStart, EdgeElement.EdgeEnd);
  SELF\IfcEdge.EdgeEnd : IfcVertex := IfcBooleanChoose (Orientation, EdgeElement.EdgeEnd, EdgeElement.EdgeStart);
 WHERE
  EdgeElementNotOriented : NOT('IFCTOPOLOGYRESOURCE.IfcOrientedEdge' IN TYPEOF(EdgeElement));
END_ENTITY;

martin1cerny avatar Apr 19 '21 07:04 martin1cerny

Now I use this code to create IfcClosedShell. It compiles well. But after attempting to add this geometry to IfcProduct there's no any visible geometry in file.

var ifcClosedShell = model.Instances.New<Xbim.Ifc2x3.TopologyResource.IfcClosedShell>(cs =>
{
  //Запишем грани
     foreach (var meshTuple in meshList)
     {                            
          var csMesh = m_Meshes[meshTuple.Item1];                            
          for (int i = 0; i < csMesh.Faces; i++)
          {
                var face = model.Instances.New<Xbim.Ifc2x3.TopologyResource.IfcFace>(fc =>
                {
                      var polyLoop = model.Instances.New<Xbim.Ifc2x3.TopologyResource.IfcPolyLoop>(pLoop =>
                      {
                            var v1 = csMesh.Vertices[csMesh.Index[i * 3]];
                            var v2 = csMesh.Vertices[csMesh.Index[i * 3 + 1]];
                            var v3 = csMesh.Vertices[csMesh.Index[i * 3 + 2]];

                            var pt1 = model.Instances.New<Xbim.Ifc2x3.GeometryResource.IfcCartesianPoint>(p => 
                                                                                p.SetXYZ(v1.Position.x, v1.Position.y, v1.Position.z));
                            var pt2 = model.Instances.New<Xbim.Ifc2x3.GeometryResource.IfcCartesianPoint>(p => 
                                                                                p.SetXYZ(v2.Position.x, v2.Position.y, v2.Position.z));
                            var pt3 = model.Instances.New<Xbim.Ifc2x3.GeometryResource.IfcCartesianPoint>(p => 
                                                                                p.SetXYZ(v3.Position.x, v3.Position.y, v3.Position.z));

                            pLoop.Polygon.Add(pt1); pLoop.Polygon.Add(pt2); pLoop.Polygon.Add(pt3);
                      });
                     var faceBound = model.Instances.New<Xbim.Ifc2x3.TopologyResource.IfcFaceBound>();
                     faceBound.Bound = polyLoop;
                     fc.Bounds.Add(faceBound);
                 });
                 cs.CfsFaces.Add(face);                                                                
         }                            
    }
});

Is this code correct? Here's my result IFC-file tst.zip

Thanks!

GVladislavG avatar Apr 20 '21 13:04 GVladislavG