POV-Ray : Newsgroups : povray.binaries.images : Penrose Tile Macros Server Time
5 Nov 2024 20:19:20 EST (-0500)
  Penrose Tile Macros (Message 1 to 10 of 11)  
Goto Latest 10 Messages Next 1 Messages >>>
From: Jon Buller
Subject: Penrose Tile Macros
Date: 22 Jun 2006 15:10:01
Message: <web.449aeaa42c4ebcd048362b170@news.povray.org>
Janet's image in
http://news.povray.org/povray.binaries.images/thread/%3Cweb.4494513cc659528fa30dd5a00%40news.povray.org%3E/
motivated me to clean up my Penrose macros and she wanted to see them, so
they are  coming in this thread, along with several demo images...
(Provided I can get all the software to work the way I want it to.)

The macros are pretty short, but the demonstration scene file is much longer
than it needs to be for any one image, because it has #if's all over it so
it can do them all at the same time.  (I should have made it generate each
image based on the clock, but I haven't done it in a long time and my first
guess at it was wrong.)

Note that the macros only generate tile type, placement, and orientation
information.  The scene file has all the information about actual shapes,
colors, etc.  In particular, notice that the Ammon Bars for the Dart tile
go outside the boundaries of the dart itself.

As for cloning Janet's image with my macros, I haven't done it, but it looks
like it is a Kite&Dart pattern with each tile broken in half and colored
seperately.  The colors look like they are a random function based on the
distance from the center point of the image.  Doing either of those things,
or both of them should not be difficult with these macros.

Let me know if you like (or don't like) them, and any changes you would like
(or have made).  Finally, please don't judge them based on the colors and
textures in the images, they can be described in no other way than "utterly
simplistic in the extreme".

Jon

----- Begin Penrose.inc -----
// Penrose tiling macros

// ---------- Penrose Constants ----------

#declare phi = (sqrt (5) + 1) / 2;        //                    ~= 1.61803
#declare c36 = phi / 2;     // = cos (    pi / 5) ~= 0.80902
#declare c72 = (phi - 1) / 2;    // = cos (2 * pi / 5) ~= 0.30902
#declare s36 = sqrt ((5 - sqrt (5)) / 8); // = sin (    pi / 5) ~= 0.58779
#declare s72 = sqrt ((5 + sqrt (5)) / 8); // = sin (2 * pi / 5) ~= 0.95106

// ---------- Macros to cache results of inflation ----------

// This isn't strictly necessary, but due to the way tiles overlap when
// the inflation routines operate on tiles, many duplicate tiles will be
// generated without doing this.  The procedure is simple, take the location
// of a new tile, and check the array entry for that location.  If false,
// the tile has not been done yet.  If true, it's already been done, so skip
it.
// This should be done at every level of the recursion to really be worth
while.

#declare inflate_cache_scale = phi + 1;

// Use this to initialize everything, the values define the rectangle where
// Penrose tiles will be allowed, level is the maximum level of recursion
// the inflation routines will be using.

#macro inflate_init (min_r, min_c, max_r, max_c, level)
  #declare inflate_minr = min_r;
  #declare inflate_minc = min_c;
  #declare inflate_maxr = max_r - min_r;
  #declare inflate_maxc = max_c - min_c;
  #local inflate_rs = ceil (inflate_cache_scale * inflate_maxr);
  #local inflate_cs = ceil (inflate_cache_scale * inflate_maxc);
  #declare inflate_done = array[inflate_rs][inflate_cs][level+1];
  #local row = 0;
  #while (row < inflate_rs)
    #local col = 0;
    #while (col < inflate_cs)
      #local lev = 0;
      #while (lev < level + 1)
        #declare inflate_done[row][col][lev] = false;
 #local lev = lev + 1;
      #end
      #local col = col + 1;
    #end
    #local row = row + 1;
  #end
#end

// This macro will determine if the tile has already been generated.  If it
hasn't
// been generated yet, call PENROSE_object to generate it.

#macro PENROSE_cache (pos, ang, level)
  #local row = floor (inflate_cache_scale * pos.x) - inflate_minr;
  #local col = floor (inflate_cache_scale * pos.z) - inflate_minc;
  #if (row > 0 & row < inflate_maxr & col > 0 & col < inflate_maxc)
    #if (inflate_done[row][col][level] = false)
      #declare inflate_done[row][col][level] = true;
      PENROSE_object (pos, ang, level)
    #end
  #end
#end

// ---------- Thick & Thin Rhomb macros ----------

// The Rhomb's sides are all of length 1.  The thick
// rhomb has angles of 72 and 108 degrees, the thin
// rhomb uses angles of 36 and 144 degrees instead.

// Given the center and orientation of a thick tile,
// generate the corners of the tile and pass them to the
// "thick_corners" macro.

#macro PENROSE_thick_corners (pos, ang)
  #local major = c36 * vrotate (x,  ang       * y);
  #local minor = s36 * vrotate (x, (ang + 90) * y);
  PENROSE_object (pos + major, pos + minor, pos - major, pos - minor)
#end

// Inflate a thick rhomb.  The original rhomb should be centered
// at "pos", and be oriented in the direction "ang".

#macro thick (pos, ang, level)
  #macro PENROSE_object (pos, ang, level)
    #if (level < 1)
      PENROSE_thick (pos, ang)
    #else
      #local new = 2 * c36 * (pos + vrotate((c36 - 1 / (2 * c36)) * x, ang *
y));
      thick (new + vrotate (s36 * x, (ang +  54) * y), ang + 144, level - 1)
      thin  (new + vrotate (s72 * x, (ang + 126) * y), ang +  36, level - 1)
      thick (new + vrotate (c36 * x, (ang + 180) * y), ang + 180, level - 1)
      thin  (new + vrotate (s72 * x, (ang - 126) * y), ang -  36, level - 1)
      thick (new + vrotate (s36 * x, (ang -  54) * y), ang - 144, level - 1)
    #end
  #end
  PENROSE_cache (pos, ang, level)
