David,

> >     Add
> >         vtkTypeRevisionMacro(vtkICPFilter, vtkPolyDataAlgorithm);
> >     to your vtkICPFilter.h.
> > 
> 
> That did the trick. However, now that it compiles correctly, when I load
> the plugin in Paraview it has a yellow warning symbol (! in a triangle)
> and it says:
> 
> Load Error, Plugin verification data mismatch in libICP.so
> undefined symbol: _ZTV12vtkICPFilter
> [...]

% nm -C libICP.so
reveals that the undefined symbol _ZTV12vtkICPFilter stems from the
following reference:
         U vtable for vtkICPFilter
http://markmail.org/message/ghz72hqqygv32lsm dealt with a similar
problem. Add

vtkCxxRevisionMacro(vtkICPFilter, "$Revision$");

to your vtkICPFilter.cxx and the code will compile and load into
ParaView. When trying to apply the filter, though, ParaView will
segfault because your XML does not correctly set the two input
connections. Nor does your constructor set the number of input ports to 2.

Out of curiosity I fixed the remaining issues. The filter plugin now
works. But I fail to see where it differs from the more general
(regarding supported data sets) "Resample with DataSet" filter. Do you
have a test case where it actually *does* make a difference?

Sven
#ifndef __vtkICPFilter_h
#define __vtkICPFilter_h

#include "vtkSmartPointer.h" // compiler errors if this is forward declared

#include "vtkPolyDataAlgorithm.h" //superclass
#include "vtkExecutive.h"

class vtkPolyData;
class vtkTransform;
class vtkInformation;
class vtkInformationVector;
class vtkIterativeClosestPointTransform;

#include "vtkMath.h"

class vtkICPFilter : public vtkPolyDataAlgorithm
{
 public:
  static vtkICPFilter *New();
  vtkTypeRevisionMacro(vtkICPFilter, vtkPolyDataAlgorithm);
  void PrintSelf(ostream &os, vtkIndent indent);

  // Description:
  // Specify the input object that is transformed
  vtkPolyData *GetInput();

  // Description:
  // Specify the source object whose points are used for the transformation
  vtkPolyData *GetSource();

  void AddSourceConnection(vtkAlgorithmOutput* input);
  void RemoveAllSources();

 protected:
  vtkICPFilter();
  ~vtkICPFilter();

  // Make sure the pipeline knows what type we expect as input
  int FillInputPortInformation( int port, vtkInformation* info );

  // Generate output
  int RequestData(vtkInformation *, vtkInformationVector **, 
vtkInformationVector *); //the function that makes this class work with the vtk 
pipeline

 private:
  //BTX
  // BTX-ETX comment is to hide these variable declarations from
  // bin/vtkWrapClientServer. If omitted, we'd get a
  // *** SYNTAX ERROR found in parsing the header file vtkICPFilter.h before 
line 34 ***

  vtkSmartPointer<vtkIterativeClosestPointTransform> ICPTransform;
  //ETX
};
#endif

#include "vtkObjectFactory.h" //for new() macro
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkTransform.h"
#include "vtkTransformPolyDataFilter.h"
#include "vtkPolyData.h"
#include "vtkIterativeClosestPointTransform.h"
#include "vtkLandmarkTransform.h"

#include "vtkICPFilter.h"

vtkStandardNewMacro(vtkICPFilter);
vtkCxxRevisionMacro(vtkICPFilter, "$Revision$");


//-----------------------------------------------------------------------------
vtkICPFilter::vtkICPFilter()
{
  // Mandatory!
  this->SetNumberOfInputPorts(2);
}


//-----------------------------------------------------------------------------
vtkICPFilter::~vtkICPFilter()
{

}


//----------------------------------------------------------------------------
vtkPolyData *vtkICPFilter::GetInput()
{
  if (this->GetNumberOfInputConnections(0) < 1)
    {
    return NULL;
    }

  return vtkPolyData::SafeDownCast(this->GetExecutive()->GetInputData(0, 0));
}


//-----------------------------------------------------------------------------
vtkPolyData *vtkICPFilter::GetSource()
{
  if (this->GetNumberOfInputConnections(1) < 1) // because the port is optional
    {
    return 0;
    }
  return static_cast<vtkPolyData *>(this->GetExecutive()->GetInputData(1, 0));
}


//----------------------------------------------------------------------------
void vtkICPFilter::AddSourceConnection(vtkAlgorithmOutput* input)
{
  this->AddInputConnection(1, input);
}


