공부를 하면서 쓰는 내용 이라 글이 지저분할 수 있습니다.
점, 선, 다각형과 원 등 각종 기하학적 도형을 다루는 알고리즘을 게산 기하 알고리즘이라고 합니다. 라고 적혀있습니다. 흔히 Vector를 다뤄서 최적 알고리즘을 구하는 경우가 이에 해당합니다.
위에서 벡터 사용한다고 했죠?
벡터 씁니다. 벡터에 대한 개념을 알아야 될 것 같아요.
2d Vector를 사용한다고 치면 자바는 벡터를 다음과 같이 사용할 수 있을것 같습니다.
public class Vector2D {
public double x;
public double y;
public Vector2D() { }
public Vector2D(double x, double y) {
this.x = x;
this.y = y;
}
public Vector2D(Vector2D v) {
set(v);
}
public void set(double x, double y) {
this.x = x;
this.y = y;
}
public void set(Vector2D v) {
this.x = v.x;
this.y = v.y;
}
public void setZero() {
x = 0;
y = 0;
}
public double[] getComponents() {
return new double[]{x, y};
}
public double getLength() {
return Math.sqrt(x * x + y * y);
}
public double getLengthSq() {
return (x * x + y * y);
}
public double distanceSq(double vx, double vy) {
vx -= x;
vy -= y;
return (vx * vx + vy * vy);
}
public double distanceSq(Vector2D v) {
double vx = v.x - this.x;
double vy = v.y - this.y;
return (vx * vx + vy * vy);
}
public double distance(double vx, double vy) {
vx -= x;
vy -= y;
return Math.sqrt(vx * vx + vy * vy);
}
public double distance(Vector2D v) {
double vx = v.x - this.x;
double vy = v.y - this.y;
return Math.sqrt(vx * vx + vy * vy);
}
public double getAngle() {
return Math.atan2(y, x);
}
public void normalize() {
double magnitude = getLength();
x /= magnitude;
y /= magnitude;
}
public Vector2D getNormalized() {
double magnitude = getLength();
return new Vector2D(x / magnitude, y / magnitude);
}
public static Vector2D toCartesian(double magnitude, double angle) {
return new Vector2D(magnitude * Math.cos(angle), magnitude * Math.sin(angle));
}
public void add(Vector2D v) {
this.x += v.x;
this.y += v.y;
}
public void add(double vx, double vy) {
this.x += vx;
this.y += vy;
}
public static Vector2D add(Vector2D v1, Vector2D v2) {
return new Vector2D(v1.x + v2.x, v1.y + v2.y);
}
public Vector2D getAdded(Vector2D v) {
return new Vector2D(this.x + v.x, this.y + v.y);
}
public void subtract(Vector2D v) {
this.x -= v.x;
this.y -= v.y;
}
public void subtract(double vx, double vy) {
this.x -= vx;
this.y -= vy;
}
public static Vector2D subtract(Vector2D v1, Vector2D v2) {
return new Vector2D(v1.x - v2.x, v1.y - v2.y);
}
public Vector2D getSubtracted(Vector2D v) {
return new Vector2D(this.x - v.x, this.y - v.y);
}
public void multiply(double scalar) {
x *= scalar;
y *= scalar;
}
public Vector2D getMultiplied(double scalar) {
return new Vector2D(x * scalar, y * scalar);
}
public void divide(double scalar) {
x /= scalar;
y /= scalar;
}
public Vector2D getDivided(double scalar) {
return new Vector2D(x / scalar, y / scalar);
}
public Vector2D getPerp() {
return new Vector2D(-y, x);
}
public double dot(Vector2D v) {
return (this.x * v.x + this.y * v.y);
}
public double dot(double vx, double vy) {
return (this.x * vx + this.y * vy);
}
public static double dot(Vector2D v1, Vector2D v2) {
return v1.x * v2.x + v1.y * v2.y;
}
public double cross(Vector2D v) {
return (this.x * v.y - this.y * v.x);
}
public double cross(double vx, double vy) {
return (this.x * vy - this.y * vx);
}
public static double cross(Vector2D v1, Vector2D v2) {
return (v1.x * v2.y - v1.y * v2.x);
}
public double project(Vector2D v) {
return (this.dot(v) / this.getLength());
}
public double project(double vx, double vy) {
return (this.dot(vx, vy) / this.getLength());
}
public static double project(Vector2D v1, Vector2D v2) {
return (dot(v1, v2) / v1.getLength());
}
public Vector2D getProjectedVector(Vector2D v) {
return this.getNormalized().getMultiplied(this.dot(v) / this.getLength());
}
public Vector2D getProjectedVector(double vx, double vy) {
return this.getNormalized().getMultiplied(this.dot(vx, vy) / this.getLength());
}
public static Vector2D getProjectedVector(Vector2D v1, Vector2D v2) {
return v1.getNormalized().getMultiplied(Vector2D.dot(v1, v2) / v1.getLength());
}
public void rotateBy(double angle) {
double cos = Math.cos(angle);
double sin = Math.sin(angle);
double rx = x * cos - y * sin;
y = x * sin + y * cos;
x = rx;
}
public Vector2D getRotatedBy(double angle) {
double cos = Math.cos(angle);
double sin = Math.sin(angle);
return new Vector2D(x * cos - y * sin, x * sin + y * cos);
}
public void rotateTo(double angle) {
set(toCartesian(getLength(), angle));
}
public Vector2D getRotatedTo(double angle) {
return toCartesian(getLength(), angle);
}
public void reverse() {
x = -x;
y = -y;
}
public Vector2D getReversed() {
return new Vector2D(-x, -y);
}
@Override
public Vector2D clone() {
return new Vector2D(x, y);
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof Vector2D) {
Vector2D v = (Vector2D) obj;
return (x == v.x) && (y == v.y);
}
return false;
}
@Override
public String toString() {
return "Vector2d[" + x + ", " + y + "]";
}
}
출처: https://gist.github.com/gunvirranu/6816d65c0231981787ebefd3bdb61f98
github에서 굉장히 좋은 vector2d 예제를 찾아서 이렇게 올립니다.
실제로 c++과는 다르게 자바는 연산자 오버로딩이 없기 때문에 method로 구현하는 것을 알 수 있습니다.
내적
벡터의 내적은 위와 같이 구성된다. A*B Cos세타 알지?
내적으로 할 수 있는 일은 3가지 정도가 있다
외적
벡터의 외적은 위와 같이 표현할 수 있다.
벡터의 외적으로 할 수 있는 일은 다음과 같다.
두 직선의 교차여부를 확인하는 것은 계산 기하 문제의 단골 주제라고 한다. 난 모르겠다
위 공식을 기억하자 위 연립 방정식을 풀면 직선이 교차 하는 것을 알 수 있다.
이 연립 방정식을 방정식 p에 대해서 풀게 된다면
따라서 위 연립 방정식을 정리하면
가 되는 것을 알 수 있다.
boolean lineInterSection(Vector2D a,Vector2D ,vector2D c,vector2D d){
double bet = (b.minus(a)).cross(d.minus(c));
if(Math.abs(bet)< 0.000000001) return false;
else return true;
}
선분과 선분사이의 각도를 구하는 함수 이용
ab = ccw(a,b,c) * ccw(a,b,d); cd = ccw(a,b,c) * ccw(c,d,b); if(ab==0 && cd ==0){ if(b < a) swap(a,b); if(d < c) swap(c,d); return !(b<c || d<a); } return ab<=0 && cd<=0;