POV-Ray : Newsgroups : povray.text.scene-files : Penrose tiling code Server Time
31 Oct 2024 19:27:57 EDT (-0400)
  Penrose tiling code (Message 1 to 3 of 3)  
From: Alex
Subject: Penrose tiling code
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

From: Alex
Subject: Re: Penrose tiling code
Date: 17 Jul 2005 21:59:44
Message: <hVwDmqDwhw2CFwmE@lazysod.org.uk>
In message <CyG### [at] lazysodorguk>, Alex <pov### [at] lazysodorguk> 
writes
>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!
>
And after a slight delay here is the code for the Penrose flooring in my 
geomag pictures. I've added an inverse video reflecting sphere for no 
reason, and am upset to find povray won't do negative reflections.





#declare area=0;        //use area light

#declare tilr=1;        //use reflective tiles



global_settings{
   assumed_gamma 1.0
   max_trace_level 6
   adc_bailout 1/250

   }

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













// wide angle camera

// max 120*90 degrees

#declare cam_location=<-680,1200,-1250>;
#declare cam_look_at=<0,50,-200>;
#declare cam_rotation=0;        //look around y axis
#declare cam_dip=0;             //look down
#declare cam_twist=0;           //tip to left
#declare cam_view_horz=100;
#declare cam_aspect_ratio=4/3;
#declare cam_view_vert=cam_view_horz/cam_aspect_ratio;
#declare cam_scale=0.1;

#declare cam_direction=cam_look_at-cam_location;
#declare
cam_dip=cam_dip-degrees(atan2(cam_direction.y,vlength(cam_direction*<1,0,1>)));
#declare cam_rotation=cam_rotation+degrees(atan2(cam_direction.x,cam_direction.z));


isosurface{
   function{z-ln(cos(sqrt(x*x+y*y)))}
   contained_by{box{<-0.53,-0.40,-0.24>,<0.53,0.40,0>}}
   threshold 0
   accuracy 0.001
   max_gradient 1.2
   no_reflection
   no_shadow
   texture{
     pigment{colour Orange}
     finish{ambient 0 diffuse 0 reflection 1}
     }
   scale cam_scale
   rotate z*cam_twist            //twist
   rotate x*cam_dip              //dip
   rotate y*cam_rotation         //round
   translate cam_location
   }


#declare cam_w=cam_view_horz*pi/360;
#declare cam_h=cam_view_vert*pi/360;

camera{
   orthographic
   right -x*cam_w
   up y*cam_h
   location z
   look_at 0
   scale cam_scale
   rotate z*cam_twist            //twist
   rotate x*cam_dip              //dip
   rotate y*cam_rotation         //round
   translate cam_location
   }







#declare dia=120;

sphere{y*(3+dia),dia
   texture{
     pigment{colour White}
     finish{ambient -1 diffuse 0 reflection 3}
     }
   }
sphere{y*(3+dia),dia+0.001
   texture{
     pigment{colour rgbft <0,0,0,0,-1>}
     finish{ambient 0 diffuse 0}
     }
     interior_texture{
     pigment{colour rgbft <0,0,0,0,1>}
     finish{ambient 0 diffuse 0}
     }
   }









#declare pigr=pigment{
                 bozo
                 colour_map{
                   [0.5 colour Gray50]
                   [1 colour Red*3]
                   }
                 translate 5
                 }

#declare pigg=pigment{
                 bozo
                 colour_map{
                   [0.5 colour Gray50]
                   [1 colour Green*3]
                   }
                 translate 23
                 }

#declare pigb=pigment{
                 bozo
                 colour_map{
                   [0.5 colour Gray50]
                   [1 colour Blue*3]
                   }
                 translate 47
                 }





plane{y,0
   texture{
     pigment{colour Gray50}
     finish{
       ambient 0
       diffuse 0.5
       }
     }
   }


box{<-1500,-20,-1500>,<1500,1800,1500>
   texture{
     pigment{
       average
       pigment_map{
         [1 pigr]
         [1 pigg]
         [1 pigb]
         }
       scale 700
       }
     finish{
       ambient 0
       diffuse 0.7
       }
     }
   }


light_source{
   <-1100,1400,-1100>,Gray30*4

   spotlight
   radius 40
   falloff 150
   tightness 1
   point_at 0
#if (area)
   area_light x*100,z*100,5,5
   adaptive 0
   jitter
#end
   fade_power 2
   fade_distance 2000/3
   }

light_source{
   <1100,1400,-1100>,Gray30*4

   spotlight
   radius 40
   falloff 150
   tightness 1
   point_at 0
#if (area)
   area_light x*100,z*100,5,5
   adaptive 0
   jitter
#end
   fade_power 2
   fade_distance 2000/3
   }

light_source{
   <-1100,1400,1100>,Gray20*4

   spotlight
   radius 40
   falloff 150
   tightness 1
   point_at 0
#if (area)
   area_light x*100,z*100,5,5
   adaptive 0
   jitter
#end
   fade_power 2
   fade_distance 2000/3
   }

light_source{
   <1100,1400,1100>,Gray20*4

   spotlight
   radius 40
   falloff 150
   tightness 1
   point_at 0
#if (area)
   area_light x*100,z*100,5,5
   adaptive 0
   jitter
#end
   fade_power 2
   fade_distance 2000/3
   }

light_source{                            // fill-in light
   <-50,500,-1400>,Gray20*4

   spotlight
   radius 40
   falloff 70
   tightness 1
   point_at 0
#if (area)
   area_light x*100,y*100,5,5
   adaptive 0
   jitter
#end
   fade_power 2
   fade_distance 1000/3
   }
















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

