/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2006-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.coordinate;
import java.util.List;
import org.geotools.geometry.iso.primitive.SurfaceBoundaryImpl;
import org.geotools.geometry.iso.primitive.SurfaceImpl;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.Envelope;
import org.opengis.geometry.coordinate.Polygon;
import org.opengis.geometry.coordinate.PolyhedralSurface;
/**
* @author Jackson Roehrig & Sanjay Jena
*
* A Polygon (Figure 21) is a surface patch that is defined by a set of boundary
* curves and an underlying surface to which these curves adhere. The default is
* that the curves are coplanar and the polygon uses planar interpolation in its
* interior.
*
* @source $URL$
*/
public class PolygonImpl extends SurfacePatchImpl implements Polygon {
/**
* The attribute "boundary" stores the SurfaceBoundary that is the boundary
* of this Polygon.
*
* Polygon::boundary : SurfaceBoundary
*
* NOTE The boundary of a surface patch need not be in the same Complex as
* the containing Surface. The curves that are contained in the interior of
* the Surface (act as common boundary to 2 surface patches) are not part of
* any Complex in which the Surface is contained. They are purely
* constructive and would not play in any topological relation between
* Surface and Curve that defines the connectivity of the Complex.
*
* IMPLEMENTATION ANNOTATION: The boundary will be realised and stored
* within the super class SurfacePatch
*/
/**
* The optional spanning surface provides a mechanism for spanning the
* interior of the polygon.
*
* Polygon::spanningSurface [0,1] : Surface
*
* NOTE The spanning surface should have no boundary components that
* intersect the boundary of the polygon, and there should be no ambiguity
* as to which portion of the surface is described by the bounding curves
* for the polygon. The most common spanning surface is an elevation model,
* which is not directly described in this standard, although Tins and
* gridded surfaces are often used in this role.
*/
// Spanning surface of the Polygon
private SurfaceImpl spanningSurface = null;
// Envelope of the Polygon
private EnvelopeImpl envelope = null;
// Array of Neighbours of the Polygon
//private SurfacePatchImpl m_neighbours[] = null;
/**
* Constructor This first variant of a constructor of Polygon creates a
* Polygon directly from a set of boundary curves (organized into a
* SurfaceBoundary) which shall be defined using coplanar Positions as
* controlPoints. Polygon::Polygon(boundary : SurfaceBondary) : Polygon
*
* NOTE The meaning of exterior in the SurfaceBoundary is consistent with
* the plane of the constructed planar polygon.
*
* @param boundary
*/
public PolygonImpl(SurfaceBoundaryImpl boundary) {
this(boundary, null);
}
/**
* This second variant of a constructor of Polygon creates a Polygon lying
* on a spanning surface. There is no restriction of the types of
* interpolation used by the composite curves used in the SurfaceBoundary,
* but they must all be lie on the "spanningSurface" for the process to
* succeed. Polygon(boundary : SurfaceBondary, spanSurf : Surface) : Polygon
*
* NOTE It is important that the boundary components be oriented properly
* for this to work. It is often the case that in bounded manifolds, such as
* the sphere, there is an ambiguity unless the orientation is properly
* used.
*
* @param boundary
* @param spanSurf -
* the Spanning Surface of the polygon
*/
public PolygonImpl(SurfaceBoundaryImpl boundary, SurfaceImpl spanSurf) {
// The Constructor will not except a boundary which is NULL; an
// exception will shall be thrown in the constructor of the super class
// SurfacePatch
// The boundary shall be build in lower classes like Triangle
/* Call super constructor to store boundary */
super(boundary);
/* Set Spanning Surface of the Polygon */
this.spanningSurface = spanSurf;
/* Create Envelope of the Polygon */
this.envelope = (EnvelopeImpl) this.createEnvelope();
}
/* (non-Javadoc)
* @see org.geotools.geometry.featgeom.coordinate.SurfacePatchImpl#getEnvelope()
*/
public Envelope getEnvelope() {
return this.envelope;
}
/**
* Creates the Envelope for the Polygon
*
* @return Envelope for the Polygon
*/
private Envelope createEnvelope() {
/* Return Envelope of the given Surface Patch Boundary */
return (this.getBoundary() != null) ? this.getBoundary().getEnvelope()
: null;
}
public PolyhedralSurface getSurface() {
return (PolyhedralSurface) super.getSurface();
}
// /**
// * This method returns the neighbours of the SurfacePatch within the
// relative Surface.
// * The order and number of the returned SurfacePatch Array depends from
// the type of SurfacePatch and has to be implemented individually.
// * This method can be useful for example for calculating the boundary of a
// surface, which is only defined by patches.
// * @return Ordered Array of neighbours of the SurfacePatch; NULL if
// neighbours not set
// */
// public SurfacePatchImpl[] getNeighbours() {
// return this.m_neighbours;
// }
// /**
// * Sets the neighbours of this SurfacePatch
// * @param neighbourPatches
// */
// public void setNeighbours(SurfacePatchImpl[] neighbourPatches) {
// this.m_neighbours = neighbourPatches;
// }
// /**
// * spanningSurface The optional spanning surface provides a mechanism for
// * spanning the interior of the polygon.
// *
// * Polygon::spanningSurface [0,1] : Surface
// *
// * NOTE The spanning surface should have no boundary components that
// * intersect the boundary of the polygon, and there should be no ambiguity
// * as to which portion of the surface is described by the bounding curves
// * for the polygon. The most common spanning surface is an elevation model,
// * which is not directly described in this standard, although Tins and
// * gridded surfaces are often used in this role.
// *
// * @return SurfaceImpl
// */
// public SurfaceImpl spanningSurface() {
// return this.spanningSurface;
// }
// /**
// * @return double
// */
// public double perimeter() {
// return this.getBoundary().getLength();
// }
/* (non-Javadoc)
* @see org.opengis.geometry.coordinate.Polygon#getSpanningSurface()
*/
public List getSpanningSurface() {
// TODO semantic JR, SJ
// TODO implementation
// TODO test
// TODO documentation
return null;
}
/* (non-Javadoc)
* @see org.opengis.geometry.coordinate.GenericSurface#getUpNormal(org.opengis.geometry.coordinate.DirectPosition)
*/
public double[] getUpNormal(DirectPosition point) {
// TODO semantic JR, SJ
// TODO implementation
// TODO test
// TODO documentation
return null;
}
/* (non-Javadoc)
* @see org.opengis.geometry.coordinate.GenericSurface#getPerimeter()
*/
public double getPerimeter() {
// TODO semantic JR, SJ
// TODO implementation
// TODO test
// TODO documentation
return 0;
}
/* (non-Javadoc)
* @see org.opengis.geometry.coordinate.GenericSurface#getArea()
*/
public double getArea() {
// TODO semantic JR, SJ
// TODO implementation
// TODO test
// TODO documentation
return 0;
}
@Override
public int hashCode() {
final int PRIME = 31;
int result = 1;
result = PRIME * result + ((envelope == null) ? 0 : envelope.hashCode());
result = PRIME * result + ((spanningSurface == null) ? 0 : spanningSurface.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final PolygonImpl other = (PolygonImpl) obj;
if (envelope == null) {
if (other.envelope != null)
return false;
} else if (!envelope.equals(other.envelope))
return false;
if (spanningSurface == null) {
if (other.spanningSurface != null)
return false;
} else if (!spanningSurface.equals(other.spanningSurface))
return false;
return true;
}
}