mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 20:31:51 +09:00
Former-commit-id: 1647fa32ef6894bd7db44f741f07c2f4dcdf9054 Former-commit-id: 0e5810dcfbe1fd59b13e7cabe9f1e93c5542da2d
235 lines
6.3 KiB
Java
235 lines
6.3 KiB
Java
package org.newdawn.slick.geom;
|
|
|
|
/**
|
|
* A simple Circle geometry
|
|
*
|
|
* @author Kevin Glass
|
|
*/
|
|
public strictfp class Circle extends Ellipse {
|
|
/** The radius of the circle */
|
|
public float radius;
|
|
|
|
/**
|
|
* Create a new circle based on its radius
|
|
*
|
|
* @param centerPointX The x location of the center of the circle
|
|
* @param centerPointY The y location of the center of the circle
|
|
* @param radius The radius of the circle
|
|
*/
|
|
public Circle(float centerPointX, float centerPointY, float radius) {
|
|
this(centerPointX, centerPointY, radius, DEFAULT_SEGMENT_COUNT);
|
|
}
|
|
|
|
/**
|
|
* Create a new circle based on its radius
|
|
*
|
|
* @param centerPointX The x location of the center of the circle
|
|
* @param centerPointY The y location of the center of the circle
|
|
* @param radius The radius of the circle
|
|
* @param segmentCount The number of segments to build the circle out of
|
|
*/
|
|
public Circle(float centerPointX, float centerPointY, float radius, int segmentCount) {
|
|
super(centerPointX, centerPointY, radius, radius, segmentCount);
|
|
this.x = centerPointX - radius;
|
|
this.y = centerPointY - radius;
|
|
this.radius = radius;
|
|
boundingCircleRadius = radius;
|
|
}
|
|
|
|
/**
|
|
* Get the x coordinate of the centre of the circle
|
|
*
|
|
* @return The x coordinate of the centre of the circle
|
|
*/
|
|
public float getCenterX() {
|
|
return getX() + radius;
|
|
}
|
|
|
|
/**
|
|
* Get the y coordinate of the centre of the circle
|
|
*
|
|
* @return The y coordinate of the centre of the circle
|
|
*/
|
|
public float getCenterY() {
|
|
return getY() + radius;
|
|
}
|
|
|
|
/**
|
|
* Get the coordinates of the center of the circle
|
|
*
|
|
* @return 2-element array with the center of the circle.
|
|
*/
|
|
@Override
|
|
public float[] getCenter() {
|
|
return new float[] { getCenterX(), getCenterY() };
|
|
}
|
|
|
|
/**
|
|
* Set the radius of this circle
|
|
*
|
|
* @param radius The radius of this circle
|
|
*/
|
|
public void setRadius(float radius) {
|
|
if (radius != this.radius) {
|
|
pointsDirty = true;
|
|
this.radius = radius;
|
|
setRadii(radius, radius);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the radius of the circle
|
|
*
|
|
* @return The radius of the circle
|
|
*/
|
|
public float getRadius() {
|
|
return radius;
|
|
}
|
|
|
|
/**
|
|
* Check if this circle touches another
|
|
*
|
|
* @param shape The other circle
|
|
* @return True if they touch
|
|
*/
|
|
public boolean intersects(Shape shape) {
|
|
if(shape instanceof Circle) {
|
|
Circle other = (Circle)shape;
|
|
float totalRad2 = getRadius() + other.getRadius();
|
|
|
|
if (Math.abs(other.getCenterX() - getCenterX()) > totalRad2) {
|
|
return false;
|
|
}
|
|
if (Math.abs(other.getCenterY() - getCenterY()) > totalRad2) {
|
|
return false;
|
|
}
|
|
|
|
totalRad2 *= totalRad2;
|
|
|
|
float dx = Math.abs(other.getCenterX() - getCenterX());
|
|
float dy = Math.abs(other.getCenterY() - getCenterY());
|
|
|
|
return totalRad2 >= ((dx*dx) + (dy*dy));
|
|
}
|
|
else if(shape instanceof Rectangle) {
|
|
return intersects((Rectangle)shape);
|
|
}
|
|
else {
|
|
return super.intersects(shape);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if a point is contained by this circle
|
|
*
|
|
* @param x The x coordinate of the point to check
|
|
* @param y The y coorindate of the point to check
|
|
* @return True if the point is contained by this circle
|
|
*/
|
|
public boolean contains(float x, float y)
|
|
{
|
|
float xDelta = x - getCenterX(), yDelta = y - getCenterY();
|
|
return xDelta * xDelta + yDelta * yDelta < getRadius() * getRadius();
|
|
}
|
|
|
|
/**
|
|
* Check if circle contains the line
|
|
* @param line Line to check against
|
|
* @return True if line inside circle
|
|
*/
|
|
private boolean contains(Line line) {
|
|
return contains(line.getX1(), line.getY1()) && contains(line.getX2(), line.getY2());
|
|
}
|
|
|
|
/**
|
|
* @see org.newdawn.slick.geom.Ellipse#findCenter()
|
|
*/
|
|
protected void findCenter() {
|
|
center = new float[2];
|
|
center[0] = x + radius;
|
|
center[1] = y + radius;
|
|
}
|
|
|
|
/**
|
|
* @see org.newdawn.slick.geom.Ellipse#calculateRadius()
|
|
*/
|
|
protected void calculateRadius() {
|
|
boundingCircleRadius = radius;
|
|
}
|
|
|
|
/**
|
|
* Check if this circle touches a rectangle
|
|
*
|
|
* @param other The rectangle to check against
|
|
* @return True if they touch
|
|
*/
|
|
private boolean intersects(Rectangle other) {
|
|
Rectangle box = other;
|
|
Circle circle = this;
|
|
|
|
if (box.contains(x+radius,y+radius)) {
|
|
return true;
|
|
}
|
|
|
|
float x1 = box.getX();
|
|
float y1 = box.getY();
|
|
float x2 = box.getX() + box.getWidth();
|
|
float y2 = box.getY() + box.getHeight();
|
|
|
|
Line[] lines = new Line[4];
|
|
lines[0] = new Line(x1,y1,x2,y1);
|
|
lines[1] = new Line(x2,y1,x2,y2);
|
|
lines[2] = new Line(x2,y2,x1,y2);
|
|
lines[3] = new Line(x1,y2,x1,y1);
|
|
|
|
float r2 = circle.getRadius() * circle.getRadius();
|
|
|
|
Vector2f pos = new Vector2f(circle.getCenterX(), circle.getCenterY());
|
|
|
|
for (int i=0;i<4;i++) {
|
|
float dis = lines[i].distanceSquared(pos);
|
|
if (dis < r2) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Check if circle touches a line.
|
|
* @param other The line to check against
|
|
* @return True if they touch
|
|
*/
|
|
private boolean intersects(Line other) {
|
|
// put it nicely into vectors
|
|
Vector2f lineSegmentStart = new Vector2f(other.getX1(), other.getY1());
|
|
Vector2f lineSegmentEnd = new Vector2f(other.getX2(), other.getY2());
|
|
Vector2f circleCenter = new Vector2f(getCenterX(), getCenterY());
|
|
|
|
// calculate point on line closest to the circle center and then
|
|
// compare radius to distance to the point for intersection result
|
|
Vector2f closest;
|
|
Vector2f segv = lineSegmentEnd.copy().sub(lineSegmentStart);
|
|
Vector2f ptv = circleCenter.copy().sub(lineSegmentStart);
|
|
float segvLength = segv.length();
|
|
float projvl = ptv.dot(segv) / segvLength;
|
|
if (projvl < 0)
|
|
{
|
|
closest = lineSegmentStart;
|
|
}
|
|
else if (projvl > segvLength)
|
|
{
|
|
closest = lineSegmentEnd;
|
|
}
|
|
else
|
|
{
|
|
Vector2f projv = segv.copy().scale(projvl / segvLength);
|
|
closest = lineSegmentStart.copy().add(projv);
|
|
}
|
|
boolean intersects = circleCenter.copy().sub(closest).lengthSquared() <= getRadius()*getRadius();
|
|
|
|
return intersects;
|
|
}
|
|
}
|