Converting C++ code to C# code - c#

I'm trying to convert the C++ opencv code demo drawContour functionality to C#. I'm having trouble with function arguments contours0[k] and contours[k] in function API Cv2.ApproxPolyDP. I get Design time compiler error stating some of the parameters are invalid for Cv2.ApproxPolyDP call. The code in question is listed below. Thanks in advance for your assistances.
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using OpenCvSharp;
class Program
{
const int w = 500;
static int levels = 3;
static Point[][] contours;
static HierarchyIndex[] hierarchy;
static void on_trackbar(int pos, object UseData)
{
Mat cnt_img = Mat.Zeros(w, w, MatType.CV_8UC3);
int _levels = levels - 3;
Cv2.DrawContours( cnt_img, contours, _levels <= 0 ? 3 : -1, Scalar.White,
3, LineTypes.AntiAlias, hierarchy, Math.Abs(_levels) );
Cv2.ImShow("contours", cnt_img);
}
static void Main()
{
Mat img = Mat.Zeros(w, w, MatType.CV_8UC1);
//Draw 6 faces
for( int i = 0; i < 6; i++ )
{
int dx = (i % 2) * 250 - 30;
int dy = (i/2)*150;
Scalar white = Scalar.White;
Scalar black = Scalar.Black;
if( i == 0 )
{
for( int j = 0; j <= 10; j++ )
{
double angle = (j + 5) * Math.PI/21;
Cv2.Line(img,
new Point(Math.Round(dx + 100 + j * 10 - 80 * Math.Cos(angle), 0),
Math.Round(dy + 100 - 90 * Math.Sin(angle), 0)),
new Point(Math.Round(dx + 100 + j * 10 - 30 * Math.Cos(angle), 0),
Math.Round(dy + 100 - 30 * Math.Sin(angle), 0)),
white, 1);
}
}
Cv2.Ellipse(img, new Point(dx + 150, dy + 100), new Size(100, 70), 0, 0, 360, white);
Cv2.Ellipse(img, new Point(dx + 115, dy + 70), new Size( 30, 20), 0, 0, 360, black);
Cv2.Ellipse(img, new Point(dx + 185, dy + 70), new Size( 30, 20), 0, 0, 360, black);
Cv2.Ellipse(img, new Point(dx + 115, dy + 70), new Size( 15, 15), 0, 0, 360, white);
Cv2.Ellipse(img, new Point(dx + 185, dy + 70), new Size( 15, 15), 0, 0, 360, white);
Cv2.Ellipse(img, new Point(dx + 115, dy + 70), new Size( 5, 5), 0, 0, 360, black);
Cv2.Ellipse(img, new Point(dx + 185, dy + 70), new Size( 5, 5), 0, 0, 360, black);
Cv2.Ellipse(img, new Point(dx + 150, dy + 100), new Size( 10, 5), 0, 0, 360, black);
Cv2.Ellipse(img, new Point(dx + 150, dy + 150), new Size( 40, 10), 0, 0, 360, black);
Cv2.Ellipse(img, new Point(dx + 27, dy + 100), new Size( 20, 35), 0, 0, 360, white);
Cv2.Ellipse(img, new Point(dx + 273, dy + 100), new Size( 20, 35), 0, 0, 360, white);
}
//show the faces
Cv2.ImShow( "image", img );
//Extract the contours so that
Point[][] contours0;
Cv2.FindContours( img, out contours0, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple);
contours = new Point[contours0.Length][];
for( int k = 0; k < contours0.Length; k++ )
Cv2.ApproxPolyDP(contours0[k], contours[k], 3, true); // compiler error!
CvTrackbar Track = new CvTrackbar("levels+3", "contours", 3, 7, on_trackbar);
on_trackbar(0, 0);
Cv2.WaitKey();
}
}

I needed to rewrite the C++ line: approxPolyDP(Mat(contours0[k]), contours[k], 3, true);
as C# line: contours[k] = Cv2.ApproxPolyDP(contours0[k], 3, true);

Related

WPF - print datagrid contents

