2012-06-23 52 views
2

有誰知道任何代碼來呈現橢圓在C#中的數組?我看了一下,找不到解決我問題的任何事情。渲染的點都填充和非填充橢圓陣列在C#

考慮以下數組:

bool[,] pixels = new bool[100, 100]; 

我正在尋找的功能來呈現這兩個矩形區域內的空心填充的橢圓。 e.g:

public void Ellipse(bool[,] pixels, Rectangle area) 
{ 
    // fill pixels[x,y] = true here for the ellipse within area. 
} 

public void FillEllipse(bool[,] pixels, Rectangle area) 
{ 
    // fill pixels[x,y] = true here for the ellipse within area. 
} 

Ellipse(pixels, new Rectangle(20, 20, 60, 60)); 
FillEllipse(pixels, new Rectangle(40, 40, 20, 20)); 

任何幫助將不勝感激。

+0

在開始時你說'有誰知道任何代碼來呈現一個數組的橢圓'然後你說'給定下面的數組... 我正在尋找函數來呈現一個空心和填充橢圓'。你是否想將一個橢圓變成一個「bool [,]'或者'bool [,]'到一個空心或橢圓形的橢圓? – 3aw5TZetdf

回答

2

像這樣的東西應該做的伎倆

public class EllipseDrawer 
{ 
    private static PointF GetEllipsePointFromX(float x, float a, float b) 
    { 
     //(x/a)^2 + (y/b)^2 = 1 
     //(y/b)^2 = 1 - (x/a)^2 
     //y/b = -sqrt(1 - (x/a)^2) --Neg root for upper portion of the plane 
     //y = b*-sqrt(1 - (x/a)^2) 
     return new PointF(x, b * -(float)Math.Sqrt(1 - (x * x/a/a))); 
    } 

    public static void Ellipse(bool[,] pixels, Rectangle area) 
    { 
     DrawEllipse(pixels, area, false); 
    } 

    public static void FillEllipse(bool[,] pixels, Rectangle area) 
    { 
     DrawEllipse(pixels, area, true); 
    } 

    private static void DrawEllipse(bool[,] pixels, Rectangle area, bool fill) 
    { 
     // Get the size of the matrix 
     var matrixWidth = pixels.GetLength(0); 
     var matrixHeight = pixels.GetLength(1); 

     var offsetY = area.Top; 
     var offsetX = area.Left; 

     // Figure out how big the ellipse is 
     var ellipseWidth = (float)area.Width; 
     var ellipseHeight = (float)area.Height; 

     // Figure out the radiuses of the ellipses 
     var radiusX = ellipseWidth/2; 
     var radiusY = ellipseHeight/2; 

     //Keep track of the previous y position 
     var prevY = 0; 
     var firstRun = true; 

     // Loop through the points in the matrix 
     for (var x = 0; x <= radiusX; ++x) 
     { 
      var xPos = x + offsetX; 
      var rxPos = (int)ellipseWidth - x - 1 + offsetX; 

      if (xPos < 0 || rxPos < xPos || xPos >= matrixWidth) 
      { 
       continue; 
      } 

      var pointOnEllipseBoundCorrespondingToXMatrixPosition = GetEllipsePointFromX(x - radiusX, radiusX, radiusY); 
      var y = (int) Math.Floor(pointOnEllipseBoundCorrespondingToXMatrixPosition.Y + (int)radiusY); 
      var yPos = y + offsetY; 

      var ryPos = (int)ellipseHeight - y - 1 + offsetY; 

      if (yPos >= 0) 
      { 
       if (xPos > -1 && xPos < matrixWidth && yPos > -1 && yPos < matrixHeight) 
       { 
        pixels[xPos, yPos] = true; 
       } 

       if(xPos > -1 && xPos < matrixWidth && ryPos > -1 && ryPos < matrixHeight) 
       { 
        pixels[xPos, ryPos] = true; 
       } 

       if (rxPos > -1 && rxPos < matrixWidth) 
       { 
        if (yPos > -1 && yPos < matrixHeight) 
        { 
         pixels[rxPos, yPos] = true; 
        } 

        if (ryPos > -1 && ryPos < matrixHeight) 
        { 
         pixels[rxPos, ryPos] = true; 
        } 
       } 
      } 

      //While there's a >1 jump in y, fill in the gap (assumes that this is not the first time we've tracked y, x != 0) 
      for (var j = prevY - 1; !firstRun && j > y - 1 && y > 0; --j) 
      { 
       var jPos = j + offsetY; 
       var rjPos = (int)ellipseHeight - j - 1 + offsetY; 

       if(jPos == rjPos - 1) 
       { 
        continue; 
       } 

       if(jPos > -1 && jPos < matrixHeight) 
       { 
        pixels[xPos, jPos] = true; 
       } 

       if(rjPos > -1 && rjPos < matrixHeight) 
       { 
        pixels[xPos, rjPos] = true; 
       } 

       if (rxPos > -1 && rxPos < matrixWidth) 
       { 
        if(jPos > -1 && jPos < matrixHeight) 
        { 
         pixels[rxPos, jPos] = true; 
        } 

        if(rjPos > -1 && rjPos < matrixHeight) 
        { 
         pixels[rxPos, rjPos] = true; 
        } 
       } 
      } 

      firstRun = false; 
      prevY = y; 
      var countTarget = radiusY - y; 

      for (var count = 0; fill && count < countTarget; ++count) 
      { 
       ++yPos; 
       --ryPos; 

       // Set all four points in the matrix we just learned about 
       // also, make the indication that for the rest of this row, we need to fill the body of the ellipse 
       if(yPos > -1 && yPos < matrixHeight) 
       { 
        pixels[xPos, yPos] = true; 
       } 

       if(ryPos > -1 && ryPos < matrixHeight) 
       { 
        pixels[xPos, ryPos] = true; 
       } 

       if (rxPos > -1 && rxPos < matrixWidth) 
       { 
        if(yPos > -1 && yPos < matrixHeight) 
        { 
         pixels[rxPos, yPos] = true; 
        } 

        if(ryPos > -1 && ryPos < matrixHeight) 
        { 
         pixels[rxPos, ryPos] = true; 
        } 
       } 
      } 
     } 
    } 
} 
+0

