Package org.geotools.geometry.iso.topograph2D

Source Code of org.geotools.geometry.iso.topograph2D.EdgeRing

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*   
*    (C) 2001-2006  Vivid Solutions
*    (C) 2001-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.geometry.iso.topograph2D;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.geotools.geometry.iso.coordinate.DirectPositionImpl;
import org.geotools.geometry.iso.coordinate.LineStringImpl;
import org.geotools.geometry.iso.coordinate.PointArrayImpl;
import org.geotools.geometry.iso.coordinate.PositionImpl;
import org.geotools.geometry.iso.primitive.CurveImpl;
import org.geotools.geometry.iso.primitive.RingImpl;
import org.geotools.geometry.iso.primitive.SurfaceBoundaryImpl;
import org.geotools.geometry.iso.primitive.SurfaceImpl;
import org.geotools.geometry.iso.util.Assert;
import org.geotools.geometry.iso.util.algorithm2D.CGAlgorithms;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.coordinate.Position;
import org.opengis.geometry.primitive.CurveSegment;
import org.opengis.geometry.primitive.OrientableCurve;
import org.opengis.geometry.primitive.Ring;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

/**
*
*
* @source $URL$
*/
public abstract class EdgeRing {

  protected DirectedEdge startDe; // the directed edge which starts the list

  // of edges for this EdgeRing

  private int maxNodeDegree = -1;

  private List edges = new ArrayList(); // the DirectedEdges making up this

  // EdgeRing

  private List pts = new ArrayList();

  private Label label = new Label(Location.NONE); // label stores the

  // locations of each
  // geometry on the face
  // surrounded by this ring

  // private LinearRing ring; // the ring created for this EdgeRing
  private Ring ring; // the ring created for this EdgeRing

  private boolean isHole;

  // if non-null, the ring is a hole and this EdgeRing is its containing shell
  private EdgeRing shell;

  // a list of EdgeRings which are holes in this EdgeRing
  private ArrayList holes = new ArrayList();

  //protected FeatGeomFactoryImpl mFeatGeomFactory;
  protected CoordinateReferenceSystem crs;

  protected CGAlgorithms cga;

  public EdgeRing(DirectedEdge start, CoordinateReferenceSystem crs,
      CGAlgorithms cga) {
    this.crs = crs;
    this.cga = cga;
    this.computePoints(start);
    // Ring is now computed (and stored) only when first asked for in the getter method.
    // This change fixed a bug where building up a polygon with holes that touch the
    // outer ring cause a "non-simple" error to occur before the maximaledgerings can
    // be changed to minimaledgerings. isHole still needs to be computed now though.
    //this.computeRing();
   
    // build list of direct positions and calculate hole
    List<DirectPosition> dpList = new LinkedList<DirectPosition>();

    for (int i = 0; i < this.pts.size(); i++) {
      double[] doubleCoords = ((Coordinate) this.pts.get(i))
          .getCoordinates();
      DirectPositionImpl dp = new DirectPositionImpl(crs, doubleCoords);
      dpList.add(dp);
    }
   
    // See if the Ring is counterclockwise oriented
    this.isHole = this.cga.isCCW(dpList);   
  }

  abstract public DirectedEdge getNext(DirectedEdge de);

  abstract public void setEdgeRing(DirectedEdge de, EdgeRing er);

  public boolean isIsolated() {
    return (label.getGeometryCount() == 1);
  }

  public boolean isHole() {
    // computePoints();
    return isHole;
  }

  public Coordinate getCoordinate(int i) {
    return (Coordinate) pts.get(i);
  }

  // If the ring obj is already computed, return it.  Otherwise, compute the ring and
  // store it for next time.
  public Ring getRing() {
    this.computeRing();
    return this.ring;
  }

  public Label getLabel() {
    return this.label;
  }

  public boolean isShell() {
    return this.shell == null;
  }

  public EdgeRing getShell() {
    return this.shell;
  }

  public void setShell(EdgeRing shell) {
    this.shell = shell;
    if (shell != null)
      shell.addHole(this);
  }

  public void addHole(EdgeRing ring) {
    this.holes.add(ring);
  }

  /**
   * Creates a Surface based on the given ring and holes
   *
   * @return the created Surface
   */
  // TODO don´t need the geomfactory parameter because it owns this parameter
  // as member variable
  public SurfaceImpl toPolygon() {

    List<Ring> interiorRings = new ArrayList<Ring>();

    for (int i = 0; i < holes.size(); i++) {
      interiorRings.add(((EdgeRing) holes.get(i)).getRing());
    }
   
    SurfaceBoundaryImpl surfaceBoundary = new SurfaceBoundaryImpl(crs,
        this.getRing(), interiorRings);
      //aGeometryFactory.getPrimitiveFactory().createSurfaceBoundary(this.getRing(),interiorRings);

    return new SurfaceImpl(surfaceBoundary); //aGeometryFactory.getPrimitiveFactory().createSurface(surfaceBoundary);
  }

