Skip to content

Instantly share code, notes, and snippets.

@nzatsepilov
Created May 12, 2017 10:27
Show Gist options
  • Save nzatsepilov/d1ac1607ef21a778bd6cd13c6f5039f5 to your computer and use it in GitHub Desktop.
Save nzatsepilov/d1ac1607ef21a778bd6cd13c6f5039f5 to your computer and use it in GitHub Desktop.
NZRoute
+ (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