I Have looked around and I have not found a solid answeer to this question. I am trying to print my datagrid content when I press a button, the main problem is that my datagrid has too much data and only whatever is shown in the screen is printing. I need It to print all data and if the data does not fit in current page create a mew page and print the rest.
Here is my solution printing Data Grid View using System.Drawing.Printing
using System.Drawing.Printing;
private int PageCounter { get; set; } = 1;
private int RowCounter { get; set; }
Print Button
private void BtnPrint_Click(object sender, EventArgs e)
{
PrintDocument printDoc = new PrintDocument();
IQueryable<PaperSize> paperSizes = printDoc.PrinterSettings.PaperSizes.Cast<PaperSize>().AsQueryable();
printDoc.DefaultPageSettings.PaperSize = paperSizes.First(ps => ps.Kind == PaperKind.A4);
printDoc.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);
pageCounter = 1;
printDoc.PrintPage += PrintDoc_PrintPage;
printDoc.Print();
}
Print Method
private void Print_Document(object sender, PrintPageEventArgs e)
{
if (e.Graphics == null)
throw new Exception("Unable to find page Graphics!");
int left = 30;
int cellLeft = left;
int top = 50;
int cellWidth = 0;
int headerHeight = 30;
string headerName = string.Empty;
string cellValue = string.Empty;
Rectangle rect = new();
int pageWidth = e.PageSettings.PaperSize.Width - 60;
int pageHeight = e.PageSettings.PaperSize.Height - 100;
Graphics g = e.Graphics;
Font font = new(FontFamily, 9);
Pen p = new(Brushes.Black, 1f);
Pen borderP = new(new SolidBrush(Color.FromArgb(240, 240, 240)), 1f);
StringFormat stringFormatCenter = new()
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
StringFormat stringFormatRight = new()
{
Alignment = StringAlignment.Far,
LineAlignment = StringAlignment.Center
};
StringFormat stringFormatLeft = new()
{
LineAlignment = StringAlignment.Center
};
if (PageCounter == 1)
{
g.DrawRectangle(p, new Rectangle(left, top, pageWidth, 30));
top += 30;
g.DrawRectangle(p, new Rectangle(left, top, pageWidth, 30));
top += 30;
g.DrawRectangle(p, new Rectangle(left, top, pageWidth, 30));
top += 30;
g.DrawRectangle(p, new Rectangle(left, top, pageWidth / 2, 30));
g.DrawRectangle(p, new Rectangle(left + (pageWidth / 2), top, pageWidth / 2, 30));
top += 30;
top = 50;
g.DrawString
("Company Name"
, new Font(FontFamily, 14f, FontStyle.Bold)
, Brushes.Black
, new Rectangle(left, top, pageWidth, 30)
, stringFormatCenter);
top += 30;
g.DrawString
("Business Type"
, new Font(FontFamily, 12f, FontStyle.Bold)
, Brushes.Black
, new Rectangle(left, top, pageWidth, 30)
, stringFormatCenter);
top += 30;
g.DrawString
("Report Name"
, new Font(FontFamily, 12f, FontStyle.Bold)
, Brushes.Black
, new Rectangle(left, top, pageWidth, 30)
, stringFormatCenter);
top += 30;
g.DrawString
("User Name: " + SelectedUser.Name
, new Font(FontFamily, 9, FontStyle.Bold)
, Brushes.Black
, new Rectangle(left, top, pageWidth / 2, 30)
, stringFormatLeft);
g.DrawString
("Report Date: " + DateTime.Now.ToString("dd-mm-yyyy hh:mm:ss")
, new Font(FontFamily, 9, FontStyle.Bold)
, Brushes.Black
, new Rectangle(left + (pageWidth / 2), top, pageWidth / 2, 30)
, stringFormatRight);
top += 30;
g.DrawString
("Login Id: " + SelectedUser.LoginId
, new Font(FontFamily, 9, FontStyle.Bold)
, Brushes.Black
, new Rectangle(left, top, pageWidth / 2, 30)
, stringFormatLeft);
g.DrawString
("Printed By: " + LoggedUser.Name
, new Font(FontFamily, 9, FontStyle.Bold)
, Brushes.Black
, new Rectangle(left + (pageWidth / 2), top, pageWidth / 2, 20)
, stringFormatRight);
top += 30;
g.DrawString
("Rights detail as follows:"
, new Font(FontFamily, 8, FontStyle.Bold)
, Brushes.Black
, new Rectangle(left, top, pageWidth, 20)
, stringFormatLeft);
top += 20;
}
g.FillRectangle(new SolidBrush(Color.FromArgb(234, 239, 250)), new Rectangle(left, top, pageWidth, headerHeight));
foreach (string name in PrintableRights.First().GetType().GetProperties().Select(p => p.Name))
{
if (name.Equals("SrNo"))
{
headerName = "Sr #";
cellWidth = Convert.ToInt32(Convert.ToDecimal(pageWidth) / 100 * 8);
}
else if (name.Equals("Code"))
{
headerName = "Code";
cellWidth = Convert.ToInt32(Convert.ToDecimal(pageWidth) / 100 * 20);
}
else if (name.Equals("Name"))
{
headerName = "Name";
cellWidth = Convert.ToInt32(Convert.ToDecimal(pageWidth) / 100 * 57);
}
else if (name.Equals("HasRight"))
{
headerName = "Right";
cellWidth = Convert.ToInt32(Convert.ToDecimal(pageWidth) / 100 * 15);
}
rect = new Rectangle(cellLeft, top, cellWidth, headerHeight);
g.DrawString(headerName, new Font(FontFamily, 10, FontStyle.Bold), Brushes.Black, rect, stringFormatLeft);
cellLeft += cellWidth;
}
top += headerHeight;
cellLeft = left;
while (RowCounter < PrintableRights.Count())
{
object row = PrintableRights.ElementAt(RowCounter);
cellLeft = left;
foreach (string name in row.GetType().GetProperties().Select(prop => prop.Name))
{
if (name.Equals("SrNo"))
cellWidth = Convert.ToInt32(Convert.ToDecimal(pageWidth) / 100 * 8);
else if (name.Equals("Code"))
cellWidth = Convert.ToInt32(Convert.ToDecimal(pageWidth) / 100 * 20);
else if (name.Equals("Name"))
cellWidth = Convert.ToInt32(Convert.ToDecimal(pageWidth) / 100 * 57);
else if (name.Equals("HasRight"))
cellWidth = Convert.ToInt32(Convert.ToDecimal(pageWidth) / 100 * 15);
rect = new Rectangle(cellLeft, top, cellWidth, 20);
g.DrawRectangle(borderP, rect);
PropertyInfo? prop = row.GetType().GetProperty(name);
if (prop != null)
{
if (prop.PropertyType == typeof(bool))
{
var val = prop.GetValue(row, null);
if (val != null && (bool)val)
g.DrawString("Yes", font, Brushes.Black, rect, stringFormatLeft);
else if (val != null)
g.DrawString("No", font, Brushes.Black, rect, stringFormatLeft);
}
else if (prop.PropertyType == typeof(int))
{
var val = prop.GetValue(row, null);
if (val != null)
g.DrawString(((int)val).ToString("N0"), font, Brushes.Black, rect, stringFormatRight);
else
g.DrawString(string.Empty, font, Brushes.Black, rect, stringFormatRight);
}
else if (prop.PropertyType == typeof(string))
{
var val = prop.GetValue(row, null);
if(val != null)
g.DrawString((string)val, font, Brushes.Black, rect, stringFormatLeft);
else
g.DrawString(string.Empty, font, Brushes.Black, rect, stringFormatLeft);
}
}
cellLeft += cellWidth;
}
top += 20;
if (RowCounter < PrintableRights.Count() - 1)
{
if (top > pageHeight - 10)
{
RowCounter++;
break;
}
}
RowCounter++;
}
if (RowCounter <= PrintableRights.Count() - 1)
{
if (top + 10 > pageHeight)
{
g.DrawString("Continue....", new Font(FontFamily, 7f), Brushes.Black, e.PageSettings.PaperSize.Width - 200, e.PageSettings.PaperSize.Height - 60);
g.DrawString("Page # " + PageCounter.ToString(), new Font(FontFamily, 7f), Brushes.Black, e.PageSettings.PaperSize.Width - 100, e.PageSettings.PaperSize.Height - 60);
PageCounter++;
e.HasMorePages = true;
}
}
else if (e.HasMorePages)
{
g.DrawString("Continue....", new Font(FontFamily, 7f), Brushes.Black, e.PageSettings.PaperSize.Width - 200, e.PageSettings.PaperSize.Height - 60);
g.DrawString("Page # " + PageCounter.ToString(), new Font(FontFamily, 7f), Brushes.Black, e.PageSettings.PaperSize.Width - 100, e.PageSettings.PaperSize.Height - 60);
PageCounter++;
}
else
{
g.DrawString("Last Page.", new Font(FontFamily, 7f), Brushes.Black, e.PageSettings.PaperSize.Width - 200, e.PageSettings.PaperSize.Height - 60);
g.DrawString("Page # " + PageCounter.ToString(), new Font(FontFamily, 7f), Brushes.Black, e.PageSettings.PaperSize.Width - 100, e.PageSettings.PaperSize.Height - 60);
}
}

How to draw a line of collection of parallelograms

For reasons of aesthetics, I want to create a line composed of parallelograms like this:
But it turns out that the OnPaint override event only allows you to draw rectangles:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Rectangle[] rectangles = new Rectangle[]
{
new Rectangle(0, 0, 100, 30),
new Rectangle(100, 0, 100, 30),
new Rectangle(200, 0, 100, 30),
new Rectangle(300, 0, 100, 30),
new Rectangle(400, 0, 100, 30),
};
e.Graphics.DrawRectangles(new Pen(Brushes.Black), rectangles);
}
My problem is that I need to convert the rectangles into parallelograms, and give each one a different color.
The FillPolygon can do the job:
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
e.Graphics.Clear(Color.White);
int x = 10;
int y = 10;
int width = 148;
int height = 64;
int lean = 36;
Color[] colors = new[] { Color.FromArgb(169, 198, 254),
Color.FromArgb(226, 112, 112),
Color.FromArgb(255, 226, 112),
Color.FromArgb(112, 226, 112),
Color.FromArgb(165, 142, 170)};
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
for (int i = 0; i < colors.Length; ++i) {
using (SolidBrush br = new SolidBrush(colors[i])) {
e.Graphics.FillPolygon(br, new Point[] { new Point(x, y),
new Point(x + lean, y + height),
new Point(x + lean + width, y + height),
new Point(x + width, y)});
x += width;
}
}
}

