/* * Geotoolkit.org - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2010-2012, Open Source Geospatial Foundation (OSGeo) * (C) 2010-2012, Geomatys * * 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.geotoolkit.test; import java.awt.image.RenderedImage; import java.awt.geom.AffineTransform; import java.awt.geom.RectangularShape; import java.awt.geom.Rectangle2D; import javax.media.jai.iterator.RectIter; import javax.media.jai.iterator.RectIterFactory; import javax.measure.Unit; import org.opengis.coverage.Coverage; import org.opengis.parameter.ParameterValue; import org.opengis.parameter.ParameterValueGroup; import org.opengis.parameter.ParameterDescriptor; import org.opengis.parameter.GeneralParameterValue; import static org.geotoolkit.test.image.ImageTestBase.SAMPLE_TOLERANCE; /** * Assertion methods used by the Geotk project in addition of the JUnit, GeoAPI and SIS assertions. * * @author Martin Desruisseaux (Geomatys) */ public strictfp class Assert extends org.apache.sis.test.Assert { /** * For subclass constructor only. */ protected Assert() { } /** * Asserts that the given parameter values are equal to the expected ones within a * positive delta. Only the elements in the given descriptor are compared, and the * comparisons are done in the units declared in the descriptor. * * @param expected The expected parameter values. * @param actual The actual parameter values. * @param tolerance The tolerance threshold for comparison of numerical values. * * @since 3.19 */ public static void assertParameterEquals(final ParameterValueGroup expected, final ParameterValueGroup actual, final double tolerance) { for (final GeneralParameterValue candidate : expected.values()) { if (!(candidate instanceof ParameterValue<?>)) { throw new UnsupportedOperationException("Not yet implemented."); } final ParameterValue<?> value = (ParameterValue<?>) candidate; final ParameterDescriptor<?> descriptor = value.getDescriptor(); final String name = descriptor.getName().getCode(); final Unit<?> unit = descriptor.getUnit(); final Class<?> valueClass = descriptor.getValueClass(); final ParameterValue<?> e = expected.parameter(name); final ParameterValue<?> a = actual .parameter(name); if (unit != null) { final double f = e.doubleValue(unit); assertEquals(name, f, a.doubleValue(unit), tolerance); } else if (valueClass == Float.class || valueClass == Double.class) { final double f = e.doubleValue(); assertEquals(name, f, a.doubleValue(), tolerance); } else { assertEquals(name, e.getValue(), a.getValue()); } } } /** * Compares two affine transforms for equality. * * @param expected The expected affine transform. * @param actual The actual affine transform. */ public static void assertTransformEquals(final AffineTransform expected, final AffineTransform actual) { assertEquals("scaleX", expected.getScaleX(), actual.getScaleX(), SAMPLE_TOLERANCE); assertEquals("scaleY", expected.getScaleY(), actual.getScaleY(), SAMPLE_TOLERANCE); assertEquals("shearX", expected.getShearX(), actual.getShearX(), SAMPLE_TOLERANCE); assertEquals("shearY", expected.getShearY(), actual.getShearY(), SAMPLE_TOLERANCE); assertEquals("translateX", expected.getTranslateX(), actual.getTranslateX(), SAMPLE_TOLERANCE); assertEquals("translateY", expected.getTranslateY(), actual.getTranslateY(), SAMPLE_TOLERANCE); } /** * Asserts that two images have the same origin and the same size. * * @param expected The image having the expected size. * @param actual The image to compare with the expected one. */ public static void assertBoundEquals(final RenderedImage expected, final RenderedImage actual) { assertEquals("Min X", expected.getMinX(), actual.getMinX()); assertEquals("Min Y", expected.getMinY(), actual.getMinY()); assertEquals("Width", expected.getWidth(), actual.getWidth()); assertEquals("Height", expected.getHeight(), actual.getHeight()); } /** * Compares two rasters for equality. The sample values are compared with {@code float} * precision, because this is the format used by the majority of geophysics raster data. * <p> * This method does not test if {@linkplain #assertBoundEquals bounds are equal} (actually, * it ensures that the image are of the same size but doesn't check if the origin is the * same). It is user responsibility to invoke the above method if desired. * * @param expected The image containing the expected pixel values. * @param actual The image containing the actual pixel values. */ public static void assertRasterEquals(final RenderedImage expected, final RenderedImage actual) { final RectIter e = RectIterFactory.create(expected, null); final RectIter a = RectIterFactory.create(actual, null); if (!e.finishedLines()) do { assertFalse(a.finishedLines()); if (!e.finishedPixels()) do { assertFalse(a.finishedPixels()); if (!e.finishedBands()) do { assertFalse(a.finishedBands()); final float pe = e.getSampleFloat(); final float pa = a.getSampleFloat(); assertEquals(pe, pa, SAMPLE_TOLERANCE); a.nextBand(); } while (!e.nextBandDone()); assertTrue(a.finishedBands()); a.nextPixel(); a.startBands(); e.startBands(); } while (!e.nextPixelDone()); assertTrue(a.finishedPixels()); a.nextLine(); a.startPixels(); e.startPixels(); } while (!e.nextLineDone()); assertTrue(a.finishedLines()); } /** * Compares the rendered view of two coverages for equality. * * @param expected The coverage containing the expected pixel values. * @param actual The coverage containing the actual pixel values. */ public static void assertRasterEquals(final Coverage expected, final Coverage actual) { assertRasterEquals(expected.getRenderableImage(0,1).createDefaultRendering(), actual.getRenderableImage(0,1).createDefaultRendering()); } /** * Ensures that all sample values in every bands are either inside the given range, * or {@link Double#NaN}. * * @param minimum The lower bound of the range, inclusive. * @param maximum The upper bound of the range, inclusive. * @param image The image to test. * * @since 3.19 */ public static void assertSampleValuesInRange(final double minimum, final double maximum, final RenderedImage image) { final RectIter it = RectIterFactory.create(image, null); if (!it.finishedLines()) do { if (!it.finishedPixels()) do { if (!it.finishedBands()) do { final double value = it.getSampleDouble(); assertBetween("Sample value", minimum, maximum, value); } while (!it.nextBandDone()); it.startBands(); } while (!it.nextPixelDone()); it.startPixels(); } while (!it.nextLineDone()); } /** * Tests if the given {@code outer} shape contains the given {@code inner} rectangle. * This method will also verify class consistency by invoking the {@code intersects} * method, and by interchanging the arguments. This method can be used for testing * the {@code outer} implementation - it should not be needed for standard implementations. * * @param outer The shape which is expected to contains the given rectangle. * @param inner The rectangle which should be contained by the shape. * * @since 3.20 */ public static void assertContains(final RectangularShape outer, final Rectangle2D inner) { assertTrue("outer.contains(inner)", outer.contains (inner)); assertTrue("outer.intersects(inner)", outer.intersects(inner)); if (outer instanceof Rectangle2D) { assertTrue ("inner.intersects(outer)", inner.intersects((Rectangle2D) outer)); assertFalse("inner.contains(outer)", inner.contains ((Rectangle2D) outer)); } assertTrue("outer.contains(centerX, centerY)", outer.contains(inner.getCenterX(), inner.getCenterY())); } /** * Tests if the given {@code r1} shape is disjoint with the given {@code r2} rectangle. * This method will also verify class consistency by invoking the {@code contains} * method, and by interchanging the arguments. This method can be used for testing * the {@code r1} implementation - it should not be needed for standard implementations. * * @param r1 The first shape to test. * @param r2 The second rectangle to test. * * @since 3.20 */ public static void assertDisjoint(final RectangularShape r1, final Rectangle2D r2) { assertFalse("r1.intersects(r2)", r1.intersects(r2)); assertFalse("r1.contains(r2)", r1.contains(r2)); if (r1 instanceof Rectangle2D) { assertFalse("r2.intersects(r1)", r2.intersects((Rectangle2D) r1)); assertFalse("r2.contains(r1)", r2.contains ((Rectangle2D) r1)); } for (int i=0; i<9; i++) { final double x, y; switch (i % 3) { case 0: x = r2.getMinX(); break; case 1: x = r2.getCenterX(); break; case 2: x = r2.getMaxX(); break; default: throw new AssertionError(i); } switch (i / 3) { case 0: y = r2.getMinY(); break; case 1: y = r2.getCenterY(); break; case 2: y = r2.getMaxY(); break; default: throw new AssertionError(i); } assertFalse("r1.contains(" + x + ", " + y + ')', r1.contains(x, y)); } } }