Defining Regions for Venn Diagram using Graphics Regions - c#

I have created a Venn diagram using simple Graphics functions provided by WinForm in the onPaint event. Here is my code for creating the Venn.
using (Brush brushLeft = new SolidBrush(LeftVennColor))
{
leftvennPath.AddEllipse(leftVenn);
leftOnlyRegion = new Region(leftVenn);
e.Graphics.FillEllipse(brushLeft, leftVenn);
e.Graphics.DrawEllipse(pen, leftVenn);
}
using (Brush brushRight = new SolidBrush(RightVennColor))
{
rightvennPath.AddEllipse(rightVenn);
rightOnlyRegion = new Region(rightVenn);
e.Graphics.FillEllipse(brushRight, rightVenn);
e.Graphics.DrawEllipse(pen, rightVenn);
}
using (GraphicsPath circle_path = new GraphicsPath())
{
circle_path.AddEllipse(leftVenn);
commonRegion.Intersect(circle_path);
}
using (GraphicsPath circle_path = new GraphicsPath())
{
circle_path.AddEllipse(rightVenn);
commonRegion.Intersect(circle_path);
}
The Venn diagram is created, but with this code my common region is the intersection of both left and right ellipses. I want to have two separate regions out of that common area, which is separated by a line. Here is the image for that,
So basically, I need all these four regions separated and clickable ( different colors for each region ).. I use Region.IsVisible(e.location) in the mouse click event to handle the click event. Could someone please help?

