/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-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. * * Created on 28 July 2002, 16:03 */ package org.geotools.filter; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.MultiLineString; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Polygon; /** * * @author James * @source $URL$ */ public class AreaFunction extends FunctionExpressionImpl{ /** Creates a new instance of AreaFunction */ public AreaFunction() { super("Area"); } public Object evaluate(Object feature) { org.opengis.filter.expression.Expression geom; geom = (org.opengis.filter.expression.Expression)getParameters().get(0); Geometry g = (Geometry)geom.evaluate(feature); return new Double( getArea( g )); } public int getArgCount() { return 1; } /** * Returns the area of a GeometryCollection. * * @param geometryCollection1 The GeometryCollection for which the * area is calulated. * @return The total area of all geometries in the collection. */ protected double getArea(GeometryCollection geometryCollection1) { double area = 0.0d; //double perimeter = 0.0d; int numberOfGeometries1 = geometryCollection1.getNumGeometries(); // Go through geometryCollection1 and sum areas of component geometries for (int i = 0; i < numberOfGeometries1; i++) { area += getArea(geometryCollection1.getGeometryN(i)); } return area; } /** * Returns. * @param geometryCollection The GeometryCollection for which the * perimeter is calulated. * @return the perimeter of a GeometryCollection. */ protected double getPerimeter(GeometryCollection geometryCollection) { double perimeter = 0.0d; int numberOfGeometries = geometryCollection.getNumGeometries(); // Go through geometryCollection and sum perimeters of component // geometries for (int i = 0; i < numberOfGeometries; i++) { perimeter += getPerimeter(geometryCollection.getGeometryN(i)); } return perimeter; } /** * Calculates and returns the area of the specified geometry.
* For Polygons, this is the total area inside the external ring less * the total of any contained by interior rings. GeometryCollections * (including MultiPolygons) are iterated through so the result is the * sum of all polygons anywhere within the collection. * Any geometry other than Polgyon or a collection returns 0; * * @param geometry The Geometry to calculate the area of. * @return The total area of the Geometry. */ public double getArea(Geometry geometry) { double area = 0.0d; if (geometry instanceof GeometryCollection) { area += getArea((GeometryCollection) geometry); } else if (geometry instanceof MultiPolygon) { area += getArea((MultiPolygon) geometry); } else if (geometry instanceof Polygon) { area += getArea((Polygon) geometry); } else { area += 0.0d; } return area; } /** * Calculates and returns the perimeter of the specified geometry.
* For Polygons, this is the total length of the exterior ring and all * internal rings. For LineStrings the total line length is returned. * GeometryCollections are iterated through so the result is the * sum of all Polygon and Line geometries anywhere within the collection. * Any point geometries return a value of 0; * * @param geometry The Geometry to calculate the area of. * @return The total area of the Geometry. */ public double getPerimeter(Geometry geometry) { double perimeter = 0.0d; if (geometry instanceof GeometryCollection) { perimeter += getPerimeter((GeometryCollection) geometry); } else if (geometry instanceof MultiPolygon) { perimeter += getPerimeter((MultiPolygon) geometry); } else if (geometry instanceof Polygon) { perimeter += getPerimeter((Polygon) geometry); } else if (geometry instanceof MultiLineString) { perimeter += getPerimeter((MultiLineString) geometry); } else if (geometry instanceof LineString) { perimeter += getPerimeter((LineString) geometry); } else { perimeter += 0.0d; } return perimeter; } /** * Returns the area of a MultiPolygon. * @param multiPolygon the MultiPolygon for which the area is calculated. * @return Total area of all polygons in multiPolygon. */ protected double getArea(MultiPolygon multiPolygon) { double area = 0.0d; int numberOfGeometries = multiPolygon.getNumGeometries(); for (int i = 0; i < numberOfGeometries; i++) { area += getArea(multiPolygon.getGeometryN(i)); } return area; } /** * Returns the perimeter of a MultiPolygon. * @param multiPolygon the MultiPolygon for which the perimeter is * calculated. * @return Total perimeter of all polygons in the multiPolygon. */ protected double getperimeter(MultiPolygon multiPolygon) { double perimeter = 0.0d; int numberOfGeometries = multiPolygon.getNumGeometries(); for (int i = 0; i < numberOfGeometries; i++) { perimeter += getPerimeter(multiPolygon.getGeometryN(i)); } return perimeter; } /** * Returns the area of a Polygon. * @param polygon the Polygon for which the area is calculated. * @return The area of the polygon. */ protected double getArea(Polygon polygon) { double area = 0.0d; double interiorArea = 0.0d; Coordinate[] exteriorRingCoordinates = polygon.getExteriorRing().getCoordinates(); int numberOfExteriorRingCoordinates = exteriorRingCoordinates.length; // Calculate the boundingBox of polygon1 aligned with the axes x and y double minx = Double.POSITIVE_INFINITY; double maxx = Double.NEGATIVE_INFINITY; double miny = Double.POSITIVE_INFINITY; double maxy = Double.NEGATIVE_INFINITY; for (int i = 0; i < numberOfExteriorRingCoordinates; i++) { minx = Math.min(minx, exteriorRingCoordinates[i].x); maxx = Math.max(maxx, exteriorRingCoordinates[i].x); miny = Math.min(miny, exteriorRingCoordinates[i].y); maxy = Math.max(maxy, exteriorRingCoordinates[i].y); } // Calculate area of each trapezoid formed by dropping lines from // each pair of coordinates in exteriorRingCoordinates to the x-axis. // x[i]