bool vtkImageDataTest::Run(bool on)
{
	lemon::test<> t;

	vtkImageData* img = MakeImageData(W, H, L);

	int ijk[3] = {1, 1, 1};
	t.is(img->ComputePointId(ijk), vtkIdType(W*H+W+1), "Verify Point Id");
	t.is(img->ComputeCellId(ijk), vtkIdType((W-1)*(H-1)+W), "Verify Cell Id");
	t.is(img->FindPoint(X0+DX/3.0, Y0+DY/3.0, Z0+DZ/3.0), vtkIdType(0), "Verify FindPoint");
	t.is(img->GetActualMemorySize(), 4*2*W*H*L/1024, "Verify ActualMemorySize");
	t.is(img->GetBounds()[0], X0, "GetBounds()[0]");
	t.is(img->GetBounds()[5], Z0+DZ*(L-1), "GetBounds()[1]");
	t.is(img->GetDataDimension(), 3, "GetDataDimension");
	t.ok(img->GetDataReleased()==0, "GetDataReleased");	// "==0" used to remove warning
	t.is(img->GetDimensions()[2], L, "GetDimension");
	t.is(img->GetMaximumNumberOfPieces(), -1, "GetMaximumNumberOfPieces");
	t.is(img->GetOrigin()[0], X0, "GetOrigin");
	t.is(((unsigned long*)img->GetScalarPointer())[W*H*1+W*2+3], (1+2+3)*100, "verify stored data");
	t.is(img->GetScalarSize(), 4, "verify GetScalerSize is 4 byte (long)");
	t.is(img->GetSpacing()[0], DX, "verify get spacing");

	img->Initialize();
	t.is(img->GetDimensions()[0], 0, "dimension is reset after Initialize()");
	img->SetDimensions(W, H, L);
	t.is(img->GetExtent()[1], W-1, "equivalency of SetDimensions and SetExtend()");

	img->Delete();

	vtkImageDataTest test;
//	vtkFilteringTestPipelineTemplate<vtkImageDataTest> pipeline(test);
//	pipeline.StartInteraction();
	return true;
}
template <typename PointT> void 
pcl::visualization::PointCloudColorHandlerRGBCloud<PointT>::getColor (vtkSmartPointer<vtkDataArray> &scalars) const
{
  if (!capable_)
    return;
  
  if (!scalars)
    scalars = vtkSmartPointer<vtkUnsignedCharArray>::New ();
  scalars->SetNumberOfComponents (3);
    
  vtkIdType nr_points = vtkIdType (cloud_->points.size ());
  reinterpret_cast<vtkUnsignedCharArray*>(&(*scalars))->SetNumberOfTuples (nr_points);
  unsigned char* colors = reinterpret_cast<vtkUnsignedCharArray*>(&(*scalars))->GetPointer (0);
    
  // Color every point
  if (nr_points != int (rgb_->points.size ()))
    std::fill (colors, colors + nr_points * 3, static_cast<unsigned char> (0xFF));
  else
    for (vtkIdType cp = 0; cp < nr_points; ++cp)
    {
      int idx = cp * 3;
      colors[idx + 0] = rgb_->points[cp].r;
      colors[idx + 1] = rgb_->points[cp].g;
      colors[idx + 2] = rgb_->points[cp].b;
    }
}
// ----------------------------------------------------------------------------
void ctkVTKChartView::removePlot(vtkPlot* plot)
{
  Q_D(ctkVTKChartView);
  vtkIdType index = this->plotIndex(plot);
  if (index == vtkIdType(-1))
    {
    return;
    }
  d->Chart->RemovePlot(index);
  emit this->plotRemoved(plot);
  this->onChartUpdated();
}
vtkSmartPointer<vtkPolyDataMapper> pointGrid()
{
    /* Creating a poly data object of 10x10x10 points */
    vtkSmartPointer<vtkPolyData> data = vtkPolyData::New();
    size_t width = 5;
    size_t height = 5;
    size_t depth = 5;
    vtkSmartPointer<vtkPoints> vertices = vtkPoints::New();
    for (size_t i = 0; i < width; ++i)
        for (size_t j = 0; j < height; ++j)
            for (size_t k = 0; k < depth; ++k)
                vertices->InsertPoint(i * height * depth + j * depth + k,
                                      i * 10.0, j * 10.0, k * 10.0);
    data->SetPoints(vertices);

    vtkSmartPointer<vtkCellArray> points = vtkCellArray::New();
    for (vtkIdType i = 0; i < vtkIdType(width * height * depth); ++i)
        points->InsertNextCell(1, &i);
    data->SetVerts(points);

    /* Adding the radii of spheres as a point dataset */
    /* Creating the radii array */
    vtkSmartPointer<vtkFloatArray> radii =
        vtkSmartPointer<vtkFloatArray>::New();
    radii->SetName("radii");
    radii->SetNumberOfTuples(width * height * depth);
    for (size_t i = 0; i < width; ++i)
        for (size_t j = 0; j < height; ++j)
            for (size_t k = 0; k < depth; ++k)
            {
                float a = float(i) / (width - 1) - 0.5;
                float b = float(j) / (height - 1) - 0.5;
                float c = float(k) / (depth - 1) - 0.5;
                float radius = 8 - 5 * 2 * sqrt(a * a + b * b + c * c);
                radii->SetTuple(i * height * depth + j * depth + k, &radius);
            }

    data->GetPointData()->AddArray(radii);

    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkPolyDataMapper::New();
    /* Assigning the data object directly to the poly mapper */
    mapper->SetInputDataObject(data);
    mapper->MapDataArrayToVertexAttribute(
        "radiusAttrib", "radii", vtkDataObject::FIELD_ASSOCIATION_POINTS, -1);

    return mapper;
}
Exemple #5
0
inline void randPSurface(vtkPolyData * polydata, std::vector<double> * cumulativeAreas, double totalArea,
                         Eigen::Vector4f& p)
{
  float r = static_cast<float> (uniform_deviate(rand()) * totalArea);

  std::vector<double>::iterator low = std::lower_bound(cumulativeAreas->begin(), cumulativeAreas->end(), r);
  vtkIdType el = vtkIdType(low - cumulativeAreas->begin());

  double A[3], B[3], C[3];
  vtkIdType npts = 0;
  vtkIdType *ptIds = NULL;
  polydata->GetCellPoints(el, npts, ptIds);
  polydata->GetPoint(ptIds[0], A);
  polydata->GetPoint(ptIds[1], B);
  polydata->GetPoint(ptIds[2], C);
  randomPointTriangle(float(A[0]), float(A[1]), float(A[2]), float(B[0]), float(B[1]), float(B[2]), float(C[0]),
                      float(C[1]), float(C[2]), p);
}
Exemple #6
0
bool HexReader::getEdges()
{
    // All line breaks and comments are removed
    // so there is no nice structure
    edgesDict = getEntry("edges",fileContents);

    if(!edgesDict.isEmpty())
    {
        //remove edges( and the terminating )
        edgesDict.replace(QRegExp("edges[\\s,\\n]*\\("),"");
        int index=edgesDict.lastIndexOf(")");
        edgesDict = edgesDict.left(index);
        edgesDict = edgesDict.simplified();

        //each entry starts with the type
        QRegExp typeReg = QRegExp("[a-z]+",Qt::CaseInsensitive);
        while(edgesDict.contains(typeReg)) //while? och capa med right?
        {
            index = edgesDict.indexOf(typeReg);
            QString type=typeReg.cap(0);
            int length = typeReg.matchedLength();
            //nextInd = -1 if there are no more matches
            int nextInd = edgesDict.indexOf(typeReg,index+length);
            //returns the entire string if nextInd=-1
            QString edgeDict=edgesDict.mid(index,nextInd-index);

            //fix edgesDict for next iteration
            if(nextInd > -1)
                edgesDict=edgesDict.mid(nextInd-1);//what I think right(nextInd) should do
            else
                edgesDict="";
            //get vertIds

            QStringList edgeDictList =
                    edgeDict.simplified().split(" ");
            if(edgeDictList.size() < 3) //6?
            {
                badEdgeEntry(edgeDict);
                continue;
            }

            bool ok0,ok1;
            vtkIdType vId0 =
                    vtkIdType(edgeDictList.at(1).toInt(&ok0));
            vtkIdType vId1 =
                    vtkIdType(edgeDictList.at(2).toInt(&ok1));
            vtkIdType eId = findEge(vId0,vId1);
            if(eId < 0)
            {
                badEdgeEntry(edgeDict);
                continue;
            }
            HexEdge *e = HexEdge::SafeDownCast(
                        readEdges->GetItemAsObject(eId));
            if(!(ok0 && ok1))
            {
                badEdgeEntry(edgeDict);
                continue;
            }
            if(type == "line")
            {
                //do nothin'
            }
            else if(type == "arc")
            {
                double pos[3];
                int pInd0 = edgeDict.indexOf("(");
                int pInd1 = edgeDict.indexOf(")");
//                QString foo = edgeDict.mid(pInd0+1,pInd1-1);
                QStringList vertList = edgeDict.mid(pInd0+1,pInd1-pInd0-1)
                        .simplified().split(" ",QString::SkipEmptyParts);
                ok1=true;ok0=true;
                pos[0]=vertList.at(0).toDouble(&ok1);
                ok0=ok0 & ok1;
                pos[1]=vertList.at(1).toDouble(&ok1);
                ok0=ok0 & ok1;
                pos[2]=vertList.at(2).toDouble(&ok1);
                ok0=ok0 & ok1;

                e->setType(HexEdge::ARC);
                e->setControlPoint(0,pos);
                e->redrawedge();
                if(!ok0)
                {
                    badEdgeEntry(edgeDict);
                    continue;
                }

            }
            else
            {
                badEdgeEntry(edgeDict);
                continue;
            }

        }

        return true;
    }
    else
    {
        return false;
    }
}
Exemple #7
0
/* MAIN FUNCTION */
void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]){

  /* ************** Inputs *******************/
  double *v;		// Vertices
  unsigned int *f;	// Faces
  
  /* ************** Others ******************* */
  unsigned int nV, nF, i, j;

  // Initialize vtk variables
  vtkPolyData *surf = vtkPolyData::New();
  vtkPoints *sverts = vtkPoints::New();
  vtkCellArray *sfaces = vtkCellArray::New();

  /* Inputs */
  v = mxGetPr(prhs[0]);
  f = (unsigned int*)mxGetPr(prhs[1]);
  
  nV = mxGetM(prhs[0]);
  nF = mxGetM(prhs[1]);
  
  // Load the point, cell, and data attributes.
  for (i=0; i<nV; i++) sverts->InsertPoint(i,v[i],v[nV+i],v[2*nV+i]);
  for (i=0; i<nF; i++) 
    {
      sfaces->InsertNextCell(3);
      for(j=0;j<3;j++)
	sfaces->InsertCellPoint((vtkIdType(f[j*nF+i]-1)));
    }
	
  // We now assign the pieces to the vtkPolyData.
  surf->SetPoints(sverts);
  surf->SetPolys(sfaces);
  sverts->Delete();
  sfaces->Delete();

vtkPolyDataNormals *pipefinal = vtkPolyDataNormals::New();
pipefinal->SetInput(surf);
pipefinal->ConsistencyOn();
pipefinal->SplittingOff();
pipefinal->NonManifoldTraversalOn();
pipefinal->Update();

  /* ************** Outputs *******************/
  // Field data for output structure
  mxArray *out_verts, *out_faces;
  double *out_vertsptr, *out_facesptr;
  
  // field names for output structure
  const char *field_names[] = {"vertices", "faces"};
  
  /* ************** Others ******************* */
  unsigned int n0,numscalars,numverts,numfaces,count,facecount,nidx;
  double pt[3];
  int dims[2] = {1, 1},vert_field,face_field;

  vtkPoints *pts;
  vtkCellArray *polys;
  vtkIdTypeArray *faces;
  
  // Get hold of vertices and faces
  
  // Vertices
  pts = pipefinal->GetOutput()->GetPoints();
  //pts = surf->GetPoints();
  numverts = pts->GetNumberOfPoints();
  out_verts = mxCreateDoubleMatrix(numverts,3,mxREAL);
  out_vertsptr = mxGetPr(out_verts);
  for(n0=0;n0<numverts;n0++)
    {
      pts->GetPoint(n0,pt);
      out_vertsptr[n0] = pt[0];
      out_vertsptr[numverts+n0] = pt[1];
      out_vertsptr[2*numverts+n0] = pt[2];
    }
  
  // Faces
  polys = pipefinal->GetOutput()->GetPolys();
  //polys = surf->GetPolys();
  faces = (vtkIdTypeArray*)polys->GetData();
  
  numfaces = polys->GetNumberOfCells();
  out_faces = mxCreateDoubleMatrix(numfaces,3,mxREAL);
  out_facesptr = mxGetPr(out_faces);
  
  count = 0;
  facecount = 0;
  nidx = 0;
  while(facecount<numfaces)
    {
      nidx = faces->GetValue(count++);
      for(n0=0;n0<nidx;n0++)
	if (n0<3)
	  // Add one to the output as faces are indexed by 0..(n-1)
	  out_facesptr[n0*numfaces+facecount] = faces->GetValue(count++)+1;
	else
	  // Print warning if face contains more than 3 vertices (non-triangular)
	  mexPrintf("Warning: Face[%d] has more than 3 vertices[%d].\n",facecount+1,count++);
      facecount++;
    }
  
  // Create the output structure
  plhs[0] = mxCreateStructArray(2, dims, 2, field_names);
  vert_field = mxGetFieldNumber(plhs[0],"vertices");
  face_field = mxGetFieldNumber(plhs[0],"faces");
  mxSetFieldByNumber(plhs[0],0,vert_field,out_verts);
  mxSetFieldByNumber(plhs[0],0,face_field,out_faces);

surf->Delete();
pipefinal->Delete();
}
    /**
    Create the vtkStructuredGrid from the provided workspace
    @param progressUpdating: Reporting object to pass progress information up the stack.
    @return fully constructed vtkDataSet.
    */
    vtkDataSet* vtkMDQuadFactory::create(ProgressAction& progressUpdating) const
    {
      vtkDataSet* product = tryDelegatingCreation<IMDEventWorkspace, 2>(m_workspace, progressUpdating);
      if(product != NULL)
      {
        return product;
      }
      else
      {
        IMDEventWorkspace_sptr imdws = this->castAndCheck<IMDEventWorkspace, 2>(m_workspace);
        // Acquire a scoped read-only lock to the workspace (prevent segfault from algos modifying ws)
        Mantid::Kernel::ReadLock lock(*imdws);

        const size_t nDims = imdws->getNumDims();
        size_t nNonIntegrated = imdws->getNonIntegratedDimensions().size();

        /*
        Write mask array with correct order for each internal dimension.
        */
        bool* masks = new bool[nDims];
        for(size_t i_dim = 0; i_dim < nDims; ++i_dim)
        {
          bool bIntegrated = imdws->getDimension(i_dim)->getIsIntegrated();
          masks[i_dim] = !bIntegrated; //TRUE for unmaksed, integrated dimensions are masked.
        }

        //Ensure destruction in any event.
        boost::scoped_ptr<IMDIterator> it(imdws->createIterator());

        // Create 4 points per box.
        vtkPoints *points = vtkPoints::New();
        points->SetNumberOfPoints(it->getDataSize() * 4);

        // One scalar per box
        vtkFloatArray * signals = vtkFloatArray::New();
        signals->Allocate(it->getDataSize());
        signals->SetName(m_scalarName.c_str());
        signals->SetNumberOfComponents(1);

        size_t nVertexes;

        vtkUnstructuredGrid *visualDataSet = vtkUnstructuredGrid::New();
        visualDataSet->Allocate(it->getDataSize());

        vtkIdList * quadPointList = vtkIdList::New();
        quadPointList->SetNumberOfIds(4);

        Mantid::API::CoordTransform* transform = NULL;
        if (m_useTransform)
        {
          transform = imdws->getTransformToOriginal();
        }

        Mantid::coord_t out[2];
        bool* useBox = new bool[it->getDataSize()];

        double progressFactor = 0.5/double(it->getDataSize());
        double progressOffset = 0.5;

        size_t iBox = 0;
        do
        {
          progressUpdating.eventRaised(progressFactor * double(iBox));

          Mantid::signal_t signal_normalized= it->getNormalizedSignal();
          if (!isSpecial( signal_normalized ) && m_thresholdRange->inRange(signal_normalized))
          {
            useBox[iBox] = true;
            signals->InsertNextValue(static_cast<float>(signal_normalized));

            coord_t* coords = it->getVertexesArray(nVertexes, nNonIntegrated, masks);
            delete [] coords;
            coords = it->getVertexesArray(nVertexes, nNonIntegrated, masks);

            //Iterate through all coordinates. Candidate for speed improvement.
            for(size_t v = 0; v < nVertexes; ++v)
            {
              coord_t * coord = coords + v*2;
              size_t id = iBox*4 + v;
              if(m_useTransform)
              {
                transform->apply(coord, out);
                points->SetPoint(id, out[0], out[1], 0);
              }
              else
              {
                points->SetPoint(id, coord[0], coord[1], 0);
              }
            }
            // Free memory
            delete [] coords;
          } // valid number of vertexes returned
          else
          {
            useBox[iBox] = false;
          }
          ++iBox;
        } while (it->next());

        delete[] masks;
        for(size_t ii = 0; ii < it->getDataSize() ; ++ii)
        {
          progressUpdating.eventRaised((progressFactor * double(ii)) + progressOffset);

          if (useBox[ii] == true)
          {
            vtkIdType pointIds = vtkIdType(ii * 4);

            quadPointList->SetId(0, pointIds + 0); //xyx
            quadPointList->SetId(1, pointIds + 1); //dxyz
            quadPointList->SetId(2, pointIds + 3); //dxdyz
            quadPointList->SetId(3, pointIds + 2); //xdyz
            visualDataSet->InsertNextCell(VTK_QUAD, quadPointList);
          } // valid number of vertexes returned
        }

        delete[] useBox;

        signals->Squeeze();
        points->Squeeze();

        visualDataSet->SetPoints(points);
        visualDataSet->GetCellData()->SetScalars(signals);
        visualDataSet->Squeeze();

        signals->Delete();
        points->Delete();
        quadPointList->Delete();

        return visualDataSet;
      }
    }
