使用NSPredicate在Mapbox中过滤MGLFeature $ id MGLFillExtrusionStyleLayer

时间:2018-02-11 18:41:54

标签: ios mapbox

我正在使用Mapbox的iOS SDK。我有2个MGLFillExtrusionStyleLayer图层显示iOS示例项目中提供的挤压建筑物。设置之后(didFinishLoadingStyle :)我正在尝试更新第二层的样式,以红色显示中心点周围的建筑物。我正在使用[mapview visibleFeaturesInRect:inStyleLayersWithIdentifiers:]来检索围绕mapview中心点的20x20 CGRect中的MGLFeature。作为检查,我将MGLFeature的数组传递给[mapview addAnnotations:]。然后我创建一个NSPredicate来过滤这些MGLFeatures对该层的$ id。例如,我的谓词形式为:$ id IN {27,19,16,16,15,15,15}。 (你会注意到一些标识符在MGLFeature的返回数组中重复。)然后我将这个谓词分配给我的层:layer.predicate = newPredicate。

Red buildings should be the same as the blue annotations.

如果查看附带的屏幕截图,您会看到mapview中心点下方的蓝色注释表明MGLFeature的数组是正确的。但是,我的图层不仅仅是红色的直接建筑着色。

我在其中过滤图层的代码段(在迭代图层数组的循环内):

    // get fill extrusion layer
    MGLFillExtrusionStyleLayer *layer = (MGLFillExtrusionStyleLayer*)[_buildingLayers objectAtIndex:i];

    // we are in a loop so get the correct layer id
    NSSet *set = [NSSet setWithObject:[NSString stringWithFormat:@"3d-buildings-%d", i]];

    // return features in a 20x20 CGRect around center point of mapview
    NSArray *features = [_mapView visibleFeaturesInRect:boundingBox inStyleLayersWithIdentifiers:set];

    // sanity check that MGLFeature's array is correct.
    // shows in Blue on screenshot
    [_mapView addAnnotations:features];

    // create string filter of MGLFeature $id's: $id IN {1,2,3,4 ...}
    if ([features count] > 0) {
        NSMutableString *filter = [NSMutableString stringWithString:@"%K IN "];
        for (int j = 0; j < [features count]; j++) {
            MGLPolygonFeature *feature = [features objectAtIndex:j];
            NSLog(@"[%@] %@", feature.identifier, [feature valueForKey:@"attributes"]);
            if (j == 0) {
                [filter appendString:[NSString stringWithFormat:@"{%@", feature.identifier]];
            } else {
                [filter appendString:[NSString stringWithFormat:@", %@", feature.identifier]];
            }
        }

        // filter string now of form: %K IN {27, 19, 16, 16, 15, 15, 15}
        [filter appendString:@"}"];

        // change buildings to red 
        // (underlying layer has same buildings in gray)
        layer.fillExtrusionColor = [MGLStyleValue valueWithRawValue:[UIColor redColor]];

        // substitute $id for %K
        NSPredicate *pred = [NSPredicate predicateWithFormat:filter argumentArray:[NSArray arrayWithObject:@"$id"]];

        // log.. now predicate is of form (example): $id IN {27, 19, 16, 16, 15, 15, 15}
        NSLog(@"pred: %@", pred);

        // assign to layer
        layer.predicate = pred;
    }

我的直接问题:MGLFeature $ id不是唯一的吗?我是否错误地使用了谓词和图层?

谢谢!

1 个答案:

答案 0 :(得分:1)

我能够直接从Mapbox获得回复。对于我的第二个问题,我确实正确地使用谓词和图层,但是,对于我的第一个问题,“MGLFeature $ id不是唯一的吗?”事实证明它们不是唯一的。请参阅下面的Mapbox的回复......

  

功能ID不是唯一的,因为我们的建筑物源数据不包含与OpenStreetMap相同的唯一标识符,以使我们的矢量图块更具性能。您看到的重复要素ID可能来自跨越多个向量图块的要素。如果您想突出显示各个建筑物,则需要添加包含具有唯一标识符的建筑物的自定义数据。我们在此处的一个较早的示例中显示了这一点:https://blog.mapbox.com/visualizing-an-entire-citys-buildings-live-with-runtime-styling-453fe7e39ae6

对于那些感兴趣的人,我确实设法创建了一个解决方法,我创建了一个新的MGLShapeSource,其中返回的MGLFeature数组在20x20 CGRect中检索。我将这个新的源添加到我的地图的MLGStyle中,然后使用该MGLShapeShource创建并添加一个全新的MGLFillExtrusionStyleLayer到地图。我将新图层的fillExtrusionColor设置为红色,以在视觉上区分其余图层上找到的建筑物。效果很好。

<强>段:

MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"filteredSource" features:MyArrayOfMGLFeatures options:nil];
[_mapView.style addSource:source];
MGLFillExtrusionStyleLayer *layer = [[MGLFillExtrusionStyleLayer alloc] initWithIdentifier:@"redBuildings" source:source]; 
layer.fillExtrusionColor = [MGLStyleValue valueWithRawValue:[UIColor redColor];
[_mapView.style addLayer:layer];