Commit 1328f7f9 authored by Mathias Goldau's avatar Mathias Goldau
Browse files

[ADD #251] Added a plane which provides a primitive sampling method and a...

[ADD #251] Added a plane which provides a primitive sampling method and a boundary concept via WGridRegular3D
parent 2bd36bf1
......@@ -273,33 +273,6 @@ std::ostream& tm_utils::operator<<( std::ostream& os, const WTriangleMesh& rhs )
return os << ss.str();
}
namespace tm_utils
{
/**
* WPosition comparator for build up a map with WPositions as keys.
*/
struct WPositionCompareLess
{
/**
* Determines if a position is "smaller" than another one.
* \warning This ordering makes no sense at all, but is needed for the map!
*
* \param pos1 First positions to compare with
* \param pos2 Second position to compare with
*
* \return True if and only if the first, second or third components of the positions are smaller
*/
bool operator()( const wmath::WPosition& pos1, const wmath::WPosition& pos2 ) const
{
if( pos1[0] < pos2[0] || pos1[1] < pos2[1] || pos1[2] < pos2[2] )
{
return true;
}
return false;
}
};
}
boost::shared_ptr< std::list< boost::shared_ptr< WTriangleMesh > > > tm_utils::componentDecomposition( const WTriangleMesh& mesh )
{
WUnionFind uf( mesh.getNumVertices() ); // idea: every vertex in own component, then successivley join in accordance with the triangles
......@@ -316,7 +289,7 @@ boost::shared_ptr< std::list< boost::shared_ptr< WTriangleMesh > > > tm_utils::c
// to reuse them in the new components too. Hence we must determine if a certain vertex is already inside the new component.
// Since the vertices are organized in a vector, we can use std::find( v.begin, v.end(), vertexToLookUp ) which results
// in O(N^2) or we could use faster lookUp via key and value leading to the map and the somehow complicated BucketType.
typedef std::map< wmath::WPosition, size_t, WPositionCompareLess > VertexType; // look up fast if a vertex is already inside the new mesh!
typedef std::map< wmath::WPosition, size_t > VertexType; // look up fast if a vertex is already inside the new mesh!
typedef std::vector< Triangle > TriangleType;
typedef std::pair< VertexType, TriangleType > BucketType; // Later on the Bucket will be transformed into the new WTriangleMesh component
std::map< size_t, BucketType > buckets; // Key identify with the cannonical element from UnionFind the new connected component
......@@ -327,7 +300,7 @@ boost::shared_ptr< std::list< boost::shared_ptr< WTriangleMesh > > > tm_utils::c
size_t component = uf.find( triangle->pointID[0] );
if( buckets.find( component ) == buckets.end() )
{
buckets[ component ] = BucketType( VertexType( WPositionCompareLess() ), TriangleType() ); // create new bucket
buckets[ component ] = BucketType( VertexType(), TriangleType() ); // create new bucket
}
// Note: We discard the order of the points and indices, but semantically the structure remains the same
......
......@@ -30,6 +30,7 @@
#include <boost/lexical_cast.hpp>
#include "../WLimits.h"
#include "WValue.h"
namespace wmath
......@@ -90,6 +91,16 @@ public:
*/
double distanceSquare( const WVector3D &other ) const;
/**
* Determines if a position is "smaller" than another one.
* \warning This ordering makes no sense at all, but is needed for a map or set!
*
* \param rhs Right hand side vector to compare with
*
* \return True if and only if the first, second or third components of the vectors are smaller
*/
bool operator<( const wmath::WVector3D& rhs ) const;
protected:
private:
};
......@@ -117,5 +128,16 @@ inline double WVector3D::dotProduct( const WVector3D& factor2 ) const
}
return result;
}
inline bool WVector3D::operator<( const wmath::WVector3D& rhs ) const
{
if( ( ( (*this)[0] < rhs[0] ) && ( std::abs( (*this)[0] - rhs[0] ) > wlimits::FLT_EPS ) ) || // using FLT_EPS to make it more robust
( ( (*this)[1] < rhs[1] ) && ( std::abs( (*this)[1] - rhs[1] ) > wlimits::FLT_EPS ) ) ||
( ( (*this)[2] < rhs[2] ) && ( std::abs( (*this)[2] - rhs[2] ) > wlimits::FLT_EPS ) ) )
{
return true;
}
return false;
}
} // End of namespace
#endif // WVECTOR3D_H
......@@ -389,3 +389,7 @@ std::vector< size_t > WGridRegular3D::getNeighbours( size_t id ) const
return neighbours;
}
bool WGridRegular3D::encloses( const wmath::WPosition& pos ) const
{
return getVoxelNum( pos ) != -1; // note this is an integer comparision, hence it should be numerical stable!
}
......@@ -379,6 +379,15 @@ public:
*/
std::vector< size_t > getNeighbours( size_t id ) const;
/**
* Decides whether a certain position is inside this grid or not.
*
* \param pos Position to test
*
* \return True if and only if the given point is inside or on boundary of this grid, otherwise false.
*/
bool encloses( const wmath::WPosition& pos ) const;
protected:
private:
/**
......
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-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/>.
//
//---------------------------------------------------------------------------
#include <set>
#include <boost/shared_ptr.hpp>
#include "../../common/math/WPosition.h"
#include "../../common/math/WVector3D.h"
#include "../WGridRegular3D.h"
#include "WPlane.h"
#include "../../common/datastructures/WTriangleMesh.h"
WPlane::WPlane( const wmath::WVector3D& normal, const wmath::WPosition& pos )
: m_normal( normal ),
m_pos( pos )
{
m_first = normal.crossProduct( wmath::WVector3D( 1, 1, 1 ) );
m_first.normalize();
m_second = normal.crossProduct( m_first );
m_second.normalize();
}
WPlane::~WPlane()
{
}
bool WPlane::isInPlane( wmath::WPosition /* point */ ) const
{
// TODO(math): implement this: pos + first*m + second*n == point ??
return false;
}
void WPlane::resetPosition( wmath::WPosition newPos )
{
// TODO(math): check if pos is in plane first!
m_pos = newPos;
}
boost::shared_ptr< std::set< wmath::WPosition > > WPlane::samplePoints( const WGridRegular3D& grid, double stepWidth )
{
// idea: start from m_pos in m_first direction until boundary reached, increment in m_second direction from m_pos and start again
boost::shared_ptr< std::set< wmath::WPosition > > result( new std::set< wmath::WPosition >() );
// the plane has two directions m_first and m_second
const wmath::WVector3D ycrement = stepWidth * m_second;
const wmath::WVector3D xcrement = stepWidth * m_first;
wmath::WPosition y_offset_up = m_pos;
wmath::WPosition y_offset_down = m_pos;
wmath::WPosition x_offset_right = m_pos;
wmath::WPosition x_offset_left = m_pos;
while( grid.encloses( y_offset_up ) || grid.encloses( y_offset_down ) )
{
if( grid.encloses( y_offset_up ) ) // walk up
{
x_offset_right = y_offset_up;
x_offset_left = y_offset_up;
while( grid.encloses( x_offset_right ) || grid.encloses( x_offset_left ) )
{
if( grid.encloses( x_offset_right ) )
{
result->insert( x_offset_right );
x_offset_right += xcrement;
}
if( grid.encloses( x_offset_left ) )
{
result->insert( x_offset_left );
x_offset_left -= xcrement;
}
}
y_offset_up += ycrement;
}
if( grid.encloses( y_offset_down ) ) // walk down
{
x_offset_right = y_offset_down;
x_offset_left = y_offset_down;
while( grid.encloses( x_offset_right ) || grid.encloses( x_offset_left ) )
{
if( grid.encloses( x_offset_right ) )
{
result->insert( x_offset_right );
x_offset_right += xcrement;
}
if( grid.encloses( x_offset_left ) )
{
result->insert( x_offset_left );
x_offset_left -= xcrement;
}
}
y_offset_down -= ycrement;
}
}
return result;
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-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 WPLANE_H
#define WPLANE_H
#include <set>
#include <boost/shared_ptr.hpp>
#include "../../common/math/WPosition.h"
#include "../../common/math/WVector3D.h"
#include "../WGridRegular3D.h"
/**
* Represents a plane with a normal vector and a position in space.
*/
class WPlane
{
public:
/**
* Constructs a plane with its normal and containing the point.
*
* \param normal Direction of the plane
* \param pos Position of the plane
*
* \return
*/
WPlane( const wmath::WVector3D& normal, const wmath::WPosition& pos );
/**
* Destructor.
*/
virtual ~WPlane();
/**
* Determines whether a given point is in this plane or not.
*
* \param point Position to query
*
* \return True if and only if the point is in this plane.
*/
bool isInPlane( wmath::WPosition point ) const;
/**
* Reset the position of the plane, normal remains the same.
*
* \param newPos New Position (point in plane).
*/
void resetPosition( wmath::WPosition newPos );
/**
* Computes sample points on that plane.
*
* \param grid
* \param stepWidth
*
* \return Vector of positions on the plane
*/
boost::shared_ptr< std::set< wmath::WPosition > > samplePoints( const WGridRegular3D& grid, double stepWidth );
protected:
wmath::WVector3D m_normal; //!< Direction of the plane
wmath::WPosition m_pos; //!< Position of the plane specifying the center
wmath::WVector3D m_first; //!< First vector in the plane
wmath::WVector3D m_second; //!< Second vector in the plane
private:
};
#endif // WPLANE_H
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-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 WPLANE_TEST_H
#define WPLANE_TEST_H
#include <cxxtest/TestSuite.h>
#include "../WPlane.h"
/**
* Unit tests the WPlane class
*/
class WPlaneTest : public CxxTest::TestSuite
{
public:
/**
* TODO(math): Document this!
*/
void testSamplePointsFromCenter( void )
{
WPlane p( wmath::WVector3D( 0, 0, 1 ), wmath::WPosition( 1, 1, 1 ) );
// boost::shared_ptr< WGridRegular3D > grid( new WGridRegular3D( ) );
}
};
#endif // WPLANE_TEST_H
......@@ -34,6 +34,7 @@
#include <cxxtest/TestSuite.h>
#include "../../common/WLimits.h"
#include "../../common/exceptions/WOutOfBounds.h"
#include "../../common/math/test/WVector3DTraits.h"
#include "../WGridRegular3D.h"
......@@ -518,6 +519,14 @@ public:
TS_ASSERT_THROWS_ANYTHING( g1.getCellId( wmath::WPosition( 3.3, 1.75, 0.78 ) ) );
}
void testEnclosesQuery( void )
{
WGridRegular3D g( 2, 2, 2, 1., 1., 1. );
TS_ASSERT( g.encloses( wmath::WPosition( 0, 0, 0 ) ) );
TS_ASSERT( g.encloses( wmath::WPosition( 1, 1, 1 ) ) );
TS_ASSERT( !g.encloses( wmath::WPosition( 1, 1, 1.0 + wlimits::DBL_EPS ) ) );
}
private:
double m_delta; //!< Maximum amount to values are allowed to differ.
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment