diff options
Diffstat (limited to 'lib/tqwtplot3d/src/qwt3d_coordsys.cpp')
| -rw-r--r-- | lib/tqwtplot3d/src/qwt3d_coordsys.cpp | 633 |
1 files changed, 633 insertions, 0 deletions
diff --git a/lib/tqwtplot3d/src/qwt3d_coordsys.cpp b/lib/tqwtplot3d/src/qwt3d_coordsys.cpp new file mode 100644 index 0000000..2aae28d --- /dev/null +++ b/lib/tqwtplot3d/src/qwt3d_coordsys.cpp @@ -0,0 +1,633 @@ +#include "qwt3d_coordsys.h"
+
+using namespace std;
+using namespace Qwt3D;
+
+
+CoordinateSystem::CoordinateSystem(Triple first, Triple second, COORDSTYLE st)
+{
+ autodecoration_ = true;
+ axes = std::vector<Axis>(12);
+ setStyle(st);
+ setLineSmooth(true);
+ init(first,second);
+
+ setAxesColor(RGBA(0,0,0,1));
+ setGridLinesColor(RGBA(0.2,0.2,0.2,1));
+ setNumberFont("Courier", 12);
+ setNumberColor(RGBA(0,0,0));
+ setLabelFont("Courier", 14, QFont::Bold);
+ setGridLines(false, false);
+}
+
+CoordinateSystem::~CoordinateSystem()
+{
+ destroy();
+}
+
+void CoordinateSystem::destroy()
+{
+ for (unsigned i=0; i!=axes.size(); ++i)
+ axes[i].setLabelString("");
+
+ detachAll();
+}
+
+void CoordinateSystem::init(Triple first, Triple second)
+{
+ destroy();
+
+ for (unsigned i=0; i!=axes.size(); ++i)
+ axes[i].setScale(LINEARSCALE);
+
+ Triple dv = second - first;
+
+ setPosition(first, second);
+
+ double majl = dv.length() / 100; // 1 %
+ setTicLength(majl, 0.6 * majl);
+
+ axes[X1].setPosition(first, first+Triple(dv.x, 0, 0)); // front bottom x
+ axes[Y1].setPosition(first, first+Triple( 0, dv.y, 0)); // bottom left y
+ axes[Z1].setPosition (first+Triple( 0, dv.y, 0), first+Triple( 0, dv.y, dv.z)); // back left z
+ axes[X1].setTicOrientation(0,-1,0);
+ axes[Y1].setTicOrientation(-1,0,0);
+ axes[Z1].setTicOrientation(-1,0,0);
+
+ axes[X1].setLimits(first.x, second.x);
+ axes[X2].setLimits(first.x, second.x);
+ axes[X3].setLimits(first.x, second.x);
+ axes[X4].setLimits(first.x, second.x);
+
+ axes[Y1].setLimits(first.y, second.y);
+ axes[Y2].setLimits(first.y, second.y);
+ axes[Y3].setLimits(first.y, second.y);
+ axes[Y4].setLimits(first.y, second.y);
+
+ axes[Z1].setLimits(first.z, second.z);
+ axes[Z2].setLimits(first.z, second.z);
+ axes[Z3].setLimits(first.z, second.z);
+ axes[Z4].setLimits(first.z, second.z);
+
+ // remaining x axes
+ axes[X2].setPosition(first+Triple( 0, 0, dv.z), first+Triple( dv.x, 0, dv.z)); // front top x
+ axes[X3].setPosition(first+Triple( 0, dv.y, dv.z), second); // back top x
+ axes[X4].setPosition(first+Triple( 0, dv.y, 0), first+Triple( dv.x, dv.y, 0)); // back bottom x
+ axes[X2].setTicOrientation(0,-1,0);
+ axes[X3].setTicOrientation(0,1,0);
+ axes[X4].setTicOrientation(0,1,0);
+
+ // remaining y axes
+ axes[Y2].setPosition(first+Triple(dv.x, 0, 0), first+Triple(dv.x, dv.y, 0)); // bottom right y
+ axes[Y3].setPosition(first+Triple(dv.x, 0, dv.z), second); // top right y
+ axes[Y4].setPosition(first+Triple(0, 0, dv.z), first+Triple(0, dv.y, dv.z)); // top left y
+ axes[Y2].setTicOrientation(1,0,0);
+ axes[Y3].setTicOrientation(1,0,0);
+ axes[Y4].setTicOrientation (-1,0,0);
+
+ // remaining z axes
+ axes[Z2].setPosition(first, first+Triple( 0, 0, dv.z)); // front left z
+ axes[Z4].setPosition(first+Triple(dv.x, dv.y, 0), second ); // back right z
+ axes[Z3].setPosition(first+Triple(dv.x, 0, 0), first+Triple(dv.x, 0, dv.z)); // front right z
+ axes[Z2].setTicOrientation(-1,0,0);
+ axes[Z4].setTicOrientation(1,0,0);
+ axes[Z3].setTicOrientation(1,0,0);
+
+ setStyle(style_);
+}
+
+void CoordinateSystem::draw()
+{
+// saveGLState();
+
+ GLStateBewarer sb(GL_LINE_SMOOTH, true);
+
+ if (!lineSmooth())
+ sb.turnOff();
+
+
+ if (autoDecoration())
+ chooseAxes();
+
+ Drawable::draw();
+
+ if( style_ == NOCOORD)
+ return;
+
+ if (majorgridlines_ || minorgridlines_)
+ recalculateAxesTics();
+ if (majorgridlines_)
+ drawMajorGridLines();
+ if (minorgridlines_)
+ drawMinorGridLines();
+
+ // restoreGLState();
+}
+
+
+//! build convex hull (6 axes: 2 x, 2 y, 2 z) and choose one of them at a time for scales, labels etc.
+void CoordinateSystem::chooseAxes()
+{
+ vector<Triple> beg(axes.size());
+ vector<Triple> end(axes.size());
+ vector<Tuple> src(2*axes.size());
+
+ unsigned i;
+ // collect axes viewport coordinates and initialize
+ for (i=0; i!=axes.size(); ++i)
+ {
+ if (style() != NOCOORD)
+ attach(&axes[i]);
+
+ beg[i] = World2ViewPort(axes[i].begin());
+ end[i] = World2ViewPort(axes[i].end());
+ src[i] = Tuple(beg[i].x, beg[i].y);
+ src[axes.size()+i] = Tuple(end[i].x, end[i].y);
+
+ axes[i].setScaling(false);
+ axes[i].setNumbers(false);
+ axes[i].setLabel(false);
+ }
+
+ vector<unsigned> idx;
+ convexhull2d(idx,src);
+
+ int rem_x = -1;
+ int rem_y = -1;
+ int rem_z = -1;
+
+
+ bool left;
+
+ int choice_x = -1;
+ int choice_y = -1;
+ int choice_z = -1;
+
+ int other_x = -1;
+ int other_y = -1;
+ int other_z = -1;
+
+ //traverse convex hull
+ for (unsigned k=0; k!=idx.size(); ++k)
+ {
+ Triple one, two;
+
+ if (idx[k] >= axes.size()) // is end point
+ one = end[idx[k]-axes.size()];
+ else // is begin point
+ one = beg[idx[k]];
+
+ unsigned int next = idx[(k+1) % idx.size()]; // next point in cv (considered as ring buffer of points)
+
+ if (next >= axes.size())
+ two = end[next-axes.size()];
+ else
+ two = beg[next];
+
+ for (i=0; i!=axes.size(); ++i)
+ {
+ if (
+ (one == beg[i] && two == end[i])
+ ||
+ (two == beg[i] && one == end[i])
+ )
+ {
+ if (i==X1 || i==X2 || i==X3 || i==X4) // x Achsen
+ {
+ if (rem_x>=0) // schon zweite Achse der konvexen Huelle ?
+ {
+ // untere der beiden x Achsen
+ double y = min(min(end[rem_x].y,end[i].y),min(beg[rem_x].y,beg[i].y));
+ choice_x = (y == beg[i].y || y == end[i].y) ? i : rem_x;
+
+ other_x = (choice_x == (int)i) ? rem_x : (int)i;
+ left = (beg[choice_x].x < beg[other_x].x || end[choice_x].x < end[other_x].x)
+ ? true
+ : false;
+
+ autoDecorateExposedAxis(axes[choice_x], left);
+
+ rem_x = -1;
+ }
+ else
+ {
+ rem_x = i;
+ }
+ }
+ else if (i==Y1 || i==Y2 || i==Y3 || i==Y4)
+ {
+ if (rem_y>=0)
+ {
+ // untere der beiden y Achsen
+ double y = min(min(end[rem_y].y,end[i].y),min(beg[rem_y].y,beg[i].y));
+ choice_y = (y == beg[i].y || y == end[i].y) ? i : rem_y;
+
+ other_y = (choice_y == (int)i) ? rem_y : (int)i;
+ left = (beg[choice_y].x < beg[other_y].x || end[choice_y].x < end[other_y].x)
+ ? true
+ : false;
+ autoDecorateExposedAxis(axes[choice_y], left);
+
+ rem_y = -1;
+ }
+ else
+ {
+ rem_y = i;
+ }
+ }
+ else if (i==Z1 || i==Z2 || i==Z3 || i==Z4)
+ {
+ if (rem_z>=0)
+ {
+ // hintere der beiden z Achsen
+ double z = max(max(end[rem_z].z,end[i].z),max(beg[rem_z].z,beg[i].z));
+ choice_z = (z == beg[i].z || z == end[i].z) ? i : rem_z;
+
+ other_z = (choice_z == (int)i) ? rem_z : (int)i;
+
+ rem_z = -1;
+
+ }
+ else
+ {
+ rem_z = i;
+ }
+ }
+ }
+ } // for axes
+ } // for idx
+
+ // fit z axis in - the onthewall axis if the decorated axes build a continous line, the opposite else
+ if (choice_x>=0 && choice_y>=0 && choice_z>=0)
+ {
+ left = (beg[choice_z].x < beg[other_z].x || end[choice_z].x < end[other_z].x)
+ ? true
+ : false;
+
+
+ if (
+ axes[choice_z].begin() == axes[choice_x].begin()
+ || axes[choice_z].begin() == axes[choice_x].end()
+ || axes[choice_z].begin() == axes[choice_y].begin()
+ || axes[choice_z].begin() == axes[choice_y].end()
+ || axes[choice_z].end() == axes[choice_x].begin()
+ || axes[choice_z].end() == axes[choice_x].end()
+ || axes[choice_z].end() == axes[choice_y].begin()
+ || axes[choice_z].end() == axes[choice_y].end()
+
+ )
+ {
+ autoDecorateExposedAxis(axes[choice_z], left);
+ }
+
+ else
+ {
+ autoDecorateExposedAxis(axes[other_z], !left);
+ choice_z = other_z; // for FRAME
+ }
+ }
+
+ if (style() == FRAME)
+ {
+ for (i=0; i!=axes.size(); ++i)
+ {
+ if ((int)i!=choice_x && (int)i!=choice_y && (int)i!=choice_z)
+ detach(&axes[i]);
+ }
+ }
+
+}
+
+
+void CoordinateSystem::autoDecorateExposedAxis(Axis& ax, bool left)
+{
+ Triple diff = World2ViewPort(ax.end()) - World2ViewPort(ax.begin());
+
+ diff = Triple(diff.x,diff.y,0); // projection
+
+ double s = diff.length();
+
+ if (!s)
+ return;
+
+ ax.setScaling(true);
+ ax.setNumbers(true);
+ ax.setLabel(true);
+
+ const double SQRT_2 = 0.7071067;
+ double sina = fabs(diff.y / s);
+
+
+ if (left) // leftmost (compared with antagonist in CV) axis -> draw decorations on the left side
+ {
+ if ( diff.x >= 0 && diff.y >= 0 && sina < SQRT_2) // 0..Pi/4
+ {
+ ax.setNumberAnchor(BottomCenter);
+ }
+ else if ( diff.x >= 0 && diff.y >= 0 && !left) // octant 2
+ {
+ ax.setNumberAnchor(CenterRight);
+ }
+ else if ( diff.x <= 0 && diff.y >= 0 && sina >= SQRT_2) // octant 3
+ {
+ ax.setNumberAnchor(CenterRight);
+ }
+ else if ( diff.x <= 0 && diff.y >= 0 ) // octant 4
+ {
+ ax.setNumberAnchor(TopCenter);
+ }
+ else if ( diff.x <= 0 && diff.y <= 0 && sina <= SQRT_2) // octant 5
+ {
+ ax.setNumberAnchor(BottomCenter);
+ }
+ else if ( diff.x <= 0 && diff.y <= 0) // octant 6
+ {
+ ax.setNumberAnchor(CenterRight);
+ }
+ else if ( diff.x >= 0 && diff.y <= 0 && sina >= SQRT_2) // octant 7
+ {
+ ax.setNumberAnchor(CenterRight);
+ }
+ else if ( diff.x >= 0 && diff.y <= 0) // octant 8
+ {
+ ax.setNumberAnchor(TopCenter);
+ }
+ }
+ else // rightmost axis
+ {
+ if ( diff.x >= 0 && diff.y >= 0 && sina <= SQRT_2)
+ {
+ ax.setNumberAnchor(TopCenter);
+ }
+ else if ( diff.x >= 0 && diff.y >= 0 && !left)
+ {
+ ax.setNumberAnchor(CenterLeft);
+ }
+ else if ( diff.x <= 0 && diff.y >= 0 && sina >= SQRT_2)
+ {
+ ax.setNumberAnchor(CenterLeft);
+ }
+ else if ( diff.x <= 0 && diff.y >= 0)
+ {
+ ax.setNumberAnchor(BottomCenter);
+ }
+ else if ( diff.x <= 0 && diff.y <= 0 && sina <= SQRT_2)
+ {
+ ax.setNumberAnchor(TopCenter);
+ }
+ else if ( diff.x <= 0 && diff.y <= 0)
+ {
+ ax.setNumberAnchor(CenterLeft);
+ }
+ else if ( diff.x >= 0 && diff.y <= 0 && sina >= SQRT_2)
+ {
+ ax.setNumberAnchor(CenterLeft);
+ }
+ else if ( diff.x >= 0 && diff.y <= 0)
+ {
+ ax.setNumberAnchor(BottomCenter);
+ }
+ }
+}
+
+
+void CoordinateSystem::setPosition(Triple first, Triple second)
+{
+ first_ = first;
+ second_ = second;
+}
+
+void CoordinateSystem::setTicLength(double major, double minor)
+{
+ for (unsigned i=0; i!=axes.size(); ++i)
+ axes[i].setTicLength(major, minor);
+}
+
+void CoordinateSystem::adjustNumbers(int val)
+{
+ for (unsigned i=0; i!=axes.size(); ++i)
+ axes[i].adjustNumbers(val);
+}
+
+void CoordinateSystem::adjustLabels(int val)
+{
+ for (unsigned i=0; i!=axes.size(); ++i)
+ axes[i].adjustLabel(val);
+}
+
+void CoordinateSystem::setAutoScale(bool val)
+{
+ for (unsigned i=0; i!=axes.size(); ++i)
+ axes[i].setAutoScale(val);
+}
+
+void CoordinateSystem::setAxesColor(RGBA val)
+{
+ for (unsigned i=0; i!=axes.size(); ++i)
+ axes[i].setColor(val);
+}
+
+void CoordinateSystem::recalculateAxesTics()
+{
+ for (unsigned i=0; i!=axes.size(); ++i)
+ axes[i].recalculateTics();
+}
+
+void CoordinateSystem::setNumberFont(QString const& family, int pointSize, int weight, bool italic)
+{
+ for (unsigned i=0; i!=axes.size(); ++i)
+ axes[i].setNumberFont(family,pointSize,weight,italic);
+}
+
+void CoordinateSystem::setNumberFont(QFont const& font)
+{
+ for (unsigned i=0; i!=axes.size(); ++i)
+ axes[i].setNumberFont(font);
+}
+
+void CoordinateSystem::setNumberColor(RGBA val)
+{
+ for (unsigned i=0; i!=axes.size(); ++i)
+ axes[i].setNumberColor( val);
+}
+
+void CoordinateSystem::setStandardScale()
+{
+ for (unsigned i=0; i!=axes.size(); ++i)
+ axes[i].setScale(LINEARSCALE);
+}
+
+void CoordinateSystem::setLabelFont(QFont const& font)
+{
+ for (unsigned i=0; i!=axes.size(); ++i)
+ axes[i].setLabelFont(font);
+}
+
+
+void CoordinateSystem::setLabelFont(QString const& family, int pointSize, int weight, bool italic)
+{
+ setLabelFont(QFont(family,pointSize,weight,italic));
+}
+
+void CoordinateSystem::setLabelColor(RGBA val)
+{
+ for (unsigned i=0; i!=axes.size(); ++i)
+ axes[i].setLabelColor(val);
+}
+
+void CoordinateSystem::setLineWidth(double val, double majfac, double minfac)
+{
+ for (unsigned i=0; i!=axes.size(); ++i)
+ axes[i].setLineWidth(val, majfac, minfac);
+}
+
+void CoordinateSystem::setStyle(COORDSTYLE s, AXIS frame_1, AXIS frame_2, AXIS frame_3)
+{
+ style_ = s;
+
+ switch (s)
+ {
+ case NOCOORD:
+ {
+ for (unsigned i=0; i!=axes.size(); ++i)
+ detach (&axes[i]);
+ }
+ break;
+ case BOX:
+ {
+ for (unsigned i=0; i!=axes.size(); ++i)
+ attach (&axes[i]);
+ }
+ break;
+ case FRAME:
+ {
+ for (unsigned i=0; i!=axes.size(); ++i)
+ detach (&axes[i]);
+ if (!autoDecoration())
+ {
+ attach(&axes[frame_1]);
+ attach(&axes[frame_2]);
+ attach(&axes[frame_3]);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+The axis used for tic calculation is chosen randomly from the respective pair.
+For most cases an identical tic distribution is therefore recommended.
+\param majors Draw grid between major tics
+\param minors Draw grid between minor tics
+\param sides Side(s), where the grid should be drawn
+*/
+void CoordinateSystem::setGridLines(bool majors, bool minors, int sides)
+{
+ sides_ = sides;
+ majorgridlines_ = majors;
+ minorgridlines_ = minors;
+}
+
+void CoordinateSystem::drawMajorGridLines()
+{
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glColor4d(gridlinecolor_.r,gridlinecolor_.g,gridlinecolor_.b,gridlinecolor_.a);
+ setDeviceLineWidth(axes[X1].majLineWidth());
+
+ glBegin( GL_LINES );
+ if (sides_ & Qwt3D::FLOOR)
+ {
+ drawMajorGridLines(axes[X1],axes[X4]);
+ drawMajorGridLines(axes[Y1],axes[Y2]);
+ }
+ if (sides_ & Qwt3D::CEIL)
+ {
+ drawMajorGridLines(axes[X2],axes[X3]);
+ drawMajorGridLines(axes[Y3],axes[Y4]);
+ }
+ if (sides_ & Qwt3D::LEFT)
+ {
+ drawMajorGridLines(axes[Y1],axes[Y4]);
+ drawMajorGridLines(axes[Z1],axes[Z2]);
+ }
+ if (sides_ & Qwt3D::RIGHT)
+ {
+ drawMajorGridLines(axes[Y2],axes[Y3]);
+ drawMajorGridLines(axes[Z3],axes[Z4]);
+ }
+ if (sides_ & Qwt3D::FRONT)
+ {
+ drawMajorGridLines(axes[X1],axes[X2]);
+ drawMajorGridLines(axes[Z2],axes[Z3]);
+ }
+ if (sides_ & Qwt3D::BACK)
+ {
+ drawMajorGridLines(axes[X3],axes[X4]);
+ drawMajorGridLines(axes[Z4],axes[Z1]);
+ }
+ glEnd();
+}
+
+void CoordinateSystem::drawMinorGridLines()
+{
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glColor4d(gridlinecolor_.r,gridlinecolor_.g,gridlinecolor_.b,gridlinecolor_.a);
+ setDeviceLineWidth(axes[X1].minLineWidth());
+
+ glBegin( GL_LINES );
+ if (sides_ & Qwt3D::FLOOR)
+ {
+ drawMinorGridLines(axes[X1],axes[X4]);
+ drawMinorGridLines(axes[Y1],axes[Y2]);
+ }
+ if (sides_ & Qwt3D::CEIL)
+ {
+ drawMinorGridLines(axes[X2],axes[X3]);
+ drawMinorGridLines(axes[Y3],axes[Y4]);
+ }
+ if (sides_ & Qwt3D::LEFT)
+ {
+ drawMinorGridLines(axes[Y1],axes[Y4]);
+ drawMinorGridLines(axes[Z1],axes[Z2]);
+ }
+ if (sides_ & Qwt3D::RIGHT)
+ {
+ drawMinorGridLines(axes[Y2],axes[Y3]);
+ drawMinorGridLines(axes[Z3],axes[Z4]);
+ }
+ if (sides_ & Qwt3D::FRONT)
+ {
+ drawMinorGridLines(axes[X1],axes[X2]);
+ drawMinorGridLines(axes[Z2],axes[Z3]);
+ }
+ if (sides_ & Qwt3D::BACK)
+ {
+ drawMinorGridLines(axes[X3],axes[X4]);
+ drawMinorGridLines(axes[Z4],axes[Z1]);
+ }
+ glEnd();
+}
+
+void CoordinateSystem::drawMajorGridLines(Axis& a0, Axis& a1)
+{
+ Triple d = a1.begin()-a0.begin();
+
+ for (unsigned int i=0; i!=a0.majorPositions().size(); ++i)
+ {
+ glVertex3d( a0.majorPositions()[i].x, a0.majorPositions()[i].y, a0.majorPositions()[i].z );
+ glVertex3d( a0.majorPositions()[i].x + d.x, a0.majorPositions()[i].y + d.y, a0.majorPositions()[i].z +d.z);
+ }
+}
+
+void CoordinateSystem::drawMinorGridLines(Axis& a0, Axis& a1)
+{
+ Triple d = a1.begin()-a0.begin();
+
+ for (unsigned int i=0; i!=a0.minorPositions().size(); ++i)
+ {
+ glVertex3d( a0.minorPositions()[i].x, a0.minorPositions()[i].y, a0.minorPositions()[i].z );
+ glVertex3d( a0.minorPositions()[i].x + d.x, a0.minorPositions()[i].y + d.y, a0.minorPositions()[i].z +d.z);
+ }
+}
|
