Python 3 class inheritance puzzle. Rhino.Input.Custom.GetPoint()

Hello,

I am working with Rhino.Input.Custom.GetPoint(). The following code works fine for python 2, but in python 3, the inherited class example fails.

I am working on the GetPointDynamicDraw example to make a custom picker. This (with some debugging) works for p2 but not p3. (https://developer.rhino3d.com/api/rhinocommon/examples/getpointdynamicdraw)

Is this Rhino, or something I have missed about p3 classes?

Any thoughts appreciated, Paul

import Rhino
import Rhino.Input.Custom as ric
import scriptcontext as sc

def RunCommand():

gp1 = ric.GetPoint()
gp1.SetCommandPrompt(“Add point 1”)
gp1.Get()
sc.doc.Objects.AddPoint(gp1.Point())
sc.doc.Views.Redraw()

gp2 = InheritedGetPoint()
gp2.SetCommandPrompt(“Add point 2”)
gp2.Get()
sc.doc.Objects.AddPoint(gp2.Point())
sc.doc.Views.Redraw()

class InheritedGetPoint (ric.GetPoint):

def __init__(self):
    pass

if name == “main”:
RunCommand()

see below for updated answer.
What does not work exactly? I can get it to execute with minor edits, but that is probably because you pasted the code outside a code block (tip: use three back-ticks to start a code block).

Edits made: the __name__ and __main__ were bold instead of surrounded by two underscores, and the double quotes were curly so I replaced them with single straight quotes.

import Rhino
import Rhino.Input.Custom as ric
import scriptcontext as sc

def RunCommand():

    gp1 = ric.GetPoint()
    gp1.SetCommandPrompt('Add point 1')
    gp1.Get()
    sc.doc.Objects.AddPoint(gp1.Point())
    sc.doc.Views.Redraw()

    gp2 = InheritedGetPoint()
    gp2.SetCommandPrompt('Add point 2')
    gp2.Get()
    sc.doc.Objects.AddPoint(gp2.Point())
    sc.doc.Views.Redraw()

class InheritedGetPoint (ric.GetPoint):

    def __init__(self):
        pass

if __name__ == '__main__':
    RunCommand()

Ha, got it. You indeed need to change the initialization like so:

class InheritedGetPoint (ric.GetPoint):

    def __init__(self):
        ric.GetPoint.__init__(self)

In Python3 the common pattern is: super().__init__(self)

It means the base class names only have to be changed once, and the __init__ calls can cascade throughout all (multiple co-operative) base classes if they all include this convention.

1 Like

I tried first that but that did not seem to work. Did you manage?

Brilliant! thanks Menno, James.

Here is the Rhino.Input.Custom.GetPoint() Dynamic Draw example, working for p3.

# API docs example updated for p3  https://developer.rhino3d.com/api/rhinocommon/examples/getpointdynamicdraw

#! python3

import Rhino
import Rhino.Geometry as rg
import Rhino.Commands as rc
import Rhino.Input.Custom as ric
import scriptcontext as sc
import System.Drawing


def RunCommand():
  gp = ric.GetPoint()
  gp.SetCommandPrompt('Center point')
  gp.Get()
  if gp.CommandResult() != rc.Result.Success:
    return gp.CommandResult()
  center_point = gp.Point()
  if center_point == rg.Point3d.Unset:
    return rc.Result.Failure
  gcp = GetCircleRadiusPoint(center_point)
  gcp.SetCommandPrompt('Radius')
  gcp.ConstrainToConstructionPlane(False)
  gcp.SetBasePoint(center_point, True)
  gcp.DrawLineFromPoint(center_point, True)
  gcp.Get()
  if gcp.CommandResult() != rc.Result.Success:
     return gcp.CommandResult()
  radius = center_point.DistanceTo(gcp.Point())
  cplane = sc.doc.Views.ActiveView.ActiveViewport.ConstructionPlane()
  sc.doc.Objects.AddCircle(rg.Circle(cplane, center_point, radius))
  sc.doc.Views.Redraw()
  return rc.Result.Success


class GetCircleRadiusPoint (ric.GetPoint):

  def __init__(self, centerPoint):
    ric.GetPoint.__init__(self)
    self.line_color = System.Drawing.Color.FromArgb(255,0,0)
    self.m_center_point = centerPoint
  
  def OnDynamicDraw(self, e):
    cplane = e.RhinoDoc.Views.ActiveView.ActiveViewport.ConstructionPlane()
    radius = self.m_center_point.DistanceTo(e.CurrentPoint)
    circle = rg.Circle(cplane, self.m_center_point, radius)
    e.Display.DrawCircle(circle, self.line_color)

if __name__ == '__main__':
    RunCommand()
1 Like