Page 1 of 2

Find a point between two points

Posted: Wed Jun 24, 2015 12:56 pm
by [blendman]
Hi

I would like to find a point between two points.
I know :
- A(x,y)
- B(x,y,)
- The angle (direction) between A and B
- The distance I would like between A and C (I can change this distance if I want)

I use :

Code: Select all

Macro distance(x1,y1,x2,y2)   
  Int(Sqr((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)) )       
EndMacro

Macro direction(x1,y1,x2,y2) ; angle
  ATan2((y2- y1),(x2- x1))
EndMacro
I'm looking for the position (x and y) of C.
(The distance between A and C = what I like (10 for example)).

An image to understand :
Image

How can I do that, please ?

Thank you.

Re: Find a point between two points

Posted: Wed Jun 24, 2015 1:15 pm
by Julian
Linear interpolation between two known points

https://en.wikipedia.org/wiki/Linear_interpolation

Re: Find a point between two points

Posted: Wed Jun 24, 2015 1:19 pm
by Julian
You should be able to find what you want here:

http://www.forums.purebasic.com/english ... 7b#p375211

Re: Find a point between two points

Posted: Wed Jun 24, 2015 1:22 pm
by infratec
Fundamental trigonometry:

Code: Select all

Macro distance(x1,y1,x2,y2)   
  Int(Sqr((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)) )       
EndMacro

Macro direction(x1,y1,x2,y2) ; angle
  ATan2((y2- y1),(x2- x1))
EndMacro

Procedure.i coordinate(x1.i, y1.i, distance.i, direction.f, *x2, *y2)
  
  PokeI(*x2, x1 + (distance * Sin(direction)))
  PokeI(*y2, y1 + (distance * Cos(direction)))
  
EndProcedure



Define.i x1, y1, x2, y2, x3, y3

x1 = 10
y1 = 10

x2 = 50
y2 = 100

Debug distance(x1, y1, x2, y2)
Debug Degree(direction(x1, y1, x2, y2))

coordinate(x1, y1, 20, direction(x1, y1, x2, y2), @x3, @y3)

Debug Str(x3) + " x " + Str(y3)


