Часто вы обнаружите, что использование векторов делает решение более понятным ...
Вот процедура из моей собственной библиотеки:
public class Line2 {
Real2 from;
Real2 to;
Vector2 vector;
Vector2 unitVector = null;
public Real2 getNearestPointOnLine(Real2 point) {
unitVector = to.subtract(from).getUnitVector();
Vector2 lp = new Vector2(point.subtract(this.from));
double lambda = unitVector.dotProduct(lp);
Real2 vv = unitVector.multiplyBy(lambda);
return from.plus(vv);
}
}
Вам нужно будет реализовать Real2 (точка) и Vector2 и dotProduct (), но они должны быть простыми:
Код выглядит примерно так:
Point2 p1 = new Point2(x1, y1);
Point2 p2 = new Point2(x2, y2);
Point2 p3 = new Point2(x3, y3);
Line2 line = new Line2(p1, p2);
Point2 p4 = getNearestPointOnLine(p3);
Библиотека (org.xmlcml.euclid) находится по адресу:
http://sourceforge.net/projects/cml/
и есть модульные тесты, которые будут использовать этот метод и покажут вам, как его использовать.
@Test
public final void testGetNearestPointOnLine() {
Real2 p = l1112.getNearestPointOnLine(new Real2(0., 0.));
Real2Test.assertEquals("point", new Real2(0.4, -0.2), p, 0.0000001);
}