[vtkusers] margin around polydata (expansion/extrusion)

gregthom gregthom99 at yahoo.com
Wed Jul 22 09:04:07 EDT 2009


Hello fellow vtk users

I hvae been trying to implement a class to take polydata and expand it in x
y z directions by a given amount, sort of extrusion.
I found this reference :http://www.mlahanas.de/CompGeom/Margins.htm

Has anybody implemented this somewhere ? Is there another means of achieving
the same purpose ? 
In my implementation from the above reference, I get a translation of my
polydata instead of and expansion/extrusion, Can someone take a look with me
?

Thank you:

Some code to work on:

/*=========================================================================
 
 
     PURPOSE.  Expands Polydata with given margins
 
=========================================================================*/
#ifndef __vtkPolyDataMargin_h
#define __vtkPolyDataMargin_h

#include "vtkPolyDataAlgorithm.h"
#include "vtkPolyData.h"
#include "vtkDoubleArray.h"

class vtkPolyData;
class vtkPoints;
class vtkThinPlateSplineTransform;
class vtkTransformPolyDataFilter;
class vtkGeneralTransform;
class vtkDoubleArray;

class vtkPolyDataMargin : public vtkPolyDataAlgorithm
{
    public:
        vtkTypeRevisionMacro(vtkPolyDataMargin,vtkPolyDataAlgorithm);
        void PrintSelf(ostream& os, vtkIndent indent);
        
        static vtkPolyDataMargin *New();
        
               
        // Description:
        // Set/Get the reference surface to compute distance from.
        //see -> why ?
http://www.vtk.org/pipermail/vtk-developers/2002-May/001464.html
        vtkSetObjectMacro(Margins,vtkDoubleArray);
        vtkGetObjectMacro(Margins,vtkDoubleArray);
        
        protected:
            vtkPolyDataMargin();
            ~vtkPolyDataMargin();
            
            virtual int RequestData(vtkInformation *, vtkInformationVector
**, vtkInformationVector *);
            
            
            vtkPolyData *m_Input;
            
            vtkDoubleArray *Margins;
            
            //Object to be deformed
            //vtkPolyData *Input;
            //Spline transformation source points
            vtkPoints *m_SourcePoints;
            //Spline transformation target points
            vtkPoints *m_TargetPoints;
            //The Spline transformation source points
            vtkThinPlateSplineTransform * m_ThinPlateTransform;
            //The transformation used to rescale PTV points
            vtkGeneralTransform * m_GeneralTransform;
            //VTK class to perform transformation of PTV points
            vtkTransformPolyDataFilter * m_TransformFilter;
            //Set PTV input
            //void SetInput(vtkPolyData * I);
            
            //Constructor of objects and possible user interface
            //void FormCreate();
            //Deform object according to specified margins
            
            
            private:
                vtkPolyDataMargin(const vtkPolyDataMargin&);  // Not
implemented.
                void operator=(const vtkPolyDataMargin&);  // Not
implemented.
};

#endif








/*=========================================================================
 
 
     PURPOSE.  See the above copyright notices for more information.
 
=========================================================================*/

#include "vtkPolyDataMargin.h"

#include "vtkCellLocator.h"

#include "vtkGenericCell.h"
#include "vtkPolyData.h"
#include "vtkPointData.h"
#include "vtkMath.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"


#include "vtkPoints.h"
#include "vtkThinPlateSplineTransform.h"
#include "vtkTransformPolyDataFilter.h"
#include "vtkGeneralTransform.h"
#include "vtkDoubleArray.h"


vtkCxxRevisionMacro(vtkPolyDataMargin, "$Revision: 1.3 $");
vtkStandardNewMacro(vtkPolyDataMargin);

vtkPolyDataMargin::vtkPolyDataMargin()
{   
    this->m_SourcePoints = NULL;
    this->m_TargetPoints = NULL;
    this->m_ThinPlateTransform = NULL;
    this->m_GeneralTransform = NULL;
    this->m_TransformFilter = NULL;
    this->m_Input = NULL;
    
    // initialize margins to zeros;
    // margins are given as:
    //(xm, xp) for the lower and upper x range 
    //(ym, yp) for the lower and upper y range 
    //(zm, zp) for the lower and upper z range
    this->Margins = vtkDoubleArray::New();
    this->Margins->SetNumberOfComponents(1);
    this->Margins->SetNumberOfTuples(6);
    this->Margins->FillComponent(0,0.0);    
    
    this->m_SourcePoints = vtkPoints::New();
    this->m_TargetPoints = vtkPoints::New();
    this->m_GeneralTransform = vtkGeneralTransform::New();
    this->m_TransformFilter = vtkTransformPolyDataFilter::New();
    this->m_ThinPlateTransform = vtkThinPlateSplineTransform::New(); 
    
    
}


vtkPolyDataMargin::~vtkPolyDataMargin()
{
    if (this->m_SourcePoints)
    {
        this->m_SourcePoints->Delete();
        this->m_SourcePoints = NULL;        
    }
    
    if (this->m_TargetPoints)
    {
        this->m_TargetPoints->Delete();
        this->m_TargetPoints = NULL;        
    }
    
    if (this->m_ThinPlateTransform)
    {
        this->m_ThinPlateTransform->Delete();
        this->m_ThinPlateTransform = NULL;        
    }
    
    if (this->m_GeneralTransform)
    {
        this->m_GeneralTransform->Delete();
        this->m_GeneralTransform = NULL;        
    }

    if (this->m_TransformFilter)
    {
        this->m_TransformFilter->Delete();
        this->m_TransformFilter = NULL;        
    }

    
    if (this->Margins)
    {
        this->Margins->Delete();
        this->Margins = NULL;  
    }
    
    //if (this->m_Input)
    //{
    //    this->m_Input->Delete();
    //    this->m_Input = NULL;  
    //}
 
}




int vtkPolyDataMargin::RequestData(vtkInformation
*vtkNotUsed(request),vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
    
    vtkInformation *inInfo  = inputVector[0]->GetInformationObject(0);
    vtkInformation *outInfo = outputVector->GetInformationObject(0);
    
    vtkPolyData *input  =
vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
    vtkPolyData *output =
vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
    
        
    //Returns bounding box in the form (xmin, xmax, ymin, ymax, zmin, zmax)
= (b[0], b[1], b[2], b[3], b[4], b[5])
    double b[6]; 
    input->GetBounds(b);
    
    //Take Source Points of bounding box
   
    this->m_SourcePoints->SetNumberOfPoints( 8 );
    this->m_SourcePoints->SetPoint( 0, b[0], b[3], b[5] );
    this->m_SourcePoints->SetPoint( 1, b[1], b[3], b[5] );
    this->m_SourcePoints->SetPoint( 2, b[0], b[3], b[4] );
    this->m_SourcePoints->SetPoint( 3, b[1], b[3], b[4] );
    this->m_SourcePoints->SetPoint( 4, b[0], b[2], b[5] );
    this->m_SourcePoints->SetPoint( 5, b[1], b[2], b[5] );
    this->m_SourcePoints->SetPoint( 6, b[0], b[2], b[4] );
    this->m_SourcePoints->SetPoint( 7, b[1], b[2], b[4] );
    
    // margins are given as:
    //(xm, xp) for the lower and upper x range 
    //(ym, yp) for the lower and upper y range 
    //(zm, zp) for the lower and upper z range 
    unsigned int nc = this->Margins->GetNumberOfComponents();
    unsigned int nt = this->Margins->GetNumberOfTuples();
    
    double xm = this->Margins->GetTuple1(0);
    double xp = this->Margins->GetTuple1(1);
    double ym = this->Margins->GetTuple1(2);
    double yp = this->Margins->GetTuple1(3);
    double zm = this->Margins->GetTuple1(4);
    double zp = this->Margins->GetTuple1(5);
    
    
    
    //Give Coordinates of expanded bounding box
    
    this->m_TargetPoints->SetNumberOfPoints( 8 );
    this->m_TargetPoints->SetPoint( 0, b[0]+xm, b[3]+yp, b[5]+zp );
    this->m_TargetPoints->SetPoint( 1, b[1]+xp, b[3]+yp, b[5]+zp );
    this->m_TargetPoints->SetPoint( 2, b[0]+xm, b[3]+yp, b[4]+zm );
    this->m_TargetPoints->SetPoint( 3, b[1]+xp, b[3]+yp, b[4]+zm );
    this->m_TargetPoints->SetPoint( 4, b[0]+xm, b[2]+ym, b[5]+zp );
    this->m_TargetPoints->SetPoint( 5, b[1]+xp, b[2]+ym, b[5]+zp );
    this->m_TargetPoints->SetPoint( 6, b[0]+xm, b[2]+ym, b[4]+zm );
    this->m_TargetPoints->SetPoint( 7, b[1]+xp, b[2]+ym, b[4]+zm );
    
   
	//this->m_Input->DeepCopy(input);
	
	   
	this->m_ThinPlateTransform->SetSourceLandmarks( this->m_SourcePoints );    
	this->m_ThinPlateTransform->SetTargetLandmarks( this->m_TargetPoints );
    
	
	this->m_GeneralTransform->SetInput( this->m_ThinPlateTransform );
	this->m_GeneralTransform->Concatenate(
this->m_ThinPlateTransform->GetInverse());
	this->m_GeneralTransform->Concatenate( this->m_ThinPlateTransform );
	
    
	this->m_TransformFilter->SetInput(input);
	this->m_TransformFilter->SetTransform( this->m_GeneralTransform);
    
    
    
    //VTK class vtkTransformPolyDataFilter to perform transformation of
points
    this->m_TransformFilter->SetInput( input );
    //Update the modification time for this object. Many filters rely on the
modification time to determine if they need to recompute their data.
    input->Modified();
    //The Spline transformation source points vtkThinPlateSplineTransform
	this->m_ThinPlateTransform->Modified();
    
    //update filter
    this->m_TransformFilter->Update(); 
    
    output->DeepCopy(this->m_TransformFilter->GetOutput());
    //output =  this->m_TransformFilter->GetOutput();
    
    return 1;
    
/*
  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
  vtkInformation *outInfo = outputVector->GetInformationObject(0);
 
  vtkPolyData *input = vtkPolyData::SafeDownCast(
    inInfo->Get(vtkDataObject::DATA_OBJECT()));
  vtkPolyData *output = vtkPolyData::SafeDownCast(
    outInfo->Get(vtkDataObject::DATA_OBJECT()));
 
  vtkIdType i, j;
  vtkIdType numberOfPoints, numberOfCellPoints;
  vtkIdType cellId, pointId;
  int subId;
  double point[3], closestPoint[3];
  double distance2, distance, signedDistance;
  double pcoords[3];
  double pointNormal[3], *normal;
  double distanceVector[3];
  double *weights;
  double dot;
  bool computeDistance, computeDistanceVectors, computeSignedDistance;
  vtkDoubleArray *distanceArray, *distanceVectorsArray,
*signedDistanceArray;
  vtkDataArray *normals;
  vtkCellLocator *locator;
  vtkGenericCell *genericCell;
  vtkCell *cell;
 
  if (!this->ReferenceSurface)
    {
    vtkErrorMacro(<<"No reference surface!");
    return 1;
    }
 
  if
((!this->DistanceArrayName)&&(!this->DistanceVectorsArrayName)&&(!this->SignedDistanceArrayName))
    {
    vtkErrorMacro(<<"No array names set!");
    return 1;
    }
 
  distanceArray = vtkDoubleArray::New();
  distanceVectorsArray = vtkDoubleArray::New();
  signedDistanceArray = vtkDoubleArray::New();
  normals = NULL;
 
  locator = vtkCellLocator::New();
  genericCell = vtkGenericCell::New();
 
  numberOfPoints = input->GetNumberOfPoints();
 
  computeDistance = false;
  computeDistanceVectors = false;
  computeSignedDistance = false;
 
  if (this->DistanceArrayName)
    {
    computeDistance = true;
    distanceArray->SetName(this->DistanceArrayName);
    distanceArray->SetNumberOfComponents(1);
    distanceArray->SetNumberOfTuples(numberOfPoints);
    }
 
  if (this->DistanceVectorsArrayName)
    {
    computeDistanceVectors = true;
    distanceVectorsArray->SetName(this->DistanceVectorsArrayName);
    distanceVectorsArray->SetNumberOfComponents(3);
    distanceVectorsArray->SetNumberOfTuples(numberOfPoints);
    }
 
  if (this->SignedDistanceArrayName)
    {
    computeSignedDistance = true;
    signedDistanceArray->SetName(this->SignedDistanceArrayName);
    signedDistanceArray->SetNumberOfComponents(1);
    signedDistanceArray->SetNumberOfTuples(numberOfPoints);
    normals = this->ReferenceSurface->GetPointData()->GetNormals();
    if (!normals)
      {
      vtkErrorMacro(<<"Signed distance requires point normals to be defined
over ReferenceSurface!");
      return 1;
      }
    }
 
  locator->SetDataSet(this->ReferenceSurface);
  locator->BuildLocator();
 
  for (i=0; i<numberOfPoints; i++)
    {
    input->GetPoint(i,point);
   
locator->FindClosestPoint(point,closestPoint,genericCell,cellId,subId,distance2);
    distanceVector[0] = point[0] - closestPoint[0];
    distanceVector[1] = point[1] - closestPoint[1];
    distanceVector[2] = point[2] - closestPoint[2];
    distance = sqrt(distance2);
 
    if (computeDistance)
      {
      distanceArray->SetTuple1(i,distance);
      }
 
    if (computeDistanceVectors)
      {
     
distanceVectorsArray->SetTuple3(i,-distanceVector[0],-distanceVector[1],-distanceVector[2]);
      }
 
    if (computeSignedDistance)
      {
      cell = this->ReferenceSurface->GetCell(cellId);
      numberOfCellPoints = cell->GetNumberOfPoints();
      weights = new double[numberOfCellPoints];
      cell->EvaluatePosition(point,NULL,subId,pcoords,distance2,weights);
      pointNormal[0] = 0.0;
      pointNormal[1] = 0.0;
      pointNormal[2] = 0.0;
      for (j=0; j<numberOfCellPoints; j++)
        {
        pointId = cell->GetPointId(j);
        normal = normals->GetTuple3(pointId);
        pointNormal[0] += weights[j] * normal[0];
        pointNormal[1] += weights[j] * normal[1];
        pointNormal[2] += weights[j] * normal[2];
        }
      dot = vtkMath::Dot(distanceVector,pointNormal);
      signedDistance = distance;
      // distance is positive if distanceVector and normal have negative dot
      if (dot>0.0)
        {
        signedDistance *= -1.0;
        }
      signedDistanceArray->SetTuple1(i,signedDistance);
      delete[] weights;
      }
    }
 
  output->DeepCopy(input);
 
  if (computeDistance)
    {
    output->GetPointData()->AddArray(distanceArray);
    }
 
  if (computeDistanceVectors)
    {
    output->GetPointData()->AddArray(distanceVectorsArray);
    }
 
  if (computeSignedDistance)
    {
    output->GetPointData()->AddArray(signedDistanceArray);
    }
 
  distanceArray->Delete();
  distanceVectorsArray->Delete();
  signedDistanceArray->Delete();
  locator->Delete();
  genericCell->Delete();
 
  return 1;
 */
}


