[vtkusers] planar points to get a plane and its normal vector

David Doria daviddoria+vtk at gmail.com
Tue Jul 7 10:21:42 EDT 2009


I'm not sure why there isn't a function for this (that I can find at
least!). You can find a function that does what you want here:

> http://www.vtk.org/pipermail/vtkusers/2004-March/072916.html
> or here
>
> http://markmail.org/message/52odxars4ijopqfe#query:fit%20plane%20vtk+page:1+mid:52odxars4ijopqfe+state:results
>
> The idea is that the eigen vector corresponding to the smallest eigen value
> of the scatter matrix of the points is the normal of the plane. It seems
> like there should be a function somewhere in vtk:
> vtkPlane* FitPlane(vtkPoints* Points);
>
> GC, when you get this working how you want it can you post it here and
> maybe someone can add it somewhere in vtk?
>
> Thanks,
>
> David
>

I extracted this function mostly from vtkDelaunay2d. Maybe someone can add
this to vtkPlane ?

vtkPlane* BestFitPlane(vtkPoints *points)
    {
        vtkIdType NumPoints = points->GetNumberOfPoints();

        //find the center of mass of the points
        double Center[3] = {0.0, 0.0, 0.0};

        for(vtkIdType i = 0; i < NumPoints; i++)
        {
            double point[3];
            points->GetPoint(i, point);

            Center[0] += point[0];
            Center[1] += point[1];
            Center[2] += point[2];
        }

        Center[0] = Center[0]/static_cast<double>(NumPoints);
        Center[1] = Center[1]/static_cast<double>(NumPoints);
        Center[2] = Center[2]/static_cast<double>(NumPoints);

        //Compute Sample Covariance Matrix (with points centered at the
origin)

        double *a[3], a0[3], a1[3], a2[3];
        a[0] = a0; a[1] = a1; a[2] = a2;
        for(unsigned int i = 0; i < 3; i++)
        {
            a0[i] = a1[i] = a2[i] = 0.0;
        }

        for(unsigned int pointId = 0; pointId < NumPoints; pointId++ )
        {
            double x[3], xp[3];
            points->GetPoint(pointId, x);
            xp[0] = x[0] - Center[0];
            xp[1] = x[1] - Center[1];
            xp[2] = x[2] - Center[2];
            for (unsigned int i = 0; i < 3; i++)
            {
                a0[i] += xp[0] * xp[i];
                a1[i] += xp[1] * xp[i];
                a2[i] += xp[2] * xp[i];
            }
        }

        for(unsigned int i = 0; i < 3; i++)
        {
            a0[i] /= static_cast<double>(NumPoints);
            a1[i] /= static_cast<double>(NumPoints);
            a2[i] /= static_cast<double>(NumPoints);
        }

        // Extract eigenvectors from covariance matrix
        double *v[3], v0[3], v1[3], v2[3];
        v[0] = v0; v[1] = v1; v[2] = v2;
        double eigval[3];
        vtkMath::Jacobi(a,eigval,v);
        //Jacobi iteration for the solution of eigenvectors/eigenvalues of a
3x3 real symmetric matrix. Square 3x3 matrix a; output eigenvalues in w; and
output eigenvectors in v. Resulting eigenvalues/vectors are sorted in
decreasing order; eigenvectors are normalized.

        vtkPlane* BestPlane = vtkPlane::New();
        //Set the plane normal to the smallest eigen vector
        BestPlane->SetNormal(v2[0], v2[1], v2[2]);

        //Set the plane origin to the center of mass
        BestPlane->SetOrigin(Center[0], Center[1], Center[2]);

        return BestPlane;
    }





and a test call:

    vtkPoints* Points = vtkPoints::New();

    //create 3 known points
    Points->InsertNextPoint(0.0, 0.0, 0.0);
    Points->InsertNextPoint(1.0, 0.0, 0.0);
    Points->InsertNextPoint(0.0, 1.0, 0.0);

    vtkPlane* BestPlane = VTKHelpers::BestFitPlane(Points);

    std::cout << "Best Plane:\n" << *BestPlane << "\n";



Thanks,

David
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.vtk.org/pipermail/vtkusers/attachments/20090707/5ad31a79/attachment.htm>


More information about the vtkusers mailing list