/**
* Copyright 2008 - 2015 The Loon Game Engine Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* @project loon
* @author cping
* @email:javachenpeng@yahoo.com
* @version 0.5
*/
package loon.geom;
import loon.utils.MathUtils;
public class Circle extends Ellipse {
/**
*
*/
private static final long serialVersionUID = 1L;
public float radius;
/**
* 构建一个圆形
*
* @param x
* @param y
* @param radius
*/
public Circle(float x, float y, float radius) {
this(x, y, radius, DEFAULT_SEGMENT_MAX_COUNT);
}
/**
* 构建一个圆形
*
* @param x
* @param y
* @param radius
* @param segment
*/
public Circle(float x, float y, float radius, int segment) {
super(x, y, radius, radius, segment);
this.x = x - radius;
this.y = y - radius;
this.radius = radius;
this.boundingCircleRadius = radius;
}
/**
* 返回当前圆形的中心X点
*
*/
@Override
public float getCenterX() {
return getX() + radius;
}
/**
* 返回当前圆形的中心Y点
*/
@Override
public float getCenterY() {
return getY() + radius;
}
/**
* 设定当前圆形半径
*
* @param radius
*/
public void setRadius(float radius) {
if (radius != this.radius) {
pointsDirty = true;
this.radius = radius;
setRadii(radius, radius);
}
}
/**
* 返回当前圆形半径
*
* @return
*/
public float getRadius() {
return radius;
}
/**
* 检查当前圆形与指定形状是否相交
*/
public boolean intersects(Shape shape) {
if (shape instanceof Circle) {
Circle other = (Circle) shape;
float totalRad2 = getRadius() + other.getRadius();
if (MathUtils.abs(other.getCenterX() - getCenterX()) > totalRad2) {
return false;
}
if (MathUtils.abs(other.getCenterY() - getCenterY()) > totalRad2) {
return false;
}
totalRad2 *= totalRad2;
float dx = MathUtils.abs(other.getCenterX() - getCenterX());
float dy = MathUtils.abs(other.getCenterY() - getCenterY());
return totalRad2 >= ((dx * dx) + (dy * dy));
} else if (shape instanceof RectBox) {
return intersects((RectBox) shape);
} else {
return super.intersects(shape);
}
}
/**
* 检查当前圆形是否包含指定直线
*
* @param line
* @return
*/
public boolean contains(Line line) {
return contains(line.getX1(), line.getY1()) && contains(line.getX2(), line.getY2());
}
@Override
protected void findCenter() {
center = new float[2];
center[0] = x + radius;
center[1] = y + radius;
}
@Override
protected void calculateRadius() {
boundingCircleRadius = radius;
}
private boolean intersects(RectBox other) {
RectBox 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;
}
public boolean intersects(Line other) {
Vector2f lineSegmentStart = new Vector2f(other.getX1(), other.getY1());
Vector2f lineSegmentEnd = new Vector2f(other.getX2(), other.getY2());
Vector2f circleCenter = new Vector2f(getCenterX(), getCenterY());
Vector2f closest;
Vector2f segv = lineSegmentEnd.sub(lineSegmentStart);
Vector2f ptv = circleCenter.sub(lineSegmentStart);
float segvLength = segv.len();
float projvl = ptv.dot(segv) / segvLength;
if (projvl < 0) {
closest = lineSegmentStart;
} else if (projvl > segvLength) {
closest = lineSegmentEnd;
} else {
Vector2f projv = segv.mul(projvl / segvLength);
closest = lineSegmentStart.add(projv);
}
boolean intersects = circleCenter.sub(closest).lengthSquared() <= getRadius() * getRadius();
return intersects;
}
}