void vtkPolyDataMargin::PrintSelf(ostream& os, vtkIndent indent)
{
    this->Superclass::PrintSelf(os,indent);
}


****************
Then use the above class like this :

   vtkDoubleArray *margins = vtkDoubleArray::New();
   margins->SetNumberOfComponents(1);
   margins->SetNumberOfTuples(6);

        margins->SetTuple1(0,5.0);
	margins->SetTuple1(1,5.0);
	margins->SetTuple1(2,5.0);
	margins->SetTuple1(3,5.0);
	margins->SetTuple1(4,5.0);
	margins->SetTuple1(5,5.0]);

   vtkPolyDataMargin * margincalculator = vtkPolyDataMargin::New();
   margincalculator->SetInput(getpolydataSurfacefromsomewhere);
   margincalculator->SetMargins(margins);
   margincalculator->Update();

   
   vtkPolyDataWriter* pwriter = vtkPolyDataWriter::New();
   pwriter->SetInput(margincalculator->GetOutput());
   pwriter->SetFileName( "testmarginexpansion.vtk" );
   pwriter->Update();

PS: The above gives me a somewhat translated surface instead of an
extruded/expanded surface.
      I hope to hear from someone with some insight.

GT.

-- 
View this message in context: http://www.nabble.com/margin-around-polydata-%28expansion-extrusion%29-tp24605713p24605713.html
Sent from the VTK - Users mailing list archive at Nabble.com.




More information about the vtkusers mailing list