0

私は現在これに取り組んでいます: 複数の .vtr ファイルを含む Paraview .vtm ファイルを生成します。各 .vtr ファイルには、次のような値と座標が含まれています。ここでは、次元 8 で作業していると仮定します。

<PointData Scalars="U">
  <DataArray type="Float32" Name="U" format="ascii">
    <!-- 8*8*8 values -->
  </DataArray>
</PointData>
<Coordinates>
  <DataArray type="Float32" Name="x" format="ascii">
    <!-- 8 x values -->
  </DataArray>
  <DataArray type="Float32" Name="y" format="ascii">
    <!-- 8 y values -->
  </DataArray>
  <DataArray type="Float32" Name="z" format="ascii">
    <!-- 8 z values -->
  </DataArray>
</Coordinates>

四次元配列を使用して値を格納します: float ****tab、 with tab[s][x][y][z]、 where :

  • s現在の分割ステップです。次の .vtr ファイルの作業を開始するたびに増加します。
  • x, y, zその価値。

これが問題の原因です。これらのポイントを配置する必要がある座標は何でもかまいません。定数 (0、0.1、0.2 などのように、ステップに続く) にすることも、そうでないこともできます。

座標を 3 つの配列に格納しますx[], y[], z[]。私の目標は、一連の値を小さな立方体に分割することです。値を 8 つのファイル (2^3 ファイル) に分割するとします。8 つの小さな立方体の正しい座標を取得する必要があります。そして、私はそれを行う方法を見つけることができません。

私のデータ構造の選択はひどいものだと確信しています。

編集 :

これが私の4つ星配列を生成する関数です:

float**** fill_array_random4d(int split, int size)
{
  float**** ret;
  ret = malloc(sizeof(float***) * split);
  for (int i = 0; i < split; i++)
  {
    ret[i] = malloc(sizeof (float**) * size);
    for (int j = 0; j < size; j++)
    {
      ret[i][j] = malloc(sizeof (float*) * size);
      for (int k = 0; k < size; k++)
      {
        ret[i][j][k] = malloc(sizeof (float) * size);
        for (int l = 0; l < size; l++)
          ret[i][j][k][l] = rand() % 100;
      }
    }
  }

  return ret;
}

かなり基本的な内容です。現在、ランダムな値を使用しています。x, y, z配列を作成して埋める方法は次のとおりです。

float *x, *y, *z;
  x = malloc(sizeof (float) * size);
  y = malloc(sizeof (float) * size);
  z = malloc(sizeof (float) * size);
  for (int i = 0; i < size * split; i++)
    x[i] = step * i;
  for (int i = 0; i < size * split; i++)
    y[i] = step * i;
  for (int i = 0; i < size * split; i++)
    z[i] = step * i;

これはまだ非常に基本的なものですが、最後に、vtk レガシー形式に従って、ファイル内の座標を出力する関数を次に示します。

void print_Coordinates(FILE *file, float *x, float *y, float *z, int size, int split)
{
  fprintf(file, "      <Coordinates>\n");
  for (int i = 0; i < 3; i++)
  {
    const char *text1 = "        <DataArray type=\"Float32\" Name=\"";
    const char *text2 = "\" format=\"ascii\">\n";
    fprintf(file, "%s%c%s", text1, 'x' + i, text2);
    for (int j = 0; j < size; j++)
    {
      if (i == 0)
        fprintf(file, "          %f\n", x[j]);
      else if (i == 1)
        fprintf(file, "          %f\n", y[j]);
      else
        fprintf(file, "          %f\n", z[j]);
    }
    fprintf(file, "        </DataArray>\n");
  }
  fprintf(file, "      </Coordinates>\n");
}

だから、ええ、それは私が望むことをまったくしません。結果のスクリーンショットは次のとおりです。

すべての立方体が重なり合っています。以前使用していたコードでは、いくつかの立方体 (ファイルごとに 1 つ) がありましたが、対角線上に配置されていました (これも良くありません)。

4

1 に答える 1

1

あなたが認めたように、データ構造にはいくつかの問題があります。

  • 最初の次元sは一致していないようです: データ構造には元のキューブと小さい方のキューブを含める必要がありますか? 小さい立方体には別の次元があるため、これは簡単ではありません。
  • 多くの個別のデータがあります: (ランダムな) データ、座標、および配列の次元です。立方体を表すには、これらすべてを追跡する必要があります。関連するデータをまとめておくための構造を作成することをお勧めします。
  • 3 次元配列をトリプル ポインターで表すというアプローチ自体に問題はありませんが、この設計により、多くの断片化された割り当てが発生します。一定次元の多次元配列は、おそらく 1 つの「フラットな」メモリ ブロックとしてより適切に表現されます。

2 つの構造を提案します。

typedef struct Cube Cube;
typedef struct Axis Axis;

struct Axis {
    int n;              /* number of values */
    float *data;        /* graduation values */
};

struct Cube {
    Axis *x, *y, *z;    /* Axes of the cube */
    float *data;        /* x-major data */
};

「軸」は、軸の 1 つに沿って値を格納します。キューブ自体は軸関連のコードを気にせず、それを 3 つのメンバー軸に委譲するだけです。「キューブ」はデータ オブジェクトです。(以下の実装では、データ表現は x-major です。つまり、x ループが最も外側で、z ループが最も内側です。ループを交換することで変更できます。)

データが取り込まれたキューブ オブジェクトがある場合は、より小さいディメンションのキューブを作成し、関連するデータ範囲を軸とキューブ データからコピーすることで、サブキューブを抽出できます。立方体全体をカバーしたい場合は、立方体をそのまま抽出して書き込むか、立方体の配列に格納して、たとえばCube *small[8]各方向に半分に分割することができます。(これは元のインデックスのようなものsですが、各キューブが独自のディメンションを持つ場合があります。)

