tests performed for points on a line in 2D

Doc: added definitions, did many fixes.
IMPORTANT: sylvain: double-check the definitions, and precise the dimension and types available for each of your function.

important change: I suggest to rename the function bounding_box to axis_aligned_bounding_box (min case later you will hack on the general one).
This commit is contained in:
Pierre Alliez 2006-03-16 22:52:57 +00:00
parent 7e9a453443
commit 04826e29aa
10 changed files with 64 additions and 41 deletions

View File

@ -210,7 +210,12 @@ BEGIN
POPUP "&Fit"
BEGIN
MENUITEM "&Line", ID_FIT_LINE
MENUITEM "Debug", ID_FIT_DEBUG
POPUP "Debug"
BEGIN
MENUITEM "Many tests for 2 points", ID_FIT_DEBUG
MENUITEM "Many points on a line", ID_DEBUG_MANYTESTSFORNUMEROUSPOINTSONALINE
END
END
END

View File

@ -90,6 +90,7 @@ BEGIN_MESSAGE_MAP(CpcaDlg, CDialog)
ON_COMMAND(ID_RANDOM_HORIZONTALLINE, OnRandomHorizontalline)
ON_COMMAND(ID_RANDOM_VERTICALLINE, OnRandomVerticalline)
ON_COMMAND(ID_FIT_DEBUG, OnFitDebug)
ON_COMMAND(ID_DEBUG_MANYTESTSFORNUMEROUSPOINTSONALINE, OnDebugManytestsfornumerouspointsonaline)
END_MESSAGE_MAP()
@ -469,13 +470,35 @@ void CpcaDlg::OnRandomVerticalline()
}
void CpcaDlg::OnFitDebug()
{
BeginWaitCursor();
for(int i=0;i<10000;i++)
{
m_points.clear();
double x1 = (double)rand() / (double)RAND_MAX;
double y1 = (double)rand() / (double)RAND_MAX;
double x2 = (double)rand() / (double)RAND_MAX;
double y2 = (double)rand() / (double)RAND_MAX;
m_points.push_back(Point_2(x1,y1));
m_points.push_back(Point_2(x2,y2));
OnFitLine();
}
EndWaitCursor();
InvalidateRect(NULL,FALSE);
}
void CpcaDlg::OnDebugManytestsfornumerouspointsonaline()
{
BeginWaitCursor();
m_points.clear();
// random line (y = ax + b)
double a = (double)rand() / (double)RAND_MAX;
double b = (double)rand() / (double)RAND_MAX;
for(int i=0;i<10000;i++)
{
double x = (double)rand() / (double)RAND_MAX;
double y = (double)rand() / (double)RAND_MAX;
double y = a * x + b;
m_points.push_back(Point_2(x,y));
}
OnFitLine();

View File

@ -80,4 +80,5 @@ public:
afx_msg void OnRandomHorizontalline();
afx_msg void OnRandomVerticalline();
afx_msg void OnFitDebug();
afx_msg void OnDebugManytestsfornumerouspointsonaline();
};

View File

@ -20,13 +20,15 @@
#define ID_RANDOM_HORIZONTALLINE 32781
#define ID_RANDOM_VERTICALLINE 32782
#define ID_FIT_DEBUG 32783
#define ID_FIT_DEBUG32784 32784
#define ID_DEBUG_MANYTESTSFORNUMEROUSPOINTSONALINE 32785
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 132
#define _APS_NEXT_COMMAND_VALUE 32784
#define _APS_NEXT_COMMAND_VALUE 32786
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif

View File

@ -1,20 +1,5 @@
This \cgal\ package provides functions to compute global informations
on the shape of a set of 2D or 3D objects such as points. It provides the computation of bounding boxes, centroids of point sets, barycenters of weighted point sets, as well as linear least squares fitting.
Linear least squares fitting approximates a set of objects by a linear
sub-space such as a line or a plane. Formally, given a set of points in $R^d$, linear least squares fitting amounts
to find the linear sub-space of $R^d$ which minimizes the sum of squared
distances from the points to their projection onto this linear sub-space. This
problem is equivalent to search for the linear sub-space which maximizes the
variance of projected points, the latter being obtained by eigen decomposition
of the covariance matrix. Eigenvectors corresponding to large eigenvalues are
the directions in which the data has strong component, or equivalently large
variance. If eigenvalues are the same there is no preferable sub-space.
This package implements the linear least squares fitting for
several objects of a \cgal\ 2D or 3D kernel: the best fit 2D line for 2D
point sets, and the best fit 3D line or plane for point and
triangle sets. The object sets are specified by iterator ranges of
containers.
on the shape of a set of 2D or 3D objects such as points. It provides the computation of axis-aligned bounding boxes, centroids of point sets, barycenters of weighted point sets, as well as linear least squares fitting for point sets in 2D, and point sets as well as triangle sets in 3D. The sets are specified by iterator ranges of containers.\\
\begin{center}
\label{fit}
@ -23,7 +8,7 @@ containers.
\includegraphics[width=1.0\textwidth]{Principal_component_analysis/fit}
\end{ccTexOnly}
\begin{ccHtmlOnly}
<img width="45%" border=0 src="./fit.png"><P>
<img width="100%" border=0 src="./fit.png"><P>
\end{ccHtmlOnly}
% Title
\begin{figure}[h]

View File

