C# & Unity:借助圆的标准方程来绘制圆

最近有了一些空闲时间,温故一下高中数学知识~


了解圆的标准方程:(x-a)²+(y-b)²=r²

(x-a)²+(y-b)²=r² 表示圆心坐标为(a,b),半径为r的圆。


个人思路:

知道了圆心坐标圆的半径,我们也可以知道圆的最左端的坐标和最右端的坐标,这里只需要知道最左端的坐标的x值最右端坐标的x值,两值之间分割得到多个点,将这些点代入方程求y值,会得到两个或一个y值,均作为二维向量数据存储下来,最后根据二维向量数据做点的连接就Ok。(知识水平表达能力有限)
请添加图片描述


C# 实现 圆的标准方程 函数:

其中需要解一元二次方程式:

 标准形式: ax²+bx+c=0(a≠0)  
 求根公式: x=[-b±√(b²-4ac)]/2a
using UnityEngine;

public class BiaoZhunFangCheng
{
    
    
    /// <summary>
    /// (x-a)²+(y-b)²=R²
    /// 已知a、b、R,给出x,求y
    /// </summary>
    /// <param name="x">x</param>
    /// <param name="center">中心点坐标(a,b)</param>
    /// <param name="r"></param>
    /// <returns>y一般有两值</returns>
    private Vector2 GetYValue(float x, Vector2 center, float r = 1f)
    {
    
    
        //求出(x-a)²
        float x_a2 = Mathf.Pow(x - center.x, 2);
        //求出R²
        float R2 = Mathf.Pow(r, 2);
        //(x-a)² 减去 R²  得到一个值
        float value = x_a2 - R2;
        //(y-b)²与这个减值的和等于 0 
        //于是得到 (y-b)² + value = 0
        //在根据平方根公式:(y-b)²就等于  y²+b²-2yb
        //于是得到 y²+b²-2yb + value = 0,其中的b和value是已知的,于是得到
        //y²-2by + (value+b²) = 0,就得到了一个一元二次方程 ax²+bx+c=0
        //其中 a = 1,b = 2b , c = (value+b²)
        //代入写好的函数得到y值
        Vector2 yValue = YiYuanErCi(a: 1, b: 2 * center.y, c: value + Mathf.Pow(center.y, 2));
        return yValue;
    }
    /// <summary>
    /// ax²+bx+c=0(a≠0)
    /// 一元二次方程求根公式:x=[-b±√(b²-4ac)]/2a
    /// </summary>
    /// <param name="a">a</param>
    /// <param name="b">b</param>
    /// <param name="c">c</param>
    /// <returns>结果一般会有两个值</returns>
    private Vector2 YiYuanErCi(float a, float b, float c)
    {
    
    
        //x=[-b±√(b²-4ac)]/2a
        float v1 = (-b + Mathf.Sqrt(Mathf.Pow(b, 2) - 4 * a * c)) / (2 * a);
        float v2 = (-b - Mathf.Sqrt(Mathf.Pow(b, 2) - 4 * a * c)) / (2 * a);
        return new Vector2(v1, v2);
    }
}


线段分割

例如:从0 ~ 1,
我想分割为三个点,就是0,0.5,1
我想分割为四个点,就是0,0.3333…,0.6666…,1
我应该怎样实现呢?

    /// <summary>
    /// 获得从某点到某点分割的点
    /// </summary>
    /// <param name="formPoint">起始点</param>
    /// <param name="toPoint">结束点</param>
    /// <param name="whatPoint">分割为几点</param>
    /// <returns>点值列表</returns>
    public List<float> GetPoints(float formPoint, float toPoint, int whatPoint)
    {
    
    
        if (whatPoint <= 2)//最少两个点
            return new List<float>() {
    
     formPoint, toPoint };
        if (formPoint == toPoint)
        {
    
    
            Debug.LogError("起始点与结束点位置相同!");
            return new List<float>() {
    
     formPoint };
        }

        //获取线段的长度
        float chaZhi = toPoint - formPoint;
        //段数比点数少一个
        //像“10米距离能种11棵树”一个到了
        int whatDuan = whatPoint - 1;
        //通过段数获取每段的长度
        float one = chaZhi / whatDuan;
        List<float> points = new List<float>();
        //首先增加第一个点
        points.Add(formPoint);
        //去掉首和尾值,只为取中间的值而循环,“这样能避免遇到例如 0.999999...这样的值后再循环执行” 的情况
        int loopCount = whatPoint - 2;
        for (int i = 1; i < loopCount + 1; i++)
        {
    
    
            points.Add(formPoint + (one * i));
        }
        //首先增加最后一个点
        points.Add(toPoint);
        return points;
    }

测试:

结合着我的思路,我尝试将圆的直径平均分为100个点,然后将这个100个点的x值代入圆的标准方程,得到两个或一个y值,从而组合得到圆上的点的坐标,绘制的结果却不尽人意。好吧…这样从端点到中心点,圆上的点是越来越紧凑的,就好像是指数函数的增长形式,好吧涉及到我的知识盲区了…
在这里插入图片描述
1000个呢?
在这里插入图片描述
好不容易写到这里了,谁能想到是这个结果(T_T),端点到中心点的规律我也不懂,抱歉浪费了你生命中的几分钟…,作为补偿,我再使用另一种方法实现一下吧


另一种方法的绘制思路是: 以圆心为起点、以半径为长度、在某角度上绘制向量,得到这个角度上向量的终点坐标,这样每隔一定度数绘制一个点,最后将点连起来就OK了
参考了大佬的文章:已知起点坐标、角度、长度求终点坐标

完整代码:

using UnityEngine;

public class CreatCircle : MonoBehaviour
{
    
    
    public GameObject obj;
    public int pointCount = 12;//圆的点数

    private void Start()
    {
    
    
        float perDu = 360f / pointCount;
        int loopIndex = pointCount - 1;

        if (obj)
        {
    
    
            for (int i = 0; i <= loopIndex; i++)
            {
    
    
                Vector2 v2 = GetEndPointByTrigonometric(i * perDu, Vector2.zero, 1f);
                Instantiate(obj, v2, Quaternion.identity);
            }
        }
    }

    /// <summary>
    /// 通过三角函数求终点坐标
    /// </summary>
    /// <param name="angle">角度</param>
    /// <param name="startPoint">起点</param>
    /// <param name="distance">距离</param>
    /// <returns>终点坐标</returns>
    public static Vector2 GetEndPointByTrigonometric(float angle, Vector2 startPoint, float distance)
    {
    
    
        Vector2 endPoint;
        //角度转弧度
        float radian = (angle * Mathf.PI) / 180;
        //计算新坐标 r 就是两者的距离
        endPoint.x = startPoint.x + distance * Mathf.Cos(radian);
        endPoint.y = startPoint.y + distance * Mathf.Sin(radian);
        return endPoint;
    }
}

12个点:
在这里插入图片描述

100个点:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_55907341/article/details/123412883