Esempio n. 1
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void TriangleNormalFilter::execute()
{
  setErrorCondition(0);
  dataCheck();
  if(getErrorCondition() < 0) { return; }

  DataContainer::Pointer sm = getDataContainerArray()->getDataContainer(getSurfaceMeshTriangleNormalsArrayPath().getDataContainerName());

  TriangleGeom::Pointer triangleGeom = sm->getGeometryAs<TriangleGeom>();

#ifdef SIMPLib_USE_PARALLEL_ALGORITHMS
  bool doParallel = true;
#endif

#ifdef SIMPLib_USE_PARALLEL_ALGORITHMS
  if (doParallel == true)
  {
    tbb::parallel_for(tbb::blocked_range<size_t>(0, triangleGeom->getNumberOfTris()),
                      CalculateNormalsImpl(triangleGeom->getVertices(), triangleGeom->getTriangles(), m_SurfaceMeshTriangleNormals), tbb::auto_partitioner());
  }
  else
#endif
  {
    CalculateNormalsImpl serial(triangleGeom->getVertices(), triangleGeom->getTriangles(), m_SurfaceMeshTriangleNormals);
    serial.generate(0, triangleGeom->getNumberOfTris());
  }

  /* Let the GUI know we are done with this filter */
  notifyStatusMessage(getHumanLabel(), "Complete");
}
void writeCellScalarData(DataContainer::Pointer dc, const QString& faceAttributeMatrixName, const QString& dataName, const QString& dataType,
                         bool writeBinaryData, FILE* vtkFile, QMap<int32_t, int32_t>& featureIds, int32_t* m_SurfaceMeshFaceLabels)
{
  TriangleGeom::Pointer triangleGeom = dc->getGeometryAs<TriangleGeom>();

  int64_t numTriangles = triangleGeom->getNumberOfTris();
  IDataArray::Pointer data = dc->getAttributeMatrix(faceAttributeMatrixName)->getAttributeArray(dataName);

  QString ss;
  if (NULL != data.get())
  {
    int32_t totalCellsWritten = 0;

    T* m = reinterpret_cast<T*>(data->getVoidPointer(0));
    fprintf(vtkFile, "\n");
    fprintf(vtkFile, "SCALARS %s %s 1\n", dataName.toLatin1().data(), dataType.toLatin1().data());
    fprintf(vtkFile, "LOOKUP_TABLE default\n");
    // Loop over all the features
    for(QMap<int32_t, int32_t>::iterator featureIter = featureIds.begin(); featureIter != featureIds.end(); ++featureIter)
    {
      int32_t gid = featureIter.key(); // The current Feature Id
      size_t size = featureIter.value(); // The number of triangles for this feature id
      std::vector<T> buffer(size, 0);
      totalCellsWritten += size;
      size_t index = 0;

      for (int j = 0; j < numTriangles; j++)
      {
        if (m_SurfaceMeshFaceLabels[j * 2] != gid && m_SurfaceMeshFaceLabels[j * 2 + 1] != gid) { continue; }
        // Get the data
        T s0 = static_cast<T>(m[j]);
        if (m_SurfaceMeshFaceLabels[j * 2 + 1] == gid)
        { s0 = s0 * -1; }


        // Write the values to the buffer after an Endian swap.
        if(writeBinaryData == true)
        {
          SIMPLib::Endian::FromSystemToBig::convert(s0);
          buffer[index] = s0;
          ++index;
        }
        else
        {

          ss = QString::number(s0);
          fprintf(vtkFile, "%s\n", ss.toLatin1().data());
        }
      }

      // Write the Buffer
      if(writeBinaryData == true)
      {
        fwrite(&(buffer.front()), sizeof(T), size, vtkFile);
      }
    }
  }

}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
int32_t AbaqusSurfaceMeshWriter::writeTriangles(FILE* f)
{
  int32_t err = 0;
  TriangleGeom::Pointer triangleGeom = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName())->getGeometryAs<TriangleGeom>();
  int64_t numTri = triangleGeom->getNumberOfTris();
  int64_t* triangles = triangleGeom->getTriPointer(0);

  fprintf(f, "*ELEMENT, TYPE=%s\n", TRI_ELEMENT_TYPE);
  for (int64_t i = 1; i <= numTri; ++i)
  {
    // When we get the node index, add 1 to it because Abaqus number is 1 based.
    int64_t nId0 = triangles[(i - 1) * 3] + 1;
    int64_t nId1 = triangles[(i - 1) * 3 + 1] + 1;
    int64_t nId2 = triangles[(i - 1) * 3 + 2] + 1;
    fprintf(f, "%lld, %lld, %lld, %lld\n", (long long int)i, (long long int)nId0, (long long int)nId1, (long long int)nId2);
  }
  return err;
}
void writeCellVectorData(DataContainer::Pointer dc, const QString& faceAttributeMatrixName, const QString& dataName, const QString& dataType,
                         bool writeBinaryData, const QString& vtkAttributeType,
                         FILE* vtkFile, QMap<int32_t, int32_t>& featureIds)
{
  TriangleGeom::Pointer triangleGeom = dc->getGeometryAs<TriangleGeom>();

  int64_t numTriangles = triangleGeom->getNumberOfTris();

  IDataArray::Pointer data = dc->getAttributeMatrix(faceAttributeMatrixName)->getAttributeArray(dataName);
  QString ss;
  if (NULL != data.get())
  {
    T* m = reinterpret_cast<T*>(data->getVoidPointer(0));
    fprintf(vtkFile, "\n");
    fprintf(vtkFile, "%s %s %s\n", vtkAttributeType.toLatin1().data(), dataName.toLatin1().data(), dataType.toLatin1().data());
    for(int i = 0; i < numTriangles; ++i)
    {
      T s0 = 0x00;
      T s1 = 0x00;
      T s2 = 0x00;
      if(writeBinaryData == true)
      {
        s0 = static_cast<T>(m[i * 3 + 0]);
        s1 = static_cast<T>(m[i * 3 + 1]);
        s2 = static_cast<T>(m[i * 3 + 2]);
        SIMPLib::Endian::FromSystemToBig::convert(s0);
        SIMPLib::Endian::FromSystemToBig::convert(s1);
        SIMPLib::Endian::FromSystemToBig::convert(s2);
        fwrite(&s0, sizeof(T), 1, vtkFile);
        fwrite(&s1, sizeof(T), 1, vtkFile);
        fwrite(&s2, sizeof(T), 1, vtkFile);

      }
      else
      {

        ss << m[i * 3 + 0] << " " << m[i * 3 + 1] << " " << m[i * 3 + 2] << " ";

        fprintf(vtkFile, "%s ", ss.toLatin1().data());
        if (i % 25 == 0) { fprintf(vtkFile, "\n"); }
      }
    }
  }
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
int SurfaceMeshToNonconformalVtk::writeCellData(FILE* vtkFile, QMap<int32_t, int32_t>& featureIds)
{
  int err = 0;
  if (NULL == vtkFile)
  {
    return -1;
  }

  DataContainer::Pointer sm = getDataContainerArray()->getDataContainer(m_SurfaceMeshFaceLabelsArrayPath.getDataContainerName());

  // Write the triangle region ids
  TriangleGeom::Pointer triangleGeom = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName())->getGeometryAs<TriangleGeom>();
  int64_t numTriangles = triangleGeom->getNumberOfTris();

  int swapped;

  // This is like a "section header"
  fprintf(vtkFile, "\n");
  fprintf(vtkFile, "CELL_DATA %lld\n", (long long int)(numTriangles * 2));

  int32_t totalCellsWritten = 0;

  // Write the FeatureId Data to the file
  fprintf(vtkFile, "SCALARS FeatureID int 1\n");
  fprintf(vtkFile, "LOOKUP_TABLE default\n");

  // Loop over all the features
  for(QMap<int32_t, int32_t>::iterator featureIter = featureIds.begin(); featureIter != featureIds.end(); ++featureIter)
  {
    int32_t gid = featureIter.key(); // The current Feature Id
    size_t size = featureIter.value(); // The number of triangles for this feature id
    std::vector<int32_t> buffer(size, 0);
    totalCellsWritten += size;

    // Endian Swap our current feature Id since we are going to write it a bunch of times.
    swapped = gid;
    SIMPLib::Endian::FromSystemToBig::convert(swapped);
    size_t index = 0;

    // Loop over all the triangles looking for the current feature id
    // this is probably sub-optimal as if we have 1000 features we are going to loop 1000 times but this will use the
    // least amount of memory. We could run a filter to group the triangles by feature but then we would need an
    // additional amount of memory equal to 3X the memory used for the triangle list because every triangle will be listed
    // twice. We could get some slightly better performance if we buffered 4K worth of data then wrote out that data
    // in one chunk versus what we are doing here.
    for (int j = 0; j < numTriangles; j++)
    {
      if (m_SurfaceMeshFaceLabels[j * 2] == gid || m_SurfaceMeshFaceLabels[j * 2 + 1] == gid)
      {
        if(m_WriteBinaryFile == true)
        {
          buffer[index] = swapped;
          ++index;
        }
        else
        {
          fprintf(vtkFile, "%d\n", gid);
        }
      }
    }
    // Write the Buffer
    if(m_WriteBinaryFile == true)
    {
      fwrite(&(buffer.front()), sizeof(int32_t), size, vtkFile);
    }
  }
#if 0
  // Write the Original Triangle ID Data to the file
  fprintf(vtkFile, "\n");
  fprintf(vtkFile, "SCALARS TriangleID int 1\n");
  fprintf(vtkFile, "LOOKUP_TABLE default\n");
  for(int i = 0; i < triangleCount * 2; ++i)
  {
    //Triangle& t = triangles[i]; // Get the current Node

    if(m_WriteBinaryFile == true)
    {
      swapped = i;
      SIMPLib::Endian::FromSystemToBig::convert(swapped);
      fwrite(&swapped, sizeof(int), 1, vtkFile);
      fwrite(&swapped, sizeof(int), 1, vtkFile);
    }
    else
    {
      fprintf(vtkFile, "%d\n", i);
      fprintf(vtkFile, "%d\n", i);
    }
  }
#endif

  QString attrMatName = m_SurfaceMeshFaceLabelsArrayPath.getAttributeMatrixName();

  notifyStatusMessage(getHumanLabel(), "Writing Face Normals...");
  writeCellNormalData<double>(sm, attrMatName, SIMPL::FaceData::SurfaceMeshFaceNormals,
                              "double", m_WriteBinaryFile, vtkFile, featureIds, m_SurfaceMeshFaceLabels);

  notifyStatusMessage(getHumanLabel(), "Writing Principal Curvature 1");
  writeCellScalarData<double>(sm, attrMatName, SIMPL::FaceData::SurfaceMeshPrincipalCurvature1,
                              "double", m_WriteBinaryFile, vtkFile, featureIds, m_SurfaceMeshFaceLabels);
  notifyStatusMessage(getHumanLabel(), "Writing Principal Curvature 2");
  writeCellScalarData<double>(sm, attrMatName, SIMPL::FaceData::SurfaceMeshPrincipalCurvature2,
                              "double", m_WriteBinaryFile, vtkFile, featureIds, m_SurfaceMeshFaceLabels);

  notifyStatusMessage(getHumanLabel(), "Writing Feature Face Id");
  writeCellScalarData<int32_t>(sm, attrMatName, SIMPL::FaceData::SurfaceMeshFeatureFaceId,
                               "int", m_WriteBinaryFile, vtkFile, featureIds, m_SurfaceMeshFaceLabels);

  notifyStatusMessage(getHumanLabel(), "Writing Gaussian Curvature");
  writeCellScalarData<double>(sm, attrMatName, SIMPL::FaceData::SurfaceMeshGaussianCurvatures,
                              "double", m_WriteBinaryFile, vtkFile, featureIds, m_SurfaceMeshFaceLabels);

  notifyStatusMessage(getHumanLabel(), "Writing Mean Curvature");
  writeCellScalarData<double>(sm, attrMatName, SIMPL::FaceData::SurfaceMeshMeanCurvatures,
                              "double", m_WriteBinaryFile, vtkFile, featureIds, m_SurfaceMeshFaceLabels);
#if 0
  writeCellVectorData<double>(sm, attrMatName, SIMPL::CellData::SurfaceMeshPrincipalDirection1,
                              "double", m_WriteBinaryFile, "VECTORS", vtkFile, nT);

  writeCellVectorData<double>(sm, attrMatName, SIMPL::CellData::SurfaceMeshPrincipalDirection2,
                              "double", m_WriteBinaryFile, "VECTORS", vtkFile, nT);

  writeCellNormalData<double>(sm, attrMatName, "Goldfeather_Triangle_Normals",
                              "double", m_WriteBinaryFile, vtkFile, nT);
#endif

  return err;
}
void writeCellNormalData(DataContainer::Pointer dc, const QString& faceAttributeMatrixName, const QString& dataName, const QString& dataType,
                         bool writeBinaryData, FILE* vtkFile, QMap<int32_t, int32_t>& featureIds, int32_t* m_SurfaceMeshFaceLabels)
{
  TriangleGeom::Pointer triangleGeom = dc->getGeometryAs<TriangleGeom>();

  int64_t numTriangles = triangleGeom->getNumberOfTris();
  IDataArray::Pointer data = dc->getAttributeMatrix(faceAttributeMatrixName)->getAttributeArray(dataName);
  QString buf;
  QTextStream ss(&buf);
  if (NULL != data.get())
  {
    int32_t totalCellsWritten = 0;

    T* m = reinterpret_cast<T*>(data->getVoidPointer(0));
    fprintf(vtkFile, "\n");
    fprintf(vtkFile, "NORMALS %s %s\n", dataName.toLatin1().data(), dataType.toLatin1().data());
    // Loop over all the features
    for(QMap<int32_t, int32_t>::iterator featureIter = featureIds.begin(); featureIter != featureIds.end(); ++featureIter)
    {
      int32_t gid = featureIter.key(); // The current Feature Id
      size_t size = featureIter.value(); // The number of triangles for this feature id
      std::vector<T> buffer(size * 3, 0);
      totalCellsWritten += size * 3;
      size_t index = 0;

      for (int j = 0; j < numTriangles; j++)
      {
        if (m_SurfaceMeshFaceLabels[j * 2] != gid && m_SurfaceMeshFaceLabels[j * 2 + 1] != gid) { continue; }
        // Get the data
        T s0 = static_cast<T>(m[j * 3 + 0]);
        T s1 = static_cast<T>(m[j * 3 + 1]);
        T s2 = static_cast<T>(m[j * 3 + 2]);
        // Flip the normal if needed because the current feature id is assigned to the triangle.labels[1]
        if (m_SurfaceMeshFaceLabels[j * 2 + 1] == gid )
        {
          s0 *= -1.0;
          s1 *= -1.0;
          s2 *= -1.0;
        }
        // Write the values to the buffer after an Endian swap.
        if(writeBinaryData == true)
        {
          SIMPLib::Endian::FromSystemToBig::convert(s0);
          buffer[index] = s0;
          ++index;

          SIMPLib::Endian::FromSystemToBig::convert(s1);
          buffer[index] = s1;
          ++index;

          SIMPLib::Endian::FromSystemToBig::convert(s2);
          buffer[index] = s2;
          ++index;
        }
        else
        {

          ss << s0 << " " << s1 << " " << s2;
          fprintf(vtkFile, "%s\n", buf.toLatin1().data());
          buf.clear();
        }
      }

      // Write the Buffer
      if(writeBinaryData == true)
      {
        fwrite(&(buffer.front()), sizeof(T), size * 3, vtkFile);
      }
    }
  }
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void SurfaceMeshToNonconformalVtk::execute()
{
  int err = 0;
  setErrorCondition(err);

  dataCheck();
  if(getErrorCondition() < 0) { return; }

  DataContainer::Pointer m = getDataContainerArray()->getDataContainer(m_SurfaceMeshFaceLabelsArrayPath.getDataContainerName());

  TriangleGeom::Pointer triangleGeom = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName())->getGeometryAs<TriangleGeom>();
  float* nodes = triangleGeom->getVertexPointer(0);
  int64_t* triangles = triangleGeom->getTriPointer(0);

  qint64 numNodes = triangleGeom->getNumberOfVertices();
  int64_t numTriangles = triangleGeom->getNumberOfTris();

  // Make sure any directory path is also available as the user may have just typed
  // in a path without actually creating the full path
  QFileInfo fi(getOutputVtkFile());
  QDir parentPath = fi.path();
  if(!parentPath.mkpath("."))
  {
    QString ss = QObject::tr("Error creating parent path '%1'").arg(parentPath.absolutePath());
    setErrorCondition(-1);
    notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
    return;
  }

  // Open the output VTK File for writing
  FILE* vtkFile = NULL;
  vtkFile = fopen(getOutputVtkFile().toLatin1().data(), "wb");
  if (NULL == vtkFile)
  {
    QString ss = QObject::tr("Error creating file '%1'").arg(getOutputVtkFile());
    setErrorCondition(-18542);
    notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
    return;
  }
  ScopedFileMonitor vtkFileMonitor(vtkFile);

  notifyStatusMessage(getHumanLabel(), "Writing Vertex Data ....");

  fprintf(vtkFile, "# vtk DataFile Version 2.0\n");
  fprintf(vtkFile, "Data set from DREAM.3D Surface Meshing Module\n");
  if (m_WriteBinaryFile)
  {
    fprintf(vtkFile, "BINARY\n");
  }
  else
  {
    fprintf(vtkFile, "ASCII\n");
  }
  fprintf(vtkFile, "DATASET POLYDATA\n");

  int numberWrittenNodes = 0;
  for (int i = 0; i < numNodes; i++)
  {
    //  Node& n = nodes[i]; // Get the current Node
    if (m_SurfaceMeshNodeType[i] > 0) { ++numberWrittenNodes; }
    else { qDebug() << "Node Type Invalid: " << i << "::" << (int)(m_SurfaceMeshNodeType[i]) ;}
  }

  fprintf(vtkFile, "POINTS %d float\n", numberWrittenNodes);

  float pos[3] = {0.0f, 0.0f, 0.0f};

  size_t totalWritten = 0;

  // Write the POINTS data (Vertex)
  for (int i = 0; i < numNodes; i++)
  {
    if (m_SurfaceMeshNodeType[i] > 0)
    {
      pos[0] = static_cast<float>(nodes[i * 3]);
      pos[1] = static_cast<float>(nodes[i * 3 + 1]);
      pos[2] = static_cast<float>(nodes[i * 3 + 2]);

      if (m_WriteBinaryFile == true)
      {
        SIMPLib::Endian::FromSystemToBig::convert(pos[0]);
        SIMPLib::Endian::FromSystemToBig::convert(pos[1]);
        SIMPLib::Endian::FromSystemToBig::convert(pos[2]);
        totalWritten = fwrite(pos, sizeof(float), 3, vtkFile);
        if(totalWritten != 3) {}
      }
      else
      {
        fprintf(vtkFile, "%f %f %f\n", pos[0], pos[1], pos[2]); // Write the positions to the output file
      }
    }
  }


  // Write the triangle indices into the vtk File
  notifyStatusMessage(getHumanLabel(), "Writing Faces ....");

  int tData[4];

  // Store all the unique Spins
  QMap<int32_t, int32_t> featureTriangleCount;
  for (int i = 0; i < numTriangles; i++)
  {
    if (featureTriangleCount.find(m_SurfaceMeshFaceLabels[i * 2]) == featureTriangleCount.end())
    {
      featureTriangleCount[m_SurfaceMeshFaceLabels[i * 2]] = 1;
    }
    else
    {
      featureTriangleCount[m_SurfaceMeshFaceLabels[i * 2]]++;
    }
    if (featureTriangleCount.find(m_SurfaceMeshFaceLabels[i * 2 + 1]) == featureTriangleCount.end())
    {
      featureTriangleCount[m_SurfaceMeshFaceLabels[i * 2 + 1]] = 1;
    }
    else
    {
      featureTriangleCount[m_SurfaceMeshFaceLabels[i * 2 + 1]]++;
    }
  }

  // Write the POLYGONS
  fprintf(vtkFile, "\nPOLYGONS %lld %lld\n", (long long int)(numTriangles * 2), (long long int)(numTriangles * 2 * 4));

  size_t totalCells = 0;
  // Loop over all the features
  for(QMap<int32_t, int32_t>::iterator featureIter = featureTriangleCount.begin(); featureIter != featureTriangleCount.end(); ++featureIter)
  {
    totalCells += featureIter.value();
  }
  Q_ASSERT(totalCells == (size_t)(numTriangles * 2) );


  // Loop over all the features
  for(QMap<int32_t, int32_t>::iterator featureIter = featureTriangleCount.begin(); featureIter != featureTriangleCount.end(); ++featureIter)
  {
    int32_t gid = featureIter.key(); // The current Feature Id
    int32_t numTriToWrite = featureIter.value(); // The number of triangles for this feature
    uint8_t doWrite = 0;

    // Loop over all the triangles looking for the current feature id
    // this is probably sub-optimal as if we have 1000 features we are going to loop 1000 times but this will use the
    // least amount of memory. We could run a filter to group the triangles by feature but then we would need an
    // additional amount of memory equal to 3X the memory used for the triangle list because every triangle will be listed
    // twice. We could get some slightly better performance if we buffered 4K worth of data then wrote out that data
    // in one chunk versus what we are doing here.
    for (int j = 0; j < numTriangles; j++)
    {
      doWrite = 0;

      if (m_SurfaceMeshFaceLabels[j * 2] == gid ) { doWrite = 1; }
      else if (m_SurfaceMeshFaceLabels[j * 2 + 1] == gid) { doWrite = 2; } // We need to flip the winding of the triangle
      if (doWrite == 0) { continue; } // Labels in the triangle did match the current feature id.

      if (doWrite == 1)
      {
        tData[0] = 3; // Push on the total number of entries for this entry
        tData[1] = triangles[j * 3];
        tData[2] = triangles[j * 3 + 1];
        tData[3] = triangles[j * 3 + 2];
      }
      else
      {
        tData[0] = 3; // Push on the total number of entries for this entry
        tData[1] = triangles[j * 3 + 2];
        tData[2] = triangles[j * 3 + 1];
        tData[3] = triangles[j * 3];
      }
      if (m_WriteBinaryFile == true)
      {

        SIMPLib::Endian::FromSystemToBig::convert(tData[0]);
        SIMPLib::Endian::FromSystemToBig::convert(tData[1]); // Index of Vertex 0
        SIMPLib::Endian::FromSystemToBig::convert(tData[2]); // Index of Vertex 1
        SIMPLib::Endian::FromSystemToBig::convert(tData[3]); // Index of Vertex 2
        fwrite(tData, sizeof(int), 4, vtkFile);
      }
      else
      {
        fprintf(vtkFile, "3 %d %d %d\n", tData[1], tData[2], tData[3]);
      }
      numTriToWrite--;
    }
    if (numTriToWrite != 0)
    {
      qDebug() << "Not enough triangles written: " << gid << "::" << numTriToWrite << " Total Triangles to Write " << featureIter.value();
    }

  }


  // Write the POINT_DATA section
  err = writePointData(vtkFile);

  // Write the CELL_DATA section
  err = writeCellData(vtkFile, featureTriangleCount);


  fprintf(vtkFile, "\n");

  setErrorCondition(0);
  notifyStatusMessage(getHumanLabel(), "Complete");
}
Esempio n. 8
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
int SurfaceMeshToVtk::writeCellData(FILE* vtkFile)
{
  int err = 0;
  if (NULL == vtkFile)
  {
    return -1;
  }

  DataContainer::Pointer sm = getDataContainerArray()->getDataContainer(m_SurfaceMeshFaceLabelsArrayPath.getDataContainerName());

  // Write the triangle region ids
  TriangleGeom::Pointer triangleGeom = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName())->getGeometryAs<TriangleGeom>();

  int64_t nT = triangleGeom->getNumberOfTris();

  int numTriangles = nT;
  int swapped;
  if (false == m_WriteConformalMesh)
  {
    numTriangles = nT * 2;
  }

  // This is like a "section header"
  fprintf(vtkFile, "\n");
  fprintf(vtkFile, "CELL_DATA %d\n", numTriangles);

  // Write the FeatureId Data to the file
  fprintf(vtkFile, "SCALARS FeatureID int 1\n");
  fprintf(vtkFile, "LOOKUP_TABLE default\n");
  for(int i = 0; i < nT; ++i)
  {
    //FaceArray::Face_t& t = triangles[i]; // Get the current Node

    if(m_WriteBinaryFile == true)
    {
      swapped = m_SurfaceMeshFaceLabels[i * 2];
      SIMPLib::Endian::FromSystemToBig::convert(swapped);
      fwrite(&swapped, sizeof(int), 1, vtkFile);
      if(false == m_WriteConformalMesh)
      {
        swapped = m_SurfaceMeshFaceLabels[i * 2 + 1];
        SIMPLib::Endian::FromSystemToBig::convert(swapped);
        fwrite(&swapped, sizeof(int), 1, vtkFile);
      }
    }
    else
    {
      fprintf(vtkFile, "%d\n", m_SurfaceMeshFaceLabels[i * 2]);
      if(false == m_WriteConformalMesh)
      {
        fprintf(vtkFile, "%d\n", m_SurfaceMeshFaceLabels[i * 2 + 1]);
      }
    }

  }