@ -13,7 +13,7 @@
\subsection{Bounding Box of a Point Set}
In the following example we use \stl\ containers of 2D and 3D points, and
compute their bounding box. The kernel from which the input points
compute their axis-aligned bounding box. The kernel from which the input points
come is automatically deduced by the function.
\ccIncludeExampleCode{Principal_component_analysis/bounding_box.C}

View File

@ -15,20 +15,30 @@
\subsection*{Summary}
This \cgal\ package provides functions to compute global informations
on the shape of a set of 2D or 3D objects such as points. It provides the computation of bounding boxes, centroids of point sets, barycenters of weighted point sets, as well as linear least squares fitting. It assumes the set of kernel primitive elements to be stored into an iterator range of a container.
on the shape of a set of 2D or 3D objects such as points. It provides the computation of axis-aligned bounding boxes for point sets, centroids of point sets and triangle sets in 2D and 3D, barycenters of weighted point sets, as well as linear least squares fitting for point sets in 2D, and point sets and triangle sets in 3D. It assumes the set of kernel primitive elements to be stored into an iterator range of a container.
\subsection*{Definitions}
\subsection*{Definition}
Given a point set in $R^d$, linear least squares fitting amounts to
find the linear sub-space of $R^d$ which minimizes the sum of squared
A \emph{bounding box} for a set of objects is a cuboid that completely
contains the set. An \emph{axis-aligned bounding box} is a bounding box
aligned with the axes of the coordinate system.\\
A \emph{centroid} is defined as average of position. A \emph{barycenter} of weighted point sets is defined as weighted average of position. When all weights are equal the barycenter coincides with the centroid.\\
Given a point set, \emph{linear least squares fitting} amounts to
find the linear sub-space which minimizes the sum of squared
distances from the points to their projection onto this linear
sub-space. This problem is equivalent to search for the linear
sub-space which maximizes the variance of projected points, the latter
being obtained by eigen decomposition of the covariance
matrix. Eigenvectors corresponding to large eigenvalues are the
matrix of the point set. Eigenvectors corresponding to large eigenvalues are the
directions in which the data has strong component, or equivalently
large variance. If eigenvalues are the same there is no preferable
sub-space.
sub-space.\\
Given a triangle set, \emph{linear least squares fitting} amounts to find the linear sub-space which minimizes the sum of squared
distances from all points in the set to their projection onto this linear
sub-space. This problem is equivalent to the one of fitting a linear sub-space to a point set, except that the covariance matrix is now derived from a continuous integral over the triangles instead of a discrete sum over the points.
\ccHeading{Functions}

View File

@ -6,14 +6,14 @@
#include <list>
#include <iostream>
typedef double FT;
typedef CGAL::Cartesian<FT> K;
typedef K::Point_2 Point_2;
typedef K::Point_3 Point_3;
typedef double FT;
typedef CGAL::Cartesian<FT> K;
typedef K::Point_2 Point_2;
typedef K::Point_3 Point_3;
int main()
{
// bounding_box of 2D points
// axis-aligned bounding box of 2D points
std::list<Point_2> points_2;
points_2.push_back(Point_2(1.0, 0.0));
points_2.push_back(Point_2(2.0, 2.0));
@ -22,7 +22,7 @@ int main()
K::Iso_rectangle_2 c2 = CGAL::bounding_box(points_2.begin(), points_2.end());
std::cout << c2 << std::endl;
// bounding_box of 3D points
// axis-aligned bounding box of 3D points
std::list<Point_3> points_3;
points_3.push_back(Point_3(1.0, 0.0, 0.5));
points_3.push_back(Point_3(2.0, 2.0, 1.2));

View File

@ -25,8 +25,9 @@ CGAL_BEGIN_NAMESPACE
namespace CGALi {
// extract eigenvalues and eigenvectors from a 2x2 symmetric matrix.
// Note: involves a square root.
// extract eigenvalues and eigenvectors from a 2x2 symmetric
// positive definite matrix.
// Note: computations involve a square root.
// Matrix numbering:
// a b
// b c
@ -48,6 +49,8 @@ namespace CGALi {
FT c = matrix[2];
FT p = c*c - 2*a*c + 4*b*b + a*a;
CGAL_assertion(a >= 0.0 && c >= 0.0);
// degenerate or isotropic case
if(p == 0.0)
{

View File

@ -152,9 +152,6 @@ fitting_plane_3(const typename K::FT covariance[6], // covariance matrix
FT eigen_values[3];
FT eigen_vectors[9];
eigen_symmetric<FT>(covariance,3,eigen_vectors,eigen_values);
CGAL_assertion(eigen_values[0] >= 0.0 &&
eigen_values[1] >= 0.0 &&
eigen_values[2] >= 0.0);
// check unicity and build fitting line accordingly
if(eigen_values[0] != eigen_values[1] &&
@ -199,9 +196,6 @@ fitting_line_3(const typename K::FT covariance[6], // covariance matrix
FT eigen_values[3];
FT eigen_vectors[9];
eigen_symmetric<FT>(covariance,3,eigen_vectors,eigen_values);
CGAL_assertion(eigen_values[0] >= 0.0 &&
eigen_values[1] >= 0.0 &&
eigen_values[2] >= 0.0);
// check unicity and build fitting line accordingly
if(eigen_values[0] != eigen_values[1])