]> git.lizzy.rs Git - BoundingBoxOutlineReloaded.git/blob - src/main/java/com/irtimaled/bbor/client/models/BoundingBoxLine.java
Add support for custom line
[BoundingBoxOutlineReloaded.git] / src / main / java / com / irtimaled / bbor / client / models / BoundingBoxLine.java
1 package com.irtimaled.bbor.client.models;
2
3 import com.irtimaled.bbor.common.BoundingBoxType;
4 import com.irtimaled.bbor.common.TypeHelper;
5 import com.irtimaled.bbor.common.models.AbstractBoundingBox;
6 import com.irtimaled.bbor.common.models.Point;
7
8 public class BoundingBoxLine extends AbstractBoundingBox {
9     private final Point minPoint;
10     private final Point maxPoint;
11     private final Double width;
12     private final Point[] corners;
13
14     protected BoundingBoxLine(Point minPoint, Point maxPoint, double width, BoundingBoxType type, Point... corners) {
15         super(type);
16         this.minPoint = minPoint;
17         this.maxPoint = maxPoint;
18         this.width = width;
19         this.corners = corners;
20     }
21
22     public static BoundingBoxLine from(Point minPoint, Point maxPoint, Double width, BoundingBoxType type) {
23         if (width == 0) return new BoundingBoxLine(minPoint, maxPoint, width, type);
24
25         double halfWidth = width / 2.0d;
26
27         double dx = maxPoint.getX() - minPoint.getX();
28         double dz = maxPoint.getZ() - minPoint.getZ();
29
30         double dxm = dx == 0 ? 0 : dx / Math.abs(dx);
31         double dzm = dz == 0 ? 0 : dz / Math.abs(dz);
32
33         double xc, zc;
34         if (dxm == 0 || dzm == 0) {
35             xc = Math.abs(dzm) * halfWidth;
36             zc = Math.abs(dxm) * halfWidth;
37         } else {
38             double h = Math.sqrt(dx * dx + dz * dz);
39             double theta = Math.acos((dz * dz + h * h - dx * dx) / (2 * dz * h));
40             zc = halfWidth * Math.sin(theta);
41             xc = Math.sqrt(halfWidth * halfWidth - zc * zc) * dxm * dzm;
42         }
43
44         return new BoundingBoxLine(minPoint, maxPoint, width, type,
45                 new Point(minPoint.getX() + xc, minPoint.getY(), minPoint.getZ() - zc),
46                 new Point(minPoint.getX() - xc, minPoint.getY(), minPoint.getZ() + zc),
47                 new Point(maxPoint.getX() - xc, maxPoint.getY(), maxPoint.getZ() + zc),
48                 new Point(maxPoint.getX() + xc, maxPoint.getY(), maxPoint.getZ() - zc));
49     }
50
51     @Override
52     public int hashCode() {
53         return TypeHelper.combineHashCodes(minPoint.hashCode(), maxPoint.hashCode());
54     }
55
56     @Override
57     public boolean equals(Object obj) {
58         if (this == obj) return true;
59         if (obj == null || getClass() != obj.getClass()) return false;
60         BoundingBoxLine other = (BoundingBoxLine) obj;
61         return minPoint.equals(other.minPoint) && maxPoint.equals(other.maxPoint);
62     }
63
64     public Point getMinPoint() {
65         return minPoint;
66     }
67
68     public Point getMaxPoint() {
69         return maxPoint;
70     }
71
72     public double getWidth() {
73         return width;
74     }
75
76     public Point[] getCorners() {
77         return corners;
78     }
79
80     @Override
81     public Boolean intersectsBounds(int minX, int minZ, int maxX, int maxZ) {
82         boolean minXWithinBounds = isBetween(minPoint.getX(), minX, maxX);
83         boolean maxXWithinBounds = isBetween(maxPoint.getX(), minX, maxX);
84         boolean minZWithinBounds = isBetween(minPoint.getZ(), minZ, maxZ);
85         boolean maxZWithinBounds = isBetween(maxPoint.getZ(), minZ, maxZ);
86
87         return (minXWithinBounds && minZWithinBounds) ||
88                 (maxXWithinBounds && maxZWithinBounds) ||
89                 (minXWithinBounds && maxZWithinBounds) ||
90                 (maxXWithinBounds && minZWithinBounds);
91     }
92
93     private boolean isBetween(double val, int min, int max) {
94         return val >= min && val <= max;
95     }
96 }