OpenWindow(0, 0, 0, 800, 600, "Test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)

CreateImage(0, 800, 600)
If StartDrawing(ImageOutput(0))
  Circle(x1, y1, 3, #White)
  Circle(x2, y2, 3, #White)
  
  LineXY(x1, y1, x2, y2, #Red)
  
  Circle(x3, y3, 3, #Green)
  StopDrawing()
EndIf


ImageGadget(0, 0, 0, 800, 600, ImageID(0))

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
Bernd

Re: Find a point between two points

Posted: Wed Jun 24, 2015 2:28 pm
by wilbert

Code: Select all

Procedure CalcPoint(x0.f, y0.f, x1.f, y1.f, distance.f, *x2.Float, *y2.Float)
  Protected.f dx, dy, p
  dx = x1 - x0
  dy = y1 - y0
  p = distance / Sqr(dx*dx + dy*dy)
  *x2\f = x0 + dx * p
  *y2\f = y0 + dy * p
EndProcedure

CalcPoint(5, 5, 10, 10, 3.5, @x.f, @y.f)
Debug x
Debug y

Re: Find a point between two points

Posted: Wed Jun 24, 2015 10:25 pm
by falsam
Blendman wants to place these points in real time while he draws with his software Animatoon.

:arrow: http://www.purebasic.fr/english/viewtop ... 30#p356530

I propose that code, but unfortunately it does not work and I do not understand why.

Code: Select all

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

Re: Find a point between two points

Posted: Thu Jun 25, 2015 7:46 am
by sancho2
I am not %100 sure what want this code to do or what any error is, but I did notice that:
1. 'interval' is set at 30 and never changes
2. 'Distance' is the distance the mouse travels
3. As soon as distance is greater than or equal to interval you do a calculation distance/ interval
Doesn't that mean that as soon as distance = 30 you do 30/30 and always get 1 as a result?
falsam wrote:

Code: Select all

...
  Protected Interval = 30
...
        Distance = Distance(PreviousPoint, CurrentPoint)
...          
          If Distance >= Interval      
            
            ;Combien de points possibles entres les deux vecteurs
            CountPoint = Distance / interval
            Debug CountPoint
            

Re: Find a point between two points

Posted: Thu Jun 25, 2015 10:10 am
by falsam
sancho2 wrote:I am not %100 sure what want this code to do or what any error is
Hello sancho. The goal is to draw points (or other drafting patterns) at regular interval.

Re: Find a point between two points

Posted: Thu Jun 25, 2015 10:16 am
by infratec
Don't know 100% your intention, but this does something:

Code: Select all

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
        Draw = #True
                     
;       Case #PB_EventType_MouseMove           
;          Draw = #False
;          If (\LeftButtonDown Or \RightButtonDown)
;            Draw = #True
;            CurrentPoint\x = x
;            CurrentPoint\Y = y
;          EndIf
      EndSelect
Bernd

Re: Find a point between two points

Posted: Thu Jun 25, 2015 11:06 am
by falsam
Hello infratec. If i comment these instructions, the code no longer works.

Re: Find a point between two points

Posted: Thu Jun 25, 2015 11:09 am
by infratec
Did you see the

Code: Select all

Draw = #TRUE
:?:

Re: Find a point between two points

Posted: Thu Jun 25, 2015 11:10 am
by falsam
I add a clarification to my request. :)

The code works if the mouse route is slow.

If I go too fast with the mouse, the intervals among the points are no longer regular.

Re: Find a point between two points

Posted: Thu Jun 25, 2015 11:14 am
by falsam
infratec wrote:Did you see the #True ?
Yes Infratec. But i would like to draw without releasing the left mouse button.

Re: Find a point between two points

Posted: Thu Jun 25, 2015 5:46 pm
by Comtois
infratec wrote:Fundamental trigonometry:
Yes

Or this way

Code: Select all

Structure Vector2
	x.f
	y.f
EndStructure

Macro direction(direction,x1,y1,x2,y2) 
	direction\x=x2-x1
	direction\y=y2-y1
EndMacro

Procedure Norme(*V.Vector2)
   Define.f Norme
   
   Norme.f = Sqr(*V\x * *V\x + *V\y * *V\y)
   If Norme
      *V\x / Norme
      *V\y / Norme
   EndIf
EndProcedure

Define.i x1, y1, x2, y2, x3, y3
Define direction.Vector2 ; direction

x1 = 10
y1 = 10

x2 = 50
y2 = 100

Direction(direction,x1,y1,x2,y2) 
Norme(@direction)

Distance = 20
x3 = x1 + Distance * Direction\x 
y3 = y1 + Distance * Direction\y 


OpenWindow(0, 0, 0, 800, 600, "Test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)

CreateImage(0, 800, 600)
If StartDrawing(ImageOutput(0))
  Circle(x1, y1, 3, #White)
  Circle(x2, y2, 3, #White)
 
  LineXY(x1, y1, x2, y2, #Red)
 
  Circle(x3, y3, 3, #Green)
  StopDrawing()
EndIf


ImageGadget(0, 0, 0, 800, 600, ImageID(0))

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Re: Find a point between two points

Posted: Fri Jun 26, 2015 5:22 pm
by Julian
Julian wrote:Linear interpolation between two known points

https://en.wikipedia.org/wiki/Linear_interpolation
The Lerp method uses no additional functions and the magnitude method only uses one Sqr call.

I'll finish this Vector2D library another day.

Code: Select all

Structure Vector2D
  x.f
  y.f
EndStructure

Macro Vector2D_Add(rV, v1, v2)
  rV\x = v1\x + v2\x
  rV\y = v1\y + v2\y
EndMacro

Macro Vector2D_Subtract(rV, v1, v2)
  rV\x = v1\x - v2\x
  rV\y = v1\y - v2\y
EndMacro

Macro Vector2D_Multiply(rV, v1, v2)
  rV\x = v1\x * v2\x
  rV\y = v1\y * v2\y
EndMacro

Macro Vector2D_MultiplyByFloat(rV, v1, f)
  rV\x = v1\x * f
  rV\y = v1\y * f
EndMacro

Macro Vector2D_Magnitude(magnitude, v1)
  CompilerIf #PB_Compiler_Debugger = #True
    If TypeOf(magnitude) <> #PB_Float
      Debug "WARNING: You are not using a float for the return value of Vector2D_Magnitude, precision might be lost"
    EndIf
  CompilerEndIf
  magnitude = Sqr(v1\x * v1\x + v1\y * v1\y)
EndMacro

Macro Vector2D_SqrMagnitude(magnitude, v1)
  CompilerIf #PB_Compiler_Debugger = #True
    If TypeOf(magnitude) <> #PB_Float
      Debug "WARNING: You are not using a float for the return value of Vector2D_SqrMagnitude, precision might be lost"
    EndIf
  CompilerEndIf
  magnitude = v1\x * v1\x + v1\y * v1\y
EndMacro

Macro Vector2D_Lerp(output, v1, v2, f)
  Vector2D_Subtract(output, v2, v1)
  Vector2D_MultiplyByFloat(output, output, f)
  Vector2D_Add(output, v1, output)
EndMacro

Define A.Vector2D
Define B.Vector2D
Define C.Vector2D
Define magnitude.f
Define distance.f

;     A 0,3
;     |\
;     | C (2,1.5)
;     |  \
; 0,0 ----B 4,0

A\x = 0
A\y = 3

B\x = 4
B\y = 0

;Use this method if you want to move along the line be a proportion of the length of the line
;ie. If you dont actually know how long the line will be but you want to be half way along
;You can shoot over the end of the line by going over 1 or before the start of the line by going under 0
distance = 0.5 ; float from 0 to 1, 0 is the origin and 1 is the destination
Vector2D_Lerp(C, A, B, distance)
Debug "Lerp version"
Debug "C x=" + C\x
Debug "C y=" + C\y

;Use this method if you want to move along the line by a float value
distance = 2.5 ; any float represnting a distance away from A
Vector2D_Subtract(C, B, A) ; Make sure we are calculating from the origin
Vector2D_Magnitude(magnitude, C) ; Return the length of the vector
Vector2D_Lerp(C, A, B, distance / magnitude) ; Move along the vector
Debug "Magnitude version"
Debug "C x=" + C\x
Debug "C y=" + C\y