Seite 1 von 2

DrawVector RotateCoordinates, Box drehen + Ecken berechnen

Verfasst: 10.10.2019 21:01
von hjbremer
Ich brauchte 45 Grad gedrehten Text in den Ecken und dieses Beispiel zeigt dies plus 90 Grad

und wie man bei variablen Winkeln die Eckpunkte berechnet

Das Ganze soll nur ein Beispiel sein wie ich es gelöst habe und ein jeder mag sich davon inspirieren lassen !

Code: Alles auswählen

;DrawVector RotateCoordinates, Box + Text drehen für 45 und 90 Grad und für andere Winkel

;HJBremer Sep.2019
;Windows 10 PB 5.70 LTS x64

EnableExplicit

#lp = Chr($21c8)
#rp = Chr($21ca)

Global fontid = LoadFont(0, "Arial", 14)

Global vsc_Red = $FF0000ff
Global vsc_Blue = $FFff0000
Global vsc_Gray = $FF888888
Global vsc_Lila = $FFbb00ff
Global vsc_Black = $FF000000
Global vsc_Orange = $FF0099ff

Procedure draw90(x.d, y.d, txt$, txtcolor=$FF000000, side=0, boxcolor=0, flag=#PB_VectorParagraph_Center)
   
   ; wenn Colorwert ohne Alpha dann sieht man nix wie bei boxcolor
   
   ; side=0 = LEFT, side=1 = RIGHT, txtcolor=$FF000000 = black
   
   Protected.d b, h, angle
   
   b = 6 + VectorTextWidth(txt$)         ;incl. #LF$ im Text 
   
   h = 3 + VectorParagraphHeight(txt$, b, VectorOutputHeight())
   
   If side = 0    ;Left
      angle = -90: y + b
   Else
      angle = 90:  x + 0    ; oder x + h dann ist Drehpunkt Ecke unten links
   EndIf
   
   SaveVectorState()
   ResetCoordinates()
   RotateCoordinates(x, y, angle)
   
   VectorSourceColor(boxcolor)
   AddPathBox(x, y, b, h)
   StrokePath(1)
   
   VectorSourceColor(txtcolor)
   MovePathCursor(x, y)   
   DrawVectorParagraph(txt$, b, h, flag)
   
   RestoreVectorState()
   
   ProcedureReturn b + 1  ; +1 ist der Wert von StrokePath() der Box
   
EndProcedure

Procedure draw45(x,y,br,hh,text$,color,angle,flag=0)
   
   ;nur für 45 + 135 in den Ecken + 90 Grad
   
   color = $FF000000 | color  ;falls Alpha fehlt
   
   VectorFont(fontid)
   
   Protected x1=x, y1=y, pfeil$   
   
   Select angle
      Case   0:  
         
      Case  90: x1 = x + 0 : pfeil$ = #rp
      Case -90: y1 = y + br : pfeil$ = #lp
         
      Case  45: x1 = x - Sqr(br * br / 2) : pfeil$ = #rp  ;Satz des Pythagoras         
      Case -45: y1 = y + Sqr(br * br / 2) : pfeil$ = #lp 
         
      Case  135: y1 = y - Sqr(br * br / 2) : pfeil$ = #rp
      Case -135: x1 = x + Sqr(br * br / 2) : pfeil$ = #lp
         
      Default: ProcedureReturn
   EndSelect   
   
   ResetCoordinates()
   RotateCoordinates(x1, y1, angle)
   
   VectorSourceColor(vsc_Black)   ;Box für Text 
   AddPathBox(x1, y1, br, hh)
   StrokePath(3)
   
   VectorSourceColor(color)
   MovePathCursor(x1, y1)   
   DrawVectorParagraph(text$+" "+pfeil$, br, hh, flag)
   ;DrawVectorText(text$)   
   
   ResetCoordinates()
   
   VectorSourceColor(vsc_Blue)  ;markiert Parameter
   AddPathBox(x, y, 2, 2)
   StrokePath(4)
   
   VectorSourceColor(vsc_Orange)  ;markiert Startwerte intern
   AddPathBox(x1, y1, 2, 2)
   StrokePath(2)
   
   VectorFont(fontid,11)      ;Info
   MovePathCursor(x1+4, y1+4)
   DrawVectorText(Str(x1)+","+Str(y1))
   
EndProcedure

Procedure draw(x,y,br,hh,text$,color,angle,flag=0)
   
   color = $FF000000 | color  ;falls Alpha fehlt
   
   VectorFont(fontid)
   
   Protected pfeil$
   
   If angle > 0: pfeil$ = #rp: EndIf
   If angle < 0: pfeil$ = #lp: EndIf
   
   ResetCoordinates()
   RotateCoordinates(x, y, angle)
   
   VectorSourceColor(vsc_Gray)   ;Box für Text 
   AddPathBox(x, y, br, hh)
   StrokePath(3)
   
   VectorSourceColor(color)
   MovePathCursor(x, y)   
   DrawVectorParagraph(text$+" "+pfeil$, br, hh, flag)
   ;oder DrawVectorText(text$) 
   
   ; VectorSourceColor($FF000000+#Green) ;Test
   ; AddPathBox(x+9, y+9, 2, 2)
   ; DrawVectorText("x")
   ; StrokePath(2)
   
   ;markiert Startpunkt x+y Parameter 
   ResetCoordinates()
   VectorSourceColor(vsc_Blue)  
   AddPathBox(x, y, 2, 2)   
   StrokePath(4) 
   
   ;-- Berechnung von x+y für Linien
   
   Protected winkel = Abs(angle)          ; muß positiv sein !!!
   
   Protected radiant.f = Radian(winkel)   ; muß Float sein !!!   
   Protected sinus.f   = Sin(radiant)
   Protected cosinus.f = Cos(radiant)
   
   ; wenn Double dann einige Linien dicker. Warum ??? keine Ahnung.
   Protected.i x_TopR, y_TopR, x_BotR, y_BotR, x_BotL, y_BotL
   
   If angle = 0
      x_BotL = x
      y_BotL = y + hh
      x_TopR = x + br  
      y_TopR = y
      x_BotR = x + br
      y_BotR = y + hh
   EndIf
   
   If angle > 0    
      
      x_BotL = x - (hh * sinus)
      y_BotL = y + (hh * cosinus)
      
      x_TopR = x + (br * cosinus)
      y_TopR = y + (br * sinus)
      
      x_BotR = x_TopR - (hh * sinus)
      y_BotR = y_TopR + (hh * cosinus)      
      
   EndIf
   
   If angle < 0
      
      x_BotL = x + (hh * sinus)
      y_BotL = y + (hh * cosinus)
      
      x_TopR = x + (br * cosinus)
      y_TopR = y - (br * sinus)
      
      x_BotR = x_TopR + (hh * sinus)
      y_BotR = y_TopR + (hh * cosinus)
      
   EndIf
   
   ;--- BottomLeft linie   
   VectorSourceColor(vsc_Black)
   
   AddPathBox(x_BotL, y, 2, 2) : StrokePath(2) 
   AddPathBox(x_BotL, y_BotL, 2, 2) : StrokePath(2) 
   
   MovePathCursor(x_BotL+1, y)                         ;x+y Start Linie, +1 damit es besser aussieht     
   AddPathLine(x_BotL+1, y_BotL) : DashPath(1,2)       ;x+y Ende Linie   
   
   ;--- TopRight linie
   VectorSourceColor(vsc_Lila)
   
   AddPathBox(x_TopR, y, 2, 2) : StrokePath(2)        ;x+y Box für Start Linie    
   AddPathBox(x_TopR, y_TopR, 2, 2) : StrokePath(2)   ;x+y Box für Ende Linie
   
   MovePathCursor(x_TopR+1, y)                        ;x+y Start Linie      
   AddPathLine(x_TopR+1, y_TopR) : DashPath(1,2)      ;x+y Ende Linie
   
   ;--- BottomRight linie
   VectorSourceColor(vsc_Red)
   
   AddPathBox(x_BotR, y, 2, 2) : StrokePath(2)  
   AddPathBox(x_BotR, y_BotR, 2, 2) : StrokePath(2)
   
   MovePathCursor(x_BotR+1, y)
   AddPathLine(x_BotR+1, y_BotR) : DashPath(1,2)
   
   ;--- Infobox
   
   Protected i$, ix, iy, ibr = 64, ihh = 68, by
   
   VectorFont(fontid,10) 
   VectorSourceColor(vsc_Black)
   
   If y_TopR < y
      ix = x - 20: iy = y + hh + 4 + 5: by = iy
   Else
      ix = x - 20: iy = y - hh - 4 - ihh: by = iy+ihh
   EndIf
   
   AddPathBox(ix, iy, ibr, ihh) : StrokePath(1) ;Infobox
   
   MovePathCursor(x, y)
   AddPathLine(ix+ibr/2, by) : DashPath(1,2)    ;Line Start xy zur Infobox
   
   MovePathCursor(ix+4, iy+4) ;für Text in der Infobox
   
   i$ = "Angle " + Str(angle) + #LF$
   i$ + "XY: " + Str(x)+","+Str(y) + #LF$
   i$ + "TR: " + Str(x_TopR)+","+Str(y_TopR) + #LF$
   i$ + "BR: " + Str(x_BotR)+","+Str(y_BotR) + #LF$
   i$ + "BL: " + Str(x_BotL)+","+Str(y_BotL)   
   
   ;DrawVectorText(i$)
   DrawVectorParagraph(i$, ibr, ihh)   ;Schrift sieht bei mir besser aus als mit DrawVectorText
   
EndProcedure
;-

;{ Start
;- Start

Define winbr = 888
Define winhh = 700
Define event

OpenWindow(0, 200, 100, winbr, winhh, "DrawVector RotateCoordinates", #PB_Window_SystemMenu)
CanvasGadget(0, 0, 0, winbr, winhh)    

If StartVectorDrawing(CanvasVectorOutput(0))
   
   VectorFont(fontid)
   
   Define boxabstand = 150
   
   Define a = 0
   Define x = 150, y = 15, br = 180, hh=100
   
   Define t$ = #LF$ + " blau: Parameter" + #LF$ + " Pfeil: Rotation"
   
   draw45(x,y,br,hh,t$,#Gray,a)      
   
   ;-draw45 oben 90 
   
   x = 450: y = 15 : br = 100 : hh=30 
   a = -90
   draw45(x, y, br, hh, "A " + Str(a), #Magenta, a, #PB_VectorParagraph_Center)  
   
   x = 550
   a = 90
   draw45(x, y, br, hh, "B " + Str(a), #Red, a, #PB_VectorParagraph_Center) 
   
   
   ;-draw45 oben Ecke links + rechts
   
   Define br = 100, hh=28, abstand = 5
   
   x = WindowWidth(0) - abstand
   y = abstand
   a = 45
   draw45(x,y,br,hh,Str(a),#Gray,a,#PB_VectorParagraph_Center)
   
   x = abstand
   y = abstand
   a = -45
   draw45(x,y,br,hh,Str(a),#Gray, a,#PB_VectorParagraph_Center)   
   
   ;-draw45 unten Ecke links + rechts
   
   x = abstand
   y = WindowHeight(0) - abstand
   a = -135
   draw45(x,y,br,hh,Str(a),#Gray,a,#PB_VectorParagraph_Center)
   
   x = WindowWidth(0) - abstand
   y = WindowHeight(0) - abstand
   a = 135
   draw45(x,y,br,hh,Str(a),#Gray,a,#PB_VectorParagraph_Center)
   
   ;- draw90
   
   VectorFont(fontid,16)
   
   x = abstand
   y = 300   
   draw90(x, y, "Copyright by HJBremer")
   
   x = VectorOutputWidth() - abstand
   y = 270
   draw90(x, y, "Copyright by HJBremer" + #LF$ + "24534 Neumünster Germany", $FFff0000, 1, $FF00ff00)
   
   ;-
   ;- draw Angle plus
   
   y = 250
   
   MovePathCursor(0, y)
   VectorSourceColor(vsc_Gray) ;graue QuerLinie
   AddPathLine(winbr, y)   
   StrokePath(1)
   
   x = 30
   a = 45
   draw(x, y, br, hh, Str(a), #Gray, a, #PB_VectorParagraph_Center)       
   
   x + boxabstand
   a = 80
   draw(x, y, br, hh, Str(a), #Gray, a, #PB_VectorParagraph_Center)   
   
   x + boxabstand/2
   a = 90
   draw(x, y, br, hh, Str(a), #Gray, a, #PB_VectorParagraph_Center)   
   
   x + boxabstand
   a = 160
   draw(x, y, br, hh, Str(a), #Gray, a, #PB_VectorParagraph_Center)       
   
   x + boxabstand
   a = 195
   draw(x, y, br, hh, Str(a), #Gray, a, #PB_VectorParagraph_Center)       
   
   x + boxabstand
   a = 220
   draw(x, y, br, hh, Str(a), #Gray, a, #PB_VectorParagraph_Center)       
   
   x + boxabstand/2
   a = 270
   draw(x, y, br, hh, Str(a), #Gray, a, #PB_VectorParagraph_Center)       
   
   
   ;- draw Angle minus 
   
   y + 240
   
   VectorSourceColor(vsc_Gray)
   MovePathCursor(0, y)
   AddPathLine(winbr, y)   
   StrokePath(1) 
   
   x = 50
   a = -65
   draw(x, y, br, hh, Str(a), #Gray, a, #PB_VectorParagraph_Center)
   
   
   x + boxabstand
   a = -30
   draw(x, y, br, hh, Str(a), #Gray, a, #PB_VectorParagraph_Center)       
   
   x + boxabstand
   a = -80
   draw(x, y, br, hh, Str(a), #Gray, a, #PB_VectorParagraph_Center)       
   
   x + boxabstand
   a = -135
   draw(x, y, br, hh, Str(a), #Gray, a, #PB_VectorParagraph_Center)  
   
   x + boxabstand
   a = -230
   draw(x, y, br, hh, Str(a), #Gray, a, #PB_VectorParagraph_Center)  
   
   x + boxabstand/2
   a = 0
   draw(x, y, br, hh, Str(a), #Gray, a, #PB_VectorParagraph_Center)  
   
   
   StopVectorDrawing()   
   
   Repeat
      Event = WaitWindowEvent()
   Until Event = #PB_Event_CloseWindow
EndIf
;}

Re: DrawVector RotateCoordinates, Box drehen + Ecken berechn

Verfasst: 11.10.2019 09:02
von RSBasic
Cool, sieht gut aus. :allright:

Re: DrawVector RotateCoordinates, Box drehen + Ecken berechn

Verfasst: 21.10.2019 14:52
von dige
@hjbremer: Super Beispiel, vielen Dank! :allright:

Ich wollte mit der VerctorLib mal eine einfache Uhr zeichnen, analog dem folgenden Javascript Beispiel.
Hat jemand von den Grafik Cracks Zeit und Lust das nach PB zu übersetzen. Meine graue Mathezelle
lässt mich leider im Stich..

Code: Alles auswählen

<script type="text/javascript">
window.onload=function(){


var ctx = clock.getContext('2d'),
    pi2 = Math.PI * 2;

/// make 0 degree point up
ctx.translate(ctx.canvas.width * 0.5, ctx.canvas.height * 0.5);
ctx.rotate(-0.5 * Math.PI);
ctx.translate(-ctx.canvas.width * 0.5, -ctx.canvas.height * 0.5);

ctx.strokeStyle = '#000';
ctx.lineCap = 'round';

/// start
(function loop() {
    renderClock()
    requestAnimationFrame(loop);
})();

function renderClock() {

    var angles = timeToAngles(),
        cx = ctx.canvas.width * 0.5,
        cy = ctx.canvas.width * 0.5,
        lh = cx * 0.45,
        lm = cx * 0.8,
        ls = cx * 0.9,
        pos;
   
    /// face
    ctx.clearRect(0, 0, cx*2, cy*2);
    ctx.beginPath();
    ctx.arc(cx, cy, cx - ctx.lineWidth - 1, 0, pi2);
   
    /// hours
    pos = lineToAngle(cx, cy, lh, angles.h);
    ctx.moveTo(cx, cy);
    ctx.lineTo(pos.x, pos.y);

    /// minutes
    pos = lineToAngle(cx, cy, lm, angles.m);
    ctx.moveTo(cx, cy);
    ctx.lineTo(pos.x, pos.y);

    ctx.lineWidth = 5;
    ctx.stroke();
    ctx.beginPath();
   
    /// seconds
    pos = lineToAngle(cx, cy, ls, angles.s);
    ctx.moveTo(cx, cy);
    ctx.lineTo(pos.x, pos.y);

    ctx.lineWidth = 2;
    ctx.stroke();
}

/// (c) Ken Fyrstenberg Nilsen (CC3.0. Attribute)
function timeToAngles() {
   
    var os = 1 / 60,                  /// mini-step
        time = new Date(),            /// get current time
        h = time.getHours(),          /// get current hour
        m = time.getMinutes(),        /// get current minutes
        s = time.getSeconds(),        /// get current seconds
        ms = time.getMilliseconds(),  /// get current milliseconds
        sa, ma, ha;                   /// for calc. angles
   
    sa = pi2 * ((s / 60) + ((os) * ms * 0.001));         /// second's angle
    ma = pi2 * ((m / 60) + ((os) * s / 60));             /// minute's angle
    ha = pi2 * (((h % 12) / 12) + (( 1 / 12) * m / 60)); /// hour's angle
   
    return {
        h: ha,
        m: ma,
        s: sa
    }
}

function lineToAngle(x, y, length, angle) {
    return {
        x: x + length * Math.cos(angle),
        y: y + length * Math.sin(angle)
    }
}

}

</script>


<body>
  <canvas id="clock" width="366" height="366"></canvas>
</body>


Re: DrawVector RotateCoordinates, Box drehen + Ecken berechn

Verfasst: 21.10.2019 15:38
von #NULL
Die glatte Bewegung des Sekundenzeigers (und eventuell auch der anderen Zeiger) kann ich leider nicht umsetzen, da die Date Library keine Millisekunden zur Verfügung stellt. Das einzige was mir dazu einfällt, ist einmalig in sehr kurzen Intervallen auf einen Sekundenwechsel zu warten und sich dann ElapsedMilliseconds() zu speichern, sodass man sich später immer die angebrochene Dauer der aktuellen Sekunde herleiten kann.

Code: Alles auswählen

EnableExplicit
Define ww, wh, style, win, canvas, event, quit

ww=800
wh=600
style | #PB_Window_ScreenCentered
style | #PB_Window_SystemMenu
style | #PB_Window_MinimizeGadget
style | #PB_Window_SizeGadget

win = OpenWindow(#PB_Any, 50, 100, ww, wh, "", style)
canvas = CanvasGadget(#PB_Any, 0, 0, ww, wh)
AddKeyboardShortcut(win, #PB_Shortcut_Escape, 10)
AddWindowTimer(win, 1, 10)

Procedure redraw()
  Shared canvas
  Protected now, h, m, s
  Protected width, height, size, radius.f, radius2.f, angle.f
 
  now = Date()
  h = Hour(now)
  m = Minute(now)
  s = Second(now)
  
  If StartVectorDrawing(CanvasVectorOutput(canvas))
    width = VectorOutputWidth()
    height = VectorOutputHeight()
    size = width
    If height < size
      size = height
    EndIf
    radius = 0.9 * (size / 2.0)
   
    VectorSourceColor($ffeeeeee)
    FillVectorOutput()
    VectorSourceColor($ff888888)
   
    AddPathCircle(width/2, height/2, radius, 0, 360)
    StrokePath(6)
   
    angle = -Radian(90) + Radian(360 * h / 12)
    radius2 = radius * 0.45
    MovePathCursor(width/2, height/2)
    AddPathLine(radius2 * Cos(angle), radius2 * Sin(angle), #PB_Path_Relative)
    StrokePath(6, #PB_Path_RoundEnd)
   
    angle = -Radian(90) + Radian(360 * m / 60)
    radius2 = radius * 0.8
    MovePathCursor(width/2, height/2)
    AddPathLine(radius2 * Cos(angle), radius2 * Sin(angle), #PB_Path_Relative)
    StrokePath(4, #PB_Path_RoundEnd)
    
    angle = -Radian(90) + Radian(360 * s / 60)
    radius2 = radius * 0.9
    MovePathCursor(width/2, height/2)
    AddPathLine(radius2 * Cos(angle), radius2 * Sin(angle), #PB_Path_Relative)
    StrokePath(2, #PB_Path_RoundEnd)
   
    StopVectorDrawing()
  EndIf
EndProcedure

Procedure resize()
  Shared win, canvas
  ResizeGadget(canvas, 0, 0, WindowWidth(win), WindowHeight(win))
  redraw()
EndProcedure

BindEvent(#PB_Event_Timer, @ redraw(), win)
BindEvent(#PB_Event_SizeWindow, @ resize(), win)

Repeat
  event = WaitWindowEvent(10)
  Select event
    Case #PB_Event_CloseWindow
      quit = #True
    Case #PB_Event_Menu
      Select EventMenu()
        Case 10
          quit = #True
      EndSelect
  EndSelect
Until quit
<edit>
Code korrigiert

Re: DrawVector RotateCoordinates, Box drehen + Ecken berechn

Verfasst: 21.10.2019 20:58
von dige
Klasse! :D Sieht super aus :allright:

Mir fällt gerade auf, dass ich mit meiner Anfrage hjbremer's Beitrag gehijackt habe :oops: sorry.

@#NULL: Wenn du magst, kannst du deinen Beitrag gern nochmal als Tipps und Tricks posten und ich lösche dann meinen Beitrag..

Re: DrawVector RotateCoordinates, Box drehen + Ecken berechn

Verfasst: 22.10.2019 11:01
von HeX0R
#NULL hat geschrieben:Die glatte Bewegung des Sekundenzeigers (und eventuell auch der anderen Zeiger) kann ich leider nicht umsetzen, da die Date Library keine Millisekunden zur Verfügung stellt. Das einzige was mir dazu einfällt, ist einmalig in sehr kurzen Intervallen auf einen Sekundenwechsel zu warten und sich dann ElapsedMilliseconds() zu speichern, sodass man sich später immer die angebrochene Dauer der aktuellen Sekunde herleiten kann.
Jo, so mache ich das auch in meinem Terminal:

Code: Alles auswählen

Global TimeStampOffset

Procedure InitTimeStamp()                                                      ;Get ms offset of elapsedmilliseconds() to date()
	Protected k

	k  = Date()

	While k = Date()
		Delay(0)
	Wend

	TimeStampOffset = Val(Right(Str(ElapsedMilliseconds()), 3))

EndProcedure

Re: DrawVector RotateCoordinates, Box drehen + Ecken berechn

Verfasst: 23.10.2019 10:14
von dige
Weil der Code auch super mit SpiderBasic läuft, habe ich das gleich mal im SB Forum gepostet :wink:

https://forums.spiderbasic.com/viewtopi ... 6491#p6491

Re: DrawVector RotateCoordinates, Box drehen + Ecken berechn

Verfasst: 23.10.2019 10:36
von #NULL
Bei der Demo hinter dem Showcase Link stimmt irgendwas nicht, die Minutenstriche und der Minutenzeiger stimmen nicht ganz überein.

Re: DrawVector RotateCoordinates, Box drehen + Ecken berechn

Verfasst: 23.10.2019 10:56
von dige
Ja, dass stimmt, weil der Kreis einfach nur mit Dotted Stil gezeichnet wird. Die Minuten Striche selbst zu zeichnen, habe ich leider nicht hinbekommen..

Re: DrawVector RotateCoordinates, Box drehen + Ecken berechn

Verfasst: 23.10.2019 18:57
von mk-soft
Habe hier ein fertiges Gadget :wink:

Link 1: viewtopic.php?f=8&t=31050
Link 2: viewtopic.php?f=8&t=31050&p=348665#p348665