001: /*************************************************************************
002: * *
003: * 1) This source code file, in unmodified form, and compiled classes *
004: * derived from it can be used and distributed without restriction, *
005: * including for commercial use. (Attribution is not required *
006: * but is appreciated.) *
007: * *
008: * 2) Modified versions of this file can be made and distributed *
009: * provided: the modified versions are put into a Java package *
010: * different from the original package, edu.hws; modified *
011: * versions are distributed under the same terms as the original; *
012: * and the modifications are documented in comments. (Modification *
013: * here does not include simply making subclasses that belong to *
014: * a package other than edu.hws, which can be done without any *
015: * restriction.) *
016: * *
017: * David J. Eck *
018: * Department of Mathematics and Computer Science *
019: * Hobart and William Smith Colleges *
020: * Geneva, New York 14456, USA *
021: * Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
022: * *
023: *************************************************************************/package edu.hws.jcm.functions;
024:
025: /**
026: * This non-public class is for use with TableFunctions. It defines one segment
027: * of a TableFunction whose style is TableFunction.SMOOTH. A cubic segment is
028: * a segment of a cubic polynomial. It is defined by six numbers: two x-coordinates,
029: * the y-value at each x-coordinate, and the derivative at each x-coordinate.
030: */
031: class CubicSegment {
032:
033: private double x1, x2, // x-ccords at endpoints with x1 < x2
034: y1, y2, // y-coords at endpoints
035: d1, d2; // derivatives at endpoints
036:
037: private double a, b, c, d; // coefficients in a(x-x1)^3 + b(x-x1)^2(x-x2) + ...
038:
039: CubicSegment() {
040: }
041:
042: CubicSegment(double x1, double x2, double y1, double y2, double d1,
043: double d2) {
044: setData(x1, x2, y1, y2, d1, d2);
045: }
046:
047: void setData(double nx1, double nx2, double ny1, double ny2,
048: double nd1, double nd2) {
049: double temp;
050: if (nx1 == nx2)
051: throw new IllegalArgumentException(
052: "Attempt to make CubicSegment of length 0");
053: if (nx1 > nx2) {
054: temp = nx1;
055: nx1 = nx2;
056: nx2 = temp;
057: temp = ny1;
058: ny1 = ny2;
059: ny2 = temp;
060: temp = nd1;
061: nd1 = nd2;
062: nd2 = temp;
063: }
064: x1 = nx1;
065: x2 = nx2;
066: y1 = ny1;
067: y2 = ny2;
068: d1 = nd1;
069: d2 = nd2;
070: temp = (x2 - x1);
071: a = y2 / (temp * temp * temp);
072: b = d2 / (temp * temp) - 3 * a;
073: temp = -temp;
074: d = y1 / (temp * temp * temp);
075: c = d1 / (temp * temp) - 3 * d;
076: }
077:
078: void setDerivativesFromNeighbors(double leftX, double leftY,
079: double rightX, double rightY) {
080: double nd1, nd2;
081: if (!Double.isNaN(leftX) && leftX < x1)
082: nd1 = (y2 - leftY) / (x2 - leftX);
083: else
084: nd1 = (y2 - y1) / (x2 - x1);
085: if (!Double.isNaN(rightX) && rightX > x2)
086: nd2 = (rightY - y1) / (rightX - x1);
087: else
088: nd2 = (y2 - y1) / (x2 - x1);
089: setData(x1, x2, y1, y2, nd1, nd2);
090: }
091:
092: double value(double x) { // should have x1 <= x <= x2, but not required
093: return derivativeValue(x, 0);
094: }
095:
096: double derivativeValue(double x, int derivativeOrder) {
097: // Assume derivativeOrder >= 0.
098: // This function, unlike value() returns the value that represents the
099: // one-sided limit at the endpoint, even if that endpoint is not
100: // in the domain.
101: switch (derivativeOrder) {
102: case 0:
103: double t1 = x - x1;
104: double t2 = t1 * t1;
105: double t3 = t2 * t1;
106: double s1 = x - x2;
107: double s2 = s1 * s1;
108: double s3 = s2 * s1;
109: return a * t3 + b * t2 * s1 + c * t1 * s2 + d * s3;
110: case 1:
111: return ((3 * a + b) * (x - x1) * (x - x1) + 2 * (b + c)
112: * (x - x1) * (x - x2) + (3 * d + c) * (x - x2)
113: * (x - x2));
114: case 2:
115: return 2 * ((3 * a + 2 * b + c) * (x - x1) + (3 * d + 2 * c + b)
116: * (x - x2));
117: case 3:
118: return 6 * (2 * a + b + c);
119: default:
120: return 0;
121: }
122: }
123:
124: }
|