Matrix Transform of Rectangle after changing its bounds - c#

I have a shape, for example a Rectangle which has the following bounds:
X = 100
Y = 100
Width = 100
Height = 100
I apply the following rotation to this rectangle using a new Matrix:
X = 100
Y = 100
Angle = 45
var transform = new Matrix();
transform.RotateAt(angle, point);
So the new Matrix has the following value:
0.7071068, 0.7071067, -0.7071067, 0.7071068, 150, -62.13202
I use this Matrix when I draw the Rectangle with Graphic:
protected override void OnPaint(PaintEventArgs e)
{
...
e.Graphic.Transform = transform;
g.DrawRectangle(Pen, bounds.X, bounds.Y, bounds.Width, bounds.Height);
}
The problem is the following: at a certain point I need to draw the same Rectangle but shifted by a certain offset, for example (50, 50). I have stored the Matrix transform and the Rectangle bounds. If I change only the bounds (adding the offset) the new Rectangle will be drawn in a wrong position, probably due to the previous rotation point.
How I have to change the Matrix in order to draw my Rectangle in the "right" position? that is, how can I retreive the right rotation point and the old rotation angle?

Try to add translation to the matrix using MatrixOrder.Prepend.
For offset (50, 50) it'll be:
transform.Translate(50, 50, MatrixOrder.Prepend);
Or create a separate matrix for this case:
var transformWithOffset = new Matrix();
transformWithOffset.Translate(50, 50);
transformWithOffset.RotateAt(angle, point);

Related

Difference between DrawPath and DrawRectangle

I am drawing lines using both Rectangle and graphicspath in my application and i am facing lose of width and height in drawing when using GraphicsPath rather than using Rectangle.
Below is the sample code which reproduces my issue,
protected override void OnPaint(PaintEventArgs e)
{
int left = ClientRectangle.X + 40, right = ClientRectangle.Width -80;
int bottom = ClientRectangle.Height - 80, top = ClientRectangle.Y + 40;
int borderWidth = 10;
Rectangle borderrectangle = new Rectangle(left, top, right, bottom);
Pen pen = new Pen(Color.Black, borderWidth);
//Draws lines using Rectangle.
e.Graphics.DrawRectangle(pen, borderrectangle);
Point[] points = new Point[]
{
new Point(left, top),
new Point(right, top),
new Point(right, bottom),
new Point(left, bottom),
};
GraphicsPath path = new GraphicsPath();
path.AddLines(points);
path.CloseFigure();
//Draws lines using Path.
e.Graphics.DrawPath(pen, path);
}
Here is the image ,
Inner rectangle is drawn using the DrawPath and outer rectangle is drawn with DrawRectangle.
Could anyone please update me the reason for width and height lose with GraphicsPath drawing, since i have given proper points as like the rectangle?
Any help will be appreciated.
When you create Rectangle you are passing right and bottom coordinates as width and height. Check Rectangle constructor parameters:
public Rectangle(
int x,
int y,
int width,
int height
)
When you use Path, you are drawing it by coordinates and everything is OK. You should create rectangle this way:
Rectangle borderrectangle = new Rectangle(left, top, right-left, bottom-top);
But make sure that width and height of ClientRectangle are greater than 120
When you are setting the values for your Rectangle, you are setting the X and Y coordinates of the top left corner as well as width and height. However, with your GraphicsPath, you are explicitly defining every corner as a separate point. To make the GraphicsPath draw exactly what the Rectangle is, you'll either need to offset your point array coordinates to equal the width and height of the Rectangle:
Point[] points = new Point[]
{
new Point(left, top),
new Point(right + left, top),
new Point(right + left, bottom + top),
new Point(left, bottom + top),
};
or construct the Rectangle to treat the right and bottom as coordinates instead of fixed lengths:
Rectangle borderrectangle = new Rectangle(left, top, right - left, bottom - top);
Considering that you are treating the values as sides and therefore coordinates, the second option will probably give you the most consistency.

how to draw polygon including negative points ? in C#

i am doing c# project. i have found a problem and unable to find answer of this problem that's why i am posting here/
i am implementing procedural floor plan generation in c#. at first i need to draw a polygon to on given points to generate grid. points can be positive or negative. points will be in floating.
From the Microsoft Documentation i am able to draw polygon for the floating positive points, but when i change points to negative it does not draw anything on form.
this method id drawing x,y coordinates 0,0 in the corner .
code example
public void DrawPolygonPointF(PaintEventArgs e)
{
// Create pen.
Pen blackPen = new Pen(Color.Black, 3);
// 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
};
// Draw polygon curve to screen.
e.Graphics.DrawPolygon(blackPen, curvePoints);
}
i have negative coordinates value for example pointF(300,-250) this method is not drawing nothing for negative coordinates value.
So please give me brief solution because i don't know much about drawing.
Thank you
In C# 0,0 is the top left corner of the screen. So negative values are off the left or top edge of your form. You need to transform your coordinates from your coordinate space to the form's. To place 0,0 dead center, you would do this:
int screenX = myX + windowWidth / 2;
int screenY = myY + windowHeight / 2;
Building off of the answer #pquest gave, and your newly added sample code, doing a "real" GDI transformation would look like this:
// Create pen.
Pen blackPen = new Pen(Color.Black, 3);
// 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);
<...snip...>
//Apply a translation Transformation to move 0,0 to the center of the
//window. You can now draw your points with negative values, without doing
//any addition to them.
int screenX = windowWidth / 2;
int screenY = windowHeight / 2;
e.Graphics.TranslateTransform((float) screenX, (float) screenY);
// Draw polygon curve to screen.
e.Graphics.DrawPolygon(blackPen, curvePoints);
GDI Transformations are very powerful. You can use them to move points around, flip points horizontally or vertically, scale things bigger or smaller, distort like a parallelogram, and even do rotations. All of these can be combined in to what is called a transformation matrix to get some very cool results.
More examples can be found on MSDN.
That's working for me to this problem.
you just need to add couple lines of code in your code.
int windowWidth = this.ClientSize.Width;
int windowHeight = this.ClientSize.Height;
int screenX = windowWidth / 2;
int screenY = windowHeight / 2;
e.Graphics.TranslateTransform((float)screenX, (float)screenY);

c# - Rotating and centering an image

I have an image, which I want to rotate clockwise by a specified number of degrees. I don't want to cut anything off, so I calculate the width and height of the new image based on the specified rotation (a rotation of 45 degrees for example requires a taller and wider image.
//Calculate required size of new image
GraphicsPath path = new GraphicsPath();
path.AddRectangle(new RectangleF(0f, 0f, bmpSource.Width, bmpSource.Height));
Matrix matrix = new Matrix();
matrix.Rotate(iRotationDegrees);
RectangleF rctNewSize = path.GetBounds(matrix);
//Create new image
Bitmap bmpRotated = new Bitmap(Convert.ToInt32(rctNewSize.Width), Convert.ToInt32(rctNewSize.Height));
using (Graphics g = Graphics.FromImage(bmpRotated))
{
//Set rotation point to center of image
g.TranslateTransform(bmpRotated.Width / 2, 0);
g.RotateTransform(iRotationDegrees);
//Draw the rotated image on the bitmap
g.DrawImageUnscaled(bmpSource, 0,0);
}
With an angle of 45 degrees, when I set the TranslateTransform to bmpRotated.Width / 2, 0 the rotated image is not quite centered horizontally, and the bottom left corner is cut off a bit.
I'm missing some math here that is correctly figuring out the appropriate dx/dy values to pass to TranslateTransform.

System.Drawing.Graphics

I have one problem relating to rotate ellipse by given Center,
Suppose I have one ellipse and what should be is to rotate that ellipse by point given by user and ellipse should be rotate around that given point.
I have tried
g.RotateTransform(…)
g.TranslateTransform(…)
Code:
Graphics g = this.GetGraphics();
g.RotateTransform((float)degreeArg); //degree to rotate object
g.DrawEllipse(Pens.Red, 300, 300, 100, 200);
this works fine but how can we give our out center to rotate ellipse....
How could it be possible please any buddy can suggest……
Thanks…….
RotateTransform always rotates about the origin. So you need to first translate your centre of rotation to the origin, then rotate, then translate it back.
Something like this:
Graphics g = this.GetGraphics();
g.TranslateTransform(300,300);
g.RotateTransform((float)degreeArg); //degree to rotate object
g.TranslateTransform(-300,-300);
g.DrawEllipse(Pens.Red, 300, 300, 100, 200);
//center of the rotation
PointF center = new PointF(...);
//angle in degrees
float angle = 45.0f;
//use a rotation matrix
using (Matrix rotate = new Matrix())
{
//used to restore g.Transform previous state
GraphicsContainer container = g.BeginContainer();
//create the rotation matrix
rotate.RotateAt(angle, center);
//add it to g.Transform
g.Transform = rotate;
//draw what you want
...
//restore g.Transform state
g.EndContainer(container);
}

Strange rotation in C# graphics

I am using OnPaint method in my class Class1 : Panel.
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
}
to rotate and draw rectangle I am using
Matrix m = new Matrix();
m.RotateAt(90, rotationPoint);
g.Transform = m;
g.FillRectangle(Brushes.Black, rectangle)
the problem is, that rotation isn't working as I want it to.
Red square is rotation point and it's located in the middle-top of rectangle. How to set x, y and rotation point so rotation would work properly?
After rotating at 90 degress it should look like this
red pixel is still at the same location.
Rotation point is not the point, which you want to rotate. It is point, around which graphics is rotated. So if you draw a rectangle on the top of the graphics and want to rotate it (rectangle) - then you should set rotation point as center of graphics and rotate image to 90 degrees.
Here is example, that does almost what you want:
base.OnPaint(e);
var g = e.Graphics;
var width = g.VisibleClipBounds.Width;
var height = g.VisibleClipBounds.Height;
var rotationPoint = new PointF(width / 2, height / 2); ;
// draw center point
g.FillRectangle(Brushes.Red, new RectangleF(rotationPoint.X - 5, rotationPoint.Y - 5, 10, 10));
using (var path = new GraphicsPath())
{
var rectangle = new RectangleF((width - 10) / 2, 0, 10, 10);
var m = new Matrix();
m.RotateAt(90, rotationPoint);
path.AddRectangle(rectangle);
path.Transform(m);
// draw rotated point
g.FillPath(Brushes.Black, path);
}

Categories

Resources