Funktion für Wertetabellen

Begonnen von Richardt, 25. August 2011, 16:09:08

Vorheriges Thema - Nächstes Thema

0 Mitglieder und 2 Gäste betrachten dieses Thema.

Richardt

Hallo,

ich habe eine Funktion programmiert um 2D und 3D Wertetabellen mit Achsenskalen zu nutzen. Vielleicht kann dies ja noch jemand gebrauchen. Habe die Funktion aber noch nicht ausführlich getestet. Vorsicht es wird mit Pointer hantiert!  ;)

Anregung und Kommentare sind erwünscht.


Zitat
FUNCTION LINEAR_INT_ARRAY :REAL
VAR_INPUT
   PT : POINTER TO ARRAY[0..32000] OF REAL;
   SIZE : UINT;
   X : REAL := 0;
   Y : REAL := 0;
   Z : REAL := 0;
   NX : UINT := 0;
   NY : UINT := 0;
   NZ : UINT := 0;
END_VAR
VAR
   ix : UINT := 1;
   iy : UINT := 1;
   iz : UINT := 1;
   X_YH_ZH : REAL := 0.0;
   X_YL_ZH : REAL := 0.0;
   Y_ZH : REAL := 0.0;
   X_YH_ZL : REAL := 0.0;
   X_YL_ZL : REAL := 0.0;
   Y_ZL : REAL := 0.0;
END_VAR

(* #######################################################################################################

Funktion LINEAR_INT_ARRAY

Diese Funktion liefert den (interpolierten) Wert einer 2D (xy) oder 3D (xyz) Wertetabelle zurück.

Der Aufbau der Wertetabelle muss ARRAY[Z, Y, X] sein.

Über die Variablen NX, NY und NZ wird die Anzahl der Werte in der Tabelle pro jeweiliger Achseangegeben. Die
Speicherstelle der Achsenskalen werden nicht mit angegeben. Somit ist das tatsächliche Array um +1 in jede Richtung
größer. Bei einer 2D Wertetabelle ist NZ = 0 zu setzten.

Die Achsenskalen befinden sich:
X-Achse:      in der aufgespannten Fläche von ARRAY[z=0, y=0, x=1] bis ARRAY[z=NZ, y=0, x=NX]
Y-Achse:      in der aufgespannten Fläche von ARRAY[z=0, y=1, x=0] bis ARRAY[z=NZ, y=NY, x=0]
Z-Achse:      in der Achse von ARRAY[z=1, y=0, x=0] bis ARRAY[z=NZ, y=0, x=0]
ARRAY[z=0, y=0, x=0] ist leer und wird nicht benutzt!

Die Achsenskalen müssen aufsteigend sortiert sein. Werte außerhalb der Skala werden extrapoliert.

Die Funktion arbeitet mit Pointer. Daher ist sie sehr effizient und benötigt keinen extra Speicherplatz. Des weiteren kommt
sie mit unterschiedlich großen Arrays aus.

Der Aufruf muss lauten:
LINEAR_INT_ARRAY(adr("array"),sizeof("array"), X, Y, Z, NX, NY, NZ);

####################################################################################################### *)


(* ------------------------- Sicherheit ------------------------- *)
IF (NX + 1) * (NY + 1) * (NZ + 1) > (SIZE -SIZEOF(pt)) / SIZEOF(pt) THEN
   LINEAR_INT_ARRAY := 0;
ELSE

   IF NX < 1 THEN NX := 1; END_IF;
   IF NY < 1 THEN NY := 1; END_IF;
   IF NZ < 1 THEN NZ := 1; END_IF;

   
   (* ------------------------- Achse bestimmen ------------------------- *)
   (* Werte auf der Achse suchen *)
   
   (* N ist Anzahl der Werte in der Tabelle, aber Achsen (tasächliche Größe des Arrays) muss mit betrachtet werden *)
   NX := NX + 1;
   NY := NY + 1;
   
   (* z-Achse *)
   IF NZ > 1 THEN
      NZ := NZ + 1;
      WHILE ( ( Z >= PT^[STEP_ARRAY(0, 0, iz, NX , NY, NZ)] ) AND ( iz < NZ - 1 ) ) DO
         iz := iz + 1;
      END_WHILE
   END_IF

   (* y-Achse *)
   WHILE ( ( Y >= PT^[STEP_ARRAY(0, iy, iz, NX, NY, NZ)] ) AND ( iy < NY - 1) ) DO
      iy := iy + 1;
   END_WHILE
   
   (* x-Achse *)
   WHILE ( ( X >= PT^[STEP_ARRAY(ix, 0, iz, NX, NY, NZ)] ) AND ( ix < NX - 1) ) DO
      ix := ix + 1;
   END_WHILE
   

   (* ------------------------- Interpolation 2D ------------------------- *)
   
   (* Berechnung X an der oberen Stelle von Y und der oberen Stelle von Z *)
   X_YH_ZH := F_LIN2(
                  X := X,
                  X1 := PT^[STEP_ARRAY(ix - 1, 0, iz, NX, NY, NZ)],
                  Y1 := PT^[STEP_ARRAY(ix - 1, iy, iz, NX, NY, NZ)],
                  X2 := PT^[STEP_ARRAY(ix, 0, iz, NX, NY, NZ)],
                  Y2 := PT^[STEP_ARRAY(ix, iy, iz, NX, NY, NZ)],
                  );
   
   (* Berechnung X an der niederen Stelle von Y und der oberen Stelle von Z *)
   X_YL_ZH := F_LIN2(
                  X := X,
                  X1 := PT^[STEP_ARRAY(ix - 1, 0, iz, NX, NY, NZ)],
                  Y1 := PT^[STEP_ARRAY(ix - 1, iy - 1, iz, NX, NY, NZ)],
                  X2 := PT^[STEP_ARRAY(ix, 0, iz, NX, NY, NZ)],
                  Y2 := PT^[STEP_ARRAY(ix, iy - 1, iz, NX, NY, NZ)],
                  );

   (* Berechnung Y an der oberen Stelle von Z *)
   Y_ZH := F_LIN2(
                  X := Y,
                  X1 := PT^[STEP_ARRAY(0, iy - 1, iz, NX, NY, NZ)],
                  Y1 := X_YL_ZH,
                  X2 := PT^[STEP_ARRAY(0, iy, iz, NX, NY, NZ)],
                  Y2 := X_YH_ZH,
                  );

   IF NZ = 1 THEN
      LINEAR_INT_ARRAY := Y_ZH;
   ELSE
      (* ------------------------- Interpolation 3D ------------------------- *)
      (* Berechnung X an der oberen Stelle von Y und der niederen Stelle von Z *)
      X_YH_ZL := F_LIN2(
                     X := X,
                     X1 := PT^[STEP_ARRAY(ix - 1, 0, iz - 1, NX, NY, NZ)],
                     Y1 := PT^[STEP_ARRAY(ix - 1, iy, iz - 1, NX, NY, NZ)],
                     X2 := PT^[STEP_ARRAY(ix, 0, iz - 1, NX, NY, NZ)],
                     Y2 := PT^[STEP_ARRAY(ix, iy, iz - 1, NX, NY, NZ)],
                     );

      (* Berechnung X an der niederen Stelle von Y und der niederen Stelle von Z *)
      X_YL_ZL := F_LIN2(
                     X := X,
                     X1 := PT^[STEP_ARRAY(ix - 1, 0, iz - 1, NX, NY, NZ)],
                     Y1 := PT^[STEP_ARRAY(ix - 1, iy - 1, iz - 1, NX, NY, NZ)],
                     X2 := PT^[STEP_ARRAY(ix, 0, iz - 1, NX, NY, NZ)],
                     Y2 := PT^[STEP_ARRAY(ix, iy - 1, iz - 1, NX, NY, NZ)],
                     );
   
      (* Berechnung Y an der niederen Stelle von Z *)
      Y_ZL := F_LIN2(
                     X := Y,
                     X1 := PT^[STEP_ARRAY(0, iy - 1, iz - 1, NX, NY, NZ)],
                     Y1 := X_YL_ZH,
                     X2 := PT^[STEP_ARRAY(0, iy, iz - 1, NX, NY, NZ)],
                     Y2 := X_YH_ZH,
                     );
   
      (* Endgültige Berechnung *)
      LINEAR_INT_ARRAY := F_LIN2(
                           X := Z,
                           X1 := PT^[STEP_ARRAY(0, 0, iz - 1, NX, NY, NZ)],
                           Y1 := Y_ZL,
                           X2 := PT^[STEP_ARRAY(0, 0, iz, NX, NY, NZ)],
                           Y2 := Y_ZH,
                           );
   
   END_IF

END_IF

Zitat
FUNCTION STEP_ARRAY :UINT
VAR_INPUT
   X : UINT := 0;
   Y : UINT := 0;
   Z : UINT := 0;
   NX : UINT := 0;
   NY : UINT := 0;
   NZ : UINT := 0;
END_VAR
VAR
END_VAR


(* #######################################################################################################

Funktion STEP_ARRAY

Diese Funktion ist ein WRAPPER für den einfachen Zugriff auf die Werrte eines 1D, 2D oder 3D Arrays über Pointer. Über die
Variablen X, Y und Z wird das gewünschte Feld angegeben. STEP_ARRAY liefert die Anzahl der nötigen Erhöhungen des
Pointers von der Basisadresse zurück.

Über die Variablen NX, NY und NZ ist die Anzahl der Werte in dem Array pro jeweiliger Achse anzugeben. Bei 2D muss
NZ = 0, bei 1D muss NZ = 0 und NY = 0.

Der Aufbau des Arrays mus ARRAY[Z, Y, X] sein.

####################################################################################################### *)


IF ( (X > NX) OR (Y > NY) OR (Z > NZ) ) THEN
   STEP_ARRAY := 0;
ELSE
   STEP_ARRAY := X + Y * NX + Z * NY * NZ;
END_IF