C#画五角星、月牙形和它们相交求面积

利用Winform作图,是非常便利的。最近在做一个几何阴影相交求解的程序。程序包含了五角星的画法,月牙的画法。以及它们相交阴影部分的面积求法。(重点判断点是否在五角星内)
效果图
在这里插入图片描述
画五角星

 //画五角星操作
        private Five_star_struct draw_five(List<Point> ps) {
            //ps[0]中心, ps[1]任意点
            float r = ComputeOpter.getDist(ps[0], ps[1]);
            Point[] vPoints = new Point[5];
            five(ps[0], r,ref vPoints);
            //vPoints 线段组,ps[0]为中心点
            Five_star_struct five_struct = new Five_star_struct(vPoints, ps[0],r);
            return five_struct;
        }
        //五角星
        private void five(Point cen, float r,ref Point[]  vPoints)
        {
            double vAngle = 2.0 * Math.PI / 4 + Math.PI;
            for (int i = 0; i < vPoints.Length; i++)
            {
                vAngle += 2.0 * Math.PI / (double)vPoints.Length;
                Point temp = new Point(
                    (float)(Math.Cos(vAngle) * r) + cen.X,
                    (float)(Math.Sin(vAngle) * r) + cen.Y);
                float ang= ComputeOpter.GetAngle(temp, cen);
                vPoints[i] = ComputeOpter.PointRotate(cen, temp, ang+90);
            }
            for (int i=1;i<5;i++) {
                gra.DrawLine(Pens.Black, vPoints[i].X, vPoints[i].Y, vPoints[i-1].X, vPoints[i-1].Y);
                if (i == 4) {           
                    gra.DrawLine(Pens.Black, vPoints[0].X, vPoints[0].Y, vPoints[4].X, vPoints[4].Y);
                }
            }       
        }

图例
在这里插入图片描述

画月牙

 //画两个圆弧
        private List<Arc_struct> draw_arc(List<Point> ptemp) {
            //ptemp[0] 起点, ptemp[1] 终点, ptemp[2] 任意点
            List<Arc_struct> cen_radius = new List<Arc_struct>();
            Point[] duandian = { ptemp[0], ptemp[1]};
            for (int i = 0; i < 2; i++)
            {
                
                float R = 0;
                Point PCenter = new Point(0, 0);
                ComputeOpter.GetCircular(ptemp[0], ptemp[1], ptemp[i + 2], ref R, ref PCenter);
                Arc_struct item = new Arc_struct(duandian,PCenter, R);
                //draw_point(PCenter);
                //draw_line(PCenter, ptemp[0]);
                cen_radius.Add(item);
                arc(ptemp[0], ptemp[1], ptemp[i + 2], PCenter, R);
            }
            return cen_radius;

        }
        //画一个圆弧
        private void arc(Point p1, Point p2, Point p3, Point cen, float R) {
            //绘制圆弧
            //p1 第一个点 p2 第二个点 cen 圆心
            Graphics g = this.CreateGraphics();
            Pen redPen = new Pen(Color.DarkRed, 5);
            float startangle = ComputeOpter.GetAngle(p1, cen);
            float scanangle = ComputeOpter.includeAngle(cen, p1, p2);
            if (p3.Y>p1.Y|| p3.Y > p2.Y) {
                scanangle = -scanangle;
            }
            gra.DrawArc(new Pen(Color.Blue, 2), cen.X - R, cen.Y - R, 2 * R, 2 * R, -startangle, scanangle);
        }

