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

Langage Delphi Discussion :

Dessin et vecteur


Sujet :

Langage Delphi

  1. #21
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    lol ben oui TLink c'est un objet à moi

    mais ton code est très proche du mien, j'ai juste 2 choses en plus

    1) je regarde la différence entre la position de la souris et le point calcul (alors que tu testes directement l'égalité entre les deux)

    2) pour que le calcul soit plus juste, je distingue les droites verticales et horizontales (en comparant DX et DY) dans mon équation de droite.

    tu peux aussi te baser sur la distance du point de la souris et celui calculé : distance = sqrt(dx*dx+dy*dy); où dx et dy sont la différence entre le point calculé et la position de la souris.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  2. #22
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Re-bonjour,

    tu peux aussi te baser sur la distance du point de la souris et celui calculé : distance = sqrt(dx*dx+dy*dy); où dx et dy sont la différence entre le point calculé et la position de la souris.
    ... comme je voulais tester la finesse de détection dans le cas de tracés très fins et de droites parallèles qui se touchent j'ai évité de passer par la distance qui sépare le point calculé et la position de la souris
    ... par contre ça me donne idée pour remédier à l'inconvénient actuel de la function PointDansTronconDroite() lorsque le tracé des traits est épais et nécessite de viser pile l'axe du tracé.
    ... suffit de modifier de sorte que if distance<=pen.width/2 then ... et du coup il sera plus facile de viser avec la souris et sans avoir à passer par un if Pixels[]=couleur.

    A+
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  3. #23
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    dans je ne sais plus quel projet...peut-être MetaDraw j'avais utilisé aussi une autre astuce intéressante. Le premier clic de souris sélectionne une première droite, si tu recliques en même endroit, c'est la suivante (si une autre est assez proche) qui est sélectionnée...le test est simple, dans ta boucle, si tu trouves une ligne qui convient alors qu'elle est déjà sélectionnée, tu continues la boucle pour voir si y'en a pas une autre qui conviendrait
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  4. #24
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    3 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 898
    Points : 8 529
    Points
    8 529
    Par défaut
    SAlut
    Alors j'ai avancé un peu mon projet, qui je l'avoue traine lamentablement , et en se qui concerne les region y'a un bémol, j'utilise un system de delta (que j'ai corrigé depuis la partie de code donné plus haut) pour tenir compte de l'epaisseur du trait, mais voila pour que se soit efficace il faudrait que je calcule la pente de la droite afin de savoir si mes Delta (x et y) doivent etre positif ou negatif...
    Donc du coup je suis en train de me demander si je vais pas opter pour la version mathematique du reperage de la droite... a suivre

    A++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  5. #25
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    sinon y'a aussi la méthode bête et méchante

    tu crées un bitmap temporaire, pour chaque ligne tu la dessines sur le bitmap d'une couleur donnée et tu regardes la couleur du pixel en x,y

    ensuite soit tu changes de couleur, soit tu effaces le bitmap pour la ligne suivante
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  6. #26
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    3 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 898
    Points : 8 529
    Points
    8 529
    Par défaut
    ha ben oui c'est pas betes ca...et ca a le merite d'etre "rapide"

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  7. #27
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    et comme ça me rappelle la méthode utilisée sous OpenGL pour déterminer sur quel objet 3D on a cliqué, je peux même te proposer une optimisation

    le bitmap peux en théorie être de la taille d'un seul pixel ! il faut juste que le dessin de tes lignes tiennent compte du déplacement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    // version  normal
     Bitmap.Canvas.MoveTo(a.x,a.y); 
     Bitmap.Canvas.LineTo(b.x,b.y);
     if Bitmap.Pixels[Mouse.x,Mouse.y]...
    // version bitmap 1x1
     OnePixel.Canvas.MoveTo(a.x-Mouse.x,a.y-Mouse.y);
     OnePixel.Canvas.LineTo(b.x-Mouse.x,b.y-Mouse.y);
     if Bitmap.Pixels[0,0] ...
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  8. #28
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    3 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 898
    Points : 8 529
    Points
    8 529
    Par défaut

    Comme j'aime des postes productifs comme ca!
    Merci (en tout cas pour moi )
    A++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  9. #29
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Bonjour,

    Voici déjà pour la détection d'un tronçon de droite un bout de code, similaire à mon code de l'autre jour, mais qui détecte et identifie par calculs la droite sur laquelle s'effectue le MouseDown en tenant compte de l'épaisseur du tracé (facilite la visée du click) et comme la détection s'effectue par calculs cela permet de détecter une droite parmi d'autres de même couleur (impossible à faire avec une détection par if Pixels[x,y]=maCouleur) et qui permettrait donc également en cas de besoin détecter une droite invisible à l'écran du style limite d'une zone :
    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
     
    // Pour détection de droites épaisses d'1 seul à plusieurs pixel(s)
    // détection par calcul tenant compte de l'épaisseur et de la position 
    // du trait et non de sa couleur qui peut être la même pour toutes les droites
    // permet même de détecter une droite invisible à l'écran du tye limite de zone
     
    type TDroite = record
                      xo,yo,                 // coordonnées d'origine
                      xe,ye : integer;       // coordonnées d'extrémité
                      coulTrait : TColor;    // couleur du tracé
                      epTrait   : Integer;   // épaisseur du tracé
                      stylTrait : TPenStyle; // style du tracé si droite d'1 seul pixel
                   end;
     
         TDroites = array [0..9] of TDroite;
     
    var  MesDroites : TDroites;
     
    procedure TForm1.FormShow(Sender: TObject);
    var       ep : byte;
    begin     // 1) série de droites fines
              ep:=1; // un seul pixel
              with MesDroites[0] do
              begin xo:=50; yo:=50; xe:=200; ye:=100;
                    coulTrait:=clRed; epTrait:=ep; stylTrait:=psSolid;
              end;
              with MesDroites[1] do // parallèle à la précédente et en contact avec celle-ci
              begin xo:=50; yo:=51; xe:=200; ye:=101;
                    coulTrait:=clLime; epTrait:=ep; stylTrait:=psDash;
              end;
              with MesDroites[2] do
              begin xo:=50; yo:=100; xe:=200; ye:=50;
                    coulTrait:=clNavy; epTrait:=ep; stylTrait:=psDot;
              end;
              with MesDroites[3] do // verticale
              begin xo:=100; yo:=110; xe:=100; ye:=150;
                    coulTrait:=clGreen; epTrait:=ep; stylTrait:=psDashDot;
              end;
              with MesDroites[4] do // horizontale
              begin xo:=100; yo:=110; xe:=50; ye:=110;
                    coulTrait:=clYellow; epTrait:=ep; stylTrait:=psDashDotDot;
              end;
              // 2) série de droites épaisses
              ep:=10; // 10 pixels
              with MesDroites[5] do
              begin xo:=50; yo:=150; xe:=200; ye:=200;
                    coulTrait:=clRed; epTrait:=ep; stylTrait:=psSolid;
              end;
              with MesDroites[6] do // parallèle à la précédente et en contact avec celle-ci
              begin xo:=50; yo:=160; xe:=200; ye:=210;
                    coulTrait:=clLime; epTrait:=ep; stylTrait:=psSolid;
              end;
              with MesDroites[7] do
              begin xo:=50; yo:=200; xe:=200; ye:=150;
                    coulTrait:=clNavy; epTrait:=ep; stylTrait:=psSolid;
              end;
              with MesDroites[8] do // verticale
              begin xo:=100; yo:=210; xe:=100; ye:=250;
                    coulTrait:=clGreen; epTrait:=ep; stylTrait:=psSolid;
              end;
              with MesDroites[9] do // horizontale
              begin xo:=100; yo:=210; xe:=50; ye:=210;
                    coulTrait:=clYellow; epTrait:=ep; stylTrait:=psSolid;
              end;
    end;
     
    procedure TForm1.btnTracerDroitesClick(Sender: TObject);
    var       i : integer;
    begin     for i:=Low(MesDroites) to High(MesDroites) do
              begin with canvas do
                    begin pen.Width:=MesDroites[i].epTrait;
                          pen.mode:=pmCopy;
                          pen.style:=MesDroites[i].stylTrait;
                          pen.color:=MesDroites[i].coulTrait;
                          moveTo(MesDroites[i].xo, MesDroites[i].yo);
                          LineTo(MesDroites[i].xe, MesDroites[i].ye);
                    end;
              end;
    end;
     
    function PointDansTronconDroite(xs,ys : integer; Droite : TDroite) : boolean;
    var      a, b, miEp, lg : Extended; dx,dy,yc : integer; okx,oky : boolean;
    begin    Result:=False;
             miEp:=Droite.epTrait/2;
             dx:=Droite.xe - Droite.xo;
             dy:=Droite.ye - Droite.yo;
             if (dx=0) and (dy=0) then // Droite réduite à 1 seul point
             begin if (xs - miEp <=Droite.xo) and (Droite.xo <= xs + miEp)
                   and (ys - miEp <=Droite.yo) and (Droite.yo <= ys + miEp)
                   then Result:=True;
                   EXIT;
             end;
             okx:=False; oky:=False;
             // okx et oky ne servent qu''à tester si le point-cible est situé entre
             // l'origine et l'extrémité du tronçon et non dans ses prolongements
             if ((dy<0) and (ys<=Droite.yo) and (ys>=Droite.ye))
             or ((dy>0) and (ys<=Droite.ye) and (ys>=Droite.yo)) then oky:=True;
             if ((dx>0) and (xs<=Droite.xe) and (xs>=Droite.xo))
             or ((dx<0) and (xs<=Droite.xo) and (xs>=Droite.xe)) then okx:=True;
     
             if (dx=0) then // Droite verticale
             begin if (xs - miEp <=Droite.xo) and (Droite.xo <= xs + miEp)
                   and oky then Result:=True;
                   EXIT;
             end else
             if (dy=0) then // Droite horizontale
             begin if (ys - miEp <=Droite.yo) and (Droite.yo <= ys + miEp)
                   and okx then Result:=True;
                   EXIT;
             end else // Droite inclinée "y = a.x + b"
             begin a:=dy/dx; // pente
                   b:=Droite.yo - a*Droite.xo;
                   yc:=round(a*xs + b);     // y-calculé(xs)
                   lg:=sqrt(dx*dx + dy*dy); // longueur tronçon de droite
                   //sinus:=dx/lg;
                   miEp:=abs(miEp*lg/dx);   // projection de miEp sur la verticale yc-ys en xs
                   if (yc + miEp >= ys) and (yc - miEp <= ys)
                   and okx and oky then Result:=True;
             end;
    end;
     
    procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    var       i : integer; ok : boolean;
    begin     i:=-1;
              repeat inc(i); ok:=PointDansTronconDroite(X,Y, MesDroites[i])
              until ok or (i=High(MesDroites));
              if ok then labelTemoin.color:=MesDroites[i].coulTrait
                    else labelTemoin.color:=clBtnFace;
              // ici on quitte la boucle dès qu'on a détecté et identifié la droite sur laquelle on vient de cliquer
              // en mémorisant l'indice-d'identification de cette droite celui-ci
              // pourra servir ensuite dans le MouseMove et le MouseUp
              // pour réaliser le déplacement de cette droite
    end;
    ... code testé : marche.
    ... reste plus qu'à faire un bout de code pour réaliser le "déplacement" de la droite sélectionnée :
    - déplacement parallèlement à elle-même ?
    - déplacement par rotation autour d'une extrémité ?
    - avec ou sans des fioritures du style "poignées" ?
    - avec ou sans apparition d'un tracé furtif de suivi du déplacement ?

    A+
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  10. #30
    Membre chevronné
    Avatar de Archimède
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2005
    Messages
    1 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 1 644
    Points : 1 975
    Points
    1 975
    Par défaut
    Ah, on voit le retraité qui a le temps de peaufiner le truc. lol
    Super, ça fait du bien de voir du code qui se respecte.
    merci pour nous faire plaisir.
    (merci à vous deux)

  11. #31
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Bonjour,

    Ah, on voit le retraité qui a le temps de peaufiner le truc.
    ... ben justement à propos de "peaufiner" je m'apprête à modifier la function PointDansTronconDroite(xs,ys : integer; Droite : TDroite) : boolean;
    de sorte qu'elle ne renvoie pas bêtement un boolean mais un réel qui lorsqu'il est différend de -1 renvoie une valeur comprise entre 0..1 renseigne sur l'éloignement du point-du-click sur la droite par rapport à l'origine de cette droite histoire de pouvoir savoir si on a cliqué du côté de l'origne ou de l'extrémité de cette droite ce qui pourra servir si on veut effectuer un déplacement par rotation autour d'une extrémité en tirant sur l'autre.

    A+
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  12. #32
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    ça me rappelle an8na, dans ce modèle 3D, les points sont déformés par squelette avec une influence défini par des sortes de capsules autour de l'os. Deux demi-sphères reliées par un cylindre.

    Du coup, pour chaque point, je détermine s'il est compris dans une des deux demi sphère ou s'il est dans le cylindre pour pour savoir s'il est influencé ou pas par l'os.

    pour ce faire, je fais une projection du point sur l'os (dans ton cas une projection orthogonale du point sur la droite).
    je calcul la distance du point projeté à chaque extrémité et à celle du point d'origine.

    pour savoir si mon point n'est pas en dehors du segment, je compare les distances aux extrémité avec la distance qui les sépare. Le point ne peux pas être plus éloigné d'une extrémité que de la distance qui les sépare
    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
     
            +C
            |
     A------+-------B
            p
     
     C
      +    +B
       \  /
        \/
        /p (pas très orthogonal comme dessin :D)
       /
      /
     +
    A
    Ici C est mon point (la souris), A, B les extrémités du segment et p la projection de C sur AB.
    les distances (A-p) et (p-B) doivent toutes les deux être inférieures à (A-B), sinon le point est en dehors du segment.

    Ensuite je regarde la distance (C-p) pour savoir si le point est suffisamment près de l'OS (de ta droite)
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  13. #33
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Bonjour,

    ça me rappelle an8na, dans ce modèle 3D ...
    ... vu an8na : c'est chouette : j'ai téléchargé pour voir le code qui doit être très instructif.

    ... En attendant, nous autres n'en sommes péniblement qu'à la détection et au déplacement d'une droite parmi d'autres.

    ... Et voiçi un bout de code où j'ai complété la détection d'une droite par la possibilité de la déplacer :
    1) Parallèlement à elle-même : si on l'agrippe avec la souris à plus de 15% d'une de ses extrémités,
    2) Par étirage+rotation autour d'une extrémité : si on l'agrippe à moins de 15% de l'autre extrémité.
    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
     
    // 1 ) Pour détection de droites épaisses d'1 seul à plusieurs pixel(s)
    //     détection par calcul tenant compte de l'épaisseur du trait
    //     permet d'identifier une droite parmi d'autres de même couleur le cas échéant,
    //     et même de détecter une droite invisible à l'écran du tye limite de zone.
    // 2 ) Pour déplacement de la droite par agrippage de la droite à la souris :
    //     - à moins de 15% d'une extrémité : déplacement par étirage-rotation
    //     - à plus de 15% d'une extrémité  : déplacement parallèlement à elle-même
     
    type TDroite = record
                      xo,yo,                 // coordonnées d'origine
                      xe,ye : integer;       // coordonnées d'extrémité
                      coulTrait : TColor;    // couleur du tracé
                      epTrait   : Integer;   // épaisseur du tracé
                      stylTrait : TPenStyle; // style du tracé si droite d'1 seul pixel
                   end;
     
         TDroites = array [0..9] of TDroite;
     
    var  MesDroites  : TDroites;
         iDroiteSelectionnee, xMp,yMp : integer;
         rOrigine    : Extended; // ratio d'éloignement du point d'agripage par rapport à l'origine de la droite
     
    procedure TForm1.FormShow(Sender: TObject);
    var       ep : byte;
    begin     color:=clWhite; //<pour tracés avec pmNotXor
              iDroiteSelectionnee:=-1;
              // 1) série de droites fines
              ep:=1; // un seul pixel
              with MesDroites[0] do
              begin xo:=50; yo:=50; xe:=200; ye:=100;
                    coulTrait:=clRed; epTrait:=ep; stylTrait:=psSolid;
              end;
              with MesDroites[1] do // parallèle à la précédente et en contact avec celle-ci
              begin xo:=50; yo:=51; xe:=200; ye:=101;
                    coulTrait:=clLime; epTrait:=ep; stylTrait:=psDash;
              end;
              with MesDroites[2] do
              begin xo:=50; yo:=100; xe:=200; ye:=50;
                    coulTrait:=clNavy; epTrait:=ep; stylTrait:=psDot;
              end;
              with MesDroites[3] do // verticale
              begin xo:=100; yo:=110; xe:=100; ye:=150;
                    coulTrait:=clGreen; epTrait:=ep; stylTrait:=psDashDot;
              end;
              with MesDroites[4] do // horizontale
              begin xo:=100; yo:=110; xe:=50; ye:=110;
                    coulTrait:=clYellow; epTrait:=ep; stylTrait:=psDashDotDot;
              end;
              // 2) série de droites épaisses
              ep:=10; // 10 pixels
              with MesDroites[5] do
              begin xo:=50; yo:=150; xe:=200; ye:=200;
                    coulTrait:=clRed; epTrait:=ep; stylTrait:=psSolid;
              end;
              with MesDroites[6] do // parallèle à la précédente et en contact avec celle-ci
              begin xo:=50; yo:=161; xe:=200; ye:=211;
                    coulTrait:=clLime; epTrait:=ep; stylTrait:=psSolid;
              end;
              with MesDroites[7] do
              begin xo:=50; yo:=200; xe:=200; ye:=150;
                    coulTrait:=clNavy; epTrait:=ep; stylTrait:=psSolid;
              end;
              with MesDroites[8] do // verticale
              begin xo:=100; yo:=210; xe:=100; ye:=250;
                    coulTrait:=clGreen; epTrait:=ep; stylTrait:=psSolid;
              end;
              with MesDroites[9] do // horizontale
              begin xo:=100; yo:=210; xe:=50; ye:=210;
                    coulTrait:=clYellow; epTrait:=ep; stylTrait:=psSolid;
              end;
    end;
     
    procedure Trace( C : tCanvas; D : TDroite; mode : TPenMode);
    begin     with C do
              begin pen.width := D.epTrait;
                    pen.color := D.coulTrait;
                    pen.Style := D.stylTrait;
                    pen.mode  := mode;
                    moveto(D.xo, D.yo);
                    lineto(D.xe, D.ye);
                    pen.mode := pmCopy;
              end;
    end;
     
    procedure TForm1.btnTracerDroitesClick(Sender: TObject);
    var       i : integer;
    begin     for i:=Low(MesDroites) to High(MesDroites)
              do Trace(Canvas, MesDroites[i], pmNotXor); //pmCopy);
    end;
     
    function PointDansTronconDroite(xs,ys : integer; Droite : TDroite) : Extended;
    //@param Result renvoie :
    //       -1 si le point xs,ys est en-dehors de la droite
    //        2 si ce point est pile celui d'une doite réduite à un point
    //       et si xs,ys est situé sur le tronçon de la droite, renvoie une valeur
    //       comprise entre 0..1 et proportionnelle à l'éloignement de ce point
    //       par rapport à l'origine de la droite.
    var      a, b, miEp, lg : Extended; dx,dy,yc : integer; okx,oky : boolean;
    begin    Result:=-1;
             miEp:=Droite.epTrait/2;
             dx:=Droite.xe - Droite.xo;
             dy:=Droite.ye - Droite.yo;
             if (dx=0) and (dy=0) then // Droite réduite à 1 seul point
             begin if (xs - miEp <=Droite.xo) and (Droite.xo <= xs + miEp)
                   and (ys - miEp <=Droite.yo) and (Droite.yo <= ys + miEp)
                   then Result:=2;
                   EXIT;
             end;
             okx:=False; oky:=False;
             // okx et oky ne servent qu''à tester si le point-cible est situé entre
             // l'origine et l'extrémité du tronçon et non dans ses prolongements
             if ((dy<0) and (ys<=Droite.yo) and (ys>=Droite.ye))
             or ((dy>0) and (ys<=Droite.ye) and (ys>=Droite.yo)) then oky:=True;
             if ((dx>0) and (xs<=Droite.xe) and (xs>=Droite.xo))
             or ((dx<0) and (xs<=Droite.xo) and (xs>=Droite.xe)) then okx:=True;
     
             if (dx=0) then // Droite verticale
             begin if (xs - miEp <=Droite.xo) and (Droite.xo <= xs + miEp)
                   and oky then Result:=(ys - Droite.yo)/dy;
                   EXIT;
             end else
             if (dy=0) then // Droite horizontale
             begin if (ys - miEp <=Droite.yo) and (Droite.yo <= ys + miEp)
                   and okx then Result:=(xs - Droite.xo)/dx;
                   EXIT;
             end else // Droite inclinée "y = a.x + b"
             begin a:=dy/dx; // pente
                   b:=Droite.yo - a*Droite.xo;
                   yc:=round(a*xs + b);     // y-calculé(xs)
                   lg:=sqrt(dx*dx + dy*dy); // longueur tronçon de droite
                   miEp:=abs(miEp*lg/dx);   // projection de miEp sur la verticale yc-ys en xs
                   if (yc + miEp >= ys) and (yc - miEp <= ys)
                   and okx and oky then Result:=(xs - Droite.xo)/dx;
             end;
    end;
     
    procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    var       i : integer;
    begin     i:=-1; iDroiteSelectionnee:=-1;
              repeat inc(i); rOrigine:=PointDansTronconDroite(X,Y, MesDroites[i])
              until (rOrigine>=0) or (i=High(MesDroites));
              // ici on quitte la boucle dès qu'on a détecté la droite sur laquelle on cliqué
              if rOrigine>=0
              then begin labelTemoin.caption:=FloatToStr(rOrigine);
                         labelTemoin.color:=MesDroites[i].coulTrait;
                         iDroiteSelectionnee:=i;
                         Screen.Cursor := crHandPoint;
                         xMp:=X; yMp:=Y;
              end
              else begin labelTemoin.color:=clBtnFace;
                         labelTemoin.caption:=FloatToStr(rOrigine);
              end;
    end;
     
    procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
    var       i,dxs,dys : integer;
    begin     i:=iDroiteSelectionnee;
              if i>=0 then
              begin dxs:=X - xMp; dys:=Y - yMp;
                    with MesDroites[i] do
                    begin Trace(Canvas, MesDroites[i], pmNotXor);
                          if rOrigine<=0.15 then // Etirage droite par agrippage près de l''origine
                          begin xo:=xo+dxs; yo:=yo+dys; end else
                          if rOrigine>=0.85 then // Etirage droite par agrippage près de l''extrémité
                          begin xe:=xe+dxs; ye:=ye+dys; end
                          else // Déplacement droite parallèle à elle-même
                          begin xo:=xo+dxs; yo:=yo+dys; xe:=xe+dxs; ye:=ye+dys; end;
                          Trace(Canvas, MesDroites[i], pmNotXor);
                    end;
                    xMp:=X; yMp:=Y;
              end;
    end;
     
    procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin     iDroiteSelectionnee:=-1;
              Screen.Cursor := crDefault;
    end;
    ... code testé : marche.
    ... n'ai vraiment pas vu l'intérêt d'ajouter ici des poignées vu que le MouseDown change le Screen.Cursor en crHandPoint.
    ... pour une utilisation avec des droites tracées ailleurs que directement sur la Form1 suffit de mdifier le code de façon à expédier les infos sur le canvas de l'objet de destination.

    A+
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  14. #34
    Membre confirmé

    Inscrit en
    Novembre 2002
    Messages
    744
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 744
    Points : 500
    Points
    500
    Par défaut
    salut ,

    merci a vous tous!
    Bye et bon code...

    Ce n'est pas tant l'aide de nos amis qui nous aide , mais notre confiance dans cette aide .

  15. #35
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    3 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 898
    Points : 8 529
    Points
    8 529
    Par défaut
    SAlut
    Donc en suivant l'idée lancée par Paul voici ce que ca donne, ca n'est pas parfait, mon code est peut etre encore trop lourd, mais c'est fonctionnel.
    J'ai detaché la partie Vecteur du reste pour que ce soit plus en relation avec ta demande (et que se soit fonctionnel aussi ... puisque le reste je l'ai pas fini )

    Je met le projet en piece jointe, comme dis au debut je gere des vecteurs flechés mais il suffira de mettre NormePointe à 0 pour generer des droites.

    Les 2 extremités sont differenciée Origine et extremité(avec la fleche).

    Les poignés sont modifiable via le Pen et le Brush qui y sont associés, en modifiant un poile on peut meme faire en sorte qu'elles soient invisible mais presentent, le code est "prevu pour" a l'origine, mais j'ai pas pris le temps de modifier.

    A++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  16. #36
    Membre confirmé

    Inscrit en
    Novembre 2002
    Messages
    744
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 744
    Points : 500
    Points
    500
    Par défaut
    Merci pour votre aide !!

    Au final j'ai utilisé les deux techniques en fonction de mes types de shapes ..

    - Detection des ligne, polyligne, segment.. par la methode de Gilbert Geyer.

    - Detection des surfaces par la methode des regions.

    Cela en memorisant bien sur les coordonnées de mes shapes au moment de leur création.
    Bye et bon code...

    Ce n'est pas tant l'aide de nos amis qui nous aide , mais notre confiance dans cette aide .

  17. #37
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Salut,

    Au fait j'ai continué avec mon code pour détecter-déplacer-agrandir non seulement des droites mais également des rectangles et des cercles.

    Si ça t'intéresse dis-le et je mettrai le code ici.

    A+
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  18. #38
    Membre actif Avatar de petitprince
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juillet 2006
    Messages
    322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juillet 2006
    Messages : 322
    Points : 267
    Points
    267
    Par défaut
    Euh oui, moi ceci m'intéresse beaucoup, surtout le redimensionnement de rectangle ...
    Merci.....

  19. #39
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Bonjour,

    A PetitPrince : Voiçi donc le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    unit uImgD;
    
    EDIT du 6/2/2008  : code supprimé ici suite à ajout du cas des polygones,
    voir nouvelle version du code dans mes messages du 6/2/2008 13h16 et 13h18.
    Le tracé s'effectue ici sur le canvas d'un TImage, on peut modifier pour n'importe quel canvas.

    Utilisation :
    - pour déplacer une droite parallèlement à elle même il suffit de l'agripper avec la souris à plus de 15% des extrémités, et si on l'agrippe à moins de 15% d'une extrémité on obtient une étiration-rotation de la droite par rapport à l'autre extrémité qui reste fixe.

    - pour déplacer un rectangle parallèlement à lui-même agripper son bord-haut à plus de 15% des extrémités. Lorsqu'on agrippe l'un des 3 autres bords à plus de 15% des angles le rectangle se redimensionne dans le sens perpendiculaire à ce bord, et si on l'agrippe à moins de 15% d'un angle on obtient sa rotation autour du centre du rectangle.
    (pour l'instant il y a deux cas de rectangles : le premier trace des rectangles dont les bords sont "pleins" sur une épaisseur égale à pen.width, et le le deuxième cas des rectangles dont les bords sont "vides" c'est à dire dont le tracé est formé par deux droites parallèles épaisses d'un seul pixel et distantes de la valeur déclarée comme épaisseur lors du FormShow)
    Lors du tracé initial les rectangles sont ici horizontaux et on les modifie à la main par la suite.

    - pour déplacer un cercle on l'agrippe n'importe où sauf dans le voisinage où le cercle croise son axe horizontal du côté droit du cercle zone réservée pour augmenter/réduire son diamètre.

    Je n'ai pas vu l'utilité d'ajouter des poignées vu que le curseur-souris change de forme quand on agrippe une ligne.

    A+

    EDIT : S'il n'y a que les rectangles qui t'intéressent, surtout ne supprimes pas ce qui traite des droites, car les 4 bords des rectangles sont formés par des droites vu que Bords : array[1..4] of TDroite;
    - Bord[1] = bord gauche lors du tracé initial à l'horizontale
    - Bord[2] = bord inférieur lors du tracé initial
    - Bord[3] = bord droit lors du tracé initial
    - Bord[4] = bord supérieur lors du tracé initial.
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  20. #40
    Membre actif Avatar de petitprince
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juillet 2006
    Messages
    322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juillet 2006
    Messages : 322
    Points : 267
    Points
    267
    Par défaut
    Merci, tout simplement génial.... Il me vient une petite question: pourrait on faire de la même manière pour un polygone quelquonque, du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    array[1..7] of TDroite;
    ? Faut-il modifier le code de manière importante ?

    En tout cas vraiment merci

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 8 PremièrePremière 123456 ... DernièreDernière

Discussions similaires

  1. dessiner vecteur 3D
    Par zaffef dans le forum MATLAB
    Réponses: 3
    Dernier message: 19/06/2015, 11h36
  2. Dessiner les vecteurs de flux optique
    Par nesnes2011 dans le forum OpenCV
    Réponses: 1
    Dernier message: 16/06/2015, 14h31
  3. dessiner un vecteur 3D
    Par sdecorme dans le forum MATLAB
    Réponses: 1
    Dernier message: 06/11/2013, 10h54
  4. [vecteurs] dessiner les courbes de Bezier
    Par luta dans le forum Flash
    Réponses: 4
    Dernier message: 03/07/2006, 09h58
  5. Réponses: 3
    Dernier message: 12/06/2002, 19h03

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