Comparer coordonnées / TPoint

Résolu
Messages postés
36
Date d'inscription
vendredi 31 décembre 2004
Statut
Membre
Dernière intervention
8 juillet 2007
-
Messages postés
600
Date d'inscription
samedi 8 juin 2002
Statut
Membre
Dernière intervention
6 avril 2010
-
Je possède un quadrilatère ayant une forme ressemblant à celle d'un diamant ( -> "<>" ),
Je possède une coordonnée, et je souhaiterai savoir si cette coordonnée se situe dans ce quadrilatère ( je connais les coordonnées des 4 sommets ).

Je n'ai vu que des fonctions pour savoir si les points sont égaux, mais aucun pour comparer leur grandeur ( > & < ).

Merci bien.

10 réponses

Messages postés
436
Date d'inscription
jeudi 9 janvier 2003
Statut
Membre
Dernière intervention
5 février 2015

bonjour,

il faut utiliser les fonctions régions "CreatePolygonRgn" et "PtInRegion"

ça permet d'utiliser toutes les formes de figure que tu veux

Exemple concret pour voir si le point "Cible" est situé dans le "diamant" :


<hr />
var
diamant:array [1..4] of TPoint;
Cible:TPoint;
HR:HRGN;
begin
     diamant[1].x:= 10; diamant[1].y:=  0;
     diamant[2].x:= 20; diamant[2].y:= 10;
     diamant[3].x:= 10; diamant[3].y:= 20;
     diamant[4].x:=  0; diamant[4].y:= 10;

     Cible.x:=10; Cible.y:=10;



     HR:=CreatePolygonRgn(diamant,4,WINDING);
     if PtInRegion(HR,Cible.x,Cible.y) then  showmessage('dedans') else showmessage('dehors');
end;


<hr />

A+

DrJerome
Messages postés
2527
Date d'inscription
jeudi 15 janvier 2004
Statut
Membre
Dernière intervention
16 octobre 2019
18
Salut,
C'est un problème de géométrie.
Tu calcules les équations des 4 droites.
Puis, pour être dans le quadrilatère, ton point doit à la fois être en dessous des 2 droites supérieures et au dessus des 2 droites inférieures.

Pour les formules:
http://perso.ensad.fr/ari/davidov/prog/encarts/droite.htm


 
Messages postés
1606
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
25 juillet 2014
12
salut,

j'ai fait quelques s rapprocahant dans le programme videosurveillance
dans l'unité choisevideo ou je teste la collision entre une caméra et
la poubelle (en fait l'angle supérieur  gauche de l'icone caméra
et le rectangle de l'image de la poubelle ça donnait ça:

Function TChoiceVideo.TestTrash(Sender: TObject; X, Y: Integer):boolean;
var H,B:Tpoint;
j:integer;
Hnt1:string;
flag:boolean;
// videoname:array[0..6] of string ;

begin
//**********on recupere la device
with sender as TControl do Hnt1:=Hint;
//*********on l'efface éventuellement de l'ecran
for j := 1 to 4 do
with Timage(findcomponent('IScreen'+inttostr(j))) do
begin
if Hint=Hnt1 then Hint:='';
end;
Result:=False;

/***** on récupère le coordonnées de la poubelle
with Trash do
begin
H.X:=Left;
H.Y:=Top;
B.X:=Left+Width;
B.Y:=Top+Height;
end;
with sender as TControl do
begin
Hnt1:=Hint;
visible:=true;

/*****le test est ICI
if (Top>H.Y)
and(left>H.X)
and(top-1 then begin flag:=true;end;
// end;
if flag then Shape1.Brush.Color:=clred else Shape1.Brush.Color:=clBtnFace;
visible:=flag;
// tag:=0;
result:=true;
end else Shape1.Brush.Color:=clBtnFace;
end;
end;


il y a beaucoup de chose ici qui ne te seront pas utiles car je pouvais déplacer plusieurs objet différents


@+

jlen
Messages postés
36
Date d'inscription
vendredi 31 décembre 2004
Statut
Membre
Dernière intervention
8 juillet 2007

Merci de vos réponses, j'avais déjà essayer ta technique jlen100 malhereusement trop imprécise pour les objets non rectangulaires/carré.

Je vais essayer de me pencher sur ta proposition Caribensila mais elle est bien compliquée !
Messages postés
1606
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
25 juillet 2014
12
il suffit de rajouter une condition au test pour savoir si le point est
à droite ou à gauche de la droite joignant le sommet opposés

@+

jlen
Messages postés
436
Date d'inscription
jeudi 9 janvier 2003
Statut
Membre
Dernière intervention
5 février 2015

regarde dans l'aide de l'api il y a d'autres fonctions rgn (régions) intéressantes (ellipses etc...)

DrJerome
Messages postés
36
Date d'inscription
vendredi 31 décembre 2004
Statut
Membre
Dernière intervention
8 juillet 2007

Merci à tous,
DRJEROME grand merci, les régions étaient pile poil ce qu'il fallait.

A la prochaine ;)
Messages postés
436
Date d'inscription
jeudi 9 janvier 2003
Statut
Membre
Dernière intervention
5 février 2015

Dernière précision ça ne prend en compte que ce qui est dans la forme (au sens strict)


càd que ce qui est pile-poil sur la ligne du pourtour de la forme n'est pas considéré "dedans" (ou alors il faut augmenter de 1 pixel le contour de la forme...)

DrJerome
Messages postés
600
Date d'inscription
samedi 8 juin 2002
Statut
Membre
Dernière intervention
6 avril 2010
1
Je rajoutterais au source de DRJEROME:

DeleteObject(HR)

à la fin (surtout si la fonction est susceptible d'être appelée beaucoup de fois). Ca sert à libérer la mémoire allouée par Windows.

Sinon, si le quadrilatère ABCD dans lequel tu veux tester la présence du point P est un parallélogramme (en particulier un losange) il y a une façon plus rapide (en connaissant les coordonnées des 3 points A,B et D):

function Test(P,A,B,D:TPoint):Boolean;
var
r,u,v:Integer;
begin
Result:=False;
r:=(D.X-A.X)*(B.Y-A.Y)-(B.X-A.X)*(D.Y-A.Y);
u:=(B.Y-A.Y)*(P.X-A.X)-(D.X-A.X)*(P.Y-A.Y);
v:=(D.Y-A.Y)*(P.X-A.X)-(B.X-A.X)*(P.Y-A.Y);
Result:=(u>=0) and (u<=r) and (v>=0) and (v<=r);
end;

Si je ne me suis pas trompé, cette fonction calcule les coordonnées du point P dans la base (A,AB,AD). Ces coordonnées sont stockées dans u et v, on vérifie qu'elles sont comprises entre 0 et 1, c'est à dire dans le parallélogramme (la fonction est un peu optimisée pour ne pas avoir à diviser par r).
Messages postés
600
Date d'inscription
samedi 8 juin 2002
Statut
Membre
Dernière intervention
6 avril 2010
1
Petite correction:

function Test(P,A,B,D:TPoint):Boolean;
var
r,u,v:Integer;
begin
r:=Abs((D.X-A.X)*(B.Y-A.Y)-(B.X-A.X)*(D.Y-A.Y));
u:=(B.Y-A.Y)*(P.X-A.X)-(D.X-A.X)*(P.Y-A.Y);
v:=(D.Y-A.Y)*(P.X-A.X)-(B.X-A.X)*(P.Y-A.Y);
Result:=(u>=0) and (u<=r) and (v>=0) and (v<=r);
end;