Noob question #003? Custom point class

Is it possible to override the Point3d constructor directly or should I override the Rhino.Geometry.Point class then somehow create my own constructor mimicking Rhino.Geometry.Point3d but adding some new properties to it?

See what I do below, is this correct?
image

I want a custom class that when run will place a point on x=0.0, y=0.0, z=0.0, always.

You can use Point3d.Zero

For custom properties you will need to write a custom library, in C# I use static class with static methods.
Maybe someone else can also show how to use Point3d class and inheritence.

In Python constructor is __init__. Did you read through https://docs.python.org/2/tutorial/classes.html yet?

I tried that as well at first but I cannot invoke my class without an argument Point3d. Which is what I want.

I think that’s Point3d.Origin…

1 Like

Yes, it is .Origin.

I thought about using that, but I need to add more options to that I don’t want it to be just a point. So I have to create it as a new class derived from Rhino.Geometry.Point

Yes, and any data you need to save with the 3dm you’ll have to add as UserData.

Yes it was Origin, the full implementation of Point3d method including this static method is shown on mcneel github page

The problem is that you can inherit from Rhino.Geometry.Point, since its a class, but you can’t inherit from Rhino.Geometry.Point3d since it’s a struct.
C# structs are sealed, which means that you can’t inherit from them. It has to do with structs being value types, and value types are always sealed, I believe.
The problem with Rhino.Geometry.Point is that it takes at least 2 arguments during initialisation, which are self and a Rhino.Geometry.Point3d. This means that when inheriting from it, you always have to provide both arguments. You can’t simply initialise your own class, which inherits, without arguments, which is inconvenient, since you want to initialise as an origin point, right?
Overriding this is probably not possible, so you have two options that I can think of:

The first one, would be to inherit from Rhino.Geometry.Point, extend it with your custom attributes and methods, and pass in a Rhino.Geometry.Point3d.Origin, when you initialise it. This way you can benefit from the already available attributes and methods, as well as your very own extensions.

The other option would be to create your very own, customised Point class. Of course, you’d have to start pretty much from scratch. However, if your custom attributes and method are, what you would primarily use either way, this would be the way to go.
Even Rhino.Geometry.Point is a pretty simple class. It’s basically just composed of three coordinates.

Your custom class could look something like this:

import Rhino

class Point3d:
    def __init__(self):
        self.x = 0.0
        self.y = 0.0
        self.z = 0.0

    def get_point(self):
        return Rhino.Geometry.Point3d(self.x, self.y, self.z)

pt = Point3d()
print pt.get_point() 

1 Like

Thank you @diff-arch,

Interestingly enough, I started doing the same thing in my first try, the same structure and overriden methods. The only difference was instead of creating the class from scratch I tried to derive it from Rhino.Geometry.Point3d :slight_smile: . Of course that failed so I ended up deriving from Rhino.Geometry.Point instead which lead me to a dead end.

Does it make sense to implement sc.doc.objects.addpoint() from inside my class?
One of the things I wished I could put to the point is upon creation to add some usertext to the object. And since this is a property of a point object not virtual point I don’t know which is the proper way to go. Make it as a method to my custom class or as a separate event that triggers every time the class is instantiated.

I don’t know, since I don’t have a lot of experience with scriptcontext. As I understand, from reading the documentation, sc.doc.objects.addpoint() adds a point to your document. If that’s what you want to achieve, implement it. However, it’s also not inheritable, since it’s a method, not a class.

Like this?

import Rhino

class Point3d:
    def __init__(self):
        self.x = 0.0
        self.y = 0.0
        self.z = 0.0
        self.usertext = None

    def set_usertext(self, usertext):
        self.usertext = usertext

    def get_point(self):
        return Rhino.Geometry.Point3d(self.x, self.y, self.z)

pt = Point3d()
print pt.set_usertext("My Usertext")

I don’t think this will work. Like I said UserText exist on objects that are added to the document. Also UserText is a type of a dictionary.

perhaps something like:

class Point3d:
    def __init__(self):
        self.x = 0.0
        self.y = 0.0
        self.z = 0.0
    def get_point(self):
        return Rhino.Geometry.Point3d(self.x,self.y,self.z)
    
    def to_object(self):
        import scriptcontext as sc
        return sc.doc.objects.AddPoint(self.get_point()) 

    def set_usertext(self,key,value):
        import rhinoscriptsyntax as rs
        obj = self.to_object()
        return rs.SetUserText(obj, key, value)

But that doesn’t work so I don’t know. This seems too advanced to me.

Why you are importing libraries in a class?

It is always a top declaration.

if you don’t do:

import Rhino

how would it know where to look for in:

return Rhino.Geometry.Point3d(self.x,self.y,self.z)

Before code runs it first looks at namespaces you declared

such as:

import Rhino
import scriptcontext as sc
import rhinoscriptsyntax as rs

only when the namespaces are declared you can use methods and classes inside.

for instance Point3d is in Rhino.Geometry namespace.

how do you declare namespaces in Python? Isn’t it a master class of a sort?

import Rhino.Geometry
import scriptcontext as sc
import rhinoscriptsyntax as rs

class Point3d:
    def __init__(self):
        self.x = 0.0
        self.y = 0.0
        self.z = 0.0
    def get_point(self):
        return Rhino.Geometry.Point3d(self.x,self.y,self.z)
    
    def to_object(self):
        
        return Rhino.RhinoDoc.ActiveDoc.Objects.AddPoint(self.get_point()) 

    def set_usertext(self,key,value):
        
        obj = self.to_object()
        return rs.SetUserText(obj, key, value)
        
pt = Point3d()

a = pt.to_object()

I see what you meant, now.

Well I put them inside the class because one may not need them in every case. If you can spare memory, not to load assemblies you don’t need, perhaps this is better performance-wise.

But all this is abstract since this class doesn’t even work. I wrote it in discourse :smiley:

Hey, what do you know, it actually works. :sunglasses:

This is how it looks now.

import Rhino
#import scriptcontext as sc
#import rhinoscriptsyntax as rs

class Point3d:
    def __init__(self):
        self.x = 0.0
        self.y = 0.0
        self.z = 0.0
        return self.set_usertext("Location",[self.x,self.y,self.z])
    
    def get_point(self):
        return Rhino.Geometry.Point3d(self.x,self.y,self.z)
    
    def to_object(self):
        import scriptcontext as sc
        return sc.doc.Objects.AddPoint(self.get_point()) 

    def set_usertext(self,key,value):
        import rhinoscriptsyntax as rs
        obj = self.to_object()
        return rs.SetUserText( obj, key, value )




pt = Point3d()