package me.hammerle.supersnuvi.util; public class CollisionLine extends CollisionObject { private float x1; private float y1; private float x2; private float y2; private float cx1; private float cy1; private float cx2; private float cy2; public CollisionLine(float x1, float y1, float x2, float y2) { this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; this.cx1 = x1; this.cy1 = y1; this.cx2 = x2; this.cy2 = y2; } @Override public Type getType() { return Type.LINE; } @Override public CollisionObject copy() { return new CollisionLine(cx1, cy1, cx2, cy2); } @Override public void save() { x1 = cx1; y1 = cy1; x2 = cx2; y2 = cy2; } @Override public CollisionObject reset() { cx1 = x1; cy1 = y1; cx2 = x2; cy2 = y2; return this; } @Override public float getWidth() { return Math.abs(x1 - x2); } @Override public float getHeight() { return Math.abs(y1 - y2); } @Override public float getMinX() { return cx1; } @Override public float getMaxX() { return cx2; } @Override public float getMinY() { return cy1; } @Override public float getMaxY() { return cy2; } @Override public CollisionObject expand(float x, float y) { return this; } @Override public CollisionObject offsetX(float x) { cx1 += x; cx2 += x; return this; } @Override public CollisionObject offsetY(float y) { cy1 += y; cy2 += y; return this; } @Override public boolean isColliding(CollisionObject cb) { switch(cb.getType()) { case BOX: return cb.isColliding(this); case LINE: return CollisionLine.intersect(x1, y1, x2, y2, cb.getMinX(), cb.getMinY(), cb.getMaxX(), cb.getMaxY()); } return false; } @Override public String toString() { StringBuilder sb = new StringBuilder("line[x1 = "); sb.append(cx1); sb.append(", y1 = "); sb.append(cy1); sb.append(", x2 = "); sb.append(cx2); sb.append(", y2 = "); sb.append(cy2); sb.append(']'); return sb.toString(); } public static boolean intersect(float x11, float y11, float x12, float y12, float x21, float y21, float x22, float y22) { if(compareFloats(x11, x12)) { if(compareFloats(x21, x22)) { return false; } else { if(!isBetween(x11, x21, x22)) { return false; } float k = (y21 - y22) / (x21 - x22); float d = y22 - k * x22; float y = d + x11 * k; return isBetween(y, y11, y12) && isBetween(y, y21, y22); } } else { if(compareFloats(x21, x22)) { if(!isBetween(x21, x11, x12)) { return false; } float k = (y11 - y12) / (x11 - x12); float d = y12 - k * x12; float y = d + x21 * k; return isBetween(y, y11, y12) && isBetween(y, y21, y22); } else { float k1 = (y11 - y12) / (x11 - x12); float k2 = (y21 - y22) / (x21 - x22); if(compareFloats(k1, k2)) { return false; } float d1 = y12 - k1 * x12; float d2 = y22 - k2 * x22; float x = (d1 - d2) / (k2 - k1); if(!isBetween(x, x11, x12) || !isBetween(x, x21, x22)) { return false; } float y = k1 * x + d1; return isBetween(y, y11, y12) && isBetween(y, y21, y22); } } } private static final float ERROR = 1.0f / 512.0f; private static boolean isBetween(float y, float y1, float y2) { float min = Math.min(y1, y2) - ERROR; float max = Math.max(y1, y2) + ERROR; return y >= min && y <= max; } private static boolean compareFloats(float a, float b) { return Math.abs(a - b) < ERROR; } }