Commit 43370abfea7cd24e86ea747adf23c021031c24dc

Authored by lsagona
1 parent 53f01ecc34
Exists in master and in 1 other branch dev

clear map canvas when importing new data set

Showing 2 changed files with 7 additions and 3 deletions Inline Diff

src/main/kotlin/map/CircleMarkerGenerator.kt View file @ 43370ab
package map 1 1 package map
2 2
import application.model.observableMessages 3 3 import application.model.observableMessages
4 4
fun clearMap(map: LeafletMapView) { 5 5 fun clearMapCanvas(map: LeafletMapView) {
map.clearAllLayer() 6 6 map.execScript("""
7 |myRenderer.removeFrom(myMap)
8 |var myRenderer = L.canvas({ padding: 0.5 });
9 """.trimMargin())
} 7 10 }
8 11
fun displayMessageOnMap(map: LeafletMapView) { 9 12 fun displayMessageOnMap(map: LeafletMapView) {
13 clearMapCanvas(map)
observableMessages.vessels.forEach { (_, value) -> 10 14 observableMessages.vessels.forEach { (_, value) ->
value.messages.forEach { (_, message) -> 11 15 value.messages.forEach { (_, message) ->
map.execScript("L.circleMarker([${message.latitude}, ${message.longitude}], {renderer: myRenderer, radius: 0.01}).addTo(myMap)") 12 16 map.execScript("L.circleMarker([${message.latitude}, ${message.longitude}], {renderer: myRenderer, radius: 0.01}).addTo(myMap)")
} 13 17 }
} 14 18 }
src/main/kotlin/map/LeafletMapView.kt View file @ 43370ab
package map 1 1 package map
2 2
import javafx.concurrent.Worker 3 3 import javafx.concurrent.Worker
import javafx.scene.layout.StackPane 4 4 import javafx.scene.layout.StackPane
import javafx.scene.paint.Color 5 5 import javafx.scene.paint.Color
import javafx.scene.shape.Polygon 6 6 import javafx.scene.shape.Polygon
import javafx.scene.web.WebEngine 7 7 import javafx.scene.web.WebEngine
import javafx.scene.web.WebView 8 8 import javafx.scene.web.WebView
import map.events.* 9 9 import map.events.*
import netscape.javascript.JSObject 10 10 import netscape.javascript.JSObject
import java.io.ByteArrayOutputStream 11 11 import java.io.ByteArrayOutputStream
import java.io.File 12 12 import java.io.File
import java.io.IOException 13 13 import java.io.IOException
import java.net.URL 14 14 import java.net.URL
import java.util.* 15 15 import java.util.*
import java.util.concurrent.CompletableFuture 16 16 import java.util.concurrent.CompletableFuture
import javax.imageio.ImageIO 17 17 import javax.imageio.ImageIO
18 18
19 19
/** 20 20 /**
* JavaFX component for displaying OpenStreetMap based maps by using the Leaflet.js JavaScript library inside a WebView 21 21 * JavaFX component for displaying OpenStreetMap based maps by using the Leaflet.js JavaScript library inside a WebView
* browser component.<br/> 22 22 * browser component.<br/>
* This component can be embedded most easily by placing it inside a StackPane, the component uses then the size of the 23 23 * This component can be embedded most easily by placing it inside a StackPane, the component uses then the size of the
* parent automatically. 24 24 * parent automatically.
* 25 25 *
* @author Stefan Saring 26 26 * @author Stefan Saring
* @author Niklas Kellner 27 27 * @author Niklas Kellner
*/ 28 28 */
class LeafletMapView : StackPane() { 29 29 class LeafletMapView : StackPane() {
30 30
private val webView = WebView() 31 31 private val webView = WebView()
private val webEngine: WebEngine = webView.engine 32 32 private val webEngine: WebEngine = webView.engine
33 33
private var varNameSuffix: Int = 1 34 34 private var varNameSuffix: Int = 1
private val mapClickEvent = MapClickEventMaker() 35 35 private val mapClickEvent = MapClickEventMaker()
private val markerClickEvent = MarkerClickEventMaker() 36 36 private val markerClickEvent = MarkerClickEventMaker()
private val mapMoveEvent = MapMoveEventMaker() 37 37 private val mapMoveEvent = MapMoveEventMaker()
internal val zoomLimitSmallMarker = 8 38 38 internal val zoomLimitSmallMarker = 8
39 39
/** 40 40 /**
* Creates the LeafletMapView component, it does not show any map yet. 41 41 * Creates the LeafletMapView component, it does not show any map yet.
*/ 42 42 */
init { 43 43 init {
this.children.add(webView) 44 44 this.children.add(webView)
} 45 45 }
46 46
/** 47 47 /**
* Displays the initial map in the web view. Needs to be called and complete before adding any markers or tracks. 48 48 * Displays the initial map in the web view. Needs to be called and complete before adding any markers or tracks.
* The returned CompletableFuture will provide the final map load state, the map can be used when the load has 49 49 * The returned CompletableFuture will provide the final map load state, the map can be used when the load has
* completed with state SUCCEEDED (use CompletableFuture#whenComplete() for waiting to complete). 50 50 * completed with state SUCCEEDED (use CompletableFuture#whenComplete() for waiting to complete).
* 51 51 *
* @param mapConfig configuration of the map layers and controls 52 52 * @param mapConfig configuration of the map layers and controls
* @return the CompletableFuture which will provide the final map load state 53 53 * @return the CompletableFuture which will provide the final map load state
*/ 54 54 */
fun displayMap(mapConfig: MapConfig): CompletableFuture<Worker.State> { 55 55 fun displayMap(mapConfig: MapConfig): CompletableFuture<Worker.State> {
val finalMapLoadState = CompletableFuture<Worker.State>() 56 56 val finalMapLoadState = CompletableFuture<Worker.State>()
57 57
webEngine.loadWorker.stateProperty().addListener { _, _, newValue -> 58 58 webEngine.loadWorker.stateProperty().addListener { _, _, newValue ->
59 59
if (newValue == Worker.State.SUCCEEDED) { 60 60 if (newValue == Worker.State.SUCCEEDED) {
executeMapSetupScripts(mapConfig) 61 61 executeMapSetupScripts(mapConfig)
} 62 62 }
63 63
if (newValue == Worker.State.SUCCEEDED || newValue == Worker.State.FAILED) { 64 64 if (newValue == Worker.State.SUCCEEDED || newValue == Worker.State.FAILED) {
finalMapLoadState.complete(newValue) 65 65 finalMapLoadState.complete(newValue)
} 66 66 }
} 67 67 }
68 68
val localFileUrl: URL = LeafletMapView::class.java.getResource("/leafletmap/leafletmap.html") 69 69 val localFileUrl: URL = LeafletMapView::class.java.getResource("/leafletmap/leafletmap.html")
webEngine.load(localFileUrl.toExternalForm()) 70 70 webEngine.load(localFileUrl.toExternalForm())
return finalMapLoadState 71 71 return finalMapLoadState
} 72 72 }
73 73
private fun executeMapSetupScripts(mapConfig: MapConfig) { 74 74 private fun executeMapSetupScripts(mapConfig: MapConfig) {
75 75
// execute scripts for layer definition 76 76 // execute scripts for layer definition
mapConfig.layers.forEachIndexed { i, layer -> 77 77 mapConfig.layers.forEachIndexed { i, layer ->
execScript("var layer${i + 1} = ${layer.javaScriptCode};") 78 78 execScript("var layer${i + 1} = ${layer.javaScriptCode};")
} 79 79 }
80 80
val jsLayers = mapConfig.layers 81 81 val jsLayers = mapConfig.layers
.mapIndexed { i, layer -> "'${layer.displayName}': layer${i + 1}" } 82 82 .mapIndexed { i, layer -> "'${layer.displayName}': layer${i + 1}" }
.joinToString(", ") 83 83 .joinToString(", ")
execScript("var baseMaps = { $jsLayers };") 84 84 execScript("var baseMaps = { $jsLayers };")
85 85
// execute script for map view creation (Leaflet attribution must not be a clickable link) 86 86 // execute script for map view creation (Leaflet attribution must not be a clickable link)
execScript( 87 87 execScript(
""" 88 88 """
|var myMap = L.map('map', { 89 89 |var myMap = L.map('map', {
| center: new L.LatLng(${mapConfig.initialCenter.latitude}, ${mapConfig.initialCenter.longitude}), 90 90 | center: new L.LatLng(${mapConfig.initialCenter.latitude}, ${mapConfig.initialCenter.longitude}),
| zoom: 5, 91 91 | zoom: 5,
| zoomControl: false, 92 92 | zoomControl: false,
| layers: [layer1] 93 93 | layers: [layer1]
|}); 94 94 |});
|L.control.scale().addTo(mymap); 95 95 |L.control.scale().addTo(myMap);
|var myRenderer = L.canvas({ padding: 0.5 });""".trimMargin() 96 96 |var myRenderer = L.canvas({ padding: 0.5 });""".trimMargin()
) 97 97 )
98 98
// eventZoomChangeIcon() 99 99 // eventZoomChangeIcon()
100 100
// execute script for layer control definition if there are multiple layers 101 101 // execute script for layer control definition if there are multiple layers
if (mapConfig.layers.size > 1) { 102 102 if (mapConfig.layers.size > 1) {
execScript( 103 103 execScript(
""" 104 104 """
|var overlayMaps = {}; 105 105 |var overlayMaps = {};
|L.control.layers(baseMaps, overlayMaps).addTo(myMap);""".trimMargin() 106 106 |L.control.layers(baseMaps, overlayMaps).addTo(myMap);""".trimMargin()
) 107 107 )
108 108
} 109 109 }
110 110
// execute script for scale control definition 111 111 // execute script for scale control definition
if (mapConfig.scaleControlConfig.show) { 112 112 if (mapConfig.scaleControlConfig.show) {
execScript( 113 113 execScript(
"L.control.scale({position: '${mapConfig.scaleControlConfig.position.positionName}', " + 114 114 "L.control.scale({position: '${mapConfig.scaleControlConfig.position.positionName}', " +
"metric: ${mapConfig.scaleControlConfig.metric}, " + 115 115 "metric: ${mapConfig.scaleControlConfig.metric}, " +
"imperial: ${!mapConfig.scaleControlConfig.metric}})" + 116 116 "imperial: ${!mapConfig.scaleControlConfig.metric}})" +
".addTo(myMap);" 117 117 ".addTo(myMap);"
) 118 118 )
} 119 119 }
120 120
// execute script for zoom control definition 121 121 // execute script for zoom control definition
if (mapConfig.zoomControlConfig.show) { 122 122 if (mapConfig.zoomControlConfig.show) {
execScript( 123 123 execScript(
"L.control.zoom({position: '${mapConfig.zoomControlConfig.position.positionName}'})" + 124 124 "L.control.zoom({position: '${mapConfig.zoomControlConfig.position.positionName}'})" +
".addTo(myMap);" 125 125 ".addTo(myMap);"
) 126 126 )
} 127 127 }
} 128 128 }
129 129
/** 130 130 /**
* Sets the view of the map to the specified geographical center position and zoom level. 131 131 * Sets the view of the map to the specified geographical center position and zoom level.
* 132 132 *
* @param position map center position 133 133 * @param position map center position
* @param zoomLevel zoom level (0 - 19 for OpenStreetMap) 134 134 * @param zoomLevel zoom level (0 - 19 for OpenStreetMap)
*/ 135 135 */
fun setView(position: LatLong, zoomLevel: Int) = 136 136 fun setView(position: LatLong, zoomLevel: Int) =
execScript("myMap.setView([${position.latitude}, ${position.longitude}], $zoomLevel);") 137 137 execScript("myMap.setView([${position.latitude}, ${position.longitude}], $zoomLevel);")
138 138
/** 139 139 /**
* Pans the map to the specified geographical center position. 140 140 * Pans the map to the specified geographical center position.
* 141 141 *
* @param position map center position 142 142 * @param position map center position
*/ 143 143 */
fun panTo(position: LatLong) = 144 144 fun panTo(position: LatLong) =
execScript("myMap.panTo([${position.latitude}, ${position.longitude}]);") 145 145 execScript("myMap.panTo([${position.latitude}, ${position.longitude}]);")
146 146
/** 147 147 /**
* Sets the zoom of the map to the specified level. 148 148 * Sets the zoom of the map to the specified level.
* 149 149 *
* @param zoomLevel zoom level (0 - 19 for OpenStreetMap) 150 150 * @param zoomLevel zoom level (0 - 19 for OpenStreetMap)
*/ 151 151 */
fun setZoom(zoomLevel: Int) = 152 152 fun setZoom(zoomLevel: Int) =
execScript("myMap.setZoom([$zoomLevel]);") 153 153 execScript("myMap.setZoom([$zoomLevel]);")
154 154
/** 155 155 /**
* Adds a Marker Object to a map 156 156 * Adds a Marker Object to a map
* 157 157 *
* @param marker the Marker Object 158 158 * @param marker the Marker Object
*/ 159 159 */
fun addMarker(marker: Marker) { 160 160 fun addMarker(marker: Marker) {
marker.addToMap(getNextMarkerName(), this) 161 161 marker.addToMap(getNextMarkerName(), this)
} 162 162 }
163 163
fun addCircle(circle: Circle) { 164 164 fun addCircle(circle: Circle) {
circle.addToMap(this) 165 165 circle.addToMap(this)
} 166 166 }
167 167
fun addZone(zone: Zone) { 168 168 fun addZone(zone: Zone) {
zone.addToMap(this) 169 169 zone.addToMap(this)
} 170 170 }
171 171
/** 172 172 /**
* Removes an existing marker from the map 173 173 * Removes an existing marker from the map
* 174 174 *
* @param marker the Marker object 175 175 * @param marker the Marker object
*/ 176 176 */
fun removeMarker(marker: Marker) { 177 177 fun removeMarker(marker: Marker) {
execScript("myMap.removeLayer(${marker.getName()});") 178 178 execScript("myMap.removeLayer(${marker.getName()});")
} 179 179 }
180 180
fun removeCircle(circle: Circle) { 181 181 fun removeCircle(circle: Circle) {
circle.removeCircle(this) 182 182 circle.removeCircle(this)
} 183 183 }
184 184
fun removeZone(zone: Zone) { 185 185 fun removeZone(zone: Zone) {
zone.removeZone() 186 186 zone.removeZone()
} 187 187 }
188 188
fun removeZone(id: String) { 189 189 fun removeZone(id: String) {
val idSanitized = id.replace("-", "") 190 190 val idSanitized = id.replace("-", "")
execScript("myMap.removeLayer(polygon$idSanitized);") 191 191 execScript("myMap.removeLayer(polygon$idSanitized);")
} 192 192 }
193 193
194 194
fun uppdateCircle(circle: Circle, latLong: LatLong, radius: Double) { 195 195 fun uppdateCircle(circle: Circle, latLong: LatLong, radius: Double) {
circle.modifyCircle(latLong, radius) 196 196 circle.modifyCircle(latLong, radius)
circle.uppdateMap() 197 197 circle.uppdateMap()
} 198 198 }
199 199
fun setEventMousePosition() { 200 200 fun setEventMousePosition() {
execScript( 201 201 execScript(
"var lat=0.0, lng=0.0;\n" + 202 202 "var lat=0.0, lng=0.0;\n" +
"myMap.addEventListener('mousemove', function(ev) {\n" + 203 203 "myMap.addEventListener('mousemove', function(ev) {\n" +
" lat = ev.latlng.lat;\n" + 204 204 " lat = ev.latlng.lat;\n" +
" lng = ev.latlng.lng;\n" + 205 205 " lng = ev.latlng.lng;\n" +
"});" 206 206 "});"
) 207 207 )
} 208 208 }
209 209
fun getMousePosition(): LatLong { 210 210 fun getMousePosition(): LatLong {
val lat = execScript("lat;") as Double 211 211 val lat = execScript("lat;") as Double
val lng = execScript("lng;") as Double 212 212 val lng = execScript("lng;") as Double
return LatLong(lat, lng) 213 213 return LatLong(lat, lng)
} 214 214 }
215 215
/** 216 216 /**
* Adds a custom marker type 217 217 * Adds a custom marker type
* 218 218 *
* @param markerName the name of the marker type 219 219 * @param markerName the name of the marker type
* @param iconUrl the url if the marker icon 220 220 * @param iconUrl the url if the marker icon
*/ 221 221 */
fun addCustomMarker(markerName: String, iconUrl: String): String { 222 222 fun addCustomMarker(markerName: String, iconUrl: String): String {
execScript( 223 223 execScript(
"var $markerName = L.icon({\n" + 224 224 "var $markerName = L.icon({\n" +
"iconUrl: '${createImage(iconUrl, "png")}',\n" + 225 225 "iconUrl: '${createImage(iconUrl, "png")}',\n" +
"iconSize: [24, 24],\n" + 226 226 "iconSize: [24, 24],\n" +
"iconAnchor: [12, 12],\n" + 227 227 "iconAnchor: [12, 12],\n" +
"});" 228 228 "});"
) 229 229 )
return markerName 230 230 return markerName
} 231 231 }
232 232
private fun createImage(path: String, type: String): String { 233 233 private fun createImage(path: String, type: String): String {
val image = ImageIO.read(File(path)) 234 234 val image = ImageIO.read(File(path))
var imageString: String? = null 235 235 var imageString: String? = null
val bos = ByteArrayOutputStream() 236 236 val bos = ByteArrayOutputStream()
237 237
try { 238 238 try {
ImageIO.write(image, type, bos) 239 239 ImageIO.write(image, type, bos)
val imageBytes = bos.toByteArray() 240 240 val imageBytes = bos.toByteArray()
241 241
val encoder = Base64.getEncoder() 242 242 val encoder = Base64.getEncoder()
imageString = encoder.encodeToString(imageBytes) 243 243 imageString = encoder.encodeToString(imageBytes)
244 244
bos.close() 245 245 bos.close()
} catch (e: IOException) { 246 246 } catch (e: IOException) {
e.printStackTrace() 247 247 e.printStackTrace()
} 248 248 }
return "data:image/$type;base64,$imageString" 249 249 return "data:image/$type;base64,$imageString"
} 250 250 }
251 251
/** 252 252 /**
* Sets the onMarkerClickListener 253 253 * Sets the onMarkerClickListener
* 254 254 *
* @param listener the onMarerClickEventListener 255 255 * @param listener the onMarerClickEventListener
*/ 256 256 */
fun onMarkerClick(listener: MarkerClickEventListener) { 257 257 fun onMarkerClick(listener: MarkerClickEventListener) {
val win = execScript("document") as JSObject 258 258 val win = execScript("document") as JSObject
win.setMember("java", this) 259 259 win.setMember("java", this)
markerClickEvent.addListener(listener) 260 260 markerClickEvent.addListener(listener)
} 261 261 }
262 262
/** 263 263 /**
* Handles the callback from the markerClickEvent 264 264 * Handles the callback from the markerClickEvent
*/ 265 265 */
fun markerClick(title: String) { 266 266 fun markerClick(title: String) {
markerClickEvent.MarkerClickEvent(title) 267 267 markerClickEvent.MarkerClickEvent(title)
} 268 268 }
269 269
/** 270 270 /**
* Sets the onMapMoveListener 271 271 * Sets the onMapMoveListener
* 272 272 *
* @param listener the MapMoveEventListener 273 273 * @param listener the MapMoveEventListener
*/ 274 274 */
fun onMapMove(listener: MapMoveEventListener) { 275 275 fun onMapMove(listener: MapMoveEventListener) {
val win = execScript("document") as JSObject 276 276 val win = execScript("document") as JSObject
win.setMember("java", this) 277 277 win.setMember("java", this)
execScript("myMap.on('moveend', function(e){ document.java.mapMove(myMap.getCenter().lat, myMap.getCenter().lng);});") 278 278 execScript("myMap.on('moveend', function(e){ document.java.mapMove(myMap.getCenter().lat, myMap.getCenter().lng);});")
mapMoveEvent.addListener(listener) 279 279 mapMoveEvent.addListener(listener)
} 280 280 }
281 281
/** 282 282 /**
* Handles the callback from the mapMoveEvent 283 283 * Handles the callback from the mapMoveEvent
*/ 284 284 */
fun mapMove(lat: Double, lng: Double) { 285 285 fun mapMove(lat: Double, lng: Double) {
val latlng = LatLong(lat, lng) 286 286 val latlng = LatLong(lat, lng)
mapMoveEvent.MapMoveEvent(latlng) 287 287 mapMoveEvent.MapMoveEvent(latlng)
} 288 288 }
289 289
/** 290 290 /**
* Sets the onMapClickListener 291 291 * Sets the onMapClickListener
* 292 292 *
* @param listener the onMapClickEventListener 293 293 * @param listener the onMapClickEventListener
*/ 294 294 */
fun onMapClick(listener: MapClickEventListener) { 295 295 fun onMapClick(listener: MapClickEventListener) {
val win = execScript("document") as JSObject 296 296 val win = execScript("document") as JSObject
win.setMember("java", this) 297 297 win.setMember("java", this)
execScript("myMap.on('click', function(e){ document.java.mapClick(e.latlng.lat, e.latlng.lng);});") 298 298 execScript("myMap.on('click', function(e){ document.java.mapClick(e.latlng.lat, e.latlng.lng);});")
mapClickEvent.addListener(listener) 299 299 mapClickEvent.addListener(listener)
} 300 300 }
301 301
/** 302 302 /**
* Handles the callback from the mapClickEvent 303 303 * Handles the callback from the mapClickEvent
*/ 304 304 */
fun mapClick(lat: Double, lng: Double) { 305 305 fun mapClick(lat: Double, lng: Double) {
val latlng = LatLong(lat, lng) 306 306 val latlng = LatLong(lat, lng)
mapClickEvent.MapClickEvent(latlng) 307 307 mapClickEvent.MapClickEvent(latlng)
} 308 308 }
309 309
/** 310 310 /**
* Draws a track path along the specified positions. 311 311 * Draws a track path along the specified positions.
* 312 312 *
* @param positions list of track positions 313 313 * @param positions list of track positions
*/ 314 314 */
fun addTrack(positions: List<LatLong>) { 315 315 fun addTrack(positions: List<LatLong>) {
316 316
val jsPositions = positions 317 317 val jsPositions = positions
.map { " [${it.latitude}, ${it.longitude}]" } 318 318 .map { " [${it.latitude}, ${it.longitude}]" }
.joinToString(", \n") 319 319 .joinToString(", \n")
320 320
execScript( 321 321 execScript(
""" 322 322 """
|var latLngs = [ 323 323 |var latLngs = [
|$jsPositions 324 324 |$jsPositions
|]; 325 325 |];
|var polyline = L.polyline(latLngs, {color: 'red', weight: 2}).addTo(myMap);""".trimMargin() 326 326 |var polyline = L.polyline(latLngs, {color: 'red', weight: 2}).addTo(myMap);""".trimMargin()
) 327 327 )
} 328 328 }
329 329
fun clearAllLayer() { 330 330 fun clearAllLayer() {
execScript(""" 331 331 execScript("""
myMap.eachLayer(function (layer) { 332 332 myMap.eachLayer(function (layer) {
map.removeLayer(layer); 333 333 map.removeLayer(layer);
}); 334 334 });
""".trimIndent()) 335 335 """.trimIndent())
} 336 336 }
337 337
fun addTrack(positions: List<LatLong>, id: String, color: Color, tooltip: String) { 338 338 fun addTrack(positions: List<LatLong>, id: String, color: Color, tooltip: String) {
339 339
val jsPositions = positions 340 340 val jsPositions = positions
.map { " [${it.latitude}, ${it.longitude}]" } 341 341 .map { " [${it.latitude}, ${it.longitude}]" }
.joinToString(", \n") 342 342 .joinToString(", \n")
343 343
val cleanTooltip = tooltip.replace("'", "&apos;") 344 344 val cleanTooltip = tooltip.replace("'", "&apos;")
execScript( 345 345 execScript(
""" 346 346 """
|var latLngs = [ 347 347 |var latLngs = [
|$jsPositions 348 348 |$jsPositions
|]; 349 349 |];
|var color = "rgb(${Math.floor(color.getRed() * 255).toInt()} ,${Math.floor(color.getGreen() * 255) 350 350 |var color = "rgb(${Math.floor(color.getRed() * 255).toInt()} ,${Math.floor(color.getGreen() * 255)
.toInt()},${Math.floor(color.getBlue() * 255).toInt()})"; 351 351 .toInt()},${Math.floor(color.getBlue() * 255).toInt()})";
|var polyline$id = L.polyline(latLngs, {color: color, weight: 2, zIndexOffset: 200}).bindTooltip('$cleanTooltip', {sticky: true}).addTo(trackGroup)""".trimMargin() 352 352 |var polyline$id = L.polyline(latLngs, {color: color, weight: 2, zIndexOffset: 200}).bindTooltip('$cleanTooltip', {sticky: true}).addTo(trackGroup)""".trimMargin()
) 353 353 )
} 354 354 }
355 355
fun makeVesselTrackTransparent(id: String) { 356 356 fun makeVesselTrackTransparent(id: String) {
execScript("polyline$id.setStyle({opacity: 0.5});") 357 357 execScript("polyline$id.setStyle({opacity: 0.5});")
} 358 358 }
359 359
fun highlightTrack(id: String) { 360 360 fun highlightTrack(id: String) {
execScript("polyline$id.setStyle({weight: 4});") 361 361 execScript("polyline$id.setStyle({weight: 4});")
} 362 362 }
363 363
fun normalizeVesselTrack(id: String) { 364 364 fun normalizeVesselTrack(id: String) {
execScript("polyline$id.setStyle({opacity: 1,weight: 2});") 365 365 execScript("polyline$id.setStyle({opacity: 1,weight: 2});")
} 366 366 }