(確かに単純な) テストを使用したこの動作の実装をmain以下に示します。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef struct Cube Cube;
typedef struct Axis Axis;

struct Axis {
    int n;              /* number of values */
    float *data;        /* graduation values */
};

struct Cube {
    Axis *x, *y, *z;    /* Axes of the cube */
    float *data;        /* x-major data */
};

/*
 *      Create a new axis with a constant step.
 */
Axis *axis_new(int n, float start, float step)
{
    Axis *axis = malloc(sizeof(*axis));
    float *p;

    axis->n = n;
    axis->data = malloc(n * sizeof(*axis->data));

    p = axis->data;
    while (n--) {
        *p = start;
        start += step;
        p++;
    }

    return axis;
}

/*
 *      Destroy and clean up axis
 */
void axis_delete(Axis *axis)
{
    if (axis) {
        free(axis->data);
        free(axis);
    }
}

/*
 *      Write axis in XML format to given file
 */
void axis_write(const Axis *axis, FILE *f, const char *name)
{
    float *p = axis->data;
    int n = axis->n;

    fprintf(f, "  <DataArray type=\"Float32\" "
        "Name=\"%s\" format=\"ascii\">\n", name);

    fprintf(f, "    ");
    while (n--) {
        fprintf(f, " %g", *p++);
    }
    fprintf(f, "\n");
    fprintf(f, "  </DataArray>\n");
}

/*
 *      Create a new axis that is a sub-axis of orig.
 */
Axis *axis_slice(const Axis *orig, int start, int len)
{
    Axis *axis = axis_new(len, 0, 0);
    memcpy(axis->data, orig->data + start, len * sizeof(*axis->data));

    return axis;
}



/*
 *      Create a cube of zero values for the given axes
 */
Cube *cube_new(Axis *x, Axis *y, Axis *z)
{
    Cube *cube = malloc(sizeof(*cube));
    int dim = x->n * y->n * z->n;

    cube->x = x;
    cube->y = y;
    cube->z = z;

    cube->data = malloc(dim * sizeof(*cube->data));

    return cube;
}

/*
 *      Destroy and clean up cube
 */
void cube_delete(Cube *cube)
{
    if (cube) {
        axis_delete(cube->x);
        axis_delete(cube->y);
        axis_delete(cube->z);

        free(cube->data);
        free(cube);
    }
}

float *cube_at(const Cube *cube, int x, int y, int z)
{
    int pos = (x * cube->y->n + y) * cube->z->n + z;
    return cube->data + pos;
}

/*
 *      Populate all x, y, z values according to the function func.
 */
void cube_populate(Cube *cube, float (*func)(float x, float y, float z))
{
    int i, j, k;
    float *p = cube->data;

    for (i = 0; i < cube->x->n; i++) {
        float x = cube->x->data[i];

        for (j = 0; j < cube->y->n; j++) {
            float y = cube->y->data[j];

            for (k = 0; k < cube->z->n; k++) {
                float z = cube->z->data[k];

                *p++ = func(x, y, z);
            }
        }
    }    
}

/*
 *      Write cube to given file.
 */
void cube_write(const Cube *cube, FILE *f)
{
    float *p = cube->data;
    int n = cube->x->n * cube->y->n * cube->z->n;

    fprintf(f, "<PointData Scalars=\"U\">\n");
    fprintf(f, "  <DataArray type=\"Float32\" Name=\"U\" format=\"ascii\">\n");

    while (n--) {
        fprintf(f, " %g", *p++);
    }
    fprintf(f, "\n");

    fprintf(f, "  </DataArray>\n");
    fprintf(f, "</PointData>\n");

    fprintf(f, "<Coordinates>\n");
    axis_write(cube->x, f, "x");
    axis_write(cube->y, f, "y");
    axis_write(cube->z, f, "z");
    fprintf(f, "</Coordinates>\n");
}

/*
 *      Create a new cube that is a sub-cube of orig.
 */
Cube *cube_slice(const Cube *orig,
    int x, int dx, int y, int dy, int z, int dz)
{
    Cube *cube;
    float *p;
    int i, j, k;

    if (x + dx > orig->x->n) return NULL;
    if (y + dy > orig->y->n) return NULL;
    if (z + dz > orig->z->n) return NULL;

    cube = cube_new(
        axis_slice(orig->x, x, dx),
        axis_slice(orig->y, y, dy),
        axis_slice(orig->z, z, dz));

    p = cube->data;

    for (i = 0; i < dx; i++) {
        for (j = 0; j < dy; j++) {
            for (k = 0; k < dz; k++) {
                *p++ = *cube_at(orig, x + i, y + j, z + k);
            }
        }
    }    

    return cube;
}

/*
 *      Example appliaction
 */
float dist2(float x, float y, float z)
{
    return x*x + y*y + z*z;
}

int main()
{
    Cube *cube = cube_new(
        axis_new(4, 0, 0.1),
        axis_new(4, 0, 0.1),
        axis_new(4, 0, 0.1));
    int i, j, k;

    cube_populate(cube, dist2);

    for (i = 0; i < 2; i++) {
        for (j = 0; j < 2; j++) {
            for (k = 0; k < 2; k++) {
                Cube *sub = cube_slice(cube, 2*i, 2, 2*j, 2, 2*k, 2);

                cube_write(sub, stdout);
                printf("--\n");
                cube_delete(sub);
            }
        }
    }

    cube_delete(cube);

    return 0;
}
于 2014-09-12T13:13:48.207 に答える