Как я могу нарисовать перпендикуляр на отрезке прямой из заданной точки? Мой отрезок линии определяется как (x1, y1), (x2, y2), если я нарисую перпендикуляр из точки (x3, y3), и он пересечется с линией в точке (x4, y4). Я хочу это выяснить (x4, y4).
Перпендикуляр на прямой из заданной точки
Ответы (14)
Я решил для вас уравнения:
k = ((y2-y1) * (x3-x1) - (x2-x1) * (y3-y1)) / ((y2-y1)^2 + (x2-x1)^2)
x4 = x3 - k * (y2-y1)
y4 = y3 + k * (x2-x1)
Где ^ 2 означает квадрат
Из wiki:
В алгебре для любого линейного уравнения y = mx + b все перпендикуляры будут иметь наклон (-1 / m), противоположный исходному наклону. Полезно запомнить слоган «найти наклон перпендикулярной прямой, перевернуть дробь и поменять знак». Напомним, что любое целое число a больше единицы и может быть записано как (a / 1)
Чтобы найти перпендикуляр данной линии, который также проходит через конкретную точку (x, y), решите уравнение y = (-1 / m) x + b, подставляя известные значения m, x и y для решения для б.
Наклон прямой m через (x1, y1) и (x2, y2) равен m = (y1 - y2) / (x1 - x2).
Я согласен с peter.murray.rust, векторы делают решение более понятным:
// first convert line to normalized unit vector
double dx = x2 - x1;
double dy = y2 - y1;
double mag = sqrt(dx*dx + dy*dy);
dx /= mag;
dy /= mag;
// translate the point and get the dot product
double lambda = (dx * (x3 - x1)) + (dy * (y3 - y1));
x4 = (dx * lambda) + x1;
y4 = (dy * lambda) + y1;
Вы часто обнаружите, что использование векторов делает решение более ясным ...
Вот процедура из моей собственной библиотеки:
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);
}
getUnitVector()
. Тоже плохо.
- person Andrey Tyukin; 02.01.2019
Вы знаете и точку, и наклон, поэтому уравнение для новой линии:
y-y3=m*(x-x3)
Поскольку линия перпендикулярна, наклон обратный. Теперь у вас есть два уравнения, и вы можете решить их пересечение.
y-y3=-(1/m)*(x-x3)
y-y1=m*(x-x1)
y=mx+b
- m
, это наклон, который вы только что нашли, b вы можете рассчитать, используя p3. Теперь у вас есть все, что нужно для линии.
- person Thanatos; 28.11.2009
Вычислите наклон линии, соединяющей точки (x1, y1) и (x2, y2) как m=(y2-y1)/(x2-x1)
Уравнение линии, соединяющей (x1, y1) и (x2, y2) с использованием формы линейного уравнения точки-наклона, будет y-y2 = m(x-x2)
Наклон линии, соединяющей (x3, y3) и (x4, y4), будет -(1/m)
Опять же, уравнение линии, соединяющей (x3, y3) и (x4, y4) с использованием формы линейного уравнения точечного уклона, будет y-y3 = -(1/m)(x-x3)
Решите эти два линейных уравнения, решая линейное уравнение с двумя переменными, и значения x и y, которые вы получите, будут вашими (x4, y4)
Надеюсь, это поможет.
ваше здоровье
Найдите уклоны для обеих линий, скажем, это m1 и m2, тогда m1 * m2 = -1 является условием перпендикулярности.
Код функции Matlab для следующей проблемы
function Pr=getSpPoint(Line,Point)
% getSpPoint(): find Perpendicular on a line segment from a given point
x1=Line(1,1);
y1=Line(1,2);
x2=Line(2,1);
y2=Line(2,1);
x3=Point(1,1);
y3=Point(1,2);
px = x2-x1;
py = y2-y1;
dAB = px*px + py*py;
u = ((x3 - x1) * px + (y3 - y1) * py) / dAB;
x = x1 + u * px;
y = y1 + u * py;
Pr=[x,y];
end
Mathematica представила функцию RegionNearest[]
в версии 10, 2014. Эта функция может использоваться для возврата ответа на этот вопрос:
{x4,y4} = RegionNearest[Line[{{x1,y1},{x2,y2}}],{x3,y3}]
Это в основном дубликат ответа Арнкришна. Я просто хотел завершить его раздел полным фрагментом кода системы Mathematica:
m = (y2 - y1)/(x2 - x1)
eqn1 = y - y3 == -(1/m)*(x - x3)
eqn2 = y - y1 == m*(x - x1)
Solve[eqn1 && eqn2, {x, y}]
Это реализация принятого ответа на C #. Он также использует ArcGis для возврата MapPoint, поскольку это то, что мы используем в этом проекте.
private MapPoint GenerateLinePoint(double startPointX, double startPointY, double endPointX, double endPointY, double pointX, double pointY)
{
double k = ((endPointY - startPointY) * (pointX - startPointX) - (endPointX - startPointX) * (pointY - startPointY)) / (Math.Pow(endPointY - startPointY, 2)
+ Math.Pow(endPointX - startPointX, 2));
double resultX = pointX - k * (endPointY - startPointY);
double resultY = pointY + k * (endPointX - startPointX);
return new MapPoint(resultX, resultY, 0, SpatialReferences.Wgs84);
}
Спасибо Рэю, так как у меня это отлично сработало. c # arcgis
Это векторизованная функция Matlab для поиска попарных проекций m
точек на n
отрезки линии. Здесь xp
и yp
- это m by 1
векторы, содержащие координаты m
различных точек, а x1
, y1
, x2
и y2
- это n by 1
векторы, содержащие координаты начальной и конечной точек n
различных отрезков линии. Возвращает m by n
матриц, x
и y
, где x(i, j)
и y(i, j)
- координаты проекции i
-й точки на j
-ю линию.
Фактическая работа выполняется в первых нескольких строках, а остальная часть функции запускает демонстрацию самопроверки, на всякий случай, когда она вызывается без параметров. Это относительно быстро, мне удалось найти проекции 2k точек на 2k отрезков линии менее чем за 0,05 секунды.
function [x, y] = projectPointLine(xp, yp, x1, y1, x2, y2)
if nargin > 0
xd = (x2-x1)';
yd = (y2-y1)';
dAB = xd.*xd + yd.*yd;
u = bsxfun(@rdivide, bsxfun(@times, bsxfun(@minus, xp, x1'), xd) + ...
bsxfun(@times, bsxfun(@minus, yp, y1'), yd), dAB);
x = bsxfun(@plus, x1', bsxfun(@times, u, xd));
y = bsxfun(@plus, y1', bsxfun(@times, u, yd));
else
nLine = 3;
nPoint = 2;
xp = rand(nPoint, 1) * 2 -1;
yp = rand(nPoint, 1) * 2 -1;
x1 = rand(nLine, 1) * 2 -1;
y1 = rand(nLine, 1) * 2 -1;
x2 = rand(nLine, 1) * 2 -1;
y2 = rand(nLine, 1) * 2 -1;
tic;
[x, y] = projectPointLine(xp, yp, x1, y1, x2, y2);
toc
close all;
plot([x1'; x2'], [y1'; y2'], '.-', 'linewidth', 2, 'markersize', 20);
axis equal;
hold on
C = lines(nPoint + nLine);
for i=1:nPoint
scatter(x(i, :), y(i, :), 100, C(i+nLine, :), 'x', 'linewidth', 2);
scatter(xp(i), yp(i), 100, C(i+nLine, :), 'x', 'linewidth', 2);
end
for i=1:nLine
scatter(x(:, i)', y(:, i)', 100, C(i, :), 'o', 'linewidth', 2);
end
end
end
Вот решение, использующее однородные координаты, для полноты картины.
Однородные точки:
p1 = (x1,y1,1), p2 = (x2,y2,1), p3 = (x3,y3,1)
линия, проходящая через две точки, является их перекрестным произведением
l_12 := p1 x p2 = (y1-y2, x2-x1, x1*y2 - x2*y1)
Расстояние (подписанное) от точки до линии - это их скалярное произведение.
d := l_12 * p3 = x3*(y1-y2) + y3*(x2-x1) + x1*y2 - x2*y1
Вектор от p4 до p3 в d раз больше вектора нормали l_12, деленного на квадрат длины вектора нормали.
n2 := (y1-y2)^2 + (x2-x1)^2
p4 := p3 + d/n2*(y1-y2, x2-x1, 0)
Примечание: если вы разделите l_12 на длину вектора нормали
l_12: = l_12 / sqrt ((y1-y2) ^ 2 + (x2-x1) ^ 2)
расстояние d будет евклидовым расстоянием.
Сначала вычислите линейную функцию, определяемую точками (x1,y2),(x2,y2)
.
Мы получили:
y1 = mx+b1 where m and b1 are constants.
Этот шаг легко вычислить по формуле линейной функции между двумя точками.
Затем вычислите линейную функцию y, проходящую через (x3, y3).
Наклон функции равен -m, где m - наклон y1.
Затем вычислите const b2 по координатам точки (x3, y3).
Получаем y2 = -mx + b2, где m и b2 - константы.
Последнее, что нужно сделать, это найти пересечение y1, y2. Вы можете найти x, решив уравнение: -mx+b2 = mx+b1
, затем поместите x в одно из уравнений, чтобы найти y.