#end

// Now do the same things for the "thin" rhomb.  Note the similarities.
// Differences should be in the locations of the corners, and the portion
// of the inflation routine that turns a single tile into multiple tiles.

#macro PENROSE_thin_corners (pos, ang)
  #local major = s72 * vrotate (x, (ang + 90) * y);
  #local minor = c72 * vrotate (x,  ang       * y);
  PENROSE_object (pos + minor, pos + major, pos - minor, pos - major)
#end

#macro thin (pos, ang, level)
  #macro PENROSE_object (pos, ang, level)
    #if (level < 1)
      PENROSE_thin (pos, ang)
    #else
      #local new = 2 * c36 * (pos + vrotate(c72 * x, ang * y));
      thick (new + vrotate (c36 * x, (ang + 108) * y), ang + 108, level - 1)
      thin  (new + vrotate (s72 * x, (ang + 162) * y), ang - 108, level - 1)
      thin  (new + vrotate (s72 * x, (ang - 162) * y), ang + 108, level - 1)
      thick (new + vrotate (c36 * x, (ang - 108) * y), ang - 108, level - 1)
    #end
  #end
  PENROSE_cache (pos, ang, level)
#end

// ---------- Kite & Dart macros ----------

// These two macros convert from Kites and Darts to Thick and Thin Rhombs.

#macro PENROSE_kite_rhombs (pos, ang, level)
  thick (pos + vrotate (s36 * x, (ang + 126) * y), ang - 144, level)
  thin  (pos + vrotate (c72 * x,  ang        * y), ang,       level)
  thick (pos + vrotate (s36 * x, (ang - 126) * y), ang + 144, level)
#end

#macro PENROSE_dart_rhombs (pos, ang, level)
  thick (pos + vrotate (s36 * x, (ang + 54) * y), ang + 144, level)
  thick (pos + vrotate (s36 * x, (ang - 54) * y), ang - 144, level)
#end

// These macros are for Kites and Darts.  They should look a whole lot
// like the Thick and Thin Rhomb macros, except the corners are a bit
different
// and the inflation itself is a bit different.  On the other hand, by
abstracting
// out some mundane thing like PENROSE_cache, we don't have to duplicate all
that
// stuff and can concentrate on stuff that actually matters.

#macro PENROSE_kite_corners (pos, ang)
  PENROSE_object (pos + vrotate (2 * c72 * x, ang * y),
                  pos + vrotate (<c72,0,-s72>, ang * y),
                  pos + vrotate (-x, ang * y),
                  pos + vrotate (<c72,0,s72>, ang * y))
#end

#macro kite (pos, ang, level)
  #macro PENROSE_object (pos, ang, level)
    #if (level < 2)
      PENROSE_kite (pos, ang)
    #else
      #local new = 2 * c36 * pos;
      kite (new + vrotate (2 * c72 * x, (ang +  72) * y), ang - 108, level -
1)
      dart (new + vrotate (          x, (ang + 144) * y), ang - 144, level -
1)
      dart (new + vrotate (          x, (ang - 144) * y), ang + 144, level -
1)
      kite (new + vrotate (2 * c72 * x, (ang -  72) * y), ang + 108, level -
1)
    #end
  #end
  PENROSE_cache (pos, ang, level)
#end

#macro PENROSE_dart_corners (pos, ang)
  PENROSE_object (pos,
                  pos + vrotate (<-c72,0,s72>, ang * y),
                  pos + vrotate (x, ang * y),
                  pos + vrotate (<-c72,0,-s72>, ang * y))
#end

#macro dart (pos, ang, level)
  #macro PENROSE_object (pos, ang, level)
    #if (level < 2)
      PENROSE_dart (pos, ang)
    #else
      #local new = 2 * c36 * pos;
      dart (new + vrotate (          x, (ang + 72) * y), ang + 144, level -
1)
      kite (new + vrotate (2 * c72 * x,  ang       * y), ang + 180, level -
1)
      dart (new + vrotate (          x, (ang - 72) * y), ang - 144, level -
1)
    #end
  #end
  PENROSE_cache (pos, ang, level)
#end
----- End Penrose.inc


Post a reply to this message


Attachments:
Download 'penrose0.png' (565 KB)

Preview of image 'penrose0.png'
penrose0.png


 

From: Jon Buller
Subject: Re: Penrose Tile Macros
Date: 22 Jun 2006 15:25:01
Message: <web.449aeddb6376349e48362b170@news.povray.org>
And after seeing the last post, I'll attach the scene file and the macro
file from the last message in p.b.s-f.  And I'll look into why Outlook
Express (evil that it is) will grab messages from news.povray.org, but
won't get the attachements or allow me to post...  Maybe it's the IT dept
and their firewalls.

Anyway, here's the image with Kites, Darts, standard curves, and Ammon Bars.


Post a reply to this message


Attachments:
Download 'penrose1.png' (624 KB)

Preview of image 'penrose1.png'
penrose1.png


 

From: Jon Buller
Subject: Re: Penrose Tile Macros
Date: 22 Jun 2006 15:35:01
Message: <web.449af0956376349e48362b170@news.povray.org>
This image has just the curves in kite and dart tiles, but they have been
offset a bit.


Post a reply to this message


Attachments:
Download 'penrose2.png' (385 KB)

Preview of image 'penrose2.png'
penrose2.png


 

From: Jon Buller
Subject: Re: Penrose Tile Macros
Date: 22 Jun 2006 15:40:00
Message: <web.449af1ff6376349e48362b170@news.povray.org>
This image has one level of Kites and Darts colored in, and the next level
outlined in white cylinders.  The colored balls are used to force the
proper tiling patterns (instead of the curves in the last image).


Post a reply to this message


Attachments:
Download 'penrose3.png' (326 KB)

Preview of image 'penrose3.png'
penrose3.png


 

