This works by making an interpolation function in initialization, which represents the surface. ThenEach time the prob is moved, it finds the Euclidean distance between the current tip position and the surface at the x-coordinates at the time.
It checks that this distance is not smaller than some crash tolerance constant value set in the initialization. (This tolerance can also be added as control variable if needed).
This also prevents the crash to occur, by forcing the slider forthat controls the tip positiony-position to bego back above the surface at that x-coordinate. Hence it is no possible to hit the surface. It also makes a Beep[]
also(just in case :).
Manipulate[
Module[{d, ys},
ys = surfaceFun[x];
d = EuclideanDistance[{x, y}, {x, surfaceFun[x]ys}];
If[y <= surfaceFun[x]ys, y = surfaceFun[x]ys + crashTol];
(*reset slider to stay above surface*)
Graphics[
{
box,
surface,
GeometricTransformation[
GeometricTransformation[tip[rg], TranslationTransform[{x, y}]],
RotationTransform[t Degree, 0.5 + {x, y}]],
Text[If[d <= crashTol, Beep[]; Style["WARNING !!", Red, 18], ""], {x, y}, {0, 1}]
}
,
PlotRange -> {{-3, 3.1}, {-1.1, 3}}]
],
{{x, 0, "Left/Right"}, -3, 2, Appearance -> "Labeled"},
{{y, 2, "Up/Down"}, -0.5, 2, 2 crashTol, Appearance -> "Labeled"},
{{t, 0, "UME tilt"}, -15, 15, Appearance -> "Labeled"},
{{rg, 0.4, "UME sharpness"}, 0.11, 0.5, Appearance -> "Labeled"},
ControlPlacement -> Above,
ContinuousAction -> True,
Alignment -> Center,
ImageMargins -> 5,
FrameMargins -> 5,
Paneled -> True,
Frame -> False,
AutorunSequencing -> {1},
Initialization :>
(
crashTol = 0.01; (*change as needed*)
surfaceData = Table[BezierFunction[{{-3, 0}, {0, 1}, {2, -1}, {3, 0}}][x], {x,
1, 0, -0.05}];
surfaceFun = Interpolation[surfaceData];
tip[rg_] := {
EdgeForm[Thin], FaceForm[White],
Polygon[{{0, 4}, {0, 0.2}, {0.5 - rg, 0}, {0.5 + rg, 0}, {1,
0.2}, {1, 4}}], FaceForm[Black], Rectangle[{0.4, 0}, {0.6, 1}]
};
box = {EdgeForm[Thin], FaceForm[Blue], Rectangle[{-3, -1}, {3, 3}]};
surface = {FaceForm[Green],
Polygon@Partition[Flatten@{{-3, -1}, {3, -1}, surfaceData}, 2]}
)
]