Example #1
0
    void checkPoints(size_t start, size_t end) const
    {
      float radius = 0.0f;
      float distToBoundary = 0.0f;
      int64_t numPoints = m_Points->getNumberOfVertices();
      FloatArrayType::Pointer llPtr = FloatArrayType::CreateArray(3, "_INTERNAL_USE_ONLY_Lower");
      FloatArrayType::Pointer urPtr = FloatArrayType::CreateArray(3, "_INTERNAL_USE_ONLY_Upper_Right");
      float* ll = llPtr->getPointer(0);
      float* ur = urPtr->getPointer(0);
      float* point = NULL;
      char code = ' ';

      for (size_t iter = start; iter < end; iter++)
      {
        // find bounding box for current feature
        GeometryMath::FindBoundingBoxOfFaces(m_Faces, m_FaceIds->getElementList(iter), ll, ur);
        GeometryMath::FindDistanceBetweenPoints(ll, ur, radius);

        // check points in vertex array to see if they are in the bounding box of the feature
        for (int64_t i = 0; i < numPoints; i++)
        {
          point = m_Points->getVertexPointer(i);
          if (m_PolyIds[i] == 0 && GeometryMath::PointInBox(point, ll, ur) == true)
          {
            code = GeometryMath::PointInPolyhedron(m_Faces, m_FaceIds->getElementList(iter), m_FaceBBs, point, ll, ur, radius, distToBoundary);
            if (code == 'i' || code == 'V' || code == 'E' || code == 'F') { m_PolyIds[i] = iter; }
          }
        }
      }
    }
