热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

c语言程序二维图形组合变换,[转]C语言图形编程(五)-二维图形变换②

第三节二维裁剪一、线段裁剪二、多边形裁剪第三节二维裁剪在二维图形的绘制或显示处理中,有时需要给出或显示某一部分原始图形。这可在适当位置按一定边界范围定义一个矩形区域(

第三节 二维裁剪

一、线段裁剪

二、多边形裁剪

第三节 二维裁剪

在二维图形的绘制或显示处理中,有时需要给出或显示某一部分原始图形。这可在适当位置按一定边界范围定义一个矩形区域(即窗口),使窗口内图形为所需部分,将其保留下来作为绘制或显示之用,而窗口边界以外的图形则予以舍弃。这种对二维原始图形的处理称为二维裁剪。

二维裁剪处理主要是判断图形元素是否在所开的窗口内,若在内则进一步求出窗口内的那一部分。也就是说裁剪处理工作有两点:第一是窗口内外的判断;第二是计算图形元素与窗口边界的交点。

在定义一个窗口时,一般规定窗口为矩形框。它在用户坐标系中的位置和大小用窗口对角点坐标或右下角点坐标(x1,y1)和右上角点坐标(x2,y2)来表示,有时也可用窗口原点(左下角点或右上角点)和窗口边长来表示。在某些情况下,用户也可以用圆心和半径来定图形窗口,或定义其它窗口。

在实际应用中,往往需要观察某一图形的各个细部,或切产生不同比例的显示图形,这些都需要对原图形作二维处理。裁剪处理是把每个图形元素分成窗口内的与窗口外两部分,舍弃窗口外部分。虽然对不同的图形元素(如点、线段、多边形等)有不同的裁剪算法,但它们的原理都是一致的。都是一对简单的不等式,由这对不等式来确定图形上的点(x,y)是否位于窗口内。在选定窗口的情况下,如窗口的四条边线是x=x1,x=x2,y=y1,y=y2时,不等式为

x1≤x≤x2

y1≤y≤y2

根据此式对图形进行逐点裁剪,不满足其中任何一个不等式的点就不在窗口内,应舍弃。显然这种算法效率很低。因此要另外设计对较大图形是行裁剪的算法,如对线段、多边形进行裁剪的算法,下面分别介绍。

一、线段裁剪

裁剪处理的关键是如何去掉窗口外的图形,这要设计出相应的算法。在线段裁剪算法中,需要检查线段相对于窗口的位置关系。对整个位于窗口内的线段须全部保留,对整个位于窗口外的线段要全部予以舍弃。对于部分位于窗口内而其余部分位于窗口外的线段 则须计算出该线段与窗口边的交点作为线段的分段点,保留位于窗口内的那部分线段,舍弃其余部分线段。一般线段两端点相对于窗口的位置有下面几种情况:

1、两端点均在窗口外同一侧位置。如图2-6中线段CD,这时线段全部位于窗口之外,故整个线段舍弃。

2、两端点均在窗口内,如图2-6中线段MN,显然整个线段位于窗口内,应全部保留。

3、两端点线段中,一点在窗口内,另一点在窗口外,如图2-6中线段PQ,在这种情况应计算出线段PQ与窗口边的交点T,保留窗口内部分线段TQ,舍弃其余部分线段PT。

4、两端点均不在窗口内,但又不处于 边界外同一侧位置,如图2-6中线段AB和线段EF,这时线段可能穿过窗口(如线段AB)也可能全部位于窗口之外(如线段EF),因此需要根据线段与窗口边界的交点来判断。若线段与窗口边线的交点中有两个交点处于窗口上,则此两交点间线段位于窗口内,予以保留,线段的其余部分位于窗口外,应舍弃;若线段与窗口边界的所有交点均在之外,则整个线段位于窗口外,应予全部舍弃。

d3935e962b8a8ccc801e237d34ca66c9.png

下面介绍线段裁剪算法(编码裁剪法)。

由上面线段相对于窗口的位置的几种情况讨论可以得知,有些线段被窗口边界切割后会产生一条以上的窗口外的线段,而窗口内的线段却只有一条。这一点很重要,它意味着要确定窗口内的线段,只要计算出它位于窗口内的两个端点。丹科恩和伊凡.瑟萨兰德就根据这一思路设计出了线段裁剪的算法。这种算法分为两步:第一步先确定该线段是否整个位于窗口内或全部位于窗口外,若属于这两种情况,则全部保留或全部舍弃;第二步对不属于第一步那两种情况的线段,则被窗口某一边界线分成两部分,再对每一部分进行第一步。具本这两步留舍测试如下进行:延长窗口各边界,将窗口及其周围共划分为九个区域,中央就是所要裁剪的区域。每个区域各用一个四位二进制数组成的代码(即代码中每一位分别为0或1)来表示,如图2-7所示。

ef97c2aa5552a2316a92a5ada8d41494.png

当线的一端点位于某一区域时,便将该区域的代码赋予端点。然后根据线从而段两端点代码就能很方便地判断出线段相对于窗口的位置关系,并决定对该线段如何进行裁剪。四位代码中每位(位的顺序由右向左排序)代码的意义如下:

第一位,点在窗口左边界线之左为1,否则为0;

第二位,点在窗口右边界线之右为1,否则为0;

第三位,点在窗口底边界线之下为1,否则为0;

第四位,点在窗口顶边界线之上为1,否则为0。

对线段进行测试时,首先对全部保留和全部舍弃线段这两种情况进行判断,即

1、当线段两端点的四位代码全由零组成时,则表示两端点均在窗口内,要全部保留该线段。

2、当线段的四位代码逻辑乘不等于零时,则表示两个端点的代码中有一相同位,同时为1;若线段两个端点在侣边界线外的同侧位置,则整个线段在窗口之外,应予全部舍弃。如图2-6中各线段端点代码(或称编码)逻辑乘如表2-1所示。

表 2-1 线段端点代码及其逻辑

----------------------------------------------------------------------

线段           端点代码             逻辑乘           注释

(见图2-6)   (见图2-7中代码规则)                    (窗口内为可见)

----------------------------------------------------------------------

AB         0 0 0 1   0 0 1 0        0 0 0 0         部分可见

CD         0 1 0 0   0 1 0 0        0 1 0 0         不可见

EF         0 0 0 1   1 0 0 0        0 0 0 0         不可见

MN         0 0 0 0   0 0 0 0        0 0 0 0         可  见

PQ         0 0 1 0   0 0 0 0        0 0 0 0         部分可见

----------------------------------------------------------------------

由表2-1可得知,当线段两端点逻辑乘非零时,则线段不可见。但当线段两端点逻辑乘为零时,则有三种情形:可见,部分可见与不可见,因此这时不需要对端两端点代码分别进行检查。

如果线段不能通过上述两种测试判断为保留或舍弃,则必须求出线段与窗口边界线的交点,即分割 线段 ,舍弃在窗口外同侧的部分线段,对留下的线段重复进行上述两种情况的判断,直到留下的线段符合上述两种情况之一为止。

二、多边形裁剪

多边形裁剪比线段裁剪要复杂许多。多边形裁剪需要解决两个问题:一是一个完整封闭的多边形经剪裁后不再是封闭的,需要用窗口边界的适当部分来封闭它;二是边界线段的边接,不适当的连接会产生错误。另外如果对多边形相对于窗口的四条边同时进行裁剪,那么很难算出应该使用窗口的哪些边界线段来封闭图形。但相对于窗口的一条边界线来裁剪多边形就比较容易,并由此可提出多边形裁剪算法。

下面介绍多边形裁剪算法(逐边裁剪法)。

伊凡.瑟萨兰德和格雷霍奇曼1974年对多边形裁剪提 出了逐边裁剪算法。他们的思路是,把多边形裁剪这样一个整体问题分割成一系列简单问题,这些简单问题解决了,对整体也解决了。具体算法是:把整个多边形先相对于窗口的第一条边界线进行裁剪,形成一个新的多边形;然后再把这个新的多边形相对于窗口的第二条边界线进行裁剪、再次形成一个新的多边形;接着用窗口的第三条边、第四条边依次进行如此剪裁,最后形成一个整个多边形经过窗口的四条边界线裁剪后的多边形。这个多边形裁剪过程如图2-8所示。

06472327049e5fede20f53ad78292dbc.png

这个算法看起来好像要很大的内存保留中间数据,其实不然,它可以采用递归方式调用同一算法,整个裁剪过程由四级同样的算法组成。每一级相对于窗口的四条边界线之一来剪裁,第一级输出的顶点传送给第二级(即把多边形每个顶点相对于第一条边界线裁剪,所形成的多边形顶点作为下一步裁剪过程输入),第二级的顶点输出传送给第三级,依此类推,最后一级产生的顶点就构成经过裁剪的多边形。具体实现采用一个数组存放原始多边形的顶点坐标,再设置一个待裁剪多边形顶点坐标数组,用来存放经某条窗口边界线裁剪后所生成的顶点坐标,不妨把这个数组称为新多边形数组,最后新多边形数组存放的是经所有窗口边界裁剪完毕而得到的结果多边形的顶点坐标。

设与多边形的顶点为P1、P2、P3、......P

n,多边形的各条边线分别为顶点P1与P2、P2与P3、......、Pn与P1的连线,其中Pn与P1的连线为多边形的封闭边。多边形在裁剪后应得到一个或几个新的多边形,其顶点为Q1、Q2、Q3......、Qn, 主要任务就是求得这些新的顶点。其过程是,首先依次按照窗口的一条边界线L对多边形的顶点Pi(i=1,2,3...,n)进行检查。若顶点在边界L以内,则保留该顶点作为裁剪后新的顶点,反之则予以舍弃。同时对于顶点Pi是否与前一顶点Pi-1处于窗口边解甲归田线L的同侧位置,还须进行检查。若它们分别位于窗口边蜀线的两侧,则应计算边线Pi-1Pi与窗口边线L的交点,并将交点保留下来作为裁剪后新的顶点输出。显然对于多边形的第一个顶点P1来说,上述后一顶检查无意义可以省略。当检查最末一个顶点Pn时,除了进行上述检查外,还须对多边形的封闭边PnP1进行检查。若封闭边PnP1与窗口边界线L相交,则应计算这一点并予以保留。这样通过以上检查便保留并输出各顶点Q1、Q2、Q3、......Qn,在这些顶点之间依次联成边线,即可得到裁剪后新的多边形。



推荐阅读
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 开发笔记:计网局域网:NAT 是如何工作的?
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了计网-局域网:NAT是如何工作的?相关的知识,希望对你有一定的参考价值。 ... [详细]
  • C语言判断正整数能否被整除的程序
    本文介绍了使用C语言编写的判断正整数能否被整除的程序,包括输入一个三位正整数,判断是否能被3整除且至少包含数字3的方法。同时还介绍了使用qsort函数进行快速排序的算法。 ... [详细]
  • 本文详细解析了JavaScript中相称性推断的知识点,包括严厉相称和宽松相称的区别,以及范例转换的规则。针对不同类型的范例值,如差别范例值、统一类的原始范例值和统一类的复合范例值,都给出了具体的比较方法。对于宽松相称的情况,也解释了原始范例值和对象之间的比较规则。通过本文的学习,读者可以更好地理解JavaScript中相称性推断的概念和应用。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 给定一个二维平面上的一些点,通过计算曼哈顿距离,求连接所有点的最小总费用。只有任意两点之间有且仅有一条简单路径时,才认为所有点都已连接。给出了几个示例并给出了对应的输出。 ... [详细]
  • 本文介绍了基于c语言的mcs51单片机定时器计数器的应用教程,包括定时器的设置和计数方法,以及中断函数的使用。同时介绍了定时器应用的举例,包括定时器中断函数的编写和频率值的计算方法。主函数中设置了T0模式和T1计数的初值,并开启了T0和T1的中断,最后启动了CPU中断。 ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • 本文介绍了游戏开发中的人工智能技术,包括定性行为和非定性行为的分类。定性行为是指特定且可预测的行为,而非定性行为则具有一定程度的不确定性。其中,追逐算法是定性行为的具体实例。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
author-avatar
手机用户2502893987
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有