/**
  * @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");
}