📜  中点椭圆绘制算法

📅  最后修改于: 2021-04-21 23:13:49             🧑  作者: Mango

中点椭圆算法用于在计算机图形学中绘制椭圆。

另请参阅:中点线算法,中点圆算法

椭圆(四向对称)

中点椭圆算法通过将象限分为两个区域,在第一个象限上绘制(查找)一个椭圆点。
然后将每个点(x,y)投影到其他三个象限(-x,y),(x,-y),(-x,-y),即,它使用4向对称。

椭圆函数:

决策参数:
最初,我们在区域1中具有两个决策参数p1 0 ,在区域2中具有p2 0
这些参数定义为:区域1中的p1 0表示为:

中点椭圆算法:

  1. 沿x轴和y轴获取输入半径,并获取椭圆的中心。
  2. 最初,我们假设椭圆以原点和第一个点为中心:(x,y 0 )=(0,r y )。
  3. 获得区域1的初始决策参数为:p1 0 = r y 2 + 1 / 4r x 2 -r x 2 r y
  4. 对于区域1中的每个x k位置:

    如果p1 k <0,则沿的下一个点是(x k + 1 ,y k )和p1 k + 1 = p1 k + 2r y 2 x k + 1 + r y 2

    否则,下一点是(x k + 1 ,y k-1 )
    并且p1 k + 1 = p1 k + 2r y 2 x k + 1 – 2r x 2 y k + 1 + r y 2

  5. 使用区域1的最后一个点(x 0 ,y 0 )获得区域2中的初始值,如下所示:p2 0 = r y 2 (x 0 +1/2) 2 + r x 2 (y 0 -1) 2- r x 2 r y 2
  6. 在区域2中从k = 0开始的每个y k ,执行以下任务。

    如果p2 k > 0,则下一个点是(x k ,y k-1 ),并且p2 k + 1 = p2 k -2r x 2 y k + 1 + r x 2

  7. 否则,下一个点是(x k + 1 ,y k -1 )和p2 k + 1 = p2 k + 2r y 2 x k + 1 -2r x 2 y k + 1 + r x 2
  8. 现在获得三个象限中的对称点,并将坐标值绘制为:x = x + xc,y = y + yc
  9. 对区域1重复上述步骤,直到2r y 2 x> = 2r x 2 y

执行:

C++
// C++ program for implementing
// Mid-Point Ellipse Drawing Algorithm
#include 
using namespace std;
  
void midptellipse(int rx, int ry, 
                  int xc, int yc)
{
    float dx, dy, d1, d2, x, y;
    x = 0;
    y = ry;
  
    // Initial decision parameter of region 1
    d1 = (ry * ry) - (rx * rx * ry) + 
                     (0.25 * rx * rx);
    dx = 2 * ry * ry * x;
    dy = 2 * rx * rx * y;
  
    // For region 1
    while (dx < dy) 
    {
  
        // Print points based on 4-way symmetry
        cout << x + xc << " , " << y + yc << endl;
        cout << -x + xc << " , " << y + yc << endl;
        cout << x + xc << " , " << -y + yc << endl;
        cout << -x + xc << " , " << -y + yc << endl;
  
        // Checking and updating value of
        // decision parameter based on algorithm
        if (d1 < 0)
        {
            x++;
            dx = dx + (2 * ry * ry);
            d1 = d1 + dx + (ry * ry);
        }
        else 
        {
            x++;
            y--;
            dx = dx + (2 * ry * ry);
            dy = dy - (2 * rx * rx);
            d1 = d1 + dx - dy + (ry * ry);
        }
    }
  
    // Decision parameter of region 2
    d2 = ((ry * ry) * ((x + 0.5) * (x + 0.5))) + 
         ((rx * rx) * ((y - 1) * (y - 1))) -
          (rx * rx * ry * ry);
  
    // Plotting points of region 2
    while (y >= 0)
    {
  
        // Print points based on 4-way symmetry
        cout << x + xc << " , " << y + yc << endl;
        cout << -x + xc << " , " << y + yc << endl;
        cout << x + xc << " , " << -y + yc << endl;
        cout << -x + xc << " , " << -y + yc << endl;
  
        // Checking and updating parameter
        // value based on algorithm
        if (d2 > 0) 
        {
            y--;
            dy = dy - (2 * rx * rx);
            d2 = d2 + (rx * rx) - dy;
        }
        else 
        {
            y--;
            x++;
            dx = dx + (2 * ry * ry);
            dy = dy - (2 * rx * rx);
            d2 = d2 + dx - dy + (rx * rx);
        }
    }
}
  
// Driver code
int main()
{
    // To draw a ellipse of major and
    // minor radius 15, 10 centred at (50, 50)
    midptellipse(10, 15, 50, 50);
  
    return 0;
}
  
// This code is contributed 
// by Akanksha Rai


C
// C program for implementing
// Mid-Point Ellipse Drawing Algorithm
  
#include 
  
void midptellipse(int rx, int ry, int xc, int yc)
{
  
    float dx, dy, d1, d2, x, y;
    x = 0;
    y = ry;
  
    // Initial decision parameter of region 1
    d1 = (ry * ry)
         - (rx * rx * ry)
         + (0.25 * rx * rx);
    dx = 2 * ry * ry * x;
    dy = 2 * rx * rx * y;
  
    // For region 1
    while (dx < dy) {
  
        // Print points based on 4-way symmetry
        printf("(%f, %f)\n", x + xc, y + yc);
        printf("(%f, %f)\n", -x + xc, y + yc);
        printf("(%f, %f)\n", x + xc, -y + yc);
        printf("(%f, %f)\n", -x + xc, -y + yc);
  
        // Checking and updating value of
        // decision parameter based on algorithm
        if (d1 < 0) {
            x++;
            dx = dx + (2 * ry * ry);
            d1 = d1 + dx + (ry * ry);
        }
        else {
            x++;
            y--;
            dx = dx + (2 * ry * ry);
            dy = dy - (2 * rx * rx);
            d1 = d1 + dx - dy + (ry * ry);
        }
    }
  
    // Decision parameter of region 2
    d2 = ((ry * ry) * ((x + 0.5) * (x + 0.5)))
         + ((rx * rx) * ((y - 1) * (y - 1)))
         - (rx * rx * ry * ry);
  
    // Plotting points of region 2
    while (y >= 0) {
  
        // printing points based on 4-way symmetry
        printf("(%f, %f)\n", x + xc, y + yc);
        printf("(%f, %f)\n", -x + xc, y + yc);
        printf("(%f, %f)\n", x + xc, -y + yc);
        printf("(%f, %f)\n", -x + xc, -y + yc);
  
        // Checking and updating parameter
        // value based on algorithm
        if (d2 > 0) {
            y--;
            dy = dy - (2 * rx * rx);
            d2 = d2 + (rx * rx) - dy;
        }
        else {
            y--;
            x++;
            dx = dx + (2 * ry * ry);
            dy = dy - (2 * rx * rx);
            d2 = d2 + dx - dy + (rx * rx);
        }
    }
}
  
// Driver code
int main()
{
    // To draw a ellipse of major and
    // minor radius 15, 10  centred at (50, 50)
    midptellipse(10, 15, 50, 50);
  
    return 0;
}


Java
// Java program for implementing
// Mid-Point Ellipse Drawing Algorithm
import java.util.*;
import java.text.DecimalFormat;
  
