Vector drawing, manual drawing curve segment selection

Share your advanced PureBasic knowledge/code with the community.
MiLoo
User
User
Posts: 47
Joined: Fri Jan 28, 2011 12:26 pm

Vector drawing, manual drawing curve segment selection

Post by MiLoo »

Code: Select all

;***********************************
;迷路仟整理 2019.02.21
;矢量绘图_手动绘制曲线段选区
;***********************************

;MovePathCursor是起点,AddPathCurveX3/Y3是终点, AddPathCurveX1/Y1,AddPathCurveX2/Y2是调节点

;-[Enumeration]
Enumeration
   #winScreen
   #cvsScreen
   #tmrScreen
   #fntScreen
EndEnumeration

;-[Structure]
Structure __PointInfo
   X.f
   Y.f
   *pSymmetry.__PointInfo
   *pOriginal.__PointInfo
EndStructure

Structure __BezierInfo
   CurrTrace.__PointInfo      ;描点:终点
   CurrLocus.__PointInfo      ;控点
   NextLocus.__PointInfo      ;控点   
EndStructure

Structure __GraphicsInfo
   *pPoint.__PointInfo
   *pPrevBezier.__GraphicsInfo
   List *pListPoint.__PointInfo()
   List ListBezier.__BezierInfo()
   DynamicIndex.l
   IsClosePath.b
   IsFinishPath.b
EndStructure


;-[Global]
Global _Graphics.__GraphicsInfo

;- **************************
;-[Redraw]
;完成曲线,建立选区
Procedure Redraw_Graphics_FinishPath()
   With _Graphics\ListBezier()
      ;绘制多段曲线组成的选区
      *pFirstBezier.__BezierInfo = FirstElement(_Graphics\ListBezier())
      *pBezier.__BezierInfo = *pFirstBezier
      While NextElement(_Graphics\ListBezier())
         MovePathCursor(*pBezier\CurrTrace\x, *pBezier\CurrTrace\y)
         AddPathCurve(*pBezier\NextLocus\x, *pBezier\NextLocus\y, \CurrLocus\x, \CurrLocus\y, \CurrTrace\x, \CurrTrace\y)
         *pBezier = _Graphics\ListBezier()
      Wend
      FirstElement(_Graphics\ListBezier())
      AddPathCurve(*pBezier\NextLocus\x, *pBezier\NextLocus\y, \CurrLocus\x, \CurrLocus\y, \CurrTrace\x, \CurrTrace\y)
      
      ;为选区边线间线并做动态处理
      Result$ = PathSegments()
      VectorSourceColor($FFFF8000)  
      StrokePath(1.5)
      AddPathSegments(Result$)
      VectorSourceColor($FF000000)
      DashPath(1.5, 10, #PB_Path_Default, _Graphics\DynamicIndex)
   EndWith
EndProcedure

;封闭曲线段
Procedure Redraw_Graphics_ClosePath()
   With _Graphics\ListBezier()
      ;绘制多段曲线组成的形状
      *pFirstBezier.__BezierInfo = FirstElement(_Graphics\ListBezier())
      *pBezier.__BezierInfo = *pFirstBezier
      While NextElement(_Graphics\ListBezier())
         MovePathCursor(*pBezier\CurrTrace\x, *pBezier\CurrTrace\y)
         AddPathCurve(*pBezier\NextLocus\x, *pBezier\NextLocus\y, \CurrLocus\x, \CurrLocus\y, \CurrTrace\x, \CurrTrace\y)
         *pBezier = _Graphics\ListBezier()
      Wend
      FirstElement(_Graphics\ListBezier())
      AddPathCurve(*pBezier\NextLocus\x, *pBezier\NextLocus\y, \CurrLocus\x, \CurrLocus\y, \CurrTrace\x, \CurrTrace\y)
      VectorSourceColor($A00000FF)
      StrokePath(1.5) 
      
      ;绘制辅助线
      ForEach _Graphics\ListBezier()
         MovePathCursor(\CurrTrace\x, \CurrTrace\y)
         AddPathLine(\CurrLocus\x, \CurrLocus\y) 
         MovePathCursor(\CurrTrace\x, \CurrTrace\y)
         AddPathLine(\NextLocus\x, \NextLocus\y)                
      Next
      VectorSourceColor($80000000)
      DashPath(1.5, 3) 

      ;绘制辅助点
      ForEach _Graphics\ListBezier()
         AddPathBox   (\CurrTrace\x-6, \CurrTrace\y-6, 12, 12)
         AddPathCircle(\NextLocus\x+0, \NextLocus\y+0, 05) 
         AddPathCircle(\CurrLocus\x+0, \CurrLocus\y+0, 05) 
      Next
      VectorSourceColor($FF808080)
      FillPath()  
   EndWith
   With *pBezier    
      ;绘制当前选中点   
      If _Graphics\pPoint
         *pBezier = _Graphics\pPoint\pOriginal
         AddPathBox   (\CurrTrace\x-6, \CurrTrace\y-6, 12, 12)
         AddPathCircle(\NextLocus\x+0, \NextLocus\y+0, 05) 
         AddPathCircle(\CurrLocus\x+0, \CurrLocus\y+0, 05) 
      EndIf 
      VectorSourceColor($FFFF8000)
      FillPath()          
   EndWith
EndProcedure

;添加曲线段
Procedure Redraw_Graphics_AddPath()

   With _Graphics\ListBezier()
      ;绘制多段曲线组成的形状
      *pFirstBezier.__BezierInfo = FirstElement(_Graphics\ListBezier())
      *pBezier.__BezierInfo = *pFirstBezier
      While NextElement(_Graphics\ListBezier())
         MovePathCursor(*pBezier\CurrTrace\x, *pBezier\CurrTrace\y)
         AddPathCurve(*pBezier\NextLocus\x, *pBezier\NextLocus\y, \CurrLocus\x, \CurrLocus\y, \CurrTrace\x, \CurrTrace\y)
         *pBezier = _Graphics\ListBezier()
      Wend
      VectorSourceColor($A00000FF)
      StrokePath(1.5) 
      
      ;绘制辅助线
      *pBezier = FirstElement(_Graphics\ListBezier())
      MovePathCursor(*pBezier\CurrTrace\x, *pBezier\CurrTrace\y)
      AddPathLine(*pBezier\NextLocus\x, *pBezier\NextLocus\y) 
      While NextElement(_Graphics\ListBezier())
         MovePathCursor(\CurrTrace\x, \CurrTrace\y)
         AddPathLine(\CurrLocus\x, \CurrLocus\y) 
         MovePathCursor(\CurrTrace\x, \CurrTrace\y)
         AddPathLine(\NextLocus\x, \NextLocus\y)                
      Wend
      VectorSourceColor($80000000)
      DashPath(1.5, 3) 

      ;绘制辅助点
      *pBezier = FirstElement(_Graphics\ListBezier())
      AddPathBox   (*pBezier\CurrTrace\x-6, *pBezier\CurrTrace\y-6, 12, 12)
      AddPathCircle(\NextLocus\x+0, \NextLocus\y+0, 05) 
      While NextElement(_Graphics\ListBezier())
         AddPathBox   (\CurrTrace\x-6, \CurrTrace\y-6, 12, 12)
         AddPathCircle(\NextLocus\x+0, \NextLocus\y+0, 05) 
         If _Graphics\ListBezier() <> *pFirstBezier
            AddPathCircle(\CurrLocus\x+0, \CurrLocus\y+0, 05) 
         EndIf 
         *pBezier = _Graphics\ListBezier()
      Wend
      VectorSourceColor($FF808080)
      FillPath()  
   EndWith  
    
   With *pBezier 
      ;绘制当前选中点       
      If _Graphics\pPoint
         *pBezier = _Graphics\pPoint\pOriginal
         AddPathBox   (\CurrTrace\x-6, \CurrTrace\y-6, 12, 12)
         AddPathCircle(\NextLocus\x+0, \NextLocus\y+0, 05) 
         If *pBezier <> *pFirstBezier
            AddPathCircle(\CurrLocus\x+0, \CurrLocus\y+0, 05) 
         EndIf 
      EndIf 
      VectorSourceColor($FFFF8000)
      FillPath()          
   EndWith

EndProcedure

;动态的绘制几何图形
Procedure Redraw_Graphics()
   *pBezier.__BezierInfo
   *pFirstBezier.__BezierInfo
   If StartVectorDrawing(CanvasVectorOutput(#cvsScreen))
      VectorSourceColor($FFFFFFFF)
      FillVectorOutput()
      VectorFont(FontID(#fntScreen), 20)
      VectorSourceColor($FFFF8000)
      MovePathCursor(010, 010)
      DrawVectorText("左键添点描点,右键单击封闭多段曲线! --- 左键双击建立选区,右键双击清空曲线段!")
      Count = ListSize(_Graphics\ListBezier())
      If Count
         If _Graphics\IsFinishPath = #True
            Redraw_Graphics_FinishPath()
         ElseIf _Graphics\IsClosePath = #True
            Redraw_Graphics_ClosePath()
         Else 
            Redraw_Graphics_AddPath()
         EndIf 
      EndIf 
      StopVectorDrawing()
    EndIf
EndProcedure

;- **************************
;-[EventGadget]
Procedure EventGadget_AddPoint(*pPoint.__PointInfo, X, Y, *pOriginal, *pSymmetry)
   *pPoint\X = X 
   *pPoint\Y = Y 
   *pPoint\pSymmetry = *pSymmetry
   *pPoint\pOriginal = *pOriginal
   AddElement(_Graphics\pListPoint())
   _Graphics\pListPoint() = *pPoint
EndProcedure

Procedure EventGadget_cvsScreen_RightClick()
   If _Graphics\IsClosePath = #False 
      *pLastBezier.__BezierInfo  = LastElement(_Graphics\ListBezier())
      *pFirstBezier.__BezierInfo = FirstElement(_Graphics\ListBezier())
      If *pFirstBezier = 0 : ProcedureReturn : EndIf 
      With *pFirstBezier
         X = \CurrTrace\x * 2 - \NextLocus\x
         Y = \CurrTrace\y * 2 - \NextLocus\y
         EventGadget_AddPoint(\CurrLocus, X, Y, \CurrTrace, \NextLocus)
         \NextLocus\pSymmetry = \CurrLocus    
         _Graphics\pPoint = \CurrLocus 
         _Graphics\pPrevBezier = *pFirstBezier
         Redraw_Graphics()
      EndWith
      _Graphics\IsClosePath = #True
      Redraw_Graphics()
   EndIf 
EndProcedure

Procedure EventGadget_cvsScreen_LeftButtonDown()

   If _Graphics\IsFinishPath = #True 
      ClearList(_Graphics\pListPoint()) 
      ClearList(_Graphics\ListBezier()) 
      _Graphics\pPoint = 0
      _Graphics\IsClosePath  = #False
      _Graphics\IsFinishPath = #False
   EndIf 
   X = GetGadgetAttribute(#cvsScreen, #PB_Canvas_MouseX)
   Y = GetGadgetAttribute(#cvsScreen, #PB_Canvas_MouseY)
   ;判断光标落点
   ForEach _Graphics\pListPoint()
      *pPoint.__PointInfo = _Graphics\pListPoint()
      If Sqr(Pow(*pPoint\X - X, 2) + Pow(*pPoint\Y - Y, 2)) < 10
         _Graphics\pPoint = *pPoint
         _Graphics\pPoint\x = X
         _Graphics\pPoint\y = Y
         Redraw_Graphics()
         ProcedureReturn
      EndIf
   Next
   If _Graphics\IsClosePath = #True
      ProcedureReturn 
   EndIf
   *pBezier.__BezierInfo = AddElement(_Graphics\ListBezier())
   With *pBezier
      ;如果是曲线起点
      If _Graphics\pPrevBezier = 0
         EventGadget_AddPoint(\NextLocus, X, Y, \CurrTrace, 0)
         EventGadget_AddPoint(\CurrTrace, X, Y, \CurrTrace, 0)
         _Graphics\pPoint = \NextLocus 
      ;如果是曲线续画
      Else 
         EventGadget_AddPoint(\CurrLocus, X, Y, \CurrTrace, \NextLocus)
         EventGadget_AddPoint(\NextLocus, X, Y, \CurrTrace, \CurrLocus)
         EventGadget_AddPoint(\CurrTrace, X, Y, \CurrTrace, 0)
         _Graphics\pPoint = \NextLocus 
      EndIf 
      _Graphics\pPrevBezier = *pBezier
      Redraw_Graphics()
   EndWith

EndProcedure

Procedure EventGadget_cvsScreen_LeftButtonUp()
   If _Graphics\IsFinishPath = #True : ProcedureReturn : EndIf 
   If _Graphics\pPoint
      _Graphics\pPoint\x = GetGadgetAttribute(#cvsScreen, #PB_Canvas_MouseX)
      _Graphics\pPoint\y = GetGadgetAttribute(#cvsScreen, #PB_Canvas_MouseY)
      _Graphics\pPoint = 0
      Redraw_Graphics()
   EndIf
EndProcedure

Procedure EventGadget_cvsScreen_MouseMove()
   If _Graphics\IsFinishPath = #True : ProcedureReturn : EndIf 
   IsButtonDown = GetGadgetAttribute(#cvsScreen, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton
   If IsButtonDown = 0 : ProcedureReturn : EndIf 
   If _Graphics\pPoint
      With _Graphics\pPoint
         x = GetGadgetAttribute(#cvsScreen, #PB_Canvas_MouseX)
         y = GetGadgetAttribute(#cvsScreen, #PB_Canvas_MouseY)
         If _Graphics\pPoint = \pOriginal
            dx = x - \x
            dy = y - \y
            *pBezier.__BezierInfo = \pOriginal
            If *pBezier\CurrLocus
               *pBezier\CurrLocus\x + dx
               *pBezier\CurrLocus\y + dy
            EndIf 
            *pBezier\NextLocus\x + dx
            *pBezier\NextLocus\y + dy
         ElseIf \pSymmetry
            \pSymmetry\x = \pOriginal\x * 2 - x
            \pSymmetry\y = \pOriginal\y * 2 - y
         EndIf 
         \x = x
         \y = y
      EndWith
      Redraw_Graphics()
   EndIf
EndProcedure

;画布事件
Procedure EventGadget_cvsScreen()

   Select EventType()
      Case #PB_EventType_LeftDoubleClick
         If _Graphics\IsClosePath = #True
            _Graphics\IsFinishPath = #True
            Redraw_Graphics()      
         EndIf 
      Case #PB_EventType_RightDoubleClick
         ClearList(_Graphics\pListPoint()) 
         ClearList(_Graphics\ListBezier()) 
         _Graphics\pPoint = 0
         _Graphics\IsClosePath  = #False
         _Graphics\IsFinishPath = #False
         Redraw_Graphics() 
      
      Case #PB_EventType_RightClick  
         EventGadget_cvsScreen_RightClick()
      Case #PB_EventType_LeftButtonDown
         EventGadget_cvsScreen_LeftButtonDown()
      Case #PB_EventType_LeftButtonUp
         EventGadget_cvsScreen_LeftButtonUp()
      Case #PB_EventType_MouseMove 
         EventGadget_cvsScreen_MouseMove()
   EndSelect 
   
EndProcedure

;- **************************
;-[Main]
LoadFont(#fntScreen, "", 12)
If OpenWindow(#winScreen, 0, 0, 800, 550, "矢量绘图_手动绘制曲线段选区", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
   CanvasGadget(#cvsScreen, 0, 0, 800, 550)
   AddWindowTimer(#winScreen, #tmrScreen, 100)
   Repeat
      WinEvent = WindowEvent()
      Select WinEvent 
         Case #PB_Event_CloseWindow : IsExitWindow = #True
         Case #PB_Event_Timer
            If EventTimer() = #tmrScreen : _Graphics\DynamicIndex+1 : Redraw_Graphics() : EndIf
         Case #PB_Event_Gadget
            Select EventGadget()
               Case #cvsScreen : EventGadget_cvsScreen()
            EndSelect
      EndSelect
   Until IsExitWindow = #True
EndIf
End


I came to the ancient oriental country - China
I will PureBasic called B++
User avatar
NicTheQuick
Addict
Addict
Posts: 1224
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: 矢量绘图_手动绘制曲线段选区

Post by NicTheQuick »

This is no coding question. This is spam.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: 矢量绘图_手动绘制曲线段选区

Post by mk-soft »

No Spam... China

Lost and finishing 2019.02.21
vector drawing _ manual drawing curve segment selection

Thanks... Its work 谢谢。 我的工作

Please english (or german)
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
blueb
Addict
Addict
Posts: 1041
Joined: Sat Apr 26, 2003 2:15 pm
Location: Cuernavaca, Mexico

Re: Vector drawing, manual drawing curve segment selection

Post by blueb »

Google translated for those of you who are curious... :)

Code: Select all

; =================================================================
;
; Author:     MiLoo   
; Date:       February 21, 2019
; Explain:    Vector drawing, manual drawing curve segment selection
;           
; Search tips:
;
; Saved as:   Drawing Curved Segments.pb      
; =================================================================

;***********************************
; lost road finishing 2019.02.21
; vector drawing _ manual drawing curve segment selection
;***********************************

; MovePathCursor (Is the starting point)
; AddPathCurveX3/Y3 (Is the end)
; AddPathCurveX1/Y1 and 
; AddPathCurveX2/Y2 (Are the adjustment points)

;-[Enumeration]
Enumeration
   #winScreen
   #cvsScreen
   #tmrScreen
   #fntScreen
EndEnumeration

;-[Structure]
Structure __PointInfo
   X.f
   Y.f
   *pSymmetry.__PointInfo
   *pOriginal.__PointInfo
EndStructure

Structure __BezierInfo
   CurrTrace.__PointInfo      ; point: end point
   CurrLocus.__PointInfo      ; Control point
   NextLocus.__PointInfo      ; Control point   
EndStructure

Structure __GraphicsInfo
   *pPoint.__PointInfo
   *pPrevBezier.__GraphicsInfo
   List *pListPoint.__PointInfo()
   List ListBezier.__BezierInfo()
   DynamicIndex.l
   IsClosePath.b
   IsFinishPath.b
EndStructure


;-[Global]
Global _Graphics.__GraphicsInfo

;- **************************
;-[Redraw]
;Complete the curve And establish a selection
Procedure Redraw_Graphics_FinishPath()
   With _Graphics\ListBezier()
      ; draw a selection of multi-segment curves
      *pFirstBezier.__BezierInfo = FirstElement(_Graphics\ListBezier())
      *pBezier.__BezierInfo = *pFirstBezier
      While NextElement(_Graphics\ListBezier())
         MovePathCursor(*pBezier\CurrTrace\x, *pBezier\CurrTrace\y)
         AddPathCurve(*pBezier\NextLocus\x, *pBezier\NextLocus\y, \CurrLocus\x, \CurrLocus\y, \CurrTrace\x, \CurrTrace\y)
         *pBezier = _Graphics\ListBezier()
      Wend
      FirstElement(_Graphics\ListBezier())
      AddPathCurve(*pBezier\NextLocus\x, *pBezier\NextLocus\y, \CurrLocus\x, \CurrLocus\y, \CurrTrace\x, \CurrTrace\y)
      
     ; for the inter-line line and dynamic processing
      Result$ = PathSegments()
      VectorSourceColor($FFFF8000)  
      StrokePath(1.5)
      AddPathSegments(Result$)
      VectorSourceColor($FF000000)
      DashPath(1.5, 10, #PB_Path_Default, _Graphics\DynamicIndex)
   EndWith
EndProcedure

; Closed curve segment
Procedure Redraw_Graphics_ClosePath()
   With _Graphics\ListBezier()
     ; draw a shape composed of multiple segments
      *pFirstBezier.__BezierInfo = FirstElement(_Graphics\ListBezier())
      *pBezier.__BezierInfo = *pFirstBezier
      While NextElement(_Graphics\ListBezier())
         MovePathCursor(*pBezier\CurrTrace\x, *pBezier\CurrTrace\y)
         AddPathCurve(*pBezier\NextLocus\x, *pBezier\NextLocus\y, \CurrLocus\x, \CurrLocus\y, \CurrTrace\x, \CurrTrace\y)
         *pBezier = _Graphics\ListBezier()
      Wend
      FirstElement(_Graphics\ListBezier())
      AddPathCurve(*pBezier\NextLocus\x, *pBezier\NextLocus\y, \CurrLocus\x, \CurrLocus\y, \CurrTrace\x, \CurrTrace\y)
      VectorSourceColor($A00000FF)
      StrokePath(1.5) 
      
     ; draw guides
      ForEach _Graphics\ListBezier()
         MovePathCursor(\CurrTrace\x, \CurrTrace\y)
         AddPathLine(\CurrLocus\x, \CurrLocus\y) 
         MovePathCursor(\CurrTrace\x, \CurrTrace\y)
         AddPathLine(\NextLocus\x, \NextLocus\y)                
      Next
      VectorSourceColor($80000000)
      DashPath(1.5, 3) 

      ; drawing auxiliary points
      ForEach _Graphics\ListBezier()
         AddPathBox   (\CurrTrace\x-6, \CurrTrace\y-6, 12, 12)
         AddPathCircle(\NextLocus\x+0, \NextLocus\y+0, 05) 
         AddPathCircle(\CurrLocus\x+0, \CurrLocus\y+0, 05) 
      Next
      VectorSourceColor($FF808080)
      FillPath()  
   EndWith
   With *pBezier    
      ; draw the currently selected point 
      If _Graphics\pPoint
         *pBezier = _Graphics\pPoint\pOriginal
         AddPathBox   (\CurrTrace\x-6, \CurrTrace\y-6, 12, 12)
         AddPathCircle(\NextLocus\x+0, \NextLocus\y+0, 05) 
         AddPathCircle(\CurrLocus\x+0, \CurrLocus\y+0, 05) 
      EndIf 
      VectorSourceColor($FFFF8000)
      FillPath()          
   EndWith
EndProcedure

; add curve segment
Procedure Redraw_Graphics_AddPath()

   With _Graphics\ListBezier()
    ; draw a shape composed of multiple segments
      *pFirstBezier.__BezierInfo = FirstElement(_Graphics\ListBezier())
      *pBezier.__BezierInfo = *pFirstBezier
      While NextElement(_Graphics\ListBezier())
         MovePathCursor(*pBezier\CurrTrace\x, *pBezier\CurrTrace\y)
         AddPathCurve(*pBezier\NextLocus\x, *pBezier\NextLocus\y, \CurrLocus\x, \CurrLocus\y, \CurrTrace\x, \CurrTrace\y)
         *pBezier = _Graphics\ListBezier()
      Wend
      VectorSourceColor($A00000FF)
      StrokePath(1.5) 
      
     ; draw guides
      *pBezier = FirstElement(_Graphics\ListBezier())
      MovePathCursor(*pBezier\CurrTrace\x, *pBezier\CurrTrace\y)
      AddPathLine(*pBezier\NextLocus\x, *pBezier\NextLocus\y) 
      While NextElement(_Graphics\ListBezier())
         MovePathCursor(\CurrTrace\x, \CurrTrace\y)
         AddPathLine(\CurrLocus\x, \CurrLocus\y) 
         MovePathCursor(\CurrTrace\x, \CurrTrace\y)
         AddPathLine(\NextLocus\x, \NextLocus\y)                
      Wend
      VectorSourceColor($80000000)
      DashPath(1.5, 3) 

     ; drawing auxiliary points
      *pBezier = FirstElement(_Graphics\ListBezier())
      AddPathBox   (*pBezier\CurrTrace\x-6, *pBezier\CurrTrace\y-6, 12, 12)
      AddPathCircle(\NextLocus\x+0, \NextLocus\y+0, 05) 
      While NextElement(_Graphics\ListBezier())
         AddPathBox   (\CurrTrace\x-6, \CurrTrace\y-6, 12, 12)
         AddPathCircle(\NextLocus\x+0, \NextLocus\y+0, 05) 
         If _Graphics\ListBezier() <> *pFirstBezier
            AddPathCircle(\CurrLocus\x+0, \CurrLocus\y+0, 05) 
         EndIf 
         *pBezier = _Graphics\ListBezier()
      Wend
      VectorSourceColor($FF808080)
      FillPath()  
   EndWith  
    
   With *pBezier 
    ; draw the currently selected point    
      If _Graphics\pPoint
         *pBezier = _Graphics\pPoint\pOriginal
         AddPathBox   (\CurrTrace\x-6, \CurrTrace\y-6, 12, 12)
         AddPathCircle(\NextLocus\x+0, \NextLocus\y+0, 05) 
         If *pBezier <> *pFirstBezier
            AddPathCircle(\CurrLocus\x+0, \CurrLocus\y+0, 05) 
         EndIf 
      EndIf 
      VectorSourceColor($FFFF8000)
      FillPath()          
   EndWith

EndProcedure

; dynamically draw geometry
Procedure Redraw_Graphics()
   *pBezier.__BezierInfo
   *pFirstBezier.__BezierInfo
   If StartVectorDrawing(CanvasVectorOutput(#cvsScreen))
      VectorSourceColor($FFFFFFFF)
      FillVectorOutput()
      VectorFont(FontID(#fntScreen), 20)
      VectorSourceColor($FFFF8000)
      MovePathCursor(010, 010)
      DrawVectorText("Left click to add a point, right click to close the multi-segment curve! --- Left-click to create a selection, right-click to clear the curve segment!")
      Count = ListSize(_Graphics\ListBezier())
      If Count
         If _Graphics\IsFinishPath = #True
            Redraw_Graphics_FinishPath()
         ElseIf _Graphics\IsClosePath = #True
            Redraw_Graphics_ClosePath()
         Else 
            Redraw_Graphics_AddPath()
         EndIf 
      EndIf 
      StopVectorDrawing()
    EndIf
EndProcedure

;- **************************
;-[EventGadget]
Procedure EventGadget_AddPoint(*pPoint.__PointInfo, X, Y, *pOriginal, *pSymmetry)
   *pPoint\X = X 
   *pPoint\Y = Y 
   *pPoint\pSymmetry = *pSymmetry
   *pPoint\pOriginal = *pOriginal
   AddElement(_Graphics\pListPoint())
   _Graphics\pListPoint() = *pPoint
EndProcedure

Procedure EventGadget_cvsScreen_RightClick()
   If _Graphics\IsClosePath = #False 
      *pLastBezier.__BezierInfo  = LastElement(_Graphics\ListBezier())
      *pFirstBezier.__BezierInfo = FirstElement(_Graphics\ListBezier())
      If *pFirstBezier = 0 : ProcedureReturn : EndIf 
      With *pFirstBezier
         X = \CurrTrace\x * 2 - \NextLocus\x
         Y = \CurrTrace\y * 2 - \NextLocus\y
         EventGadget_AddPoint(\CurrLocus, X, Y, \CurrTrace, \NextLocus)
         \NextLocus\pSymmetry = \CurrLocus    
         _Graphics\pPoint = \CurrLocus 
         _Graphics\pPrevBezier = *pFirstBezier
         Redraw_Graphics()
      EndWith
      _Graphics\IsClosePath = #True
      Redraw_Graphics()
   EndIf 
EndProcedure

Procedure EventGadget_cvsScreen_LeftButtonDown()

   If _Graphics\IsFinishPath = #True 
      ClearList(_Graphics\pListPoint()) 
      ClearList(_Graphics\ListBezier()) 
      _Graphics\pPoint = 0
      _Graphics\IsClosePath  = #False
      _Graphics\IsFinishPath = #False
   EndIf 
   X = GetGadgetAttribute(#cvsScreen, #PB_Canvas_MouseX)
   Y = GetGadgetAttribute(#cvsScreen, #PB_Canvas_MouseY)
  ; judge the cursor to drop
   ForEach _Graphics\pListPoint()
      *pPoint.__PointInfo = _Graphics\pListPoint()
      If Sqr(Pow(*pPoint\X - X, 2) + Pow(*pPoint\Y - Y, 2)) < 10
         _Graphics\pPoint = *pPoint
         _Graphics\pPoint\x = X
         _Graphics\pPoint\y = Y
         Redraw_Graphics()
         ProcedureReturn
      EndIf
   Next
   If _Graphics\IsClosePath = #True
      ProcedureReturn 
   EndIf
   *pBezier.__BezierInfo = AddElement(_Graphics\ListBezier())
   With *pBezier
      ; If it is the starting point of the curve
      If _Graphics\pPrevBezier = 0
         EventGadget_AddPoint(\NextLocus, X, Y, \CurrTrace, 0)
         EventGadget_AddPoint(\CurrTrace, X, Y, \CurrTrace, 0)
         _Graphics\pPoint = \NextLocus 
      ;If it is a sequel
      Else 
         EventGadget_AddPoint(\CurrLocus, X, Y, \CurrTrace, \NextLocus)
         EventGadget_AddPoint(\NextLocus, X, Y, \CurrTrace, \CurrLocus)
         EventGadget_AddPoint(\CurrTrace, X, Y, \CurrTrace, 0)
         _Graphics\pPoint = \NextLocus 
      EndIf 
      _Graphics\pPrevBezier = *pBezier
      Redraw_Graphics()
   EndWith

EndProcedure

Procedure EventGadget_cvsScreen_LeftButtonUp()
   If _Graphics\IsFinishPath = #True : ProcedureReturn : EndIf 
   If _Graphics\pPoint
      _Graphics\pPoint\x = GetGadgetAttribute(#cvsScreen, #PB_Canvas_MouseX)
      _Graphics\pPoint\y = GetGadgetAttribute(#cvsScreen, #PB_Canvas_MouseY)
      _Graphics\pPoint = 0
      Redraw_Graphics()
   EndIf
EndProcedure

Procedure EventGadget_cvsScreen_MouseMove()
   If _Graphics\IsFinishPath = #True : ProcedureReturn : EndIf 
   IsButtonDown = GetGadgetAttribute(#cvsScreen, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton
   If IsButtonDown = 0 : ProcedureReturn : EndIf 
   If _Graphics\pPoint
      With _Graphics\pPoint
         x = GetGadgetAttribute(#cvsScreen, #PB_Canvas_MouseX)
         y = GetGadgetAttribute(#cvsScreen, #PB_Canvas_MouseY)
         If _Graphics\pPoint = \pOriginal
            dx = x - \x
            dy = y - \y
            *pBezier.__BezierInfo = \pOriginal
            If *pBezier\CurrLocus
               *pBezier\CurrLocus\x + dx
               *pBezier\CurrLocus\y + dy
            EndIf 
            *pBezier\NextLocus\x + dx
            *pBezier\NextLocus\y + dy
         ElseIf \pSymmetry
            \pSymmetry\x = \pOriginal\x * 2 - x
            \pSymmetry\y = \pOriginal\y * 2 - y
         EndIf 
         \x = x
         \y = y
      EndWith
      Redraw_Graphics()
   EndIf
EndProcedure

;Canvas event
Procedure EventGadget_cvsScreen()

   Select EventType()
      Case #PB_EventType_LeftDoubleClick
         If _Graphics\IsClosePath = #True
            _Graphics\IsFinishPath = #True
            Redraw_Graphics()      
         EndIf 
      Case #PB_EventType_RightDoubleClick
         ClearList(_Graphics\pListPoint()) 
         ClearList(_Graphics\ListBezier()) 
         _Graphics\pPoint = 0
         _Graphics\IsClosePath  = #False
         _Graphics\IsFinishPath = #False
         Redraw_Graphics() 
      
      Case #PB_EventType_RightClick  
         EventGadget_cvsScreen_RightClick()
      Case #PB_EventType_LeftButtonDown
         EventGadget_cvsScreen_LeftButtonDown()
      Case #PB_EventType_LeftButtonUp
         EventGadget_cvsScreen_LeftButtonUp()
      Case #PB_EventType_MouseMove 
         EventGadget_cvsScreen_MouseMove()
   EndSelect 
   
EndProcedure

;- **************************
;-[Main]
LoadFont(#fntScreen, "", 12)
If OpenWindow(#winScreen, 0, 0, 800, 550, "Vector drawing... manual drawing curve segment selection", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
   CanvasGadget(#cvsScreen, 0, 0, 800, 550)
   AddWindowTimer(#winScreen, #tmrScreen, 100)
   Repeat
      WinEvent = WindowEvent()
      Select WinEvent 
         Case #PB_Event_CloseWindow : IsExitWindow = #True
         Case #PB_Event_Timer
            If EventTimer() = #tmrScreen : _Graphics\DynamicIndex+1 : Redraw_Graphics() : EndIf
         Case #PB_Event_Gadget
            Select EventGadget()
               Case #cvsScreen : EventGadget_cvsScreen()
            EndSelect
      EndSelect
   Until IsExitWindow = #True
EndIf
End

- It was too lonely at the top.

System : PB 6.10 Beta 9 (x64) and Win Pro 11 (x64)
Hardware: AMD Ryzen 9 5900X w/64 gigs Ram, AMD RX 6950 XT Graphics w/16gigs Mem
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Vector drawing, manual drawing curve segment selection

Post by Kwai chang caine »

Works fine thanks 8)
ImageThe happiness is a road...
Not a destination
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: Vector drawing, manual drawing curve segment selection

Post by davido »

@MiLoo,
Nice. Thank you for sharing.
Works on my MacBook Pro, too.

@blueb,
Thank you for taking the trouble to translate.
DE AA EB
Post Reply