计算机制图——三点画弧

三点画弧(C#)

全局变量

  • 静态存储
	Graphics g;
	List<Point> arc = new List<Point>();

相关事件

  • 鼠标点击事件
    private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
    {
        // 直接在picturebox上点就可以,点够3个就画弧
        // 可重复点,3个一组
        Point arcPoint = new Point(e.X, e.Y);
        arc.Add(arcPoint);
        if (arc.Count == 3)
            paintArc(arc);  // 自定义函数,见下
    }

相关函数

  • paintArc
    private void paintArc(List<Point> arc)
    {
        Pen p = new Pen(Color.Black, 1);

        // 将点的每个点都显示在窗体上
        for (int i = 0; i < 3; i++)
            g.DrawEllipse(p, arc[i].X, arc[i].Y, 2, 2);

        // ABCDEF为求圆心的辅助变量
        int A = arc[0].X - arc[1].X;
        int B = arc[0].Y - arc[1].Y;
        int C = arc[0].X - arc[2].X;
        int D = arc[0].Y - arc[2].Y;
        double E = (arc[0].X * arc[0].X - arc[1].X * arc[1].X + arc[0].Y * arc[0].Y - arc[1].Y * arc[1].Y) / 2;
        double F = (arc[0].X * arc[0].X - arc[2].X * arc[2].X + arc[0].Y * arc[0].Y - arc[2].Y * arc[2].Y) / 2;

        // 利用克拉默法则求圆心
        double X = -(D * E - B * F) / (B * C - A * D);
        double Y = -(A * F - C * E) / (B * C - A * D);

        // 将圆心显示在窗体上
        Point center = new Point(Convert.ToInt16(X), Convert.ToInt16(Y));
        g.DrawEllipse(p, center.X, center.Y, 2, 2);

        // 两点间距离求半径
        double R = Math.Sqrt((arc[0].X - X) * (arc[0].X - X) + (arc[0].Y - Y) * (arc[0].Y - Y));

        // 求OX与O1, O3间的夹角,顺时针
        // 单纯的cos无法判断,需要借助sin
        // 且注意y轴指向下
        double cosValue1 = (arc[0].X - X) / R;
        double sinValue1 = (arc[0].Y - Y) / R;
        double angle1 = Math.Acos(cosValue1)/Math.PI*180;
        if (sinValue1 < 0)
            angle1 = 360 - angle1;

        double cosValue2 = (arc[2].X - X) / R;
        double sinValue2 = (arc[2].Y - Y) / R;
        double angle3 = Math.Acos(cosValue2) / Math.PI * 180;
        if (sinValue2 < 0)
            angle3 = 360 - angle3;

        // 根据矢量叉积判断1、2、3点为顺时针还是逆时针
        // mode=1为顺时针
        int mode = (arc[1].X - arc[0].X) * (arc[2].Y - arc[1].Y) - (arc[1].Y - arc[0].Y) * (arc[2].X - arc[1].X) > 0 ? 1 : 0;

        // 分了四种情况:
        // 1、2、3顺时针绘制,角1大于角3 or 角1小于角3
        // 1、2、3逆时针绘制,角1大于角3 or 角1小于角3
        if (mode == 1)
            if (angle3 > angle1)
                g.DrawArc(p, (int)(X - R), (int)(Y - R), (int)(2 * R), (int)(2 * R), (float)angle1, (float)(angle3 - angle1));
            else
                g.DrawArc(p, (int)(X - R), (int)(Y - R), (int)(2 * R), (int)(2 * R), (float)angle1, (float)(360 - (angle1 - angle3)));
        else
            if (angle3 > angle1)
                g.DrawArc(p, (int)(X - R), (int)(Y - R), (int)(2 * R), (int)(2 * R), (float)angle1, (float)(angle3 - angle1 - 360));
            else
                g.DrawArc(p, (int)(X - R), (int)(Y - R), (int)(2 * R), (int)(2 * R), (float)angle1, (float)(angle3 - angle1));

        // 清除掉point链表,以边存储下一组圆弧
        arc.Clear();
    }

运行结果

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值