// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void TriangleNormalFilter::execute() { setErrorCondition(0); dataCheck(); if(getErrorCondition() < 0) { return; } DataContainer::Pointer sm = getDataContainerArray()->getDataContainer(getSurfaceMeshTriangleNormalsArrayPath().getDataContainerName()); TriangleGeom::Pointer triangleGeom = sm->getGeometryAs<TriangleGeom>(); #ifdef SIMPLib_USE_PARALLEL_ALGORITHMS bool doParallel = true; #endif #ifdef SIMPLib_USE_PARALLEL_ALGORITHMS if (doParallel == true) { tbb::parallel_for(tbb::blocked_range<size_t>(0, triangleGeom->getNumberOfTris()), CalculateNormalsImpl(triangleGeom->getVertices(), triangleGeom->getTriangles(), m_SurfaceMeshTriangleNormals), tbb::auto_partitioner()); } else #endif { CalculateNormalsImpl serial(triangleGeom->getVertices(), triangleGeom->getTriangles(), m_SurfaceMeshTriangleNormals); serial.generate(0, triangleGeom->getNumberOfTris()); } /* Let the GUI know we are done with this filter */ notifyStatusMessage(getHumanLabel(), "Complete"); }
void writeCellScalarData(DataContainer::Pointer dc, const QString& faceAttributeMatrixName, const QString& dataName, const QString& dataType, bool writeBinaryData, FILE* vtkFile, QMap<int32_t, int32_t>& featureIds, int32_t* m_SurfaceMeshFaceLabels) { TriangleGeom::Pointer triangleGeom = dc->getGeometryAs<TriangleGeom>(); int64_t numTriangles = triangleGeom->getNumberOfTris(); IDataArray::Pointer data = dc->getAttributeMatrix(faceAttributeMatrixName)->getAttributeArray(dataName); QString ss; if (NULL != data.get()) { int32_t totalCellsWritten = 0; T* m = reinterpret_cast<T*>(data->getVoidPointer(0)); fprintf(vtkFile, "\n"); fprintf(vtkFile, "SCALARS %s %s 1\n", dataName.toLatin1().data(), dataType.toLatin1().data()); fprintf(vtkFile, "LOOKUP_TABLE default\n"); // Loop over all the features for(QMap<int32_t, int32_t>::iterator featureIter = featureIds.begin(); featureIter != featureIds.end(); ++featureIter) { int32_t gid = featureIter.key(); // The current Feature Id size_t size = featureIter.value(); // The number of triangles for this feature id std::vector<T> buffer(size, 0); totalCellsWritten += size; size_t index = 0; for (int j = 0; j < numTriangles; j++) { if (m_SurfaceMeshFaceLabels[j * 2] != gid && m_SurfaceMeshFaceLabels[j * 2 + 1] != gid) { continue; } // Get the data T s0 = static_cast<T>(m[j]); if (m_SurfaceMeshFaceLabels[j * 2 + 1] == gid) { s0 = s0 * -1; } // Write the values to the buffer after an Endian swap. if(writeBinaryData == true) { SIMPLib::Endian::FromSystemToBig::convert(s0); buffer[index] = s0; ++index; } else { ss = QString::number(s0); fprintf(vtkFile, "%s\n", ss.toLatin1().data()); } } // Write the Buffer if(writeBinaryData == true) { fwrite(&(buffer.front()), sizeof(T), size, vtkFile); } } } }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- int32_t AbaqusSurfaceMeshWriter::writeTriangles(FILE* f) { int32_t err = 0; TriangleGeom::Pointer triangleGeom = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName())->getGeometryAs<TriangleGeom>(); int64_t numTri = triangleGeom->getNumberOfTris(); int64_t* triangles = triangleGeom->getTriPointer(0); fprintf(f, "*ELEMENT, TYPE=%s\n", TRI_ELEMENT_TYPE); for (int64_t i = 1; i <= numTri; ++i) { // When we get the node index, add 1 to it because Abaqus number is 1 based. int64_t nId0 = triangles[(i - 1) * 3] + 1; int64_t nId1 = triangles[(i - 1) * 3 + 1] + 1; int64_t nId2 = triangles[(i - 1) * 3 + 2] + 1; fprintf(f, "%lld, %lld, %lld, %lld\n", (long long int)i, (long long int)nId0, (long long int)nId1, (long long int)nId2); } return err; }
void writeCellVectorData(DataContainer::Pointer dc, const QString& faceAttributeMatrixName, const QString& dataName, const QString& dataType, bool writeBinaryData, const QString& vtkAttributeType, FILE* vtkFile, QMap<int32_t, int32_t>& featureIds) { TriangleGeom::Pointer triangleGeom = dc->getGeometryAs<TriangleGeom>(); int64_t numTriangles = triangleGeom->getNumberOfTris(); IDataArray::Pointer data = dc->getAttributeMatrix(faceAttributeMatrixName)->getAttributeArray(dataName); QString ss; if (NULL != data.get()) { T* m = reinterpret_cast<T*>(data->getVoidPointer(0)); fprintf(vtkFile, "\n"); fprintf(vtkFile, "%s %s %s\n", vtkAttributeType.toLatin1().data(), dataName.toLatin1().data(), dataType.toLatin1().data()); for(int i = 0; i < numTriangles; ++i) { T s0 = 0x00; T s1 = 0x00; T s2 = 0x00; if(writeBinaryData == true) { s0 = static_cast<T>(m[i * 3 + 0]); s1 = static_cast<T>(m[i * 3 + 1]); s2 = static_cast<T>(m[i * 3 + 2]); SIMPLib::Endian::FromSystemToBig::convert(s0); SIMPLib::Endian::FromSystemToBig::convert(s1); SIMPLib::Endian::FromSystemToBig::convert(s2); fwrite(&s0, sizeof(T), 1, vtkFile); fwrite(&s1, sizeof(T), 1, vtkFile); fwrite(&s2, sizeof(T), 1, vtkFile); } else { ss << m[i * 3 + 0] << " " << m[i * 3 + 1] << " " << m[i * 3 + 2] << " "; fprintf(vtkFile, "%s ", ss.toLatin1().data()); if (i % 25 == 0) { fprintf(vtkFile, "\n"); } } } } }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- int SurfaceMeshToNonconformalVtk::writeCellData(FILE* vtkFile, QMap<int32_t, int32_t>& featureIds) { int err = 0; if (NULL == vtkFile) { return -1; } DataContainer::Pointer sm = getDataContainerArray()->getDataContainer(m_SurfaceMeshFaceLabelsArrayPath.getDataContainerName()); // Write the triangle region ids TriangleGeom::Pointer triangleGeom = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName())->getGeometryAs<TriangleGeom>(); int64_t numTriangles = triangleGeom->getNumberOfTris(); int swapped; // This is like a "section header" fprintf(vtkFile, "\n"); fprintf(vtkFile, "CELL_DATA %lld\n", (long long int)(numTriangles * 2)); int32_t totalCellsWritten = 0; // Write the FeatureId Data to the file fprintf(vtkFile, "SCALARS FeatureID int 1\n"); fprintf(vtkFile, "LOOKUP_TABLE default\n"); // Loop over all the features for(QMap<int32_t, int32_t>::iterator featureIter = featureIds.begin(); featureIter != featureIds.end(); ++featureIter) { int32_t gid = featureIter.key(); // The current Feature Id size_t size = featureIter.value(); // The number of triangles for this feature id std::vector<int32_t> buffer(size, 0); totalCellsWritten += size; // Endian Swap our current feature Id since we are going to write it a bunch of times. swapped = gid; SIMPLib::Endian::FromSystemToBig::convert(swapped); size_t index = 0; // Loop over all the triangles looking for the current feature id // this is probably sub-optimal as if we have 1000 features we are going to loop 1000 times but this will use the // least amount of memory. We could run a filter to group the triangles by feature but then we would need an // additional amount of memory equal to 3X the memory used for the triangle list because every triangle will be listed // twice. We could get some slightly better performance if we buffered 4K worth of data then wrote out that data // in one chunk versus what we are doing here. for (int j = 0; j < numTriangles; j++) { if (m_SurfaceMeshFaceLabels[j * 2] == gid || m_SurfaceMeshFaceLabels[j * 2 + 1] == gid) { if(m_WriteBinaryFile == true) { buffer[index] = swapped; ++index; } else { fprintf(vtkFile, "%d\n", gid); } } } // Write the Buffer if(m_WriteBinaryFile == true) { fwrite(&(buffer.front()), sizeof(int32_t), size, vtkFile); } } #if 0 // Write the Original Triangle ID Data to the file fprintf(vtkFile, "\n"); fprintf(vtkFile, "SCALARS TriangleID int 1\n"); fprintf(vtkFile, "LOOKUP_TABLE default\n"); for(int i = 0; i < triangleCount * 2; ++i) { //Triangle& t = triangles[i]; // Get the current Node if(m_WriteBinaryFile == true) { swapped = i; SIMPLib::Endian::FromSystemToBig::convert(swapped); fwrite(&swapped, sizeof(int), 1, vtkFile); fwrite(&swapped, sizeof(int), 1, vtkFile); } else { fprintf(vtkFile, "%d\n", i); fprintf(vtkFile, "%d\n", i); } } #endif QString attrMatName = m_SurfaceMeshFaceLabelsArrayPath.getAttributeMatrixName(); notifyStatusMessage(getHumanLabel(), "Writing Face Normals..."); writeCellNormalData<double>(sm, attrMatName, SIMPL::FaceData::SurfaceMeshFaceNormals, "double", m_WriteBinaryFile, vtkFile, featureIds, m_SurfaceMeshFaceLabels); notifyStatusMessage(getHumanLabel(), "Writing Principal Curvature 1"); writeCellScalarData<double>(sm, attrMatName, SIMPL::FaceData::SurfaceMeshPrincipalCurvature1, "double", m_WriteBinaryFile, vtkFile, featureIds, m_SurfaceMeshFaceLabels); notifyStatusMessage(getHumanLabel(), "Writing Principal Curvature 2"); writeCellScalarData<double>(sm, attrMatName, SIMPL::FaceData::SurfaceMeshPrincipalCurvature2, "double", m_WriteBinaryFile, vtkFile, featureIds, m_SurfaceMeshFaceLabels); notifyStatusMessage(getHumanLabel(), "Writing Feature Face Id"); writeCellScalarData<int32_t>(sm, attrMatName, SIMPL::FaceData::SurfaceMeshFeatureFaceId, "int", m_WriteBinaryFile, vtkFile, featureIds, m_SurfaceMeshFaceLabels); notifyStatusMessage(getHumanLabel(), "Writing Gaussian Curvature"); writeCellScalarData<double>(sm, attrMatName, SIMPL::FaceData::SurfaceMeshGaussianCurvatures, "double", m_WriteBinaryFile, vtkFile, featureIds, m_SurfaceMeshFaceLabels); notifyStatusMessage(getHumanLabel(), "Writing Mean Curvature"); writeCellScalarData<double>(sm, attrMatName, SIMPL::FaceData::SurfaceMeshMeanCurvatures, "double", m_WriteBinaryFile, vtkFile, featureIds, m_SurfaceMeshFaceLabels); #if 0 writeCellVectorData<double>(sm, attrMatName, SIMPL::CellData::SurfaceMeshPrincipalDirection1, "double", m_WriteBinaryFile, "VECTORS", vtkFile, nT); writeCellVectorData<double>(sm, attrMatName, SIMPL::CellData::SurfaceMeshPrincipalDirection2, "double", m_WriteBinaryFile, "VECTORS", vtkFile, nT); writeCellNormalData<double>(sm, attrMatName, "Goldfeather_Triangle_Normals", "double", m_WriteBinaryFile, vtkFile, nT); #endif return err; }
void writeCellNormalData(DataContainer::Pointer dc, const QString& faceAttributeMatrixName, const QString& dataName, const QString& dataType, bool writeBinaryData, FILE* vtkFile, QMap<int32_t, int32_t>& featureIds, int32_t* m_SurfaceMeshFaceLabels) { TriangleGeom::Pointer triangleGeom = dc->getGeometryAs<TriangleGeom>(); int64_t numTriangles = triangleGeom->getNumberOfTris(); IDataArray::Pointer data = dc->getAttributeMatrix(faceAttributeMatrixName)->getAttributeArray(dataName); QString buf; QTextStream ss(&buf); if (NULL != data.get()) { int32_t totalCellsWritten = 0; T* m = reinterpret_cast<T*>(data->getVoidPointer(0)); fprintf(vtkFile, "\n"); fprintf(vtkFile, "NORMALS %s %s\n", dataName.toLatin1().data(), dataType.toLatin1().data()); // Loop over all the features for(QMap<int32_t, int32_t>::iterator featureIter = featureIds.begin(); featureIter != featureIds.end(); ++featureIter) { int32_t gid = featureIter.key(); // The current Feature Id size_t size = featureIter.value(); // The number of triangles for this feature id std::vector<T> buffer(size * 3, 0); totalCellsWritten += size * 3; size_t index = 0; for (int j = 0; j < numTriangles; j++) { if (m_SurfaceMeshFaceLabels[j * 2] != gid && m_SurfaceMeshFaceLabels[j * 2 + 1] != gid) { continue; } // Get the data T s0 = static_cast<T>(m[j * 3 + 0]); T s1 = static_cast<T>(m[j * 3 + 1]); T s2 = static_cast<T>(m[j * 3 + 2]); // Flip the normal if needed because the current feature id is assigned to the triangle.labels[1] if (m_SurfaceMeshFaceLabels[j * 2 + 1] == gid ) { s0 *= -1.0; s1 *= -1.0; s2 *= -1.0; } // Write the values to the buffer after an Endian swap. if(writeBinaryData == true) { SIMPLib::Endian::FromSystemToBig::convert(s0); buffer[index] = s0; ++index; SIMPLib::Endian::FromSystemToBig::convert(s1); buffer[index] = s1; ++index; SIMPLib::Endian::FromSystemToBig::convert(s2); buffer[index] = s2; ++index; } else { ss << s0 << " " << s1 << " " << s2; fprintf(vtkFile, "%s\n", buf.toLatin1().data()); buf.clear(); } } // Write the Buffer if(writeBinaryData == true) { fwrite(&(buffer.front()), sizeof(T), size * 3, vtkFile); } } } }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void SurfaceMeshToNonconformalVtk::execute() { int err = 0; setErrorCondition(err); dataCheck(); if(getErrorCondition() < 0) { return; } DataContainer::Pointer m = getDataContainerArray()->getDataContainer(m_SurfaceMeshFaceLabelsArrayPath.getDataContainerName()); TriangleGeom::Pointer triangleGeom = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName())->getGeometryAs<TriangleGeom>(); float* nodes = triangleGeom->getVertexPointer(0); int64_t* triangles = triangleGeom->getTriPointer(0); qint64 numNodes = triangleGeom->getNumberOfVertices(); int64_t numTriangles = triangleGeom->getNumberOfTris(); // Make sure any directory path is also available as the user may have just typed // in a path without actually creating the full path QFileInfo fi(getOutputVtkFile()); QDir parentPath = fi.path(); if(!parentPath.mkpath(".")) { QString ss = QObject::tr("Error creating parent path '%1'").arg(parentPath.absolutePath()); setErrorCondition(-1); notifyErrorMessage(getHumanLabel(), ss, getErrorCondition()); return; } // Open the output VTK File for writing FILE* vtkFile = NULL; vtkFile = fopen(getOutputVtkFile().toLatin1().data(), "wb"); if (NULL == vtkFile) { QString ss = QObject::tr("Error creating file '%1'").arg(getOutputVtkFile()); setErrorCondition(-18542); notifyErrorMessage(getHumanLabel(), ss, getErrorCondition()); return; } ScopedFileMonitor vtkFileMonitor(vtkFile); notifyStatusMessage(getHumanLabel(), "Writing Vertex Data ...."); fprintf(vtkFile, "# vtk DataFile Version 2.0\n"); fprintf(vtkFile, "Data set from DREAM.3D Surface Meshing Module\n"); if (m_WriteBinaryFile) { fprintf(vtkFile, "BINARY\n"); } else { fprintf(vtkFile, "ASCII\n"); } fprintf(vtkFile, "DATASET POLYDATA\n"); int numberWrittenNodes = 0; for (int i = 0; i < numNodes; i++) { // Node& n = nodes[i]; // Get the current Node if (m_SurfaceMeshNodeType[i] > 0) { ++numberWrittenNodes; } else { qDebug() << "Node Type Invalid: " << i << "::" << (int)(m_SurfaceMeshNodeType[i]) ;} } fprintf(vtkFile, "POINTS %d float\n", numberWrittenNodes); float pos[3] = {0.0f, 0.0f, 0.0f}; size_t totalWritten = 0; // Write the POINTS data (Vertex) for (int i = 0; i < numNodes; i++) { if (m_SurfaceMeshNodeType[i] > 0) { pos[0] = static_cast<float>(nodes[i * 3]); pos[1] = static_cast<float>(nodes[i * 3 + 1]); pos[2] = static_cast<float>(nodes[i * 3 + 2]); if (m_WriteBinaryFile == true) { SIMPLib::Endian::FromSystemToBig::convert(pos[0]); SIMPLib::Endian::FromSystemToBig::convert(pos[1]); SIMPLib::Endian::FromSystemToBig::convert(pos[2]); totalWritten = fwrite(pos, sizeof(float), 3, vtkFile); if(totalWritten != 3) {} } else { fprintf(vtkFile, "%f %f %f\n", pos[0], pos[1], pos[2]); // Write the positions to the output file } } } // Write the triangle indices into the vtk File notifyStatusMessage(getHumanLabel(), "Writing Faces ...."); int tData[4]; // Store all the unique Spins QMap<int32_t, int32_t> featureTriangleCount; for (int i = 0; i < numTriangles; i++) { if (featureTriangleCount.find(m_SurfaceMeshFaceLabels[i * 2]) == featureTriangleCount.end()) { featureTriangleCount[m_SurfaceMeshFaceLabels[i * 2]] = 1; } else { featureTriangleCount[m_SurfaceMeshFaceLabels[i * 2]]++; } if (featureTriangleCount.find(m_SurfaceMeshFaceLabels[i * 2 + 1]) == featureTriangleCount.end()) { featureTriangleCount[m_SurfaceMeshFaceLabels[i * 2 + 1]] = 1; } else { featureTriangleCount[m_SurfaceMeshFaceLabels[i * 2 + 1]]++; } } // Write the POLYGONS fprintf(vtkFile, "\nPOLYGONS %lld %lld\n", (long long int)(numTriangles * 2), (long long int)(numTriangles * 2 * 4)); size_t totalCells = 0; // Loop over all the features for(QMap<int32_t, int32_t>::iterator featureIter = featureTriangleCount.begin(); featureIter != featureTriangleCount.end(); ++featureIter) { totalCells += featureIter.value(); } Q_ASSERT(totalCells == (size_t)(numTriangles * 2) ); // Loop over all the features for(QMap<int32_t, int32_t>::iterator featureIter = featureTriangleCount.begin(); featureIter != featureTriangleCount.end(); ++featureIter) { int32_t gid = featureIter.key(); // The current Feature Id int32_t numTriToWrite = featureIter.value(); // The number of triangles for this feature uint8_t doWrite = 0; // Loop over all the triangles looking for the current feature id // this is probably sub-optimal as if we have 1000 features we are going to loop 1000 times but this will use the // least amount of memory. We could run a filter to group the triangles by feature but then we would need an // additional amount of memory equal to 3X the memory used for the triangle list because every triangle will be listed // twice. We could get some slightly better performance if we buffered 4K worth of data then wrote out that data // in one chunk versus what we are doing here. for (int j = 0; j < numTriangles; j++) { doWrite = 0; if (m_SurfaceMeshFaceLabels[j * 2] == gid ) { doWrite = 1; } else if (m_SurfaceMeshFaceLabels[j * 2 + 1] == gid) { doWrite = 2; } // We need to flip the winding of the triangle if (doWrite == 0) { continue; } // Labels in the triangle did match the current feature id. if (doWrite == 1) { tData[0] = 3; // Push on the total number of entries for this entry tData[1] = triangles[j * 3]; tData[2] = triangles[j * 3 + 1]; tData[3] = triangles[j * 3 + 2]; } else { tData[0] = 3; // Push on the total number of entries for this entry tData[1] = triangles[j * 3 + 2]; tData[2] = triangles[j * 3 + 1]; tData[3] = triangles[j * 3]; } if (m_WriteBinaryFile == true) { SIMPLib::Endian::FromSystemToBig::convert(tData[0]); SIMPLib::Endian::FromSystemToBig::convert(tData[1]); // Index of Vertex 0 SIMPLib::Endian::FromSystemToBig::convert(tData[2]); // Index of Vertex 1 SIMPLib::Endian::FromSystemToBig::convert(tData[3]); // Index of Vertex 2 fwrite(tData, sizeof(int), 4, vtkFile); } else { fprintf(vtkFile, "3 %d %d %d\n", tData[1], tData[2], tData[3]); } numTriToWrite--; } if (numTriToWrite != 0) { qDebug() << "Not enough triangles written: " << gid << "::" << numTriToWrite << " Total Triangles to Write " << featureIter.value(); } } // Write the POINT_DATA section err = writePointData(vtkFile); // Write the CELL_DATA section err = writeCellData(vtkFile, featureTriangleCount); fprintf(vtkFile, "\n"); setErrorCondition(0); notifyStatusMessage(getHumanLabel(), "Complete"); }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- int SurfaceMeshToVtk::writeCellData(FILE* vtkFile) { int err = 0; if (NULL == vtkFile) { return -1; } DataContainer::Pointer sm = getDataContainerArray()->getDataContainer(m_SurfaceMeshFaceLabelsArrayPath.getDataContainerName()); // Write the triangle region ids TriangleGeom::Pointer triangleGeom = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName())->getGeometryAs<TriangleGeom>(); int64_t nT = triangleGeom->getNumberOfTris(); int numTriangles = nT; int swapped; if (false == m_WriteConformalMesh) { numTriangles = nT * 2; } // This is like a "section header" fprintf(vtkFile, "\n"); fprintf(vtkFile, "CELL_DATA %d\n", numTriangles); // Write the FeatureId Data to the file fprintf(vtkFile, "SCALARS FeatureID int 1\n"); fprintf(vtkFile, "LOOKUP_TABLE default\n"); for(int i = 0; i < nT; ++i) { //FaceArray::Face_t& t = triangles[i]; // Get the current Node if(m_WriteBinaryFile == true) { swapped = m_SurfaceMeshFaceLabels[i * 2]; SIMPLib::Endian::FromSystemToBig::convert(swapped); fwrite(&swapped, sizeof(int), 1, vtkFile); if(false == m_WriteConformalMesh) { swapped = m_SurfaceMeshFaceLabels[i * 2 + 1]; SIMPLib::Endian::FromSystemToBig::convert(swapped); fwrite(&swapped, sizeof(int), 1, vtkFile); } } else { fprintf(vtkFile, "%d\n", m_SurfaceMeshFaceLabels[i * 2]); if(false == m_WriteConformalMesh) { fprintf(vtkFile, "%d\n", m_SurfaceMeshFaceLabels[i * 2 + 1]); } } } #if 0 // Write the Original Triangle ID Data to the file fprintf(vtkFile, "\n"); fprintf(vtkFile, "SCALARS TriangleID int 1\n"); fprintf(vtkFile, "LOOKUP_TABLE default\n"); for(int i = 0; i < nT; ++i) { //Triangle& t = triangles[i]; // Get the current Node if(m_WriteBinaryFile == true) { swapped = i; SIMPLib::Endian::FromSystemToBig::convert(swapped); fwrite(&swapped, sizeof(int), 1, vtkFile); if(false == m_WriteConformalMesh) { fwrite(&swapped, sizeof(int), 1, vtkFile); } } else { fprintf(vtkFile, "%d\n", i); if(false == m_WriteConformalMesh) { fprintf(vtkFile, "%d\n", i); } } } #endif QString attrMatName = m_SurfaceMeshFaceLabelsArrayPath.getAttributeMatrixName(); writeCellScalarData<int32_t>(sm, attrMatName, DREAM3D::FaceData::SurfaceMeshFeatureFaceId, "int", m_WriteBinaryFile, m_WriteConformalMesh, vtkFile, nT); writeCellScalarData<double>(sm, attrMatName, DREAM3D::FaceData::SurfaceMeshPrincipalCurvature1, "double", m_WriteBinaryFile, m_WriteConformalMesh, vtkFile, nT); writeCellScalarData<double>(sm, attrMatName, DREAM3D::FaceData::SurfaceMeshPrincipalCurvature2, "double", m_WriteBinaryFile, m_WriteConformalMesh, vtkFile, nT); writeCellVectorData<double>(sm, attrMatName, DREAM3D::FaceData::SurfaceMeshPrincipalDirection1, "double", m_WriteBinaryFile, m_WriteConformalMesh, "VECTORS", vtkFile, nT); writeCellVectorData<double>(sm, attrMatName, DREAM3D::FaceData::SurfaceMeshPrincipalDirection2, "double", m_WriteBinaryFile, m_WriteConformalMesh, "VECTORS", vtkFile, nT); writeCellScalarData<double>(sm, attrMatName, DREAM3D::FaceData::SurfaceMeshGaussianCurvatures, "double", m_WriteBinaryFile, m_WriteConformalMesh, vtkFile, nT); writeCellScalarData<double>(sm, attrMatName, DREAM3D::FaceData::SurfaceMeshMeanCurvatures, "double", m_WriteBinaryFile, m_WriteConformalMesh, vtkFile, nT); writeCellNormalData<double>(sm, attrMatName, DREAM3D::FaceData::SurfaceMeshFaceNormals, "double", m_WriteBinaryFile, m_WriteConformalMesh, vtkFile, nT); writeCellNormalData<double>(sm, attrMatName, "Goldfeather_Triangle_Normals", "double", m_WriteBinaryFile, m_WriteConformalMesh, vtkFile, nT); return err; }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void SurfaceMeshToVtk::execute() { int err = 0; setErrorCondition(err); dataCheck(); if(getErrorCondition() < 0) { return; } setErrorCondition(0); DataContainer::Pointer sm = getDataContainerArray()->getDataContainer(m_SurfaceMeshFaceLabelsArrayPath.getDataContainerName()); /* Place all your code to execute your filter here. */ TriangleGeom::Pointer triangleGeom = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName())->getGeometryAs<TriangleGeom>(); float* nodes = triangleGeom->getVertexPointer(0); int64_t* triangles = triangleGeom->getTriPointer(0); qint64 numNodes = triangleGeom->getNumberOfVertices(); int64_t numTriangles = triangleGeom->getNumberOfTris(); // Make sure any directory path is also available as the user may have just typed // in a path without actually creating the full path QFileInfo fi(getOutputVtkFile()); QDir parentPath = fi.path(); if(!parentPath.mkpath(".")) { QString ss = QObject::tr("Error creating parent path '%1'").arg(parentPath.absolutePath()); notifyErrorMessage(getHumanLabel(), ss, -1); setErrorCondition(-1); return; } // Open the output VTK File for writing FILE* vtkFile = NULL; vtkFile = fopen(getOutputVtkFile().toLatin1().data(), "wb"); if (NULL == vtkFile) { QString ss = QObject::tr("Error creating file '%1'").arg(getOutputVtkFile()); notifyErrorMessage(getHumanLabel(), ss, -18542); setErrorCondition(-18542); return; } ScopedFileMonitor vtkFileMonitor(vtkFile); fprintf(vtkFile, "# vtk DataFile Version 2.0\n"); fprintf(vtkFile, "Data set from DREAM.3D Surface Meshing Module\n"); if (m_WriteBinaryFile) { fprintf(vtkFile, "BINARY\n"); } else { fprintf(vtkFile, "ASCII\n"); } fprintf(vtkFile, "DATASET POLYDATA\n"); int numberWrittenumNodes = 0; for (int i = 0; i < numNodes; i++) { // Node& n = nodes[i]; // Get the current Node if (m_SurfaceMeshNodeType[i] > 0) { ++numberWrittenumNodes; } } fprintf(vtkFile, "POINTS %d float\n", numberWrittenumNodes); float pos[3] = {0.0f, 0.0f, 0.0f}; size_t totalWritten = 0; // Write the POINTS data (Vertex) for (int i = 0; i < numNodes; i++) { if (m_SurfaceMeshNodeType[i] > 0) { pos[0] = static_cast<float>(nodes[i * 3]); pos[1] = static_cast<float>(nodes[i * 3 + 1]); pos[2] = static_cast<float>(nodes[i * 3 + 2]); if (m_WriteBinaryFile == true) { SIMPLib::Endian::FromSystemToBig::convert(pos[0]); SIMPLib::Endian::FromSystemToBig::convert(pos[1]); SIMPLib::Endian::FromSystemToBig::convert(pos[2]); totalWritten = fwrite(pos, sizeof(float), 3, vtkFile); if (totalWritten != sizeof(float) * 3) { } } else { fprintf(vtkFile, "%f %f %f\n", pos[0], pos[1], pos[2]); // Write the positions to the output file } } } int tData[4]; int triangleCount = numTriangles; // int tn1, tn2, tn3; if (false == m_WriteConformalMesh) { triangleCount = numTriangles * 2; } // Write the POLYGONS fprintf(vtkFile, "\nPOLYGONS %d %d\n", triangleCount, (triangleCount * 4)); for (int j = 0; j < numTriangles; j++) { // Triangle& t = triangles[j]; tData[1] = triangles[j * 3]; tData[2] = triangles[j * 3 + 1]; tData[3] = triangles[j * 3 + 2]; if (m_WriteBinaryFile == true) { tData[0] = 3; // Push on the total number of entries for this entry SIMPLib::Endian::FromSystemToBig::convert(tData[0]); SIMPLib::Endian::FromSystemToBig::convert(tData[1]); // Index of Vertex 0 SIMPLib::Endian::FromSystemToBig::convert(tData[2]); // Index of Vertex 1 SIMPLib::Endian::FromSystemToBig::convert(tData[3]); // Index of Vertex 2 fwrite(tData, sizeof(int), 4, vtkFile); if (false == m_WriteConformalMesh) { tData[0] = tData[1]; tData[1] = tData[3]; tData[3] = tData[0]; tData[0] = 3; SIMPLib::Endian::FromSystemToBig::convert(tData[0]); fwrite(tData, sizeof(int), 4, vtkFile); } } else { fprintf(vtkFile, "3 %d %d %d\n", tData[1], tData[2], tData[3]); if (false == m_WriteConformalMesh) { fprintf(vtkFile, "3 %d %d %d\n", tData[3], tData[2], tData[1]); } } } // Write the POINT_DATA section err = writePointData(vtkFile); // Write the CELL_DATA section err = writeCellData(vtkFile); fprintf(vtkFile, "\n"); setErrorCondition(0); notifyStatusMessage(getHumanLabel(), "Complete"); }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void SharedFeatureFaceFilter::execute() { setErrorCondition(0); dataCheck(); if(getErrorCondition() < 0) { return; } DataContainer::Pointer sm = getDataContainerArray()->getDataContainer(m_SurfaceMeshFaceLabelsArrayPath.getDataContainerName()); AttributeMatrix::Pointer faceFeatureAttrMat = sm->getAttributeMatrix(getFaceFeatureAttributeMatrixName()); TriangleGeom::Pointer triangleGeom = sm->getGeometryAs<TriangleGeom>(); int64_t totalPoints = triangleGeom->getNumberOfTris(); QMap<uint64_t, int32_t> faceSizeMap; QMap<uint64_t, int32_t> faceIdMap; // This maps a unique 64 bit integer to an increasing 32 bit integer int32_t index = 1; struct { int g; int r; } faceId; uint64_t* faceId_64 = reinterpret_cast<uint64_t*>(&faceId); int32_t fl0 = -1; int32_t fl1 = -1; std::vector< std::pair<int32_t, int32_t> > faceLabelMap; faceLabelMap.push_back( std::pair<int32_t, int32_t>(0, 0) ); // Loop through all the Triangles and figure out how many triangles we have in each one. for (int64_t t = 0; t < totalPoints; ++t) { fl0 = m_SurfaceMeshFaceLabels[t * 2]; fl1 = m_SurfaceMeshFaceLabels[t * 2 + 1]; if (fl0 < fl1) { faceId.g = fl0; faceId.r = fl1; } else { faceId.g = fl1; faceId.r = fl0; } QMap<uint64_t, int32_t>::iterator iter = faceSizeMap.find(*faceId_64); if (iter == faceSizeMap.end()) { faceSizeMap[*faceId_64] = 1; faceIdMap[*faceId_64] = index; m_SurfaceMeshFeatureFaceIds[t] = index; faceLabelMap.push_back( std::pair<int32_t, int32_t>(faceId.g, faceId.r) ); ++index; } else { iter.value()++; m_SurfaceMeshFeatureFaceIds[t] = faceIdMap[*faceId_64]; } } // resize + update pointers QVector<size_t> tDims(1, index); faceFeatureAttrMat->resizeAttributeArrays(tDims); m_SurfaceMeshFeatureFaceLabels = m_SurfaceMeshFeatureFaceLabelsPtr.lock()->getPointer(0); m_SurfaceMeshFeatureFaceNumTriangles = m_SurfaceMeshFeatureFaceNumTrianglesPtr.lock()->getPointer(0); for (int32_t i = 0; i < index; i++) { // get feature face labels m_SurfaceMeshFeatureFaceLabels[2 * i + 0] = faceLabelMap[i].first; m_SurfaceMeshFeatureFaceLabels[2 * i + 1] = faceLabelMap[i].second; // get feature triangle count faceId.g = faceLabelMap[i].first; faceId.r = faceLabelMap[i].second; m_SurfaceMeshFeatureFaceNumTriangles[i] = faceSizeMap[*faceId_64]; } /* Let the GUI know we are done with this filter */ notifyStatusMessage(getHumanLabel(), "Complete"); }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- int32_t AbaqusSurfaceMeshWriter::writeFeatures(FILE* f) { //*Elset, elset=Feature1 //1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 int32_t err = 0; TriangleGeom::Pointer triangleGeo = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName())->getGeometryAs<TriangleGeom>(); int64_t nTriangles = triangleGeo->getNumberOfTris(); // Store all the unique Spins std::set<int32_t> uniqueSpins; for (int64_t i = 0; i < nTriangles; i++) { uniqueSpins.insert(m_SurfaceMeshFaceLabels[i * 2]); uniqueSpins.insert(m_SurfaceMeshFaceLabels[i * 2 + 1]); } int32_t spin = 0; //Loop over the unique Spins for (std::set<int32_t>::iterator spinIter = uniqueSpins.begin(); spinIter != uniqueSpins.end(); ++spinIter ) { spin = *spinIter; if (spin < 0) { continue; } fprintf(f, "*ELSET, ELSET=Feature%d\n", spin); { QString ss = QObject::tr("Writing ELSET for Feature Id %1").arg(spin); notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss); } // Loop over all the triangles for this spin int64_t lineCount = 0; for (int64_t t = 0; t < nTriangles; ++t) { if (m_SurfaceMeshFaceLabels[t * 2] != spin && m_SurfaceMeshFaceLabels[t * 2 + 1] != spin) { continue; // We do not match either spin so move to the next triangle } // Only print 15 Triangles per line if (lineCount == 15) { fprintf (f, ", %lld\n", (long long int)(t)); lineCount = 0; } else if(lineCount == 0) // First value on the line { fprintf(f, "%lld", (long long int)(t)); lineCount++; } else { fprintf(f, ", %lld", (long long int)(t)); lineCount++; } } // Make sure we have a new line at the end of the section if (lineCount != 0) { fprintf(f, "\n"); } } return err; }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void AbaqusSurfaceMeshWriter::execute() { int32_t err = 0; setErrorCondition(err); dataCheck(); if(getErrorCondition() < 0) { return; } DataContainer::Pointer sm = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName()); // Make sure any directory path is also available as the user may have just typed // in a path without actually creating the full path QFileInfo fi(getOutputFile()); QDir parentPath = fi.path(); if(!parentPath.mkpath(".")) { QString ss = QObject::tr("Error creating parent path '%1'").arg(parentPath.absolutePath()); setErrorCondition(-8005); notifyErrorMessage(getHumanLabel(), ss, getErrorCondition()); return; } TriangleGeom::Pointer triangleGeom = sm->getGeometryAs<TriangleGeom>(); // Store all the unique Spins std::set<int32_t> uniqueSpins; for (int64_t i = 0; i < triangleGeom->getNumberOfTris(); i++) { uniqueSpins.insert(m_SurfaceMeshFaceLabels[i * 2]); uniqueSpins.insert(m_SurfaceMeshFaceLabels[i * 2 + 1]); } FILE* f = fopen(m_OutputFile.toLatin1().data(), "wb"); ScopedFileMonitor fileMonitor(f); err = writeHeader(f, triangleGeom->getNumberOfVertices(), triangleGeom->getNumberOfTris(), uniqueSpins.size() - 1); if(err < 0) { QString ss = QObject::tr("Error writing header for file '%1'").arg(m_OutputFile); setErrorCondition(-8001); notifyErrorMessage(getHumanLabel(), ss, getErrorCondition()); return; } err = writeNodes(f); if(err < 0) { QString ss = QObject::tr("Error writing nodes for file '%1'").arg(m_OutputFile); setErrorCondition(-8002); notifyErrorMessage(getHumanLabel(), ss, getErrorCondition()); return; } err = writeTriangles(f); if(err < 0) { QString ss = QObject::tr("Error writing triangles for file '%1'").arg(m_OutputFile); setErrorCondition(-8003); notifyErrorMessage(getHumanLabel(), ss, getErrorCondition()); return; } err = writeFeatures(f); if(err < 0) { QString ss = QObject::tr("Error writing Features for file '%1'").arg(m_OutputFile); setErrorCondition(-8004); notifyErrorMessage(getHumanLabel(), ss, getErrorCondition()); return; } notifyStatusMessage(getHumanLabel(), "Complete"); }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void ReadStlFile::eliminate_duplicate_nodes() { DataContainer::Pointer sm = getDataContainerArray()->getDataContainer(m_SurfaceMeshDataContainerName); TriangleGeom::Pointer triangleGeom = sm->getGeometryAs<TriangleGeom>(); float* vertex = triangleGeom->getVertexPointer(0); int64_t nNodes = triangleGeom->getNumberOfVertices(); int64_t* triangles = triangleGeom->getTriPointer(0); int64_t nTriangles = triangleGeom->getNumberOfTris(); float stepX = (m_maxXcoord - m_minXcoord) / 100.0f; float stepY = (m_maxYcoord - m_minYcoord) / 100.0f; float stepZ = (m_maxZcoord - m_minZcoord) / 100.0f; QVector<QVector<size_t> > nodesInBin(100 * 100 * 100); // determine (xyz) bin each node falls in - used to speed up node comparison int32_t bin = 0, xBin = 0, yBin = 0, zBin = 0; for (int64_t i = 0; i < nNodes; i++) { xBin = (vertex[i * 3] - m_minXcoord) / stepX; yBin = (vertex[i * 3 + 1] - m_minYcoord) / stepY; zBin = (vertex[i * 3 + 2] - m_minZcoord) / stepZ; if (xBin == 100) { xBin = 99; } if (yBin == 100) { yBin = 99; } if (zBin == 100) { zBin = 99; } bin = (zBin * 10000) + (yBin * 100) + xBin; nodesInBin[bin].push_back(i); } // Create array to hold unique node numbers Int64ArrayType::Pointer uniqueIdsPtr = Int64ArrayType::CreateArray(nNodes, "uniqueIds"); int64_t* uniqueIds = uniqueIdsPtr->getPointer(0); for (int64_t i = 0; i < nNodes; i++) { uniqueIds[i] = i; } #ifdef SIMPLib_USE_PARALLEL_ALGORITHMS tbb::task_scheduler_init init; bool doParallel = true; #endif //Parallel algorithm to find duplicate nodes #ifdef SIMPLib_USE_PARALLEL_ALGORITHMS if (doParallel == true) { tbb::parallel_for(tbb::blocked_range<size_t>(0, 100 * 100 * 100), FindUniqueIdsImpl(triangleGeom->getVertices(), nodesInBin, uniqueIds), tbb::auto_partitioner()); } else #endif { FindUniqueIdsImpl serial(triangleGeom->getVertices(), nodesInBin, uniqueIds); serial.convert(0, 100 * 100 * 100); } //renumber the unique nodes int64_t uniqueCount = 0; for (int64_t i = 0; i < nNodes; i++) { if(uniqueIds[i] == i) { uniqueIds[i] = uniqueCount; uniqueCount++; } else { uniqueIds[i] = uniqueIds[uniqueIds[i]]; } } // Move nodes to unique Id and then resize nodes array for (int64_t i = 0; i < nNodes; i++) { vertex[uniqueIds[i] * 3] = vertex[i * 3]; vertex[uniqueIds[i] * 3 + 1] = vertex[i * 3 + 1]; vertex[uniqueIds[i] * 3 + 2] = vertex[i * 3 + 2]; } triangleGeom->resizeVertexList(uniqueCount); // Update the triangle nodes to reflect the unique ids int64_t node1 = 0, node2 = 0, node3 = 0; for (int64_t i = 0; i < nTriangles; i++) { node1 = triangles[i * 3]; node2 = triangles[i * 3 + 1]; node3 = triangles[i * 3 + 2]; triangles[i * 3] = uniqueIds[node1]; triangles[i * 3 + 1] = uniqueIds[node2]; triangles[i * 3 + 2] = uniqueIds[node3]; } }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void WriteTriangleGeometry::execute() { int err = 0; setErrorCondition(err); dataCheck(); if(getErrorCondition() < 0) { return; } DataContainer::Pointer dataContainer = getDataContainerArray()->getPrereqDataContainer<AbstractFilter>(this, getDataContainerSelection()); TriangleGeom::Pointer triangleGeom = dataContainer->getGeometryAs<TriangleGeom>(); QString geometryType = triangleGeom->getGeometryTypeAsString(); float* nodes = triangleGeom->getVertexPointer(0); int64_t* triangles = triangleGeom->getTriPointer(0); qint64 numNodes = triangleGeom->getNumberOfVertices(); qint64 maxNodeId = numNodes - 1; int64_t numTriangles = triangleGeom->getNumberOfTris(); // ++++++++++++++ Write the Nodes File +++++++++++++++++++++++++++++++++++++++++++ // Make sure any directory path is also available as the user may have just typed // in a path without actually creating the full path notifyStatusMessage(getHumanLabel(), "Writing Nodes Text File"); QFileInfo fi(getOutputNodesFile()); QDir parentPath = fi.path(); if(!parentPath.mkpath(".")) { QString ss = QObject::tr("Error creating parent path '%1'").arg(parentPath.absolutePath()); notifyErrorMessage(getHumanLabel(), ss, -1); setErrorCondition(-1); return; } FILE* nodesFile = NULL; nodesFile = fopen(getOutputNodesFile().toLatin1().data(), "wb"); if (NULL == nodesFile) { setErrorCondition(-100); notifyErrorMessage(getHumanLabel(), "Error opening Nodes file for writing", -100); return; } fprintf(nodesFile, "# All lines starting with '#' are comments\n"); fprintf(nodesFile, "# DREAM.3D Nodes file\n"); fprintf(nodesFile, "# DREAM.3D Version %s\n", SIMPLib::Version::Complete().toLatin1().constData()); fprintf(nodesFile, "# Node Data is X Y Z space delimited.\n"); fprintf(nodesFile, "Node Count: %lld\n", numNodes); for (int i = 0; i < numNodes; i++) { fprintf(nodesFile, "%8.5f %8.5f %8.5f\n", nodes[i * 3], nodes[i * 3 + 1], nodes[i * 3 + 2]); } fclose(nodesFile); // ++++++++++++++ Write the Triangles File +++++++++++++++++++++++++++++++++++++++++++ notifyStatusMessage(getHumanLabel(), "Writing Triangles Text File"); QFileInfo triFI(getOutputTrianglesFile()); parentPath = triFI.path(); if(!parentPath.mkpath(".")) { QString ss = QObject::tr("Error creating parent path '%1'").arg(parentPath.absolutePath()); notifyErrorMessage(getHumanLabel(), ss, -1); setErrorCondition(-1); return; } FILE* triFile = fopen(getOutputTrianglesFile().toLatin1().data(), "wb"); if (NULL == triFile) { setErrorCondition(-100); notifyErrorMessage(getHumanLabel(), "Error opening Triangles file for writing", -100); return; } fprintf(triFile, "# All lines starting with '#' are comments\n"); fprintf(triFile, "# DREAM.3D Triangle file\n"); fprintf(triFile, "# DREAM.3D Version %s\n", SIMPLib::Version::Complete().toLatin1().constData()); fprintf(triFile, "# Each Triangle consists of 3 Node Ids.\n"); fprintf(triFile, "# NODE IDs START AT 0.\n"); fprintf(triFile, "Geometry Type: %s\n", geometryType.toLatin1().constData()); fprintf(triFile, "Node Count: %lld\n", numNodes); fprintf(triFile, "Max Node Id: %lld\n", maxNodeId ); fprintf(triFile, "Triangle Count: %lld\n", (long long int)(numTriangles)); int n1, n2, n3; for (int64_t j = 0; j < numTriangles; ++j) { n1 = triangles[j * 3]; n2 = triangles[j * 3 + 1]; n3 = triangles[j * 3 + 2]; fprintf(triFile, "%d %d %d\n", n1, n2, n3); } fclose(triFile); /* Let the GUI know we are done with this filter */ notifyStatusMessage(getHumanLabel(), "Complete"); }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void FeatureFaceCurvatureFilter::execute() { setErrorCondition(0); dataCheck(); if(getErrorCondition() < 0) { return; } DataContainer::Pointer sm = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName()); // Get our Reference counted Array of Face Structures TriangleGeom::Pointer triangleGeom = sm->getGeometryAs<TriangleGeom>(); // Just to double check we have everything. int64_t numTriangles = triangleGeom->getNumberOfTris(); // Make sure the Face Connectivity is created because the FindNRing algorithm needs this and will // assert if the data is NOT in the SurfaceMesh Data Container ElementDynamicList::Pointer vertLinks = triangleGeom->getElementsContainingVert(); if (NULL == vertLinks.get()) { triangleGeom->findElementsContainingVert(); } // get the QMap from the SharedFeatureFaces filter SharedFeatureFaces_t sharedFeatureFaces; int32_t maxFaceId = 0; for (int64_t t = 0; t < numTriangles; ++t) { if (m_SurfaceMeshFeatureFaceIds[t] > maxFaceId) { maxFaceId = m_SurfaceMeshFeatureFaceIds[t]; } } std::vector<int32_t> faceSizes(maxFaceId + 1, 0); // Loop through all the Triangles and assign each one to a unique Feature Face Id. for (int64_t t = 0; t < numTriangles; ++t) { faceSizes[m_SurfaceMeshFeatureFaceIds[t]]++; } // Allocate all the vectors that we need for (size_t iter = 0; iter < faceSizes.size(); ++iter) { FaceIds_t v; v.reserve(faceSizes[iter]); sharedFeatureFaces[iter] = v; } // Loop through all the Triangles and assign each one to a unique Feature Face Id. for(int64_t t = 0; t < numTriangles; ++t) { sharedFeatureFaces[m_SurfaceMeshFeatureFaceIds[t]].push_back(t); } m_TotalFeatureFaces = sharedFeatureFaces.size(); m_CompletedFeatureFaces = 0; #ifdef SIMPLib_USE_PARALLEL_ALGORITHMS tbb::task_scheduler_init init; bool doParallel = true; #endif #ifdef SIMPLib_USE_PARALLEL_ALGORITHMS tbb::task_group* g = new tbb::task_group; #else #endif // typedef here for conveneince typedef SharedFeatureFaces_t::iterator SharedFeatureFaceIterator_t; for(SharedFeatureFaceIterator_t iter = sharedFeatureFaces.begin(); iter != sharedFeatureFaces.end(); ++iter) { QString ss = QObject::tr("Working on Face Id %1/%2").arg((*iter).first).arg(maxFaceId); notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss); FaceIds_t& triangleIds = (*iter).second; #ifdef SIMPLib_USE_PARALLEL_ALGORITHMS if (doParallel == true) { g->run(CalculateTriangleGroupCurvatures(m_NRing, triangleIds, m_UseNormalsForCurveFitting, m_SurfaceMeshPrincipalCurvature1sPtr.lock(), m_SurfaceMeshPrincipalCurvature2sPtr.lock(), m_SurfaceMeshPrincipalDirection1sPtr.lock(), m_SurfaceMeshPrincipalDirection2sPtr.lock(), m_SurfaceMeshGaussianCurvaturesPtr.lock(), m_SurfaceMeshMeanCurvaturesPtr.lock(), triangleGeom, m_SurfaceMeshFaceLabelsPtr.lock(), m_SurfaceMeshFaceNormalsPtr.lock(), m_SurfaceMeshTriangleCentroidsPtr.lock(), this ) ); } else #endif { CalculateTriangleGroupCurvatures curvature(m_NRing, triangleIds, m_UseNormalsForCurveFitting, m_SurfaceMeshPrincipalCurvature1sPtr.lock(), m_SurfaceMeshPrincipalCurvature2sPtr.lock(), m_SurfaceMeshPrincipalDirection1sPtr.lock(), m_SurfaceMeshPrincipalDirection2sPtr.lock(), m_SurfaceMeshGaussianCurvaturesPtr.lock(), m_SurfaceMeshMeanCurvaturesPtr.lock(), triangleGeom, m_SurfaceMeshFaceLabelsPtr.lock(), m_SurfaceMeshFaceNormalsPtr.lock(), m_SurfaceMeshTriangleCentroidsPtr.lock(), this ); curvature(); } } // *********************** END END END END END END ******************************************************************** #ifdef SIMPLib_USE_PARALLEL_ALGORITHMS g->wait(); // Wait for all the threads to complete before moving on. delete g; #endif /* Let the GUI know we are done with this filter */ notifyStatusMessage(getHumanLabel(), "Complete"); }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void WriteStlFile::execute() { int32_t err = 0; setErrorCondition(0); dataCheck(); if(getErrorCondition() < 0) { return; } // Make sure any directory path is also available as the user may have just typed // in a path without actually creating the full path QDir stlDir(getOutputStlDirectory()); if (!stlDir.mkpath(".")) { QString ss = QObject::tr("Error creating parent path '%1'").arg(getOutputStlDirectory()); notifyErrorMessage(getHumanLabel(), ss, -1); setErrorCondition(-1); return; } TriangleGeom::Pointer triangleGeom = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName())->getGeometryAs<TriangleGeom>(); float* nodes = triangleGeom->getVertexPointer(0); int64_t* triangles = triangleGeom->getTriPointer(0); int64_t nTriangles = triangleGeom->getNumberOfTris(); if (nTriangles > std::numeric_limits<int32_t>::max()) { QString ss = QObject::tr("The number of triangles is %1, but the STL specification only supports triangle counts up to %2").arg(nTriangles).arg(std::numeric_limits<int32_t>::max()); notifyErrorMessage(getHumanLabel(), ss, -1); setErrorCondition(-1); return; } // Store all the unique Spins QMap<int32_t, int32_t> uniqueGrainIdtoPhase; if (m_GroupByPhase == true) { for (int64_t i = 0; i < nTriangles; i++) { uniqueGrainIdtoPhase.insert(m_SurfaceMeshFaceLabels[i * 2], m_SurfaceMeshFacePhases[i * 2]); uniqueGrainIdtoPhase.insert(m_SurfaceMeshFaceLabels[i * 2 + 1], m_SurfaceMeshFacePhases[i * 2 + 1]); } } else { for (int64_t i = 0; i < nTriangles; i++) { uniqueGrainIdtoPhase.insert(m_SurfaceMeshFaceLabels[i * 2], 0); uniqueGrainIdtoPhase.insert(m_SurfaceMeshFaceLabels[i * 2 + 1], 0); } } unsigned char data[50]; float* normal = (float*)data; float* vert1 = (float*)(data + 12); float* vert2 = (float*)(data + 24); float* vert3 = (float*)(data + 36); uint16_t* attrByteCount = (uint16_t*)(data + 48); *attrByteCount = 0; size_t totalWritten = 0; float u[3] = { 0.0f, 0.0f, 0.0f }, w[3] = { 0.0f, 0.0f, 0.0f }; float length = 0.0f; int32_t spin = 0; int32_t triCount = 0; //Loop over the unique Spins for (QMap<int32_t, int32_t>::iterator spinIter = uniqueGrainIdtoPhase.begin(); spinIter != uniqueGrainIdtoPhase.end(); ++spinIter ) { spin = spinIter.key(); // Generate the output file name QString filename = getOutputStlDirectory() + "/" + getOutputStlPrefix(); if (m_GroupByPhase == true) { filename = filename + QString("Ensemble_") + QString::number(spinIter.value()) + QString("_"); } filename = filename + QString("Feature_") + QString::number(spin) + ".stl"; FILE* f = fopen(filename.toLatin1().data(), "wb"); { QString ss = QObject::tr("Writing STL for Feature Id %1").arg(spin); notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss); } QString header = "DREAM3D Generated For Feature ID " + QString::number(spin); if (m_GroupByPhase == true) { header = header + " Phase " + QString::number(spinIter.value()); } err = writeHeader(f, header, 0); if (err < 0) { } triCount = 0; // Reset this to Zero. Increment for every triangle written // Loop over all the triangles for this spin for (int64_t t = 0; t < nTriangles; ++t) { // Get the true indices of the 3 nodes int64_t nId0 = triangles[t * 3]; int64_t nId1 = triangles[t * 3 + 1]; int64_t nId2 = triangles[t * 3 + 2]; vert1[0] = static_cast<float>(nodes[nId0 * 3]); vert1[1] = static_cast<float>(nodes[nId0 * 3 + 1]); vert1[2] = static_cast<float>(nodes[nId0 * 3 + 2]); if (m_SurfaceMeshFaceLabels[t * 2] == spin) { //winding = 0; // 0 = Write it using forward spin } else if (m_SurfaceMeshFaceLabels[t * 2 + 1] == spin) { //winding = 1; // Write it using backward spin // Switch the 2 node indices int64_t temp = nId1; nId1 = nId2; nId2 = temp; } else { continue; // We do not match either spin so move to the next triangle } vert2[0] = static_cast<float>(nodes[nId1 * 3]); vert2[1] = static_cast<float>(nodes[nId1 * 3 + 1]); vert2[2] = static_cast<float>(nodes[nId1 * 3 + 2]); vert3[0] = static_cast<float>(nodes[nId2 * 3]); vert3[1] = static_cast<float>(nodes[nId2 * 3 + 1]); vert3[2] = static_cast<float>(nodes[nId2 * 3 + 2]); // Compute the normal u[0] = vert2[0] - vert1[0]; u[1] = vert2[1] - vert1[1]; u[2] = vert2[2] - vert1[2]; w[0] = vert3[0] - vert1[0]; w[1] = vert3[1] - vert1[1]; w[2] = vert3[2] - vert1[2]; normal[0] = u[1] * w[2] - u[2] * w[1]; normal[1] = u[2] * w[0] - u[0] * w[2]; normal[2] = u[0] * w[1] - u[1] * w[0]; length = sqrtf(normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2]); normal[0] = normal[0] / length; normal[1] = normal[1] / length; normal[2] = normal[2] / length; totalWritten = fwrite(data, 1, 50, f); if (totalWritten != 50) { QString ss = QObject::tr("Error Writing STL File. Not enough elements written for Feature Id %1. Wrote %2 of 50.").arg(spin).arg(totalWritten); notifyErrorMessage(getHumanLabel(), ss, -1201); } triCount++; } fclose(f); err = writeNumTrianglesToFile(filename, triCount); } setErrorCondition(0); notifyStatusMessage(getHumanLabel(), "Complete"); return; }