-1

I have been working on a polyline overlay and have been helped very well when I was stuck, I am hoping for some more assistance again.

In my project I am drawing polylines on a map from touches began to touches moved. the coordinates of where my finger is dragged is added to my array and displayed.

When I want to clear my lines i simply empty the array, this is fine

However, If i want to remove/undo the last line drawn. I was under the impression that I could just minus the last value from my array, but while thinking more deeply I realized that I may have a problem. Each element in the array is a coordinate where my finger last touched. I havent tried this yet, but I am imagining if I only minus the last value of the array, I am going to spend a long time "erasing" a line which I drew. I was looking for a method, by which when i press "Undo" it erases the entire line i drew. Even if that line extends from North America to England.

Sleep Paralysis
  • 449
  • 7
  • 22
  • What determines what a line is? Is it a simple element in an array, is it multiple elements in the array? If it's multiple elements, how do you define the element that starts of the line and the element that finishes off the line? – Pavan Dec 17 '14 at 03:21
  • @Pavan I dont believe i understand the question 100%. However, on touchhes began I add the coords into an array, this array is upated in touches moved and those coords I run my finger along is added to the array then drawn on the map – Sleep Paralysis Dec 17 '14 at 03:23
  • So question 1) Could a single line possibly have multiple coordinates? If the answer to question one is yes, then 2) Take the following action: a user pressing his finger down to begin drawing a line, swipes across the screen, and then lifts his finger up. Is this action classed them drawing a single line? – Pavan Dec 17 '14 at 03:24
  • 1) Yes it can. yes indeed – Sleep Paralysis Dec 17 '14 at 03:34
  • And the problem you're having is that when you try and remove the last element of your coordinates arrays, you're imagining that visually, it would only remove a portion of the line? aha :D It's nice that you have thought about it in advance; yes, that is what woud happen; it's a fun problem to solve; and luckily for you, its quite an easy fix. :) – Pavan Dec 17 '14 at 03:35
  • @Pavan easy fix? /Wipes sweat off forehead. but how will we know, what are the new coords added? add them to another array and compare? – Sleep Paralysis Dec 17 '14 at 03:41
  • Fear not, for I am here to help you out and hopefully be able to guide you in the right direction. ;) writing the answer right now. – Pavan Dec 17 '14 at 03:47

1 Answers1

0

The OP wishes to be able to undo the last line that was drawn. The problem he imagines is that removing a single element from the array would visually only remove a part of the line drawn by the user. What he wishes to do is to remove all the elements within the array that make up the line.

I haven't done a lot on drawing but my solution to your problem should work.

Do the following, create an enumerated data type that would create three possible states for each coordinate drawn to the screen/added to the array.

This data type would look something like this:

typedef NS_ENUM(NSInteger, PKLinePointState) {
    PKLinePointStart,
    PKLinePointMiddle,
    PKLinePointEnd
};

The idea here is that you will use this data type to determine which elements in your array are the starting points and which elements in your array are the ending points. This way you can make determine the lines in your array, and so therefor be able to determine how many elements to delete until you hit a coordinate that has status of PKLinePointStart.

You don't want to store just coordinates in your array, instead you want to store a data model which will hold more information so that you can do the sexy things you wish to accomplish.

The first data model will be used to store the start and ending coordinates and elements within the array. This will make it easier work with your coordinates. This is what it would look like:

LinePointModel.h

typedef NS_ENUM(NSInteger, PKLinePointState) {
        PKLinePointStart,
        PKLinePointMiddle,
        PKLinePointEnd
    };

@interface LinePointModel : NSObject

@property (assign) CGPoint linePointCoordinate; 
@property (assign) PKLinePointState linePointState; 
@end

//you may want to create a custom initialiser so that the coordinate and state are initialised straight away.
//It would look something like this -(instanceType)initWithLinePointCoordinate:(CGPoint)coordinate andLinePointState:(PKLinePointState)linePointstate;

LinePointModel.m

//I'll let you complete the initialiser method in the implementation file.

Now that you've created your data model that will store your coordinates properly in the coordinates array, here's how I would add them to the array.

The logic Phase 1:

When the user taps on a screen - the touchesBegan method gets called, you would want to create an instance of the LinePointModel and have its coordinate value set to the first coordinate the user taps on the screen and would set the state to PKLinePointStart which would mark the beginning of the line. Add this element to the array.

Then, when the user drags across the screen, you will receive multiple coordinates from the touchesMoved. Here you will create an instance of the same data model again setting the coordinate but this time the state will be stored as PKLinePointMiddle, we dont really care about these points, since we wont be checking against this state, but its still good to give it a value so that we know that any elements within the array that have this state only servers to form a point, points which eventually make a whole line. Here these instances will keep getting added to the array as many times as it needs until the user finally stops dragging - drawing the current line - on the screen.

Soon as the the touchesEnded method gets called - signifying the end of the line - the user lifting up his finger, this is where you create your last instance of the the data model, set the coordinate accordingly, and finally the state would be the PKLinePointEnd state. Again, you would add this instance of within the array too.

Now you have a meaningful custom array that keeps track of all the coordinates but lets you know which element has the starting state, midde and ending state.

Every starting state is coupled with the ending state with as many middle elements needed to make up the line.

If you want to stop here, you simply run the for loop, and determine the latest start and end elements added within your array. :)

The logic Phase 2 - Improving the algorithm:

Now you dont wan't to be looping through thousands of elements in an array just to determine how far in your array you have to go back to just to delete a line, that would be inefficient. This is where your second data model will be useful. This second data model will keep track of your lines and store which elements in your array make up its line by storing the start and end index or even better, store the array of the coordinates which is what we will do.

LineArrayModel.h

@interface LineArrayModel : NSObject

@property (nonatomic, retain) NSMutableArray *arrayOfLinePoints;  //What matters.
//@property (assign) int lineNumber; 
//@property (assign) CGFloat lineThickness;
//@property (strong, nonatomic) UIColor *lineColor;
@end

Using this data model, you would then create a temporary array whenever a user draws a line on the screen, and as soon as they are done drawing a line, you would grab the array and store it in an instance of LineArrayModel; and it's this instance that you would use to store in a new array called, myLinesArray. This is the array that you would then use to draw your lines on your screen.

Then to simply undo a line you just remove the last instance of LineArrayModel in the array that stores all your lines, and then simply redraw your lines if necessary.

Let me know how you get on.

Pavan
  • 17,840
  • 8
  • 59
  • 100
  • Check it out sleep paralysis :) – Pavan Dec 17 '14 at 04:28
  • Thanks, I was thinking along those lines myself :) – Sleep Paralysis Dec 17 '14 at 13:07
  • Were you really? From the sweat you were wiping off your forehead, it didn't seem to be the case ;) . Anyway, no problem. Goodluck. – Pavan Dec 18 '14 at 01:18
  • haha because , it seemed like (and it still looks like) alot to take in. :D – Sleep Paralysis Dec 18 '14 at 02:09
  • No problem. If you need any help, do let me know. I would however be interested in possibly getting a rough idea of what you're making. – Pavan Dec 18 '14 at 02:12
  • why not, however. Could it be possible we speak somewhere more private such as Skype or some other media? – Sleep Paralysis Dec 18 '14 at 05:02
  • Mr Pavan, could we rendezvous? I have implemented about 90% of what you suggested, however, i have trouble making use of PKLinePointState. – Sleep Paralysis Dec 23 '14 at 22:18
  • @SleepParalysis Take another look at the code I've written for the `LinePointModel.h` class file. I didn't format the code properly until now. The `PKLinePointState` variable is used to set each datapoint's `point state` so that you can later on figure out which datapoint is the `start`, `middle` datapoints, and `end`. You set each datapoint's point state through apple's touch methods mentioned in my answer. Once the user has let go of the screen, you can then group all the `start`, `middle`, and `end` objects - making one line - and store them in one `LineArrayModel` object for each line. – Pavan Dec 24 '14 at 02:33
  • -(void) initWithLinePointCoordinate:(CGPoint)coordinate andLinePointState:(PKLinePointState)linePointstate { if (handleTouch==YES) { [self.arrayOfLinePoints addObject:[NSValue valueWithCGPoint:coordinate]]; int where=linePointstate; } NSLog(@"%d",linePointstate); } – Sleep Paralysis Dec 24 '14 at 03:20
  • I am assigning the coords to the array,but i am not handingling the linepoint correctly – Sleep Paralysis Dec 24 '14 at 03:20
  • @SleepParalysis Hey, Happy new year. Just wondering, did you ever finish this project? – Pavan Jan 01 '16 at 16:17