Transform.ChangeBasis or Orient3Pt

I want to locate a curve on two points, just like the “Orient3Pt” or “Orient” command in Rhino. I read the documentation and searched the forum. The answer I got is Transform.ChangeBasis Method, but there are not many documents explained in it. , The search example is the same, I don’t understand it well, can someone give me an example or explanation to help me understand it better? Thank you very much!
The effect I want to achieve is as follows:

Can you post a .3dm file with the geometry in it?

The idea of the ChangeBasis method is that you identify the source plane (looks like Plane.WorldXZ) and the target plane. The target plane goes through the two start points of the two curves and its normal could be calculated by the vector cross product of the vector between the two points and the Vector3d.XAxis vector.

A complicating factor could be that the blue curve seems to have a slightly different shape than the red one; the red one seems to be a bit more flattened than the blue one. This can also be handled with change basis I think, by choosing basis vectors of the correct length.

demo.3dm (26.4 KB)
the red one seems to be a bit more flattened than the blue one.
Because of scaling

Transform.PlaneToPlane might also help

1 Like

Thank you very much for your help, I have basically understood these commands. Just to calculate the plane formed between the two points is still a bit lacking in knowledge for me, I still need to learn related knowledge, in short, thank you very much for your help! :+1:t2:

Yes, thank you very much for your help, it is also very useful for me

1 Like

It took a while, but today I had some time to figure this out. Please see the command below for the plane-to-plane transformation.

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
  Result res = RhinoGet.GetOneObject("Select outline", false, ObjectType.Curve, out var outlineRef);
  if (res != Result.Success)
    return res;

  // deselect before continuing
  doc.Objects.Select(outlineRef, false);

  res = RhinoGet.GetMultipleObjects("Select two rails", false, ObjectType.Curve, out var railRefs);
  if (res != Result.Success)
    return res;

  if (railRefs.Length != 2)
    RhinoApp.WriteLine("Please select exactly two rails.");
    return Result.Success;

  Curve outline = outlineRef.Curve();

  Curve railA = railRefs[0].Curve();
  Curve railB = railRefs[1].Curve();

  Point3d rA = railA.PointAtStart;
  Point3d rB = railB.PointAtStart;
  // find the intersection points on the outline curve that should align with 
  // the two rail curves
  var cxx = Intersection.CurvePlane(outline, Plane.WorldZX, doc.ModelAbsoluteTolerance);
  if (null == cxx || cxx.Count != 2)
    RhinoApp.WriteLine("Failed to intersect outline curve with the ZX plane to obtain two intersection points.");
    return Result.Success;

  Point3d cxA = cxx[0].PointA;
  Point3d cxB = cxx[1].PointA;

  // determine the scaling factor and scale the outline and the two intersection points
  var scale = Transform.Scale(Point3d.Origin, (rB - rA).Length / (cxB - cxA).Length);

  // define the outline plane (start of transform) and the rails plane (end of transform)
  Plane oPlane = new Plane(cxA, (cxB - cxA), Vector3d.YAxis);
  Plane rPlane = new Plane(rA, (rB -rA), Vector3d.YAxis);

  // transform the scaled outline curve 
  var xform = Transform.PlaneToPlane(oPlane, rPlane);
  if (outline.Transform(xform))
    RhinoApp.WriteLine("Failed to transform the outline curve.");
    return Result.Success;

  return Result.Success;

thank you very much!!!
Unexpectedly, you still remember, thank you!
You solved a lot of my problems!

1 Like