[dasher] Added DasherSpaceLine to draw lines on screen that are straight in Dasher-space
- From: Patrick Welche <pwelche src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dasher] Added DasherSpaceLine to draw lines on screen that are straight in Dasher-space
- Date: Mon, 17 May 2010 11:43:24 +0000 (UTC)
commit 05c4d21fe28272110c5b76ad44fca7313a8b5f00
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date: Wed Jan 6 21:24:27 2010 +0000
Added DasherSpaceLine to draw lines on screen that are straight in Dasher-space
(and hence curved on the screen if nonlinearity is enabled.) These can be used
for the mouse line according to new BP_CURVE_MOUSE_LINE (off by default).
Also fix DasherViewSq & IntfBase to handle runtime changes in BP_NONLINEAR_Y
Src/DasherCore/DasherInterfaceBase.cpp | 1 +
Src/DasherCore/DasherView.cpp | 50 +++++++++++++++++++++++
Src/DasherCore/DasherView.h | 20 +++++++++-
Src/DasherCore/DasherViewSquare.cpp | 68 ++++++++++++++++++++++++++++++--
Src/DasherCore/DasherViewSquare.h | 4 ++
Src/DasherCore/DefaultFilter.cpp | 6 ++-
Src/DasherCore/Parameters.h | 3 +-
7 files changed, 144 insertions(+), 8 deletions(-)
---
diff --git a/Src/DasherCore/DasherInterfaceBase.cpp b/Src/DasherCore/DasherInterfaceBase.cpp
index dbd7881..d8b785f 100644
--- a/Src/DasherCore/DasherInterfaceBase.cpp
+++ b/Src/DasherCore/DasherInterfaceBase.cpp
@@ -326,6 +326,7 @@ void CDasherInterfaceBase::InterfaceEventHandler(Dasher::CEvent *pEvent) {
ScheduleRedraw();
break;
case LP_MARGIN_WIDTH:
+ case BP_NONLINEAR_Y:
ScheduleRedraw();
break;
case LP_NODE_BUDGET:
diff --git a/Src/DasherCore/DasherView.cpp b/Src/DasherCore/DasherView.cpp
index 1c83283..08b9f6a 100644
--- a/Src/DasherCore/DasherView.cpp
+++ b/Src/DasherCore/DasherView.cpp
@@ -29,6 +29,7 @@
#include "DasherScreen.h"
using namespace Dasher;
+using std::vector;
// Track memory leaks on Windows to the line that new'd the memory
#ifdef _WIN32
@@ -105,6 +106,55 @@ void CDasherView::Display() {
m_pScreen->Display();
}
+void CDasherView::DasherSpaceLine(myint x1, myint y1, myint x2, myint y2, int iWidth, int iColor) {
+ if (!ClipLineToVisible(x1, y1, x2, y2)) return;
+ vector<CDasherScreen::point> vPoints;
+ CDasherScreen::point p;
+ Dasher2Screen(x1, y1, p.x, p.y);
+ vPoints.push_back(p);
+ DasherLine2Screen(x1,y1,x2,y2,vPoints);
+ CDasherScreen::point *pts = new CDasherScreen::point[vPoints.size()];
+ for (int i = vPoints.size(); i-->0; ) pts[i] = vPoints[i];
+ Screen()->Polyline(pts, vPoints.size(), iWidth, iColor);
+}
+
+bool CDasherView::ClipLineToVisible(myint &x1, myint &y1, myint &x2, myint &y2) {
+ if (x1 > x2) return ClipLineToVisible(x2,y2,x1,y1);
+ //ok. have x1 <= x2...
+ myint iDasherMinX, iDasherMinY, iDasherMaxX, iDasherMaxY;
+ VisibleRegion(iDasherMinX, iDasherMinY, iDasherMaxX, iDasherMaxY);
+ if (x1 > iDasherMaxX) {
+ DASHER_ASSERT(x2>iDasherMaxX);
+ return false; //entirely offscreen!
+ }
+ if (x2 < iDasherMinX) {
+ DASHER_ASSERT(x1<iDasherMinX);
+ return false;
+ }
+ if (y1 < iDasherMinY && y2 < iDasherMinY) return false;
+ if (y1 > iDasherMaxY && y2 > iDasherMaxY) return false;
+ if (x1 < iDasherMinX) {
+ y1 = y2+((y1-y2)*(iDasherMinX-x2)/(x1 - x2));
+ x1 = iDasherMinX;
+ }
+ if (x2 > iDasherMaxX) {
+ y2 = y1 + (y2-y1)*(iDasherMaxX-x1)/(x2-x1);
+ x2 = iDasherMaxX;
+ }
+ for (int i=0; i<2; i++) {
+ myint &y(i ? y2 : y1), &oy(i ? y1 : y2);
+ myint &x(i ? x2 : x1), &ox(i ? x1 : x2);
+ if (y<iDasherMinY) {
+ x = ox- (ox-x)*(oy-iDasherMinY)/(oy-y);
+ y = iDasherMinY;
+ } else if (y>iDasherMaxY) {
+ x = ox-(ox-x)*(oy-iDasherMaxY)/(oy-y);
+ y = iDasherMaxY;
+ }
+ }
+ return true;
+}
+
/// Draw a polyline specified in Dasher co-ordinates
void CDasherView::DasherPolyline(myint *x, myint *y, int n, int iWidth, int iColour) {
diff --git a/Src/DasherCore/DasherView.h b/Src/DasherCore/DasherView.h
index 9d45981..28416f7 100644
--- a/Src/DasherCore/DasherView.h
+++ b/Src/DasherCore/DasherView.h
@@ -6,7 +6,6 @@
#define __DasherView_h_
namespace Dasher {
- class CDasherScreen;
class CDasherModel;
class CDasherInput; // Why does DasherView care about input? - pconlon
class CDasherComponent;
@@ -17,6 +16,7 @@ namespace Dasher {
#include "DasherTypes.h"
#include "DasherComponent.h"
#include "ExpansionPolicy.h"
+#include "DasherScreen.h"
/// \defgroup View Visualisation of the model
/// @{
@@ -136,6 +136,9 @@ public:
/// Basic drawing primitives specified in Dasher coordinates.
/// @{
+ ///Draw a straight line in Dasher-space - which may be curved on the screen...
+ void DasherSpaceLine(myint x1, myint y1, myint x2, myint y2, int iWidth, int iColour);
+
///
/// Draw a polyline specified in Dasher co-ordinates
///
@@ -168,6 +171,21 @@ public:
/// @}
protected:
+ /// Clips a line (specified in Dasher co-ordinates) to the visible region
+ /// by intersecting with all boundaries.
+ /// \return true if any part of the line was within the visible region; in this case, (x1,y1)-(x2,y2) delineate exactly that part
+ /// false if the line would be entirely outside the visible region; x1, y1, x2, y2 unaffected.
+ bool ClipLineToVisible(myint &x1, myint &y1, myint &x2, myint &y2);
+
+ ///Convert a straight line in Dasher-space, to coordinates for a corresponding polyline on the screen
+ /// (because of nonlinearity, this may require multiple line segments)
+ /// \param x1,y1 Dasher co-ordinates of start of line segment; note that these are guaranteed within VisibleRegion.
+ /// \param x2,y2 Dasher co-ordinates of end of line segment; also guaranteed within VisibleRegion.
+ /// \param vPoints vector to which to add screen points. Note that at the point that DasherLine2Screen is called,
+ /// the screen coordinates of the first point should already have been added to this vector; DasherLine2Screen
+ /// will then add exactly one CDasherScreen::point for each line segment required.
+ virtual void DasherLine2Screen(myint x1, myint y1, myint x2, myint y2, std::vector<CDasherScreen::point> &vPoints)=0;
+
// Orientation of Dasher Screen
/* inline void MapScreen(screenint * DrawX, screenint * DrawY); */
/* inline void UnMapScreen(screenint * DrawX, screenint * DrawY); */
diff --git a/Src/DasherCore/DasherViewSquare.cpp b/Src/DasherCore/DasherViewSquare.cpp
index 309da14..52f0c0a 100644
--- a/Src/DasherCore/DasherViewSquare.cpp
+++ b/Src/DasherCore/DasherViewSquare.cpp
@@ -27,7 +27,6 @@
//#include "DasherGameMode.h"
#include "DasherViewSquare.h"
#include "DasherModel.h"
-#include "DasherScreen.h"
#include "DasherView.h"
#include "DasherTypes.h"
#include "Event.h"
@@ -92,9 +91,10 @@ void CDasherViewSquare::HandleEvent(Dasher::CEvent *pEvent) {
m_bVisibleRegionValid = false;
break;
case LP_MARGIN_WIDTH:
- m_bVisibleRegionValid = false;
- SetScaleFactor();
- break;
+ case BP_NONLINEAR_Y:
+ m_bVisibleRegionValid = false;
+ SetScaleFactor();
+ break;
default:
break;
}
@@ -796,6 +796,66 @@ void CDasherViewSquare::Dasher2Polar(myint iDasherX, myint iDasherY, double &r,
r = sqrt(x * x + y * y);
}
+void CDasherViewSquare::DasherLine2Screen(myint x1, myint y1, myint x2, myint y2, vector<CDasherScreen::point> &vPoints) {
+ if (x1!=x2 && y1!=y2 && GetBoolParameter(BP_NONLINEAR_Y)) {
+ //only diagonal lines ever get changed...
+ if ((y1 < m_Y3 && y2 > m_Y3) ||(y2 < m_Y3 && y1 > m_Y3)) {
+ //crosses bottom non-linearity border
+ int x_mid = x1+(x2-x1) * (m_Y3-y1)/(y2-y1);
+ DasherLine2Screen(x1, y1, x_mid, m_Y3, vPoints);
+ x1=x_mid; y1=m_Y3;
+ }//else //no, a single line might cross _both_ borders!
+ if ((y1 > m_Y2 && y2 < m_Y2) || (y2 > m_Y2 && y1 < m_Y2)) {
+ //crosses top non-linearity border
+ int x_mid = x1 + (x2-x1) * (m_Y2-y1)/(y2-y1);
+ DasherLine2Screen(x1, y1, x_mid, m_Y2, vPoints);
+ x1=x_mid; y1=m_Y2;
+ }
+ double dMax(static_cast<double>(GetLongParameter(LP_MAX_Y)));
+ if (GetBoolParameter(BP_NONLINEAR_Y) && (x1 / dMax > m_dXmpb || x2 / dMax > m_dXmpb)) {
+ //into logarithmic section
+ CDasherScreen::point pStart, pScreenMid, pEnd;
+ Dasher2Screen(x2, y2, pEnd.x, pEnd.y);
+ for(;;) {
+ Dasher2Screen(x1, y1, pStart.x, pStart.y);
+ //a straight line on the screen between pStart and pEnd passes through pScreenMid:
+ pScreenMid.x = (pStart.x + pEnd.x)/2;
+ pScreenMid.y = (pStart.y + pEnd.y)/2;
+ //whereas a straight line _in_Dasher_space_ passes through pDasherMid:
+ int xMid=(x1+x2)/2, yMid=(y1+y2)/2;
+ CDasherScreen::point pDasherMid;
+ Dasher2Screen(xMid, yMid, pDasherMid.x, pDasherMid.y);
+
+ //since we know both endpoints are in the same section of the screen wrt. Y nonlinearity,
+ //the midpoint along the DasherY axis of both lines should be the same.
+ const Dasher::Opts::ScreenOrientations orient(Dasher::Opts::ScreenOrientations(GetLongParameter(LP_REAL_ORIENTATION)));
+ if (orient==Dasher::Opts::LeftToRight || orient==Dasher::Opts::RightToLeft) {
+ DASHER_ASSERT(abs(pDasherMid.y - pScreenMid.y)<=1);//allow for rounding error
+ if (abs(pDasherMid.x - pScreenMid.x)<=1) break; //call a straight line accurate enough
+ } else {
+ DASHER_ASSERT(abs(pDasherMid.x - pScreenMid.x)<=1);
+ if (abs(pDasherMid.y - pScreenMid.y)<=1) break;
+ }
+ //line should appear bent. Subdivide!
+ DasherLine2Screen(x1,y1,xMid,yMid,vPoints); //recurse for first half (to Dasher-space midpoint)
+ x1=xMid; y1=yMid; //& loop round for second half
+ }
+ //broke out of loop. a straight line (x1,y1)-(x2,y2) on the screen is an accurate portrayal of a straight line in Dasher-space.
+ vPoints.push_back(pEnd);
+ return;
+ }
+ //ok, not in x nonlinear section; fall through.
+ }
+#ifdef DEBUG
+ CDasherScreen::point pTest;
+ Dasher2Screen(x1, y1, pTest.x, pTest.y);
+ DASHER_ASSERT(vPoints.back().x == pTest.x && vPoints.back().y == pTest.y);
+#endif
+ CDasherScreen::point p;
+ Dasher2Screen(x2, y2, p.x, p.y);
+ vPoints.push_back(p);
+}
+
void CDasherViewSquare::VisibleRegion( myint &iDasherMinX, myint &iDasherMinY, myint &iDasherMaxX, myint &iDasherMaxY ) {
// TODO: Change output parameters to pointers and allow NULL to mean
// 'I don't care'. Need to be slightly careful about this as it will
diff --git a/Src/DasherCore/DasherViewSquare.h b/Src/DasherCore/DasherViewSquare.h
index 156383c..81ca815 100644
--- a/Src/DasherCore/DasherViewSquare.h
+++ b/Src/DasherCore/DasherViewSquare.h
@@ -6,6 +6,7 @@
#define __DasherViewSquare_h__
#include "DasherView.h"
#include "DelayedDraw.h"
+#include "DasherScreen.h"
#include <deque>
#include "Alphabet/GroupInfo.h"
@@ -97,6 +98,7 @@ public:
/// @}
+ void DasherSpaceLine(myint x1, myint x2, myint y1, myint y2, int iColor, int iWidth);
private:
///
@@ -170,6 +172,8 @@ private:
inline myint CustomIDiv(myint iNumerator, myint iDenominator);
+ void DasherLine2Screen(myint x1, myint y1, myint x2, myint y2, vector<CDasherScreen::point> &vPoints);
+
// Called on screen size changes
void SetScaleFactor();
diff --git a/Src/DasherCore/DefaultFilter.cpp b/Src/DasherCore/DefaultFilter.cpp
index 80a7550..b5fdffe 100644
--- a/Src/DasherCore/DefaultFilter.cpp
+++ b/Src/DasherCore/DefaultFilter.cpp
@@ -159,8 +159,10 @@ void CDefaultFilter::DrawMouseLine(CDasherView *pView) {
ApplyTransform(x[1], y[1]);
// Actually plot the line
-
- pView->DasherPolyline(x, y, 2, GetLongParameter(LP_LINE_WIDTH), 1);
+ if (GetBoolParameter(BP_CURVE_MOUSE_LINE))
+ pView->DasherSpaceLine(x[0],y[0],x[1],y[1], GetLongParameter(LP_LINE_WIDTH), 1);
+ else
+ pView->DasherPolyline(x, y, 2, GetLongParameter(LP_LINE_WIDTH), 1);
/* // Plot a brachistochrone
diff --git a/Src/DasherCore/Parameters.h b/Src/DasherCore/Parameters.h
index 7727a8e..a7436a2 100644
--- a/Src/DasherCore/Parameters.h
+++ b/Src/DasherCore/Parameters.h
@@ -30,7 +30,7 @@
// All parameters go into the enums here
// They are unique across the different types
enum {
- BP_DRAW_MOUSE_LINE, BP_DRAW_MOUSE,
+ BP_DRAW_MOUSE_LINE, BP_DRAW_MOUSE, BP_CURVE_MOUSE_LINE,
BP_SHOW_SLIDER, BP_START_MOUSE,
BP_START_SPACE, BP_START_STYLUS, BP_STOP_IDLE, BP_KEY_CONTROL, BP_CONTROL_MODE,
BP_COLOUR_MODE, BP_MOUSEPOS_MODE,
@@ -124,6 +124,7 @@ struct sp_table {
static bp_table boolparamtable[] = {
{BP_DRAW_MOUSE_LINE, "DrawMouseLine", PERS, true, "Draw Mouse Line"},
{BP_DRAW_MOUSE, "DrawMouse", PERS, false, "Draw Mouse Position"},
+ {BP_CURVE_MOUSE_LINE, "CurveMouseLine", PERS, false, "Curve mouse line according to screen nonlinearity"},
#ifdef WITH_MAEMO
{BP_SHOW_SLIDER, "ShowSpeedSlider", PERS, false, "ShowSpeedSlider"},
#else
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]