#declare bd=0.01;         //rhomb outline thickness
#declare thick=3/27;
#declare bev_dep=0.04;           // depth of bevel at edge from top surface
#declare bev_ang=40;            // angle of top face of tile to bevel

#declare it=8;

#declare rnx=seed(1);
#declare rny=seed(2);
#declare rnz=seed(3);

#declare colour_thin=colour rgb <7,3,0>/9;
#declare colour_fat=colour rgb <2,0,8>/9; //<1,1,1>/2-(colour_thin-<1,1,1>/2)/(phi+1);

#declare g_size=ceil(2.4*pow(phi,it));
#declare got=array[g_size*2+1][g_size*2+1][10][it+1];        // x * y * 10



#declare fat=intersection{
                plane{z,thick}           // top
                plane{-z,0}            //bottom

                plane{x,0 rotate 0*y translate (s36*s54-bd)*x rotate 54*z}     
//sides
                plane{x,0 rotate 0*y translate (s36*s54-bd)*x rotate 126*z}
                plane{x,0 rotate 0*y translate (s36*s54-bd)*x rotate 234*z}
                plane{x,0 rotate 0*y translate (s36*s54-bd)*x rotate 306*z}

                plane{x,0 rotate (bev_ang-90)*y translate
(s36*s54-bd)*x+(thick-bev_dep)*z rotate 54*z}      //bevel
                plane{x,0 rotate (bev_ang-90)*y translate
(s36*s54-bd)*x+(thick-bev_dep)*z rotate 126*z}
                plane{x,0 rotate (bev_ang-90)*y translate
(s36*s54-bd)*x+(thick-bev_dep)*z rotate 234*z}
                plane{x,0 rotate (bev_ang-90)*y translate
(s36*s54-bd)*x+(thick-bev_dep)*z rotate 306*z}

                translate s54*x
                bounded_by{box{<0,-s36,0>,<2*s54,s36,thick>}}
                texture{
                  pigment{colour_fat}
                  finish{
                    ambient 0
                    #if (tilr)
                      diffuse 0.5
                      reflection 0.4
                    #else
                      diffuse 0.7
                    #end
                    phong 1
                    phong_size 70
                    }
                  normal{bumps 0.04 scale 1/2 translate
<rand(rnx),rand(rny),rand(rnz)>*1000}
                  }
                }





#declare thin=intersection{
                plane{z,thick}           // top
                plane{-z,0}            //bottom

                plane{x,0 rotate 0*y translate (s72*s18-bd)*x rotate 18*z}     
//sides
                plane{x,0 rotate 0*y translate (s72*s18-bd)*x rotate 162*z}
                plane{x,0 rotate 0*y translate (s72*s18-bd)*x rotate 198*z}
                plane{x,0 rotate 0*y translate (s72*s18-bd)*x rotate 342*z}

                plane{x,0 rotate (bev_ang-90)*y translate
(s72*s18-bd)*x+(thick-bev_dep)*z rotate 18*z}      //bevel
                plane{x,0 rotate (bev_ang-90)*y translate
(s72*s18-bd)*x+(thick-bev_dep)*z rotate 162*z}
                plane{x,0 rotate (bev_ang-90)*y translate
(s72*s18-bd)*x+(thick-bev_dep)*z rotate 198*z}
                plane{x,0 rotate (bev_ang-90)*y translate
(s72*s18-bd)*x+(thick-bev_dep)*z rotate 342*z}

                translate s18*x
                bounded_by{box{<0,-s72,0>,<2*s18,s72,thick>}}
                texture{
                  pigment{colour_thin}
                  finish{
                    ambient 0
                    #if (tilr)
                      diffuse 0.5
                      reflection 0.4
                    #else
                      diffuse 0.7
                    #end
                    phong 1
                    phong_size 70
                    }
                  normal{bumps 0.04 scale 1/2 translate
<rand(rnx),rand(rny),rand(rnz)>*1000}
                  }
                }


#macro inf_fat(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;

#if (levl=0)


     object{fat rotate z*angl translate posn rotate<-90,0,0> scale 27}


#else

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

   inf_fat((posn*phi+vrotate(<1+2*s54,0>,z*angl)),angl+180,levl-1)
   inf_fat((posn*phi+vrotate(<1+s18,s72>,z*angl)),angl-144,levl-1)
   inf_fat((posn*phi+vrotate(<1+s18,-s72>,z*angl)),angl+144,levl-1)

   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
   #end //ifndef
#end  //macro inf_fat



#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;

#if (levl=0)


     object{thin rotate z*angl translate posn rotate<-90,0,0> scale 27}


#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






inf_fat(<0,0>,18,it)
inf_fat(<0,0>,90,it)
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

From: Dave Matthews
Subject: Re: Penrose tiling code
Date: 18 Jul 2005 12:30:01
Message: <web.42dbd865660bab327196f5900@news.povray.org>
Alex <pov### [at] lazysodorguk> wrote:
> 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.
>
Thanks for the code!

A while back, I posted an include file, with the code lifted from an IRTC
entry by John Van Sickle:

http://news.povray.org/povray.binaries.scene-files/thread/%3C3fafcd40%241%40news.povray.org%3E/?ttop=215138&toff=150

I thought at the time that there should be some sort of method of generating
the tilings based on "seeds" as you have done, but I couldn't puzzle it
out.  Now I'll have to look over your code, to see how you did it.

Oh, also, really cool geomag images, by the way!

Dave Matthews


Post a reply to this message

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