|
Prev: How to xor?
Next: Continuation paper
From: LuisGLopez on 28 Sep 2005 11:19 Hi! Again with a simple code ;) It's about plotting Koch figures (curve, snowflake... and more!). (http://en.wikipedia.org/wiki/Koch_curve). I did a search in c.l.l., but didn't find anything. Maybe too simple? Anyway, I must confess that I am *very* *proud* of it! :P Really... I just wanted to draw the Koch curve, but then realize that, with the *same* code I made, I could draw *any* koch figure of my choice! I think that that's due to the way that lisp is 'shaping' my mind... well, I would like to think so! :) (Graphics initialization code omited): ------------------------------------------ (defun x (pt) (car pt)) (defun y (pt) (cdr pt)) (defun point (x y) (cons x y)) (defun draw-line (A B) (xlib:draw-line *win* *gctxt* (round (x A)) (round (y A)) (round (x B)) (round (y B)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Koch curve code (defconstant +tan60+ (tan (/ pi 3))) (defun punto-a-un-tercio-entre (A B) "Yields the point at one third the distance between A and B." (point (/ (+ (x B) (* 2 (x A))) 3) (/ (+ (y B) (* 2 (y A))) 3))) (defun punto-equilátero (A B) "Yields the point that forms an equilateral triangle with A and B. Well, one of them: the one 'at the left of' A." (let ((D (point (/ (+ (x A) (x B)) 2) (/ (+ (y A) (y B)) 2)))) (point (- (x D) (* +tan60+ (- (y D) (y A)))) (+ (y D) (* +tan60+ (- (x D) (x A))))))) (defun koch (puntos &key (clear t)) (let ((puntos-nuevos (make-array (1+ (* 4 (1- (length puntos)))) :fill-pointer 0))) (dotimes (i (1- (length puntos))) (let* ((A (elt puntos i)) (B (elt puntos (1+ i))) (A1 (punto-a-un-tercio-entre A B)) (B1 (punto-a-un-tercio-entre B A))) (draw-line A B) (vector-push A puntos-nuevos) (vector-push A1 puntos-nuevos) (vector-push (punto-equilátero A1 B1) puntos-nuevos) (vector-push B1 puntos-nuevos))) (vector-push (elt puntos (1- (length puntos))) puntos-nuevos) (xlib:display-force-output *dpy*) (sleep 1) (when clear (clear-window)) (koch puntos-nuevos :clear clear))) (defun dibujar-koch (puntos &key (clear t)) (open-window) (koch puntos :clear clear)) -------------------------------------- suggested examples: (dibujar-koch (vector (point 500 250) (point 100 250))) (dibujar-koch (vector (point 100 400) (point 400 400) (point 400 100) (point 100 100) (point 100 400))) (dibujar-koch (vector (point 100 400) (point 500 400) (punto-equilátero (point 500 400) (point 100 400)) (point 100 400))) Any C&C? :-) Luis.
From: Raph on 28 Sep 2005 13:03 Very nice. For the CLISP users out there (Windows or Linux), I have added the new Koch drawing code to my little Canvas Demo Application. (Your original "Beautiful Patterns" post forced me to write it, because I wanted to see what you were talking about!) :) The code requires CLISP and GTK, and works on Linux and Windows. See http://www.gotlisp.com/gtk-drawing.html for more details. Thanks, Luis! Raph
From: A.L. on 28 Sep 2005 14:20 On 28 Sep 2005 08:19:37 -0700, "LuisGLopez" <luis.g.lopez(a)gmail.com> wrote: >Hi! > >Again with a simple code ;) > >It's about plotting Koch figures (curve, snowflake... and more!). >(http://en.wikipedia.org/wiki/Koch_curve). > >I did a search in c.l.l., but didn't find anything. Maybe too simple? >Anyway, I must confess that I am *very* *proud* of it! :P And below is in Java. Could somebody, using both examples, explain why "Lisp is better"?... A.L. public class Koch { // Koch curve of order n public static void koch(int n, double size) { if (n == 0) StdDraw.forward(size); else { koch(n-1, size); StdDraw.rotate(60); koch(n-1, size); StdDraw.rotate(-120); koch(n-1, size); StdDraw.rotate(60); koch(n-1, size); } } public static void main(String args[]) { int N = Integer.parseInt(args[0]); int width = 512; int height = (int) (2 * width / Math.sqrt(3)); double size = width / Math.pow(3.0, N); StdDraw.create(width, height); StdDraw.setScale(0, 0, width, height); // three Koch curves in the shape of an equilateral triangle StdDraw.moveTo(0, width * Math.sqrt(3) / 2); koch(N, size); StdDraw.rotate(-120); koch(N, size); StdDraw.rotate(-120); koch(N, size); StdDraw.show(); } } Taken rom http://www.cs.princeton.edu/introcs/27recursion/Koch.java.html
From: Marc Battyani on 28 Sep 2005 17:12 "A.L." wrote: > On 28 Sep 2005 08:19:37 -0700, "LuisGLopez" <luis.g.lopez(a)gmail.com> > wrote: > > >It's about plotting Koch figures (curve, snowflake... and more!). > >(http://en.wikipedia.org/wiki/Koch_curve). > > > >I did a search in c.l.l., but didn't find anything. Maybe too simple? > >Anyway, I must confess that I am *very* *proud* of it! :P > > > And below is in Java. Could somebody, using both examples, explain why > "Lisp is better"?... > > A.L. The Koch figure is the example 8 of the cl-pdf examples: http://www.fractalconcept.com:8000/public/open-source/cl-pdf/examples/exampl es.lisp Here it is: (defun vk-fractal (l level) (pdf:with-saved-state (if (zerop level) (progn (pdf:move-to 0 0) (pdf:line-to l 0) (pdf:stroke)) (loop with l3 = (/ l 3.0) and l-1 = (1- level) for angle in '(nil 60 -120 60) do (when angle (pdf:rotate angle)) (vk-fractal l3 l-1)))) (pdf:translate l 0)) The with-saved-state/translate stuff is to avoid the floating point rounding accumulation errors in the pdf readers for high order values. Compared to the Java one, at least this one generates a cool pdf file: http://www.fractalconcept.com:8000/public/open-source/cl-pdf/examples/ex8.pd f You can zoom the level 6 with your pdf reader to see the deeper levels. (Don't try with the Java version you would be disappointed ;-) > public class Koch { > > // Koch curve of order n > public static void koch(int n, double size) { > if (n == 0) StdDraw.forward(size); > else { > koch(n-1, size); > StdDraw.rotate(60); > koch(n-1, size); > StdDraw.rotate(-120); > koch(n-1, size); > StdDraw.rotate(60); > koch(n-1, size); > } > } Creating a class just to draw a simple curve like this is a perfect example of bad taste. And being forced to declare it as public, static and void is well... pathetic. ;-) Marc [Sorry, I should not feed the trolls especially during the troll season (every fall ;-) ]
From: Raph on 28 Sep 2005 17:46
If I (defun yucky-draw-line (length) ... ) as a function that draws "length" pixels from global_point_x, global_point_y in the direction of the current global_angle, then I can reproduce the results of the Java code easily: (defun my_koch (num size) (if (= 0 num) (yucky-draw-line size) (loop for angle in '(nil 60 -120 60) do (when angle (setq global_angle (+ global_angle angle))) (my_koch (- num 1) size)))) (defun the_main_thingy (koch-level) (setf my-width 512) (setf my-height (/ (* 2 my-width) (sqrt 3))) (setf my-size (/ (float my-width) (expt 3 koch-level))) (setq global_point_x 0) (setq global_point_y (round (/ (* (float my-width) (sqrt 3)) 2))) (loop for angle in '(nil -120 -120) do (when angle (setq global_angle (+ global_angle angle))) (my_koch koch-level my-size))) That's it. Happy to post the entire working code (meaning, the yucky-draw-line function) if you want it. That's *not* the point. The point is that the above code ONLY draws the snowflake Koch curve. Luis specifically said "Really... I just wanted to draw the Koch curve, but then realize that, with the *same* code I made, I could draw *any* koch figure of my choice!" Look at his examples: This draws a Koch Curve based on a line... (dibujar-koch (vector (point 500 250) (point 100 250))) This draws a Koch Curve based on a square... (dibujar-koch (vector (point 100 400) (point 400 400) (point 400 100) (point 100 100) (point 100 400))) And this is the snowflake... (dibujar-koch (vector (point 100 400) (point 500 400) (punto-equilátero (point 500 400) (point 100 400)) (point 100 400))) Could you do it in Java? Sure. The point is not that you can't do this in Java, but that Luis' relatively small code segment allows Koch curves to be drawn out of vectors of points. I think the code size and complexity required to do this in Java would be larger. If we're going to do language trolling, let's at least do it with the same example problem. It's not about just drawing the Koch snowflake. Thanks! Raph |