Hi John,
You can get some speedup by using unboxed math in draw-tree (see
below). What kind of speed difference are you seeing?
Stu
(import '(javax.swing JFrame JPanel )
'(java.awt Color Graphics Graphics2D))
(defn draw-tree [ #^Graphics g2d angle x y length branch-angle depth]
(when (> depth 0)
(let [angle (double angle)
x (double x)
y (double y)
length (double length)
branch-angle (double branch-angle)
depth (double depth)
new-x (- x (* length (Math/sin (Math/toRadians angle))))
new-y (- y (* length (Math/cos (Math/toRadians angle))))
new-length (fn [] (* length (+ 0.75 (rand 0.1))))
new-angle (fn [op] (op angle (* branch-angle (+ 0.75
(rand)))))]
(. g2d drawLine x y new-x new-y)
(draw-tree g2d (new-angle +) new-x new-y (new-length) branch-
angle (- depth 1))
(draw-tree g2d (new-angle -) new-x new-y (new-length) branch-
angle (- depth 1)))))
(defn render [ #^Graphics g w h]
(doto g
(.setColor (Color/BLACK))
(.fillRect 0 0 w h)
(.setColor (Color/GREEN)))
(let [init-length ( / (min w h) 5),
branch-angle (* 10 (/ w h)),
max-depth 12]
(draw-tree g 0.0 (/ w 2) h init-length branch-angle max-depth)))
(defn create-panel []
"Create a panel with a customised render"
(proxy [JPanel] []
(paintComponent [g]
(proxy-super paintComponent g)
(time (render g (. this getWidth) (. this
getHeight))))))
(defn run []
(let [frame (JFrame. "Clojure Fractal Tree")
panel (create-panel)]
(doto frame
(.add panel)
(.setSize 640 400)
(.setVisible true))))
(run)
Hi, the other day I was at a conference in London and learned Scala.
As my first program I translated a favourite fractal tree program
(which I stole from: http://marblemice.com/2009/04/26/clojure-fractal-tree/)
.
The programs are almost exactly the same in the two languages.
The Scala version seems quite a lot faster than the Clojure one. I
added type hints for the Graphics objects, but there's also a
reflection warning from the JPanel proxy, which I think is
unimportant, but which I can't see how to get rid of.
Is the reason the Clojure version is slow that recursive calls to
draw-
tree are boxing and unboxing primitive types? If so is there anything
that can be done? Did I just pick a particularly bad example program?
Or am I just missing something silly? Is there an easy way to examine
the byte-code?
Is it human-readable? Can it be done from a REPL like disassemble in
Lisp?
------------------------------------------- clojure version
(import '(javax.swing JFrame JPanel )
'(java.awt Color Graphics Graphics2D))
(defn draw-tree [ #^Graphics g2d angle x y length branch-angle depth]
(if (> depth 0)
(let [new-x (- x (* length (Math/sin (Math/toRadians angle))))
new-y (- y (* length (Math/cos (Math/toRadians angle))))
new-length (fn [] (* length (+ 0.75 (rand 0.1))))
new-angle (fn [op] (op angle (* branch-angle (+ 0.75
(rand)))))]
(. g2d drawLine x y new-x new-y)
(draw-tree g2d (new-angle +) new-x new-y (new-length) branch-
angle (- depth 1))
(draw-tree g2d (new-angle -) new-x new-y (new-length) branch-
angle (- depth 1)))))
(defn render [ #^Graphics g w h ]
(doto g
(.setColor (Color/BLACK))
(.fillRect 0 0 w h)
(.setColor (Color/GREEN)))
(let [init-length ( / (min w h) 5),
branch-angle (* 10 (/ w h)),
max-depth 12]
(draw-tree g 0.0 (/ w 2) h init-length branch-angle max-depth)))
(defn create-panel []
"Create a panel with a customised render"
(proxy [JPanel] []
(paintComponent [g]
(proxy-super paintComponent g)
(render g (. this getWidth) (. this getHeight)))))
(defn run []
(let [frame (JFrame. "Clojure Fractal Tree")
panel (create-panel)]
(doto frame
(.add panel)
(.setSize 640 400)
(.setVisible true))))
(run)
----------------------------------------------- scala version
import scala.swing._
import java.awt._
import javax.swing._
object ScalaFractalTree {
def main(args: Array[String]){
val frame=new JFrame("Scala Fractal Tree")
val panel=new MyPanel()
frame add panel
frame setSize (640, 400)
frame setVisible true
}
}
class MyPanel extends JPanel{
override def paintComponent(g:Graphics):Unit = {
super.paintComponent(g)
render(g, getWidth(), this.getHeight())
}
def render(g:Graphics, w:Int, h:Int){
g.setColor (Color.BLACK)
g.fillRect( 0, 0, w, h)
g.setColor (Color.GREEN)
val initlength=if (w<h) w/5 else h/5
val branchangle=10*w/h
val maxdepth=12
drawtree( g, 0.0, w/2.0, h ,initlength, branchangle, maxdepth)
}
def drawtree(g:Graphics, angle:Double, x:Double, y:Double,
length:Double,
branchangle:Double, depth:Double){
if (depth>0){
val newx= x-length*(Math.sin(Math.toRadians( angle)))
val newy= y-length*(Math.cos(Math.toRadians( angle)))
val newlength1 = length*(0.75+0.1*Math.random)
val newlength2 = length*(0.75+0.1*Math.random)
val newangle1 = angle+branchangle*(0.75+Math.random)
val newangle2 = angle-branchangle*(0.75+Math.random)
g.drawLine(x.toInt, y.toInt, newx.toInt, newy.toInt)
drawtree(g, newangle1, newx, newy, newlength1, branchangle,
depth-1)
drawtree(g, newangle2, newx, newy, newlength2, branchangle,
depth-1)
}
}
}
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient
with your first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en