Raw File
PCA3.h
#pragma once

#include "SurfaceMeshHelper.h"
#include <Eigen/Core>
#include <Eigen/Eigenvalues>
using namespace Eigen;

#define (vec) (Eigen::Vector3d(vec[0], vec[1], vec[2]))
#define (vec) (Vector3d(vec[0], vec[1], vec[2]))

class PCA3
{
public:
    PCA3(const std::vector<Vector3d> & points)
	{
		int n = points.size();

        double	x, y, z, xx, yy, zz, xy, xz, yz,
			sumX (0.0), sumY (0.0), sumZ (0.0),
			sumX2(0.0), sumY2(0.0), sumZ2(0.0),
			sumXY(0.0), sumXZ(0.0), sumYZ(0.0);

        mean = Vector3d(0,0,0);

        foreach(SurfaceMesh::Point p, points){
            mean += p;
            x = p.x();	y = p.y();	z = p.z();

            sumX  += x / n		;	sumY  += y / n		;	sumZ  += z / n;
            sumX2 += x * x / n	;	sumY2 += y * y / n	;	sumZ2 += z * z / n;
            sumXY += x * y / n	;	sumXZ += x * z / n	;	sumYZ += y * z / n;
		}

        mean /= points.size();

        xx = sumX2 - sumX * sumX; yy = sumY2 - sumY * sumY;	zz = sumZ2 - sumZ * sumZ;
        xy = sumXY - sumX * sumY; xz = sumXZ - sumX * sumZ;	yz = sumYZ - sumY * sumZ;

		Matrix3d covariance;
		covariance << xx, xy, xz,
					  xy, yy, yz,
					  xz, yz, zz;

		// Solve for eigenvalues and eigenvectors.
		// Eigen values are sorted in ascending order,
		SelfAdjointEigenSolver<Eigen::Matrix3d> es(covariance);
		e_values = es.eigenvalues();
		e_vectors = es.eigenvectors();
	}

	Vector3d eigenvalues()
	{
		return (e_values);
	}

	std::vector<Vector3d> eigenvectors()
	{
		std::vector<Vector3d> vectors;
		for (int i = 2;i >= 0;i--)
		{
			// Descending order
			vectors.push_back((e_vectors.col(i)));
		}

		return vectors;
	}

    static void setPlane(const std::vector<Vector3d> & points, Vector3d & center, Vector3d & normal)
    {
        PCA3 pca(points);
        center = pca.mean;
        Vector3d n = pca.e_vectors.col(1).normalized().cross(pca.e_vectors.col(2).normalized());
        normal = Vector3d(n[0], n[1], n[2]);
    }

	Vector3d center()
	{
		return mean;
	}

private:
	Vector3d e_values;
	Matrix3d e_vectors;
    Vector3d mean;
};
back to top