Unity实现任意两点之间画一条直线——bresenham算法(直线的处理)

Posted leixuan111

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity实现任意两点之间画一条直线——bresenham算法(直线的处理)相关的知识,希望对你有一定的参考价值。

    在家里闲着没事,在网上看到一个好玩的需求,在亮点之间画一条直线。

 听起来很简单,unity就提供了很多的API,不过大部分是以屏幕画一条线类似的方式做的。如果我们需要让部队等 一个集群排列成一条斜线呢?

 其实这也和屏幕渲染一条直线的道理是一样的。

   屏幕要画一条直线的话,其实也是在屏幕的像素坐标系里面x,y进行赋值,把连续数转换成离散数,放大看的时候,就会看到一条直线其实是一条梯子状的线。

   在实际的场景中可以把我们的地图当成一个屏幕,地图最小格子单位当成一个屏幕的像素点,这样就相当于构建了一套屏幕坐标系了

   在网上找了很多的资料,但是都说的特别复杂,我找到一篇说的比较简练清楚的。

   cnblogs.com/feiquan/archive/2018/03/04/8506283.html   

   

(此图来源于网络)   技术图片

 

 

 

     图中格子即为最小像素单位,设一条直线从p1到达p2 , p1的坐标为(0,0),作一个以p2,p1为顶点的直角三角形,可得tan ∠p1 = (p2.y - p1.y) / (p2.x - p1.x) 

         可算得  float value =   tan  ∠p1 

   通过∠p1的斜率可得出直线上某一个点的y值为是多少

   因为格子已经是最小单位了,而y的高度可能为小数,所以需要做离散化处理

   定义一个值当做校准指标,这里我们按0.5来算,每个点在经过像素单位的时候,将y小于0.5的按0来计算,并存储,抹除掉的这个值我们统计起来。  

     float slope = 0

     每计算一次点的坐标 slope = y + slope 

   当slope > 0.5的时候,y的坐标向上移一格,并清零。进行下一次的统计

   直到遍历完成

 

   注意,这里需要考虑2种情况,这条直线在某个象限里面,角度小于45°的时候是以是y轴作为偏差值处理,也就是 0< tan ∠p1 <= 1的情况,在大于45°的情况,以此类推,就要把x当做偏差值处理了,不明白的小伙伴可以想象成,如果这个角度大于45°的话,把坐标系反转一下,就是一个竖着的小于45°的角了然后直接照搬上述方式代入计算。

        代码只处理了0-90度情况,同理可以推导出 2/3/4象限的排列坐标,根据象限将x或者y取绝对值即可。

   效果如图    

<45°的效果

技术图片

 

 

 

>45°的情况

技术图片

 

 

 

   接下来上代码

 

  

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Bresenham : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        List<Vector2> mList =   GetPointList(new Vector2(0,0),new Vector2(10,128));
        for (int i = 0; i < mList.Count; i++)
        {
            GameObject cube =  GameObject.CreatePrimitive(PrimitiveType.Cube);
            Vector2 pos =  mList[i];
            cube.transform.position = new Vector3(pos.x,pos.y,0);
        }
    }
    public List<Vector2> GetPointList(Vector2 startPos,Vector2 endPos)
    {

        //构建直角三角形
        //distance_y为对边
        //distance_x为直角边
        float distance_x = endPos.x - startPos.x ; 
        float distance_y = endPos.y - startPos.y ;

        float slope_x =  distance_y / distance_x ; //tan 求斜率
        float slope_y =  distance_x/distance_y ;//当slope_x > 1  

        Vector2 pos = startPos;
        float y = startPos.y;
        float x = startPos.x ;
        int num = 0 ;
        float sumValue = 0; //累计值
        List<Vector2> posList =  new List<Vector2>();
        posList.Add(startPos);

//45度内 if (slope_x > 0 && slope_x <= 1) { for (int i = 0; i < distance_x; i++) { y = posList[num].y; x = x + 1 ; sumValue = sumValue + slope_x; if (sumValue > 0.5f) { sumValue = 0; y += 1; } num += 1; posList.Add(new Vector2(x,y)); } }else if(slope_x > 1 ) { for (int i = 0; i < distance_y; i++) { y = y + 1; x = posList[num].x ; sumValue = sumValue + slope_y; if (sumValue > 0.5f) { sumValue = 0; x += 1; } num += 1; posList.Add(new Vector2(x,y)); } } return posList; } }

 

  

以上是关于Unity实现任意两点之间画一条直线——bresenham算法(直线的处理)的主要内容,如果未能解决你的问题,请参考以下文章

matlab中如何画一条直线

需要在网页上的两点之间画一条线

如何在matplotlib中两个坐标轴之间画一条直线光标

小松教你手游开发unity实用技能在GameObject前画一条线

LQ0081 直线GCD+数学

有关matlab画直线