Beispiel #1
0
        /**
         * Computes the range of substrokes to use when computing matches based on looseness.
         * When matching, sub strokes are matched up with one another to find the best
         * matching.  But if two substrokes are +/-  beyond this range, then the comparison
         * is short-circuited for some computation savings.
         *
         * @param subStrokeCount the substroke count of the input character
         * @param looseness the looseness, 0-1
         * @return the range
         */
        private int getSubStrokesRange(int subStrokeCount)
        {
            // Return the maximum if looseness = 1.0.
            // Otherwise we'd have to ensure that the floating point value led to exactly the right int count.
            if (looseness == 1.0)
            {
                return(CharacterDescriptor.MAX_CHARACTER_SUB_STROKE_COUNT);
            }

            // We use a CubicCurve that grows slowly at first and then rapidly near the end to the maximum.

            double y0 = subStrokeCount * 0.25;

            double ctrl1X = 0.4;
            double ctrl1Y = 1.5 * y0;

            double ctrl2X = 0.75;
            double ctrl2Y = 1.5 * ctrl1Y;

            double[]     solutions = new double[1];
            CubicCurve2D curve     = new CubicCurve2D(0, y0, ctrl1X, ctrl1Y, ctrl2X, ctrl2Y, 1, CharacterDescriptor.MAX_CHARACTER_SUB_STROKE_COUNT);
            //CurveUtils.solveCubicCurveForX(curve, looseness, solutions);
            //double t = solutions[0];
            double t = curve.GetFirstSolutionForX(looseness);

            // We get the t value on the parametrized curve where the x value matches the looseness.
            // Then we compute the y value for that t.  This gives the range.

            //return (int)Math.Round(CurveUtils.getPointOnCubicCurve(curve, t).getY());
            return((int)Math.Round(curve.GetYOnCurve(t)));
        }
Beispiel #2
0
        /**
         * A common helper method to initialize a table of precomputed score values using a cubic curve
         * @param curve the curve
         * @param numSamples the number of samples to compute
         * @return the score array table
         */
        static private double[] initCubicCurveScoreTable(CubicCurve2D curve, int numSamples)
        {
            double x1 = curve.X1;
            double x2 = curve.X2;

            double range = x2 - x1;

            double x    = x1;
            double xInc = range / numSamples;  // even incrementer to increment x value by when sampling across the curve

            double[] scoreTable = new double[numSamples];

            // For use to pass into with solveCubicCurve
            double[] solutions = new double[1];

            // Sample evenly across the curve and set the samples into the table.
            for (int i = 0; i < numSamples; i++)
            {
                //CurveUtils.solveCubicCurveForX(curve, Math.Min(x, x2), solutions);
                //double t = solutions[0];
                double t = curve.GetFirstSolutionForX(Math.Min(x, x2));
                //scoreTable[i] = CurveUtils.getPointOnCubicCurve(curve, t).getY();
                scoreTable[i] = curve.GetYOnCurve(t);


                x += xInc;
            }

            return(scoreTable);
        }
Beispiel #3
0
        /**
         * Computes a range of strokes to use based on the given looseness.
         * Only characters whose number of strokes are within the input number of strokes
         * +/- this range will be considered during comparison.  This helps cut down
         * on matching cost.
         *
         * @param strokeCount the number of input strokes
         * @param looseness the looseness, 0-1
         * @return the range
         */
        private int getStrokesRange(int strokeCount)
        {
            // Just return some extreme values if at minimum or maximum.
            // Helps to avoid possible floating point issues when near the extremes.
            if (looseness == 0.0)
            {
                return(0);
            }
            else if (looseness == 1.0)
            {
                return(CharacterDescriptor.MAX_CHARACTER_STROKE_COUNT);
            }

            // We use a CubicCurve that grows slowly at first and then rapidly near the end to the maximum.
            // This is so a looseness at or near 1.0 will return a range that will consider all characters.

            double ctrl1X = 0.35;
            double ctrl1Y = strokeCount * 0.4;

            double ctrl2X = 0.6;
            double ctrl2Y = strokeCount;

            double[]     solutions = new double[1];
            CubicCurve2D curve     = new CubicCurve2D(0, 0, ctrl1X, ctrl1Y, ctrl2X, ctrl2Y, 1, CharacterDescriptor.MAX_CHARACTER_STROKE_COUNT);
            //CurveUtils.solveCubicCurveForX(curve, looseness, solutions);
            //double t = solutions[0];
            double t = curve.GetFirstSolutionForX(looseness);

            // We get the t value on the parametrized curve where the x value matches the looseness.
            // Then we compute the y value for that t.  This gives the range.

            //return (int)Math.Round(CurveUtils.getPointOnCubicCurve(curve, t).getY());
            return((int)Math.Round(curve.GetYOnCurve(t)));
        }