Actual coordinate after ScaleTransfrom() - c#

I am drawing a rectangle in a WinForms application in C# and I want to get the actual coordinates of the rectangle after applying ScaleTransform() method.
Graphics g = e.Graphics;
g.ScaleTransform(2.0F,2.0F,System.Drawing.Drawing2D.MatrixOrder.Append);
g.DrawRectangle(pen, 20, 40, 100,100)

Once you have set a ScaleTransform in your Graphics object (or any transform for that matter), you can use it to transform the points of your rectangle (or any other points).
For example:
// your existing code
Graphics g = e.Graphics;
g.ScaleTransform(2.0F,2.0F,System.Drawing.Drawing2D.MatrixOrder.Append);
// say we have some rectangle ...
Rectangle rcRect = new Rectangle(20, 40, 100, 100);
// make an array of points
Point[] pPoints =
{
new Point(rcRect.Left, rcRect.Top), // top left
new Point(rcRect.Right, rcRect.Top), // top right
new Point(rcRect.Left, rcRect.Bottom), // bottom left
new Point(rcRect.Right, rcRect.Bottom), // bottom right
};
// get a copy of the transformation matrix
using (Matrix mat = g.Transform)
{
// use it to transform the points
mat.TransformPoints(pPoints);
}
Note the using syntax above - this is because, as MSDN says:
Because the matrix returned and by the Transform property is a copy of
the geometric transform, you should dispose of the matrix when you no
longer need it.
As a slightly less wordy alternative, you can do the same thing using the TransformPoints method of the Graphics class (MSDN here) - so construct your array of points as above, then just do this:
g.TransformPoints(CoordinateSpace.Page, CoordinateSpace.World, pPoints);
MSDN describes the relevant coordinate spaces used in the above function:
GDI+ uses three coordinate spaces: world, page, and device. World
coordinates are the coordinates used to model a particular graphic
world and are the coordinates you pass to methods in the .NET
Framework. Page coordinates refer to the coordinate system used by a
drawing surface, such as a form or a control. Device coordinates are
the coordinates used by the physical device being drawn on, such as a
screen or a printer. The Transform property represents the world
transformation, which maps world coordinates to page coordinates.

Related

Monogame: Render only inside specified area