太棒了。奇怪的是,雖然矩形的X位置似乎沒有兌現。 – Rob

+0

不確定是否只需要矩形大小的橢圓或基於X和Y偏移定位。我將在今晚定位時更新我的​​答案。 – mlorbetske

+0

X和Y實際上,代碼似乎沒有使用area.X或area.Y ???否則,我很樂意爲這個答案提供賞金,它幾乎就在那裏。你可以更新它以包括矩形的位置嗎? – Rob

1

這更適用於所有語言一般,我不知道爲什麼你正在尋找特別像這樣的事情,而不是使用預先存在的圖形庫(功課?),而是繪製一個橢圓,我會建議使用中點線繪製算法,可以適應橢圓(也圓):

http://en.wikipedia.org/wiki/Midpoint_circle_algorithm

我不知道我完全同意,這是布氏算法的推廣(當然我們被教導Bresenham和中點算法是不同的,但被證明產生相同的結果),但該頁面應該給你一個開始。查看特定於橢圓的算法底部附近的文章鏈接。

至於填充的橢圓形,我說你最好的選擇是採取掃描線的方法 - 依次查看每一行,找出哪些像素的左側和右側都在線條,然後填寫每個像素插圖中。

+0

這不是家庭作業,我對數學並不是很了不起,這就是爲什麼這是如此具體。 – Rob

0

做會做最簡單的事情就是迭代在你的矩陣中的每個元素,並檢查一些橢圓方程是否取值爲http://en.wikipedia.org/wiki/Ellipse

採取我會開始什麼真正

enter image description here

是類似的東西

 bool[,] pixels = new bool[100, 100]; 

     double a = 30; 
     double b = 20; 
     for (int i = 0; i < 100; i++) 
      for (int j = 0; j < 100; j++) 
      { 
       double x = i-50; 
       double y = j-50; 
       pixels[i, j] = (x/a) * (x/a) + (y/b) * (y/b) > 1; 
      } 

如果你的橢圓反過來,不只是cha nge ><

對於空洞的,您可以檢查(x/a) * (x/a) + (y/b) * (y/b)1之間的差異是否在特定閾值內。如果只是將不等式改爲等式,它可能會遺漏一些像素。

現在,我還沒有真正完全測試這一點,所以如果被正確使用的公式我不知道,但我只是想說明這個概念。

2

雖然目前似乎已經成爲一個perfectly valid answer源代碼和所有對這個問題,我只想指出,WriteableBitmapEx項目中還含有大量的高效的source code用於在所謂的WriteableBitmap對象中繪製和填充不同的多邊形類型(如橢圓)。

該代碼可以很容易地適用於應以不同方式呈現2D陣列(或2D陣列的1D表示)的一般場景。

對於橢圓形的情況下,要特別注意DrawEllipse...方法在WriteableBitmapShapeExtensions.cs文件,並在WriteableBitmapFillExtensions.cs FillEllipse...方法文件,一切都坐落在主幹/來源/ WriteableBitmapEx子文件夾。