3D line

3D line

anishkt
Contributor Contributor
295 Views
2 Replies
Message 1 of 3

3D line

anishkt
Contributor
Contributor

Hi,

I have a bit of an experience in autolisp, VBA and VB.Net when it comes to Autocad customisation. About 2 years ago, I started using Revit and recently, I set upon doing some customisation in revit. And I find it difficult even to carry out simple tasks. And I find almost no examples or tutorials that I can check out.

The task is very simple. I have an excel file(extracted from autocad drawing) with 3d co-ordinates. I need to re-create this 3d line in revit project and then sweep a profile family along this path(within the project environment).

I was able to create the line in 2D on a sketch plane. But I cannot figure out how to create a 3d 'polyline' (or equivalent) in revit.

Can someone help?

 

 

0 Likes
296 Views
2 Replies
Replies (2)
Message 2 of 3

ricaun
Advisor
Advisor

In Revit is kinda annoying to create a 3d line, usually you need a plane reference.

 

But if you only need the visual line the easiest way is to create a DirectShape with Line objects, and in the same way you could create a sweep and create a DirectShape with that solid.

 

You could search for some sample for DirectShape, and when I find some gonna share here.

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 3 of 3

RPTHOMAS108
Mentor
Mentor

You only need to consider planes if you are drawing lines or other curves i.e. creating CurveElements not Curves.

 

Here is a simple example of sweeping a polyline. The tricky part of sweeping is getting the right plane orientation for the end of the curve. If the start curve is a line you can do the below (first example) for others you can do similar with Curve.ComputeDerivatives (2nd example) important to note that for certain curves the vectors from this function will not be normalised and sometimes not even orthogonal. However you can usually use them to create an orthogonal and normalised system. Both these cases are simple extrusions but there is scope in the API function to add different profiles along the sweep and at different parameter positions along each curve.

 

    Private Function Obj_230129b(ByVal commandData As Autodesk.Revit.UI.ExternalCommandData,
ByRef message As String, ByVal elements As Autodesk.Revit.DB.ElementSet) As Result
        Dim UIApp As UIApplication = commandData.Application
        Dim UIDoc As UIDocument = commandData.Application.ActiveUIDocument
        If UIDoc Is Nothing Then Return Result.Cancelled Else
        Dim IntDoc As Document = UIDoc.Document

        Dim Pt = Function(x As Double, y As Double, z As Double)
                     Return New XYZ(x, y, z)
                 End Function

        Dim Points As XYZ() = New XYZ(10) {Pt(0, 0, 0), Pt(0.2, 0, 0.2), Pt(0.4, 0, 0.4), Pt(0.6, 0, 0.8),
                                         Pt(0.8, 0, 0.8), Pt(1, 0, 1), Pt(1.2, 0, 0.8), Pt(1.4, 0, 0.8),
                                         Pt(1.6, 0, 0.4), Pt(1.8, 0, 0.2), Pt(2, 0, 0)}

        'check vertical case
        'Points = New XYZ(1) {Pt(0, 0, 0), Pt(0, 0, 2)}

        Dim CLPath As New CurveLoop
        For i = 0 To Points.Length - 2
            CLPath.Append(Line.CreateBound(Points(i), Points(i + 1)))
        Next

        Dim StartSeg As Line = CLPath(0)
        Dim Dir As XYZ = StartSeg.Direction.Normalize 'should be normalised anyway
        Dim V0 As XYZ = XYZ.BasisZ
        'Check if direction of line is more towards 0,0,1 or 1,0,0
        If Math.Abs(Dir.DotProduct(XYZ.BasisZ)) > Math.Abs(Dir.DotProduct(XYZ.BasisX)) Then
            V0 = XYZ.BasisX
        Else
            V0 = XYZ.BasisZ
        End If
        Dim By As XYZ = Dir.CrossProduct(V0).Normalize
        Dim Bx As XYZ = Dir.CrossProduct(By).Normalize

        Dim A0 As Arc = Arc.Create(Points(0), 0.01, 0, Math.PI, Bx, By)
        Dim A1 As Arc = Arc.Create(Points(0), 0.01, Math.PI, 2 * Math.PI, Bx, By)

        Dim EP As Double = StartSeg.GetEndParameter(0)

        Dim Profile As New CurveLoop
        Profile.Append(A0)
        Profile.Append(A1)

        Using tx As New Transaction(IntDoc, "Curve")
            If tx.Start = TransactionStatus.Started Then
                Dim S As Solid = GeometryCreationUtilities.CreateSweptGeometry(CLPath, 0, EP, {Profile}.ToList)

                Dim DS As DirectShape = DirectShape.CreateElement(IntDoc,
                                            New ElementId(BuiltInCategory.OST_GenericModel))

                DS.SetShape(New GeometryObject(0) {S}.ToList)

                tx.Commit()
            End If
        End Using

        Return Result.Succeeded
    End Function

 