This may be a strange question, but I'm trying to find a way to render sprites only inside a specific allowed area rather then the entire buffer/texture.
Like so:
Basically allowing me to draw to the buffer or texture2D as I normally would, but with actual drawing happening only inside this specified area and remaining pixels outside of it remaining untouched.
Why this is needed - I'm building my own UI system and I would like to avoid using intermediary buffers as it is quite slow when there are many UI components on the screen (and each has to draw to their own buffer to prevent child elements being drawn outside of parent bounds).
And just to clarify - this is all for simple 2D rendering, not 3D.
If your UI is actually drawn with SpriteBatch you can use ScissorRectangle
GraphicsDevice.RasterizerState.ScissorTestEnable = true;
spriteBatch.GraphicsDevice.ScissorRectangle = ...
In 3D, you can render to a texture and draw just a portion of it - or with a shader (you could actually just send in the dimensions as parameter and set it to black in PixelShader if the Pixel is outside that Rectangle (or whatever you want to accomplish)
You can use:
spriteBatch.Draw(yourTexture,
//where and the size of what you want to draw on screen
//for example, new Rectangle(100, 100, 50, 50)//position and width, height
destinationRectangle,
//the area you want to draw from the original texture
//for example, new Rectangle(0, 0, 50, 50)//position and width, height
sourceRectangle,
Color.White);
Then it will only draw the area that you chose before. Hope this helps!

How transparency works in drawing rectangle(border or whole area)(C#)?

I have a colormap plot and want to apply mesh dimensions on the picture plot. This request was successfully done by using the following code:
// draw mesh pattern
Pen transPen = new Pen(Color.FromArgb(128, 150, 150, 150),2);
g.DrawRectangle(transPen, (float)X,
(float)Y,
(float)dx,
(float)dy);
// draw contour square (brush , x , y , dx , dy)
g.FillRectangle(myContourBrush,
(float)X,
(float)Y,
(float)dx,
(float)dy);
Now my question is : the first transparent rectangle are transparent just in border area or all rectangle area? I don't want to affect colormap color, I just want to have mesh pattern.
The DrawRectangle method only draws the edge. If you want to fill it, you must use FillRectangle. Take a look for yourself. You might have to zoom in quite a bit to notice the color change.

Creating Circles in a row in C#

I am very new to programming and have a quick question regarding a practical exercise i am undergoing for my studies. I am trying to create an application where the user can enter the number of rows and the nuber of columns in which circles will be drawn next to each other (to make a grid of circles essentially)
I have been able to do this in C# by using a rectangle object and shifting it's X axis value over by an amount but i cannot find out how to do this with a circle. Does this work in the same way? I have seen on MSDN that there is a circle class but i can't get this to work.
Do i need to do some thing with a fill ellipse? As this is the only way i can currently figure out how to draw a circle.
I am not looking for a complete solve, just a few basic pointers to help a newbie leearn the ropes.
Thanks!!
Assuming that you have desktop winforms application,
and using System.Drawing.Graphics object to draw inside window.
To draw a rectangle, you probably use one of DrawRectangle methods:
// Create bounding rectangle.
Rectangle rect = new Rectangle(0, 0, 200, 200);
// Draw rectangle to screen.
e.Graphics.DrawRectangle(blackPen, rect);
To draw a circle instead of rectangle, just use DrawEllipse method,
and move bounding rectangle the same way you did, by shifting x and y coordinates.
// Create bounding rectangle.
Rectangle rect = new Rectangle(0, 0, 200, 200);
// Draw circle to screen.
e.Graphics.DrawEllipse(blackPen, rect);

Create a Region or GraphicsPath from the non-transparent areas of a bitmap

I want to hit-test a drawn bitmap to see if a given Point is visible in the non-transparent pixels of the image.
For example, to do this test for the whole bitmap rectangle, you would do something like this:
Bitmap bitmap = new Bitmap("filename.jpg");
GraphicsPath path = new GraphicsPath();
Rectangle bitmapRect = new Rectangle(x, y, bitmap.Width, bitmap.Height);
path.AddRectangle(bitmapRect);
if (path.IsVisible(mouseLocation))
OnBitmapClicked();
However, if I have a bitmap of a non-rectangular item and I want to be able to check if they are clicking on the non-transparent area, is there any supported way in the .NET framework to do this?
The only way I could think to do this is to lock the bitmap bytes into an array, and iterate through it, adding each x,y coordinate that is non-transparent to an array of Point structures. Then use those point structures to assemble a GraphicsPath.
Since these points would be zero-based I would need to offset my mouse location with the distance between the x,y coordinate that the image is being drawn at and 0,0. But this way I could essentially use the same GraphicsPath for each image if I draw it multiple times, as long as the image is not skewed or scaled differently.
If this is the only good route, how would I add the points to the GraphicsPath? Draw lines from point to point? Draw a closed curve?
IMHO a simpler technique would be to look at the alpha component of the hit pixel:
Color pixel = bitmap.GetPixel(mouseLocation.X, mouseLocation.Y);
bool hit = pixel.A > 0;

Why might Graphics.RotateTransform() not be applied?

I have the following function:
static private Image CropRotate(Image wholeImage, Rectangle cropArea)
{
Bitmap cropped = new Bitmap(cropArea.Width, cropArea.Height);
using(Graphics g = Graphics.FromImage(cropped))
{
g.DrawImage(wholeImage, new Rectangle(0, 0, cropArea.Width, cropArea.Height), cropArea, GraphicsUnit.Pixel);
g.RotateTransform(180f);
}
return cropped as Image;
}
It's supposed to crop an image, then rotate the resulting sub-image. In actuality though, it only performs the crop.
Why is RotateTransform() not being applied?
Have you tried putting the RotateTransform() before the DrawImage()?
The example on the msdn page shows the transformation being applied before any drawing is done.
The RotateTransform call alters the current transform matrix, which has an effect on all subsequent operations. It does not transform the already output operations at all. This is the same for any of the operations that change the transform matrix (like ScaleTransform).
Make sure you call these before you perform the operations you want transformed - in this case, before the call to DrawImage.
You can use this to do something like
Draw (not rotated or scaled)
Rotate (only changes transform matrix)
Scale (only changes transform matrix)
Draw (now rotated and scaled)
ClearTransform (only changes transform matrix)
Draw (not rotated or scaled)
the first and last draw outputs will not be transformed, but the middle one would be affected by both the rotate and scale (in that order).

Categories