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).

Était-ce utile?

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.

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top