캔버스에 그린 고무줄 선택 사각형입니다. 내 문제는 캔버스 내용이 회전하지 않으면 사각형의 올바른 크기를 쉽게 얻을 수 있다는 것입니다. 그러나 직사각형이 회전하자마자 더 이상 커서로 크기가 조정되지 않습니다. 화면과 평행을 유지하려면 고무 밴드가 필요합니다.
var dragPt = new PointF(e.Position.X - G.ReferenceOffset.X, e.Position.Y - G.ReferenceOffset.Y);
var rotation = ADEEnvironment.RotateAngle;
var width = (dragPt.X - pressPt.X);
var height = (dragPt.Y - pressPt.Y);
코드는 매우 사소합니다. 마우스 아래로 마우스 위치를 캡처합니다. pressPt. 마우스 이동 이벤트에서 현재 마우스 위치 dragPt를 가져 와서 고무줄 사각형의 너비와 높이를 계산하고이 값을 사용하여 pressPt에서 원점을 가진 사각형을 만듭니다.
캔버스의 카메라가 회전하지 않으면 제대로 작동합니다. 디스플레이를 회전 할 때 화면이 그려지는 캔버스가 아니라 화면과 정렬되도록 고무 밴드가 필요합니다. 고무줄도 회전 시켜서 그대로 둡니다.
고무줄 사각형을 회전하여 화면과의 정렬 상태로 되 돌리면 사각형의 크기가 더 이상 올바르게 조정되지 않습니다. 그래서 많은 엉망이 된 후에 약간의 삼각법을 시도했습니다.
var width = (float)((dragPt.X - pressPt.X) / Math.Cos(rotation));
var height = (float)((dragPt.Y - pressPt.Y) / Math.Cos(rotation));
작동하지 않고 회전 각도가 0> 360 일 수 있다는 점을 감안할 때 매우 지저분합니다.
이 질문에 대한 답변을 포함하여 선택 사각형을 만드는 방법에 대한 다른 코드를 살펴 보았습니다 . 크기 조정 가능한 사각형 선택 도구를 만드는 방법? 하지만 내가 사용하고있는 그래픽 엔진 (Piccolo)과 관련이 있기 때문에 가능한 기본 코드를 사용하고 싶습니다.
스크린 샷을 몇 장 올리려고하는데 고무줄을 캡처 할 수 없습니다. 나는 이것이 다른 어떤 것보다 수학 문제에 가깝고 고치기 쉬어야한다고 생각하지만 디스플레이 회전의 효과를 설명하기 위해 어떤 수학 계산을해야하는지 알 수 없습니다.
이 코드는 Paint
이벤트를 사용하여
회전되지 않은 고무 밴드
예제 직사각형의 모서리를 확인합니다.
// one example 'object'
Rectangle R0 = new Rectangle(182,82,31,31);
// a few helpers
Point curMouse = Point.Empty;
Point downMouse = Point.Empty;
Rectangle RM = Rectangle.Empty;
float angle = 30;
Point center = new Point(-55, -22);
private void canvas_Paint(object sender, PaintEventArgs e)
{
// preprare the canvas to rotate around a center point:
e.Graphics.TranslateTransform(center.X , center.Y);
e.Graphics.RotateTransform(angle);
e.Graphics.TranslateTransform(-center.X, -center.Y);
// draw one object and reset
e.Graphics.DrawRectangle(Pens.Green, R0);
e.Graphics.ResetTransform();
// for testing (and hittesting): this is the unrotated obejct:
e.Graphics.DrawRectangle(Pens.LightGray, R0);
// allowing for any way the rubber band is drawn..
// ..should be moved to a helper function!
Size S = new Size( Math.Abs(downMouse.X - curMouse.X),
Math.Abs(downMouse.Y - curMouse.Y));
Point P0 = new Point(Math.Min(downMouse.X, curMouse.X),
Math.Min(downMouse.Y, curMouse.Y));
RM = new Rectangle(P0, S);
// the ruber band
e.Graphics.DrawRectangle(Pens.Red, RM);
}
private void canvas_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
curMouse = e.Location;
canvas.Invalidate();
}
private void canvas_MouseDown(object sender, MouseEventArgs e)
{
downMouse = e.Location;
curMouse = e.Location;
}
IMO, 더 흥미로운 부분은 어떤 객체가 선택되는지 결정하는 것입니다. 교차로가 계산됩니까 아니면 완전히 차단되어야합니까?
이 게시물에서 멋진 회전 코드 를 발견 하고 수정 된 Rectangle
.
물론 더 복잡한 객체는 더 복잡한 포인트 목록을 요구합니다. 정말 정확한 결과를 얻으려면 지원 GraphicsPaths
하는 집합 작업을 수행 해야 할 수도 있습니다 Regions
. 하지만 단순한 볼록 껍질이 가능합니다 ..
물론 반복적으로 계산하는 대신 회전 된 점을 저장하는 것이 좋습니다.
static Point RotatePoint(Point pointToRotate, Point centerPoint, double angleInDegrees)
{
double angleInRadians = angleInDegrees * (Math.PI / 180);
double cosTheta = Math.Cos(angleInRadians);
double sinTheta = Math.Sin(angleInRadians);
return new Point
{
X =
(int)
(cosTheta * (pointToRotate.X - centerPoint.X) -
sinTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.X),
Y =
(int)
(sinTheta * (pointToRotate.X - centerPoint.X) +
cosTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.Y)
};
}
private void canvas_MouseUp(object sender, MouseEventArgs e)
{
List<Point> points = new List<Point>();
points.Add(RotatePoint(new Point(R0.Left, R0.Top), center, angle));
points.Add(RotatePoint(new Point(R0.Right, R0.Top), center, angle) );
points.Add(RotatePoint(new Point(R0.Right, R0.Bottom), center, angle) );
points.Add(RotatePoint(new Point(R0.Left, R0.Bottom), center, angle));
bool ok = true;
foreach (Point pt in points) if (!RM.Contains(pt)) ok = false;
if (ok) this.Text = "HIT"; else this.Text = "no hit";
}
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다