Skip to content

Commit af2b866

Browse files
committed
added some good tools for intersecting lines with circles
fixed some naming and did away with a capture region math tools method
1 parent 26c15c0 commit af2b866

File tree

1 file changed

+188
-7
lines changed

1 file changed

+188
-7
lines changed

ihmc-robotics-toolkit/src/main/java/us/ihmc/robotics/EuclidCoreMissingTools.java

Lines changed: 188 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package us.ihmc.robotics;
22

33
import static us.ihmc.euclid.geometry.tools.EuclidGeometryTools.ONE_MILLIONTH;
4+
import static us.ihmc.euclid.geometry.tools.EuclidGeometryTools.ONE_TRILLIONTH;
45
import static us.ihmc.euclid.tools.EuclidCoreTools.normSquared;
56

67
import us.ihmc.commons.MathTools;
@@ -19,6 +20,8 @@
1920
import us.ihmc.euclid.tuple2D.Point2D;
2021
import us.ihmc.euclid.tuple2D.interfaces.Point2DBasics;
2122
import us.ihmc.euclid.tuple2D.interfaces.Point2DReadOnly;
23+
import us.ihmc.euclid.tuple2D.interfaces.Vector2DReadOnly;
24+
import us.ihmc.euclid.tuple3D.interfaces.Point3DBasics;
2225
import us.ihmc.euclid.tuple3D.interfaces.Tuple3DBasics;
2326
import us.ihmc.euclid.tuple3D.interfaces.Tuple3DReadOnly;
2427
import us.ihmc.euclid.tuple3D.interfaces.Vector3DReadOnly;
@@ -506,7 +509,7 @@ else if (percentage < 0.0)
506509
* <li><tt>x<sub>n</sub></tt> is {@code inputNormalPartToPack}.
507510
* </ul>
508511
* </p>
509-
*
512+
*
510513
* @param input the tuple to extract the normal part of. Not modified.
511514
* @param normalAxis the normal vector. It is normalized internally if needed. Not
512515
* modified.
@@ -539,7 +542,7 @@ public static void extractNormalPart(Tuple3DReadOnly input, Vector3DReadOnly nor
539542
* <li><tt>x<sub>n</sub></tt> is {@code inputNormalPartToPack}.
540543
* </ul>
541544
* </p>
542-
*
545+
*
543546
* @param input the tuple to extract the normal part of. Not modified.
544547
* @param normalAxis the normal vector. It is normalized internally if needed. Not
545548
* modified.
@@ -569,7 +572,7 @@ public static void extractNormalPart(FrameTuple3DReadOnly input, FrameVector3DRe
569572
* <li><tt>x<sub>n</sub></tt> is {@code inputNormalPartToPack}.
570573
* </ul>
571574
* </p>
572-
*
575+
*
573576
* @param input the tuple to extract the normal part of. Not modified.
574577
* @param normalAxis the normal vector. It is normalized internally if needed. Not
575578
* modified.
@@ -600,7 +603,7 @@ public static void extractNormalPart(FrameTuple3DReadOnly input, FrameVector3DRe
600603
* <li><tt>x<sub>t</sub></tt> is {@code inputTangentialPartToPack}.
601604
* </ul>
602605
* </p>
603-
*
606+
*
604607
* @param input the tuple to extract the tangential part of. Not modified.
605608
* @param normalAxis the normal vector. It is normalized internally if needed. Not
606609
* modified.
@@ -639,7 +642,7 @@ public static void extractTangentialPart(Tuple3DReadOnly input, Vector3DReadOnly
639642
* <li><tt>x<sub>t</sub></tt> is {@code inputTangentialPartToPack}.
640643
* </ul>
641644
* </p>
642-
*
645+
*
643646
* @param input the tuple to extract the tangential part of. Not modified.
644647
* @param normalAxis the normal vector. It is normalized internally if needed. Not
645648
* modified.
@@ -670,7 +673,7 @@ public static void extractTangentialPart(FrameTuple3DReadOnly input, FrameVector
670673
* <li><tt>x<sub>t</sub></tt> is {@code inputTangentialPartToPack}.
671674
* </ul>
672675
* </p>
673-
*
676+
*
674677
* @param input the tuple to extract the tangential part of. Not modified.
675678
* @param normalAxis the normal vector. It is normalized internally if needed. Not
676679
* modified.
@@ -697,7 +700,7 @@ public static void extractTangentialPart(FrameTuple3DReadOnly input, FrameVector
697700
* <li><tt>y</tt> is {@code input}.
698701
* </ul>
699702
* </p>
700-
*
703+
*
701704
* @param input the tuple containing the normal part used to update {@code tupleToModify}.
702705
* Not modified.
703706
* @param normalAxis the normal vector. It is normalized internally if needed. Not modified.
@@ -712,4 +715,182 @@ public static void setNormalPart(Tuple3DReadOnly input, Vector3DReadOnly normalA
712715
double dot = (TupleTools.dot(normalAxis, input) - TupleTools.dot(normalAxis, tupleToModify)) / normalLengthSquared;
713716
tupleToModify.scaleAdd(dot, normalAxis, tupleToModify);
714717
}
718+
719+
public static int intersectionBetweenLineSegment2DAndCylinder3D(double circleRadius, Point2DReadOnly circlePosition,
720+
Point2DReadOnly startPoint, Point2DReadOnly endPoint,
721+
Point2DBasics firstIntersectionToPack,
722+
Point2DBasics secondIntersectionToPack)
723+
{
724+
return intersectionBetweenLine2DAndCircle(circleRadius, circlePosition.getX(), circlePosition.getY(), startPoint.getX(), startPoint.getY(), false,
725+
endPoint.getX(), endPoint.getY(), false, firstIntersectionToPack, secondIntersectionToPack);
726+
}
727+
728+
public static int intersectionBetweenRay2DAndCircle(double circleRadius, Point2DReadOnly circlePosition,
729+
Point2DReadOnly startPoint, Point2DReadOnly pointOnRay,
730+
Point2DBasics firstIntersectionToPack,
731+
Point2DBasics secondIntersectionToPack)
732+
{
733+
return intersectionBetweenLine2DAndCircle(circleRadius, circlePosition.getX(), circlePosition.getY(), startPoint.getX(), startPoint.getY(), false,
734+
pointOnRay.getX(), pointOnRay.getY(), true,
735+
firstIntersectionToPack, secondIntersectionToPack);
736+
}
737+
738+
public static int intersectionBetweenRay2DAndCircle(double circleRadius, Point2DReadOnly circlePosition,
739+
Point2DReadOnly startPoint, Vector2DReadOnly direction,
740+
Point2DBasics firstIntersectionToPack,
741+
Point2DBasics secondIntersectionToPack)
742+
{
743+
return intersectionBetweenLine2DAndCircle(circleRadius, circlePosition.getX(), circlePosition.getY(), startPoint.getX(), startPoint.getY(), false,
744+
startPoint.getX() + direction.getX(), startPoint.getY() + direction.getY(), true,
745+
firstIntersectionToPack, secondIntersectionToPack);
746+
}
747+
748+
public static int intersectionBetweenLine2DAndCircle(double circleRadius, Point2DReadOnly circlePosition,
749+
Point2DReadOnly pointOnLine, Vector2DReadOnly direction,
750+
Point2DBasics firstIntersectionToPack,
751+
Point2DBasics secondIntersectionToPack)
752+
{
753+
return intersectionBetweenLine2DAndCircle(circleRadius, circlePosition.getX(), circlePosition.getY(), pointOnLine.getX(), pointOnLine.getY(), true,
754+
pointOnLine.getX() + direction.getX(), pointOnLine.getY() + direction.getY(), true,
755+
firstIntersectionToPack, secondIntersectionToPack);
756+
}
757+
758+
private static int intersectionBetweenLine2DAndCircle(double circleRadius, double circlePositionX, double circlePositionY,
759+
double startX, double startY, boolean canIntersectionOccurBeforeStart,
760+
double endX, double endY, boolean canIntersectionOccurAfterEnd,
761+
Point2DBasics firstIntersectionToPack,
762+
Point2DBasics secondIntersectionToPack)
763+
{
764+
if (circleRadius < 0.0)
765+
throw new IllegalArgumentException("The circle radius has to be positive.");
766+
767+
if (firstIntersectionToPack != null)
768+
firstIntersectionToPack.setToNaN();
769+
if (secondIntersectionToPack != null)
770+
secondIntersectionToPack.setToNaN();
771+
772+
if (circleRadius == 0.0)
773+
return 0;
774+
775+
double radiusSquared = circleRadius * circleRadius;
776+
777+
double dx = endX - startX;
778+
double dy = endY - startY;
779+
780+
double dIntersection1 = Double.NaN;
781+
double dIntersection2 = Double.NaN;
782+
783+
// Compute possible intersections with the circle
784+
//
785+
double deltaPX = startX - circlePositionX;
786+
double deltaPY = startY - circlePositionY;
787+
788+
double A = EuclidCoreTools.normSquared(dx, dy);
789+
double B = 2.0 * (dx * deltaPX + dy * deltaPY);
790+
double C = EuclidCoreTools.normSquared(deltaPX, deltaPY) - radiusSquared;
791+
792+
double delta = EuclidCoreTools.squareRoot(B * B - 4 * A * C);
793+
794+
if (Double.isFinite(delta))
795+
{
796+
double oneOverTwoA = 0.5 / A;
797+
double dCircle1 = -(B + delta) * oneOverTwoA;
798+
double dCircle2 = -(B - delta) * oneOverTwoA;
799+
800+
double intersection1X = dCircle1 * dx + startX;
801+
double intersection1Y = dCircle1 * dy + startY;
802+
803+
if (Math.abs(EuclidGeometryTools.percentageAlongLine2D(intersection1X, intersection1Y, circlePositionX, circlePositionY, 1.0, 0.0)) > circleRadius - ONE_TRILLIONTH)
804+
dCircle1 = Double.NaN;
805+
806+
if (Double.isFinite(dCircle1))
807+
{
808+
if (Double.isNaN(dIntersection1) || Math.abs(dCircle1 - dIntersection1) < ONE_TRILLIONTH)
809+
{
810+
dIntersection1 = dCircle1;
811+
}
812+
else if (dCircle1 < dIntersection1)
813+
{
814+
dIntersection2 = dIntersection1;
815+
dIntersection1 = dCircle1;
816+
}
817+
else
818+
{
819+
dIntersection2 = dCircle1;
820+
}
821+
}
822+
823+
double intersection2X = dCircle2 * dx + startX;
824+
double intersection2Y = dCircle2 * dy + startY;
825+
826+
if (Math.abs(EuclidGeometryTools.percentageAlongLine2D(intersection2X, intersection2Y, circlePositionX, circlePositionY, 1.0, 0.0)) > circleRadius - ONE_TRILLIONTH)
827+
dCircle2 = Double.NaN;
828+
else if (Math.abs(dCircle1 - dCircle2) < ONE_TRILLIONTH)
829+
dCircle2 = Double.NaN;
830+
831+
if (Double.isFinite(dCircle2))
832+
{
833+
if (Double.isNaN(dIntersection1))
834+
{
835+
dIntersection1 = dCircle2;
836+
}
837+
else if (dCircle2 < dIntersection1)
838+
{
839+
dIntersection2 = dIntersection1;
840+
dIntersection1 = dCircle2;
841+
}
842+
else
843+
{
844+
dIntersection2 = dCircle2;
845+
}
846+
}
847+
848+
}
849+
850+
if (!canIntersectionOccurBeforeStart)
851+
{
852+
if (dIntersection2 < 0.0)
853+
dIntersection2 = Double.NaN;
854+
855+
if (dIntersection1 < 0.0)
856+
{
857+
dIntersection1 = dIntersection2;
858+
dIntersection2 = Double.NaN;
859+
}
860+
}
861+
862+
if (!canIntersectionOccurAfterEnd)
863+
{
864+
if (dIntersection2 > 1.0)
865+
dIntersection2 = Double.NaN;
866+
867+
if (dIntersection1 > 1.0)
868+
{
869+
dIntersection1 = dIntersection2;
870+
dIntersection2 = Double.NaN;
871+
}
872+
}
873+
874+
if (Double.isNaN(dIntersection1))
875+
return 0;
876+
877+
if (firstIntersectionToPack != null)
878+
{
879+
firstIntersectionToPack.set(dx, dy);
880+
firstIntersectionToPack.scale(dIntersection1);
881+
firstIntersectionToPack.add(startX, startY);
882+
}
883+
884+
if (Double.isNaN(dIntersection2))
885+
return 1;
886+
887+
if (secondIntersectionToPack != null)
888+
{
889+
secondIntersectionToPack.set(dx, dy);
890+
secondIntersectionToPack.scale(dIntersection2);
891+
secondIntersectionToPack.add(startX, startY);
892+
}
893+
894+
return 2;
895+
}
715896
}

0 commit comments

Comments
 (0)