Final solution:
cx0, cy0, radius0 center and radius of left circle
cx1, cy1, radius1 center and radius of right circle
The function takes the regions by ref.
private void FindRegions(int cx0, int cx1, int cy0, int cy1, int radius0, int radius1, ref Region rgnLeft, ref Region rgnRight)
{
//Left circle
GraphicsPath gpL = new GraphicsPath();
//Right circle
GraphicsPath gpR = new GraphicsPath();
//The right small region (yellow color)
GraphicsPath gp = new GraphicsPath();
//Points of intersection
PointF pnt1 = new PointF();
PointF pnt2 = new PointF();
Graphics g = this.CreateGraphics();
gpL.AddEllipse(new Rectangle(cx0 - radius0, cy0 - radius0, 2 * radius0, 2 * radius0));
gpR.AddEllipse(new Rectangle(cx1 - radius0, cy1 - radius1, 2 * radius1, 2 * radius1));
g.DrawPath(Pens.Red, gpL);
g.DrawPath(Pens.Blue, gpR);
int numPoints = FindCircleCircleIntersections((single)cx0, (single)cx1, (single)cy0, (single)cy1, (single)radius0, (single)radius1, ref pnt1, ref pnt2);
if (numPoints != 2)
{
//No regions
return;
}
Double theta, fe;
Double dx = (double)pnt1.X - (double)pnt2.X;
Double dy = (double)pnt1.Y - (double)pnt2.Y;
Double dist = Math.Sqrt(dx * dx + dy * dy);
PointF minPoint, maxPoint;
if (pnt2.Y < pnt1.Y)
{
minPoint = pnt2;
maxPoint = pnt1;
}
else
{
minPoint = pnt1;
maxPoint = pnt2;
}
//theta is the angle between the three points pnt1, pnt2 and left center
theta = Math.Acos((dist / 2D) / 100D);
theta = (theta * 180D) / Math.PI;
theta = 90D - theta;
theta *= 2D;
//fe is the starting angle of the point(between pnt1 and pnt2) with
//the smaller y coordinate. The angle is measured from x axis and clockwise
fe = Math.Asin( Math .Abs ( (-(Double)minPoint.Y + (double)cy0) )/ (double)radius0);
fe = (fe * 180D) / Math.PI;
if (minPoint.X > cx0 && minPoint.Y >= cy0)
{
//fe = (90 - fe) + 270;
}
else if (minPoint.X > cx0 && minPoint.Y < cy0)
{
fe = (90D - fe) + 270D;
}
else if (minPoint.X == cx0 && minPoint.Y < cy0)
{
fe = 270D;
}
else
{
fe += 180D;
}
gp.AddArc(new Rectangle(cx0 - radius0, cy0 - radius0, 2 * radius0, 2 * radius0), (float)fe, (float)theta);
gp.AddLine(maxPoint, minPoint);
gp.CloseFigure();
g.DrawPath(Pens.Green, gp);
Region rgnL = new Region(gpL);
Region rgnR = new Region(gpR);
Region rgnInt = new Region(gpL);
Region rgn = new Region(gp); //right small
rgnInt.Intersect(rgnR);
rgnInt.Exclude(rgn); //left small
g.FillRegion(Brushes.DarkGreen, rgnInt);
g.FillRegion(Brushes.DarkGray, rgn);
rgnLeft = rgnInt.Clone();
rgnRight = rgn.Clone();
g.Dispose();
rgnL.Dispose();
rgnR.Dispose();
rgnInt.Dispose();
rgn.Dispose();
gpL.Dispose();
gpR.Dispose();
gp.Dispose();
}
private int FindCircleCircleIntersections(Single cx0, Single cx1, Single cy0, Single cy1, Single radius0, Single radius1,
ref PointF intersection1, ref PointF intersection2)
{
// Find the distance between the centers.
Single dx = cx0 - cx1;
Single dy = cy0 - cy1;
Double dist = Math.Sqrt(dx * dx + dy * dy);
// See how many solutions there are.
if (dist > radius0 + radius1)
{
//No solutions, the circles are too far apart.
intersection1 = new PointF(Single.NaN, Single.NaN);
intersection2 = new PointF(Single.NaN, Single.NaN);
return 0;
}
else if (dist < Math.Abs(radius0 - radius1))
{
// No solutions, one circle contains the other.
intersection1 = new PointF(Single.NaN, Single.NaN);
intersection2 = new PointF(Single.NaN, Single.NaN);
return 0;
}
else if ((dist == 0) && (radius0 == radius1))
{
// No solutions, the circles coincide.
intersection1 = new PointF(Single.NaN, Single.NaN);
intersection2 = new PointF(Single.NaN, Single.NaN);
return 0;
}
else
{
// Find a and h.
Double a = (radius0 * radius0 - radius1 * radius1 + dist * dist) / (2 * dist);
Double h = Math.Sqrt(radius0 * radius0 - a * a);
// Find P2.
Double cx2 = cx0 + a * (cx1 - cx0) / dist;
Double cy2 = cy0 + a * (cy1 - cy0) / dist;
// Get the points P3.
intersection1 = new PointF( (Single)(cx2 + h * (cy1 - cy0) / dist), (Single)(cy2 - h * (cx1 - cx0) / dist));
intersection2 = new PointF( (Single)(cx2 - h * (cy1 - cy0) / dist), (Single)(cy2 + h * (cx1 - cx0) / dist));
// See if we have 1 or 2 solutions.
if (dist == radius0 + radius1) return 1;
return 2;
}
}
EDIT
Region has only a Fill method and no Draw one. So you cant do it with regions. GraphicPath
however HAS both Fill and Draw.
You said that you need to validate if a point is inside the region BUT you can do the same with GraphicPath
myGraphicPath.IsVisible();
So, dont use regions but paths. It is better for another reason. GraphicPath can draw AntiAlias but regions dont. Set
g.SmoothingMode = SmoothingMode.AntiAlias;
To enable AntiAlias. All goodies with paths!
Change the function name from FindRegions to FindPaths and send paths as refference:
private void FindPaths(int cx0, int cx1, int cy0, int cy1, int radius0, int radius1, ref GraphicsPath gpLeft, ref GraphicsPath gpRight)
The code is exactly the same, but add in the and:
private void FindPaths(int cx0, int cx1, int cy0, int cy1, int radius0, int radius1, ref GraphicsPath gpLeft, ref GraphicsPath gpRight)
{
...
...
//Above code exactly the same
//replace these
//rgnLeft = rgnInt.Clone();
//rgnRight = rgn.Clone();
//with these
GraphicsPath gpLeftSmall = (GraphicsPath)gp.Clone();
Matrix matrix = new Matrix();
PointF pntf = new PointF();
pntf.X = (float)(Math.Min((double)pnt1.X, (double)pnt2.X) + Math.Abs((double)(pnt1.X - pnt2.X) / 2D));
pntf.Y = (float)(Math.Min((double)pnt1.Y, (double)pnt2.Y) + Math.Abs((double)(pnt1.Y - pnt2.Y) / 2D));
matrix.RotateAt(180, pntf);
gpLeftSmall.Transform(matrix);
g.DrawPath(Pens.Black, gpLeftSmall); //If you want to draw it
//passed by refference
gpLeft = gpLeftSmall.Clone();
gpRight = gp.Clone();
g.Dispose();
rgnL.Dispose();
rgnR.Dispose();
rgnInt.Dispose();
rgn.Dispose();
gpL.Dispose();
gpR.Dispose();
gp.Dispose();
gpLeftSmall.Dispose();
matrix.Dispose();
}
Reference:
Determine where two circles intersect

Related

How can i fill part of image with color?

I have image which i add in my form.How can i fill part of image?
I have this
What I'm trying to achieve:
To floodfill an area you need a foodfill routine and very little else.
See this example:
It uses two pictureboxes, also a label to display the chosen color.
And two mouse click events, one to pick the color:
private void pictureBoxPalette_MouseClick(object sender, MouseEventArgs e)
{
Point sPt = scaledPoint(pictureBoxPalette, e.Location);
lbl_color.BackColor = ((Bitmap)pictureBoxPalette.Image).GetPixel(sPt.X, sPt.Y);
}
..and one to call the fill:
private void pictureBoxTgt_MouseClick(object sender, MouseEventArgs e)
{
Point sPt = scaledPoint(pictureBoxTgt, e.Location);
Bitmap bmp = (Bitmap)pictureBoxTgt.Image;
Color c0 = bmp.GetPixel(sPt.X, sPt.Y);
Fill4(bmp, sPt, c0, lbl_color.BackColor);
pictureBoxTgt.Image = bmp;
}
The Floodfill routine is taken from this post; it is basically a direct implementation of a wikipedia algorithm..:
static void Fill4(Bitmap bmp, Point pt, Color c0, Color c1)
{
Color cx = bmp.GetPixel(pt.X, pt.Y);
if (cx.GetBrightness() < 0.01f) return; // optional, to prevent filling a black grid
Rectangle bmpRect = new Rectangle(Point.Empty, bmp.Size);
Stack<Point> stack = new Stack<Point>();
int x0 = pt.X;
int y0 = pt.Y;
stack.Push(new Point(x0, y0) );
while (stack.Any() )
{
Point p = stack.Pop();
if (!bmpRect.Contains(p)) continue;
cx = bmp.GetPixel(p.X, p.Y);
if (cx.ToArgb() == c0.ToArgb()) //*
{
bmp.SetPixel(p.X, p.Y, c1);
stack.Push(new Point(p.X, p.Y + 1));
stack.Push(new Point(p.X, p.Y - 1));
stack.Push(new Point(p.X + 1, p.Y));
stack.Push(new Point(p.X - 1, p.Y));
}
}
}
Note: (*) Color equality will fail if one of the colors is a known or named color. So we need to convert to a common format..
Update
I have updated the code to include a function that will scale a mouse click location to an image pixel point; now it will work with SizeMode=StretchImage as well, so you can work on the whole image..
static Point scaledPoint(PictureBox pb, Point pt)
{
float scaleX = 1f * pb.Image.Width / pb.ClientSize.Width;
float scaleY = 1f * pb.Image.Height / pb.ClientSize.Height;
return new Point((int)(pt.X * scaleX), (int)(pt.Y * scaleY));
}
Of course you can then save the Image.
Note that your original image is 4bpp and must be converted to 24bpp or better before coloring..
Also note that for SizeMode=Zoom the calculations are a little more involved. Here is an example that should work with any SizeMode.:
static Point scaledPoint(PictureBox pbox, Point pt)
{
Size si = pbox.Image.Size;
Size sp = pbox.ClientSize;
int left = 0;
int top = 0;
if (pbox.SizeMode == PictureBoxSizeMode.Normal ||
pbox.SizeMode == PictureBoxSizeMode.AutoSize) return pt;
if (pbox.SizeMode == PictureBoxSizeMode.CenterImage)
{
left = (sp.Width - si.Width) / 2;
top = (sp.Height - si.Height) / 2;
return new Point(pt.X - left, pt.Y - top);
}
if (pbox.SizeMode == PictureBoxSizeMode.Zoom)
{
if (1f * si.Width / si.Height < 1f * sp.Width / sp.Height)
left = (sp.Width - si.Width * sp.Height / si.Height) / 2;
else
top = (sp.Height - si.Height * sp.Width / si.Width) / 2;
}
pt = new Point(pt.X - left, pt.Y - top);
float scaleX = 1f * pbox.Image.Width / (pbox.ClientSize.Width - 2 * left) ;
float scaleY = 1f * pbox.Image.Height / (pbox.ClientSize.Height - 2 * top);
return new Point((int)(pt.X * scaleX), (int)(pt.Y * scaleY));
}

