예제 #1
0
        /// <summary>
        /// Creates an array of positions that are aggregated based on the given aggregation type.
        /// This MUST be called AFTER each time the other dimensions change.
        /// </summary>
        /// <param name="data"></param>
        /// <param name="dimension"></param>
        /// <param name="aggregation"></param>
        /// <returns></returns>
        public float[] SetAggregatedDimension(float[] yData, IATKBarAggregation aggregation)
        {
            // Extract independent arrays of the position values for the x and z dimensions
            Vector3[] vertices = View.GetVertices();
            float[]   xData    = new float[vertices.Length];
            float[]   zData    = new float[vertices.Length];
            for (int i = 0; i < DataSource.DataCount; i++)
            {
                xData[i] = vertices[i].x;
                zData[i] = vertices[i].z;
            }

            // Get the unique "categories" of the x and z dimensions (these are technically floats)
            var xCategories = xData.Distinct();
            var zCategories = zData.Distinct();

            // LAZY HACK: Set a value in the mesh's normal.y value to designate whether to show or hide the point to prevent z-fighting and mass lag
            float[] masterBars = new float[DataSource.DataCount];

            // Create a dictionary that will store the values assocatied with each (x, z) pairs of aggregating values (x bins * z bins = n lists)
            Dictionary <float, Dictionary <float, List <float> > > aggGroups = new Dictionary <float, Dictionary <float, List <float> > >();

            // Iterate through each position and assign the data values to the respective (x, z) pair
            for (int i = 0; i < DataSource.DataCount; i++)
            {
                Dictionary <float, List <float> > innerDict;
                if (!aggGroups.TryGetValue(xData[i], out innerDict))
                {
                    innerDict           = new Dictionary <float, List <float> >();
                    aggGroups[xData[i]] = innerDict;
                }

                List <float> innerList;
                if (!innerDict.TryGetValue(zData[i], out innerList))
                {
                    innerList           = new List <float>();
                    innerDict[zData[i]] = innerList;
                    masterBars[i]       = 1;
                }

                // If the aggregation type is count, we don't need to use the y axis values
                if (aggregation == IATKBarAggregation.Count || yData == null)
                {
                    innerList.Add(0);
                }
                else
                {
                    innerList.Add(yData[i]);
                }
            }

            // LAZY HACK: Send the master values to the mesh now
            View.SetUVs(masterBars, IATKDimension.Y);

            // Create another dictionary that will store the aggregated value for each (x, z) pair group
            float max = 0;
            Dictionary <float, Dictionary <float, float> > aggregatedValues = new Dictionary <float, Dictionary <float, float> >();

            foreach (float xCategory in xCategories)
            {
                foreach (float zCategory in zCategories)
                {
                    // Calculate final aggregated value
                    if (!aggGroups[xCategory].ContainsKey(zCategory))
                    {
                        continue;
                    }

                    List <float> values     = aggGroups[xCategory][zCategory];
                    float        aggregated = 0;
                    switch (aggregation)
                    {
                    case IATKBarAggregation.Count:
                        aggregated = values.Count;
                        break;

                    case IATKBarAggregation.Average:
                        aggregated = values.Average();
                        break;

                    case IATKBarAggregation.Sum:
                        aggregated = values.Sum();
                        break;

                    case IATKBarAggregation.Median:
                        values.Sort();
                        float mid = (values.Count - 1) / 2f;
                        aggregated = (values[(int)(mid)] + values[(int)(mid + 0.5f)]) / 2;
                        break;

                    case IATKBarAggregation.Min:
                        aggregated = values.Min();
                        break;

                    case IATKBarAggregation.Max:
                        aggregated = values.Max();
                        break;
                    }

                    // Set value
                    Dictionary <float, float> innerDict;
                    if (!aggregatedValues.TryGetValue(xCategory, out innerDict))
                    {
                        innerDict = new Dictionary <float, float>();
                        aggregatedValues[xCategory] = innerDict;
                    }
                    innerDict[zCategory] = aggregated;

                    // We need to normalise back into 0..1 for these specific aggregations, so we collect the max value
                    if (aggregation == IATKBarAggregation.Count || aggregation == IATKBarAggregation.Sum)
                    {
                        if (max < aggregated)
                        {
                            max = aggregated;
                        }
                    }
                }
            }

            // Set y position based on newly aggregated values
            float[] positions = new float[DataSource.DataCount];
            for (int i = 0; i < DataSource.DataCount; i++)
            {
                // For specific aggregations, normalise
                if (aggregation == IATKBarAggregation.Count || aggregation == IATKBarAggregation.Sum)
                {
                    positions[i] = UtilMath.NormaliseValue(aggregatedValues[xData[i]][zData[i]], 0, max, 0, 1);
                }
                else
                {
                    positions[i] = aggregatedValues[xData[i]][zData[i]];
                }
            }

            return(positions);
        }
예제 #2
0
 public void SetBarAggregation(IATKBarAggregation barAggregation)
 {
     BarAggregation = barAggregation;
     UpdateView(IATKProperty.Y);
 }