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

net.finmath.plots.Plot2DFX Maven / Gradle / Ivy

Go to download

finmath lib plot extensions provide convenient plotting methods by providing consistent wrappers to plot libraries (like JFreeChart or JavaFX).

The newest version!
/*
 * (c) Copyright Christian P. Fries, Germany. Contact: [email protected].
 *
 * Created on 21 May 2018
 */

package net.finmath.plots;

import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.NumberFormat;
import java.util.Collections;
import java.util.List;
import java.util.function.DoubleUnaryOperator;
import java.util.stream.Collectors;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.Chart;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;

/**
 * Small convenient wrapper for Java FX line plot.
 *
 * @author Christian Fries
 */
public class Plot2DFX implements Plot {

	private List plotables;

	private String title = "";
	private String xAxisLabel = "x";
	private String yAxisLabel = "y";
	private NumberFormat xAxisNumberFormat;
	private NumberFormat yAxisNumberFormat;
	private Boolean isLegendVisible = false;

	private transient JFrame frame;
	private LineChart chart;
	private final Object updateLock = new Object();

	public Plot2DFX(final List plotables) {
		super();
		this.plotables = plotables;
	}

	public Plot2DFX(final double xmin, final double xmax, final int numberOfPointsX, final DoubleUnaryOperator function) {
		this(xmin, xmax, numberOfPointsX, Collections.singletonList(new Named("",function)));
	}

	public Plot2DFX(final double xmin, final double xmax, final int numberOfPointsX, final List> doubleUnaryOperators) {
		this(doubleUnaryOperators.stream().map(namedFunction -> { return new PlotableFunction2D(xmin, xmax, numberOfPointsX, namedFunction, null); }).collect(Collectors.toList()));
	}

	public Plot2DFX() {
		this(null);
	}

	private void init() {
		//defining the axes
		final NumberAxis xAxis = new NumberAxis();
		final NumberAxis yAxis = new NumberAxis();
		xAxis.setLabel(xAxisLabel);
		yAxis.setLabel(yAxisLabel);
		//creating the chart
		chart = new LineChart(xAxis,yAxis);
		update();
	}

	private void update() {
		Platform.runLater(new Runnable() {
			@Override public void run() {
				if(plotables == null) {
					return;
				}
				chart.setTitle(title);
				for(int functionIndex=0; functionIndex plotableSeries = plotable.getSeries();
					XYChart.Series series = null;
					if(functionIndex < chart.getData().size()) {
						series = chart.getData().get(functionIndex);
					}
					if(series == null) {
						series = new XYChart.Series();
						chart.getData().add(functionIndex,series);
					}
					series.setName(plotable.getName());
					for(int i = 0; i data = null;
						if(i < series.getData().size()) {
							data = (Data) series.getData().get(i);
						}
						if(data == null) {
							data = new XYChart.Data(plotableSeries.get(i).getX(), plotableSeries.get(i).getY());
							if(style != null && style.getShape() != null) {
								//								data.setNode(new javafx.scene.shape.Rectangle(10,10, color));
								data.setNode(new javafx.scene.shape.Circle(6, color));

							}
							series.getData().add(i, data);
						}
						data.setXValue(plotableSeries.get(i).getX());
						data.setYValue(plotableSeries.get(i).getY());
					}

					/*
					 * Apply style to line
					 */
					if(style != null && style.getStroke() != null) {
						series.getNode().setStyle("-fx-stroke: rgba(" + rgba + ");");
					} else {
						series.getNode().setStyle("-fx-stroke: none;");
					}

					/*
			String rgb = String.format("%d, %d, %d", (int) (color.getRed() * 255), (int) (color.getGreen() * 255),(int) (color.getBlue() * 255));
			series.getNode().setStyle("-fx-stroke: rgba(" + rgb + ",1.0);  -fx-background-color: #FF0000, white;");
			series.getNode().setStyle("-fx-stroke: rgba(" + rgb + ",1.0);  -fx-background-color: #FF0000, white;");
					 */
					//			lineChart.setStyle("-fx-create-symbols: false;");

					//			.default-color2.chart-line-symbol { -fx-background-color: #dda0dd, white; }
				}
				final Node[] legendItems = chart.lookupAll(".chart-legend-item-symbol").toArray(new Node[0]);
				for(int i = 0; i plotables) {
		this.plotables = plotables;
		synchronized (updateLock) {
			if(chart != null) {
				update();
			}
		}
		return this;
	}

	@Override
	public Plot2DFX setTitle(final String title) {
		this.title = title;
		return this;
	}

	@Override
	public Plot2DFX setXAxisLabel(final String xAxisLabel) {
		this.xAxisLabel = xAxisLabel;
		return this;
	}

	@Override
	public Plot2DFX setYAxisLabel(final String yAxisLabel) {
		this.yAxisLabel = yAxisLabel;
		return this;
	}

	public Plot2DFX setYAxisRange(final Double min, final Double max) {
		if(chart == null || chart.getYAxis() == null) {
			return this;
		}
		if(min == null || max == null) {
			chart.getYAxis().setAutoRanging(true);
		}
		else {
			chart.getYAxis().setAutoRanging(false);
			((NumberAxis)chart.getYAxis()).setLowerBound(min);
			((NumberAxis)chart.getYAxis()).setUpperBound(max);
		}
		return this;
	}

	@Override
	public Plot setZAxisLabel(final String zAxisLabel) {
		throw new UnsupportedOperationException("The 2D plot does not suport a z-axis. Try 3D plot instead.");
	}

	/**
	 * @param isLegendVisible the isLegendVisible to set
	 */
	@Override
	public Plot setIsLegendVisible(final Boolean isLegendVisible) {
		this.isLegendVisible = isLegendVisible;
		return this;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy