Package org.geotools.caching.grid.spatialindex

Source Code of org.geotools.caching.grid.spatialindex.GridRootNode

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2007-2008, Open Source Geospatial Foundation (OSGeo)
*
*    This library is free software; you can redistribute it and/or
*    modify it under the terms of the GNU Lesser General Public
*    License as published by the Free Software Foundation;
*    version 2.1 of the License.
*
*    This library is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*    Lesser General Public License for more details.
*/
package org.geotools.caching.grid.spatialindex;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.geotools.caching.spatialindex.AbstractSpatialIndex;
import org.geotools.caching.spatialindex.NodeIdentifier;
import org.geotools.caching.spatialindex.Region;
import org.geotools.caching.spatialindex.RegionNodeIdentifier;
import org.geotools.caching.spatialindex.Shape;

/**
* The root node of a grid, which has n GridNodes as children. As GridNodes do,
* it can store data too.
*
* @author Christophe Rousson, SoC 2007, CRG-ULAVAL
*
*
*
*
*
* @source $URL$
*/
public class GridRootNode extends GridNode {
  private static final long serialVersionUID = 4675163856302389522L;
  protected double tiles_size;

  protected int[] tiles_number;
  protected ArrayList<NodeIdentifier> children; // list of NodeIdentifiers
  protected int childrenCapacity = -1;

  /**
   * No-arg constructor for serialization purpose. Deserialized nodes must
   * call setIdentifier before using
   *
   */
  GridRootNode() {
    super();
  }

  /**
   * the mbr is read from the id;
   */
  protected GridRootNode(int gridsize, RegionNodeIdentifier id) {
    super(id);
    init(gridsize);
  }

  private void init(int gridsize) {
    int dims = getShape().getDimension();
    Region mbr = (Region) getShape();
    tiles_number = new int[dims];

    double area = 1;

    for (int i = 0; i < dims; i++) {
      area *= (mbr.getHigh(i) - mbr.getLow(i));
    }

    tiles_size = Math.pow(area / gridsize, 1d / dims);
    int newcapacity = 1;

    for (int i = 0; i < dims; i++) {
      int tmp;
      double dtmp = (mbr.getHigh(i) - mbr.getLow(i)) / tiles_size;
      tmp = (int) dtmp;

      if (tmp < dtmp) {
        tmp += 1;
      }

      tiles_number[i] = tmp;
      newcapacity *= tmp;
    }
    assert (newcapacity >= gridsize);
    // capacity = newcapacity;
    childrenCapacity = newcapacity;
    children = new ArrayList<NodeIdentifier>(childrenCapacity);
  }

  /**
   * Creates the grid by appending children to this node.
   *
   */
  protected void split(GridSpatialIndex index) {
    int dims = tiles_number.length;
    double[] pos = new double[dims];
    double[] nextpos = new double[dims];
    Region mbr = (Region) getShape();
    // int id = 0;

    for (int i = 0; i < dims; i++) {
      pos[i] = mbr.getLow(i);
      nextpos[i] = pos[i] + tiles_size;
    }

    do {
      Region reg = new Region(pos, nextpos);
      RegionNodeIdentifier id = (RegionNodeIdentifier) index
          .findUniqueInstance(new RegionNodeIdentifier(reg));
      GridNode child = createNode(id);
      index.writeNode(child);
      this.children.add(child.getIdentifier());
      // id++;
    } while (increment(pos, nextpos));
  }

  public List<Integer> getChildren(Shape shape) {
    Region mbr = (Region) getShape();
    Region childMBR = shape.getMBR();
    int dims = mbr.getDimension();
    int[] gridminindex = new int[dims];
    for (int i = 0; i < gridminindex.length; i++) {
      if (childMBR.getLow(i) <= mbr.getLow(i)) {
        gridminindex[i] = 0;
      } else {
        gridminindex[i] = (int) Math.floor((childMBR.getLow(i) - mbr.getLow(i))/ tiles_size);
      }
    }
    int[] gridmaxindex = new int[dims];
    for (int i = 0; i < gridminindex.length; i++) {
      if (childMBR.getHigh(i) >= mbr.getHigh(i)) {
        gridmaxindex[i] = tiles_number[i] - 1;
      } else {
        gridmaxindex[i] = (int) Math.floor((childMBR.getHigh(i) - mbr.getLow(i))/ tiles_size);
      }
    }

    // want to iterate from gridminindex to gridmaxindex
    int current[] = gridminindex.clone();
    return iterate(current, gridminindex, gridmaxindex, 0);

  }

