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