绘制椭圆基于sqrt的函数

时间:2015-05-21 21:07:06

标签: vb.net plot lua draw ellipse

我试图在Lua或基于VB的代码中创建一个函数 绘制/绘制椭圆和填充椭圆。

我对这个数学知之甚少,我可以帮忙。

我用google搜索谷歌关于使用代码绘制省略号的所有内容,但我找不到一个简单的工作示例,我可以将其编码到我的Lua / VB代码中。

以下是我访问过的一些网站,但无法使代码正常工作或无法正常将代码转换为Lua或VB ...

任何人都可以帮我制作可以绘制椭圆和填充椭圆的代码吗?

这里是我尝试从这里转换为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()

4 个答案:

答案 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