【问题标题】:How to identify the polygone is triangle in wpf如何在wpf中识别多边形是三角形
【发布时间】:2018-08-30 08:47:41
【问题描述】:

我有“n”个多边形,如下所示。

    <Polygon Points="544,245,544,175,568,175,568,175" Stroke="Black" StrokeThickness="1" />
    <Polygon Points="2,223,96,223,96,153,96,153" Stroke="Black" StrokeThickness="1" />
    <Polygon Points="350,315,350,333,306,333,306,395,306,395" Stroke="Black" StrokeThickness="1" />
    <Polygon Points="164,53,160,53,160,51,160,55,160,55" Stroke="Black" StrokeThickness="1" />
    <Polygon Points="264,63,264,58,264,68,264,63,267,63,267,60,267,66,267,63,270,63,270,58,270,68,270,68" Stroke="Black" StrokeThickness="1" />
    <Polygon Points="8,63,444,63,444,168,444,168" Stroke="Black" StrokeThickness="1" />
    <Polygon Points="212,169,212,93,285,93,285,63,285,63" Stroke="Black" StrokeThickness="1" />
    <Polygon Points="26,93,127,93,127,148,29,148,29,148" Stroke="Black" StrokeThickness="1" />
    <Polygon Points="152,116,152,132,212,132,212,132" Stroke="Black" StrokeThickness="1" />
    <Polygon Points="121,316,121,333,70,333,70,366,70,366" Stroke="Black" StrokeThickness="1" />
    <Polygon Points="464,395,488,395,488,284,527,284,527,284" Stroke="Black" StrokeThickness="1" />
    <Polygon Points="168,63,168,67,180,59,180,67,168,59,168,59" Stroke="Black" StrokeThickness="1" />
    <Polygon Points="173,62,173,56,165,56,165,51,175,51,175,61,175,61" Stroke="Black" StrokeThickness="1" />
    <Polygon Points="3,285,121,285,121,316,211,316,211,304,211,304" Stroke="Black" StrokeThickness="1" />

请帮我找出这些多边形中的三角形是什么

我已尝试识别如下顶点..

        Polygon polygon = new Polygon();
        polygon.Points = new System.Windows.Media.PointCollection()
        {
            new Point(446,134),
            new Point(442,134),
            new Point(444,140),
            new Point(444,140),
        }; 

        List<double> verticesPoints = new List<double>();
        for (int i = 0; i < polygon.Points.Count - 1; i++)
        {
            var point1 = polygon.Points[i];
            var point2 = polygon.Points[i + 1];

            //calculate delta x and delta y between the two points
            var deltaX = Math.Pow((point2.X - point1.X), 2);
            var deltaY = Math.Pow((point2.Y - point1.Y), 2);

            //pythagras theorem for distance
            var distance = Math.Sqrt(deltaY + deltaX);

            //distance is zero..then same point
            if (distance != 0)
            {
                verticesPoints.Add(distance);
            }
        }
       ///Here is the code to calculate angle and consider the triangle
       ///three vertices then it might be triangle.
        if (verticesPoints.Count == 3)
        {
            ///use The Law of Cosines
            ///cos(C) = a2 + b2 − c2 /2ab
            ///cos(A) = b2 + c2 − a2 /bc
            ///cos(B) = c2 + a2 − b2 /ca
            var a = ((Math.Pow(verticesPoints[1], 2)) + (Math.Pow(verticesPoints[2], 2)) - (Math.Pow(verticesPoints[0], 2)))
                      / (2 * verticesPoints[1] * verticesPoints[2]);

            var b = ((Math.Pow(verticesPoints[0], 2)) + (Math.Pow(verticesPoints[2], 2)) - (Math.Pow(verticesPoints[1], 2)))
                     / (2 * verticesPoints[0] * verticesPoints[2]);

            var c = ((Math.Pow(verticesPoints[0], 2)) + (Math.Pow(verticesPoints[1], 2)) - (Math.Pow(verticesPoints[2], 2)))
                     / (2 * verticesPoints[0] * verticesPoints[1]);

            ///Inverse of cos
            var radians1 = Math.Acos(a);
            ///Convert radian to degree
            double degrees1 = (radians1 * 180.0) / Math.PI;

            ///Inverse of cos
            var radians2 = Math.Acos(b);
            //Convert radian to degree
            double degrees2 = (radians2 * 180.0) / Math.PI;

            ///Inverse of cos
            var radians3 = Math.Acos(c);
            ///Convert radian to degree
            double degrees3 = (radians3 * 180.0) / Math.PI;

            var totalDegrees = degrees1 + degrees2 + degrees3;
            if (totalDegrees == 180)
            {
               // Consider triangle
            }
        }

