使用c#Graphics.IsVisible似乎已关闭 [英] Using c# Graphics.IsVisible seems to be off

查看:57
本文介绍了使用c#Graphics.IsVisible似乎已关闭的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,希望这对于有图形经验的人来说非常简单,并且可以解释这里的问题(我猜它与Rounding有关。



我我在这里绘制一个三角形,我正在使用IsVisible并对一个点进行点击测试(看看该点是否在三角形内部。为了测试目的,我在几行中扫描几个点。三角形是(0,0),(10,0),(10,10)。我希望点5,5在线上是正确的(即不确定它是否击中),但在X中更早没有(例如但是如果你看下面我的结果,这会开始在4.5,5之前更早地评估真实。这只是一个舍入误差吗?(因为它到目前为止有点奇怪)。



有没有更好的方法进行命中测试?我不能只做公式,因为我希望我的代码相当通用。



Hello, hopefully this is super simple for someone experienced with graphics and can explain the problem here (I'm guessing it has to do with Rounding.

I'm drawing a triangle here and I'm using IsVisible and doing a hit test on a point (to see if the point is inside the triangle. For testing purposes I'm scanning a few points in a couple of lines. The triangle is (0,0),(10,0),(10,10). I would've expected the point 5,5 to be right on the line (i.e. unsure if it hits), but certainly nothing earlier in X (e.g. 4.9,5) to be a hit. However if you look at my results below, this starts to evaluate true far earlier at 4.5,5. Is this just a rounding error? (sort of weird since it's so far).

Is there a better way to do a hit test? I can't just do equations as I want my code to be fairly generic.

private static GraphicsPath RunHitTestsWithGP()
{
    var gp = new GraphicsPath();
    gp.StartFigure();
    gp.AddLines(new PointF[]
        {
            new PointF(0, 0),
            new PointF(10, 0),
            new PointF(10, 10),
            new PointF(0, 0)
        });
    gp.CloseFigure();

    for (int i = 0; i < 20; i++)
    {
        var t1 = new PointF(4f + i / 10f, 5);
        System.Diagnostics.Debug.WriteLine("Testing: {0} Yields: {1}", t1, gp.IsVisible(t1));
    }

    for (int i = 0; i < 20; i++)
    {
        var t1 = new PointF(4f + i / 10f, 6);
        System.Diagnostics.Debug.WriteLine("Testing: {0} Yields: {1}", t1, gp.IsVisible(t1));
    }
    return gp;
}







Testing: {X=4, Y=5} Yields: False
Testing: {X=4.1, Y=5} Yields: False
Testing: {X=4.2, Y=5} Yields: False
Testing: {X=4.3, Y=5} Yields: False
Testing: {X=4.4, Y=5} Yields: False
Testing: {X=4.5, Y=5} Yields: True
Testing: {X=4.6, Y=5} Yields: True
Testing: {X=4.7, Y=5} Yields: True
Testing: {X=4.8, Y=5} Yields: True
Testing: {X=4.9, Y=5} Yields: True
Testing: {X=5, Y=5} Yields: True
Testing: {X=5.1, Y=5} Yields: True
Testing: {X=5.2, Y=5} Yields: True
Testing: {X=5.3, Y=5} Yields: True
Testing: {X=5.4, Y=5} Yields: True
Testing: {X=5.5, Y=5} Yields: True
Testing: {X=5.6, Y=5} Yields: True
Testing: {X=5.7, Y=5} Yields: True
Testing: {X=5.8, Y=5} Yields: True
Testing: {X=5.9, Y=5} Yields: True


Testing: {X=4, Y=6} Yields: False
Testing: {X=4.1, Y=6} Yields: False
Testing: {X=4.2, Y=6} Yields: False
Testing: {X=4.3, Y=6} Yields: False
Testing: {X=4.4, Y=6} Yields: False
Testing: {X=4.5, Y=6} Yields: False
Testing: {X=4.6, Y=6} Yields: False
Testing: {X=4.7, Y=6} Yields: False
Testing: {X=4.8, Y=6} Yields: False
Testing: {X=4.9, Y=6} Yields: False
Testing: {X=5, Y=6} Yields: False
Testing: {X=5.1, Y=6} Yields: False
Testing: {X=5.2, Y=6} Yields: False
Testing: {X=5.3, Y=6} Yields: False
Testing: {X=5.4, Y=6} Yields: False
Testing: {X=5.5, Y=6} Yields: True
Testing: {X=5.6, Y=6} Yields: True
Testing: {X=5.7, Y=6} Yields: True
Testing: {X=5.8, Y=6} Yields: True
Testing: {X=5.9, Y=6} Yields: True

推荐答案

已知问题。调用graphicspath.isvisible时,浮点值将四舍五入为整数。



令人难以置信和悲伤,但确实如此。我正在以另一种方式工作。我会尽快给你更新。



更新:



在考虑之后,这很有道理,就像double.equals您需要定义差异度量或精度。否则它将是无限精确的。所以一个简单的数学解决方法可能是扩大规模,然后进行命中测试。换句话说,确定要舍入的小数位(即4,9,4.99,4.999)。所以下面的解决方案可行,但也许你可以稍微改进一下,因为它只会工作到一个点然后它会溢出。我检查了5位小数,它的工作原理。您还必须考虑条目的精度,例如带有像素的真实场景中的图形,例如,您无法检测到小数像素。不确定该应用程序的用途是什么,但这应该指向正确的方向。



Known issue. Floating point values are rounded to integers when calling graphicspath.isvisible.

unbelievable and sad, but true. I am working on another way. I will update you shortly.

Update:

After thinking about it, it makes sense, like double.equals you would need to define a difference measure, or precision. Otherwise it would be infinitesimally precise. So a simple mathematical workaround could be to scale up and then do the hit test. In other words determine at what decimal place do you want to round(i.e. 4,9, 4.99, 4.999). So the solution below works, but maybe you could refine it a bit, because it will only work to a point and then it overflows. I checked it for 5 decimal places and it works. You also have to consider the precision of the entries, like for graphics in real world scenarios with pixels, for example, you can't detect a fractional pixel. Not sure what the purpose of the app is, but this should point you in the right direction.

private static GraphicsPath RunHitTestsWithGP(int DecimalPlaces)
{
	dynamic gp = new GraphicsPath();
	int Scale = Math.Pow(10, DecimalPlaces);
	gp.StartFigure();
	gp.AddLines(new PointF[] {
		ScalePointF(new PointF(0, 0), DecimalPlaces),
		ScalePointF(new PointF(10, 0), DecimalPlaces),
		ScalePointF(new PointF(10, 10), DecimalPlaces),
		ScalePointF(new PointF(0, 0), DecimalPlaces)
	});
	gp.CloseFigure();
	for (int i = 0; i <= 19; i++) {
		dynamic t1 = new PointF(4f + i / 10f, 5);
		Console.WriteLine("Testing: {0} Yields: {1}", t1, gp.IsVisible(ScalePointF(t1, DecimalPlaces)));
	}

	for (int i = 0; i <= 19; i++) {
		dynamic t1 = new PointF(4f + i / 10f, 6);
		Console.WriteLine("Testing: {0} Yields: {1}", t1, gp.IsVisible(ScalePointF(t1, DecimalPlaces)));
	}
	return gp;
}

private static PointF ScalePointF(PointF PointFToScale, int DecimalPlaces)
{
	return new PointF(PointFToScale.X * (Math.Pow(10, DecimalPlaces)), PointFToScale.Y * (Math.Pow(10, DecimalPlaces)));
}


啊,我根据你的输入做了一点阅读,谢谢。有点烦人的是他们似乎在宣传浮点图形时实际上并没有得到很好的支持。
Ah, I did a little further reading based on your input, thanks. Kind of annoying that they seem to advertise floating point graphics when in fact it is not well supported.


这篇关于使用c#Graphics.IsVisible似乎已关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