How can I do Hough Transform in OpenCV and C#?

Regarding this Opencv Tutorial, the following C++ code snippet:
vector<Vec4i> lines;
// Find hough lines
HoughLinesP(edges, lines, 1, CV_PI / 180, 100, 100, 10);
// Prepare blank mat with same sizes as image
Mat Blank(image.rows, image.cols, CV_8UC3, Scalar(0, 0, 0));
// Draw lines into image and Blank images
for (size_t i = 0; i < lines.size(); i++)
{
Vec4i l = lines[i];
line(image, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 0), 2, CV_AA);
line(Blank, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(255, 255, 255), 2, CV_AA);
}
has been translated into C# like this:
private void openFileDialogButton_Click(object sender, EventArgs e)
{
try
{
const string filename = #"E:\___MSc in Computer Systems & Network\EMSC1,2,3\lena.png";
Mat image = Cv2.ImRead(filename, LoadMode.GrayScale);
Mat edges = new Mat();
Cv2.Canny(image, edges, 95, 100);
Cv2.ImWrite("edges.jpg", edges);
Mat dx = new Mat();
Mat dy = new Mat();
Cv2.Sobel(edges, dx, MatType.CV_32F, 1, 0);
Cv2.Sobel(edges, dy, MatType.CV_32F, 0, 1);
Cv2.ImWrite("dx.jpg", dx);
Cv2.ImWrite("dy.jpg", dy);
Mat linesssssss = new Mat();
Cv.HoughLines2((CvArr)linesssssss.ToIplImage(),
(CvMat)edges,
HoughLinesMethod.Standard,
1,
Math.PI / 180,
100, 100, 10);
//Cv2.HoughLinesP(edges, lines, 1, Math.PI / 180, 100, 100, 10);
List<Vec4i> lines = IntPtrToList(linesssssss.Data);
Mat Blank = new Mat(image.Rows, image.Cols, MatType.CV_8UC3, new Scalar(0, 0, 0));
for (int i = 0; i < lines.Count; i++)
{
Vec4i l = lines[i];
Cv2.Line(image, new OpenCvSharp.CPlusPlus.Point(l[0], l[1]), new OpenCvSharp.CPlusPlus.Point(l[2], l[3]), new Scalar(0, 0, 0), 2, Cv.AA);
Cv2.Line(Blank, new OpenCvSharp.CPlusPlus.Point(l[0], l[1]), new OpenCvSharp.CPlusPlus.Point(l[2], l[3]), new Scalar(255, 255, 255), 2, Cv.AA);
}
//Cv2.ImWrite("houg.jpg", image);
//Cv2.ImShow("Edges", image);
//Cv2.ImWrite("houg2.jpg", Blank);
//Cv2.ImShow("Edges Structure", Blank);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Unfortunately, it seems to be not working. It is giving the following exception:
Nonpositive cols or rows
This is the original image from the article:
Based on Github's sample code for HoughLinesP:
static void Main(string[] args)
{
string filename = "Alliance.jpg";
Mat imageIn = Cv2.ImRead(filename, ImreadModes.GrayScale).Resize(new Size(800, 600));
Mat edges = new Mat();
Cv2.Canny(imageIn, edges, 95, 100);
//HoughLinesP
LineSegmentPoint[] segHoughP = Cv2.HoughLinesP(edges, 1, Math.PI / 180, 100, 100, 10);
Mat imageOutP = imageIn.EmptyClone();
foreach (LineSegmentPoint s in segHoughP)
imageOutP.Line(s.P1, s.P2, Scalar.White, 1, LineTypes.AntiAlias, 0);
using (new Window("Edges", WindowMode.AutoSize, edges))
using (new Window("HoughLinesP", WindowMode.AutoSize, imageOutP))
{
Window.WaitKey(0);
}
}

Changing Levels By Choices

Hey so I have this code here and what i am trying to do is make 2 more similar levels so when i have tile map 2 and 3 i would have a menu where the player could choose to play on a certain map... i am wondering how i would make this menu, would you please give me some insight on where to begin what type of code i could use etc.
Simple choice menu look:
Levels
Level 1
Level 2
Level 3
and the user would click on it and it would trigger/open one of the tilemaps.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace MarsCitadel
{
static class Tilemap
{
#region declarations
public const int TileWidth = 32;
public const int TileHeight = 32;
public const int MapWidth = 50;
public const int MapHeight = 50;
public const int FloorTileStart = 0; // 32 x 32 rectangle from sprite sheet
public const int FloorTileEnd = 3;
public const int WallTileStart = 4;
public const int WallTileEnd = 7;
static private Texture2D texturebarrens;
static private Texture2D textureroad;
//static private List<Rectangle> tiles = new List <Rectangle> ();
static private int[,] mapSquares = new int[MapWidth, MapHeight];
static private Random rand = new Random();
#endregion
#region intialization
static public void intialization(Texture2D tiletexture, Texture2D tiletexture2)
{
texturebarrens = tiletexture;
textureroad = tiletexture2;
//tiles.Clear();
//tiles.Add(new Rectangle(0, 0, TileWidth, TileHeight));
for (int x = 0; x < MapWidth; x++)
{
for (int y = 0; y < MapHeight; y++)
{
mapSquares[x, y] = FloorTileStart;
}
}
GenerateRandomMap();
}
#endregion
#region information about map squares
static public int getsquareatpixelX(int pixelX)
{
return pixelX / TileWidth;
}
static public int getsquareatpixelY(int pixelY)
{
return pixelY / TileHeight;
}
static public Vector2 getsquarebypixel(Vector2 pixellocation)
{
return new Vector2(getsquareatpixelX((int)pixellocation.X), getsquareatpixelY((int)pixellocation.Y));
}
static public Vector2 Getsquarecenter(int squareX, int squareY)
{
return new Vector2((squareX * TileWidth) + (TileWidth / 2), (squareY * TileHeight) + (TileHeight / 2));
}
static public Vector2 Getsquarecenter(Vector2 square)
{
return Getsquarecenter((int)square.X, (int)square.Y);
}
static public Rectangle Squareworldrectangle(int x, int y)
{
return new Rectangle(x * TileWidth, y * TileHeight, TileWidth, TileHeight);
}
static public Rectangle Squareworldrectangle(Vector2 square)
{
return Squareworldrectangle((int)square.X, (int)square.Y);
}
public static Rectangle Squarescreenrectangle(int x, int y)
{
return Camera.Transform(Squareworldrectangle(x, y));
}
public static Rectangle Squarescreenrectangle(Vector2 square)
{
return Squareworldrectangle((int)square.X, (int)square.Y);
}
#endregion
#region information about map tiles
static public int GetTileAtSquare(int tileX, int tileY)
{
if (((tileX >= 0) && (tileX <= MapWidth)) && ((tileX >= 0) && (tileX <= MapHeight)))
{
return mapSquares[tileX, tileY];
}
else return -1;
}
static public void SetTileAtSquare(int tileX, int tileY, int tile)
{
if (((tileX >= 0) && (tileX <= MapWidth)) && ((tileX >= 0) && (tileX <= MapHeight)))
{
mapSquares[tileX, tileY] = tile;
}
}
static public int GetTileAtPixel(int pixelX, int pixelY)
{
return GetTileAtSquare(getsquareatpixelX(pixelX), getsquareatpixelY(pixelY));
}
static public int GetTileAtPixel(Vector2 pixelLocation)
{
return GetTileAtPixel((int)pixelLocation.X, (int)pixelLocation.Y);
}
static public bool IsWallTile(int tileX, int tileY)
{
int tileindex = GetTileAtSquare(tileX, tileY);
if (tileindex == -1) return false;
return tileindex >= WallTileStart;
}
static public bool IsWallTile(Vector2 square)
{
return IsWallTile((int)square.X, (int)square.Y);
}
static public bool IsWallTileByPixel(Vector2 pixelLocation)
{
return IsWallTile(getsquareatpixelX((int)pixelLocation.X), getsquareatpixelY((int)pixelLocation.Y));
}
#endregion
#region drawing
static public void Draw(SpriteBatch spritebatch)
{
//int startX = getsquareatpixelX((int)Camera.Position.X);
//int endX = getsquareatpixelX((int)Camera.Position.X + Camera.ViewPortWidth);
//int startY = getsquareatpixelY((int)Camera.Position.Y);
//int endY = getsquareatpixelY((int)Camera.Position.Y + Camera.ViewPortHeight);
int startX = 0; int endX = 50;
int startY = 0; int endY = 50;
for (int x = startX; x <= endX; x++)
{
for (int y = startY; y <= endY; y++)
{
if ((x >= 0) && (y >= 0) && (x < MapWidth) && (y < MapHeight))
{
spritebatch.Draw(texturebarrens, new Rectangle(x * 32, y * 32, 32, 32), Color.White);
}
}
}
spritebatch.Draw(textureroad, new Rectangle(0 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(1 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(2 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(3 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(4 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(5 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(6 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(7 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(8 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(9 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(10 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(11 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(12 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(13 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(14 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(15 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(16 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(17 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(18 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(19 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(20 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(21 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(22 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(23 * 32, 7 * 32, 32, 32), Color.White);
spritebatch.Draw(textureroad, new Rectangle(24 * 32, 7 * 32, 32, 32), Color.White);
}
#endregion
#region map generation
static public void GenerateRandomMap()
{
int WallchancePerSquare = 10;
int floorTile = rand.Next(FloorTileStart, FloorTileEnd + 1);
int wallTile = rand.Next(WallTileStart, WallTileEnd + 1);
for (int x = 0; x < MapWidth; x++)
{
for (int y = 0; y < MapHeight; y++)
{
mapSquares[x, y] = floorTile;
// if (x == 0 || y == 0 || x == MapWidth - 1 || y == MapHeight - 1)
//{
//mapSquares[x, y] = wallTile;
// continue;
// }
if (x == 1 || y == 1 || x == MapWidth - 2 || y == MapHeight - 2)
{
continue;
}
if (rand.Next(0, 100) < WallchancePerSquare)
{
mapSquares[x, y] = wallTile;
}
}
}
}
#endregion
}
}
Make the Tilemap class abstract, then each version of your map can be a different sub-class of Tilemap (there may be other ways to optimize this, try looking up some design pattern such as "decorator" or "strategy" patterns). Create a Menu class which allows the user to select a map, say with a variety of buttons. Clicking a button should then instantiate the corresponding sub-class of Tilemap, any other code can refer to these objects as Tilemap without knowing which sub-class is implemented.

How do I draw an annulus (doughnut) using GDI+?

I have been trying to draw an annulus (ring with thickness) with a transparent hole and a gradient rim in C# with very little success. Does anyone have any suggestions on how to do this?
here's a nice Blend Utility
Here's the Final result - thanks to BlueMonkMN
Rectangle GetSquareRec(double radius, int x, int y)
{
double r = radius;
double side = Math.Sqrt(Math.Pow(r, 2) / 2);
Rectangle rec = new Rectangle(x - ((int)side), y - ((int)side), (int)(side * 2) + x, (int)(side * 2) + y);
return rec;
}
void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics gTarget = e.Graphics;
gTarget.SmoothingMode = SmoothingMode.AntiAlias;
GraphicsPath pTemp = new GraphicsPath();
Rectangle r = GetSquareRec(200, 225, 225);
pTemp.AddEllipse(r);
pTemp.AddEllipse(GetSquareRec(50, 225, 225));
Color[] colors = new Color[5];
colors[0] = Color.FromArgb(192, 192, 192);
colors[1] = Color.FromArgb(105, 0, 0);
colors[2] = Color.FromArgb(169, 169, 169);
colors[3] = Color.FromArgb(0, 0, 0);
colors[4] = Color.FromArgb(0, 0, 0);
float[] positions = new float[5];
positions[0] = 0f;
positions[1] = 0.1f;
positions[2] = 0.35f;
positions[3] = 0.5f;
positions[4] = 1f;
ColorBlend Cb = new ColorBlend();
Cb.Colors = colors;
Cb.Positions = positions;
PathGradientBrush pgb = new PathGradientBrush(pTemp);
pgb.InterpolationColors = Cb;
pgb.CenterPoint = new PointF(r.X + (r.Width / 2), r.Y + (r.Height / 2));
gTarget.FillPath(pgb, pTemp);
}
http://www.freeimagehosting.net/uploads/th.515733e62e.jpg
This is how I did it in the Scrolling Game Development Kit:
pTemp = new GraphicsPath();
pTemp.AddEllipse(Start.X, Start.Y, End.X - Start.X, End.Y - Start.Y);
pTemp.AddEllipse((Start.X * 3 + End.X) / 4f,
(Start.Y * 3 + End.Y) / 4f,
(End.X - Start.X) / 2f,
(End.Y - Start.Y) / 2f);
PathGradientBrush pgb = new PathGradientBrush(pTemp);
Blend b = new Blend();
b.Factors = new float[] { 0, 1, 1 };
b.Positions = new float[] { 0, .5F, 1 };
pgb.Blend = b;
pgb.CenterColor = ((SolidBrush)CurrentBrush).Color;
pgb.SurroundColors = new Color[] {CurrentPen.Color};
gTarget.FillPath(pgb, pTemp);
pgb.Dispose();
pTemp.Dispose();
(source: enigmadream.com)
I edited the original SGDK code for this sample because originally I wasn't smart enough to scale the gradient to exclude the hole, but now I guess I am :).
If you would rather see the gradient like this:
(source: enigmadream.com)
Then change the blend code to look like this:
Blend blend = new Blend();
blend.Factors = new float[] { 0, 1, 0, 0 };
blend.Positions = new float[] { 0, 0.25F, .5F, 1 };
pgb.Blend = blend;
You may use two calls to Graphics.DrawArc combined, drawing the top and bottom or left and right portions of the annulus, one portion at a time.

Categories