class GFG
{
  
static void midptellipse(float rx, float ry, 
                        float xc, float yc)
{
  
    float dx, dy, d1, d2, x, y;
    x = 0;
    y = ry;
  
    // Initial decision parameter of region 1
    d1 = (ry * ry) - (rx * rx * ry) +
                    (0.25f * rx * rx);
    dx = 2 * ry * ry * x;
    dy = 2 * rx * rx * y;
    DecimalFormat df = new DecimalFormat("#,###,##0.00000");
      
    // For region 1
    while (dx < dy)
    {
      
        // Print points based on 4-way symmetry
        System.out.println(df.format((x + xc)) + 
                            ", "+df.format((y + yc)));
        System.out.println(df.format((-x + xc)) +
                            ", "+ df.format((y + yc)));
        System.out.println(df.format((x + xc)) + 
                            ", "+ df.format((-y + yc)));
        System.out.println(df.format((-x + xc)) +
                            ", "+df.format((-y + yc)));
  
        // Checking and updating value of
        // decision parameter based on algorithm
        if (d1 < 0) 
        {
            x++;
            dx = dx + (2 * ry * ry);
            d1 = d1 + dx + (ry * ry);
        }
        else
        {
            x++;
            y--;
            dx = dx + (2 * ry * ry);
            dy = dy - (2 * rx * rx);
            d1 = d1 + dx - dy + (ry * ry);
        }
    }
  
    // Decision parameter of region 2
    d2 = ((ry * ry) * ((x + 0.5f) * (x + 0.5f)))
        + ((rx * rx) * ((y - 1) * (y - 1)))
        - (rx * rx * ry * ry);
  
    // Plotting points of region 2
    while (y >= 0) {
  
        // printing points based on 4-way symmetry
        System.out.println(df.format((x + xc)) + 
                            ", " + df.format((y + yc)));
        System.out.println(df.format((-x + xc)) + 
                            ", "+ df.format((y + yc)));
        System.out.println(df.format((x + xc)) +
                            ", " + df.format((-y + yc)));
        System.out.println(df.format((-x + xc)) +
                            ", " + df.format((-y + yc)));
  
        // Checking and updating parameter
        // value based on algorithm
        if (d2 > 0) {
            y--;
            dy = dy - (2 * rx * rx);
            d2 = d2 + (rx * rx) - dy;
        }
        else {
            y--;
            x++;
            dx = dx + (2 * ry * ry);
            dy = dy - (2 * rx * rx);
            d2 = d2 + dx - dy + (rx * rx);
        }
    }
}
  
// Driver code
public static void main(String args[])
{
    // To draw a ellipse of major and
    // minor radius 15, 10 centred at (50, 50)
    midptellipse(10, 15, 50, 50);
} 
}
  
// This code is contributed by
// Surendra_Gangwar


Python3
# Python3 program for implementing 
# Mid-Point Ellipse Drawing Algorithm 
  
def midptellipse(rx, ry, xc, yc): 
  
    x = 0; 
    y = ry; 
  
    # Initial decision parameter of region 1 
    d1 = ((ry * ry) - (rx * rx * ry) +
                      (0.25 * rx * rx)); 
    dx = 2 * ry * ry * x; 
    dy = 2 * rx * rx * y; 
  
    # For region 1 
    while (dx < dy): 
  
        # Print points based on 4-way symmetry 
        print("(", x + xc, ",", y + yc, ")"); 
        print("(",-x + xc,",", y + yc, ")");
        print("(",x + xc,",", -y + yc ,")"); 
        print("(",-x + xc, ",", -y + yc, ")"); 
  
        # Checking and updating value of 
        # decision parameter based on algorithm 
        if (d1 < 0): 
            x += 1; 
            dx = dx + (2 * ry * ry); 
            d1 = d1 + dx + (ry * ry); 
        else:
            x += 1; 
            y -= 1; 
            dx = dx + (2 * ry * ry); 
            dy = dy - (2 * rx * rx); 
            d1 = d1 + dx - dy + (ry * ry); 
  
    # Decision parameter of region 2 
    d2 = (((ry * ry) * ((x + 0.5) * (x + 0.5))) +
          ((rx * rx) * ((y - 1) * (y - 1))) - 
           (rx * rx * ry * ry)); 
  
    # Plotting points of region 2 
    while (y >= 0):
  
        # printing points based on 4-way symmetry 
        print("(", x + xc, ",", y + yc, ")"); 
        print("(", -x + xc, ",", y + yc, ")"); 
        print("(", x + xc, ",", -y + yc, ")"); 
        print("(", -x + xc, ",", -y + yc, ")"); 
  
        # Checking and updating parameter 
        # value based on algorithm 
        if (d2 > 0):
            y -= 1; 
            dy = dy - (2 * rx * rx); 
            d2 = d2 + (rx * rx) - dy; 
        else:
            y -= 1; 
            x += 1; 
            dx = dx + (2 * ry * ry); 
            dy = dy - (2 * rx * rx); 
            d2 = d2 + dx - dy + (rx * rx); 
  
