Problem
I have a list of points in C# that I draw on a panel on a Windows Forms object. The lists variables are two listA and listB. The points in listB are the points in listA except that they have gone through some transformation to deform it to resemble the shape formed by points in listA and then added some outliers to make them look different. If you can try these on your visual studio then this is the code...
class Form1 : Form
{
//declare the list to hold points for
//shapes
List<Point> listA = new List<Point>();
List<Point> listB = new List<Point>();
//this methods transforms,applies outliers and draws the shapes on panel1
private void button1_click(EventArgs e, object sender)
{
//clear the lists for initializing
listA.Clear();
listB.Clear();
Point p1a = new Point(20, 30);
Point p2a = new Point(120, 50);
Point p3a = new Point(160, 80);
Point p4a = new Point(180, 300);
Point p5a = new Point(100, 220);
Point p6a = new Point(50, 280);
Point p7a = new Point(20, 140);
//Hold the Points in an array
Point[] mypoints = new Point[] { p1a, p2a, p3a, p4a, p5a, p6a, p7a };
//add the points to the List with one call
listA.AddRange(mypoints);
//define a new Transformation
//that will translate shapeA to have a slightly different imageB
Transformation t2 = new Transformation();
t2.A = 1.05; t2.B = 0.05; t2.T1 = 15; t2.T2 = 22;
//assign the new translated points to listB
listB = applytransformation(t2, listA);
//Add outliers to listb by manipulating the values in the list
Shape2[2] = new Point(Shape2[2].X + 10, Shape2[2].Y + 3);
//create a new instance of pen
//for drawing imageA in blue
Pen penner = new Pen(Brushes.Blue, 3);
//Create a new instance of pen for
//drawing imageB in red
Pen mypen = new Pen(Brushes.Red, 3);
//get the graphic context
Graphics g = panel1.CreateGraphics();
//draw both shapes
DisplayShape(listA, penner, g);
DisplayShape(listB, mypen, g);
}
//the method below does the transformation of imagea into imageb by manipulating the points and the transformation
List<Point> applytransformation(Transformation x, List<Point> shape)
{
List<Point> Tlist = new List<Point>();
foreach (Point c in shape) {
double xprime = x.A * c.X + x.B * c.Y + x.T1;
double yprime = x.B * c.X * -1 + x.A * c.Y + x.T2;
Point ptrans = new Point((int)xprime, (int)yprime);
Tlist.Add(ptrans);
}
//it returns the points that will be used to draw imageB
return Tlist;
}
//this method draws the points on the panel
void DisplayShape(List<Point> Shp, Pen pen, Graphics G)
{
Point? prevPoint = null;//nullable
foreach (Point pt in Shp) {
G.DrawEllipse(pen, new Rectangle(pt.X - 2, pt.Y - 2, 4, 4));
if (prevPoint != null) {
G.DrawLine(pen, (Point)prevPoint, pt);
}
prevPoint = pt;
}
G.DrawLine(pen, Shp[0], Shp[Shp.Count - 1]);
}
}
public class Transformation
{
public double A { get; set; }
public double B { get; set; }
public double T1 { get; set; }
public double T2 { get; set; }
}
Goal
I want to remove all the outliers in imageB so that it resembles imageA even if it won't be perfect. All methods or algorithms are welcome ie RANSAC,minimum cost function. I have tried to find an authoritative source online that can guide or help me achieve this in C# with zero success. The code I have provided is a minimum reproducible example that can be replicated on any visual studio IDE.Please help, Thank You for your time and contribution.
Expected Output
I added an image to make it clear the result I want
If you have many points forming a cloud of points where the line defining the shape goes through, then you can remove outliers. As an example see Removing outliers. But in this case, every point in the list seems to be a vertex of the shape. Removing a point will alter the shape considerably.
Can you explain what these shapes represent? hat should happen if you remove an outlier? Should it be replaced by another point?
While this is not an answer to your question, here is an improved and simplified version of the code:
List<Point> listA, listB; // Initialization not required.
private void button1_click(EventArgs e, object sender)
{
// Simplify initialization with collection and object initializers.
listA = new List<Point> {
new Point(20, 30), new Point(120, 50),
new Point(160, 80), new Point(180, 300),
new Point(100, 220), new Point(50, 280),
new Point(20, 140)
};
var t2 = new Transformation { A = 1.05, B = 0.05, T1 = 15, T2 = 22 };
listB = ApplyTransformation(t2, listA);
// Simplify shifting point.
Shape2[2] += new Size(10, 3);
// Invalidate panel and let Panel1_Paint draw it.
// Never create your own Graphics object.
panel1.Invalidate();
}
private void Panel1_Paint(object sender, PaintEventArgs e)
{
if (listA != null && listB != null) {
// Use predefined pens instead of creating brushes.
DisplayShape(listA, Pens.Blue, e.Graphics);
DisplayShape(listB, Pens.Red, e.Graphics);
}
}
List<Point> ApplyTransformation(Transformation x, List<Point> shape)
{
// Prevent list resizing by specifying initial size.
var transformedList = new List<Point>(shape.Count);
foreach (Point c in shape) {
double xprime = x.A * c.X + x.B * c.Y + x.T1;
double yprime = x.B * c.X * -1 + x.A * c.Y + x.T2;
transformedList.Add(new Point((int)xprime, (int)yprime));
}
return transformedList;
}
void DisplayShape(List<Point> shape, Pen pen, Graphics g)
{
// By using "for" instead of "foreach" we have indexes we can use to
// simplify closing the shape, since we always have a previous point.
for (int i = 0; i < shape.Count; i++) {
Point prevPoint = i > 0 ? shape[i - 1] : shape[shape.Count - 1];
Point pt = shape[i];
// No need to create a rectangle,
// there is an overload accepting location and size.
g.DrawEllipse(pen, pt.X - 2, pt.Y - 2, 4, 4);
g.DrawLine(pen, prevPoint, pt);
}
}
Since C# 8.0 and in .NET Core projects we can also write shape[^1] to get the last point instead of shape[shape.Count - 1].
Related
Basically i have a windows form that user will be able to draw different shapes(e.g square, circle and triangle), user will be able to highlight any of these shapes after drawing and then control that highlighted shape by moving or rotating it, i don't know how to rotate the shape. any one can help, this is my code (only to draw a square)
PS: user need to click twice on the form to draw the shape between those 2 points as shown below also i know i should be using onPaint method but this is the requirements of the task
Thanks
public Square(Point keyPt, Point oppPt) // constructor
{
this.keyPt = keyPt;
this.oppPt = oppPt;
}
// You will need a different draw method for each kind of shape. Note the square is drawn
// from first principles. All other shapes should similarly be drawn from first principles.
// Ideally no C# standard library class or method should be used to create, draw or transform a shape
// and instead should utilse user-developed code.
public void draw(Graphics g, Pen blackPen)
{
// This method draws the square by calculating the positions of the other 2 corners
double xDiff, yDiff, xMid, yMid; // range and mid points of x & y
// calculate ranges and mid points
xDiff = oppPt.X - keyPt.X;
yDiff = oppPt.Y - keyPt.Y;
xMid = (oppPt.X + keyPt.X) / 2;
yMid = (oppPt.Y + keyPt.Y) / 2;
// draw square
g.DrawLine(blackPen, (int)keyPt.X, (int)keyPt.Y, (int)(xMid + yDiff / 2), (int)(yMid - xDiff / 2));
g.DrawLine(blackPen, (int)(xMid + yDiff / 2), (int)(yMid - xDiff / 2), (int)oppPt.X, (int)oppPt.Y);
g.DrawLine(blackPen, (int)oppPt.X, (int)oppPt.Y, (int)(xMid - yDiff / 2), (int)(yMid + xDiff / 2));
g.DrawLine(blackPen, (int)(xMid - yDiff / 2), (int)(yMid + xDiff / 2), (int)keyPt.X, (int)keyPt.Y);
}
public void fillSquare(Graphics g, Brush redBrush)
{
float xDiff = oppPt.X - keyPt.X;
float yDiff = oppPt.Y - keyPt.Y;
float xMid = (oppPt.X + keyPt.X) / 2;
float yMid = (oppPt.Y + keyPt.Y) / 2;
var path = new GraphicsPath();
path.AddLines(new PointF[] {
keyPt,
new PointF(xMid + yDiff/2, yMid-xDiff/2),
oppPt
});
path.AddLines(new PointF[] {
keyPt,
new PointF(xMid - yDiff/2, yMid + xDiff/2),
oppPt
});
path.CloseFigure();
// Fill Triangle
g.FillPath(redBrush, path);
}
}
}
i have tried this method but something is missing i don't know what is it
private void itemRotation(PaintEventArgs e)
{
Pen blackpen = new Pen(Color.Black);
Graphics g = e.Graphics;
Font myFont = new System.Drawing.Font("Helvetica", 9);
Brush blackwriter = new SolidBrush(System.Drawing.Color.Black);
if (rotateItem)
{
for (int i = 0; i < shapes.Count; i++)
{
if (shapes[i].Selected)
{
if (shapes[i].ShapeType == (int)ShapeTypes.Square)
{
PointF center = new PointF(shapes[i].keyPt.X + (shapes[i].oppPt.X / 2.0F), shapes[i].keyPt.Y + (shapes[i].oppPt.Y / 2.0F));
shapes[i].keyPt = new Point(shapes[i].keyPt.X, shapes[i].keyPt.Y);
shapes[i].oppPt = new Point(shapes[i].oppPt.X, shapes[i].oppPt.Y);
Matrix myMatrix = new Matrix();
myMatrix.Rotate(30);
g.Transform = myMatrix;
((Square)shapes[i]).draw(g, blackpen);
g.DrawString("2nd pos", myFont, blackwriter, shapes[i].keyPt.X, shapes[i].oppPt.X);
}
}
}
}
}
Below is an example of how to draw the same shape (a GraphicsPath) into various locations and rotations.
The key here is the following two commands
e.Graphics.TranslateTransform(x, y);
e.Graphics.RotateTransform(-angle);
See results below:
and the code used to generate it:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
// This code defines a graphics shape using a GraphicsPath
// and draws multiple copies along a grid and with various
// rotation angle angles.
e.Graphics.SmoothingMode=SmoothingMode.AntiAlias;
var target = sender as PictureBox;
// Step 1 - Define a rectangle 20 by 12 pixels, center at origin.
var gp = new GraphicsPath();
gp.AddLines(new PointF[] {
new PointF(-10, -6),
new PointF( 10, -6),
new PointF( 10, 6),
new PointF(-10, 6) });
gp.CloseFigure();
// Step 2 - Define a 10×9 grid with two loops
float angle = 0;
for (int i = 0; i<9; i++)
{
// divide the control height into 10 divisions
float y = (i+1)*target.Height/10;
for (int j = 0; j<10; j++)
{
// divide the control width into 11 divisions
float x = (j+1)*target.Width/11;
// Save the default transformation state
var state = e.Graphics.Save();
// Traslate the origin to (x,y), each grid point
e.Graphics.TranslateTransform(x, y);
// Rotate shape by an angle (negative = CCW)
e.Graphics.RotateTransform(-angle);
// Draw the shape
e.Graphics.FillPath(Brushes.LightSeaGreen, gp);
e.Graphics.DrawPath(Pens.Black, gp);
// Restore the default transformation state
e.Graphics.Restore(state);
// Increment the angle by one degree.
// The idea is to show all 90 degrees of rotation in a 10×9 grid.
angle++;
}
}
}
I am trying to save the triangle I drew and draw again while the previous triangle is still there. I did this in rectangle, square, circle and ellipse and it worked. I don't know why it won't in Triangle. Is there something wrong in the code?
This is how I draw and "save (not working)"
Shape Class
public void DrawTriangle(Color c, int stroke,PointF[] tpoints, float w, Graphics g)
{
this.width = w;
this.strokeThickness = stroke;
this.tPoints = tpoints;
g.InterpolationMode = InterpolationMode.High;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.DrawPolygon(new Pen(c, stroke), tpoints);
}
Form 1
public void DrawTriangle()
{
tC = Color.Red;
strokeTriangle = trackBar_Stroke.Value;
tW = Convert.ToInt32((Convert.ToInt32(tbox_Width.Text) * 96) / 25.4);
tH = (Convert.ToInt32((tW * (Math.Sqrt(3))) / 2));
tX = (pictureBox_Canvass.Width - tW) / 2;
tY = ((pictureBox_Canvass.Width - (tH)) / 2) + tH;
float angle = 0;
t_Points[0].X = tX;
t_Points[0].Y = tY;
t_Points[1].X = (float)(tX + tW * Math.Cos(angle));
t_Points[1].Y = (float)(tY + tW * Math.Sin(angle));
t_Points[2].X = (float)(tX + tW * Math.Cos(angle - Math.PI / 3));
t_Points[2].Y = (float)(tY + tW * Math.Sin(angle - Math.PI / 3));
}
public void AcceptTriangle()
{
Shape shape = new Shape();
tC = Color.Gray;
shape.strokeThickness = strokeTriangle;
shape.width = tW;
shape.x = tX;
shape.y = tY;
shape.tPoints = t_Points;
s._triangle.Add(shape);
}
s.DrawTriangle(tC, strokeTriangle,t_Points, tX, tY, tW, e.Graphics);
This is how I iterate it.
public List<Shape> _triangle = new List<Shape>();
foreach(Shape shapes3 in s._triangle)
{
shapes3.DrawTriangle(shapes3.color, shapes3.strokeThickness, shapes3.tPoints, shapes3.width, e.Graphics);
}
At two points in your code you write an array assignment like this.:
this.tPoints = tpoints;
.. and this:
shape.tPoints = t_Points;
It is a common error to assume that this creates an array with data. It doesn't. All it does is make an array variable point to an array that was there before.
The data are not duplicated. So when you overwrite the data or clear them the 'new' array now points to the changed or cleared data.
So all your objects have the very same points.
To correct create actual copies of the data!
The simplest way is to add a ToArray() call like this:
this.tPoints = tpoints.ToArray();
.. and this:
shape.tPoints = t_Points.ToArray();
To reiterate:
int[] p1 = new int[2] { 23, 42 }; // Now we have one array.
int[] p2 = new int[2] { 3, 2 }; // Now we have two arrays.
p2 = p1; // Now we have only one array again.
p2[1]=1234; // Now p1[1] is 1234
Accepting the Triangle (Saving to the list)
var triangle = new Shape
{
strokeThickness = strokeTriangle,
color = tC,
tPoints = t_Points.ToArray(),
x=tX,
y=tY,
width = tW,
};
s._triangle.Add(triangle);
Iterating through the list
foreach(Shape shapes3 in s._triangle)
{
shapes3.DrawTriangle(shapes3.color, shapes3.strokeThickness,shapes3.tPoints.ToArray(), shapes3.x, shapes3.y, shapes3.width, e.Graphics);
}
The application I'm maintaining has custom drawing functionality, which draws some king of "objects" on an Graphics surface. Object boundaries are described with Rectangle.
Sometimes I need to detect objects, whose rectangles are intersecting with given rectangle.
If the number of objects is large enough, simple iteration like this:
var objectsToManage = _objects.Where(_ => rc.IntersectsWith(_.InscribeRect));
obviously, too slow (_objects here is List<MyObjType>, IscribeRect is object boundaries, and rc is a given rectangle).
I'm thinking about how to do this much faster. First idea is to "sort" objects by theirs rectangles and put them into sorted set... But I'm suspecting, that I'm re-inventing the wheel.
Is there any well-known approaches to achieve what I want?
This is can be done using Quadtrees. You can find a c# implementation here: Virtualized WPF Canvas (the quadtree code is not strictly related to WPF), also lots of info here: ZoomableApplication2: A Million Items and another implementation here: PriorityQuadTree
#region FnLineMerginRectandLines
public static bool LineIntersectsRect(Point p1, Point p2, Rectangle r)
{
return LineIntersectsLine(p1, p2, new Point(r.X, r.Y), new Point(r.X + r.Width, r.Y)) ||
LineIntersectsLine(p1, p2, new Point(r.X + r.Width, r.Y), new Point(r.X + r.Width, r.Y + r.Height)) ||
LineIntersectsLine(p1, p2, new Point(r.X + r.Width, r.Y + r.Height), new Point(r.X, r.Y + r.Height)) ||
LineIntersectsLine(p1, p2, new Point(r.X, r.Y + r.Height), new Point(r.X, r.Y)) ||
(r.Contains(p1) && r.Contains(p2));
}
private static bool LineIntersectsLine(Point l1p1, Point l1p2, Point l2p1, Point l2p2)
{
float q = (l1p1.Y - l2p1.Y) * (l2p2.X - l2p1.X) - (l1p1.X - l2p1.X) * (l2p2.Y - l2p1.Y);
float d = (l1p2.X - l1p1.X) * (l2p2.Y - l2p1.Y) - (l1p2.Y - l1p1.Y) * (l2p2.X - l2p1.X);
if (d == 0)
{
return false;
}
float r = q / d;
q = (l1p1.Y - l2p1.Y) * (l1p2.X - l1p1.X) - (l1p1.X - l2p1.X) * (l1p2.Y - l1p1.Y);
float s = q / d;
if (r < 0 || r > 1 || s < 0 || s > 1)
{
return false;
}
return true;
}
#endregion
public class Line
{
private int Point1X;
private int Point1Y;
private int Point2X;
private int Point2Y;
public Point P1;
public Point P2;
public Line()
{
}
public Line(int left, int top, int width, int height)
{
this.Point1X = Convert.ToInt32(left);
this.Point1Y = Convert.ToInt32(top);
this.Point2X = Convert.ToInt32(width);
this.Point2Y = Convert.ToInt32(height);
P1 = new Point(Point1X, Point1Y);
P2 = new Point(Point2X, Point2Y);
}
public Line(string left, string top, string width, string height)
{
this.Point1X = Convert.ToInt32(left);
this.Point1Y = Convert.ToInt32(top);
this.Point2X = Convert.ToInt32(width);
this.Point2Y = Convert.ToInt32(height);
P1 = new Point(Point1X, Point1Y);
P2 = new Point(Point2X, Point2Y);
}
public Line(Point p1, Point P2)
{
this.P1 = p1;
this.P2 = P2;
}
}
public static List<Line>getfourborders(Rectangle RT)
{
Line topline = new Line(new Point(RT.Left,RT.Top),new Point(RT.Width+RT.Left,RT.Top));// Top Line
Line leftline = new Line((new Point(RT.Left,RT.Top)),new Point(RT.Left,RT.Top+RT.Height));// left Line
Line rightline = new Line((new Point(RT.Left+RT.Width,RT.Top)),new Point(RT.Left + RT.Width,RT.Top+RT.Height));// Right Line
Line bottomline = new Line((new Point(RT.Left,RT.Top+RT.Height)),new Point(RT.Left+RT.Width,RT.Top+RT.Height));//bottom line
List<Line> borderlines = new List<Line>();
borderlines.Add(leftline);
borderlines.Add(topline);
borderlines.Add(rightline);
borderlines.Add(bottomline);
return borderlines;
}
//YourObjectList() contains a rectangle type
public class myobject
{
public myobject(object S, Rectangle RT)
{
this.Rt = RT;
this.anyobjecttype= S;
}
public Rectangle Rt;
public object anyobjecttype ;
}
public List<myobject> CompareRectangles(List<myobject> Rect ,Rectangle GivenRectangle)
{
List<myobject> intersectingobjects = new List<myobject>();
Rectangle CompareWith = new Rectangle();//"_objects.Where(_ => rc.IntersectsWith(_.InscribeRect));"
foreach(myobject iterate in Rect)
{
List<Line> BorderLines = new List<Line>();
BorderLines.AddRange(getfourborders(iterate.Rt));
bool Intersects = BorderLines.Any(x=>LineIntersectsRect(x.P1,x.P2,CompareWith));
if (Intersects)
intersectingobjects.Add(iterate);
}
return intersectingobjects;
}
create another function to get all the border lines(get four points and create four lines from rectangle 1 ) and check if any of the line merges with another rectanglecompare using lineintersectsRect if any of that returns true then the rectangle 1 will intersect with your rectangle R, you can loop it to check rectangle 2 intersects with rectanglecompare and so on..
make sure that you don't pass divide by zero exception in line intersects with line
How can i draw a polygon according to the input coordinates which are given in C#.
You didn't show any code because based on those coordinate, you are applying some form of scaling to the image.
Using the Paint event of a PictureBox, here is an example using those coordinates on the screen. It fills in the polygon, then draws the border, then it loops through all the points to draw the red circle:
void pictureBox1_Paint(object sender, PaintEventArgs e) {
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.Clear(Color.White);
// draw the shading background:
List<Point> shadePoints = new List<Point>();
shadePoints.Add(new Point(0, pictureBox1.ClientSize.Height));
shadePoints.Add(new Point(pictureBox1.ClientSize.Width, 0));
shadePoints.Add(new Point(pictureBox1.ClientSize.Width,
pictureBox1.ClientSize.Height));
e.Graphics.FillPolygon(Brushes.LightGray, shadePoints.ToArray());
// scale the drawing larger:
using (Matrix m = new Matrix()) {
m.Scale(4, 4);
e.Graphics.Transform = m;
List<Point> polyPoints = new List<Point>();
polyPoints.Add(new Point(10, 10));
polyPoints.Add(new Point(12, 35));
polyPoints.Add(new Point(22, 35));
polyPoints.Add(new Point(24, 22));
// use a semi-transparent background brush:
using (SolidBrush br = new SolidBrush(Color.FromArgb(100, Color.Yellow))) {
e.Graphics.FillPolygon(br, polyPoints.ToArray());
}
e.Graphics.DrawPolygon(Pens.DarkBlue, polyPoints.ToArray());
foreach (Point p in polyPoints) {
e.Graphics.FillEllipse(Brushes.Red,
new Rectangle(p.X - 2, p.Y - 2, 4, 4));
}
}
}
You may use Graphics.DrawPolygon. You can store the coordinates in an array of Point and then you can pass that to DrawPolygon method. You may wanna see:
Drawing with Graphics in WinForms using C#
private System.Drawing.Graphics g;
System.Drawing.Point[] p = new System.Drawing.Point[6];
p[0].X = 0;
p[0].Y = 0;
p[1].X = 53;
p[1].Y = 111;
p[2].X = 114;
p[2].Y = 86;
p[3].X = 34;
p[3].Y = 34;
p[4].X = 165;
p[4].Y = 7;
g = PictureBox1.CreateGraphics();
g.DrawPolygon(pen1, p);
This simple function is able to generate an array of PointF equal to the vertices of the regular polygon to be drawn, where "center" is the center of the polygon, "sides" is its number of sides, "sideLength" is the size of each side in pixels and "offset" is its slope.
public PointF[] GetRegularPolygonScreenVertex(Point center, int sides, int sideLength, float offset)
{
var points = new PointF[sides];
for (int i = 0; i < sides; i++)
{
points[i] = new PointF(
(float)(center.X + sideLength * Math.Cos((i * 360 / sides + offset) * Math.PI / 180f)),
(float)(center.Y + sideLength * Math.Sin((i * 360 / sides + offset) * Math.PI / 180f))
);
}
return points;
}
The result obtained can be used to draw a polygon, e.g. with the function:
GraphicsObject.DrawPolygon(new Pen(Brushes.Black, GetRegularPolygonScreenVertex(new Point(X, Y), 6, 30, 60f));
Which will generate a regular hexagon with a side of 30 pixels inclined by 30°.
hex
Here I have to create a diamond using drawlines method and make it move horizontally along a path that is half way from the top of the form.
I created a diamond and it is moving horizontally, but i want it to start moving from a position which is half way from the top of the form.
This is the code to create a diamond,
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
Point p1 = new Point(5+x, 0);
Point p2 = new Point(10+x, 5);
Point p3 = new Point(5+x, 10);
Point p4 = new Point(0+x, 5);
Point[] ps = { p1, p2, p3, p4, p1 };
Pen p_yellow = new Pen(Color.Yellow, 5);
g.DrawLines(p_yellow, ps);
this.BackColor = System.Drawing.Color.DarkBlue;
}
I can make it move using the timer and following is the code,
private void timer1_Tick(object sender, EventArgs e)
{
if (x < 500)
x += 2;
else
timer1.Enabled = false;
this.Invalidate();
}
please tell me how to bring the diamond to a point which is half way from the top of the form?
private void Form1_Paint(object sender, PaintEventArgs e)
{
int height = 10;
int middle = height / 2;
int middleform = Form1.height / 2;
int diamondMiddleOfTheForm;
diamondMiddleOfTheForm = middleForm - middle;
Graphics g = e.Graphics;
Point p1 = new Point(5 + x, 0 + diamondMiddleOfTheForm);
Point p2 = new Point(10 + x, 5 + diamondMiddleOfTheForm);
Point p3 = new Point(5 + x, 10 + diamondMiddleOfTheForm);
Point p4 = new Point(0 + x, 5 + diamondMiddleOfTheForm);
Point[] ps = { p1, p2, p3, p4, p1 };
Pen p_yellow = new Pen(Color.Yellow, 5);
g.DrawLines(p_yellow, ps);
this.BackColor = System.Drawing.Color.DarkBlue;
}
It shows an error at middleForm = Form1.Height / 2 and diamondMiddleOfTheForm = middleForm - middle
I apologize for my mistake, if I did any in implementing what you said...
you need to find the height of the diamond, first. take the highest point in the diamond: 0, and add the lowest point in the diamond: 10
height = 10
then find the middle of the diamond, vertically:
middle = height / 2
then find the middle of the form:
middleForm = form.Height / 2
then calculate the position of the diamond by moving it "up" from the middle of the form by half the height of the diamond:
diamondMiddleOfTheForm = middleForm - midddle
the "diamondMiddleOfTheForm" variable tells you where to offset your "y" values
Point p1 = new Point(5+x, 0+diamondMiddleOfTheForm);
Point p2 = new Point(10+x, 5+diamondMiddleOfTheForm);
Point p3 = new Point(5+x, 10+diamondMiddleOfTheForm);
Point p4 = new Point(0+x, 5+diamondMiddleOfTheForm);