我正在努力实现“快速抗锯齿圆圈生成器”例程,吴晓林在他的论文“一种有效的抗锯齿技术”中描述了 Siggraph '91。
这是我使用 Python 3 和 PySDL2 编写的代码:
def draw_antialiased_circle(renderer, position, radius):
def _draw_point(renderer, offset, x, y):
sdl2.SDL_RenderDrawPoint(renderer, offset.x - x, offset.y + y)
sdl2.SDL_RenderDrawPoint(renderer, offset.x + x, offset.y + y)
sdl2.SDL_RenderDrawPoint(renderer, offset.x - x, offset.y - y)
sdl2.SDL_RenderDrawPoint(renderer, offset.x + x, offset.y - y)
i = 0
j = radius
d = 0
T = 0
sdl2.SDL_SetRenderDrawColor(renderer, 255, 255, 255, sdl2.SDL_ALPHA_OPAQUE)
_draw_point(renderer, position, i, j)
while i < j + 1:
i += 1
s = math.sqrt(max(radius * radius - i * i, 0.0))
d = math.floor(sdl2.SDL_ALPHA_OPAQUE * (math.ceil(s) - s) + 0.5)
if d < T:
j -= 1
T = d
if d > 0:
alpha = d
sdl2.SDL_SetRenderDrawColor(renderer, 255, 255, 255, alpha)
_draw_point(renderer, position, i, j)
if i != j:
_draw_point(renderer, position, j, i)
if (sdl2.SDL_ALPHA_OPAQUE - d) > 0:
alpha = sdl2.SDL_ALPHA_OPAQUE - d
sdl2.SDL_SetRenderDrawColor(renderer, 255, 255, 255, alpha)
_draw_point(renderer, position, i, j + 1)
if i != j + 1:
_draw_point(renderer, position, j + 1, i)
j而不是 i因为要么我误解了什么,要么他的论文有错误。事实上,他初始化了 i与半径值,j与 0 ,然后定义循环条件 i <= j仅当半径为 0 时才为真.此更改使我对所描述的内容进行了其他一些小的修改,并且我还更改了 if d > T至 if d < T只是因为它看起来很破。
(sqrt(2) / 2, sqrt(2) / 2) 区域),也出现了严重的错误。我设法通过更改 if d < T 使最后一个问题消失了。条件到 if d <= T ,但同样的问题随后出现在每个八分圆的开头。最佳答案
让我们解构您的实现以找出您犯了哪些错误:
def draw_antialiased_circle(renderer, position, radius):
radius意思?画圆是不可能的,你只能画一个圆环(一个圆环/甜甜圈),因为除非你有一定的厚度你是看不到它的。因此半径不明确,是内半径,中点半径还是外半径?如果你没有在变量名中指定,它会变得困惑。或许我们可以一探究竟。def _draw_point(renderer, offset, x, y):
sdl2.SDL_RenderDrawPoint(renderer, offset.x - x, offset.y + y)
sdl2.SDL_RenderDrawPoint(renderer, offset.x + x, offset.y + y)
sdl2.SDL_RenderDrawPoint(renderer, offset.x - x, offset.y - y)
sdl2.SDL_RenderDrawPoint(renderer, offset.x + x, offset.y - y)
i = 0
j = radius
d = 0
T = 0
i到 0 和 j到半径,这些必须是 x和 y坐标。什么是d和 T ?非描述性的变量名称无济于事。复制科学家的算法以使用您知道的更长的变量名称使它们真正可以理解时,这是可以的!sdl2.SDL_SetRenderDrawColor(renderer, 255, 255, 255, sdl2.SDL_ALPHA_OPAQUE)
_draw_point(renderer, position, i, j)
(0, radius)中的正方形完全不透明。所以现在我们知道了什么 radius即,它是环的外半径,环的宽度显然是一个像素。或者至少,这就是这个特殊情况告诉我们的……让我们看看这是否适用于通用代码。while i < j + 1:
i > j ,然后停止。 IE。我们正在绘制一个八分圆。 i += 1
i = 0处绘制了我们关心的所有像素。位置,让我们进入下一个。 s = math.sqrt(max(radius * radius - i * i, 0.0))
s是一个浮点数,它是点 i 处八分圆的 y 分量在 x 轴上。 IE。 x 轴上方的高度。出于某种原因,我们有一个 max在那里,也许我们担心非常小的圆圈……但这并不能告诉我们该点是否在外半径/内半径上。 d = math.floor(sdl2.SDL_ALPHA_OPAQUE * (math.ceil(s) - s) + 0.5)
(math.ceil(s) - s)给我们一个 0 到 1.0 之间的数字。此数字将增加为 s减少,所以 i增加,然后一旦达到 1.0 将重置为 0.0,因此呈锯齿状。sdl2.SDL_ALPHA_OPAQUE * (math.ceil(s) - s)提示我们使用锯齿输入来生成一定程度的不透明,即消除圆圈的锯齿。 0.5 常数添加似乎没有必要。 floor()表明我们只对整数值感兴趣——可能 API 只接受整数值。这一切表明d最终是介于 0 和 SDL_ALPHA_OPAQUE 之间的整数级别,从 0 开始,然后逐渐增加为 i增加,那么当 ceil(s) - s从 1 回到 0,它也再次回落到低点。s差不多radius自 i是 1,(假设一个非平凡大小的圆)所以假设我们有一个整数半径(第一个特殊情况代码显然是假设的)ceil(s) - s是 0 if d < T:
j -= 1
d = T
d已经从高变低,我们向下移动屏幕,这样我们的 j位置保持在理论上应该靠近戒指的位置。d是 100.9。然后在下一次迭代中它下降了,但仅下降到 100.1。因为 d和 T相等,因为地板消除了它们的差异,我们不递减j在这种情况下,这是至关重要的。我想可能解释了八分圆末端的奇怪曲线。if d < 0:
alpha = d
sdl2.SDL_SetRenderDrawColor(renderer, 255, 255, 255, alpha)
_draw_point(renderer, position, i, j)
d低,所以这很吸引 (1, radius)一个几乎完全透明的元素。但是开始的特殊情况为 (0, radius) 绘制了一个完全不透明的元素。 ,很明显这里会出现图形故障。这就是你所看到的。if i != j:
_draw_point(renderer, position, j, i)
_draw_point() 中只画了 4 个点。 ,因为你在这里做了另一个对称。它会简化您的代码,而不是。if (sdl2.SDL_ALPHA_OPAQUE - d) > 0:
alpha = sdl2.SDL_ALPHA_OPAQUE - d
sdl2.SDL_SetRenderDrawColor(renderer, 255, 255, 255, alpha)
_draw_point(renderer, position, i, j + 1)
import math
def draw_antialiased_circle(outer_radius):
def _draw_point(x, y, alpha):
# draw the 8 symmetries.
print('%d:%d @ %f' % (x, y, alpha))
i = 0
j = outer_radius
last_fade_amount = 0
fade_amount = 0
MAX_OPAQUE = 100.0
while i < j:
height = math.sqrt(max(outer_radius * outer_radius - i * i, 0))
fade_amount = MAX_OPAQUE * (math.ceil(height) - height)
if fade_amount < last_fade_amount:
# Opaqueness reset so drop down a row.
j -= 1
last_fade_amount = fade_amount
# The API needs integers, so convert here now we've checked if
# it dropped.
fade_amount_i = int(fade_amount)
# We're fading out the current j row, and fading in the next one down.
_draw_point(i, j, MAX_OPAQUE - fade_amount_i)
_draw_point(i, j - 1, fade_amount_i)
i += 1
outer_radius ,算法在 (0, outer_radius - 1) 处绘制一个 100% 不透明的正方形地点。但是,如果您想转换为 (0, 0.5)位置,您可能希望圆在 (0, outer_radius - 1) 处平滑地混叠至 50% 的不透明度。和 (0, outer_radius)位置,这个算法没有给你,因为它忽略了原点。因此,如果您想准确地使用此算法,则必须在传入原点之前对其进行四舍五入,因此使用浮点数没有任何好处。
关于python - 绘制一个由 Xaolin Wu 描述的抗锯齿圆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37589165/
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?
我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案
我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b
我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的rubyyaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir
我的问题的一个例子是体育游戏。一场体育比赛有两支球队,一支主队和一支客队。我的事件记录模型如下:classTeam"Team"has_one:away_team,:class_name=>"Team"end我希望能够通过游戏访问一个团队,例如:Game.find(1).home_team但我收到一个单元化常量错误:Game::team。谁能告诉我我做错了什么?谢谢, 最佳答案 如果Gamehas_one:team那么Rails假设您的teams表有一个game_id列。不过,您想要的是games表有一个team_id列,在这种情况下