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
260 stars 131 forks source link

points of a selected slab #421

Closed RoyTimmers1980 closed 1 year ago

RoyTimmers1980 commented 1 year ago

I cant seem to get the points of a selected slab using vb.net in the data i see in visual studio the data is there.....

see sreenshot for code i have sofar

image

andyward commented 1 year ago

What are you hoping to with the points of a slab (at the highest level)? i.e. Are you trying to get dimensions/ of the slab? Or visualise the slab? Or edit a slab? or something else?

The screenshot shows you have a Slab's representation which is an IfcExtrudedAreaSolid describing a shape derived from sweeping an a Area profile 200 (mm) along the Z plane. The Swept area profile is defined by a PolyLine with 7 points (so presumably we're not describing a rectangular profile).

If you want to get the absolute world coordinates of the Slab after placement you'll likely want to use Xbim.Geometry repo's Geometry Engine to do the heavy lifting.

RoyTimmers1980 commented 1 year ago

Andyward, i'm trying to get the points(7) off the slab so i can draw it in Autocad via code

andyward commented 1 year ago

Those points can just be enumerated from the IfcPolyline Points property. So something like

For Each point As IIfcCartesianPoint In Solid.SweptArea.OuterCurve.Points
    Debug.Write(point .X, point .Y)
Next

But they are probably not going to to give you want you expect: you'll find they will typically give you a set of X/Y Cartesian points that define a closed Polyline defining the 'elevation view' of your slab (i.e. a side view).

I'd expect you want a plan view of your slab in AutoCAD? Even if you did want the side-view, these points may need transforming to the world coords to be appropriate.

It sounds like you'll need the Geometry Engine which handles most of this complexity to build a scene, and project to a 2D plan view

RoyTimmers1980 commented 1 year ago

Andy,

i'm getting this error:

Error BC30456 'outercurve' is not a member of 'IfcProfileDef'. I

this de code so far:

'***** IFC plattegrond
<CommandMethod("IFC2PG")>
Public Sub IFC2PG()
    'Eerst even opslaan
    'Draw.SaveActiveDrawing()
    'Draw.AllLayerOn()

    'Maak een nieuwe instantie van de IfcStore-klasse en open het IFC-bestand
    'Dim model As IfcStore = IfcStore.Open("C:\IFC\AllplanIFC.ifc")   '"1. Obergeschoss"
    ' Open het IFC-bestand
    Dim model As IfcStore = IfcStore.Open("C:\IFC\AllplanIFC.ifc")

    ' Haal de eerste verdieping op
    Dim level As IIfcBuildingStorey = model.Instances.OfType(Of IIfcBuildingStorey)().FirstOrDefault(Function(x) x.Name = "1. Obergeschoss")

    ' Haal alle vloeren op die zich op het niveau bevinden
    Dim slabs As IEnumerable(Of IIfcSlab) = model.Instances.OfType(Of IIfcSlab)().Where(Function(x) x.ContainedInStructure.FirstOrDefault(Function(y) y.RelatingStructure Is level) IsNot Nothing)

    MsgBox(slabs.Count)

    For Each slab In slabs

        'MsgBox(slab.HasOpenings.Count)   'werkt
        'MsgBox(slab.GetType.ToString)
        Dim Solid As IfcExtrudedAreaSolid = slab.Representation.Representations(0).Items(0)

        Dim CoordsString As String = ""

        'depth is vloerdikte
        'MsgBox(Solid.Depth.Value.ToString)

        If Solid IsNot Nothing Then

            For Each point As IIfcCartesianPoint In Solid.SweptArea.outercurve.points
                MsgBox(point.X)
                MsgBox(point.Y)
            Next

        End If

    Next

End Sub
andyward commented 1 year ago

It should be Solid.SweptArea.OuterCurve.Points - note the case

RoyTimmers1980 commented 1 year ago

Case does not make a difference, see image. OuterCurve is not avaiable in the list so i think im missing something see second image

image

image

andyward commented 1 year ago

It's because you would need to cast to the appropriate implementation of the abstract Ifc type. Very naively this would do the job:

            If Solid IsNot Nothing Then
                Dim Area As IIfcArbitraryClosedProfileDef = Solid.SweptArea
                Dim Curve As IIfcPolyline = Area.OuterCurve
                For Each point As IIfcCartesianPoint In Curve.Points
                    MsgBox(point.X)
                    MsgBox(point.Y)
                Next

            End If

But as I've said, I don't believe it will answer your problem.

You want to be using the Geometry engine in some form like:

using Xbim.Ifc;
using Xbim.Ifc4.Interfaces;
using Xbim.ModelGeometry.Scene;

var fileName = @"C:\IFC\AllplanIFC.ifc";

using (var model = IfcStore.Open(fileName))
{
    // get the item that you need
    var slab = model.Instances.OfType<IIfcSlab>().First();

    var geometryContext = new Xbim3DModelContext(model);
    // Use the Geometry engine to generate the 3D geometry
    geometryContext.CreateContext();

    // Get the (first) Shape Instance of this item
    Xbim.Common.Geometry.XbimShapeInstance shapeInstance = geometryContext.ShapeInstancesOf(slab).FirstOrDefault();
    // Get the geometry of the instance. Vertices, Normals, Faces etc in WCS - plus styling
    Xbim.Common.Geometry.XbimShapeGeometry shapeGeom = geometryContext.ShapeGeometry(shapeInstance);
    // World placement should you need it
    Xbim.Common.Geometry.XbimVector3D? globalPos = shapeInstance?.Transformation.Translation;
}

The VB version will be similar

RoyTimmers1980 commented 1 year ago

Thanks Andy!

this worked:

        If Solid IsNot Nothing Then
            Dim Area As IIfcArbitraryClosedProfileDef = Solid.SweptArea
            Dim Curve As IIfcPolyline = Area.OuterCurve
            For Each point As IIfcCartesianPoint In Curve.Points
                MsgBox(point.X)
                MsgBox(point.Y)
            Next

        End If
RoyTimmers1980 commented 1 year ago

Andy, i stranded on an error when the sweptarea is an IfcRectangleProfileDef then de points are not available just X and Y dimensions?? how can i extract de points off the wall like the previous example?

And the location seems to be in the center off the slab from a point of the slab??? how can i get the points from the originpoint off the model?

this is the code for the rectangle :

                    ElseIf AreaType = "IfcRectangleProfileDef" Then

                        'solid is een rechthoek
                        Dim Area As IIfcRectangleProfileDef = Solid.SweptArea
                        Dim Xdim As Double = Area.XDim
                        Dim Ydim As Double = Area.YDim
andyward commented 1 year ago

I think this is why you should leave this to the Geometry Engine. There's dozens of different ways of representing geometry and placement in IFC, and you'll never sensibly cover them all. The xbim Geometry Engine has 15 years of work behind it, and that's building on the decades of work in OpenCascade behind the scenes.

Take a look at my example in https://github.com/xBimTeam/XbimGeometry/issues/421#issuecomment-1490329208