/*
GeoGebra - Dynamic Mathematics for Schools
Copyright Markus Hohenwarter and GeoGebra Inc., http://www.geogebra.org
This file is part of GeoGebra.
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.
*/
/*
* Polyline.java
*
* Created on 16. November 2001, 09:26
*/
package org.geogebra.desktop.euclidian;
import java.awt.geom.GeneralPath;
import java.util.Iterator;
import java.util.List;
import org.geogebra.common.awt.GPoint;
import org.geogebra.common.euclidian.draw.DrawConic;
/**
* adapted from polyline
*
* @author Michael Borcherds
*/
public class PolyBezier {
int n;
private int max_capacity = DrawConic.MAX_PLOT_POINTS;
double[] x, y;
public GeneralPath gp = new GeneralPath();
// Creates new Polyline for n vertices
public PolyBezier(int n) {
setNumberOfPoints(n);
}
public PolyBezier(List<GPoint> al) {
setNumberOfPoints(al.size());
int i = 0;
Iterator<GPoint> it = al.iterator();
while (it.hasNext()) {
GPoint p = it.next();
x[i] = p.getX();
y[i] = p.getY();
i++;
}
buildGeneralPath();
}
public void setPoints(int n, double[] x, double[] y) {
this.n = n;
this.x = x;
this.y = y;
}
void setNumberOfPoints(int n) {
this.n = n;
if (n > max_capacity || x == null) {
max_capacity = n;
x = new double[max_capacity];
y = new double[max_capacity];
}
}
/**
* builds a general path of a polyline from points (x[0], y[0]) to (x[n-1],
* y[n-1])
*/
final public void buildGeneralPath() {
double u[] = new double[n + 1];
double X2[];// = new double[n + 1];
double Y2[];// = new double[n + 1];
double Xb[];// = new double[4];
double Yb[];// = new double[4];
for (int i = 0; i <= n - 1; i++)
{
u[i] = i; // dummy x-coordinates
}
double xp1 = 1e32d, xpn = 1e32d; // "natural" end condition
double yp1 = 1e32d, ypn = 1e32d; // "natural" end condition
// double xp1 = x[2]-x[1], xpn=x[n]-x[n-1];
// double yp1 = y[2]-y[1], ypn=y[n]-y[n-1];
X2 = spline(u, x, n - 1, xp1, xpn); // x-coords
Y2 = spline(u, y, n - 1, yp1, ypn); // y-coords
gp.reset();
gp.moveTo((float) x[0], (float) y[0]); // starting point
// gp.lineTo((float) x[1], (float) y[1]);
// gp.lineTo((float) x[2], (float) y[2]);
for (int i = 0; i < n - 1; i++) {
Xb = tobezier(x, X2, i);
Yb = tobezier(y, Y2, i);
if (i % 2 == 10) {
gp.moveTo((float) Xb[3], (float) Yb[3]);
} else {
gp.curveTo((float) Xb[1], (float) Yb[1], (float) Xb[2],
(float) Yb[2], (float) Xb[3], (float) Yb[3]);
}
}
}
public void addline(double x, double y) {
if (Math.abs(x) < Float.MAX_VALUE && Math.abs(y) < Float.MAX_VALUE) {
gp.lineTo((float) x, (float) y);
}
}
public static double[] tobezier(double xa[], double x2a[], int k) {
double U[] = new double[4];
double x0 = xa[k];
double x1 = xa[k + 1];
double s0 = x2a[k];
double s1 = x2a[k + 1];
U[0] = x0;
U[3] = x1;
U[1] = (2d * x0 + x1 - (2d * s0 + s1) / 6d) / 3d;
U[2] = (x0 + 2d * x1 - (s0 + 2d * s1) / 6d) / 3d;
return U;
}
public static double[] spline(double x[], double y[], int n, double yp1,
double ypn) {
double y2[] = new double[n + 1];
double u[] = new double[n + 1];
double sig, p, un, qn;
int i0, i1;
i0 = 0;
i1 = i0 + 1;
if (yp1 > 1e30d) {
y2[i0] = 0d;
u[i0] = 0d;
} else {
y2[i0] = -0.5d;
u[i0] = (3d / (x[i1] - x[i0]))
* ((y[i1] - y[i0]) / (x[i1] - x[i0]) - yp1);
}
for (int i = i1; i <= n - 1; i++) {
sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]);
p = sig * y2[i - 1] + 2d;
y2[i] = (sig - 1d) / p;
u[i] = (6d
* ((y[i + 1] - y[i]) / (x[i + 1] - x[i])
- (y[i] - y[i - 1]) / (x[i] - x[i - 1]))
/ (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p;
}
if (ypn > 1e30d) {
qn = 0d;
un = 0d;
} else {
qn = 0.5d;
un = (3d / (x[n] - x[n - 1]))
* (ypn - (y[n] - y[n - 1]) / (x[n] - x[n - 1]));
}
y2[n] = (un - qn * u[n - 1]) / (qn * y2[n - 1] + 1d);
for (int k = n - 1; k >= i0; k--) {
y2[k] = y2[k] * y2[k + 1] + u[k];
}
return y2;
}
public static double[] findCoefs(double a[], int n) {
int i;
double b[] = new double[n + 1];
double r[] = new double[n + 1];
double c[] = new double[n + 1];
b[0] = 2 * (a[1] - a[0]) / 3.0;
for (i = 1; i < n; i++) {
b[i] = a[i + 1] - a[i - 1];
}
b[n] = 2 * (a[n] - a[n - 1]) / 3.0;
r[n] = 1;
r[n - 1] = 1;
for (i = n - 2; i >= 0; i--) {
r[i] = 4 * r[i + 1] - r[i + 2];
}
for (i = 1; i <= n; i += 2) {
r[i] = -r[i];
}
c[0] = 0.0;
for (i = n; i >= 0; i--) {
c[0] += r[i] * b[i];
}
c[0] /= (r[0] + r[1]);
c[1] = b[0] - c[0];
for (i = 1; i < n; i++) {
c[i + 1] = b[i] - 4 * c[i] - c[i - 1];
}
return c;
}
}