Commit f131681b authored by Andreas Schwarzkopf's avatar Andreas Schwarzkopf

[ADD #371] Plane clustering approach implementation of Lari/Habib

 * Steps done:
 *   - Implemented the plane point clustering approach of Lari/Habib
 *
 * Probable remaining steps that remain to be implemented:
 *   - Applying a modified convex hull boundary detection algorithm to separate
 *     Spatially disconnected planar patches that were detected to belong to the same
 *     Planar formula.
parent d6da7de6
......@@ -50,7 +50,7 @@ void WPCADetector::setMinPointsPerVoxelToDraw( size_t minPointsPerVoxelToDraw )
}
void WPCADetector::analyze()
{
analyzeNode( ( WPcaDetectOctNode* )( m_analyzableOctree->getRootNode() ) );
analyzeNode( static_cast<WPcaDetectOctNode*>( m_analyzableOctree->getRootNode() ) );
}
void WPCADetector::analyzeNode( WPcaDetectOctNode* node )
{
......@@ -71,13 +71,13 @@ void WPCADetector::analyzeNode( WPcaDetectOctNode* node )
{
for ( int child = 0; child < 8; child++ )
if ( node->getChild( child ) != 0 )
analyzeNode( ( WPcaDetectOctNode* )( node->getChild( child ) ) );
analyzeNode( static_cast<WPcaDetectOctNode*>( node->getChild( child ) ) );
}
}
boost::shared_ptr< WTriangleMesh > WPCADetector::getOutline()
{
boost::shared_ptr< WTriangleMesh > tmpMesh( new WTriangleMesh( 0, 0 ) );
drawNode( ( WPcaDetectOctNode* )( m_analyzableOctree->getRootNode() ), tmpMesh );
drawNode( static_cast<WPcaDetectOctNode*>( m_analyzableOctree->getRootNode() ), tmpMesh );
return tmpMesh;
}
......@@ -96,7 +96,7 @@ void WPCADetector::drawNode( WPcaDetectOctNode* node, boost::shared_ptr< WTriang
{
for ( int child = 0; child < 8; child++ )
if ( node->getChild( child ) != 0 )
drawNode( ( WPcaDetectOctNode* )(node->getChild( child ) ), outputMesh );
drawNode( static_cast<WPcaDetectOctNode*>( node->getChild( child ) ), outputMesh );
}
}
void WPCADetector::drawLeafNode( WPcaDetectOctNode* node, boost::shared_ptr< WTriangleMesh > outputMesh )
......
......@@ -208,7 +208,7 @@ public:
{
GRAY = 1,
RGB = 3,
RGBA =4
RGBA = 4
};
/**
......
......@@ -23,41 +23,32 @@
//---------------------------------------------------------------------------
#include <iostream>
#include <algorithm>
#include <vector>
#include "WParameterDomainKdNode.h"
#include "WKdPointND.h"
WParameterDomainKdNode::WParameterDomainKdNode( size_t dimensions ) : WKdTreeND( dimensions )
using std::cout;
using std::endl;
WKdPointND::WKdPointND( vector<double> coordinate )
{
m_coordinate = coordinate;
}
WParameterDomainKdNode::~WParameterDomainKdNode()
WKdPointND::WKdPointND( double x, double y, double z )
{
m_coordinate = vector<double>( 3, 0 );
m_coordinate[0] = x;
m_coordinate[1] = y;
m_coordinate[2] = z;
}
vector<double> WParameterDomainKdNode::getEigenValues()
{
return m_eigenValues;
}
WKdTreeND* WParameterDomainKdNode::getNewInstance( size_t dimensions )
WKdPointND::~WKdPointND()
{
return new WParameterDomainKdNode( dimensions );
}
void WParameterDomainKdNode::setEigenValues( vector<double> eigenValues )
{
m_eigenValues = eigenValues;
}
void WParameterDomainKdNode::setEigenVectors( vector<WVector3d> eigenVectors )
{
m_eigenVectors = eigenVectors;
}
void WParameterDomainKdNode::setParametersXYZ0( vector<double> parametersXYZ0 )
size_t WKdPointND::getDimensionCount()
{
m_parametersXYZ0 = parametersXYZ0;
return m_coordinate.size();
}
vector<double> WParameterDomainKdNode::getParametersXYZ0()
vector<double> WKdPointND::getCoordinate()
{
return m_parametersXYZ0;
return m_coordinate;
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WKDPOINTND_H
#define WKDPOINTND_H
#include <vector>
#include <algorithm>
using std::vector;
using std::size_t;
using std::cout;
using std::endl;
/**
* A kd tree point that is added to n dimensional kd trees.
*/
class WKdPointND
{
public:
/**
* Instance to create an n dimensional kd tree point instance.
* \param coordinate N dimensional coordinate of the new kd tree point.
*/
explicit WKdPointND( vector<double> coordinate );
/**
* Instance to create a three dimensional kd tree point instance.
* \param x X coordinate of the new kd tree point.
* \param y Y coordinate of the new kd tree point.
* \param z Z coordinate of the new kd tree point.
*/
WKdPointND( double x, double y, double z );
/**
* Destroys a kd tree point instance.
*/
virtual ~WKdPointND();
/**
* Returns the dimension count of a kd tree point.
* \return Dimension count of a kd tree point.
*/
size_t getDimensionCount();
/**
* Returns the coordinate of a kd tree point.
* \return Coordinate of a kd tree point.
*/
vector<double> getCoordinate();
private:
/**
* N dimensional coordinate of a kd tree point.
*/
vector<double> m_coordinate;
};
#endif // WKDPOINTND_H
......@@ -53,7 +53,7 @@ WKdTreeND::WKdTreeND( size_t dimensions )
m_splittingDimension = 0;
m_splittingPosition = 0.0;
m_allowDoubles = true;
m_points = new vector<vector<double> >();
m_points = new vector<WKdPointND* >();
m_parentSplittingDimension = dimensions;
m_higherChild = 0;
m_lowerChild = 0;
......@@ -70,7 +70,7 @@ WKdTreeND::~WKdTreeND()
delete m_higherChild;
}
}
void WKdTreeND::add( vector<vector<double> >* addables )
void WKdTreeND::add( vector<WKdPointND*>* addables )
{
if( addables->size() == 0 )
return;
......@@ -84,8 +84,9 @@ void WKdTreeND::add( vector<vector<double> >* addables )
{
if( m_points->size() == 2 )
{
m_splittingPosition = ( m_points->at( 0 )[m_splittingDimension]
+ m_points->at( 1 )[m_splittingDimension] ) / 2.0;
double point1Scalar = m_points->at( 0 )->getCoordinate()[m_splittingDimension];
double point2Scalar = m_points->at( 1 )->getCoordinate()[m_splittingDimension];
m_splittingPosition = ( point1Scalar + point2Scalar ) / 2.0;
}
else
{
......@@ -117,7 +118,7 @@ bool WKdTreeND::canSplit()
{
return m_splittingDimension < m_dimensions;
}
void WKdTreeND::fetchPoints( vector<vector<double> >* targetPointSet )
void WKdTreeND::fetchPoints( vector<WKdPointND* >* targetPointSet )
{
if( m_points->size() == 0 && m_lowerChild == 0 && m_lowerChild == 0 )
{
......@@ -143,6 +144,17 @@ void WKdTreeND::fetchPoints( vector<vector<double> >* targetPointSet )
}
}
}
vector<WKdPointND*>* WKdTreeND::getAllPoints()
{
vector<WKdPointND*>* outputPoints = new vector<WKdPointND*>();
vector<WKdTreeND*>* kdNodes = getAllLeafNodes();
for( size_t nodeIndex = 0; nodeIndex < kdNodes->size(); nodeIndex++ )
for( size_t pointIndex = 0; pointIndex < kdNodes->at(nodeIndex)->getNodePoints()->size(); pointIndex++ )
outputPoints->push_back( kdNodes->at( nodeIndex )->getNodePoints()->at( pointIndex ) );
kdNodes->resize( 0 );
kdNodes->reserve( 0 );
return outputPoints;
}
vector<WKdTreeND*>* WKdTreeND::getAllLeafNodes()
{
vector<WKdTreeND*>* outputLeafNodes = new vector<WKdTreeND*>();
......@@ -177,7 +189,7 @@ WKdTreeND* WKdTreeND::getLowerChild()
{
return m_lowerChild;
}
vector<vector<double> >* WKdTreeND::getNodePoints()
vector<WKdPointND*>* WKdTreeND::getNodePoints()
{
return m_points;
}
......@@ -193,14 +205,14 @@ WKdTreeND* WKdTreeND::getNewInstance( size_t dimensions )
{
return new WKdTreeND( dimensions );
}
void WKdTreeND::addPointsToChildren( vector<vector<double> >* newPoints )
void WKdTreeND::addPointsToChildren( vector<WKdPointND* >* newPoints )
{
vector<vector<double> >* lowerPoints = new vector<vector<double> >();
vector<vector<double> >* higherPoints = new vector<vector<double> >();
vector<WKdPointND* >* lowerPoints = new vector<WKdPointND* >();
vector<WKdPointND* >* higherPoints = new vector<WKdPointND* >();
for( size_t index = 0; index < newPoints->size(); index++ )
{
vector<double> newPoint = newPoints->at( index );
double position = newPoint.at( m_splittingDimension );
WKdPointND* newPoint = newPoints->at( index );
double position = newPoint->getCoordinate().at( m_splittingDimension );
if( position < m_splittingPosition )
{
lowerPoints->push_back( newPoint );
......@@ -215,16 +227,14 @@ void WKdTreeND::addPointsToChildren( vector<vector<double> >* newPoints )
delete lowerPoints;
delete higherPoints;
}
void WKdTreeND::calculateSplittingPosition( vector<vector<double> >* inputPoints )
void WKdTreeND::calculateSplittingPosition( vector<WKdPointND* >* inputPoints )
{
if( !canSplit() )
return;
size_t count = inputPoints->size();
vector<double>* line = new vector<double>();
line->reserve( count );
line->resize( count );
vector<double>* line = new vector<double>( inputPoints->size(), 0 );
for( size_t index = 0; index < inputPoints->size(); index++ )
line->at( index ) = inputPoints->at( index ).at( m_splittingDimension );
line->at( index ) = inputPoints->at( index )->getCoordinate()[m_splittingDimension];
std::sort( line->begin(), line->end() );
size_t medianIdx = count / 2;
m_splittingPosition = line->at( medianIdx );
......@@ -294,7 +304,7 @@ void WKdTreeND::calculateSplittingPosition( vector<vector<double> >* inputPoints
line->reserve( 0 );
delete line;
}
bool WKdTreeND::determineNewSplittingDimension( vector<vector<double> >* inputPoints )
bool WKdTreeND::determineNewSplittingDimension( vector<WKdPointND* >* inputPoints )
{
m_splittingDimension = m_dimensions;
if( inputPoints->size() < 2 )
......@@ -308,7 +318,7 @@ bool WKdTreeND::determineNewSplittingDimension( vector<vector<double> >* inputPo
for( size_t index = 0; index < inputPoints->size(); index++ )
for( size_t dimension = 0; dimension < getDimensions(); dimension++ )
{
double position = inputPoints->at( index ).at( dimension );
double position = inputPoints->at( index )->getCoordinate().at( dimension );
if( index == 0 || position < boundingBoxMin->at( dimension ) )
boundingBoxMin->at( dimension ) = position;
if( index == 0 || position > boundingBoxMax->at( dimension ) )
......
......@@ -27,6 +27,7 @@
#include <vector>
#include <algorithm>
#include "WKdPointND.h"
using std::vector;
using std::size_t;
......@@ -46,6 +47,9 @@ public:
* \param dimensions The dimension count of the kd tree.
*/
explicit WKdTreeND( size_t dimensions );
/**
* Destroys an n dimensional kd tree node.
*/
virtual ~WKdTreeND();
/**
* Adds points to the kd tree. It's better to add all the points into an empty tree.
......@@ -53,7 +57,7 @@ public:
* unbalanced binary tree inside adding a larger amount of points.
* \param addables Points to add.
*/
void add( vector<vector<double> >* addables );
void add( vector<WKdPointND*>* addables );
/**
* Says whether a kd tree node can be split or not. Firstly the method to determine
* the splitting dimension should be executed. A true value is returned if the
......@@ -65,14 +69,14 @@ public:
* Fetches all the points from a kd tree node into a list.
* \param targetPointSet Target point list to put points to.
*/
void fetchPoints( vector<vector<double> >* targetPointSet );
void fetchPoints( vector<WKdPointND* >* targetPointSet );
// double getAreaMin(size_t dimension); //TODO(aschwarzkopf): Consider to purge in future
// double getAreaMax(size_t dimension); //TODO(aschwarzkopf): Consider to purge in future
/**
* Returns all the leaf nodes of the kd tree.
* \return All the leaf nodes of the kd tree.
* Returns all points that belont to a kd tree leaf node.
* \return all points that belong to a kd tree leaf node.
*/
vector<WKdTreeND*>* getAllLeafNodes();
vector<WKdPointND*>* getAllPoints();
/**
* Returns the dimension count of the kd tree.
* \return The dimension count of the kd tree.
......@@ -101,7 +105,7 @@ public:
* return points.
* \return The points of a kd tree node.
*/
vector<vector<double> >* getNodePoints();
vector<WKdPointND*>* getNodePoints();
/**
* Returns the dimension across which the current node is split.
* \return The dimension across which the current node is split.
......@@ -124,20 +128,25 @@ protected:
virtual WKdTreeND* getNewInstance( size_t dimensions );
private:
/**
* Returns all the leaf nodes of the kd tree.
* \return All the leaf nodes of the kd tree.
*/
vector<WKdTreeND*>* getAllLeafNodes();
/**
* This method is used by the method to add new points. It puts points either to the
* node of the lower or higher position across the splitting dimension. The method is
* executed after the splitting dimension and position are calculated.
* \param newPoints Points to append to child nodes.
*/
void addPointsToChildren( vector<vector<double> >* newPoints );
void addPointsToChildren( vector<WKdPointND* >* newPoints );
/**
* Calculates the splitting position between the two child nodes. It calculates the
* median of all input points across the splitting dimension between two children.
* Always check out the splitting dimension before that.
* \param points Input points to calculate the median across the splitted dimension.
*/
void calculateSplittingPosition( vector<vector<double> >* points );
void calculateSplittingPosition( vector<WKdPointND* >* points );
/**
* Determines the new splitting dimension between two child nodes. Afterwards the
* splitting position can be calculated across that dimension after executing that
......@@ -145,7 +154,7 @@ private:
* \param inputPoints Input points to analyse the most optimal splitting dimension.
* \return The kd tree node can be split or not.
*/
bool determineNewSplittingDimension( vector<vector<double> >* inputPoints );
bool determineNewSplittingDimension( vector<WKdPointND* >* inputPoints );
/**
* Fetches all kd tree leaf nodes into a node list.
* \param targetNodeList The target list where leaf nodes are put.
......@@ -200,7 +209,7 @@ private:
/**
* Points covered by a kd tree node.
*/
vector<vector<double> >* m_points;
vector<WKdPointND* >* m_points;
// vector<double> areaMin; //TODO(aschwarzkopf): Decide later whether to keep or not: It can be easily purged.
......
......@@ -30,10 +30,10 @@ WPointDistance::WPointDistance()
{
m_pointDistance = 0;
}
WPointDistance::WPointDistance( vector<double> sourcePoint, vector<double> comparedPoint )
WPointDistance::WPointDistance( vector<double> sourcePoint, WKdPointND* comparedPoint )
{
m_comparedCoordinate = comparedPoint;
m_pointDistance = getPointDistance( sourcePoint, comparedPoint );
m_comparedPoint = comparedPoint;
m_pointDistance = getPointDistance( sourcePoint, getComparedPoint()->getCoordinate() );
}
WPointDistance::~WPointDistance()
......@@ -41,7 +41,11 @@ WPointDistance::~WPointDistance()
}
vector<double> WPointDistance::getComparedCoordinate()
{
return m_comparedCoordinate;
return m_comparedPoint->getCoordinate();
}
WKdPointND* WPointDistance::getComparedPoint()
{
return m_comparedPoint;
}
double WPointDistance::getDistance()
{
......
......@@ -29,6 +29,7 @@
#include <iostream>
#include <vector>
#include "WKdPointND.h"
using std::vector;
......@@ -52,7 +53,7 @@ public:
* \param comparedPoint The second point that is used to calculate the distance
* between. The object stores its coordinates by that.
*/
WPointDistance( vector<double> sourcePoint, vector<double> comparedPoint );
WPointDistance( vector<double> sourcePoint, WKdPointND* comparedPoint );
/**
* Object destructor
*/
......@@ -62,6 +63,12 @@ public:
* \return The compared point coordinate.
*/
vector<double> getComparedCoordinate();
/**
* Returns the point that is considered within the current distance calculation
* instance.
* \return Point that is considered within the current distance calculation instance.
*/
WKdPointND* getComparedPoint();
/**
* Returns the distance between the reference point and the compared one.
* \return The distance between the two instantiated points using the constructor.
......@@ -81,6 +88,8 @@ public:
* \return The distance of this object is smaller than the right one or not.
*/
bool operator<( WPointDistance const& right ) const;
private:
/**
* The euclidian distance between the two points instantiated using the constructor.
*/
......@@ -89,7 +98,7 @@ public:
* The unidimensional coordinate of the compared point instantiated using the
* constructor.
*/
vector<double> m_comparedCoordinate;
WKdPointND* m_comparedPoint;
};
#endif // WPOINTDISTANCE_H
......@@ -24,6 +24,7 @@
#include <algorithm>
#include <vector>
#include <limits>
#include "WPointSearcher.h"
......@@ -37,8 +38,8 @@ WPointSearcher::WPointSearcher( WKdTreeND* kdTree )
}
WPointSearcher::~WPointSearcher()
{
m_searchedPoint.resize( 0 );
m_searchedPoint.reserve( 0 );
m_searchedCoordinate.resize( 0 );
m_searchedCoordinate.reserve( 0 );
}
vector<WPosition>* WPointSearcher::convertToPointSet( vector<WPointDistance>* pointDistances )
{
......@@ -55,11 +56,12 @@ vector<WPointDistance>* WPointSearcher::getNearestPoints()
{
vector<WPointDistance>* nearestPoints = new vector<WPointDistance>();
double index = 1;
for( index = 1; index <= m_distanceSteps
size_t distanceSteps = m_maxResultPointCount == std::numeric_limits< size_t >::max() ?1 :m_distanceSteps;
for( index = 1; index <= distanceSteps
&& nearestPoints->size() < m_maxResultPointCount; index++ )
{
nearestPoints->resize( 0 );
nearestPoints->reserve( 0 );
delete nearestPoints;
nearestPoints = new vector<WPointDistance>();
double maxDistance = m_maxSearchDistance * pow( 2.0, - ( double )m_distanceSteps + ( double )index );
fetchNearestPoints( m_examinedKdTree, nearestPoints, maxDistance );
//cout << "Attempt at max distance: " << maxDistance << " size = " << nearestPoints->size() << endl;
......@@ -81,7 +83,7 @@ void WPointSearcher::setExaminedKdTree( WKdTreeND* kdTree )
}
void WPointSearcher::setSearchedPoint( vector<double> searchedPoint )
{
m_searchedPoint = searchedPoint;
m_searchedCoordinate = searchedPoint;
}
void WPointSearcher::setMaxSearchDistance( double distance )
{
......@@ -93,24 +95,25 @@ void WPointSearcher::setMaxResultPointCount( size_t maxPointCount )
}
void WPointSearcher::fetchNearestPoints( WKdTreeND* currentNode, vector<WPointDistance>* targetPoints, double maxDistance )
{
vector<vector<double> >* nodePoints = currentNode->getNodePoints();
vector<WKdPointND* >* nodePoints = currentNode->getNodePoints();
WKdTreeND* lowerChild = currentNode->getLowerChild();
WKdTreeND* higherChild = currentNode->getHigherChild();
if( nodePoints->size() > 0 && lowerChild == 0 && higherChild == 0)
{
for( size_t index = 0; index < nodePoints->size(); index++ )
{
vector<double> point = nodePoints->at( index );
if( WPointDistance::getPointDistance( m_searchedPoint, point ) <= maxDistance )
targetPoints->push_back( WPointDistance( m_searchedPoint, point ) );
WKdPointND* point = nodePoints->at( index );
if( WPointDistance::getPointDistance( m_searchedCoordinate, point->getCoordinate() ) <= maxDistance )
targetPoints->push_back( WPointDistance( m_searchedCoordinate, nodePoints->at( index ) ) );
}
}
else
{
if( nodePoints->size() == 0 && lowerChild != 0 && higherChild != 0 )
{
double splittingDimension = currentNode->getSplittingDimension();
double splittingPosition = currentNode->getSplittingPosition();
double pointCoord = m_searchedPoint.at( currentNode->getSplittingDimension() );
double pointCoord = m_searchedCoordinate.at( splittingDimension );
if( pointCoord < splittingPosition + maxDistance )
fetchNearestPoints( currentNode->getLowerChild(), targetPoints, maxDistance );
if( pointCoord > splittingPosition - maxDistance )
......
......@@ -29,6 +29,7 @@
#include <vector>
#include "WPointDistance.h"
#include "WKdTreeND.h"
#include "WKdPointND.h"
#include "core/common/math/linearAlgebra/WPosition.h"
using std::cout;
......@@ -89,13 +90,8 @@ public:
* \param maxPointCount The maximal neighbor count that is found for a coordinate.
*/
void setMaxResultPointCount( size_t maxPointCount );
/**
* A performance setting that has no effect on the result. Often the limited point
* count is covered by a significantly smaller radius than the limit.
* Searching through the nodes it firstly traverses nodes of a smaller distance. The
* first radius is searched radius divided by pow(2, steps).
*/
size_t m_distanceSteps;
private:
/**
* Kd tree where nearest points are searched.
*/
......@@ -103,7 +99,7 @@ public:
/**
* The coordinate of which nearest points will be returned.
*/
vector<double> m_searchedPoint;
vector<double> m_searchedCoordinate;
/**
* maximal euclidian distance within which neighbors are searched.
*/
......@@ -112,8 +108,13 @@ public:
* Maximal output neighbor count.
*/
size_t m_maxResultPointCount;
private:
/**
* A performance setting that has no effect on the result. Often the limited point
* count is covered by a significantly smaller radius than the limit.
* Searching through the nodes it firstly traverses nodes of a smaller distance. The
* first radius is searched radius divided by pow(2, steps).
*/
size_t m_distanceSteps;
/**
* Fetches the nearest points into a point list using a kd tree node. It doesn't
* consider the maximal point count.
......
......@@ -52,6 +52,13 @@ vector<double> WLeastSquares::getHessescheNormalForm()
{
return m_hessescheNormalForm;
}
vector<double> WLeastSquares::getNormalVectorNotNormalized()
{
vector<double> normalVector;
for( size_t dimension = 0; dimension < m_hessescheNormalForm.size() - 1; dimension++ )
normalVector.push_back( m_hessescheNormalForm[dimension] );
return normalVector;