按Xaolin Wu的描述绘制一个反锯齿圆(Drawing an antialiased circle as described by Xaolin Wu)
我希望实施由吴小林在Siggraph '91发表在他的论文“An Efficient Antialiasing Technique”中的“Fast Anti-Aliased Circle Generator”例程。
这是我使用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
,我也改变了if d > T
只是因为它看起来不对。除了每个八分圆的开始和结束时,这个实现大部分工作得很好,在那里出现了一些毛刺。
上面的圆的半径为1.正如您可以在每个八分圆的开始处所看到的那样(例如在(0,1)区域中),循环内绘制的像素不与在第一个像素之前绘制的第一个像素对齐循环开始。 另外,在每个八分区结束时(例如
(sqrt(2) / 2, sqrt(2) / 2)
区域)都会出错。 我设法通过将if d < T
条件改为if d <= T
来消除这个最后一个问题,但是同样的问题会在每个八分圆的开始处出现。问题1 :我做错了什么?
问题2 :如果我希望输入位置和半径是浮点,会不会有任何疑问 ?
I'm tyring to implement the “Fast Anti-Aliased Circle Generator” routine that was described by Xiaolin Wu in his paper “An Efficient Antialiasing Technique” from Siggraph '91.
This is the code that I wrote using Python 3 and 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)
This is a naive implementation of what I believe is being described in his paper, at the exception that I assigned the radius value to
j
instead ofi
because either I misunderstand something or there's a mistake in his paper. Indeed, he initializesi
with the radius value,j
with0
, and then defines the loop conditioni <= j
which can only be true when the radius is0
. This change led me to make some other minor modifications from what's described, and I also changedif d > T
toif d < T
simply because it looked broken otherwise.This implementation works mostly well except at the start and the end of each octant, where some glitches appear.
The circle above has a radius of 1. As you can see at the start of each octant (such as in the (0, 1) area), the pixels drawn within the loop are not aligned to the first pixel that is drawn before the loop starts. Also something goes awfully wrong towards the end of each octant (such as in the
(sqrt(2) / 2, sqrt(2) / 2)
area). I managed to make this last issue disappear by changing theif d < T
condition toif d <= T
, but the same problem then shows up at the start of each octant.Question 1: What am I doing wrong?
Question 2: Would there be any gotcha if I wanted the input position and radius to be floating points?
原文:https://stackoverflow.com/questions/37589165
最满意答案
相关问答
更多-
运行时是我认为的标准NuGet 包的一部分。 The runtime is part of a standard NuGet package going forward I believe.
-
你在这里混淆了几个概念。 只是因为一个版本稍后发布,并不意味着它有更多的功能。 .NET Core 1.0是一个LTS版本,将提供2或3年iirc的更新。 所以即使在1.1发布之后,还将有1.0的维护来修复错误或安全问题。 在软件开发中一直是这样,看看Java。 Java 1.8发布后,还有Java 1.7的更新。 .NET Core SDK包含用于恢复软件包,构建,部署和运行.NET Core应用程序的dotnet cli工具,它还包含提供框架DLL(如.NET Framework 4.x设置)的.NET ...
-
.NET核心运行时(.NET Core Runtime)[2022-03-07]
win32-x64不是有效的运行时标识符。 改为使用win-x64或查看.NET Core RID目录以获取有效的运行时标识符列表。 win32-x64 is not a valid runtime identifier. Use win-x64 instead or see the .NET Core RID Catalog for a list of valid runtime identifiers. -
您是否将Visual Studio更新到15.7.1版? 我在更新到2.1.0-rc1-final后运行asp核心应用程序时遇到问题,我也安装了最新的sdk,但输出是: dotnet.exe' has exited with code -2147450730 解决方案是更新Visual Studio,现在一切正常。 更新:现在我看到,您还没有安装适当的SDK和运行时来运行此版本。 您必须安装.NET Core 2.1 RC1 SDK和最新的运行时。 Have you updated Visual Stud ...
-
将http://registry.npmjs.org添加到我的代理绕过解决了这个问题,所以它实际上是我的代理设置 Adding http://registry.npmjs.org to my Proxy Bypass resolved this issue, so it in fact was my proxy settings
-
您正在查看v0.16版本的教程 - 现在已经过时了,除非您特别使用此版本,否则您应该使用最新的文档和最新的 Composer版本。 最新的文档在这里: https : //hyperledger.github.io/composer/latest/tutorials/developer-tutorial 用Composer composer -v检查你的Composer版本,希望你使用v0.19.6或类似的。 (Composer运行时安装是一个v0.16命令,不再存在于v0.19中。* - 新的命令在本教程 ...
-
我找出了导致问题的原因,C ++ / CLI dll被编译为x64。 ASP.NET运行时似乎并不那样,只能在Win32或AnyCPU平台上运行,即使代码编译和运行。 C ++ / CLI项目的唯一两个平台选项是Win32和x64,我需要它是x64,因为它要发布到Azure云,但这会导致这些运行时错误,另一方面Win32会根本不在Azure上运行。 我最终做的是创建一个C#包装器,使用P / Invoke直接调用我的C库,因为C#项目平台设置可以设置为“AnyCPU”,所以现在错误消失了。 总而言之,如果您 ...
-
使用C ++ / CLI中的ConcRT在concrt.h中通过以下语句显式禁用,因为它不受官方支持... #if defined(_M_CEE) #error ERROR: Concurrency Runtime is not supported when compiling /clr. #endif 您可以使用PInvoke来解决上面建议的问题,或者您也可以使用指向实现惯用语的指针通过向前声明一个'pimpl'类来解决这个问题,并将对concrt.h的依赖隐藏到本机.cpp文件中,您可以然后编译 ...
-
除了其他.Net语言具有的依赖关系(例如.Net框架)之外,C ++ / CLI还需要C ++运行时。 您可以从Microsoft 下载适用于VS 2012的C ++运行时可再发行组件。 根据C ++ / CLI程序集的编译设置选择x86或x64版本,而不是目标计算机正在运行的Windows版本。 请注意,这只是Release编译的运行时。 调试编译使用不同的运行时,该运行时没有可再发行的,并且仅与Visual Studio一起安装。 In addition to the dependencies that ...
-
如果我在VS 2010中使用C ++ / CLI,我需要哪个VC ++运行时?(Which VC++ Runtime do I need if I'm using C++/CLI in VS 2010?)[2022-09-10]
你的工作将通过使用这个完成。 Visual C ++ 2008 - 2 MB 我使用的是同样的。 your job ll be done by using this one. Visual C++ 2008 -- 2 MB I am using the same.