1 /*
2 * Copyright (c) 2003-2008 by Cosylab d. d.
3 *
4 * This file is part of CosyBeans-Common.
5 *
6 * CosyBeans-Common is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * CosyBeans-Common is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with CosyBeans-Common. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 package com.cosylab.gui.components.gauger;
21
22 import java.awt.Graphics;
23 import java.awt.Point;
24 import java.awt.Rectangle;
25 import java.awt.geom.Point2D;
26
27 import java.util.ArrayList;
28
29
30 /**
31 * Abstract utility class that provides the mathematic foundation for drawing
32 * the Gauger scales. Scale is defined in its own coordinate system with the
33 * axis (u, v). In this system the extents of the scale are defined to be (0,
34 * 0) and (1, 1), meaning that any point on this scale can be specified with
35 * the (u, v) parameter value between 0 and 1. This class is the
36 * implementation of this transformation and the component cartesian
37 * coordinate system.
38 *
39 * @author <a href="mailto:ales.pucelj@cosylab.com">Ales Pucelj</a>
40 * @version $id$
41 */
42 public abstract class ScaleTransform
43 {
44 private Point2D tempPoint = new Point2D.Double();
45 private Point labelPosition = new Point();
46 private boolean polar = false;
47
48 /**
49 * Abstract base class for scale segments.
50 *
51 * @author $Author: jbobnar $
52 * @version $Revision: 1.4 $
53 */
54 public class ScaleSegment
55 {
56 }
57
58 /**
59 * Class defining linear scale segment.
60 *
61 * @author $Author: jbobnar $
62 * @version $Revision: 1.4 $
63 */
64 public class LineSegment extends ScaleSegment
65 {
66 /** Starting point of line */
67 public Point2D lineStart;
68
69 /** Ending point of line */
70 public Point2D lineEnd;
71
72 /**
73 * Creates a new LineSegment object.
74 *
75 * @param xs X coordinate of starting point.
76 * @param ys Y coordinate of starting point.
77 * @param xe X coordinate of ending point.
78 * @param ye Y coordinate of ending point.
79 */
80 public LineSegment(double xs, double ys, double xe, double ye)
81 {
82 lineStart = new Point2D.Double(xs, ys);
83 lineEnd = new Point2D.Double(xe, ye);
84 }
85 }
86
87 /**
88 * Definition of arc scale segment.
89 *
90 * @author $Author: jbobnar $
91 * @version $Revision: 1.4 $
92 */
93 public class ArcSegment extends ScaleSegment
94 {
95 /** Center point of arc */
96 public Point2D center;
97
98 /** Outer radius of arc */
99 public double rOuter;
100
101 /** Inner radius of arc */
102 public double rInner;
103
104 /** Starting angle of arc */
105 public double startAngle;
106
107 /** Included angle of arc */
108 public double arcAngle;
109
110 /**
111 * Creates a new ArcSegment object.
112 *
113 * @param c Center point
114 * @param r inner radius
115 * @param R Outer radius
116 * @param start Starting angle
117 * @param angle Included angle
118 */
119 public ArcSegment(Point2D c, double r, double R, double start,
120 double angle)
121 {
122 center = c;
123 rOuter = R;
124 rInner = r;
125 startAngle = start;
126 arcAngle = angle;
127 }
128 }
129
130 /**
131 * Defines rectangular scale segment.
132 *
133 * @author $Author: jbobnar $
134 * @version $Revision: 1.4 $
135 */
136 public class RectangleSegment extends ScaleSegment
137 {
138 /** Coordinates of rectangle */
139 public Rectangle rect;
140
141 /**
142 * Creates a new RectangleSegment object.
143 *
144 * @param rect Coordinates of rectangle.
145 */
146 public RectangleSegment(Rectangle rect)
147 {
148 this.rect = rect;
149 }
150 }
151
152 /** Segments comprising this scale. */
153 private ArrayList<ScaleSegment> segments = null;
154
155 /**
156 * Creates a new ScaleTransform object.
157 */
158 public ScaleTransform()
159 {
160 super();
161 segments = new ArrayList<ScaleSegment>();
162 }
163
164 /**
165 * Sets whether this transform is polar. A polar scale will be rendered in
166 * polar coordinates rather then cartesian. Lines will be rendered as arcs
167 * and text will be rotated.
168 *
169 * @param value True if polar.
170 */
171 public void setPolar(boolean value)
172 {
173 polar = value;
174 }
175
176 /**
177 * Returns whether this scale is polar.
178 *
179 * @return True if polar.
180 *
181 * @see setPolar(boolean)
182 */
183 public boolean isPolar()
184 {
185 return polar;
186 }
187
188 /**
189 * Sets the component parameters for this transformation.
190 *
191 * @param w width of the component that will display this transformation
192 * @param h height of the component that will display this transformation
193 * @param marginX not used
194 * @param marginY not used
195 * @param tickOffset space between the edge of the scale and the first tick
196 */
197 public abstract void setParameters(int w, int h, int marginX, int marginY,
198 int tickOffset);
199
200 /**
201 * Maps the point specified with (u, v) coordinates in the scale space to
202 * cartesian space with coordinates (x, y). (u, v) values must be in
203 * [0..1] range, the (x, y) points will be in (0..w-1, 0..h-1) range.
204 *
205 * @param scaleSpace point in scale space
206 * @param cartesianSpace point in cartesian space
207 */
208 public abstract void mapUVtoXY(Point2D scaleSpace, Point2D cartesianSpace);
209
210 /**
211 * Maps the point specified with (u, v) coordinates in the scale space to
212 * cartesian space with coordinates (x, y). (u, v) values must be in
213 * [0..1] range, the (x, y) points will be in (0..w-1, 0..h-1) range.
214 *
215 * @param u coordinate in scale space
216 * @param v coordinate in scale space
217 * @param cartesianSpace point in cartesian space
218 */
219 public void mapUVtoXY(double u, double v, Point2D cartesianSpace)
220 {
221 tempPoint.setLocation(u, v);
222 mapUVtoXY(tempPoint, cartesianSpace);
223 }
224
225 /**
226 * Maps point specified with (u, v) coordinates in scale space to
227 * cartesian space with coordinates (x, y)
228 *
229 * @param u coordinate in scale space.
230 * @param v coordinate in scale space.
231 *
232 * @return Point2D cartesianSpace point.
233 *
234 * @see mapUVtoXY(u, v, Point2D)
235 */
236 public Point2D mapUVtoXY(double u, double v)
237 {
238 Point2D point = new Point2D.Double();
239 mapUVtoXY(u, v, point);
240
241 return point;
242 }
243
244 /**
245 * Returns angle between horizontal and specified relative position in
246 * scale space. This angle is defined as angle between X axis and line
247 * from point (x, 0.0) to point (x, 100.0). This is the angle at which
248 * vertical straight line in polar mode is rotated in cartesian space.
249 *
250 * @param x Relative point in scale space in range 0.0 to 1.0.
251 *
252 * @return double angle in radians
253 */
254 public final double getAngle(double x)
255 {
256 final Point2D p1 = mapUVtoXY(x, 0);
257 final Point2D p2 = mapUVtoXY(x, 100000.0);
258
259 final double dx = (p2.getX() - p1.getX());
260 final double dy = (p2.getY() - p1.getY());
261
262 double phi = (dx == 0.0) ? 0 : -Math.atan(dy / dx) - Math.PI * 0.5;
263
264 if(dx < 0) {
265 phi += Math.PI;
266 }
267
268 return phi;
269 }
270
271 /**
272 * Returns the width of scale in pixels at the specified location v in the
273 * scale space. Although the scale for v is only defined in the range
274 * [0..1], this value can generaly return even values outside this range,
275 * although this is not guaranteed.
276 *
277 * @return Width of scale in pixels.
278 */
279 public abstract double scaleWidth(double v);
280
281 /**
282 * Returns the height of scale in pixels at the specified location u in the
283 * scale space. Although the scale for u is only defined in the range
284 * [0..1], this value can generaly return even values outside this range,
285 * although this is not guaranteed.
286 *
287 * @return Height of scale in pixels.
288 */
289 public abstract double scaleHeight(double u);
290
291 /**
292 * Returns the point where the label should be positioned. This point
293 * represents geometric center of the text. There are no limits to the
294 * size of the text written around this position.
295 *
296 * @return Center point for label.
297 */
298 public Point getLabelPosition()
299 {
300 return labelPosition;
301 }
302
303 /**
304 * Returns the number of segments describing this scale. Even if the value
305 * is zero, this transform may still provide space transformation
306 * functionality.
307 *
308 * @return Number of segments.
309 */
310 public int getSegmentCount()
311 {
312 return segments.size();
313 }
314
315 /**
316 * Adds segment to this transform.
317 *
318 * @param segment to add.
319 */
320 protected void addSegment(ScaleSegment segment)
321 {
322 segments.add(segment);
323 }
324
325 /**
326 * Returns scale segment at specified index.
327 *
328 * @param i Index of segment.
329 *
330 * @return Scale segment.
331 */
332 public ScaleSegment getSegment(int i)
333 {
334 return (ScaleSegment)(segments.get(i));
335 }
336
337 /**
338 * Sets position of value label. The position is center point of label.
339 *
340 * @param x coordinate of label center.
341 * @param y coordinate of label center.
342 */
343 protected void setLabelPosition(int x, int y)
344 {
345 labelPosition.x = x;
346 labelPosition.y = y;
347 }
348
349 /**
350 * Measues the width of tick label.
351 *
352 * @param g Graphic context.
353 * @param x Relative position of tick.
354 * @param text Tick label.
355 *
356 * @return Width of label in pixels.
357 */
358 public abstract int measureTick(Graphics g, double x, String text);
359 }
360
361 /* __oOo__ */