Curve.ProjectToPlane Method Issue

When using this method on a curve, like:

some_curve.ProjectToPlane(Rhino.Geometry.Plane.WorldXY)

I get this:
image

isn’t the first argument supposed to be self, the curve itself that I want to project?

NOTE: It’s the WIP that I’m testing this on.

Doc string says it is not for some reason:

Help on built-in function ProjectToPlane

 |  ProjectToPlane(...)
 |          ProjectToPlane(curve: Curve, plane: Plane) -> Curve
 |          
 |              Constructs a curve by projecting an existing curve to a plane.
 |          
 |              curve: A curve.
 |              plane: A plane.
 |              Returns: The projected curve on success; null on failure.

Yes, I saw, but what’s this argument for, the output curve or the original :smiley:

For original I would say:

projectedCrv = Rhino.Geometry.Curve.ProjectToPlane(originalCrv, Rhino.Geometry.Plane.WorldXY)
1 Like

Thanks @djordje,

I still consider this very weird and unnatural. Why is it a method of the Curve class if I have to provide that same curve as an argument.

This indicates that a new curve is the output… the original is not changed.

image

(otherwise, if something is changed in place, you get a Boolean return, True or False if success/failure)

no it doesn’t

Yes, it does

It says that the output is A curve, not THE curve

No, it says the return is an object of type ‘Curve’ (not A or The)

Come on, now.

The main topic is the first argument. It’s clear what the output is, alas “obfuscated”.
It has to be, IMO, self and accept just the second argument.
Not forcing you to provide the curve again. You can invoke this method from a curve, why do you have to add the same curve again as first argument?

If you run this:

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

crvID=rs.GetObject("Pick a curve")
crv=rs.coercecurve(crvID)
plane=Rhino.Geometry.Plane.WorldXY
crv.ProjectToPlane(crv,plane)
sc.doc.Objects.AddCurve(crv)
sc.doc.Views.Redraw()

You will see that you don’t get the curve projected, you get the original back again. So your ‘argument’ doesn’t hold water. This is what works:

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

crvID=rs.GetObject("Pick a curve")
crv=rs.coercecurve(crvID)
plane=Rhino.Geometry.Plane.WorldXY
proj_crv=Rhino.Geometry.Curve.ProjectToPlane(crv,plane)
sc.doc.Objects.AddCurve(proj_crv)
sc.doc.Views.Redraw()
1 Like

It’s weird!

Weird

That’s how static methods in C# work. They will always return a new object because they dont operate at the level of the class. Static methods cant access non-static fields in their containing type, and they cant access an instance variable of any object unless it is explicitly passed in a method parameter. Alas the Curve in the method arguments. I don’t see any problem with that method, Rhinocommons description works as intended.

You can think of this particular concept (static methods) in different ways. In this case, think of it as just a stray function, placed somewhere, doesn’t matter where, which provides a functionality for you, like so:

var crv = ProjectToPlane(Curve crv, params...);

Now you may ask, WHERE do I find this function? Had it been used in a non-object oriented language you would have looked for a file containing a library with the name Curve in it, then you may have put that name before the function so that the function could be found by the compiler, in this case a “Curve” library full of curve related functions. The syntax could have looked like so:

var crv = Curve.ProjectToPlane(Curve crv, params...);

However, C# is a Object Oriented (OOP) language, which means that functions should typically be members of a class (then they change name to being called “methods” instead), so then, instead of making a “library” for curve-stuff, we put all curve related stuff into the Curve class itself, but, to enable calling the curve-stuff without having an instance of a curve, those methods are made “static” (means, call the methods directly without having a “new Curve” instance at hand).

The resulting OOP use case looks like this:

var crv = Curve.ProjectToPlane(Curve crv, params...);

See the difference? No, it looks the same! Only the way the source code is organised looks different between OOP and regular procedural languages. So instead of a file with diverse functions all over the text file

file: Curve_Library.txt

public Point3d MidPoint(Curve crv, params...)
{
    return ... // the mid point
}

public Point3d PointAt(Curve crv, double t)
{
    return ... // the point at parameter t
}

public Curve ProjectToPlane(Curve crv, params...)
{
    return ... // the translated Curve
}

… instead you make a Class where you put all those functions, and if you want to be able to call the functions without having an actual curve instance, you just put the keyword “static” in front of the function name AND then it’s exactly the same concept as in a file of diverse functions:

file: Curve.cs

namespace IvelinCommon
{
	public class Curve
	{
		// Remove the parameter and do the job on the instance itself
		// (no "static" keyword here)
		public Point3d MidPoint()
		{
		    return ... // the mid point
		}
		// This method works directly on an instance  in RhinoCommon,
		//  so therefore it is *not* static in RhinoCommon. But here, let's 
		// pretend we are making our own geometry library named 
		// "IvelinCommon" in OOP style, so then we make our own Curve 
		// class, and then we can just copy and paste 
		// our old traditional "procedural" style library code into the 
		// class and add the keyword "static" in front of the function 
		// name and so end up having essentially the same thing as before,
		// namely a function that can be called from anywhere at anytime 
		// without having to create a Curve instance:
		public static Point3d PointAt(Curve crv, double t)
		{
		    return ... // the point at parameter t
		}
		public static Curve ProjectToPlane(Curve crv, params...)
		{
		    return ... // the translated Curve
		}
	} // end of class
} // end of namespace

So in short, “static” is only to mimic an old traditional function library coding style in the OOP world.

Um. Kind of.

// Rolf

2 Likes