Commit 78935bd622fe4fc1337b6cb6f8dc73d3cb031477
1 parent
3b26be8f99
Exists in
master
and in
1 other branch
slider bind to all type of map
Showing 7 changed files with 104 additions and 47 deletions Side-by-side Diff
- src/main/kotlin/application/controller/MapPanelController.kt
- src/main/kotlin/application/controller/TimePanel.kt
- src/main/kotlin/application/controller/VesselListPanelController.kt
- src/main/kotlin/application/model/Vessel.kt
- src/main/kotlin/map/LeafletMapView.kt
- src/main/kotlin/map/MapDisplayer.kt
- src/main/resources/gui/timePanel.fxml
src/main/kotlin/application/controller/MapPanelController.kt
View file @
78935bd
... | ... | @@ -24,12 +24,6 @@ |
24 | 24 | setStateListener() |
25 | 25 | observableCurrentTime() |
26 | 26 | |
27 | - /*val completeFutureMap: CompletableFuture<Worker.State> = mapView.displayMap(MapConfig()) | |
28 | - completeFutureMap.whenComplete{ | |
29 | - workerState, _ -> | |
30 | - if (workerState == Worker.State.SUCCEEDED) { | |
31 | - } | |
32 | - }*/ | |
33 | 27 | map.children.add(mapView) |
34 | 28 | map.children |
35 | 29 | } |
36 | 30 | |
37 | 31 | |
... | ... | @@ -47,16 +41,24 @@ |
47 | 41 | } |
48 | 42 | |
49 | 43 | private fun observableCurrentTime() { |
50 | - observableCurrentTime.listeners.add(object : CurrentTime{ | |
44 | + observableCurrentTime.listeners.add(object : CurrentTime { | |
51 | 45 | override fun onValueChanged(newValue: Int) { |
52 | - updateMap() | |
46 | + if (observableSelectedVessel.vessel.mmsi != null) { | |
47 | + updateMap(observableSelectedVessel.vessel.mmsi!!) | |
48 | + } else { | |
49 | + updateMap() | |
50 | + } | |
53 | 51 | } |
54 | 52 | }) |
55 | 53 | } |
56 | 54 | |
57 | 55 | private fun updateMap() { |
58 | - if (observableIsReplayState.value){ | |
59 | - displayTargetedVessels(mapView) | |
56 | + if (observableIsReplayState.value) { | |
57 | + when (observableMapState.state) { | |
58 | + ALL_MESSAGES -> displayTimedAllMessageOnMap(mapView) | |
59 | + CLUSTERED_MESSAGES -> displayTimedClusterMessageOnMap(mapView) | |
60 | + HEAT_MAP -> displayTimedHeatMapOnMap(mapView) | |
61 | + } | |
60 | 62 | } else { |
61 | 63 | when (observableMapState.state) { |
62 | 64 | ALL_MESSAGES -> displayAllMessageOnMap(mapView) |
... | ... | @@ -67,10 +69,18 @@ |
67 | 69 | } |
68 | 70 | |
69 | 71 | private fun updateMap(selectedMMSI: String) { |
70 | - when (observableMapState.state) { | |
71 | - ALL_MESSAGES -> displayAllMessageOnMap(mapView, selectedMMSI) | |
72 | - CLUSTERED_MESSAGES -> displayClusterMessageOnMap(mapView, selectedMMSI) | |
73 | - HEAT_MAP -> displayHeatMapOnMap(mapView, selectedMMSI) | |
72 | + if (observableIsReplayState.value) { | |
73 | + when (observableMapState.state) { | |
74 | + ALL_MESSAGES -> displayTimedAllMessageOnMap(mapView, selectedMMSI) | |
75 | + CLUSTERED_MESSAGES -> displayTimedClusterMessageOnMap(mapView, selectedMMSI) | |
76 | + HEAT_MAP -> displayTimedHeatMapOnMap(mapView, selectedMMSI) | |
77 | + } | |
78 | + } else { | |
79 | + when (observableMapState.state) { | |
80 | + ALL_MESSAGES -> displayAllMessageOnMap(mapView, selectedMMSI) | |
81 | + CLUSTERED_MESSAGES -> displayClusterMessageOnMap(mapView, selectedMMSI) | |
82 | + HEAT_MAP -> displayHeatMapOnMap(mapView, selectedMMSI) | |
83 | + } | |
74 | 84 | } |
75 | 85 | } |
76 | 86 | |
77 | 87 | |
78 | 88 | |
... | ... | @@ -85,15 +95,13 @@ |
85 | 95 | private fun setObservableSelectedVesselListener() { |
86 | 96 | observableSelectedVessel.listeners.add(object : SelectedVesselListener { |
87 | 97 | override fun onValueChanged(newValue: Vessel) { |
88 | - if (newValue.mmsi != null){ | |
98 | + if (newValue.mmsi != null) { | |
89 | 99 | updateMap(newValue.mmsi) |
90 | - }else { | |
100 | + } else { | |
91 | 101 | updateMap() |
92 | 102 | } |
93 | 103 | } |
94 | 104 | }) |
95 | 105 | } |
96 | - | |
97 | - | |
98 | 106 | } |
src/main/kotlin/application/controller/TimePanel.kt
View file @
78935bd
... | ... | @@ -29,6 +29,8 @@ |
29 | 29 | } |
30 | 30 | |
31 | 31 | private fun setSliderMinMax() { |
32 | + timeSlider.min = 0.0 | |
33 | + timeSlider.max = 0.0 | |
32 | 34 | observableVessel.listeners.add(object : MessageListener{ |
33 | 35 | override fun onValueChanged(newValue: MutableMap<String?, Vessel>) { |
34 | 36 | timeSlider.max = Vessel.maxTime.toDouble() |
src/main/kotlin/application/controller/VesselListPanelController.kt
View file @
78935bd
... | ... | @@ -6,10 +6,12 @@ |
6 | 6 | import application.model.observableVessel |
7 | 7 | import javafx.collections.FXCollections |
8 | 8 | import javafx.collections.ObservableList |
9 | -import javafx.event.EventHandler | |
10 | 9 | import javafx.fxml.FXML |
11 | 10 | import javafx.fxml.Initializable |
12 | -import javafx.scene.control.* | |
11 | +import javafx.scene.control.ListCell | |
12 | +import javafx.scene.control.ListView | |
13 | +import javafx.scene.control.MultipleSelectionModel | |
14 | +import javafx.scene.control.SelectionMode | |
13 | 15 | import javafx.scene.input.MouseEvent |
14 | 16 | import java.net.URL |
15 | 17 | import java.util.* |
src/main/kotlin/application/model/Vessel.kt
View file @
78935bd
... | ... | @@ -7,32 +7,11 @@ |
7 | 7 | val messages: SortedMap<Long, Message> = sortedMapOf() |
8 | 8 | var messageToDisplay: Message? = null |
9 | 9 | get() { |
10 | - // messages.forEach { (key, value) -> | |
11 | -// if(observableCurrentTime.value < key) { | |
12 | -// field = value | |
13 | -// return@forEach | |
14 | -// } | |
15 | -// } | |
16 | - field = messages.asSequence().map{ it }.firstOrNull {observableCurrentTime.value < it.key}.let { it?.value } | |
10 | + field = | |
11 | + messages.asSequence().map { it }.firstOrNull { observableCurrentTime.value < it.key }.let { it?.value } | |
17 | 12 | return field |
18 | 13 | } |
19 | 14 | |
20 | - // val timesNormalized : SortedMap<Long, LocalDateTime> = sortedMapOf() | |
21 | - | |
22 | -// fun getAllNormalizedDate(): SortedMap<Long, LocalDateTime> { | |
23 | -// var offset: Long? = null | |
24 | -// if(timesNormalized.size == 0){ | |
25 | -// messages.keys.forEach { | |
26 | -// val currentTime = it.toEpochSecond(ZoneOffset.UTC) | |
27 | -// if(offset == null){ | |
28 | -// offset = currentTime | |
29 | -// } | |
30 | -// timesNormalized[currentTime - offset!!]= it | |
31 | -// } | |
32 | -// } | |
33 | -// return timesNormalized | |
34 | -// } | |
35 | - | |
36 | 15 | fun getAllTime(): ArrayList<MessageData?> { |
37 | 16 | val timeList = arrayListOf<MessageData?>() |
38 | 17 | messages.forEach { |
... | ... | @@ -159,7 +138,7 @@ |
159 | 138 | return res |
160 | 139 | } |
161 | 140 | |
162 | - companion object{ | |
141 | + companion object { | |
163 | 142 | var maxTime: Long = 0 |
164 | 143 | var minTime: Long = 0 |
165 | 144 | } |
src/main/kotlin/map/LeafletMapView.kt
View file @
78935bd
... | ... | @@ -93,6 +93,7 @@ |
93 | 93 | | layers: [layer1] |
94 | 94 | |}); |
95 | 95 | |L.control.scale().addTo(myMap); |
96 | + |var markers = [] | |
96 | 97 | |var myRenderer = L.canvas({ padding: 0.5 }); |
97 | 98 | |var markerClusters = L.markerClusterGroup({spiderfyOnMaxZoom: false, disableClusteringAtZoom: 10}); |
98 | 99 | |var heatLayer = L.heatLayer([]).addTo(myMap);""".trimMargin() |
src/main/kotlin/map/MapDisplayer.kt
View file @
78935bd
... | ... | @@ -6,6 +6,7 @@ |
6 | 6 | clearMapCanvas(map) |
7 | 7 | clearMapCluster(map) |
8 | 8 | clearHeatMap(map) |
9 | + clearMarker(map) | |
9 | 10 | } |
10 | 11 | |
11 | 12 | fun clearMapCluster(map: LeafletMapView) { |
... | ... | @@ -35,6 +36,17 @@ |
35 | 36 | ) |
36 | 37 | } |
37 | 38 | |
39 | +fun clearMarker(map: LeafletMapView) { | |
40 | + map.execScript( | |
41 | + """ | |
42 | + |for(var i = 0; i < markers.length; i++){ | |
43 | + |myMap.removeLayer(markers[i]); | |
44 | + |} | |
45 | + |markers = [] | |
46 | + """.trimMargin() | |
47 | + ) | |
48 | +} | |
49 | + | |
38 | 50 | fun displayAllMessageOnMap(map: LeafletMapView) { |
39 | 51 | clearMap(map) |
40 | 52 | observableVessel.vessels.forEach { (_, value) -> |
... | ... | @@ -44,6 +56,14 @@ |
44 | 56 | } |
45 | 57 | } |
46 | 58 | |
59 | +fun displayTimedAllMessageOnMap(map: LeafletMapView) { | |
60 | + clearMap(map) | |
61 | + observableVessel.vessels.forEach { (_, value) -> | |
62 | + val message = value.messageToDisplay ?: return@forEach | |
63 | + map.execScript("markers.push(L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {radius: 0.01, color: '#${message.getHexColorStroke()}'}).addTo(myMap))") | |
64 | + } | |
65 | +} | |
66 | + | |
47 | 67 | fun displayAllMessageOnMap(map: LeafletMapView, selectedMMSI: String) { |
48 | 68 | clearMap(map) |
49 | 69 | observableVessel.vessels.forEach { (_, value) -> |
... | ... | @@ -57,6 +77,18 @@ |
57 | 77 | } |
58 | 78 | } |
59 | 79 | |
80 | +fun displayTimedAllMessageOnMap(map: LeafletMapView, selectedMMSI: String) { | |
81 | + clearMap(map) | |
82 | + observableVessel.vessels.forEach { (_, value) -> | |
83 | + val message = value.messageToDisplay ?: return@forEach | |
84 | + if (selectedMMSI == message.mmsi.value) { | |
85 | + map.execScript("markers.push(L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {renderer: myRenderer, radius: 2, color: '#ff4040'}).addTo(myMap))") | |
86 | + } else { | |
87 | + map.execScript("markers.push(L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {renderer: myRenderer, radius: 0.01, color: '#${message.getHexColorStroke()}'}).addTo(myMap))") | |
88 | + } | |
89 | + } | |
90 | +} | |
91 | + | |
60 | 92 | fun displayClusterMessageOnMap(map: LeafletMapView) { |
61 | 93 | clearMap(map) |
62 | 94 | observableVessel.vessels.forEach { (_, value) -> |
63 | 95 | |
... | ... | @@ -67,11 +99,11 @@ |
67 | 99 | map.execScript("myMap.addLayer(markerClusters);") |
68 | 100 | } |
69 | 101 | |
70 | -fun displayTargetedVessels(map: LeafletMapView) { | |
102 | +fun displayTimedClusterMessageOnMap(map: LeafletMapView) { | |
71 | 103 | clearMap(map) |
72 | 104 | observableVessel.vessels.forEach { (_, value) -> |
73 | 105 | val message = value.messageToDisplay ?: return@forEach |
74 | - map.execScript("markerClusters.addLayer(L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {renderer: myRenderer, radius: 0.01, color: '#${message.getHexColorStroke()}'}));") | |
106 | + map.execScript("markerClusters.addLayer(L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {radius: 0.01, color: '#${message.getHexColorStroke()}'}));") | |
75 | 107 | } |
76 | 108 | map.execScript("myMap.addLayer(markerClusters);") |
77 | 109 | } |
... | ... | @@ -90,6 +122,19 @@ |
90 | 122 | map.execScript("myMap.addLayer(markerClusters);") |
91 | 123 | } |
92 | 124 | |
125 | +fun displayTimedClusterMessageOnMap(map: LeafletMapView, selectedMMSI: String) { | |
126 | + clearMap(map) | |
127 | + observableVessel.vessels.forEach { (_, value) -> | |
128 | + val message = value.messageToDisplay ?: return@forEach | |
129 | + if (selectedMMSI == message.mmsi.value) { | |
130 | + map.execScript("markers.push(L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {radius: 2, color: '#ff4040'}).addTo(myMap));") | |
131 | + } else { | |
132 | + map.execScript("markerClusters.addLayer(L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {radius: 0.01, color: '#${message.getHexColorStroke()}'}));") | |
133 | + } | |
134 | + } | |
135 | + map.execScript("myMap.addLayer(markerClusters);") | |
136 | +} | |
137 | + | |
93 | 138 | fun displayHeatMapOnMap(map: LeafletMapView) { |
94 | 139 | clearMap(map) |
95 | 140 | observableVessel.vessels.forEach { (_, value) -> |
... | ... | @@ -99,6 +144,14 @@ |
99 | 144 | } |
100 | 145 | } |
101 | 146 | |
147 | +fun displayTimedHeatMapOnMap(map: LeafletMapView) { | |
148 | + clearMap(map) | |
149 | + observableVessel.vessels.forEach { (_, value) -> | |
150 | + val message = value.messageToDisplay ?: return@forEach | |
151 | + map.execScript("heatLayer.addLatLng([${message.latitude.value}, ${message.longitude.value}]);") | |
152 | + } | |
153 | +} | |
154 | + | |
102 | 155 | fun displayHeatMapOnMap(map: LeafletMapView, selectedMMSI: String) { |
103 | 156 | clearMap(map) |
104 | 157 | observableVessel.vessels.forEach { (_, value) -> |
... | ... | @@ -111,5 +164,17 @@ |
111 | 164 | } |
112 | 165 | } |
113 | 166 | map.execScript("myMap.addLayer(markerClusters);") |
167 | +} | |
168 | + | |
169 | +fun displayTimedHeatMapOnMap(map: LeafletMapView, selectedMMSI: String) { | |
170 | + clearMap(map) | |
171 | + observableVessel.vessels.forEach { (_, value) -> | |
172 | + val message = value.messageToDisplay ?: return@forEach | |
173 | + if (selectedMMSI == message.mmsi.value) { | |
174 | + map.execScript("markers.push(L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {radius: 2, color: '#ff4040'}).addTo(myMap));") | |
175 | + } else { | |
176 | + map.execScript("heatLayer.addLatLng([${message.latitude.value}, ${message.longitude.value}]);") | |
177 | + } | |
178 | + } | |
114 | 179 | } |
src/main/resources/gui/timePanel.fxml
View file @
78935bd
... | ... | @@ -14,7 +14,7 @@ |
14 | 14 | <HBox.margin> |
15 | 15 | <Insets left="5.0" right="5.0" /> |
16 | 16 | </HBox.margin></Button> |
17 | - <Slider fx:id="timeSlider"> | |
17 | + <Slider fx:id="timeSlider" prefHeight="14.0" prefWidth="475.0"> | |
18 | 18 | <HBox.margin> |
19 | 19 | <Insets left="5.0" right="5.0" /> |
20 | 20 | </HBox.margin></Slider> |