Package org.neo4j.gis.spatial

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

/**
* 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 java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import junit.framework.AssertionFailedError;

import org.geotools.data.neo4j.StyledImageExporter;
import org.junit.Test;
import org.neo4j.gis.spatial.rtree.Envelope;
import org.neo4j.gis.spatial.pipes.GeoPipeFlow;
import org.neo4j.gis.spatial.pipes.GeoPipeline;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.CoordinateList;
import com.vividsolutions.jts.geom.Point;


public class TestSimplePointLayer extends Neo4jTestCase {

  private static final Coordinate testOrigin = new Coordinate(13.0, 55.6);

  @Test
  public void testNearestNeighborSearchOnEmptyLayer() {
    SpatialDatabaseService db = new SpatialDatabaseService(graphDb());
    EditableLayer layer = (EditableLayer) db.createSimplePointLayer("test", "Longitude", "Latitude");
    assertNotNull(layer);

        try (Transaction tx = graphDb().beginTx()) {
            // finds geometries around point
            List<SpatialDatabaseRecord> results = GeoPipeline.startNearestNeighborLatLonSearch(layer, new Coordinate(15.3, 56.2), 1.0)
                .toSpatialDatabaseRecordList();

            // should find no results
            assertEquals(0, results.size());
            tx.success();
        }
   
  }

  @Test
  public void testSimplePointLayer() {
    SpatialDatabaseService db = new SpatialDatabaseService(graphDb());
    EditableLayer layer = (EditableLayer) db.createSimplePointLayer("test", "Longitude", "Latitude");
    assertNotNull(layer);
    SpatialRecord record = layer.add(layer.getGeometryFactory().createPoint(new Coordinate(15.3, 56.2)));
    assertNotNull(record);

        try (Transaction tx = graphDb().beginTx()) {
            // finds geometries that contain the given geometry
            List<SpatialDatabaseRecord> results = GeoPipeline
                .startContainSearch(layer, layer.getGeometryFactory().toGeometry(new com.vividsolutions.jts.geom.Envelope(15.0, 16.0, 56.0, 57.0)))
                .toSpatialDatabaseRecordList();

            // should not be contained
            assertEquals(0, results.size());

            results = GeoPipeline
                .startWithinSearch(layer, layer.getGeometryFactory().toGeometry(new com.vividsolutions.jts.geom.Envelope(15.0, 16.0, 56.0, 57.0)))
                .toSpatialDatabaseRecordList();

            assertEquals(1, results.size());
            tx.success();
        }
  }

  @Test
  public void testNeoTextLayer() {
    SpatialDatabaseService db = new SpatialDatabaseService(graphDb());
    try (Transaction tx = graphDb().beginTx()) {
            SimplePointLayer layer = db.createSimplePointLayer("neo-text");
            assertNotNull(layer);
            assertNotNull("layer name is not null",layer.getName());
            for (Coordinate coordinate : makeCoordinateDataFromTextFile("NEO4J-SPATIAL.txt", testOrigin)) {
                SpatialRecord record = layer.add(coordinate);
                assertNotNull(record);
            }
            saveLayerAsImage(layer, 700, 70);

            Envelope bbox = layer.getIndex().getBoundingBox();
            double[] centre = bbox.centre();

            List<GeoPipeFlow> results = GeoPipeline
                .startNearestNeighborLatLonSearch(layer, new Coordinate(centre[0] + 0.1, centre[1]), 10.0)
                .sort("OrthodromicDistance").toList();

            saveResultsAsImage(results, "temporary-results-layer-" + layer.getName(), 130, 70);
            assertEquals(71, results.size());
            checkPointOrder(results);

            results = GeoPipeline
                .startNearestNeighborLatLonSearch(layer, new Coordinate(centre[0] + 0.1, centre[1]), 5.0)
                .sort("OrthodromicDistance").toList();

            saveResultsAsImage(results, "temporary-results-layer2-" + layer.getName(), 130, 70);
            assertEquals(30, results.size());
            checkPointOrder(results);

            // Now test the old API
            results = layer.findClosestPointsTo(new Coordinate(centre[0] + 0.1, centre[1]), 10.0);
            assertEquals(71, results.size());
            checkPointOrder(results);
            results = layer.findClosestPointsTo(new Coordinate(centre[0] + 0.1, centre[1]), 1000);
            assertEquals(265, results.size())// There are only 265 points in dataset
            checkPointOrder(results);
            results = layer.findClosestPointsTo(new Coordinate(centre[0] + 0.1, centre[1]), 100);
            assertEquals(100, results.size())// We expect an exact count from the layer method (but not from the pipeline)
            checkPointOrder(results);
            results = layer.findClosestPointsTo(new Coordinate(centre[0] + 0.1, centre[1]));
            assertEquals(100, results.size())// The default in SimplePointLayer is 100 results
            checkPointOrder(results);
            tx.success();
        }
   
  }

  @Test
  public void testIndexingExistingPointNodes() {
    GraphDatabaseService db = graphDb();
    SpatialDatabaseService sdb = new SpatialDatabaseService(db);
    SimplePointLayer layer = sdb.createSimplePointLayer("my-points", "x", "y");

    Coordinate[] coords = makeCoordinateDataFromTextFile("NEO4J-SPATIAL.txt", testOrigin);
    try (Transaction tx = db.beginTx()) {
      for (Coordinate coordinate : coords) {
        Node n = db.createNode();
        n.setProperty("x", coordinate.x);
        n.setProperty("y", coordinate.y);
        layer.add(n);
      }
      tx.success();
    }
        saveLayerAsImage(layer, 700, 70);

    assertEquals(coords.length, layer.getIndex().count());
  }
 
  @Test
  public void testIndexingExistingPointNodesWithMultipleLocations() {
    GraphDatabaseService db = graphDb();
    SpatialDatabaseService sdb = new SpatialDatabaseService(db);
    double x_offset = 0.15, y_offset = 0.15;
    SimplePointLayer layerA = sdb.createSimplePointLayer("my-points-A", "xa", "ya", "bbox_a");
    SimplePointLayer layerB = sdb.createSimplePointLayer("my-points-B", "xb", "yb", "bbox_b");

    Coordinate[] coords = makeCoordinateDataFromTextFile("NEO4J-SPATIAL.txt", testOrigin);
    try (Transaction tx = db.beginTx()) {
      for (Coordinate coordinate : coords) {
        Node n = db.createNode();
        n.setProperty("xa", coordinate.x);
        n.setProperty("ya", coordinate.y);
        n.setProperty("xb", coordinate.x + x_offset);
        n.setProperty("yb", coordinate.y + y_offset);

        layerA.add(n);
        layerB.add(n);

        tx.success();
      }
    }
    saveLayerAsImage(layerA, 700, 70);
    saveLayerAsImage(layerB, 700, 70);
    Envelope bboxA = layerA.getIndex().getBoundingBox();
    Envelope bboxB = layerB.getIndex().getBoundingBox();
    double[] centreA = bboxA.centre();
    double[] centreB = bboxB.centre();

    List<SpatialDatabaseRecord> resultsA;
    List<SpatialDatabaseRecord> resultsB;
    try (Transaction tx = db.beginTx()) {
      resultsA = GeoPipeline.startNearestNeighborLatLonSearch(layerA,
          new Coordinate(centreA[0] + 0.1, centreA[1]), 10.0).toSpatialDatabaseRecordList();
      resultsB = GeoPipeline.startNearestNeighborLatLonSearch(layerB,
          new Coordinate(centreB[0] + 0.1, centreB[1]), 10.0).toSpatialDatabaseRecordList();
      tx.success();
    }
    List<SpatialDatabaseRecord> results = new ArrayList<SpatialDatabaseRecord>();
    results.addAll(resultsA);
    results.addAll(resultsB);
        assertEquals(71, resultsA.size());
        assertEquals(71, resultsB.size());
        assertEquals(142, results.size());
    saveResultsAsImage(resultsA, "temporary-results-layer-" + layerA.getName(), 130, 70);
    saveResultsAsImage(resultsB, "temporary-results-layer-" + layerB.getName(), 130, 70);
    saveResultsAsImage(results, "temporary-results-layer-" + layerA.getName() + "-" + layerB.getName(), 200, 200);

    assertEquals(coords.length, layerA.getIndex().count());
    assertEquals(coords.length, layerB.getIndex().count());
  }

  private void checkPointOrder(List<GeoPipeFlow> results) {
    for (int i = 0; i < results.size() - 1; i++) {
      GeoPipeFlow first = results.get(i);
      GeoPipeFlow second = results.get(i + 1);
      double d1 = (Double) first.getProperties().get("OrthodromicDistance");
      double d2 = (Double) second.getProperties().get("OrthodromicDistance");
      assertTrue("Point at position " + i + " (d=" + d1 + ") must be closer than point at position " + (i + 1) + " (d=" + d2
          + ")", d1 <= d2);
    }
  }

  @Test
  public void testDensePointLayer() {
    SpatialDatabaseService db = new SpatialDatabaseService(graphDb());
        try (Transaction tx = graphDb().beginTx()) {
            SimplePointLayer layer = db.createSimplePointLayer("neo-dense", "lon", "lat");
            assertNotNull(layer);
            for (Coordinate coordinate : makeDensePointData()) {
                Point point = layer.getGeometryFactory().createPoint(coordinate);
                SpatialRecord record = layer.add(point);
                assertNotNull(record);
            }
            saveLayerAsImage(layer, 300, 300);

            Envelope bbox = layer.getIndex().getBoundingBox();
            double[] centre = bbox.centre();

            List<SpatialDatabaseRecord> results = GeoPipeline
                .startNearestNeighborLatLonSearch(layer, new Coordinate(centre[0], centre[1]), 10.0)
                .toSpatialDatabaseRecordList();
            saveResultsAsImage(results, "temporary-results-layer-" + layer.getName(), 150, 150);
            assertEquals(456, results.size());

            // Repeat with sorting
            results = GeoPipeline
                .startNearestNeighborLatLonSearch(layer, new Coordinate(centre[0], centre[1]), 10.0)
                .sort("OrthodromicDistance")
                .toSpatialDatabaseRecordList();
            saveResultsAsImage(results, "temporary-results-layer-sorted-" + layer.getName(), 150, 150);
            assertEquals(456, results.size());
            tx.success();
        }
  }

  private void saveLayerAsImage(Layer layer, int width, int height) {
    ShapefileExporter shpExporter = new ShapefileExporter(graphDb());
    shpExporter.setExportDir("target/export/SimplePointTests");
    StyledImageExporter imageExporter = new StyledImageExporter(graphDb());
    imageExporter.setExportDir("target/export/SimplePointTests");
    imageExporter.setZoom(0.9);
    imageExporter.setSize(width, height);
    try {
      imageExporter.saveLayerImage(layer.getName());
      shpExporter.exportLayer(layer.getName());
    } catch (Exception e) {
            e.printStackTrace();
      throw new AssertionFailedError("Failed to save layer '" + layer.getName() + "' as image: " + e.getMessage());
    }
  }

  private void saveResultsAsImage(List<? extends SpatialRecord> results, String layerName, int width, int height) { 
    ShapefileExporter shpExporter = new ShapefileExporter(graphDb());
    shpExporter.setExportDir("target/export/SimplePointTests");
    StyledImageExporter imageExporter = new StyledImageExporter(graphDb());
    imageExporter.setExportDir("target/export/SimplePointTests");
    imageExporter.setZoom(0.9);
    imageExporter.setSize(width, height);
    SpatialDatabaseService db = new SpatialDatabaseService(graphDb());
    EditableLayer tmpLayer = (EditableLayer) db.createSimplePointLayer(layerName, "lon", "lat");
    for (SpatialRecord record : results) {
      tmpLayer.add(record.getGeometry());
    }
    try {
      imageExporter.saveLayerImage(layerName);
      shpExporter.exportLayer(layerName);
    } catch (Exception e) {
      throw new AssertionFailedError("Failed to save results image: " + e.getMessage());
    }
  }

  @SuppressWarnings("unchecked")
  private static Coordinate[] makeCoordinateDataFromTextFile(String textFile, Coordinate origin) {
    CoordinateList data = new CoordinateList();
    try {
      BufferedReader reader = new BufferedReader(new FileReader("src/main/resources/"+textFile));
      String line;
      int row = 0;
      while ((line = reader.readLine()) != null) {
        int col = 0;
        for (String character : line.split("")) {
          if (col > 0 && !character.matches("\\s")) {
            Coordinate coordinate = new Coordinate(origin.x + (double) col / 100.0, origin.y - (double) row / 100.0);
            data.add(coordinate);
          }
          col++;
        }
        row++;
      }
    } catch (IOException e) {
      throw new AssertionFailedError("Input data for string test invalid: " + e.getMessage());
    }
    return data.toCoordinateArray();
  }

  @SuppressWarnings("unchecked")
  private static Coordinate[] makeDensePointData() {
    CoordinateList data = new CoordinateList();
    Coordinate origin = new Coordinate(13.0, 55.6);
    for (int row = 0; row < 40; row++) {
      for (int col = 0; col < 40; col++) {
        Coordinate coordinate = new Coordinate(origin.x + (double) col / 100.0, origin.y - (double) row / 100.0);
        data.add(coordinate);
      }
    }
    return data.toCoordinateArray();
  }

}
TOP

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

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.