/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2014, 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.process.spatialstatistics.transformation; import java.util.NoSuchElementException; import java.util.logging.Logger; import org.geotools.data.collection.ListFeatureCollection; import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.feature.collection.SubFeatureCollection; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.process.spatialstatistics.core.FeatureTypes; import org.geotools.util.logging.Logging; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.filter.Filter; import org.opengis.referencing.crs.CoordinateReferenceSystem; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.Point; /** * Windrose Anchor SimpleFeatureCollection Implementation * * @author Minpa Lee, MangoSystem * * @source $URL$ */ public class WindroseAnchorFeatureCollection extends GXTSimpleFeatureCollection { protected static final Logger LOGGER = Logging.getLogger(WindroseAnchorFeatureCollection.class); static final int SEG = 32; static String[] NORTH = { "E", "ENE", "NE", "NNE", "N", "NNW", "NW", "WNW", "W", "WSW", "SW", "SSW", "S", "SSE", "SE", "ESE" }; static String[] FIELDS = { "distance", "direction" }; private Point center; private double radius; private SimpleFeatureType schema; public WindroseAnchorFeatureCollection(SimpleFeatureCollection delegate, Point center) { super(delegate); ReferencedEnvelope bounds = delegate.getBounds(); double xF = Math.pow(bounds.getMaxX() - bounds.getMinX(), 2.0); double yF = Math.pow(bounds.getMaxY() - bounds.getMinY(), 2.0); this.radius = (Math.pow(xF + yF, 0.5)) / 1.98; this.center = center; if (center == null) { this.center = new GeometryFactory().createPoint(bounds.centre()); } // create schema CoordinateReferenceSystem crs = delegate.getSchema().getCoordinateReferenceSystem(); schema = FeatureTypes.getDefaultType("windrose_anchor", LineString.class, crs); schema = FeatureTypes.add(schema, FIELDS[0], Double.class, 38); schema = FeatureTypes.add(schema, FIELDS[1], String.class, 6); } @Override public SimpleFeatureIterator features() { return new WindroseAnchorFeatureIterator(getSchema(), center, radius); } @Override public SimpleFeatureType getSchema() { return schema; } @Override public SimpleFeatureCollection subCollection(Filter filter) { if (filter == Filter.INCLUDE) { return this; } return new SubFeatureCollection(this, filter); } @Override public ReferencedEnvelope getBounds() { return delegate.getBounds(); } @Override public int size() { return 21; } static class WindroseAnchorFeatureIterator implements SimpleFeatureIterator { private Point center; private double radius; private SimpleFeatureIterator iter; public WindroseAnchorFeatureIterator(SimpleFeatureType schema, Point center, double radius) { this.center = center; this.radius = radius; this.init(new SimpleFeatureBuilder(schema)); } private void init(SimpleFeatureBuilder builder) { ListFeatureCollection result = new ListFeatureCollection(builder.getFeatureType()); String typeName = builder.getFeatureType().getTypeName(); int featureID = 1; // create circle double radius_step = radius / 5; for (int index = 0; index < 5; index++) { double buffer_radius = radius_step * (index + 1); SimpleFeature feature = builder.buildFeature(buildID(typeName, featureID++)); feature.setDefaultGeometry(center.buffer(buffer_radius, SEG).getBoundary()); feature.setAttribute(FIELDS[0], buffer_radius); result.add(feature); } // create direction for (int index = 0; index < 16; index++) { double degree = 22.5 * index; SimpleFeature feature = builder.buildFeature(buildID(typeName, featureID++)); feature.setDefaultGeometry(createLine(center, Math.toRadians(degree), radius)); feature.setAttribute(FIELDS[1], NORTH[index]); result.add(feature); } this.iter = result.features(); } public void close() { this.iter.close(); } public boolean hasNext() { return this.iter.hasNext(); } public SimpleFeature next() throws NoSuchElementException { return this.iter.next(); } private Coordinate createPoint(Coordinate centroid, double radian, double radius) { double dx = Math.cos(radian) * radius; double dy = Math.sin(radian) * radius; return new Coordinate(centroid.x + dx, centroid.y + dy); } private Geometry createLine(Point centroid, double radian, double radius) { Coordinate[] coordinates = new Coordinate[2]; coordinates[0] = centroid.getCoordinate(); coordinates[1] = createPoint(coordinates[0], radian, radius); return centroid.getFactory().createLineString(coordinates); } } }