Trait, courbe, ligne, points tillés, etc...

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: Trouver un point entre deux points

Message par blendman »

C'est mieux, mais c'est pas encore complètement opérationnel ;)

Teste en dessinant :

Code : Tout sélectionner

Structure vector2f
  x.f
  y.f
EndStructure


Procedure GenerateIntervalPoint( List in.vector2f(), List out.vector2f() , interval.l = 10  )
   
  ClearList(out())

  Protected size.l = ListSize(in())
 
  ; il manque le premier élément
  AddElement(out())
  
  SelectElement(in(),0)
  out()\x = in()\x
  out()\y =in()\y

 
  For i = 1 To size-1
   

    A.vector2f
    B.vector2f
   
    SelectElement(in(),i-1)
    A\x = in()\x
    A\y = in()\y
   
    SelectElement(in(),i)
    B\x = in()\x
    B\y = in()\y
   
   
    dist.d = Sqr((B\x-A\x)*(B\x-A\x) + (B\y-A\y)*(B\y-A\y))

    If dist > interval And dist > 0
     
      direction.vector2f
        direction\x = B\x - A\x
        direction\y = B\y - A\y
       
      lenght.f =  Sqr(direction\x * direction\x + direction\y * direction\y)
     
      If lenght > 0
        direction\x / lenght
        direction\y / lenght
      EndIf

      insertNumber.l = (dist / interval)-1

      Start.vector2f
     
      Start\x = A\x
      Start\y = A\y
     
      AddElement(out())
      out()\x = Start\x
      out()\y = Start\y
     
      For j = 0 To insertNumber - 1
       
        AddElement(out())
       
        offset.i = insertNumber + 1
       
        out()\x = Start\x + (direction\x * interval)
        out()\y = Start\y + (direction\y * interval)
       
        Start\x + (direction\x * interval)
        Start\y + (direction\y * interval)
       
      Next
    EndIf
   
    Next

EndProcedure



NewList MesPoints.vector2f()
NewList MesPointsIntermediaires.vector2f()



; 
; AddElement(MesPoints())
; MesPoints()\x = 10
; MesPoints()\y = 10
; 
; 
; AddElement(MesPoints())
; MesPoints()\x = 395
; MesPoints()\y = 127
; 
; 
; AddElement(MesPoints())
; MesPoints()\x = 682
; MesPoints()\y = 263
; 
; AddElement(MesPoints())
; MesPoints()\x = 569
; MesPoints()\y = 241
; 
; GenerateIntervalPoint( MesPoints(), MesPointsIntermediaires(), 20)
; 


w = 1024
h= 768

OpenWindow(0, 0, 0, w,h, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)


CanvasGadget(0,0,0,w,h)
If StartDrawing(CanvasOutput(0))
  ForEach MesPointsIntermediaires()
    Circle(MesPointsIntermediaires()\x ,MesPointsIntermediaires()\y,4,0)
  Next   
  StopDrawing()
EndIf