# Driver code 
  
# To draw a ellipse of major and 
# minor radius 15, 10 centred at (50, 50) 
midptellipse(10, 15, 50, 50); 
  
# This code is contributed by chandan_jnu


C#
// C# program for implementing
// Mid-Point Ellipse Drawing Algorithm
using System;
  
class GFG
{
  
static void midptellipse(double rx, double ry, 
                        double xc, double yc)
{
  
    double dx, dy, d1, d2, x, y;
    x = 0;
    y = ry;
  
    // Initial decision parameter of region 1
    d1 = (ry * ry) - (rx * rx * ry) +
                    (0.25f * rx * rx);
    dx = 2 * ry * ry * x;
    dy = 2 * rx * rx * y;
      
    // For region 1
    while (dx < dy)
    {
      
        // Print points based on 4-way symmetry
        Console.WriteLine(String.Format("{0:0.000000}",
                            (x + xc)) + ", "+String.Format
                            ("{0:0.000000}",(y + yc)));
        Console.WriteLine(String.Format("{0:0.000000}",
                            (-x + xc)) + ", "+ String.Format
                            ("{0:0.000000}",(y + yc)));
        Console.WriteLine(String.Format("{0:0.000000}",
                            (x + xc)) + ", "+String.Format
                            ("{0:0.000000}",(-y + yc)));
        Console.WriteLine(String.Format("{0:0.000000}",
                            (-x + xc)) +", "+String.Format
                            ("{0:0.000000}",(-y + yc)));
  
        // Checking and updating value of
        // decision parameter based on algorithm
        if (d1 < 0) 
        {
            x++;
            dx = dx + (2 * ry * ry);
            d1 = d1 + dx + (ry * ry);
        }
        else
        {
            x++;
            y--;
            dx = dx + (2 * ry * ry);
            dy = dy - (2 * rx * rx);
            d1 = d1 + dx - dy + (ry * ry);
        }
    }
  
    // Decision parameter of region 2
    d2 = ((ry * ry) * ((x + 0.5f) * (x + 0.5f)))
        + ((rx * rx) * ((y - 1) * (y - 1)))
        - (rx * rx * ry * ry);
  
    // Plotting points of region 2
    while (y >= 0)
    {
  
        // printing points based on 4-way symmetry
        Console.WriteLine(String.Format("{0:0.000000}",
                            (x + xc)) + ", " + String.Format
                            ("{0:0.000000}",(y + yc)));
        Console.WriteLine(String.Format("{0:0.000000}",
                            (-x + xc)) + ", "+ String.Format
                            ("{0:0.000000}",(y + yc)));
        Console.WriteLine(String.Format("{0:0.000000}",
                            (x + xc)) + ", " + String.Format
                            ("{0:0.000000}",(-y + yc)));
        Console.WriteLine(String.Format("{0:0.000000}",
                            (-x + xc)) + ", " + String.Format
                            ("{0:0.000000}",(-y + yc)));
  
        // Checking and updating parameter
        // value based on algorithm
        if (d2 > 0)
        {
            y--;
            dy = dy - (2 * rx * rx);
            d2 = d2 + (rx * rx) - dy;
        }
        else 
        {
            y--;
            x++;
            dx = dx + (2 * ry * ry);
            dy = dy - (2 * rx * rx);
            d2 = d2 + dx - dy + (rx * rx);
        }
    }
}
  
// Driver code
static void Main()
{
  
    // To draw a ellipse of major and
    // minor radius 15, 10 centred at (50, 50)
    midptellipse(10, 15, 50, 50);
} 
}
  
