У меня есть следующий вектор c++:
std::vector<myStruct> myVec;
Где myStruct содержит:
struct myStruct {
Point3D start;
Point3D end;
double lenght;
}
struct Point3D {
double x, y, z;
}
Теперь в моем mex файле я хотел бы преобразовать это в mxArray, сохраняя ту же структуру.
текущий (не функционирующий) код:
// basic 'out'
mxArray *out;
mwSize dims[2] = { 1, 1 };
const char *pointField[] = {"point"};
const char *fields[] = {"start", "end","lenght"};
const char *3dFields[] = {"x", "y", "z"};
out = mxCreateStructArray(2,dims,(int)myVec.size(),pointField);
for( int i = 0 ; i < myVec.size() ; ++i)
{
// create struct to fill
mxArray *point = mxCreateStructArray(2, dims, 3, fields);
// create struct for start
mxArray *start= mxCreateStructArray(2, dims, 3, 3dFields);
mxSetField( start, 0, "x", mxCreateDoubleScalar(myVec[i].start.x) );
mxSetField( start, 0, "y", mxCreateDoubleScalar(myVec[i].start.y) );
mxSetField( start, 0, "z", mxCreateDoubleScalar(myVec[i].start.z) );
// create struct for end
mxArray *end= mxCreateStructArray(2, dims, 3, 3dFields);
mxSetField( end, 0, "x", mxCreateDoubleScalar(myVec[i].end.x) );
mxSetField( end, 0, "y", mxCreateDoubleScalar(myVec[i].end.y) );
mxSetField( end, 0, "z", mxCreateDoubleScalar(myVec[i].end.z) );
// add start + end to 'point'
mxSetField( point, 0, "start", start);
mxSetField( point, 0, "end", end);
mxSetField( point, 0, "lenght", mxCreateDoubleScalar(myVec[i].lenght) );
// add completed 'point' struct to out at given index i
mxSetField(out, i, "point", point );
}
plhs[0] = out;
Как вы можете видеть, важно, чтобы у меня было 1 выходное значение, которое может содержать несколько "точек" -structs, из которых каждая точка имеет начало (xyz) -struct, end (xyz) -struct и значение длины.
Пока этот код выводит только одну структуру в правильном формате, но затем для второй итерации он создает только пустые значения "end" непосредственно на уровне, где "точка".
Что мне нужно изменить, чтобы эта работа работала правильно?
Заранее спасибо!
Вот моя реализация:
#include "mex.h"
#include <vector>
// C++ struct
struct Point3D {
double x, y, z;
};
struct myStruct {
Point3D start;
Point3D end;
double length;
};
const char *fieldsPoint[] = {"x", "y", "z"};
const char *fieldsStruct[] = {"start", "end", "length"};
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
if (nrhs != 0 || nlhs > 1) {
mexErrMsgIdAndTxt("MATLAB:MEX", "Wrong number of arguments.");
}
// create C++ vector of structs
std::vector<myStruct> v;
for (int i=0; i<10; i++) {
myStruct s = {
{1.0+i, 2.0+i, 3.0+i},
{4.0+i, 5.0+i, 6.0+i},
i
};
v.push_back(s);
}
// convert it to MATLAB struct array and return it as output
mxArray *p;
plhs[0] = mxCreateStructMatrix(1, v.size(), 3, fieldsStruct);
for (int i=0; i<v.size(); i++) {
// start point
p = mxCreateStructMatrix(1, 1, 3, fieldsPoint);
mxSetField(p, 0, "x", mxCreateDoubleScalar(v[i].start.x));
mxSetField(p, 0, "y", mxCreateDoubleScalar(v[i].start.y));
mxSetField(p, 0, "z", mxCreateDoubleScalar(v[i].start.z));
mxSetField(plhs[0], i, "start", p);
// end point
p = mxCreateStructMatrix(1, 1, 3, fieldsPoint);
mxSetField(p, 0, "x", mxCreateDoubleScalar(v[i].end.x));
mxSetField(p, 0, "y", mxCreateDoubleScalar(v[i].end.y));
mxSetField(p, 0, "z", mxCreateDoubleScalar(v[i].end.z));
mxSetField(plhs[0], i, "end", p);
// length
mxSetField(plhs[0], i, "length", mxCreateDoubleScalar(v[i].length));
}
}
Мы компилируем и вызываем MEX-функцию из MATLAB:
>> mex -largeArrayDims vec_struct.cpp
>> s = vec_struct()
s =
1x10 struct array with fields:
start
end
length
Как вы можете видеть, это создает массив структуры длиной 10. Например, 5-ю структуру получает доступ как:
>> s(5)
ans =
start: [1x1 struct]
end: [1x1 struct]
length: 4
>> s(5).start
ans =
x: 5
y: 6
z: 7
>> s(5).start.x
ans =
5
Вышеуказанный MEX файл эквивалентен следующему коду MATLAB:
ss = struct();
for i=1:10
ss(i).start = struct('x',1+i-1, 'y',2+i-1, 'z',3+i-1);
ss(i).end = struct('x',4+i-1, 'y',5+i-1, 'z',6+i-1);
ss(i).length = i-1;
end
Я вижу два вопроса (не обязательно полный):
out
создается как скалярная структура в вашем коде, вместо этого он должен, вероятно, быть
out = mxCreateStructMatrix(1, (int)myVec.size(), 3, pointField);
Вы указываете const char *fields[] = {"start", "end","depth"};
но затем вы пытаетесь установить поле lenght
.
Первой проблемой может быть причина вашего наблюдения - в mex вам придется предварительно распределить матрицу структуры соответствующим образом.
myVec.point(17).start.x
противmyVec(17).point.start.x
, и я думаю, что вы, вероятно, хотите вместоmyVec(17).start.x
. Но я просто догадываюсь.