/* * 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. */ package org.geotools.renderer.lite; import java.awt.Rectangle; import java.awt.geom.AffineTransform; import java.util.HashMap; import junit.framework.TestCase; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.referencing.CRS; import org.geotools.referencing.crs.DefaultEngineeringCRS; import org.geotools.referencing.crs.DefaultGeographicCRS; import org.geotools.resources.XMath; import org.opengis.referencing.crs.CoordinateReferenceSystem; import com.vividsolutions.jts.geom.Envelope; public class RenderUtilitiesTest extends TestCase { public void testScaleOutsideCrsDefinition() throws Exception { CoordinateReferenceSystem utm1N = CRS.decode("EPSG:32601"); ReferencedEnvelope re = new ReferencedEnvelope(new Envelope(0, 0, 100, 100), utm1N); try { RendererUtilities.calculateScale(re, 100, 100, 75); fail("Should have failed, envelope outside of the source crs validity area"); } catch (IllegalArgumentException e) { // ok } } public void testScaleProjected() throws Exception { CoordinateReferenceSystem utm1N = CRS.decode("EPSG:32601"); // valid coords for utm nord 1 start from (200000, 0) ReferencedEnvelope re = new ReferencedEnvelope(new Envelope(200000, 200100, 0, 100), utm1N); double scale = RendererUtilities.calculateScale(re, 100, 100, 2.54); assertEquals(100.0, scale, 0.1); // account for projection deformation } public void testScaleCartesian() throws Exception { ReferencedEnvelope re = new ReferencedEnvelope(new Envelope(0, 10, 0, 10), DefaultEngineeringCRS.CARTESIAN_2D); double scale = RendererUtilities.calculateScale(re, 10 * 100, 10 * 100, 2.54); assertEquals(1.0, scale, 0.00001); // no projection deformation here! } public void testScaleGeneric() throws Exception { ReferencedEnvelope re = new ReferencedEnvelope(new Envelope(0, 10, 0, 10), DefaultEngineeringCRS.GENERIC_2D); double scale = RendererUtilities.calculateScale(re, 10 * 100, 10 * 100, 2.54); assertEquals(1.0, scale, 0.00001); // no projection deformation here! } public void testOGCScaleProjected() throws Exception { ReferencedEnvelope re = new ReferencedEnvelope(new Envelope(0, 10, 0, 10), DefaultEngineeringCRS.CARTESIAN_2D); int tenMetersPixels = (int) Math.round(10 / 0.00028); double scale = RendererUtilities.calculateOGCScale(re, tenMetersPixels , new HashMap()); assertEquals(1.0, scale, 0.0001); } public void testOGCScaleGeographic() throws Exception { // same example as page 29 in the SLD OGC spec, but with the expected scale corrected // since the OGC document contains a very imprecise one ReferencedEnvelope re = new ReferencedEnvelope(new Envelope(0, 2, 0, 2), DefaultGeographicCRS.WGS84); double scale = RendererUtilities.calculateOGCScale(re, 600 , new HashMap()); assertEquals(1325232.03, scale, 0.01); } public void testOGCScaleAffineProjected() throws Exception { // 1 pixel == 500 m => 0.00028 m [ screen] == 500 m [world] // => scaleDenominator = 500/0.00028 final AffineTransform screenToWord = AffineTransform.getScaleInstance(500,500); final AffineTransform worldToScreen = screenToWord.createInverse(); final CoordinateReferenceSystem crs = DefaultEngineeringCRS.CARTESIAN_2D; double scale; scale = RendererUtilities.calculateOGCScaleAffine(crs, worldToScreen,new HashMap()); assertEquals(500/0.00028, scale, 0.0001); worldToScreen.rotate(1.0); scale = RendererUtilities.calculateOGCScaleAffine(crs, worldToScreen,new HashMap()); assertEquals(500/0.00028, scale, 0.0001); worldToScreen.translate(100.0,100.0); scale = RendererUtilities.calculateOGCScaleAffine(crs, worldToScreen,new HashMap()); assertEquals(500/0.00028, scale, 0.0001); } public void testOGCScaleAffineGeographic() throws Exception { // 1 pixel == 0.5 degree => 0.00028 m [ screen] == 0.5 degree * OGC_DEGREE_TO_METERS m [world] // => scaleDenominator = 0.5 * OGC_DEGREE_TO_METERS/0.00028 final AffineTransform screenToWord = AffineTransform.getScaleInstance(0.5,0.5); final AffineTransform worldToScreen = screenToWord.createInverse(); final CoordinateReferenceSystem crs = DefaultGeographicCRS.WGS84; double scale; scale = RendererUtilities.calculateOGCScaleAffine(crs, worldToScreen,new HashMap()); assertEquals(0.5*RendererUtilities.OGC_DEGREE_TO_METERS/0.00028, scale, 0.0001); worldToScreen.rotate(1.0); scale = RendererUtilities.calculateOGCScaleAffine(crs, worldToScreen,new HashMap()); assertEquals(0.5*RendererUtilities.OGC_DEGREE_TO_METERS/0.00028, scale, 0.0001); worldToScreen.translate(100.0,100.0); scale = RendererUtilities.calculateOGCScaleAffine(crs, worldToScreen,new HashMap()); assertEquals(0.5*RendererUtilities.OGC_DEGREE_TO_METERS/0.00028, scale, 0.0001); } public void testCreateMapEnvelope() throws Exception { final double offset = 10000; final Rectangle paintArea = new Rectangle(0,0,800,600); final AffineTransform worldToScreen = AffineTransform.getScaleInstance(0.5,0.5); worldToScreen.translate(-offset,-offset); AffineTransform at = new AffineTransform(worldToScreen); Envelope env = RendererUtilities.createMapEnvelope(paintArea, at); assertEnvelopeEquals(new Envelope(offset,offset+1600,offset,offset+1200),env,0.001); // Test for negative world coordinates at.translate(2*offset,2*offset); env = RendererUtilities.createMapEnvelope(paintArea, at); assertEnvelopeEquals(new Envelope(-offset,-offset+1600,-offset,-offset+1200),env,0.001); // Restore to standard offset at.translate(-2*offset,-2*offset); at.rotate(Math.PI/2.0,offset,offset); env = RendererUtilities.createMapEnvelope(paintArea, at); assertEnvelopeEquals(new Envelope(offset,offset+1200,offset-1600,offset),env,0.0001); at = new AffineTransform(worldToScreen); at.rotate(Math.PI/4.0,offset,offset); env = RendererUtilities.createMapEnvelope(paintArea, at); assertEnvelopeEquals(new Envelope( offset, offset+Math.cos(Math.PI/4.0)*1600 + Math.sin(Math.PI/4.0)*1200, offset-Math.sin(Math.PI/4.0)*1600, offset+Math.cos(Math.PI/4.0)*1200),env,0.0001); } private void assertEnvelopeEquals(Envelope expected, Envelope actual, double delta) { if (expected.equals(actual)) { return; } boolean equals = true; equals &= Math.abs(expected.getMinX() - actual.getMinX()) <= delta; equals &= Math.abs(expected.getMaxX() - actual.getMaxX()) <= delta; equals &= Math.abs(expected.getMinY() - actual.getMinY()) <= delta; equals &= Math.abs(expected.getMaxY() - actual.getMaxY()) <= delta; if (!equals) { failNotEquals(null,expected,actual); } } /** * The following test is from the tile module where the behavior * of RenderUtilities changed between 2.2. and 2.4. */ public void testCenterTile() throws Exception { Envelope centerTile = new Envelope( 0, 36, -18, 18 ); CoordinateReferenceSystem crs = DefaultGeographicCRS.WGS84; double scale = RendererUtilities.calculateScale(centerTile, crs, 512, 512, 72.0 ); double groundDistance = XMath.hypot( 36, 36) * (1852 * 60); double pixelDistance = XMath.hypot(512, 512) * (0.0254 / 72); double expected = groundDistance / pixelDistance; assertEquals(expected, scale, expected * 0.05); // no projection deformation here! } }