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;
    }
}

 

  

原文地址:https://www.cnblogs.com/leixuan111/p/12245987.html

时间: 2024-11-08 20:20:37

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

画任意两点之间的连线

function drawLine(obj1, obj2){ var oneTop = $(obj1).position().top; var oneLeft = $(obj1).position().left; var twoTop = $(obj2).position().top; var twoLeft = $(obj2).position().left; var chaWidth = Math.abs(oneLeft-twoLeft); var chaHeight = Math.abs(

百度地图api文档实现任意两点之间的最短路线规划

两个点之间的路线是使用“Marker”点连接起来的,目前还没找到改变点颜色的方法,测试过使用setStyle没有效果. <html><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta name="viewport" content="initial-scale=1.0, user-sc

Floyd-Warshall算法(求解任意两点间的最短路) 详解 + 变形 之 poj 2253 Frogger

/* 好久没有做有关图论的题了,复习一下. --------------------------------------------------------- 任意两点间的最短路(Floyd-Warshall算法) 动态规划: dp[k][i][j] := 节点i可以通过编号1,2...k的节点到达j节点的最短路径. 使用1,2...k的节点,可以分为以下两种情况来讨论: (1)i到j的最短路正好经过节点k一次 dp[k-1][i][k] + dp[k-1][k][j] (2)i到j的最短路完全

任意两点间最短距离floyd-warshall ---- POJ 2139 Six Degrees of Cowvin Bacon

floyd-warshall算法 通过dp思想 求任意两点之间最短距离 重复利用数组实现方式dist[i][j] i - j的最短距离 for(int k = 1; k <= N; k++) for (int i = 1; i <= N; i++) for (int j = 1; j <= N; j++) dist[i][j] = min(dist[i][j], dist[i][k]+dist[k][j]); 非常好实现 O(V^3) 这里贴一道刚好用到的题 http://poj.org

POJ No 2139 Six Degress of Cowvin Bacon(warshall_floyd(任意两点最短路径))

题目: http://poj.org/problem?id=2139 题解:N只牛,在一组的两只牛,分别两只之间为 “1度”,自己到自己为0度,M组牛.求,N只牛之中,两只牛之间 平均最短度数*100.模板Floyd算法,求任意两点之间最短路径. #include <iostream> #include <algorithm> #include <iomanip> using namespace std; const int maxn = 300 + 24; const

2014东北农大校赛--D.Cross the middle (任意两点最短路径 Floyd)

Cross the middle Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 36  Solved: 13 [Submit][Status][Web Board] Description n个点的图,给出任意两点之间的距离,m个询问,每次询问Mid是否可能出现在从Start到End的最短路径上. Input 第一行n,m 接下来是一个n*n的邻接矩阵,w[i][j]表示i到j的距离 接下来m行 每行start,end,mid N,m<=100,

任意两点间的最短路 Floyd及其本质

我们知道在已知起点的情况下,求到其他任何一点的最短路是用dijkstra,那么在一个有向图中,我们想知道任意两点之间的最短路,我们就可以使用floyd,而且这个算法表面看起来非常的简单,就是一个三重循环,如果这个图有N个点,那么复杂度为O(|N|3),代码如下. 1 for(int k=0;k<n;k++) 2 for(int i=0;i<n;i++) 3 for(int j=0;j<n;j++) 4 d[i][j]=min(d[i][j],d[i][k]+d[k][j]); 在复杂度这

任意两点间的最短路问题 Floyd-Warshall算法

这一算法与之前的Bellman-F=Ford算法一样,都可以判断负环 只需要检查dp [i] [j] 是负数的顶点i即可 1 // 求解任意两点间的最短路径问题 2 // Floyed-Warshall算法 3 // 复杂度O(N^3),N为顶点数 4 5 #include <cstdio> 6 #include <iostream> 7 8 using namespace std; 9 // 用dp的思路来求解 10 // dp[k][i][j]:从i到j,只利用前K个节点的最短

蓝桥--危险系数(求两点之间的割点个数)

历届试题 危险系数 时间限制:1.0s   内存限制:256.0MB 问题描述 抗日战争时期,冀中平原的地道战曾发挥重要作用. 地道的多个站点间有通道连接,形成了庞大的网络.但也有隐患,当敌人发现了某个站点后,其它站点间可能因此会失去联系. 我们来定义一个危险系数DF(x,y): 对于两个站点x和y (x != y), 如果能找到一个站点z,当z被敌人破坏后,x和y不连通,那么我们称z为关于x,y的关键点.相应的,对于任意一对站点x和y,危险系数DF(x,y)就表示为这两点之间的关键点个数. 本