Fill regular polygons with 2 colors

I have drawn regular polygons and divided those into equal parts.
It's like this :
but I want to fill it with 2 colors like this :
How do I implement this?
Code how to draw polygons is below:
Graphics g = e.Graphics;
nPoints = CalculateVertices(sides, radius, angle, center);
g.DrawPolygon(navypen, nPoints);
g.FillPolygon(BlueBrush, nPoints);
Point center = new Point(ClientSize.Width / 2, ClientSize.Height / 2);
for(int i = 0; i < sides; i++) {
g.DrawLine(new Pen(Color.Navy), center.X, center.Y, nPoints[i].X, nPoints[i].Y);
}
private PointF[] CalculateVertices(int sides, int radius, float startingAngle, Point center)
{
if (sides < 3) {
sides = 3;
}
//throw new ArgumentException("Polygon must have 3 sides or more.");
List<PointF> points = new List<PointF>();
float step = 360.0f / sides;
float angle = startingAngle; //starting angle
for (double i = startingAngle; i < startingAngle + 360.0; i += step) //go in a circle
{
points.Add(DegreesToXY(angle, radius, center));
angle += step;
}
return points.ToArray();
}
private PointF DegreesToXY(float degrees, float radius, Point origin)
{
PointF xy = new PointF();
double radians = degrees * Math.PI / 180.0;
xy.X = (int)(Math.Cos(radians) * radius + origin.X);
xy.Y = (int)(Math.Sin(-radians) * radius + origin.Y);
return xy;
}
There are several ways but the most straight-forward is to draw the polygons (triangles) of different colors separately.
Assumig a List<T> for colors:
List<Color> colors = new List<Color> { Color.Yellow, Color.Red };
You can add this before the DrawLine call:
using (SolidBrush brush = new SolidBrush(colors[i%2]))
g.FillPolygon(brush, new[] { center, nPoints[i], nPoints[(i+1)% sides]});
Note how I wrap around both the nPoints and the colors using the % operator!

Given bounding rectangle, starting angle, and sweep angle, how to determine points of the arc endpoints

