]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/GridUtils.java
Merge commit 'd186091'
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / utils / GridUtils.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.scenegraph.utils;\r
13 \r
14 import java.awt.geom.AffineTransform;\r
15 import java.awt.geom.Point2D;\r
16 import java.util.Arrays;\r
17 \r
18 /**\r
19  * A set of utilities for calculating even spacings. Useful for grid/rules\r
20  * spacing calculations.\r
21  * \r
22  * @author Tuukka Lehtonen\r
23  * @author Marko Luukkainen (original)\r
24  */\r
25 public final class GridUtils {\r
26 \r
27     private static double gridLineEvenSpacings[] = new double[] { 1.0, 2.0, 5.0, 10.0 };\r
28 \r
29     /**\r
30      * Returns next even grid spacing for value.\r
31      * \r
32      * @param value to round to nearest even grid spacing\r
33      * @param gridSize the base grid size that will multiply the even spacings\r
34      *        returned by this method\r
35      * @param lessThan <code>true</code> to select the nearest even spacing <=\r
36      *        value or <code>false</code> to select the nearest even spacing >=\r
37      *        value\r
38      * @return the calculated nearest even grid spacing\r
39      */\r
40     public static double getEvenGridSpacing(double value, double gridSize, boolean lessThan) {\r
41         double exp = Math.floor(Math.log10(value));\r
42         double gs = Math.pow(10.0, exp) * gridSize;\r
43 //        System.out.println("getEvenGridSpacing(" + value + ", " + gridSize + ", " + lessThan + "): " + exp + ", " + gs);\r
44         int i = lessThan ? 1 : 0;\r
45         int max = lessThan ? gridLineEvenSpacings.length : gridLineEvenSpacings.length - 1;\r
46         while (i < max) {\r
47 //            System.out.println("COMPARE(" + gridLineEvenSpacings[i] + "): " + gridLineEvenSpacings[i]*gs + " >= " + value);\r
48             if (gridLineEvenSpacings[i] * gs >= value) {\r
49                 if (lessThan)\r
50                     --i;\r
51                 break;\r
52             }\r
53             i++;\r
54         }\r
55         // FIXME: this is a workaround to keep the next line from causing an NPE\r
56         // Need to check the calculations and make some sense into this code once\r
57         // again to be sure.\r
58         if (i >= gridLineEvenSpacings.length)\r
59             return 2 * gridLineEvenSpacings[gridLineEvenSpacings.length - 1] * gs;\r
60         return gridLineEvenSpacings[i] * gs;\r
61     }\r
62 \r
63     /**\r
64      * Returns next even grid spacing for value with the assumed grid size of\r
65      * <code>1.0</code>.\r
66      * \r
67      * @param value to round to nearest even grid spacing\r
68      * @param lessThan <code>true</code> to select the nearest even spacing <=\r
69      *        value or <code>false</code> to select the nearest even spacing >=\r
70      *        value\r
71      * @return the calculated nearest even grid spacing\r
72      */\r
73     public static double getEvenGridSpacing(double value, boolean lessThan) {\r
74         return getEvenGridSpacing(value, 1.0, lessThan);\r
75     }\r
76 \r
77     /**\r
78      * Returns next even number for value and exponent of the value.\r
79      * \r
80      * @param value in units\r
81      * @param array of at least two elements where the results will be put\r
82      * @return the specified array, where even number is element [0] and\r
83      *         exponent is element [1]\r
84      */\r
85     public static double[] getEvenGridSpacingWithExp(double value, double[] array) {\r
86         if (array == null)\r
87             throw new NullPointerException("null array");\r
88         if (array.length < 2)\r
89             throw new NullPointerException("");\r
90         \r
91         /* TODO Time-Spacing        \r
92         1s 5s 10s 20s 30s        \r
93         1m 5m 10m 20m 30m   \r
94         1h 2h 6h 12h         \r
95          */\r
96 \r
97         double sig = Math.signum( value );\r
98         double exp = Math.floor(Math.log10( Math.abs(value) ));\r
99         double gs = Math.pow(10.0, exp);\r
100         int i = 0;\r
101         while (i < gridLineEvenSpacings.length - 1) {\r
102             if (gridLineEvenSpacings[i] * gs >= value) {\r
103                 break;\r
104             }\r
105             i++;\r
106         }\r
107         array[0] = gridLineEvenSpacings[i] * gs * sig;\r
108         array[1] = exp;\r
109         return array;\r
110     }\r
111 \r
112     /**\r
113      * Returns next even number for value and exponent of the value.\r
114      * \r
115      * @param value in units\r
116      * @return array where even number is [0] element and exponent is [1]\r
117      *         element\r
118      */\r
119     public static double[] getEvenGridSpacingWithExp(double value) {\r
120         return getEvenGridSpacingWithExp(value, new double[2]);\r
121     }\r
122 \r
123     /**\r
124      * @param fromCoord\r
125      * @param gridSpacing\r
126      * @return\r
127      */\r
128     public static double distanceToNextGridCoord(double fromCoord, double gridSpacing) {\r
129         double mod = Math.IEEEremainder(fromCoord, gridSpacing);\r
130         if (mod < 0) {\r
131             return -mod;\r
132         } else if (mod > 0) {\r
133             return (gridSpacing - mod);\r
134         }\r
135         return 0;\r
136     }\r
137 \r
138     /**\r
139      * @param fromCoord\r
140      * @param gridSpacing\r
141      * @return\r
142      */\r
143     public static double distanceToPrevGridCoord(double fromCoord, double gridSpacing) {\r
144         double mod = Math.IEEEremainder(fromCoord, gridSpacing);\r
145         if (mod < 0) {\r
146             return (gridSpacing + mod);\r
147         } else if (mod > 0) {\r
148             return mod;\r
149         }\r
150         return 0;\r
151     }\r
152     \r
153     /**\r
154      * @param coord\r
155      * @param gridSpacing\r
156      * @param scale\r
157      * @return\r
158      */\r
159     public static double distanceToNextGridCoordScaled(double coord, double gridSpacing, double scale) {\r
160         double result = distanceToNextGridCoord(coord, gridSpacing);\r
161         return result * scale;\r
162     }\r
163 \r
164     /**\r
165      * @param coord\r
166      * @param gridSpacing\r
167      * @param scale\r
168      * @return\r
169      */\r
170     public static double distanceToPrevGridCoordScaled(double coord, double gridSpacing, double scale) {\r
171         double result = distanceToPrevGridCoord(coord, gridSpacing);\r
172         return result * scale;\r
173     }\r
174     \r
175     /**\r
176      * @param coord\r
177      * @param gridSpacing\r
178      * @return\r
179      */\r
180     public static double distanceToNearestGridCoord(double coord, double gridSpacing) {\r
181         double dist = GridUtils.distanceToNextGridCoord(coord, gridSpacing);\r
182         if (dist > gridSpacing / 2)\r
183             dist = dist - gridSpacing;\r
184         return dist;\r
185     }\r
186 \r
187     /**\r
188      * @param tr\r
189      * @param gridSpacing\r
190      */\r
191     public static void snapToGrid(AffineTransform tr, double gridSpacing) {\r
192         double gdx = GridUtils.distanceToNearestGridCoord(tr.getTranslateX(), gridSpacing);\r
193         double gdy = GridUtils.distanceToNearestGridCoord(tr.getTranslateY(), gridSpacing);\r
194         //System.out.println("SNAP TO GRID: delta=(" + gdx + ", " + gdy + "), tr = " + tr);\r
195         tr.translate(gdx, gdy);\r
196     }\r
197 \r
198     /**\r
199      * @param p\r
200      * @param gridSpacing\r
201      */\r
202     public static void snapToGrid(Point2D p, double gridSpacing) {\r
203         snapToGrid(p, gridSpacing, gridSpacing);\r
204     }\r
205 \r
206     /**\r
207      * @param p\r
208      * @param gridXSpacing\r
209      * @param gridYSpacing\r
210      */\r
211     public static void snapToGrid(Point2D p, double gridXSpacing, double gridYSpacing) {\r
212         double x = p.getX();\r
213         double y = p.getY();\r
214         double gdx = GridUtils.distanceToNearestGridCoord(x, gridXSpacing);\r
215         double gdy = GridUtils.distanceToNearestGridCoord(y, gridYSpacing);\r
216         p.setLocation(x + gdx, y + gdy);\r
217     }\r
218 \r
219     /**\r
220      * @param t\r
221      * @param gridSpacing\r
222      * @return\r
223      */\r
224     public static double snapToGrid(double t, double gridSpacing) {\r
225         double dt = GridUtils.distanceToNearestGridCoord(t, gridSpacing);\r
226         return t + dt;\r
227     }\r
228 \r
229     /**\r
230      * Returns an even grid spacing where initialValue*scale <= limit.\r
231      * \r
232      * @param initialValue\r
233      * @param scale\r
234      * @param limit\r
235      * @param gridSize\r
236      * @param lessThan <code>true</code> to select the nearest even spacing <=\r
237      *        limit/scale or <code>false</code> to select the nearest even spacing >=\r
238      *        limit/scale\r
239      * @return\r
240      */\r
241     public static double limitedEvenGridSpacing(double initialValue, double scale, double limit, double gridSize, boolean lessThan) {\r
242         while (initialValue * scale > limit)\r
243             initialValue /= 2;\r
244         return getEvenGridSpacing(initialValue, gridSize, lessThan);\r
245     }\r
246 \r
247     /**\r
248      * Returns an even grid spacing where initialValue*scale <= limit\r
249      * \r
250      * @param initialValue\r
251      * @param scale\r
252      * @param limit\r
253      * @param lessThan <code>true</code> to select the nearest even spacing <=\r
254      *        limit/scale or <code>false</code> to select the nearest even spacing >=\r
255      *        limit/scale\r
256      * @return\r
257      */\r
258     public static double limitedEvenGridSpacing(double initialValue, double scale, double limit, boolean lessThan) {\r
259         return limitedEvenGridSpacing(initialValue, scale, limit, 1.0, lessThan);\r
260     }\r
261 \r
262     /**\r
263      * A simple test for these routines.\r
264      */\r
265     public static void main(String[] args) {\r
266         System.out.println(Arrays.toString(getEvenGridSpacingWithExp(15)));\r
267         System.out.println(Arrays.toString(getEvenGridSpacingWithExp(16.3)));\r
268         System.out.println(Arrays.toString(getEvenGridSpacingWithExp(143.41)));\r
269         System.out.println(Arrays.toString(getEvenGridSpacingWithExp(500.0)));\r
270         System.out.println(Arrays.toString(getEvenGridSpacingWithExp(10000.0)));\r
271         System.out.println(Arrays.toString(getEvenGridSpacingWithExp(0.5)));\r
272 \r
273         //double aa[] = new double[2];\r
274         System.out.println(getEvenGridSpacing(15, true));\r
275         System.out.println(getEvenGridSpacing(15, false));\r
276         System.out.println(getEvenGridSpacing(16.3, true));\r
277         System.out.println(getEvenGridSpacing(16.3, false));\r
278         System.out.println(getEvenGridSpacing(143.41, true));\r
279         System.out.println(getEvenGridSpacing(143.41, false));\r
280         System.out.println(getEvenGridSpacing(500.0, true));\r
281         System.out.println(getEvenGridSpacing(500.0, false));\r
282         System.out.println(getEvenGridSpacing(10000.0, true));\r
283         System.out.println(getEvenGridSpacing(10000.0, false));\r
284         System.out.println(getEvenGridSpacing(0.5, true));\r
285         System.out.println(getEvenGridSpacing(0.5, false));\r
286         System.out.println(getEvenGridSpacing(0.045, true));\r
287         System.out.println(getEvenGridSpacing(0.045, false));\r
288         System.out.println(getEvenGridSpacing(0.000605, true));\r
289         System.out.println(getEvenGridSpacing(0.000605, false));\r
290 \r
291         System.out.println(getEvenGridSpacing(143, 2.54, true));\r
292         System.out.println(getEvenGridSpacing(143, 2.54, false));\r
293     }\r
294 \r
295 }