注意!
本文被第1次更新,可能存在后续更新

直线画法

直线的斜截式方程

在二维空间下,一条直线的方程可以被描述为若干种形式,其中比较常见的一种是斜截式方程:
\[y=kx+b\]
其中\(k\)称为直线的斜率,反映直线的倾斜情况,假定直线与水平面成角\(\theta\)(右侧角),则\(k\)与\(\theta\)存在如下关系:
\[k=\tan\theta\]
而\(b\)称为截距,反映该直线在二维空间中的位置

数字微分分析(DDA)

可对直线\(y=kx+b\)进行微分处理得到:
\[\frac{\mathrm{d}y}{\mathrm{d}x}=k=\tan \theta\]
对于缓直线(\(|k|\le1\))的时候,可考虑将直线考虑为X型直线(水平走向),这个时候可取x方向的单位点作为取样点计算y的值:
\[y=kx+b(x\in\mathbb{Z})\]
对于给定的线段\((x_1,y_1)\rightarrow(x_2,y_2)\),这里考虑取样值的走向\(\delta x\)为:
\[\delta x=\mathrm{sgn} (x_2-x_1)\]
这确定了,若曲线走向从右向左的时候,这条直线也是以这个走向被绘制出来而不至于南辕北辙。

缓直线之所以考虑成X走向,是因为对于每一个\(x+\delta x\),在\(\delta x =1\)的时候,其得到的\(\delta y\)总小于1,而对应地,对于陡直线(\(|k|\ge1\))则相应地令\(\delta y=1\),则对应于\(y+\delta y\)得到的\(\delta x\)也总小于1,这样也就把陡曲线考虑为Y向曲线得到的误差是在可接受范围之内的(当差值\(\delta>1\)的时候,轴向上相邻两点将得到两个不邻接的像素点亮,这将打破直线的连续性并使得直线观感变差)。

若结果为小数,则遵循四舍五入原则(加0.5后再取整)