Given a bounding rectangle, starting angle and the sweep angle, how do I determine the points of each end of the arc?
private void myPaint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
Rectangle rc = new Rectangle(242, 299, 200, 300);
Pen penRed = new Pen(Color.Red, 1);
g.DrawArc(penRed, rc, 18, -108);
// TODO - Determine Point of each end of arc
// Point pt1 = ???
// Point pt2 = ???
}
Using the equation of an ellipse from this excellent Mathematics answer We can calculate the start and end points of your ellipse, given the start angle and sweep.
First, we need the center of the bounding box, so we know how to shift the coordinates. That's simply
Rectangle rc = new Rectangle(242, 299, 200, 300);
int cX = (rc.Left + rc.Right) / 2;
int cY = (rc.Bottom + rc.Top) / 2;
// For debugging purposes, let's mark that point.
g.FillRectangle(Brushes.Yellow, Rectangle.FromLTRB(cX - 3, cY - 3, cX + 3, cY + 3));
We then need to convert the angles from degrees into radians, and change the clockwise angle to a counter-clockwise angle like so:
double minTheta = (Math.PI / 180) * (360 - start);
double maxTheta = (Math.PI / 180) * (360 - (start + sweep));
We'll also define 2 helper functions, the first to normalize an angle (map arbitrary angles into the range 0-360) and the second to adjust the calculated (x, y) coordinates into the correct quadrant. (Given that positive y is actually down on the form)
public double NormalizeAngle(double angle)
{
while (angle >= 360) angle -= 360;
while (angle < 0) angle += 360;
return angle;
}
public void AdjustCoordinatesForAngle(double angle, ref double x, ref double y)
{
if (angle > 0 && angle <= 90)
{
x *= 1;
y *= 1;
}
else if (angle >= 90 && angle < 180)
{
x *= -1;
y *= 1;
}
else if (angle >= 180 && angle < 270)
{
x *= -1;
y *= -1;
}
else if (angle >= 270 && angle < 360)
{
x *= 1;
y *= -1;
}
}
We now have enough information to calculate the start and end points.
double minTheta = (Math.PI / 180) * (360 - start);
double maxTheta = (Math.PI / 180) * (360 - (start + sweep));
double a = width / 2.0;
double b = height / 2.0;
double denom = Math.Pow(a, 2) * Math.Pow(Math.Tan(minTheta), 2);
denom = denom / Math.Pow(b, 2);
denom = Math.Sqrt(denom + 1);
double x = Math.Abs(a / denom);
double y = Math.Abs((a * Math.Tan(minTheta)) / denom);
start = NormalizeAngle(start);
this.AdjustCoordinatesForAngle(start, ref x, ref y);
Those coordinates are relative to the bounding box's center, so we offset it using the center point we calculated above:
x += cX;
y += cY;
We can now draw the point:
g.FillRectangle(Brushes.Purple, new Rectangle((int)x - 3, (int)y - 3, 6, 6));
All together the paint function looks like this:
private void myPaint(object sender, PaintEventArgs e)
{
double start = 18;
double sweep = -108;
Graphics g = e.Graphics;
g.Clear(Color.Black);
Rectangle rc = new Rectangle(200, 10, 200, 300);
int cX = (rc.Left + rc.Right) / 2;
int cY = (rc.Bottom + rc.Top) / 2;
g.FillRectangle(Brushes.Yellow, Rectangle.FromLTRB(cX - 3, cY - 3, cX + 3, cY + 3));
int width = rc.Width;
int height = rc.Height;
if (start >= 360) start -= 360;
double minTheta = (Math.PI / 180) * (360 - start);
double maxTheta = (Math.PI / 180) * (360 - (start + sweep));
double a = width / 2.0;
double b = height / 2.0;
double denom = Math.Pow(a, 2) * Math.Pow(Math.Tan(minTheta), 2);
denom = denom / Math.Pow(b, 2);
denom = Math.Sqrt(denom + 1);
double x = Math.Abs(a / denom);
double y = Math.Abs((a * Math.Tan(minTheta)) / denom);
start = NormalizeAngle(start);
this.AdjustCoordinatesForAngle(start, ref x, ref y);
x += cX;
y += cY;
g.FillRectangle(Brushes.Purple, new Rectangle((int)x - 3, (int)y - 3, 6, 6));
denom = Math.Pow(a, 2) * Math.Pow(Math.Tan(maxTheta), 2);
denom = denom / Math.Pow(b, 2);
denom = Math.Sqrt(denom + 1);
x = Math.Abs(a / denom);
y = Math.Abs((a * Math.Tan(maxTheta)) / denom);
double endAngle = (start + sweep);
endAngle = NormalizeAngle(endAngle);
this.AdjustCoordinatesForAngle(endAngle, ref x, ref y);
x += cX;
y += cY;
g.FillRectangle(Brushes.Blue, new Rectangle((int)x - 3, (int)y - 3, 6, 6));
Pen penRed = new Pen(Color.Red, 1);
g.DrawRectangle(Pens.Green, rc);
g.DrawArc(penRed, rc, (float)start, (float)sweep);
}
I painted the window background black to make the boxes and lines stand out better, and I left in some additional drawing elements, so it is easier to see what's happening in the calculations above.
Placing the code into a form, and associating with the form's paint event produces this result:
One final note, due to rounding, the start and end points may be off by a pixel or two. If you want more accuracy, you'd have to draw the arc yourself.

Display GPS coordinates in a canvas

