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