#if 0
  // Write the Original Triangle ID Data to the file
  fprintf(vtkFile, "\n");
  fprintf(vtkFile, "SCALARS TriangleID int 1\n");
  fprintf(vtkFile, "LOOKUP_TABLE default\n");
  for(int i = 0; i < nT; ++i)
  {
    //Triangle& t = triangles[i]; // Get the current Node

    if(m_WriteBinaryFile == true)
    {
      swapped = i;
      SIMPLib::Endian::FromSystemToBig::convert(swapped);
      fwrite(&swapped, sizeof(int), 1, vtkFile);
      if(false == m_WriteConformalMesh)
      {
        fwrite(&swapped, sizeof(int), 1, vtkFile);
      }
    }
    else
    {
      fprintf(vtkFile, "%d\n", i);
      if(false == m_WriteConformalMesh)
      {
        fprintf(vtkFile, "%d\n", i);
      }
    }
  }
#endif

  QString attrMatName = m_SurfaceMeshFaceLabelsArrayPath.getAttributeMatrixName();

  writeCellScalarData<int32_t>(sm, attrMatName, DREAM3D::FaceData::SurfaceMeshFeatureFaceId,
                               "int", m_WriteBinaryFile, m_WriteConformalMesh, vtkFile, nT);

  writeCellScalarData<double>(sm, attrMatName, DREAM3D::FaceData::SurfaceMeshPrincipalCurvature1,
                              "double", m_WriteBinaryFile, m_WriteConformalMesh, vtkFile, nT);

  writeCellScalarData<double>(sm, attrMatName, DREAM3D::FaceData::SurfaceMeshPrincipalCurvature2,
                              "double", m_WriteBinaryFile, m_WriteConformalMesh, vtkFile, nT);

  writeCellVectorData<double>(sm, attrMatName, DREAM3D::FaceData::SurfaceMeshPrincipalDirection1,
                              "double", m_WriteBinaryFile, m_WriteConformalMesh, "VECTORS", vtkFile, nT);

  writeCellVectorData<double>(sm, attrMatName, DREAM3D::FaceData::SurfaceMeshPrincipalDirection2,
                              "double", m_WriteBinaryFile, m_WriteConformalMesh, "VECTORS", vtkFile, nT);

  writeCellScalarData<double>(sm, attrMatName, DREAM3D::FaceData::SurfaceMeshGaussianCurvatures,
                              "double", m_WriteBinaryFile, m_WriteConformalMesh, vtkFile, nT);

  writeCellScalarData<double>(sm, attrMatName, DREAM3D::FaceData::SurfaceMeshMeanCurvatures,
                              "double", m_WriteBinaryFile, m_WriteConformalMesh, vtkFile, nT);

  writeCellNormalData<double>(sm, attrMatName, DREAM3D::FaceData::SurfaceMeshFaceNormals,
                              "double", m_WriteBinaryFile, m_WriteConformalMesh, vtkFile, nT);

  writeCellNormalData<double>(sm, attrMatName, "Goldfeather_Triangle_Normals",
                              "double", m_WriteBinaryFile, m_WriteConformalMesh, vtkFile, nT);

  return err;
}
Esempio n. 9
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void SurfaceMeshToVtk::execute()
{
  int err = 0;
  setErrorCondition(err);
  dataCheck();
  if(getErrorCondition() < 0) { return; }

  setErrorCondition(0);
  DataContainer::Pointer sm = getDataContainerArray()->getDataContainer(m_SurfaceMeshFaceLabelsArrayPath.getDataContainerName());  /* Place all your code to execute your filter here. */
  TriangleGeom::Pointer triangleGeom = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName())->getGeometryAs<TriangleGeom>();
  float* nodes = triangleGeom->getVertexPointer(0);
  int64_t* triangles = triangleGeom->getTriPointer(0);

  qint64 numNodes = triangleGeom->getNumberOfVertices();
  int64_t numTriangles = triangleGeom->getNumberOfTris();

  // Make sure any directory path is also available as the user may have just typed
  // in a path without actually creating the full path
  QFileInfo fi(getOutputVtkFile());
  QDir parentPath = fi.path();

  if(!parentPath.mkpath("."))
  {

    QString ss = QObject::tr("Error creating parent path '%1'").arg(parentPath.absolutePath());
    notifyErrorMessage(getHumanLabel(), ss, -1);
    setErrorCondition(-1);
    return;
  }

  // Open the output VTK File for writing
  FILE* vtkFile = NULL;
  vtkFile = fopen(getOutputVtkFile().toLatin1().data(), "wb");
  if (NULL == vtkFile)
  {

    QString ss = QObject::tr("Error creating file '%1'").arg(getOutputVtkFile());
    notifyErrorMessage(getHumanLabel(), ss, -18542);
    setErrorCondition(-18542);
    return;
  }
  ScopedFileMonitor vtkFileMonitor(vtkFile);

  fprintf(vtkFile, "# vtk DataFile Version 2.0\n");
  fprintf(vtkFile, "Data set from DREAM.3D Surface Meshing Module\n");
  if (m_WriteBinaryFile)
  {
    fprintf(vtkFile, "BINARY\n");
  }
  else
  {
    fprintf(vtkFile, "ASCII\n");
  }
  fprintf(vtkFile, "DATASET POLYDATA\n");

  int numberWrittenumNodes = 0;
  for (int i = 0; i < numNodes; i++)
  {
    //  Node& n = nodes[i]; // Get the current Node
    if (m_SurfaceMeshNodeType[i] > 0) { ++numberWrittenumNodes; }
  }

  fprintf(vtkFile, "POINTS %d float\n", numberWrittenumNodes);

  float pos[3] = {0.0f, 0.0f, 0.0f};

  size_t totalWritten = 0;

  // Write the POINTS data (Vertex)
  for (int i = 0; i < numNodes; i++)
  {
    if (m_SurfaceMeshNodeType[i] > 0)
    {
      pos[0] = static_cast<float>(nodes[i * 3]);
      pos[1] = static_cast<float>(nodes[i * 3 + 1]);
      pos[2] = static_cast<float>(nodes[i * 3 + 2]);

      if (m_WriteBinaryFile == true)
      {
        SIMPLib::Endian::FromSystemToBig::convert(pos[0]);
        SIMPLib::Endian::FromSystemToBig::convert(pos[1]);
        SIMPLib::Endian::FromSystemToBig::convert(pos[2]);
        totalWritten = fwrite(pos, sizeof(float), 3, vtkFile);
        if (totalWritten != sizeof(float) * 3)
        {

        }
      }
      else
      {
        fprintf(vtkFile, "%f %f %f\n", pos[0], pos[1], pos[2]); // Write the positions to the output file
      }
    }
  }

  int tData[4];
  int triangleCount = numTriangles;
  //  int tn1, tn2, tn3;
  if (false == m_WriteConformalMesh)
  {
    triangleCount = numTriangles * 2;
  }
  // Write the POLYGONS
  fprintf(vtkFile, "\nPOLYGONS %d %d\n", triangleCount, (triangleCount * 4));
  for (int j = 0; j < numTriangles; j++)
  {
    //  Triangle& t = triangles[j];
    tData[1] = triangles[j * 3];
    tData[2] = triangles[j * 3 + 1];
    tData[3] = triangles[j * 3 + 2];

    if (m_WriteBinaryFile == true)
    {
      tData[0] = 3; // Push on the total number of entries for this entry
      SIMPLib::Endian::FromSystemToBig::convert(tData[0]);
      SIMPLib::Endian::FromSystemToBig::convert(tData[1]); // Index of Vertex 0
      SIMPLib::Endian::FromSystemToBig::convert(tData[2]); // Index of Vertex 1
      SIMPLib::Endian::FromSystemToBig::convert(tData[3]); // Index of Vertex 2
      fwrite(tData, sizeof(int), 4, vtkFile);
      if (false == m_WriteConformalMesh)
      {
        tData[0] = tData[1];
        tData[1] = tData[3];
        tData[3] = tData[0];
        tData[0] = 3;
        SIMPLib::Endian::FromSystemToBig::convert(tData[0]);
        fwrite(tData, sizeof(int), 4, vtkFile);
      }
    }
    else
    {
      fprintf(vtkFile, "3 %d %d %d\n", tData[1], tData[2], tData[3]);
      if (false == m_WriteConformalMesh)
      {
        fprintf(vtkFile, "3 %d %d %d\n", tData[3], tData[2], tData[1]);
      }
    }
  }

  // Write the POINT_DATA section
  err = writePointData(vtkFile);
  // Write the CELL_DATA section
  err = writeCellData(vtkFile);

  fprintf(vtkFile, "\n");

  setErrorCondition(0);
  notifyStatusMessage(getHumanLabel(), "Complete");
}
Esempio n. 10
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void SharedFeatureFaceFilter::execute()
{
  setErrorCondition(0);
  dataCheck();
  if(getErrorCondition() < 0) { return; }

  DataContainer::Pointer sm = getDataContainerArray()->getDataContainer(m_SurfaceMeshFaceLabelsArrayPath.getDataContainerName());
  AttributeMatrix::Pointer faceFeatureAttrMat = sm->getAttributeMatrix(getFaceFeatureAttributeMatrixName());

  TriangleGeom::Pointer triangleGeom = sm->getGeometryAs<TriangleGeom>();
  int64_t totalPoints = triangleGeom->getNumberOfTris();

  QMap<uint64_t, int32_t> faceSizeMap;
  QMap<uint64_t, int32_t> faceIdMap; // This maps a unique 64 bit integer to an increasing 32 bit integer
  int32_t index = 1;
  struct { int g; int r; } faceId;
  uint64_t* faceId_64 = reinterpret_cast<uint64_t*>(&faceId);
  int32_t fl0 = -1;
  int32_t fl1 = -1;

  std::vector< std::pair<int32_t, int32_t> > faceLabelMap;
  faceLabelMap.push_back( std::pair<int32_t, int32_t>(0, 0) );

  // Loop through all the Triangles and figure out how many triangles we have in each one.
  for (int64_t t = 0; t < totalPoints; ++t)
  {
    fl0 = m_SurfaceMeshFaceLabels[t * 2];
    fl1 = m_SurfaceMeshFaceLabels[t * 2 + 1];
    if (fl0 < fl1)
    {
      faceId.g = fl0;
      faceId.r = fl1;
    }
    else
    {
      faceId.g = fl1;
      faceId.r = fl0;
    }

    QMap<uint64_t, int32_t>::iterator iter = faceSizeMap.find(*faceId_64);
    if (iter == faceSizeMap.end())
    {
      faceSizeMap[*faceId_64] = 1;
      faceIdMap[*faceId_64] = index;
      m_SurfaceMeshFeatureFaceIds[t] = index;
      faceLabelMap.push_back( std::pair<int32_t, int32_t>(faceId.g, faceId.r) );
      ++index;
    }
    else
    {
      iter.value()++;
      m_SurfaceMeshFeatureFaceIds[t] = faceIdMap[*faceId_64];
    }
  }

  // resize + update pointers
  QVector<size_t> tDims(1, index);
  faceFeatureAttrMat->resizeAttributeArrays(tDims);
  m_SurfaceMeshFeatureFaceLabels = m_SurfaceMeshFeatureFaceLabelsPtr.lock()->getPointer(0);
  m_SurfaceMeshFeatureFaceNumTriangles = m_SurfaceMeshFeatureFaceNumTrianglesPtr.lock()->getPointer(0);

  for (int32_t i = 0; i < index; i++)
  {
    // get feature face labels
    m_SurfaceMeshFeatureFaceLabels[2 * i + 0] = faceLabelMap[i].first;
    m_SurfaceMeshFeatureFaceLabels[2 * i + 1] = faceLabelMap[i].second;

    // get feature triangle count
    faceId.g = faceLabelMap[i].first;
    faceId.r = faceLabelMap[i].second;
    m_SurfaceMeshFeatureFaceNumTriangles[i] = faceSizeMap[*faceId_64];
  }

  /* Let the GUI know we are done with this filter */
  notifyStatusMessage(getHumanLabel(), "Complete");
}
Esempio n. 11
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
int32_t AbaqusSurfaceMeshWriter::writeFeatures(FILE* f)
{
  //*Elset, elset=Feature1
  //1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
  int32_t err = 0;

  TriangleGeom::Pointer triangleGeo = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName())->getGeometryAs<TriangleGeom>();

  int64_t nTriangles = triangleGeo->getNumberOfTris();

  // Store all the unique Spins
  std::set<int32_t> uniqueSpins;
  for (int64_t i = 0; i < nTriangles; i++)
  {
    uniqueSpins.insert(m_SurfaceMeshFaceLabels[i * 2]);
    uniqueSpins.insert(m_SurfaceMeshFaceLabels[i * 2 + 1]);
  }

  int32_t spin = 0;

  //Loop over the unique Spins
  for (std::set<int32_t>::iterator spinIter = uniqueSpins.begin(); spinIter != uniqueSpins.end(); ++spinIter )
  {
    spin = *spinIter;
    if (spin < 0) { continue; }

    fprintf(f, "*ELSET, ELSET=Feature%d\n", spin);

    {
      QString ss = QObject::tr("Writing ELSET for Feature Id %1").arg(spin);
      notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
    }

    // Loop over all the triangles for this spin
    int64_t lineCount = 0;
    for (int64_t t = 0; t < nTriangles; ++t)
    {
      if (m_SurfaceMeshFaceLabels[t * 2] != spin && m_SurfaceMeshFaceLabels[t * 2 + 1] != spin)
      {
        continue; // We do not match either spin so move to the next triangle
      }

      // Only print 15 Triangles per line
      if (lineCount == 15)
      {
        fprintf (f, ", %lld\n", (long long int)(t));
        lineCount = 0;
      }
      else if(lineCount == 0) // First value on the line
      {
        fprintf(f, "%lld", (long long int)(t));
        lineCount++;
      }
      else
      {
        fprintf(f, ", %lld", (long long int)(t));
        lineCount++;
      }

    }
    // Make sure we have a new line at the end of the section
    if (lineCount != 0)
    {
      fprintf(f, "\n");
    }
  }
  return err;
}
Esempio n. 12
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void AbaqusSurfaceMeshWriter::execute()
{
  int32_t err = 0;
  setErrorCondition(err);
  dataCheck();
  if(getErrorCondition() < 0) { return; }

  DataContainer::Pointer sm = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName());

  // Make sure any directory path is also available as the user may have just typed
  // in a path without actually creating the full path
  QFileInfo fi(getOutputFile());
  QDir parentPath = fi.path();
  if(!parentPath.mkpath("."))
  {
    QString ss = QObject::tr("Error creating parent path '%1'").arg(parentPath.absolutePath());
    setErrorCondition(-8005);
    notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
    return;
  }

  TriangleGeom::Pointer triangleGeom = sm->getGeometryAs<TriangleGeom>();

  // Store all the unique Spins
  std::set<int32_t> uniqueSpins;
  for (int64_t i = 0; i < triangleGeom->getNumberOfTris(); i++)
  {
    uniqueSpins.insert(m_SurfaceMeshFaceLabels[i * 2]);
    uniqueSpins.insert(m_SurfaceMeshFaceLabels[i * 2 + 1]);
  }

  FILE* f = fopen(m_OutputFile.toLatin1().data(), "wb");
  ScopedFileMonitor fileMonitor(f);

  err = writeHeader(f, triangleGeom->getNumberOfVertices(), triangleGeom->getNumberOfTris(), uniqueSpins.size() - 1);
  if(err < 0)
  {
    QString ss = QObject::tr("Error writing header for file '%1'").arg(m_OutputFile);
    setErrorCondition(-8001);
    notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
    return;
  }
  err = writeNodes(f);
  if(err < 0)
  {
    QString ss = QObject::tr("Error writing nodes for file '%1'").arg(m_OutputFile);
    setErrorCondition(-8002);
    notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
    return;
  }
  err = writeTriangles(f);
  if(err < 0)
  {
    QString ss = QObject::tr("Error writing triangles for file '%1'").arg(m_OutputFile);
    setErrorCondition(-8003);
    notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
    return;
  }
  err = writeFeatures(f);
  if(err < 0)
  {
    QString ss = QObject::tr("Error writing Features for file '%1'").arg(m_OutputFile);
    setErrorCondition(-8004);
    notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
    return;
  }

  notifyStatusMessage(getHumanLabel(), "Complete");
}
Esempio n. 13
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
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];
  }
}
Esempio n. 14
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void WriteTriangleGeometry::execute()
{
  int err = 0;
  setErrorCondition(err);

  dataCheck();
  if(getErrorCondition() < 0) { return; }
  DataContainer::Pointer dataContainer = getDataContainerArray()->getPrereqDataContainer<AbstractFilter>(this, getDataContainerSelection());

  TriangleGeom::Pointer triangleGeom = dataContainer->getGeometryAs<TriangleGeom>();
  QString geometryType = triangleGeom->getGeometryTypeAsString();
  float* nodes = triangleGeom->getVertexPointer(0);
  int64_t* triangles = triangleGeom->getTriPointer(0);

  qint64 numNodes = triangleGeom->getNumberOfVertices();
  qint64 maxNodeId = numNodes - 1;
  int64_t numTriangles = triangleGeom->getNumberOfTris();

  // ++++++++++++++ Write the Nodes File +++++++++++++++++++++++++++++++++++++++++++
  // Make sure any directory path is also available as the user may have just typed
  // in a path without actually creating the full path
  notifyStatusMessage(getHumanLabel(), "Writing Nodes Text File");
  QFileInfo fi(getOutputNodesFile());
  QDir parentPath = fi.path();

  if(!parentPath.mkpath("."))
  {

    QString ss = QObject::tr("Error creating parent path '%1'").arg(parentPath.absolutePath());
    notifyErrorMessage(getHumanLabel(), ss, -1);
    setErrorCondition(-1);
    return;
  }
  FILE* nodesFile = NULL;
  nodesFile = fopen(getOutputNodesFile().toLatin1().data(), "wb");
  if (NULL == nodesFile)
  {
    setErrorCondition(-100);
    notifyErrorMessage(getHumanLabel(), "Error opening Nodes file for writing", -100);
    return;
  }
  fprintf(nodesFile, "# All lines starting with '#' are comments\n");
  fprintf(nodesFile, "# DREAM.3D Nodes file\n");
  fprintf(nodesFile, "# DREAM.3D Version %s\n", SIMPLib::Version::Complete().toLatin1().constData());
  fprintf(nodesFile, "# Node Data is X Y Z space delimited.\n");
  fprintf(nodesFile, "Node Count: %lld\n", numNodes);
  for (int i = 0; i < numNodes; i++)
  {
    fprintf(nodesFile, "%8.5f %8.5f %8.5f\n", nodes[i * 3], nodes[i * 3 + 1], nodes[i * 3 + 2]);
  }
  fclose(nodesFile);

  // ++++++++++++++ Write the Triangles File +++++++++++++++++++++++++++++++++++++++++++
  notifyStatusMessage(getHumanLabel(), "Writing Triangles Text File");
  QFileInfo triFI(getOutputTrianglesFile());
  parentPath = triFI.path();
  if(!parentPath.mkpath("."))
  {

    QString ss = QObject::tr("Error creating parent path '%1'").arg(parentPath.absolutePath());
    notifyErrorMessage(getHumanLabel(), ss, -1);
    setErrorCondition(-1);
    return;
  }
  FILE* triFile = fopen(getOutputTrianglesFile().toLatin1().data(), "wb");
  if (NULL == triFile)
  {
    setErrorCondition(-100);
    notifyErrorMessage(getHumanLabel(), "Error opening Triangles file for writing", -100);
    return;
  }

  fprintf(triFile, "# All lines starting with '#' are comments\n");
  fprintf(triFile, "# DREAM.3D Triangle file\n");
  fprintf(triFile, "# DREAM.3D Version %s\n", SIMPLib::Version::Complete().toLatin1().constData());
  fprintf(triFile, "# Each Triangle consists of 3 Node Ids.\n");
  fprintf(triFile, "# NODE IDs START AT 0.\n");
  fprintf(triFile, "Geometry Type: %s\n", geometryType.toLatin1().constData());
  fprintf(triFile, "Node Count: %lld\n", numNodes);
  fprintf(triFile, "Max Node Id: %lld\n", maxNodeId );
  fprintf(triFile, "Triangle Count: %lld\n", (long long int)(numTriangles));

  int n1, n2, n3;
  for (int64_t j = 0; j < numTriangles; ++j)
  {
    n1 = triangles[j * 3];
    n2 = triangles[j * 3 + 1];
    n3 = triangles[j * 3 + 2];

    fprintf(triFile, "%d %d %d\n",  n1, n2, n3);
  }

  fclose(triFile);

  /* Let the GUI know we are done with this filter */
  notifyStatusMessage(getHumanLabel(), "Complete");
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void FeatureFaceCurvatureFilter::execute()
{
  setErrorCondition(0);
  dataCheck();
  if(getErrorCondition() < 0) { return; }

  DataContainer::Pointer sm = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName());

  // Get our Reference counted Array of Face Structures
  TriangleGeom::Pointer triangleGeom = sm->getGeometryAs<TriangleGeom>();

  // Just to double check we have everything.
  int64_t numTriangles = triangleGeom->getNumberOfTris();

  // Make sure the Face Connectivity is created because the FindNRing algorithm needs this and will
  // assert if the data is NOT in the SurfaceMesh Data Container
  ElementDynamicList::Pointer vertLinks = triangleGeom->getElementsContainingVert();
  if (NULL == vertLinks.get())
  {
    triangleGeom->findElementsContainingVert();
  }

  // get the QMap from the SharedFeatureFaces filter
  SharedFeatureFaces_t sharedFeatureFaces;

  int32_t maxFaceId = 0;
  for (int64_t t = 0; t < numTriangles; ++t)
  {
    if (m_SurfaceMeshFeatureFaceIds[t] > maxFaceId) { maxFaceId = m_SurfaceMeshFeatureFaceIds[t]; }
  }
  std::vector<int32_t> faceSizes(maxFaceId + 1, 0);
  // Loop through all the Triangles and assign each one to a unique Feature Face Id.
  for (int64_t t = 0; t < numTriangles; ++t)
  {
    faceSizes[m_SurfaceMeshFeatureFaceIds[t]]++;
  }

  // Allocate all the vectors that we need
  for (size_t iter = 0; iter < faceSizes.size(); ++iter)
  {
    FaceIds_t v;
    v.reserve(faceSizes[iter]);
    sharedFeatureFaces[iter] = v;
  }

  // Loop through all the Triangles and assign each one to a unique Feature Face Id.
  for(int64_t t = 0; t < numTriangles; ++t)
  {
    sharedFeatureFaces[m_SurfaceMeshFeatureFaceIds[t]].push_back(t);
  }

  m_TotalFeatureFaces = sharedFeatureFaces.size();
  m_CompletedFeatureFaces = 0;

#ifdef SIMPLib_USE_PARALLEL_ALGORITHMS
  tbb::task_scheduler_init init;
  bool doParallel = true;
#endif


#ifdef SIMPLib_USE_PARALLEL_ALGORITHMS
  tbb::task_group* g = new tbb::task_group;
#else

#endif
  // typedef here for conveneince
  typedef SharedFeatureFaces_t::iterator SharedFeatureFaceIterator_t;

  for(SharedFeatureFaceIterator_t iter = sharedFeatureFaces.begin(); iter != sharedFeatureFaces.end(); ++iter)
  {
    QString ss = QObject::tr("Working on Face Id %1/%2").arg((*iter).first).arg(maxFaceId);
    notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);

    FaceIds_t& triangleIds = (*iter).second;
#ifdef SIMPLib_USE_PARALLEL_ALGORITHMS
    if (doParallel == true)
    {
      g->run(CalculateTriangleGroupCurvatures(m_NRing, triangleIds, m_UseNormalsForCurveFitting,
                                              m_SurfaceMeshPrincipalCurvature1sPtr.lock(), m_SurfaceMeshPrincipalCurvature2sPtr.lock(),
                                              m_SurfaceMeshPrincipalDirection1sPtr.lock(), m_SurfaceMeshPrincipalDirection2sPtr.lock(),
                                              m_SurfaceMeshGaussianCurvaturesPtr.lock(), m_SurfaceMeshMeanCurvaturesPtr.lock(), triangleGeom,
                                              m_SurfaceMeshFaceLabelsPtr.lock(),
                                              m_SurfaceMeshFaceNormalsPtr.lock(),
                                              m_SurfaceMeshTriangleCentroidsPtr.lock(),
                                              this ) );
    }
    else
#endif
    {
      CalculateTriangleGroupCurvatures curvature(m_NRing, triangleIds, m_UseNormalsForCurveFitting,
                                                 m_SurfaceMeshPrincipalCurvature1sPtr.lock(), m_SurfaceMeshPrincipalCurvature2sPtr.lock(),
                                                 m_SurfaceMeshPrincipalDirection1sPtr.lock(), m_SurfaceMeshPrincipalDirection2sPtr.lock(),
                                                 m_SurfaceMeshGaussianCurvaturesPtr.lock(), m_SurfaceMeshMeanCurvaturesPtr.lock(), triangleGeom,
                                                 m_SurfaceMeshFaceLabelsPtr.lock(),
                                                 m_SurfaceMeshFaceNormalsPtr.lock(),
                                                 m_SurfaceMeshTriangleCentroidsPtr.lock(),
                                                 this );
      curvature();
    }
  }
  // *********************** END END END END END END  ********************************************************************

