// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- 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 ReadStlFile::readFile() { DataContainer::Pointer sm = getDataContainerArray()->getDataContainer(m_SurfaceMeshDataContainerName); // Open File FILE* f = fopen(m_StlFilePath.toLatin1().data(), "rb"); if (NULL == f) { setErrorCondition(-1003); notifyErrorMessage(getHumanLabel(), "Error opening STL file", -1003); return; } // Read Header char h[80]; int32_t triCount = 0; fread(h, sizeof(int32_t), 20, f); fread(&triCount, sizeof(int32_t), 1, f); TriangleGeom::Pointer triangleGeom = sm->getGeometryAs<TriangleGeom>(); triangleGeom->resizeTriList(triCount); triangleGeom->resizeVertexList(triCount * 3); float* nodes = triangleGeom->getVertexPointer(0); int64_t* triangles = triangleGeom->getTriPointer(0); // Resize the triangle attribute matrix to hold the normals and update the normals pointer QVector<size_t> tDims(1, triCount); sm->getAttributeMatrix(getFaceAttributeMatrixName())->resizeAttributeArrays(tDims); updateFaceInstancePointers(); // Read the triangles static const size_t k_StlElementCount = 12; float v[k_StlElementCount]; unsigned short attr; for (int32_t t = 0; t < triCount; ++t) { fread(reinterpret_cast<void*>(v), sizeof(float), k_StlElementCount, f); fread(reinterpret_cast<void*>(&attr), sizeof(unsigned short), 1, f); if (attr > 0) { std::vector<unsigned char> buffer(attr); // Allocate a buffer for the STL attribute data to be placed into fread( reinterpret_cast<void*>(&(buffer.front())), attr, 1, f); // Read the bytes into the buffer so that we can skip it. } if(v[3] < m_minXcoord) { m_minXcoord = v[3]; } if(v[3] > m_maxXcoord) { m_maxXcoord = v[3]; } if(v[4] < m_minYcoord) { m_minYcoord = v[4]; } if(v[4] > m_maxYcoord) { m_maxYcoord = v[4]; } if(v[5] < m_minZcoord) { m_minZcoord = v[5]; } if(v[5] > m_maxZcoord) { m_maxZcoord = v[5]; } if(v[6] < m_minXcoord) { m_minXcoord = v[6]; } if(v[6] > m_maxXcoord) { m_maxXcoord = v[6]; } if(v[7] < m_minYcoord) { m_minYcoord = v[7]; } if(v[7] > m_maxYcoord) { m_maxYcoord = v[7]; } if(v[8] < m_minZcoord) { m_minZcoord = v[8]; } if(v[8] > m_maxZcoord) { m_maxZcoord = v[8]; } if(v[9] < m_minXcoord) { m_minXcoord = v[9]; } if(v[9] > m_maxXcoord) { m_maxXcoord = v[9]; } if(v[10] < m_minYcoord) { m_minYcoord = v[10]; } if(v[10] > m_maxYcoord) { m_maxYcoord = v[10]; } if(v[11] < m_minZcoord) { m_minZcoord = v[11]; } if(v[11] > m_maxZcoord) { m_maxZcoord = v[11]; } m_FaceNormals[3 * t + 0] = v[0]; m_FaceNormals[3 * t + 1] = v[1]; m_FaceNormals[3 * t + 2] = v[2]; nodes[3 * (3 * t + 0) + 0] = v[3]; nodes[3 * (3 * t + 0) + 1] = v[4]; nodes[3 * (3 * t + 0) + 2] = v[5]; nodes[3 * (3 * t + 1) + 0] = v[6]; nodes[3 * (3 * t + 1) + 1] = v[7]; nodes[3 * (3 * t + 1) + 2] = v[8]; nodes[3 * (3 * t + 2) + 0] = v[9]; nodes[3 * (3 * t + 2) + 1] = v[10]; nodes[3 * (3 * t + 2) + 2] = v[11]; triangles[t * 3] = 3 * t + 0; triangles[t * 3 + 1] = 3 * t + 1; triangles[t * 3 + 2] = 3 * t + 2; } return; }