// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void subtractVector3d(DataArray<double>::Pointer data, double* v) { size_t count = data->GetNumberOfTuples(); for(size_t i = 0; i < count; ++i) { double* ptr = data->GetPointer(i*3); ptr[0] = ptr[0] - v[0]; ptr[1] = ptr[1] - v[1]; ptr[2] = ptr[2] - v[2]; } }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- std::vector<int32_t> TriangleOps::findAdjacentTriangles(SurfaceMeshDataContainer* sm, int32_t triangleIndex, int32_t label) { std::vector<int32_t> adjacentTris; // Get the master list of triangles for the mesh DREAM3D::SurfaceMesh::FaceList_t::Pointer facesPtr = sm->getFaces(); // DREAM3D::SurfaceMesh::Face_t* faces = facesPtr->GetPointer(0); IDataArray::Pointer flPtr = sm->getFaceData(DREAM3D::FaceData::SurfaceMeshFaceLabels); DataArray<int32_t>* faceLabelsPtr = DataArray<int32_t>::SafePointerDownCast(flPtr.get()); int32_t* faceLabels = faceLabelsPtr->GetPointer(0); // Get the Triangle Neighbor Structure MeshFaceNeighbors::Pointer triNeighbors = sm->getMeshFaceNeighborLists(); // For the specific triangle that was passed, get its neighbor list uint16_t count = triNeighbors->getNumberOfFaces(triangleIndex); int32_t* nList = triNeighbors->getNeighborListPointer(triangleIndex); if (count < 3) { std::cout << "Triangle Neighbor List had only " << count << " neighbors. Must be at least 3." << std::endl; BOOST_ASSERT(false); } else if (count == 3) // This triangle only has 3 neighbors so we are assuming all three have the same label set. { for (uint16_t n = 0; n < count; ++n) { adjacentTris.push_back(nList[n]); } } else { // Iterate over the indices to find triangles that match the label and are NOT the current triangle index for (uint16_t n = 0; n < count; ++n) { int32_t fl_0 = faceLabels[nList[n]*2]; int32_t fl_1 = faceLabels[nList[n]*2 + 1]; if ( (fl_0 == label || fl_1 == label) && (nList[n] != triangleIndex) ) { // std::cout << " Found Adjacent Triangle: " << t->tIndex << std::endl; adjacentTris.push_back(nList[n]); // ++index; } } } return adjacentTris; }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void LinkFieldMapToCellArray::dataCheck(bool preflight, size_t voxels, size_t fields, size_t ensembles) { setErrorCondition(0); std::stringstream ss; VoxelDataContainer* m = getVoxelDataContainer(); IDataArray::Pointer data = m->getCellData(m_SelectedCellDataArrayName); if (NULL == data.get()) { ss.str(""); ss << "Selected array '" << m_SelectedCellDataArrayName << "' does not exist in the Voxel Data Container. Was it spelled correctly?"; setErrorCondition(-11001); addErrorMessage(getHumanLabel(),ss.str(),getErrorCondition()); return; } std::string dType = data->getTypeAsString(); IDataArray::Pointer p = IDataArray::NullPointer(); if (dType.compare("int32_t") == 0) { DataArray<int32_t>* field = DataArray<int32_t>::SafePointerDownCast(data.get()); m_SelectedCellData = field->GetPointer(0); } else { ss.str(""); ss << "Selected array '" << m_SelectedCellDataArrayName << "' is not an Integer array. Is this the array you want to use?"; setErrorCondition(-11001); addErrorMessage(getHumanLabel(),ss.str(),getErrorCondition()); return; } m->clearFieldData(); BoolArrayType::Pointer active = BoolArrayType::CreateArray(fields, 1, DREAM3D::FieldData::Active); // bool* mActive = m_Active->GetPointer(0); m->addFieldData(DREAM3D::FieldData::Active, active); }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void CalculateTriangleGroupCurvatures::operator()() const { // Get the Triangles Array // DREAM3D::SurfaceMesh::FaceList_t::Pointer trianglesPtr = m_SurfaceMeshDataContainer->getFaces(); // DREAM3D::SurfaceMesh::Face_t* triangles = trianglesPtr->GetPointer(0); IDataArray::Pointer flPtr = m_SurfaceMeshDataContainer->getFaceData(DREAM3D::FaceData::SurfaceMeshFaceLabels); DataArray<int32_t>* faceLabelsPtr = DataArray<int32_t>::SafePointerDownCast(flPtr.get()); int32_t* faceLabels = faceLabelsPtr->GetPointer(0); // Instantiate a FindNRingNeighbors class to use during the loop FindNRingNeighbors::Pointer nRingNeighborAlg = FindNRingNeighbors::New(); // Make Sure we have triangle centroids calculated IDataArray::Pointer centroidPtr = m_SurfaceMeshDataContainer->getFaceData(DREAM3D::FaceData::SurfaceMeshFaceCentroids); if (NULL == centroidPtr.get()) { std::cout << "Triangle Centroids are required for this algorithm" << std::endl; return; } DataArray<double>* centroids = DataArray<double>::SafePointerDownCast(centroidPtr.get()); // Make sure we have triangle normals calculated IDataArray::Pointer normalPtr = m_SurfaceMeshDataContainer->getFaceData(DREAM3D::FaceData::SurfaceMeshFaceNormals); if (NULL == normalPtr.get()) { std::cout << "Triangle Normals are required for this algorithm" << std::endl; return; } DataArray<double>* normals = DataArray<double>::SafePointerDownCast(normalPtr.get()); int32_t* fl = faceLabels + m_TriangleIds[0] * 2; int grain0 = 0; int grain1 = 0; if (fl[0] < fl[1]) { grain0 = fl[0]; grain1 = fl[1]; } else { grain0 = fl[1]; grain1 = fl[0]; } bool computeGaussian = (m_GaussianCurvature.get() != NULL); bool computeMean = (m_MeanCurvature.get() != NULL); bool computeDirection = (m_PrincipleDirection1.get() != NULL); std::stringstream ss; std::vector<int>::size_type tCount = m_TriangleIds.size(); // For each triangle in the group for(std::vector<int>::size_type i = 0; i < tCount; ++i) { if (m_ParentFilter->getCancel() == true) { return; } int triId = m_TriangleIds[i]; nRingNeighborAlg->setTriangleId(triId); nRingNeighborAlg->setRegionId0(grain0); nRingNeighborAlg->setRegionId1(grain1); nRingNeighborAlg->setRing(m_NRing); nRingNeighborAlg->setSurfaceMeshDataContainer(m_SurfaceMeshDataContainer); nRingNeighborAlg->generate(); DREAM3D::SurfaceMesh::UniqueFaceIds_t triPatch = nRingNeighborAlg->getNRingTriangles(); BOOST_ASSERT(triPatch.size() > 1); DataArray<double>::Pointer patchCentroids = extractPatchData(triId, triPatch, centroids->GetPointer(0), std::string("Patch_Centroids")); DataArray<double>::Pointer patchNormals = extractPatchData(triId, triPatch, normals->GetPointer(0), std::string("Patch_Normals")); // Translate the patch to the 0,0,0 origin double sub[3] = {patchCentroids->GetComponent(0,0),patchCentroids->GetComponent(0,1), patchCentroids->GetComponent(0,2)}; subtractVector3d(patchCentroids, sub); double np[3] = {patchNormals->GetComponent(0,0), patchNormals->GetComponent(0,1), patchNormals->GetComponent(0, 2) }; double seedCentroid[3] = {patchCentroids->GetComponent(0,0), patchCentroids->GetComponent(0,1), patchCentroids->GetComponent(0,2) }; double firstCentroid[3] = {patchCentroids->GetComponent(1,0), patchCentroids->GetComponent(1,1), patchCentroids->GetComponent(1,2) }; double temp[3] = {firstCentroid[0] - seedCentroid[0], firstCentroid[1] - seedCentroid[1], firstCentroid[2] - seedCentroid[2]}; double vp[3] = {0.0, 0.0, 0.0}; // Cross Product of np and temp MatrixMath::NormalizeVector(np); MatrixMath::CrossProduct(np, temp, vp); MatrixMath::NormalizeVector(vp); // get the third orthogonal vector double up[3] = {0.0, 0.0, 0.0}; MatrixMath::CrossProduct(vp, np, up); // this constitutes a rotation matrix to a local coordinate system double rot[3][3] = {{up[0], up[1], up[2]}, {vp[0], vp[1], vp[2]}, {np[0], np[1], np[2]} }; double out[3]; // Transform all centroids and normals to new coordinate system for(size_t m = 0; m < patchCentroids->GetNumberOfTuples(); ++m) { ::memcpy(out, patchCentroids->GetPointer(m*3), 3*sizeof(double)); MatrixMath::Multiply3x3with3x1(rot, patchCentroids->GetPointer(m*3), out); ::memcpy(patchCentroids->GetPointer(m*3), out, 3*sizeof(double)); ::memcpy(out, patchNormals->GetPointer(m*3), 3*sizeof(double)); MatrixMath::Multiply3x3with3x1(rot, patchNormals->GetPointer(m*3), out); ::memcpy(patchNormals->GetPointer(m*3), out, 3*sizeof(double)); // We rotate the normals now but we dont use them yet. If we start using part 3 of Goldfeathers paper then we // will need the normals. } { // Solve the Least Squares fit static const unsigned int NO_NORMALS = 3; static const unsigned int USE_NORMALS = 7; int cols = NO_NORMALS; if (m_UseNormalsForCurveFitting == true) { cols = USE_NORMALS; } int rows = patchCentroids->GetNumberOfTuples(); Eigen::MatrixXd A(rows, cols); Eigen::VectorXd b(rows); double x, y, z; for(int m = 0; m < rows; ++m) { x = patchCentroids->GetComponent(m, 0); y = patchCentroids->GetComponent(m, 1); z = patchCentroids->GetComponent(m, 2); A(m) = 0.5 * x * x; // 1/2 x^2 A(m + rows) = x * y; // x*y A(m + rows*2) = 0.5 * y * y; // 1/2 y^2 if (m_UseNormalsForCurveFitting == true) { A(m + rows*3) = x*x*x; A(m + rows*4) = x*x*y; A(m + rows*5) = x*y*y; A(m + rows*6) = y*y*y; } b[m] = z; // The Z Values } Eigen::Matrix2d M; if (false == m_UseNormalsForCurveFitting) { typedef Eigen::Matrix<double, NO_NORMALS, 1> Vector3d; Vector3d sln1 = A.colPivHouseholderQr().solve(b); // Now that we have the A, B, C constants we can solve the Eigen value/vector problem // to get the principal curvatures and pricipal directions. M << sln1(0), sln1(1), sln1(1), sln1(2); } else { typedef Eigen::Matrix<double, USE_NORMALS, 1> Vector7d; Vector7d sln1 = A.colPivHouseholderQr().solve(b); // Now that we have the A, B, C, D, E, F & G constants we can solve the Eigen value/vector problem // to get the principal curvatures and pricipal directions. M << sln1(0), sln1(1), sln1(1), sln1(2); } Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> eig(M); Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d>::RealVectorType eValues = eig.eigenvalues(); Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d>::MatrixType eVectors = eig.eigenvectors(); // Kappa1 >= Kappa2 double kappa1 = eValues(0) * -1;// Kappa 1 double kappa2 = eValues(1) * -1; //kappa 2 BOOST_ASSERT(kappa1 >= kappa2); m_PrincipleCurvature1->SetValue(triId, kappa1); m_PrincipleCurvature2->SetValue(triId, kappa2); if (computeGaussian == true) { m_GaussianCurvature->SetValue(triId, kappa1*kappa2); } if (computeMean == true) { m_MeanCurvature->SetValue(triId, (kappa1+kappa2)/2.0); } if (computeDirection == true) { Eigen::Matrix3d e_rot_T; e_rot_T.row(0) = Eigen::Vector3d(up[0], vp[0], np[0]); e_rot_T.row(1) = Eigen::Vector3d(up[1], vp[1], np[1]); e_rot_T.row(2) = Eigen::Vector3d(up[2], vp[2], np[2]); // Rotate our principal directions back into the original coordinate system Eigen::Vector3d dir1 ( eVectors.col(0)(0), eVectors.col(0)(1), 0.0 ); dir1 = e_rot_T * dir1; ::memcpy(m_PrincipleDirection1->GetPointer(triId * 3), dir1.data(), 3*sizeof(double) ); Eigen::Vector3d dir2 ( eVectors.col(1)(0), eVectors.col(1)(1), 0.0 ); dir2 = e_rot_T * dir2; ::memcpy(m_PrincipleDirection2->GetPointer(triId * 3), dir2.data(), 3*sizeof(double) ); } } } // End Loop over this triangle m_ParentFilter->tbbTaskProgress(); }