Nun soll das Modul selbst keine Kurven zeichnen oder sowas. Vielmehr ist das Modul dafür gedacht, aus einer skalaren Zahl zwischen 0 und 1 einen n-dimensionalen Vektor zu berechnen bzw. aus einem n-dimensionalen Vektor eine skalare Zahl, und das eineindeutig.
Dass heißt, jede Zahl zwischen 0 und 1 ist genau einem Punkt in der Ebene, im Raum oder im Hyperraum zugeordnet.
(Natürlich geht Genauigkeit verloren, wenn man aus einer Double, zwei oder mehr Doubles macht. Das sollte hoffentlich klar sein.)
Wofür sollte man sowas brauchen? Nun, ein klassisches Anwendungsbeispiel wäre die Umwandlung von einem Bild (zwei Dimensionen mit Helligkeitswert) in einen Ton (eine Dimension, die Frequenz, mit Lautstärke) oder andersherum. Ein schönes Video gibt es dazu von 3Blue1Brown
Code: Alles auswählen
Global Dimensions.i = 2
Global Dim Vector.d(Dimensions-1)
Global Scalar.d
Scalar = 0.3 ; Pick a scalar number between 0.0 and 1.0
Debug Scalar
SpaceFillingCurve::PeanoVector(@Vector(), Scalar, Dimensions)
Debug "{" + StrD(Vector(0), 5) + ", " + StrD(Vector(1), 5) + "}"
Debug SpaceFillingCurve::PeanoScalar(@Vector(), Dimensions)
0.29999999999999999
{0.75000, 0.25000}
0.3000000000000001
Code: Alles auswählen
DeclareModule SpaceFillingCurve
#MaxDepth = 20
Structure DoubleArray
d.d[0]
EndStructure
; Peano-curve
Declare.i PeanoVector(*Vector.DoubleArray, Scalar.d, Dimensions.i=2, Depth.i=#MaxDepth) ; Gives the n-dimensional vector from a scalar number using the Peano-curve.
Declare.d PeanoScalar(*Vector.DoubleArray, Dimensions.i=2, Depth.i=#MaxDepth) ; Gives the scalar number from an n-dimensional vector using the Peano-curve.
EndDeclareModule
Module SpaceFillingCurve
EnableExplicit
#DoubleEpsilon = 2.2204460492503130808e-16
Procedure.d PeanoScalar(*VectorIn.DoubleArray, Dimensions.i=2, Depth.i=#MaxDepth)
Protected MaxI.i = Dimensions-1
Protected Dim Vector.d(MaxI)
Protected Dim Direction.d(MaxI)
Protected I.i, J.i
Protected Scaling.d = 1.0
Protected Scalar.d = 0.5
For I = MaxI To 0 Step -1
Vector(I) = *VectorIn\d[I]
Direction(I) = 1.0
Next
While Depth > 0
For I = MaxI To 0 Step -1
Scaling / 3.0
If Scaling < #DoubleEpsilon : Break : EndIf
Vector(I) * 3
If Vector(I) < 1
Scalar - Scaling * Direction(I)
ElseIf Vector(I) < 2
Vector(I) - 1
For J = MaxI To 0 Step -1
If J <> I
Direction(J) = -Direction(J)
EndIf
Next
Else
Vector(I) - 2
Scalar + Scaling * Direction(I)
EndIf
Next
Depth - 1
Wend
ProcedureReturn Scalar
EndProcedure
Procedure.i PeanoVector(*VectorOut.DoubleArray, ScalarIn.d, Dimensions.i=2, Depth.i=#MaxDepth)
Protected MaxI.i = Dimensions-1
Protected Dim Direction.d(MaxI)
Protected I.i, J.i
Protected Scaling.d = 1.0
For I = MaxI To 0 Step -1
*VectorOut\d[I] = 0.5
Direction(I) = 1.0
Next
While Depth > 0
Scaling / 3.0
If Scaling < #DoubleEpsilon : Break : EndIf
For I = MaxI To 0 Step -1
ScalarIn * 3
If ScalarIn < 1.0
*VectorOut\d[I] - Scaling * Direction(I)
ElseIf ScalarIn < 2.0
ScalarIn - 1.0
For J = MaxI To 0 Step -1
If J <> I
Direction(J) = -Direction(J)
EndIf
Next
Else
*VectorOut\d[I] + Scaling * Direction(I)
ScalarIn - 2.0
EndIf
Next
Wend
ProcedureReturn *VectorOut
EndProcedure
EndModule