Repeat
  Event = WaitWindowEvent()
  
  
  EventGadget = EventGadget()
  
  Select event
      
      
    Case #PB_Event_CloseWindow
      End
    Case #PB_Event_Gadget
      
      Select EventGadget
        Case 0
          If EventType() = #PB_EventType_LeftButtonDown 
            draw = 1
          ElseIf EventType() = #PB_EventType_LeftButtonUp
            draw = 0
            
          ElseIf (EventType() = #PB_EventType_MouseMove And GetGadgetAttribute(0, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton)
            
            If draw = 1
              x = GetGadgetAttribute(0, #PB_Canvas_MouseX)
              y = GetGadgetAttribute(0, #PB_Canvas_MouseY)
              
              AddElement(MesPoints())
              MesPoints()\x = x
              MesPoints()\y = y
              
              GenerateIntervalPoint( MesPoints(), MesPointsIntermediaires(), 20) ; je ne sais pas si c'est top de le générer à chaque tour de boucle,
              ; ce serait mieux de vider la liste MesPoints(), j'imagine (sauf le dernier élément)

              If StartDrawing(CanvasOutput(0))
                Box(0,0,w,h,RGBA(255,255,255,255))
                ForEach MesPointsIntermediaires()
                  Circle(MesPointsIntermediaires()\x ,MesPointsIntermediaires()\y,4,0)
                Next   
                StopDrawing()
              EndIf

              
            EndIf
          EndIf

      EndSelect      
  EndSelect  
Until Event = #PB_Event_CloseWindow
Certain point n'apparaissent pas, et des fois, la distance n'est pas bonne.
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: Trouver un point entre deux points

Message par blendman »

falsam a écrit :Bien entendu je suppose que tu veux une fonction pour dessiner à main levée ?
Oui, c'est le but ;)

@G-rom : en fait, je pense qu'il faut remplacer (dans la liste in()) un point lorsqu'il n'est pas bon par un point ok et repartir depuis ce point ok pour la suite ;)
Dernière modification par blendman le mer. 24/juin/2015 11:02, modifié 1 fois.
Avatar de l’utilisateur
falsam
Messages : 7317
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Trouver un point entre deux points

Message par falsam »

Un premier essai ou je dessine des cercles pleins distants entres eux de 40 pixels

Code : Tout sélectionner

Enumeration Window
  #MainForm
EndEnumeration

Enumeration Gadgets
  #Canvas
EndEnumeration

Structure Canvas
  LeftButtonDown.i
  RightButtonDown.i
  LastX.i
  LastY.i
EndStructure

Global Draw, This.Canvas

Global CurrentPoint.Point
Global LastPoint.Point

Declare EventDraw()
Declare.d Distance(*p.Point, *q.Point)

If OpenWindow(#MainForm, 0, 0, 1024, 768, "Canvas Draw", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  CanvasGadget(#Canvas, 0, 0, 1024, 768)
  BindGadgetEvent(#Canvas, @EventDraw())
  
  Repeat : Until WaitWindowEvent(10) = #PB_Event_CloseWindow
EndIf

Procedure EventDraw()
  
  Protected x.i = GetGadgetAttribute(#Canvas, #PB_Canvas_MouseX)
  Protected y.i = GetGadgetAttribute(#Canvas, #PB_Canvas_MouseY)
  Protected color.l = RGB(128, 128, 128)
  Protected Distance.f
  
  With This
    Select EventType()
       Case #PB_EventType_LeftButtonDown
         \LeftButtonDown = #True
            \LastX = x
            \LastY = y 
            
         Case #PB_EventType_LeftButtonUp
           \LeftButtonDown = #False
           
         Case #PB_EventType_RightButtonDown           
            \RightButtonDown = #True
            \lastX = x
            \lastY = y
            
         Case #PB_EventType_RightButtonUp
           \RightButtonDown = #False
           
         Case #PB_EventType_MouseMove   
           Draw = #False
           If (\LeftButtonDown Or \RightButtonDown)
                  Draw = #True
           EndIf
            
      EndSelect
      
      
      ;Pour cet démo la distance entre deux vecteurs est de 40pixels
      If Draw
        ;Quel est le point courrant ?
        CurrentPoint\x = x
        CurrentPoint\y = y
        
        ;Quel est le dernier point
        LastPoint\x = \lastX
        LastPoint\y = \lastY
        
        ;Distance entres ces deux vecteurs
        Distance = Distance(LastPoint, CurrentPoint)
        
        
        If StartDrawing(CanvasOutput(#Canvas))
          
          If Distance > 40      
            Circle(\lastX, \lastY, 10, color)
            \lastX = x
            \lastY = y
          EndIf
          
          StopDrawing()
         EndIf
      EndIf
   EndWith
 EndProcedure
 
 ;Distance entres deux vecteurs
 Procedure.d Distance(*p.Point, *q.Point)
  Protected Distance.d
  
  ;Distance horizontale
  dx.d = *p\x - *q\x   
  
  ;Distance verticale
  dy.d = *p\y - *q\y
  
  ;Théoréme de Pythagore
  Distance.d = Sqr(dx*dx + dy*dy )
  
  ProcedureReturn Distance
EndProcedure
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: Trouver un point entre deux points

Message par G-Rom »

Certain point n'apparaissent pas, et des fois, la distance n'est pas bonne.
La distance est bonne (il faut juste rajouté le point B à la fin), c'est ta gestion des event qui n'est pas bonne. Je préfère la version à Falsam , elle marchera dans tout les cas de figure.
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: Trouver un point entre deux points

Message par blendman »

@falsam : c'est presque ça, mais il y a un bug lorsqu'on dessine vite, l'écart se creuse entre certains cercles ;)
Avatar de l’utilisateur
falsam
Messages : 7317
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Trouver un point entre deux points

Message par falsam »

blendman a écrit :@falsam : c'est presque ça, mais il y a un bug lorsqu'on dessine vite, l'écart se creuse entre certains cercles ;)
Ce qui implique de calculer le nombres de points possible entres les deux vecteurs. Hum je m'y colle :)
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
falsam
Messages : 7317
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Trouver un point entre deux points

Message par falsam »

Tu dessines quand meme super vite pour obtenir ce decalage :mrgreen:
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: Trouver un point entre deux points

Message par blendman »

falsam a écrit :Tu dessines quand meme super vite pour obtenir ce decalage :mrgreen:
avec un tablette graphique, oui, ça va hyper vite ;)
C'est d'ailleurs le but :)

Il y aurait moyen d'enregistrer ces points (ceux à la bonne place) dans un tableau, avant de les dessiner?
Ainsi, je pourrais recalculer une sorte de courbe de bézier avec les points obtenus. Ca me permettrait d'avoir de belles courbes de dessin lissées (j'ai quelques formules de béziers que je pourrais réutiliser je pense ^^).

En tout cas, merci à toi et à G-rom, vous êtes super rapides :mrgreen:

Edit :
en réfléchissant, je me demande si on ne doit pas modifier certains points (le B) pour leur donner la bonne place avant de calculer le suivant ?
Avatar de l’utilisateur
falsam
Messages : 7317
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Trouver un point entre deux points

Message par falsam »

blendman a écrit :Il y aurait moyen d'enregistrer ces points (ceux à la bonne place) dans un tableau, avant de les dessiner?
Tu sais quand tu cliques et quand tu relaches le clic. Donc oui tu connais tous les points. je ne sais pas résoudre la courbe de bézier mais je sais te ressortir un tableau des points.

Le code dans quelques minutes.
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: Trouver un point entre deux points

Message par G-Rom »

J'avais fait un code sur bézier il y a très longtemps , je viens de l'adapter :

Code : Tout sélectionner

InitSprite() : InitKeyboard() : InitMouse() 
OpenWindow(0,0,0,800,600,"SPRITE TORSION")
OpenWindowedScreen(WindowID(0),0,0,800,600,1,0,0)


Structure POINTF
x.f
y.f
EndStructure

Structure BEZIER
P.POINTF[4]
EndStructure

Structure Perpendiculaires
P1.POINTF
P2.POINTF
EndStructure

Global NewList Droites.Perpendiculaires()


Global SubDivide
Procedure CountSubDivide(*b.BEZIER,level)
SubDivide+1
If level<=0
Else
  CountSubDivide(*b,level-1)
  CountSubDivide(*b,level-1)
EndIf
EndProcedure


Declare DrawBezier(Global_Bezier,level)
MyBezier.BEZIER


MyBezier\P[0]\x = 100
MyBezier\P[0]\y = 500

MyBezier\P[1]\x = 100
MyBezier\P[1]\y = 100

MyBezier\P[3]\x = 700
MyBezier\P[3]\y = 500
; 
MyBezier\P[2]\x = 700
MyBezier\P[2]\y = 100



;Sprite Procedural
CreateSprite(0,256,256)
StartDrawing(SpriteOutput(0))
For y = -128 To 128
Line(0,y+128,256,1,RGB(64,128+y,255))
Next
StopDrawing()

; CreateSprite3D(0,0)






LOD=5




Repeat
ExamineKeyboard() : ClearScreen(RGB(0,0,0))
ExamineMouse()

event = WindowEvent()


;          Start3D()
;          Sprite3DQuality(1)

        ForEach Droites()

            If NextElement(Droites())<>0
            Nx_a.f=Droites()\P1\x
            Ny_a.f=Droites()\P1\y
            Nx_b.f=Droites()\P2\x
            Ny_b.f=Droites()\P2\y
            PreviousElement(Droites())
            EndIf     
          
            If PreviousElement(Droites())<>0
            Px_a.f=Droites()\P1\x
            Py_a.f=Droites()\P1\y
            Px_b.f=Droites()\P2\x
            Py_b.f=Droites()\P2\y
            NextElement(Droites())
            EndIf     
       
       
       
       
       SpriteBlendingMode(7,2)
       TransformSprite(0,Nx_a,Ny_a,Droites()\P1\x,Droites()\P1\y,Droites()\P2\x,Droites()\P2\y,Nx_b,Ny_b)
       DisplaySprite(0,0,0)
        ;LineXY(Nx_a,Ny_a,Droites()\P1\x,Droites()\P1\y,RGB(0,255,0))
        ;LineXY(Nx_b,Ny_b,Droites()\P2\x,Droites()\P2\y,RGB(0,255,0))
        ;LineXY(Droites()\P1\x,Droites()\P1\y,Droites()\P2\x,Droites()\P2\y,RGB(0,255,0))


          Next 

       ClearList(Droites())
;       Stop3D()




StartDrawing(ScreenOutput())

    Mx = MouseX()
    My = MouseY()  
    
    Circle(Mx,My,4,RGB(0,0,255))
    
    If t<ElapsedMilliseconds()
    t=ElapsedMilliseconds()+500
    ;LOD=(LOD+1)%8
EndIf
    
    
   DrawBezier(MyBezier,LOD)
  
    
  
    SubDivide=0
      For i = 0 To 3
      If Mx<MyBezier\P[i]\x+4 And Mx>MyBezier\P[i]\x-4 And My<MyBezier\P[i]\y+4 And My>MyBezier\P[i]\y-4
      Circle(MyBezier\P[i]\x,MyBezier\P[i]\y,8,RGB(0,255,0))
      CTRL = i
      Else
      Circle(MyBezier\P[i]\x,MyBezier\P[i]\y,2,RGB(0,255,0))
      EndIf 
    Next 
    
    
    If CTRL <> -1
      If MouseButton(1)
        MyBezier\P[CTRL]\x = Mx 
        MyBezier\P[CTRL]\y = My
        Else
        CTRL = -1
      EndIf
      
    EndIf
StopDrawing()



FlipBuffers()

Until KeyboardPushed(#PB_Key_Escape) Or event = #PB_Event_CloseWindow

Procedure DrawBezierBase(*b.BEZIER,color)
  LineXY(*b\P[0]\x,*b\P[0]\y,*b\P[1]\x,*b\P[1]\y,color)
  LineXY(*b\P[1]\x,*b\P[1]\y,*b\P[2]\x,*b\P[2]\y,color/4)
  LineXY(*b\P[2]\x,*b\P[2]\y,*b\P[3]\x,*b\P[3]\y,color)
EndProcedure

Procedure Distance(x1,y1,x2,y2)
Protected Result.f
Result = Sqr(  (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)  )
ProcedureReturn Result
EndProcedure

Procedure.f GetAngle(xb,yb,Xa,Ya) 

      
   ;calcul de l'angle en radian 
    
   ar.f=ATan((Ya-yb)/(Xa-xb)) 
   
   ;conversion en degres (je suis pas un crac des radians, je préfère bosser avec les degrés) 
   ad=ar*360/2/3.1415 

    
   ;ajout de la partie de l'angle suivant la position des points car Atang ne renvoie qu'un angle de -90 à 90 
   If Xa<xb And Ya<yb : ad=180+ad :EndIf ; cas haut gauche 
   If Xa>xb And Ya<yb : ad=360+ad :EndIf ;cas haut droite 
   If Xa<xb And Ya>yb : ad=180+ad :EndIf ; cas bas gauche 
   If Xa>xb And Ya>yb :           :EndIf ; cas bas droite 

   ; reconversion en radian si tu en as besoins 
   ;ar=ad*2*3.1415/360 
    
  ProcedureReturn ad+ar
EndProcedure 



Procedure DrawBezierRecursive (*b.BEZIER ,level.l) 

Static OldX.f,OldY.f,i.l,Pca.l,Pcb.l,h.f

  ; Change la hauteur des perpendiculaires
  h=20+10*Cos(ElapsedMilliseconds()/2000)
         
                  
                  
         If (level <= 0) 
          LineXY((*b\P[0]\x + 0.5),(*b\P[0]\y + 0.5),(*b\P[3]\x + 0.5),(*b\P[3]\y + 0.5),RGB(Random(255),Random(255),Random(255)))
          Ang = GetAngle((*b\P[0]\x + 0.5),(*b\P[0]\y + 0.5),(*b\P[3]\x + 0.5),(*b\P[3]\y + 0.5))
          Dist.f = Distance((*b\P[0]\x + 0.5),(*b\P[0]\y + 0.5),(*b\P[3]\x + 0.5),(*b\P[3]\y + 0.5))/2
          
          M.POINTF
          UP.POINTF
          DW.POINTF
          ;Calcule des perpendiculaires
          M\x = *b\P[0]\x + Dist * Cos(Ang*#PI/180)
          M\y = *b\P[0]\y + Dist * Sin(Ang*#PI/180)

          UP\x = M\x + h * Cos((Ang+90)*#PI/180)
          UP\y = M\y + h * Sin((Ang+90)*#PI/180)
       
          DW\x = M\x - h * Cos((Ang+90)*#PI/180)
          DW\y = M\y - h * Sin((Ang+90)*#PI/180)
      
          AddElement(Droites())
          Droites()\P1\x=UP\x
          Droites()\P1\y=UP\y
          Droites()\P2\x=DW\x
          Droites()\P2\y=DW\y

         ;Dessin des Perpendiculaire
         LineXY(UP\x ,UP\y,DW\x,DW\y,255)
          
          Else 
                  left.BEZIER 
                  right.BEZIER
                 
                 left\P[0]\x = *b\P[0]\x
                 left\P[0]\y = *b\P[0]\y
                 left\P[1]\x = (*b\P[0]\x + *b\P[1]\x) / 2
                 left\P[1]\y = (*b\P[0]\y + *b\P[1]\y) / 2
                 left\P[2]\x = (*b\P[0]\x + 2**b\P[1]\x + *b\P[2]\x) / 4
                 left\P[2]\y = (*b\P[0]\y + 2**b\P[1]\y + *b\P[2]\y) / 4
                 left\P[3]\x = (*b\P[0]\x + 3**b\P[1]\x + 3**b\P[2]\x + *b\P[3]\x) / 8
                 left\P[3]\y = (*b\P[0]\y + 3**b\P[1]\y + 3**b\P[2]\y + *b\P[3]\y) / 8
                  
  ;               DrawBezierBase(left,RGB(0,255,0))
                 right\P[0]\x = left\P[3]\x;
                 right\P[0]\y = left\P[3]\y;
                 right\P[1]\x = (*b\P[1]\x + 2**b\P[2]\x + *b\P[3]\x) / 4
                 right\P[1]\y = (*b\P[1]\y + 2**b\P[2]\y + *b\P[3]\y) / 4
                 right\P[2]\x = (*b\P[2]\x + *b\P[3]\x) / 2
                 right\P[2]\y = (*b\P[2]\y + *b\P[3]\y) / 2
                 right\P[3]\x = *b\P[3]\x
                 right\P[3]\y = *b\P[3]\y
                 
                
;                 DrawBezierBase(right,RGB(0,0,255));
                 DrawBezierRecursive (left, level -1);
                 DrawBezierRecursive (right, level -1);
         EndIf
         

EndProcedure

Procedure DrawBezier(Global_Bezier,level)
       DrawBezierBase(Global_Bezier,RGB(255,255,255));
       DrawBezierRecursive(Global_Bezier,level);
EndProcedure
ca peu toujours te servir.
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: Trouver un point entre deux points

Message par blendman »

@falsam : ok, j'attends de tester ;)

@G-rom : merci, je l'avais déjà trouvé ton code :mrgreen:, le résultat est superbe. Je m'en servirai sans doute par la suite, lorsque j'ajouterai des outils simples en vectoriel (enfin, si j'y arrive ^^).
Avatar de l’utilisateur
falsam
Messages : 7317
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Trouver un point entre deux points

Message par falsam »

J'ai juste ajouté

Code : Tout sélectionner

Global NewList Points.Point() 
Point est une structure PureBasic
et

Code : Tout sélectionner

;Mémorisation des points 
AddElement(Points())
Points()\x = \lastX
Points()\y = \lasty
Le code mise à jour

Code : Tout sélectionner

Enumeration Window
  #MainForm
EndEnumeration

Enumeration Gadgets
  #Canvas
EndEnumeration

Structure Canvas
  LeftButtonDown.i
  RightButtonDown.i
  LastX.i
  LastY.i
EndStructure

Global Draw, This.Canvas

Global CurrentPoint.Point
Global LastPoint.Point
Global NewList Points.Point()

Declare EventDraw()
Declare.d Distance(*p.Point, *q.Point)

If OpenWindow(#MainForm, 0, 0, 1024, 768, "Canvas Draw", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  CanvasGadget(#Canvas, 0, 0, 1024, 768)
  BindGadgetEvent(#Canvas, @EventDraw())
  
  Repeat : Until WaitWindowEvent(10) = #PB_Event_CloseWindow
EndIf

Procedure EventDraw()
  
  Protected x.i = GetGadgetAttribute(#Canvas, #PB_Canvas_MouseX)
  Protected y.i = GetGadgetAttribute(#Canvas, #PB_Canvas_MouseY)
  Protected color.l = RGB(128, 128, 128)
  Protected Distance.f, Interval = 40
  
  With This
    Select EventType()
       Case #PB_EventType_LeftButtonDown
         \LeftButtonDown = #True
            \LastX = x
            \LastY = y 
            
         Case #PB_EventType_LeftButtonUp
           \LeftButtonDown = #False
           
         Case #PB_EventType_RightButtonDown           
            \RightButtonDown = #True
            \lastX = x
            \lastY = y
            
         Case #PB_EventType_RightButtonUp
           \RightButtonDown = #False
           
         Case #PB_EventType_MouseMove   
           Draw = #False
           If (\LeftButtonDown Or \RightButtonDown)
                  Draw = #True
           EndIf
            
      EndSelect
      
      
      ;Pour cet démo la distance entre deux vecteurs est de 40pixels
      If Draw
        ;Quel est le point courrant ?
        CurrentPoint\x = x
        CurrentPoint\y = y
        
        ;Quel est le dernier point
        LastPoint\x = \lastX
        LastPoint\y = \lastY
        
        ;Distance entres ces deux vecteurs
        Distance = Distance(LastPoint, CurrentPoint)
        
        
        If StartDrawing(CanvasOutput(#Canvas))
          
          If Distance > Interval      
            ;Mémorisation des points 
            AddElement(Points())
            Points()\x = \lastX
            Points()\y = \lasty
            
            ;Ici je ne sais pas comment faire pour la courbe de bézier
            ;par contre tu peux visualiser la liste chainée dans les options de débogage
            
            Circle(\lastX, \lastY, 10, color)
            \lastX = x
            \lastY = y
          EndIf
          
          StopDrawing()
         EndIf
      EndIf
   EndWith
 EndProcedure
 
 ;Distance entres deux vecteurs
 Procedure.d Distance(*p.Point, *q.Point)
  Protected Distance.d
  
  ;Distance horizontale
  dx.d = *p\x - *q\x   
  
  ;Distance verticale
  dy.d = *p\y - *q\y
  
  ;Théoréme de Pythagore
  Distance.d = Sqr(dx*dx + dy*dy )
  
  ProcedureReturn Distance
EndProcedure
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: Trouver un point entre deux points

Message par blendman »

@falsam : ok pour la sauvegarde, manque plus que la correction des points quand on dessine ultra-vite, comme un foufou (comme moi lol) :mrgreen:
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: Trouver un point entre deux points

Message par G-Rom »

falsam a écrit :

Code : Tout sélectionner

Global NewList Points.Point() 
Point est une structure PureBasic
Non, c'est une structure de l'api windows. ;)
Avatar de l’utilisateur
falsam
Messages : 7317
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Trouver un point entre deux points

Message par falsam »

@G-Rom: Ooops tu as raison c'est une API :)

J'ai changé mon code pour éviter les API mais malheureusement il n'est pas parfait et j'avoue que je cale !!

Code : Tout sélectionner

EnableExplicit

Enumeration Window
  #MainForm
EndEnumeration

Enumeration Gadgets
  #Canvas
EndEnumeration

Structure Canvas
  LeftButtonDown.i
  RightButtonDown.i
EndStructure

Global Draw, This.Canvas

Structure VPoint
  x.f
  y.f
EndStructure

Global PreviousPoint.VPoint
Global CurrentPoint.VPoint

Declare EventDraw()
Declare.d Distance(*p.VPoint, *q.VPoint)

If OpenWindow(#MainForm, 0, 0, 1024, 768, "Canvas Draw", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  CanvasGadget(#Canvas, 0, 0, 1024, 768)
  BindGadgetEvent(#Canvas, @EventDraw())
  
  Repeat : Until WaitWindowEvent(0) = #PB_Event_CloseWindow
EndIf

Procedure EventDraw()
  
  Protected color.l = RGB(128, 128, 128)
  Protected Distance
  Protected Interval = 30
  Protected CountPoint, N
  
  Protected x = GetGadgetAttribute(#Canvas, #PB_Canvas_MouseX)
  Protected y = GetGadgetAttribute(#Canvas, #PB_Canvas_MouseY)
  
  Protected NextPointX.f, NextPointY.f
  Protected DeltaX.f, DeltaY.f
  
  With This
    Select EventType()
      Case #PB_EventType_LeftButtonDown
        \LeftButtonDown = #True
        PreviousPoint\x = x
        PreviousPoint\Y = y 
              
      Case #PB_EventType_LeftButtonUp
        \LeftButtonDown = #False
        CurrentPoint\x = x
        CurrentPoint\Y = y 
                      
       Case #PB_EventType_MouseMove   
         Draw = #False
         If (\LeftButtonDown Or \RightButtonDown)
           Draw = #True
           CurrentPoint\x = x
           CurrentPoint\Y = y 
         EndIf
      EndSelect
      
      ;Drawing
      If Draw
                
        ;distance between two vectors
        Distance = Distance(PreviousPoint, CurrentPoint)
        
        If StartDrawing(CanvasOutput(#Canvas))
          
          If Distance >= Interval      
            
            ;Combien de points possibles entres les deux vecteurs
            CountPoint = Distance / interval
            Debug CountPoint
            
            ;Memorizing the first point
            NextPointX = PreviousPoint\x
            NextPointY = PreviousPoint\y
            
            DeltaX = CurrentPoint\x - PreviousPoint\x 
            DeltaY = CurrentPoint\y - PreviousPoint\y
            
            ; Place the equidistant point
            For N = 1 To CountPoint
              
              NextPointX = NextPointX + Round(DeltaX/CountPoint,#PB_Round_Nearest) 
              NextPointY = NextPointY + Round(DeltaY/CountPoint,#PB_Round_Nearest)
              
              If N = 1
                Circle(NextPointX, NextPointY, 10, RGB(218, 165, 32))
              Else
                Circle(NextPointX, NextPointY, 10, RGB(154, 205, 50))
              EndIf              
            Next
            
            PreviousPoint\x = NextPointX
            PreviousPoint\y = NextPointY
            
          EndIf
          
          StopDrawing()
         EndIf
      EndIf
   EndWith
 EndProcedure
 
 
 Procedure.d Distance(*p.VPoint, *q.VPoint)
  Protected Distance.d, dx.d, dy.d
  
  dx = *p\x - *q\x   
  dy = *p\y - *q\y
  
  Distance = Sqr(dx*dx + dy*dy )
  
  ProcedureReturn Distance
EndProcedure
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Répondre