예제 #1
0
 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++;
 }
예제 #2
0
  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;
  }
예제 #3
0
 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;
 }
예제 #4
0
파일: KdTree.java 프로젝트: desperius/algs
 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());
   }
 }
예제 #5
0
  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();
    }
  }
예제 #6
0
  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());
    }
  }
예제 #7
0
  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();
    }
  }
예제 #8
0
  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();
    }
  }
예제 #9
0
 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);
   }
 }
예제 #10
0
 // a nearest neighbor in the set to point p; null if the set is empty
 public Point2D nearest(Point2D p) {
   if (p == null) throw new NullPointerException("point");
   Point2D nearestPoint = null;
   double nearestDist = MAX_DISTANCE;
   for (Point2D currPoint : points) {
     double currDist = currPoint.distanceTo(p);
     if (currDist < nearestDist) {
       nearestDist = currDist;
       nearestPoint = currPoint;
     }
   }
   return nearestPoint;
 }
예제 #11
0
파일: KdTree.java 프로젝트: desperius/algs
  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;
  }
예제 #12
0
 public boolean contains(Point2D p) {
   if (p.equals(value)) {
     return true;
   } else if (onLeft(p)) {
     return left != null && left.contains(p);
   } else if (onRight(p)) {
     return right != null && right.contains(p);
   } else {
     System.out.println("Impossible!");
     return false;
   }
 }
예제 #13
0
  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;
  }
예제 #14
0
  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);
    }
  }
예제 #15
0
    public Point2D nearest(Point2D p, Point2D nearest) {

      if (slightlyEquals(p, nearest)) return nearest;
      double minDistance = p.distanceSquaredTo(nearest);
      if (left != null) {
        final double distanceTo = p.distanceTo(left.value);
        if (distanceTo <= minDistance) {
          minDistance = distanceTo;
          nearest = left.value;
        }
      }
      if (right != null) {
        final double distanceTo = p.distanceTo(right.value);
        if (distanceTo <= minDistance) {
          minDistance = distanceTo;
          nearest = right.value;
        }
      }
      Point2D lnearest = nearest;
      if (left != null && left.rect.distanceTo(nearest) < minDistance) {
        lnearest = left.nearest(p, nearest);
      }
      Point2D rnearest = nearest;
      if (right != null && right.rect.distanceTo(nearest) < minDistance) {
        rnearest = right.nearest(p, nearest);
      }

      final double ldist = p.distanceTo(lnearest);
      final double rdist = p.distanceTo(rnearest);
      if (ldist < minDistance) {
        nearest = lnearest;
        minDistance = ldist;
      }
      if (rdist < minDistance) {
        nearest = rnearest;
        minDistance = rdist;
      }
      return nearest;
    }
예제 #16
0
 // a nearest neighbor in the set to point p; null if the set is empty
 public Point2D nearest(Point2D p) {
   if (p == null) throw new NullPointerException("Point2D cannot be null!");
   if (set.isEmpty()) return null;
   double minDistance = Double.MAX_VALUE;
   Point2D minPoint = null;
   for (Point2D point : set) {
     double distance = p.distanceSquaredTo(point);
     if (distance < minDistance) {
       minDistance = distance;
       minPoint = point;
     }
   }
   return minPoint;
 }
예제 #17
0
  private void nearest(
      final Node node, final Holder<Point2D> nearest, final Point2D p, final boolean vertical) {

    if (node == null) {
      return;
    } else if (node.key.compareTo(p) == 0) {
      nearest.value = node.key;
      return;
    } else if (p.distanceTo(node.key) < p.distanceTo(nearest.value)) {
      nearest.value = node.key;
    }

    if (onTheLeft(p, node.key, vertical)) {
      nearest(node.left, nearest, p, !vertical);
      if (distanceToVertical(p, node.key, vertical) < p.distanceTo(nearest.value)) {
        nearest(node.right, nearest, p, !vertical);
      }
    } else if (onTheRight(p, node.key, vertical)) {
      nearest(node.right, nearest, p, !vertical);
      if (distanceToVertical(p, node.key, vertical) < p.distanceTo(nearest.value)) {
        nearest(node.left, nearest, p, !vertical);
      }
    }
  }
예제 #18
0
 public Point2D ceiling(Point2D p, boolean inclusive) {
   requireNonNull(p);
   if (value.equals(p)) {
     return value;
   } else if (onRight(p)) {
     if (right != null && right.onLeft(p)) {
       return inclusive ? value : right.value;
     } else if (right != null && right.onRight(p)) {
       return right.ceiling(p, inclusive);
     } else {
       return inclusive ? value : null;
     }
   } else if (onLeft(p)) {
     return left == null ? inclusive ? null : value : left.ceiling(p, inclusive);
   } else {
     return inclusive ? value : null;
   }
 }
예제 #19
0
 // draw all points to standard draw
 public void draw() {
   for (Point2D point2D : root.subSet(LOWER, HIGHER)) {
     StdDraw.point(point2D.x(), point2D.y());
   }
 }
예제 #20
0
  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;
  }
예제 #21
0
  public static void main(String[] args) {

    String filename = args[0];
    In in = new In(filename);

    StdDraw.show(0);

    // initialize the data structures with N points from standard input
    PointSET brute = new PointSET();
    KdTree kdtree = new KdTree();
    while (!in.isEmpty()) {
      double x = in.readDouble();
      double y = in.readDouble();
      Point2D p = new Point2D(x, y);
      kdtree.insert(p);
      brute.insert(p);
    }

    double x0 = 0.0, y0 = 0.0; // initial endpoint of rectangle
    double x1 = 0.0, y1 = 0.0; // current location of mouse
    boolean isDragging = false; // is the user dragging a rectangle

    // draw the points
    StdDraw.clear();
    StdDraw.setPenColor(StdDraw.BLACK);
    StdDraw.setPenRadius(.01);
    brute.draw();

    while (true) {
      StdDraw.show(40);

      // user starts to drag a rectangle
      if (StdDraw.mousePressed() && !isDragging) {
        x0 = StdDraw.mouseX();
        y0 = StdDraw.mouseY();
        isDragging = true;
        continue;
      }

      // user is dragging a rectangle
      else if (StdDraw.mousePressed() && isDragging) {
        x1 = StdDraw.mouseX();
        y1 = StdDraw.mouseY();
        continue;
      }

      // mouse no longer pressed
      else if (!StdDraw.mousePressed() && isDragging) {
        isDragging = false;
      }

      RectHV rect =
          new RectHV(Math.min(x0, x1), Math.min(y0, y1), Math.max(x0, x1), Math.max(y0, y1));
      // draw the points
      StdDraw.clear();
      StdDraw.setPenColor(StdDraw.BLACK);
      StdDraw.setPenRadius(.01);
      brute.draw();

      // draw the rectangle
      StdDraw.setPenColor(StdDraw.BLACK);
      StdDraw.setPenRadius();
      rect.draw();

      // draw the range search results for brute-force data structure in
      // red
      StdDraw.setPenRadius(.03);
      StdDraw.setPenColor(StdDraw.RED);
      for (Point2D p : brute.range(rect)) p.draw();

      // draw the range search results for kd-tree in blue
      StdDraw.setPenRadius(.02);
      StdDraw.setPenColor(StdDraw.BLUE);
      for (Point2D p : kdtree.range(rect)) p.draw();

      StdDraw.show(40);
    }
  }
예제 #22
0
 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;
 }
예제 #23
0
 // draw all points to standard draw
 public void draw() {
   for (Point2D point : points) {
     point.draw();
   }
 }
예제 #24
0
 // draw all points to standard draw
 public void draw() {
   for (Point2D point : set) {
     point.draw();
   }
 }
예제 #25
0
 private double distanceTo(Point2D p1, Point2D p2) {
   if (p2 == null) return Double.MAX_VALUE;
   return p1.distanceTo(p2);
 }
예제 #26
0
 private boolean onRight(final Point2D p) {
   return (even && (p.x() > value.x())) || (!even && (p.y() > value.y()));
 }
예제 #27
0
 private boolean onLeft(final Point2D p) {
   return (even && (p.x() <= value.x())) || (!even && (p.y() <= value.y()));
 }