Commit d82e0762 authored by Tobias Neeb's avatar Tobias Neeb
Browse files

[ADD #736] extend TransferFunction2D-Class to work with triangular widgets

parent 677e1956
......@@ -29,33 +29,92 @@
#include "WAssert.h"
#include "WTransferFunction2D.h"
#include "WLogger.h"
#include "core/kernel/WKernel.h"
void WTransferFunction2D::sample2DTransferFunction( unsigned char*array, int width, int height ) const
{
if( m_widget.size() < 1 ) return;
if( m_widget.size() < 1 && m_triangle_widgets.size() < 1 ) return;
WColor color;
// Iterate over widgets and write the color in the "texture" (array) in normalized space
for( auto const &w : m_widget )
if( m_widget.size() >= 1 )
{
for( auto const &w : m_widget )
{
color = w.color;
int xMin = static_cast<int>( w.isoX * width );
int xMax = static_cast<int>( ( w.isoX + w.width ) * width );
int yMin = static_cast<int>( w.isoY * height );
int yMax = static_cast<int>( ( w.isoY + w.height ) * height );
for( int x = xMin; x < xMax; ++x )
{
for( int y = yMin; y < yMax; ++y )
{
for( int j = 0; j < 3; ++j )
{
array[4 * width * x + 4 * y + j] = color[j] * 255.;
}
array[4 * width * x + 4 * y + 3] = color[3] * 255. * m_opacityScale;
}
}
}
}
if( m_triangle_widgets.size() >= 1 )
{
color = w.color;
int xMin = static_cast< int >( w.isoX * width );
int xMax = static_cast< int >( ( w.isoX + w.width ) * width );
int yMin = static_cast< int >( w.isoY * height );
int yMax = static_cast< int >( ( w.isoY + w.height ) * height );
for( int x = xMin; x < xMax; ++x )
for( auto const &w : m_triangle_widgets )
{
for( int y = yMin; y < yMax; ++y )
color = w.color;
int xMin = static_cast<int>( w.isoX * width );
int xMax = static_cast<int>( ( w.isoX + w.width ) * width );
int yMin = static_cast<int>( w.isoY * height );
int yMax = static_cast<int>( ( w.isoY + w.height ) * height );
for( int x = xMin; x < xMax; ++x )
{
for( int j = 0; j < 3; ++j )
for( int y = yMin; y < yMax; ++y )
{
array[ 4 * width * x + 4 * y + j ] = color[ j ] * 255.;
wlog::debug( "WTransferFunction2D" ) << "Triangle:" << w.points;
if( isPointInTriangle( w.points, PolyPoint( x, y ) ) )
{
for( int j = 0; j < 3; ++j )
{
array[4 * width * x + 4 * y + j] = color[j] * 255.;
}
array[4 * width * x + 4 * y + 3] = color[3] * 255. * m_opacityScale;
}
}
array[ 4 * width * x + 4 * y + 3 ] = color[ 3 ] * 255. * m_opacityScale;
}
}
}
}
bool WTransferFunction2D::isPointInTriangle( const PolyPoint trianglePoints[], PolyPoint point ) const
{
float m1, m2, m3;
PolyPoint p, p1, p2, p3;
p = point;
p1 = trianglePoints[0];
p2 = trianglePoints[1];
p3 = trianglePoints[2];
m1 = ( ( p2.y - p3.y ) * ( p.x - p3.x ) + ( p3.x - p2.x ) * ( p.y - p3.y ) ) /
( ( p2.y - p3.y ) * ( p1.x - p3.x ) + ( p3.x - p2.x ) * ( p1.y - p3.y ) );
m2 = ( ( p3.y - p1.y ) * ( p.x - p3.x ) + ( p1.x - p3.x ) * ( p.y - p3.y ) ) /
( ( p2.y - p3.y ) * ( p1.x - p3.x ) + ( p3.x - p2.x ) * ( p1.y - p3.y ) );
m3 = 1.0f - m1 - m2;
if( m1 > 0 && m2 > 0 && m3 > 0 )
{
wlog::debug( "WTransferFunction2D" ) << "Point in triangle: (" << p.x << "," << p.y << ")";
return true;
}
else
{
return false;
}
}
bool WTransferFunction2D::operator==( const WTransferFunction2D &rhs ) const
{
if( m_histogram != rhs.m_histogram )
......@@ -66,7 +125,10 @@ bool WTransferFunction2D::operator==( const WTransferFunction2D &rhs ) const
{
return false;
}
if( m_triangle_widgets.size() != rhs.m_triangle_widgets.size() )
{
return false;
}
std::vector< BoxEntry >::const_iterator it1 = m_widget.begin();
std::vector< BoxEntry >::const_iterator it2 = rhs.m_widget.begin();
for( ;
......@@ -78,6 +140,17 @@ bool WTransferFunction2D::operator==( const WTransferFunction2D &rhs ) const
return false;
}
}
std::vector<TriangleEntry>::const_iterator it3 = m_triangle_widgets.begin();
std::vector<TriangleEntry>::const_iterator it4 = rhs.m_triangle_widgets.begin();
for( ;
it3 != m_triangle_widgets.end();
++it3, ++it4 )
{
if( !( *it3 == *it4 ) )
{
return false;
}
}
return true;
}
......@@ -99,13 +172,19 @@ void WTransferFunction2D::addBoxWidget( double isoX, double isoY, double width,
m_widget.emplace_back( BoxEntry( isoX, isoY, width, height, color ) );
}
void WTransferFunction2D::addTriangleWidget( WTransferFunction2D::PolyPoint points[], double isoX, double isoY, double width, double height,
const WColor &color )
{
m_triangle_widgets.emplace_back( TriangleEntry( points, isoX, isoY, width, height, color ) );
}
std::ostream& operator << ( std::ostream& out, const WTransferFunction2D& tf )
{
size_t numBoxWidgets = tf.numBoxWidgets();
for( size_t i = 0; i < numBoxWidgets; ++i )
{
double isoX = tf.getIsovalueX( i );
double isoY = tf.getIsovalueY( i );
double isoX = tf.getIsovalueX( BOX, i );
double isoY = tf.getIsovalueY( BOX, i );
double width = tf.getWidth( i );
double height = tf.getHeight( i );
WColor c = tf.getColor( i );
......@@ -114,3 +193,10 @@ std::ostream& operator << ( std::ostream& out, const WTransferFunction2D& tf )
}
return out;
}
//TODO(T. Neeb): Check updates between Polygon, ResizePoints and TF
//TODO(T. Neeb): Thread onSleep Save the triangle
......@@ -31,6 +31,11 @@
#include "WColor.h"
#include "WHistogram2D.h"
#include "core/dataHandler/WValueSetBase.h"
#include "qtgui/controlPanel/transferFunction2D/WTransferFunction2DEnums.h"
/**
* A class that stores a 2D transfer function texture and scales it to
......@@ -56,7 +61,8 @@ public:
WTransferFunction2D( const WTransferFunction2D &rhs )
: m_opacityScale( rhs.m_opacityScale ),
m_histogram( rhs.m_histogram ),
m_widget( rhs.m_widget )
m_widget( rhs.m_widget ),
m_triangle_widgets( rhs.m_triangle_widgets )
{
}
......@@ -71,6 +77,7 @@ public:
this->m_opacityScale = rhs.m_opacityScale;
setHistogram( rhs.m_histogram );
this->m_widget = rhs.m_widget;
this->m_triangle_widgets = rhs.m_triangle_widgets;
return ( *this );
}
......@@ -118,7 +125,7 @@ public:
}
/**
* Get the number of widgets
* Get the number of box widgets
*
* \returns the number of box widgets
*/
......@@ -127,26 +134,59 @@ public:
return m_widget.size();
}
/**
* Get the number of trianlge widgets
*
* \returns the number of triangle widgets
*/
size_t numTriangleWidgets() const
{
return m_triangle_widgets.size();
}
/**
* The isovalue of the color at a given index.
*
* \param shape determines from which widget-list to get the isoX from (WIP!)
* \param i the index widget in the list.
* \returns the posX of the widget at index i
*/
double getIsovalueX( size_t i ) const
double getIsovalueX( Shapes shape, size_t i ) const
{
return m_widget.at( i ).isoX;
switch( shape )
{
case BOX:
return m_widget.at( i ).isoX;
break;
case TRIANGLE:
return m_triangle_widgets.at( i ).isoX;
break;
default:
return 0;
break;
}
}
/**
* The isovalue of the color at a given index.
*
* \param shape determines from which widget-list to get the isoY from (WIP!)
* \param i the index widget in the list.
* \returns the posY of the widget at index i
*/
double getIsovalueY( size_t i ) const
double getIsovalueY( Shapes shape, size_t i ) const
{
return m_widget.at( i ).isoY;
switch( shape )
{
case BOX:
return m_widget.at( i ).isoY;
break;
case TRIANGLE:
return m_triangle_widgets.at( i ).isoY;
break;
default:
return 0;
break;
}
}
/**
......@@ -193,6 +233,44 @@ public:
*/
void addBoxWidget( double isoX, double isoY, double width, double height, const WColor& color );
/**
* (WIP) Point of a polygon shape
*
*/
struct PolyPoint
{
/**
* Default constructor for a PolyPoint
*
* @param xc x-coordinate
* @param yc y-coordinate
*/
PolyPoint( double xc = 0, double yc = 0 )
{
x = xc;
y = yc;
}
/** x-coordiante of the point */
double x;
/** y-coordinate of the point */
double y;
};
/**
* Insert a new triangle widget
*
* \param points the points of the triangle to be added
* \param isoX the new iso value
* \param isoY the new iso value
* \param width the new iso value
* \param height the new iso value
* \param color the new color at the given iso value
*/
void addTriangleWidget( PolyPoint points[], double isoX, double isoY, double width, double height, const WColor &color );
/**
* sample/render the transfer function into the given container as a set of RGBA quadruples.
* \param array pointer to an allocated data structure
......@@ -203,6 +281,18 @@ public:
*/
void sample2DTransferFunction( unsigned char*array, int width, int height ) const;
/**
* Using barycentric coordinates check if the point is in a triangle specified by an array of points
*
* @param trianglePoints
* @param point
* @return true
* @return false
*/
bool isPointInTriangle( const PolyPoint trianglePoints[], PolyPoint point ) const;
private:
/**
* Prototype for a storage element
......@@ -261,7 +351,6 @@ private:
return isoX == rhs.isoX && isoY == rhs.isoY && width == rhs.width
&& height == rhs.height && color == rhs.color;
}
/** the width of the box */
double width;
/** the height of the box */
......@@ -270,6 +359,47 @@ private:
WColor color;
};
/**
* Entry of a triangle widget with ist position and color
*/
struct TriangleEntry : public Entry
{
/** default constructor
* \param isoX the x pos
* \param isoY the y pos
* \param width the width of the triangle
* \param height the height of the triangle
* \param color the color of the triangle
* \param points the points of the triangle
*/
TriangleEntry( PolyPoint points[], double isoX, double isoY, double width, double height, WColor color ) : Entry( isoX, isoY ),
width( width ), height( height ), color( color )
{
TriangleEntry::points[0] = points[0];
TriangleEntry::points[1] = points[1];
TriangleEntry::points[2] = points[2];
}
/**
* comparison operator to check for changes
* \param rhs TrriangleEntry to compare to
* \returns true if rhs equals this
*/
bool operator==( const TriangleEntry &rhs ) const
{
return isoX == rhs.isoX && isoY == rhs.isoY && color == rhs.color;
}
/** the points of the triangle */
PolyPoint points[3];
/** the width of the triangle */
double width;
/** the height of the triangle */
double height;
/** the color of the Triangle */
WColor color;
};
/**
* Factor by which the output opacity is scaled
* to allow for easier specification of very small
......@@ -287,6 +417,11 @@ private:
*/
std::vector< BoxEntry > m_widget;
/**
* Hold a list of triangle widgets used in the 2D TF
*/
std::vector<TriangleEntry> m_triangle_widgets;
friend std::ostream& operator << ( std::ostream& out, const WTransferFunction2D& tf );
};
......
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