#ifdef SIMPLib_USE_PARALLEL_ALGORITHMS
  g->wait(); // Wait for all the threads to complete before moving on.
  delete g;
#endif

  /* Let the GUI know we are done with this filter */
  notifyStatusMessage(getHumanLabel(), "Complete");
}
Esempio n. 16
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void WriteStlFile::execute()
{
  int32_t err = 0;
  setErrorCondition(0);
  dataCheck();
  if(getErrorCondition() < 0) { return; }

  // Make sure any directory path is also available as the user may have just typed
  // in a path without actually creating the full path
  QDir stlDir(getOutputStlDirectory());
  if (!stlDir.mkpath("."))
  {
    QString ss = QObject::tr("Error creating parent path '%1'").arg(getOutputStlDirectory());
    notifyErrorMessage(getHumanLabel(), ss, -1);
    setErrorCondition(-1);
    return;
  }

  TriangleGeom::Pointer triangleGeom = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName())->getGeometryAs<TriangleGeom>();
  float* nodes = triangleGeom->getVertexPointer(0);
  int64_t* triangles = triangleGeom->getTriPointer(0);
  int64_t nTriangles = triangleGeom->getNumberOfTris();

  if (nTriangles > std::numeric_limits<int32_t>::max())
  {
    QString ss = QObject::tr("The number of triangles is %1, but the STL specification only supports triangle counts up to %2").arg(nTriangles).arg(std::numeric_limits<int32_t>::max());
    notifyErrorMessage(getHumanLabel(), ss, -1);
    setErrorCondition(-1);
    return;
  }

  // Store all the unique Spins
  QMap<int32_t, int32_t> uniqueGrainIdtoPhase;
  if (m_GroupByPhase == true)
  {
    for (int64_t i = 0; i < nTriangles; i++)
    {
      uniqueGrainIdtoPhase.insert(m_SurfaceMeshFaceLabels[i * 2], m_SurfaceMeshFacePhases[i * 2]);
      uniqueGrainIdtoPhase.insert(m_SurfaceMeshFaceLabels[i * 2 + 1], m_SurfaceMeshFacePhases[i * 2 + 1]);
    }
  }
  else
  {
    for (int64_t i = 0; i < nTriangles; i++)
    {
      uniqueGrainIdtoPhase.insert(m_SurfaceMeshFaceLabels[i * 2], 0);
      uniqueGrainIdtoPhase.insert(m_SurfaceMeshFaceLabels[i * 2 + 1], 0);
    }
  }

  unsigned char data[50];
  float* normal = (float*)data;
  float* vert1 = (float*)(data + 12);
  float* vert2 = (float*)(data + 24);
  float* vert3 = (float*)(data + 36);
  uint16_t* attrByteCount = (uint16_t*)(data + 48);
  *attrByteCount = 0;

  size_t totalWritten = 0;
  float u[3] = { 0.0f, 0.0f, 0.0f }, w[3] = { 0.0f, 0.0f, 0.0f };
  float length = 0.0f;

  int32_t spin = 0;
  int32_t triCount = 0;

  //Loop over the unique Spins
  for (QMap<int32_t, int32_t>::iterator spinIter = uniqueGrainIdtoPhase.begin(); spinIter != uniqueGrainIdtoPhase.end(); ++spinIter )
  {
    spin = spinIter.key();

    // Generate the output file name
    QString filename = getOutputStlDirectory() + "/" + getOutputStlPrefix();
    if (m_GroupByPhase == true)
    {
      filename = filename + QString("Ensemble_") + QString::number(spinIter.value()) + QString("_");
    }
    filename = filename + QString("Feature_") + QString::number(spin) + ".stl";
    FILE* f = fopen(filename.toLatin1().data(), "wb");
    {
      QString ss = QObject::tr("Writing STL for Feature Id %1").arg(spin);
      notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
    }

    QString header = "DREAM3D Generated For Feature ID " + QString::number(spin);
    if (m_GroupByPhase == true)
    {
      header = header + " Phase " + QString::number(spinIter.value());
    }
    err = writeHeader(f, header, 0);
    if (err < 0)
    {
    }
    triCount = 0; // Reset this to Zero. Increment for every triangle written

    // Loop over all the triangles for this spin
    for (int64_t t = 0; t < nTriangles; ++t)
    {
      // Get the true indices of the 3 nodes
      int64_t nId0 = triangles[t * 3];
      int64_t nId1 = triangles[t * 3 + 1];
      int64_t nId2 = triangles[t * 3 + 2];

      vert1[0] = static_cast<float>(nodes[nId0 * 3]);
      vert1[1] = static_cast<float>(nodes[nId0 * 3 + 1]);
      vert1[2] = static_cast<float>(nodes[nId0 * 3 + 2]);

      if (m_SurfaceMeshFaceLabels[t * 2] == spin)
      {
        //winding = 0; // 0 = Write it using forward spin
      }
      else if (m_SurfaceMeshFaceLabels[t * 2 + 1] == spin)
      {
        //winding = 1; // Write it using backward spin
        // Switch the 2 node indices
        int64_t temp = nId1;
        nId1 = nId2;
        nId2 = temp;
      }
      else
      {
        continue; // We do not match either spin so move to the next triangle
      }

      vert2[0] = static_cast<float>(nodes[nId1 * 3]);
      vert2[1] = static_cast<float>(nodes[nId1 * 3 + 1]);
      vert2[2] = static_cast<float>(nodes[nId1 * 3 + 2]);

      vert3[0] = static_cast<float>(nodes[nId2 * 3]);
      vert3[1] = static_cast<float>(nodes[nId2 * 3 + 1]);
      vert3[2] = static_cast<float>(nodes[nId2 * 3 + 2]);

      // Compute the normal
      u[0] = vert2[0] - vert1[0];
      u[1] = vert2[1] - vert1[1];
      u[2] = vert2[2] - vert1[2];

      w[0] = vert3[0] - vert1[0];
      w[1] = vert3[1] - vert1[1];
      w[2] = vert3[2] - vert1[2];

      normal[0] = u[1] * w[2] - u[2] * w[1];
      normal[1] = u[2] * w[0] - u[0] * w[2];
      normal[2] = u[0] * w[1] - u[1] * w[0];

      length = sqrtf(normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2]);
      normal[0] = normal[0] / length;
      normal[1] = normal[1] / length;
      normal[2] = normal[2] / length;

      totalWritten = fwrite(data, 1, 50, f);
      if (totalWritten != 50)
      {
        QString ss = QObject::tr("Error Writing STL File. Not enough elements written for Feature Id %1. Wrote %2 of 50.").arg(spin).arg(totalWritten);
        notifyErrorMessage(getHumanLabel(), ss, -1201);
      }
      triCount++;
    }
    fclose(f);
    err = writeNumTrianglesToFile(filename, triCount);
  }

  setErrorCondition(0);
  notifyStatusMessage(getHumanLabel(), "Complete");

  return;
}