Page 1 of 2

Zoom an vector drawn image

Posted: Tue Mar 14, 2017 10:40 am
by Amundo
Hi All, it pains me to ask for help, but what little hair I have left will not last much longer!

Attached code draws an object using the Vector Drawing library. I have the movement and rotation worked out, I just can't for the life of me work out how to zoom the object and have it rendered in the same x/y position.

(Zoom is via NUMPAD+/-, Movement via arrow keys, Rotate via CTRL-LEFT/CTRL-RIGHT).

The code is part of creating a more complex object, just wanted to get the basics going first.

Any help much appreciated! (I just know it's something simple :oops: )

Code: Select all

EnableExplicit

;-> Globals
Global.l hWndInv
; ; Global.l srcNumber, srcWidth, srcHeight, srcDepth
Global.l hwnd, xPos, yPos, Factor, event, KeyPressed, width, height, oldxPos, oldyPos, oldwidth, oldheight
Global.d oldAngle, rotation, Zoom
Global.l width, height, screenWidth, screenHeight
;}

;-> Constants
#ProgName         = "Spiral"
#MaskColor        = 0
#AlphaLevel       = 5
#initialImageSize = 800
#EE                = 2.718281828
#maxLoops         = 5000
#direction        = 0
#deg2rad          = 0.0175
#minSize          = 10
#maxSize          = 8180
#maxZoom          = 120 ; for some reason, numbers above this GPF
#ZoomFactor1      = 0.01
#ZoomFactor2      = 0.1
#ZoomFactor3      = 1
#RotateFactor1    = 1
#RotateFactor2    = 10
#RotateFactor3    = 45
#SizeFactor1      = 10
#SizeFactor2      = 20
#SizeFactor3      = 30
#PosFactor1       = #SizeFactor1 / 2
#PosFactor2       = #SizeFactor2 / 2
#PosFactor3       = #SizeFactor3 / 2
;}

;-> Enumerations
Enumeration
	#ZoomIn
	#ZoomIn2
	#ZoomIn3
	#ZoomOut
	#ZoomOut2
	#ZoomOut3
	#MoveLeft
	#MoveLeft2
	#MoveRight
	#MoveRight2
	#MoveUp
	#MoveUp2
	#MoveDown
	#MoveDown2
	#RotateC
	#RotateC2
	#RotateC3
	#RotateCC
	#RotateCC2
	#RotateCC3
	#ESCape
	#Reset
EndEnumeration
;}

#DotSpacing              = 5
#ZoomFactor              = 0.5

Procedure DrawStar()
	
	#MiddleX	= 552
	#MiddleY	= 360
	#MinX			= -1000
	#MinY			= -1000
	#MaxX			= 2000
	#MaxY			= 2000
	
	Protected.l i
	
	If StartVectorDrawing(WindowVectorOutput(0))
		
		VectorSourceColor(RGBA(0, 0, 0, 255))
		FillVectorOutput()
		TranslateCoordinates(xPos, yPos)
		; ; 		TranslateCoordinates(xPos * Zoom, yPos * Zoom)
		RotateCoordinates(#MiddleX * Zoom, #MiddleY * Zoom, rotation)
		ScaleCoordinates(Zoom, Zoom)
		VectorSourceColor(RGBA(255, 0, 0, 255))
		
		; Draw spokes
		VectorSourceColor(RGBA(0, 255, 0, 255))
		MovePathCursor(#MiddleX, #MinY, #PB_Path_Default)
		AddPathLine(#MiddleX, #MaxY)
		MovePathCursor(#MinX, #MiddleY)
		AddPathLine(#MaxX, #MiddleY)
		
		MovePathCursor(#MiddleX, #MiddleY)
		AddPathLine(200, 200, #PB_Path_Relative)
		MovePathCursor(#MiddleX, #MiddleY)
		AddPathLine(-200, -200, #PB_Path_Relative)
		MovePathCursor(#MiddleX, #MiddleY)
		AddPathLine(200, -200, #PB_Path_Relative)
		MovePathCursor(#MiddleX, #MiddleY)
		AddPathLine(-200, 200, #PB_Path_Relative)
		
		DashPath(1, 5)
		
		StopVectorDrawing()
		
	EndIf
	
EndProcedure													 ;DrawStar()

Procedure UpdateImage()
	Protected hdc
	
	SetWindowTitle(0, #ProgName + "  Zoom:" + StrF(Zoom, 4) + "  Width:" + StrF(width, 4))
	
	DrawStar()
	
EndProcedure ;UpdateImage()

Procedure ResetStar()
	
	rotation = 0
	Zoom = 1
	width = 800
	height = width
	UpdateImage()
	
EndProcedure

Procedure Initialise()
	
	xPos = 0
	yPos = 0
	rotation = 0
	Zoom = 1
	width = 800
	height = width
	
	ExamineDesktops()
	
	hWndInv = OpenWindow(0, 0, 0, DesktopWidth(0) / 2, DesktopHeight(0) / 2, #ProgName, _
	#PB_Window_TitleBar | #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_ScreenCentered | _
	#PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget, 0)
	SetWindowColor(0, #MaskColor)
	SetWindowLong_(hWndInv, #GWL_EXSTYLE, GetWindowLong_(hWndInv, #GWL_EXSTYLE) | #WS_EX_LAYERED)
	SetLayeredWindowAttributes_(hWndInv, #MaskColor, 1, #LWA_COLORKEY)
	StickyWindow(0, 1)
	
	AddKeyboardShortcut(0, #PB_Shortcut_Add, #ZoomIn)
	AddKeyboardShortcut(0, #PB_Shortcut_Add + #PB_Shortcut_Shift, #ZoomIn2)
	AddKeyboardShortcut(0, #PB_Shortcut_Add + #PB_Shortcut_Alt, #ZoomIn3)
	AddKeyboardShortcut(0, #PB_Shortcut_Subtract, #ZoomOut)
	AddKeyboardShortcut(0, #PB_Shortcut_Subtract + #PB_Shortcut_Shift, #ZoomOut2)
	AddKeyboardShortcut(0, #PB_Shortcut_Subtract + #PB_Shortcut_Alt, #ZoomOut3)
	AddKeyboardShortcut(0, #PB_Shortcut_Left, #MoveLeft)
	AddKeyboardShortcut(0, #PB_Shortcut_Left + #PB_Shortcut_Shift, #MoveLeft2)
	AddKeyboardShortcut(0, #PB_Shortcut_Right, #MoveRight)
	AddKeyboardShortcut(0, #PB_Shortcut_Right + #PB_Shortcut_Shift, #MoveRight2)
	AddKeyboardShortcut(0, #PB_Shortcut_Up, #MoveUp)
	AddKeyboardShortcut(0, #PB_Shortcut_Up + #PB_Shortcut_Shift, #MoveUp2)
	AddKeyboardShortcut(0, #PB_Shortcut_Down, #MoveDown)
	AddKeyboardShortcut(0, #PB_Shortcut_Down + #PB_Shortcut_Shift, #MoveDown2)
	AddKeyboardShortcut(0, #PB_Shortcut_Right + #PB_Shortcut_Control, #RotateC)
	AddKeyboardShortcut(0, #PB_Shortcut_Right + #PB_Shortcut_Control + #PB_Shortcut_Shift, #RotateC2)
	AddKeyboardShortcut(0, #PB_Shortcut_Right + #PB_Shortcut_Alt, #RotateC3)
	AddKeyboardShortcut(0, #PB_Shortcut_Left + #PB_Shortcut_Control, #RotateCC)
	AddKeyboardShortcut(0, #PB_Shortcut_Left + #PB_Shortcut_Control + #PB_Shortcut_Shift, #RotateCC2)
	AddKeyboardShortcut(0, #PB_Shortcut_Left + #PB_Shortcut_Alt, #RotateCC3)
	AddKeyboardShortcut(0, #PB_Shortcut_Escape, #ESCape)
	AddKeyboardShortcut(0, #PB_Shortcut_R + #PB_Shortcut_Control, #Reset)
	
	DrawStar()
	
EndProcedure ;Initialise()

;-> MAIN

Initialise()

UpdateImage()

Repeat
	
	event = WaitWindowEvent()
	
	Select event
			
		Case #PB_Event_Repaint
			screenWidth = WindowWidth(0)
			UpdateImage()
			
		Case #PB_Event_Menu
			KeyPressed = EventMenu()
			;      Debug KeyPressed
			
			Select KeyPressed
					
					;-Move 
				Case #MoveLeft
					xPos - 1
					;          Debug "xPos: " + Str(xPos)
					UpdateImage()
				Case #MoveLeft2
					xPos - 10
					UpdateImage()
				Case #MoveRight
					xPos + 1
					;          Debug "xPos: " + Str(xPos)
					UpdateImage()
				Case #MoveRight2
					xPos + 10
					UpdateImage()
				Case #MoveUp
					yPos - 1
					UpdateImage()
				Case #MoveUp2
					yPos - 10
					UpdateImage()
				Case #MoveDown
					yPos + 1
					UpdateImage()
				Case #MoveDown2
					yPos + 10
					UpdateImage()
					
					;-Zoom Spiral In
				Case #ZoomIn
					Debug "Case #ZoomIn"
					Debug "Zoom = " + StrF(Zoom)
					Debug "width = " + StrF(width)
					Debug "screenWidth = " + StrF(screenWidth)
					; ; ; ; ;       If Zoom <= #maxZoom And width < screenWidth
					If Zoom <= #maxZoom
						Debug "If Zoom <= #maxZoom And width < screenWidth"
						Zoom + #ZoomFactor1
						width + #SizeFactor1 : height + #SizeFactor1
						xPos - #PosFactor1 : yPos - #PosFactor1
						UpdateImage()
					Else
						Debug "NOT If Zoom <= #maxZoom And width < screenWidth"
					EndIf
				Case #ZoomIn2
					Debug "Case #ZoomIn2"
					If Zoom <= #maxZoom
						; If width < #maxSize
						Zoom + #ZoomFactor2
						width + #SizeFactor2 : height + #SizeFactor2
						xPos - #PosFactor2 : yPos - #PosFactor2
						UpdateImage()
					EndIf
				Case #ZoomIn3
					Debug "Case #ZoomIn3"
					If Zoom <= #maxZoom
						Zoom + #ZoomFactor3
						width + #SizeFactor3 : height + #SizeFactor3
						xPos - #PosFactor3 : yPos - #PosFactor3
						UpdateImage()
					EndIf
					
					;-Zoom  Out
				Case #ZoomOut
					Debug "Case #ZoomOut"
					If width > #minSize
						If Zoom > #ZoomFactor1
							Zoom - #ZoomFactor1
							If Zoom <= 0
								Zoom = #ZoomFactor1
							EndIf
							width - #SizeFactor1 : height - #SizeFactor1
							xPos + #PosFactor1 : yPos + #PosFactor1
							UpdateImage()
						EndIf
					EndIf
				Case #ZoomOut2
					Debug "Case #ZoomOut2"
					If width > #minSize
						If Zoom > #ZoomFactor2
							Zoom - #ZoomFactor2
							If Zoom <= 0
								Zoom = #ZoomFactor2
							EndIf
							width - #SizeFactor2 : height - #SizeFactor2
							xPos + #PosFactor2 : yPos + #PosFactor2
							UpdateImage()
						EndIf
					EndIf
				Case #ZoomOut3
					Debug "Case #ZoomOut3"
					If width > #minSize
						If Zoom > #ZoomFactor3
							Zoom - #ZoomFactor3
							If Zoom <= 0
								Zoom = #ZoomFactor3
							EndIf
							width - #SizeFactor3 : height - #SizeFactor3
							xPos + #PosFactor3 : yPos + #PosFactor3
							UpdateImage()
						EndIf
					EndIf
					
					;- Rotate  Clockwise
				Case #RotateC
					rotation - #RotateFactor1
					;          Debug "Angle: " + StrF(ANGLE)
					UpdateImage()
				Case #RotateC2
					rotation - #RotateFactor2
					;          Debug "Angle: " + StrF(ANGLE)
					UpdateImage()
				Case #RotateC3
					rotation - #RotateFactor3
					;          Debug "Angle: " + StrF(ANGLE)
					UpdateImage()
					
					;-Rotate 1 CounterClockwise
				Case #RotateCC
					rotation + #RotateFactor1
					;          Debug "Angle: " + StrF(ANGLE)
					UpdateImage()
				Case #RotateCC2
					rotation + #RotateFactor2
					;          Debug "Angle: " + StrF(ANGLE)
					UpdateImage()
				Case #RotateCC3
					rotation + #RotateFactor3
					;          Debug "Angle: " + StrF(ANGLE)
					UpdateImage()
					
				Case #Reset
					ResetStar()
					
			EndSelect ;KeyPressed
			
	EndSelect ;Event
	
Until KeyPressed = #ESCape Or event = #PB_Event_CloseWindow

End
;}

Re: Zoom an vector drawn image

Posted: Tue Mar 14, 2017 10:54 am
by Torp
May be that this code could help you ?

Code: Select all

EnableExplicit

Declare Ev_MouseMove()
Declare Ev_Repaint()
Declare Ev_MousePan()
Declare Ev_MouseWheel()

Global.i Event
Global.d x_PosOrigin, y_PosOrigin, Zoom, Zoom_Factor, y_WscreenSize, x_WscreenSize

Zoom_Factor = 1.10 : Zoom = 1.0

;{ Evènements personnalisés
Enumeration #PB_Event_FirstCustomValue
   #Ev_Repaint
EndEnumeration
;}

;{ Structure Mouse/Curseur }
Structure Str_Mouse
   x_Wld.d                        ;// Coordonnée X monde avant "TranslateCoordinates"
   y_Wld.d                        ;// Coordonnée Y monde avant "TranslateCoordinates"
   
   x_CoordW.d                  ;// Coordonnée X monde
   y_CoordW.d                  ;// Coordonnée X monde
   
   x_PrW.d                        ;// Coordonnée X monde précédente
   y_PrW.d                        ;// Coordonnée Y monde précédente
   
   x_Can.l                        ;// Coordonnée Souris X sur le Canvas
   y_Can.l                        ;// Coordonnée Souris Y sur le Canvas
   
   Move.b                        ;// La souris se déplace
   Pan.b                           ;// Déplacement panoramique
   Wheel.b                        ;// Molette Souris
EndStructure

;Init Structure
Global Mouse.Str_Mouse
;}

Procedure Ev_MouseMove()
   Mouse\x_Can = GetGadgetAttribute(0, #PB_Canvas_MouseX)
   Mouse\y_Can = GetGadgetAttribute(0, #PB_Canvas_MouseY)
   Mouse\Move ! 1
   PostEvent(#Ev_Repaint)
EndProcedure

Procedure Ev_MousePan()
   Mouse\Pan ! 1 ; inverse la valeur 0|1
EndProcedure

Procedure Ev_MouseWheel()
   Mouse\Wheel ! 1
   Select GetGadgetAttribute(0, #PB_Canvas_WheelDelta)
      Case 1
         ;Debug "in"
         Zoom =  Zoom * Zoom_Factor
      Case -1
         ;Debug "out"
         Zoom = Zoom / Zoom_Factor   
   EndSelect
   PostEvent(#Ev_Repaint)
EndProcedure

Procedure Ev_Repaint()
   ;Debug "Repaint"
   If StartVectorDrawing(CanvasVectorOutput(0, #PB_Unit_Millimeter))
     
      VectorFont(FontID(0), 3)
     
      FlipCoordinatesY(y_WscreenSize / 2, #PB_Coordinate_User) ; 0,0 en bas à gauche
      ScaleCoordinates(Zoom, Zoom, #PB_Coordinate_User)
     
      If Mouse\Move And Not Mouse\Pan
         ;Debug "Move"
         Mouse\Move ! 1
         Mouse\x_Wld = ConvertCoordinateX(Mouse\x_Can, Mouse\y_Can, #PB_Coordinate_Device, #PB_Coordinate_User)
         Mouse\y_Wld = ConvertCoordinateY(Mouse\x_Can, Mouse\y_Can, #PB_Coordinate_Device, #PB_Coordinate_User)
         TranslateCoordinates(x_PosOrigin, y_PosOrigin, #PB_Coordinate_User)
         Mouse\x_CoordW = ConvertCoordinateX(Mouse\x_Can, Mouse\y_Can, #PB_Coordinate_Device, #PB_Coordinate_User)
         Mouse\y_CoordW = ConvertCoordinateY(Mouse\x_Can, Mouse\y_Can, #PB_Coordinate_Device, #PB_Coordinate_User)
      ElseIf Mouse\Move And Mouse\Pan
         ;Debug "Move et Pan"
         Mouse\Move ! 1
         Mouse\x_PrW = Mouse\x_Wld
         Mouse\y_PrW = Mouse\y_Wld
         Mouse\x_Wld = ConvertCoordinateX(Mouse\x_Can, Mouse\y_Can, #PB_Coordinate_Device, #PB_Coordinate_User)
         Mouse\y_Wld = ConvertCoordinateY(Mouse\x_Can, Mouse\y_Can, #PB_Coordinate_Device, #PB_Coordinate_User)
         x_PosOrigin = x_PosOrigin + Mouse\x_Wld - Mouse\x_PrW
         y_PosOrigin = y_PosOrigin + Mouse\y_Wld - Mouse\y_PrW
         TranslateCoordinates(x_PosOrigin, y_PosOrigin, #PB_Coordinate_User)
         Mouse\x_CoordW = ConvertCoordinateX(Mouse\x_Can, Mouse\y_Can, #PB_Coordinate_Device, #PB_Coordinate_User)
         Mouse\y_CoordW = ConvertCoordinateY(Mouse\x_Can, Mouse\y_Can, #PB_Coordinate_Device, #PB_Coordinate_User)
      ElseIf Mouse\Wheel
         ;Debug "Wheel"
         Mouse\x_PrW = Mouse\x_Wld
         Mouse\y_PrW = Mouse\y_Wld
         Mouse\x_Wld = ConvertCoordinateX(Mouse\x_Can, Mouse\y_Can, #PB_Coordinate_Device, #PB_Coordinate_User)
         Mouse\y_Wld = ConvertCoordinateY(Mouse\x_Can, Mouse\y_Can, #PB_Coordinate_Device, #PB_Coordinate_User)
         x_PosOrigin = x_PosOrigin  +  Mouse\x_Wld - Mouse\x_PrW
         y_PosOrigin = y_PosOrigin  +    Mouse\y_Wld - Mouse\y_PrW
         TranslateCoordinates(x_PosOrigin, y_PosOrigin, #PB_Coordinate_User)
         Mouse\x_CoordW = ConvertCoordinateX(Mouse\x_Can, Mouse\y_Can, #PB_Coordinate_Device, #PB_Coordinate_User)
         Mouse\y_CoordW = ConvertCoordinateY(Mouse\x_Can, Mouse\y_Can, #PB_Coordinate_Device, #PB_Coordinate_User)
      EndIf
     
      If Mouse\Pan Or Mouse\Wheel
         ;Debug "draw"
         Mouse\Wheel ! 1
         VectorSourceColor(RGBA(80, 80, 80, 255)) : FillVectorOutput()
         
         AddPathBox(0, 0, x_WscreenSize, y_WscreenSize)
         VectorSourceColor(RGBA(255,0,0,255))
         StrokePath(0.2)
         
         VectorSourceColor(RGBA(255,255,0,255))
         AddPathCircle(0, 0, 1)
         StrokePath(0.5)
         
         MovePathCursor(-4, 5)
         SaveVectorState()
            FlipCoordinatesY(y_WscreenSize / 2, #PB_Coordinate_User)
            AddPathText("Origin")
         RestoreVectorState()
         FillPath()
         
         MovePathCursor(15, 45)
         SaveVectorState()
            FlipCoordinatesY(y_WscreenSize / 2, #PB_Coordinate_User)
            DrawVectorImage(ImageID(0), 255)
         RestoreVectorState()
      EndIf
     
      StopVectorDrawing()
   EndIf
   StatusBarText(0, 0, "World Coord.: " + StrF(Mouse\x_CoordW, 2) + ", " + StrF(Mouse\y_CoordW, 2))
   StatusBarText(0, 1, "Screen Coord.: " + Str(Mouse\x_Can) + ", " + Str(Mouse\y_Can))
EndProcedure

If OpenWindow(0,0,0,500,300,"Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   
   CanvasGadget(0,0,0,500,277, #PB_Canvas_Keyboard )
   CreateStatusBar(0,WindowID(0))
   
   AddStatusBarField(200)
   AddStatusBarField(200)
   
   LoadFont(0, "Calibri", 20, #PB_Font_Italic)
   LoadImage(0, #PB_Compiler_Home + "examples/Sources/Data/PureBasicLogo.bmp")
   
   BindGadgetEvent(0,    @Ev_MouseWheel(),    #PB_EventType_MouseWheel)
   BindGadgetEvent(0,    @Ev_MouseMove(),       #PB_EventType_MouseMove)
   BindGadgetEvent(0,    @Ev_MousePan(),       #PB_EventType_MiddleButtonDown)
   BindGadgetEvent(0,    @Ev_MousePan(),       #PB_EventType_MiddleButtonUp)
   BindEvent(#Ev_Repaint, @Ev_Repaint())
   
   If StartVectorDrawing(CanvasVectorOutput(0, #PB_Unit_Millimeter))
      ; Init
      x_WscreenSize = VectorOutputWidth()
      y_WscreenSize = VectorOutputHeight()
      StopVectorDrawing()
   EndIf
   
   Mouse\Move = 1 : Mouse\Wheel = 1
   PostEvent(#Ev_Repaint)
   
   Repeat
      Event = WaitWindowEvent()
   Until Event = #PB_Event_CloseWindow
   
EndIf

Re: Zoom an vector drawn image

Posted: Tue Mar 14, 2017 11:00 am
by Amundo
Thanks Torp, I actually came across your code and thought "I just need to work out how this code does it".....

:(

I was concentrating on this part of your code:

Code: Select all

      ElseIf Mouse\Wheel
         ;Debug "Wheel"
         Mouse\x_PrW = Mouse\x_Wld
         Mouse\y_PrW = Mouse\y_Wld
         Mouse\x_Wld = ConvertCoordinateX(Mouse\x_Can, Mouse\y_Can, #PB_Coordinate_Device, #PB_Coordinate_User)
         Mouse\y_Wld = ConvertCoordinateY(Mouse\x_Can, Mouse\y_Can, #PB_Coordinate_Device, #PB_Coordinate_User)
         x_PosOrigin = x_PosOrigin  +  Mouse\x_Wld - Mouse\x_PrW
         y_PosOrigin = y_PosOrigin  +    Mouse\y_Wld - Mouse\y_PrW
         TranslateCoordinates(x_PosOrigin, y_PosOrigin, #PB_Coordinate_User)
         Mouse\x_CoordW = ConvertCoordinateX(Mouse\x_Can, Mouse\y_Can, #PB_Coordinate_Device, #PB_Coordinate_User)
         Mouse\y_CoordW = ConvertCoordinateY(Mouse\x_Can, Mouse\y_Can, #PB_Coordinate_Device, #PB_Coordinate_User)
      EndIf
but couldn't work it out :oops:

I realise I need to adjust my X/Y pos (in the TranslateCoordinates statement) using some formula, but I just can't grasp it.

Re: Zoom an vector drawn image

Posted: Tue Mar 14, 2017 11:06 am
by #NULL
maybe rotate first and then translate is what you want? that way it will translate into the rotated direction.

Code: Select all

    RotateCoordinates(#MiddleX * Zoom, #MiddleY * Zoom, rotation)
    TranslateCoordinates(xPos, yPos)

Re: Zoom an vector drawn image

Posted: Tue Mar 14, 2017 11:09 am
by Amundo
Thanks #NULL, but still the same after moving TranslateCoordinates after RotateCoordinates

Re: Zoom an vector drawn image

Posted: Tue Mar 14, 2017 12:46 pm
by Torp
As the Zoom is sensitive to the position of the mouse, at each iteration of the wheel, I retain the previous coordinates,

Code: Select all

Mouse \ x_PrW = Mouse \ x_Wld
Mouse \ y_PrW = Mouse \ y_Wld
Then I store the new coordinates of the mouse on the canvas, which I convert into coordinates "of the world"

Code: Select all

Mouse \ x_Wld = ConvertCoordinateX (Mouse \ x_Can, Mouse \ y_Can, #PB_Coordinate_Device, #PB_Coordinate_User)
Mouse \ y_Wld = ConvertCoordinateY (Mouse \ x_Can, Mouse \ y_Can, #PB_Coordinate_Device, #PB_Coordinate_User)
and i make the difference and I recal the coordinates :

Code: Select all

X_PosOrigin = x_PosOrigin + Mouse \ x_Wld - Mouse \ x_PrW
Y_PosOrigin = y_PosOrigin + Mouse \ y_Wld - Mouse \ y_PrW
TranslateCoordinates (x_PosOrigin, y_PosOrigin, #PB_Coordinate_User)
Pay attention to the order in which you make your transformations. Look if by the transformation of scale in the first, this does not solve your problem.

Re: Zoom an vector drawn image

Posted: Tue Mar 14, 2017 12:57 pm
by Little John
@Amundo

I don't have time for looking at the details of your code.

However, on principle these are the steps for zooming:
  • Choose 1 point of your image that is not going to move (an "anchor point", so to say).
    If you have e.g. a circle, then the center probably would be the most convenient anchor point.
    Depending on which point you chose, the visual zooming effect will be different, of course.
  • Be sure that you can easily calculate or have saved all needed distances from the anchor point (e.g. in a structure, or an array).
    E.g. for a circle, the only distance you need is its radius (if its center is used as anchor point).
    For a more complex object, you'll need the distances of several points from the anchor point.
  • Get the current zoom factor from the mouse or from the keyboard.
  • Re-calculate every distance by multiplying it with (current zoom factor / previous zoom factor).
  • In case of a circle, now you have the new radius, which is all information you need.
    For a more complex object, re-calculate the coordinates of all needed points by applying their new distances from the anchor point.
My tip:
Write a small experimental program, that does nothing else but drawing and zooming a circle.
Then change the program, so that it draws and zooms say a pentagon.
After that, you'll probably have the needed experience that will allow you to include zooming into your original program. :-)

I hope this helps. Good luck!

Re: Zoom an vector drawn image

Posted: Tue Mar 14, 2017 3:29 pm
by Amundo
@Torp: yes, I debugged the hell out of your section of code, hoping for divine intervention - no such luck. Your code has the "benefit" of having a mouse coordinate to calculate from.

@Little John: thanks for taking a look and offering suggestions.

Thinking a bit more about it from you're guys' ideas, and assuming the zoom is linearly applied (to pixels, in my case), I just need to use the inverse of the zoom factor added to the width and height of my overall object. Back to the drawing board...

Re: Zoom an vector drawn image

Posted: Fri Mar 31, 2017 5:50 am
by Amundo
Well, after so many trial-and-error attempts, I now have no hair and my eyebrows are white, I think I've finally found a procedure that produces the result I'm after.

Rather than post a whole lot of code, I'll just summarise:

1. Use ScaleCoordinates() to set correct zoom factor

Code: Select all

ScaleCoordinates(Zoom, Zoom)
2. Use ConvertCoordinateX/Y to translate your anchor point from #PB_Coordinate_Device to #PB_Coordinate_User

Code: Select all

TopLeftX = ConvertCoordinateX(xPos + #TopLeft, yPos + #TopLeft, #PB_Coordinate_Device, #PB_Coordinate_User)
TopLeftY = ConvertCoordinateY(xPos + #TopLeft, yPos + #TopLeft, #PB_Coordinate_Device, #PB_Coordinate_User)
3. Calculate adjustment factor based on difference of translated anchor point and original anchor point, multiplied by 1.5 (thanks Torp - kinda)

Code: Select all

xAdjusted = (TopLeftX - #TopLeft) * 1.5
yAdjusted = (TopLeftY - #TopLeft) * 1.5
4. Use TranslateCoordinates() using above adjustment factor to shift up/down/left/right according to size increase/decrease

Code: Select all

TranslateCoordinates(xAdjusted, yAdjusted)
5. Use RotateCoordinates() to apply any rotations around the fixed middle point

Code: Select all

RotateCoordinates(#MiddleX, #MiddleY, rotation)
6. Plot your shape (in this example, just a simple square - thanks Little John)!

Code: Select all

MovePathCursor(#TopLeft, #TopLeft)
AddPathLine(#TopRight, #TopLeft)
AddPathLine(#BottomRight, #BottomRight)
AddPathLine(#TopLeft, #BottomRight)
ClosePath()
StrokePath(1)
Hope I can apply it to my more complex shape - I have no hair left to pull out, eyebrows will have to do!

Just goes to show - sheer, blind, dumb, pig-headed persistence will get you there.

Re: Zoom an vector drawn image

Posted: Fri Mar 31, 2017 9:17 am
by Little John
Hi,

for demonstrating the concept that I posted previously, here is some simple working code. Maybe it is of use for you. Use the mouse wheel for zooming.

//edit 2017-04-04:
There is an extended version of this code below in this thread.

Code: Select all

CompilerIf #PB_Compiler_Version < 550
   MessageRequester("Error", "PureBasic version 5.50 or newer required because the new bounding box functions are used.")   
   
CompilerElse
   EnableExplicit
   
   Structure PointD
      x.d
      y.d
   EndStructure
   
   Structure Polygon
      Array p.PointD(0)
      center.PointD
      color.i
      width.i
   EndStructure
   
   
   Procedure ZoomObject (*obj.Polygon, factor.d)
      Protected.i i, last = ArraySize(*obj\p())
      
      With *obj
         For i = 0 To last
            \p(i)\x + factor * (\p(i)\x - \center\x)
            \p(i)\y + factor * (\p(i)\y - \center\y)
         Next
      EndWith
   EndProcedure
   
   
   Procedure DrawObject (canvas.i, *obj.Polygon)
      Protected.i i, last = ArraySize(*obj\p())
      
      If StartVectorDrawing(CanvasVectorOutput(canvas))
         ; clear canvas
         VectorSourceColor(RGBA(255, 255, 255, 255))
         FillVectorOutput()
         
         ; draw object and get the center of its bounding box
         With *obj
            MovePathCursor(\p(0)\x, \p(0)\y)
            For i = 1 To last
               AddPathLine(\p(i)\x, \p(i)\y)
            Next
            ClosePath()
            
            \center\x = PathBoundsX() + PathBoundsWidth()/2.0
            \center\y = PathBoundsY() + PathBoundsHeight()/2.0
            
            VectorSourceColor(\color)
            StrokePath(\width)
         EndWith
         
         StopVectorDrawing()
      EndIf
   EndProcedure
   
   
   ; Gadgets
   Enumeration
      #Canvas
   EndEnumeration
   
   
   Define obj.Polygon, zoom.i, event.i
   
   If OpenWindow(0, 0, 0, 400, 400, "Zoom demo", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) = 0
      End
   EndIf
   
   CanvasGadget(#Canvas, 0, 0, 400, 400)
   
   ;-- Define a pentagon
   With obj
      Dim \p(4)
      \p(0)\x = 100.0 : \p(0)\y = 250.0
      \p(1)\x = 250.0 : \p(1)\y = 250.0
      \p(2)\x = 250.0 : \p(2)\y = 170.0
      \p(3)\x = 175.0 : \p(3)\y = 140.0
      \p(4)\x = 100.0 : \p(4)\y = 170.0
      \color = RGBA(255, 0, 0, 255)
      \width = 2
   EndWith
   
   DrawObject(#Canvas, @obj)
   
   Repeat
      event = WaitWindowEvent()
      
      If event = #PB_Event_Gadget
         Select EventGadget() 
            Case #Canvas
               Select EventType()
                  Case #PB_EventType_MouseWheel
                     zoom = GetGadgetAttribute(#Canvas, #PB_Canvas_WheelDelta) 
                     ZoomObject(@obj, 0.1*zoom)
                     DrawObject(#Canvas, @obj)
               EndSelect   
         EndSelect      
      EndIf   
   Until event = #PB_Event_CloseWindow
CompilerEndIf

Re: Zoom an vector drawn image

Posted: Fri Mar 31, 2017 10:10 am
by Lord
Shouldn't #PB_Canvas_Keyboard be set for CanvasGadget?
Without it doesn't work here. But remember, I'm a dummy. :D

Re: Zoom an vector drawn image

Posted: Fri Mar 31, 2017 11:59 am
by RASHAD
Very simple using Mouse Wheel

Code: Select all

Global oldsx.f,oldsy.f

Procedure Drawcg(scalex.f,scaley.f)   
  StartVectorDrawing(CanvasVectorOutput(0))
    VectorSourceColor(RGBA(255,255,255,255))
    FillVectorOutput()
    VectorFont(LoadFont(0, "Times New Roman", 60, #PB_Font_Bold))    
    ScaleCoordinates(scalex,scaley)
    MovePathCursor(100, 50)
    DrawVectorImage(ImageID(0), 200)
    MovePathCursor(300, 100)    
    AddPathCircle(300, 100, 75, 0, 235, #PB_Path_Connected)
    ClosePath()    
    VectorSourceColor(RGBA(0,255, 0, 255))
    StrokePath(10) 
    MovePathCursor(100, 100)
    VectorSourceColor(RGBA(255, 0, 0, 255))     
    DrawVectorText("Test")
  StopVectorDrawing()
  oldsx = scalex :oldsy = scaley
EndProcedure
  
  If OpenWindow(0, 0, 0, 800, 400, "VectorDrawing", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    CanvasGadget(0, 0, 0, 800, 400)
    LoadImage(0, #PB_Compiler_Home + "examples/Sources/Data/PureBasicLogo.bmp")    
    Drawcg(1,1)
    
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Quit = 1
          
        Case #PB_Event_Gadget
          Select EventGadget()
            Case 0
              Select EventType()
                Case #PB_EventType_MouseWheel 
                  Value.f = GetGadgetAttribute(0,#PB_Canvas_WheelDelta )/10
                  Drawcg(oldsx+value,oldsy+value)
              EndSelect
          EndSelect
      EndSelect          
    Until Quit = 1
  EndIf

Code: Select all

Enumeration
  #JustCanvas
EndEnumeration

UseJPEGImageDecoder()
UseJPEGImageEncoder()

CreateImage(0, 200, 200)
StartDrawing(ImageOutput(0))
  For x = 0 To 199
    For y = 0 To 199
      Plot(x,y, RGB(x,y,x*y))
    Next
  Next
StopDrawing()

Global Event.I, Type.I

If OpenWindow(0, 0, 0, 400, 400, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CanvasGadget(#JustCanvas, 10, 10, 380, 380, #PB_Canvas_ClipMouse | #PB_Canvas_Keyboard)
  StartDrawing(CanvasOutput(#JustCanvas))
    DrawImage(ImageID(0),90,90)
  StopDrawing()
   nwidth = 200
   nheight = 200
   nx = 90
   ny = 90
 SetActiveGadget(#JustCanvas)
  Repeat
    Event = WaitWindowEvent()
   
    If Event = #PB_Event_Gadget
     
      Select EventGadget()
       
      Case #JustCanvas
        Type = EventType()
        Select EventType()
        Case #PB_EventType_MouseWheel
           Pos = GetGadgetAttribute(#JustCanvas, #PB_Canvas_WheelDelta)
           If Pos = 1
               nwidth = nwidth + 4
               nheight = nheight + 4
               nx = nx - 2
               ny = ny -2
               CopyImage(0,1)
               ResizeImage(1,nwidth,nheight)
               StartDrawing(CanvasOutput(#JustCanvas))               
                 Box(0,0,380,380,#White)
                 DrawImage(ImageID(1),nx,ny)
               StopDrawing()
           ElseIf pos < 0
               If nwidth > 4 And nheight > 4
                 nwidth = nwidth - 4
                 nheight = nheight - 4
                 nx = nx + 2
                 ny = ny + 2               
                 CopyImage(0,1)
                 ResizeImage(1,nwidth,nheight)
                 StartDrawing(CanvasOutput(#JustCanvas))                 
                   Box(0,0,380,380,#White)
                   DrawImage(ImageID(1),nx,ny)
                 StopDrawing()
               EndIf
           EndIf
         
        Case #PB_EventType_LeftButtonDown
          Debug "LeftButtonDown"
         
        Case #PB_EventType_LeftButtonUp
          Debug "LeftButtonUp"                       
         
        EndSelect
      EndSelect
    EndIf
  Until Event = #PB_Event_CloseWindow
EndIf

Re: Zoom an vector drawn image

Posted: Fri Mar 31, 2017 1:59 pm
by Lord
Hi Rashad!

In your first example you used

Code: Select all

...
  CanvasGadget(0, 0, 0, 800, 400)
...
  Select EventType()
    Case #PB_EventType_MouseWheel
      Value.f = GetGadgetAttribute(0,#PB_Canvas_WheelDelta )/10
...
In your second example you used

Code: Select all

...
  CanvasGadget(#JustCanvas, 10, 10, 380, 380, #PB_Canvas_ClipMouse | #PB_Canvas_Keyboard)
...
 Select EventType()
   Case #PB_EventType_MouseWheel
     Pos = GetGadgetAttribute(#JustCanvas, #PB_Canvas_WheelDelta)
...
In first example zoom doesn't work, in the second it does.
I used PB5.50(x86) to test.
Has something changed from 5.50 to 5.60? I didn't find anything in respect to mousewheel.
In help file for PB5.50 is mentioned, that #PB_Canvas_Keyboard has to be used in order to get mousewheel working.
Am I wrong?

Re: Zoom an vector drawn image

Posted: Fri Mar 31, 2017 9:24 pm
by RASHAD
Hi Lord
The first snippet works as expected with PB 5.60 x86,5.44 x86 Win 10 x64 unless you mean something else

The second is a work around (Resizing 2D drawing)
I do not consider it right zooming

Re: Zoom an vector drawn image

Posted: Sat Apr 01, 2017 10:56 am
by Lord
Hi Rashad!
RASHAD wrote:...
The first snippet works as expected with PB 5.60 x86,5.44 x86 Win 10 x64 unless you mean something else
...
Here, on PB5.43LTS(x86) Win7(x64), the mouse wheel doesn't have any effect until I add #PB_Canvas_Keyboard as a flag to CanvasGadget().
It was already mentioned here: http://www.purebasic.fr/english/viewtop ... 8&p=499896