CGRect changes width when device rotated - objective-c

I want to draw a XoY coordinate axis... The axis are CGRects .. the thing is they change width when the device is rotated ... I would want them to maintain their with in all rotations. Does width 5.0 mean different things when the device is in portrait rather than landscape?
Here is the code:
CGContextSaveGState(ctx);
CGContextSetFillColorWithColor(ctx, [[UIColor whiteColor] CGColor]);
// the axis is a rect ...
//axis start point
CGFloat axisStartX = viewBounds.size.width * LEFT_EXCLUSION_LENGTH_PERCENT;
CGFloat axisStartY = viewBounds.size.height * UNDER_EXCLUSION_LENGTH_PERCENT;
CGFloat axisLength = viewBounds .size.height - (viewBounds.size.height * OVER_EXCLUSION_LENGTH_PERCENT) - viewBounds.size.height * UNDER_EXCLUSION_LENGTH_PERCENT;
CGContextAddRect(ctx, CGRectMake(axisStartX, axisStartY, AXIS_LINE_WIDTH, axisLength));
CGContextFillPath(ctx);
CGContextRestoreGState(ctx);

I would not know what you are up to with this calculation, but viewBounds.size.height may change on rotation, depending on what it represents. But if its height varies for different orientations then the axisLength will vary too. And axisLength is the height of your rect.

If you want you rect to be of same size in every orientation than do this!
CGContextSaveGState(ctx);
CGContextSetFillColorWithColor(ctx, [[UIColor whiteColor] CGColor]);
// the axis is a rect ...
//axis start point
CGFloat boxSize = MIN(viewBounds.size.width, viewBounds.size.height);
CGFloat axisStartX = boxSize * LEFT_EXCLUSION_LENGTH_PERCENT;
CGFloat axisStartY = boxSize * UNDER_EXCLUSION_LENGTH_PERCENT;
CGFloat axisLength = boxSize - (boxSize * OVER_EXCLUSION_LENGTH_PERCENT) - boxSize * UNDER_EXCLUSION_LENGTH_PERCENT;
CGContextAddRect(ctx, CGRectMake(axisStartX, axisStartY, AXIS_LINE_WIDTH, axisLength));
CGContextFillPath(ctx);
CGContextRestoreGState(ctx);
The idea here is that whatever the orientation is, the size remains same and visible on screen.
hope that helps!

Related

Make NSBezierPath to stay relative to the NSView on windowResize

In my program I'm drawing some shapes inside an NSView using NSBezierPath. Everything works and looks great except when I resize the window.
Example
Initial drawing
Window resize
Does anyone know what I should use to prevent this square from being anchored to the initial position, but make it readjust relative the the initial scale.
Any help is appreciated!
If you are doing your drawing in drawRect: then the answer is NO. You will need to rebuild and reposition your path each time. What you can do is something along the following lines:
- (void) drawRect:(NSRect)dirtyRect
{
// Assuming that _relPos with x and y having values bewteen 0 and 1.
// To keep the square in the middle of the view you would set _relPos to
// CGPointMake(0.5, 0.5).
CGRect bounds = self.bounds;
CGRect rect;
rect.size.width = 100;
rect.size.height = 100;
rect.origin.x = bounds.origin.x + bounds.size.width * _relPos.x - rect.size.width /2;
rect.origin.y = bounds.origin.y + bounds.size.height * _relPos.y - rect.size.height/2;
NSBezierPath *path = [NSBezierPath bezierPathWithRect:rect];
[[NSColor redColor] set];
path.lineWidth = 2;
[path stroke];
}

Plotting out Compass Bearing on iPhone screen

Ok so here is my question,
Let's say you have a bearing of 80 degrees. I would like to plot that out on the iPhone screen with a simple 10x10 square. Let's figure the top of the iPhone in portrait mode is North.
Any ideas on how I would accomplish this?
BTW - I don't want to use the following method:
CGAffineTransform where = CGAffineTransformMakeRotation(degreesToRadians(x_rounded));
[self.compassContainer2 setTransform:where];
I would like to plot out on the screen manually via setting the X -Y cords on the iPhone screen.
- (void)drawRect:(CGRect)rect
{
float compass_bearing = 80.0; // 0 = North, 90 = East, etc.
CGContextRef theContext = UIGraphicsGetCurrentContext();
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, 5.0, 5.0);
CGPathAddLineToPoint(path, NULL,
5.0 + 5.0 * cos((compass_bearing - 90.0) * M_PI / 180.0),
5.0 + 5.0 * sin((compass_bearing - 90.0) * M_PI / 180.0));
CGContextSetLineWidth(theContext, 2.0);
CGContextSetStrokeColorWithColor(theContext, [UIColor blackColor].CGColor);
CGContextAddPath(theContext, path);
CGContextStrokePath(theContext);
CGPathRelease(path);
}
So it sounds to me like what you want to accomplish should exist within the drawRect method of a custom view, and then this view would be added to your screen by whatever method you desired (i.e. storyboard or programmatically). Here is a possible implementation that you could use to draw a straight line from the center of the view based on some 'angle':
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
// Drawing code
CGFloat angle = 0.0 /180.0 * M_PI ;
//Set this to be the length from the center
CGFloat lineDist = 320.0;
CGContextSetLineWidth(context, 5.0);
//Set Color
[[UIColor redColor] setStroke];
//Draw the line
CGContextBeginPath(context);
//Move to center
CGContextMoveToPoint(context, self.frame.size.width/2, self.frame.size.height/2);
//Draw line based on unit circle
//Calculate point based on center starting point, and some movement from there based on the angle.
CGFloat xEndPoint = lineDist * sin(angle) + self.frame.size.width/2;
//Calculate point based on center starting point, and some movement from there based on the angle. (0 is the top of the view, so want to move up when your answer is negative)
CGFloat yEndPoint = -lineDist * cos(angle) + self.frame.size.height/2;
CGContextAddLineToPoint(context, xEndPoint, yEndPoint);
CGContextStrokePath(context);
}

How to set size of UIScrollView frame programmatically?

I am newbie so my question can be really obvious, but I didn't find any solution so far.
I did in IB UIScrollView and connected it with File's Owner.
I would like to set now the frame size of my UIScrollView (named ScrollView).
const CGFloat BoardWidth = 320;
const CGFloat BoardHeight = 400;
//I tried this way but 'Expression is assignable' - said Xcode
ScrollView.frame.size.width = BoardWidth;
ScrollView.frame.size.height = BoardWidth;
So how can I the easiest set own sizes of ScrollView frame?
CGRect scrollFrame = CGRrectMake(x, y, w, h);
ScrollView.frame = scrollFrame;
Or if you need only to change the width and height;
CGRect scrollFrame;
scrollFrame.origin = ScrollView.frame.origin;
scrollFrame.size = CGSizeMake(w, h);
ScrollView.frame = scrollFrame;
Edit keeping the center unchanged:
CGRect scrollFrame;
CGFloat newX = scrollView.frame.origin.x + (scrollView.frame.size.width - w) / 2;
CGFloat newY = scrollView.frame.origin.y + (scrollView.frame.size.height - y) / 2;
scrollFrame.origin = CGPointMake(newX, newY);
scrollFrame.size = CGSizeMake(w, h);
scrollView.frame = scrollFrame;
you need to do this, for example.
ScrollView.frame = CGRectMake(0, 0, BoardWidth, BoardHeight);
Once done you need also to set contentSize property. It's the area that 'extends' behind the frame of your UIScrollView.
If you want to scroll only horizontally:
ScrollView.contentSize = CGSizeMake(w * BoardWidth, BoardHeight);
If you want to scroll only vertically:
ScrollView.contentSize = CGSizeMake(BoardWidth, h * BoardHeight);
If you want to scroll both horizontally and vertically:
ScrollView.contentSize = CGSizeMake(w * BoardWidth, h * BoardHeight);
where w and h are generic values to increment your width and/or your height.
If you want have an horizontal (for example) discrete scroll (e.g. you have some pages with the same dimension of your screen).
ScrollView.pagingEnabled = YES;
ScrollView.contentSize = CGSizeMake(p * BoardWidth, BoardHeight);
where p is the number of pages you want to display.
Hope it helps.
You can do it as below,
scrollView.frame = CGRectMake(xOrigin,yOrigin,width,height);
If you are looking for content size of scrollview then it as below,
scrollView.contentSize = CGSizeMake(width,height);
CGRect Frame = ScrollView.frame
Frame.frame.size.width = BoardWidth;
Frame.frame.size.width = BoardWidth;
ScrollView.frame = Frame;
Since frame is a structure..you can't set the frame of an object directly.. You will have to make a Cgrect and then manipulate it.
using contentSize property
ScrollView.contentSize = CGSizeMake(320, 520);
it needs to be bigger than the frame so it actually scrolls.

How to fill gaps in imageview (not covered by image) with color?

I want to create an image of fixed size e.g. 612 by 612. I am using an image picker to select photos from my iphone. So in order to ensure that all the photos fit to the 612 by 612 size without distortion, I am using the following method to re-scale the photo so that they conform to the size of 612 by 612. However as a result, blank spaces might be created in the final image. (see example below)
I am using the following code to scale my image (of fixed size 612 by 612)
//Scale the image to fit to imageview
UIImage *image = [self scaleImage:img toRectSize:CGRectMake(0, 0, 612, 612)];
//Method to scale image
- (UIImage *)scaleImage:(UIImage *)img toRectSize:(CGRect)screenRect
{
UIGraphicsBeginImageContext(screenRect.size);
float hfactor = img.size.width / screenRect.size.width;
float vfactor = img.size.height / screenRect.size.height;
float factor = MAX(hfactor, vfactor);
float newWidth = img.size.width / factor;
float newHeight = img.size.height / factor;
float leftOffset = (screenRect.size.width - newWidth) / 2;
float topOffset = (screenRect.size.height - newHeight) / 2;
CGRect newRect = CGRectMake(leftOffset, topOffset, newWidth, newHeight);
[img drawInRect:newRect blendMode:kCGBlendModePlusDarker alpha:1];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
As mentioned, as the image is sometimes not a full square, I get a result like what you see below:
How can I feel up the white spaces in the image with black color?
One way is to set the backgroundColor of UIImageView to blackColor.
Another way is to fill the rect with blackColor while you scale the image.
- (UIImage *)scaleImage:(UIImage *)img toRectSize:(CGRect)screenRect {
...
CGRect newRect = CGRectMake(leftOffset, topOffset, newWidth, newHeight);
// Fill the original rect with black color
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [[UIColor blackColor] CGColor]);
CGContextFillRect(context, screenRect);
[img drawInRect:newRect blendMode:kCGBlendModeNormal alpha:1];
...
}
Note that the blendMode in drawInRect:blendMode:alpha: method is set to kCGBlendModeNormal. If you set some other blend modes you will get undesired results. For example, if you set the blend mode to kCGBlendModePlusDarker and fill the rect with blackColor then the entire image will become black.
Set the background color on your UIImageView to black and you'll get what you want

Need help to make own coordinate system (classic, center of UIView is 0,0)

I need to create my own coordinate system in UIView, where 0,0 is center of UIView. But I don't know ho to do this. Please help.
UIView *view = /*...*/;
CGContextRef ctx = /*...*/;
/* Shift center from UL corner to mid-x, mid-y. */
CGRect bounds = [view bounds];
CGFloat hx = bounds.size.width / 2.0;
CGFloat hy = bounds.size.height / 2.0;
CGContextTranslateCTM(ctx, hx, hy);
/* y still increases down, and x to the right. */
/* if you want y to increase up, then flip y: */
CGContextScaleCTM(ctx, 1.0/*sx*/, -1.0/*sy*/);
By default, (0,0) is in the upper left corner of the view. To move this point to the view's center, modify its bounds:
CGFloat width = self.bounds.size.width;
CGFloat height = self.bounds.size.height;
self.bounds = CGRectMake(-width/2.0, -height/2.0, width, height);
Make sure to repeat this calculation whenever the size of the view changes.