/******************************************************************************* * Copyright (c) 2015 David Smiley * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License, Version 2.0 which * accompanies this distribution and is available at * http://www.apache.org/licenses/LICENSE-2.0.txt ******************************************************************************/ package org.locationtech.spatial4j.shape.impl; import com.carrotsearch.randomizedtesting.annotations.Repeat; import org.locationtech.spatial4j.context.SpatialContext; import org.locationtech.spatial4j.shape.RandomizedShapeTest; import org.locationtech.spatial4j.shape.Rectangle; import org.locationtech.spatial4j.shape.SpatialRelation; import org.junit.Test; import java.util.ArrayList; import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class BBoxCalculatorTest extends RandomizedShapeTest { public BBoxCalculatorTest() { super(SpatialContext.GEO); } // note: testing latitude would be so simple that's effectively the same code as the code to be tested. So I don't. @Test @Repeat(iterations = 100) public void testGeoLongitude() { BBoxCalculator calc = new BBoxCalculator(ctx); final int numShapes = randomIntBetween(1, 4);//inclusive List<Rectangle> rects = new ArrayList<>(numShapes); for (int i = 0; i < numShapes; i++) { Rectangle rect = randomRectangle(30);// divisible by rects.add(rect); calc.expandRange(rect); } Rectangle boundary = calc.getBoundary(); if (numShapes == 1) { assertEquals(rects.get(0), boundary); return; } // If the boundary is the world-bounds, check that it's right. if (boundary.getMinX() == -180 && boundary.getMaxX() == 180) { // each longitude should be present in at least one shape: for (int lon = -180; lon <= +180; lon++) { assertTrue(atLeastOneRectHasLon(rects, lon)); } return; } // Test that it contains all shapes: for (Rectangle rect : rects) { assertRelation(SpatialRelation.CONTAINS, boundary, rect); } // Test that the left & right are boundaries: assertTrue(atLeastOneRectHasLon(rects, boundary.getMinX())); assertFalse(atLeastOneRectHasLon(rects, normX(boundary.getMinX() - 0.5))); assertTrue(atLeastOneRectHasLon(rects, boundary.getMaxX())); assertFalse(atLeastOneRectHasLon(rects, normX(boundary.getMaxX() + 0.5))); // Test that this is the smallest enclosing boundary by ensuring the gap (opposite the bbox) is // the largest: if (boundary.getWidth() > 180) { // conversely if wider than 180 then no wider gap is possible double biggerGap = 360.0 - boundary.getWidth() + 0.5; for (Rectangle rect : rects) { // try to see if a bigger gap could lie to the right of this rect double gapRectLeft = rect.getMaxX() + 0.25; double gapRectRight = gapRectLeft + biggerGap; Rectangle testGap = makeNormRect(gapRectLeft, gapRectRight, -90, 90); boolean fits = true; for (Rectangle rect2 : rects) { if (rect2.relate(testGap).intersects()) { fits = false; break; } } assertFalse(fits);//should never fit because it's larger than the biggest gap } } } private boolean atLeastOneRectHasLon(List<Rectangle> rects, double lon) { for (Rectangle rect : rects) { if (rect.relateXRange(lon, lon).intersects()) { return true; } } return false; } }