ampholyte a écrit:Merci pour cette réponse,
Est-ce que cette algorithme est toujours vérifiée ou existe-t-il des cas particuliers ?
Existe-t-il également un algorithme plus facilement intégrable en code .
Merci encore pour ta réponse claire et rapide =)
Dlzlogic a écrit:Dans la réalité, le problème est un peu plus compliqué.
La raison tient au fait que tous les calculs en informatique sont faits avec un nombre fini de chiffres significatifs. Dans ce domaine, on ne peut pas tester l'égalité de deux réels, parce un réel, ça n'existe pas en informatique.
Dlzlogic a écrit:J'ai regardé mon module, je ne calcule pas les intersections, mais je repère le segment qui intersecte la verticale passant par le point.
Dlzlogic a écrit:Il y a aussi une autre technique qu'il ne faut pas négliger, qui consiste à trouver le côté le plus proche du point. Si on a pris la précaution d'orienter le polygone dans un sens conventionnel, la position du point, à droite ou à gauche du segment donnera le résultat.
Skullkid a écrit:On peut tout à fait tester l'égalité entre deux flottants, ou au pire comparer la différence de deux flottants à un epsilon petit donné...
Il peut n'y avoir aucun côté du polygone qui intercepte la verticale, ou plusieurs... Mais une fois que tu les as, tu fais quoi ?
Cette technique ne marche que si le polygone est convexe, ou alors tu as une définition spéciale de "côté le plus proche d'un point".
float c=3.0/7.0;
if (c == 3.0/7.0) printf("Egal\n");
else printf("Différent !!\n");
Dlzlogic a écrit:Je suppose que tu as une grande expérience de ce type de test.
Bien-sûr on peut tester si 2 flottants sont égaux, mais la question n'est pas de savoir si on peut ou non le faire, mais de savoir si le test est toujours valide.
Dlzlogic a écrit:Je n'ai pas tout détaillé, j'avoue que je ne souviens plus des détails, mais si ça intéresse notre ami, je lui donnerai volontiers ma fonction.
Dlzlogic a écrit:Il est vrai que la notion "côté plus proche d'un point " serait à préciser. Je ne pense pas avoir dit que la projection du point sur le côté devait appartenir au segment.
Dlzlogic a écrit:C'est une question difficile qu'on ne peut pas régler en 5 lignes.
Que penses-tu par exemple des polygones avec trou?
ampholyte a écrit:J'aurais juste à parcourir l'ensemble des points de mon polygone B pour savoir s'il est inclus ou non dans A
Aurais-je dit qu'il ne fallait pas gérer l'epsilon? C'est même indispensable lorsqu'on travaille avec des valeur qui ne sont pas que des entiers. Et c'est pas "au pire" c'est indispensable.
Je n'ai pas compris en quoi ce test n'est pas correct.
Ah j'ai compris, c'est le 'f' qui manque à ton avis ? Je ne sais pas quel langage impose ce suffixe 'f'.
Mon compilateur accepte aussi le 'f', il est vrai que dans ce cas la comparaison est bonne, mais si tu comptes sur ces astuces de langages, bonjour les dégâts.
Naturellement tu ignores l'origine de ce test, pourquoi son auteur a éprouvé le besoin de le mettre etc. Tu as juste cherché à montrer que j'avais tort.
D'ailleurs, as-tu la moindre idée de la raison du résultat "différent" ?
bool TLigne::AppZone(TPointLong pXY, bool strict) const
{
if (prem == NULL) return false; // pas forcément une erreur
// version de base
// la version écran est identique, mais le calcul est fait en pixels
// un point appartenant au contour est considéré comme intérieur
// la ligne peut être une Zone (Aire > 0)
// ou une ligne fermée
//if (xm == 625214269 && ym ==151169720)
//{
// bool imp=true;
//}
//Todo:On pourrait rajouter les test de tolérence de bord (Zones)
long xm=pXY.x;
long ym=pXY.y;
long oyH=MAXLONG; // Point en haut donc y plus grand que ym
long oyB=-MAXLONG; // Point en bas donc y plus petit que ym
long x1,y1,x2,y2;
long yc;
//fprintf(espion,"AppZone xm=%d ym=%d \n",xm,ym);
//fprintf(espion,"Appel de Aire 11: prem(%p)\n",LitPrem());
//fflush(espion);
float A=LitAire(true);
if (A == -1) return false;
Point3D *pt1=PtPrem(); //PtSuiv((TMatricule*)NULL);
x1=pt1->ValX();
y1=pt1->ValY();
Point3D *pt2, *pt1H=NULL, *pt2H=NULL, *pt1B=NULL, *pt2B=NULL ;
SListe *lpt=prem;
char cma='*';
for (lpt=lpt->suiv; lpt; lpt=lpt->suiv)
{
pt2=PtCour(lpt);
x2=pt2->ValX();
y2=pt2->ValY();
if (strchr("*#",cma)) // le code du point pt1
{
//fprintf(espion,"AppZone x1=%d y1=%d x2=%d y2=%d\n",x1,y1,x2,y2);
if (( xm >= x1 && xm x2 && xm labs (xm-x1))
{
double xm1=xm-x1;
double y21=y2-y1;
double x21=x2-x1;
double ym21=xm1*y21/x21;
yc=y1+ym21;
}
else
{
double xm1=xm-x2;
double y12=y1-y2;
double x12=x1-x2;
double ym12=xm1*y12/x12;
yc=y2+ym12;
}
// pour résoudre le problème de points sur la ligne
if (strict)
{
if (labs(ym-yc) oyB)
{
oyB=yc;
pt1B=pt1;
pt2B=pt2;
}
if (yc-tUB > ym && yc/*+tUB*/ oyB)
{
oyB=yc;
pt1B=pt1;
pt2B=pt2;
}
if (yc+tUB > ym && yc-tUB cma;
}
if (oyH != MAXLONG && oyB != -MAXLONG )
{
int IPV=IProdVect(pXY,pt1H->XY(),pt2H->XY());
if ( A > 0 && IPV > 0 || A XY(),pt2B->XY());
if ( A > 0 && IPV > 0 || A < 0 && IPV < 0) return true;
else return false;
}
else return false;
}
else return false;
}
ce n'est pas indispensable de passer par de l'epsilone
Il y a un point incontournable, c'est la comparaison de deux flottants, qu'ils soient float, double ou big, ça ne change rien, cette comparaison ne doit être faite qu'avec un epsilon
il faut prendre des précautions
Dlzlogic a écrit:
- Code: Tout sélectionner
[...]
if (labs(xm-x2) > labs (xm-x1))
{
double xm1=xm-x1;
double y21=y2-y1;
double x21=x2-x1;
double ym21=xm1*y21/x21;
yc=y1+ym21;
}
else
{
double xm1=xm-x2;
double y12=y1-y2;
double x12=x1-x2;
double ym12=xm1*y12/x12;
yc=y2+ym12;
}
[...]
Dlzlogic a écrit:J'ai regardé mon module, je ne calcule pas les intersections, mais je repère le segment qui intersecte la verticale passant par le point.
Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 51 invités
Tu pars déja ?
Identification
Pas encore inscrit ?
Ou identifiez-vous :