public boolean insert(Point2D p) { if (p.equals(value)) { return false; } if (onLeft(p)) { if (left == null) { final TreeNode treeNode = newNode(p, this); treeNode.rect = even ? new RectHV(rect.xmin(), rect.ymin(), value.x(), rect.ymax()) : new RectHV(rect.xmin(), rect.ymin(), rect.xmax(), value.y()); left = treeNode; return true; } else { return left.insert(p); } } else if (onRight(p)) { if (right == null) { TreeNode treeNode = newNode(p, this); treeNode.rect = even ? new RectHV(rect.xmin(), value.y(), rect.xmax(), rect.ymax()) : new RectHV(rect.xmin(), value.y(), rect.xmax(), rect.ymax()); right = treeNode; return true; } else { return right.insert(p); } } return false; }
private int compare(Point2D p, Point2D q, Orientation orientation) { if (orientation == Orientation.LR) { return Double.compare(p.x(), q.x()); } else { return Double.compare(p.y(), q.y()); } }
private boolean onTheRight(final Point2D point, final Point2D current, final boolean vertical) { if (vertical) { return point.x() >= current.x(); } else { return point.y() >= current.y(); } }
private double distanceToVertical(final Point2D p, final Point2D v, final boolean vertical) { if (vertical) { return Math.abs(p.x() - v.x()); } else { return Math.abs(p.y() - v.y()); } }
private void insert1(Point2D p) { if (contains(p)) return; boolean newAdded = false; if (root == null) { initRoot(p); } else { TreeNode curr = root; while (true) { if (TreeNode.slightlyEquals(p, curr.value)) { return; } if (curr.even) { if (p.x() <= curr.value.x()) { if (curr.left == null) { TreeNode left = newNode(p, curr); left.rect = new RectHV(curr.rect.xmin(), curr.rect.ymin(), curr.value.x(), curr.rect.ymax()); curr.left = left; break; } else { curr = curr.left; } } else { if (curr.right == null) { TreeNode right = newNode(p, curr); right.rect = new RectHV(curr.value.x(), curr.rect.ymin(), curr.rect.xmax(), curr.rect.ymax()); curr.right = right; break; } else { curr = curr.right; } } } else { if (p.y() < curr.value.y()) { if (curr.left == null) { TreeNode left = newNode(p, curr); left.rect = new RectHV(curr.rect.xmin(), curr.rect.ymin(), curr.rect.xmax(), curr.value.y()); curr.left = left; break; } else { curr = curr.left; } } else { if (curr.right == null) { TreeNode right = newNode(p, curr); right.rect = new RectHV(curr.rect.xmin(), curr.value.y(), curr.rect.xmax(), curr.rect.ymax()); curr.right = right; break; } else { curr = curr.right; } } } } } size++; }
private KdNode put( KdNode nd, Point2D p, int turn, double xmin, double ymin, double xmax, double ymax) { if (nd == null) { sz++; return new KdNode(p, null, null, new RectHV(xmin, ymin, xmax, ymax)); } // Neglect nodes that collides with one // Already in the tree double ndx = nd.point.x(); double ndy = nd.point.y(); if (nd.point.equals(p)) return nd; else if (turn == 0) { if (p.x() < ndx) { nd.left = put(nd.left, p, 1 - turn, xmin, ymin, Math.min(ndx, xmax), ymax); } else { nd.right = put(nd.right, p, 1 - turn, Math.max(ndx, xmin), ymin, xmax, ymax); } } else { if (p.y() < ndy) { nd.left = put(nd.left, p, 1 - turn, xmin, ymin, xmax, Math.min(ndy, ymax)); } else { nd.right = put(nd.right, p, 1 - turn, xmin, Math.max(ndy, ymin), xmax, ymax); } } return nd; }
private boolean onTheRight(final Point2D point, final RectHV rect, final boolean vertical) { if (vertical) { return rect.xmin() > point.x(); } else { return rect.ymin() > point.y(); } }
private boolean onTheLeft(final Point2D point, final RectHV rect, final boolean vertical) { if (vertical) { return rect.xmax() < point.x(); } else { return rect.ymax() < point.y(); } }
private boolean search(KdNode nd, Point2D p, int turn) { if (nd == null) return false; if (nd.point.equals(p)) { return true; } else if (turn == 0) { if (p.x() < nd.point.x()) return search(nd.left, p, 1 - turn); else return search(nd.right, p, 1 - turn); } else { if (p.y() < nd.point.y()) return search(nd.left, p, 1 - turn); else return search(nd.right, p, 1 - turn); } }
private Point2D find(KdNode nd, double curDist, Point2D target, int turn) { Point2D curClosest = null; if (nd == null) return curClosest; // Pruning if (nd.rect.distanceTo(target) > curDist) { return null; } if (nd.point.distanceTo(target) < curDist) { curClosest = nd.point; curDist = nd.point.distanceTo(target); } // Always search the plane that target is on according to // current node if ((turn == 0 && target.x() < nd.point.x()) || (turn == 1 && target.y() < nd.point.y())) { Point2D left = find(nd.left, curDist, target, 1 - turn); if (left != null && left.distanceTo(target) < curDist) { curClosest = left; curDist = left.distanceTo(target); } Point2D right = find(nd.right, curDist, target, 1 - turn); if (right != null && right.distanceTo(target) < curDist) { curClosest = right; curDist = right.distanceTo(target); } } else { Point2D right = find(nd.right, curDist, target, 1 - turn); if (right != null && right.distanceTo(target) < curDist) { curClosest = right; curDist = right.distanceTo(target); } Point2D left = find(nd.left, curDist, target, 1 - turn); if (left != null && left.distanceTo(target) < curDist) { curClosest = left; curDist = left.distanceTo(target); } } return curClosest; }
private Point2D findNearest( Node x, Point2D p, Point2D nearest, double minDist, Orientation orientation) { if (x == null) { return nearest; } Point2D closest = nearest; double closestDistance = minDist; double distance = x.p.distanceSquaredTo(p); if (distance < minDist) { closest = x.p; closestDistance = distance; } Node first, second; if (orientation == Orientation.LR) { if (p.x() < x.p.x()) { first = x.lb; second = x.rt; } else { first = x.rt; second = x.lb; } } else { if (p.y() < x.p.y()) { first = x.lb; second = x.rt; } else { first = x.rt; second = x.lb; } } Orientation nextOrientation = orientation.next(); if (first != null && first.rect.distanceSquaredTo(p) < closestDistance) { closest = findNearest(first, p, closest, closestDistance, nextOrientation); closestDistance = closest.distanceSquaredTo(p); } if (second != null && second.rect.distanceSquaredTo(p) < closestDistance) { closest = findNearest(second, p, closest, closestDistance, nextOrientation); } return closest; }
private Point2D get(final Node x, final Point2D key, final boolean vertical) { if (x == null) { return null; } if (x.key.equals(key)) { return x.key; } double cmp; if (vertical) { cmp = key.x() - x.key.x(); } else { cmp = key.y() - x.key.y(); } if (cmp <= 0) { return get(x.left, key, !vertical); } else { return get(x.right, key, !vertical); } }
private Node put(final Node x, final Point2D key, final boolean vertical) { if (x == null) { return new Node(key, 1); } double cmp; if (vertical) { cmp = key.x() - x.key.x(); } else { cmp = key.y() - x.key.y(); } if (key.equals(x.key)) { // do nothing } else if (cmp <= 0) { x.left = put(x.left, key, !vertical); x.N = 1 + size(x.left) + size(x.right); } else if (cmp > 0) { x.right = put(x.right, key, !vertical); x.N = 1 + size(x.left) + size(x.right); } return x; }
// draw all points to standard draw public void draw() { for (Point2D point2D : root.subSet(LOWER, HIGHER)) { StdDraw.point(point2D.x(), point2D.y()); } }
private boolean onRight(final Point2D p) { return (even && (p.x() > value.x())) || (!even && (p.y() > value.y())); }
private boolean onLeft(final Point2D p) { return (even && (p.x() <= value.x())) || (!even && (p.y() <= value.y())); }
private static boolean slightlyEquals(Point2D p1, Point2D p2) { return Math.abs(p1.x() - p2.x()) < 0.000001 && Math.abs(p1.y() - p2.y()) < 0.000001; }