Geometry.java 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. package holeg.utility.math.vector;
  2. import static holeg.utility.math.Maths.EPSILON;
  3. import holeg.utility.math.Maths;
  4. import java.awt.Rectangle;
  5. import java.util.Optional;
  6. /**
  7. * A helper class for geometric shapes and operations.
  8. */
  9. public class Geometry {
  10. /**
  11. * Construct a Rectangle with only the points from two corners.
  12. * The Rectangle is axis aligned.
  13. * The ordering of the corner is irrelevant.
  14. * @param corner a corner of the Rectangle
  15. * @param otherCorner another corner of the Rectangle
  16. * @return the corresponding rectangle
  17. */
  18. public static Rectangle createRectangleFromCorners(Vec2i corner, Vec2i otherCorner) {
  19. //Calculate left top corner, width, height
  20. Vec2i topLeft = new Vec2i(Math.min(corner.getX(), otherCorner.getX()),
  21. Math.min(corner.getY(), otherCorner.getY()));
  22. Vec2i bottomRight = new Vec2i(Math.max(corner.getX(), otherCorner.getX()),
  23. Math.max(corner.getY(), otherCorner.getY()));
  24. int width = bottomRight.getX() - topLeft.getX();
  25. int height = bottomRight.getY() - topLeft.getY();
  26. return new Rectangle(topLeft.getX(), topLeft.getY(), width, height);
  27. }
  28. /**
  29. * If the line Intersect the circle the projection is returned.
  30. * @param line the 2d line
  31. * @param circle the 2d circle
  32. * @return the projection
  33. */
  34. public static Optional<Vec2f> getProjectionOnSegmentIfInRange(Line line, Circle circle) {
  35. float lineLengthSqr = line.lengthSqr();
  36. if (lineLengthSqr < EPSILON) {
  37. if (line.p1.getDistanceSqr(circle.position) < circle.radius * circle.radius) {
  38. return Optional.of(new Vec2f(line.p1));
  39. } else {
  40. return Optional.empty();
  41. }
  42. }
  43. Vec2f p2p1 = line.p2.subtract(line.p1);
  44. float t = Maths.clamp(Vec2f.dot(circle.position.subtract(line.p1), p2p1) / lineLengthSqr, 0.0f,
  45. 1.0f);
  46. Vec2f projection = line.p1.add(p2p1.multiply(t));
  47. if (projection.getDistanceSqr(circle.position) < circle.radius * circle.radius) {
  48. return Optional.of(projection);
  49. } else {
  50. return Optional.empty();
  51. }
  52. }
  53. /**
  54. * A simple representation of a 2d circle via a center point and a radius.
  55. */
  56. public static class Circle {
  57. /**
  58. * The center of the circle.
  59. */
  60. public Vec2f position;
  61. /**
  62. * The radius of the circle.
  63. */
  64. public float radius;
  65. /**
  66. * Construct the circle with a center point and a radius.
  67. * @param position center of the circle
  68. * @param radius radius of the circle
  69. */
  70. public Circle(Vec2f position, float radius) {
  71. this.position = position;
  72. this.radius = radius;
  73. }
  74. }
  75. /**
  76. * A simple representation of a 2D-line via two points.
  77. */
  78. public static class Line {
  79. /**
  80. * First point
  81. */
  82. Vec2f p1;
  83. /**
  84. * Second Point
  85. */
  86. Vec2f p2;
  87. /**
  88. * Construct a line via two points.
  89. *
  90. * @param p1 first point
  91. * @param p2 second point
  92. */
  93. public Line(Vec2f p1, Vec2f p2) {
  94. this.p1 = p1;
  95. this.p2 = p2;
  96. }
  97. /**
  98. * Returns the squared length of the line.
  99. *
  100. * @return the squared length of the line
  101. */
  102. float lengthSqr() {
  103. return p1.getDistanceSqr(p2);
  104. }
  105. }
  106. }