IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Mathématiques Discussion :

Distance d'un point à un segment de droite


Sujet :

Mathématiques

  1. #1
    Membre éprouvé Avatar de defluc
    Homme Profil pro
    Architecte
    Inscrit en
    Mai 2002
    Messages
    1 383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : Belgique

    Informations professionnelles :
    Activité : Architecte

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 383
    Points : 1 199
    Points
    1 199
    Par défaut Distance d'un point à un segment de droite
    Bonjour,

    Pour trouver la distance d'un point à un segment de droite, j'utilise la fonction suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Function DistPntSegm(XPnt, YPnt, Xb, Yb, Xe, Ye : Double) : Double;
    Var
     TestX : Double;
    begin
       Result := 1.7 * Power(10,308);
       TestX := PerpendFoot(XPnt, YPnt, Xb, Yb, Xe, Ye)[1];
       if PointOnSegment(Xb, Xe, TestX) then
          Result := DistPntLine(XPnt, YPnt, Xb, Yb, Xe, Ye);
    end;
    Dans laquelle je cherche les coordonnées du pied de la perpendiculaire abaissée de ce point sur la droite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Function PerpendFoot(XPnt, YPnt, Xb, Yb, Xe, Ye : Double) : TPntArray;
    Var
      A, B, C : Double;
    begin
      Result[1] := 0;
      Result[2] := 0;
      A := Xb - Xe;
      if A = 0 then exit;
      A := (Yb - Ye)/A; // b = begin e = ending
      B := (Xb*Ye-Xe*Yb)/(Xb-Xe);
      C := (YPnt-A*XPnt-B)/(1+Sqr(A));
      Result[1] := XPnt + A*C;  //  Coordonnée X
      Result[2] := YPnt - C;      //  Coordonnée Y 
    end;
    . Puis, je vérifie si ce point est bien sur la droite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Function PointOnSegment(Xb, Xe, XPnt : Double) : Boolean;
    Var
      A: Double;
    begin
      Result := False;
      if A = 0 then exit;
      A:= (Xe-Xb);
      if A > 0 then A := (XPnt-Xb)/A;
      if Not((A<0) or (A > 1)) then Result := True
                               else result := False;
    end;
    . Et enfin, si c'est le cas, je calcule la distance du point à la droite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Function DistPntLine(XPnt, YPnt, Xb, Yb, Xe, Ye : Double) : Double;
    Var
      A, B, C, L : Double;
    begin
      A := Yb - Ye;
      B := Xe - Xb;
      C := (Xb*Ye)-(Xe*Yb);
      L := Sqrt(Sqr(Xb-Xe)+Sqr(Yb-Ye));
      Result := Abs(((A*XPnt)+(B*YPnt)+ C)/L);
    end;
    Les résultats ne sont pas satisfaisants pour des raisons que j'attribue aux comparaisons de valeurs en virgule flottante.
    Cela m'aiderait si quelqu'un pouvait me proposer un algo donnant satisfaction à 100%.

    Merci d'avance

  2. #2
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    Légère adaptation du code de la classe QuadEdge de l'implémentation de la Triangulation de Delaunay

    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    /**
     * Return the distance from a point to a segment
     *
     * @param ps,pe the start/end of the segment
     * @param p the given point
     * @return the distance from the given point to the segment
     */
    private static double distanceToSegment(Point ps, Point pe, Point p) {
     
    	if (ps.x==pe.x && ps.y==pe.y) return distance(ps,p);
     
    	int sx=pe.x-ps.x;
    	int sy=pe.y-ps.y;
     
    	int ux=p.x-ps.x;
    	int uy=p.y-ps.y;
     
    	int dp=sx*ux+sy*uy;
    	if (dp<0) return distance(ps,p);
     
    	int sn2 = sx*sx+sy*sy;
    	if (dp>sn2) return distance(pe,p);
     
    	double ah2 = dp*dp / sn2;
    	int un2=ux*ux+uy*uy;
    	return Math.sqrt(un2-ah2);
    }
     
    /**
     * return the distance between two points
     *
     * @param p1,p2 the two points
     * @return dist the distance
     */
    private static double distance(Point p1, Point p2) {
    	int d2 = (p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y);
    	return Math.sqrt(d2);
    }

  3. #3
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 77
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Points : 1 913
    Points
    1 913
    Par défaut
    On peut aussi faire ça ainsi:
    On utilise une notion: celle de puissance d'un point par rapport à une droite:
    Si ux+vy+w=0 est l'équation de la droite D
    et a et b sont les coordonnées du point M
    Puissance(M,D) = ua+vb+w par définition.
    Cette notion a deux intérêts:
    Elle permet de distinguer les deux demi-plans séparé par la droite en:
    P(M,D) >0 et P(M,D)<0
    La distance d'un point à une droite s'exprime aussi au moyen de la puissance:
    d(M,D)=p(M,D)/sqrt(u^2+v^2)
    La méthode est alors la suivante.
    Si [BE] est le segment, on calcule les équations des deux perpendiculaires à [BE]
    passant par B et E, c'est immédiat, elle sont du type ux+vy+w=0 où u et v sont les coordonnées du vecteur BE, le w s'obtenant en traduisant l'appartenance de B (resp E) aux droites en question.
    Appelons D1 et D2 ces perpendiculaires.
    Tout se résume maintenant à savoir la position de M par rapport à ces deux droites, pour cela on calcule:
    P(M,D1) P(M,D2) P(B,D2) P(E,D1)
    Il suffit ensuite de comparer les signes de ces quantités pour savoir si M est à l'intérieur de la bande délimitée par D1 et D2 où bien à l'expérieur du côté D1 ou à l'extérieur côté D2.
    PS: Ceci est plus facile à FAIRE qu'à DIRE
    Avantages: Le calcul des puissances ne nécessite ni division ni racines carrées.
    Il n'est pas nécessaire de connaitre la projection de M sur (BE), autrement dit la discrimination se fait uniquement sur des sommes et des produits. Bien entendu quand le cas est reconnu il faut calculer une racine et faire une division pas moyen d'y échapper quelle que soit la méthode.

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    415
    Détails du profil
    Informations personnelles :
    Âge : 58
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 415
    Points : 486
    Points
    486
    Par défaut
    Pratiquement la même que Pseudocode, en fait... sauf pour la fin (je n'ai pas compris la projection ? )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
     
            /// <summary>
            /// Retourne la distance du point P au segment AB.
            /// Si A et B sont confondus, retourne la distance de A a P
            /// Si la projection perpendiculaire du point sur la droite contenant AB est hors de AB, retourne double.PositiveInfinity.
            /// Sinon retourne la distance du point à la droite contenant AB.
            /// </summary>
            /// <param name="P"></param>
            /// <param name="A"></param>
            /// <param name="B"></param>
            /// <returns></returns>
            static double DistancePaAB( Point P, Point A, Point B )
            {
                Point AB = new Point() { X = B.X - A.X, Y = B.Y - A.Y }; // Vecteur AB
                double scalaireABAB = Scalaire( AB, AB );
     
                Point AP = new Point() { X = P.X - A.X, Y = P.Y - A.Y }; // Vecteur AP
     
                // A et B sont confondus
                if ( scalaireABAB <= double.Epsilon )
                {
                    return Norme( AP );
                }
                else
                {
                    double scalaireAPAB = Scalaire( AP, AB );
     
                    // Si le produit scalaire est négatif : P est 'avant' A dans le sens AB.
                    // S'il est plus grand que le scalaire AB AB : P est 'apres' B dans le sens AB.
                    // Dans les deux cas, la projection de P sur la droite contenant AB est hors de AB
                    if ( (scalaireAPAB < 0d) || (scalaireAPAB > scalaireABAB) )
                    {
                        return double.PositiveInfinity;
                    }
                    // Sinon la distance est la composante scalaire de AP sur le vecteur perpendiculaire à AB
                    else
                    {
                        Point perpAB = new Point() { X = AB.Y, Y = -AB.X }; // Un vecteur perpendiculaire à AB
     
                        return Math.Abs( Scalaire( AP, perpAB ) / Math.Sqrt( scalaireABAB ) );
                    }
                }
            }
     
            static double Norme( Point V )
            {
                return Math.Sqrt( (V.X * V.X) + (V.Y * V.Y) );
            }
     
            static double Scalaire( Point V1, Point V2 )
            {
                return (V1.X * V2.X) + (V1.Y * V2.Y);
            }

  5. #5
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 77
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Points : 1 913
    Points
    1 913
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    # -*- coding: cp1252 -*-
    import math
     
    # calcule la distance du point M de coordonnées xM,yM, au segment BE
    # B coordonnées xB,yB  E cordonnes xE,yE
    # en utilisant la puissance d'un point par rapport à une droite
     
    def distance(xB,yB,xE,yE,xM,yM):
        # coordonnées a,b du vecteur EB
        a=xE-xB
        b=yE-yB
        # équation de la perpendiculaire D1 en B à (EB): ax+by+w1
        w1=-a*xB-b*yB
        # équation de la perpendiculaire D2 en E à (EB): ax+by+w2
        w2=-a*xE-b*yE
        # équation de la droite (EB) : bx-ay+w3
        w3= a*yB-b*xB
        #puissance de M par rapport à D1
        PMD1=a*xM+b*yM+w1
        # puissance de M par rapport à D2
        PMD2=a*xM+b*yM+w2
        #puissance de B par rapport à D2
        PBD2=a*xB+b*yB+w2
        #puissance de E par rapport à D1
        PED1=a*xE+b*yE+w1
        # A ce stade encore ni racine ni quotient
        if PMD1*PED1 <0: #M et E de part et d'autre de D1
            return math.sqrt((xM-xB)*(xM-xB)+(yM-yB)*(yM-yB)) # pas de quotient
        if PMD2*PBD2 <0: #M et B de part et d'autre de D2
            return math.sqrt((xM-xE)*(xM-xE)+(yM-yE)*(yM-yE)) # idem
        # sinon
        return abs(b*xM-a*yM+w3)/math.sqrt(a*a+b*b) # là rien à faire
     
     
    def main():
        xB=yB=1
        xE=yE=2
        xM=yM=0
        print distance(xB,yB,xE,yE,xM,yM)
        xM=1
        print distance(xB,yB,xE,yE,xM,yM)
        xM=2
        print distance(xB,yB,xE,yE,xM,yM)
        xM=3
        print distance(xB,yB,xE,yE,xM,yM)
    if __name__ == '__main__':
        main()

  6. #6
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    Citation Envoyé par Alikendarfen Voir le message
    Pratiquement la même que Pseudocode, en fait... sauf pour la fin (je n'ai pas compris la projection ? )
    Tu as raison, c'était pas très clair. J'ai modifié le code pour que ca soit plus compréhensible.





    ==> |AH|² = (AB.AC)² / |AB|²

    Pythagore : AC²=AH²+HC²

    ==> distance(H,C) = Racine( AC² - AH² )

  7. #7
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Points : 17 923
    Points
    17 923
    Billets dans le blog
    2
    Par défaut
    je re-reprends mes citations :

    http://www.developpez.net/forums/sho...7&postcount=10

    Cette fois c'est le point 1.02

  8. #8
    Membre éprouvé Avatar de defluc
    Homme Profil pro
    Architecte
    Inscrit en
    Mai 2002
    Messages
    1 383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : Belgique

    Informations professionnelles :
    Activité : Architecte

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 383
    Points : 1 199
    Points
    1 199
    Par défaut
    Je vous remercie pour vos sources.
    J'ai essayé de les transposer en Delphi mais les résultats ne correspondent pas à mes attentes. Peut-être parce que ma "traduction" est erronée.

  9. #9
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    Citation Envoyé par defluc Voir le message
    Je vous remercie pour vos sources.
    J'ai essayé de les transposer en Delphi mais les résultats ne correspondent pas à mes attentes. Peut-être parce que ma "traduction" est erronée.
    L'autre solution c'est qu'on se soit tous plantés... mais franchement, ca ne serait pas de bol.

  10. #10
    Membre éprouvé Avatar de defluc
    Homme Profil pro
    Architecte
    Inscrit en
    Mai 2002
    Messages
    1 383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : Belgique

    Informations professionnelles :
    Activité : Architecte

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 383
    Points : 1 199
    Points
    1 199
    Par défaut
    Voici ma source en Delphi qui «laisse passer» des cas qui ne le devraient pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    Function DistPntToSegment(Xp, Yp, Xb, Yb, Xe, Ye : Double) : Double;
    Var
      ScalaireABAB, ScalaireAPAB, ABx, ABy, APx, APy : Double;
    begin
      ABX := Xe - Xb;
      ABY := Ye - Yb;
      APX := Xp - Xb;
      APY := Yp - Yb;
      if (Xe = Xb) and (Ye = Yb) then
      begin   //  A et B son confondus
        Result := Abs(Sqrt(Sqr(Xp-Xb)+Sqr(Yp-Ye)));;
        exit;
      end;
      ScalaireABAB := (ABX * ABX) + (ABY * ABY);
      ScalaireAPAB := (APX * ABX) + (APY * ABY);
      if (ScalaireAPAB < 0) And (ScalaireAPAB > ScalaireABAB) then
      begin   // La projection de P sur la droite se fait en dehors du segment
        Result := 1.7 * Power(10,308);
        exit;
      end;
      Result := Abs(((APX * ABY) + (APY * -ABX))/Sqrt(ScalaireABAB));
    end;

  11. #11
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 77
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Points : 1 913
    Points
    1 913
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      begin   // La projection de P sur la droite se fait en dehors du segment
        Result := 1.7 * Power(10,308);
        exit;
      end;
    Et alors ? Est ce une raison pour retourner une valeur astronomique ???
    Result := 1.7 * Power(10,308);
    As tu seulement lu nos nombreuses réponses ?

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    415
    Détails du profil
    Informations personnelles :
    Âge : 58
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 415
    Points : 486
    Points
    486
    Par défaut
    Citation Envoyé par defluc Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Function DistPntToSegment(Xp, Yp, Xb, Yb, Xe, Ye : Double) : Double;
    Var
    ....
     
      if (ScalaireAPAB < 0) And (ScalaireAPAB > ScalaireABAB) then
    ...
    Tu as mis "And" au lieu de "Or"

  13. #13
    Membre éprouvé Avatar de defluc
    Homme Profil pro
    Architecte
    Inscrit en
    Mai 2002
    Messages
    1 383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : Belgique

    Informations professionnelles :
    Activité : Architecte

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 383
    Points : 1 199
    Points
    1 199
    Par défaut
    Pour Alikendarfen : le résultat reste erroné même après la modification
    if (ScalaireAPAB < 0) And (ScalaireAPAB > ScalaireABAB) then
    Il doit donc y avoir une autre erreur dans ma source.

    Pour Zavonen : Bon d'accord, «1.7 * Power(10,308)», c'était rapport à la notion d'infini que je pourrais effectivement limiter au maximum probable que mon application ne devrait pas rencontrer comme distance.

    Pour ton deuxième commentaire, j'ai lu toutes les réponses mais les traductions en Delphi ne me donnent pas encore de résultats probants.

    Concernant ta méthode, voici ce que j'ai codé pour ce qui est de
    Si [BE] est le segment, on calcule les équations des deux perpendiculaires à [BE] passant par B et E
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Function PntToSegmByPower(Xp, Yp, Xb, Yb, Xe, Ye : Double) : Double;
    Var
      a, b, c, cp, Perp1, Perp2 : Double;
    begin
      a := Ye - Xb;        // Coordonnées de l'équation paramétrique du vecteur sont (a;b)
      b := Xb - Xe;
      c := Xe*Yb - Xb-Ye;
      cp := b*Xb - a*Yb; 
      Perp1 := -b*Xb + a*Yb + c;  // Le vecteur perpendiculaire mené de (Xb;Yb) est (-b*Xb;a*Yb)
      Perp2 := -b*Xe + a*Ye + c;  // Le vecteur perpendiculaire mené de (Xe;Ye) est (-b*Xe;a*Ye)
    end;
    Mais pour la suite, je coince

  14. #14
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Points : 17 923
    Points
    17 923
    Billets dans le blog
    2
    Par défaut
    on t'as dit qu'avec les équations paramétriques ce serait plus dur..

    Dans la référence que j''ai pointé, tu as directement le paramètre r qui te donne la solution...

    C'est pourtant pas compliqué

  15. #15
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    Citation Envoyé par defluc Voir le message
    Pour Zavonen : Bon d'accord, «1.7 * Power(10,308)», c'était rapport à la notion d'infini que je pourrais effectivement limiter au maximum probable que mon application ne devrait pas rencontrer comme distance.
    Ce n'était pas le sens de la remarque de Zavonen.

    ce n'est pas parce que la projection du point ne tombe pas entre les extrémités du segment que la distance est forcément infinie !!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    ^
    |
    | P  A        B
    | X  X--------X
    |
    +---------------->
     
    Distance(P,[AB]) = 3

  16. #16
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 77
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Points : 1 913
    Points
    1 913
    Par défaut
    Ce n'était pas le sens de la remarque de Zavonen.
    Merci Pseudocode, il y en a au moins qui suit ...
    Cela dit, je pense qu'on peut tout reprendre, je veux dire n'importe laquelle des méthodes présentées ici dans cette discussion pour résoudre l'autre problème:
    Distance d'un point à un polygone CONVEXE; C'est à mon avis le minimum des distances aux côtés considérés comme des segments.
    Preuve:
    Soit T le point du polygone réalisant le minimum de distance avec M. Ce point existe (pour des raisons de compacité) mais n'est pas forcément unique.
    Le segment [TM] contient forcément un point C du contour du polygone et la distance MC est plus petite que la distance MT donc la distance de M au polygone est égale à la distance au pourtour. Cette distance est atteinte en un point C toujours pourra raison de compacité, (non forcément unique à nouveau), C appartient à un côté MnMn+1 il est impossible de trouver sur ce côté un point plus proche de M, cela contredirait la définition même de T. Donc la distance de M au polygone est égale à la distance de M à ce côté.
    D'où mon affirmation.
    Maintenant il n'y a plus qu'à itérer une des méthodes données sur les côtés consécutifs du polygone.

  17. #17
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    415
    Détails du profil
    Informations personnelles :
    Âge : 58
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 415
    Points : 486
    Points
    486
    Par défaut
    Citation Envoyé par pseudocode Voir le message
    Ce n'était pas le sens de la remarque de Zavonen.

    ce n'est pas parce que la projection du point ne tombe pas entre les extrémités du segment que la distance est forcément infinie !!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    ^
    |
    | P  A        B
    | X  X--------X
    |
    +---------------->
     
    Distance(P,[AB]) = 3
    Ca ce n'est qu'une question de convention, non ? Tout dépend de l'énoncé et de ce qu'on considère comme valide comme distance point / segment.

  18. #18
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 77
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Points : 1 913
    Points
    1 913
    Par défaut
    Non, il n'y a ici aucune question de convention.
    Distance d'un point M à un ensemble K dans un espace métrique E c'est par définition:
    Inf d(M,P) pour P dans K.
    Ce Inf existe toujours car les nombres d(M,P) sont minorés par 0 (théorème de la borne inférieure). En outre, comme un segment est un compact (fermé borné) et que la fonction P --> d(M,P) est continue le inf est effectivement atteint ( Il existe un P dans K tel que d(M,P)=Inf), cependant ce point peut ne pas être unique.

  19. #19
    Membre éprouvé Avatar de defluc
    Homme Profil pro
    Architecte
    Inscrit en
    Mai 2002
    Messages
    1 383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : Belgique

    Informations professionnelles :
    Activité : Architecte

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 383
    Points : 1 199
    Points
    1 199
    Par défaut
    Et bien Zavonen, j'ai suivi ton conseil et j'ai encodé ce que le lien que tu m'as gentiment renseigné propose.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    Function TMapForm.DistPntSegm(XPnt, YPnt, Xb, Yb, Xe, Ye : Double) : Double;
    Var
     Len, ParamR, ParamS, X, Y : Double;
    begin                               
      Result := 999999;
      Len := Dist2Pnts(Xb, Yb, Xe, Ye);
      ParamR := ((Xpnt - Xb)*(Xe - Xb) + (YPnt - Yb) + (Ye - Yb))/Sqr(Len);
      if (ParamR > 0) and (ParamR < 1) then
      begin
        X := Xb + ParamR * (Xe - Xb); // X point projection de Xpnt sur le segment
        Y := Yb + ParamR * (Ye - Yb); // Y point projection de Ypnt sur le segment
        ParamS := ((Yb - Ypnt)*(Xe - Xb) - (Xb - XPnt) + (Ye - Yb))/Sqr(Len);
        Result := Abs(ParamS) * Len;
      end;
    end;
    J'ai malheureusement encore des erreurs.
    La condition
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      if (ParamR > 0) and (ParamR < 1) then
    est parfois remplie alors que la projection du point est en dehors du segment.

  20. #20
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    On peut voir le code de la fonction "Dist2Pnts()" ?

Discussions similaires

  1. Calcul de distance entre un point et un segment
    Par orland dans le forum Mathématiques
    Réponses: 7
    Dernier message: 03/01/2013, 17h13
  2. Réponses: 1
    Dernier message: 02/01/2013, 16h13
  3. distance entre un point et un segment
    Par 3aychoucha dans le forum C++
    Réponses: 6
    Dernier message: 11/08/2011, 19h26
  4. Segments de droites à partir de points
    Par MetalGeek dans le forum Mathématiques
    Réponses: 7
    Dernier message: 18/02/2009, 13h43
  5. [MATH] Point par rapport à une droite
    Par teska dans le forum Mathématiques
    Réponses: 6
    Dernier message: 14/05/2003, 17h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo