C# 动态画线的方法

kfheimao 2011-10-18 03:53:21
简单的说就是类似windows自带的画图板中的刷子
但是我发现一个问题
就是系统自带的画的线也不是很平滑
我采用的是定义一个arraylist
在移动鼠标的时候坐标ADD到arraylist里
最后鼠标键放开的时候按照arraylist里的点逐个连接起来画
但是发现似乎运行效率很低,有时候棱角分明
如果电脑卡的时候还 会出现线断掉的情况
我发现像PS、SAI、那些软件就不会出现那种情况,看着比系统自带的平滑的多
请问大家有没有好的方法呢
...全文
626 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
kfheimao 2011-10-20
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 skyparty 的回复:]
引用 7 楼 kfheimao 的回复:
如果鼠标移动的快了获取的点会较少,画出的线很不平滑

对的,鼠标移动快的时候折线很明显,可以用贝塞尔曲线代替直线试试效果

那个像素补偿的算法比较复杂,太久没碰,记不清楚了
本质上就是判断曲线在哪个位置可能缺少一个像素,就给他加上
因为曲线是连续的,像素是离散的整数,所以在离散化的时候就会有缺陷,表现出来就是锯齿了
理论上锯齿是不可避免的,……
[/Quote]
非常感谢你说的。。。虽然还是没点我想要的资料
但是给了我一个方向性的东西,呵呵
谢谢啦
kfheimao 2011-10-19
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 skyparty 的回复:]
画线是要做特殊处理的,楼主可以看看像素填充的一些算法
根据线的斜率做一些补偿
[/Quote]
麻烦能举个例子么?
不胜感激
小赖赖 2011-10-19
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 kfheimao 的回复:]
如果鼠标移动的快了获取的点会较少,画出的线很不平滑
[/Quote]
对的,鼠标移动快的时候折线很明显,可以用贝塞尔曲线代替直线试试效果

那个像素补偿的算法比较复杂,太久没碰,记不清楚了
本质上就是判断曲线在哪个位置可能缺少一个像素,就给他加上
因为曲线是连续的,像素是离散的整数,所以在离散化的时候就会有缺陷,表现出来就是锯齿了
理论上锯齿是不可避免的,差别只在于肉眼能否分辨出而已
kfheimao 2011-10-19
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 skyparty 的回复:]
引用 4 楼 kfheimao 的回复:
麻烦能举个例子么?
不胜感激

定义直线方程为ax+by+c=0;(x,y为屏幕上的坐标)
画线时,计算直线上的每个点,逐一画出,模拟连续直线

当a或b为0的时候,
假设a=0,用for(x=0;x<1024;++x){DrawPoint(x,-c/b);}这时画的线是平滑的

当a,b都不为0时,如果还用for(x=0;x<1024……
[/Quote]

还有个问题是,我发现当鼠标在一定区域移动
我用鼠标的MOVE事件来获取坐标
如果鼠标移动的快了获取的点会较少,画出的线很不平滑
如果慢点的话,会好很多
kfheimao 2011-10-19
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 skyparty 的回复:]
引用 4 楼 kfheimao 的回复:
麻烦能举个例子么?
不胜感激

定义直线方程为ax+by+c=0;(x,y为屏幕上的坐标)
画线时,计算直线上的每个点,逐一画出,模拟连续直线

当a或b为0的时候,
假设a=0,用for(x=0;x<1024;++x){DrawPoint(x,-c/b);}这时画的线是平滑的

当a,b都不为0时,如果还用for(x=0;x<1024……
[/Quote]
哇。。万分感谢啊。。
很想知道那个做像素补偿点是大概怎么个做法呢?
从来没接触这个方面啊。。。。
小赖赖 2011-10-19
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 kfheimao 的回复:]
麻烦能举个例子么?
不胜感激
[/Quote]
定义直线方程为ax+by+c=0;(x,y为屏幕上的坐标)
画线时,计算直线上的每个点,逐一画出,模拟连续直线

当a或b为0的时候,
假设a=0,用for(x=0;x<1024;++x){DrawPoint(x,-c/b);}这时画的线是平滑的

当a,b都不为0时,如果还用for(x=0;x<1024;++x){DrawPoint(x,(-c-a*x)/b);}画线,就会出现锯齿或者断点,而当a,b之间的差距越大时,锯齿或断点越明显
为平滑直线,
第一步:防止断点
判断a,b的大小,a大就用x做循环,b大则要用y做循环
现假设a大,循环应该为for(y=0;y<768;++y){DrawPoint((-c-b*y)/a,y;}//就是要当一个坐标递增1时,另一个坐标的递增不超过1,否则就会出现断点
而屏幕坐标都是整数,所以x坐标应该被取整,
这时会发现如果用4舍5入取整,整体的x值会略微偏大,正确的做法应该是5逢偶进位,逢奇截断,假设这个取整函数为intx
for(y=0;y<768;++y){DrawPoint(intx(-c-b*y)/a,y;}

第二步:平滑锯齿
如果直线很细,就是每个点的像素为1*1,那么锯齿是肯定有的
需要增加直线的粗度,比如为5,并在不够平滑的地方,增加一些像素点做补偿
这个算法比较复杂,这里说不清楚

曲线同理
小赖赖 2011-10-18
  • 打赏
  • 举报
回复
画线是要做特殊处理的,楼主可以看看像素填充的一些算法
根据线的斜率做一些补偿
kfheimao 2011-10-18
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 gomoku 的回复:]
下贴2楼有个示例代码。
http://topic.csdn.net/u/20110418/16/88f31d34-c293-4f84-ba59-77a81638b1b2.html
[/Quote]
确实有点改善。。。但是还是有点看着不自然啊
gomoku 2011-10-18
  • 打赏
  • 举报
回复
下贴2楼有个示例代码。
http://topic.csdn.net/u/20110418/16/88f31d34-c293-4f84-ba59-77a81638b1b2.html

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