这是在画布上绘制的橡皮筋选择矩形。我的问题是,如果画布内容没有旋转,很容易获得正确的矩形大小。但是一旦旋转,矩形就不再与光标一起变大。我需要橡皮筋与屏幕保持平行
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> 0的任何值。 360
我查看了有关如何创建选择矩形的其他代码,其中包含此问题的答案:How to make a resizeable rectangle selection tool? 但我想尽可能使用我的基本代码,因为它与我使用的图形引擎(Piccolo)有关。
我会张贴一些截图,但我无法捕捉橡皮筋。我认为这更像是一个数学问题,而且应该很容易修复,但我无法确定要对旋转显示的效果进行何种数学计算。
答案 0 :(得分:2)
此代码使用Paint
事件来绘制
未旋转的橡皮筋
并检查示例rectanlge的角落
// 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,更有趣的部分是决定选择哪些对象。是否会计算任何交叉点还是应该完全包含它?
我找到了一个很好的旋转代码in this post并添加了一个示例来检查固定的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";
}