也可考虑银行家舍入法(Banker 's Rounding)进行舍入

极端情形

完全水平(k=0)

这种情况下,线段认为X型这种情况下y只能得到b

完全垂直(k=∞)

这种情况下直线不存在斜截式方程、斜率式方程(因为斜率和截距都不存在),斜率被认为无穷大(正无穷或负无穷),这种情况下显然被认为Y型曲线

方向通用情形

一般地,如果绘制一条线段,我们更多的会考虑这种绘制方式:

给定两点A和B,然后通过两点可以确定一条直线以及这条线段。

其中,给定两点A和B即给定这两点的坐标,这两种坐标可以被表示为:
\[P_A(x_a,y_a),P_B(x_b,y_b)\]
这里没有体现出一个至关重要的信息:斜率,但这一信息可以通过这两个坐标推算得出,由于给定两点有先后顺序(这个顺序将决定绘制的走向),因此这两点可认为构成了向量
\[\vec{v}=P_B-P_A=(x_b-x_a,y_b-y_a)=(\Delta x,\Delta y)\]
如果考虑把这个向量投射到复平面上,可以得到:
\[z=\Delta x+i\Delta y\]
而斜率\(k\)的反正切即为\(z\)的辐角
\[\arg z=\arctan \frac{\Delta y}{\Delta x}=\arctan k\]
但需注意,这里\(\Delta x\)可能为0,同样地,\(\Delta y\)也有类似的可能,当仅有\(\Delta y=0\)的时候,有\(k=0\),然而,其他的情况要复杂得多,若仅有\(\Delta x=0\),则直线是铅直的,也就是斜率为∞,而两个同时为0的时候则上式直接变为未定式(此时两点重合,实际上得到的是\(\vec{0}\),而这个向量是任意方向的)。
但所幸,一般的程序数学库中提供了函数atan2可以很好的解决这个问题,atan2的提出主要是出于两种目的:

  1. 解决斜率为∞的情形
  2. 降低当x或y中任意一个值过大而导致的运算误差(这实际上无法规避)

atan2取得两个参数xy作为输入并返回这个向量正确的方位角\(\theta\)(当然,实际上是弧度形式)。尽管它并不得到斜率(因为其本质还是反正切,正好把\(\theta\)从正切中取出),但是直接通过方位角,我们仍然可以确定一些事情:
\[|k|>1\Rightarrow \pm \frac{\pi}{4} < \theta < \pm \frac{3\pi}{4}\]
\[|k|<1\Rightarrow -\frac{\pi}{4} < \theta < \frac{\pi}{4} \vee \frac{3\pi}{4} < \theta < \frac{5\pi}{4}\left(-\frac{3\pi}{4}\right)\]

这里还需考虑,当xy都为0的时候,这可能导致atan2无法正常工作,因此这个情况需要预先代替atan2进行处理。

光栅通用情形(注意这里着重讨论端点不落在整数位上)

由于在屏幕上是离散空间,因此绘制需要光栅化,因此,当结果存在小数时,则应当进行适当的舍入操作,当然,上文提及一种策略是四舍五入策略。

但是这仅仅是对于中间确定点亮像素的情形,这里仍然需要考虑:如果\(P_A\)和\(P_B\)的坐标就很不老实该怎么办??

如果此时提前对\(P_A\)和\(P_B\)做光栅化(坐标取整)则是否会存在潜在的问题??

这里将这两点的坐标做如下考虑:
\[x_a=I_{xa}+F_{xa}\]
\[x_b=I_{xb}+F_{xb}\]
\[\cdots\]
\[I\in\mathbb{Z},|F|<1\]

以人话的方式说,这里面\(I\)表示整数部分,\(F\)表示小数部分。
这里只考虑有斜率的情形,斜率可以表述为:
\[
k=\frac{(I_{yb}+F_{yb})-(I_{ya}+F_{ya})}{(I_{xb}+F_{xb})-(I_{xa}+F_{xa})}
\]

假设\(F_{yb}>0.5,F_{ya}<0.5,F_{xb}<0.5,F_{xa}>0.5\),则
\[k'=\frac{(I_{yb}+1)-I_{ya}}{I_{xb}-(I_{xa}+1)}\]

此时造成误差:
\[\Delta k=k-k'=\frac{-2af+ag+ah-a+2be-bg-bh-b-ce+cf+c-de+df+d-e-f+g+h}{e^2-eg-eh-e-f^2+fg+fh-f+g+h}\]
\[a=I_{yb},b=F_{yb}\dots k=\frac{a+b-c-d}{e+f-g-h}\]
上式计算过于复杂,这里定性分析一下,考虑到小数部分都很小,因此两个F相乘的项忽略不计,I乘以F的项统一认为是同一阶,最后剩下的部分是:
\[k\approx\frac{ag-a-b-ce+c+d-e-f+g+h}{e^2-eg-e-f+g+h}\]
其中认为所有I乘以I也是同阶的。所有的I和所有的F分别内部彼此同阶,则上式再次化简得到:
\[k\approx\frac{\Delta I-\Delta F}{0}\]
好吧我承认这是一个非常敷衍了事的证明方法(如果你看着不爽,你完全可以认为这™就是一团废话然后自己证明一番,但我会认为你十有八九会面对一堆abcd无从下手,当然也许我方向就有问题,你完全可以认为这个分析过程是错的),因为这里把很多东西混淆掉了并且忽略了众多的情况,这是一个很粗糙的分析,但是这个提示我们一个信号:分子阶次高于分母。

这提示了一个问题,当两个点离得非常远的时候如果提前把两个点光栅化的话,斜率可能会发生较为显著的变化(当然,真正拿图画出来的时候可能更直观,但老实说这个误差从某种程度上来说差角确实不算大,但斜率确实是有明显的变化),当斜率发生变化的时候最主要导致的问题就是

我™又得重新确定点了!!因为线偏了!!

当然,更糟糕的是,当某一点沿着线段移动到另一点的时候,你将看到这个线段会鬼畜地抖动(因为每次运动一段距离之后可能变成整数点也可能不会变但误差形式可能又会发生变化然后线的偏离程度可能也会发生变化),当然这个幅度并不会很大,但是问题在于如果线段越长这种效应恐怕是越明显的,最重要的是,无论幅度大小与否这根本就不应当发生,但是,我们仍然有方法去解决这个问题,其实很简单,在对端点进行光栅化之前,先把斜率求出来。

对线影响最强烈的莫过于斜率!!!
线越长,影响越明显

方向对于一条直线来说太重要了,考虑一下当你正拿着一把楞次(会爆炸的弓箭)瞄准一个正在蹲坑的Grineer,然后在发射的时候你的手抖那么1度,命中了在隔壁扫描结合目标的队友,他在目标的10米以外的位置……
确定了方向,就意味着这条直线不会走向一个很奇怪的位置,在这个算法中才不至于产生这种效应。

但如果仅仅是这样的话,这条线存在可能比预期低那么1个像素的可能,当然这也是非常不明显的,而且实际上也只有几个点会发生这种变化,这个实际上也不会造成什么抖动的效应,不过本着力求完美的原则,而且这个过程并不会浪费太多的时间,这里还是考虑把点多少修正一下,这个做法也同样很简单,那就是并非直接对端点进行舍入,而是顺着端点推到最近的整数位点计算它对应的y值。

To be continued...

[未完结]数字微分分析法的直线绘制(DDA)的更多相关文章

  1. 黑盒测试用例设计方法&理论结合实际 -> 边界值分析法

    一. 概念 边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法.通常边界值分析法是作为对等价类划分法的补充,这种情况下,其测试用例来自等价类的边界. 二. 边界值分析法的应用 根据大量的测 ...

  2. 编译原理(六)自底向上分析之LR分析法

    自底向上分析之LR分析法 说明:以老师PPT为标准,借鉴部分教材内容,AlvinZH学习笔记. 基本概念 1. LR分析:从左到右扫描(L)自底向上进行规约(R),是规范规约,也即最右推导(规范推导) ...

  3. 《编译原理》LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析

    <编译原理>LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析 笔记 直接做题是有一些特定步骤,有技巧.但也必须先了解一些基本概念,本篇会通过例题形式解释概念,会容易理解和记忆,以 ...

  4. 从Elo Rating System谈到层次分析法

    1. Elo Rating System Elo Rating System对于很多人来说比较陌生,根据wikipedia上的解释:Elo评分系统是一种用于计算对抗比赛(例如象棋对弈)中对手双方技能水 ...

  5. Procrustes Analysis普氏分析法

    选取N幅同类目标物体的二维图像,并用上一篇博文的方法标注轮廓点,这样就得到训练样本集: 由于图像中目标物体的形状和位置存在较大偏差,因此所得到的数据并不具有仿射不变性,需要对其进行归一化处理.这里采用 ...

  6. AX中四种库存ABC分析法原理研究

    库存ABC分类,简单的说就是抓大放小,是为了让我们抓住重点,用最大精力来管理最重要的物料,而对于不太重要的物料则可以用较少的精力进行管理.它和我们平常说的八二法则有异曲同工之妙. 既然要应用库存ABC ...

  7. 帕累托分析法(Pareto Analysis)(柏拉图分析)

    帕累托分析法(Pareto Analysis)(柏拉图分析) ABC分类法是由意大利经济学家帕雷托首创的.1879年,帕累托研究个人收入的分布状态图是地,发现少数人收入占全部人口收入的大部分,而多数人 ...

  8. SWOT分析法

    SWOT(Strengths Weakness Opportunity Threats)分析法,又称为态势分析法或优劣势分析法,用来确定企业自身的竞争优势(strength).竞争劣势(weaknes ...

  9. 5W1H分析法

    "5W1H分析法"也叫"六何分析法",它是一种分析方法也可以说是一种创造技法.是对选定的项目.工序和操作,都要从原因(Why).对象(What).地点(Wher ...

随机推荐

  1. bzoj 4295 [PA2015]Hazard 贪心,暴力

    [PA2015]Hazard Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 69  Solved: 19[Submit][Status][Discus ...

  2. 解决vue项目route使用history模式,tomcat部署刷新url 404问题

    在webapps/项目名 创建WEB-INF ,创建web.xml文件 文件内容如下: <?xml version="1.0" encoding="UTF-8&qu ...

  3. JVM指令详解(下)

    九.自增减指令 该指令用于对本地(局部)变量进行自增减操作.该指令第一参数为本地变量的编号,第二个参数为自增减的数量. 比如对于代码:                 int d=10; d++; d ...

  4. mongodb window安装学习

    https://blog.csdn.net/u011692780/article/details/81223525 教程:http://www.runoob.com/mongodb/mongodb-t ...

  5. hdu 4504(动态规划)

    威威猫系列故事——篮球梦 Time Limit: 300/100 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total ...

  6. LeetCode OJ--Add Two Numbers

    http://oj.leetcode.com/problems/add-two-numbers/ 将用链表表示的两个数相加,(2 -> 4 -> 3) + (5 -> 6 -> ...

  7. AC日记——花店橱窗布置 codevs 1028

    题目描述 Description 假设以最美观的方式布置花店的橱窗,有F束花,V个花瓶,我们用美学值(一个整数)表示每束花放入每个花瓶所产生的美学效果.为了取得最佳的美学效果,必须使花的摆放取得最大的 ...

  8. vue生命周期回调方法

    最近在用vue开发一个商品列表页,因需要根据请求回的字段是否有内容来显示隐藏该字段, 但因为vue异步加载导致显示隐藏方法不起作业(主要是判断条件取不到页面渲染内容),围观了vue生命周期后发现upd ...

  9. python 中各种数据类型的排序问题

    list #按照list的第二键值排序 disP2P = [[1,2,3],[2,3,4],[4,5,6]] disP2P = sorted(disP2P,key = lambda x:x[2]) s ...

  10. 洛谷—— P2117 小Z的矩阵

    https://www.luogu.org/problemnew/show/2117 题目描述 小Z最近迷上了矩阵,他定义了一个对于一种特殊矩阵的特征函数G.对于N*N的矩阵A,A的所有元素均为0或1 ...