From: Janet
Subject: Re: Penrose Tile Macros
Date: 23 Jun 2006 00:40:01
Message: <web.449b6fe96376349e9656733b0@news.povray.org>
Wow! Thanks! This looks wonderful. I love the ones with the curved torus
shapes - the "Conway lines"?? I will play. Its like having a new toy. It
looks really clean too :)


Post a reply to this message

From: Jon Buller
Subject: Re: Penrose Tile Macros
Date: 23 Jun 2006 02:15:01
Message: <web.449b85666376349e2ff3aa640@news.povray.org>
"Janet" <par### [at] attnet> wrote:
> Wow! Thanks! This looks wonderful. I love the ones with the curved torus
> shapes - the "Conway lines"?? I will play. Its like having a new toy. It
> looks really clean too :)

Thanks, let me know how the playing goes.  I like the curves too.  Take a
look
at "Pathways" in the 2004 POVcomp.  That kind of image is why I did this.
Now if I only had the artistic eye and talent to get the rest of the way
there!  (Computer Science majors aren't always known for their artistic
abilities. 8^)

The next thing I plan to add is a group of objects to do with edges what the
existing macros do with vertices.  That is, all the ways you can put two
tiles together on a single edge, instead of all the ways you can put tiles
around a single point.  I think that set might help if someone wants to
create a new curve through the tiling.


Post a reply to this message

From: Jellby
Subject: Re: Penrose Tile Macros
Date: 24 Jun 2006 04:47:49
Message: <tv6vm3-ud3.ln1@badulaque.unex.es>
Among other things, Jon Buller saw fit to write:

> Anyway, here's the image with Kites, Darts, standard curves, and Ammon
> Bars.

Magnificent!

Are the bars/lines supposed to be straight? They don't look so...

-- 
light_source{9+9*x,1}camera{orthographic look_at(1-y)/4angle 30location
9/4-z*4}light_source{-9*z,1}union{box{.9-z.1+x clipped_by{plane{2+y-4*x
0}}}box{z-y-.1.1+z}box{-.1.1+x}box{.1z-.1}pigment{rgb<.8.2,1>}}//Jellby


Post a reply to this message

From: Jon Buller
Subject: Re: Penrose Tile Macros
Date: 25 Jun 2006 18:35:00
Message: <web.449f0d666376349e2ff3aa640@news.povray.org>
Jellby <me### [at] privacynet> wrote:
> Among other things, Jon Buller saw fit to write:
>
> > Anyway, here's the image with Kites, Darts, standard curves, and Ammon
> > Bars.
>
> Magnificent!

Thank you.

> Are the bars/lines supposed to be straight? They don't look so...

Yes, the blue bars/lines are supposed to be straight, but taking a closer
look, I see the pixeled edges change spacing a bit from one spot to another.
A sure sign that the slope of the line is changing slightly.  Must be either
floating point round off error, or the points where the bars intersect the
tile edges weren't described accurately in the source I coded them from.

Jon

P.S. I found a reference to doing penrose tiling with a pair of triangles.
4 triangles make a "Kite" two make a "Dart", and the two types each pair up
to make the two different Rhombs.  The advantage of this new way is that
when the triangles "inflate", the new parts don't overlap, so duplicate
checking doesn't need to be done.  (Or simple code doesn't generate multiple
copies of the same object.)  The disadvantage is that I am not sure if it is
easy/possible to tell which triangles belong to which Kite, Dart, or Rhomb
without looking at the triangle's neighbors.  I'll play with it some more
and see if I can figure it out.


Post a reply to this message

From: PM 2Ring
Subject: Re: Penrose Tile Macros
Date: 26 Jun 2006 09:00:01
Message: <web.449fd9596376349e1bd1c060@news.povray.org>
"Jon Buller" <jon### [at] bullersnet> wrote:

Nice work, Jon. And the code is relatively easy to read, too.

> P.S. I found a reference to doing penrose tiling with a pair of triangles.
> 4 triangles make a "Kite" two make a "Dart", and the two types each pair up
> to make the two different Rhombs.  The advantage of this new way is that
> when the triangles "inflate", the new parts don't overlap, so duplicate
> checking doesn't need to be done.  (Or simple code doesn't generate multiple
> copies of the same object.)

The Penrose macros posted my John Van Sickle & myself don't generate
duplicates... I hope! :) These macros operate on the golden isoceles
triangles, rather than on darts & kites, etc.

> The disadvantage is that I am not sure if it is
> easy/possible to tell which triangles belong to which Kite, Dart, or Rhomb
> without looking at the triangle's neighbors.  I'll play with it some more
> and see if I can figure it out.

Good luck! I think you will need to examine neighbours.


Post a reply to this message

From: Jon Buller
Subject: Re: Penrose Tile Macros
Date: 27 Jun 2006 03:05:01
Message: <web.44a0d3916376349e2ff3aa640@news.povray.org>
"PM 2Ring" <nomail@nomail> wrote:
> "Jon Buller" <jon### [at] bullersnet> wrote:
>
> > The disadvantage is that I am not sure if it is
> > easy/possible to tell which triangles belong to which Kite, Dart, or Rhomb
> > without looking at the triangle's neighbors.  I'll play with it some more
> > and see if I can figure it out.
>
> Good luck! I think you will need to examine neighbours.

OK, I now see that doing Rhomb tiling is simple without any duplicate
detection. (That is, the inflation doesn't overlap it's neighbors, and it
works without using that init_inflate macro and friends.)

Consider this:

#macro tri (pos, ang, typ, level)
  #if (level < 1)
    PENROSE_triangle (pos, ang, typ)
  #else
    #if (abs(typ) = 18)
      tri (phi * (pos + vrotate (x, (ang - typ) * y)),
           ang + typ * 6, typ,     level - 1)
      tri (phi *  pos + vrotate (x, (ang + typ) * y),
           ang - typ * 6, typ * 3, level - 1)
    #else
      #local new = phi * pos + (phi - 1) * vrotate (x, (ang + typ) * y);
      tri (new, ang,             -typ,     level - 1)
      #local new = new + vrotate (x, (ang - typ) * y);
      tri (new, ang - typ * 8/3,  typ,     level - 1)
      tri (new, ang + typ * 8/3, -typ / 3, level - 1)
    #end
  #end
#end

Call this as the others, pos and ang are the location and orientation of the
triangle, level is how many inflate operations to do.  That typ parameter is
the size and orientation of the triangle.  It takes values of -54, -18, 18,
and 54.  To draw a triangle, draw unit length edges from pos in the
direction of ang + typ and ang - typ (and connect those two points for the
final edge).

It is simple to draw the triangles themselves.  But notice that if you draw
each edge (I'll call them +, -, and o) in a different color, all the
triangles have the same edge type for a shared edge.  Since a Rhomb is just
two 54 triangles that share an "o" edge, and any triangle with an "o" edge
has the neighbor of that edge that is also an "o" edge.  The other
interesting thing is that the other triangle is the negative type of its
neighbor.  So to draw rhombs instead of triangles, just ignore the negative
type triangles(-54 & -18), and treat the +54 triangles as rhombs that have
points of pos, pos+, pos-, and pos+-  (add the + and - direction vectors
together for pos+-)

Starting with a +54 triangle and a -54 triangle sharing "o" edges, and using
the rhomb generation macros from before with all the decorations on, you get
the attached image.  Note that the tri macro does not need that huge array
of true/false values to tell if it has already generated a tile at a
specific location or not, but can still generate a rhomb tiling without any
duplicate objects.

I still haven't figured out how to do Kites & Darts yet, but I think it
might be possible.  In fact, I think it's more possible now than I did when
I wrote that last message.


Post a reply to this message


Attachments:
Download 'penrose.png' (183 KB)

Preview of image 'penrose.png'
penrose.png


 

Goto Latest 10 Messages Next 1 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.