I'm trying to display GPS coordinates in a canvas.
I have 400 towns in France + USA. I just want to display them in a canvas.
For each town I have its latitude and longitude (taken with google api : https://developers.google.com/maps/documentation/geocoding/ ).
I've managed to have a first result using this thread : Converting from longitude\latitude to Cartesian coordinates
Here is my result :
My code is the following (assuming "_liste" contains a list of Towns) :
private void Button_visualise_Click(object sender, RoutedEventArgs e)
{
System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
watch.Start();
List<Town> _list = LibDAO.Towns_DAO.GetAllTown().Where(u=>u.IdPays == 2 || u.IdPays == 1).ToList<Town>();
this.my_canvas.Children.Clear();
double min_x = 0;
double max_x = 0;
double min_y = 0;
double max_y = 0;
for (int i = 0; i < _list .Count; i++)
{
Ellipse ell = new Ellipse() { Width = 30, Height = 30, Fill = Brushes.Blue };
Point p = ToCanvas(_list [i].Latitude, _list [i].Longitude);
Canvas.SetLeft(ell, p.X);
Canvas.SetTop(ell, p.Y);
if (p.X < min_x) min_x = p.X;
if (p.X > max_x) max_x = p.X;
if (p.Y < min_y) min_y = p.Y;
if (p.Y > max_y) max_y = p.Y;
this.my_canvas.Children.Add(ell);
}
SetCoordinateSystem(this.my_canvas, min_x, max_x, min_y, max_y);
watch.Stop();
}
public static Canvas SetCoordinateSystem(Canvas canvas, Double xMin, Double xMax, Double yMin, Double yMax)
{
var width = xMax - xMin;
var height = yMax - yMin;
var translateX = -xMin;
var translateY = height + yMin;
var group = new TransformGroup();
group.Children.Add(new TranslateTransform(translateX, -translateY));
group.Children.Add(new ScaleTransform(canvas.ActualWidth / width, canvas.ActualHeight / -height));
canvas.RenderTransform = group;
return canvas;
}
private const int earthRadius = 6367;
private Point ToCanvas(double lat, double lon)
{
lon = ConvertToRadians(lon);
lat = ConvertToRadians(lat);
double x = earthRadius * Math.Cos(lat) * Math.Cos(lon); //((lon * my_canvas.ActualWidth) / 360.0) - 180.0; ;// //
double y = earthRadius * Math.Cos(lat) * Math.Sin(lon);// ((lat * my_canvas.ActualHeight) / 180.0) - 90.0;
return new Point(x, y);
}
public double ConvertToRadians(double angle)
{
return (Math.PI / 180) * angle;
}
As you can see in my result it's almost perfect, we can recognize the 2 countries but why are they in the wrong place ? (I would like to have them like this : http://geology.com/world/world-map.gif
Am I missing something ?
Based on this link, my result may be displayed with "Azimuthal (projections onto a plane)" while I would prefer this : http://en.wikipedia.org/wiki/Equirectangular_projection
So I'm thinking of changing my function "ToCanvas" but I don't know the component "the standard parallels (north and south of the equator) where the scale of the projection is true;"
Bonus question : What's the best way to get the border from a country in GPS coordinates ? I would like to draw the border of USA for example, so I guessed I could just get coordinates of borders to draw the country.
I've tried several websites, managed to get a .shp file from there : http://www.naturalearthdata.com/downloads/110m-cultural-vectors/, but I didn't manage to retrieve borders coordinates from there.
Thank you
EDIT Seems better with this code :
private Point ToCanvas(double lat, double lon)
{
// Equirectangular projection
double x1 = lon * Math.Cos(ConvertToRadians(lat));
double y1 = lat;
//lon = ConvertToRadians(lon);
//lat = ConvertToRadians(lat);
//double x = earthRadius * Math.Cos(lat) * Math.Cos(lon); //((lon * my_canvas.ActualWidth) / 360.0) - 180.0; ;// //
//double y = earthRadius * Math.Cos(lat) * Math.Sin(lon);// ((lat * my_canvas.ActualHeight) / 180.0) - 90.0;
return new Point(x1 * 10, y1 * 10);
}

Drawing polar curve Lemiscate bug

I´m trying to draw a lemiscate. My code isn't drawing the curve correctly. Why does the line start or end at the point 0,0 (left corner)?
private void drawLemiscate(Graphics g, int a, int Sx,int Sy)
{
int x, y;
Point[] p = new Point[720];
for (int phi = 0; phi < 720; phi++)
{
int r = (int)(a * Math.Cos(2 * degreeToRadians(phi)));
if (r > 0)
continue;
x = (int)Math.Round((r * Math.Sin(degreeToRadians(phi)) + Sx));
y = (int)Math.Round((r * Math.Cos(degreeToRadians(phi)) + Sy));
p[phi] = new Point(x, y);
}
Pen pen = new Pen(Color.Red, 1);
g.DrawLines(pen, p);
canvas.Invalidate();
}
private double degreeToRadians(double angle)
{
return Math.PI * angle / 180.0;
}
You should investigate which element of p is (0, 0). You can use the debugger to inspect it or use a loop to look for it and print out which index(es) have (0, 0).
Hint: consider what effect if (r > 0) continue; has on your output.

Categories