All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wikibrain.spatial.util.ClosestPointIndex Maven / Gradle / Ivy

The newest version!
package org.wikibrain.spatial.util;

import ags.utils.dataStructures.MaxHeap;
import ags.utils.dataStructures.trees.thirdGenKD.KdTree;
import ags.utils.dataStructures.trees.thirdGenKD.SquareEuclideanDistanceFunction;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;
import org.geotools.referencing.GeodeticCalculator;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Creates a spherical approximation of the closest points to a particular point.
 * This class is threadsafe for multiple readers or writers (but not both).
 *
 *
 * @author Shilad Sen
 */
public class ClosestPointIndex implements Serializable {
    private final KdTree index = new KdTree(3);

    public ClosestPointIndex() {}

    /**
     * Insert a geometry into the index and associate it with a particular id.
     * If the geometry is not a point, uses WikiBrainSpatialUtils.getCenter to
     * convert it to a single point.
     *
     * @param id
     * @param geometry
     */
    public void insert(int id, Geometry geometry) {
        Point p = WikiBrainSpatialUtils.getCenter(geometry);
        Result r = new Result(id, geometry, p);
        synchronized (index) {
            index.addPoint(WikiBrainSpatialUtils.get3DPoints(p), r);
        }
    }

    /**
     * Return the closest points to the specified point.
     * The returned distances are estimated using the Haversine formula.
     * @param query
     * @param maxNeighbors
     * @return
     */
    public List query(Geometry query, int maxNeighbors) {
        final Point c = WikiBrainSpatialUtils.getCenter(query);
        final double[] c1 = WikiBrainSpatialUtils.get3DPoints(c);
        MaxHeap heap = index.findNearestNeighbors(
                c1,
                maxNeighbors,
                new SquareEuclideanDistanceFunction());

        List results = new ArrayList();
        while (heap.size() > 0) {
            Result r = heap.getMax();
            heap.removeMax();
            double d = WikiBrainSpatialUtils.haversine(c, r.point);
            results.add(new Result(r.id, r.geometry, r.point, d));
        }
        Collections.reverse(results);

        return results;
    }

    public int size() {
        return index.size();
    }

    public static class Result implements Serializable {
        public final int id;
        public final Geometry geometry;
        public final Point point;
        public final double distance;

        public Result(int id, Geometry geometry, Point point) {
            this(id, geometry, point, -1);
        }

        public Result(int id, Geometry geometry, Point point, double distance) {
            this.id = id;
            this.geometry = geometry;
            this.point = point;
            this.distance = distance;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy