package net.kennux.cubicworld.util; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType; import com.badlogic.gdx.math.Vector2; /** * Statics helper class contains some functions used to draw statistic information. * For example rendering a line diagram. * * @author kennux * */ public class StatisticsHelper { /** * Initializes the spritebatch, shape renderer and bitmap font if they aren't initialized already. */ private static void init() { if (font == null) font = new BitmapFont(); if (shapeRenderer == null) shapeRenderer = new ShapeRenderer(); if (spriteBatch == null) spriteBatch = new SpriteBatch(); } /** * Renders a line diagram with min and max value sizes calculated from entries array. * * @param position * @param size * @param entries */ public static void renderLineDiagram(String caption, Vector2 position, Vector2 size, float[] entries) { // Get lowest and highest entry // And pixels per entry. Float lowestEntry = null; Float highestEntry = null; for (float e : entries) { if (lowestEntry == null || lowestEntry.floatValue() > e) lowestEntry = new Float(e); else if (highestEntry == null || highestEntry.floatValue() < e) highestEntry = new Float(e); } renderLineDiagram(caption, position, size, entries, lowestEntry, highestEntry); } /** * Renders a line diagram with max value sizes calculated from entries array. * * @param position * @param size * @param entries * @param minEntry * The minimum entry value */ public static void renderLineDiagram(String caption, Vector2 position, Vector2 size, float[] entries, Float minEntry) { // Get lowest and highest entry // And pixels per entry. Float highestEntry = null; for (float e : entries) { if (highestEntry == null || highestEntry.floatValue() < e) highestEntry = new Float(e); } renderLineDiagram(caption, position, size, entries, minEntry, highestEntry); } /** * Renders a line diagram. * The caption will get rendered at: Vector2(position.x, position.y + size.y + 20), so 20 pixel over the main diagram. * If you don't want a caption put an empty string or null in caption. * * @param size * The width and height of the line diagram in screenspace. * @param position * The position of the line diagram in screenspace. * @param entries * The entries to show. Index is their position, 0 = left. * @param minEntry * The minimum entry value * @param maxEntry * The maximum entry value */ public static void renderLineDiagram(String caption, Vector2 position, Vector2 size, float[] entries, Float minEntry, Float maxEntry) { init(); shapeRenderer.begin(ShapeType.Line); // Render frame shapeRenderer.line(new Vector2(position).add(0, -1), new Vector2(position).add(0, size.y + 1)); // Y+ shapeRenderer.line(position, new Vector2(position).add(size.x, 0)); // X+ // Render entries if (maxEntry != null && minEntry != null) { // Calculate all needed variables for rendering float pixelsXPerEntry = size.x / entries.length; float highestLowestDistance = maxEntry - minEntry; float xAxisPointer = 0; Vector2 lastPosition = null; // Render lines from every entry point to the next. for (float e : entries) { float entryHeight = ((e - minEntry) / highestLowestDistance) * size.y; Vector2 pos = new Vector2(xAxisPointer, entryHeight).add(position); if (lastPosition != null) { // Extend shapeRenderer.line(lastPosition, pos); } xAxisPointer += pixelsXPerEntry; lastPosition = pos; } } shapeRenderer.end(); spriteBatch.begin(); // Render caption if (caption != null && !caption.isEmpty()) font.draw(spriteBatch, caption + ":", position.x, position.y + size.y + 20); // Render fonts if (maxEntry != null && minEntry != null) { font.draw(spriteBatch, minEntry.toString(), position.x - 50, position.y + 20); font.draw(spriteBatch, maxEntry.toString(), position.x - 50, position.y + size.y); } spriteBatch.end(); } /** * Renders a pie chart to the screen at the given position with the given size. * The caption will get rendered at: Vector2(position.x, position.y + (radius*2) + 20), so 20 pixel over the main diagram. * If you don't want a caption put an empty string or null in caption. * * @param caption * @param position * @param radius * @param entryValues * @param entryColors */ public static void renderPiechart(String caption, Vector2 position, float radius, float[] entryValues, Color[] entryColors) { init(); // Add all entries int entriesAdded = 0; for (float e : entryValues) entriesAdded += e; // Get entry percentages float[] entryPercentages = new float[entryValues.length]; for (int i = 0; i < entryPercentages.length; i++) { entryPercentages[i] = entryValues[i] / entriesAdded; } // Calculate center position Vector2 centerPosition = new Vector2(position).add(radius, radius); // Render arcs shapeRenderer.begin(ShapeType.Filled); float currentDegrees = 0; // Render all entries for (int i = 0; i < entryPercentages.length; i++) { // Calculate degrees float degrees = entryPercentages[i] * 360; // Set color shapeRenderer.setColor(entryColors[i]); // Render arc shapeRenderer.arc(centerPosition.x, centerPosition.y, radius, currentDegrees, degrees); currentDegrees += degrees; } shapeRenderer.end(); // Reset color shapeRenderer.setColor(Color.WHITE); spriteBatch.begin(); // Render caption if (caption != null && !caption.isEmpty()) font.draw(spriteBatch, caption + ":", position.x, position.y + (radius * 2) + 20); spriteBatch.end(); } /** * The sprite batch used for rendering the debug information to the screen. */ private static SpriteBatch spriteBatch; /** * The shape renderer used for rendering diagrams. */ private static ShapeRenderer shapeRenderer; /** * The font used for rendering. */ private static BitmapFont font; }