Mógłbym napisać więcej ale resztę sobie już wymyślisz. Masz poniżej rozszerzenia do liczenia odległości do punktu i do odcinka. Napiszesz sobie statyczną metodę rozszerzenie dla Rectangle które na podstawie poniższych metod znajdzie Ci najbliżysz element punkty A B C D odcinki AB BC CD DA lub regiony "wewnątrz"/ "na zewnątrz" prostokąta. Przy wyszukiwaniu elementów prostokąta zrobisz sobie margines odległości dla wyszukiwania odcinków (powiedzmy 3-4) troche wiekszy margines dla punktów (6-8) tak żeby miały wyższy priorytet. stwórz sobie najlepiej Enum z takimi elementami rectangle. potem na ich podstawie napiszesz sobie metodę resize dla Rectange przyjmującą jeden z elementów rectangle i wektor przesunię "myszki" ... mniej wiecej jest taki plan.
public static class DistanceExtensions
{
/// <summary>
/// (READY)(Extension) count distance do point
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static double Distance(this Point a, Point b)
{
return Distance((PointF)a, (PointF)b);
}
/// <summary>
/// (READY)(Extension) count point distance do point
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static double Distance(this PointF a, PointF b)
{
double xdiff = a.X - b.X;
double ydiff = a.Y - b.Y;
return Math.Sqrt(xdiff * xdiff + ydiff * ydiff);
}
/// <summary>
///
/// </summary>
/// <param name="A"></param>
/// <param name="B"></param>
/// <param name="C"></param>
/// <returns></returns>
private static double cross(PointF A, PointF B, PointF C)
{
PointF AB = new PointF();
PointF AC = new PointF();
AB.X = B.X - A.X;
AB.Y = B.Y - A.Y;
AC.X = C.X - A.X;
AC.Y = C.Y - A.Y;
double cross = AB.X * AC.Y - AB.Y * AC.X;
return cross;
}
/// <summary>
///
/// </summary>
/// <param name="A"></param>
/// <param name="B"></param>
/// <param name="C"></param>
/// <returns></returns>
private static double dot(PointF A, PointF B, PointF C)
{
PointF AB = new PointF();
PointF BC = new PointF();
AB.X = B.X - A.X;
AB.Y = B.Y - A.Y;
BC.X = C.X - B.X;
BC.Y = C.Y - B.Y;
double dot = AB.X * BC.X + AB.Y * BC.Y;
return dot;
}
/// <summary>
///
/// </summary>
/// <param name="A"></param>
/// <param name="B"></param>
/// <param name="C"></param>
/// <returns></returns>
public static double DistancaLine(this Point A, Point B, Point C)
{
return ((PointF)A).DistancaLine((PointF)B, (PointF)C, true);
}
/// <summary>
/// (READY)(Extension) count point distance do segment/line
/// </summary>
/// <param name="A">start ponit</param>
/// <param name="B">first point in segment/line</param>
/// <param name="C">second point in segemtn/line</param>
/// <param name="isSegment">true if it's segment false if it's line</param>
/// <returns>distance to line</returns>
public static double DistancaLine(this PointF A, PointF B, PointF C, bool isSegment)
{
double dist = cross(B, C,A) / Distance( B,C);
if (isSegment)
{
double dot1 = dot( B, C,A);
if (dot1 > 0) return Distance(B, C);
double dot2 = dot(C, B, A);
if (dot2 > 0) return Distance(A, C);
}
return Math.Abs(dist);
}
}