content: /*****************************************************************************
   *                        Shapeways, Inc Copyright (c) 2011
   *                               Java Source
   *
   * This source is licensed under the GNU LGPL v2.1
   * Please read http://www.gnu.org/copyleft/lgpl.html for more information
   *
   * This software comes with the standard NO WARRANTY disclaimer for any
   * purpose. Use it at your own risk. If there's a problem you get to fix it.
   *
   ****************************************************************************/
  
  package abfab3d.grid;
  
  // External Imports
  
  import abfab3d.core.Grid2D;
  import abfab3d.core.GridDataDesc;
  import abfab3d.core.Bounds;
  
  import javax.vecmath.Tuple3d;
  
  import java.io.Serializable;
  import static abfab3d.core.Output.printf;
  
  /**
   * Base class implementation of Grids.  Includes common code that
   * may get overwritten by faster implementations.
   * <p/>
   * Likely better performance for memory access that is not slice aligned.
   * <p/>
   * Uses the X3D coordinate system.  Y-up.  Grid is located
   * on positive right side octant.
   *
   * @author Alan Hudson
   */
  public abstract class BaseGrid2D implements Grid2D, Cloneable, Serializable {
  
      protected static final boolean DEBUG = false;
      protected static final boolean STATS = false;
  
      /**
       * The width of the grid
       */
      protected int width;
  
      /**
       * The depth of the grid
       */
      protected int height;
  
      /**
       * The voxel size
       */
      protected double pixelSize;
  
      /**
       * Half the horizontal size
       */
      protected double hpixelSize;
  
      /**
       * location of the grid corner
       */
      protected double xorig = 0.;
      protected double yorig = 0.;
      protected double zorig = 0.;  
  
      // attribute descriptor used for this grid
      protected GridDataDesc m_gridDataDesc = GridDataDesc.getDefaultAttributeDesc(8);
  
      /**
       * Constructor.
       *
       * @param w       The number of voxels in width
       * @param h       The number of voxels in depth
       * @param pixel   The size of the pixels
       */
      public BaseGrid2D(int w, int h, double pixel) {
          width = w;
          height = h;
          this.pixelSize = pixel;
          this.hpixelSize = pixelSize / 2.0;
  
          if (STATS) {
              System.out.println("WARNING:  BaseGrid started in STATS mode");
          }
      }
  
      /**
       * Constructor.
       *
       * @param bounds the bounds of the grid
       * @param pixel The size of the pixels
       */
      public BaseGrid2D(Bounds bounds, double pixel) {
          
          this.width = bounds.getWidthVoxels(pixel);
          this.height = bounds.getHeightVoxels(pixel);
          this.pixelSize = pixel;
          this.hpixelSize = pixelSize / 2.0;
          this.xorig = bounds.xmin;
          this.yorig = bounds.ymin;
  
          if (STATS) {
              System.out.println("WARNING:  BaseGrid started in STATS mode");
          }
      }
  
  
  
      /**
       * Get the grid bounds in world coordinates.
       */
      public Bounds getGridBounds() {
  
          Bounds bounds = new Bounds(xorig, xorig + width * pixelSize,
                                     yorig, yorig + height * pixelSize,
                                     zorig, zorig + pixelSize, pixelSize);
          return bounds;
      }
  
      /**
       * Set the grid bounds in world coordinates.
       *
       * @param bounds grid bounds 
       */
      public void setGridBounds(Bounds bounds) {
  
          if(DEBUG)printf("setGridBounds(%s)\n", bounds);
  
          xorig = bounds.xmin;
          yorig = bounds.ymin;
          zorig = bounds.zmin;
          pixelSize = (bounds.xmax - bounds.xmin) / width;
  
          if(DEBUG)printf("getGridBounds() returns: %s\n", getGridBounds());
      }
  
      /**
       * Set the grid bounds in world coordinates.
       *
       * @param bounds array {xmin, xmax, zmin, ymax, zmin, zmax}
       */
      //public void setGridBounds(double[] bounds) {
      //    setGridBounds(new Bounds(bounds));
      //}
  
      /**
       * Determine if a voxel coordinate is inside the grid space.
       *
       * @param x The x coordinate
       * @param y The y coordinate
       * @return True if the coordinate is inside the grid space
       */
      public boolean insideGrid(int x, int y) {
          if (x >= 0 && x < width && y >= 0 && y < height ) {
  
              return true;
          }
  
          return false;
      }
  
      /**
       * Get the number of height cells.
       *
       * @return the val
       */
      public int getHeight() {
          return height;
      }
  
      /**
       * Get the number of width cells.
       *
       * @return the val
       */
      public int getWidth() {
          return width;
      }
  
      /**
       * Get the number of dots per meter.
       *
       * @return The value
       */
      public double getVoxelSize() {
          return pixelSize;
      }
  
      /**
       * Get the world coordinates of from the grid coordinates without half voxel shift 
       * 
       * @param x      The x value in grid coords
       * @param y      The y value in grid coords
       * @param coords The ans is placed into this preallocated array(2).
       */
      public void getWorldCoords(int x, int y, Tuple3d coords) {
  
          coords.x = x * pixelSize + hpixelSize + xorig;
          coords.y = y * pixelSize + hpixelSize + yorig;
  
      }
  
      /**
       * Get the grid coordinates for a world coordinate.
       *
       * @param x      The x value in world coords
       * @param y      The y value in world coords
       * @param coords The ans is placed into this preallocated array(2).
       */
      public void getGridCoords(double x, double y, Tuple3d coords) {
          coords.x = ((x - xorig) / pixelSize) - 0.5;
          coords.y = ((y - yorig) / pixelSize) - 0.5;
      }
  
  
  
      public abstract Object clone();
  
      /**
       assign to the grid a description of a voxel attributes
       @param description The attirbute description
       @override
       */
      public void setDataDesc(GridDataDesc description){
          m_gridDataDesc = description;
      }
  
      /**
       @return voxel attribute description assigned to the grid
       @override
       */
      public GridDataDesc getDataDesc(){
          return m_gridDataDesc;
      }
  
      /**
         copy grid bounds from srcGrid to this
       */
      public void copyBounds(Grid2D srcGrid){
  
          this.setGridBounds(srcGrid.getGridBounds());
  
      }
  
  }
  
  