
# macro front_wall_grille( tag, g_dim )
  // A fixed or mobile grille.
  
  // {tag}    tag for part identification.
  // {g_dim}  dimensions of grille.
  
  //  Origin is at right front lower corner.
  
  // Grille without holes:
  #local g_solid =
    box{
      < 0, 0, 0 > + eps3,
      g_dim - eps3
    }
    
  // Punch for holes:
  #local g_punch = 
    intersection{
      union{
        #local m_th = g_dim.x; // Thickness of metalon.
        
        // Number of holes in each direction:
        #local h_ny = int((g_dim.y - m_th)/(100 + m_th) + 0.5);
        #local h_nz = int((g_dim.z - m_th)/(315 + m_th) + 0.5);

        // Hole spacing in each direction:
        #local h_sty = (g_dim.y - m_th)/h_ny; // Y step of holes.
        #local h_stz = (g_dim.z - m_th)/h_nz; // Z step holes.

        #local h_sy = h_sty - m_th; // Y size of full holes.
        #local h_sz = h_stz - m_th; // Z size of full holes.
        #local h_punch = box{ < 0, 0, 0 > - eps3, < m_th, h_sy, h_sz > + eps3 } // Punch for 1 hole.

        #local h_shiftz = true; // If true, shifts next column.
        
        #local dy = m_th;
        #while (dy < g_dim.y - m_th)
          #local dz = m_th - h_shiftz*h_stz/2;
          #while (dz < g_dim.z - m_th)
            // #debug concat("!! h_shiftz = ", str(h_shiftz,1,0))
            // #debug concat(" dy = ", str(dy,1,1), " dz = ", str(dz,1,1), "\n")
            object{ h_punch translate < 0, dy, dz > }
            #local dz = dz + h_stz;
          #end
          #local dy = dy + h_sty;
          #local h_shiftz = 1 - h_shiftz;
        #end
      }
      box{ < 0, m_th, m_th > - 1.1*eps3, < m_th, g_dim.y - m_th, g_dim.z - m_th > + 1.1*eps3 }
    }

  #local grille =
    difference{ 
      object{ g_solid } 
      object{ g_punch }
      translate - g_dim.x*x
    }

  grille
  
#end
