Issue with modifying Curves

Issue with modifying Curves

BenoitE&A
Collaborator Collaborator
2,827 Views
2 Replies
Message 1 of 3

Issue with modifying Curves

BenoitE&A
Collaborator
Collaborator

Hey all,

I have a problem with the function Curve.MakeBound(double startParameter, double endParameter). 

I test the length of the shorten curve before using MakeBound, and still Revit returns an exception of the type : The new parametrization made the curve too small for Revit's tolerance. 

I don't get it : I did not modify the parametrization so it should be the natural parametrization of the curve that is returned. I test whether the length of the future curve is long enough or not, then why is this exception returned?

 

Here is the principle of my code:

// Get 2 curves from a given model

Curve cv1, cv2; 

 

// Find intersections

if (cv1.Intersect(cv2, out IntersectionResultArray ira)==SetComparisonResult.Overlap)
{
                        // Multiple intersections : not treated for now
                        if (ira.Size>1) { numeroErreur = 1; }
                        // Get the first intersection point

                        XYZ intersectionPoint = ira.get_Item(0).XYZPoint;
                       
                        // Get the parameter of cv1 at intersectionPoint
                        double paraIntersection1 = polygone1[i].Project(intersectionPoint).Parameter;
                        
                        // Test whether the curve length is long enough to create the 2 pieces, else doesn't create them
                        if (Math.Abs(cv1.GetEndParameter(0) - paraIntersection1) > tolerance
                            && Math.Abs(paraIntersection1- cv1.GetEndParameter(1)) > tolerance)
                        {
                            Curve curvePiece= cv1.Clone();
                            // Cut cv1 into 2 piecessss
                            cv1.MakeBound(cv1.GetEndParameter(0), paraIntersection1);

                            curvePiece = curvePiece.MakeBound(paraIntersection1, cv1.GetEndParameter(1));

                        }

}

 

Of course if somebody has a solution to do the same not using parametrization of the curve I'd be glad of any other solution.

Sincerely

Benoit


Benoit FAVRE
CEO of etudes & automates
www.etudesetautomates.com/
0 Likes
Accepted solutions (1)
2,828 Views
2 Replies
Replies (2)
Message 2 of 3

RPTHOMAS108
Mentor
Mentor
Accepted solution

The line:

 

curvePiece = curvePiece.MakeBound(paraIntersection1, cv1.GetEndParameter(1))

 

Effectively creates a 0 length curve because you have changed the variable cv1 already to make the EndParameter(1) match the parameter of your intersection result.

 

You should instead create two new curves from the unchanged original as below.

 

Note also the parameters returned by GetEndPointParameter can really only be used as you are doing for straight lines. Other types of curves have a different parameter relationship to the curve length e.g. arc parameters are given in terms of an angle which you would have to multiply by the radius to get the arc segment length. Elliptical arcs are more complicated to get segment lengths from to test for short curves. Probably for such cases it is easier to catch the exception. Although perhaps someone else is aware of a more convenient method for getting curve lengths without first creating the curve. 

 

C#

 

public object SplitCurve(Autodesk.Revit.UI.ExternalCommandData commandData, ref string message, Autodesk.Revit.DB.ElementSet elements)
        {

            if (commandData.Application.ActiveUIDocument == null)
                return Result.Succeeded;
            UIDocument IntUIDoc = commandData.Application.ActiveUIDocument;
            Document IntDoc = IntUIDoc.Document;

            Reference R = null;
            try
            {
                R = IntUIDoc.Selection.PickObject(ObjectType.Element);
            }
            catch (Exception)
            {
            }
            if (R == null)
                return Result.Cancelled;

            XYZ Pt = R.GlobalPoint;
            Element El = IntDoc.GetElement(R);
            CurveElement CE = El as CurveElement;
            if (CE == null)
                return Result.Failed;

            Curve Crv0 = CE.GeometryCurve;

            IntersectionResult IR = Crv0.Project(Pt);

            Curve Crv_Pt1 = Crv0.Clone();
            Curve Crv_Pt2 = Crv0.Clone();

            double SCT = commandData.Application.Application.ShortCurveTolerance;

            if (Crv0.GetType() == typeof(Line))
            {
                double L1 = Math.Abs(IR.Parameter - Crv0.GetEndParameter(0));
                double L2 = Math.Abs(Crv0.GetEndParameter(1) - IR.Parameter);
                if (L1 < SCT || L2 < SCT)
                {
                    TaskDialog.Show("Error", "Resulting curve parts too small.");
                    return Result.Failed;
                }
                else
                {
                    Crv_Pt1.MakeBound(Crv0.GetEndParameter(0), IR.Parameter);
                    Crv_Pt2.MakeBound(IR.Parameter, Crv0.GetEndParameter(1));
                }
            }
            else
            {
                try
                {
                    Crv_Pt1.MakeBound(Crv0.GetEndParameter(0), IR.Parameter);
                    Crv_Pt2.MakeBound(IR.Parameter, Crv0.GetEndParameter(1));
                }
                catch (Exception ex)
                {
                    TaskDialog.Show("Error", ex.Message);
                    return Result.Failed;
                }
            }

            using (Transaction Tx = new Transaction(IntDoc, "Curve split"))
            {
                if (Tx.Start() == TransactionStatus.Started)
                {
                    IntDoc.Create.NewDetailCurve(IntDoc.ActiveView, Crv_Pt1);
                    IntDoc.Create.NewDetailCurve(IntDoc.ActiveView, Crv_Pt2);
                    IntDoc.Delete(El.Id);
                    Tx.Commit();
                }
            }

            return Result.Succeeded;
        }

 

