|
49 | 49 | return flattenedShapes;
|
50 | 50 | }
|
51 | 51 |
|
52 |
| -@interface MapDocument () <NSWindowDelegate, NSSharingServicePickerDelegate, NSMenuDelegate, NSSplitViewDelegate, MGLMapViewDelegate> |
| 52 | +@interface MapDocument () <NSWindowDelegate, NSSharingServicePickerDelegate, NSMenuDelegate, NSSplitViewDelegate, MGLMapViewDelegate, MGLComputedShapeSourceDataSource> |
53 | 53 |
|
54 | 54 | @property (weak) IBOutlet NSArrayController *styleLayersArrayController;
|
55 | 55 | @property (weak) IBOutlet NSTableView *styleLayersTableView;
|
@@ -639,6 +639,47 @@ - (IBAction)removeCustomStyleLayer:(id)sender {
|
639 | 639 | [self.mapView.style removeLayer:layer];
|
640 | 640 | }
|
641 | 641 |
|
| 642 | +- (IBAction)insertGraticuleLayer:(id)sender { |
| 643 | + [self.undoManager registerUndoWithTarget:self handler:^(id _Nonnull target) { |
| 644 | + [self removeGraticuleLayer:sender]; |
| 645 | + }]; |
| 646 | + |
| 647 | + if (!self.undoManager.isUndoing) { |
| 648 | + [self.undoManager setActionName:@"Add Graticule Layer"]; |
| 649 | + } |
| 650 | + |
| 651 | + MGLComputedShapeSource *source = [[MGLComputedShapeSource alloc] initWithIdentifier:@"graticule" |
| 652 | + options:@{MGLShapeSourceOptionMaximumZoomLevel:@14}]; |
| 653 | + source.dataSource = self; |
| 654 | + [self.mapView.style addSource:source]; |
| 655 | + MGLLineStyleLayer *lineLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"graticule.lines" |
| 656 | + source:source]; |
| 657 | + [self.mapView.style addLayer:lineLayer]; |
| 658 | + MGLSymbolStyleLayer *labelLayer = [[MGLSymbolStyleLayer alloc] initWithIdentifier:@"graticule.labels" |
| 659 | + source:source]; |
| 660 | + labelLayer.text = [MGLStyleValue valueWithRawValue:@"{value}"]; |
| 661 | + [self.mapView.style addLayer:labelLayer]; |
| 662 | +} |
| 663 | + |
| 664 | +- (IBAction)removeGraticuleLayer:(id)sender { |
| 665 | + [self.undoManager registerUndoWithTarget:self handler:^(id _Nonnull target) { |
| 666 | + [self insertGraticuleLayer:sender]; |
| 667 | + }]; |
| 668 | + |
| 669 | + if (!self.undoManager.isUndoing) { |
| 670 | + [self.undoManager setActionName:@"Delete Graticule Layer"]; |
| 671 | + } |
| 672 | + |
| 673 | + MGLStyleLayer *layer = [self.mapView.style layerWithIdentifier:@"graticule.lines"]; |
| 674 | + [self.mapView.style removeLayer:layer]; |
| 675 | + |
| 676 | + layer = [self.mapView.style layerWithIdentifier:@"graticule.labels"]; |
| 677 | + [self.mapView.style removeLayer:layer]; |
| 678 | + |
| 679 | + MGLSource *source = [self.mapView.style sourceWithIdentifier:@"graticule"]; |
| 680 | + [self.mapView.style removeSource:source]; |
| 681 | +} |
| 682 | + |
642 | 683 | #pragma mark Offline packs
|
643 | 684 |
|
644 | 685 | - (IBAction)addOfflinePack:(id)sender {
|
@@ -926,6 +967,9 @@ - (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
|
926 | 967 | if (menuItem.action == @selector(insertCustomStyleLayer:)) {
|
927 | 968 | return ![self.mapView.style layerWithIdentifier:@"mbx-custom"];
|
928 | 969 | }
|
| 970 | + if (menuItem.action == @selector(insertGraticuleLayer:)) { |
| 971 | + return ![self.mapView.style sourceWithIdentifier:@"graticule"]; |
| 972 | + } |
929 | 973 | if (menuItem.action == @selector(showAllAnnotations:) || menuItem.action == @selector(removeAllAnnotations:)) {
|
930 | 974 | return self.mapView.annotations.count > 0;
|
931 | 975 | }
|
@@ -1095,6 +1139,53 @@ - (CGFloat)mapView:(MGLMapView *)mapView alphaForShapeAnnotation:(MGLShape *)ann
|
1095 | 1139 | return 0.8;
|
1096 | 1140 | }
|
1097 | 1141 |
|
| 1142 | +#pragma mark - MGLComputedShapeSourceDataSource |
| 1143 | +- (NSArray<id <MGLFeature>>*)featuresInCoordinateBounds:(MGLCoordinateBounds)bounds zoomLevel:(NSUInteger)zoom { |
| 1144 | + double gridSpacing; |
| 1145 | + if(zoom >= 13) { |
| 1146 | + gridSpacing = 0.01; |
| 1147 | + } else if(zoom >= 11) { |
| 1148 | + gridSpacing = 0.05; |
| 1149 | + } else if(zoom == 10) { |
| 1150 | + gridSpacing = .1; |
| 1151 | + } else if(zoom == 9) { |
| 1152 | + gridSpacing = 0.25; |
| 1153 | + } else if(zoom == 8) { |
| 1154 | + gridSpacing = 0.5; |
| 1155 | + } else if (zoom >= 6) { |
| 1156 | + gridSpacing = 1; |
| 1157 | + } else if(zoom == 5) { |
| 1158 | + gridSpacing = 2; |
| 1159 | + } else if(zoom >= 4) { |
| 1160 | + gridSpacing = 5; |
| 1161 | + } else if(zoom == 2) { |
| 1162 | + gridSpacing = 10; |
| 1163 | + } else { |
| 1164 | + gridSpacing = 20; |
| 1165 | + } |
| 1166 | + |
| 1167 | + NSMutableArray <id <MGLFeature>> * features = [NSMutableArray array]; |
| 1168 | + CLLocationCoordinate2D coords[2]; |
| 1169 | + |
| 1170 | + for (double y = ceil(bounds.ne.latitude / gridSpacing) * gridSpacing; y >= floor(bounds.sw.latitude / gridSpacing) * gridSpacing; y -= gridSpacing) { |
| 1171 | + coords[0] = CLLocationCoordinate2DMake(y, bounds.sw.longitude); |
| 1172 | + coords[1] = CLLocationCoordinate2DMake(y, bounds.ne.longitude); |
| 1173 | + MGLPolylineFeature *feature = [MGLPolylineFeature polylineWithCoordinates:coords count:2]; |
| 1174 | + feature.attributes = @{@"value": @(y)}; |
| 1175 | + [features addObject:feature]; |
| 1176 | + } |
| 1177 | + |
| 1178 | + for (double x = floor(bounds.sw.longitude / gridSpacing) * gridSpacing; x <= ceil(bounds.ne.longitude / gridSpacing) * gridSpacing; x += gridSpacing) { |
| 1179 | + coords[0] = CLLocationCoordinate2DMake(bounds.sw.latitude, x); |
| 1180 | + coords[1] = CLLocationCoordinate2DMake(bounds.ne.latitude, x); |
| 1181 | + MGLPolylineFeature *feature = [MGLPolylineFeature polylineWithCoordinates:coords count:2]; |
| 1182 | + feature.attributes = @{@"value": @(x)}; |
| 1183 | + [features addObject:feature]; |
| 1184 | + } |
| 1185 | + |
| 1186 | + return features; |
| 1187 | +} |
| 1188 | + |
1098 | 1189 | @end
|
1099 | 1190 |
|
1100 | 1191 | @interface ValidatedToolbarItem : NSToolbarItem
|
|
0 commit comments