--- normalisiert die Eingabewinkel zuerst, damit wird z.b. -2*360 zu 0 wird
--- prüft jetzt auch den Überlauf in die andere Richtung, also wenn diff < -180
- der Hauptcode prüft jetzt für den stop nach Änderung des Winkels, ob diff sich umgekehrt hat; olddegree wird nach Änderung sicherheitshalber nochmal normalisiert.-
Einmal komplett (die Absätze sind wie gehabt, aber die eckigen Ecken sind jetzt rund):
Code: Alles auswählen
Structure coordinates
  x.i
  y.i
EndStructure
Global NewList coordinates.coordinates()
Procedure makeCoordinatesList(posxystring$)
  number = CountString(posxystring$,",")
  For loop = 1 To number Step 2 ; Step 2, weil hier die Lücken zwischen den Abschnitten aus dem Original fehlen
   AddElement(coordinates())
   With coordinates()
    \x = Val(StringField(posxystring$,loop,","))
    \y = Val(StringField(posxystring$,loop + 1,","))
   EndWith
  Next
EndProcedure
Procedure.f ATan3(y.i,x.i)
  If y > 0 And x < 0 ; links oben
   ProcedureReturn ATan(y/x) * 180/#PI +180
  ElseIf y < 0 And x < 0 ; links unten
   ProcedureReturn  ATan(y/x) *180/#PI + 180
  ElseIf y < 0 And x > 0 ; rechts unten
   ProcedureReturn ATan(y/x) *180/#PI + 360
  ElseIf y > 0 And x > 0; rechts oben
   ProcedureReturn ATan(y/x) *180/#PI
  ElseIf y < 0 And x = 0 ; links  (x u. y vertauscht wg. Koordinatensystem! Real also x < 0, y = 0)
   ProcedureReturn 270
  ElseIf y > 0 And x = 0 ; rechts (         ""       )
   ProcedureReturn 90
  ElseIf y = 0 And x < 0 ; unten  (         ""       )
   ProcedureReturn 180
  ElseIf y = 0 And x > 0 ; oben   (         ""       )
   ProcedureReturn 360 
  EndIf
EndProcedure
Procedure.s plotlineLow(x1,y1,x2,y2,image,colour)
  colour = RGB(0,0,255)
  dx = x2 - x1
  dy = y2 - y1
  yi = 1
  If dy < 0
   yi = -1
   dy = -dy
  EndIf
  D = 2*dy - dx
  y = y1
  StartDrawing(ImageOutput(image))
  For x = x1 To x2
     Plot(x,y,colour)
      If D > 0
      y = y + yi
      D = D - 2*dx
     EndIf
     D = D + 2*dy
    Next
  StopDrawing()
EndProcedure
Procedure.s plotLineHigh(x1,y1,x2,y2,image,colour)
  colour = RGB(0,0,255)
  dx = x2 - x1
  dy = y2 - y1
  xi = 1
  If dx < 0
   xi = -1
   dx = -dx
  EndIf
  D = 2*dx - dy
  x = x1
  StartDrawing(ImageOutput(image))
  For y = y1 To y2
    Plot(x,y,colour)
   If D > 0
    x = x + xi
    D = D - 2*dy
   EndIf
   D = D + 2*dx
  Next
  StopDrawing()
EndProcedure
Procedure selectPlotHighLow(x1,y1,x2,y2,image,colour)
  If Abs(y2 - y1) < Abs(x2 - x1)
    If x1 > x2
     plotLineLow(x2, y2, x1, y1,image,colour)
    Else
     plotLineLow(x1,y1, x2,y2,image,colour)
    EndIf
  Else
    If y1 > y2
     plotLinehigh(x2, y2, x1, y1,image,colour)
    Else
      plotLinehigh(x1, y1, x2, y2,image,colour)
    EndIf
  EndIf
 EndProcedure
 
 
Procedure.f getDistance(startX,startY,endX,endY)
  xDistanceSquare = (endX - startX) * (endX - startX)
  yDistanceSquare =  (endY - startY) * (endY - startY) 
  distance.f = Sqr(xDistanceSquare + yDistanceSquare)
 ProcedureReturn distance
EndProcedure
Procedure.f normalizeAngle(a.f)
  ; normalisieren zu 0..360
  While a < 0
    a + 360
  Wend
  While a >= 360
    a - 360
  Wend
  ProcedureReturn a
EndProcedure
Procedure.f angleDiff(aFrom.f, aTo.f)
  Protected aDiff.f
  aDiff = normalizeAngle(aTo) - normalizeAngle(aFrom)
  
  ; bei mehr als einer halben drehung, die andere richtung nehmen
  If aDiff >= 180
    aDiff - 360
  EndIf
  If aDiff <= -180
    aDiff + 360
  EndIf
  ProcedureReturn aDiff
