You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
8.0 KiB

5 months ago
/*===========================================================================*\
* *
* IsoEx *
* Copyright (C) 2002 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Library General Public License as published *
* by the Free Software Foundation, version 2. *
* *
* This library 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 *
* Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS RegularGrid - IMPLEMENTATION
//
//=============================================================================
#define ISOEX_REGULAR_GRID_C
//== INCLUDES =================================================================
#include "RegularGridT.hh"
#include <algorithm>
//== NAMESPACES ===============================================================
namespace IsoEx
{
//== IMPLEMENTATION ==========================================================
template<class Vec3>
void
RegularGrid<Vec3>::
initialize( const Vec3& _origin,
const Vec3& _x_axis,
const Vec3& _y_axis,
const Vec3& _z_axis,
unsigned int _x_res,
unsigned int _y_res,
unsigned int _z_res )
{
origin_ = _origin;
x_axis_ = _x_axis;
y_axis_ = _y_axis;
z_axis_ = _z_axis;
x_res_ = _x_res;
y_res_ = _y_res;
z_res_ = _z_res;
// CubeIdx and PointIdx have 32 bits
// -> its 3 components should require <= 10 bits
assert( x_res_ < 1024 );
assert( y_res_ < 1024 );
assert( z_res_ < 1024 );
n_cubes_ = ( _x_res - 1 ) * ( _y_res - 1 ) * ( _z_res - 1 );
n_points_ = _x_res * _y_res * _z_res;
dx_ = x_axis_ / ( real )( x_res_ -1 );
dy_ = y_axis_ / ( real )( y_res_ -1 );
dz_ = z_axis_ / ( real )( z_res_ -1 );
Vec3 x_axisn = x_axis_; x_axisn.normalize();
Vec3 y_axisn = y_axis_; y_axisn.normalize();
Vec3 z_axisn = z_axis_; z_axisn.normalize();
to_world_.identity();
for ( int i = 0; i < 3; ++i )
{
to_world_( i, 0 ) = x_axisn[i];
to_world_( i, 1 ) = y_axisn[i];
to_world_( i, 2 ) = z_axisn[i];
to_world_( i, 3 ) = origin_[i];
}
to_local_ = to_world_;
to_local_.invert();
offsets_[0] = 0;
offsets_[1] = 1;
offsets_[2] = 1 + x_res_;
offsets_[3] = x_res_;
offsets_[4] = x_res_ * y_res_;
offsets_[5] = 1 + x_res_ * y_res_;
offsets_[6] = 1 + x_res_ + x_res_ * y_res_;
offsets_[7] = x_res_ + x_res_ * y_res_;
}
//-----------------------------------------------------------------------------
template<class Vec3>
typename RegularGrid<Vec3>::PointIdx
RegularGrid<Vec3>::
nearest_point( const Vec3 &_p )
{
Vec3 pl = to_local( _p );
// grid spacing
real dxf = dx().norm();
real dyf = dy().norm();
real dzf = dz().norm();
// get gird cell
int x = ( int )( pl[0] / dxf );
int y = ( int )( pl[1] / dyf );
int z = ( int )( pl[2] / dzf );
// transform to point coordinates
return x + y * x_res_ + z * x_res_ * y_res_;
}
//-----------------------------------------------------------------------------
template<class Vec3>
typename RegularGrid<Vec3>::PointIdx
RegularGrid<Vec3>::
point_idx( CubeIdx _idx, unsigned char _corner ) const
{
assert( _corner < 8 );
// get cube coordinates
unsigned int X( x_res_ -1 ), Y( y_res_ -1 );
unsigned int x = _idx % X; _idx /= X;
unsigned int y = _idx % Y; _idx /= Y;
unsigned int z = _idx;
// transform to point coordinates
_idx = x + y * x_res_ + z * x_res_ * y_res_;
// add offset
return _idx + offsets_[_corner];
}
//-----------------------------------------------------------------------------
template<class Vec3>
Vec3
RegularGrid<Vec3>::
point( PointIdx _idx ) const
{
unsigned int x = _idx % x_res_; _idx /= x_res_;
unsigned int y = _idx % y_res_; _idx /= y_res_;
unsigned int z = _idx;
return origin_ + dx_*x + dy_*y + dz_*z;
}
//-----------------------------------------------------------------------------
template<class Vec3>
Vec3
RegularGrid<Vec3>::
point( int x, int y, int z ) const
{
return origin_ + dx_*x + dy_*y + dz_*z;
}
//-----------------------------------------------------------------------------
template<class Vec3>
Vec3
RegularGrid<Vec3>::
to_local( const Vec3 &_pw )
{
return to_local_.transform_point( _pw );
}
//-----------------------------------------------------------------------------
template<class Vec3>
Vec3
RegularGrid<Vec3>::
to_world( const Vec3 &_pl )
{
return to_world_.transform_point( _pl );
}
//-----------------------------------------------------------------------------
template<class Vec3>
bool
RegularGrid<Vec3>::
ray_intersect_local( const Vec3 &_o, const Vec3 &_d,
Vec3 &_entry, Vec3 &_exit )
{
// ray cube intersections
std::vector< Intersection > intersections_;
// upper,right,front cube corner
Vec3 cc( x_axis().norm(), y_axis().norm(), z_axis().norm() );
// find ray-cube intersections
for ( unsigned int i = 0; i < 3; ++i )
{
if ( fabs( _d[i] ) > 1E-9 )
{
// enter
intersections_.resize( intersections_.size() + 1 );
intersections_.back().lambda = -_o[i]/_d[i];
if ( _d[i] > 0.0 )
intersections_.back().enter = true;
else
intersections_.back().enter = false;
// leaving
intersections_.resize( intersections_.size() + 1 );
intersections_.back().lambda = ( _o[i]-cc[i] )/( -_d[i] );
if ( _d[i] > 0.0 )
intersections_.back().enter = false;
else
intersections_.back().enter = true;
}
}
// find last entry and first exit point
real l_en = -FLT_MAX;
real l_ex = FLT_MAX;
for ( unsigned int i = 0; i < intersections_.size(); ++i )
{
if ( intersections_[i].enter )
{
if ( l_en < intersections_[i].lambda )
l_en = intersections_[i].lambda;
}
else
{
if ( l_ex > intersections_[i].lambda )
l_ex = intersections_[i].lambda;
}
}
// does the ray intersect the cube
if ( l_en == -FLT_MAX || l_ex == FLT_MAX || l_ex < l_en )
return false;
_entry = _o + _d*l_en;
_exit = _o + _d*l_ex;
return true;
}
//=============================================================================
} // namespace IsoEx
//=============================================================================