51 #include <QDataStream>
52 #include <QTextStream>
58 using namespace UTILSLIB;
59 using namespace FSLIB;
60 using namespace Eigen;
71 , m_vecOffset(Vector3f::Zero(3))
82 , m_vecOffset(Vector3f::Zero(3))
89 Surface::Surface(
const QString &subject_id, qint32 hemi,
const QString &surf,
const QString &subjects_dir)
94 , m_vecOffset(Vector3f::Zero(3))
106 , m_vecOffset(Vector3f::Zero(3))
126 m_matTris.resize(0,3);
135 printf(
"\tcomputing normals\n");
137 MatrixX3f r1(
tris.rows(),3); MatrixX3f r2(
tris.rows(),3); MatrixX3f r3(
tris.rows(),3);
139 for(qint32 i = 0; i <
tris.rows(); ++i)
141 r1.row(i) =
rr.row(
tris(i, 0));
142 r2.row(i) =
rr.row(
tris(i, 1));
143 r3.row(i) =
rr.row(
tris(i, 2));
146 MatrixX3f x = r2 - r1;
147 MatrixX3f y = r3 - r1;
148 MatrixX3f tri_nn(x.rows(),y.cols());
149 tri_nn.col(0) = x.col(1).cwiseProduct(y.col(2)) - x.col(2).cwiseProduct(y.col(1));
150 tri_nn.col(1) = x.col(2).cwiseProduct(y.col(0)) - x.col(0).cwiseProduct(y.col(2));
151 tri_nn.col(2) = x.col(0).cwiseProduct(y.col(1)) - x.col(1).cwiseProduct(y.col(0));
154 MatrixX3f tmp = tri_nn.cwiseProduct(tri_nn);
155 VectorXf normSize = tmp.rowwise().sum();
156 normSize = normSize.cwiseSqrt();
158 for(qint32 i = 0; i < normSize.size(); ++i)
160 tri_nn.row(i) /= normSize(i);
162 MatrixX3f
nn = MatrixX3f::Zero(
rr.rows(), 3);
164 for(qint32 p = 0; p <
tris.rows(); ++p)
166 Vector3i verts =
tris.row(p);
167 for(qint32 j = 0; j < verts.size(); ++j)
168 nn.row(verts(j)) = tri_nn.row(p);
171 tmp =
nn.cwiseProduct(
nn);
172 normSize = tmp.rowwise().sum();
173 normSize = normSize.cwiseSqrt();
175 for(qint32 i = 0; i < normSize.size(); ++i)
177 nn.row(i) /= normSize(i);
184 bool Surface::read(
const QString &subject_id, qint32 hemi,
const QString &surf,
const QString &subjects_dir,
Surface &p_Surface,
bool p_bLoadCurvature)
189 QString p_sFile = QString(
"%1/%2/surf/%3.%4").arg(subjects_dir).arg(subject_id).arg(
hemi == 0 ?
"lh" :
"rh").arg(
surf);
191 return read(p_sFile, p_Surface, p_bLoadCurvature);
196 bool Surface::read(
const QString &path, qint32 hemi,
const QString &surf,
Surface &p_Surface,
bool p_bLoadCurvature)
201 QString p_sFile = QString(
"%1/%2.%3").arg(path).arg(
hemi == 0 ?
"lh" :
"rh").arg(
surf);
203 return read(p_sFile, p_Surface, p_bLoadCurvature);
212 QFile t_File(p_sFile);
214 if (!t_File.open(QIODevice::ReadOnly))
216 printf(
"\tError: Couldn't open the surface file\n");
220 printf(
"Reading surface...\n");
223 qint32 t_NameIdx = 0;
224 if(p_sFile.contains(
"lh."))
225 t_NameIdx = p_sFile.indexOf(
"lh.");
226 else if(p_sFile.contains(
"rh."))
227 t_NameIdx = p_sFile.indexOf(
"rh.");
231 p_Surface.m_sFilePath = p_sFile.mid(0,t_NameIdx);
232 p_Surface.m_sFileName = p_sFile.mid(t_NameIdx,p_sFile.size()-t_NameIdx);
234 QDataStream t_DataStream(&t_File);
235 t_DataStream.setByteOrder(QDataStream::BigEndian);
243 qint32 NEW_QUAD_FILE_MAGIC_NUMBER = 16777213;
244 qint32 TRIANGLE_FILE_MAGIC_NUMBER = 16777214;
245 qint32 QUAD_FILE_MAGIC_NUMBER = 16777215;
247 qint32 magic = IOUtils::fread3(t_DataStream);
255 if(magic == QUAD_FILE_MAGIC_NUMBER || magic == NEW_QUAD_FILE_MAGIC_NUMBER)
257 nvert = IOUtils::fread3(t_DataStream);
258 nquad = IOUtils::fread3(t_DataStream);
259 if(magic == QUAD_FILE_MAGIC_NUMBER)
260 printf(
"\t%s is a quad file (nvert = %d nquad = %d)\n", p_sFile.toUtf8().constData(),nvert,nquad);
262 printf(
"\t%s is a new quad file (nvert = %d nquad = %d)\n", p_sFile.toUtf8().constData(),nvert,nquad);
265 verts.resize(nvert, 3);
266 if(magic == QUAD_FILE_MAGIC_NUMBER)
269 for(qint32 i = 0; i < nvert; ++i)
271 for(qint32 j = 0; j < 3; ++j)
273 t_DataStream >> iVal;
274 IOUtils::swap_short(iVal);
275 verts(i,j) = ((float)iVal) / 100;
281 t_DataStream.readRawData((
char *)verts.data(), nvert*3*
sizeof(float));
282 for(qint32 i = 0; i < nvert; ++i)
283 for(qint32 j = 0; j < 3; ++j)
284 IOUtils::swap_floatp(&verts(i,j));
287 MatrixXi quads = IOUtils::fread3_many(t_DataStream, nquad*4);
288 MatrixXi quads_new(4, nquad);
290 for(qint32 j = 0; j < quads.cols(); ++j)
292 for(qint32 i = 0; i < quads.rows(); ++i)
294 quads_new(i,j) = quads(count, 0);
298 quads = quads_new.transpose();
302 faces = MatrixXi::Zero(2*nquad,3);
303 for(qint32
k = 0;
k < nquad; ++
k)
305 RowVectorXi quad = quads.row(
k);
306 if ((quad[0] % 2) == 0)
308 faces(nface,0) = quad[0];
309 faces(nface,1) = quad[1];
310 faces(nface,2) = quad[3];
313 faces(nface,0) = quad[2];
314 faces(nface,1) = quad[3];
315 faces(nface,2) = quad[1];
320 faces(nface,0) = quad(0);
321 faces(nface,1) = quad(1);
322 faces(nface,2) = quad(2);
325 faces(nface,0) = quad(0);
326 faces(nface,1) = quad(2);
327 faces(nface,2) = quad(3);
332 else if(magic == TRIANGLE_FILE_MAGIC_NUMBER)
334 QString s = t_File.readLine();
337 t_DataStream >> nvert;
338 t_DataStream >> nface;
339 IOUtils::swap_int(nvert);
340 IOUtils::swap_int(nface);
342 printf(
"\t%s is a triangle file (nvert = %d ntri = %d)\n", p_sFile.toUtf8().constData(), nvert, nface);
343 printf(
"\t%s", s.toUtf8().constData());
346 verts.resize(3, nvert);
347 t_DataStream.readRawData((
char *)verts.data(), nvert*3*
sizeof(
float));
348 for(qint32 i = 0; i < 3; ++i)
349 for(qint32 j = 0; j < nvert; ++j)
350 IOUtils::swap_floatp(&verts(i,j));
353 faces.resize(nface, 3);
355 for(qint32 i = 0; i < nface; ++i)
357 for(qint32 j = 0; j < 3; ++j)
359 t_DataStream >> iVal;
360 IOUtils::swap_int(iVal);
367 qWarning(
"Bad magic number (%d) in surface file %s",magic,p_sFile.toUtf8().constData());
371 verts.transposeInPlace();
372 verts.array() *= 0.001f;
374 p_Surface.m_matRR = verts.block(0,0,verts.rows(),3);
375 p_Surface.m_matTris = faces.block(0,0,faces.rows(),3);
378 p_Surface.m_matNN =
compute_normals(p_Surface.m_matRR, p_Surface.m_matTris);
381 if(t_File.fileName().contains(
"lh."))
382 p_Surface.m_iHemi = 0;
383 else if(t_File.fileName().contains(
"rh."))
384 p_Surface.m_iHemi = 1;
387 p_Surface.m_iHemi = -1;
392 p_Surface.m_sSurf = t_File.fileName().mid((t_NameIdx+3),t_File.fileName().size() - (t_NameIdx+3));
397 QString t_sCurvatureFile = QString(
"%1%2.curv").arg(p_Surface.m_sFilePath).arg(p_Surface.m_iHemi == 0 ?
"lh" :
"rh");
403 printf(
"\tRead a surface with %d vertices from %s\n[done]\n",nvert,p_sFile.toUtf8().constData());
414 printf(
"Reading curvature...");
415 QFile t_File(p_sFileName);
417 if (!t_File.open(QIODevice::ReadOnly))
419 printf(
"\tError: Couldn't open the curvature file\n");
423 QDataStream t_DataStream(&t_File);
424 t_DataStream.setByteOrder(QDataStream::BigEndian);
426 qint32 vnum = IOUtils::fread3(t_DataStream);
427 qint32 NEW_VERSION_MAGIC_NUMBER = 16777215;
429 if(vnum == NEW_VERSION_MAGIC_NUMBER)
431 qint32 fnum, vals_per_vertex;
432 t_DataStream >> vnum;
434 t_DataStream >> fnum;
435 t_DataStream >> vals_per_vertex;
437 curv.resize(vnum, 1);
438 t_DataStream.readRawData((
char *)
curv.data(), vnum*
sizeof(
float));
439 for(qint32 i = 0; i < vnum; ++i)
440 IOUtils::swap_floatp(&
curv(i));
444 qint32 fnum = IOUtils::fread3(t_DataStream);
447 curv.resize(vnum, 1);
448 for(qint32 i = 0; i < vnum; ++i)
450 t_DataStream >> iVal;
451 IOUtils::swap_short(iVal);
452 curv(i) = ((float)iVal) / 100;