Example #2
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
IGeometry::Pointer VertexGeom::deepCopy()
{
  VertexGeom::Pointer vertexCopy = VertexGeom::CreateGeometry(getVertices(), getName());

  vertexCopy->setSpatialDimensionality(getSpatialDimensionality());

  return vertexCopy;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void MakeDataContainer::dataCheck()
{
  DataArrayPath tempPath;
  setErrorCondition(0);
  DataContainer::Pointer m = getDataContainerArray()->createNonPrereqDataContainer<AbstractFilter>(this, getDataContainerName());
  if (getErrorCondition() < 0)
  {
    return;
  }
  QVector<size_t> tDims(3, 64);
  AttributeMatrix::Pointer cellAttrMat = m->createNonPrereqAttributeMatrix<AbstractFilter>(this, getCellAttributeMatrixName(), tDims, DREAM3D::AttributeMatrixType::Cell);
  if (getErrorCondition() < 0)
  {
    return;
  }
  //  tDims.resize(1);
  //  tDims[0] = 0;
  //  AttributeMatrix::Pointer cellEnsembleAttrMat = m->createNonPrereqAttributeMatrix<AbstractFilter>(this, getCellEnsembleAttributeMatrixName(), tDims, DREAM3D::AttributeMatrixType::CellEnsemble);
  //  if(getErrorCondition() < 0)
  //  {
  //    return;
  //  }

  QVector<size_t> dims(1, 1);
  m_FeatureIdsPtr = cellAttrMat->createNonPrereqArray<DataArray<int32_t>, AbstractFilter, int32_t>(this,  m_FeatureIdsArrayName, 0, dims); /* Assigns the shared_ptr<> to an instance variable that is a weak_ptr<> */
  if( NULL != m_FeatureIdsPtr.lock().get() ) /* Validate the Weak Pointer wraps a non-NULL pointer to a DataArray<T> object */
  {
    m_FeatureIds = m_FeatureIdsPtr.lock()->getPointer(0);    /* Now assign the raw pointer to data from the DataArray<T> object */
  }

  //ImageGeom::Pointer image = ImageGeom::CreateGeometry("TestImageGeom");
  //image->setResolution(0.1f, 0.2f, 0.3f);
  //image->setOrigin(100.3f, 987.234f, 0.0f);
  //image->setDimensions(64, 64, 64);
  //m->setGeometry(image);

  VertexGeom::Pointer vertices = VertexGeom::CreateGeometry(100, "TestVertexGeom");
  SharedVertexList::Pointer test = vertices->getVertices();
  float* verts = test->getPointer(0);
  for (int64_t i = 0; i < vertices->getNumberOfVertices(); i++)
  {
    verts[3 * i] = float(0.1 + i);
    verts[3 * i + 1] = float(0.2 + i);
    verts[3 * i + 2] = float(0.3 + i);
  }
  m->setGeometry(vertices);

}
Example #4
0
    void checkPoints(size_t start, size_t end) const
    {
      float radius = 0.0f;
      FloatArrayType::Pointer llPtr = FloatArrayType::CreateArray(3, "_INTERNAL_USE_ONLY_Lower_Left");
      FloatArrayType::Pointer urPtr = FloatArrayType::CreateArray(3, "_INTERNAL_USE_ONLY_Upper_Right");
      FloatArrayType::Pointer ll_rotPtr = FloatArrayType::CreateArray(3, "_INTERNAL_USE_ONLY_Lower_Left_Rotated");
      FloatArrayType::Pointer ur_rotPtr = FloatArrayType::CreateArray(3, "_INTERNAL_USE_ONLY_Upper_Right_Rotated");
      float* ll = llPtr->getPointer(0);
      float* ur = urPtr->getPointer(0);
      float* ll_rot = ll_rotPtr->getPointer(0);
      float* ur_rot = ur_rotPtr->getPointer(0);
      float* point = NULL;
      char code = ' ';
      float g[3][3] = { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } };

      for (size_t iter = start; iter < end; iter++)
      {
        Int32Int32DynamicListArray::ElementList& faceIds = m_FaceIds->getElementList(iter);

        FOrientArrayType om(9, 0.0);
        FOrientTransformsType::qu2om(FOrientArrayType(m_AvgQuats[iter]), om);
        om.toGMatrix(g);

        // find bounding box for current feature
        GeometryMath::FindBoundingBoxOfFaces(m_Faces, faceIds, ll, ur);
        GeometryMath::FindBoundingBoxOfRotatedFaces(m_Faces, faceIds, g, ll_rot, ur_rot);
        GeometryMath::FindDistanceBetweenPoints(ll, ur, radius);

        generatePoints(iter, m_Points, m_InFeature, m_AvgQuats, m_LatticeConstants, m_Basis, ll_rot, ur_rot);

        // check points in vertex array to see if they are in the bounding box of the feature
        int64_t numPoints = m_Points[iter]->getNumberOfVertices();
        VertexGeom::Pointer vertArray = m_Points[iter];
        BoolArrayType::Pointer boolArray = m_InFeature[iter];
        for (int64_t i = 0; i < numPoints; i++)
        {
          point = vertArray->getVertexPointer(i);
          if (boolArray->getValue(i) == false)
          {
            code = GeometryMath::PointInPolyhedron(m_Faces, faceIds, m_FaceBBs, point, ll, ur, radius);
            if (code == 'i' || code == 'V' || code == 'E' || code == 'F') { m_InFeature[start]->setValue(i, true); }
          }
        }
      }
    }
Example #5
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void InsertAtoms::assign_points(QVector<VertexGeom::Pointer> points, QVector<BoolArrayType::Pointer> inFeature)
{
  size_t count = 0;
  int32_t numFeatures = points.size();
  for (int32_t i = 0; i < numFeatures; i++)
  {
    int64_t numPoints = points[i]->getNumberOfVertices();
    bool* inside = inFeature[i]->getPointer(0);
    for (int64_t j = 0; j < numPoints; j++)
    {
      if (inside[j] == true) { count++; }
    }
  }

  DataContainer::Pointer v = getDataContainerArray()->getDataContainer(getVertexDataContainerName());
  VertexGeom::Pointer vertices = VertexGeom::CreateGeometry(count, DREAM3D::VertexData::SurfaceMeshNodes);

  AttributeMatrix::Pointer vertexAttrMat = v->getAttributeMatrix(getVertexAttributeMatrixName());
  QVector<size_t> tDims(1, count);
  vertexAttrMat->resizeAttributeArrays(tDims);
  updateVertexInstancePointers();

  count = 0;
  float coords[3] = { 0.0f, 0.0f, 0.0f };
  for (int32_t i = 0; i < numFeatures; i++)
  {
    int64_t numPoints = points[i]->getNumberOfVertices();
    bool* inside = inFeature[i]->getPointer(0);
    for (int64_t j = 0; j < numPoints; j++)
    {
      if (inside[j] == true)
      {
        coords[0] = points[i]->getVertexPointer(j)[0];
        coords[1] = points[i]->getVertexPointer(j)[1];
        coords[2] = points[i]->getVertexPointer(j)[2];
        vertices->setCoords(count, coords);
        m_AtomFeatureLabels[count] = i;
        count++;
      }
    }
  }
  v->setGeometry(vertices);
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void MakeDataContainer::execute()
{
  int err = 0;
  setErrorCondition(err);

  // Run the data check to get references to all of our data arrays initialized to the values stored in memory
  dataCheck();
  if (getErrorCondition() < 0)
  {
    return;
  }

  //ImageGeom::Pointer image = getDataContainerArray()->getDataContainer(getDataContainerName())->getGeometryAs<ImageGeom>();

  //size_t index;
  //size_t iDims[3] = {0, 0, 0};
  //image->getDimensions(iDims);

  //for (size_t z=0;z<image->getZPoints();z++)
  //{
  //  for (size_t y=0;y<image->getYPoints();y++)
  //  {
  //    for (size_t x=0;x<image->getXPoints();x++)
  //    {
  //      index = (z * iDims[0] * iDims[1]) + (y * iDims[0]) + x;
  //      m_FeatureIds[index] = z + x + y;
  //    }
  //  }
  //}

  VertexGeom::Pointer verts = getDataContainerArray()->getDataContainer(getDataContainerName())->getGeometryAs<VertexGeom>();

  for (int64_t i = 0; i < verts->getNumberOfVertices(); i++)
  {
    m_FeatureIds[i] = i;
  }


  /* Let the GUI know we are done with this filter */
  notifyStatusMessage(getHumanLabel(), "Complete");

}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
VertexGeom::Pointer RegularGridSampleSurfaceMesh::generate_points()
{
  VertexGeom::Pointer points = VertexGeom::CreateGeometry((m_XPoints * m_YPoints * m_ZPoints), "_INTERNAL_USE_ONLY_points");

  int64_t count = 0;
  float coords[3] = { 0.0f, 0.0f, 0.0f };
  for (int64_t k = 0; k < m_ZPoints; k++)
  {
    for (int64_t j = 0; j < m_YPoints; j++)
    {
      for (int64_t i = 0; i < m_XPoints; i++)
      {
        coords[0] = (float(i) + 0.5f) * m_Resolution.x + m_Origin.x;
        coords[1] = (float(j) + 0.5f) * m_Resolution.y + m_Origin.y;
        coords[2] = (float(k) + 0.5f) * m_Resolution.z + m_Origin.z;
        points->setCoords(count, coords);
        count++;
      }
    }
  }

  return points;
}
Example #8
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void InsertAtoms::execute()
{
  setErrorCondition(0);
  dataCheck();
  if(getErrorCondition() < 0) { return; }

  // Validate that the selected AvgQuats array has tuples equal to the largest
  // Feature Id; the filter would not crash otherwise, but the user should
  // be notified of unanticipated behavior ; this cannot be done in the dataCheck since
  // we don't have acces to the data yet
  int32_t numFeaturesIn = static_cast<int32_t>(m_AvgQuatsPtr.lock()->getNumberOfTuples());
  bool mismatchedFeatures = true;
  int32_t largestFeature = 0;
  size_t numTuples = m_SurfaceMeshFaceLabelsPtr.lock()->getNumberOfTuples();
  for (size_t i = 0; i < numTuples; i++)
  {
    if (m_SurfaceMeshFaceLabels[2 * i] > largestFeature)
    {
      largestFeature = m_SurfaceMeshFaceLabels[2 * i];
      if (largestFeature >= numFeaturesIn)
      {
        mismatchedFeatures = true;
        break;
      }
    }
    else if (m_SurfaceMeshFaceLabels[2 * i + 1] > largestFeature)
    {
      largestFeature = m_SurfaceMeshFaceLabels[2 * i + 1];
      if (largestFeature >= numFeaturesIn)
      {
        mismatchedFeatures = true;
        break;
      }
    }
  }

  if (mismatchedFeatures == true)
  {
    QString ss = QObject::tr("The number of Features in the AvgQuats array (%1) is larger than the largest Feature Id in the SurfaceMeshFaceLabels array").arg(numFeaturesIn);
    setErrorCondition(-5555);
    notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
    return;
  }

  if (largestFeature != (numFeaturesIn - 1))
  {
    QString ss = QObject::tr("The number of Features in the AvgQuats array (%1) does not match the largest Feature Id in the SurfaceMeshFaceLabels array").arg(numFeaturesIn);
    setErrorCondition(-5555);
    notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
    return;
  }

  FloatVec3_t latticeConstants;
  latticeConstants.x = m_LatticeConstants.x / 10000.0;
  latticeConstants.y = m_LatticeConstants.y / 10000.0;
  latticeConstants.z = m_LatticeConstants.z / 10000.0;

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

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

  // pull down faces
  TriangleGeom::Pointer triangleGeom = sm->getGeometryAs<TriangleGeom>();
  int64_t numFaces = m_SurfaceMeshFaceLabelsPtr.lock()->getNumberOfTuples();

  // create array to hold bounding vertices for each face
  FloatArrayType::Pointer llPtr = FloatArrayType::CreateArray(3, "Lower_Left_Internal_Use_Only");
  FloatArrayType::Pointer urPtr = FloatArrayType::CreateArray(3, "Upper_Right_Internal_Use_Only");
  float* ll = llPtr->getPointer(0);
  float* ur = urPtr->getPointer(0);
  VertexGeom::Pointer faceBBs = VertexGeom::CreateGeometry(2 * numFaces, "faceBBs");

  // walk through faces to see how many features there are
  int32_t g1 = 0, g2 = 0;
  int32_t maxFeatureId = 0;
  for (int64_t i = 0; i < numFaces; i++)
  {
    g1 = m_SurfaceMeshFaceLabels[2 * i];
    g2 = m_SurfaceMeshFaceLabels[2 * i + 1];
    if (g1 > maxFeatureId) { maxFeatureId = g1; }
    if (g2 > maxFeatureId) { maxFeatureId = g2; }
  }

  // add one to account for feature 0
  int32_t numFeatures = maxFeatureId + 1;

  // create a dynamic list array to hold face lists
  Int32Int32DynamicListArray::Pointer faceLists = Int32Int32DynamicListArray::New();
  QVector<int32_t> linkCount(numFeatures, 0);

  // fill out lists with number of references to cells
  typedef boost::shared_array<int32_t> SharedInt32Array_t;
  SharedInt32Array_t linkLocPtr(new int32_t[numFaces]);
  int32_t* linkLoc = linkLocPtr.get();

  ::memset(linkLoc, 0, numFaces * sizeof(int32_t));

  // traverse data to determine number of faces belonging to each feature
  for (int64_t i = 0; i < numFaces; i++)
  {
    g1 = m_SurfaceMeshFaceLabels[2 * i];
    g2 = m_SurfaceMeshFaceLabels[2 * i + 1];
    if (g1 > 0) { linkCount[g1]++; }
    if (g2 > 0) { linkCount[g2]++; }
  }

  // now allocate storage for the faces
  faceLists->allocateLists(linkCount);

  // traverse data again to get the faces belonging to each feature
  for (int64_t i = 0; i < numFaces; i++)
  {
    g1 = m_SurfaceMeshFaceLabels[2 * i];
    g2 = m_SurfaceMeshFaceLabels[2 * i + 1];
    if (g1 > 0) { faceLists->insertCellReference(g1, (linkLoc[g1])++, i); }
    if (g2 > 0) { faceLists->insertCellReference(g2, (linkLoc[g2])++, i); }
    // find bounding box for each face
    GeometryMath::FindBoundingBoxOfFace(triangleGeom, i, ll, ur);
    faceBBs->setCoords(2 * i, ll);
    faceBBs->setCoords(2 * i + 1, ur);
  }

  // generate the list of sampling points fom subclass
  QVector<VertexGeom::Pointer> points(numFeatures);
  QVector<BoolArrayType::Pointer> inFeature(numFeatures);
  for (int32_t i = 0; i < numFeatures; i++)
  {
    points[i] = VertexGeom::CreateGeometry(0, "_INTERNAL_USE_ONLY_points");
    inFeature[i] = BoolArrayType::CreateArray(0, "_INTERNAL_USE_ONLY_inside");
  }

  QuatF* avgQuats = reinterpret_cast<QuatF*>(m_AvgQuats);

#ifdef SIMPLib_USE_PARALLEL_ALGORITHMS
  if (doParallel == true)
  {
    tbb::parallel_for(tbb::blocked_range<size_t>(0, numFeatures),
                      InsertAtomsImpl(triangleGeom, faceLists, faceBBs, avgQuats, latticeConstants, m_Basis, points, inFeature), tbb::auto_partitioner());

  }
  else
#endif
  {
    InsertAtomsImpl serial(triangleGeom, faceLists, faceBBs, avgQuats, latticeConstants, m_Basis, points, inFeature);
    serial.checkPoints(0, numFeatures);
  }

  assign_points(points, inFeature);

  notifyStatusMessage(getHumanLabel(), "Complete");
}
Example #9
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
int DataContainer::readMeshDataFromHDF5(hid_t dcGid, bool preflight)
{
  herr_t err = 0;
  unsigned int geometryType = DREAM3D::GeometryType::UnknownGeometry;

  err = QH5Lite::readScalarAttribute(dcGid, DREAM3D::Geometry::Geometry, DREAM3D::Geometry::GeometryType, geometryType);
  if (err < 0)
  {
    return err;
  }

  hid_t geometryId = H5Gopen(dcGid, DREAM3D::Geometry::Geometry.toLatin1().data(), H5P_DEFAULT);
  if (geometryId < 0)
  {
    return -1;
  }
  HDF5ScopedGroupSentinel gSentinel(&geometryId, false);

  IGeometry::Pointer geomPtr = IGeometry::NullPointer();

  if (NULL == m_Geometry.get())
  {
    switch(geometryType)
    {
      case DREAM3D::GeometryType::ImageGeometry:
      {
        ImageGeom::Pointer image = ImageGeom::New();
        err = image->readGeometryFromHDF5(geometryId, preflight);
        err = GeometryHelpers::GeomIO::ReadMetaDataFromHDF5(dcGid, image);
        setGeometry(image);
        break;
      }
      case DREAM3D::GeometryType::VertexGeometry:
      {
        VertexGeom::Pointer vertices = VertexGeom::New();
        err = vertices->readGeometryFromHDF5(geometryId, preflight);
        err = GeometryHelpers::GeomIO::ReadMetaDataFromHDF5(dcGid, vertices);
        setGeometry(vertices);
        break;
      }
      case DREAM3D::GeometryType::EdgeGeometry:
      {
        EdgeGeom::Pointer edges = EdgeGeom::New();
        err = edges->readGeometryFromHDF5(geometryId, preflight);
        err = GeometryHelpers::GeomIO::ReadMetaDataFromHDF5(dcGid, edges);
        setGeometry(edges);
        break;
      }
      case DREAM3D::GeometryType::TriangleGeometry:
      {
        TriangleGeom::Pointer triangles = TriangleGeom::New();
        err = triangles->readGeometryFromHDF5(geometryId, preflight);
        err = GeometryHelpers::GeomIO::ReadMetaDataFromHDF5(dcGid, triangles);
        setGeometry(triangles);
        break;
      }
      case DREAM3D::GeometryType::QuadGeometry:
      {
        QuadGeom::Pointer quads = QuadGeom::New();
        err = quads->readGeometryFromHDF5(geometryId, preflight);
        err = GeometryHelpers::GeomIO::ReadMetaDataFromHDF5(dcGid, quads);
        setGeometry(quads);
        break;
      }
      case DREAM3D::GeometryType::UnknownGeometry:
        setGeometry(geomPtr);
        break;
      default:
        setGeometry(geomPtr);
        break;
    }
  }

  return err;
}
Example #10
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void SampleSurfaceMesh::execute()
{
  setErrorCondition(0);
  dataCheck();
  if(getErrorCondition() < 0) { return; }

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

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

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

  // pull down faces
  int64_t numFaces = m_SurfaceMeshFaceLabelsPtr.lock()->getNumberOfTuples();

  // create array to hold bounding vertices for each face
  FloatArrayType::Pointer llPtr = FloatArrayType::CreateArray(3, "_INTERNAL_USE_ONLY_Lower_Left");
  FloatArrayType::Pointer urPtr = FloatArrayType::CreateArray(3, "_INTERNAL_USE_ONLY_Upper_Right");
  float* ll = llPtr->getPointer(0);
  float* ur = urPtr->getPointer(0);
  VertexGeom::Pointer faceBBs = VertexGeom::CreateGeometry(2 * numFaces, "_INTERNAL_USE_ONLY_faceBBs");

  // walk through faces to see how many features there are
  int32_t g1 = 0, g2 = 0;
  int32_t maxFeatureId = 0;
  for (int64_t i = 0; i < numFaces; i++)
  {
    g1 = m_SurfaceMeshFaceLabels[2 * i];
    g2 = m_SurfaceMeshFaceLabels[2 * i + 1];
    if (g1 > maxFeatureId) { maxFeatureId = g1; }
    if (g2 > maxFeatureId) { maxFeatureId = g2; }
  }
  // add one to account for feature 0
  int32_t numFeatures = maxFeatureId + 1;

  // create a dynamic list array to hold face lists
  Int32Int32DynamicListArray::Pointer faceLists = Int32Int32DynamicListArray::New();
  std::vector<int32_t> linkCount(numFeatures, 0);

  // fill out lists with number of references to cells
  typedef boost::shared_array<int32_t> SharedInt32Array_t;
  SharedInt32Array_t linkLocPtr(new int32_t[numFaces]);
  int32_t* linkLoc = linkLocPtr.get();

  ::memset(linkLoc, 0, numFaces * sizeof(int32_t));

  // traverse data to determine number of faces belonging to each feature
  for (int64_t i = 0; i < numFaces; i++)
  {
    g1 = m_SurfaceMeshFaceLabels[2 * i];
    g2 = m_SurfaceMeshFaceLabels[2 * i + 1];
    if (g1 > 0) { linkCount[g1]++; }
    if (g2 > 0) { linkCount[g2]++; }
  }

  // now allocate storage for the faces
  faceLists->allocateLists(linkCount);

  // traverse data again to get the faces belonging to each feature
  for (int64_t i = 0; i < numFaces; i++)
  {
    g1 = m_SurfaceMeshFaceLabels[2 * i];
    g2 = m_SurfaceMeshFaceLabels[2 * i + 1];
    if (g1 > 0) { faceLists->insertCellReference(g1, (linkLoc[g1])++, i); }
    if (g2 > 0) { faceLists->insertCellReference(g2, (linkLoc[g2])++, i); }
    // find bounding box for each face
    GeometryMath::FindBoundingBoxOfFace(triangleGeom, i, ll, ur);
    faceBBs->setCoords(2 * i, ll);
    faceBBs->setCoords(2 * i + 1, ur);
  }

  // generate the list of sampling points from subclass
  VertexGeom::Pointer points = generate_points();
  if(getErrorCondition() < 0 || NULL == points.get()) { return; }
  int64_t numPoints = points->getNumberOfVertices();

  // create array to hold which polyhedron (feature) each point falls in
  Int32ArrayType::Pointer iArray = Int32ArrayType::NullPointer();
  iArray = Int32ArrayType::CreateArray(numPoints, "_INTERNAL_USE_ONLY_polyhedronIds");
  iArray->initializeWithZeros();
  int32_t* polyIds = iArray->getPointer(0);

#ifdef SIMPLib_USE_PARALLEL_ALGORITHMS
  if (doParallel == true)
  {
    tbb::parallel_for(tbb::blocked_range<size_t>(0, numFeatures),
                      SampleSurfaceMeshImpl(triangleGeom, faceLists, faceBBs, points, polyIds), tbb::auto_partitioner());
  }
  else
#endif
  {
    SampleSurfaceMeshImpl serial(triangleGeom, faceLists, faceBBs, points, polyIds);
    serial.checkPoints(0, numFeatures);
  }

  assign_points(iArray);

  notifyStatusMessage(getHumanLabel(), "Complete");
}