특정 지점을 중심으로 정점을 회전하는 방법은 무엇입니까?
2D 공간에 두 개의 점이 있고이 점 중 하나를 X도 회전하고 다른 점이 중심 역할을한다고 가정합니다.
float distX = Math.abs( centerX -point2X );
float distY = Math.abs( centerY -point2Y );
float dist = FloatMath.sqrt( distX*distX + distY*distY );
지금까지 두 점 사이의 거리를 찾아야했습니다 ... 그 점에서 어디로 가야할지 아이디어가 있습니까?
가장 쉬운 방법은 세 가지 변환을 구성하는 것입니다.
- 점 1을 원점으로 가져 오는 번역
- 필요한 각도만큼 원점을 중심으로 회전
- 포인트 1을 원래 위치로 되 돌리는 번역
이 모든 작업을 수행하면 다음과 같은 변형으로 끝납니다.
newX = centerX + (point2x-centerX)*Math.cos(x) - (point2y-centerY)*Math.sin(x);
newY = centerY + (point2x-centerX)*Math.sin(x) + (point2y-centerY)*Math.cos(x);
이것은 x
시계 방향 회전 ( 좌표계의 표준 또는 오른손 방향)에 대해 각도 가 음수 라고 가정합니다 . 그렇지 않은 경우 sin(x)
.
2 차원 회전 매트릭스가 필요합니다. http://en.wikipedia.org/wiki/Rotation_matrix
당신의 새로운 포인트는
newX = centerX + ( cosX * (point2X-centerX) + sinX * (point2Y -centerY))
newY = centerY + ( -sinX * (point2X-centerX) + cosX * (point2Y -centerY))
시계 반대 방향이 아닌 시계 방향으로 회전하기 때문에
Java Graphics2D API를 사용한다고 가정하고 다음 코드를 시도하십시오.
Point2D result = new Point2D.Double();
AffineTransform rotation = new AffineTransform();
double angleInRadians = (angle * Math.PI / 180);
rotation.rotate(angleInRadians, pivot.getX(), pivot.getY());
rotation.transform(point, result);
return result;
피벗은 회전하는 지점입니다.
"1"을 0,0으로 번역
회전
x = sin (각도) * r; y = cos (각도) * r;
다시 번역
2D의 다른 점을 중심으로 점을 회전하는 방법은 다음과 같습니다. 3D에서 이것은 z 축에 대한 회전으로 사용될 수 있습니다. 점의 z- 좌표는 변경되지 않기 때문에 입력됩니다. 3D에서 x 축과 y 축에 대한 회전도 쉽게 구현할 수 있습니다.
코드는 JavaScript로되어 있습니다. 시작 부분에 주석 처리 된 줄은 함수에 대한 테스트 세트입니다. 또한 사용의 예가됩니다.
//A = new Array(0,0)
//S = new Array(-1,0)
//fi = 90
//alert("rotujBod: " + rotatePoint(A, S, fi))
function rotatePoint(A, S, fi) {
/** IN points A - rotated point, S - centre, fi - angle of rotation (rad)
* points in format [Ax, Ay, Az], angle fi (float)
* OUT point B
*/
r = Math.sqrt((A[0] - S[0])*(A[0] - S[0]) + (A[1] - S[1])*(A[1] - S[1]))
originOfRotation = new Array(S[0] + r, S[1])
if (A[1] < S[1]) {
A2 = new Array(A[0], -1*A[1])
originalAngle = -1*sizeOfAngle(originOfRotation, S, A2)
} else {
originalAngle = sizeOfAngle(originOfRotation, S, A)
}
x = S[0] + r*Math.cos(fi + originalAngle)
y = S[1] + r*Math.sin(fi + originalAngle)
B = new Array(x, y)
return(B)
}
function sizeOfAngle(A, S, B) {
ux = A[0] - S[0]
uy = A[1] - S[1]
vx = B[0] - S[0]
vy = B[1] - S[1]
if((Math.sqrt(ux*ux + uy*uy)*Math.sqrt(vx*vx + vy*vy)) == 0) {return 0}
return Math.acos((ux*vx + uy*vy)/(Math.sqrt(ux*ux + uy*uy)*Math.sqrt(vx*vx + vy*vy)))
}
여기에 회전 방향을 신경 쓰는 버전이 있습니다. 오른쪽 (시계 방향)은 음수이고 왼쪽 (시계 반대 방향)은 양수입니다. 점 또는 2D 벡터를 보내고이 메서드 (마지막 줄)에서 기본 요소를 설정하여 성능을위한 메모리 할당을 피할 수 있습니다. vector2 및 mathutils를 사용하는 라이브러리 또는 java의 내장 포인트 클래스로 대체해야 할 수 있으며 mathutils 대신 math.toradians ()를 사용할 수 있습니다.
/**
* rotates the point around a center and returns the new point
* @param cx x coordinate of the center
* @param cy y coordinate of the center
* @param angle in degrees (sign determines the direction + is counter-clockwise - is clockwise)
* @param px x coordinate of point to rotate
* @param py y coordinate of point to rotate
* */
public static Vector2 rotate_point(float cx,float cy,float angle,float px,float py){
float absangl=Math.abs(angle);
float s = MathUtils.sin(absangl * MathUtils.degreesToRadians);
float c = MathUtils.cos(absangl * MathUtils.degreesToRadians);
// translate point back to origin:
px -= cx;
py -= cy;
// rotate point
float xnew;
float ynew;
if (angle > 0) {
xnew = px * c - py * s;
ynew = px * s + py * c;
}
else {
xnew = px * c + py * s;
ynew = -px * s + py * c;
}
// translate point back:
px = xnew + cx;
py = ynew + cy;
return new Vector2(px, py);
}
이 방법은 게시물에서 시도한 방법보다 더 많은 성능을 제공합니다. 매우 비용이 많이 드는 sqrt를 사용하기 때문에 이런 식으로 각도에서 라디안으로 변환하여 룩업 테이블로 관리하기 때문입니다. 그래서 그것은 매우 높은 성능을 가지고 있습니다.
참조 URL : https://stackoverflow.com/questions/12161277/how-to-rotate-a-vertex-around-a-certain-point
'IT이야기' 카테고리의 다른 글
부분 문자열의 Javascript getElementById 기반 (0) | 2021.04.27 |
---|---|
조각 트랜잭션 애니메이션이 완료된 후 작업 수행 (0) | 2021.04.27 |
데이터베이스 크기가 2GB보다 크면 SQLite 성능이 저하? (0) | 2021.04.26 |
Express.js의 MEAN 스택 역할 (0) | 2021.04.26 |
문자열에 다른 문자열이 포함되어 있지 않은지 확인하는 Bash (0) | 2021.04.26 |