@@ -157,6 +157,8 @@ object MapStyles {
157157 val QUIET_DARK = Quiet (" #172234" , " #0B1625" , " #172A24" , " #233049" , " #1E2A40" , " #2E3C57" , " #1C283B" , " #6C7B94" , " #46709A" )
158158
159159 /* * A quiet map for the train diagram: land, water, parks, faint roads and suburb names, so the lines stand out. */
160+ fun diagramJson (dark : Boolean ): String = diagram(dark)
161+
160162 private fun diagram (dark : Boolean ): String {
161163 val c = if (dark) QUIET_DARK else QUIET_LIGHT
162164 fun arr (vararg v : Any ) = JSONArray ().also { a -> v.forEach { a.put(it) } }
@@ -523,61 +525,76 @@ private fun byZoom(p: String) = Expression.interpolate(Expression.linear(), Expr
523525 */
524526private fun drawLayers (s : Style , lines : List <MapLine >, links : List <MapLine >, stops : List <MapStop >, basemap : Basemap , dark : Boolean ) {
525527 fun put (layer : Layer ) = if (s.getLayer(" crowd-dots" ) != null ) s.addLayerBelow(layer, " crowd-dots" ) else s.addLayer(layer)
526- val zoom = Expression .zoom()
527528 if (s.getSource(" akl-lines" ) == null ) {
528- val dg = basemap == Basemap .Diagram
529- val caseCol = when {
530- dg -> if (dark) MapStyles .QUIET_DARK .bg else MapStyles .QUIET_LIGHT .bg
531- basemap == Basemap .Streets && ! dark -> " #FFFFFF"
532- else -> " #0B1628"
533- }
534529 for (id in listOf (" akl-lines" , " akl-links" , " akl-stops" )) s.addSource(GeoJsonSource (id))
535- val round = arrayOf(PropertyFactory .lineCap(Property .LINE_CAP_ROUND ), PropertyFactory .lineJoin(Property .LINE_JOIN_ROUND ))
536- put(LineLayer (" akl-lines-case" , " akl-lines" ).withProperties(* round,
537- PropertyFactory .lineColor(Expression .switchCase(Expression .toBool(Expression .get(" z" )), Expression .color(android.graphics.Color .parseColor(caseCol)),
538- Expression .color(android.graphics.Color .parseColor(" #0B1628" )))),
539- PropertyFactory .lineOpacity(Expression .switchCase(Expression .toBool(Expression .get(" z" )), Expression .literal(if (dg) 1f else 0.8f ), Expression .literal(0.55f ))),
540- PropertyFactory .lineWidth(byZoom(" cw" )),
541- PropertyFactory .lineOffset(byZoom(" o" ))))
542- put(LineLayer (" akl-lines" , " akl-lines" ).withProperties(* round,
543- PropertyFactory .lineColor(Expression .toColor(Expression .get(" c" ))),
544- PropertyFactory .lineWidth(byZoom(" w" )),
545- PropertyFactory .lineOffset(byZoom(" o" ))))
546- put(LineLayer (" akl-links-case" , " akl-links" ).withProperties(* round,
547- PropertyFactory .lineColor(Expression .toColor(Expression .get(" c" ))),
548- PropertyFactory .lineWidth(Expression .interpolate(Expression .linear(), zoom,
549- Expression .stop(9 , 6f ), Expression .stop(12 , 11.4f ), Expression .stop(16 , 19f )))))
550- put(LineLayer (" akl-links" , " akl-links" ).withProperties(* round,
551- PropertyFactory .lineColor(Color .White .toArgb()),
552- PropertyFactory .lineWidth(Expression .interpolate(Expression .linear(), zoom,
553- Expression .stop(9 , 2.8f ), Expression .stop(12 , 6.2f ), Expression .stop(16 , 13.8f )))))
554- put(CircleLayer (" akl-stops" , " akl-stops" ).withProperties(
555- PropertyFactory .circleColor(Color .White .toArgb()),
556- PropertyFactory .circleStrokeColor(Expression .toColor(Expression .get(" c" ))),
557- PropertyFactory .circleRadius(byZoom(" rad" )),
558- PropertyFactory .circleStrokeWidth(Expression .interpolate(Expression .linear(), zoom,
559- Expression .stop(9 , num(" sw9" )), Expression .stop(13 , num(" sw13" ))))))
560- // names: the most important stations win the space, the rest appear as you zoom in
561- val darkLabels = basemap != Basemap .Satellite && dark
562- put(SymbolLayer (" akl-stop-labels" , " akl-stops" ).withProperties(
563- PropertyFactory .textField(Expression .step(zoom, Expression .toString(Expression .get(" l0" )),
564- Expression .stop(10.4 , Expression .toString(Expression .get(" l1" ))), Expression .stop(11 , Expression .toString(Expression .get(" label" ))))),
565- PropertyFactory .textFont(arrayOf(" Noto Sans Bold" )),
566- PropertyFactory .textSize(Expression .interpolate(Expression .linear(), zoom,
567- Expression .stop(10 , num(" ts10" )), Expression .stop(14 , num(" ts14" )))),
568- PropertyFactory .textVariableAnchor(arrayOf(Property .TEXT_ANCHOR_LEFT , Property .TEXT_ANCHOR_RIGHT , Property .TEXT_ANCHOR_TOP ,
569- Property .TEXT_ANCHOR_BOTTOM , Property .TEXT_ANCHOR_TOP_LEFT , Property .TEXT_ANCHOR_BOTTOM_RIGHT )),
570- PropertyFactory .textRadialOffset(0.95f ),
571- PropertyFactory .textJustify(Property .TEXT_JUSTIFY_AUTO ),
572- PropertyFactory .symbolSortKey(num(" rank" )),
573- PropertyFactory .textPadding(3f ),
574- PropertyFactory .textMaxWidth(9f ),
575- PropertyFactory .textColor(android.graphics.Color .parseColor(if (darkLabels) " #E6ECF5" else " #1A2744" )),
576- PropertyFactory .textHaloColor(if (darkLabels) android.graphics.Color .parseColor(if (dg) MapStyles .QUIET_DARK .bg else " #0B1628" )
577- else android.graphics.Color .argb(235 , 255 , 255 , 255 )),
578- PropertyFactory .textHaloWidth(2.2f )))
530+ aklLayers(basemap, dark).forEach { put(it) }
579531 }
580- s.getSourceAs<GeoJsonSource >(" akl-lines" )?.setGeoJson(FeatureCollection .fromFeatures(lines.map { l ->
532+ val (l, k, st) = aklData(lines, links, stops)
533+ s.getSourceAs<GeoJsonSource >(" akl-lines" )?.setGeoJson(l)
534+ s.getSourceAs<GeoJsonSource >(" akl-links" )?.setGeoJson(k)
535+ s.getSourceAs<GeoJsonSource >(" akl-stops" )?.setGeoJson(st)
536+ }
537+
538+ /* * The route lines, platform bars, stop dots and names as map layers, bottom to top, fed by akl-lines, akl-links and akl-stops. */
539+ internal fun aklLayers (basemap : Basemap , dark : Boolean ): List <Layer > {
540+ val out = ArrayList <Layer >()
541+ val zoom = Expression .zoom()
542+ val dg = basemap == Basemap .Diagram
543+ val caseCol = when {
544+ dg -> if (dark) MapStyles .QUIET_DARK .bg else MapStyles .QUIET_LIGHT .bg
545+ basemap == Basemap .Streets && ! dark -> " #FFFFFF"
546+ else -> " #0B1628"
547+ }
548+ val round = arrayOf(PropertyFactory .lineCap(Property .LINE_CAP_ROUND ), PropertyFactory .lineJoin(Property .LINE_JOIN_ROUND ))
549+ out + = LineLayer (" akl-lines-case" , " akl-lines" ).withProperties(* round,
550+ PropertyFactory .lineColor(Expression .switchCase(Expression .toBool(Expression .get(" z" )), Expression .color(android.graphics.Color .parseColor(caseCol)),
551+ Expression .color(android.graphics.Color .parseColor(" #0B1628" )))),
552+ PropertyFactory .lineOpacity(Expression .switchCase(Expression .toBool(Expression .get(" z" )), Expression .literal(if (dg) 1f else 0.8f ), Expression .literal(0.55f ))),
553+ PropertyFactory .lineWidth(byZoom(" cw" )),
554+ PropertyFactory .lineOffset(byZoom(" o" )))
555+ out + = LineLayer (" akl-lines" , " akl-lines" ).withProperties(* round,
556+ PropertyFactory .lineColor(Expression .toColor(Expression .get(" c" ))),
557+ PropertyFactory .lineWidth(byZoom(" w" )),
558+ PropertyFactory .lineOffset(byZoom(" o" )))
559+ out + = LineLayer (" akl-links-case" , " akl-links" ).withProperties(* round,
560+ PropertyFactory .lineColor(Expression .toColor(Expression .get(" c" ))),
561+ PropertyFactory .lineWidth(Expression .interpolate(Expression .linear(), zoom,
562+ Expression .stop(9 , 6f ), Expression .stop(12 , 11.4f ), Expression .stop(16 , 19f ))))
563+ out + = LineLayer (" akl-links" , " akl-links" ).withProperties(* round,
564+ PropertyFactory .lineColor(Color .White .toArgb()),
565+ PropertyFactory .lineWidth(Expression .interpolate(Expression .linear(), zoom,
566+ Expression .stop(9 , 2.8f ), Expression .stop(12 , 6.2f ), Expression .stop(16 , 13.8f ))))
567+ out + = CircleLayer (" akl-stops" , " akl-stops" ).withProperties(
568+ PropertyFactory .circleColor(Color .White .toArgb()),
569+ PropertyFactory .circleStrokeColor(Expression .toColor(Expression .get(" c" ))),
570+ PropertyFactory .circleRadius(byZoom(" rad" )),
571+ PropertyFactory .circleStrokeWidth(Expression .interpolate(Expression .linear(), zoom,
572+ Expression .stop(9 , num(" sw9" )), Expression .stop(13 , num(" sw13" )))))
573+ // names: the most important stations win the space, the rest appear as you zoom in
574+ val darkLabels = basemap != Basemap .Satellite && dark
575+ out + = SymbolLayer (" akl-stop-labels" , " akl-stops" ).withProperties(
576+ PropertyFactory .textField(Expression .step(zoom, Expression .toString(Expression .get(" l0" )),
577+ Expression .stop(10.4 , Expression .toString(Expression .get(" l1" ))), Expression .stop(11 , Expression .toString(Expression .get(" label" ))))),
578+ PropertyFactory .textFont(arrayOf(" Noto Sans Bold" )),
579+ PropertyFactory .textSize(Expression .interpolate(Expression .linear(), zoom,
580+ Expression .stop(10 , num(" ts10" )), Expression .stop(14 , num(" ts14" )))),
581+ PropertyFactory .textVariableAnchor(arrayOf(Property .TEXT_ANCHOR_LEFT , Property .TEXT_ANCHOR_RIGHT , Property .TEXT_ANCHOR_TOP ,
582+ Property .TEXT_ANCHOR_BOTTOM , Property .TEXT_ANCHOR_TOP_LEFT , Property .TEXT_ANCHOR_BOTTOM_RIGHT )),
583+ PropertyFactory .textRadialOffset(0.95f ),
584+ PropertyFactory .textJustify(Property .TEXT_JUSTIFY_AUTO ),
585+ PropertyFactory .symbolSortKey(num(" rank" )),
586+ PropertyFactory .textPadding(3f ),
587+ PropertyFactory .textMaxWidth(9f ),
588+ PropertyFactory .textColor(android.graphics.Color .parseColor(if (darkLabels) " #E6ECF5" else " #1A2744" )),
589+ PropertyFactory .textHaloColor(if (darkLabels) android.graphics.Color .parseColor(if (dg) MapStyles .QUIET_DARK .bg else " #0B1628" )
590+ else android.graphics.Color .argb(235 , 255 , 255 , 255 )),
591+ PropertyFactory .textHaloWidth(2.2f ))
592+ return out
593+ }
594+
595+ /* * The features for akl-lines, akl-links and akl-stops. */
596+ internal fun aklData (lines : List <MapLine >, links : List <MapLine >, stops : List <MapStop >): Triple <FeatureCollection , FeatureCollection , FeatureCollection > {
597+ val lineFc = FeatureCollection .fromFeatures(lines.map { l ->
581598 Feature .fromGeometry(MultiLineString .fromLngLats(l.parts.map { part -> part.map { Point .fromLngLat(it.second, it.first) } })).also { f ->
582599 val k9 = if (l.z) 0.6f else 1f
583600 val k16 = if (l.z) 1.9f else 1f
@@ -590,12 +607,12 @@ private fun drawLayers(s: Style, lines: List<MapLine>, links: List<MapLine>, sto
590607 f.addNumberProperty(" o$k " , l.offset * v)
591608 }
592609 }
593- }))
594- s.getSourceAs< GeoJsonSource >( " akl-links " )?.setGeoJson( FeatureCollection .fromFeatures(links.map { l ->
610+ })
611+ val linkFc = FeatureCollection .fromFeatures(links.map { l ->
595612 Feature .fromGeometry(MultiLineString .fromLngLats(l.parts.map { part -> part.map { Point .fromLngLat(it.second, it.first) } }))
596613 .also { it.addStringProperty(" c" , hex(l.color)) }
597- }))
598- s.getSourceAs< GeoJsonSource >( " akl-stops " )?.setGeoJson( FeatureCollection .fromFeatures(stops.map { st ->
614+ })
615+ val stopFc = FeatureCollection .fromFeatures(stops.map { st ->
599616 Feature .fromGeometry(Point .fromLngLat(st.lon, st.lat)).also { f ->
600617 val label = st.label ? : " "
601618 f.addStringProperty(" c" , hex(st.color))
@@ -611,7 +628,8 @@ private fun drawLayers(s: Style, lines: List<MapLine>, links: List<MapLine>, sto
611628 f.addNumberProperty(" ts10" , if (st.rank <= 0 ) 12f else 11f )
612629 f.addNumberProperty(" ts14" , if (st.rank <= 0 ) 14f else 12.5f )
613630 }
614- }))
631+ })
632+ return Triple (lineFc, linkFc, stopFc)
615633}
616634
617635/* * The crowd's source and layers: a dot per vehicle, a heading arrow, and the route once zoomed in. */
0 commit comments