Пример #1
0
        public List <IDisplayAxis> GeneratePossibleConfigurations(float minTextSize, float maxTextSize, List <float> stepSequence)
        {
            // first convert the step sequence to a label sequence
            List <string> labels = new List <string>();

            for (int i = 0; i < stepSequence.Count; i++)
            {
                T      value          = DataConverter.FloatToValue(stepSequence[i]);
                string formattedValue = DataConverter.ValueToString(value);
                if (!labels.Contains(formattedValue)) // avoid duplicates
                {
                    labels.Add(formattedValue);
                }
            }

            // now create all possible DisplayAxes from this
            List <IDisplayAxis> possibilities = new List <IDisplayAxis>();

            for (float fontSize = minTextSize; fontSize <= maxTextSize; fontSize += 0.1f)
            {
                for (int i = 0; i < 2; i++)
                {
                    bool        horizontalAlignment = (i == 0);
                    DisplayAxis displayAxis         = new DisplayAxis(this, labels, fontSize, horizontalAlignment, Horizontal);
                    possibilities.Add(displayAxis);
                }
            }
            return(possibilities);
        }
Пример #2
0
        /// <summary>
        /// Performs the Extended Wilkinson algorithm which returns an optimal labeling for numeric numbers based on the given settings
        /// </summary>
        /// <param name="availableSpace">States how much space in world units there is available for the axis</param>
        /// <param name="horizontalAxis">If set to true, the axis is orientated horizontally</param>
        /// <param name="targetDensity">Specifies how many labels should be placed per world unit</param>
        /// <param name="dataMin">The minimum of the data range</param>
        /// <param name="dataMax">The maximum of the dtaa range</param>
        /// <param name="axisMin">Gives the chosen minimum of the axis labeling</param>
        /// <param name="axisMax">Gives the chosen maximum of the axis labeling</param>
        /// <returns>An axis configuration which includes styling and the chosen labels</returns>
        public static IDisplayAxis PerformExtendedWilkinson(IAxis axis, float availableSpace, float targetDensity, out float axisMin, out float axisMax)
        {
            float bestScore = -2;

            axisMin = axis.NumericDataMin;
            axisMax = axis.NumericDataMax;

            if (axisMin == axisMax)
            {
                Debug.LogError("Cannot work on same min and max data");
                return(null);
            }

            IDisplayAxis bestOption = null;

            for (int j = 1; j < int.MaxValue; j++) // there are break statements which terminate this loop
            {
                foreach (float q in Q)             // (j,q): determines step size
                {
                    float sm = SimplicityMax(q, j);
                    if (Vector4.Dot(new Vector4(sm, 1, 1, 1), weights) < bestScore)
                    {
                        // finish the search
                        j = int.MaxValue - 1;
                        break;
                    }
                    for (int k = 2; k < int.MaxValue; k++) // try different numbers of labels
                    {
                        float dm = DensityMax(k / availableSpace, targetDensity);
                        if (Vector4.Dot(new Vector4(sm, 1, dm, 1), weights) < bestScore)
                        {
                            break;
                        }
                        float delta = (axis.NumericDataMax - axis.NumericDataMin) / (k + 1) / (j * q);
                        for (int z = Mathf.CeilToInt(Mathf.Log10(delta)); z < int.MaxValue; z++) // power of 10 multiplier for the step size
                        {
                            float lStep = q * j * Mathf.Pow(10, z);
                            float cm    = CoverageMax(axis.NumericDataMin, axis.NumericDataMax, lStep * (k - 1));
                            if (Vector4.Dot(new Vector4(sm, cm, dm, 1), weights) < bestScore)
                            {
                                break;
                            }
                            for (float start = Mathf.Floor(axis.NumericDataMax / lStep) - (k - 1); start <= Mathf.Ceil(axis.NumericDataMin / lStep); start += 1f / j) // possible start labels
                            {
                                float lmin = start * lStep;
                                float lmax = lmin + (k - 1) * lStep;
                                float s    = Simplicity(q, j, lmin, lmax, lStep);
                                float d    = Density(k / availableSpace, targetDensity);
                                float c    = Coverage(axis.NumericDataMin, axis.NumericDataMax, lmin, lmax);

                                if (Vector4.Dot(new Vector4(s, c, d, 1), weights) < bestScore)
                                {
                                    continue;
                                }

                                List <float> stepSequence = Enumerable.Range(0, k).Select(x => lmin + x * lStep).ToList();
                                //List<string> labels = stepSequence.Select(value => value.ToString("0.##")).ToList();

                                // optimize legibility
                                List <IDisplayAxis> possibilities = axis.GeneratePossibleConfigurations(minTextSize, maxTextSize, stepSequence);
                                float        legibility;
                                IDisplayAxis localBest = DisplayAxis.FindBestLegibility(possibilities, out legibility, minTextSize, targetTextSize, 0.02f, availableSpace);

                                float score = Vector4.Dot(new Vector4(s, c, d, legibility), weights);
                                if (score > bestScore)
                                {
                                    bestOption = localBest;
                                    bestScore  = score;
                                    axisMax    = lmax;
                                    axisMin    = lmin;
                                }
                            }
                        }
                    }
                }
            }
            return(bestOption);
        }