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 :
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
Re: Find a point between two points
Posted: Wed Jun 24, 2015 1:19 pm
by Julian
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.
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

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
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