1. NodeBox 1
    1. Homepage
    2. NodeBox 3Node-based app for generative design and data visualization
    3. NodeBox OpenGLHardware-accelerated cross-platform graphics library
    4. NodeBox 1Generate 2D visuals using Python code (Mac OS X only)
  2. Gallery
  3. Documentation
  4. Forum
  5. Blog

1.9.1 drawing primitive change

Posted by Mark on Oct 30, 2007

Hi,

In the previous version of Nodebox I had worked out some subclasses of BezierPath that worked pretty well, although certainly a little hackish which are broken in 1.9.1 with the depreciation of DrawingPrimitives. I would like to rework this code for 1.9.1 and was wondering if you could give me a pointer of where to start if I want to make subclasses that act like nodebox primitive shapes. I've attached some code to show what I was doing before with a generic Polygon class. I'm sure with enough time I can dig through the source code, but a little direction sure would save some time.

class Polygon(BezierPath):
    def __init__(self, sides, radius, center_x, center_y):
        t = 0
        p = NSBezierPath.bezierPath()
        self.vertices = []
        self.vertices.append((center_x + cos(t) * radius, center_y + sin(t) * radius))
        p.moveToPoint_( self.vertices[0] )
        for i in range(1, sides):               
            t += 2*pi/sides
            self.vertices.append((center_x + cos(t) * radius, center_y + sin(t) * radius))
            p.lineToPoint_(self.vertices[i] ) 
        p.closePath()
        BezierPath.__init__(self, _ctx, p)
        self.radius = radius
        self.sides = sides
        self.center = (center_x, center_y)
    def apothem(self):
        return self.radius * (cos(pi/self.sides))
    def sideLength(self): 
        from math import cos, sin, pi
        return 2 * self.radius * sin(pi/self.sides)
Thanks


 
Posted by Mark on Oct 30, 2007

I should add that

from DrawingPrimitives import BezierPath
should prceed the earlier example



Posted by Tom De Smedt on Oct 30, 2007

Hi Mark,

Changes in 1.9.1 were made to separate Cocoa from the NodeBox renderer, so we could write different renderers in the future (e.g. SVG, cross-platform, ...). Instead of DrawingPrimitives you now use:

from nodebox.graphics import BezierPath
That's basically all you need to do. However, you could take a few further steps to omit Cocoa calls from your script:
from math import cos, sin, pi
from nodebox.graphics import BezierPath
 
class Polygon(BezierPath):
    def __init__(self, sides, radius, center_x, center_y):
        t = 0
        self.vertices = []
        self.vertices.append((center_x + cos(t) * radius, center_y + sin(t) * radius))
        BezierPath.__init__(self, _ctx, None)    
        self.moveto( *self.vertices[0] )
        for i in range(1, sides):               
            t += 2*pi/sides
            self.vertices.append((center_x + cos(t) * radius, center_y + sin(t) * radius))
            self.lineto( *self.vertices[i] ) 
        self.closepath()
        self.radius = radius
        self.sides = sides
        self.center = (center_x, center_y)
    def apothem(self):
        return self.radius * (cos(pi/self.sides))
    def sideLength(self): 
        return 2 * self.radius * sin(pi/self.sides)
On a more abstract level, if you're going to create a graphical object that doesn't inherit from any existing object, you need to subclass Grob:
from nodebox.graphics import Grob
 
class SomeGraphicalObject(Grob):
    def __init__(self):
        # Register the object in the scene graph.
        Grob.__init__(self, _ctx)
        _ctx.canvas.append(self)
    def _draw(self):
        # Executed when NodeBox updates the canvas,
        # contains all drawing code.
        pass
Best regards,
Tom