How to draw a line with an array of CGPoint - iphone

I have an array of CGpoint and I want to connect these points to create a line. I know how to do it by subclass the UIView. but what I want to do here is that I already have an array of CGPoint and I have a button, when I click the button the line will be shown.
I don't know how to do this.
However I try something like following: (aLine is the array with CGPoint)
#define POINT(X) [[aLine objectAtIndex:X]CGPointValue]
CGContextRef context = UIGraphicsGetCurrentContext();
for (int i = 0;i < (aLine.count-1);i++){
CGPoint pt1 = POINT(i);
CGPoint pt1 = POINT(i+1);
CGContextMoveToPoint(context,pt1.x,pt1.y);
CGContextAddLineToPoint(context,pt2.x,pt2.y);
CGContextStrokePath(context);
}
Anyone can help me? thanks.

You're almost there! Firstly you need to set the stroke colour...
CGContextSetStrokeColor(context, CGColorGetComponents([colour CGColor]));
Then when you're done connecting your points (exactly what your code is currently doing) just close the path and stroke it...
CGContextClosePath(context);
CGContextDrawPath(context, kCGPathStroke);

Related

Coloring In between CGPaths

I am building a drawing type tool into my app.
It takes a touch points from the user and draws lines between the points. If the user creates 3 touch points or greater, it joins the last point to the first point.
An extract of the code is :
startPoint = [[secondDotsArray objectAtIndex:i] CGPointValue];
endPoint = [[secondDotsArray objectAtIndex:(i + 1)] CGPointValue];
CGContextAddEllipseInRect(context,(CGRectMake ((endPoint.x - 5.7), (endPoint.y - 5.7)
, 9.0, 9.0)));
CGContextDrawPath(context, kCGPathFill);
CGContextMoveToPoint(context, startPoint.x, startPoint.y);
CGContextAddLineToPoint(context, endPoint.x, endPoint.y);
CGContextStrokePath(context);
I wish to "color in " the area contained within these paths.
What should I look at?
You need to use the CGContextFillPath API. You should be careful of how you define the path, though:
Start by calling CGContextMoveToPoint on the initial point
Proceed by drawing all segments except the closing one with CGContextAddLineToPoint
Close the path with CGContextClosePath. Do not add line to point on the final segment.
The call of CGContextFillPath will produce a path colored with the fill color that you have previously set.
Here is an example:
CGPoint pt0 = startPoint = [[secondDotsArray objectAtIndex:0] CGPointValue];
CGContextMoveToPoint(context, pt0.x, pt0.y);
for (int i = 1 ; i < noOfDots ; i++) {
CGPoint next = [[secondDotsArray objectAtIndex:i] CGPointValue];
CGContextAddLineToPoint(context, next.x, next.y);
}
CGContextClosePath(context);
CGContextFillPath(context);

Emboss effect in Core Graphics

I am again here with two Question, both inter-related
I want to draw embossed lines with core graphics.
Can any one suggest me how to give inner shadows to line drawn on touch events?
Even for drawing outer shadows.
Shadow drawn overlaps in between. and line drawn with colors other than black is like worm..
Can any one help me?
Following image illustrates what I mean to explain for Question 2:
Shadows creates are not even. They darken at some points
I am adding the code that I am using to draw lines..
for (int i=0; i<[currentPath count]; i++)
{
CGPoint mid1 = [[self midPoint:[currentPath objectAtIndex:i+1] :[currentPath objectAtIndex:i]] CGPointValue];
CGPoint mid2 = [[self midPoint:[currentPath objectAtIndex:i+2] :[currentPath objectAtIndex:i+1]] CGPointValue];
CGContextMoveToPoint(context, mid1.x, mid1.y);
CGContextAddQuadCurveToPoint(context, [[currentPath objectAtIndex:i+1] CGPointValue].x, [[currentPath objectAtIndex:i+1] CGPointValue].y, mid2.x, mid2.y);
CGContextSetShadow(context, CGSizeMake(-2, -2), 3);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetStrokeColorWithColor(context,[color CGColor]);
CGContextSetLineWidth(context, linewidth);
CGContextStrokePath(context);
i+=2;
}
I found my solution..
Problem was very silly...
I was stoking path on every iteration which was creating the issue.. Now I can draw even with alpha less then 1..
CGContextStrokePath(context);
This line goes outside for loop.. And all is working fine now :)
For your overlapping shadows, you want a transparency layer to composite them first. See Transparency Layers in the Quartz 2D Programming Guide.
It looks like you are drawing the path by using a series of circles.
The trouble is that you have set the shadow on the individual dots, and that's why you are getting the strange effects.
A possible solution - dont put a shadow on the dots, put on the path: duplicate the line that you have drawn, draw it in a different colour, offset it and put in under your actual line.
Alternatively, if you are using layers - have a look at shadow paths.

Core Graphics draw line with outline

I'm drawing an arbitrary line with Core Graphics with a width of 4 pixels, now I would like this line to have a 1 pixel outline of another colour. I can't see any CG functions that would achieve this "out of the box" but I'm looking for suggestions on how it could be done. This is my existing code:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 4.0);
CGPoint curPoint = [(NSValue*)[points objectAtIndex:0] CGPointValue];
CGContextMoveToPoint(context, curPoint.x, curPoint.y);
for( int i = 1; i < [points count]; i++ ) {
curPoint = [(NSValue*)[points objectAtIndex:i] CGPointValue];
CGContextAddLineToPoint(context, curPoint.x, curPoint.y);
CGContextStrokePath(context);
CGContextMoveToPoint(context, curPoint.x, curPoint.y);
}
This produces the single line. I would like to produce a 4px line with a 1px line highlighting the 4px line like this:
iOS 5.0 added a new feature CGPathCreateCopyByStrokingPath() that does what you want.
First create a CGPathRef for the black path, and then create a copy of it with CGPathCreateCopyByStrokingPath().
This will give you a new path, which you can fill in black and stroke in red, to get what you want.
Also, creating paths is a bit slow. You should avoid creating paths while performing screen drawing. All your paths should be stored in RAM and ready to go before you start drawing to the screen. drawRect: should only draw the path, not create it.
Similar to what Abhi Beckert suggests, but you can use this function:
CGContextReplacePathWithStrokedPath(CGContextRef c);
Which is present in older SDKs too - iOS 4.1, MacOS X 10.6, for example.
Also it is better to create the whole path and then stroke it (or stroke and fill in the same time) at the end - in other words no need to have CGContextStrokePath inside the loop.
I am afraid you will have to draw the path again with the line width set to 1. If you want it to be on the outside of your 4 pixel path, you will have to adjust your path accordingly.
Edit: One other option comes to mind - you can stroke a pattern - see Apple's QuartzDemo for an example how.
To add an answer to my own question, it can be done by drawing a line a few pixels wider in the highlight colour followed by the actual line on top. This produces the outline effect.
There isn't a built-in way to convert a stroke to a path, and then stroke that path. That said, you may be able to approximate this by drawing the line twice: once with a 6 pixel stroke (4 pixels + 1 on each side) and then again with a 4 pixel stroke in a different color
Similar to:
CGContextRef context = UIGraphicsGetCurrentContext();
CGPoint curPoint = [(NSValue*)[points objectAtIndex:0] CGPointValue];
CGContextMoveToPoint(context, curPoint.x, curPoint.y);
for( int i = 1; i < [points count]; i++ ) {
curPoint = [(NSValue*)[points objectAtIndex:i] CGPointValue];
CGContextAddLineToPoint(context, curPoint.x, curPoint.y);
}
// Set your 1 pixel highlight color here using CGContextSetRGBStrokeColor or equivalent
// CGContextSetRGBStrokeColor(...)
CGContextSetLineWidth(context, 6.0);
CGContextStrokePath(context);
// Set your 4 pixel stroke color here using CGContextSetRGBStrokeColor or equivalent
// CGContextSetRGBStrokeColor(...)
CGContextSetLineWidth(context, 4.0);
CGContextStrokePath(context);
Another idea would be setting up a shadow via CGContextSetShadowWithColor(context, CGSizeZero, 1.0, yourHighlightColorHere) prior to drawing the stroke, although this won't draw the highlight color with full opacity. (I also can't remember if shadows property shadow strokes - I have only used them with fills)

