Package org.neo4j.gis.spatial

Source Code of org.neo4j.gis.spatial.TestSpatialQueries

/**
* Copyright (c) 2010-2013 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.gis.spatial;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import org.junit.Test;
import org.neo4j.gis.spatial.pipes.GeoPipeline;

import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
import org.neo4j.graphdb.Transaction;

public class TestSpatialQueries extends Neo4jTestCase {

  /**
   * This test case is designed to capture the conditions described in the bug
   * report at https://github.com/neo4j/neo4j-spatial/issues/11. There are
   * three geometries, one pPoint and two LineStrings, one short and one long.
   * The short LineString is closer to the Point, but SearchClosest returns
   * the long LineString.
   *
   * @throws ParseException
   */
  @Test
  public void testSearchClosestWithShortLongLineStrings() throws ParseException {
    SpatialDatabaseService spatial = new SpatialDatabaseService(graphDb());
    EditableLayer layer = spatial.getOrCreateEditableLayer("test", "WKT");
    WKTReader wkt = new WKTReader(layer.getGeometryFactory());
    Geometry shortLineString = wkt.read("LINESTRING(16.3493032 48.199882,16.3479487 48.1997337)");
    Geometry longLineString = wkt
        .read("LINESTRING(16.3178388 48.1979135,16.3195494 48.1978011,16.3220815 48.197824,16.3259696 48.1978297,16.3281211 48.1975952,16.3312482 48.1968743,16.3327931 48.1965196,16.3354641 48.1959911,16.3384376 48.1959609,16.3395792 48.1960223,16.3458708 48.1970974,16.3477719 48.1975147,16.348008 48.1975665,16.3505572 48.1984533,16.3535613 48.1994545,16.3559474 48.2011765,16.3567056 48.2025723,16.3571261 48.2038308,16.3578393 48.205176)");
    Geometry point = wkt.read("POINT(16.348243 48.199678)");
    layer.add(shortLineString);
    layer.add(longLineString);

    // First calculate the distances explicitly
    Geometry closestGeom = null;
    double closestDistance = Double.MAX_VALUE;
    System.out.println("Calculating explicit distance to the point " + point + ":");
    for (Geometry geom : new Geometry[] { shortLineString, longLineString }) {
      double distance = point.distance(geom);
      System.out.println("\tDistance " + distance + " to " + geom);
      if (distance < closestDistance) {
        closestDistance = distance;
        closestGeom = geom;
      }
    }
    System.out.println("Found closest: " + closestGeom);
    System.out.println();

    // Now use the SearchClosest class to perform the search for the closest
    System.out.println("Searching for geometries close to " + point);
        GeoPipeline pipeline;
        try (Transaction tx = graphDb().beginTx()) {
            pipeline = GeoPipeline.startNearestNeighborSearch(layer, point.getCoordinate(), 100)
                    .sort("Distance")
                    .getMin("Distance");
            for (SpatialRecord result : pipeline) {
                System.out.println("\tGot search result: " + result);
                assertEquals("Did not find the closest", closestGeom.toString(), result.getGeometry().toString());
            }
            tx.success();
        }
        try (Transaction tx = graphDb().beginTx()) {
            // Repeat with an envelope
            Envelope env = new Envelope(point.getCoordinate().x, point.getCoordinate().x, point.getCoordinate().y, point.getCoordinate().y);
            env.expandToInclude(shortLineString.getEnvelopeInternal());
            env.expandToInclude(longLineString.getEnvelopeInternal());
            pipeline = GeoPipeline.startNearestNeighborSearch(layer, point.getCoordinate(), env)
                    .sort("Distance")
                    .getMin("Distance");
            System.out.println("Searching for geometries close to " + point + " within " + env);
            for (SpatialRecord result : pipeline) {
                System.out.println("\tGot search result: " + result);
                assertEquals("Did not find the closest", closestGeom.toString(), result.getGeometry().toString());
            }
            tx.success();
        }

        try (Transaction tx = graphDb().beginTx()) {
            // Repeat with a buffer big enough to work
            double buffer = 0.0001;
            pipeline = GeoPipeline.startNearestNeighborSearch(layer, point.getCoordinate(), buffer)
                    .sort("Distance")
                    .getMin("Distance");
            System.out.println("Searching for geometries close to " + point + " within buffer " + buffer);
            for (SpatialRecord result : pipeline) {
                System.out.println("\tGot search result: " + result);
                assertEquals("Did not find the closest", closestGeom.toString(), result.getGeometry().toString());
            }
            tx.success();
        }

    // Repeat with a buffer too small to work correctly
    //TODO: Since the new Envelope class in graph-collections seems to not have the same bug as the old JTS Envelope, this test case no longer works. We should think of a new test case.
//    buffer = 0.00001;
//    closest = new SearchClosest(point, buffer);
//    System.out.println("Searching for geometries close to " + point + " within buffer " + buffer);
//    layer.getIndex().executeSearch(closest);
//    for (SpatialDatabaseRecord result : closest.getExtendedResults()) {
//      System.out.println("\tGot search result: " + result);
//      // NOTE the test below is negative, because the buffer was badly chosen
//      assertThat("Unexpectedly found the closest", result.getGeometry().toString(), is(not(closestGeom.toString())));
//    }

    // Repeat with the new limit API
        try (Transaction tx = graphDb().beginTx()) {

            int limit = 10;
            pipeline = GeoPipeline.startNearestNeighborSearch(layer, point.getCoordinate(), limit)
                .sort("Distance")
                .getMin("Distance");
            System.out.println("Searching for geometries close to " + point + " within automatic window designed to get about " + limit + " geometries");
            for (SpatialRecord result : pipeline) {
                System.out.println("\tGot search result: " + result);
                assertThat("Did not find the closest", result.getGeometry().toString(), is(closestGeom.toString()));
            }
            tx.success();
        }
  }
}
TOP

Related Classes of org.neo4j.gis.spatial.TestSpatialQueries

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.