//----------------------------------------------------------------------------
void vtkICPFilter::RemoveAllSources()
{
  this->SetInputConnection(1, 0);
}


//----------------------------------------------------------------------------
int vtkICPFilter::FillInputPortInformation( int port, vtkInformation* info )
{
  if (!this->Superclass::FillInputPortInformation(port, info))
    {
    return 0;
    }
  if ( port == 0 )
    {
    info->Set( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData" );
    return 1;
    }
  else if ( port == 1 )
    {
    info->Set( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData" );
    return 1;
    }
  return 0;
}


//----------------------------------------------------------------------------
int vtkICPFilter::RequestData(vtkInformation *vtkNotUsed(request),
                              vtkInformationVector **inputVector,
                              vtkInformationVector *outputVector)
{
  // get the info objects
  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
  vtkInformation *outInfo = outputVector->GetInformationObject(0);

  // get the input and output
  vtkPolyData *input = vtkPolyData::SafeDownCast(
                                                 
inInfo->Get(vtkDataObject::DATA_OBJECT()));
  vtkPolyData *output = vtkPolyData::SafeDownCast(
                                                  
outInfo->Get(vtkDataObject::DATA_OBJECT()));

  //ICP Transform
  this->ICPTransform = 
vtkSmartPointer<vtkIterativeClosestPointTransform>::New();
  this->ICPTransform->SetSource(this->GetInput());
  this->ICPTransform->SetTarget(this->GetSource());

  //icp->CheckMeanDistanceOn();
  //icp->SetMaximumNumberOfIterations(maxiters);
  //icp->SetThresh(Thresh);
  //icp->StartByMatchingCentroidsOn(); //align center of masses as first 
transformation

  //all points are used if this is not done, the idea is to use a subset of the 
points if they are very dense
  //icp->SetMaximumNumberOfLandmarks(1000);

  //icp->SetMaximumMeanDistance(accuracy); //the test distance for convergence

  //if you don't do this, it defaults to similarity transform (translation, 
rotation, and isotropic scaling)
  this->ICPTransform->GetLandmarkTransform()->SetModeToRigidBody();

  //icp->Modified(); //is this necessary?
  this->ICPTransform->Update();

  //bring the source to the target
  vtkSmartPointer<vtkTransformPolyDataFilter> TransformFilter = 
vtkSmartPointer<vtkTransformPolyDataFilter>::New();
  TransformFilter->SetInput(this->GetInput());
  TransformFilter->SetTransform(this->ICPTransform);
  TransformFilter->Update();
  output->ShallowCopy(TransformFilter->GetOutput());

  return 1;
}



////////// External Operators /////////////

void vtkICPFilter::PrintSelf(ostream &os, vtkIndent indent)
{
}
<ServerManagerConfiguration>
  <ProxyGroup name="filters">
    <!-- ================================================================== -->
    <SourceProxy name="ICP" class="vtkICPFilter" label="ICP">
      <Documentation
         long_help="Perform registration using iterative closest points."
         short_help="vtkICPFilter.">
      </Documentation>

      <InputProperty
         name="Input"
         command="AddInputConnection"
         clean_command="RemoveAllInputs">
        <ProxyGroupDomain name="groups">
          <Group name="sources"/>
          <Group name="filters"/>
        </ProxyGroupDomain>
        <DataTypeDomain name="input_type">
          <DataType value="vtkPolyData"/>
        </DataTypeDomain>
        <Documentation>
          Set the source data set. This data set will be moved towards the target data set.
        </Documentation>
      </InputProperty>

      <InputProperty
         name="Source"
         command="AddSourceConnection"
         clean_command="RemoveAllSources">
        <ProxyGroupDomain name="groups">
          <Group name="sources"/>
          <Group name="filters"/>
        </ProxyGroupDomain>
        <DataTypeDomain name="input_type">
          <DataType value="vtkPolyData"/>
        </DataTypeDomain>
        <Documentation>
          Set the target data set. This data set will remain unchanged.
        </Documentation>
      </InputProperty>

    </SourceProxy>
    <!-- End ICP -->
  </ProxyGroup>
  <!-- End Filters Group -->
</ServerManagerConfiguration>
_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the ParaView Wiki at: 
http://paraview.org/Wiki/ParaView

Follow this link to subscribe/unsubscribe:
http://www.paraview.org/mailman/listinfo/paraview

Reply via email to