11
A tutorial on Cellular Automata and PolyMedia Pixel using Rhino.Python Pramod Parajuli University of Technology, Sydney 2011 Cellular Automata & PolyMedia Pixel using Rhino.Python Objective To develop a cellular automata (Conway's Game of Life) simulation in Rhino.Python. Pramod Parajuli, 2011 1 Agenda ! Algorithm ! Implementation ! Rhino.Python ! Cellular Automata ! Polymedia Pixel ! Finalization ! Programming style ! Toolbar creation for UI Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011 2 Cellular Automata & PolyMedia Pixel using Rhino.Python Algorithm Python, Rhino.Python Cellular Automata Implementation Finalization Pramod Parajuli, 2011 3

74113635 Rhino Python Tutorial

Embed Size (px)

Citation preview

Page 1: 74113635 Rhino Python Tutorial

A tutorial on Cellular Automata and PolyMedia Pixel using Rhino.Python

Pramod Parajuli University of Technology, Sydney

2011

Cellular Automata & PolyMedia Pixel using Rhino.Python

Objective

To develop a cellular automata (Conway's Game of Life) simulation in Rhino.Python.

Pramod Parajuli, 2011

1

Agenda

!  Algorithm

!  Implementation !  Rhino.Python !  Cellular Automata !  Polymedia Pixel

!  Finalization !  Programming style !  Toolbar creation for UI

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

2

Cellular Automata & PolyMedia Pixel using Rhino.Python

Algorithm Python, Rhino.Python

Cellular Automata Implementation

Finalization

Pramod Parajuli, 2011

3

Page 2: 74113635 Rhino Python Tutorial

Cellular Automata (Conway's Game of Life)

In an unlimited universe, there are four(4) basic rules for a cell;

!  Any live cell with fewer than two live neighbours dies, as if caused by under-population.

!  Any live cell with two or three live neighbours lives on to the next generation.

!  Any live cell with more than three live neighbours dies, as if by overcrowding.

!  Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

4 Cellular Automata (Conway's Game of Life)

In simple terms;

!  If already ALIVE and < 2 neighbours, then DIE

!  If already ALIVE and neighbours = 2 or 3, then LIVE

!  If already ALIVE and > 3 neighbours, then DIE

!  If already DEAD and exactly 3 neighbours, then LIVE

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

5

GoL - practice

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

6

Cellular Automata & PolyMedia Pixel using Rhino.Python

Algorithm

Python, Rhino.Python Cellular Automata Implementation

Finalization

Pramod Parajuli, 2011

7

Page 3: 74113635 Rhino Python Tutorial

Python – quick reference

Lists >>> a = [1, 2, 3]

>>> print(a)

[1, 2, 3]

>>> a[2] = 5

>>> print(a)

[1, 2, 5]

>>> sum(a)

8

>>> b = a

>>> a[2] = 10

>>> print(b)

???

>>> b = a[:]

>>> a[2] = 30

>>> print(b)

??? Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

8 Python – quick reference

Why lists?

>>> world = [ [0, 0, 0, 0, 0],

[0, 0, 1, 0, 0],

[0, 0, 1, 0, 0],

[0, 0, 1, 0, 0],

[0, 0, 0, 0, 0] ]

>>> print(world)

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

9

Python – quick reference

for loops

>>> for i in world:

print I [0, 0, 0, 0, 0] [0, 0, 1, 0, 0] [0, 0, 1, 0, 0] [0, 0, 1, 0, 0] [0, 0, 0, 0, 0]

>>> b = [1, 2, 3]

>>> sum(b)

>>> len(b)

>>> c = [ [1, 2, 3], [4, 5, 6]]

>>> len(c)

???

>>> zip(*c)

???

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

10 Python – quick reference

Why ‘for’ loop?

>>> for aRow in world:

for aCol in aRow:

countNeighbours(aRow, aCol)

What is ‘countNeighbours’ ?? We will revisit it later.

Cellular Automata & PolyMedia Pixel using Rhino.Python

0 0 0 0 0

0 0 1 0 0

0 0 1 0 0

0 0 1 0 0

0 0 0 0 0

0 1 1 1 0

0 2 1 2 0

0 3 2 3 0

0 2 1 2 0

0 0 0 0 0

Pramod Parajuli, 2011

11

Page 4: 74113635 Rhino Python Tutorial

Python – quick reference

Functions

>>> def add(x, y):

return x+y

>>> p = 10

>>> q = 5

>>> add(p, q)

15

>>> p = “10”

>>> q = “5”

>>> add(p, q)

???

Functions from libraries

>>> import math

>>> math.sin(30 * math.pi / 180)

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

12 Python – quick reference

More on slices

>>> world[1:2]

[[0, 0, 1, 0, 0 ]]

>>> z = [1, 2, 3, 4, 5]

>>> z[1:4]

???

>>> z[1:4][1]

???

For our world, we need to select only 8 cells around current cell.

How to select?

We select 3x3 slice and remove the one at the centre. !en sum all the ‘1’s in the slice.

!at will give us the no. of neighbours in the surrounding of a cell.

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

13

Rhino.Python

Some examples

First.py

import rhinoscriptsyntax as rs

rs.AddPoint([1,2,3])

center = [20, 0, 0]

radius = 5

rs.AddSphere(center, radius)

""

Second.py import rhinoscriptsyntax as rs

rs.EnableRedraw(False)

for i in range(0, 50):

if(i%5 == 0):

rs.AddSphere([i, 0, 0], 0.5)

else:

rs.AddPoint([i, 0, 0])

rs.EnableRedraw(True)

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

14 Rhino.Python

drawSine.py import rhinoscriptsyntax as rs import math def drawSineWave(): print 'Drawing sine wave' sineHeight = rs.GetReal("Please enter height:") x = -30 y = -30 z = math.sin(-30 * math.pi / 180.0) * 70 drawStart = [x, y, z] for currentAngle in range(-90, 90): currentRadian = currentAngle * math.pi / 180.0

# settin z to a scaled value with intercept z = math.sin(currentRadian) * 70 x = currentAngle y = currentAngle drawEnd = [x, y, z] rs.AddLine(drawStart, drawEnd) drawStart = drawEnd

drawBox.py - demo

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

15

Page 5: 74113635 Rhino Python Tutorial

Rhino.Python

Some bits for Classes and objects import rhinoscriptsyntax as rs import math # let’s create a class ‘Tutorial class Tutorial: def __init__(self, _title, _curveA, _curveB): self.title = _title self.curveA = _curveA self.curveB = _curveB def displayName(self): displayString = 'Title of this object is ' + self.title print(displayString) def drawEdgeSurface(self): surface = rs.AddEdgeSrf([self.curveA, self.curveB]) rs.ObjectColor(surface, [0xff, 0x90, 0xc0])

def main(): firstCurve = rs.GetObject("Select first curve") secondCurve = rs.GetObject("Select second curve") # creating instance of Tutorial – newCurve # We will be using this instance holds the data about # curves and also can execute its function on the data. newCurve = Tutorial('Curve drawing tutorial',

firstCurve, secondCurve) newCurve.displayName() newCurve.drawEdgeSurface() if( __name__ == '__main__' ): main()

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

16 Drawing pseudo-surface using lines between curves

•  Draw 2 curves

•  Divide curves into slices

•  Get the end points of the slices

•  Connect the points with lines

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

17

Draw pseudo-surface using lines between curves

import rhinoscriptsyntax as rs class CurveLine: def __init__(self, _strCurveA, _strCurveB, _numSlices): self.strCurveA = _strCurveA self.strCurveB = _strCurveB self._numSlices = _numSlices def drawLines(self): ptsCurveA = rs.DivideCurve(self.strCurveA, self._numSlices, True, True) ptsCurveB = rs.DivideCurve(self.strCurveB, self._numSlices, True, True) counter = 0 for everyPOint in ptsCurveA: rs.AddLine( ptsCurveA[counter], ptsCurveB[counter]) counter += 1 def main(): firstCurve = rs.GetObject("Pick first curve", 4) secondCurve = rs.GetObject("Pick second curve", 4) newSurface = CurveLine(firstCurve, secondCurve, 100) newSurface.drawLines()

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

18 Draw pseudo-surface using curves between curves

•  Draw 3 curves (2 for end edge and 1 for control point

•  Divide all curves into slices

•  Get the endpoints of slices in three di"erent lists

•  Form new curves from three points in three lists

•  Use these three points as control points to draw a curve

•  Repeat for all points Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

19

Page 6: 74113635 Rhino Python Tutorial

Draw pseudo-surface using curves between curves class CurveSurface: def __init__(self, _strCurveA, _strCurveB, _strCurveC, _numSlices): self.strCurveA = _strCurveA # similarly, create strCurveB, strCurveC self._numSlices = _numSlices def drawCurvesBetween(self): ptsCurveA = rs.DivideCurve(self.strCurveA, self._numSlices, True, True) # similarly, divide strCurveB, strCurveC counter = 0 for everyPOint in ptsCurveA: rs.AddCurve( [ptsCurveA[counter], ptsCurveB[counter], ptsCurveC[counter]]) counter += 1 def main(): firstCurve = rs.GetObject("Pick first curve", 4) secondCurve = rs.GetObject("Pick second curve", 4) thirdCurve = rs.GetObject("Pick third curve", 4) newSurface = CurveSurface(firstCurve, secondCurve, thirdCurve, 100) newSurface.drawCurvesBetween()

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

20 Draw surfaces using EdgeSurface between curves

Cellular Automata & PolyMedia Pixel using Rhino.Python

•  Draw curves between curves as in previous example

•  Draw EdgeSurface in between those curves

Pramod Parajuli, 2011

21

Draw surfaces using EdgeSurface between curves

def drawSurfaceBetween(self): ptsCurveA = rs.DivideCurve(self.strCurveA, self.numSlicesL, True, True) ptsCurveB = rs.DivideCurve(self.strCurveB, self.numSlicesL, True, True) ptsCurveC = rs.DivideCurve(self.strCurveC, self.numSlicesL, True, True) counter = 0 previousCurve = rs.AddCurve([ptsCurveA[counter], ptsCurveB[counter], ptsCurveC[counter]]) counter += 1 for everyPOint in ptsCurveA: currentCurve = rs.AddCurve( [ptsCurveA[counter], ptsCurveB[counter], ptsCurveC[counter]]) currentSurface = rs.AddEdgeSrf([previousCurve, currentCurve]) rs.ObjectColor(currentSurface, [counter+70, counter + 150, counter + 200]) previousCurve = currentCurve counter += 1

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

22

Cellular Automata & PolyMedia Pixel using Rhino.Python

Algorithm

Python, Rhino.Python

Cellular Automata Implementation Polymedia Pixel

Finalization

Pramod Parajuli, 2011

23

Page 7: 74113635 Rhino Python Tutorial

Cellular Automata (Conway's Game of Life)

!e algorithm:

!  If already ALIVE and < 2 neighbours, then DIE

!  If already ALIVE and neighbours = 2 or 3, then LIVE

!  If already ALIVE and > 3 neighbours, then DIE

!  If already DEAD and exactly 3 neighbours, then LIVE

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

24 Cellular Automata (Conway's Game of Life) Requirements – data structures

!  List to hold state of life of cells, let’s say – world[][]

!  List to hold neighbour count of every cell, let’s say – neighbours[][]

!  List to work for counting and deciding the life state for next stage, let’s say – buffer[][]

!  Size of the world – worldSize

!  Boundary of the world in Rhino3d – can be de#ned as starting from –(worldSize/2) to +(worldSize/2) in XY plane rangeX = worldSize/2 rangeY = worldSize/2

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

25

Cellular Automata (Conway's Game of Life)

Requirements - functions

!  A function to create empty list for world, neighbours, and buffer - __init__(worldSize)

!  A function to #ll initial life states randomly in world - fillRandomLives

!  A function to #ll initial number of neighbour in neighbours - fillRandomNeighbours

!  A function to count neighbours given the cell location – countNeighbours(row, col)

!  A function to count neighbours of all cells by calling countNeighbours(row, col) iteratively – countAllNeighbours

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

26 Cellular Automata (Conway's Game of Life)

Requirements - functions

!  A function to decide state of cells for next phase using cellular automata rules and update it in buffer – decideLife !  Check state of cell from world !  Check neighbour count from neighbours !  Decide next state of the cell

!  Write the state to buffer

!  A function to update graphics on the Rhino3d according to life states in buffer - updateGraphics

!  A function to update world from buffer - updateGraphics Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

27

Page 8: 74113635 Rhino Python Tutorial

Cellular Automata (Conway's Game of Life)

Requirements – functions

!  A function to count neighbours given the cell location – countNeighbours(row, col)

!  A function to count neighbours of all cells by calling countNeighbours(row, col) iteratively – countAllNeighbours

!  A function to draw box on the Rhino 3D – drawBox(basePoint, length, width, height, objColor)

!  A function to add two lists numerically by elements (used by drawBox) – addLists(list1, list2)

!  A main program to de#ne thread of control - main Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

28

Cellular Automata & PolyMedia Pixel using Rhino.Python

Algorithm

Python, Rhino.Python

Cellular Automata Implementation

Polymedia Pixel Finalization

Pramod Parajuli, 2011

29

PolyMedia Pixel

•  Spreading a component object over di"erent types of surfaces (polysurface, opensurface)

•  Di"erent tasks required to be done to accomplish it •  Join and explode surfaces •  Evaluate surface to retrieve points •  Explode meshes or mesh objects into sub-meshes •  Playing with layers •  Surface normal, and object orientation •  Other utility functions such as view and plane for orientation, boundingbox

for scaling etc.

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

30 PolyMedia Pixel

Joining surfaces import rhinoscriptsyntax as rs

objs = []

surface1 = rs.GetObject('Select first surface', rs.filter.surface)

surface2 = rs.GetObject('Select second surface', rs.filter.surface)

objs.append(surface1)

objs.append(surface2)

rs.JoinSurfaces(objs, True)

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

31

Page 9: 74113635 Rhino Python Tutorial

PolyMedia Pixel Exploding poly-surface and mesh import rhinoscriptsyntax as rs

newsurface = rs.GetObject("Select a poly-surface object”,

rs.filter.polysurface)

objs = rs.ExplodePolysurfaces(newsurface)

rs.MoveObjects(objs, [20, 0, 0])

# similarly, we can explode mesh objects

newmesh = rs.GetObject("Select a mesh object", rs.filter.mesh)

meshobjs = rs.ExplodeMeshes(newmesh)

rs.MoveObjects(meshobjs, [20, 0, 0])

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

32 PolyMedia Pixel Evaluate surface (Divide surface)

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

33

PolyMedia Pixel

Evaluate surface (Divide surface) def DivideSlab(srf, divisions):

domain0 = rs.SurfaceDomain(srf, 0)

domain1 = rs.SurfaceDomain(srf, 1)

for i in range(divisions+1):

u = domain0[0] + (domain0[1]-domain0[0])*i/divisions

for j in range(divisions+1):

v = domain1[0] + (domain1[1]-domain1[0])*j/divisions

point = rs.EvaluateSurface(srf,u,v)

drawBox(point, 100, 100, 20, [0x00, 0x90, 0xC0])

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

34 PolyMedia Pixel

Layers srf = rs.GetObject("Select poly-surface to divide") oldLayer = rs.ObjectLayer(srf) newLayer = rs.AddLayer("dotsLayer") rs.LayerVisible(newLayer, False) rs.EnableRedraw(False) # explode current polysurface into small surfaces first objSurfaces = rs.ExplodePolysurfaces(srf) rs.CurrentLayer(newLayer) ""

for aSurface in objSurfaces: DivideSlab(aSurface, 5, newLayer) rs.LayerVisible(newLayer, True) rs.EnableRedraw(True) rs.LayerVisible(oldLayer, False)

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

35

Page 10: 74113635 Rhino Python Tutorial

PolyMedia Pixel

Surface normal

import rhinoscriptsyntax as rs obj = rs.GetObject("Select a surface", rs.filter.surface) if obj: point = rs.GetPointOnSurface(obj) if point: param = rs.SurfaceClosestPoint(obj, point) normal = rs.SurfaceNormal(obj, param) rs.AddPoints( [point, point + normal] )

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

36 PolyMedia Pixel

Object orientation import rhinoscriptsyntax as rs

obj = rs.GetObject("Select object to orient")

if obj:

    reference = rs.GetPoints(message1="First reference point")

    if reference and len(reference)>0:

        target = rs.GetPoints(message1="First target point")

        if target and len(target)>0:

            rs.OrientObject( obj, reference, target )

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

37

PolyMedia Pixel

Object orientation on surface demo

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

38 PolyMedia Pixel

!e algorithm for poly-pixel implementation •  Select component object •  Select surface •  Check surface type •  If surface is poly-surface, explode and retain all open surfaces, if not will have

only one open surface •  For all open surface/s, evaluate the surface according to no. of slice user want to

do •  Ask user whether to scale component or not, scale accordingly •  Make copies of the component object, move them to center of all the evaluated

point on the surface, then orient them to surface normal

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

39

Page 11: 74113635 Rhino Python Tutorial

Cellular Automata & PolyMedia Pixel using Rhino.Python

Algorithm

Python, Rhino.Python

Cellular Automata Implementation

Polymedia Pixel

Finalization

Pramod Parajuli, 2011

40 Finalizing

Creating custom toolbar to run script

•  Right click on the empty space by the side of existing tabs

•  Click ‘Insert Toolbar’

•  In ‘Select Toolbar’ box, click ‘New’

•  Provide name to the toolbar ‘RhinoTutorial’

•  Now you can see newly created toolbar.

•  Shift+right click on the icon in the toolbar.

•  Edit the icon.

•  Provide button text and tooltip text.

•  In the ‘macro library’, select ‘New Macro’

•  In the command box: include followings:

!-_RunPythonScript (" # your python code here ")

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

41

Finalizing

Comments in the source-code •  Use # to begin single comments

•  Use “”” to begin and end multiple line comments “”” ---------------------------- Program : <XYZ> Description: <This program is creates …> By: <Your name> Date: 31/10/2011 Revision: 1/11/2011 – Added new feature

2/11/2011 – Optimized function ‘foo’ etc. ------------ “”” import rhinoscriptsyntax as rs # YOUR CODE STARTS HERE # For Classes, Functions, Special data structures also, write their name, description, return values etc.

Cellular Automata & PolyMedia Pixel using Rhino.Python Pramod Parajuli, 2011

42