How can I visually display points in a UIBezierPath? - ios

I'm trying to change the shape of a CAShapeLayer from a circle to a different shape. Looking at this question:
Smooth shape shift animation
I found the solution but my question is how can I visually see how many points a UIBezierPath has. Is there a way to color a point different than the line it produces?
For example,it's simple with a line to understand that there are two point, but if we make a circle with bezierPathWithRoundedRect, does that count as one point or are there more?

You would need to add the circle yourself to visually see the dots. Just keep track of the CGPoints you give to the path and draw a circle around each one.
Btw.. if you use PaintCode, you can edit the bezier path and see the point -- it's very useful.

Related

Circle with fluid/strechy stroke

Me and my team are working on an app for a client. We are trying to understand how to achieve this kind of animations (refer only to the circle stroke) :
We tried using a CADisplayLink to set up and change the circle, but it generated non-fluid results.
We couldn't find a way to create a circle from "components" of UIBezierPath and change each of the anchors.
Any suggestions on how to achieve this kind of effect, or how to construct a circle from seperated points, would be highly appricated
Best Regards,
Roi and the team
I suggest using Catmull-Rom splines. Those allow you to create smooth curves using only points that are on the curve, whereas Bezier curves require that you define control points that are not on the curve.
Once you have beginning and ending CGPaths its pretty easy to create a CAAnimation of the path from it's starting to it's ending state (although animating change to a CGPath only works correctly if the starting and ending paths in the animation have the same number and type of points.)
You could probably also use Bezier curves, but you would need to generate the control points for the circle and it's distorted shape.
Check out this sample app that uses Catmull-Rom splines to create a distorted circle shape:
http://wareto.com/animating-shapes-using-cashapelayer-and-cabasicanimation
(Written in Objective-C, but the technique is the same in Swift.)
A Catmull-Rom spline with 8 control points evenly spaced around a circle where the distance from the center of each control points is varied by ± r/12 seems about right:

why the curve have been into a straight line in image [duplicate]

There a is an ellipse on the picture,just as following.
I have got the points of the contour by using opencv. But you can see the pictrue,because the resolution is low, there is a straight line on the contour.How can i fit it into curve like the blue line?
One Of the method to solve your problem is to vectorize your shape (moving from simple intensity space to vectors space).
I am not aware of the state-of-art in this field. However, from school information, I can suggest this solution.
Bezier curves, you can try to model your shape using simple bezier curve.This is not a hard operation you can google for dozen of them. Then, you can resizing it as much as you want after that you may render it to simple image.
Be aware that you may also Splines instead of Bezier.
Another method would be more simple but less efficient. Since you mentioned OpenCV, you can apply the cv::fitEllipse on the points. Be aware that this will return a RotatedRect which contains the ellipse. You can infer your ellipse simply like this:
Center = Center of RotatedRect.
Longest Radius = The Line which pass from the center and intersect with the two small sides of the RotatedRect.
Smallest Radius = The Line which pass from the center and intersect with the two long sides of the RotatedRect.
After you got your Ellipse Parameters, You can resize it as you want then just repaint it in the size you want using cv::ellipse.
I know that this is a pseudo answer. However, I think every thing is easy to apply. If you faced any problem implementing it, just give me a comment.

Moving Tail Animation

I want to make an animation with a moving line, similar to a dog waging his tail.
I'm not sure how to begin. I've used Core Animation's CAShapeLayer for progress bars before but don't know if it would work for this. I also used PaintCode in the past to help for custom paths, for example to create a custom UIBezierPath for an object to animate on. But also not sure if PaintCode would help with this.
Any ideas?
This wouldn't be that hard. Yes, using a CAShapeLayer animation would be the way to go.
I would make the non-changing part of the image into a bitmap, and then draw your shape layer animation on top.
The trick with shape layer animation is that the shape you use needs to have the same number of control points for all the parts of your animation.
In the case of your tail animation you should be able to map it out as a set of quadratic bezier curves. You could probably draw the tail as a single thick path with a rounded end cap. (kCGLineCapRound). You'd make the starting curve a quadratic bezier curve with the starting point down at the beginning of the straight part of the tail, the next control point slightly to the right and below the curved tip, the next control point above and to the left of the first control point but still below and to the right of the tip, and the last control point at the tip.
The ending curve would have the first control point at the same place on the base of the tail, the second control point at about the top of the curve and to the left, the next control point above the curve and about 2/3 of the way between the base point and the tip, and the last point at the tip of the tail.
You might want to play with the path tool in Adobe Photoshop (or GIMP) and use it to create the starting and ending tail curve shapes using a single quadratic Bezier curve, then write down the control point positions that you use and enter them into your code.
You'd create a CABasicAnimation of the CAShapeLayer where you set the fromValue to the starting CGPath and the toValue to the ending CGPath. Just make sure that the starting and ending paths have the same number of control point.
I have a project called RandomBlobs (link) on Github that shows how to animate a curve using CGPaths and CABasicAnimations, but it is written in Objective-C, and instead of using quadratic bezier curves, it creates another kind of a curve called a Catmull-Rom spline. quadratic bezier curves are actually much simpler to set up than Catcall-Rom splines however, and the idea behind animating changes to a CAShapeLayer using CABasicAnimation should be fairly easy to translate from Objective-C to Swift if you've worked with CAShapelayers before. You could also use a series of Catmull-Rom splines to get the tail animation you're after. The advantage of Catmull-Rom splines is that all the control points are on the curve.