Exemple #9
0
/**
Create the vtkStructuredGrid from the provided workspace
@param progressUpdating: Reporting object to pass progress information up the
stack.
@return fully constructed vtkDataSet.
*/
vtkSmartPointer<vtkDataSet>
vtkMDQuadFactory::create(ProgressAction &progressUpdating) const {
  auto product = tryDelegatingCreation<IMDEventWorkspace, 2>(m_workspace,
                                                             progressUpdating);
  if (product != nullptr) {
    return product;
  } else {
    g_log.warning() << "Factory " << this->getFactoryTypeName()
                    << " is being used. You are viewing data with less than "
                       "three dimensions in the VSI. \n";

    IMDEventWorkspace_sptr imdws =
        this->castAndCheck<IMDEventWorkspace, 2>(m_workspace);
    // Acquire a scoped read-only lock to the workspace (prevent segfault from
    // algos modifying ws)
    Mantid::Kernel::ReadLock lock(*imdws);

    const size_t nDims = imdws->getNumDims();
    size_t nNonIntegrated = imdws->getNonIntegratedDimensions().size();

    /*
    Write mask array with correct order for each internal dimension.
    */
    auto masks = Mantid::Kernel::make_unique<bool[]>(nDims);
    for (size_t i_dim = 0; i_dim < nDims; ++i_dim) {
      bool bIntegrated = imdws->getDimension(i_dim)->getIsIntegrated();
      masks[i_dim] =
          !bIntegrated; // TRUE for unmaksed, integrated dimensions are masked.
    }

    // Make iterator, which will use the desired normalization. Ensure
    // destruction in any eventuality.
    boost::scoped_ptr<IMDIterator> it(
        createIteratorWithNormalization(m_normalizationOption, imdws.get()));

    // Create 4 points per box.
    vtkNew<vtkPoints> points;
    points->SetNumberOfPoints(it->getDataSize() * 4);

    // One scalar per box
    vtkNew<vtkFloatArray> signals;
    signals->Allocate(it->getDataSize());
    signals->SetName(vtkDataSetFactory::ScalarName.c_str());
    signals->SetNumberOfComponents(1);

    size_t nVertexes;

    auto visualDataSet = vtkSmartPointer<vtkUnstructuredGrid>::New();
    visualDataSet->Allocate(it->getDataSize());

    vtkNew<vtkIdList> quadPointList;
    quadPointList->SetNumberOfIds(4);

    Mantid::API::CoordTransform const *transform = NULL;
    if (m_useTransform) {
      transform = imdws->getTransformToOriginal();
    }

    Mantid::coord_t out[2];
    auto useBox = std::vector<bool>(it->getDataSize());

    double progressFactor = 0.5 / double(it->getDataSize());
    double progressOffset = 0.5;

    size_t iBox = 0;
    do {
      progressUpdating.eventRaised(progressFactor * double(iBox));

      Mantid::signal_t signal = it->getNormalizedSignal();
      if (std::isfinite(signal) && m_thresholdRange->inRange(signal)) {
        useBox[iBox] = true;
        signals->InsertNextValue(static_cast<float>(signal));

        auto coords = std::unique_ptr<coord_t[]>(
            it->getVertexesArray(nVertexes, nNonIntegrated, masks.get()));

        // Iterate through all coordinates. Candidate for speed improvement.
        for (size_t v = 0; v < nVertexes; ++v) {
          coord_t *coord = coords.get() + v * 2;
          size_t id = iBox * 4 + v;
          if (m_useTransform) {
            transform->apply(coord, out);
            points->SetPoint(id, out[0], out[1], 0);
          } else {
            points->SetPoint(id, coord[0], coord[1], 0);
          }
        }
      } // valid number of vertexes returned
      else {
        useBox[iBox] = false;
      }
      ++iBox;
    } while (it->next());

    for (size_t ii = 0; ii < it->getDataSize(); ++ii) {
      progressUpdating.eventRaised((progressFactor * double(ii)) +
                                   progressOffset);

      if (useBox[ii] == true) {
        vtkIdType pointIds = vtkIdType(ii * 4);

        quadPointList->SetId(0, pointIds + 0); // xyx
        quadPointList->SetId(1, pointIds + 1); // dxyz
        quadPointList->SetId(2, pointIds + 3); // dxdyz
        quadPointList->SetId(3, pointIds + 2); // xdyz
        visualDataSet->InsertNextCell(VTK_QUAD, quadPointList.GetPointer());
      } // valid number of vertexes returned
    }

    signals->Squeeze();
    points->Squeeze();

    visualDataSet->SetPoints(points.GetPointer());
    visualDataSet->GetCellData()->SetScalars(signals.GetPointer());
    visualDataSet->Squeeze();

    // Hedge against empty data sets
    if (visualDataSet->GetNumberOfPoints() <= 0) {
      vtkNullUnstructuredGrid nullGrid;
      visualDataSet = nullGrid.createNullData();
    }

    vtkSmartPointer<vtkDataSet> dataSet = visualDataSet;
    return dataSet;
  }
}
Exemple #10
0
void mexFunction(int nlhs,       mxArray *plhs[],
				 int nrhs, const mxArray *prhs[])
{
	/* ************** Inputs *******************/
	double *v;			// Vertices
	unsigned int *f;	// Faces
	double	factor1,factor2;	// Parameters: Reduction Factor
	int		interact;	// whether or not to interact

	/* ************** Outputs *******************/
	// Field data for output structure
	mxArray *out_verts, *out_faces;
	double *out_vertsptr, *out_facesptr;

	// field names for output structure
	const char *field_names[] = {"vertices", "faces"};


	/* ************** Others ******************* */
	unsigned int nV, nF, i, j;
	unsigned int n0,numscalars,numverts,numfaces,count,facecount,nidx;
	double pt[3];
    int dims[2] = {1, 1},vert_field,face_field;

	// Initialize vtk variables
	vtkPolyData *surf = vtkPolyData::New();
	vtkPoints *sverts = vtkPoints::New();
	vtkCellArray *sfaces = vtkCellArray::New();
	vtkSmoothPolyDataFilter *smoother = vtkSmoothPolyDataFilter::New();
	//vtkDecimate	*decimate = vtkDecimate::New();
	vtkDecimatePro	*decimate = vtkDecimatePro::New();
	vtkPolyDataConnectivityFilter *connector = vtkPolyDataConnectivityFilter::New();

	vtkPoints *pts;
	vtkCellArray *polys;
	vtkIdTypeArray *faces;

	/* Inputs */
	v = mxGetPr(prhs[0]);
	f = (unsigned int*)mxGetPr(prhs[1]);
	factor1 = *mxGetPr(prhs[2]);
	factor2 = *mxGetPr(prhs[3]);


	nV = mxGetM(prhs[0]);
	nF = mxGetM(prhs[1]);

	if (nrhs==5)
		interact = (int)(*mxGetPr(prhs[4]));
	else
		interact = 0;
	
	// Load the point, cell, and data attributes.
	for (i=0; i<nV; i++) sverts->InsertPoint(i,v[i],v[nV+i],v[2*nV+i]);
	for (i=0; i<nF; i++) 
	{
		sfaces->InsertNextCell(3);
		for(j=0;j<3;j++)
			sfaces->InsertCellPoint((vtkIdType(f[j*nF+i]-1)));
	}
	
	// We now assign the pieces to the vtkPolyData.
	surf->SetPoints(sverts);
	sverts->Delete();
	surf->SetPolys(sfaces);
	sfaces->Delete();
	
	// decimate the mesh
	//decimate->SetInput(skinExtractor->GetOutput());
	decimate->SetInput(surf);

	decimate->SetPreserveTopology(int(factor2));
	decimate->SetTargetReduction(factor1);
	//decimate->SetMaximumCost(factor1);
	//decimate->SetMaximumCollapsedEdges(int(factor2));
	//decimate->SetInitialFeatureAngle(45);
	//decimate->SetMaximumIterations(20);
	//decimate->SetMaximumSubIterations(2);
	//decimate->PreserveEdgesOn();
	//decimate->SetInitialError(.0002);
	//decimate->SetErrorIncrement(.0005);

	// smooth the mesh
	smoother->SetInput(decimate->GetOutput());
	smoother->SetNumberOfIterations(10);
	smoother->SetRelaxationFactor(0.1);
	smoother->SetFeatureAngle(60);
	smoother->FeatureEdgeSmoothingOff();
	smoother->BoundarySmoothingOff();
	smoother->SetConvergence(0);

	//extract largest connected region to get a manifold surface
	connector->SetInput(smoother->GetOutput());
	connector->SetExtractionModeToLargestRegion();
	connector->Update();


	// Get hold of vertices and faces
	
	// Vertices
	pts = connector->GetOutput()->GetPoints();
	//pts = surf->GetPoints();
	numverts = pts->GetNumberOfPoints();
	out_verts = mxCreateDoubleMatrix(numverts,3,mxREAL);
	out_vertsptr = mxGetPr(out_verts);
	for(n0=0;n0<numverts;n0++)
	{
		pts->GetPoint(n0,pt);
		out_vertsptr[n0] = pt[0];
		out_vertsptr[numverts+n0] = pt[1];
		out_vertsptr[2*numverts+n0] = pt[2];
	}

	// Faces
	polys = connector->GetOutput()->GetPolys();
	//polys = surf->GetPolys();
	faces = (vtkIdTypeArray*)polys->GetData();

	numfaces = polys->GetNumberOfCells();
	out_faces = mxCreateDoubleMatrix(numfaces,3,mxREAL);
	out_facesptr = mxGetPr(out_faces);

	count = 0;
	facecount = 0;
	nidx = 0;
	while(facecount<numfaces)
	{
		nidx = faces->GetValue(count++);
		for(n0=0;n0<nidx;n0++)
			if (n0<3)
				// Add one to the output as faces are indexed by 0..(n-1)
				out_facesptr[n0*numfaces+facecount] = faces->GetValue(count++)+1;
			else
				// Print warning if face contains more than 3 vertices (non-triangular)
				mexPrintf("Warning: Face[%d] has more than 3 vertices[%d].\n",facecount+1,count++);
		facecount++;
	}

	// Create the output structure
	plhs[0] = mxCreateStructArray(2, dims, NUMBER_OF_FIELDS, field_names);
    vert_field = mxGetFieldNumber(plhs[0],"vertices");
    face_field = mxGetFieldNumber(plhs[0],"faces");
	mxSetFieldByNumber(plhs[0],0,vert_field,out_verts);
	mxSetFieldByNumber(plhs[0],0,face_field,out_faces);


	// Clean up. Delete all vtk objects
	surf->Delete();
	decimate->Delete();
	smoother->Delete();
	connector->Delete();
}