I have a bit of code that is trying to figure out the correct bounding box for a rectangle that is being rotated -5 degrees:
CGRect rectangleToRotate = CGRectMake(0,0,104.949, 131.017);
CGAffineTransform rotateTransform = CGAffineTransformMakeRotation((M_PI * -5) / 180);
CGRectApplyAffineTransform (rectangleToRotate, rotateTransform);
The result that is produced is a rectangle with size: {115.968, 139.664} which, for some reason is too huge and doesn't tightly encompass the rectangle. Yet when I go take this same scenario in Adobe Illustrator, the bounding box is: {104.659, 132.143} which is correct.
What exactly am I missing here?
I guess you are doing something wrong in illustrator. How should the bounding box be smaller (104.9 to 104.6) AFTER a 5 degree rotation.. thats just wrong.
The CGRect results are quite right. I tested it in Photoshop.
A 105x131px rect will result in a 117x141px bounding box after a -5 degree rotation.
Related
I'm trying to draw a polygon using a CustomPainter, this is working fine. Then I would like to draw a 2nd polygon identical to the first underneath it but X times the size. Currently I am transforming the path like:
polygon1 = new Path();
polygon1.addPolygon(polygonPoints, true);
double scale = 1.5;
Matrix4 matrix4 = Matrix4.identity()
..scale(scale,scale,0);
Path polygon2 = Path.from(polygon1)
..transform(matrix4.storage);
However, it seems that polygon2 is also translated which is undesired. I would like it to be perfectly behind the polygon1.
How do I achieve this?
Pictures for reference:
Polygon 1 (green) and Polygon 2 (orange) far away from (0,0) and NOT aligned
Polygon 1 (green) and Polygon 2 (orange) at ~ (0,0) and aligned
I managed to centre the scaled polygon2 by normalizing polygon1 w.r.t. point 0, then scaling the path as above, and finally shifting both paths using the Offset from point 0. Furthermore, the polygon2 needs to be shifted w.r.t to the polygon1 and for this I used polygon1's Rect parameter bottomCenter.
I'm trying to figure out what all these arguments do, as when I draw my bullet image it appears as a solid block instead of a sprite that alternates between solid color and an empty portion (i.e instead of 10101 it's 11111, with 0's being empty parts in the texture).
Before, I was using batch.draw(texture, float x, float y) and it displays the texture correctly. However I was playing around with rotation, and this is the version of draw that seemed most suitable:
batch.draw(texture, x, y, originX, originY, width, height, scaleX, scaleY, rotation, srcX, srcY, srcWidth, srcHeight, flipX, flipY)
I can figure out the obvious ones, those being originX, originY (location to draw the image from its upper left pixel I believe) however then I don't know what the x, y coordinate after texture is for.
scaleX,scaleY, rotation, and flipX, flipY I know what to do with, but what is srcX and srcY, along with the srcWidth and srcHeight for?
edit: I played around and figured out what the srcX,srcY and srcHeight,Width do. I can not figure out what originX,Y does, even though I'm guess it's the centerpoint of the image. Since I don't want to play around with this one anyway, should I leave it as 0,0?
What would be common uses for manipulating the centerpoint of images?
Answering main question.
srcX, srcY, srcWidth, srcHeight are values determine which part (rectangle) of source texture you want to draw. For example, your source image is 100x100 pixels of size. And you want to draw only 60x60 part in a middle of source image.
batch.draw(texture, x, y, 20, 20, 60, 60);
Answering your edited question.
Origin is a center point for rotation and scale transformations. So if you want to your sprite scales and rotates around it's center point you should set origin values so:
float originX = width * 0.5f;
float originY = height * 0.5f;
In case you don't care about rotation and scaling you may not specify this params (leave it 0).
And keep in mind, that origin is not determines image drawing position (this is most common mistake). It means that two next method calls are draw image at same position (forth and fifth params are originX and originY):
batch.draw(image, x, y, 0, 0, width, height, ...);
batch.draw(image, x, y, 50, 50, width, height, ...);
According to the documentation, the parameters are as defined:
srcX - the x-coordinate in texel space
srcY - the y-coordinate in texel space
srcWidth - the source with in texels
srcHeight - the source height in texels
Simply trying to rotate a rectangle around it's origin, or its upper left corner like so:
Am using the following:
panGestureRecognizer.view.transform = CGAffineTransformRotate(panGestureRecognizer.view.transform, (M_PI * angle) / 180);
But the rectangle is sort of rotating in a big loop. Is there some sort of translation I need to do to get this to work?
You just need to set the anchor point: https://developer.apple.com/library/mac/#documentation/graphicsimaging/reference/CALayer_class/Introduction/Introduction.html#//apple_ref/occ/instp/CALayer/anchorPoint
panGestureRecognizer.view.layer.anchorPoint = CGPointMake(0.0, 0.0);
Further Reading: For more advanced stuff you could try some of the tips detailed here for matrix transformations: https://stackoverflow.com/a/8536553/563381
I want to :
rotate an image (size 512x512) with 45 degrees.
make some processing on it.
rotate the image with -45 degrees.
my problem is when i apply rotation with 45 degrees and -45 degrees, the size of the image changes and i want it to be the same.
The usual procedure to rotate images is to scale the image up, rotate the image and scale it down. This way, you can avoid the dark margins that will appear when you rotate.
Matlab does this process automatically. So if you want a particular dimension for the image, you have to choose the appropriate region of the image after you have rotated it.
Suppose we wanted to rotate the image and want to retain the same dimensions as the original image, we can do this:
img = imread('image.png');
r = numel(img(:,1));
c = numel(img(:,2));
nimg = imrotate(img, 45);
nimg = imrotate(nimg, 45);
n_R = numel(nimg(:,1));
n_C = numel(nimg(:,2));
n_R = n_R+mod(n_R, 2); %to avoid dimensions being in double datatype
n_C = n_C+mod(n_C, 2);
oimg = nimg(((n_R/2)-(r/2)):((n_R/2)+(r/2)), ((n_C/2)-(c/2)):((n_C/2)+(c/2)),:);
imwrite(oimg, 'rot_image.png');
You can't do it. It doesn't make sense. Simple experiment:
get a square piece a paper and hold it against a white wall
draw the borders of the square on the wall
rotate the piece of paper 45 degrees
draw another square on the wall that encloses the rotated piece of paper
take the piece of paper out of the wall and observe why you can't do that
leave the marks on the wall so you don't forget
I have a custom UIView which is drawn using its -[drawRect:] method.
The problem is that the anti-aliasing acts very weird as black lines horizontal or vertical lines are drawn very blurry.
If I disable anti-aliasing with CGContextSetAllowsAntialiasing, everything is drawn as expected.
Anti-Aliasing:
alt text http://dustlab.com/stuff/antialias.png
No Anti-Aliasing (which looks like the expected result with AA):
alt text http://dustlab.com/stuff/no_antialias.png
The line width is exactly 1, and all coordinates are integral values.
The same happens if I draw a rectangle using CGContextStrokeRect, but not if I draw exactly the same CGRect with UIRectStroke.
Since a stroke expands equal amounts to both sides, a line of one pixel width must not be placed on an integer coordinate, but at 0.5 pixels offset.
Calculate correct coordinates for stroked lines like this:
CGPoint pos = CGPointMake(floorf(pos.x) + 0.5f, floorf(pos.y) + 0.5f);
BTW: Don't cast your values to int and back to float to get rid of the decimal part. There's a function for this in C called floor.
in your view frames, you probably have float values that are not integers. While the frames are precise enough to do fractions of a pixel (float), you will get blurriness unless you cast to an int
CGRect frame = CGRectMake((int)self.frame.bounds..., (int)...., (int)...., (int)....);