Skip to content

Commit

Permalink
Livemap attribution (#199)
Browse files Browse the repository at this point in the history
Fix #191 Fix #193
  • Loading branch information
ISeleznev-HORIS committed Sep 11, 2020
1 parent 01c8489 commit 2d53d66
Show file tree
Hide file tree
Showing 12 changed files with 61 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ abstract class DemoModelBase(private val dimension: DoubleVector) {
// raster tiles without geocoding
tileSystemProvider = RasterTileSystemProvider("https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png")
geocodingService = Services.bogusGeocodingService()
attribution = "© wikimedia.org"

// vector tiles and geocoding
//tileSystemProvider = VectorTileSystemProvider(Services.devTileProvider())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class RasterTilesDemoModel(dimension: DoubleVector) : DemoModelBase(dimension) {
override fun createLiveMapSpec(): LiveMapBuilder {
return basicLiveMap {
tileSystemProvider = RasterTileSystemProvider("http:https://c.tile.stamen.com/toner/{z}/{x}/{y}@2x.png")
attribution = "© stamen.com"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import kotlin.random.Random
class LiveMap : PlotConfigDemoBase() {
fun plotSpecList(): List<Map<String, Any>> {
return listOf(
multiLayerTooltips()
// mapJoinBar()
multiLayerTooltips(),
mapJoinBar()
// antiMeridian()
// tooltips()
// symbol_point(),
Expand Down Expand Up @@ -53,7 +53,8 @@ class LiveMap : PlotConfigDemoBase() {
"tiles": {
"kind": "vector_lets_plot",
"url": "ws:https://10.0.0.127:3933",
"theme": null
"theme": "dark",
"attribution": "Map data © OpenStreetMap contributors"
}
},
{
Expand Down Expand Up @@ -100,7 +101,8 @@ class LiveMap : PlotConfigDemoBase() {
"display_mode": "pie",
"tiles": {
"kind": "raster_zxy",
"url": "https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}@2x.png"
"url": "https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}@2x.png",
"attribution": "© wikimedia.org"
},
"geocoding": {
"url": "http:https://10.0.0.127:3020"
Expand Down
11 changes: 9 additions & 2 deletions livemap/src/commonMain/kotlin/jetbrains/livemap/LiveMap.kt
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ class LiveMap(
private val myMapLocationConsumer: (DoubleRectangle) -> Unit,
private val myGeocodingService: GeocodingService,
private val myMapLocationRect: Async<Rect<World>>?,
private val myZoom: Int?
private val myZoom: Int?,
private val myAttribution: String?
) : Disposable {
private val myRenderTarget: RenderTarget = myDevParams.read(RENDER_TARGET)
private var myTimerReg = Registration.EMPTY
Expand Down Expand Up @@ -240,7 +241,13 @@ class LiveMap(
AnimationObjectSystem(componentManager),
AnimationSystem(componentManager),
ViewportUpdateSystem(componentManager),
LiveMapUiSystem(myUiService, componentManager, myMapLocationConsumer, myLayerManager),
LiveMapUiSystem(
myUiService,
componentManager,
myMapLocationConsumer,
myLayerManager,
myAttribution
),

CellStateUpdateSystem(componentManager),
TileRequestSystem(componentManager),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class LiveMapBuilder {

var mapLocationConsumer: (DoubleRectangle) -> Unit = { _ -> Unit }

var attribution: String? = null

var devParams: DevParams =
DevParams(HashMap<String, Any>())
Expand All @@ -83,6 +84,8 @@ class LiveMapBuilder {

devParams = devParams,

attribution = attribution,

// deprecated
isClustering = false,
isLabels = true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ class LiveMapFactory(
myMapProjection
)
),
myZoom = myLiveMapSpec.zoom
myZoom = myLiveMapSpec.zoom,
myAttribution = myLiveMapSpec.attribution
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ class LiveMapSpec(
val isLoopY: Boolean,
val mapLocationConsumer: (DoubleRectangle) -> Unit,
val tileSystemProvider: TileSystemProvider,
val attribution: String?,
val devParams: DevParams
)
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Label(override var origin: DoubleVector, private var text: Text) : RenderB
dimension = text.measureText(ctx) + DoubleVector(2 * padding, 2 * padding)

rectangle.apply {
rect = DoubleRectangle(DoubleVector.ZERO, dimension)
rect = DoubleRectangle(DoubleVector.ZERO, this@Label.dimension)
color = background
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ class LiveMapUiSystem(
private val myUiService: UiService,
componentManager: EcsComponentManager,
private val myMapLocationConsumer: (DoubleRectangle) -> Unit,
private val myLayerManager: LayerManager
private val myLayerManager: LayerManager,
private val myAttribution: String?
) : AbstractSystem<LiveMapContext>(componentManager) {
private lateinit var myLiveMapLocation: LiveMapLocation
private lateinit var myZoomPlus: MutableImage
Expand Down Expand Up @@ -93,20 +94,22 @@ class LiveMapUiSystem(
val buttonMakeGeometry = myUiService.addButton(myMakeGeometry)
addListenersToMakeGeometryButton(buttonMakeGeometry)

val osm = Text().apply {
color = Color.BLACK
fontFamily = CONTRIBUTORS_FONT_FAMILY
fontHeight = 11.0
text = listOf(LINK_TO_OSM_CONTRIBUTORS)
}
if (myAttribution != null) {
val attributionText = Text().apply {
color = Color.BLACK
fontFamily = CONTRIBUTORS_FONT_FAMILY
fontHeight = 11.0
text = listOf(myAttribution)
}

val contributors = Label(DoubleVector(myViewport.size.x, 0.0), osm).apply {
background = Color(200, 200, 200, 179)
this.padding = 2.0
position = Label.LabelPosition.LEFT
}
val attributionLabel = Label(DoubleVector(myViewport.size.x, 0.0), attributionText).apply {
background = Color(200, 200, 200, 179)
this.padding = 2.0
position = Label.LabelPosition.LEFT
}

myUiService.addRenderable(contributors)
myUiService.addRenderable(attributionLabel)
}
}

private fun addListenersToGetCenterButton(button: EcsEntity) {
Expand Down Expand Up @@ -278,7 +281,6 @@ class LiveMapUiSystem(
+ "XOCvF3bjfOJyAiRAAiRAv4wb94ohdcx3dRx6dEkcEiABEiAB+n9qCrfk+FVVdb5KCR4RwVrbnATv3tmq7CEBEiAB+vdA965tV16X1LabWFOow7bu8aSmIMe2ANUM9Mg36JuAiGgJAMYY"
+ "ZyGKoihfV4qZlwCQ57mTf8lai/1+X3rZgpIkCdvt9reyvSwIAif6fqy1OB6PyPP80l42HA6jZjYAlkrTdHZuN5u4QMHMSyJaGmM+R1GUA8B3Hdvtjp1TGh0AAAAASUVORK5CYII=")

private const val LINK_TO_OSM_CONTRIBUTORS = "Map data \u00a9 OpenStreetMap contributors"
private const val CONTRIBUTORS_FONT_FAMILY =
"-apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, " + "\"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ internal class LiveMapSpecBuilder {
myDevParams.isSet(DEBUG_TILES),
myDevParams.read(COMPUTATION_PROJECTION_QUANT)
),
attribution = myLiveMapOptions.tileProvider[Tile.ATTRIBUTION] as String?,
devParams = myDevParams
)
}
Expand All @@ -133,6 +134,7 @@ internal class LiveMapSpecBuilder {
const val KIND = "kind"
const val URL = "url"
const val THEME = "theme"
const val ATTRIBUTION = "attribution"

const val VECTOR_LETS_PLOT = "vector_lets_plot"
const val RASTER_ZXY = "raster_zxy"
Expand Down
14 changes: 9 additions & 5 deletions python-package/lets_plot/plot/geom_livemap_.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from .geom import _geom
from .util import is_geo_data_regions, map_join_regions
from .._global_settings import has_global_value, get_global_val
from ..settings_utils import MAPTILES_KIND, MAPTILES_URL, MAPTILES_THEME, GEOCODING_PROVIDER_URL, _RASTER_ZXY, _VECTOR_LETS_PLOT
from ..settings_utils import MAPTILES_KIND, MAPTILES_URL, MAPTILES_THEME, MAPTILES_ATTRIBUTION, GEOCODING_PROVIDER_URL, _RASTER_ZXY, _VECTOR_LETS_PLOT

try:
import pandas
Expand Down Expand Up @@ -128,7 +128,7 @@ def geom_livemap(mapping=None, data=None, symbol=None, show_legend=None, samplin
OPTIONS_MAPTILES_KIND = 'kind'
OPTIONS_MAPTILES_URL = 'url'
OPTIONS_MAPTILES_THEME = 'theme'

OPTIONS_MAPTILES_ATTRIBUTION = 'attribution'
OPTIONS_GEOCODING_PROVIDER_URL = 'url'


Expand Down Expand Up @@ -159,13 +159,15 @@ def _prepare_tiles(tiles: Union[str, dict]) -> Optional[dict]:
if tiles.get(MAPTILES_KIND, None) == _RASTER_ZXY:
return {
OPTIONS_MAPTILES_KIND: _RASTER_ZXY,
OPTIONS_MAPTILES_URL: tiles.get(MAPTILES_URL, None)
OPTIONS_MAPTILES_URL: tiles.get(MAPTILES_URL, None),
OPTIONS_MAPTILES_ATTRIBUTION: tiles.get(MAPTILES_ATTRIBUTION, None),
}
elif tiles.get(MAPTILES_KIND, None) == _VECTOR_LETS_PLOT:
return {
OPTIONS_MAPTILES_KIND: _VECTOR_LETS_PLOT,
OPTIONS_MAPTILES_URL: tiles.get(MAPTILES_URL, None),
OPTIONS_MAPTILES_THEME: tiles.get(MAPTILES_THEME, None),
OPTIONS_MAPTILES_ATTRIBUTION: tiles.get(MAPTILES_ATTRIBUTION, None),
}
else:
raise ValueError("Unsupported 'tiles' kind: " + tiles.get(MAPTILES_KIND, None))
Expand All @@ -177,14 +179,16 @@ def _prepare_tiles(tiles: Union[str, dict]) -> Optional[dict]:
if get_global_val(MAPTILES_KIND) == _RASTER_ZXY:
return {
OPTIONS_MAPTILES_KIND: _RASTER_ZXY,
OPTIONS_MAPTILES_URL: get_global_val(MAPTILES_URL)
OPTIONS_MAPTILES_URL: get_global_val(MAPTILES_URL),
OPTIONS_MAPTILES_ATTRIBUTION: get_global_val(MAPTILES_ATTRIBUTION) if has_global_value(MAPTILES_ATTRIBUTION) else None,
}

if get_global_val(MAPTILES_KIND) == _VECTOR_LETS_PLOT:
return {
OPTIONS_MAPTILES_KIND: _VECTOR_LETS_PLOT,
OPTIONS_MAPTILES_URL: get_global_val(MAPTILES_URL) if has_global_value(MAPTILES_URL) else None,
OPTIONS_MAPTILES_THEME: get_global_val(MAPTILES_THEME) if has_global_value(MAPTILES_THEME) else None
OPTIONS_MAPTILES_THEME: get_global_val(MAPTILES_THEME) if has_global_value(MAPTILES_THEME) else None,
OPTIONS_MAPTILES_ATTRIBUTION: get_global_val(MAPTILES_ATTRIBUTION) if has_global_value(MAPTILES_ATTRIBUTION) else None,
}

raise ValueError('Tile provider is not set.')
Expand Down
13 changes: 10 additions & 3 deletions python-package/lets_plot/settings_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
MAPTILES_KIND = 'maptiles_kind'
MAPTILES_URL = 'maptiles_url'
MAPTILES_THEME = 'maptiles_theme'
MAPTILES_ATTRIBUTION = 'maptiles_attribution'

GEOCODING_PROVIDER_URL = 'geocoding_url'


Expand All @@ -30,22 +32,27 @@ def maptiles_lets_plot(url: str, theme: str = None) -> dict:
return {
MAPTILES_KIND: _VECTOR_LETS_PLOT,
MAPTILES_URL: url,
MAPTILES_THEME: theme
MAPTILES_THEME: theme,
MAPTILES_ATTRIBUTION: 'Map data © OpenStreetMap contributors'
}


def maptiles_zxy(url: str) -> dict:
def maptiles_zxy(url: str, attribution: str = None) -> dict:
"""
:param url:
Template for a standard raster ZXY tile provider with {z}, {x} and {y} wildcards, e.g. 'http:https://my.tile.com/{z}/{x}/{y}.png'
:param attribution:
An attribution or a copyright notice to display on the map as required by the tile license.
:return:
Tile provider settings
"""
assert isinstance(url, (str, type(None))), "'url' argument is not str: {}".format(type(url))
assert isinstance(attribution, (str, type(None))), "'attribution' argument is not str: {}".format(type(url))

return {
MAPTILES_KIND: _RASTER_ZXY,
MAPTILES_URL: url
MAPTILES_URL: url,
MAPTILES_ATTRIBUTION: attribution
}

def geocoding_service(url: str):
Expand Down

0 comments on commit 2d53d66

Please sign in to comment.