diff -urN  povray-3.6.1/source/frame.h  povray-3.6.1-ww/source/frame.h
---  povray-3.6.1/source/frame.h	2004-07-18 12:16:25.000000000 +0200
+++  povray-3.6.1-ww/source/frame.h	2004-07-24 17:10:28.000000000 +0200
@@ -1312,6 +1312,7 @@
    struct { void *Fn; void *Data; } Function;\
    PIGMENT *Pigment; \
    OBJECT *Object;\
+   short Grid_Type; \
  } Vals;
 
 struct Pattern_Struct
diff -urN  povray-3.6.1/source/parse.h  povray-3.6.1-ww/source/parse.h
---  povray-3.6.1/source/parse.h	2004-07-18 12:16:26.000000000 +0200
+++  povray-3.6.1-ww/source/parse.h	2004-07-24 16:56:58.000000000 +0200
@@ -246,6 +246,7 @@
   GIF_TOKEN,
   GRADIENT_TOKEN,
   GRANITE_TOKEN,
+  GRID_PATTERN_TOKEN,
   HASH_TOKEN,
   HAT_TOKEN,
   HEIGHT_FIELD_TOKEN,
diff -urN  povray-3.6.1/source/parstxtr.cpp  povray-3.6.1-ww/source/parstxtr.cpp
---  povray-3.6.1/source/parstxtr.cpp	2004-07-18 12:16:26.000000000 +0200
+++  povray-3.6.1-ww/source/parstxtr.cpp	2004-07-24 17:15:09.000000000 +0200
@@ -1181,6 +1181,25 @@
        EXIT
      END_CASE
 
+     CASE (GRID_PATTERN_TOKEN)
+       New->Type = GRID_PATTERN;
+       New->Frequency = 1.0;
+       EXPECT
+         CASE (CYLINDRICAL_TOKEN)
+           New->Vals.Grid_Type = 1;
+           EXIT
+         END_CASE
+         CASE (PLANAR_TOKEN)
+           New->Vals.Grid_Type = 0;
+           EXIT
+         END_CASE
+         OTHERWISE
+           Error("Invalid grid_pattern type. Valid types are 'planar' and 'cylindrical'.");
+         END_CASE
+       END_EXPECT
+       EXIT
+     END_CASE
+
      CASE (DENSITY_FILE_TOKEN)
        if (Old_Type==DENSITY_FILE_PATTERN) 
        {
diff -urN  povray-3.6.1/source/pattern.cpp  povray-3.6.1-ww/source/pattern.cpp
---  povray-3.6.1/source/pattern.cpp	2004-07-18 12:16:26.000000000 +0200
+++  povray-3.6.1-ww/source/pattern.cpp	2004-07-24 17:21:28.000000000 +0200
@@ -88,6 +88,7 @@
 static DBL function_pattern (VECTOR EPoint, TPATTERN *TPat); // iso_surface - added
 static DBL gradient_pattern (VECTOR EPoint, TPATTERN *TPat);
 static DBL granite_pattern (VECTOR EPoint, TPATTERN *TPat);
+static DBL grid_pattern (VECTOR EPoint, TPATTERN *TPat);
 static DBL hexagon_pattern (VECTOR EPoint);
 static DBL julia_pattern (VECTOR EPoint, TPATTERN *TPat);
 static DBL julia3_pattern (VECTOR EPoint, TPATTERN *TPat);
@@ -175,6 +176,7 @@
 		case CRACKLE_PATTERN:     value = crackle_pattern    (EPoint, TPat);   break;
 		case GRADIENT_PATTERN:    value = gradient_pattern   (EPoint, TPat);   break;
 		case GRANITE_PATTERN:     value = granite_pattern    (EPoint, TPat);   break;
+		case GRID_PATTERN:        value = grid_pattern       (EPoint, TPat);   break;
 		case HEXAGON_PATTERN:     value = hexagon_pattern    (EPoint);         break;
 		case JULIA_PATTERN:       value = julia_pattern      (EPoint, TPat);   break;
 		case JULIA3_PATTERN:      value = julia3_pattern     (EPoint, TPat);   break;
@@ -1886,6 +1888,74 @@
 }
 
 
+/*****************************************************************************
+*
+* FUNCTION
+*
+*   grid_pattern
+*
+* INPUT
+*
+*   EPoint -- The point in 3d space at which the pattern
+*   is evaluated.
+*
+* OUTPUT
+*
+* RETURNS
+*
+*   Double value between 0.0 and 1.0. 
+*
+* AUTHOR
+*
+*   Wolfgang Wieser
+*
+* DESCRIPTION
+*
+*   Grid pattern can be used for easy creation of cylindrical 
+*   (Vals.Grid_Type = 1) and planar (Vals.Grid_Type = 0) grids. 
+*
+******************************************************************************/
+
+inline DBL _fract(register DBL x)
+{  return(x-floor(x));  }
+
+static DBL grid_pattern (VECTOR EPoint, TPATTERN *TPat)
+{
+  DBL mindist=0.5;
+
+  switch(TPat->Vals.Grid_Type)
+  {
+    case 0:  /* planar */
+    {
+      DBL xlen=_fract( EPoint[X] );
+      DBL zlen=_fract( EPoint[Z] );
+
+      if(xlen>0.5)  xlen=1.0-xlen;
+      if(zlen>0.5)  zlen=1.0-zlen;
+      mindist = min(xlen,zlen);
+      mindist+=mindist;
+    } break;
+    case 1:  /* cylindrical */
+    {
+      /*DBL rad=_fract( hypot(EPoint[X],EPoint[Z]) );*/
+      DBL ylen=_fract( EPoint[Y] );
+      DBL phi=atan2(EPoint[Z],EPoint[X]);  // -pi..+pi
+      DBL sector=_fract( TPat->Frequency*(phi+M_PI)/M_PI );
+
+      if(sector>0.5)  sector=1.0-sector;
+      if(ylen>0.5)  ylen=1.0-ylen;
+      mindist = min(sector,ylen);
+      mindist+=mindist;
+    } break;
+  }
+
+  if(mindist>1.0)  mindist=1.0;
+  else if(mindist<0.0)  mindist=0.0;
+  
+  return(mindist/TPat->Frequency);
+}
+
+
 /*****************************************************************************
 *
 * FUNCTION
diff -urN  povray-3.6.1/source/pattern.h  povray-3.6.1-ww/source/pattern.h
---  povray-3.6.1/source/pattern.h	2004-07-18 12:16:26.000000000 +0200
+++  povray-3.6.1-ww/source/pattern.h	2004-07-24 17:06:20.000000000 +0200
@@ -83,6 +83,7 @@
   AGATE_PATTERN,
   GRANITE_PATTERN,
   GRADIENT_PATTERN,
+  GRID_PATTERN,
 /*  PATTERN1_PATTERN,
   PATTERN2_PATTERN,
   PATTERN3_PATTERN,*/
diff -urN  povray-3.6.1/source/tokenize.cpp  povray-3.6.1-ww/source/tokenize.cpp
---  povray-3.6.1/source/tokenize.cpp	2004-07-18 12:16:27.000000000 +0200
+++  povray-3.6.1-ww/source/tokenize.cpp	2004-07-24 17:07:03.000000000 +0200
@@ -365,6 +365,7 @@
   {GRAY_TOKEN, "gray"},
   {GRAY_THRESHOLD_TOKEN, "gray_threshold" },
   {GREEN_TOKEN, "green"},
+  {GRID_PATTERN_TOKEN, "grid_pattern" },
   {HASH_TOKEN, "#"},
   {HAT_TOKEN, "^"},
   {HEIGHT_FIELD_TOKEN, "height_field"},

