--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.scenegraph.utils;\r
+\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Point2D;\r
+import java.util.Arrays;\r
+\r
+/**\r
+ * A set of utilities for calculating even spacings. Useful for grid/rules\r
+ * spacing calculations.\r
+ * \r
+ * @author Tuukka Lehtonen\r
+ * @author Marko Luukkainen (original)\r
+ */\r
+public final class GridUtils {\r
+\r
+ private static double gridLineEvenSpacings[] = new double[] { 1.0, 2.0, 5.0, 10.0 };\r
+\r
+ /**\r
+ * Returns next even grid spacing for value.\r
+ * \r
+ * @param value to round to nearest even grid spacing\r
+ * @param gridSize the base grid size that will multiply the even spacings\r
+ * returned by this method\r
+ * @param lessThan <code>true</code> to select the nearest even spacing <=\r
+ * value or <code>false</code> to select the nearest even spacing >=\r
+ * value\r
+ * @return the calculated nearest even grid spacing\r
+ */\r
+ public static double getEvenGridSpacing(double value, double gridSize, boolean lessThan) {\r
+ double exp = Math.floor(Math.log10(value));\r
+ double gs = Math.pow(10.0, exp) * gridSize;\r
+// System.out.println("getEvenGridSpacing(" + value + ", " + gridSize + ", " + lessThan + "): " + exp + ", " + gs);\r
+ int i = lessThan ? 1 : 0;\r
+ int max = lessThan ? gridLineEvenSpacings.length : gridLineEvenSpacings.length - 1;\r
+ while (i < max) {\r
+// System.out.println("COMPARE(" + gridLineEvenSpacings[i] + "): " + gridLineEvenSpacings[i]*gs + " >= " + value);\r
+ if (gridLineEvenSpacings[i] * gs >= value) {\r
+ if (lessThan)\r
+ --i;\r
+ break;\r
+ }\r
+ i++;\r
+ }\r
+ // FIXME: this is a workaround to keep the next line from causing an NPE\r
+ // Need to check the calculations and make some sense into this code once\r
+ // again to be sure.\r
+ if (i >= gridLineEvenSpacings.length)\r
+ return 2 * gridLineEvenSpacings[gridLineEvenSpacings.length - 1] * gs;\r
+ return gridLineEvenSpacings[i] * gs;\r
+ }\r
+\r
+ /**\r
+ * Returns next even grid spacing for value with the assumed grid size of\r
+ * <code>1.0</code>.\r
+ * \r
+ * @param value to round to nearest even grid spacing\r
+ * @param lessThan <code>true</code> to select the nearest even spacing <=\r
+ * value or <code>false</code> to select the nearest even spacing >=\r
+ * value\r
+ * @return the calculated nearest even grid spacing\r
+ */\r
+ public static double getEvenGridSpacing(double value, boolean lessThan) {\r
+ return getEvenGridSpacing(value, 1.0, lessThan);\r
+ }\r
+\r
+ /**\r
+ * Returns next even number for value and exponent of the value.\r
+ * \r
+ * @param value in units\r
+ * @param array of at least two elements where the results will be put\r
+ * @return the specified array, where even number is element [0] and\r
+ * exponent is element [1]\r
+ */\r
+ public static double[] getEvenGridSpacingWithExp(double value, double[] array) {\r
+ if (array == null)\r
+ throw new NullPointerException("null array");\r
+ if (array.length < 2)\r
+ throw new NullPointerException("");\r
+ \r
+ /* TODO Time-Spacing \r
+ 1s 5s 10s 20s 30s \r
+ 1m 5m 10m 20m 30m \r
+ 1h 2h 6h 12h \r
+ */\r
+\r
+ double sig = Math.signum( value );\r
+ double exp = Math.floor(Math.log10( Math.abs(value) ));\r
+ double gs = Math.pow(10.0, exp);\r
+ int i = 0;\r
+ while (i < gridLineEvenSpacings.length - 1) {\r
+ if (gridLineEvenSpacings[i] * gs >= value) {\r
+ break;\r
+ }\r
+ i++;\r
+ }\r
+ array[0] = gridLineEvenSpacings[i] * gs * sig;\r
+ array[1] = exp;\r
+ return array;\r
+ }\r
+\r
+ /**\r
+ * Returns next even number for value and exponent of the value.\r
+ * \r
+ * @param value in units\r
+ * @return array where even number is [0] element and exponent is [1]\r
+ * element\r
+ */\r
+ public static double[] getEvenGridSpacingWithExp(double value) {\r
+ return getEvenGridSpacingWithExp(value, new double[2]);\r
+ }\r
+\r
+ /**\r
+ * @param fromCoord\r
+ * @param gridSpacing\r
+ * @return\r
+ */\r
+ public static double distanceToNextGridCoord(double fromCoord, double gridSpacing) {\r
+ double mod = Math.IEEEremainder(fromCoord, gridSpacing);\r
+ if (mod < 0) {\r
+ return -mod;\r
+ } else if (mod > 0) {\r
+ return (gridSpacing - mod);\r
+ }\r
+ return 0;\r
+ }\r
+\r
+ /**\r
+ * @param fromCoord\r
+ * @param gridSpacing\r
+ * @return\r
+ */\r
+ public static double distanceToPrevGridCoord(double fromCoord, double gridSpacing) {\r
+ double mod = Math.IEEEremainder(fromCoord, gridSpacing);\r
+ if (mod < 0) {\r
+ return (gridSpacing + mod);\r
+ } else if (mod > 0) {\r
+ return mod;\r
+ }\r
+ return 0;\r
+ }\r
+ \r
+ /**\r
+ * @param coord\r
+ * @param gridSpacing\r
+ * @param scale\r
+ * @return\r
+ */\r
+ public static double distanceToNextGridCoordScaled(double coord, double gridSpacing, double scale) {\r
+ double result = distanceToNextGridCoord(coord, gridSpacing);\r
+ return result * scale;\r
+ }\r
+\r
+ /**\r
+ * @param coord\r
+ * @param gridSpacing\r
+ * @param scale\r
+ * @return\r
+ */\r
+ public static double distanceToPrevGridCoordScaled(double coord, double gridSpacing, double scale) {\r
+ double result = distanceToPrevGridCoord(coord, gridSpacing);\r
+ return result * scale;\r
+ }\r
+ \r
+ /**\r
+ * @param coord\r
+ * @param gridSpacing\r
+ * @return\r
+ */\r
+ public static double distanceToNearestGridCoord(double coord, double gridSpacing) {\r
+ double dist = GridUtils.distanceToNextGridCoord(coord, gridSpacing);\r
+ if (dist > gridSpacing / 2)\r
+ dist = dist - gridSpacing;\r
+ return dist;\r
+ }\r
+\r
+ /**\r
+ * @param tr\r
+ * @param gridSpacing\r
+ */\r
+ public static void snapToGrid(AffineTransform tr, double gridSpacing) {\r
+ double gdx = GridUtils.distanceToNearestGridCoord(tr.getTranslateX(), gridSpacing);\r
+ double gdy = GridUtils.distanceToNearestGridCoord(tr.getTranslateY(), gridSpacing);\r
+ //System.out.println("SNAP TO GRID: delta=(" + gdx + ", " + gdy + "), tr = " + tr);\r
+ tr.translate(gdx, gdy);\r
+ }\r
+\r
+ /**\r
+ * @param p\r
+ * @param gridSpacing\r
+ */\r
+ public static void snapToGrid(Point2D p, double gridSpacing) {\r
+ snapToGrid(p, gridSpacing, gridSpacing);\r
+ }\r
+\r
+ /**\r
+ * @param p\r
+ * @param gridXSpacing\r
+ * @param gridYSpacing\r
+ */\r
+ public static void snapToGrid(Point2D p, double gridXSpacing, double gridYSpacing) {\r
+ double x = p.getX();\r
+ double y = p.getY();\r
+ double gdx = GridUtils.distanceToNearestGridCoord(x, gridXSpacing);\r
+ double gdy = GridUtils.distanceToNearestGridCoord(y, gridYSpacing);\r
+ p.setLocation(x + gdx, y + gdy);\r
+ }\r
+\r
+ /**\r
+ * @param t\r
+ * @param gridSpacing\r
+ * @return\r
+ */\r
+ public static double snapToGrid(double t, double gridSpacing) {\r
+ double dt = GridUtils.distanceToNearestGridCoord(t, gridSpacing);\r
+ return t + dt;\r
+ }\r
+\r
+ /**\r
+ * Returns an even grid spacing where initialValue*scale <= limit.\r
+ * \r
+ * @param initialValue\r
+ * @param scale\r
+ * @param limit\r
+ * @param gridSize\r
+ * @param lessThan <code>true</code> to select the nearest even spacing <=\r
+ * limit/scale or <code>false</code> to select the nearest even spacing >=\r
+ * limit/scale\r
+ * @return\r
+ */\r
+ public static double limitedEvenGridSpacing(double initialValue, double scale, double limit, double gridSize, boolean lessThan) {\r
+ while (initialValue * scale > limit)\r
+ initialValue /= 2;\r
+ return getEvenGridSpacing(initialValue, gridSize, lessThan);\r
+ }\r
+\r
+ /**\r
+ * Returns an even grid spacing where initialValue*scale <= limit\r
+ * \r
+ * @param initialValue\r
+ * @param scale\r
+ * @param limit\r
+ * @param lessThan <code>true</code> to select the nearest even spacing <=\r
+ * limit/scale or <code>false</code> to select the nearest even spacing >=\r
+ * limit/scale\r
+ * @return\r
+ */\r
+ public static double limitedEvenGridSpacing(double initialValue, double scale, double limit, boolean lessThan) {\r
+ return limitedEvenGridSpacing(initialValue, scale, limit, 1.0, lessThan);\r
+ }\r
+\r
+ /**\r
+ * A simple test for these routines.\r
+ */\r
+ public static void main(String[] args) {\r
+ System.out.println(Arrays.toString(getEvenGridSpacingWithExp(15)));\r
+ System.out.println(Arrays.toString(getEvenGridSpacingWithExp(16.3)));\r
+ System.out.println(Arrays.toString(getEvenGridSpacingWithExp(143.41)));\r
+ System.out.println(Arrays.toString(getEvenGridSpacingWithExp(500.0)));\r
+ System.out.println(Arrays.toString(getEvenGridSpacingWithExp(10000.0)));\r
+ System.out.println(Arrays.toString(getEvenGridSpacingWithExp(0.5)));\r
+\r
+ //double aa[] = new double[2];\r
+ System.out.println(getEvenGridSpacing(15, true));\r
+ System.out.println(getEvenGridSpacing(15, false));\r
+ System.out.println(getEvenGridSpacing(16.3, true));\r
+ System.out.println(getEvenGridSpacing(16.3, false));\r
+ System.out.println(getEvenGridSpacing(143.41, true));\r
+ System.out.println(getEvenGridSpacing(143.41, false));\r
+ System.out.println(getEvenGridSpacing(500.0, true));\r
+ System.out.println(getEvenGridSpacing(500.0, false));\r
+ System.out.println(getEvenGridSpacing(10000.0, true));\r
+ System.out.println(getEvenGridSpacing(10000.0, false));\r
+ System.out.println(getEvenGridSpacing(0.5, true));\r
+ System.out.println(getEvenGridSpacing(0.5, false));\r
+ System.out.println(getEvenGridSpacing(0.045, true));\r
+ System.out.println(getEvenGridSpacing(0.045, false));\r
+ System.out.println(getEvenGridSpacing(0.000605, true));\r
+ System.out.println(getEvenGridSpacing(0.000605, false));\r
+\r
+ System.out.println(getEvenGridSpacing(143, 2.54, true));\r
+ System.out.println(getEvenGridSpacing(143, 2.54, false));\r
+ }\r
+\r
+}
\ No newline at end of file