但上面的代码不适用于&lt;Polygon Points="446,134,442,134,444,140,444,140" Stroke="Black" StrokeThickness="1" /&gt;,它只给出两个顶点,但它是一个三角形,有些场景有 3 个顶点,但总度​​数不是 180

【问题讨论】:

  • 只循环看看多边形是否有3个点?到目前为止,您尝试了哪些方法,您对哪一部分有问题?
  • @Diado 比这要复杂一点(例如,一行 3 个点),但这是一个好的开始 :) 当然,到目前为止的代码会有所帮助。
  • 扩展@John 的评论:检查一个点是否在线可以按照stackoverflow.com/questions/11907947/…中的描述进行
  • 再想一想,我不会比较距离而是比较角度,即每对之间的var angle = Math.Atan2(deltaY, deltaX)。如果角度保持不变(在浮点算术怪癖的一些余量范围内),则当前顶点只是前一个顶点的延伸,并且都形成一条线。

标签: c# wpf


【解决方案1】:

这里的代码遍历点并计算每个点之间的梯度。如果两个连续点的梯度相同,则它们必须是同一条线,因此noOfPoints 不递增,否则递增。

第一个梯度存储在firstGradient中,以便检查连接最后一个点和第一个点的梯度是否与第一个和第二个点之间的梯度相同。

        Polygon polygon = new Polygon();
        polygon.Points = new System.Windows.Media.PointCollection()
    {
        new Point(446,134),
        new Point(442,134),
        new Point(444,140),
        new Point(444,140),
    };

        List<double> verticesPoints = new List<double>();
        double? firstGradient = null;
        double? gradient = null;
        double? newGradient = null;
        int noOfSides = 1;

        for (int i = 0; i < polygon.Points.Count - 1; i++)
        {
            var point1 = polygon.Points[i];
            var point2 = polygon.Points[i + 1];

            if(point1 == point2) { continue;}

            //calculate delta x and delta y between the two points
            var deltaX = point2.X - point1.X;
            var deltaY = point2.Y - point1.Y;

            //calculate gradient
            newGradient = (deltaY / deltaX);

            if (i == 0)
            {
                firstGradient = newGradient;
            }

            if ((gradient != newGradient) && (i != polygon.Points.Count - 2))
            {
                noOfSides++;
            }
            else if (i == polygon.Points.Count - 2)
            {
                if ((gradient != newGradient) && (firstGradient != newGradient)) //This now checks the gradient between the last and first point.
                {

                    point1 = polygon.Points[i+1];
                    point2 = polygon.Points[0];

                    if (point1 == point2) { continue; }

                    //calculate delta x and delta y between the two points
                    deltaX = point2.X - point1.X;
                    deltaY = point2.Y - point1.Y;

                    //calculate gradient
                    newGradient = (deltaY / deltaX);

                    if(newGradient != firstGradient)
                    {
                        noOfSides++;
                    }

                }


            gradient = newGradient;
        }

【讨论】:

  • @SharanRM 什么矩形?
  • 代码无法识别三角形...一些多边形是矩形...
  • @SharanRM 逻辑是将三角形识别为矩形还是将矩形识别为三角形?
  • @SharanRM 能否请您向我发送一组该代码无法正确识别三角形的点?
  • 谢谢大家..使用AForge.Math.Geometry库解决了这个问题。参考aforgenet.com/articles/shape_checker
【解决方案2】:

我已经使用“AForge.NET”解决了上述问题

        Polygon polygon = new Polygon();
        polygon.Points = new PointCollection()
        {
             new Point(446,134),
             new Point(442,134),
             new Point(444,140),
             new Point(444,140),
        };

        SimpleShapeChecker shapeChecker = new  SimpleShapeChecker();
        List<IntPoint> edgePoints = new List<IntPoint>();
        List<IntPoint> corners;
        for (int i = 0; i <= polygon.Points.Count - 1; i++)
        {
            edgePoints.Add(new IntPoint((int)polygon.Points[i].X, (int)polygon.Points[i].Y));
        }

        shapeChecker.MinAcceptableDistortion = 0.2f;
        shapeChecker.LengthError = 0;
        shapeChecker.AngleError = 5;
        shapeChecker.RelativeDistortionLimit = 0;

        if (shapeChecker.IsTriangle(edgePoints, out corners))
        {
            //shape is triangle
        }

需要在命名空间下面添加

using AForge;
using AForge.Math.Geometry;

参考:http://aforgenet.com/articles/shape_checker/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-25
    • 1970-01-01
    相关资源
    最近更新 更多