Bon, je pense qu'il faut essayer de rester calme.
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. L'expression "le cas échant" est un peu étonnante : quand introduira-t-on ce test, qu'est-ce qui provoquera la décision de l'introduire.
Il en est de même pour un point très proche d'un côté. Il est exactement dessus, à droite ou à gauche ? Il est fréquent et normal de prévoir la possibilité d'une bande axée sur le côté, mais ça ne fait que transposer ce problème.
Naturellement le test avec les intersection est valable, mais il ne faut pas oublier que si on fait une comparaison de deux flottants, il faut prendre des précautions. C'est le seul point sur lequel j'ai voulu insister.
Le test que j'ai donné, c'est pas moi qui l'ai fait. Celui qui l'a fait s'en est servi pour permettre de visualiser quelque-chose, pas plus. Ce n'est pas parce que un test peut être détourné que ce qu'il essaye de montrer est faux.
Si vous voulez un autre test, il suffit de prendre 2 droites, calculer leur intersection, Ca donne un point et tester si la distance de ce point à chacune des droites est égale à 0.
Je sais que ce problème est difficile. Une fois résolu, la position d'un polygone par rapport à un autre polygone, c'est de la rigolade.
- Code: Tout sélectionner
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;
}
Bien sûr je détaillerai et j'expliquerai tout ce qu'on veux.