This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Neat Graphics with Scala Processing

If you just enjoy programming or are exploring Scala then you will find Nathan Hamblen's Scala version of Processing a pure delight. He has created an IDE where you can write Scala programs that access the incredible power of the Processing Projects graphics library. In a few lines you can create appealing images, visual simulations, art work or presentations.

Processing is an award winning open source project initiated by Casey Reas and Benjamin Fry, both formerly of the Aesthetics and Computation Group at the MIT Media Lab. It is "a programming language and integrated development environment (IDE) built for the electronic arts and visual design communities", You can learn more about the original Open Source project on Wapedia.

SPDE ScreenshotSPDE Screenshot

About a year ago, Nathan created his first version of the Scala Processing Development Environment(SPDE) which integrates the Scala compiler with the simple to use Processing IDE. Now you can type in a Scala program, hit run and see the results. To find out more about this Scala version of Processing and how to download it here or visit the site about SPDE to learn how he did it. More detail technical implementation notes on the SPDE project can be found here.

Setting up the SPDE is a simple task. You must first download and install the Java JRE and the Java JDK which you can find on the Sun Java Site. Then, after unzipping and installing SPDE, the Scala Processing Development Environment, you will need to modify the SPDE batch file to set the JAVA_HOME environment variable. Inserting something like "set JAVA_HOME=c:\Program Files\Java\jdk1.6.0_16" as the first line does this nicely on a Windows system.

Nathan has provided a nice set of examples with the SPDE. You can see some of them demonstrated on this site. Many people find the simulation of bird flocking fascinating. You will find an 'Exhibition' of what other people have produced using the Java Processing environment on the Processing Site. Some are just really amazing.

SPDE is just one of Nathan's many contributions to the community. Check out his blog 'Codespiel' to see what other projects he is into.

For those of you who are mathematically minded or interested in self similar systems and fractals, Anthony Bagwell has provided us with the following code examples. The first is a concise way to create a representation of the popular Sierpinski gasket. The second provides a Turtle like draw class that will display L-systems. You can copy and paste the code examples into the SPDE window to see them run and produce similar results to the screen.

Sierpinski Gasket

Sierpinski Gasket Sierpinski Gasket

// Sierpinski Gasket Example for SPDE
val d= 200
size(d*2, d*2)
background(0, 10, 20)
var a=List(List(d/2,0,255,0,0),List(d,d,0,255,0),List(0,d,0,0,255))
var p=List(d,0,255,0,0)
def draw() {
  for(i<-1 to 10) {
    p=p zip a.random map{case (x,y)=>x/2+y}
    stroke(p(2),p(3),p(4))
    point(p(0), p(1))
  }
}

L-Systems or Lindenmayer-Systems

L-Systems are based on using a set of replacement rules that are applied as productions on an initial string (or axiom). The resultant strings can then be interpreted as directions for a "Turtle". For example, to produce the flake the initial string is "F++F++F" then on each iteration the replacement rule is simple, for each F replace it with "F-F++F-F" The resulting string can now be interpreted as Turtle movements. F means step turtle forward, - means turtle turn left by given angle and + means turn right by given angle.

In the example SPDE Scala program you can choose which of several popular L-systems you would like to see or create your own. The production rules are nicely implemented by means of a partial function and case algebraic pattern matching features of Scala. Folds are used to apply the production rules and then create the list of turtle movements.

Use wikipedia to find more information about L-Systems.

Running the Koch Snowflake, Hilbert Space Filling Curves and Sierpinski Gaskets will give the following results.

Koch SnowflakeKoch SnowflakeHilbert Space Filling CurvesHilbert Space Filling CurvesSierpinski Gasket Sierpinski Gasket

// L-System Example for SPDE
size(900,700)
smooth
val chs=5 // choose 0 to 5
var cur=List(spier1,spier2,flake,pentigree,hilbert1,hilbert2)(chs)

def spier1 = new L_Sys("F+F+F",PI*2/3,1.0,{
    case 'F'=>"F+F-F-F+F"
  })

def spier2 = new L_Sys("X",PI/3,1.0,{
    case 'X' => "+Y-X-Y+"
    case 'Y' => "-X+Y+X-"
  })

def flake = new L_Sys("F++F++F",PI/3,1.0,{
    case 'F'=>"F-F++F-F"
  })
  
def pentigree = new L_Sys("F-F-F-F-F", PI*2/5,1.0,{
   case 'F'=>"F-F++F+F-F-F"
 })
 
def hilbert1 = new L_Sys("xF",PI/2,0.5,{
    case 'x' => "+yF-xFx-Fy+"
    case 'y' => "-xF+yFy+Fx-"
  })
 
def hilbert2 = new L_Sys("XF",PI/2,0.45,{
    case 'X' => "+YFG-XFX-GFY+"
    case 'Y' => "-XFG+YFY+GFX-"
    case 'F' => "HHH"
    case 'G' => ""
  })
 
var points=cur.points
background(255)
// Initial String, turtle turn angle (rads), sizing ratio, Production Rules 
class L_Sys(b:String,a:double,r:double ,f:(char)=>String){
  var s=b
  var step=1.0
  var angle=a
  var start=(.0,0.0,0.0)
  var ratio=1.0
// Run couple of trial iterations to calculate step scaling to use
// so that each iteration just fills window  
  var d1=br._2-tl._2
  next
  next
  var d2=br._2-tl._2
  ratio=sqrt(d1/d2)
  step=height/d1
  start=((-tl._1*(ratio*ratio)+width-br._1*ratio*ratio)/2,-tl._2*(ratio*ratio),.0)
  s=b
  ratio=if(r!=1.0)r else ratio
  def tl()={
    points.foldLeft(start){case ((mx,my,ma),(x,y,a))=>(min(mx,x),min(my,y),0)}
  }
  def br()={
    points.foldLeft(start){case ((mx,my,ma),(x,y,a))=>(max(mx,x),max(my,y),0)}
} def next(){ s=s.map((c)=>{ try {f(c)} catch { case e:Exception => c.toString } }).mkString step=step*ratio } // Turtle def points()={ s.foldLeft(List(start)){ case ((x,y,a)::t , c) => { c match { case '+' => (x,y,a+angle)::t case '-' => (x,y,a-angle)::t case c if c.isUpperCase => (x+step*sin(a),y+step*cos(a),a)::(x,y,a)::t case _ => (x,y,a)::t } } } } } def draw() { if(points.length>1) { var a=points.head points=points.tail var b=points.head line(a._1,a._2,b._1,b._2) } else { background(255) cur.next points=cur.points } }

Re: Neat Graphics with Scala Processing

Hi guys, thanks a lot for taking a look at the project! I hope it's alright if I add your examples to the spde-examples project on github, so people can easily run them and fork their own variations.

Does List().random method exists?

In the fractal example, you create a list of lists, and extract an element of it using the random function

 

// Sierpinski Gasket Example for SPDE
var a=List(List(d/2,0,255,0,0),List(d,d,0,255,0),List(0,d,0,0,255))
...
p=p zip a.random map{case (x,y)=>x/2+y}

How do you do that? List doesn't seem to have a random method.

 

Re: Does List().random method exists?

Unfortunatelty you are right the Scala collections do not include a random method, however n8han helpfuly added one using implicits. He has hidden a lot of neet stuff in SPDE the only way to find out about it is to poke about in the examples and in the source code. You can see how he added the random method bellow.

import scala.util.Random
private val rand = new Random

implicit def seq2RichRandom[K](seq: Seq[K]) = new RichRandom(seq)

protected class RichRandom[K](seq: Seq[K]) {
  def random: K = seq((rand.nextFloat * seq.length).toInt)
}

Re: Neat Graphics with Scala Processing

Is there a working version for Scala 2.10.x ?

 

Thanks.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland