jcckit.plot.CartesianCoordinateSystem Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of plantuml-gplv2 Show documentation
Show all versions of plantuml-gplv2 Show documentation
PlantUML is a component that allows to quickly write diagrams from text.
// THIS FILE HAS BEEN GENERATED BY A PREPROCESSOR.
/* +=======================================================================
* |
* | PlantUML : a free UML diagram generator
* |
* +=======================================================================
*
* (C) Copyright 2009-2024, Arnaud Roques
*
* Project Info: https://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* https://plantuml.com/patreon (only 1$ per month!)
* https://plantuml.com/liberapay (only 1€ per month!)
* https://plantuml.com/paypal
*
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License V2.
*
* THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
* LICENSE ("AGREEMENT"). [GNU General Public License V2]
*
* ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES
* RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
*
* You may obtain a copy of the License at
*
* https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PlantUML can occasionally display sponsored or advertising messages. Those
* messages are usually generated on welcome or error images and never on
* functional diagrams.
* See https://plantuml.com/professional if you want to remove them
*
* Images (whatever their format : PNG, SVG, EPS...) generated by running PlantUML
* are owned by the author of their corresponding sources code (that is, their
* textual description in PlantUML language). Those images are not covered by
* this GPL v2 license.
*
* The generated images can then be used without any reference to the GPL v2 license.
* It is not even necessary to stipulate that they have been generated with PlantUML,
* although this will be appreciated by the PlantUML team.
*
* There is an exception : if the textual description in PlantUML language is also covered
* by any license, then the generated images are logically covered
* by the very same license.
*
* This is the IGY distribution (Install GraphViz by Yourself).
* You have to install GraphViz and to setup the GRAPHVIZ_DOT environment variable
* (see https://plantuml.com/graphviz-dot )
*
* Icons provided by OpenIconic : https://useiconic.com/open
* Archimate sprites provided by Archi : http://www.archimatetool.com
* Stdlib AWS provided by https://github.com/milo-minderbinder/AWS-PlantUML
* Stdlib Icons provided https://github.com/tupadr3/plantuml-icon-font-sprites
* ASCIIMathML (c) Peter Jipsen http://www.chapman.edu/~jipsen
* ASCIIMathML (c) David Lippman http://www.pierce.ctc.edu/dlippman
* CafeUndZopfli ported by Eugene Klyuchnikov https://github.com/eustas/CafeUndZopfli
* Brotli (c) by the Brotli Authors https://github.com/google/brotli
* Themes (c) by Brett Schwarz https://github.com/bschwarz/puml-themes
* Twemoji (c) by Twitter at https://twemoji.twitter.com/
*
*/
package jcckit.plot;
import jcckit.data.DataPoint;
import jcckit.graphic.ClippingRectangle;
import jcckit.graphic.ClippingShape;
import jcckit.graphic.GraphPoint;
import jcckit.graphic.GraphicAttributes;
import jcckit.graphic.GraphicalComposite;
import jcckit.graphic.GraphicalElement;
import jcckit.graphic.LineAttributes;
import jcckit.graphic.Polygon;
import jcckit.graphic.Text;
import jcckit.transformation.CartesianTransformation;
import jcckit.transformation.Transformation;
import jcckit.util.ConfigParameters;
/**
* A Cartesian coordinate system. One or both axes can be logarithmic.
*
* @author Franz-Josef Elmer
*/
public class CartesianCoordinateSystem implements CoordinateSystem {
/** Configuration parameter key. */
public static final String ORIGIN_KEY = "origin",
X_AXIS_KEY = "xAxis",
Y_AXIS_KEY = "yAxis";
private final CartesianTransformation _transformation;
private final GraphicalComposite _view;
private final ClippingRectangle _clippingRectangle;
/**
* Creates an instance from the specified configuration parameters.
*
* Key & Default Value Type Mandatory
* Description
* origin = 0.15, 0.1
* double[] no
* Position (in device-independent coordinates) of the lower-left
* corner of the axis box.
* xAxis
* ConfigParameters no
* Parameters defining the x-axis. For definitions and default
* values see {@link AxisParameters#createXAxis
* AxisParameters.createXAxis()}.
* yAxis
* ConfigParameters no
* Parameters defining the y-axis. For definitions and default
* values see {@link AxisParameters#createYAxis
* AxisParameters.createYAxis()}.
*
*/
public CartesianCoordinateSystem(ConfigParameters config) {
this(new GraphPoint(config.getDoubleArray(ORIGIN_KEY,
new double[] {0.15, 0.1})),
AxisParameters.createXAxis(config.getNode(X_AXIS_KEY)),
AxisParameters.createYAxis(config.getNode(Y_AXIS_KEY)));
}
/**
* Creates an instance for the specified origin and parameters
* of both axes.
* @param origin Position (in device-independent coordinates) of the
* lower-left corner of the axis box.
* @param xAxisParameters Parameters of the x-axis.
* @param yAxisParameters Parameters of the y-axis.
*/
public CartesianCoordinateSystem(GraphPoint origin,
AxisParameters xAxisParameters,
AxisParameters yAxisParameters) {
double x = origin.getX();
double y = origin.getY();
_transformation = new CartesianTransformation(xAxisParameters.logScale,
yAxisParameters.logScale,
new DataPoint(xAxisParameters.minimum, yAxisParameters.minimum),
new GraphPoint(x, y),
new DataPoint(xAxisParameters.maximum, yAxisParameters.maximum),
new GraphPoint(x + xAxisParameters.axisLength,
y + yAxisParameters.axisLength));
_clippingRectangle = new ClippingRectangle(x, y,
x + xAxisParameters.axisLength,
y + yAxisParameters.axisLength);
_view = new GraphicalComposite(null);
createView(origin, xAxisParameters, yAxisParameters);
}
/** Creates the graphical representation of this coordinate system. */
private void createView(GraphPoint origin,
AxisParameters xAxisParameters,
AxisParameters yAxisParameters) {
double x0 = origin.getX();
double x1 = x0 + xAxisParameters.axisLength;
double y0 = origin.getY();
double y1 = y0 + yAxisParameters.axisLength;
GraphPoint lowerLeftCorner = new GraphPoint(x0, y0);
GraphPoint upperLeftCorner = new GraphPoint(x0, y1);
GraphPoint lowerRightCorner = new GraphPoint(x1, y0);
GraphPoint upperRightCorner = new GraphPoint(x1, y1);
LineAttributes xLineAttributes = xAxisParameters.axisAttributes;
LineAttributes yLineAttributes = yAxisParameters.axisAttributes;
createTicsAndGrid(true, y0, y1, xAxisParameters);
createTicsAndGrid(false, x0, x1, yAxisParameters);
addLine(lowerLeftCorner, lowerRightCorner, xLineAttributes);
addLine(lowerLeftCorner, upperLeftCorner, yLineAttributes);
addLine(upperLeftCorner, upperRightCorner, xLineAttributes);
addLine(lowerRightCorner, upperRightCorner, yLineAttributes);
createLabel(0.5 * (x0 + x1), y0, xAxisParameters);
createLabel(x0, 0.5 * (y0 + y1), yAxisParameters);
}
private void createLabel(double x, double y, AxisParameters parameters) {
if (parameters.axisLabel.length() > 0) {
_view.addElement(new Text(
new GraphPoint(x + parameters.axisLabelPosition.getX(),
y + parameters.axisLabelPosition.getY()),
parameters.axisLabel, parameters.axisLabelAttributes));
}
}
private void createTicsAndGrid(boolean isXAxis, double low, double high,
AxisParameters parameters) {
double[] tics = parameters.calculateTics();
int offIndex = isXAxis ? 1 : 0;
double[] point = new double[2]; // helper array
for (int i = 0; i < tics.length; i++) {
point[1 - offIndex] = tics[i];
point[offIndex] = 1;
GraphPoint gPoint1 =
_transformation.transformToGraph(new DataPoint(point[0], point[1]));
point[0] = gPoint1.getX();
point[1] = gPoint1.getY();
point[offIndex] = high;
gPoint1 = new GraphPoint(point[0], point[1]);
point[offIndex] += parameters.ticLength;
addLine(gPoint1, new GraphPoint(point[0], point[1]),
parameters.ticAttributes);
point[offIndex] = low;
GraphPoint gPoint2 = new GraphPoint(point[0], point[1]);
if (parameters.grid) {
addLine(gPoint1, gPoint2, parameters.gridAttributes);
}
point[offIndex] -= parameters.ticLength;
addLine(gPoint2, new GraphPoint(point[0], point[1]),
parameters.ticAttributes);
if (parameters.ticLabelFormat != null) {
point[offIndex] += parameters.ticLength;
point[0] += parameters.ticLabelPosition.getX();
point[1] += parameters.ticLabelPosition.getY();
_view.addElement(new Text(new GraphPoint(point[0], point[1]),
parameters.ticLabelFormat.form(tics[i]),
parameters.ticLabelAttributes));
}
}
}
private void addLine(GraphPoint point1, GraphPoint point2,
GraphicAttributes attributes) {
Polygon line = new Polygon(attributes, false);
line.addPoint(point1);
line.addPoint(point2);
_view.addElement(line);
}
/**
* Returns the graphical representation of the coordinate system.
* In each call the same instance is returned.
*/
public GraphicalElement getView() {
return _view;
}
/**
* Returns the clipping rectangle of specified by the axis.
* In each call the same instance is returned.
*/
public ClippingShape getClippingShape() {
return _clippingRectangle;
}
/**
* Returns the transformation of data coordinates into the device-independent
* coordinates of the axis box.
* In each call the same instance is returned.
*/
public Transformation getTransformation() {
return _transformation;
}
}