#import "ExampleCustomDrawableStyleLayer.h" #import "MLNCustomDrawableStyleLayer.h" #import "MLNStyleLayer.h" #import #include #include #include #include #include #include #include @interface MLNCustomDrawableStyleLayer (Internal) - (instancetype)initWithPendingLayer:(std::unique_ptr)pendingLayer; @end class ExampleCustomDrawableStyleLayerHost; @implementation ExampleCustomDrawableStyleLayer - (instancetype)initWithIdentifier:(NSString *)identifier { auto layer = std::make_unique( identifier.UTF8String, std::make_unique(self)); return self = [super initWithPendingLayer:std::move(layer)]; } @end class ExampleCustomDrawableStyleLayerHost : public mbgl::style::CustomDrawableLayerHost { public: ExampleCustomDrawableStyleLayerHost(ExampleCustomDrawableStyleLayer *styleLayer) { layerRef = styleLayer; layer = nil; } void initialize() override { if (layerRef == nil) return; else if (layer == nil) layer = layerRef; } void update(Interface &interface) override { // if we have built our drawable(s) already, either update or skip if (interface.getDrawableCount()) return; constexpr float extent = mbgl::util::EXTENT; // add classic polylines { using namespace mbgl; // set tile interface.setTileID({11, 327, 792}); constexpr auto numLines = 6; Interface::LineOptions options[numLines]{ {/*geometry=*/{}, /*blur=*/0.0f, /*opacity=*/1.0f, /*gapWidth=*/0.0f, /*offset=*/0.0f, /*width=*/8.0f, /*color=*/Color::red()}, {/*geometry=*/{}, /*blur=*/4.0f, /*opacity=*/1.0f, /*gapWidth=*/2.0f, /*offset=*/-1.0f, /*width=*/4.0f, /*color=*/Color::blue()}, {/*geometry=*/{}, /*blur=*/16.0f, /*opacity=*/1.0f, /*gapWidth=*/1.0f, /*offset=*/2.0f, /*width=*/16.0f, /*color=*/Color(1.f, 0.5f, 0, 0.5f)}, {/*geometry=*/{}, /*blur=*/2.0f, /*opacity=*/1.0f, /*gapWidth=*/1.0f, /*offset=*/-2.0f, /*width=*/2.0f, /*color=*/Color(1.f, 1.f, 0, 0.3f)}, {/*geometry=*/{}, /*blur=*/0.5f, /*opacity=*/0.5f, /*gapWidth=*/1.0f, /*offset=*/0.5f, /*width=*/0.5f, /*color=*/Color::black()}, {/*geometry=*/{}, /*blur=*/24.0f, /*opacity=*/0.5f, /*gapWidth=*/1.0f, /*offset=*/-5.0f, /*width=*/24.0f, /*color=*/Color(1.f, 0, 1.f, 0.2f)}, }; for (auto &opt : options) { opt.geometry.beginCap = style::LineCapType::Butt; opt.geometry.endCap = style::LineCapType::Butt; opt.geometry.joinType = style::LineJoinType::Miter; } constexpr auto numPoints = 10; GeometryCoordinates polyline; for (auto ipoint{0}; ipoint < numPoints; ++ipoint) { polyline.emplace_back(ipoint * extent / numPoints, std::sin(ipoint * 2 * M_PI / numPoints) * extent / numLines / 2.f); } for (auto index{0}; index < numLines; ++index) { for (auto &p : polyline) { p.y += extent / numLines; } // set property values interface.setLineOptions(options[index]); // add polyline interface.addPolyline(polyline, Interface::LineShaderType::Classic); } } // add wide vector polylines with tile coordinates { using namespace mbgl; // set tile interface.setTileID({11, 327, 792}); constexpr auto numLines = 6; Interface::LineOptions options[numLines]{ {/*geometry=*/{}, /*blur=*/0.0f, /*opacity=*/1.0f, /*gapWidth=*/0.0f, /*offset=*/0.0f, /*width=*/8.0f, /*color=*/Color::red()}, {/*geometry=*/{}, /*blur=*/4.0f, /*opacity=*/1.0f, /*gapWidth=*/2.0f, /*offset=*/-1.0f, /*width=*/4.0f, /*color=*/Color::blue()}, {/*geometry=*/{}, /*blur=*/16.0f, /*opacity=*/1.0f, /*gapWidth=*/1.0f, /*offset=*/2.0f, /*width=*/16.0f, /*color=*/Color(1.f, 0.5f, 0, 0.5f)}, {/*geometry=*/{}, /*blur=*/2.0f, /*opacity=*/1.0f, /*gapWidth=*/1.0f, /*offset=*/-2.0f, /*width=*/2.0f, /*color=*/Color(1.f, 1.f, 0, 0.3f)}, {/*geometry=*/{}, /*blur=*/0.5f, /*opacity=*/0.5f, /*gapWidth=*/1.0f, /*offset=*/0.5f, /*width=*/0.5f, /*color=*/Color::black()}, {/*geometry=*/{}, /*blur=*/24.0f, /*opacity=*/0.5f, /*gapWidth=*/1.0f, /*offset=*/-5.0f, /*width=*/24.0f, /*color=*/Color(1.f, 0, 1.f, 0.2f)}, }; for (auto &opt : options) { opt.geometry.beginCap = style::LineCapType::Butt; opt.geometry.endCap = style::LineCapType::Butt; opt.geometry.joinType = style::LineJoinType::Miter; } constexpr auto numPoints = 10; GeometryCoordinates polyline; for (auto ipoint{0}; ipoint < numPoints; ++ipoint) { polyline.emplace_back(ipoint * extent / numPoints, std::sin(ipoint * 2 * M_PI / numPoints) * extent / numLines / 2.f); } for (auto index{0}; index < numLines; ++index) { for (auto &p : polyline) { if (0 == index) p.y += 0.25f * extent / numLines; p.y += extent / numLines; } // set property values interface.setLineOptions(options[index]); // add polyline interface.addPolyline(polyline, Interface::LineShaderType::WideVector); // add clone for (auto &p : polyline) { p.y += 0.05f * extent / numLines; } interface.addPolyline(polyline, Interface::LineShaderType::WideVector); for (auto &p : polyline) { p.y -= 0.05f * extent / numLines; } } } // add fill polygon { using namespace mbgl; // set tile interface.setTileID({11, 327, 790}); GeometryCollection geometry{ { // ring 1 {static_cast(extent * 0.1f), static_cast(extent * 0.2f)}, {static_cast(extent * 0.5f), static_cast(extent * 0.5f)}, {static_cast(extent * 0.7f), static_cast(extent * 0.5f)}, {static_cast(extent * 0.5f), static_cast(extent * 1.0f)}, {static_cast(extent * 0.0f), static_cast(extent * 0.5f)}, {static_cast(extent * 0.1f), static_cast(extent * 0.2f)}, }, { // ring 2 {static_cast(extent * 0.1f), static_cast(extent * 0.25f)}, {static_cast(extent * 0.15f), static_cast(extent * 0.5f)}, {static_cast(extent * 0.25f), static_cast(extent * 0.45f)}, {static_cast(extent * 0.1f), static_cast(extent * 0.25f)}, }, }; // set properties interface.setFillOptions({/*color=*/Color::green(), /*opacity=*/0.5f}); // add fill interface.addFill(geometry); } // add symbol { using namespace mbgl; // set tile interface.setTileID({11, 327, 789}); GeometryCoordinate position{static_cast(extent * 0.5f), static_cast(extent * 0.5f)}; // load image UIImage *assetImage = [UIImage imageNamed:@"pin"]; assert(assetImage.CGImage != NULL); std::shared_ptr image = std::make_shared( MLNPremultipliedImageFromCGImage(assetImage.CGImage)); // set symbol options Interface::SymbolOptions options; options.texture = interface.context.createTexture2D(); options.texture->setImage(image); options.texture->setSamplerConfiguration({gfx::TextureFilterType::Linear, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp}); const std::array, 2> textureCoordinates = { {{0.0f, 0.08f}, {1.0f, 0.9f}}}; const float xspan = textureCoordinates[1][0] - textureCoordinates[0][0]; const float yspan = textureCoordinates[1][1] - textureCoordinates[0][1]; assert(xspan > 0.0f && yspan > 0.0f); options.size = {static_cast(image->size.width * xspan), static_cast(image->size.height * yspan)}; options.anchor = {0.5f, 0.95f}; options.angleDegrees = 45.0f; options.scaleWithMap = true; options.pitchWithMap = false; interface.setSymbolOptions(options); // add symbol interface.addSymbol(position, textureCoordinates); } // add polylines using wide vectors using geographic coordinates { using namespace mbgl; // add polyline with geographic coordinates Interface::LineOptions options = {/*geometry=*/{}, /*blur=*/0.0f, /*opacity=*/1.0f, /*gapWidth=*/0.0f, /*offset=*/0.0f, /*width=*/12.0f, /*color=*/{.0f, .0f, .0f, .5f}}; options.geometry.beginCap = style::LineCapType::Square; options.geometry.endCap = style::LineCapType::Square; options.geometry.joinType = style::LineJoinType::Bevel; options.geometry.type = FeatureType::LineString; interface.setLineOptions(options); LineString polyline_geo{ // San Francisco {-122.38186800073211, 37.77466003457463}, {-122.3869373450997, 37.774352128895615}, {-122.38680767979824, 37.773294612880306}, {-122.38476465260224, 37.773350946288765}, {-122.38146223043374, 37.77194168964067}, {-122.6813560305925, 37.666084247570964}, {-122.26765538866474, 37.65037232584494}, {-122.42528413673159, 38.020443518012584}, // Seattle {-122.34927775216809, 47.62050663596438}, // New York {-74.04454331829972, 40.6892168305434}, }; interface.addPolyline(polyline_geo, Interface::LineShaderType::WideVector); } // add polylines using wide vectors in tile coordinates { using namespace mbgl; // set tile interface.setTileID({11, 327, 790}); Interface::LineOptions options{/*geometry=*/{}, /*blur=*/0.0f, /*opacity=*/1.0f, /*gapWidth=*/0.0f, /*offset=*/0.0f, /*width=*/7.0f, /*color=*/{1.0f, 0, 0, .5f}}; options.geometry.beginCap = style::LineCapType::Round; options.geometry.endCap = style::LineCapType::Round; options.geometry.joinType = style::LineJoinType::Round; // add polyline with tile coordinates GeometryCollection polyline_tile{ { // ring 1 {static_cast(extent * 0.1f), static_cast(extent * 0.2f)}, {static_cast(extent * 0.5f), static_cast(extent * 0.5f)}, {static_cast(extent * 0.7f), static_cast(extent * 0.5f)}, {static_cast(extent * 0.5f), static_cast(extent * 1.0f)}, {static_cast(extent * 0.0f), static_cast(extent * 0.5f)}, }, { // ring 2 {static_cast(extent * 0.1f), static_cast(extent * 0.25f)}, {static_cast(extent * 0.15f), static_cast(extent * 0.5f)}, {static_cast(extent * 0.25f), static_cast(extent * 0.45f)}, }, }; options.geometry.type = FeatureType::Polygon; interface.setLineOptions(options); interface.addPolyline(polyline_tile[0], Interface::LineShaderType::WideVector); interface.addPolyline(polyline_tile[1], Interface::LineShaderType::WideVector); } // finish interface.finish(); } void deinitialize() override { if (layer == nil) return; layerRef = layer; layer = nil; } private: __weak ExampleCustomDrawableStyleLayer *layerRef; ExampleCustomDrawableStyleLayer *layer = nil; };