org.ams.testapps.paintandphysics.cardhouse.TurnCircle.java Source code

Java tutorial

Introduction

Here is the source code for org.ams.testapps.paintandphysics.cardhouse.TurnCircle.java

Source

/*
 *
 *  The MIT License (MIT)
 *
 *  Copyright (c) <2015> <Andreas Modahl>
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *  THE SOFTWARE.
 *
 */

package org.ams.testapps.paintandphysics.cardhouse;

import com.badlogic.gdx.Application;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import org.ams.core.Util;

/** A circle that is made to visualize the area one can touch to turn an object. */
public class TurnCircle {

    private boolean debug = false;
    private boolean visible = false;

    private final Vector2 position = new Vector2();

    // circle
    private final float radius;
    private final float width;
    private final Array<Util.Triangle> triangulatedCircle;

    // camera is used to update zoom
    private final OrthographicCamera camera;
    private float zoom = 1;

    // color
    private final Color color = new Color();
    private final Color moreOpaqueColor = new Color();

    // tiny square in the middle
    private float angleSquareAngle = 0;
    private boolean drawAngleSquare = true;

    // markers
    private float markerSpacing = 5;
    private boolean drawMarkers = true;

    // helper variables for rendering
    private final short[] fillingTriangle = new short[] { 0, 1, 2 };
    private final float[] tmp_triangle = new float[6];

    private final float[] t = new float[6];
    private final int[] triangle = new int[6];

    private final Vector2 v = new Vector2();
    private final Vector2 v1 = new Vector2();

    /**
     * A circle that is made to visualize the area one can touch to turn an object.
     *
     * @param camera The camera you draw the world with.
     * @param radius distance from center of circle to the inner part of the colored outline.
     * @param width  the width of the colored outline.
     */
    public TurnCircle(OrthographicCamera camera, float radius, float width) {
        if (debug)
            Gdx.app.setLogLevel(Application.LOG_DEBUG);

        this.camera = camera;

        setColor(Color.PINK);

        // reasonable size for all densities
        this.radius = radius * (float) Math.pow(Gdx.graphics.getDensity(), 0.25);
        this.width = width * (float) Math.pow(Gdx.graphics.getDensity(), 0.25);

        // create triangles that together form a circle
        Array<Vector2> outer = makeCircle(new Vector2(), this.radius + this.width);
        Array<Vector2> inner = makeCircle(new Vector2(), this.radius);
        Array<Array<Vector2>> holes = new Array<Array<Vector2>>();
        holes.add(inner);
        triangulatedCircle = Util.makeTriangles(outer, holes, false);
    }

    private void debug(String text) {
        if (debug)
            Gdx.app.log("Turn Circle", text);

    }

    /** The opacity value is not used. */
    public void setColor(Color color) {
        this.color.set(color);
        this.color.a = 0.4f;
        this.moreOpaqueColor.set(color);
        this.moreOpaqueColor.a = 0.8f;
    }

    /** The opacity value is not used. */
    public Color getColor() {
        return color;
    }

    /** Markers for angle. See {@link #setDrawMarkers(boolean)}. */
    public void setMarkerSpacing(float markerSpacing) {
        this.markerSpacing = markerSpacing;
    }

    /** Markers for angle. See {@link #setDrawMarkers(boolean)}. */
    public float getMarkerSpacing() {
        return markerSpacing;
    }

    /** Markers for angle. See {@link #setMarkerSpacing(float)}. */
    public void setDrawMarkers(boolean drawMarkers) {
        this.drawMarkers = drawMarkers;
    }

    /** Markers for angle. See {@link #setMarkerSpacing(float)}. */
    public boolean isDrawingMarkers() {
        return drawMarkers;
    }

    /** A tiny square in the middle that can be turned. See {@link #setAngleSquareAngle(float)}. */
    public void setDrawAngleSquare(boolean drawAngleSquare) {
        this.drawAngleSquare = drawAngleSquare;
    }

    /** A tiny square in the middle that can be turned. See {@link #setAngleSquareAngle(float)}. */
    public boolean isDrawingAngleSquare() {
        return drawAngleSquare;
    }

    /** Angle of the tiny square in the middle. Measured in radians. See {@link #setDrawAngleSquare(boolean)}. */
    public void setAngleSquareAngle(float angleSquareAngle) {
        this.angleSquareAngle = angleSquareAngle;
    }

    /** Angle of the tiny square in the middle. Measured in radians. */
    public float getAngleSquareAngle() {
        return angleSquareAngle;
    }

    public void setVisible(boolean visible) {
        this.visible = visible;
    }

    public boolean isVisible() {
        return visible;
    }

    /** Set position of the center of the circle. */
    public void setPosition(Vector2 position) {
        this.position.set(position);
    }

    /** Set position of the center of the circle. */
    public Vector2 getPosition() {
        return position;
    }

    /** Create vertices forming the outline of a circle. */
    private Array<Vector2> makeCircle(Vector2 center, float radius) {
        Array<Vector2> vertices = new Array<Vector2>();

        int n = 100;

        for (int i = 0; i < n; i++) {
            Vector2 vertex = new Vector2(radius, 0);
            vertex.rotateRad(i * MathUtils.PI2 / n);
            vertex.add(center);
            vertices.add(vertex);
        }
        return vertices;
    }

    /** Whether v is outside the colored outline. */
    public boolean isOutsideTurnCircle(Vector2 v) {
        if (!visible)
            return false;

        float dst = v.dst(position);
        boolean outside = dst > (radius + width) * zoom;

        if (debug)
            debug(outside ? v + " is outside circle." : v + " is not outside circle.");
        return outside;

    }

    /** Whether v is on the colored outline. */
    public boolean isOnTurnCircle(Vector2 v) {
        if (!visible)
            return false;

        float dst = v.dst(position);
        boolean isOn = radius * zoom < dst && dst < (radius + width) * zoom;

        if (debug)
            debug(isOn ? v + " is on circle." : v + " is not on circle.");
        return isOn;

    }

    /** Whether v is inside the colored outline. */
    public boolean isInsideTurnCircle(Vector2 v) {
        if (!visible)
            return false;

        float dst = v.dst(position);
        boolean inside = dst < radius * zoom;

        if (debug)
            debug(inside ? v + " is inside circle." : v + " is not inside circle.");
        return inside;

    }

    /** Radius of the inside. */
    public float getRadius() {
        return radius;
    }

    /** Width of the color outline. */
    public float getWidth() {
        return width;
    }

    /** Draw the turn circle. */
    public void draw(ShapeRenderer worldRenderer) {
        if (!visible)
            return;

        zoom = camera.zoom * (float) Math.sqrt(camera.viewportHeight / 10);

        worldRenderer.set(ShapeRenderer.ShapeType.Filled);
        worldRenderer.setColor(color);

        // draw circle
        for (Util.Triangle t : triangulatedCircle) {
            tmp_triangle[0] = t.a.x * zoom + position.x;
            tmp_triangle[1] = t.a.y * zoom + position.y;
            tmp_triangle[2] = t.b.x * zoom + position.x;
            tmp_triangle[3] = t.b.y * zoom + position.y;
            tmp_triangle[4] = t.c.x * zoom + position.x;
            tmp_triangle[5] = t.c.y * zoom + position.y;

            renderPolygonFilling(worldRenderer, tmp_triangle, fillingTriangle);
        }

        if (drawAngleSquare) {
            // draw square in middle
            float half = 0.1f * zoom;

            worldRenderer.rect(position.x - half, position.y - half, half, half, half * 2, half * 2, 1, 1,
                    angleSquareAngle * MathUtils.radiansToDegrees);
        }

        if (drawMarkers) {
            // draw angle markers
            worldRenderer.set(ShapeRenderer.ShapeType.Line);
            worldRenderer.setColor(moreOpaqueColor);

            int n = (int) (360 / markerSpacing);

            float inner = radius * zoom;
            float outer = (radius + width * 0.1f) * zoom;

            float rotate = MathUtils.PI2 / n;
            for (int i = 0; i < n; i++) {
                v.set(inner, 0).rotateRad(rotate * i).add(position);
                v1.set(outer, 0).rotateRad(rotate * i).add(position);
                worldRenderer.line(v.x, v.y, v1.x, v1.y);
            }
        }

    }

    /** Fill polygon with color. */
    private void renderPolygonFilling(ShapeRenderer renderer, float[] polygon, short[] fillingTriangles) {

        int ntriangles = fillingTriangles.length / 3;
        for (int i = 0; i < ntriangles; i++) {
            for (int j = 0; j < 3; j++) {
                triangle[j] = fillingTriangles[j + i * 3];
            }
            for (int j = 0; j < 3; j++) {
                t[2 * j] = polygon[triangle[j] * 2];
                t[2 * j + 1] = polygon[triangle[j] * 2 + 1];
            }

            renderer.triangle(t[0], t[1], t[2], t[3], t[4], t[5]);
        }
    }
}