VB:

 

Public Function SplitCurve(ByVal commandData As Autodesk.Revit.UI.ExternalCommandData, _
                           ByRef message As String, ByVal elements As Autodesk.Revit.DB.ElementSet)

        If commandData.Application.ActiveUIDocument Is Nothing Then Return Result.Succeeded Else 
        Dim IntUIDoc As UIDocument = commandData.Application.ActiveUIDocument
        Dim IntDoc As Document = IntUIDoc.Document

        Dim R As Reference = Nothing
        Try
            R = IntUIDoc.Selection.PickObject(Selection.ObjectType.Element)
        Catch ex As Exception
        End Try
        If R Is Nothing Then Return Result.Cancelled Else 

        Dim Pt As XYZ = R.GlobalPoint
        Dim El As Element = IntDoc.GetElement(R)
        Dim CE As CurveElement = TryCast(El, CurveElement)
        If CE Is Nothing Then Return Result.Failed Else 

        Dim Crv0 As Curve = CE.GeometryCurve

        Dim IR As IntersectionResult = Crv0.Project(Pt)

        Dim Crv_Pt1 As Curve = Crv0.Clone
        Dim Crv_Pt2 As Curve = Crv0.Clone

        Dim SCT As Double = commandData.Application.Application.ShortCurveTolerance

        If Crv0.GetType = GetType(Line) Then
            Dim L1 As Double = Math.Abs(IR.Parameter - Crv0.GetEndParameter(0))
            Dim L2 As Double = Math.Abs(Crv0.GetEndParameter(1) - IR.Parameter)
            If L1 < SCT OrElse L2 < SCT Then
                TaskDialog.Show("Error", "Resulting curve parts too small.")
                Return Result.Failed
            Else
                Crv_Pt1.MakeBound(Crv0.GetEndParameter(0), IR.Parameter)
                Crv_Pt2.MakeBound(IR.Parameter, Crv0.GetEndParameter(1))
            End If
        Else
            Try
                Crv_Pt1.MakeBound(Crv0.GetEndParameter(0), IR.Parameter)
                Crv_Pt2.MakeBound(IR.Parameter, Crv0.GetEndParameter(1))
            Catch ex As Exception
                TaskDialog.Show("Error", ex.Message)
                Return Result.Failed
            End Try
        End If
       
        Using Tx As New Transaction(IntDoc, "Curve split")
            If Tx.Start = TransactionStatus.Started Then
                IntDoc.Create.NewDetailCurve(IntDoc.ActiveView, Crv_Pt1)
                IntDoc.Create.NewDetailCurve(IntDoc.ActiveView, Crv_Pt2)
                IntDoc.Delete(El.Id)
                Tx.Commit()
            End If
        End Using

        Return Result.Succeeded
    End Function

 

0 Likes
Message 3 of 3

BenoitE&A
Collaborator
Collaborator

Thank you Thomas, you are absolutely right my code is dumb !!

Your solution using an exception is nice but... would require to do Something of the exception. Perhaps change de curve into a line (from starting point to end point).

Anyway, thank you.

Benoit


Benoit FAVRE
CEO of etudes & automates
www.etudesetautomates.com/
0 Likes