Draw line with increasing lineWidth on iPhone - objective-c

I'm drawing a line on iOS by stroking a path onto a CALayer. How can I stroke this line with an increasing lineWidth (stroke width), so that the left end of the line is thinner than the right end? (It really has to be a line, not a shape or closed path, since I'm going to be using the strokeEnd property.)
Thank you for your help!

Use a draw function. It's pretty annoying to get used to at first, but it does its job. If you need anymore help just leave comment
-(void)draw{
float lineHeight = 5;//change this as you see fit, like set it equal to an incrementing/decrementing variable of your choice...
glEnable(GL_LINE_SMOOTH);
glLineWidth(lineHeight); // change this as you see fit
glColor4ub(255,255,255,255); // change these as you see fit :)
ccDrawLine(ccp(10,310), ccp(30,310)); // these numbers are probably off, you'll have to mess with these to get it in the right position :)
[super draw];
}

Related

How to draw half an ellipse in Win2D?

I want to draw either the lower or the upper half of an elliptical arc using Win2D in a C++/winrt app. I can draw the curve, but it includes a diagonal line at its start that looks as if I had begun with a straight line segment - as if the figure didn't begin at the arc but rather some distance down and to the right. How I can restrict drawing to just the arc? Here is the code and an image of the result:
float2 arcSize(100, 6);
auto pathBuilder = CanvasPathBuilder(drawingSession.Device());
pathBuilder.BeginFigure(244, 175);
//Starting at 3 o"clock, sweep pi radians, that is, to 9:00
pathBuilder.AddArc(arcSize,50,6,0.0, 3.14);
pathBuilder.EndFigure(CanvasFigureLoop::Open); //Don't close path
auto geometry = CanvasGeometry::CreatePath(pathBuilder);
session.DrawGeometry(geometry,244, 175, Colors::Black(),1.5);
OK, thanks to that hint from Inspectable I have the solution: the problem lies in where the path begins. In my code I had mistakenly used the proposed arc size as the first argument to AddArc when really that should be the arc center coordinates. And the BeginFigure in the case of this arc must be the point lying at the right edge, at what would be 3:00 in a circle. With the ArcCenter correct in relation to the BeginFigure then AddArc doesn't draw the extra line.
[Update:] p.s. The x and y coordinates for the DrawGeometry call should be zero in this case; that draws it at its original coordinates from BeginFigure, not offset. Maybe this p.s can gain me another -1 for this question.

Sprite Kit: SKSpriteNodes hanging off left side of screen despite (0,0) anchor points

I'm adding an array of SKSpriteNodes (640px wide) directly to my SKScene:
for (backgroundTile in backgroundTiles) {
backgroundTile.anchorPoint = CGPointMake(0.0, 0.0);
backgroundTile.position = CGPointMake(BG_TILE_X_POS, tilePlacementPositionY);
[self addChild:backgroundTile];
tilePlacementPositionY += tileHeight;
}
(BG_TILE_X_POS is 0.0)
But despite having an X position of 0.0 and their anchor points being set to (0.0,0.0) they still hang off the left side of the screen by 150px.
I can compensate that by giving them an X position of 150 and have also tried:
self.size = view.bounds.size;
…but that only enlarges the visible parts of the sprites so that they fill the screen; cropping off the top sprite.
I assume I'm making a rookie mistake but, looking through the documentation, nothing's striking me as obvious (which I guess it should be).
So, how do I position the sprites flush to the left edge? Any help would be appreciated.
Thanks.
I'd overlooked the obvious. I'd only created placeholder sprites at x2 resolution but stored them in their image sets as 1x resolution. Finally, with the setting:
self.size = view.bounds.size;
everything behaves as expected.
Silly mistake. I was convinced the problem was with the code, not the assets.

Applying a scale and translate transformation to UIBezierPath

I have a UIBezierPath and I would like to:
Move to any coordinate on the UIView
Make bigger or smaller
I am drawing the UIBezierPath based off of a list of predefined coordinates. I implemented this code:
CGAffineTransform move = CGAffineTransformMakeTranslation(0, 0);
CGAffineTransform moveAndScale = CGAffineTransformScale(move, 1.0f, 1.0f);
[shape applyTransform:moveAndScale];
I have also tried scaling and then moving the shape, it seems to make little to no difference.
Using this code:
[shape moveToPoint:CGPointMake(0, 0)];
I start drawing the shape at (0, 0), but this is what happens. I assume this is because a line is being drawn from 0, 0 to the next point in the list.
When I set the move transformation to (0, 0) this is where it draws. Here, moveToPoint is set to the first coordinate pair in the list. As you can see, it is not at 0, 0.
Finally, increasing the 1.0f moves the shape off the screen completely, no matter where the I tell the shape to move.
Can someone help me understand why the shape is not drawing at 0, 0 and why it moves off the screen when I scale it.
(As requested by the OP in a comment above)
I might be wrong on this one, but doesn't this code
CGAffineTransformMakeTranslation(0, 0);
just say that something should be moved 0 pixels along the x-axis and 0 pixels along the y-axis? (reference) It won't actually move anything to origo (0, 0), as it seems you are trying to do.
Also, it seems like you have slightly misunderstood how to properly use moveToPoint:.. Think of it as a way to move your cursor, but without actually drawing anything. It is just a way to say 'I want to start drawing at this point'. The drawing itself can be performed by other methods. If you wanted to e.g. draw a square with sides of length L, then you could do something like this..
// 'shape' is a UIBezierPath
NSInteger L = 100;
CGPoint origin = CGPointMake(50, 50);
[shape moveToPoint:origin]; // Initial point to draw from
[shape addLineToPoint:CGPointMake(origin.x+L, origin.y)]; // Draw from origin to the right
[shape addLineToPoint:CGPointMake(origin.x+L, origin.y+L)]; // Draw a vertical line
[shape addLineToPoint:CGPointMake(origin.x, origin.y+L)]; // Draw bottom line
[shape addLineToPoint:origin]; // Draw vertical line back to origin
Note that this code is not tested at all, but it should give you the idea of how to use moveToPoint: and addLineToPoint:.
You need to be careful of the order you apply the transforms in and you should think about concatenating the transforms together and applying them in one go.
The order is important as each transform affects all x,y positions in the path. So, the translation is affected by the scale. Reverse the order and the path will be scaled and then moved.
Also, the coordinate system is important, particularly if you are scaling. Ensure you draw around 0,0 and then scale and then translate. This is easiest if you normalise the points. Normalising for lat/long values means dividing latitude by 90 and longitude by 180 (this will actually give you a range -1..1). When doing this you should first scale the path, then translate it to the centre of the view, then apply your desired translation.

Draw rotated text to parent coordinate system

I have a UIView, which I'm drawing manually in the 'drawRect'-Function.
It is basically a coordinate system, which has 'Values' on the Y-Axis and 'Time' on the 'X-Axis'.
Due to space issues, I want the Timestamps to be vertical, instead of horizontal.
For this purpose, I use:
CGContextSaveGState(ctx); //Saves the current graphic context state
CGContextRotateCTM(ctx, M_PI_2); //Rotates the context by 90° clockwise
strPos = CGContextConvertPointToUserSpace(ctx, strPos); //SHOULD convert to Usercoordinates
[str drawAtPoint:strPos withFont:fnt]; //Draws the text to the rotated CTM
CGContextRestoreGState(ctx); //Restores the CTM to the previous state.
ctx (CGContextRef), strPos (CGPoint) and str (NSString) are variables, that have been initialized properly and correctly for 'horizontal text', with a width of the text height.
While this code works flawlessly on the iPhone 3, it gives me a complete mess on the iPhone 4 (Retina), because the CGContextConvertPointToUserSpace function produces completely different results, even though the coordinate system of the iPhone is supposed to remain the same.
I also tried using CGAffineTransform, but only with the same results.
To summarize my question: How do I draw a text to a calculated position in the parent coordinate system (0, 0 being top left)?
After studying the Apple docs regarding Quartz 2D once more, I came to realize, that the rotation by Pi/2 moves all my writing off screen to the left.
I can make the writing appear in a vertical line by translating the CTM by +height.
I'll keep trying, but would still be happy to get an answer.
Edit: Thanks to lawicko's heads-up I was able to fix the problem. See Answer for details.
I would like to thank lawicko for pointing this out.
During my tests I made two mistakes...but he is of course correct. Using CGContextShowTextAtPoint is the most simple solution, since it doesn't require the rotation of the entire CTM.
Again, THANK you.
Now, for the actual answer to my question.
To draw a rotated text at position x/y, the following code works for me.
CGAffineTransform rot = CGAffineTransformMakeRotation(M_PI_2); //Creates the rotation
CGContextSelectFont(ctx, "TrebuchetMS", 10, kCGEncodingMacRoman); //Selects the font
CGContextSetTextMatrix(ctx, CGAffineTransformScale(rot, 1, -1)); //Mirrors the rotated text, so it will be displayed correctly.
CGContextShowTextAtPoint(ctx, strPos.x, strPos.y, TS, 5); //Draws the text
ctx is the CGContext, strPos the desired position in the parent coordinate system, TS a char array.
Again, thank you lawicko.
I probably would've searched forever if not for your suggestion.
Maybe this answer will help someone else, who comes across the same problem.

Drawing a chart with gradient in Objective C

I'm trying to make a simple app where a chart is drawn with a line and X axis. I want to fill parts of the view enclosed by chart and X axis with gradient. To fill them I use the following code
CGContextSaveGState(c);
CGContextAddPath(c, CGContextCopyPath(c));
CGContextClip(c);
CGContextDrawLinearGradient(c, g, previousPointOfIntersection, intersectionPoint, 0);
CGContextRestoreGState(c);
every time the line crosses the X axis. However, the problem is that the gradient fills the whole view between previous point of intersection and current one.
Is this a right way to draw a gradient for a part of view enclosed by lines?
I'd be very happy to hear any suggestions regarding my problem :)
P.S. here's the code of my class http://pastebin.com/wYiHkuVi
I'd say you don't have the path in the context that you think you do.
If you've "stroked" the path for your graph it's been used up.
Replace your Add Path with:
CGContextAddEllipseInRect(c, self.bounds);
to see if you get some clipping occurring.
If so, then you need to rebuild your path here instead of the AddPath/Ellipse code.