我试图在Lua或基于VB的代码中创建一个函数 绘制/绘制椭圆和填充椭圆。
我对这个数学知之甚少,我可以帮忙。
我用google搜索谷歌关于使用代码绘制省略号的所有内容,但我找不到一个简单的工作示例,我可以将其编码到我的Lua / VB代码中。
以下是我访问过的一些网站,但无法使代码正常工作或无法正常将代码转换为Lua或VB ...
http://groups.csail.mit.edu/graphics/classes/6.837/F98/Lecture6/circle.html
http://www.sourcecodesworld.com/source/show.asp?ScriptID=112
How do I draw an ellipse with arbitrary orientation pixel by pixel?
任何人都可以帮我制作可以绘制椭圆和填充椭圆的代码吗?
这里是我尝试从这里转换为Lua的一些代码:
https://gist.github.com/Wollw/3291916
此代码存在一些问题(缺少像素),我认为它没有正确转换,但我不知道该怎么做。
function plotEllipseRect(x0, y0, x1, y1)
-- values of diameter
a = math.abs(x1-x0)
b = math.abs(y1-y0)
b1 = 2.5
-- error increment
dx = 4*(1-a)*b*b
dy = 4*(b1+1)*a*a
-- error of 1.step
err = dx+dy+b1*a*a
-- e2 = 0
if (x0 > x1) then -- if called with swapped points
x0 = x1
x1 = x1 + a
end
if (y0 > y1) then -- .. exchange them
y0 = y1
end
-- starting pixel
y0 = y0 + (b+1)/2
y1 = y0-b1
a = a * 8*a
b1 = 8*b*b
repeat
dot(x1, y0) -- I. Quadrant
dot(x0, y0) -- II. Quadrant
dot(x0, y1) -- III. Quadrant
dot(x1, y1) -- IV. Quadrant
e2 = 2*err
if (e2 <= dy) then -- y step
y0 = y0 + 1
y1 = y1 - 1
dy = dy + a
err = err + dy
end
if (e2 >= dx or 2*err > dy) then -- x step
x0 = x0 + 1
x1 = x1 - 1
dx = dx + b1
err = err + dx
end
until (x0 >= x1)
while (y0-y1 < b) do -- too early stop of flat ellipses a=1
dot(x0-1, y0) -- -> finish tip of ellipse
y0 = y0 + 1
dot(x1+1, y0)
dot(x0-1, y1)
y1 = y1 - 1
dot(x1+1, y1)
end
end
[编辑:]
我几乎得到了填充的一个! 请参阅下面的代码中的注释,以了解问题所在...
我使用EGSL来测试这个Lua代码: http://www.egsl.retrogamecoding.org//pages/downloads.php
function DrawEllipse(xc,yc,w,h)
local w2 = w * w
local h2 = h * h
local fw2 = 4 * w2
local fh2 = 4 * h2
xc = xc + w
yc = yc + h
local x = 0
local y = h
local s = 2 * h2 + w2 * (1 - h)
while h2 * x <= w2 * y do
dot(xc + x, yc + y)
dot(xc - x, yc + y)
dot(xc + x, yc - y)
dot(xc - x, yc - y)
redraw()
inkey()
color(int(rnd()*255),int(rnd()*255),int(rnd()*255)) --random color to see changes
if s >= 0 then
s = s + fw2 * (1 - y)
y = y - 1
color(255,0,255)
line(xc + x, yc + y, xc - x, yc + y)
line(xc + x, yc - y, xc - x, yc - y)
end
s = s + h2 * ((4 * x) + 6)
x = x + 1
end
x = w
y = 0
s = 2 * w2 + h2 * (1 - w)
line(xc + x, yc + y, xc - x, yc + y) --to prevent the first line to be drawn twice
redraw()
inkey()
s = s + w2 * ((4 * y) + 6)
y = y + 1
while w2 * y < h2 * (x-2) do
line(xc + x, yc + y, xc - x, yc + y)
redraw()
inkey()
color(int(rnd()*255),int(rnd()*255),int(rnd()*255))
line(xc + x, yc - y, xc - x, yc - y)
redraw()
inkey()
color(int(rnd()*255),int(rnd()*255),int(rnd()*255))
if s >= 0 then
s = s + fh2 * (1 - x)
x = x - 1
end
s = s + w2 * ((4 * y) + 6)
y = y + 1
end
dot(xc + x, yc + y)
dot(xc - x, yc + y)
redraw()
inkey()
color(int(rnd()*255),int(rnd()*255),int(rnd()*255))
dot(xc + x, yc - y)
dot(xc - x, yc - y)
redraw()
inkey()
end
openwindow (70,70,32,"Resize Window")
color(255,255,0)
DrawEllipse(10,10,20,20) --works perfect!
inkey()
cls()
DrawEllipse(10,10,10,20) --problems with last 2 horizontal lines between the pixels!
inkey()
cls()
DrawEllipse(10,10,20,10) --works perfect to!
closewindow()
答案 0 :(得分:1)
以下VB适用于我,基于提供的第一个链接;我这里和链接代码之间的唯一区别是我移动xc和yc,因为你不能在位图中为像素设置负x或y值。
Public Shared Function DrawEllipse(ByVal xc As Integer, ByVal yc As Integer, ByVal w As Integer, ByVal h As Integer, ByVal doFill As Boolean) As Drawing.Bitmap
Dim w2 As Integer = w * w
Dim h2 As Integer = h * h
Dim fw2 As Integer = 4 * w2
Dim fh2 As Integer = 4 * h2
// cheat by moving xc and yc so that we can handle quadrants
xc = w
yc = h
Dim bm As New Drawing.Bitmap(w2, h2)
// first half
Dim x As Integer = 0
Dim y As Integer = h
Dim s As Integer = 2 * h2 + w2 * (1 - h)
While h2 * x <= w2 * y
If doFill Then
For i As Integer = -y To y
bm.SetPixel(xc + x, yc + i, Drawing.Color.Red)
bm.SetPixel(xc - x, yc + i, Drawing.Color.Red)
Next
Else
bm.SetPixel(xc + x, yc + y, Drawing.Color.Red)
bm.SetPixel(xc - x, yc + y, Drawing.Color.Red)
bm.SetPixel(xc + x, yc - y, Drawing.Color.Red)
bm.SetPixel(xc - x, yc - y, Drawing.Color.Red)
End If
If s >= 0 Then
s += fw2 * (1 - y)
y -= 1
End If
s += h2 * ((4 * x) + 6)
x += 1
End While
// second half
x = w
y = 0
s = 2 * w2 + h2 * (1 - w)
While w2 * y <= h2 * x
If doFill Then
For i As Integer = -x To x
bm.SetPixel(xc + i, yc + y, Drawing.Color.Red)
bm.SetPixel(xc + i, yc - y, Drawing.Color.Red)
Next
Else
bm.SetPixel(xc + x, yc + y, Drawing.Color.Red)
bm.SetPixel(xc - x, yc + y, Drawing.Color.Red)
bm.SetPixel(xc + x, yc - y, Drawing.Color.Red)
bm.SetPixel(xc - x, yc - y, Drawing.Color.Red)
End If
If s >= 0 Then
s += fh2 * (1 - x)
x -= 1
End If
s += w2 * ((4 * y) + 6)
y += 1
End While
Return bm
End Function
(旁白:我使用//而不是'用于评论......只是为了提高可读性。如果你复制到Visual Studio,你将不得不修复它)
答案 1 :(得分:1)
好的,我通过检查找到了填充椭圆的解决方案 如果来自后半部分的像素将被绘制在椭圆的前半部分的x范围内。
function drawellipse(xc, yc, w, h, dofill)
--trouble with the size, 1 pixel to large on x and y to...
w=w/2 --good solution for making it the right size?
h=h/2 --good solution for making it the right size?
local w2 = w * w
local h2 = h * h
local fw2 = 4 * w2
local fh2 = 4 * h2
-- cheat by moving xc and yc so that we can handle quadrants
xc = xc + w
yc = yc + h
-- first half
local x = 0
local y = h
local s = 2 * h2 + w2 * (1 - h)
while h2 * x <= w2 * y do
if dofill then
for i = -y , y do
color(0,255,0)
dot(xc + x, yc + i)
dot(xc - x, yc + i)
--redraw()inkey()
end
else
color(255,0,255)
dot(xc + x, yc + y)
dot(xc - x, yc + y)
dot(xc + x, yc - y)
dot(xc - x, yc - y)
--redraw()inkey()
end
if s >= 0 then
s =s+ fw2 * (1 - y)
y =y- 1
end
s =s+ h2 * ((4 * x) + 6)
x =x+ 1
end
color(255,0,255)
line(xc + x,0,xc - x,0)
test1 = xc + x
test2 = xc - x
print(test1 .. '/' .. test2)
redraw()inkey()
-- second half
x = w
y = 0
s = 2 * w2 + h2 * (1 - w)
while w2 * y <= h2 * x do
if dofill then
for i = -x , x do
if not(xc + i > test2 and xc + i < test1) then
color(255,255,0)
dot(xc + i, yc + y)
dot(xc + i, yc - y)
redraw()inkey()
end
end
else
color(0,255,255)
dot(xc + x, yc + y)
dot(xc - x, yc + y)
dot(xc + x, yc - y)
dot(xc - x, yc - y)
redraw()inkey()
end
if s >= 0 then
s =s+ fh2 * (1 - x)
x =x- 1
end
s =s+ w2 * ((4 * y) + 6)
y =y+ 1
end
end
答案 2 :(得分:0)
在vb.net中,你有Graphics.DrawEllipse和Graphics.DrawArc。在Lua你可以使用Cairo,我知道它有弧功能。
如果您在.Net中的GraphicsPath中制作椭圆的位置以及在何处对其存储在内存中的方式进行反向工程,您会发现它存储为四条贝塞尔曲线。我在vb.net中实现了自己的图形库一次,这就是我做的。我在Actionscript中实现的最佳资源,遗憾的是我无法找到我正在讨论的图形库。
TLDR;你应该看看贝塞尔曲线。
答案 3 :(得分:0)
这是一个完全不同的,非常简单的看法,虽然椭圆看起来并不像#34;漂亮&#34;作为其他算法;这只是使用椭圆的数学定义,并且循环x计算给定x,w和h的y坐标。
Public Shared Function DrawEllipse2(ByVal xc As Integer, ByVal yc As Integer, ByVal w As Integer, ByVal h As Integer, ByVal doFill As Boolean) As Drawing.Bitmap
Dim bm As New Drawing.Bitmap(w * w, h * h)
For x As Integer = xc - w To xc + w
Dim y As Integer = CInt((Math.Sqrt(1 - ((x * x) / (w * w)))) * h)
If doFill Then
For j As Integer = -y To y
bm.SetPixel(w + x, h + j, Drawing.Color.Red)
Next
Else
bm.SetPixel(w + x, h + y, Drawing.Color.Red)
bm.SetPixel(w + x, h - y, Drawing.Color.Red)
End If
Next
Return bm
End Function