/**
 * file KDTree2D.java
 */

package math.geom2d.point;


import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import math.geom2d.Box2D;
import math.geom2d.Point2D;
import math.geom2d.Vector2D;
import math.geom2d.line.StraightLine2D;


/**
 * A data structure for storing a great number of points. During construction
 * of the tree, median point in current coordinate is chosen for each step,
 * ensuring the final tree is balanced. The cost for retrieving a point is 
 * O(log n).
* The cost for building the tree is O(n log^2 n), that can take some time for * large points sets.
* This implementation is semi-dynamic: points can be added, but can not be * removed. * @author dlegland * */ public class KDTree2D { //TODO: make KDTree2D implements PointSet2D public class Node{ private Point2D point; private Node left; private Node right; public Node(Point2D point){ this.point = point; this.left = null; this.right = null; } public Node(Point2D point, Node left, Node right){ this.point = point; this.left = left; this.right = right; } public Point2D getPoint() { return point; } public Node getLeftChild() { return left; } public Node getRightChild() { return right; } public boolean isLeaf() { return left == null && right == null; } } private class XComparator implements Comparator { /* (non-Javadoc) * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ public int compare(Point2D p1, Point2D p2){ if (p1.x() < p2.x()) return -1; if (p1.x() > p2.x()) return +1; return Double.compare(p1.y(), p2.y()); } } private class YComparator implements Comparator { /* (non-Javadoc) * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ public int compare(Point2D p1, Point2D p2){ if(p1.y()p2.y()) return +1; return Double.compare(p1.x(), p2.x()); } } private Node root; private Comparator xComparator; private Comparator yComparator; public KDTree2D(ArrayList points) { this.xComparator = new XComparator(); this.yComparator = new YComparator(); root = makeTree(points, 0); } private Node makeTree(List points, int depth) { // Add a leaf if(points.size() == 0) return null; // select direction int dir = depth%2; // sort points according to i-th dimension if (dir == 0) { // Compare points based on their x-coordinate Collections.sort(points, xComparator); } else { // Compare points based on their x-coordinate Collections.sort(points, yComparator); } int n = points.size(); int med = n/2; // compute median return new Node( points.get(med), makeTree(points.subList(0, med), depth+1), makeTree(points.subList(med+1, n), depth+1)); } public Node getRoot() { return root; } public boolean contains(Point2D value){ return contains(value, root, 0); } private boolean contains(Point2D point, Node node, int depth){ if(node==null) return false; // select direction int dir = depth%2; // sort points according to i-th dimension int res; if(dir==0){ // Compare points based on their x-coordinate res = xComparator.compare(point, node.point); }else{ // Compare points based on their x-coordinate res = yComparator.compare(point, node.point); } if(res<0) return contains(point, node.left, depth+1); if(res>0) return contains(point, node.right, depth+1); return true; } public Node getNode(Point2D point) { return getNode(point, root, 0); } private Node getNode(Point2D point, Node node, int depth){ if(node==null) return null; // select direction int dir = depth%2; // sort points according to i-th dimension int res; if(dir==0){ // Compare points based on their x-coordinate res = xComparator.compare(point, node.point); }else{ // Compare points based on their x-coordinate res = yComparator.compare(point, node.point); } if(res<0) return getNode(point, node.left, depth+1); if(res>0) return getNode(point, node.right, depth+1); return node; } public void add(Point2D point){ add(point, root, 0); } private void add(Point2D point, Node node, int depth) { // select direction int dir = depth%2; // sort points according to i-th dimension int res; if(dir==0){ // Compare points based on their x-coordinate res = xComparator.compare(point, node.point); }else{ // Compare points based on their x-coordinate res = yComparator.compare(point, node.point); } if(res<0){ if(node.left==null) node.left = new Node(point); else add(point, node.left, depth+1); } if(res>0) if(node.right==null) node.right = new Node(point); else add(point, node.right, depth+1); } public Collection rangeSearch(Box2D range) { ArrayList points = new ArrayList(); rangeSearch(range, points, root, 0); return points; } /** * range search, by recursively adding points to the collection. */ private void rangeSearch(Box2D range, Collection points, Node node, int depth) { if(node==null) return; // extract the point Point2D point = node.getPoint(); double x = point.x(); double y = point.y(); // check if point is in range boolean tx1 = range.getMinX() points = new ArrayList(n); points.add(new Point2D(5, 5)); points.add(new Point2D(10, 10)); points.add(new Point2D(20, 20)); System.out.println("Check KDTree2D"); KDTree2D tree = new KDTree2D(points); System.out.println(tree.contains(new Point2D(5, 5))); System.out.println(tree.contains(new Point2D(6, 5))); } }

Ads help maintain this website.