How to draw a double dashed line in Quartz

I am trying to create an app that allows the user to draw a dotted line with their finger on an iPad. I have all of the drawing routines to create single lines. My question is how should I go about drawing a double line in such a way that it will not overlap itself when you create curves. I have been trying to accomplish this by Adding a second line to my Path with an offset of the x and y of the current point. This works fine as long as you move vertically or horizontally. When you draw at an angle, the double lines become a single line.
I am keeping an array of points stored as NSValues (pathPoints) so that I can store them for later use. Starting point is the first point in pathPoints.
UIGraphicsBeginImageContext(self.frame.size);
//This needs to be a dotted line
CGFloat pattern[] = {10,20};
CGContextSetLineDash(UIGraphicsGetCurrentContext(), 3, pattern, 2);
CGMutablePathRef path = CGPathCreateMutable();
CGMutablePathRef path2 = CGPathCreateMutable();
CGPoint startingPoint = [[pathPoints objectAtIndex:0] CGPointValue];
CGPathMoveToPoint(path, nil, startingPoint.x, startingPoint.y);
CGPathMoveToPoint(path2, nil, startingPoint.x + 10, startingPoint.y + 10);
for (int i = 1; i < [pathPoints count]; i++)
{
CGPoint linePoint = [[pathPoints objectAtIndex:i] CGPointValue];
CGPathAddLineToPoint(path, nil, linePoint.x, linePoint.y);
CGPathAddLineToPoint(path2, nil, linePoint.x + 10, linePoint.y + 10);
}
// of course later on I add the paths to the context and stroke them.
CGContextAddPath(UIGraphicsGetCurrentContext(), path);
CGContextAddPath(UIGraphicsGetCurrentContext(), path2);
CGContextStrokePath(UIGraphicsGetCurrentContext());
UIGraphicsEndImageContext();
I greatly appreciate any help I can get with this.
If you're okay with the lines being joined at the end (see image below) then you can create the effect using CGContextReplacePathWithStrokedPath().
/**
* CGContextRef context = <the context you're drawing to>
* CGFloat lineWidth = <the width of each of your two lines>
* CGFloat lineSpace = <the space between the two lines>
**/
// Create your path here (same as you would for a single line)
CGContextSetLineWidth(context, lineWidth + lineSpace);
CGContextReplacePathWithStrokedPath(context);
CGContextSetLineWidth(context, lineWidth);
CGContextStrokePath(context);

I need to draw a line on a view, and have the line be straight no matter what, but dynamic in length

Ok I need to implement a simple measuring tool for an iPad app I am working on. I don't have any experience with drawing, so I am really struggling. When the user presses down on the view (in measuring mode) the line's origin starts. I need to then be able to draw a line to wherever the user drags their finger, as they are dragging their finger, and have it be straight the entire time too.
I have the logic that calculates the distance between two points working based on two UITapGestureRecognizers, but I am thinking I will need to implement the touchesBegan/Ended methods instead.
How can I draw a line as the user drags, and make it stay straight the entire time?
I just need a point in the right direction.
Thanks!!
Check out a good tutorial like this.
Skip to the section on drawing lines:
void draw1PxStroke(CGContextRef context, CGPoint startPoint, CGPoint endPoint,
CGColorRef color) {
CGContextSaveGState(context);
CGContextSetLineCap(context, kCGLineCapSquare);
CGContextSetStrokeColorWithColor(context, color);
CGContextSetLineWidth(context, 1.0);
CGContextMoveToPoint(context, startPoint.x + 0.5, startPoint.y + 0.5);
CGContextAddLineToPoint(context, endPoint.x + 0.5, endPoint.y + 0.5);
CGContextStrokePath(context);
CGContextRestoreGState(context);
}
and then here is the call to that method:
// Add in color section
CGColorRef separatorColor = [UIColor colorWithRed:208.0/255.0 green:208.0/255.0
blue:208.0/255.0 alpha:1.0].CGColor;
// Add at bottom
CGPoint startPoint = CGPointMake(0, 0);
CGPoint endPoint = CGPointMake(100, 20);
draw1PxStroke(context, startPoint, endPoint, separatorColor);