001: /*
002: * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved
003: *
004: * This library is free software; you can redistribute it and/or modify
005: * it under the terms of the GNU Lesser General Public License as published by
006: * the Free Software Foundation; either version 2.1 of the License, or
007: * (at your option) any later version.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU Lesser General Public License for more details
013: * (http://www.gnu.org/copyleft/lesser.html).
014: *
015: * You should have received a copy of the GNU Lesser General Public License
016: * along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019: package jcckit.plot;
020:
021: import jcckit.graphic.GraphPoint;
022: import jcckit.graphic.GraphicAttributes;
023: import jcckit.graphic.GraphicalComposite;
024: import jcckit.graphic.GraphicalElement;
025: import jcckit.graphic.Rectangle;
026: import jcckit.util.ConfigParameters;
027: import jcckit.util.Factory;
028:
029: /**
030: * Symbol factory for creating symbols with error bars. It wraps
031: * a {@link SymbolFactory} for creating the symbol. The error bars
032: * are {@link Rectangle Rectangles}.
033: * <p>
034: * Curves with error bars are based on <em>two</em>
035: * {@link jcckit.data.DataCurve DataCurves}:
036: * <ol><li>The plain curve.
037: * <li>An instance which stores the errors in <i>x</i> and <i>y</i>.
038: * It is assumed that the errors are positive values defining
039: * the error symmetrically around the curve points.
040: * </ol>
041: * <p>
042: * The <tt>ErrorBarFactory</tt> needs an instance of {@link PositionHint}
043: * as initial {@link Hint} for the next curve. Its origin must be
044: * the origin of the data coordinate system in device-independent coordinates.
045: * The position of <tt>PositionHint</tt> must be undefined.
046: *
047: * @author Franz-Josef Elmer
048: */
049: public class ErrorBarFactory implements SymbolFactory {
050: /** Configuration parameter key. */
051: public static final String SYMBOL_FACTORY_KEY = "symbolFactory";
052:
053: private final SymbolFactory _symbolFactory;
054: private final GraphicAttributes _attributes;
055: private final double _size;
056:
057: /**
058: * Creates an instance from the specified configuration parameters.
059: * <table border=1 cellpadding=5>
060: * <tr><th>Key & Default Value</th><th>Type</th><th>Mandatory</th>
061: * <th>Description</th></tr>
062: * <tr><td><tt>symbolFactory = null</tt></td>
063: * <td><tt>ConfigParameters</tt></td><td>no</td>
064: * <td>Definition of the wrapped {@link SymbolFactory} which generates
065: * the curve symbol without bars. By default an empty
066: * {@link GraphicalComposite} will be created.</td></tr>
067: * <tr><td><tt>size = 0</tt></td>
068: * <td><tt>double</tt></td><td>no</td>
069: * <td>Width of the error bars.</td></tr>
070: * <tr><td><tt>attributes = null</tt></td>
071: * <td><tt>ConfigParameters</tt></td><td>no</td>
072: * <td>Definition of the {@link GraphicAttributes} of the error
073: * bars.</td></tr>
074: * </table>
075: */
076: public ErrorBarFactory(ConfigParameters config) {
077: _symbolFactory = (SymbolFactory) Factory.createOrGet(config
078: .getNode(SYMBOL_FACTORY_KEY), null);
079: _size = config.getDouble(SIZE_KEY, 0);
080: _attributes = (GraphicAttributes) Factory.createOrGet(config
081: .getNode(ATTRIBUTES_KEY), null);
082: }
083:
084: /**
085: * Creates the legend symbol. Calls the wrapped {@link SymbolFactory}
086: * or returns an empty instance of {@link GraphicalComposite} if undefined.
087: */
088: public GraphicalElement createLegendSymbol(
089: GraphPoint centerPosition, double size) {
090: return _symbolFactory == null ? new GraphicalComposite(null)
091: : _symbolFactory.createLegendSymbol(centerPosition,
092: size);
093: }
094:
095: /**
096: * Creates either the curve symbol or the error bars. Error bars are
097: * created when <tt>hintFromPreviousCurve</tt> is an instance of
098: * {@link PositionHint} and its position attribute is not <tt>null</tt>.
099: * Otherwise the curve symbol is created. The position attributes stores
100: * the curve point (in device-independent coordinates). The origin is
101: * always as set in the initial <tt>PositionHint</tt>. The hint for
102: * the next curve wrapped by the returned <tt>Symbol</tt> is always
103: * a <tt>PositionHint</tt>.
104: */
105: public Symbol createSymbol(GraphPoint point,
106: Hint hintFromPreviousPoint, Hint hintFromPreviousCurve) {
107: GraphPoint origin = new GraphPoint(null);
108: GraphPoint position = null;
109: if (hintFromPreviousCurve instanceof PositionHint) {
110: origin = ((PositionHint) hintFromPreviousCurve).getOrigin();
111: position = ((PositionHint) hintFromPreviousCurve)
112: .getPosition();
113: }
114: if (position == null) {
115: if (_symbolFactory == null) {
116: return new Symbol(new GraphicalComposite(null),
117: hintFromPreviousPoint, new PositionHint(origin,
118: point));
119: } else {
120: return _symbolFactory.createSymbol(point,
121: hintFromPreviousPoint, new PositionHint(origin,
122: point));
123: }
124: } else {
125: double xError = point.getX() - origin.getX();
126: double yError = point.getY() - origin.getY();
127: GraphicalComposite errorBars = new GraphicalComposite(null);
128: if (xError > 0) {
129: errorBars.addElement(new Rectangle(position,
130: 2 * xError, _size, _attributes));
131: }
132: if (yError > 0) {
133: errorBars.addElement(new Rectangle(position, _size,
134: 2 * yError, _attributes));
135: }
136: return new Symbol(errorBars, hintFromPreviousPoint,
137: new PositionHint(origin, null));
138: }
139: }
140: }
|