private void computeSpline(final ChartModel inputModel, DefaultChartModel splineModel) { splineModel.clearPoints(); // Create some double arrays and populate them from the chart model // TODO: xs and ys are assumed to be sorted in the call to computeSplineSlopes, which is not // guaranteed final int pointCount = inputModel.getPointCount(); double xs[] = new double[pointCount]; double ys[] = new double[pointCount]; for (int i = 0; i < pointCount; i++) { Chartable p = inputModel.getPoint(i); xs[i] = p.getX().position(); ys[i] = p.getY().position(); } double[] slopes = SplineEngine.computeSplineSlopes(pointCount - 1, xs, ys); // Number of divisions in each segment int nDivs = 20; double rx, ry; for (int seg = 0; seg < pointCount - 1; seg++) { double xstep = (xs[seg + 1] - xs[seg]) / nDivs; for (int i = 0; i <= nDivs; i++) { rx = xs[seg] + i * xstep; ry = SplineEngine.splineEval( rx, xs[seg], xs[seg + 1], ys[seg], ys[seg + 1], slopes[seg], slopes[seg + 1]); splineModel.addPoint(rx, ry); } } }
private JPanel createDemo() { upper = new DefaultChartModel(); lower = new DefaultChartModel(); splineChartModel = new DefaultChartModel(); chart = new Chart(); demoPanel = new JPanel(); demoPanel.setPreferredSize(new Dimension(500, 500)); demoPanel.setLayout(new BorderLayout()); assert xPoints.length == lowerPoints.length && lowerPoints.length == upperPoints.length; for (int i = 0; i < xPoints.length; i++) { lower.addPoint(xPoints[i], lowerPoints[i]); upper.addPoint(xPoints[i], upperPoints[i]); } Range<?> xRange = lower.getXRange(); Range<Double> yRange = new CombinedNumericRange().add(lower.getYRange()).add(upper.getYRange()); Axis xAxis = new Axis(xRange); Axis yAxis = new Axis(yRange); chart.setXAxis(xAxis); chart.setYAxis(yAxis); chart.setShadowVisible(false); PointStyle pointStyle = new PointStyle(Color.green.darker(), PointShape.SQUARE); ChartStyle chartStyle = new ChartStyle(); chartStyle.setPointStyle(pointStyle); chartStyle.setLinesVisible(false); chartStyle.setPointsVisible(true); chart.addModel(lower, chartStyle); chart.addModel(upper, chartStyle); // ChartStyle averageChartStyle = new ChartStyle(Color.blue, false, true); ChartStyle splineChartStyle = new ChartStyle(); splineChartStyle.setLinesVisible(true); LineStyle lineStyle = new LineStyle(); lineStyle.setColor(Color.blue); lineStyle.setWidth(1); splineChartStyle.setLineStyle(lineStyle); final AnnotatedChartModel[] baseModels = new AnnotatedChartModel[] {lower, upper}; averageModel = new AverageChartModel(baseModels); // chart.addModel(averageModel, averageChartStyle); chart.addModel(splineChartModel, splineChartStyle); computeSpline(averageModel, splineChartModel); demoPanel.add(chart, BorderLayout.CENTER); chart.addMouseListener( new MouseListener() { public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2 && nearestModel != null && _nearestPoint != null) { ((DefaultChartModel) nearestModel).removePoint(_nearestPoint); ((DefaultChartModel) nearestModel).update(); computeSpline(averageModel, splineChartModel); } } public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mousePressed(MouseEvent e) { Point p = e.getPoint(); Double minDistance = null; for (ChartModel model : baseModels) { PointSelection nearest = chart.nearestPoint(p, model); Chartable chartable = nearest.getSelected(); double distance = nearest.getDistance(); if (minDistance == null || distance < minDistance) { _nearestPoint = chartable; nearestModel = model; minDistance = distance; } } } public void mouseReleased(MouseEvent e) {} }); chart.addMouseMotionListener( new MouseMotionListener() { public void mouseDragged(MouseEvent e) { if (nearestModel != null) { Point p = e.getPoint(); Point2D realPoint = chart.calculateUserPoint(p); if (realPoint != null) { ((ChartPoint) _nearestPoint).setY(new RealPosition(realPoint.getY())); } // TODO: Should not have to call an update() method! ((DefaultChartModel) nearestModel).update(); computeSpline(averageModel, splineChartModel); } } public void mouseMoved(MouseEvent e) {} }); return demoPanel; }
public JPanel createDemo() { model = new DefaultChartModel(); demoPanel = new JPanel(); Axis xAxis = new CategoryAxis<Country>(countries); xAxis.setLabel("Countries"); Axis yAxis = new Axis(new NumericRange(0, 25)); yAxis.setLabel("Numbers"); chart = new Chart(); chart.setXAxis(xAxis); chart.setYAxis(yAxis); Font titleFont = UIManager.getFont("Label.font").deriveFont(Font.BOLD, 14f); chart.setTitle( new AutoPositionedLabel("Chart with Categorical X Values", Color.blue, titleFont)); chart.setVerticalGridLinesVisible(false); chart.setShadowVisible(true); model .addPoint(usa, 22) .addPoint(uk, 18) .addPoint(france, 13.5) .addPoint(germany, 12) .addPoint(russia, 8) .addPoint(china, 7); Color green = new Color(0, 170, 0); ChartStyle style = new ChartStyle(green, true, true); style.setLineWidth(6); style.setPointSize(20); chart.addModel(model, style).setPointRenderer(new SphericalPointRenderer()); ChartStyle redHighlightStyle = new ChartStyle(new Color(200, 0, 0), PointShape.DISC, 20).withPointsAndLines(); redHighlightStyle.setLineWidth(6); redHighlightStyle.setLineColor(green); chart.setHighlightStyle(redHighlight, redHighlightStyle); demoPanel.setLayout(new BorderLayout()); demoPanel.add(chart, BorderLayout.CENTER); chart.addMouseMotionListener( new MouseMotionListener() { // Allow the user to drag _points in the vertical direction public void mouseDragged(MouseEvent e) { rollover(e); if (highlighted != null) { Point p = e.getPoint(); Point2D userPoint = chart.calculateUserPoint(p); if (userPoint != null) { highlighted.setY(new RealPosition(userPoint.getY())); } chart.repaint(); } } // Add a rollover effect public void mouseMoved(MouseEvent e) { rollover(e); } private void rollover(MouseEvent e) { Point p = e.getPoint(); PointSelection selection = chart.nearestPoint(p, model); if (highlighted != null) { highlighted.setHighlight(null); } Chartable selected = selection.getSelected(); Point2D selectedCoords = new Point2D.Double(selected.getX().position(), selected.getY().position()); Point dp = chart.calculatePixelPoint(selectedCoords); // Only activate the rollover effect when within 50 pixels of a point if (p.distance(dp) < 50) { highlighted = (ChartPoint) selection.getSelected(); highlighted.setHighlight(redHighlight); ChartCategory<?> x = (ChartCategory<?>) selected.getX(); chart.setToolTipText( String.format("%s : %.1f", x.getName(), selected.getY().position())); } else { chart.setToolTipText(null); } chart.repaint(); } }); chart.addMouseListener( new MouseAdapter() { @Override public void mouseExited(MouseEvent e) { if (highlighted != null) { highlighted.setHighlight(null); chart.repaint(); } } }); demoPanel.setPreferredSize(new Dimension(500, 500)); return demoPanel; }