Files
Terrarum/lib/slick-source/org/newdawn/slick/geom/Circle.java
Song Minjae 059abff814 added sources for Slick
Former-commit-id: 1647fa32ef6894bd7db44f741f07c2f4dcdf9054
Former-commit-id: 0e5810dcfbe1fd59b13e7cabe9f1e93c5542da2d
2016-12-30 23:29:12 +09:00

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;
}
}