// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
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];
  }

}
示例#2
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
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();
}