Skróć linię o liczbę pikseli

Rysuję niestandardowy diagram obiektów biznesowych za pomocą .NET GDI +. Między innymi diagram składa się z kilku linii łączących obiekty.

W konkretnym scenariuszu muszę skrócić linię o określoną liczbę pikseli, powiedzmy 10 pikseli, tj. Znaleźć punkt na linii, który leży 10 pikseli przed końcowym punktem linii.

Wyobraź sobie okrąg o promieniur = 10 pikseli i linia z punktem początkowym (x1, y1) i punktem końcowym (x2, y2). Okrąg jest wyśrodkowany w punkcie końcowym linii, jak na poniższej ilustracji.

Ilustracja http://i45.tinypic.com/140b5w5.gif

Jak obliczyć punkt oznaczony czerwonym kółkiem, tj. Przecięcie między okręgiem a linią? Dałoby mi to nowy punkt końcowy linii, skracając go o 10 pikseli.

Rozwiązanie

Dziękuję za odpowiedzi, z których udało mi się zebrać następującą procedurę. Nazwałem go LengthenLine, ponieważ uważam, że bardziej naturalne jest przekazywanie ujemnej liczby pikseli, jeśli chcę skrócić linię.

W szczególności próbowałem stworzyć funkcję, która mogłaby narysować linię z zaokrąglonymi rogami, które można znaleźćtutaj.

public void LengthenLine(PointF startPoint, ref PointF endPoint, float pixelCount)
{
  if (startPoint.Equals(endPoint))
    return; // not a line

  double dx = endPoint.X - startPoint.X;
  double dy = endPoint.Y - startPoint.Y;
  if (dx == 0)
  {
    // vertical line:
    if (endPoint.Y < startPoint.Y)
      endPoint.Y -= pixelCount;
    else
      endPoint.Y += pixelCount;
  }
  else if (dy == 0)
  {
    // horizontal line:
    if (endPoint.X < startPoint.X)
      endPoint.X -= pixelCount;
    else
      endPoint.X += pixelCount;
  }
  else
  {
    // non-horizontal, non-vertical line:
    double length = Math.Sqrt(dx * dx + dy * dy);
    double scale = (length + pixelCount) / length;
    dx *= scale;
    dy *= scale;
    endPoint.X = startPoint.X + Convert.ToSingle(dx);
    endPoint.Y = startPoint.Y + Convert.ToSingle(dy);
  }
}

questionAnswers(3)

yourAnswerToTheQuestion