#include <math.h>
#include "qwt3d_color.h"
#include "qwt3d_plot.h"
#include "qwt3d_enrichment_std.h"
using namespace Qwt3D;
/////////////////////////////////////////////////////////////////
//
// CrossHair
//
/////////////////////////////////////////////////////////////////
CrossHair::CrossHair()
{
configure(0, 1, false, false);
}
CrossHair::CrossHair(double rad, double linewidth, bool smooth, bool boxed)
{
configure(rad, linewidth, smooth, boxed);
}
void CrossHair::configure(double rad, double linewidth, bool smooth, bool boxed)
{
plot = 0;
radius_ = rad;
linewidth_ = linewidth;
smooth_ = smooth;
boxed_ = boxed;
}
void CrossHair::drawBegin()
{
setDeviceLineWidth( linewidth_ );
oldstate_ = glIsEnabled(GL_LINE_SMOOTH);
if (smooth_)
glEnable(GL_LINE_SMOOTH);
else
glDisable(GL_LINE_SMOOTH);
glBegin( GL_LINES );
}
void CrossHair::drawEnd()
{
glEnd();
if (oldstate_)
glEnable(GL_LINE_SMOOTH);
else
glDisable(GL_LINE_SMOOTH);
}
void CrossHair::draw(Qwt3D::Triple const& pos)
{
RGBA rgba = (*plot->dataColor())(pos);
glColor4d(rgba.r,rgba.g,rgba.b,rgba.a);
double diag = (plot->hull().maxVertex-plot->hull().minVertex).length() * radius_;
glVertex3d( pos.x - diag, pos.y, pos.z);
glVertex3d( pos.x + diag, pos.y, pos.z);
glVertex3d( pos.x, pos.y - diag, pos.z);
glVertex3d( pos.x, pos.y + diag, pos.z);
glVertex3d( pos.x, pos.y, pos.z - diag);
glVertex3d( pos.x, pos.y, pos.z + diag);
// hull
if (!boxed_)
return;
glVertex3d( pos.x - diag, pos.y - diag, pos.z + diag);
glVertex3d( pos.x + diag, pos.y - diag, pos.z + diag);
glVertex3d( pos.x - diag, pos.y - diag, pos.z - diag);
glVertex3d( pos.x + diag, pos.y - diag, pos.z - diag);
glVertex3d( pos.x - diag, pos.y + diag, pos.z + diag);
glVertex3d( pos.x + diag, pos.y + diag, pos.z + diag);
glVertex3d( pos.x - diag, pos.y + diag, pos.z - diag);
glVertex3d( pos.x + diag, pos.y + diag, pos.z - diag);
glVertex3d( pos.x - diag, pos.y - diag, pos.z + diag);
glVertex3d( pos.x - diag, pos.y + diag, pos.z + diag);
glVertex3d( pos.x - diag, pos.y - diag, pos.z - diag);
glVertex3d( pos.x - diag, pos.y + diag, pos.z - diag);
glVertex3d( pos.x + diag, pos.y - diag, pos.z + diag);
glVertex3d( pos.x + diag, pos.y + diag, pos.z + diag);
glVertex3d( pos.x + diag, pos.y - diag, pos.z - diag);
glVertex3d( pos.x + diag, pos.y + diag, pos.z - diag);
glVertex3d( pos.x - diag, pos.y - diag, pos.z - diag);
glVertex3d( pos.x - diag, pos.y - diag, pos.z + diag);
glVertex3d( pos.x + diag, pos.y - diag, pos.z - diag);
glVertex3d( pos.x + diag, pos.y - diag, pos.z + diag);
glVertex3d( pos.x - diag, pos.y + diag, pos.z - diag);
glVertex3d( pos.x - diag, pos.y + diag, pos.z + diag);
glVertex3d( pos.x + diag, pos.y + diag, pos.z - diag);
glVertex3d( pos.x + diag, pos.y + diag, pos.z + diag);
}
/////////////////////////////////////////////////////////////////
//
// Dot
//
/////////////////////////////////////////////////////////////////
Dot::Dot()
{
configure(1, false);
}
Dot::Dot(double pointsize, bool smooth)
{
configure(pointsize, smooth);
}
void Dot::configure(double pointsize, bool smooth)
{
plot = 0;
pointsize_ = pointsize;
smooth_ = smooth;
}
void Dot::drawBegin()
{
setDevicePointSize( pointsize_ );
oldstate_ = glIsEnabled(GL_POINT_SMOOTH);
if (smooth_)
glEnable(GL_POINT_SMOOTH);
else
glDisable(GL_POINT_SMOOTH);
//glPointSize(10);
glBegin( GL_POINTS );
}
void Dot::drawEnd()
{
glEnd();
if (oldstate_)
glEnable(GL_POINT_SMOOTH);
else
glDisable(GL_POINT_SMOOTH);
}
void Dot::draw(Qwt3D::Triple const& pos)
{
RGBA rgba = (*plot->dataColor())(pos);
glColor4d(rgba.r,rgba.g,rgba.b,rgba.a);
glVertex3d( pos.x, pos.y, pos.z);
}
/////////////////////////////////////////////////////////////////
//
// Cone
//
/////////////////////////////////////////////////////////////////
Cone::Cone()
{
hat = gluNewQuadric();
disk = gluNewQuadric();
configure(0, 3);
}
Cone::Cone(double rad, unsigned quality)
{
hat = gluNewQuadric();
disk = gluNewQuadric();
configure(rad, quality);
}
Cone::~Cone()
{
gluDeleteQuadric(hat);
gluDeleteQuadric(disk);
}
void Cone::configure(double rad, unsigned quality)
{
plot = 0;
radius_ = rad;
quality_ = quality;
oldstate_ = GL_FALSE;
gluQuadricDrawStyle(hat,GLU_FILL);
gluQuadricNormals(hat,GLU_SMOOTH);
gluQuadricOrientation(hat,GLU_OUTSIDE);
gluQuadricDrawStyle(disk,GLU_FILL);
gluQuadricNormals(disk,GLU_SMOOTH);
gluQuadricOrientation(disk,GLU_OUTSIDE);
}
void Cone::draw(Qwt3D::Triple const& pos)
{
RGBA rgba = (*plot->dataColor())(pos);
glColor4d(rgba.r,rgba.g,rgba.b,rgba.a);
GLint mode;
glGetIntegerv(GL_MATRIX_MODE, &mode);
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glTranslatef(pos.x, pos.y, pos.z);
gluCylinder(hat, 0.0, radius_, radius_*2, quality_, 1);
glTranslatef(0, 0, radius_*2);
gluDisk(disk, 0.0, radius_, quality_, 1);
glPopMatrix();
glMatrixMode(mode);
}
/////////////////////////////////////////////////////////////////
//
// Arrow
//
/////////////////////////////////////////////////////////////////
Arrow::Arrow()
{
hat = gluNewQuadric();
disk = gluNewQuadric();
base = gluNewQuadric();
bottom = gluNewQuadric();
gluQuadricDrawStyle(hat,GLU_FILL);
gluQuadricNormals(hat,GLU_SMOOTH);
gluQuadricOrientation(hat,GLU_OUTSIDE);
gluQuadricDrawStyle(disk,GLU_FILL);
gluQuadricNormals(disk,GLU_SMOOTH);
gluQuadricOrientation(disk,GLU_OUTSIDE);
gluQuadricDrawStyle(base,GLU_FILL);
gluQuadricNormals(base,GLU_SMOOTH);
gluQuadricOrientation(base,GLU_OUTSIDE);
gluQuadricDrawStyle(bottom,GLU_FILL);
gluQuadricNormals(bottom,GLU_SMOOTH);
gluQuadricOrientation(bottom,GLU_OUTSIDE);
configure(3, 0.4, 0.06, 0.02);
}
Arrow::~Arrow()
{
gluDeleteQuadric(hat);
gluDeleteQuadric(disk);
gluDeleteQuadric(base);
gluDeleteQuadric(bottom);
}
/**
\param segs number of faces for the fields arrows (see the gallery for examples)
\param relconelength see picture
\param relconerad see picture
\param relstemrad see picture
\image html arrowanatomy.png
*/
void Arrow::configure(int segs, double relconelength, double relconerad, double relstemrad)
{
plot = 0;
segments_ = segs;
oldstate_ = GL_FALSE;
rel_cone_length = relconelength;
rel_cone_radius = relconerad;
rel_stem_radius = relstemrad;
}
void Arrow::draw(Qwt3D::Triple const& pos)
{
Triple end = top_;
Triple beg = pos;
Triple vdiff = end-beg;
double length = vdiff.length();
glColor4d(rgba_.r,rgba_.g,rgba_.b,rgba_.a);
double radius[2];
radius[0] = rel_cone_radius * length;
radius[1] = rel_stem_radius * length;
GLint mode;
glGetIntegerv(GL_MATRIX_MODE, &mode);
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
Triple axis;
double phi = calcRotation(axis, FreeVector(beg,end));
glTranslatef(beg.x, beg.y, beg.z);
glRotatef(phi, axis.x, axis.y, axis.z);
double baseheight = (1-rel_cone_length) * length;
glTranslatef(0, 0, baseheight);
gluCylinder(hat, radius[0], 0.0, rel_cone_length * length, segments_,1);
gluDisk(disk,radius[1],radius[0], segments_,1);
glTranslatef(0, 0, -baseheight);
gluCylinder(base, radius[1],radius[1], baseheight,segments_,1);
gluDisk(disk,0,radius[1],segments_,1);
glPopMatrix();
glMatrixMode(mode);
}
//! transform a vector on the z axis with length |beg-end|, to get them in coincidence with the vector(beg,end)
/**
\return Angle in degree to rotate
\param axis The axis to rotate around
\param beg result vector base point
\param end result vector top point
*/
double Arrow::calcRotation(Triple& axis, FreeVector const& vec)
{
Triple end = vec.top;
Triple beg = vec.base;
Triple firstbeg(0.0,0.0,0.0);
Triple firstend(0.0,0.0,(end-beg).length());
Triple first = firstend - firstbeg;
first.normalize();
Triple second = end-beg;
second.normalize();
axis = normalizedcross(first,second);
double cosphi = dotProduct(first,second);
return 180 * acos(cosphi) / Qwt3D::PI;
}
syntax highlighted by Code2HTML, v. 0.9.1