EndProcedure
; unittest
CompilerIf 0
  Define.f a1, a2
  a1 =   0.0 : a2 =  45.0 : Debug "" + a1 + " -> " + a2 + " = " + angleDiff(a1, a2) ;   45
  a1 =  90.0 : a2 =  80.0 : Debug "" + a1 + " -> " + a2 + " = " + angleDiff(a1, a2) ;  -10
  a1 = 170.0 : a2 = 190.0 : Debug "" + a1 + " -> " + a2 + " = " + angleDiff(a1, a2) ;   20
  a1 = 100.0 : a2 = 260.0 : Debug "" + a1 + " -> " + a2 + " = " + angleDiff(a1, a2) ;  160
  a1 =  90.0 : a2 = 270.0 : Debug "" + a1 + " -> " + a2 + " = " + angleDiff(a1, a2) ;  180
  a1 =  80.0 : a2 = 280.0 : Debug "" + a1 + " -> " + a2 + " = " + angleDiff(a1, a2) ; -160
  a1 =  10.0 : a2 = 350.0 : Debug "" + a1 + " -> " + a2 + " = " + angleDiff(a1, a2) ;  -20
  a1 =  10.0 : a2 = 360.0 : Debug "" + a1 + " -> " + a2 + " = " + angleDiff(a1, a2) ;  -10
  a1 =  10.0 : a2 =   0.0 : Debug "" + a1 + " -> " + a2 + " = " + angleDiff(a1, a2) ;  -10
  a1 = 360.0 : a2 = 350.0 : Debug "" + a1 + " -> " + a2 + " = " + angleDiff(a1, a2) ;  -10
  a1 =   0.0 : a2 = 350.0 : Debug "" + a1 + " -> " + a2 + " = " + angleDiff(a1, a2) ;  -10
  a1 = -45.0 : a2 =  0.0 : Debug "" + a1 + " -> " + a2 + " = " + angleDiff(a1, a2) ;   45
  a1 = -45.0 : a2 = -90.0 : Debug "" + a1 + " -> " + a2 + " = " + angleDiff(a1, a2);  -45
  
  ; -10 -> 10
  a1 = -4*360-10 : a2 = -2*360+10 : Debug "" + a1 + " -> " + a2 + " = " + angleDiff(a1, a2) ;  20
  
  ; 10 -> -10
  a1 =  4*360+10 : a2 =  2*360-10 : Debug "" + a1 + " -> " + a2 + " = " + angleDiff(a1, a2) ; -20
  End
CompilerEndIf
 
 Procedure makeLinesWithCurves(image,colour)
 
  length.f = 3; Länge der "Bauklötzchen", hier = 4 pixel
 
  ForEach coordinates() 
     
   If run = 0 ; erster Abschnitt noch ohne Kurven
     startx = coordinates()\x ; Anfang der Linienabschnitte
     starty = coordinates()\y 
   EndIf
     
   If NextElement(coordinates())
   
    endx = coordinates()\x ; Ende der Linienabschnitte
    endy = coordinates()\y
         
     If Not ListIndex(coordinates()) = ListSize(coordinates()) ; letztes Element ist bereits erreicht - nix mehr malen
      distance.f = getDistance(startX,startY,endX,endY) ; Entfernung zwischen zwei Punkten
      olddegree.f = degree.f ; Letzer Winkel eines Abschnittes
      olddegree1.f = degree.f
      degree.f = ATan3(endx-startx, endy-starty) ; Winkel zun nächsten Punkt(aktueller Winkel)
      Debug StrF(degree,2) ; Im Original ist das Koordinatensystem verdreht (Atan3), deshalb werden die Winkel scheinbar falsch angezeigt, ist aber berücksichtigt
      newdegree.f = degree.f ; aktueller Winkel
      newdegree1.f = degree.f
     
      abirration = 8     ; Winkeländerung in der Kurve pro Pixel 
     
