MKMapView - Stroking a path - objective-c

Im trying to stroke and fill a path for an overlay view for a MapView. Now the fill works, the stroke doesnt... Any ideas from looking at the code below?
- (void)drawMapRect:(MKMapRect)mapRect
zoomScale:(MKZoomScale)zoomScale
inContext:(CGContextRef)ctx
{
CGContextSetRGBStrokeColor(ctx, 1.0, 0.0, 0.0, 0.8);
CGContextSetRGBFillColor(ctx, 0.0, 0.0, 0.8, 0.4);
CGContextSetLineCap(ctx, kCGLineCapRound);
CGContextSetLineWidth(ctx, 8.0);
CGPoint pt;
pt = [self pointForMapPoint:MKMapPointForCoordinate(CLLocationCoordinate2DMake(0, 0))];
CGContextMoveToPoint(ctx, pt.x, pt.y);
pt = [self pointForMapPoint:MKMapPointForCoordinate(CLLocationCoordinate2DMake(-2, 3))];
CGContextAddLineToPoint(ctx, pt.x, pt.y);
pt = [self pointForMapPoint:MKMapPointForCoordinate(CLLocationCoordinate2DMake(-2, 5))];
CGContextAddLineToPoint(ctx, pt.x, pt.y);
pt = [self pointForMapPoint:MKMapPointForCoordinate(CLLocationCoordinate2DMake(-4, 4))];
CGContextAddLineToPoint(ctx, pt.x, pt.y);
CGContextDrawPath(ctx, kCGPathFillStroke);
}

This made it work...
CGContextSetLineWidth(ctx, 1 * MKRoadWidthAtZoomScale(zoomScale));

Related

How to rotate CGContext about center?

I have the following code to create a multi-colored ImageContext:
UIGraphicsBeginImageContext(self.view.frame.size);
[self.imageToDelete drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGColorRef mycolor;
mycolor = [[UIColor blueColor] CGColor];
CGPoint mid = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), mid.x, mid.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), mid.x, mid.y+50);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(),3);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeCopy);
CGContextSetStrokeColorWithColor(UIGraphicsGetCurrentContext(), mycolor);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
mycolor = [[UIColor whiteColor] CGColor];
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), mid.x, mid.y+50);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), mid.x, mid.y+75);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(),3);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeCopy);
CGContextSetStrokeColorWithColor(UIGraphicsGetCurrentContext(), mycolor);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
mycolor = [[UIColor cyanColor] CGColor];
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), mid.x, mid.y+75);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), mid.x, mid.y+100);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(),3);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeCopy);
CGContextSetStrokeColorWithColor(UIGraphicsGetCurrentContext(), mycolor);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
self.imageToDelete = UIGraphicsGetImageFromCurrentImageContext();
[self.mainImage drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) blendMode:kCGBlendModeCopy alpha:1.0];
[self.imageToDelete drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) blendMode:kCGBlendModeNormal alpha:1];
self.mainImage = UIGraphicsGetImageFromCurrentImageContext();
SKSpriteNode *node = [SKSpriteNode spriteNodeWithTexture:[SKTexture textureWithImage:self.mainImage]];
node.zPosition = 100;
node.position = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
node.size = self.mainImage.size;
[self addChild:node];
UIGraphicsEndImageContext();
This is the result:
I would like to rotate this line about the center of the screen (or the top of this line), and keep the original line as well. Is there a way to make a copy, and rotate it about the center point? To clarify, mid is a CGPoint defined as (self.view.frame.size.width/2,self.view.frame.size.height/2), and this is done in Sprite-Kit, iOS, Objective-C.
Rotation is around the origin. To rotate around another point, translate that point to the origin, rotate, and translate back.
This supplements #matt's answer with an example (with Swift 5, iOS 16), ... a function added to a subclass of UIView, where the view is comprised of sublayers of CAShapeLayer derived from UIBezierPath.
As Matt indicated, CGContext rotation centers at origin, therefore one must
translate center of view to origin, do the rotation, then translate back. Note, also the conversion of degrees to radians in the parameter of rotate().
func asImage(rotationDegrees: CGFloat) -> UIImage {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
let image = renderer.image(actions: { _ in
if let ctx = UIGraphicsGetCurrentContext() {
ctx.translateBy(x: bounds.size.width / 2, y: bounds.size.height / 2)
ctx.rotate(by: rotationDegrees * .pi / 180)
ctx.translateBy(x: -bounds.size.width / 2, y: -bounds.size.height / 2)
for sublayer in self.layer.sublayers!.reversed() {
sublayer.render(in: ctx)
}
}
})
return image
}

Drawing in Quartz 2D by pushing a button

I'm a little bit nooby in Objective-C and I just started working with Quartz 2D. My problem is very simple: I want to draw in Quartz 2D by pressing button. I don't know how I can do that because there are two different classes in my project. I used that tutorial: http://www.techotopia.com/index.php/An_iOS_7_Graphics_Tutorial_using_Core_Graphics_and_Core_Image
Here is my code:
ViewController.h
#interface ViewController : UIViewController
- (IBAction)Start;
ViewController.m
- (IBAction)Start {
}
Draw2D.h
#import <UIKit/UIKit.h>
#interface Draw2D : UIView
#end
Draw2D.m
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2.0);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGFloat components[] = {0.0, 0.0, 1.0, 1.0};
CGColorRef color = CGColorCreate(colorspace, components);
CGContextSetStrokeColorWithColor(context, color);
CGContextMoveToPoint(context, 30, 30);
CGContextAddLineToPoint(context, 300, 400);
CGContextStrokePath(context);
CGColorSpaceRelease(colorspace);
CGColorRelease(color);
}
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 4.0);
CGContextSetStrokeColorWithColor(context,
[UIColor blueColor].CGColor);
CGRect rectangle = CGRectMake(60,170,200,80);
CGContextAddRect(context, rectangle);
CGContextStrokePath(context);
}
If you want to show Draw2D view upon pressing a button, you can add draw2DView as subview of your ViewController:
/// ViewController
- (IBAction)Start:(UIButton *)sender
{
[self.view addSubview:draw2DView];
}
and you should remove these lines in your Draw2D initWithFrame method
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2.0);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGFloat components[] = {0.0, 0.0, 1.0, 1.0};
CGColorRef color = CGColorCreate(colorspace, components);
CGContextSetStrokeColorWithColor(context, color);
CGContextMoveToPoint(context, 30, 30);
CGContextAddLineToPoint(context, 300, 400);
CGContextStrokePath(context);
CGColorSpaceRelease(colorspace);
CGColorRelease(color);
They are below return self; therefore will not be triggered.

Core Graphics AddQuadCureToPoint from Center of View/Circle

What I am trying to accomplish is drawing curved lines from a center of a view. So far with the help of much googling and this site...I've accomplished the image below.
http://www.flickr.com/photos/57562417#N00/9100635690/
What I would like to do is have curved lines like the following image...
http://www.flickr.com/photos/57562417#N00/9100634674/
Any and all help would be appreciated. I've included the code thus far.
#import <UIKit/UIKit.h>
#interface ChartView : UIView
#property (nonatomic,assign) int angle;
#end
----------------------------------------------------------------------
#import "ChartView.h"
#import <QuartzCore/QuartzCore.h>
/** Helper Functions **/
#define degree_to_radians(deg) ( (M_PI * (deg)) / 180.0 )
#define radians_to_degrees(rad) ( (180.0 * (rad)) / M_PI )
#interface ChartView(){
int radius;
}
#end
#implementation ChartView
-(id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if(self){
self.backgroundColor = [UIColor whiteColor];
[self.layer setBorderWidth:1.0];
[self.layer setBorderColor:[UIColor redColor].CGColor];
//Define the circle radius taking into account the safe area
radius = self.frame.size.width/2;
//Initialize the Angle at 0
self.angle = 360;
}
return self;
}
-(void)drawRect:(CGRect)rect{
//Circle center
int numberOfSections = 96; //24 major lines
CGFloat angleSize = 2 * M_PI/numberOfSections;
CGContextRef context = UIGraphicsGetCurrentContext();
//draw the main outside circle
CGRect circleRect = CGRectMake(0.0, 0.0, 720., 720.);
CGContextSetLineWidth(context, .5);
CGContextSetRGBStrokeColor(context, 0.0, 2.0, 4.0, 1.0);
CGContextStrokeEllipseInRect(context, circleRect);
CGPoint centerPoint = CGPointMake(circleRect.size.width/2 , circleRect.size.height/2);
//setup for drawing lines from center, straight lines, need curved lines
CGContextTranslateCTM(context, 0.0, 0.0);
for (int x = 0; x < numberOfSections; x++) {
CGContextSetLineWidth(context, .5);
CGContextSetRGBStrokeColor(context, 0.0, 2.0, 4.0, 1.0);
CGContextMoveToPoint(context, self.frame.size.width/2, self.frame.size.height/2);
CGContextAddLineToPoint(context, centerPoint.x + radius * cos(angleSize * x) ,centerPoint.y + radius * sin(angleSize * x));
CGContextStrokePath(context);
}
CGContextSetLineWidth(context, .5);
CGContextSetRGBStrokeColor(context, 0.0, 2.0, 4.0, 1.0);
CGContextSetRGBFillColor(context, 1., 1., 1., 1.0);
//Taken from Hypnotizer code
float maxRadius = 360.0;
CGContextSetLineWidth(context, 0.5f);
CGContextSetRGBStrokeColor(context, 0.0, 2.0, 4.0, 1.0);
//need to add 100 lines form a certain radius to a max radius
for (float currentRadius = maxRadius; currentRadius > 99; currentRadius -=2.6) {
CGContextAddArc(context, centerPoint.x, centerPoint.y, currentRadius, 0.0, M_PI * 2.0, YES);
CGContextStrokePath(context);
}
}
#end
Alright, I've got some code for you that I tried out and does the curved line effect you mentioned in that second picture:
- (void)drawRect:(CGRect)rect {
radius = self.frame.size.width / 2;
// Circle center
int numberOfSections = 96; // 24 major lines
CGFloat angleSize = 2 * M_PI/ numberOfSections;
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect circleRect = CGRectMake(0.0, 0.0, 720., 720.);
CGPoint centerPoint = CGPointMake(circleRect.size.width / 2, circleRect.size.height / 2);
/* Create mask to create 'hole' in the center */
CGContextAddArc(context, centerPoint.x, centerPoint.y, 720 / 2.0, 0.0, M_PI * 2.0, YES);
CGContextAddArc(context, centerPoint.x, centerPoint.y, 100, 0.0, M_PI * 2.0, NO);
CGContextClip(context);
// draw the main outside circle
CGContextSetLineWidth(context, .5);
CGContextSetRGBStrokeColor(context, 0.0, 2.0, 4.0, 1.0);
CGContextStrokeEllipseInRect(context, circleRect);
// setup for drawing lines from center, straight lines, need curved lines
CGContextTranslateCTM(context, 0.0, 0.0);
for (int x = 0; x < numberOfSections; x++) {
CGContextSetLineWidth(context, .5);
CGContextSetRGBStrokeColor(context, 0.0, 2.0, 4.0, 1.0);
double angle = angleSize * x;
CGPoint outsidePoint = CGPointMake(centerPoint.x + radius * cos(angle), centerPoint.y + radius * sin(angle));
CGPoint control1 = CGPointMake(centerPoint.x + radius/3 * cos(angle-0.5), centerPoint.y + radius/3 * sin(angle-0.5));
CGPoint control2 = CGPointMake(centerPoint.x + (2*radius/3) * cos(angle-0.5), centerPoint.y + (2*radius/3) * sin(angle-0.5));
UIBezierPath *bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint:CGPointMake(circleRect.size.width / 2, circleRect.size.height / 2)];
[bezierPath addCurveToPoint:outsidePoint controlPoint1:control1 controlPoint2:control2];
CGContextAddPath(context, bezierPath.CGPath);
CGContextStrokePath(context);
}
CGContextSetLineWidth(context, .5);
CGContextSetRGBStrokeColor(context, 0.0, 2.0, 4.0, 1.0);
CGContextSetRGBFillColor(context, 1., 1., 1., 1.0);
// Taken from Hypnotizer code
float maxRadius = 360.0;
CGContextSetLineWidth(context, 0.5f);
CGContextSetRGBStrokeColor(context, 0.0, 2.0, 4.0, 1.0);
// need to add 100 lines form a certain radius to a max radius
for (float currentRadius = maxRadius; currentRadius > 99; currentRadius -= 2.6) {
CGContextAddArc(context, centerPoint.x, centerPoint.y, currentRadius, 0.0, M_PI * 2.0, YES);
CGContextStrokePath(context);
}
}

UITableView with static cell - different separation color per section?