// This code is contributed by mits


PHP
= 0) 
    { 
  
        // printing points based on 4-way symmetry 
        echo "( ",$x + $xc,", ", $y + $yc ," )\n"; 
        echo "( ",-$x + $xc,", ", $y + $yc , " )\n"; 
        echo "( ",$x + $xc,", ", -$y + $yc, " )\n"; 
        echo "( ",-$x + $xc,", ", -$y + $yc, " )\n"; 
  
        // Checking and updating parameter 
        // value based on algorithm 
        if ($d2 > 0) 
        { 
            $y--; 
            $dy = $dy - (2 * $rx * $rx); 
            $d2 = $d2 + ($rx * $rx) - $dy; 
        } 
        else 
        { 
            $y--; 
            $x++; 
            $dx = $dx + (2 * $ry * $ry); 
            $dy = $dy - (2 * $rx * $rx); 
            $d2 = $d2 + $dx - $dy + ($rx * $rx); 
        } 
    } 
} 
  
// Driver code 
  
// To draw a ellipse of major and 
// minor radius 15, 10 centred at (50, 50) 
midptellipse(10, 15, 50, 50); 
  
// This code is contributed by Ryuga
?>


输出:
(50.000000, 65.000000)
(50.000000, 65.000000)
(50.000000, 35.000000)
(50.000000, 35.000000)
(51.000000, 65.000000)
(49.000000, 65.000000)
(51.000000, 35.000000)
(49.000000, 35.000000)
(52.000000, 65.000000)
(48.000000, 65.000000)
(52.000000, 35.000000)
(48.000000, 35.000000)
(53.000000, 64.000000)
(47.000000, 64.000000)
(53.000000, 36.000000)
(47.000000, 36.000000)
(54.000000, 64.000000)
(46.000000, 64.000000)
(54.000000, 36.000000)
(46.000000, 36.000000)
(55.000000, 63.000000)
(45.000000, 63.000000)
(55.000000, 37.000000)
(45.000000, 37.000000)
(56.000000, 62.000000)
(44.000000, 62.000000)
(56.000000, 38.000000)
(44.000000, 38.000000)
(57.000000, 61.000000)
(43.000000, 61.000000)
(57.000000, 39.000000)
(43.000000, 39.000000)
(57.000000, 60.000000)
(43.000000, 60.000000)
(57.000000, 40.000000)
(43.000000, 40.000000)
(58.000000, 59.000000)
(42.000000, 59.000000)
(58.000000, 41.000000)
(42.000000, 41.000000)
(58.000000, 58.000000)
(42.000000, 58.000000)
(58.000000, 42.000000)
(42.000000, 42.000000)
(59.000000, 57.000000)
(41.000000, 57.000000)
(59.000000, 43.000000)
(41.000000, 43.000000)
(59.000000, 56.000000)
(41.000000, 56.000000)
(59.000000, 44.000000)
(41.000000, 44.000000)
(59.000000, 55.000000)
(41.000000, 55.000000)
(59.000000, 45.000000)
(41.000000, 45.000000)
(60.000000, 54.000000)
(40.000000, 54.000000)
(60.000000, 46.000000)
(40.000000, 46.000000)
(60.000000, 53.000000)
(40.000000, 53.000000)
(60.000000, 47.000000)
(40.000000, 47.000000)
(60.000000, 52.000000)
(40.000000, 52.000000)
(60.000000, 48.000000)
(40.000000, 48.000000)
(60.000000, 51.000000)
(40.000000, 51.000000)
(60.000000, 49.000000)
(40.000000, 49.000000)
(60.000000, 50.000000)
(40.000000, 50.000000)
(60.000000, 50.000000)
(40.000000, 50.000000)