how to resize polygon in C#? - c#

I draw Polygon with this code:
Graphics surface;
surface = this.CreateGraphics();
SolidBrush brush = new SolidBrush(Color.Olive);
Point[] points = { new Point(50, 50), new Point(250, 50), new Point(50, 250) };
surface.FillPolygon(brush, points);
how to resize polygon Similar to the following?
Pic

Try this:
var g = e.Graphics;
var points=new PointF[] { new PointF(0, 0), new PointF(1, 0), new PointF(0, 1) };
var st=g.SaveState();
g.TranslateTransform(100f, 100f);
g.ScaleTransform(40f, 40f);
g.FillPolygon(Brushes.Olive, points);
g.Transform=mx;
g.TranslateTransform(300f, 100f);
g.ScaleTransform(80f, 80f);
g.FillPolygon(Brushes.MediumOrchid, points);
g.Restore(st);
which draws to polygons of the same shape on different locations with different sizes.
(red annotations added by me)

You have a couple options. A simple, rather silly solution would be to use linq:
double resizeValue = 1.5;
points.Select(x => new Point(x.X*resizeValue, x.Y*resizeValue);
That way is simple to understand, I think. May be better ways, but if this is all you're doing, it's probably sufficient.

Related

Drawing a Rectangle of Size 2X2 Inches -Inches to Pixel Conversion

I need to draw a rectangle that should be around the size 2X2 Inches when printed on a paper.
I know that i can draw a rectangle using
g.DrawRectangle(pen, 100,100, 100, 200);
This application will only be used in computers.How can i convert the inches to pixels properly so that i can get the desired dimensions when printed.
To make an image print in the right size by default, it needs to have the right combination of dpi and pixels.
Let's look at an example:
// aiming at 150dpi and 4x6 inches:
float dpi = 150;
float width = 4;
float height = 6;
using (Bitmap bmp = new Bitmap((int)(dpi * width), (int)(dpi * height)))
{
// first set the resolution
bmp.SetResolution(dpi, dpi);
// then create a suitable Graphics object:
using (Graphics G = Graphics.FromImage(bmp))
using (Pen pen = new Pen(Color.Orange))
{
pen.Alignment = System.Drawing.Drawing2D.PenAlignment.Center;
G.Clear(Color.FloralWhite);
// using pixels here:
Size sz = new System.Drawing.Size((int)dpi * 2 - 1, (int)dpi * 2 - 1);
G.DrawRectangle(pen, new Rectangle(new Point(0, 0), sz));
G.DrawRectangle(pen, new Rectangle(new Point(0, 300), sz));
G.DrawRectangle(pen, new Rectangle(new Point(0, 600), sz));
G.DrawRectangle(pen, new Rectangle(new Point(300, 0), sz));
G.DrawRectangle(pen, new Rectangle(new Point(300, 300), sz));
G.DrawRectangle(pen, new Rectangle(new Point(300, 600), sz));
// alternative code:
// we can also set the Graphics object to measure stuff in inches;
G.PageUnit = GraphicsUnit.Inch;
// or fractions of it, let's use 10th:
G.PageScale = 0.1f;
using (Pen pen2 = new Pen(Color.MediumPurple, 1f / dpi * G.PageScale))
{
// draw one rectangle offset by an inch:
G.DrawRectangle(pen2, 10f, 10f, 20f, 20f);
}
bmp.Save(#"D:\xxx.jpg", ImageFormat.Jpeg);
}
}
Note that I had to subtract 1 pixel from the drawn size as DrawRectangle overdraws by 1 pixel!
Note that the coordinates I draw at depend on the resolution! Also note how the jpeg format creates a lot of smeared colors. Pngcreates crisper results, especially once you print text..
Also note how I had to scale down the PenWidth in the alternative code!

C# fill polygon (triangle)

I have problem with draw two polygons.
I want to fill two triangles, but one is greater than the second.
I am using UserControl in winforms.
Code:
Point[] DOWN = new Point[] {new Point(0, 0), new Point(10, 0), new Point(5, 5)};
Point[] UP = new Point[] { new Point(0, 15), new Point(10, 15), new Point(5, 10) };
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
SolidBrush brush = new SolidBrush(Color.FromArgb(253, 198, 19));
e.Graphics.FillPolygon(brush, DOWN);
e.Graphics.FillPolygon(brush, UP);
brush.Dispose();
}
Where is problem?
Try setting the PixelOffsetMode property:
e.Graphics.PixelOffsetMode = PixelOffsetMode.Half;
using (SolidBrush brush = new SolidBrush(Color.FromArgb(253, 198, 19))) {
e.Graphics.FillPolygon(brush, DOWN);
e.Graphics.FillPolygon(brush, UP);
}
Result:
Try keeping the order counter-clockwise and start from the highest point:
new Point(5, 10), new Point(10, 15), new Point(0, 15)
Tell us if that helped. Sometimes those algorithms don't behave well on border conditions.

How to shear rectangle without moving it?

I'd like to ask whether it is possible to shear object without actually moving it. Here's the code I'm doing it right now
Matrix matrix = new Matrix();
matrix.Shear(2, 0);
g.Transform = matrix ;
g.DrawRectangle(Pens.Black, new Rectangle(200, 200, 100, 100));
g.ResetTransform();
The Shear factors are relative to the origin of the coordinate system.
So to keep the shear result at the 'same' location you need to add a translation matrix.
Create a translation that moves the point that should be static to the origin of the coordinate system. In the example the static point is (200,300) so the translation is (-200, -300)
apply the translation
Shear
create the inverse of the translation. In the example: (200, 300)
apply the inverse translation
BTW: Make sure you Dispose the matrices and other GDI+ objects!!
Matrix matrix = new Matrix();
matrix.Translate(200, 300);
matrix.Shear(2, 0);
matrix.Translate(-200, -300);
g.Transform = matrix ;
g.DrawRectangle(Pens.Black, new Rectangle(200, 200, 100, 100));
g.ResetTransform();
Or
using (var g = this.CreateGraphics())
{
using(Matrix translation = new Matrix(),
reverseTranslation = translation.Clone(),
sheer = new Matrix()
combination = new Matrix())
{
translation.Translate(200, 300);
reverseTranslation.Invert();
sheer.Shear(2, 0);
combination.Multiply(translation);
combination.Multiply(sheer);
combination.Multiply(reverseTranslation);
g.Transform = combination;
g.DrawRectangle(Pens.Black, new Rectangle(200, 200, 100, 100));
g.ResetTransform();
g.DrawRectangle(Pens.Black, new Rectangle(200, 200, 100, 100));
}
}
This is what you need to do:
Translate the lower-left corner of your rectangle to the origin.
Let the offset be (-dX, -dY).
Apply your shear transform.
Apply the inverse translation to your rectangle, i.e., (dX, dY).

C# GDI+ curve drawing issue

I'm trying to draw a series of connected segments, but the curved segments seem to produce an artifact, whereby the outer side of the curve is not smooth at all, but very jagged. This is part of a GIS program I am making.
For these lines, the line itself needs to be quite wide, as this represents the range of data that can be collected on this line for the GIS data. There also has to be an area directly under the line where no data is collected. This also can be wide, but not as wide as the main line.
I have done this using a graphics path, which I then widen and use as a clipping region to block the area directly under the line. I then draw the actual line. The sample code below does this, with made up values for ease of regenerating.
This works fine with straight lines, but with curved lines there are very irregular shapes on the outside of the curves. I have no idea why this happens.
Any ideas would be much appreciated, cheers,
Greg
I made this sample code using a basic form with a picturebox and a button on it, whereby when I clicked the button it would execute this method:
private void drawCurvedLine()
{
//initialise the plot area:
Bitmap image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
pictureBox1.BackgroundImage = image;
Graphics g = Graphics.FromImage(image);
//the width of the pen represents the width of a sonar swathe:
Pen widePen = new Pen(new SolidBrush(Color.FromArgb(80, Color.Blue)), 50);
PointF[] points = new PointF[4];
//first straight:
points[0] = new PointF(287.284149F,21.236269F);
points[1] = new PointF(183.638443F,406.936249F);
//second straight:
points[2] = new PointF(130.842773F, 515.574036F);
points[3] = new PointF(-1950.91321F, 3491.868F);
//graphics path for the line:
GraphicsPath gPath = new GraphicsPath();
gPath.AddLine(points[0], points[1]);
gPath.AddArc(new RectangleF(-445.464447F,3.84924316F,640.067444F,640.067444F), -(90 - 105.0412369999982F), 10.8775282F);
gPath.AddArc(new RectangleF(-445.464417F, 3.84915161F, 640.067444F, 640.067444F), -(90 - 115.91811484539707F), 10.8775091F);
gPath.AddLine(points[2], points[3]);
//widen the line to the width equal to what the fish will not be able to see:
gPath.Widen(new Pen(Color.White, 10));
//now exclude that widened line from the main graphics:
g.ExcludeClip(new Region(gPath));
//draw the swathe line:
g.DrawPath(widePen, gPath);
//reset the clipping for the next line:
g.ResetClip();
}
Try to use a separate GraphicsPath for excluded region:
private void drawCurvedLine()
{
//initialise the plot area:
Bitmap image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
pictureBox1.BackgroundImage = image;
using(Graphics g = Graphics.FromImage(image))
{
PointF[] points = new PointF[4];
//first straight:
points[0] = new PointF(287.284149F, 21.236269F);
points[1] = new PointF(183.638443F, 406.936249F);
//second straight:
points[2] = new PointF(130.842773F, 515.574036F);
points[3] = new PointF(-1950.91321F, 3491.868F);
//graphics path for the line:
using(GraphicsPath gPath = new GraphicsPath())
{
gPath.AddLine(points[0], points[1]);
gPath.AddArc(new RectangleF(-445.464447F, 3.84924316F, 640.067444F, 640.067444F), -(90 - 105.0412369999982F), 10.8775282F);
gPath.AddArc(new RectangleF(-445.464417F, 3.84915161F, 640.067444F, 640.067444F), -(90 - 115.91811484539707F), 10.8775091F);
gPath.AddLine(points[2], points[3]);
//widen the line to the width equal to what the fish will not be able to see:
using(GraphicsPath innerPath = (GraphicsPath)gPath.Clone())
{
using(Pen pen = new Pen(Color.White, 10))
{
innerPath.Widen(pen);
}
//now exclude that widened line from the main graphics:
using(Region reg = new Region(innerPath))
{
g.ExcludeClip(reg);
//draw the swathe line:
//the width of the pen represents the width of a sonar swathe:
using(Pen widePen = new Pen(new SolidBrush(Color.FromArgb(80, Color.Blue)), 50))
{
g.DrawPath(widePen, gPath);
}
//reset the clipping for the next line:
g.ResetClip();
}
}
}
}
}
Set the smoothing mode properly on your Graphics instance. Take a look here.
Try setting the CompositingQuality, the InterpolationMode and the SmoothingMode properties to increase the quality of your Graphics object:
using(Graphics g = Graphics.FromImage(image))
{
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.AntiAlias;
//...
}

c# radial gradient brush effect in GDI and winforms

I have created a c# windows application and written 75% of the code. The program allows the user to create a flow chart, and will shade the flow chart shapes according to their status. I wanted them to become 3d buttons such as from the website Webdesign.org
Rather than create a PNG for each button, I wanted to create them in C# using brushes or other technique, such as:
// Create solid brush.
SolidBrush blueBrush = new SolidBrush(Color.Blue);
// Create points that define polygon.
PointF point1 = new PointF(50.0F, 50.0F);
PointF point2 = new PointF(100.0F, 25.0F);
PointF point3 = new PointF(200.0F, 5.0F);
PointF point4 = new PointF(250.0F, 50.0F);
PointF point5 = new PointF(300.0F, 100.0F);
PointF point6 = new PointF(350.0F, 200.0F);
PointF point7 = new PointF(250.0F, 250.0F);
PointF[] curvePoints = {point1, point2, point3, point4, point5, point6, point7};
// Define fill mode.
FillMode newFillMode = FillMode.Winding;
// Fill polygon to screen.
e.Graphics.FillPolygon(blueBrush, curvePoints, newFillMode);
I know WPF has radial gradients, but can I do something simular in CGI?
Unlike WPF, GDI+/WinForms does not have a RadialGradientBrush. However you can achieve the same effect using a PathGradientBrush.
Here's an example:
Rectangle bounds = ...;
using (var ellipsePath = new GraphicsPath())
{
ellipsePath.AddEllipse(bounds);
using (var brush = new PathGradientBrush(ellipsePath))
{
brush.CenterPoint = new PointF(bounds.Width/2f, bounds.Height/2f);
brush.CenterColor = Color.White;
brush.SurroundColors = new[] { Color.Red };
brush.FocusScales = new PointF(0, 0);
e.Graphics.FillRectangle(brush, bounds);
}
}
The PathGradientBrush has lots of properties to experiment with to ensure you get the effect you're after.
Take a look at this Codeproject article, and then at the Path gradient.

Categories