Perpendiculaire sur une ligne à partir d'un point donné
-
06-07-2019 - |
Question
Comment puis-je dessiner une perpendiculaire sur un segment de droite à partir d'un point donné? Mon segment de droite est défini comme (x1, y1), (x2, y2), si je trace une perpendiculaire à partir d'un point (x3, y3) et que celle-ci se rencontre au point (x4, y4). Je veux savoir ceci (x4, y4).
La solution
J'ai résolu les équations pour vous:
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)
Où ^ 2 signifie carré
Autres conseils
De wiki :
En algèbre, pour toute équation linéaire y = mx + b, les perpendiculaires seront tous avoir une pente de (-1 / m), le contraire réciproque de la pente d'origine. Il est utile pour mémoriser le slogan " to trouver la pente de la perpendiculaire ligne, retournez la fraction et changez le signe. " Rappelons que tout nombre entier un est lui-même sur un, et peut être écrit comme (a / 1)
Pour trouver la perpendiculaire d'une donnée ligne qui passe aussi par un point particulier (x, y), résoudre le équation y = (-1 / m) x + b, en remplaçant dans les valeurs connues de m, x et y à résoudre pour b.
La pente de la ligne, m, à travers (x1, y1) et (x2, y2) est m = (y1 - y2) / (x1 - x2)
Je suis d'accord avec peter.murray.rust, les vecteurs rendent la solution plus claire:
// 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;
Vous constaterez souvent que l'utilisation de vecteurs rend la solution plus claire ...
Voici une routine de ma propre bibliothèque:
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);
}
}
Vous devrez implémenter Real2 (un point), Vector2 et dotProduct (), mais ceux-ci doivent être simples:
Le code ressemble alors à quelque chose comme:
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);
La bibliothèque (org.xmlcml.euclid) se trouve à: http://sourceforge.net/projects/cml/
et il existe des tests unitaires qui exerceront cette méthode et vous montreront comment l'utiliser.
@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);
}
Vous connaissez le point et la pente, l'équation de la nouvelle ligne est la suivante:
y-y3=m*(x-x3)
Puisque la ligne est perpendiculaire, la pente est l’inverse négatif. Vous avez maintenant deux équations et pouvez résoudre leur intersection.
y-y3=-(1/m)*(x-x3)
y-y1=m*(x-x1)
Calcule la pente de la ligne joignant les points (x1, y1) et (x2, y2) comme m = (y2-y1) / (x2-x1)
L'équation de la ligne joignant (x1, y1) et (x2, y2) à l'aide de la forme point-pente de l'équation de la ligne serait y-y2 = m (x-x2)
La pente de la ligne joignant (x3, y3) et (x4, y4) serait - (1 / m)
Encore une fois, l'équation de la ligne joignant (x3, y3) et (x4, y4) en utilisant la forme point-pente de l'équation de la ligne, serait y-y3 = - (1 / m) (x-x3)
Résolvez ces deux équations linéaires en résolvant une équation linéaire à deux variables et les valeurs de x et y que vous obtiendrez seraient votre (x4, y4)
J'espère que cela vous aidera.
acclamations
Découvrez les pistes pour les deux lignes, dites pentes sont m1 et m2 puis m1 * m2 = -1 est la condition pour perpendicularité.
Code de fonction Matlab pour le problème suivant
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 a introduit la fonction RegionNearest []
dans la version 10, 2014. Cette fonction peut être utilisée pour renvoyer une réponse à cette question:
{x4,y4} = RegionNearest[Line[{{x1,y1},{x2,y2}}],{x3,y3}]
Ceci est principalement un duplicata de la réponse d'Arnkrishn. Je voulais juste compléter sa section avec un extrait de code complet de Mathematica:
m = (y2 - y1)/(x2 - x1)
eqn1 = y - y3 == -(1/m)*(x - x3)
eqn2 = y - y1 == m*(x - x1)
Solve[eqn1 && eqn2, {x, y}]
Ceci est une implémentation C # de la réponse acceptée. Il utilise également ArcGis pour renvoyer un MapPoint, comme c’est ce que nous utilisons pour ce projet.
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);
}
Merci à Ray car cela a parfaitement fonctionné pour moi. c # arcgis
Il s'agit d'une fonction Matlab vectorisée permettant de rechercher des projections paires de points m
sur des segments de ligne n
. Ici xp
et yp
sont des vecteurs m par 1
contenant les coordonnées de m
points différents, et x1
, y1
, x2
et y2
sont des vecteurs n par 1
contenant les coordonnées des points de départ et d'arrivée de n
différents segments de ligne.
Il retourne les matrices m par n
, x
et y
, où x (i, j)
et y (i, j)
sont les coordonnées de projection du i
-th point sur la j
-th line.
Le travail réel est effectué dans les premières lignes et le reste de la fonction exécute une démonstration automatique, juste au cas où elle est appelée sans paramètre. C’est relativement rapide, j’ai réussi à trouver des projections de 2k points sur des segments de ligne de 2k en moins de 0.05s.
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