/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-2011, 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.vector; import static org.junit.Assert.assertTrue; import java.awt.geom.Point2D; import org.geotools.coverage.grid.GridCoverage2D; import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.feature.DefaultFeatureCollection; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.referencing.crs.DefaultGeographicCRS; import org.junit.Test; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.util.ProgressListener; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.MultiPoint; import com.vividsolutions.jts.geom.impl.PackedCoordinateSequenceFactory; /** * @author Martin Davis - OpenGeo * */ public class HeatmapProcessTest { /** * A test of a simple surface, validating that the process * can be invoked and return a reasonable result in a simple situation. * * Test includes data which lies outside the heatmap buffer area, * to check that it is filtered correctly * (i.e. does not cause out-of-range errors, and does not affect generated surface). * * @throws Exception */ @Test public void testSimpleSurface() { ReferencedEnvelope bounds = new ReferencedEnvelope(0, 10, 0, 10, DefaultGeographicCRS.WGS84); Coordinate[] data = new Coordinate[] { new Coordinate(4, 4), new Coordinate(4, 6), // include a coordinate outside the heatmap buffer bounds, to ensure it is filtered correctly new Coordinate(100, 100) }; SimpleFeatureCollection fc = createPoints(data, bounds); ProgressListener monitor = null; HeatmapProcess process = new HeatmapProcess(); GridCoverage2D cov = process.execute(fc, // data 20, //radius null, // weightAttr 1, // pixelsPerCell bounds, // outputEnv 100, // outputWidth 100, // outputHeight monitor // monitor) ); // following tests are checking for an appropriate shape for the surface float center1 = coverageValue(cov, 4, 4); float center2 = coverageValue(cov, 4, 6); float midway = coverageValue(cov, 4, 5); float far = coverageValue(cov, 9, 9); // peaks are roughly equal float peakDiff = Math.abs(center1 - center2); assert(peakDiff < center1 / 10); // dip between peaks assertTrue(midway > center1 / 2); // surface is flat far away assertTrue(far < center1 / 1000); } private float coverageValue(GridCoverage2D cov, double x, double y) { float[] covVal = new float[1]; Point2D worldPos = new Point2D.Double(x, y); cov.evaluate(worldPos, covVal); return covVal[0]; } private SimpleFeatureCollection createPoints(Coordinate[] pts, ReferencedEnvelope bounds) { SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder(); tb.setName("data"); tb.setCRS(bounds.getCoordinateReferenceSystem()); tb.add("shape", MultiPoint.class); tb.add("value", Double.class); SimpleFeatureType type = tb.buildFeatureType(); SimpleFeatureBuilder fb = new SimpleFeatureBuilder(type); DefaultFeatureCollection fc = new DefaultFeatureCollection(); GeometryFactory factory = new GeometryFactory(new PackedCoordinateSequenceFactory()); for (Coordinate p : pts) { Geometry point = factory.createPoint(p); fb.add(point); fb.add(p.z); fc.add(fb.buildFeature(null)); } return fc; } }