Committing curve trim to Rhino document (noob help)


#1

Hello all,

I apologize since this is a very basic question. I am very familiar with the Revit API which uses transaction based database modification. RhinoCommon appears to modify it’s database by direct calls to the document. This makes adding, deleting and modifying elements pretty straightforward. I am running into a problem with trimming a curve. Yes, a very simple task which has an explicit method is giving me trouble. Below is my code which trims a curve from the intersections of 2 cut curves:

void TrimCurve(Curve crv, Curve cutCrv1, Curve cutCrv2) {
    List<double> cutParams = new List<double>();
    CurveIntersections c1Ints = Intersection.CurveCurve(crv, cutCrv1, 0.001, 0.0);
    CurveIntersections c2Ints = Intersection.CurveCurve(crv, cutCrv2, 0.001, 0.0);
    cutParams.AddRange(from e in c1Ints where e.IsPoint select e.ParameterA);
    cutParams.AddRange(from e in c2Ints where e.IsPoint select e.ParameterA);
    if (2 == cutParams.Count) {
        cutParams.Sort();
        Curve trimCrv = crv.Trim(cutParams[0], cutParams[1]);
        if (null == trimCrv) {
            RhinoApp.WriteLine("Failed to split curve at given point");
        }
    } else {
        RhinoApp.WriteLine("One or both cut curves do not intersect the split curve");
    }
}

The documentation says that the Trim method will return the trimmed portion of the curve. The trim method is not returning null but the curve is not being trimmed in the document. Is this method meant to actually trim the curve? Should I instead try splitting the curve at the parameter points, identifying the portion I don’t want and deleting it? I’m stuck and feeling like I’m missing something pretty fundamental. Thanks for any advice.


(Menno Deij - van Rijswijk) #3

Yes, you must add the new curve to the document like so:

doc.Objects.AddCurve(trimCurve);

This is why you get a reference to the document in your command. Also, you can delete the input curve(s) if you want to.


#4

Thanks for the reply!

I initially thought that is what I needed to do but the documentation says that the curve returned is the trimmed portion. If I was to trim an unclosed curve, thereby splitting the curve in two, the single returned trim curve doesn’t give me the remaining portions of the trimmed curve. Am I to reconstruct either end of the curve. If that’s the case, why even use the trim method. Just construct the two ends and then delete the original curve.

Am I just missing something. Any further explanation would be great. Thanks again.


(Menno Deij - van Rijswijk) #5

This is a complete command that does what you want. Hopefully it helps you understand the steps in adding/deleting. Also, you want to issue a doc.Views.Redraw() when the curve is added - otherwise the views are redrawn when you change the view with the mouse.

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
    doc.Objects.UnselectAll();
    ObjRef cRef;
    Result res = RhinoGet.GetOneObject("Select curve to trim", false, ObjectType.Curve, out cRef);
    if (res != Result.Success) return res;

    doc.Objects.UnselectAll();
    ObjRef[] oRef;
    res = RhinoGet.GetMultipleObjects("Select two curves that intersect", false, ObjectType.Curve, out oRef);
    doc.Objects.UnselectAll();
    if (res != Result.Success)
        return res;
    if  (oRef.Length != 2)
    {
        RhinoApp.WriteLine("You selected "+oRef.Length+" curves. Expected 2.");
        return Result.Failure;
    }

    Curve crv = cRef.Curve();
    Curve cutCrv1 = oRef[0].Curve();
    Curve cutCrv2 = oRef[1].Curve();

    List<double> cutParams = new List<double>();
    CurveIntersections c1Ints = Intersection.CurveCurve(crv, cutCrv1, 0.001, 0.0);
    CurveIntersections c2Ints = Intersection.CurveCurve(crv, cutCrv2, 0.001, 0.0);
    cutParams.AddRange(from e in c1Ints where e.IsPoint select e.ParameterA);
    cutParams.AddRange(from e in c2Ints where e.IsPoint select e.ParameterA);
    if (2 == cutParams.Count)
    {
        cutParams.Sort();
        Curve trimCrv = crv.Trim(cutParams[0], cutParams[1]);
        if (null == trimCrv)
        {
            RhinoApp.WriteLine("Failed to split curve at given point");
            return Result.Failure;
        }
        doc.Objects.AddCurve(trimCrv);
        doc.Objects.Delete(cRef, true);
        doc.Views.Redraw(); 
        return Result.Success;
    }
            
    RhinoApp.WriteLine("One or both cut curves do not intersect the split curve");
    return Result.Failure;
}

#6

Thanks for the work good sir. I’m also realizing that I don’t want to trim from cutParams[0] to cutParams[1] since that will return only the portion of the cure i want to get rid of. Instead I need to do 2 trim operations for open curves from startParam to cutParams[0] and again for cutParams[1] to endParam.

Thanks for all the getting commands. I actually handle this in a slightly different way and then separated out the command to do the split.

Thanks agian.


(Menno Deij - van Rijswijk) #7

(please don’t call me sir, I’m just trying to help as I am being helped on this forum).

To perform your “trim” operations, you could do the following

if (2 == cutParams.Count)
    {
        Interval domain = crv.Domain;
        cutParams.Sort();
        Interval firstSubDomain = new Interval(domain.Min, cutParams[0]);
        Curve toFirstCut = crv.ToNurbsCurve(firstSubDomain);
        Interval lastSubDomain = new Interval(cutParams[1], domain.Max);
        Curve fromLastCut = crv.ToNurbsCurve(lastSubDomain);

        doc.Objects.AddCurve(toFirstCut);
        doc.Objects.AddCurve(fromLastCut);
        doc.Objects.Delete(cRef, true);
        doc.Views.Redraw(); 
        return Result.Success;
    }

Basically, using ToNurbsCurve(Interval) will give you a sub curve.