Modifying smooth curve with Anchor points - swift

I wish to emulate this effect in Xcode with Swift. After some research I managed to find some articles about drawing smooth curves using a set of points .But I am still unclear about how I could to dynamically modify curves when the user touches/holds the screen.
Question :
I know how to make a smooth Bezier curve, but how can I add gesture recognizers such that by dragging the curve its shape changes.
I only need someone to point me in the right direction. Is there a guide or article in particular that could be useful?

Create transparent ControlPointView for every control point of the curve with a size of 50*50pt, so that users can easily tap them and drag.
Add a small image in the middle of every ControlPointView, so that users can see where the control point is located.
Add UIPanGestureRecognizer on every ControlPointView and handle it in view controller.
Use centers of control points to rebuild UIBezierPath every time gesture recognizer's state is changed.

Related

Resizing curve by dragging control points

I'm trying to resize a drawn quadCurve by dragging one of its 3 control points so the curve can fit. What is the best approach to do this? letting you know that I'm using an imageView for drawing. Not using drawRect.
I know that I should detect if the touch is on the control points which is pretty easy but I don't know what to do after in my touchMoved and touchEnded methods.
Several things:
I would not use an image view for this. This is the kind of problem that drawRect: is for.
Don't use touchesMoved. Use a UIPanGestureRecognizer on the control points.
Make the control points subviews so you can attach gesture recognizers to them.
To work well, the control points typically need to have a pretty large hit area (larger than they are visually). You can do this pretty easily by making the control point views larger than what they draw (so if they're drawn as a 13 point circle, you put that in the middle of a 23 point view).
For an example of code that does all this see CurvyTextView.m. It doesn't do the last point (the control point views are too small to use well on a real device). Ignore all the text drawing code. You just care about updateControlPoints, addControlPoint:color:, initWithFrame:, pan:, and drawPath.

a touchable polygon on a view ?

I need to show a view on which I need to animate a polygon using its vertices. The polygon should be touchable, thus fire an event once touched, and I need to be able to move its vertices using some animation procedure, once it has fired that event.
I need to have three polygons like that to form a 3D Cube.
The darkened area is the view (actually an image) on which I have the cube.
There are two steps in the process: drawing and event handling.
Drawing can be done with Quartz2D, by implementing a drawRect in a view, calculating the coordinates of the cube on screen, followed by creating and drawing the path, which works fine for solidly filled shapes. The alternative method uses an OpenGL view where you specify triangles.
At the event handling end, you can implement onTouchesBegan: and friends to get the location of the interaction, and possibly hitTest: to allow other views below it to handle subsequent events. The next thing you will need to decide is how accurate you want to be - you can define a box that roughly matches the cube and test that for touches. Most people will want to touch it somewhere in the middle anyway. For accurate testing, you need the screen coordinates, and test each triangle in each polygon to see if it contains the location. Google turned up a nice explanation on the maths needed for that. In the OpenGL case, you'll have to manually repeat the calculations performed by OpenGL to find out where on screen your polygons have ended up.

UIGesture recognition on different areas of a UIImageView

I have this image:
What I want to do is to add a UITapGestureRecognizer to this image (or I can split the image in the different parts it consists of and add for each part a UITapGestureRecognizer) in order to have different actions according to the leaf tapped. If I split the image in different images each for each leaf the UIImageViews will probably overlap and tapping on one will be recognized as a tap on another one. Having just one image implies knowing the points of the screen that belongs to a leaf rather than to another one.
Any clues on how to do it would be really appreciated.
Thanks
Change your behavior by examining the gesture recognizer's locationInView:.
If you handle the image as one unit, implement this in your gesture recognizer call back to decide which "leaf" (if any) was tapped.
If you handle the image as multiple images, you could also implement it in your callback, or you could also implement in, e.g., your delegate's gestureRecognizerShouldBegin: to suppress events for touches outside the leaf as drawn.
EDIT: I didn't realize that you might also be looking for assistance on figuring out whether a point lies within a leaf. #PhillipMills is correct on this point: we need to know how you are drawing the image.
FOLLOW-UP: This is somewhat outside my area of expertise.
The easiest approach (from a hit-testing standpoint) is to do what #PhillipMills suggested, using Quartz drawing and CGPathContainsPoint(). If you have detailed graphics that you need rendered as a PNG, you could certainly construct a simple path that would be (virtually) overlayed to allow hit testing.
Your other options, AFAIK, are to do hit testing mathematically, but you would basically be reimplementing CGPathContainsPoint() but without a path, or to employ various tricks that look at the color of the pixels at your touch point to do hit testing. Googling will turn up some useful results if you go this route, but honestly for a shape as simple as what you've drawn, just use some UIBezierPath code to recreate in code.
Not sure if this will be helpful but if you get stuck on figuring out which leaf was clicked, you could use an old image map trick we used to use in CD-ROM projects for pixel accurate click tracking on images.
You have your full size image. Make a 25% (or less) scaled version of it. Fill each of the leaf regions you want to track clicks on with a different color; anything you want to ignore make black. When the full size image is clicked, get the x/y coordinates and scale them by the percentage of your scaled image. Then get the pixel color of the scaled image at the scaled x/y coordinate. By determining the pixel color you will know which leaf was clicked.
Sounds clunky but it works really well and is fast.
(all that said, I don't think alpha areas of images trigger the gesture recognizer - so breaking the image up would be less complicated/code intensive.)
If you can break the shape apart into the constituent elements, then you can put each into it's own layer and use the method discussed in this stackoverflow discussion to determine which was touched: Hit Testing with CALayer using the alpha properties of the CALayer contents

How to add overlays designed by user on button click in a map

I am interested in adding an option to my GIS Map application, the ability to draw Polygon, circle, polyroutes overlays for the user to search data within.The problem is that I've read and tested codes of how to draw an overlay, but they are always static.I want it to be dynamic, with dynamic center and points (or radius) set by the user on click.A mystery for me.(I'm a beginner in iPhone programming, this is my first app.)And I'm not using and don't want to use things like ArcGIS API for iPhone.I would appreciate any help.
To let the user "draw" an arbitrary polygon on the map, one approach is to use draggable annotations that represent the corners of the polygon. Provide an "Add Corner" button and some kind of Remove Corner button on each annotation.
See my answer to User creating a box on MKMapView for some more details. On that question though, the OP actually ended up using another solution described in the comments which would work well if the polygons are always rectangles.
For implementing a button in an annotation view (if you want a "Remove Corner" button on the annotations), see my answer to How to get click event from a button added over MKAnnotationView.
Once you a have a polygon or other overlay on the map, dragging it by direct touches may only be possible by adding a gesture recognizer to the map (with its own scrolling turned off) and using a custom MKOverlay and MKOverlayView that allow coordinate changes. Adding a gesture recognizer directly to an MKOverlayView doesn't seem to work and the built-in overlay classes don't allow changes to coordinates.
An alternative to moving by direct touches is putting some controls on the side (Up/Down/Left/Right/etc buttons) that modify the custom overlay.
The Apple sample app Breadcrumb gives an example of a custom overlay/view for a path. In WWDC 2010, the sample app LocationReminders gives an example of a custom overlay/view for a circle that can move and resize.
Finally, when you do a search for businesses, you could use the overlay's boundingMapRect (which is always a rectangle regardless of the overlay's shape) as the bounding box for the initial search and then check if the coordinate of each business found is in the overlay's actual shape using the answer to How to determine if an annotation is inside of MKPolygonView (iOS).

Moving a UIView along a CGPath according to touch position

I have a line graph I've drawn in Quartz, and a UIView 'bubble' that I'd like to ideally pop up when the user touches the single plot line, and moves their finger along it. The bubble displays some extra graph information.
I'd like to 'attach' the UIView to the CGPath plot, but I'm having trouble conceptually figuring out the best way to do this. I know you can animate a view along a CGPath, but this doesn't seem to work for me, because the user needs to 'scrub' along the graph themselves with their finger rather than any automatic animation.
Does anyone have any suggestions of a good approach?
Maybe you don't need to animate it. Touch events fly by pretty quickly -- maybe if you just move the view to the appropriate location relative to the touch without animation the move will be smooth enough. If that's not good enough, you'll have to animate along the graph segment from the current location of the view (see CALayer presentationLayer) to the desired location. The key is that you'll be animating every time you receive a touch event (and any previous animations would be cancelled).
Like Neil said, your best bet is to just move with the touch events, it will look smooth if all you're doing is moving a view. Use [aTouch locationInView:view] to get the touch's position, then find the closest point on the path (maybe use the x value and look up the y value on the path for the x).