1 package com.github.davidmoten.rtree.geometry.internal; 2 3 import com.github.davidmoten.guavamini.Preconditions; 4 import com.github.davidmoten.rtree.geometry.Geometry; 5 import com.github.davidmoten.rtree.geometry.Rectangle; 6 import com.github.davidmoten.rtree.internal.util.ObjectsHelper; 7 8 import java.util.Objects; 9 import java.util.Optional; 10 11 public final class RectangleDouble implements Rectangle { 12 private final double x1, y1, x2, y2; 13 14 private RectangleDouble(double x1, double y1, double x2, double y2) { 15 Preconditions.checkArgument(x2 >= x1); 16 Preconditions.checkArgument(y2 >= y1); 17 this.x1 = x1; 18 this.y1 = y1; 19 this.x2 = x2; 20 this.y2 = y2; 21 } 22 23 public static RectangleDouble create(double x1, double y1, double x2, double y2) { 24 return new RectangleDouble((double) x1, (double) y1, (double) x2, (double) y2); 25 } 26 27 @Override 28 public double x1() { 29 return x1; 30 } 31 32 @Override 33 public double y1() { 34 return y1; 35 } 36 37 @Override 38 public double x2() { 39 return x2; 40 } 41 42 @Override 43 public double y2() { 44 return y2; 45 } 46 47 @Override 48 public Rectangle add(Rectangle r) { 49 return new RectangleDouble(min(x1, r.x1()), min(y1, r.y1()), max(x2, r.x2()), 50 max(y2, r.y2())); 51 } 52 53 @Override 54 public boolean contains(double x, double y) { 55 return x >= x1 && x <= x2 && y >= y1 && y <= y2; 56 } 57 58 @Override 59 public boolean intersects(Rectangle r) { 60 if (r instanceof RectangleDouble) { 61 RectangleDouble rd = (RectangleDouble) r; 62 return intersects(rd); 63 } else { 64 return GeometryUtil.intersects(x1, y1, x2, y2, r.x1(), r.y1(), r.x2(), r.y2()); 65 } 66 } 67 68 private boolean intersects(RectangleDouble rd) { 69 return GeometryUtil.intersects(x1, y1, x2, y2, rd.x1, rd.y1, rd.x2, rd.y2); 70 } 71 72 @Override 73 public double distance(Rectangle r) { 74 return GeometryUtil.distance(x1, y1, x2, y2, r.x1(), r.y1(), r.x2(), r.y2()); 75 } 76 77 @Override 78 public Rectangle mbr() { 79 return this; 80 } 81 82 @Override 83 public String toString() { 84 return "Rectangle [x1=" + x1 + ", y1=" + y1 + ", x2=" + x2 + ", y2=" + y2 + "]"; 85 } 86 87 @Override 88 public int hashCode() { 89 return Objects.hash(x1, y1, x2, y2); 90 } 91 92 @Override 93 public boolean equals(Object obj) { 94 Optional<RectangleDouble> other = ObjectsHelper.asClass(obj, RectangleDouble.class); 95 if (other.isPresent()) { 96 return Objects.equals(x1, other.get().x1) && Objects.equals(x2, other.get().x2) 97 && Objects.equals(y1, other.get().y1) && Objects.equals(y2, other.get().y2); 98 } else 99 return false; 100 } 101 102 @Override 103 public double intersectionArea(Rectangle r) { 104 if (!intersects(r)) 105 return 0; 106 else { 107 return create(max(x1, r.x1()), max(y1, r.y1()), min(x2, r.x2()), min(y2, r.y2())) 108 .area(); 109 } 110 } 111 112 @Override 113 public Geometry geometry() { 114 return this; 115 } 116 117 private static double max(double a, double b) { 118 if (a < b) 119 return b; 120 else 121 return a; 122 } 123 124 private static double min(double a, double b) { 125 if (a < b) 126 return a; 127 else 128 return b; 129 } 130 131 @Override 132 public double perimeter() { 133 return 2 * (x2 - x1) + 2 * (y2 - y1); 134 } 135 136 @Override 137 public double area() { 138 return (x2 - x1) * (y2 - y1); 139 } 140 141 @Override 142 public boolean isDoublePrecision() { 143 return true; 144 } 145 146 }