Rotating an NSView - cocoa

I need to rotate the frame of an instance of NSView in such a way that its width becomes its height and its height becomes its width. The view contains a string and it is important that this string is rotated as well.
I had a look at NSView's setFrameRotation: but this rotates around the frame origin which is not what I want. I suppose that technically my requirement is not a rotation but more a mirroring at a 45 degree angle from the origin.
How can I accomplish this?

Try Desire to rotate around centre
This piece of could should helper.
[NSView rotateByAngle]

Related

Monogame - sprite not rotating around origin point

I'm trying to rotate a sprite around its center with following code:
Vector2 origin = new Vector2(position.Width / 2, position.Height / 2);
s.Draw(position, origin, angle, Color.White);
spriteBatch.Draw(texture, position, sourceRectangle, color, rotation, origin, SpriteEffects.None, 0);
Note: Since I'm drawing from a sprite sheet, the source rectangle is being calculated.
The original size of my sprite is 15x32. If I use this size, the rotation looks nearly correct but it's still a little bit shifted:
However, when I resize the width and height to 75x128 the sprite is completely displaced:
Is there a way to always place the sprite correct, when resizing it? And why is the sprite even displaced when drawing it in the original size?
By the way, the green box is the origin point with the size of the sprite.
Thank you very much!
Ok I figured it out myself!
When creating the origin point, I used the new Width and Height (75, 128) but one has to use the width and height of the original sprite. In this case (15, 32).

About cutting of / cropping a uiview

so i have a uiview that is initialized with a frame that has the height and width that is present for the user, i want the user to be able to draw inside this frame but when the user presses a button, i want the view to cut off that extra wasted space so that the frame is only as big as what the user was drawing. I tried to do something like this
CGRect boundbox = CGPathGetBoundingBox([myPath CGPath]);
boundbox.origin.x = self.frame.origin.x;
boundbox.origin.y = self.frame.origin.y;
self.frame = boundbox;
However, this does not remove that extra wasted space, it only resizes the view, so that the drawn content looks smaller than previously. What i would like to do instead is to remove
that "whitespace", i was thinking if it could be possible to scale up the content of the uiview, but im not sure.
To clarify what i mean:
The red border is the area / frame that the user can draw on, the text in the middle is a drawing, when the user presses a button, i want the frame to only encircle the drawing like in figure 2.
Now lets say i have the following scenario, i have drawn a circle on the middle of the screen.
When i then press the button, the scale remains the same but the circle is still in the same position but we have now changed the draw area, so the circle / drawing will look like its cut off like in figure 4.
What i want to do is to move the drawing / bezier path so that it is positioned in the middle of the frame. So that the red area encircles the blue circle.
[EDIT]
Given your drawings. A UIView will not re-position items in it when you change it's frame property (or it's CGRect). In this case you will need to track the items drawn YOURSELF, and then when the button is pressed perform the object translations yourself.
What that means is you will have to find the object that is left most, the object that is topmost, then move all objects left by that amount, and up by that amount so that all objects are (as a grouping) top-left aligned within the view's frame. After this you will need to self recognize which object is the right most touching and which object is the bottom most touching.
NOW, since you have already moved the items left-top, the right most point will define your frame width, and the bottom most point will define your frame height.
IF YOU SO DESIRE, you should be able to zoom in using the properties below after you have done this.
[First Answer]
If I understand your question correctly, you may want to still perform your box frame manipulation, but if you wish to scale you may want to look into the
contentScaleFactor or
contentStretch
properties.
contentScaleFactor should scale both dimensions based upon a singular floating point value (i.e. xWidth * scaleFactor, yHeight * scale factor).
contentStretch is a CGRect which means that it should scale each dimension (axis) separately.

Rotating an NSView and getting its corner points

I am rotating an NSView using:
setFrameRotation:
Which rotates the view around its bottom left corner. What is the best way to rotate a view around its center point?
Also, i want to get the points in the superview of its corners. Using:
view.frame.origin
Just gives me the corner before i rotate it. How would i get the actual points of its corners once it has been rotated?
Thanks in advance, Ben
To get an effective rotation about the center of the frame, you have to translate the frame's origin.
Also, of course view.frame.origin gives the origin before you rotate it. It's also giving you the origin after you rotate it, because the rotation is around the origin. The origin isn't moving. If you do translate the origin to get rotation around the center, you'll then know the new origin.
To get the other corners, you'd use [view convertPoint:pt toView:view.superview], where pt is each of the corners in the view's coordinate system. E.g. NSMakePoint(NSMaxX([view bounds]), NSMinY([view bounds])).
You can actually use this technique to obtain the translation you want. Compute the desired center of the view, or just record the current center if it's where you want it. Then rotate the view. Obtain the new location of the center using -convertPoint:toView:. Then translate the origin by the difference between the new center and the desired center.

Question about anchor point

So I have been playing around with animations lately and I've come across the anchor point. I understand that the anchor point is (0.5, 0.5) by default, which is the middle of the view, and you can change it so that the anchor point is on one of the borders. My question is, how do I go on about this if I want my view to rotate around a specific point in the view's superview? Any help is greatly appreciated
Checkout this question how to rotate CALayer at one point
Also - although I guess you've probably already done this - have a read of Core Animation Programming Guide, Layer Geometry and Transforms.
Your question differs in that you want to specify a rotation point that is in your view's superview. To do that, you want to convert that superview point to the subview. You can do that as follows:
Take your superview bounds, e.g. (0, 0, 500, 500)
Take your subview frame, e.g. (50, 50, 100, 100)
Take your superview rotation point, e.g. (75, 75)
Convert that to a point relative to the subview as follows:
CGFloat subviewX = 75.0f - subview.frame.x;
CGFloat subviewX = 75.0f - subview.frame.y;
That gives the result expected (25.0f, 25.0f)
To rotate a CALayer with a CABasicAnimation, have a look at the selected answer for this question: CALayer with rotation animation.
I figured it out myself: I wanted the anchor point to be on the left screen border, so I did the following:
CGFloat subviewX = ((1/view.frame.size.width)*view.frame.origin.x) * (-1);
CGFloat subviewY = 0.5;

Does a given rect intersect a rotated view?

I have an NSView that is rotated using -setFrameRotation. (This is necessary because the view responds to mouse events, and you don't get correct behavior if you merely draw the view with a rotated NSAffineTransform.)
Given a rect in the rotated view's superview coordinates, how can I determine what portion of the rect intersects the rotated view's frame?
Use case: the Cocoa text system proposes to draw text in a line fragment rectangle. I need to determine how much of that rectangle may be filled with text without overlapping the rotated view.
Take the point, use an affine transform to rotate into the coordinate system of the bounds of the rect and then rect-test that.

Resources