From: LuisGLopez on
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
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
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
"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
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

 |  Next  |  Last
Pages: 1 2 3
Prev: How to xor?
Next: Continuation paper