Last active
September 16, 2015 17:14
-
-
Save GeePawHill/b813e18db8e68322b803 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.geepawhill.whiteboard.util; | |
import javafx.geometry.Bounds; | |
import javafx.geometry.Point2D; | |
import javafx.scene.Node; | |
import javafx.scene.shape.Rectangle; | |
public class PointPair | |
{ | |
public final double fromX; | |
public final double fromY; | |
public final double toX; | |
public final double toY; | |
public PointPair(double fromX, double fromY, double toX, double toY) | |
{ | |
this.fromX = fromX; | |
this.fromY = fromY; | |
this.toX = toX; | |
this.toY = toY; | |
} | |
public PointPair(Point2D from, Point2D to) | |
{ | |
this(from.getX(), from.getY(), to.getX(), to.getY()); | |
} | |
public PointPair(Bounds bounds) | |
{ | |
this(bounds.getMinX(), bounds.getMinY(), bounds.getMaxX(), bounds.getMaxY()); | |
} | |
public PointPair(Node node) | |
{ | |
this(node.getBoundsInParent()); | |
} | |
public double width() | |
{ | |
return toX-fromX; | |
} | |
public double height() | |
{ | |
return toY-fromY; | |
} | |
public double centerX() | |
{ | |
return (fromX + toX) / 2d; | |
} | |
public double centerY() | |
{ | |
return (fromY + toY) / 2d; | |
} | |
public Point2D center() | |
{ | |
return new Point2D(centerX(), centerY()); | |
} | |
public PointPair offset(double amount) | |
{ | |
return new PointPair(fromX - amount, fromY - amount, toX + amount, toY + amount); | |
} | |
public Compass compass() | |
{ | |
int diffCase = (diffBits((int) fromX, (int) toX) << 4) + diffBits((int) fromY, (int) toY); | |
switch (diffCase) | |
{ | |
default: | |
return Compass.ERROR; | |
case 0x01: | |
return Compass.S; | |
case 0x02: | |
return Compass.N; | |
case 0x10: | |
return Compass.E; | |
case 0x11: | |
return Compass.SE; | |
case 0x12: | |
return Compass.NE; | |
case 0x20: | |
return Compass.W; | |
case 0x21: | |
return Compass.SW; | |
case 0x22: | |
return Compass.NW; | |
} | |
} | |
private int diffBits(int from, int to) | |
{ | |
// 0 means dimensions = | |
// 1 means from>to | |
// 2 means to>from | |
int diff = to - from; | |
if (diff == 0) | |
return 0; | |
else | |
{ | |
if (diff > 0) return 1; | |
} | |
return 2; | |
} | |
public Point2D intersectAtPoint(PointPair other) | |
{ | |
double width = width(); | |
double height = height(); | |
double otherWidth = other.width(); | |
double otherHeight = other.height(); | |
double s = (-height * (fromX - other.fromX) + width * (fromY - other.fromY)) / (-otherWidth * height + width * otherHeight); | |
double t = (otherWidth * (fromY - other.fromY) - otherHeight * (fromX - other.fromX)) / (-otherWidth * height + width * otherHeight); | |
if (s >= 0d && s <= 1d && t >= 0d && t <= 1d) { return new Point2D(fromX + (t * width), fromY + (t * height)); } | |
return null; | |
} | |
public PointPair fractionAnchoredAtFrom(double fraction) | |
{ | |
return new PointPair(fromX,fromY, fromX+(width()*fraction), fromY+(height()*fraction)); | |
} | |
public void copyToNode(Rectangle box) | |
{ | |
box.setX(fromX); | |
box.setY(fromY); | |
box.setWidth(width()); | |
box.setHeight(height()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.geepawhill.whiteboard.util; | |
import static org.junit.Assert.*; | |
import javafx.geometry.BoundingBox; | |
import javafx.geometry.Point2D; | |
import javafx.scene.shape.Line; | |
import org.geepawhill.whiteboard.util.Compass; | |
import org.geepawhill.whiteboard.util.PointPair; | |
import org.junit.Test; | |
public class PointPairTest | |
{ | |
final double DOUBLE_ACCURACY = 0.9d; // as long as we're integer-true | |
@Test | |
public void simpleConstructor() | |
{ | |
PointPair pair = new PointPair(0d,10d,100d,160d); | |
assertDoubles(0d,pair.fromX); | |
assertDoubles(10d,pair.fromY); | |
assertDoubles(100d,pair.toX); | |
assertDoubles(160d,pair.toY); | |
} | |
@Test | |
public void pointConstructor() | |
{ | |
PointPair pair = new PointPair(new Point2D(0d,10d),new Point2D(100d,160d)); | |
assertDoubles(0d,pair.fromX); | |
assertDoubles(10d,pair.fromY); | |
assertDoubles(100d,pair.toX); | |
assertDoubles(160d,pair.toY); | |
} | |
@Test | |
public void boundsConstructor() | |
{ | |
PointPair pair = new PointPair(new BoundingBox(0d,10d,100d,150d)); | |
assertDoubles(0d,pair.fromX); | |
assertDoubles(10d,pair.fromY); | |
assertDoubles(100d,pair.toX); | |
assertDoubles(160d,pair.toY); | |
} | |
@Test | |
public void nodeConstructor() | |
{ | |
PointPair pair = new PointPair(new Line(0d,10d,100d,160d)); | |
assertDoubles(0d,pair.fromX); | |
assertDoubles(10d,pair.fromY); | |
assertDoubles(100d,pair.toX); | |
assertDoubles(160d,pair.toY); | |
} | |
@Test | |
public void dimensions() | |
{ | |
PointPair pair = new PointPair( 0d, 10d, 100d, 150d); | |
assertDoubles(100d,pair.width()); | |
assertDoubles(140d,pair.height()); | |
} | |
@Test | |
public void centers() | |
{ | |
PointPair pair = new PointPair(0d,10d,100d,160d); | |
assertDoubles(50d,pair.centerX()); | |
assertDoubles(85d,pair.centerY()); | |
assertEquals(new Point2D(50d,85d),pair.center()); | |
} | |
@Test | |
public void offsets() | |
{ | |
PointPair pair = new PointPair(0d,10d,100d,160d); | |
assertPairs(new PointPair(-5d,5d,105d,165d),pair.offset(5d)); | |
assertPairs(new PointPair(5d,15d,95d,155d),pair.offset(-5d)); | |
} | |
@Test | |
public void directions() | |
{ | |
assertEquals(Compass.E, new PointPair(0d,0d,100d,0d).compass()); | |
assertEquals(Compass.W, new PointPair(100d,0d,0d,0d).compass()); | |
assertEquals(Compass.N, new PointPair(0d,100d,0d,0d).compass()); | |
assertEquals(Compass.S, new PointPair(0d,0d,0d,100d).compass()); | |
assertEquals(Compass.NW, new PointPair(100d,100d,0d,0d).compass()); | |
assertEquals(Compass.NE, new PointPair(0d,100d,100d,0d).compass()); | |
assertEquals(Compass.SW, new PointPair(100d,0d,0d,100d).compass()); | |
assertEquals(Compass.SE, new PointPair(0d,0d,100d,100d).compass()); | |
} | |
@Test | |
public void simpleIntersection() | |
{ | |
PointPair one = new PointPair(0d,0d,100d,200d); | |
PointPair other = new PointPair(0d,200d,100d,0d); | |
Point2D actual = one.intersectAtPoint(other); | |
assertDoubles(50d,actual.getX()); | |
assertDoubles(100d,actual.getY()); | |
} | |
@Test | |
public void noIntersection() | |
{ | |
PointPair one = new PointPair(0d,0d,100d,200d); | |
PointPair other = new PointPair(100d,200d,100d,200d); | |
assertNull(one.intersectAtPoint(other)); | |
} | |
@Test | |
public void fractionAnchoredAtFrom() | |
{ | |
PointPair pair = new PointPair( 0d, 10d, 100d, 150d); | |
PointPair partial = pair.fractionAnchoredAtFrom(.5d); | |
assertDoubles(0d,partial.fromX); | |
assertDoubles(10d,partial.fromY); | |
assertDoubles(50d,partial.toX); | |
assertDoubles(80d,partial.toY); | |
} | |
private void assertDoubles(double expected,double actual) | |
{ | |
assertEquals(expected,actual,DOUBLE_ACCURACY); | |
} | |
private void assertPairs(PointPair left,PointPair right) | |
{ | |
assertDoubles(left.fromX,right.fromX); | |
assertDoubles(left.fromY,right.fromY); | |
assertDoubles(left.toX,right.toX); | |
assertDoubles(left.toY,right.toY); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment