gpt4 book ai didi

c# - 如何在椭圆内绑定(bind)一个圆?

转载 作者:可可西里 更新时间:2023-11-01 07:56:25 27 4
gpt4 key购买 nike

这篇文章的标题很难想到,所以如果你能想到一个更具描述性的标题,请告诉我。无论如何,我的问题很具体,需要一些简单的数学知识。我正在编写一个 C# WinForms 应用程序,它有点像旧的“xeyes”Linux 应用程序。它基本上是一组跟随鼠标光标的眼睛。起初这听起来很简单,但是如果您是像我这样的完美主义者,可能会变得相当复杂 :P。到目前为止,这是我的代码(只有 paint 方法,调用间隔为 16)。

int lx = 35;
int ly = 50;
int rx;
int ry;

int wx = Location.X + Width / 2;
int wy = Location.Y + Height / 2;

Rectangle bounds = Screen.FromControl(this).Bounds;

// Calculate X

float tempX = (mx - wx) / (float)(bounds.Width / 2);

// Calculate Y

float tempY = (my - wy) / (float)(bounds.Height / 2);

// Draw eyes

e.Graphics.FillEllipse(Brushes.LightGray, 10, 10, 70, 100);
e.Graphics.FillEllipse(Brushes.LightGray, 90, 10, 70, 100);

// Draw pupils (this only draws the left one)

e.Graphics.FillEllipse(Brushes.Black, lx += (int)(25 * tempX), ly += (int)(40 * tempY), 20, 20);

现在这在基本级别上确实有效,但是如果用户将光标放在 0,0 上,有时会发生这种情况。

The pupil can exit the main eye.

现在我的问题是如何解决这个问题? IF 语句是什么来检查鼠标指针的位置,然后据此缩小瞳孔 X?

谢谢。

编辑:这是我获取鼠标位置的地方(mymx):

private void timer_Tick(object sender, EventArgs e)
{
mx = Cursor.Position.X;
my = Cursor.Position.Y;

Invalidate();
}

定时器在eyes_Load事件中启动,间隔为16。

编辑 2: 最终解决方案:http://pastebin.com/fT5HfiQR

最佳答案

将眼球建模为以下椭圆:

enter image description here

它的等式是:

enter image description here

以及连接其中心和光标的线:

enter image description here

(不用担心奇点)

然后我们可以求解得到交点:

enter image description here

在哪里

enter image description here

现在您可以通过将中心到光标的距离除以 sigma 来计算到眼球边缘的距离。剩下的只是插值以限制瞳孔的位置:

enter image description here

enter image description here

你想要的if语句就是then

enter image description here


(请注意,对于 math-mo,上面的内容略有简化,假设您的椭圆不是太窄;精确 解决方案是非解析的)


编辑:我在 VB.NET 中的测试:

enter image description here

enter image description here

enter image description here


编辑 2:C# 端口

PointF Bound(double xc, double yc, double w, double h, double xm, double ym, double r)
{
double dx = xm - xc, dy = ym - yc;
if (Math.Abs(dx) > 0.001 && Math.Abs(dy) > 0.001)
{
double dx2 = dx * dx, dy2 = dy * dy;
double sig = 1.0 / Math.Sqrt(dx2 / (w * w * 0.25) + dy2 / (h * h * 0.25));
double d = Math.Sqrt(dx2 + dy2), e = d * sig;
if (d > e - r)
{
double ratio = (e - r) / d;
return new PointF((float)(xc + dx * ratio),
(float)(yc + dy * ratio));
}
}
return new PointF((float)xm, (float)ym);
}
  • xc, yc: 椭圆中心坐标
  • w, h:椭圆的宽高
  • xm, ym:鼠标坐标
  • r:要约束的圆(瞳孔)的半径
  • 返回:你想放置圆心的点

编辑 3:非常感谢 Quinchilion 进行了以下优化(该死的,这狠狠地打了我的脸)

PointF Bound(double xc, double yc, double w, double h, double xm, double ym, double r)
{
double x = (xm - xc) / (w - r);
double y = (ym - yc) / (h - r);
double dot = x*x + y*y;
if (dot > 1) {
double mag = 1.0 / Math.Sqrt(dot);
x *= mag; y *= mag;
}
return new PointF((float)(x * (w - r) + xc), (float)(y * (h - r) + yc));
}

关于c# - 如何在椭圆内绑定(bind)一个圆?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37621970/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com