11package us .ihmc .robotics ;
22
33import static us .ihmc .euclid .geometry .tools .EuclidGeometryTools .ONE_MILLIONTH ;
4+ import static us .ihmc .euclid .geometry .tools .EuclidGeometryTools .ONE_TRILLIONTH ;
45import static us .ihmc .euclid .tools .EuclidCoreTools .normSquared ;
56
67import us .ihmc .commons .MathTools ;
1920import us .ihmc .euclid .tuple2D .Point2D ;
2021import us .ihmc .euclid .tuple2D .interfaces .Point2DBasics ;
2122import us .ihmc .euclid .tuple2D .interfaces .Point2DReadOnly ;
23+ import us .ihmc .euclid .tuple2D .interfaces .Vector2DReadOnly ;
24+ import us .ihmc .euclid .tuple3D .interfaces .Point3DBasics ;
2225import us .ihmc .euclid .tuple3D .interfaces .Tuple3DBasics ;
2326import us .ihmc .euclid .tuple3D .interfaces .Tuple3DReadOnly ;
2427import 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