;     Kurven legen .................................
     
      If curve  ; 1 Abschnitt keine Kurve
     
      stop = 0
      StartDrawing(ImageOutput(image))   
     
      ; Anfang Kurven legen, Farbe = Rot
      Repeat
       
        ;-------------------------------
        ; Hier wird bestimmt, ob der Winkel in der Kurve gegenüber dem Ankunftswinkel (olddegree) vergrößert oder verkleinert wird.
        ; Und das kriege ich nicht hin - siehe die Kringel beim Kurvenzeichnen!
        
        _diff.f = angleDiff(olddegree1, newdegree1)
        
        If _diff >= 0
          olddegree + abirration
          If angleDiff(olddegree, newdegree) <= 0
            stop = 1
          EndIf : ;Original
        Else
          olddegree - abirration
          If angleDiff(olddegree, newdegree) >= 0
            stop = 1
          EndIf
        EndIf
        olddegree = normalizeAngle(olddegree)
     
      ;----------------------------     
   
       sinus.f = Sin(Radian(olddegree.f))
       cosinus.f = Cos(Radian(olddegree.f))
       slX.f = (sinus.f * length.f); Berechnet Veränderung von x im Winkel auf der Strecke.
       slY.f = (cosinus.f * length.f) ; berechnet Veränderung von y im Winkel aif der Strecle
       degree.f = ATan3(endx-startx, endy-starty) ; Berechnet den aktuellen Winkel zum Zielpunkt nach Setzen eines Klötzchens
       Plot(startx,starty,RGB(255,0,0))
       startX = startX + slX ; Veränderung startx/starty = x/y-Koordinaten nach dem Setzen eines Klötchens
       startY = startY + slY
      Until stop ; Olddegree = ankunftswinkel ist jetzt wegen +/- abirration so ungefähr gleich dem Zielwinkel
      StopDrawing()
     EndIf
;    ;ende Kurven legen .................................
     
      degree.f = ATan3(endx-startx, endy-starty) ; Winkel vom Kurvenende zum nächsten Punkt/Gerade Linie
      distance.f = getDistance(startX,startY,endX,endY) ; NeuBerechnung der Entfernung
      sinus.f = Sin(Radian(degree))
      cosinus.f = Cos(Radian(degree))
      slX.f = (sinus * length.f); Berechnet Veränderung von x im Winkel auf der strecke
      slY.f = (cosinus * length.f) ; berechnet Veränderung von y im Winkel
   
      ;Gerade Linie
     
      StartDrawing(ImageOutput(image))
      While distance.f  > 0; Abbruch wenn, wenn Entfrnung negativ, Zilpunkt ist mehr oder weniger erreicht
       
       Plot(startX,startY,RGB(234,255,0))
       
       startX = startX + slX ; veränderung startx in der Schleife/Nächste Platte;
       startY = startY + slY
       distance.f = distance.f - length.f
      Wend
      StopDrawing()
      curve + 1 ; erster Abschnitt ist eine Gerade, ab jetzt Kurven
     EndIf
   EndIf
  Next    ;Foreach roads()1
 
EndProcedure
 
Procedure makeLines(image,colour)
 
  ForEach coordinates()
   With coordinates()
    startx = \x
    starty = \y
   EndWith
   If endx  ; Daher keine Linie zum ersten Punkt
    selectPlotHighLow(startx,starty,endx,endy,image,colour) ; Erstmal gerade Linie zum nächsten Punkt
  EndIf
  endx = startx
  endy = starty
 Next
 EndProcedure
Global imagewidth = 1400
Global imagehight = 900
window = OpenWindow(#PB_Any,300,50,imagewidth,imagehight,"Bauklötzchen",#PB_Window_MinimizeGadget| #PB_Window_MaximizeGadget|#PB_Window_SizeGadget)
image = CreateImage(#PB_Any,imagewidth,imagehight,24,RGB(110,110,110))
imgad = ImageGadget(#PB_Any,0,0,imagewidth,imageheight,ImageID(image))
;x/y-Koordinaten
posXYstring$ = "228,605,193,496,193,495,225,432,226,430,271,388,272,388,336,409,337,410,371,457,372,458,337,512,335,514,334,549,334,549,384,587,384," +
              "587,433,633,435,635,439,672,439,672,508,640,510,638,482,573,481,571,448,525,447,523,507,481,508,480,506,430,506,430,521,384,522,383," +
              "677,376,680,376,715,437,715,437,661,497,659,498,596,491,594,490,574,544,574,546,649,599,649,599,708,616,710,616,727,660,727,663,683," +
              "693,680,694,770,739,770,739,856,696,856,696,803,618,802,616,798,539,798,538,856,508,856,508,793,451,792,450,819,397,819,397,894,384," +
              "897,384,977,334,978,333,958,148,958,147,794,87,793,87,635,120,632,121,600,170,600,170,644,253,645,255,753,275,754,275,833,251,836,250,764,189,"
makeCoordinatesList(posXYstring$)
makeLines(image,3) ; 3 = blau
ResizeGadget(imgad, 0,0,#PB_Ignore,#PB_Ignore)
Repeat
 
event = WaitWindowEvent() 
If message = 0
 message = MessageRequester("Test", "Linien mit Kurven auf 'OK' klicken",#PB_MessageRequester_Ok)
 makeLinesWithCurves(image,2) ;2 = Grün
 ResizeGadget(imgad, 0,0,#PB_Ignore,#PB_Ignore)
EndIf
   
If event = #PB_Event_CloseWindow
  close = 1
EndIf
Until  close