I have UITableView with static cells in 4 sections done in Storyboard. However, I want to change the separator color for one section ([UIColor clearColor]). How can I do that??? Is it actually possible?
I can set the separatorColor to clearColor for the entire table, but not only for one specific section.
Screenshot of table view section:
AFAIK there is no method for this. But you can put a background image to the cell which has a separator at the bottom and set separatorstyle to UITableViewCellSeparatorStyleNone. So you have your own separator in every cell.
Maybe you can achieve your goal by setting the header text for the section to an empty string.
One approach would to create your own UIView subclass and do your own custom drawing in drawRect:. You would take this view and add it as the backgroundView of your table view cell. Something like this:
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 1.0);
// Draw black line
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGFloat components[] = {0.0, 0.0, 0.0, 0.3};
CGColorRef blackColor = CGColorCreate(colorspace, components);
CGContextSetStrokeColorWithColor(context, blackColor);
CGContextMoveToPoint(context, 0, rect.size.height - 1.5);
CGContextAddLineToPoint(context, rect.size.width, rect.size.height - 1.5);
CGContextStrokePath(context);
CGColorRelease(blackColor);
// Draw white bottom line
CGFloat whiteComponents[] = {1.0, 1.0, 1.0, 0.75f};
CGColorRef whiteColor = CGColorCreate(colorspace, whiteComponents);
CGContextSetStrokeColorWithColor(context, whiteColor);
CGContextMoveToPoint(context, 0, rect.size.height - 0.5);
CGContextAddLineToPoint(context, rect.size.width, rect.size.height - 0.5);
CGContextStrokePath(context);
CGColorRelease(whiteColor);
// Draw top white line
CGFloat whiteTransparentComponents[] = {1.0, 1.0, 1.0, 0.45};
CGColorRef whiteTransparentColor = CGColorCreate(colorspace, whiteTransparentComponents);
CGContextSetStrokeColorWithColor(context, whiteTransparentColor);
CGContextMoveToPoint(context, 0, 0.5);
CGContextAddLineToPoint(context, rect.size.width, 0.5);
CGContextStrokePath(context);
CGColorRelease(whiteTransparentColor);
CGColorSpaceRelease(colorspace);
}

Objective C: Draw(Write) on Touch in a UIScrollView

I have this code on my touchesMoved but like the others its not working on UIScrollView
Here it is, on my touchesMoved:
touchSwiped = YES;
currentTouch = [touch locationInView:self.view];
currentTouch.y -= 5;
UIGraphicsBeginImageContext(self.view.frame.size);
[writeView.image drawInRect:CGRectMake(0, 0, 768, 1024)];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, 15);
CGContextSetRGBStrokeColor(context, 0, 0, 0, 1);
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGContextMoveToPoint(context, endPoint.x, endPoint.y);
CGContextAddLineToPoint(context, currentTouch.x, currentTouch.y);
CGContextStrokePath(context);
writeView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
endPoint = currentTouch;
touchMoved++;
if (touchMoved == 10) {
touchMoved = 0;
}
so, i transferred it using Gesture recognizer but still it is not working.
i used the PanGestureRecognizer
here:
- (void) writePan:(UIPanGestureRecognizer *)writingRecognizerP {
switch (writingRecognizerP.state)
{
case UIGestureRecognizerStateChanged:
[scrollView setScrollEnabled:NO];
[scrollView setUserInteractionEnabled:NO];
touchSwiped = YES;
currentTouch = [writingRecognizerP locationInView:scrollView];
currentTouch.y -= 5;
UIGraphicsBeginImageContext(self.view.frame.size);
[writeView.image drawInRect:CGRectMake(0, 0, 768, 1024)];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, 15);
CGContextSetRGBStrokeColor(context, 0, 0, 0, 1);
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGContextMoveToPoint(context, endPoint.x, endPoint.y);
CGContextAddLineToPoint(context, currentTouch.x, currentTouch.y);
CGContextStrokePath(context);
writeView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
endPoint = currentTouch;
touchMoved++;
if (touchMoved == 10) {
touchMoved = 0;
}
break;
case UIGestureRecognizerStateEnded:
[scrollView setScrollEnabled:YES];
[scrollView setUserInteractionEnabled:YES];
break;
}
}
anyone who has an idea how will i able to write on touch??
it'll be much appreciated! :)
You should do all your drawing in -drawRect:, and when something changes send your view -setNeedsDisplay or setNeedsDisplayInRect: message.