图例
在这里插入图片描述
判断点是否在五角星内
方法:由于五角星对应一个正六边形,一个正六边形对应一个圆。那么五角星就可以看做有一个圆心。在图上任意一点与圆心的连线记作L,判断L如果与五角星的五个坐标点连成的线段(一共五条)相交,如果相交数小于等于1,则在五角星内,如果大于1,则说明不在五角星内。
1.在五角星内
在这里插入图片描述
2.不在五角星内
在这里插入图片描述
判断点线段是否相交相交
引用:https://blog.csdn.net/HowardEmily/article/details/75451854利用叉积求解,
代码:引用上述链接。

        private static int GetIntersection(Point a, Point b, Point c, Point d, ref Point intersection)
        {

            //判断异常
            if (Math.Abs(b.X - a.Y) + Math.Abs(b.X - a.X) + Math.Abs(d.Y - c.Y) + Math.Abs(d.X - c.X) == 0)
            {
                if (c.X - a.X == 0)
                {
                    MessageBox.Show("ABCD是同一个点!");
                }
                else
                {
                    MessageBox.Show("AB是一个点,CD是一个点,且AC不同!");
                }
                return 0;
            }

            if (Math.Abs(b.Y - a.Y) + Math.Abs(b.X - a.X) == 0)
            {
                if ((a.X - d.X) * (c.Y - d.Y) - (a.Y - d.Y) * (c.X - d.X) == 0)
                {
                   // MessageBox.Show("A、B是一个点,且在CD线段上!");
                }
                else
                {
                    //MessageBox.Show("A、B是一个点,且不在CD线段上!");
                }
                return 0;
            }

            if (Math.Abs(d.Y - c.Y) + Math.Abs(d.X - c.X) == 0)
            {
                if ((d.X - b.X) * (a.Y - b.Y) - (d.Y - b.Y) * (a.X - b.X) == 0)
                {
                   // MessageBox.Show("C、D是一个点,且在AB线段上!");
                }
                else
                {
                   // MessageBox.Show("C、D是一个点,且不在AB线段上!");
                }
            }


            if ((b.Y - a.Y) * (c.X - d.X) - (b.X - a.X) * (c.Y - d.Y) == 0)
            {
                //MessageBox.Show("线段平行,无交点!");
                return 0;
            }

            intersection.X = ((b.X - a.X) * (c.X - d.X) * (c.Y - a.Y) - c.X * (b.X - a.X) * (c.Y - d.Y) + a.X * (b.Y - a.Y) * (c.X - d.X)) / ((b.Y - a.Y) * (c.X - d.X) - (b.X - a.X) * (c.Y - d.Y));
            intersection.Y = ((b.Y - a.Y) * (c.Y - d.Y) * (c.X - a.X) - c.Y * (b.Y - a.Y) * (c.X - d.X) + a.Y * (b.X - a.X) * (c.Y - d.Y)) / ((b.X - a.X) * (c.Y - d.Y) - (b.Y - a.Y) * (c.X - d.X));


            if ((intersection.X - a.X) * (intersection.X - b.X) <= 0 && (intersection.X - c.X) * (intersection.X - d.X) <= 0 && (intersection.Y - a.Y) * (intersection.Y - b.Y) <= 0 && (intersection.Y - c.Y) * (intersection.Y - d.Y) <= 0)
            {
               //MessageBox.Show("线段相交于点(" + intersection.X + "," + intersection.Y + ")!");
                return 1; //'相交
            }
            else
            {
               // MessageBox.Show("线段相交于虚交点(" + intersection.X + "," + intersection.Y + ")!");
                return 0; //'相交但不在线段上
            }
        }

求面积

 //判别面积
        public void discriminate(Five_star_struct lc,List<Arc_struct> cr) {
            int startp_x = Convert.ToInt16(lc.cenp.X - lc.R);
            int endp_x = Convert.ToInt16(lc.cenp.X + lc.R);
            int startp_y = Convert.ToInt16(lc.cenp.Y - lc.R);
            int endp_y = Convert.ToInt16(lc.cenp.Y+ lc.R);
            int f = ComputeOpter.Distinguish_up_down(cr[0].Points[0], cr[0].Points[1],cr[0].cenp,cr[1].cenp);
            int count=0;
            if (f == -1) {//圆心在同侧
                for (int i = startp_x; i < endp_x; i++)
                {
                    for (int j = startp_y; j < endp_y; j++)
                    {
                        Point testp = new Point(i, j);
                        if (ComputeOpter.getDist(testp, cr[0].cenp) < cr[0].R)
                        {
                            if (ComputeOpter.getDist(testp, cr[1].cenp) < cr[1].R)
                            {
                                int intersect_num = getcount(lc.lines, testp, lc.cenp);
                                
                                if (intersect_num <= 1)
                                {
                                    draw_point(testp);
                                    count += 1;
                                }
                            }
                        }
                    }
                }

            }
            if (f == 0)
            {//圆心在同不同侧
                for (int i = startp_x; i < endp_x; i++)
                {
                    for (int j = startp_y; j < endp_y; j++)
                    {
                        Point testp = new Point(i, j);
                        if ((ComputeOpter.getDist(testp, cr[0].cenp) < cr[0].R&& ComputeOpter.getDist(testp, cr[1].cenp) > cr[1].R )
                            || (ComputeOpter.getDist(testp, cr[0].cenp) > cr[0].R && ComputeOpter.getDist(testp, cr[1].cenp) < cr[1].R))
                        {
                            int intersect_num = getcount(lc.lines, testp,lc.cenp);
                            if (intersect_num <= 1)
                            {
                                draw_point(testp);
                                count += 1;
                            }
                        }
                    }
                }
            }
            this.textBox1.Text="面积:" + count;
        }

源码下载:https://download.csdn.net/download/qq_26654503/10938886

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值