Created
May 12, 2017 10:27
-
-
Save nzatsepilov/d1ac1607ef21a778bd6cd13c6f5039f5 to your computer and use it in GitHub Desktop.
NZRoute
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
+ (instancetype)deserialize:(NSData *)data error:(NSError **)error { | |
if (data.length == 0) { | |
return nil; | |
} | |
NZRoute *route = [NZRoute new]; | |
route.data = [NSMutableData dataWithData:data]; | |
RouteHeader header; | |
NSUInteger headerSize = sizeof(header); | |
if (data.length < headerSize) { | |
*error = CreateError(@"Invalid data of header"); | |
return nil; | |
} | |
if ((data.length - headerSize) % headerSize > 0) { | |
*error = CreateError(@"Invalid data of points"); | |
return nil; | |
} | |
[data getBytes:&header length:headerSize]; | |
route.pointsCount = header.pointsCount; | |
route.pointsOffset = headerSize; | |
route.distance = [route calculateDistance]; | |
return route; | |
} | |
- (GeoPoint)pointAtIndex:(NSUInteger)index { | |
if (self.pointsCount == 0 || index > self.pointsCount - 1) { | |
return GeoPointMake(NAN, NAN, NAN); | |
} | |
GeoPoint point; | |
NSUInteger pointSize = sizeof(point); | |
NSUInteger start = self.pointsOffset + pointSize * index; | |
[self.data getBytes:&point range:NSMakeRange(start, pointSize)]; | |
return point; | |
} | |
- (NSData *)getDataForPointsInRange:(NSRange)range error:(NSError **)error { | |
if (range.length > self.pointsCount) { | |
*error = CreateError(@"Invalid range"); | |
return nil; | |
} | |
RouteHeader header = RouteHeaderDefault(); | |
header.pointsCount = (int)range.length; | |
NSMutableData *data = [NSMutableData dataWithBytes:&header length:sizeof(header)]; | |
for (NSUInteger i = range.location; i < range.location + range.length; ++i) { | |
GeoPoint point = [self pointAtIndex:i]; | |
[data appendBytes:&point length:sizeof(point)]; | |
} | |
return data; | |
} | |
- (BOOL)appendPoint:(GeoPoint)point { | |
if (!GeoPointIsValid(point)) { | |
return NO; | |
} | |
RouteHeader header; | |
NSUInteger headerSize = sizeof(header); | |
[self.data getBytes:&header length:headerSize]; | |
header.pointsCount++; | |
[self.data replaceBytesInRange:NSMakeRange(0, headerSize) withBytes:&header]; | |
[self.data appendBytes:&point length:sizeof(point)]; | |
if (self.pointsCount > 2) { | |
GeoPoint a = [self pointAtIndex:self.pointsCount - 2]; | |
GeoPoint b = [self pointAtIndex:self.pointsCount - 1]; | |
self.distance += GeoPointDistance(a, b); | |
} | |
self.pointsCount++; | |
return YES; | |
} | |
- (NSData *)serialize { | |
return self.data; | |
} | |
- (CLLocationDistance)calculateDistance { | |
if (self.pointsCount < 2) { | |
return 0; | |
} | |
CLLocationDistance distance = 0; | |
for (int i = 1; i < self.pointsCount; ++i) { | |
distance += GeoPointDistance([self pointAtIndex:i - 1], [self pointAtIndex:i]); | |
} | |
return distance; | |
} | |
#pragma mark - Private | |
- (void)commonInit { | |
self.data = [NSMutableData data]; | |
RouteHeader header = RouteHeaderDefault(); | |
NSUInteger headerSize = sizeof(header); | |
[self.data appendBytes:&header length:headerSize]; | |
self.pointsOffset = headerSize; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment