POV-Ray : Newsgroups : povray.text.scene-files : Penrose tiling code : Penrose tiling code Server Time
1 Jun 2024 19:33:47 EDT (-0400)
  Penrose tiling code  
From: Alex
Date: 17 Jul 2005 11:37:19
Message: <CyG7PTBrsn2CFwx0@lazysod.org.uk>
As requested, here is some code for generating Penrose tilings.

This was my development code, with some comments added. It just produces
a plain tiling image in a similar fashion to fractint.

A scene file for the penrose flooring in my images will hopefully be
following as soon as I have edited it!






global_settings{
  assumed_gamma 1.0
  }

#include "colors.inc"
#include "math.inc"

#declare s18=sin(1*pi/10);           // sin 18 degrees
#declare s36=sin(2*pi/10);           // etc
#declare s54=sin(3*pi/10);
#declare s72=sin(4*pi/10);
#declare phi=(sqrt(5)+1)/2;

#declare bd=0.04;         //rhomb outline thickness


#declare it=3;            // level of recursion  0=none  10=lots  11=can't allocate a
big block of memory!


                        // create an array to store positions of tiles at each
recursion level, to weed out duplicates
                        // just a crude array indexed by nearest integer of x co-ord
and y co-ord and orientation of tile.


#declare g_size=ceil(2.4*pow(phi,it));                       // calc integer size of
array needed, prob a little larger than needed
#declare got=array[g_size*2+1][g_size*2+1][10][it+1];        // x * y * 10 * recursion
level


                                                       // the objects to be used as
tiles.
                                                       // un-commenting the spheres
will show the orientation of the tiles


#declare fat=union{         // sphere{<s54/2,0>,s54*s36/4 texture{pigment{colour
Red}finish{ambient 1}}}
               polygon{
                
5,<bd/s36,0>,<s54,s36-bd/s54>,<2*s54-bd/s36,0>,<s54,-s36+bd/s54>,<bd/s36,0>
                 texture{
                   pigment{colour Yellow}
                   finish{ambient 1}
                   }
                 }
               polygon{
                 5,<0,0>,<s54,s36>,<2*s54,0>,<s54,-s36>,<0,0>
                 translate z/100
                 texture{
                   pigment{colour Gray20}
                   finish{ambient 1}
                   }
                 }
               }

#declare thin=union{        // sphere{<s18/2,0>,s18*s72/4 texture{pigment{colour
Red}finish{ambient 1}}}
                polygon{
                 
5,<bd/s72,0>,<s18,s72-bd/s18>,<2*s18-bd/s72,0>,<s18,-s72+bd/s18>,<bd/s72,0>
                  texture{
                  pigment{colour Blue}
                  finish{ambient 1}
                  }
                }
              polygon{
                5,<0,0>,<s18,s72>,<2*s18,0>,<s18,-s72>,<0,0>
                translate z/100
                texture{
                pigment{colour Gray20}
                finish{ambient 1}
                }
              }
            }




                                                   // this macro inflates the fat
rhombs

#macro inf_fat(posn,angl,levl)                      // takes tile position,
orientation and current recursion level

  #declare a1=1.2*posn.x+g_size;                  // calc indexes to array to see if
this tile has been done before
  #declare a2=1.2*posn.y+g_size;                   // 1.2 multiplier controls
granularity of indexing, lowering reduces resolution of array, raising increases
memory usage.
                                                             // must change size of
array above in concert with this.
  #declare a3=mod((floor((angl+378)/36)),10);

  #ifndef (got[a1][a2][a3][levl])                 // only execute the rest of the
macro if the array index has not been defined yet
                                                   // we're about to do the current
rhomb so let's define the array element so we know in future not to do it again.
    #declare got[a1][a2][a3][levl]=1;                // comment out this line to
disable the duplication checking to compare number of scene level objects, memory
usage and parse/render times

#if (levl=0)

     object{fat rotate z*angl translate posn}       // if at last recursion level then
we draw a real tile

#else    //if levl=0
                                                     // if not then we call the macros
recursively to substitute this 'tile' with several others
  #if (angl<0) #declare angl=angl+360; #end
  #if (angl>360) #declare angl=angl-360; #end         // pull angle into 0-360 range

  inf_fat((posn*phi+vrotate(<1+2*s54,0>,z*angl)),angl+180,levl-1)        // scale
current position by golden ratio
  inf_fat((posn*phi+vrotate(<1+s18,s72>,z*angl)),angl-144,levl-1)        // add offset
for subst tiles, rotating by the orientation of the tile
  inf_fat((posn*phi+vrotate(<1+s18,-s72>,z*angl)),angl+144,levl-1)       // and also
reduce the recursion level by one to avoid infinite loops

  inf_thin((posn*phi+vrotate(<1+s18,s72>,z*angl)),angl-36,levl-1)
  inf_thin((posn*phi+vrotate(<1+s18,-s72>,z*angl)),angl+36,levl-1)

#end   //if levl
  #end //ifndef
#end  //macro inf_fat




                                                          // this macro inflates thin
rhombs, works same as above.
#macro inf_thin(posn,angl,levl)

  #declare a1=1.2*posn.x+g_size;
  #declare a2=1.2*posn.y+g_size;
  #declare a3=mod((floor((angl+378)/36)),10);

  #ifndef (got[a1][a2][a3][levl])
    #declare got[a1][a2][a3][levl]=1;                     // comment out this line to
disable the duplication checking to compare number of scene level objects, memory
usage and parse/render times

#if (levl=0)


    object{thin rotate z*angl translate posn}


#else

  #if (angl<0) #declare angl=angl+360; #end
  #if (angl>360) #declare angl=angl-360; #end

  inf_thin((posn*phi+vrotate(<1,0>,z*angl)),angl+108,levl-1)
  inf_thin((posn*phi+vrotate(<1,0>,z*angl)),angl-108,levl-1)

  inf_fat((posn*phi+vrotate(<s54-s18,s36+s72>,z*angl)),angl-108,levl-1)
  inf_fat((posn*phi+vrotate(<s54-s18,-s36-s72>,z*angl)),angl+108,levl-1)

#end   //if
  #end //ifndef
#end  //macro inf_thin






camera{
                                                    // tiles are placed in x,y plane,
look at from -z axis
right<4,0,0>
up<0,3,0>
direction<0,0,10>
location<0,0,-12*pow(phi,it)>//2       // this gets the whole tiling visible by moving
the camera in and out - tag '/2' to the end to zoom in and fill the whloe screen
look_at<0,0,0>
}


inf_fat(<0,0>,18,it)                           // 5 seed tiles to kick the whole thing
off.
inf_fat(<0,0>,90,it)                           // These can be changed, but that may
require changes to the duplicate checking if any are away from the origin
inf_fat(<0,0>,162,it)
inf_fat(<0,0>,234,it)
inf_fat(<0,0>,306,it)

-- 
Alex


Post a reply to this message

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