If you want a smooth fit then you'll have to use a spline, the most straightforward one to use is the HermiteSpline. The more points you have the less the abrupt changes in the curve. This is the advantage of NurbSpline, less control points required but other complexities to consider.

 

Similar example with HermiteSpline

 

    Private Function Obj_230129b(ByVal commandData As Autodesk.Revit.UI.ExternalCommandData,
ByRef message As String, ByVal elements As Autodesk.Revit.DB.ElementSet) As Result
        Dim UIApp As UIApplication = commandData.Application
        Dim UIDoc As UIDocument = commandData.Application.ActiveUIDocument
        If UIDoc Is Nothing Then Return Result.Cancelled Else
        Dim IntDoc As Document = UIDoc.Document

        Dim Pt = Function(x As Double, y As Double, z As Double)
                     Return New XYZ(x, y, z)
                 End Function

        Dim Points As XYZ() = New XYZ(10) {Pt(0, 0, 0), Pt(0.2, 0, 0.2), Pt(0.4, 0, 0.4), Pt(0.6, 0, 0.8),
                                         Pt(0.8, 0, 0.8), Pt(1, 0, 1), Pt(1.2, 0, 0.8), Pt(1.4, 0, 0.8),
                                         Pt(1.6, 0, 0.4), Pt(1.8, 0, 0.2), Pt(2, 0, 0)}

        Dim HC As HermiteSpline = HermiteSpline.Create(Points.ToList, False)
        Dim T As Transform = HC.ComputeDerivatives(0, False)
        Dim Bx As XYZ = T.BasisX.Normalize 'tangent with direction of curve
        Dim By As XYZ = T.BasisY.Normalize
        Dim Bz As XYZ = Bx.CrossProduct(By).Normalize
        By = Bz.CrossProduct(Bx).Normalize

        Dim A0 As Arc = Arc.Create(Points(0), 0.01, 0, Math.PI, Bz, By)
        Dim A1 As Arc = Arc.Create(Points(0), 0.01, Math.PI, 2 * Math.PI, Bz, By)

        Dim EP As Double = HC.GetEndParameter(0)

        Dim Profile As New CurveLoop
        Profile.Append(A0)
        Profile.Append(A1)

        Dim CLPath As New CurveLoop
        CLPath.Append(HC)

        Using tx As New Transaction(IntDoc, "Curve")
            If tx.Start = TransactionStatus.Started Then
                Dim S As Solid = GeometryCreationUtilities.CreateSweptGeometry(CLPath, 0, EP, {Profile}.ToList)

                Dim DS As DirectShape = DirectShape.CreateElement(IntDoc,
                                            New ElementId(BuiltInCategory.OST_GenericModel))

                DS.SetShape(New GeometryObject(0) {S}.ToList)

                tx.Commit()
            End If
        End Using

        Return Result.Succeeded
    End Function

 

0 Likes