  /**
   * Compute a Ring from the point list previously collected. Test if the ring
   * is a hole (i.e. if it is CCW) and set the hole flag accordingly.
   */
  private void computeRing() {
    if (this.ring != null)
      return; // don't compute more than once

    // OLD CODE:
    // Coordinate[] coord = new Coordinate[pts.size()];
    // for (int i = 0; i < pts.size(); i++) {
    // coord[i] = (Coordinate) pts.get(i);
    // }

    //Coordinate[] coord = new Coordinate[this.pts.size()];
    List<Position> dpList = new LinkedList<Position>();

    for (int i = 0; i < this.pts.size(); i++) {
      double[] doubleCoords = ((Coordinate) this.pts.get(i))
          .getCoordinates();
      Position dp = new PositionImpl( new DirectPositionImpl(crs, doubleCoords) );
      dpList.add(dp);
    }
   
    // Create List of CurveSegment´s (LineString´s)
    LineStringImpl lineString = new LineStringImpl(new PointArrayImpl(
        dpList), 0.0);
    List<CurveSegment> segments = new ArrayList<CurveSegment>();
    segments.add(lineString);
   
    // Create List of OrientableCurve´s (Curve´s)
    OrientableCurve curve = new CurveImpl(crs, segments);
    List<OrientableCurve> orientableCurves = new ArrayList<OrientableCurve>();
    orientableCurves.add(curve);

    this.ring = new RingImpl(orientableCurves);   
    // this.ring = (RingImpl) this.mFeatGeomFactory.getPrimitiveFactory().createRingByDirectPositions(dpList);
   
    // isHole is now calculated in the constructor.
    /*
    // See if the Ring is counterclockwise oriented
    this.isHole = this.cga.isCCW(CoordinateArrays
        .toCoordinateArray(this.ring.asDirectPositions()));
    */

    // Debug.println( (isHole ? "hole - " : "shell - ") +
    // WKTWriter.toLineString(new
    // CoordinateArraySequence(ring.getCoordinates())));
  }

  /**
   * Returns the list of DirectedEdges that make up this EdgeRing
   */
  public List getEdges() {
    return edges;
  }

  /**
   * Collect all the points from the DirectedEdges of this ring into a
   * contiguous list
   */
  protected void computePoints(DirectedEdge start) {
    // System.out.println("buildRing");
    startDe = start;
    DirectedEdge de = start;
    boolean isFirstEdge = true;
    do {
      Assert.isTrue(de != null, "found null Directed Edge");
      if (de.getEdgeRing() == this)
        throw new TopologyException(
            "Directed Edge visited twice during ring-building at "
                + de.getCoordinate());

      edges.add(de);
      // Debug.println(de);
      // Debug.println(de.getEdge());
      Label label = de.getLabel();
      Assert.isTrue(label.isArea());
      mergeLabel(label);
      addPoints(de.getEdge(), de.isForward(), isFirstEdge);
      isFirstEdge = false;
      setEdgeRing(de, this);
      de = getNext(de);
    } while (de != startDe);
  }

  public int getMaxNodeDegree() {
    if (maxNodeDegree < 0)
      computeMaxNodeDegree();
    return maxNodeDegree;
  }

  private void computeMaxNodeDegree() {
    maxNodeDegree = 0;
    DirectedEdge de = startDe;
    do {
      Node node = de.getNode();
      int degree = ((DirectedEdgeStar) node.getEdges())
          .getOutgoingDegree(this);
      if (degree > maxNodeDegree)
        maxNodeDegree = degree;
      de = getNext(de);
    } while (de != startDe);
    maxNodeDegree *= 2;
  }

  public void setInResult() {
    DirectedEdge de = startDe;
    do {
      de.getEdge().setInResult(true);
      de = de.getNext();
    } while (de != startDe);
  }

  protected void mergeLabel(Label deLabel) {
    mergeLabel(deLabel, 0);
    mergeLabel(deLabel, 1);
  }

  /**
   * Merge the RHS label from a DirectedEdge into the label for this EdgeRing.
   * The DirectedEdge label may be null. This is acceptable - it results from
   * a node which is NOT an intersection node between the Geometries (e.g. the
   * end node of a LinearRing). In this case the DirectedEdge label does not
   * contribute any information to the overall labelling, and is simply
   * skipped.
   */
  protected void mergeLabel(Label deLabel, int geomIndex) {
    int loc = deLabel.getLocation(geomIndex, org.geotools.geometry.iso.topograph2D.Position.RIGHT);
    // no information to be had from this label
    if (loc == Location.NONE)
      return;
    // if there is no current RHS value, set it
    if (label.getLocation(geomIndex) == Location.NONE) {
      label.setLocation(geomIndex, loc);
      return;
    }
  }

  protected void addPoints(Edge edge, boolean isForward, boolean isFirstEdge) {
    Coordinate[] edgePts = edge.getCoordinates();
    if (isForward) {
      int startIndex = 1;
      if (isFirstEdge)
        startIndex = 0;
      for (int i = startIndex; i < edgePts.length; i++) {
        pts.add(edgePts[i]);
      }
    } else { // is backward
      int startIndex = edgePts.length - 2;
      if (isFirstEdge)
        startIndex = edgePts.length - 1;
      for (int i = startIndex; i >= 0; i--) {
        pts.add(edgePts[i]);
      }
    }
  }

  /**
   * This method will cause the ring to be computed. It will also check any
   * holes, if they have been assigned.
   */
  public boolean containsPoint(Coordinate p) {
    Ring shell = this.getRing();

    // TODO: auskommentiert; anpassen!
    // Envelope env = shell.getEnvelopeInternal();
    // if (!env.contains(p))
    // return false;
    // if (!this.cga.isPointInRing(p, shell.getCoordinates()))
    // return false;
    //
    // for (Iterator i = this.holes.iterator(); i.hasNext();) {
    // EdgeRing hole = (EdgeRing) i.next();
    // if (hole.containsPoint(p))
    // return false;
    // }
    // return true;
    return true;
  }

}
TOP

Related Classes of org.geotools.geometry.iso.topograph2D.EdgeRing

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.