summaryrefslogtreecommitdiff
path: root/dwr/tools.cc
diff options
context:
space:
mode:
Diffstat (limited to 'dwr/tools.cc')
-rw-r--r--dwr/tools.cc243
1 files changed, 243 insertions, 0 deletions
diff --git a/dwr/tools.cc b/dwr/tools.cc
new file mode 100644
index 0000000..d45ebd3
--- /dev/null
+++ b/dwr/tools.cc
@@ -0,0 +1,243 @@
+/*
+ * RTFL
+ *
+ * Copyright 2013-2015 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version; with the following exception:
+ *
+ * The copyright holders of RTFL give you permission to link this file
+ * statically or dynamically against all versions of the graphviz
+ * library, which are published by AT&T Corp. under one of the following
+ * licenses:
+ *
+ * - Common Public License version 1.0 as published by International
+ * Business Machines Corporation (IBM), or
+ * - Eclipse Public License version 1.0 as published by the Eclipse
+ * Foundation.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ----------------------------------------------------------------------
+ *
+ * A part of the code was written by Keith Vertanen and has been
+ * released to the public domain; see below.
+ */
+
+#include "tools.hh"
+
+#include <math.h>
+
+using namespace dw::core;
+using namespace dw::core::style;
+
+namespace rtfl {
+
+namespace dw {
+
+namespace tools {
+
+// Used for b-splines, see below.
+struct point {
+ double x;
+ double y;
+ double z;
+};
+
+static void bspline (int n, int t, point *control, point *output,
+ int num_output);
+
+void drawArrowHead (View *view, Style *style,
+ int x1, int y1, int x2, int y2, int aheadlen)
+{
+ if (x1 != x2 || y1 != y2) {
+ // TODO: Use faster algorithm avoding floating point numbers. Also,
+ // regard that using integers could cause overflow errors.
+
+ int l = sqrt ((double)(x2 - x1) * (double)(x2 - x1) +
+ (double)(y2 - y1) * (double)(y2 - y1));
+ int x3 = (aheadlen * x1 + (l - aheadlen) * x2) / l;
+ int y3 = (aheadlen * y1 + (l - aheadlen) * y2) / l;
+
+ int x4 = x3 - (y2 - y3) / 2;
+ int y4 = y3 + (x2 - x3) / 2;
+ view->drawLine (style->color, Color::SHADING_NORMAL, x2, y2, x4, y4);
+
+ int x5 = x3 + (y2 - y3) / 2;
+ int y5 = y3 - (x2 - x3) / 2;
+ view->drawLine (style->color, Color::SHADING_NORMAL, x2, y2, x5, y5);
+ }
+}
+
+void drawBSpline (::dw::core::View *view, ::dw::core::style::Style *style,
+ int degree, int numPoints, int *x, int *y)
+{
+ point *in = new point[numPoints];
+ for (int i = 0; i < numPoints; i++) {
+ in[i].x = x[i];
+ in[i].y = y[i];
+ in[i].z = 0;
+ }
+
+ int numOut = 5 * numPoints;
+ point *out = new point[numOut];
+
+ bspline(numPoints - 1, degree, in, out, numOut);
+
+ for (int i = 0; i < numOut - 1; i++)
+ view->drawLine (style->color, ::dw::core::style::Color::SHADING_NORMAL,
+ out[i].x, out[i].y,
+ out[i + 1].x, out[i + 1].y);
+
+ delete[] in;
+ delete[] out;
+}
+
+/* ----------------------------------------------------------------------
+ The following code was copied from
+ <ftp://ftp.grnet.gr/pub/lang/algorithms/c++/bspline.cpp>.
+
+ It should be modified so that it is better adapted to our needs
+ (no z coordinate, no unnecessary conversion between int and
+ double, etc.)
+ ---------------------------------------------------------------------- */
+
+/*********************************************************************
+
+ Simple b-spline curve algorithm
+
+ Copyright 1994 by Keith Vertanen (vertankd@cda.mrs.umn.edu)
+
+ Released to the public domain (your mileage may vary)
+
+**********************************************************************/
+
+static void compute_intervals(int *u, int n, int t);
+static double blend(int k, int t, int *u, double v);
+static void compute_point(int *u, int n, int t, double v, point *control,
+ point *output);
+
+void bspline(int n, int t, point *control, point *output, int num_output)
+
+/*********************************************************************
+
+Parameters:
+ n - the number of control points minus 1
+ t - the degree of the polynomial plus 1
+ control - control point array made up of point stucture
+ output - array in which the calculate spline points are to be put
+ num_output - how many points on the spline are to be calculated
+
+Pre-conditions:
+ n+2>t (no curve results if n+2<=t)
+ control array contains the number of points specified by n
+ output array is the proper size to hold num_output point structures
+
+
+**********************************************************************/
+
+{
+ int *u;
+ double increment,interval;
+ point calcxyz;
+ int output_index;
+
+ u=new int[n+t+1];
+ compute_intervals(u, n, t);
+
+ increment=(double) (n-t+2)/(num_output-1); // how much parameter goes up each time
+ interval=0;
+
+ for (output_index=0; output_index<num_output-1; output_index++)
+ {
+ compute_point(u, n, t, interval, control, &calcxyz);
+ output[output_index].x = calcxyz.x;
+ output[output_index].y = calcxyz.y;
+ output[output_index].z = calcxyz.z;
+ interval=interval+increment; // increment our parameter
+ }
+ output[num_output-1].x=control[n].x; // put in the last point
+ output[num_output-1].y=control[n].y;
+ output[num_output-1].z=control[n].z;
+
+ delete u;
+}
+
+double blend(int k, int t, int *u, double v) // calculate the blending value
+{
+ double value;
+
+ if (t==1) // base case for the recursion
+ {
+ if ((u[k]<=v) && (v<u[k+1]))
+ value=1;
+ else
+ value=0;
+ }
+ else
+ {
+ if ((u[k+t-1]==u[k]) && (u[k+t]==u[k+1])) // check for divide by zero
+ value = 0;
+ else
+ if (u[k+t-1]==u[k]) // if a term's denominator is zero,use just the other
+ value = (u[k+t] - v) / (u[k+t] - u[k+1]) * blend(k+1, t-1, u, v);
+ else
+ if (u[k+t]==u[k+1])
+ value = (v - u[k]) / (u[k+t-1] - u[k]) * blend(k, t-1, u, v);
+ else
+ value = (v - u[k]) / (u[k+t-1] - u[k]) * blend(k, t-1, u, v) +
+ (u[k+t] - v) / (u[k+t] - u[k+1]) * blend(k+1, t-1, u, v);
+ }
+ return value;
+}
+
+void compute_intervals(int *u, int n, int t) // figure out the knots
+{
+ int j;
+
+ for (j=0; j<=n+t; j++)
+ {
+ if (j<t)
+ u[j]=0;
+ else
+ if ((t<=j) && (j<=n))
+ u[j]=j-t+1;
+ else
+ if (j>n)
+ u[j]=n-t+2; // if n-t=-2 then we're screwed, everything goes to 0
+ }
+}
+
+void compute_point(int *u, int n, int t, double v, point *control,
+ point *output)
+{
+ int k;
+ double temp;
+
+ // initialize the variables that will hold our outputted point
+ output->x=0;
+ output->y=0;
+ output->z=0;
+
+ for (k=0; k<=n; k++)
+ {
+ temp = blend(k,t,u,v); // same blend is used for each dimension coordinate
+ output->x = output->x + (control[k]).x * temp;
+ output->y = output->y + (control[k]).y * temp;
+ output->z = output->z + (control[k]).z * temp;
+ }
+}
+
+} // namespace tools
+
+} // namespace rtfl
+
+} // namespace dw