All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.scudata.cellset.graph.draw.DrawCurve Maven / Gradle / Ivy

Go to download

SPL(Structured Process Language) A programming language specially for structured data computing.

There is a newer version: 20240823
Show newest version
package com.scudata.cellset.graph.draw;

import java.awt.*;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.*;

import com.scudata.cellset.graph.*;
import com.scudata.chart.Consts;
import com.scudata.chart.Utils;

/**
 * ????ͼʵ??
 * 
 * @author Joancy
 *
 */

public class DrawCurve extends DrawBase {
	/**
	 * ʵ?ֻ?ͼ????
	 */
	public void draw(StringBuffer htmlLink) {
		drawing(this, htmlLink);
	}

	/**
	 * ???ݻ?ͼ????db??ͼ????????ͼ??ij????Ӵ???htmlLink
	 * 
	 * @param db
	 *            ????Ļ?ͼ????
	 * @param htmlLink
	 *            ?????ӻ???
	 */
	public static void drawing(DrawBase db, StringBuffer htmlLink) {
		GraphParam gp = db.gp;
		ExtGraphProperty egp = db.egp;
		Graphics2D g = db.g;
		ArrayList labelList = db.labelList;
		int VALUE_RADIUS = db.VALUE_RADIUS;
		ArrayList pointList = db.pointList;
		double seriesWidth;
		double coorWidth;
		double categorySpan;
		double dely;
		double tmpInt;
		double x, y;

		gp.coorWidth = 0;

		Point2D.Double beginPoint[];
		double beginVal[];
		ArrayList catPoints[];

		db.initGraphInset();
		db.createCoorValue();
		db.drawLegend(htmlLink);
		db.drawTitle();
		db.drawLabel();
		db.keepGraphSpace();

		db.adjustCoorInset();
		gp.graphRect = new Rectangle2D.Double(gp.leftInset, gp.topInset, gp.graphWidth
				- gp.leftInset - gp.rightInset, gp.graphHeight - gp.topInset
				- gp.bottomInset);

		if (gp.graphRect.width < 10 || gp.graphRect.height < 10) {
			return;
		}

		if (gp.coorWidth < 0 || gp.coorWidth > 10000) {
			gp.coorWidth = 0;
		}
		seriesWidth = gp.graphRect.width
				/ (((gp.catNum + 1) * gp.categorySpan / 100.0) + gp.coorWidth
						/ 200.0 + gp.catNum * gp.serNum);

		coorWidth = seriesWidth * (gp.coorWidth / 200.0);
		categorySpan = seriesWidth * (gp.categorySpan / 100.0);

		tmpInt =  ((gp.catNum + 1) * categorySpan + coorWidth + gp.catNum
				* gp.serNum * seriesWidth);
		gp.graphRect.x += (gp.graphRect.width - tmpInt) / 2;
		gp.graphRect.width = tmpInt;

		dely = (gp.graphRect.height - coorWidth) / gp.tickNum;
		tmpInt =  (dely * gp.tickNum + coorWidth);
		gp.graphRect.y += (gp.graphRect.height - tmpInt) / 2;
		gp.graphRect.height = tmpInt;

		gp.gRect1 = (Rectangle2D.Double)gp.graphRect.clone();
		gp.gRect2 = (Rectangle2D.Double)gp.graphRect.clone();

		gp.gRect1.y += coorWidth;
		gp.gRect1.width -= coorWidth;
		gp.gRect1.height -= coorWidth;
		gp.gRect2.x += coorWidth;
		gp.gRect2.width -= coorWidth;
		gp.gRect2.height -= coorWidth;

		/* ???????? */
		db.drawGraphRect();
		/* ??Y?? */
		for (int i = 0; i <= gp.tickNum; i++) {
			db.drawGridLine(dely, i);
			Number coory = (Number) gp.coorValue.get(i);
			String scoory = db.getFormattedValue(coory.doubleValue());

			x = gp.gRect1.x - gp.tickLen;
			y =  (gp.gRect1.y + gp.gRect1.height - i * dely);
			gp.GFV_YLABEL.outText(x, y, scoory);
			// ???û???
			if (coory.doubleValue() == gp.baseValue + gp.minValue) {
				gp.valueBaseLine =  (gp.gRect1.y + gp.gRect1.height - i
						* dely);
			}
		}
		// ????????
		db.drawWarnLine();
		/* ??X?? */
		beginPoint = new Point2D.Double[gp.serNum];
		beginVal = new double[gp.serNum];
		catPoints = new ArrayList[gp.serNum];
		for (int j = 0; j < gp.serNum; j++) {
			ArrayList catList = new ArrayList();
			catPoints[j] = catList;
		}

		ArrayList cats = egp.categories;
		int cc = cats.size();
		Color c;
		for (int i = 0; i < cc; i++) {
			ExtGraphCategory egc = (ExtGraphCategory) cats.get(i);
			double posx = DrawLine.getPosX(gp, i, cc, categorySpan, seriesWidth);

			boolean valvis = (i % (gp.graphXInterval + 1) == 0);// ?????Ƿ???ʾֵ????Table?ֿ?
			boolean vis = valvis && !gp.isDrawTable;
			if (vis) {
				c = egp.getAxisColor(GraphProperty.AXIS_BOTTOM);
				Utils.setStroke(g, c, Consts.LINE_SOLID, 1.0f);
				db.drawLine(posx, gp.gRect1.y + gp.gRect1.height, posx,
						gp.gRect1.y + gp.gRect1.height + gp.tickLen, c);
				// ??????????
				db.drawGridLineCategoryV(posx);
			}

			String value = egc.getNameString();
			x = posx;
			y = gp.gRect1.y + gp.gRect1.height + gp.tickLen;
			gp.GFV_XLABEL.outText(x, y, value, vis);
			for (int j = 0; j < gp.serNum; j++) {
				ExtGraphSery egs = egc.getExtGraphSery(gp.serNames.get(j));
				double val = egs.getValue();
				double tmp = val - gp.baseValue;
				double len =  (dely * gp.tickNum * (tmp - gp.minValue) / (gp.maxValue * gp.coorScale));

				if (gp.isDrawTable) {
					posx =  db.getDataTableX(i);
				}

				Point2D.Double endPoint;
				if (egs.isNull()) {
					endPoint = null;
				} else {
					endPoint = new Point2D.Double(posx, gp.valueBaseLine - len);
				}

				// ???????
				if (gp.dispValueOntop && !egs.isNull() && valvis) {
					String sval = db.getDispValue(egc, egs, gp.serNum); // getFormattedValue(val);
					x = endPoint.x;
					y = endPoint.y;
					if (!gp.isMultiSeries) {
						c = db.getColor(i);
					} else {
						c = db.getColor(j);
					}
					ValueLabel vl = new ValueLabel(sval, new Point2D.Double(x, y
							- VALUE_RADIUS), c);
					labelList.add(vl);
				}

				boolean vis2 = (i % (gp.graphXInterval + 1) == 0);
				if (!egs.isNull() && gp.drawLineDot && vis2) {
					double xx, yy, ww, hh;
					xx = endPoint.x - VALUE_RADIUS;
					yy = endPoint.y - VALUE_RADIUS;
					ww = 2 * VALUE_RADIUS;
					hh = ww;
					Color backColor;
					if (!gp.isMultiSeries) {
						backColor = db.getColor(i);
					} else {
						backColor = db.getColor(j);
					}

					ValuePoint vp = new ValuePoint(endPoint, backColor);
					pointList.add(vp);
					db.htmlLink(xx, yy, ww, hh, htmlLink, egc.getNameString(),
							egs);
				} // ?????ϵ?С????
				if (i > 0) {
					g.setColor(db.getColor(j));
					DrawLine.drawVTrendLine(db, beginPoint[j], endPoint, val
							- beginVal[j]);
				}
				DrawLine.drawHTrendLine(db, beginPoint[j]);
				beginPoint[j] = endPoint;
				if (endPoint != null) {
					ArrayList catList = catPoints[j];
					catList.add(endPoint);
				}
				beginVal[j] = val;
			}
		}

		Stroke stroke = db.getLineStroke();
		if (stroke != null) {
			g.setStroke(stroke);
		}

		for (int j = 0; j < gp.serNum; j++) {
			ArrayList serPoints = catPoints[j];
			if (serPoints.size() == 0) {
				continue;
			}

			g.setColor(db.getColor(j));

			Point2D.Double p1;
			Point2D.Double p2;
			int n;
			double x1, y1, x2, y2;
			double[] xs;
			double[] ys;
			byte curveType = egp.getCurveType();
			Line2D.Double dLine;
			switch (curveType) {
			case GraphProperty.CURVE_LAGRANGE:
				p1 = serPoints.get(0);
				p2 = serPoints.get(serPoints.size() - 1);
				x1 = p1.x;
				y1 = p1.y;
				double delta = 0.2;
				for (x2 = p1.x + delta; x2 <= p2.x; x2 += delta) {
					y2 = Lagrange(serPoints, x2);
					dLine = new Line2D.Double(x1, y1, x2, y2);
					g.draw(dLine);
					x1 = x2;
					y1 = y2;
				}
				break;
			case GraphProperty.CURVE_AKIMA:
				n = serPoints.size();
				xs = new double[n];
				ys = new double[n];
				for (int i = 0; i < n; i++) {
					Point2D.Double pt = serPoints.get(i);
					xs[i] = pt.x;
					ys[i] = pt.y;
				}
				for (int k = 0; k < serPoints.size() - 1; k++) {
					p1 = serPoints.get(k);
					x1 = p1.x;
					y1 = p1.y;
					p2 = serPoints.get(k + 1);
					double[] s = s(xs, ys, k); // , t
					for (x2 = p1.x + 1; x2 <= p2.x; x2 += 1) {
						y2 = akima(p1.x, x2, s);
						dLine = new Line2D.Double(x1, y1, x2, y2);
						g.draw(dLine);
						x1 = x2;
						y1 = y2;
					}
				}
				break;
			case GraphProperty.CURVE_3SAMPLE:
				n = serPoints.size();
				xs = new double[n];
				ys = new double[n];
				for (int i = 0; i < n; i++) {
					Point2D.Double pt = serPoints.get(i);
					xs[i] = pt.x;
					ys[i] = pt.y;
				}

				p1 = serPoints.get(0);
				p2 = serPoints.get(serPoints.size() - 1);
				x1 = p1.x;
				y1 = p1.y;
				for (x2 = p1.x + 1; x2 <= p2.x; x2 += 1) {
					y2 =  sample(xs, ys, x2);
					dLine = new Line2D.Double(x1, y1, x2, y2);
					g.draw(dLine);
					x1 = x2;
					y1 = y2;
				}
				break;
			}
		}

		db.outPoints();
		db.outLabels();
		/* ?ػ?һ?»??? */
		g.setStroke(new BasicStroke());
		db.drawLine(gp.gRect1.x, gp.valueBaseLine, gp.gRect1.x
				+ gp.gRect1.width, gp.valueBaseLine,
				egp.getAxisColor(GraphProperty.AXIS_BOTTOM));
		db.drawLine(gp.gRect1.x + gp.gRect1.width, gp.valueBaseLine,
				 (gp.gRect1.x + gp.gRect1.width + coorWidth),
				 (gp.valueBaseLine - coorWidth),
				egp.getAxisColor(GraphProperty.AXIS_BOTTOM));
	}

	/**
	 * ???????ղ?ֵ?㷨
	 * 
	 * @param points
	 *            ArrayList?????е?
	 * @param deltaX
	 *            int?? ??ֵ??X
	 * @return int????ֵ???պ??Y
	 */
	private static double Lagrange(ArrayList points, double deltaX) {
		double sum = 0;
		double L;
		for (int i = 0; i < points.size(); i++) {
			L = 1;
			Point2D.Double pi = points.get(i);
			for (int j = 0; j < points.size(); j++) {
				Point2D.Double pj = points.get(j);
				if (j != i) {
					L = L * (deltaX - pj.x) / (pi.x - pj.x);
				}
			}
			sum = sum + L * pi.y;
		}
		return sum;
	}

	private static double akima(double xk, double t, double[] s) {
		double d = t - xk;
		double dd = d * d;
		return s[0] + s[1] * d + s[2] * dd + s[3] * d * dd;
	}

	private static double[] s(double[] x, double[] y, int k) {
		double t = 0;
		int kk, m, l;
		double[] u = new double[5];
		double[] s = new double[5];
		double p, q;
		s[4] = 0.0;
		s[0] = 0.0;
		s[1] = 0.0;
		s[2] = 0.0;
		s[3] = 0.0;
		int n = x.length;
		if (n < 1) {
			return s;
		}
		if (n == 1) {
			s[0] = y[0];
			s[4] = y[0];
			return s;
		}
		if (n == 2) {
			s[0] = y[0];
			s[1] = (y[1] - y[0]) / (x[1] - x[0]);
			if (k < 0) {
				s[4] = (y[0] * (t - x[1]) - y[1] * (t - x[0])) / (x[0] - x[1]);
			}
			return s;
		}
		if (k < 0) {
			if (t <= x[1]) {
				kk = 0;
			} else if (t >= x[n - 1]) {
				kk = n - 2;
			} else {
				kk = 1;
				m = n;
				while (((kk - m) != 1) && ((kk - m) != -1)) {
					l = (kk + m) / 2;
					if (t < x[l - 1]) {
						m = l;
					} else {
						kk = l;
					}
				}
				kk = kk - 1;
			}
		} else {
			kk = k;
		}
		if (kk >= n - 1) {
			kk = n - 2;
		}
		u[2] = (y[kk + 1] - y[kk]) / (x[kk + 1] - x[kk]);
		if (n == 3) {
			if (kk == 0) {
				u[3] = (y[2] - y[1]) / (x[2] - x[1]);
				u[4] = 2.0 * u[3] - u[2];
				u[1] = 2.0 * u[2] - u[3];
				u[0] = 2.0 * u[1] - u[2];
			} else {
				u[1] = (y[1] - y[0]) / (x[1] - x[0]);
				u[0] = 2.0 * u[1] - u[2];
				u[3] = 2.0 * u[2] - u[1];
				u[4] = 2.0 * u[3] - u[2];
			}
		} else {
			if (kk <= 1) {
				u[3] = (y[kk + 2] - y[kk + 1]) / (x[kk + 2] - x[kk + 1]);
				if (kk == 1) {
					u[1] = (y[1] - y[0]) / (x[1] - x[0]);
					u[0] = 2.0 * u[1] - u[2];
					if (n == 4) {
						u[4] = 2.0 * u[3] - u[2];
					} else {
						u[4] = (y[4] - y[3]) / (x[4] - x[3]);
					}
				} else {
					u[1] = 2.0 * u[2] - u[3];
					u[0] = 2.0 * u[1] - u[2];
					u[4] = (y[3] - y[2]) / (x[3] - x[2]);
				}
			} else if (kk >= (n - 3)) {
				u[1] = (y[kk] - y[kk - 1]) / (x[kk] - x[kk - 1]);
				if (kk == (n - 3)) {
					u[3] = (y[n - 1] - y[n - 2]) / (x[n - 1] - x[n - 2]);
					u[4] = 2.0 * u[3] - u[2];
					if (n == 4) {
						u[0] = 2.0 * u[1] - u[2];
					} else {
						u[0] = (y[kk - 1] - y[kk - 2])
								/ (x[kk - 1] - x[kk - 2]);
					}
				} else {
					u[3] = 2.0 * u[2] - u[1];
					u[4] = 2.0 * u[3] - u[2];
					u[0] = (y[kk - 1] - y[kk - 2]) / (x[kk - 1] - x[kk - 2]);
				}
			} else {
				u[1] = (y[kk] - y[kk - 1]) / (x[kk] - x[kk - 1]);
				u[0] = (y[kk - 1] - y[kk - 2]) / (x[kk - 1] - x[kk - 2]);
				u[3] = (y[kk + 2] - y[kk + 1]) / (x[kk + 2] - x[kk + 1]);
				u[4] = (y[kk + 3] - y[kk + 2]) / (x[kk + 3] - x[kk + 2]);
			}
		}
		s[0] = fabs(u[3] - u[2]);
		s[1] = fabs(u[0] - u[1]);
		if ((s[0] + 1.0 == 1.0) && (s[1] + 1.0 == 1.0)) {
			p = (u[1] + u[2]) / 2.0;
		} else {
			p = (s[0] * u[1] + s[1] * u[2]) / (s[0] + s[1]);
		}
		s[0] = fabs(u[3] - u[4]);
		s[1] = fabs(u[2] - u[1]);
		if ((s[0] + 1.0 == 1.0) && (s[1] + 1.0 == 1.0)) {
			q = (u[2] + u[3]) / 2.0;
		} else {
			q = (s[0] * u[2] + s[1] * u[3]) / (s[0] + s[1]);
		}
		s[0] = y[kk];
		s[1] = p;
		s[3] = x[kk + 1] - x[kk];
		s[2] = (3.0 * u[2] - 2.0 * p - q) / s[3];
		s[3] = (q + p - 2.0 * u[2]) / (s[3] * s[3]);
		if (k < 0) {
			p = t - x[kk];
			s[4] = s[0] + s[1] * p + s[2] * p * p + s[3] * p * p * p;
		}
		return s;
	}

	private static double fabs(double d) {
		return Math.abs(d);
	}

	// ??????????????ֵ
	private static double sample(double[] x, double[] y, double tx) {
		int n = x.length, m;
		double dy[], ddy[], t[], z[], dz[], ddz[];
		dy = new double[n];
		dy[0] = 1;
		dy[n - 1] = -1;
		ddy = new double[n];

		t = new double[] { tx };
		m = 1;
		z = new double[1];
		dz = new double[1];
		ddz = new double[1];
		int i, j;
		double h0, h1, alpha, beta, g;
		double[] s = new double[n];
		s[0] = dy[0];
		dy[0] = 0.0;
		h0 = x[1] - x[0];
		for (j = 1; j <= n - 2; j++) {
			h1 = x[j + 1] - x[j];
			alpha = h0 / (h0 + h1);
			beta = (1.0 - alpha) * (y[j] - y[j - 1]) / h0;
			beta = 3.0 * (beta + alpha * (y[j + 1] - y[j]) / h1);
			dy[j] = -alpha / (2.0 + (1.0 - alpha) * dy[j - 1]);
			s[j] = (beta - (1.0 - alpha) * s[j - 1]);
			s[j] = s[j] / (2.0 + (1.0 - alpha) * dy[j - 1]);
			h0 = h1;
		}
		for (j = n - 2; j >= 0; j--) {
			dy[j] = dy[j] * dy[j + 1] + s[j];
		}
		for (j = 0; j <= n - 2; j++) {
			s[j] = x[j + 1] - x[j];
		}
		for (j = 0; j <= n - 2; j++) {
			h1 = s[j] * s[j];
			ddy[j] = 6.0 * (y[j + 1] - y[j]) / h1 - 2.0
					* (2.0 * dy[j] + dy[j + 1]) / s[j];
		}
		h1 = s[n - 2] * s[n - 2];
		ddy[n - 1] = 6. * (y[n - 2] - y[n - 1]) / h1 + 2.
				* (2. * dy[n - 1] + dy[n - 2]) / s[n - 2];
		g = 0.0;
		for (i = 0; i <= n - 2; i++) {
			h1 = 0.5 * s[i] * (y[i] + y[i + 1]);
			h1 = h1 - s[i] * s[i] * s[i] * (ddy[i] + ddy[i + 1]) / 24.0;
			g = g + h1;
		}
		for (j = 0; j <= m - 1; j++) {
			if (t[j] >= x[n - 1]) {
				i = n - 2;
			} else {
				i = 0;
				while (t[j] > x[i + 1]) {
					i = i + 1;
				}
			}
			h1 = (x[i + 1] - t[j]) / s[i];
			h0 = h1 * h1;
			z[j] = (3.0 * h0 - 2.0 * h0 * h1) * y[i];
			z[j] = z[j] + s[i] * (h0 - h0 * h1) * dy[i];
			dz[j] = 6.0 * (h0 - h1) * y[i] / s[i];
			dz[j] = dz[j] + (3.0 * h0 - 2.0 * h1) * dy[i];
			ddz[j] = (6.0 - 12.0 * h1) * y[i] / (s[i] * s[i]);
			ddz[j] = ddz[j] + (2.0 - 6.0 * h1) * dy[i] / s[i];
			h1 = (t[j] - x[i]) / s[i];
			h0 = h1 * h1;
			z[j] = z[j] + (3.0 * h0 - 2.0 * h0 * h1) * y[i + 1];
			z[j] = z[j] - s[i] * (h0 - h0 * h1) * dy[i + 1];
			dz[j] = dz[j] - 6.0 * (h0 - h1) * y[i + 1] / s[i];
			dz[j] = dz[j] + (3.0 * h0 - 2.0 * h1) * dy[i + 1];
			ddz[j] = ddz[j] + (6.0 - 12.0 * h1) * y[i + 1] / (s[i] * s[i]);
			ddz[j] = ddz[j] - (2.0 - 6.0 * h1) * dy[i + 1] / s[i];
		}
		return z[0];
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy