All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.mathiewz.slick.geom.RoundedRectangle Maven / Gradle / Ivy

Go to download

The main purpose of this libraryis to modernize and maintain the slick2D library.

The newest version!
package com.github.mathiewz.slick.geom;

import java.util.ArrayList;
import java.util.List;

import com.github.mathiewz.slick.util.FastTrig;

/**
 * Class to create rounded rectangles with.
 *
 * @author Mark Bernard
 */
public class RoundedRectangle extends Rectangle {
    /** Indicates the top left corner should be rounded */
    public static final int TOP_LEFT = 1;
    /** Indicates the top right corner should be rounded */
    public static final int TOP_RIGHT = 2;
    /** Indicates the bottom right corner should be rounded */
    public static final int BOTTOM_RIGHT = 4;
    /** Indicates the bottom left corner should be rounded */
    public static final int BOTTOM_LEFT = 8;
    /** Indicates the all cornders should be rounded */
    public static final int ALL = TOP_LEFT | TOP_RIGHT | BOTTOM_RIGHT | BOTTOM_LEFT;

    /** Default number of segments to draw the rounded corners with */
    private static final int DEFAULT_SEGMENT_COUNT = 25;

    /** radius of each corner */
    private float cornerRadius;
    /** number of segments for each corner */
    private final int segmentCount;
    /** The flags indicating which corners should be rounded */
    private final int cornerFlags;

    /**
     * Construct a rectangle with rounded corners.
     *
     * @param x
     *            The x position of the rectangle.
     * @param y
     *            The y position of the rectangle.
     * @param width
     *            The width of the rectangle.
     * @param height
     *            The hieght of the rectangle.
     * @param cornerRadius
     *            The radius to use for the arc in each corner.
     */
    public RoundedRectangle(float x, float y, float width, float height, float cornerRadius) {
        this(x, y, width, height, cornerRadius, DEFAULT_SEGMENT_COUNT);
    }

    /**
     * Construct a rectangle with rounded corners.
     *
     * @param x
     *            The x position of the rectangle.
     * @param y
     *            The y position of the rectangle.
     * @param width
     *            The width of the rectangle.
     * @param height
     *            The hieght of the rectangle.
     * @param cornerRadius
     *            The radius to use for the arc in each corner.
     * @param segmentCount
     *            The number of segments to use to draw each corner arc.
     */
    public RoundedRectangle(float x, float y, float width, float height, float cornerRadius, int segmentCount) {
        this(x, y, width, height, cornerRadius, segmentCount, ALL);
    }

    /**
     * Construct a rectangle with rounded corners.
     *
     * @param x
     *            The x position of the rectangle.
     * @param y
     *            The y position of the rectangle.
     * @param width
     *            The width of the rectangle.
     * @param height
     *            The hieght of the rectangle.
     * @param cornerRadius
     *            The radius to use for the arc in each corner.
     * @param segmentCount
     *            The number of segments to use to draw each corner arc.
     * @param cornerFlags
     *            Indicates which corners should be rounded
     */
    public RoundedRectangle(float x, float y, float width, float height, float cornerRadius, int segmentCount, int cornerFlags) {
        super(x, y, width, height);

        if (cornerRadius < 0) {
            throw new IllegalArgumentException("corner radius must be >= 0");
        }
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.cornerRadius = cornerRadius;
        this.segmentCount = segmentCount;
        pointsDirty = true;
        this.cornerFlags = cornerFlags;
    }

    /**
     * Get the radius for each corner.
     *
     * @return The radius for each corner.
     */
    public float getCornerRadius() {
        return cornerRadius;
    }

    /**
     * Set the radius for each corner.
     *
     * @param cornerRadius
     *            The radius for each corner to set.
     */
    public void setCornerRadius(float cornerRadius) {
        if (cornerRadius >= 0) {
            if (cornerRadius != this.cornerRadius) {
                this.cornerRadius = cornerRadius;
                pointsDirty = true;
            }
        }
    }

    /**
     * Get the height of this rectangle.
     *
     * @return The height of this rectangle.
     */
    @Override
    public float getHeight() {
        return height;
    }

    /**
     * Set the height of this rectangle.
     *
     * @param height
     *            The height to set.
     */
    @Override
    public void setHeight(float height) {
        if (this.height != height) {
            this.height = height;
            pointsDirty = true;
        }
    }

    /**
     * Get the width of this rectangle.
     *
     * @return The width of this rectangle.
     */
    @Override
    public float getWidth() {
        return width;
    }

    /**
     * Set the width of this rectangle.
     *
     * @param width
     *            The width to set.
     */
    @Override
    public void setWidth(float width) {
        if (width != this.width) {
            this.width = width;
            pointsDirty = true;
        }
    }

    @Override
    protected void createPoints() {
        maxX = x + width;
        maxY = y + height;
        minX = x;
        minY = y;
        float useWidth = width - 1;
        float useHeight = height - 1;
        if (cornerRadius == 0) {
            points = new Float[8];

            points[0] = x;
            points[1] = y;

            points[2] = x + useWidth;
            points[3] = y;

            points[4] = x + useWidth;
            points[5] = y + useHeight;

            points[6] = x;
            points[7] = y + useHeight;
        } else {
            float doubleRadius = cornerRadius * 2;
            if (doubleRadius > useWidth) {
                doubleRadius = useWidth;
                cornerRadius = doubleRadius / 2;
            }
            if (doubleRadius > useHeight) {
                doubleRadius = useHeight;
                cornerRadius = doubleRadius / 2;
            }

            ArrayList tempPoints = new ArrayList<>();
            // the outer most set of points for each arc will also ac as the points that start the
            // straight sides, so the straight sides do not have to be added.

            // top left corner arc
            if ((cornerFlags & TOP_LEFT) != 0) {
                tempPoints.addAll(createPoints(segmentCount, cornerRadius, x + cornerRadius, y + cornerRadius, 180, 270));
            } else {
                tempPoints.add(new Float(x));
                tempPoints.add(new Float(y));
            }

            // top right corner arc
            if ((cornerFlags & TOP_RIGHT) != 0) {
                tempPoints.addAll(createPoints(segmentCount, cornerRadius, x + useWidth - cornerRadius, y + cornerRadius, 270, 360));
            } else {
                tempPoints.add(new Float(x + useWidth));
                tempPoints.add(new Float(y));
            }

            // bottom right corner arc
            if ((cornerFlags & BOTTOM_RIGHT) != 0) {
                tempPoints.addAll(createPoints(segmentCount, cornerRadius, x + useWidth - cornerRadius, y + useHeight - cornerRadius, 0, 90));
            } else {
                tempPoints.add(new Float(x + useWidth));
                tempPoints.add(new Float(y + useHeight));
            }

            // bottom left corner arc
            if ((cornerFlags & BOTTOM_LEFT) != 0) {
                tempPoints.addAll(createPoints(segmentCount, cornerRadius, x + cornerRadius, y + useHeight - cornerRadius, 90, 180));
            } else {
                tempPoints.add(new Float(x));
                tempPoints.add(new Float(y + useHeight));
            }

            points = new Float[tempPoints.size()];
            for (int i = 0; i < tempPoints.size(); i++) {
                points[i] = tempPoints.get(i).floatValue();
            }
        }

        findCenter();
        calculateRadius();
    }

    /**
     * Generate the points to fill a corner arc.
     *
     * @param numberOfSegments
     *            How fine to make the ellipse.
     * @param radius
     *            The radius of the arc.
     * @param cx
     *            The x center of the arc.
     * @param cy
     *            The y center of the arc.
     * @param start
     *            The start angle of the arc.
     * @param end
     *            The end angle of the arc.
     * @return The points created.
     */
    private List createPoints(int numberOfSegments, float radius, float cx, float cy, float start, float end) {
        ArrayList tempPoints = new ArrayList<>();

        int step = 360 / numberOfSegments;

        for (float a = start; a <= end + step; a += step) {
            float ang = a;
            if (ang > end) {
                ang = end;
            }
            float x = (float) (cx + FastTrig.cos(Math.toRadians(ang)) * radius);
            float y = (float) (cy + FastTrig.sin(Math.toRadians(ang)) * radius);

            tempPoints.add(new Float(x));
            tempPoints.add(new Float(y));
        }

        return tempPoints;
    }

    /**
     * Apply a transformation and return a new shape. This will not alter the current shape but will
     * return the transformed shape.
     *
     * @param transform
     *            The transform to be applied
     * @return The transformed shape.
     */
    @Override
    public Shape transform(Transform transform) {
        checkPoints();

        Polygon resultPolygon = new Polygon();

        Float result[] = new Float[points.length];
        transform.transform(points, 0, result, 0, points.length / 2);
        resultPolygon.points = result;
        resultPolygon.findCenter();

        return resultPolygon;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy