]> gerrit.simantics Code Review - simantics/district.git/blobdiff - org.simantics.district.maps/src/org/simantics/maps/sg/Formatting.java
Optimization of district scene graph node rendering
[simantics/district.git] / org.simantics.district.maps / src / org / simantics / maps / sg / Formatting.java
diff --git a/org.simantics.district.maps/src/org/simantics/maps/sg/Formatting.java b/org.simantics.district.maps/src/org/simantics/maps/sg/Formatting.java
new file mode 100644 (file)
index 0000000..67c803d
--- /dev/null
@@ -0,0 +1,92 @@
+package org.simantics.maps.sg;
+
+import java.util.Locale;
+
+/**
+ * @author Tuukka Lehtonen
+ */
+class Formatting {
+
+    private static final transient double EPSILON = 0.01;
+
+    private static final transient double TRIM_THRESHOLD_MAX_VALUE = Math.pow(10, 4);
+
+    private static final transient String[] SI_UNIT_LARGE_PREFIXES = {
+        "k", "M", "G", "T", "P", "E", "Z", "Y"
+    };
+
+    public static enum FormatMode {
+        LIMIT_DIGITS,
+        LIMIT_DECIMALS,
+    }
+
+    public static String formatValue(double value, int max, boolean removeTrailingZeros, FormatMode formatMode) {
+        return formatValue(value, max, removeTrailingZeros, formatMode, TRIM_THRESHOLD_MAX_VALUE);
+    }
+
+    public static String formatValue(double value, int max, boolean removeTrailingZeros, FormatMode formatMode, double trimThresholdMaxValue) {
+        return formatValue(value, max, removeTrailingZeros, formatMode, trimThresholdMaxValue, true);
+    }
+
+    public static String formatValue(double value, int max, boolean removeTrailingZeros, FormatMode formatMode, double trimThresholdMaxValue, boolean trimLargeValues) {
+        //System.out.println("formatValue(" + value + ", " + max + ", " + removeTrailingZeros + ", " + formatMode + ", " + trimThresholdMaxValue + ", " + trimLargeValues + ")");
+        int allowedDecimals = max;
+        if (formatMode == FormatMode.LIMIT_DIGITS) {
+            int magnitude = (int) Math.ceil(Math.log10(Math.abs(value)));
+            //System.out.println("magnitude(" + value + "): " + magnitude);
+            allowedDecimals -= Math.abs(magnitude);
+            if (allowedDecimals < 0)
+                allowedDecimals = 0;
+            //System.out.println("allowedDecimals: " + allowedDecimals);
+        }
+
+        String valueStr = String.format(Locale.US, "%." + allowedDecimals + "f", value);
+        if (allowedDecimals > 0) {
+            if (removeTrailingZeros) {
+                for (int trunc = valueStr.length() - 1; trunc > 0; --trunc) {
+                    char ch = valueStr.charAt(trunc);
+                    if (ch == '.') {
+                        valueStr = valueStr.substring(0, trunc);
+                        break;
+                    }
+                    if (ch != '0') {
+                        valueStr = valueStr.substring(0, trunc + 1);
+                        break;
+                    }
+                }
+            }
+            if (Math.abs(value) + EPSILON > trimThresholdMaxValue) {
+                // Cut anything beyond a possible decimal dot out since they
+                // should not show anyway. This is a complete hack that tries to
+                // circumvent floating-point inaccuracy problems.
+                int dotIndex = valueStr.lastIndexOf('.');
+                if (dotIndex > -1) {
+                    valueStr = valueStr.substring(0, dotIndex);
+                }
+            }
+        }
+
+        if (valueStr.equals("-0"))
+            valueStr = "0";
+
+        if (trimLargeValues) {
+            double trimValue = value;
+            if (Math.abs(value) + EPSILON >= trimThresholdMaxValue) {
+                for (int i = 0; Math.abs(trimValue) + EPSILON >= trimThresholdMaxValue; ++i) {
+                    double trim = trimValue / 1000;
+                    if (Math.abs(trim) - EPSILON < trimThresholdMaxValue) {
+                        valueStr = valueStr.substring(0, valueStr.length() - (i + 1) * 3);
+                        valueStr += SI_UNIT_LARGE_PREFIXES[i];
+                        break;
+                    }
+                    trimValue = trim;
+                }
+            }
+        }
+
+        //System.out.println("formatted result: " + valueStr);
+
+        return valueStr;
+    }
+
+}