  private List<Integer> iterate(int current[], int min[], int max[], int index) {
    ArrayList<Integer> values = new ArrayList<Integer>();
    if (index >= min.length) {
      return Collections.singletonList(new Integer(this.gridIndexToNodeId(current)));
    }
    for (int i = min[index]; i <= max[index]; i++) {
      current[index] = i;
      values.addAll(iterate(current, min, max, index + 1));
    }
    return values;

  }

  protected GridNode createNode(RegionNodeIdentifier id) {
    // return new GridNode(grid, reg);
    return new GridNode(id);
  }

  /**
   * Computes sequentially the corner position of each tile in the grid.
   *
   * @param pos
   * @param nextpos
   * @return false if the upperright corner of the grid has been reached, true
   *         otherwise
   */
  boolean increment(double[] pos, double[] nextpos) {
    Region mbr = (Region) getShape();
    int dims = pos.length;

    if ((dims != tiles_number.length)
        || (nextpos.length != tiles_number.length)) {
      throw new IllegalArgumentException(
          "Cursor has not the same dimension as grid.");
    }

    for (int i = 0; i < dims; i++) {
      if (((nextpos[i] - mbr.getHigh(i)) > 0)
          || (Math.abs(nextpos[i] - mbr.getHigh(i)) < AbstractSpatialIndex.EPSILON)) {
        pos[i] = mbr.getLow(i);
        nextpos[i] = pos[i] + tiles_size;

        if (i == (dims - 1)) {
          return false;
        }
      } else {
        pos[i] = nextpos[i];
        nextpos[i] = pos[i] + tiles_size;

        break;
      }
    }

    return true;
  }

  public String toString() {
    StringBuffer sb = new StringBuffer();
    // sb.append("GridRootNode: capacity:" + capacity + ", MBR:" + mbr);
    sb.append("GridRootNode: MBR: " + this.getShape() + ", capacity: "
        + getCapacity());

    return sb.toString();
  }

  public NodeIdentifier getChildIdentifier(int index)
      throws IndexOutOfBoundsException {
    return (NodeIdentifier) children.get(index);
  }

  public void setChildIdentifier(int index, NodeIdentifier id) {
    children.set(index, id);
  }

  public int getChildrenCount() {
    return children.size();
  }

  public int getLevel() {
    return 1;
  }

  public boolean isIndex() {
    if (children.isEmpty()) {
      return false;
    } else {
      return true;
    }
  }

  public boolean isLeaf() {
    return !isIndex();
  }

  /**
   * Converts an array of indexes into the id of a node.
   *
   * @param index
   * @return
   */
  public int gridIndexToNodeId(int[] index) {
    if (index.length != tiles_number.length) {
      throw new IllegalArgumentException("Argument has " + index.length
          + " dimensions whereas grid has " + tiles_number.length);
    } else {
      int result = 0;
      int offset = 1;

      for (int i = 0; i < index.length; i++) {
        result += (offset * index[i]);
        offset *= tiles_number[i];
      }

      return result;
    }
  }

  /**
   * Only clears data the root node; does not clear the children.
   */
  public void clear() {
    super.clear();
  }

  public String toReadableText() {
    StringBuffer sb = new StringBuffer();
    sb.append("RootNode *****");
    sb.append(super.toReadableText());

    return sb.toString();
  }

  /**
   * The maximum of allowable nodes in the grid.
   *
   * @return
   */
  public int getCapacity() {
    return this.childrenCapacity;
  }

  /**
   * The number of tiles/nodes in a given dimension.
   *
   * @param dim
   * @return
   */
  public int getMaximumTileCount(int dim) {
    if (dim < 0 || dim > tiles_number.length) {
      return -1;
    }
    return tiles_number[dim];
  }

  /**
   * @returns the size of the children tiles
   */
  public double getTileSize() {
    return this.tiles_size;
  }
 
//  public void printGrid(){
//    System.out.println(makePolygon((Region)this.getShape()));
//   
//    for(int i = 0; i < getChildrenCount(); i ++){
//      NodeIdentifier id = this.getChildIdentifier(i);
//      System.out.println(makePolygon((Region)id.getShape()));
//    }
//  }
// 
//  public String makePolygon(Region r){
//    double minx = r.getLow(0);
//    double maxx = r.getHigh(0);
//    double miny = r.getLow(1);
//    double maxy = r.getHigh(1);
//    return "POLYGON(( " + minx + " " + miny + ", " + minx  + " " + maxy  + "," + maxx + " " + maxy + "," + maxx + " " + miny + "," + minx + " " + miny + "))";
//  }
}
TOP

Related Classes of org.geotools.caching.grid.spatialindex.GridRootNode

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.