我目前正在研究此问题:我生成一个包含几个.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
和tab[s][x][y][z]
,其中:s
是当前的拆分步骤。每当我开始处理下一个.vtr文件时,它就会递增。x, y, z
值。现在是造成我麻烦的原因:我必须放置这些点的坐标可以是任何东西。它可以是常数(跟着一个步,例如0、0.1、0.2等),也可以不是常数。
我将坐标存储在三个数组中:
x[], y[], z[]
。我的目标是将一组值切成较小的多维数据集。假设我将值分成8个文件(2 ^ 3个文件),我必须为8个小立方体检索正确的坐标。我找不到做到这一点的方法。我很确定我的数据结构选择很糟糕,有人可以在这方面给我一些帮助吗?
编辑:
这是生成我的四星数组的函数:
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");
}
所以,是的,它根本不满足我的要求。
这是结果的屏幕截图:
所有的多维数据集都彼此重叠。使用我之前使用的代码,我有几个多维数据集(每个文件一个),但是它们在对角线上对齐(也不好)。
最佳答案
您已经承认,您的数据结构存在一些问题:
第一维s
似乎不一致:数据结构是否应包括原始多维数据集和较小的多维数据集?这并不容易,因为较小的立方体具有其他尺寸。
您有许多单独的数据:(随机)数据,坐标和数组维。为了表示多维数据集,您需要跟踪所有这些。我建议创建一个结构以将相关数据保持在一起。
用三重指针表示三维数组的方法本身没有任何问题,但是设计导致许多零散的分配。具有恒定尺寸的多维数组可能更好地表示为一个“平面”存储块。
我建议两种结构:
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 */
};
“轴”沿其中一个轴存储值。多维数据集本身不必担心与轴相关的代码,而仅将其委托给它的三个成员轴。 “多维数据集”是您的数据对象。 (在下面的实现中,数据表示形式为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;
}