com.github.mathiewz.slick.geom.RoundedRectangle Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of modernized-slick Show documentation
Show all versions of modernized-slick Show documentation
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 - 2025 Weber Informatics LLC | Privacy Policy