Curve line into circle in iOS

I have this idea of transforming a straight line into a circle but the offset of a cell drag in a table view.
As I drag the cell, I want the line to curve into a circle around an image.
I've included a picture below to help demonstrate different states with different drag offsets.
Im not sure where to start, was thinking of maybe using UIBezierPath to draw but not sure if that's the best solution.
If you want it to animate then you have your work cut out for you.
Core Animation of curves is based on CGPath objects, which is the underlying Core Foundation class behind UIBezierPath.
The secret to making a curve animate from one shape to another is to use the same number and type of control points. You won't be able to use any of the standard arc or oval shortcuts (which generate more complex bezier curves that look like arcs.)
Instead, you'll have to build an approximation of a circle piecewise out of a linked series of cubic bezier curves. You should be able to get fairly close with 4 linked cubic bezier curves who's endpoints line are at the N/S/E/W compass points of a circle, and the intermediate control points are spaced evenly outside the circle. A couple of years ago I looked up an article on the net for approximating a circle using Bezier points. I would suggest doing some searching on that.
Alternately, I guess you could generate a circle bezier curve using one of the CGPath or UIBezier shortcuts, then deconstruct the resulting path into the primitives that make it up. Erica Sadun's outstanding iOS Developer's Cookbook series includes a recipe that shows how to deconstruct a UIBezier path into it's primitives.
Once you have a set of control points for a circle, you would need to re-map them into control points that make your line. (A Bezier curve always passes through it's beginning and end points, and if you put the inner 2 control points of a Cubic Bezier on a line, it will turn the curve into a line.)
Now you have 2 shapes made up of the same number of bezier curves and the same number of control points: A circle and a line. You can transform the line into the circle or the circle into the line by moving each of the control points to different x/y coordinates.
Then you might be able to apply a linear interpolation between the starting and ending coordinates of your control points. Use the user's drag of the table view to generate a value from 0 to 1, and apply that to your interpolated control point values (at 0.0, your control points would be at their "straight line" position and your curve would draw as a straight line. At 1.0, they'd be at their circle position, and your curve would draw as a circle. At points between, they'd be a fraction of the way between their beginning and ending positions, and you'd get a shape that was between a line and a circle.
Once you have figured out how to generate the control points to create a curve that moves smoothly from a straight line to a circle, you are ready to tackle doing it using Core Animation and a CAShapeLayer.
If that makes sense then you can probably figure out how to do this. If you have no idea what I am talking about they you are probably in over your head.
(I'm a senior Cocoa/iOS developer. I've done a lot of Core Animation and it would probably take me 3 or 4 hours to get what you are after to work, once I had the circle bezier control points to start from.)
Come to think of it, it would probably be a lot simpler to use UIView keyframe animation. That lets you specify an array of control points that ALL lie on the desired curve, and generates a smooth curve from those points.. Best yet, it is a UIView animation, which is a heck of a lot easier to use than CAAnimation.
Take a look at my demo project RandomBlobs on github. That should give you a head start on using UIView keyframe animation. The method you want is called animateKeyframesWithDuration:delay:options:animations:completion:.
The down-side of point-based keyframe animation is that sometimes the curve you get has "kinks" or loops in it that you don't expect or want. You have to avoid sharp bends. In sketching it out, though, I think a line-to-circle transition might work with keyframe view animation.

Draw curve with varying line width

I know how to draw curve with Core Graphic or using UIBezierPath.
But, I want to draw a curve that is wide to begin with and thin at the end:
I searched many question about curve, bezier path or something similar on Google. But i can't find any ideal for implementing it.
Can you help me ?
The two methods that immediately come to mind are...
Calculating the path
This is probably the most complex. It would involve calculating the path for the entire shape and adding this as a path and filling it.
Using a line method
You create a series of points that will lie along the centre line of your curve. Maybe 5 points between each point.
Then at each point you can use that as a centre point of a line perpendicular to the tangent of the curve at the point.
The perpendicular line will have a length which you can calculate depending on how far through the curve you are.
Then use this line to create a square path to the line from the previous point.
Then fill that square.
Move to the next point. Add the line and create a box back to the previous line and so on.
At the end are a circle with centre point of the last point. This will create the end.
It's complex but doable if you split down the functions.

Resources