Building on Gale's answer, I made the formula/math a little simpler, and I added my working C# code. I've built this in Unity, and used the same variables as Gale did.
SHMin
// 1. Get the max angle that E can turn (whichever way) in Radians = maxEAng
float maxEAng = Mathf.Max(Mathf.Abs(EHinge.min), Mathf.Abs(EHinge.max)) * Mathf.Deg2Rad;
// 2. Use the max angle of E to calculate the vector to H from E
Vector2 EHVec = new Vector2(Mathf.Cos(maxEAng), Mathf.Sin(maxEAng)) * EHlen;
// 3. Add the length of SE to the x of the vector towards the end effector to find the position of H
Vector2 H = new Vector2(EHVec.x + SElen, EHVec.y);
// 4. The min distance from S to H is the magnitude of the position of H, given that S is at 0,0
SHMin = H.magnitude;
Calculate which grip is in range
THis code loops through all the grips (points) and for each one checks if it is reachable, given the constraints of the arm.
// Set H equal to a grip in the list
for (int i = 4; i < gripArray.Length; i++) { Vector2 H= gripArray[i].position;
// Get SHlen: SHlen = length(H - S)
float SELen = (H - S).magnitude;
//Early Out: If (SE < minDistanceToE), then the point is too close for the arm to reach.
if (SE < minDistanceToE) {continue;}
// Early Out: If(SH > Slen + Elen), then point is beyond the reach of the arm
if (SH > Slen + Elen){continue;}
// Use law of cosines to find angle between SE and SH c ^ 2 = a ^ 2 + b ^ 2 − 2ab cos(C) // This will be Elen ^ 2 = Slen ^ 2 + SHlen ^ 2 - 2(Elen)(SHlen)cos(C) // Which solves to C = ACOS((Slen ^ 2 + SHlen ^ 2 - Elen ^ 2) / (2(Slen)(SHlen))
float C = Mathf.Acos( (Mathf.Pow(Slen, 2) + Mathf.Pow(SHlen, 2) - Mathf.Pow(Elen, 2)) / (2 * Slen * SHlen) );
// Create a vector representing the direction of SE respective to SH // vecA = (cos(C), sin(C))
Vector2 vecA = new Vector2(Mathf.Cos(C), Mathf.Sin(C));
// Normalize SHnorm = normalize(SH)
Vector2 SENorm = (H -S).normalized;
// What are the angles for the direction of SE respective to SH + SH respective to the (0,-1) rotation limit axis
var SEVecAngle = Vector2.SignedAngle(new Vector2(1, 0), vecA) ; var SHAng= Vector2.SignedAngle(new Vector2(0, -1), SHnorm); var combinedAngle = SEVecAngle + SHAng;
// Final Out: If(combinedAngle > maxSAngle or < minSAngle), where the max and min angle is measured from rotation axis (0,-1) then arm can't reach the point.
if (combinedAngle > maxSAngle || combinedAngle < minSAngle) {continue;} Debug.Log(“Grip “ + [I] + “ is reachable!”