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