package org.geogebra.common.kernel; /** * Normalized path that uses a path parameter in range [0,1]. * * @author Markus Hohenwarter */ public class PathNormalizer { /** * Converts path parameter value tn from range [0, 1] to [min, max]. * * @param pn * parameter value in [0,1] * @param min * of range [min, max] * @param max * of range [min, max] * @return parameter value in [min, max] */ public static double toParentPathParameter(double pn, double min, double max) { double tn = pn; // for Points as Paths (min=max=0) if (min == max) { return min; } if (tn < 0) { tn = 0; } else if (tn > 1) { tn = 1; } if (min == Double.NEGATIVE_INFINITY) { if (max == Double.POSITIVE_INFINITY) { // [0,1] -> (-infinite, +infinite) // first: (0,1) -> (-1,1), then use infFunction(-1 ... 1) return infFunction(2 * tn - 1); } // [0,1] -> (-infinite, max_param] // max_param + infFunction(-1 ... 0) return max + infFunction(tn - 1); } if (max == Double.POSITIVE_INFINITY) { // [0,1] -> [min_param, +infinite) // min_param + infFunction(0 ... 1) return min + infFunction(tn); } // [0,1] -> [min_param, max_param] return (1 - tn) * min + tn * max; } /** * Converts path parameter value t from range [min, max] to [0, 1]. * * @param p * parameter to be normalized * * @param min * of range [min, max] * @param max * of range [min, max] * @return parameter value in [0,1] */ public static double toNormalizedPathParameter(double p, double min, double max) { double t = p; // for Points as Paths (min=max=0) if (min == max) { return 0; } if (t < min) { t = min; } else if (t > max) { t = max; } if (min == Double.NEGATIVE_INFINITY) { if (max == Double.POSITIVE_INFINITY) { // (-infinite, +infinite) -> [0,1] if (t == Double.NEGATIVE_INFINITY) { return 0; } else if (t == Double.POSITIVE_INFINITY) { return 1; } else { // (-infinite, +infinite) -> (0,1) // solve for tn: t = infFunction(2*tn - 1); return 0.5 + 0.5 * inverseInfFunction(t); } } // (-infinite, max] -> [0,1] if (t == Double.NEGATIVE_INFINITY) { return 0; } // solve for tn: t = max + infFunction(tn - 1); return 1 + inverseInfFunction(t - max); } if (max == Double.POSITIVE_INFINITY) { // [min, +infinite) -> [0,1] // solve for tn: t = min + infFunction(tn) return inverseInfFunction(t - min); } // [min, max] -> [0,1] // solve for tn: t = (1 - tn) * min + tn * max; return (t - min) / (max - min); } /** * Function t: (-1, 1) -> (-inf, +inf) * * @param t * parameter from (-1,1) * @return parameter in (-1,1) to be mapped into all reals */ public static double infFunction(double t) { return t / (1 - Math.abs(t)); } /** * Function z: (-inf, +inf) -> (-1, 1) * * @param z * arbitrary parameter * @return arbitrary parameter to be mapped into (-1,1) */ public static double inverseInfFunction(double z) { if (z == Double.NEGATIVE_INFINITY) { return -1 + PathMover.OPEN_BORDER_OFFSET; } if (z >= 0) { return z / (1 + z); } return z / (1 - z); } /* * TEST */ // public static void main(String[] args) { // // for (int i=0; i<10; i++) { // double t = 2*Math.random()-1; // System.out.println("t = " + t); // // double tn = toNormalizedPathParameter(t, Double.NEGATIVE_INFINITY, // Double.POSITIVE_INFINITY); // double t2= toParentPathParameter(tn, Double.NEGATIVE_INFINITY, // Double.POSITIVE_INFINITY); // System.out.println("\ttn = " + tn + ", error: " + (t2-t)); // // tn = toNormalizedPathParameter(t, Double.NEGATIVE_INFINITY, 3); // t2= toParentPathParameter(tn, Double.NEGATIVE_INFINITY, 3); // System.out.println("\ttn = " + tn + ", error: " + (t2-t)); // // tn = toNormalizedPathParameter(t, -7, Double.POSITIVE_INFINITY); // t2= toParentPathParameter(tn, -7, Double.POSITIVE_INFINITY); // System.out.println("\ttn = " + tn + ", error: " + (t2-t)); // // tn = toNormalizedPathParameter(t, -5, 9); // t2= toParentPathParameter(tn, -5, 9); // System.out.println("\ttn = " + tn + ", error: " + (t2-t)); // } // // } }