/** * @brief generate Generates the Normals for the triangles * @param start The starting DREAM3D::SurfaceMesh::Face_t Index * @param end The ending DREAM3D::SurfaceMesh::Face_t Index */ void generate(size_t start, size_t end) const { DREAM3D::SurfaceMesh::Vert_t* nodes = m_Nodes->GetPointer(0); DREAM3D::SurfaceMesh::Face_t* triangles = m_Triangles->GetPointer(0); for (size_t i = start; i < end; i++) { // Get the true indices of the 3 nodes VectorType normal = TriangleOps::computeNormal(nodes[triangles[i].verts[0]], nodes[triangles[i].verts[1]], nodes[triangles[i].verts[2]]); m_Normals[i*3+0] = normal.x; m_Normals[i*3+1] = normal.y; m_Normals[i*3+2] = normal.z; } }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- int AbaqusSurfaceMeshWriter::writeTriangles(FILE* f) { int err = 0; DREAM3D::SurfaceMesh::FaceListPointer_t trianglePtr = getSurfaceMeshDataContainer()->getFaces(); DREAM3D::SurfaceMesh::Face_t* triangles = trianglePtr->GetPointer(0); size_t numTri = trianglePtr->GetNumberOfTuples(); fprintf(f, "*ELEMENT, TYPE=%s\n", TRI_ELEMENT_TYPE); for(size_t i = 1; i <= numTri; ++i) { // When we get the node index, add 1 to it because Abaqus number is 1 based. int nId0 = triangles[i-1].verts[0] + 1; int nId1 = triangles[i-1].verts[1] + 1; int nId2 = triangles[i-1].verts[2] + 1; fprintf(f, "%lu, %d, %d, %d\n", i, nId0, nId1, nId2); } return err; }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void generateNeighborLists(DREAM3D::SurfaceMesh::VertListPointer_t nodes, DREAM3D::SurfaceMesh::FaceListPointer_t faces, MeshVertLinks::Pointer cellLinks) { size_t nFaces = faces->GetNumberOfTuples(); allocate(faces->GetNumberOfTuples()); // Allocate an array of bools that we use each iteration of triangle so that we don't put duplicates into the array boost::shared_array<bool> visitedPtr(new bool[nFaces]); bool* visited = visitedPtr.get(); ::memset(visitedPtr.get(), 0, nFaces); // Reuse this vector for each loop. Avoids re-allocating the memory each time through the loop std::vector<int> loop_neighbors(32, 0); // Build up the Face Adjacency list now that we have the cell links for(size_t t = 0; t < nFaces; ++t) { // std::cout << "Analyzing Face " << t << std::endl; DREAM3D::SurfaceMesh::Face_t& seedFace = *(faces->GetPointer(t)); for(size_t v = 0; v < 3; ++v) { // std::cout << " vert " << v << std::endl; int nTris = cellLinks->getNumberOfFaces(seedFace.verts[v]); int* vertIdxs = cellLinks->getFaceListPointer(seedFace.verts[v]); for(int vt = 0; vt < nTris; ++vt) { if (vertIdxs[vt] == static_cast<int>(t) ) { continue; } // This is the same triangle as our "source" triangle if (visited[vertIdxs[vt]] == true) { continue; } // We already added this triangle so loop again // std::cout << " Comparing Face " << vertIdxs[vt] << std::endl; DREAM3D::SurfaceMesh::Face_t& vertTri = *(faces->GetPointer(vertIdxs[vt])); int vCount = 0; // Loop over all the vertex indices of this triangle and try to match 2 of them to the current loop triangle // If there are 2 matches then that triangle is a neighbor of this triangle. if there are more than 2 matches // then there is a real problem with the mesh and the program is going to assert. // Unrolled the loop to shave about 25% of time off the outer loop. int seedTriVert0 = seedFace.verts[0]; int seedTriVert1 = seedFace.verts[1]; int seedTriVert2 = seedFace.verts[2]; int trgtTriVert0 = vertTri.verts[0]; int trgtTriVert1 = vertTri.verts[1]; int trgtTriVert2 = vertTri.verts[2]; if (seedTriVert0 == trgtTriVert0 || seedTriVert0 == trgtTriVert1 || seedTriVert0 == trgtTriVert2 ) { vCount++; } if (seedTriVert1 == trgtTriVert0 || seedTriVert1 == trgtTriVert1 || seedTriVert1 == trgtTriVert2 ) { vCount++; } if (seedTriVert2 == trgtTriVert0 || seedTriVert2 == trgtTriVert1 || seedTriVert2 == trgtTriVert2 ) { vCount++; } BOOST_ASSERT(vCount < 3); // No way 2 faces can share all 3 vertices. Something is VERY wrong at this point // So if our vertex match count is 2 and we have not visited the triangle in question then add this triangle index // into the list of Face Indices as neighbors for the source triangle. if (vCount == 2) { //std::cout << " Neighbor: " << vertIdxs[vt] << std::endl; // Use the current count of neighbors as the index // into the loop_neighbors vector and place the value of the vertex triangle at that index loop_neighbors[this->Array[t].ncells] = vertIdxs[vt]; this->Array[t].ncells++;// Increment the count for the next time through if (this->Array[t].ncells >= loop_neighbors.size()) { loop_neighbors.resize(loop_neighbors.size() + 10); } visited[vertIdxs[vt]] = true; // Set this triangle as visited so we do NOT add it again } } } BOOST_ASSERT(this->Array[t].ncells > 2); // Reset all the visited triangle indexs back to false (zero) for(size_t k = 0;k < this->Array[t].ncells; ++k) { visited[loop_neighbors[k]] = false; } // Allocate the array storage for the current triangle to hold its Face list this->Array[t].cells = new int[this->Array[t].ncells]; // Only copy the first "N" values from the loop_neighbors vector into the storage array ::memcpy(this->Array[t].cells, &(loop_neighbors[0]), sizeof(int) * this->Array[t].ncells); } }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void GoldfeatherReader::execute() { int err = 0; std::stringstream ss; setErrorCondition(err); SurfaceMeshDataContainer* m = getSurfaceMeshDataContainer(); if(NULL == m) { setErrorCondition(-999); notifyErrorMessage("The Voxel DataContainer Object was NULL", -999); return; } setErrorCondition(0); FILE* f = fopen(m_InputFile.c_str(), "r"); if (NULL == f) { setErrorCondition(-999); notifyErrorMessage("Error opening Input file", getErrorCondition()); return; } ScopedFileMonitor fileMonitor(f); int nNodes = 0; fscanf(f, "%d\n", &nNodes); dataCheck(false, nNodes, 1, 1); // Allocate the Nodes, Normals, curvatures and principal direction vectors DREAM3D::SurfaceMesh::VertListPointer_t nodesPtr = DREAM3D::SurfaceMesh::VertList_t::CreateArray(nNodes, DREAM3D::VertexData::SurfaceMeshNodes); nodesPtr->initializeWithZeros(); DREAM3D::SurfaceMesh::Vert_t* nodes = nodesPtr->GetPointer(0); DoubleArrayType::Pointer normalsPtr = DoubleArrayType::CreateArray(nNodes, 3, DREAM3D::VertexData::SurfaceMeshNodeNormals); double* normals = normalsPtr->GetPointer(0); DoubleArrayType::Pointer pcurv1Ptr = DoubleArrayType::CreateArray(nNodes, 1, "Principal_Curvature_1"); double* pcurv1 = pcurv1Ptr->GetPointer(0); DoubleArrayType::Pointer pcurv2Ptr = DoubleArrayType::CreateArray(nNodes, 1, "Principal_Curvature_2"); double* pcurv2 = pcurv2Ptr->GetPointer(0); DoubleArrayType::Pointer pDirection1Ptr = DoubleArrayType::CreateArray(nNodes, 3, "Principal_Direction_1"); double* pDirection1 = pDirection1Ptr->GetPointer(0); DoubleArrayType::Pointer pDirection2Ptr = DoubleArrayType::CreateArray(nNodes, 3, "Principal_Direction_2"); double* pDirection2 = pDirection2Ptr->GetPointer(0); float x, y, z, n0, n1, n2, p1, p2; for(int n = 0; n < nNodes; ++n) { fscanf(f, "%f %f %f %f %f %f %f %f\n", &x, &y, &z, &n0, &n1, &n2, &p1, &p2); nodes[n].pos[0] = x; nodes[n].pos[1] = y; nodes[n].pos[2] = z; normals[n*3+0] = n0; normals[n*3+1] = n1; normals[n*3+2] = n2; pcurv1[n] = p1; pcurv2[n] = p2; // Read the next line of the data which is the principal direction vectors fscanf(f, "%f %f %f %f %f %f\n", &x, &y, &z, &n0, &n1, &n2); pDirection1[n*3+0] = x; pDirection1[n*3+1] = y; pDirection1[n*3+2] = z; pDirection2[n*3+0] = n0; pDirection2[n*3+1] = n1; pDirection2[n*3+2] = n2; } m->setVertices(nodesPtr); m->addVertexData(normalsPtr->GetName(), normalsPtr); m->addVertexData(pcurv1Ptr->GetName(), pcurv1Ptr); m->addVertexData(pcurv2Ptr->GetName(), pcurv2Ptr); m->addVertexData(pDirection1Ptr->GetName(), pDirection1Ptr); m->addVertexData(pDirection2Ptr->GetName(), pDirection2Ptr); int nTriangles = 0; err = fscanf(f, "%d\n", &nTriangles); if (err < 0) { off_t fpos; fpos = ftell(f); setErrorCondition(-876); notifyErrorMessage("Error Reading the number of Triangles from the file", getErrorCondition()); return; } DREAM3D::SurfaceMesh::FaceListPointer_t trianglesPtr = DREAM3D::SurfaceMesh::FaceList_t::CreateArray(nTriangles, DREAM3D::FaceData::SurfaceMeshFaces); trianglesPtr->initializeWithZeros(); DREAM3D::SurfaceMesh::Face_t* triangles = trianglesPtr->GetPointer(0); DataArray<int32_t>::Pointer faceLabelPtr = DataArray<int32_t>::CreateArray(nTriangles, 2, DREAM3D::FaceData::SurfaceMeshFaceLabels); faceLabelPtr->initializeWithZeros(); int32_t* faceLabels = faceLabelPtr->GetPointer(0); DoubleArrayType::Pointer triNormalsPtr = DoubleArrayType::CreateArray(nTriangles, 3, DREAM3D::FaceData::SurfaceMeshFaceNormals); double* triNormals = triNormalsPtr->GetPointer(0); for(int t = 0; t < nTriangles; ++t) { fscanf(f, "%f %f %f %f %f %f", &x, &y, &z, &n0, &n1, &n2); triangles[t].verts[0] = x; triangles[t].verts[1] = y; triangles[t].verts[2] = z; // triangles[t].tIndex = t; faceLabels[t*2] = 0; faceLabels[t*2+1] = 1; triNormals[t*3+0] = n0; triNormals[t*3+1] = n1; triNormals[t*3+2] = n2; } m->setFaces(trianglesPtr); m->addFaceData(faceLabelPtr->GetName(), faceLabelPtr); m->addFaceData(triNormalsPtr->GetName(), triNormalsPtr); /* Let the GUI know we are done with this filter */ notifyStatusMessage("Complete"); }