Files
blog/posts/7207243b/index.html

572 lines
82 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>OpenGL-直线的扫描转换 | Bi's Blog</title><meta name="author" content="biss"><meta name="copyright" content="biss"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="这篇文章来介绍直线扫描转换算法 DDA数值微分线段算法算法简介数值微分法即DDA法(Digital Differential Analyzer),是一种基于微分方程来生成直线的方法。在计算机图形学中,并没有线段的概念,而是一个个像素点组成了线段。 DDA法生成线段的步骤一般如下 有了起始点($x_1y_1$)和终点($x_ny_n$ $$\Delta x =|x_n-x_1|">
<meta property="og:type" content="article">
<meta property="og:title" content="OpenGL-直线的扫描转换">
<meta property="og:url" content="https://blog.biss.click/posts/7207243b/index.html">
<meta property="og:site_name" content="Bi's Blog">
<meta property="og:description" content="这篇文章来介绍直线扫描转换算法 DDA数值微分线段算法算法简介数值微分法即DDA法(Digital Differential Analyzer),是一种基于微分方程来生成直线的方法。在计算机图形学中,并没有线段的概念,而是一个个像素点组成了线段。 DDA法生成线段的步骤一般如下 有了起始点($x_1y_1$)和终点($x_ny_n$ $$\Delta x =|x_n-x_1|">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://pic.biss.click/image/c5457adc-214c-4a18-9aa6-43fbc0bfc2f4.webp">
<meta property="article:published_time" content="2026-04-11T11:01:02.000Z">
<meta property="article:modified_time" content="2026-04-11T11:56:17.367Z">
<meta property="article:author" content="biss">
<meta property="article:tag" content="OpenGL">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://pic.biss.click/image/c5457adc-214c-4a18-9aa6-43fbc0bfc2f4.webp"><script type="application/ld+json">{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "OpenGL-直线的扫描转换",
"url": "https://blog.biss.click/posts/7207243b/",
"image": "https://pic.biss.click/image/c5457adc-214c-4a18-9aa6-43fbc0bfc2f4.webp",
"datePublished": "2026-04-11T11:01:02.000Z",
"dateModified": "2026-04-11T11:56:17.367Z",
"author": [
{
"@type": "Person",
"name": "biss",
"url": "https://blog.biss.click"
}
]
}</script><link rel="shortcut icon" href="/images/Bi.ico"><link rel="canonical" href="https://blog.biss.click/posts/7207243b/index.html"><link rel="preconnect" href="//unpkg.com"><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://unpkg.com/@fortawesome/fontawesome-free/css/all.min.css"><link rel="stylesheet" href="https://unpkg.com/node-snackbar/dist/snackbar.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://unpkg.com/@fancyapps/ui/dist/fancybox/fancybox.css" media="print" onload="this.media='all'"><script>
(() => {
const saveToLocal = {
set: (key, value, ttl) => {
if (!ttl) return
const expiry = Date.now() + ttl * 86400000
localStorage.setItem(key, JSON.stringify({ value, expiry }))
},
get: key => {
const itemStr = localStorage.getItem(key)
if (!itemStr) return undefined
const { value, expiry } = JSON.parse(itemStr)
if (Date.now() > expiry) {
localStorage.removeItem(key)
return undefined
}
return value
}
}
window.btf = {
saveToLocal,
getScript: (url, attr = {}) => new Promise((resolve, reject) => {
const script = document.createElement('script')
script.src = url
script.async = true
Object.entries(attr).forEach(([key, val]) => script.setAttribute(key, val))
script.onload = script.onreadystatechange = () => {
if (!script.readyState || /loaded|complete/.test(script.readyState)) resolve()
}
script.onerror = reject
document.head.appendChild(script)
}),
getCSS: (url, id) => new Promise((resolve, reject) => {
const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = url
if (id) link.id = id
link.onload = link.onreadystatechange = () => {
if (!link.readyState || /loaded|complete/.test(link.readyState)) resolve()
}
link.onerror = reject
document.head.appendChild(link)
}),
addGlobalFn: (key, fn, name = false, parent = window) => {
if (!true && key.startsWith('pjax')) return
const globalFn = parent.globalFn || {}
globalFn[key] = globalFn[key] || {}
globalFn[key][name || Object.keys(globalFn[key]).length] = fn
parent.globalFn = globalFn
}
}
const activateDarkMode = () => {
document.documentElement.setAttribute('data-theme', 'dark')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
}
}
const activateLightMode = () => {
document.documentElement.setAttribute('data-theme', 'light')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
}
}
btf.activateDarkMode = activateDarkMode
btf.activateLightMode = activateLightMode
const theme = saveToLocal.get('theme')
theme === 'dark' ? activateDarkMode() : theme === 'light' ? activateLightMode() : null
const asideStatus = saveToLocal.get('aside-status')
if (asideStatus !== undefined) {
document.documentElement.classList.toggle('hide-aside', asideStatus === 'hide')
}
const detectApple = () => {
if (/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)) {
document.documentElement.classList.add('apple')
}
}
detectApple()
})()
</script><script>const GLOBAL_CONFIG = {
root: '/',
algolia: undefined,
localSearch: undefined,
translate: {"defaultEncoding":2,"translateDelay":0,"msgToTraditionalChinese":"繁","msgToSimplifiedChinese":"簡"},
highlight: {"plugin":"highlight.js","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":200,"highlightFullpage":true,"highlightMacStyle":false},
copy: {
success: '复制成功',
error: '复制失败',
noSupport: '浏览器不支持'
},
relativeDate: {
homepage: false,
post: false
},
runtime: '',
dateSuffix: {
just: '刚刚',
min: '分钟前',
hour: '小时前',
day: '天前',
month: '个月前'
},
copyright: undefined,
lightbox: 'fancybox',
Snackbar: {"chs_to_cht":"已切换为繁体中文","cht_to_chs":"已切换为简体中文","day_to_night":"已切换为深色模式","night_to_day":"已切换为浅色模式","bgLight":"#49b1f5","bgDark":"#1f1f1f","position":"bottom-left"},
infinitegrid: {
js: 'https://unpkg.com/@egjs/infinitegrid/dist/infinitegrid.min.js',
buttonText: '加载更多'
},
isPhotoFigcaption: false,
islazyloadPlugin: false,
isAnchor: false,
percent: {
toc: true,
rightside: true,
},
autoDarkmode: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
title: 'OpenGL-直线的扫描转换',
isHighlightShrink: false,
isToc: true,
pageType: 'post'
}</script><link rel="stylesheet" href="/css/shuoshuo.css"><link rel="stylesheet" href="/css/shuoshuoshouye.css"><link rel="stylesheet" href="/css/nav.css"><link rel="stylesheet" href="/css/style.css"><link rel="stylesheet" href="/css/poem.css"><link rel="stylesheet" href="/css/swiper.css"><link rel="stylesheet" href="https://cdn.jsdmirror.com/npm/instantsearch.css/themes/reset-min.css"><link rel="stylesheet" href="https://cdn.jsdmirror.com/gh/bishshi/welcomemessage/welcome.css"><link rel="stylesheet" href="https://cdn.jsdmirror.com/gh/bishshi/sidecalendar/calendar.css"><link rel="stylesheet" href="https://cdn.jsdmirror.com/gh/bishshi/rightmenu/rightmenu.css"><link rel="stylesheet" href="https://cdn.jsdmirror.com/gh/bishshi/webfont/font.css"><link rel="stylesheet" href="https://cdn.jsdmirror.com/npm/aplayer/dist/APlayer.min.css" media="all" onload="this.media=&quot;all&quot;"><!-- hexo injector head_end start --><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/5.4.5/css/swiper.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn1.tianli0.top/npm/hexo-butterfly-swiper/lib/swiperstyle.css" media="print" onload="this.media='all'"><!-- hexo injector head_end end --><style type="text/css">
.spoiler {
display: inline;
}
p.spoiler {
display: flex;
}
.spoiler a {
pointer-events: none;
}
.spoiler-blur, .spoiler-blur > * {
transition: text-shadow .5s ease;
}
.spoiler .spoiler-blur, .spoiler .spoiler-blur > * {
color: rgba(0, 0, 0, 0);
background-color: rgba(0, 0, 0, 0);
text-shadow: 0 0 10px grey;
cursor: pointer;
}
.spoiler .spoiler-blur:hover, .spoiler .spoiler-blur:hover > * {
text-shadow: 0 0 5px grey;
}
.spoiler-box, .spoiler-box > * {
transition: color .5s ease,
background-color .5s ease;
}
.spoiler .spoiler-box, .spoiler .spoiler-box > * {
color: black;
background-color: black;
text-shadow: none;
}</style><meta name="generator" content="Hexo 8.1.1"><link rel="alternate" href="/atom.xml" title="Bi's Blog" type="application/atom+xml">
</head><body><div class="bg-animation" id="web_bg" style="background-image: url(/images/background.png);"></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img text-center"><img src="https://free.picui.cn/free/2025/08/10/689845496a283.png" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"></div><div class="site-data text-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">38</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">12</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">6</div></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 存档</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/shuoshuo/"><i class="fa-fw fa-regular fa-comment"></i><span> 说说</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg fixed" id="page-header" style="background-image: url(https://pic.biss.click/image/c5457adc-214c-4a18-9aa6-43fbc0bfc2f4.webp);"><nav id="nav"><span id="blog-info"><div id="ls-menu-container"><i class="fas fa-fingerprint"></i><div id="ls-menu-panel"><div class="ls-section"><div class="ls-title">😀 个人网站</div><div class="ls-grid"><a href="/"><i class="fas fa-rss"></i> 个人博客</a><a target="_blank" rel="noopener" href="https://github.com/bishshi"><i class="fab fa-github"></i> Github</a><a target="_blank" rel="noopener" href="https://space.bilibili.com/20665809"><i class="fab fa-bilibili"></i> 哔哩哔哩</a></div></div><div class="ls-section"><div class="ls-title">😎 常用服务</div><div class="ls-grid"><a target="_blank" rel="noopener" href="https://git.biss.click/biss"><i class="fas fa-code"></i> 代码仓库</a><a target="_blank" rel="noopener" href="https://mm.biss.click"><i class="fas fa-pen-nib"></i> 日常说说</a><a target="_blank" rel="noopener" href="https://pic.biss.click"><i class="fas fa-image"></i> 图床</a><a target="_blank" rel="noopener" href="https://git.biss.click"><i class="fas fa-code-branch"></i> 代码仓库</a></div></div><div class="ls-section"><div class="ls-title">🛸 实用工具</div><div class="ls-grid"><a target="_blank" rel="noopener" href="https://cover.biss.click"><i class="fas fa-palette"></i> 封面设计</a><a target="_blank" rel="noopener" href="https://doc.biss.click"><i class="fas fa-file"></i> 文档服务</a><a target="_blank" rel="noopener" href="https://status.biss.click"><i class="fas fa-server"></i> 服务监测</a><a target="_blank" rel="noopener" href="https://typesense.biss.click"><i class="fas fa-magnifying-glass"></i> 搜索后端</a></div></div></div></div><a class="nav-site-title" href="/"><span class="site-name">Bi's Blog</span></a></span><a class="nav-page-title" href="javascript:void(0);" onclick="btf.scrollToDest(0, 500)"><span class="site-name">OpenGL-直线的扫描转换</span></a><div id="nav-right"><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 存档</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/shuoshuo/"><i class="fa-fw fa-regular fa-comment"></i><span> 说说</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div></div><div id="random-post-button"><a class="site-page social-icon" id="random-post-link" href="javascript:void(0);" onclick="randomPost()"><i class="fas fa-solid fa-shuffle"></i></a></div><div id="search-button"><a class="site-page social-icon search-typesense-trigger"><i class="fas fa-search fa-fw"></i></a></div><div id="toggle-menu"><span class="site-page"><i class="fas fa-bars fa-fw"></i></span></div></div></nav><div id="post-info"><h1 class="post-title">OpenGL-直线的扫描转换</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2026-04-11T11:01:02.000Z" title="发表于 2026-04-11 19:01:02">2026-04-11</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2026-04-11T11:56:17.367Z" title="更新于 2026-04-11 19:56:17">2026-04-11</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/technology/">技术</a><i class="fas fa-angle-right post-meta-separator"></i><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/technology/learning/">学习</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">总字数:</span><span class="word-count">2k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>8分钟</span></span><span class="post-meta-separator">|</span><span id="" data-flag-title=""><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">浏览量:</span><span id="twikoo_visitors"><i class="fa-solid fa-spinner fa-spin"></i></span></span><span class="post-meta-separator">|</span><span class="post-meta-commentcount"><i class="far fa-comments fa-fw post-meta-icon"></i><span class="post-meta-label">评论数:</span><a href="/posts/7207243b/#post-comment"><span id="twikoo-count"><i class="fa-solid fa-spinner fa-spin"></i></span></a></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="container post-content" id="article-container"><div class="ai-summary"><div class="ai-explanation" style="display: block;" data-summary="这篇文章介绍了三种直线扫描转换算法DDA算法、中点画线算法和Bresenham算法。 DDA算法通过计算直线起点和终点的坐标差值来确定步数和增量依次绘制直线上的点。算法实现简单适用于任意直线但精度较低。 中点画线算法仅适用于斜率为0或1的直线通过计算中点和斜率来确定直线上的像素点效率较高。 Bresenham算法根据直线的斜率和误差项来确定像素点的位置适用于任意直线且精度高但实现稍复杂。">AI正在绞尽脑汁想思路ING···</div><div class="ai-title"> <div class="ai-title-left"> <i class="fa-brands fa-slack"></i><div class="ai-title-text">BiのAI摘要</div></div><div class="ai-tag" id="ai-tag">HunYuan-Lite</div></div></div><div id="post-outdate-notice" data="{&quot;limitDay&quot;:365,&quot;messagePrev&quot;:&quot;It has been&quot;,&quot;messageNext&quot;:&quot;days since the last update, the content of the article may be outdated.&quot;,&quot;postUpdate&quot;:&quot;2026-04-11 19:56:17&quot;}" hidden=""></div><p>这篇文章来介绍直线扫描转换算法</p>
<h1 id="DDA数值微分线段算法"><a href="#DDA数值微分线段算法" class="headerlink" title="DDA数值微分线段算法"></a>DDA数值微分线段算法</h1><h2 id="算法简介"><a href="#算法简介" class="headerlink" title="算法简介"></a>算法简介</h2><p>数值微分法即DDA法(Digital Differential Analyzer),是一种基于微分方程来生成直线的方法。在计算机图形学中,并没有线段的概念,而是一个个像素点组成了线段。</p>
<p>DDA法生成线段的步骤一般如下</p>
<ol>
<li>有了起始点($x_1y_1$)和终点($x_ny_n$</li>
<li>$$\Delta x =|x_n-x_1|, \Delta y=|y_n-y_1|$$</li>
<li>比较$\Delta x$和$\Delta y$的大小;<br> steps=$\Delta x$和$\Delta y$中较大者;</li>
<li>$$step_x=\frac{\Delta x}{steps}step_y=\frac{\Delta y}{steps}$$</li>
</ol>
<h2 id="算法实现"><a href="#算法实现" class="headerlink" title="算法实现"></a>算法实现</h2><p>DDA算法实现如下</p>
<figure class="highlight cpp"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;cmath&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;GL/glut.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 窗口宽度和高度</span></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> WIDTH = <span class="number">640</span>;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> HEIGHT = <span class="number">480</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">drawDDALine</span><span class="params">(<span class="type">int</span> x1, <span class="type">int</span> y1, <span class="type">int</span> x2, <span class="type">int</span> y2)</span> </span>{</span><br><span class="line"> <span class="type">float</span> x = x1;</span><br><span class="line"> <span class="type">float</span> y = y1;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 计算差值</span></span><br><span class="line"> <span class="type">int</span> dx = x2 - x1;</span><br><span class="line"> <span class="type">int</span> dy = y2 - y1;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 确定步数,取 dx 和 dy 中绝对值较大的那个</span></span><br><span class="line"> <span class="type">int</span> steps = std::<span class="built_in">abs</span>(dx) &gt; std::<span class="built_in">abs</span>(dy) ? std::<span class="built_in">abs</span>(dx) : std::<span class="built_in">abs</span>(dy); <span class="comment">//三元表达式</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// 计算每一步的增量</span></span><br><span class="line"> <span class="type">float</span> xIncrement = (<span class="type">float</span>)dx / steps;</span><br><span class="line"> <span class="type">float</span> yIncrement = (<span class="type">float</span>)dy / steps;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 开始绘制点</span></span><br><span class="line"> <span class="built_in">glBegin</span>(GL_POINTS);</span><br><span class="line"> <span class="built_in">glVertex2i</span>((<span class="type">int</span>)<span class="built_in">round</span>(x), (<span class="type">int</span>)<span class="built_in">round</span>(y)); <span class="comment">// 绘制起点</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> k = <span class="number">0</span>; k &lt; steps; k++) {</span><br><span class="line"> x += xIncrement;</span><br><span class="line"> y += yIncrement;</span><br><span class="line"> <span class="comment">// 将浮点坐标四舍五入取整转换为整数像素坐标</span></span><br><span class="line"> std::cout &lt;&lt; (<span class="type">int</span>)<span class="built_in">round</span>(x) &lt;&lt; <span class="string">", "</span> &lt;&lt; (<span class="type">int</span>)<span class="built_in">round</span>(y)&lt;&lt;<span class="string">"\n"</span>;</span><br><span class="line"> <span class="built_in">glVertex2i</span>((<span class="type">int</span>)<span class="built_in">round</span>(x), (<span class="type">int</span>)<span class="built_in">round</span>(y));</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">glEnd</span>();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 显示回调函数</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">display</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">drawDDALine</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">50</span>, <span class="number">20</span>);</span><br><span class="line"> <span class="built_in">glFlush</span>();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 初始化 OpenGL 设置</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">init</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="comment">// 设置背景颜色为白色</span></span><br><span class="line"> <span class="built_in">glClearColor</span>(<span class="number">1.0f</span>, <span class="number">1.0f</span>, <span class="number">1.0f</span>, <span class="number">1.0f</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 设置投影矩阵为 2D 正交投影</span></span><br><span class="line"> <span class="built_in">glMatrixMode</span>(GL_PROJECTION);</span><br><span class="line"> <span class="built_in">glLoadIdentity</span>();</span><br><span class="line"> <span class="comment">// 定义可视区域,左下角(0,0),右上角(WIDTH, HEIGHT)</span></span><br><span class="line"> <span class="built_in">gluOrtho2D</span>(<span class="number">0.0</span>, WIDTH, <span class="number">0.0</span>, HEIGHT);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">(<span class="type">int</span> argc, <span class="type">char</span>** argv)</span> </span>{</span><br><span class="line"> <span class="comment">// 初始化 GLUT</span></span><br><span class="line"> <span class="built_in">glutInit</span>(&amp;argc, argv);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 设置显示模式单缓冲、RGB 颜色模式</span></span><br><span class="line"> <span class="built_in">glutInitDisplayMode</span>(GLUT_SINGLE | GLUT_RGB);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 设置窗口大小和位置</span></span><br><span class="line"> <span class="built_in">glutInitWindowSize</span>(WIDTH, HEIGHT);</span><br><span class="line"> <span class="built_in">glutInitWindowPosition</span>(<span class="number">100</span>, <span class="number">100</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 创建窗口</span></span><br><span class="line"> <span class="built_in">glutCreateWindow</span>(<span class="string">"DDA算法"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 注册回调函数</span></span><br><span class="line"> <span class="built_in">glutDisplayFunc</span>(display);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 初始化设置</span></span><br><span class="line"> <span class="built_in">init</span>();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 进入主循环</span></span><br><span class="line"> <span class="built_in">glutMainLoop</span>();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure>
<h1 id="中点画线算法"><a href="#中点画线算法" class="headerlink" title="中点画线算法"></a>中点画线算法</h1><h2 id="算法简介-1"><a href="#算法简介-1" class="headerlink" title="算法简介"></a>算法简介</h2><p>只考虑当直线的斜率$|k|&lt; 1$时的情况,假设现在有一条直线$(x_1,y_1,x_2,y_2)$,那么第一个点一定是$(x_1,y_1)$无疑,下一个点的$x$坐标为$x_1+1$,$y$坐标要么为$y1$要么为$y1+1$。关键在于每次取下一个点时,是取前一个的$y1$呢,还是$y1+1$,这时一定是取直线上点最靠近的那个了,而判断取哪个点就用到了中点,我们将中点代入直线中 $d=F(x_1+1,y_1+0.5)=a \cdot (x_1+1)+b \cdot (y_1+0.5)+c$。</p>
<ol>
<li>如果直线$d&gt;=0$,则取下边的点也就是$(x_1+1,y_1)$。</li>
<li>如果直线$d&lt;0$,则取上边的点也就是$(x_1+1,y_1+1)$。</li>
</ol>
<p>它的实际过程就是这样每次根据前边的点判断下一个点在哪,然后进行打亮,但这样每次判断的时候都得代入直线方程计算太麻烦了,我们将这俩种情况分别代入直线方程中可以找出规律:</p>
<ol>
<li>当直线$d&gt;=0$时,经过化解得$d_1=d+a$;</li>
<li>当直线$d&lt;0$时,经过化解得$d_2=d+a+b$;</li>
<li>初始值$d_0=a+0.5b$。</li>
</ol>
<p>也就是说每次的增量要么为$a$,要么为$a+b$,那么这样判断的时候就简单多了因为我们每次只是判断它的正负。所以给等式同时乘2将其中浮点数0.5化为整数,这样硬件操作时无疑更快了。</p>
<h2 id="算法实现-1"><a href="#算法实现-1" class="headerlink" title="算法实现"></a>算法实现</h2><figure class="highlight cpp"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;GL/freeglut.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;cmath&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 中点画线算法函数 (仅针对斜率 0 &lt;= k &lt;= 1 的情况进行演示,其它象限需类比处理)</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">drawLineMidpoint</span><span class="params">(<span class="type">int</span> x0, <span class="type">int</span> y0, <span class="type">int</span> x1, <span class="type">int</span> y1)</span> </span>{</span><br><span class="line"> <span class="type">int</span> a = y0 - y1;</span><br><span class="line"> <span class="type">int</span> b = x1 - x0;</span><br><span class="line"> <span class="type">int</span> d = <span class="number">2</span> * a + b;</span><br><span class="line"> <span class="type">int</span> d1 = <span class="number">2</span> * a;</span><br><span class="line"> <span class="type">int</span> d2 = <span class="number">2</span> * (a + b);</span><br><span class="line"></span><br><span class="line"> <span class="type">int</span> x = x0, y = y0;</span><br><span class="line"></span><br><span class="line"> <span class="built_in">glBegin</span>(GL_POINTS);</span><br><span class="line"> <span class="built_in">glVertex2i</span>(x, y); <span class="comment">// 画起点</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> (x &lt; x1) {</span><br><span class="line"> <span class="keyword">if</span> (d &lt; <span class="number">0</span>) {</span><br><span class="line"> x++;</span><br><span class="line"> y++;</span><br><span class="line"> d += d2;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> x++;</span><br><span class="line"> d += d1;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">glVertex2i</span>(x, y);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">glEnd</span>();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 渲染回调函数</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">display</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">glClear</span>(GL_COLOR_BUFFER_BIT);</span><br><span class="line"> <span class="built_in">glColor3f</span>(<span class="number">1.0</span>, <span class="number">1.0</span>, <span class="number">1.0</span>); <span class="comment">// 设置画笔颜色为白色</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// 调用算法画一条直线 (x0, y0) 到 (x1, y1)</span></span><br><span class="line"> <span class="comment">// 注意:此处的坐标对应屏幕像素坐标</span></span><br><span class="line"> <span class="built_in">drawLineMidpoint</span>(<span class="number">50</span>, <span class="number">50</span>, <span class="number">450</span>, <span class="number">300</span>);</span><br><span class="line"></span><br><span class="line"> <span class="built_in">glFlush</span>();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 初始化设置</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">init</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">glClearColor</span>(<span class="number">0.0</span>, <span class="number">0.0</span>, <span class="number">0.0</span>, <span class="number">1.0</span>); <span class="comment">// 背景设为黑色</span></span><br><span class="line"> <span class="built_in">glMatrixMode</span>(GL_PROJECTION);</span><br><span class="line"> <span class="built_in">glLoadIdentity</span>();</span><br><span class="line"> <span class="comment">// 设置正交投影矩阵,使坐标系与窗口像素对应</span></span><br><span class="line"> <span class="built_in">gluOrtho2D</span>(<span class="number">0</span>, <span class="number">500</span>, <span class="number">0</span>, <span class="number">500</span>); </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">(<span class="type">int</span> argc, <span class="type">char</span>** argv)</span> </span>{</span><br><span class="line"> <span class="built_in">glutInit</span>(&amp;argc, argv);</span><br><span class="line"> <span class="built_in">glutInitDisplayMode</span>(GLUT_SINGLE | GLUT_RGB);</span><br><span class="line"> <span class="built_in">glutInitWindowSize</span>(<span class="number">500</span>, <span class="number">500</span>);</span><br><span class="line"> <span class="built_in">glutInitWindowPosition</span>(<span class="number">100</span>, <span class="number">100</span>);</span><br><span class="line"> <span class="built_in">glutCreateWindow</span>(<span class="string">"Midpoint Line Algorithm - FreeGLUT"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="built_in">init</span>();</span><br><span class="line"> <span class="built_in">glutDisplayFunc</span>(display);</span><br><span class="line"> <span class="built_in">glutMainLoop</span>();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure>
<h1 id="Bresenham算法"><a href="#Bresenham算法" class="headerlink" title="Bresenham算法"></a>Bresenham算法</h1><h2 id="算法简介-2"><a href="#算法简介-2" class="headerlink" title="算法简介"></a>算法简介</h2><p>假设我们需要由$(x_0, y_0)$这一点,绘画一直线至右下角的另一点$(x_1, y_1)$x,y分别代表其水平及垂直坐标并且$x_1 - x_0 &gt; y_1 - y_0$。在此我们使用电脑系统常用的坐标系,即$x$坐标值沿$x$轴向右增长,$y$坐标值沿$y$轴向下增长。</p>
<p>因此x及y之值分别向右及向下增加而两点之水平距离为$x_{1}-x_{0}$且垂直距离为$y_{1}-y_{0}$。由此得之,该线的斜率必定介乎于$0$至$1$之间。而此算法之目的,就是找出在$x_{0}$与$x_{1}$之间,第$x$行相对应的第$y$列,从而得出一像素点,使得该像素点的位置最接近原本的线。</p>
<p>对于由$(x_0, y_0)$及$(x_1, y_1)$两点所组成之直线,公式如下:<br>$$y-y_{0}={\frac {y_{1}-y_{0}}{x_{1}-x_{0}}}(x-x_{0})$$<br>因此对于每一点的x其y的值是<br>$${\frac {y_{1}-y_{0}}{x_{1}-x_{0}}}(x-x_{0})+y_{0}$$<br>因为$x$及$y$皆为整数,但并非每一点$x$所对应的$y$皆为整数故此没有必要去计算每一点x所对应之$y$值。反之由于此线之斜率介乎于$1$至$0$之间,故此我们只需要找出当$x$到达那一个数值时,会使$y$上升$1$,若$x$尚未到此值,则$y$不变。至于如何找出相关的$x$值,则需依靠斜率。斜率之计算方法为$m=(y_{1}-y_{0})/(x_{1}-x_{0})$。由于此值不变,故可于运算前预先计算,减少运算次数。</p>
<p>要实行此算法,我们需计算每一像素点与该线之间的误差。于上述例子中,误差应为每一点$x$中,其相对的像素点之$y$值与该线实际之$y$值的差距。每当$y$的值增加$1$,误差的值就会增加$m$。每当误差的值超出$0.5$,线就会比较靠近下一个映像点,因此$y$的值便会加$1$,且误差减$1$。</p>
<h2 id="算法实现-2"><a href="#算法实现-2" class="headerlink" title="算法实现"></a>算法实现</h2><figure class="highlight cpp"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;GL/freeglut.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;cmath&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 通用 Bresenham 画线算法</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">drawLineBresenham</span><span class="params">(<span class="type">int</span> x0, <span class="type">int</span> y0, <span class="type">int</span> x1, <span class="type">int</span> y1)</span> </span>{</span><br><span class="line"> <span class="type">int</span> dx = <span class="built_in">abs</span>(x1 - x0);</span><br><span class="line"> <span class="type">int</span> dy = <span class="built_in">abs</span>(y1 - y0);</span><br><span class="line"> <span class="type">int</span> sx = (x0 &lt; x1) ? <span class="number">1</span> : <span class="number">-1</span>; <span class="comment">// X 方向步进</span></span><br><span class="line"> <span class="type">int</span> sy = (y0 &lt; y1) ? <span class="number">1</span> : <span class="number">-1</span>; <span class="comment">// Y 方向步进</span></span><br><span class="line"> <span class="type">int</span> err = dx - dy; <span class="comment">// 初始误差项</span></span><br><span class="line"></span><br><span class="line"> <span class="built_in">glBegin</span>(GL_POINTS);</span><br><span class="line"> <span class="keyword">while</span> (<span class="literal">true</span>) {</span><br><span class="line"> <span class="built_in">glVertex2i</span>(x0, y0); <span class="comment">// 绘制当前点</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (x0 == x1 &amp;&amp; y0 == y1) <span class="keyword">break</span>; <span class="comment">// 到达终点</span></span><br><span class="line"></span><br><span class="line"> <span class="type">int</span> e2 = <span class="number">2</span> * err;</span><br><span class="line"> <span class="comment">// 判断是否在 X 方向步进</span></span><br><span class="line"> <span class="keyword">if</span> (e2 &gt; -dy) {</span><br><span class="line"> err -= dy;</span><br><span class="line"> x0 += sx;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// 判断是否在 Y 方向步进</span></span><br><span class="line"> <span class="keyword">if</span> (e2 &lt; dx) {</span><br><span class="line"> err += dx;</span><br><span class="line"> y0 += sy;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">glEnd</span>();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 渲染回调</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">display</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">glClear</span>(GL_COLOR_BUFFER_BIT);</span><br><span class="line"> <span class="built_in">glColor3f</span>(<span class="number">0.0f</span>, <span class="number">0.8f</span>, <span class="number">0.4f</span>); <span class="comment">// 设置一个好看的绿色(类似你图中的图标颜色)</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// 绘制几条不同方向的线来测试算法的健壮性</span></span><br><span class="line"> <span class="built_in">drawLineBresenham</span>(<span class="number">50</span>, <span class="number">50</span>, <span class="number">450</span>, <span class="number">400</span>); <span class="comment">// 第一象限</span></span><br><span class="line"> <span class="built_in">drawLineBresenham</span>(<span class="number">50</span>, <span class="number">400</span>, <span class="number">450</span>, <span class="number">50</span>); <span class="comment">// 第四象限</span></span><br><span class="line"> <span class="built_in">drawLineBresenham</span>(<span class="number">250</span>, <span class="number">50</span>, <span class="number">250</span>, <span class="number">450</span>); <span class="comment">// 垂直线</span></span><br><span class="line"> <span class="built_in">drawLineBresenham</span>(<span class="number">50</span>, <span class="number">250</span>, <span class="number">450</span>, <span class="number">250</span>); <span class="comment">// 水平线</span></span><br><span class="line"></span><br><span class="line"> <span class="built_in">glFlush</span>();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">init</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">glClearColor</span>(<span class="number">0.1f</span>, <span class="number">0.1f</span>, <span class="number">0.1f</span>, <span class="number">1.0f</span>); <span class="comment">// 深色背景</span></span><br><span class="line"> <span class="built_in">glMatrixMode</span>(GL_PROJECTION);</span><br><span class="line"> <span class="built_in">glLoadIdentity</span>();</span><br><span class="line"> <span class="built_in">gluOrtho2D</span>(<span class="number">0</span>, <span class="number">500</span>, <span class="number">0</span>, <span class="number">500</span>); <span class="comment">// 建立 500x500 的直角坐标系</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">(<span class="type">int</span> argc, <span class="type">char</span>** argv)</span> </span>{</span><br><span class="line"> <span class="built_in">glutInit</span>(&amp;argc, argv);</span><br><span class="line"> <span class="built_in">glutInitDisplayMode</span>(GLUT_SINGLE | GLUT_RGB);</span><br><span class="line"> <span class="built_in">glutInitWindowSize</span>(<span class="number">600</span>, <span class="number">600</span>);</span><br><span class="line"> <span class="built_in">glutCreateWindow</span>(<span class="string">"Bresenham Line Algorithm"</span>);</span><br><span class="line"> <span class="built_in">init</span>();</span><br><span class="line"> <span class="built_in">glutDisplayFunc</span>(display);</span><br><span class="line"> <span class="built_in">glutMainLoop</span>();</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure></article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta"><i class="fas fa-circle-user fa-fw"></i>文章作者: </span><span class="post-copyright-info"><a href="https://blog.biss.click">biss</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta"><i class="fas fa-square-arrow-up-right fa-fw"></i>文章链接: </span><span class="post-copyright-info"><a href="https://blog.biss.click/posts/7207243b/">https://blog.biss.click/posts/7207243b/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta"><i class="fas fa-circle-exclamation fa-fw"></i>版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外,均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来源 <a href="https://blog.biss.click" target="_blank">Bi's Blog</a></span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/OpenGL/">OpenGL</a></div><div class="post-share"><style>#web-share-btn {
background: var(--btn-bg);
color: var(--btn-color);
border: none;
padding: 0.5rem 1rem;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s;
}
#web-share-btn:hover {
background: var(--btn-hover-color);
}
</style><div id="web-share-component"><button id="web-share-btn" title="分享本文"><i class="fas fa-share-alt"></i><span> 分享</span></button></div><script>(() => {
const setupWebShare = () => {
const btn = document.getElementById('web-share-btn')
if (!btn) return
// 点击事件处理
btn.addEventListener('click', async () => {
if (navigator.share) {
try {
await navigator.share({
title: 'OpenGL-直线的扫描转换',
text: '...',
url: window.location.href
})
} catch (err) {
console.log('分享取消或失败', err)
}
} else {
// 降级处理:比如弹出提示或复制链接
const shareData = window.location.href
navigator.clipboard.writeText(shareData).then(() => {
btf.snackbarShow('系统不支持分享,已将链接复制到剪贴板')
})
}
})
}
// 考虑到 Butterfly 的 Pjax 跳转,需要重新绑定
setupWebShare()
document.addEventListener('pjax:complete', setupWebShare)
})()</script></div></div><nav class="pagination-post" id="pagination"><a class="pagination-related full-width" href="/posts/437a5198/" title="OpenGL-基础程序"><img class="cover" src="https://pic.biss.click/image/2fcb9566-f7f6-4132-81cb-4cd646967519.webp" onerror="onerror=null;src='/img/404.jpg'" alt="cover of next post"><div class="info text-right"><div class="info-1"><div class="info-item-1">下一篇</div><div class="info-item-2">OpenGL-基础程序</div></div><div class="info-2"><div class="info-item-1">代码展示我们先从基本的OpenGL程序开始吧这是一个简单的OpenGL程序 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354#include&lt;GL/glut.h&gt;using namespace std;// 回调函数void myDisplay(){ // 清除缓冲区 glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); // 正交模式 glMatrixMode(GL_PROJECTION); gluOrtho2D(0.0, 500.0, 0.0, 500.0); glColor4f(0.0, 1.0, 0.0, 0.0); glRectf(50.0, 50.0, 400.0, 400.0); // 划线 glColor3f(1.0, 1.0, 0.0); glBegin(GL_LINES); glVertex2f(50.0, 50....</div></div></div></a></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span>相关推荐</span></div><div class="relatedPosts-list"><a class="pagination-related" href="/posts/c4477b0c/" title="配置OpenGL环境"><img class="cover" src="https://pic.biss.click/image/d19b9e03-9442-4b85-94a0-a3780b9f4440.webp" alt="cover"><div class="info text-center"><div class="info-1"><div class="info-item-1"><i class="far fa-calendar-alt fa-fw"></i> 2026-04-02</div><div class="info-item-2">配置OpenGL环境</div></div><div class="info-2"><div class="info-item-1">最近要学计算机图形学所以会用到OpenGL配置环境有点繁琐记录了下来。 安装Visual Studio现在我们先来安装Visual Studiovisual studio下载后安装即可|在安装时选择“使用C++的桌面开发”这样安装时就会安装C++的编译器了。 安装 Cmake这个可选因为我们可以使用Visual Studio的编译器MSVC来编译项目。Cmake是一个开源的跨平台软件构建工具它可以生成不同系统的构建文件比如MakefileNinjaVS项目文件等等。我们可以下载Cmakecmake下载后安装即可。 安装GLFWOpenGL有许多工具比如GLFWGLEW等等这里我们安装GLFW。 工具 类别 主要职责 特点 GLUT 窗口管理 + 工具库 创建窗口、处理鼠标键盘、提供内置渲染循环。 古老、简单。使用“固定管线”(老旧技术),适合教学。 GLFW 窗口管理库 创建窗口、处理输入、管理多个上下文。 现代、轻量。只管窗口和输入,不负责渲染逻辑,是目前的主流。 GLAD 配置/加载库 加载 OpenGL 函数指针...</div></div></div></a><a class="pagination-related" href="/posts/437a5198/" title="OpenGL-基础程序"><img class="cover" src="https://pic.biss.click/image/2fcb9566-f7f6-4132-81cb-4cd646967519.webp" alt="cover"><div class="info text-center"><div class="info-1"><div class="info-item-1"><i class="far fa-calendar-alt fa-fw"></i> 2026-04-11</div><div class="info-item-2">OpenGL-基础程序</div></div><div class="info-2"><div class="info-item-1">代码展示我们先从基本的OpenGL程序开始吧这是一个简单的OpenGL程序 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354#include&lt;GL/glut.h&gt;using namespace std;// 回调函数void myDisplay(){ // 清除缓冲区 glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); // 正交模式 glMatrixMode(GL_PROJECTION); gluOrtho2D(0.0, 500.0, 0.0, 500.0); glColor4f(0.0, 1.0, 0.0, 0.0); glRectf(50.0, 50.0, 400.0, 400.0); // 划线 glColor3f(1.0, 1.0, 0.0); glBegin(GL_LINES); glVertex2f(50.0, 50....</div></div></div></a></div></div><hr class="custom-hr"><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="fas fa-comments fa-fw"></i><span> 评论</span></div></div><div class="comment-wrap"><div><div id="twikoo-wrap"></div></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info text-center"><div class="avatar-img"><img src="https://free.picui.cn/free/2025/08/10/689845496a283.png" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"></div><div class="author-info-name">biss</div><div class="author-info-description"></div><div class="site-data"><a href="/archives/"><div class="headline">文章</div><div class="length-num">38</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">12</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">6</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/bishshi"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons"><a class="social-icon" href="https://github.com/bishshi" target="_blank" title="Github"><i class="fab fa-github" style="color: #24292e;"></i></a><a class="social-icon" href="mailto:bishsh2006@gmail.com" target="_blank" title="Email"><i class="fas fa-envelope" style="color: #4a7dbe;"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content"></div><div id="welcome-ip-location-info"></div></div><div class="card-widget" id="card-poem"><div id="poem_sentence"></div><div id="poem_info"><div id="poem_dynasty"></div><div id="poem_author"></div></div></div><script src="https://cdn.liumingye.cn/npm/js-heo@1.0.11/poem/jinrishici.js" charset="utf-8"></script><script type="text/javascript">jinrishici.load(function(result) {
var sentence = document.querySelector("#poem_sentence")
var author = document.querySelector("#poem_author")
var dynasty = document.querySelector("#poem_dynasty")
var sentenceText = result.data.content
sentenceText = sentenceText.substr(0, sentenceText.length - 1);
sentence.innerHTML = sentenceText
dynasty.innerHTML = result.data.origin.dynasty
author.innerHTML = result.data.origin.author + '《' + result.data.origin.title + '》'
});</script><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#DDA%E6%95%B0%E5%80%BC%E5%BE%AE%E5%88%86%E7%BA%BF%E6%AE%B5%E7%AE%97%E6%B3%95"><span class="toc-number">1.</span> <span class="toc-text">DDA数值微分线段算法</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AE%97%E6%B3%95%E7%AE%80%E4%BB%8B"><span class="toc-number">1.1.</span> <span class="toc-text">算法简介</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AE%97%E6%B3%95%E5%AE%9E%E7%8E%B0"><span class="toc-number">1.2.</span> <span class="toc-text">算法实现</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%B8%AD%E7%82%B9%E7%94%BB%E7%BA%BF%E7%AE%97%E6%B3%95"><span class="toc-number">2.</span> <span class="toc-text">中点画线算法</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AE%97%E6%B3%95%E7%AE%80%E4%BB%8B-1"><span class="toc-number">2.1.</span> <span class="toc-text">算法简介</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AE%97%E6%B3%95%E5%AE%9E%E7%8E%B0-1"><span class="toc-number">2.2.</span> <span class="toc-text">算法实现</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Bresenham%E7%AE%97%E6%B3%95"><span class="toc-number">3.</span> <span class="toc-text">Bresenham算法</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AE%97%E6%B3%95%E7%AE%80%E4%BB%8B-2"><span class="toc-number">3.1.</span> <span class="toc-text">算法简介</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AE%97%E6%B3%95%E5%AE%9E%E7%8E%B0-2"><span class="toc-number">3.2.</span> <span class="toc-text">算法实现</span></a></li></ol></li></ol></div></div><div class="card-widget card-post-series"><div class="item-headline"><i class="fa-solid fa-layer-group"></i><span>系列文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/posts/7207243b/" title="OpenGL-直线的扫描转换"><img src="https://pic.biss.click/image/c5457adc-214c-4a18-9aa6-43fbc0bfc2f4.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="OpenGL-直线的扫描转换"></a><div class="content"><a class="title" href="/posts/7207243b/" title="OpenGL-直线的扫描转换">OpenGL-直线的扫描转换</a><time datetime="2026-04-11T11:01:02.000Z" title="发表于 2026-04-11 19:01:02">2026-04-11</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/437a5198/" title="OpenGL-基础程序"><img src="https://pic.biss.click/image/2fcb9566-f7f6-4132-81cb-4cd646967519.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="OpenGL-基础程序"></a><div class="content"><a class="title" href="/posts/437a5198/" title="OpenGL-基础程序">OpenGL-基础程序</a><time datetime="2026-04-11T10:20:34.000Z" title="发表于 2026-04-11 18:20:34">2026-04-11</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/c4477b0c/" title="配置OpenGL环境"><img src="https://pic.biss.click/image/d19b9e03-9442-4b85-94a0-a3780b9f4440.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="配置OpenGL环境"></a><div class="content"><a class="title" href="/posts/c4477b0c/" title="配置OpenGL环境">配置OpenGL环境</a><time datetime="2026-04-01T20:52:16.000Z" title="发表于 2026-04-02 04:52:16">2026-04-02</time></div></div></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/posts/7207243b/" title="OpenGL-直线的扫描转换"><img src="https://pic.biss.click/image/c5457adc-214c-4a18-9aa6-43fbc0bfc2f4.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="OpenGL-直线的扫描转换"></a><div class="content"><a class="title" href="/posts/7207243b/" title="OpenGL-直线的扫描转换">OpenGL-直线的扫描转换</a><time datetime="2026-04-11T11:01:02.000Z" title="发表于 2026-04-11 19:01:02">2026-04-11</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/437a5198/" title="OpenGL-基础程序"><img src="https://pic.biss.click/image/2fcb9566-f7f6-4132-81cb-4cd646967519.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="OpenGL-基础程序"></a><div class="content"><a class="title" href="/posts/437a5198/" title="OpenGL-基础程序">OpenGL-基础程序</a><time datetime="2026-04-11T10:20:34.000Z" title="发表于 2026-04-11 18:20:34">2026-04-11</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/c4477b0c/" title="配置OpenGL环境"><img src="https://pic.biss.click/image/d19b9e03-9442-4b85-94a0-a3780b9f4440.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="配置OpenGL环境"></a><div class="content"><a class="title" href="/posts/c4477b0c/" title="配置OpenGL环境">配置OpenGL环境</a><time datetime="2026-04-01T20:52:16.000Z" title="发表于 2026-04-02 04:52:16">2026-04-02</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/b559997d/" title="opencv应用-算术运算">opencv应用-算术运算</a><time datetime="2026-03-17T05:13:08.000Z" title="发表于 2026-03-17 13:13:08">2026-03-17</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/e8f95ead/" title="opencv应用-基础操作">opencv应用-基础操作</a><time datetime="2026-03-15T01:56:51.000Z" title="发表于 2026-03-15 09:56:51">2026-03-15</time></div></div></div></div></div></div></main><footer id="footer"><div class="footer-other"><div class="footer-copyright"><span class="copyright">©&nbsp;2025 - 2026 By biss</span><span class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></span></div><div class="footer_custom_text"><p> <a style="margin-inline:5px" target="_blank" href="https://hexo.io/zh-cn/"><img src="https://img.shields.io/badge/Frame-Hexo-blue?style=flat&amp;logo=hexo" title="hexo 8.1"></a> <a style="margin-inline:5px" target="_blank" href="https://butterfly.js.org"><img src="https://img.shields.io/badge/Theme-Butterfly-pink?style=flat" title="butterfly主题"></a> <a style="margin-inline:5px" target="_blank" href="https://creativecommons.org/licenses/by-nc-sa/4.0/"><img src="https://img.shields.io/badge/Copyright-BY--NC--SA-red?style=flat&amp;logo=alchemy" title="CC BY-NC-SA 4.0"></a> <a href="https://www.trustssl.cc/ipv6.php?domain=blog.biss.click" title="本站已支持IPv6访问" target="_blank"><img src="https://static.coolcdn.cn/images/ipv6.svg"></a> </p></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="translateLink" type="button" title="简繁转换"></button><button id="darkmode" type="button" title="日间和夜间模式切换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><a id="to_comment" href="#post-comment" title="前往评论"><i class="fas fa-comments"></i></a><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="/js/tw_cn.js"></script><script src="https://unpkg.com/@fancyapps/ui/dist/fancybox/fancybox.umd.js"></script><script src="https://unpkg.com/node-snackbar/dist/snackbar.min.js"></script><div class="js-pjax"><script>(() => {
const loadMathjax = () => {
if (!window.MathJax) {
window.MathJax = {
loader: {
load: [
// Four font extension packages (optional)
//- '[tex]/bbm',
//- '[tex]/bboldx',
//- '[tex]/dsfont',
'[tex]/mhchem'
],
paths: {
'mathjax-newcm': '[mathjax]/../@mathjax/mathjax-newcm-font',
//- // Four font extension packages (optional)
//- 'mathjax-bbm-extension': '[mathjax]/../@mathjax/mathjax-bbm-font-extension',
//- 'mathjax-bboldx-extension': '[mathjax]/../@mathjax/mathjax-bboldx-font-extension',
//- 'mathjax-dsfont-extension': '[mathjax]/../@mathjax/mathjax-dsfont-font-extension',
'mathjax-mhchem-extension': '[mathjax]/../@mathjax/mathjax-mhchem-font-extension'
}
},
output: {
font: 'mathjax-newcm',
},
tex: {
inlineMath: [['$', '$'], ['\\(', '\\)']],
tags: 'none',
packages: {
'[+]': [
'mhchem'
]
}
},
chtml: {
scale: 1.1
},
options: {
enableMenu: true,
menuOptions: {
settings: {
enrich: false // Turn off Braille and voice narration text automatic generation
}
},
renderActions: {
findScript: [10, doc => {
for (const node of document.querySelectorAll('script[type^="math/tex"]')) {
const display = !!node.type.match(/; *mode=display/)
const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display)
const text = document.createTextNode('')
node.parentNode.replaceChild(text, node)
math.start = {node: text, delim: '', n: 0}
math.end = {node: text, delim: '', n: 0}
doc.math.push(math)
}
}, '']
}
}
}
const script = document.createElement('script')
script.src = 'https://unpkg.com/mathjax/tex-mml-chtml.js'
script.id = 'MathJax-script'
script.async = true
document.head.appendChild(script)
} else {
MathJax.startup.document.state(0)
MathJax.texReset()
MathJax.typesetPromise()
}
}
btf.addGlobalFn('encrypt', loadMathjax, 'mathjax')
window.pjax ? loadMathjax() : window.addEventListener('load', loadMathjax)
})()</script><script>(() => {
const applyThemeDefaultsConfig = theme => {
if (theme === 'dark-mode') {
Chart.defaults.color = "rgba(255, 255, 255, 0.8)"
Chart.defaults.borderColor = "rgba(255, 255, 255, 0.2)"
Chart.defaults.scale.ticks.backdropColor = "transparent"
} else {
Chart.defaults.color = "rgba(0, 0, 0, 0.8)"
Chart.defaults.borderColor = "rgba(0, 0, 0, 0.1)"
Chart.defaults.scale.ticks.backdropColor = "transparent"
}
}
// Recursively traverse the config object and automatically apply theme-specific color schemes
const applyThemeConfig = (obj, theme) => {
if (typeof obj !== 'object' || obj === null) return
Object.keys(obj).forEach(key => {
const value = obj[key]
// If the property is an object and has theme-specific options, apply them
if (typeof value === 'object' && value !== null) {
if (value[theme]) {
obj[key] = value[theme] // Apply the value for the current theme
} else {
// Recursively process child objects
applyThemeConfig(value, theme)
}
}
})
}
const runChartJS = ele => {
window.loadChartJS = true
Array.from(ele).forEach((item, index) => {
const chartSrc = item.firstElementChild
const chartID = item.getAttribute('data-chartjs-id') || ('chartjs-' + index) // Use custom ID or default ID
const width = item.getAttribute('data-width')
const existingCanvas = document.getElementById(chartID)
// If a canvas already exists, remove it to avoid rendering duplicates
if (existingCanvas) {
existingCanvas.parentNode.remove()
}
const chartDefinition = chartSrc.textContent
const canvas = document.createElement('canvas')
canvas.id = chartID
const div = document.createElement('div')
div.className = 'chartjs-wrap'
if (width) {
div.style.width = width
}
div.appendChild(canvas)
chartSrc.insertAdjacentElement('afterend', div)
const ctx = document.getElementById(chartID).getContext('2d')
const config = JSON.parse(chartDefinition)
const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark-mode' : 'light-mode'
// Set default styles (initial setup)
applyThemeDefaultsConfig(theme)
// Automatically traverse the config and apply dual-mode color schemes
applyThemeConfig(config, theme)
new Chart(ctx, config)
})
}
const loadChartJS = () => {
const chartJSEle = document.querySelectorAll('#article-container .chartjs-container')
if (chartJSEle.length === 0) return
window.loadChartJS ? runChartJS(chartJSEle) : btf.getScript('https://unpkg.com/chart.js/dist/chart.umd.js').then(() => runChartJS(chartJSEle))
}
// Listen for theme change events
btf.addGlobalFn('themeChange', loadChartJS, 'chartjs')
btf.addGlobalFn('encrypt', loadChartJS, 'chartjs')
window.pjax ? loadChartJS() : document.addEventListener('DOMContentLoaded', loadChartJS)
})()</script><script>(() => {
const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'
const option = null
const getCount = () => {
const countELement = document.getElementById('twikoo-count')
if(!countELement) return
twikoo.getCommentsCount({
envId: 'https://comment.biss.click',
region: '',
urls: [window.location.pathname],
includeReply: false
}).then(res => {
countELement.textContent = res[0].count
}).catch(err => {
console.error(err)
})
}
const init = (el = document, path = location.pathname) => {
twikoo.init({
el: el.querySelector('#twikoo-wrap'),
envId: 'https://comment.biss.click',
region: '',
onCommentLoaded: () => {
btf.loadLightbox(document.querySelectorAll('#twikoo .tk-content img:not(.tk-owo-emotion)'))
},
...option,
path: isShuoshuo ? path : (option && option.path) || path
})
GLOBAL_CONFIG_SITE.pageType === 'post' && getCount()
isShuoshuo && (window.shuoshuoComment.destroyTwikoo = () => {
if (el.children.length) {
el.innerHTML = ''
el.classList.add('no-comment')
}
})
}
const loadTwikoo = (el, path) => {
if (typeof twikoo === 'object') setTimeout(() => init(el, path), 0)
else btf.getScript('https://unpkg.com/twikoo/dist/twikoo.min.js').then(() => init(el, path))
}
if (isShuoshuo) {
'Twikoo' === 'Twikoo'
? window.shuoshuoComment = { loadComment: loadTwikoo }
: window.loadOtherComment = loadTwikoo
return
}
if ('Twikoo' === 'Twikoo' || !false) {
if (false) btf.loadComment(document.getElementById('twikoo-wrap'), loadTwikoo)
else loadTwikoo()
} else {
window.loadOtherComment = loadTwikoo
}
})()</script></div><script src="https://code.jquery.com/jquery-4.0.0.min.js"></script><script src="/js/random.js"></script><script src="/js/shuoshuoshouye.js"></script><script src="/js/ai-summary.js"></script><script src="/js/search/typesense-search.js"></script><script src="/js/footer.js" <script=""></script><script src="https://cdn.jsdmirror.com/gh/bishshi/welcomemessage/txmap.js"></script><script src="https://cdn.jsdmirror.com/gh/bishshi/rightmenu@1.2/rightmenu.js"></script><script src="https://cdn.jsdmirror.com/gh/bishshi/sidecalendar@latest/calendar.js"></script><script src="https://cdn.jsdmirror.com/npm/chinese-lunar@0.1.4/lib/chinese-lunar.js"></script><script src="https://cdn.jsdmirror.com/npm/instantsearch.js@4.56.0"></script><script src="https://cdn.jsdmirror.com/npm/typesense-instantsearch-adapter@2.7.0/dist/typesense-instantsearch-adapter.min.js"></script><script src="https://unpkg.com/pjax/pjax.min.js" defer="defer"></script><script>document.addEventListener('DOMContentLoaded', () => {
const pjaxSelectors = ["head > title","#config-diff","#body-wrap","#rightside-config-hide","#rightside-config-show",".js-pjax"]
window.pjax = new Pjax({
elements: 'a:not([target="_blank"])',
selectors: pjaxSelectors,
cacheBust: false,
analytics: false,
scrollRestoration: false
})
const triggerPjaxFn = (val) => {
if (!val) return
Object.values(val).forEach(fn => {
try {
fn()
} catch (err) {
console.debug('Pjax callback failed:', err)
}
})
}
document.addEventListener('pjax:send', () => {
// removeEventListener
btf.removeGlobalFnEvent('pjaxSendOnce')
btf.removeGlobalFnEvent('themeChange')
// reset readmode
const $bodyClassList = document.body.classList
if ($bodyClassList.contains('read-mode')) $bodyClassList.remove('read-mode')
triggerPjaxFn(window.globalFn.pjaxSend)
})
document.addEventListener('pjax:complete', () => {
btf.removeGlobalFnEvent('pjaxCompleteOnce')
document.querySelectorAll('script[data-pjax]').forEach(item => {
const newScript = document.createElement('script')
const content = item.text || item.textContent || item.innerHTML || ""
Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value))
newScript.appendChild(document.createTextNode(content))
item.parentNode.replaceChild(newScript, item)
})
triggerPjaxFn(window.globalFn.pjaxComplete)
})
document.addEventListener('pjax:error', e => {
if (e.request.status === 404) {
true
? pjax.loadUrl('/404.html')
: window.location.href = e.request.responseURL
}
})
})</script></div><div class="js-pjax" id="rightMenu"><div class="rightMenu-group rightMenu-small"><a class="rightMenu-item" href="javascript:window.history.back();"><i class="fa fa-arrow-left"></i></a><a class="rightMenu-item" href="javascript:window.history.forward();"><i class="fa fa-arrow-right"></i></a><a class="rightMenu-item" href="javascript:window.location.reload();"><i class="fa fa-refresh"></i></a><a class="rightMenu-item" href="javascript:window.scrollTo(0, 0);"><i class="fa fa-arrow-up"></i></a></div><div class="rightMenu-group rightMenu-line hide" id="menu-text"><a class="rightMenu-item" href="javascript:rmf.copySelect();"><i class="fa fa-copy"></i><span>复制</span></a><a class="rightMenu-item" href="javascript:rmf.searchinThisPage();"><i class="fas fa-search"></i><span>站内搜索</span></a></div><div class="rightMenu-group rightMenu-line hide" id="menu-too"><a class="rightMenu-item" href="javascript:window.open(window.getSelection().toString());window.location.reload();"><i class="fa fa-link"></i><span>转到链接</span></a></div><div class="rightMenu-group rightMenu-line hide" id="menu-paste"><a class="rightMenu-item" href="javascript:rmf.paste()"><i class="fa fa-copy"></i><span>粘贴</span></a></div><div class="rightMenu-group rightMenu-line hide" id="menu-post"><a class="rightMenu-item" href="javascript:rmf.copyWordsLink()"><i class="fa fa-link"></i><span>复制本文地址</span></a></div><div class="rightMenu-group rightMenu-line hide" id="menu-to"><a class="rightMenu-item" href="javascript:rmf.openWithNewTab()"><i class="fa fa-window-restore"></i><span>新窗口打开</span></a><a class="rightMenu-item" href="javascript:rmf.open()"><i class="fa fa-link"></i><span>转到链接</span></a><a class="rightMenu-item" href="javascript:rmf.copyLink()"><i class="fa fa-copy"></i><span>复制链接</span></a></div><div class="rightMenu-group rightMenu-line hide" id="menu-img"><a class="rightMenu-item" href="javascript:rmf.saveAs()"><i class="fa fa-download"></i><span>保存图片</span></a><a class="rightMenu-item" href="javascript:rmf.openWithNewTab()"><i class="fa fa-window-restore"></i><span>在新窗口打开</span></a><a class="rightMenu-item" href="javascript:rmf.click()"><i class="fa fa-arrows-alt"></i><span>全屏显示</span></a><a class="rightMenu-item" href="javascript:rmf.copyLink()"><i class="fa fa-copy"></i><span>复制图片链接</span></a></div><div class="rightMenu-group rightMenu-line"><a class="rightMenu-item" href="javascript:randomPost()"><i class="fa fa-paper-plane"></i><span>随便逛逛</span></a><a class="rightMenu-item" href="javascript:rmf.switchDarkMode();"><i class="fa fa-moon"></i><span>昼夜切换</span></a><a class="rightMenu-item" href="javascript:rmf.translate();"><i class="iconfont icon-fanti"></i><span>繁简转换</span></a><a class="rightMenu-item" href="javascript:rmf.switchReadMode();"><i class="fa fa-book"></i><span>阅读模式</span></a><a class="rightMenu-item" href="javascript:pjax.loadUrl(&quot;/privacy/&quot;);"><i class="fa fa-info-circle"></i><span>隐私声明</span></a><a class="rightMenu-item" href="javascript:pjax.loadUrl(&quot;/cookie/&quot;);"><i class="fa fa-info-circle"></i><span>Cookie协议</span></a><a class="rightMenu-item" href="javascript:pjax.loadUrl(&quot;/cc/&quot;);"><i class="fa fa-info-circle"></i><span>版权声明</span></a></div></div><!-- hexo injector body_end start --><script data-pjax="">
function butterfly_swiper_injector_config(){
var parent_div_git = document.getElementById('recent-posts');
var item_html = '<div class="recent-post-item" style="height: auto;width: 100%"><div class="blog-slider swiper-container-fade swiper-container-horizontal" id="swiper_container"><div class="blog-slider__wrp swiper-wrapper" style="transition-duration: 0ms;"><div class="blog-slider__item swiper-slide" style="background:url(https://pic.biss.click/image/fca16741-64fa-495b-aa5e-a2ef077461ef.webp);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2026-02-23</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;posts/56f57c0b/&quot;);" href="javascript:void(0);" alt="">自建renovate-bot</a><div class="blog-slider__text">还不知道怎么描述哦</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://pic.biss.click/image/63a5c345-cb40-4e92-bc7b-7dc4daaf5b74.webp);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2025-09-28</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;posts/b57500e9/&quot;);" href="javascript:void(0);" alt="">在Openwrt上安装AdguardHome</a><div class="blog-slider__text">还不知道怎么描述哦</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://pic.biss.click/image/961bc881-cb0a-4ab7-ace5-9990e71c30a0.webp);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2026-02-07</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;posts/34725d47/&quot;);" href="javascript:void(0);" alt="">安装gitea</a><div class="blog-slider__text">还不知道怎么描述哦</div></div></div></div><div class="blog-slider__pagination swiper-pagination-clickable swiper-pagination-bullets"></div><div class="swiper-button-prev"></div><div class="swiper-button-next"></div></div></div>';
console.log('已挂载butterfly_swiper')
parent_div_git.insertAdjacentHTML("afterbegin",item_html)
}
var elist = 'undefined'.split(',');
var cpage = location.pathname;
var epage = '/';
var flag = 0;
for (var i=0;i<elist.length;i++){
if (cpage.includes(elist[i])){
flag++;
}
}
if ((epage ==='all')&&(flag == 0)){
butterfly_swiper_injector_config();
}
else if (epage === cpage){
butterfly_swiper_injector_config();
}
</script><script defer="" src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/5.4.5/js/swiper.min.js"></script><script defer="" data-pjax="" src="https://npm.elemecdn.com/hexo-butterfly-swiper-lyx/lib/swiper_init.js"></script><!-- hexo injector body_end end --></body></html>