Commit f39d90e6068c17e06645704f2f102d47aa985a59

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

Select/deselect MMSI

Showing 14 changed files with 76 additions and 120 deletions Inline Diff

src/main/kotlin/application/App.kt View file @ f39d90e
1 @file:JvmName("App")
2
package application 1 3 package application
2 4
import javafx.application.Application 3 5 import javafx.application.Application
import javafx.application.Platform 4 6 import javafx.application.Platform
import javafx.event.EventHandler 5 7 import javafx.event.EventHandler
import javafx.fxml.FXMLLoader 6 8 import javafx.fxml.FXMLLoader
import javafx.scene.Parent 7 9 import javafx.scene.Parent
import javafx.scene.Scene 8 10 import javafx.scene.Scene
import javafx.stage.Stage 9 11 import javafx.stage.Stage
import javafx.stage.WindowEvent 10
import jfxtras.styles.jmetro.JMetro 11 12 import jfxtras.styles.jmetro.JMetro
import jfxtras.styles.jmetro.Style 12 13 import jfxtras.styles.jmetro.Style
import kotlin.system.exitProcess 13 14 import kotlin.system.exitProcess
14 15
class App : Application() { 15 16 class App : Application() {
var style : Style = Style.LIGHT 16 17 var style: Style = Style.LIGHT
17 18
override fun start(primaryStage: Stage?) { 18 19 override fun start(primaryStage: Stage?) {
19 20
val fxmlLoader = FXMLLoader(App::class.java.getResource("/gui/windows.fxml")) 20 21 val fxmlLoader = FXMLLoader(App::class.java.getResource("/gui/windows.fxml"))
val parent: Parent = fxmlLoader.load() 21 22 val parent: Parent = fxmlLoader.load()
val scene = Scene(parent) 22 23 val scene = Scene(parent)
JMetro(scene, style) 23 24 JMetro(scene, style)
primaryStage!!.scene = scene 24 25 primaryStage!!.scene = scene
primaryStage.title = "Maritime Visualisation" 25 26 primaryStage.title = "Maritime Visualisation"
primaryStage.onCloseRequest = EventHandler { closeApplication() } 26 27 primaryStage.onCloseRequest = EventHandler { closeApplication() }
primaryStage.show() 27 28 primaryStage.show()
} 28 29 }
29 30
private fun closeApplication() { 30 31 private fun closeApplication() {
Platform.exit() 31 32 Platform.exit()
exitProcess(0) 32 33 exitProcess(0)
} 33 34 }
34 35
companion object { 35 36 companion object {
@JvmStatic 36 37 @JvmStatic
src/main/kotlin/application/Logger.kt View file @ f39d90e
package application 1 File was deleted
2
import org.slf4j.Logger 3
import org.slf4j.LoggerFactory 4
src/main/kotlin/application/VisualisationChart.kt View file @ f39d90e
package application 1 File was deleted
2
import javafx.scene.chart.Axis 3
import javafx.scene.chart.ScatterChart 4
5
src/main/kotlin/application/controller/DataPanelController.kt View file @ f39d90e
package application.controller 1 1 package application.controller
2 2
import application.model.* 3 3 import application.model.*
import javafx.collections.FXCollections 4 4 import javafx.collections.FXCollections
import javafx.collections.ObservableList 5 5 import javafx.collections.ObservableList
import javafx.fxml.FXML 6 6 import javafx.fxml.FXML
import javafx.fxml.Initializable 7 7 import javafx.fxml.Initializable
import javafx.scene.control.ListCell 8 8 import javafx.scene.control.ListCell
import javafx.scene.control.ListView 9 9 import javafx.scene.control.ListView
import javafx.scene.layout.StackPane 10
import org.charts.dataviewer.api.config.DataViewerConfiguration 11 10 import org.charts.dataviewer.api.config.DataViewerConfiguration
import org.charts.dataviewer.api.data.PlotData 12 11 import org.charts.dataviewer.api.data.PlotData
import org.charts.dataviewer.api.trace.LineTrace 13
import org.charts.dataviewer.api.trace.ScatterTrace 14 12 import org.charts.dataviewer.api.trace.ScatterTrace
import org.charts.dataviewer.javafx.JavaFxDataViewer 15 13 import org.charts.dataviewer.javafx.JavaFxDataViewer
import org.charts.dataviewer.utils.TraceColour 16 14 import org.charts.dataviewer.utils.TraceColour
import org.charts.dataviewer.utils.TraceMode 17
import org.charts.dataviewer.utils.TraceVisibility 18 15 import org.charts.dataviewer.utils.TraceVisibility
import java.net.URL 19 16 import java.net.URL
import java.util.* 20 17 import java.util.*
21 18
22 19
class DataPanelController : Initializable, SelectedVesselListener { 23 20 class DataPanelController : Initializable, SelectedVesselListener {
private var dataList: ObservableList<Pair<String, ArrayList<MessageData?>>> = FXCollections.observableArrayList() 24 21 private var dataList: ObservableList<Pair<String, ArrayList<MessageData?>>> = FXCollections.observableArrayList()
private lateinit var timeData: ArrayList<MessageData?> 25 22 private lateinit var timeData: ArrayList<MessageData?>
26 23
27 24
@FXML 28 25 @FXML
var dataListView = ListView<Pair<String, ArrayList<MessageData?>>>() 29 26 var dataListView = ListView<Pair<String, ArrayList<MessageData?>>>()
30 27
// @FXML 31
// var stackPanePlot = StackPane() 32
33
@FXML 34 28 @FXML
var dataViewer = JavaFxDataViewer() 35 29 var dataViewer = JavaFxDataViewer()
36 30
// @FXML 37
// var xaxisNumber: CategoryAxis = CategoryAxis() 38
// 39
// @FXML 40
// var yaxisNumber: NumberAxis = NumberAxis() 41
// 42
// @FXML 43
// lateinit var scatterChartNumber: ScatterChart<String, Number> 44
// 45
// @FXML 46
// var xaxisCategory: CategoryAxis = CategoryAxis() 47
// 48
// @FXML 49
// var yaxisCategory: CategoryAxis = CategoryAxis() 50
// 51
// @FXML 52
// lateinit var scatterChartCategory: ScatterChart<String, String> 53
54 31
override fun initialize(location: URL?, resources: ResourceBundle?) { 55 32 override fun initialize(location: URL?, resources: ResourceBundle?) {
// xaxisNumber.animated = false 56
// yaxisNumber.animated = false 57
// xaxisCategory.animated = false 58
// yaxisCategory.animated = false 59
setObservableSelectedVesselListener() 60 33 setObservableSelectedVesselListener()
dataListView.items = dataList 61 34 dataListView.items = dataList
62 35
63 36
val plotData = PlotData() 64 37 val plotData = PlotData()
plotData.addTrace(createScatterTrace()) 65
val config = DataViewerConfiguration() 66 38 val config = DataViewerConfiguration()
config.showLegend(true) 67 39 config.showLegend(true)
config.setLegendInsidePlot(false) 68 40 config.setLegendInsidePlot(false)
69 41
dataListView.setCellFactory { 70 42 dataListView.setCellFactory {
object : ListCell<Pair<String, ArrayList<MessageData?>>?>() { 71 43 object : ListCell<Pair<String, ArrayList<MessageData?>>?>() {
override fun updateItem(item: Pair<String, ArrayList<MessageData?>>?, empty: Boolean) { 72 44 override fun updateItem(item: Pair<String, ArrayList<MessageData?>>?, empty: Boolean) {
super.updateItem(item, empty) 73 45 super.updateItem(item, empty)
text = if (empty) { 74 46 text = if (empty) {
null 75 47 null
} else { 76 48 } else {
item?.first 77 49 item?.first
} 78 50 }
} 79 51 }
} 80 52 }
} 81 53 }
82 54
dataListView.selectionModel.selectedItemProperty().addListener { _, _, newValue -> 83 55 dataListView.selectionModel.selectedItemProperty().addListener { _, _, newValue ->
if (newValue == null) { 84 56 if (newValue == null) {
plotData.allTraces.clear() 85 57 plotData.allTraces.clear()
config.setxAxisTitle("") 86 58 config.setxAxisTitle("")
config.setyAxisTitle("") 87 59 config.setyAxisTitle("")
60 dataViewer.updateConfiguration(config)
61
dataViewer.resetPlot() 88 62 dataViewer.resetPlot()
89 63
return@addListener 90 64 return@addListener
} 91 65 }
92 66
val getValueVisitorX = GetValueVisitor() 93 67 val getValueVisitorX = GetValueVisitor()
val getValueVisitorY = GetValueVisitor() 94 68 val getValueVisitorY = GetValueVisitor()
95 69
val arrayListStringX = arrayListOf<String>() 96 70 val arrayListStringX = arrayListOf<String>()
val arrayListDoubleX = arrayListOf<Double>() 97 71 val arrayListDoubleX = arrayListOf<Double>()
val arrayListStringY = arrayListOf<String>() 98 72 val arrayListStringY = arrayListOf<String>()
val arrayListDoubleY = arrayListOf<Double>() 99 73 val arrayListDoubleY = arrayListOf<Double>()
100 74
for (x in 0 until newValue.second.size) { 101 75 for (x in 0 until newValue.second.size) {
timeData[x]?.accept(getValueVisitorX) 102 76 timeData[x]?.accept(getValueVisitorX)
newValue.second[x]?.accept(getValueVisitorY) 103 77 newValue.second[x]?.accept(getValueVisitorY)
104 78
if (getValueVisitorY.value.toDoubleOrNull() == null) { 105 79 if (getValueVisitorY.value.toDoubleOrNull() == null) {
arrayListStringX.add(getValueVisitorX.value) 106 80 arrayListStringX.add(getValueVisitorX.value)
arrayListStringY.add(getValueVisitorY.value) 107 81 arrayListStringY.add(getValueVisitorY.value)
} else { 108 82 } else {
arrayListStringX.add(getValueVisitorX.value) 109 83 arrayListStringX.add(getValueVisitorX.value)
arrayListDoubleY.add(getValueVisitorY.value.toDouble()) 110 84 arrayListDoubleY.add(getValueVisitorY.value.toDouble())
} 111 85 }
} 112 86 }
113 87
val scatterTrace = ScatterTrace<Any>() 114 88 val scatterTrace = ScatterTrace<Any>()
scatterTrace.traceColour = TraceColour.RED 115 89 scatterTrace.traceColour = TraceColour.RED
scatterTrace.traceVisibility = TraceVisibility.TRUE 116 90 scatterTrace.traceVisibility = TraceVisibility.TRUE
117 91
val serieStringX: Array<String> = arrayListStringX.toTypedArray() 118 92 val serieStringX: Array<String> = arrayListStringX.toTypedArray()
// val serieDoubleX: Array<Double> = arrayListDoubleX.toTypedArray() 119 93 // val serieDoubleX: Array<Double> = arrayListDoubleX.toTypedArray()
val serieStringY: Array<String> = arrayListStringY.toTypedArray() 120 94 val serieStringY: Array<String> = arrayListStringY.toTypedArray()
val serieDoubleY: Array<Double> = arrayListDoubleY.toTypedArray() 121 95 val serieDoubleY: Array<Double> = arrayListDoubleY.toTypedArray()
122 96
if (getValueVisitorY.value.toDoubleOrNull() == null) { 123 97 if (getValueVisitorY.value.toDoubleOrNull() == null) {
scatterTrace.setxArray(serieStringX) 124 98 scatterTrace.setxArray(serieStringX)
scatterTrace.setyArray(serieStringY) 125 99 scatterTrace.setyArray(serieStringY)
} else { 126 100 } else {
scatterTrace.setxArray(serieStringX) 127 101 scatterTrace.setxArray(serieStringX)
scatterTrace.setyArray(serieDoubleY) 128 102 scatterTrace.setyArray(serieDoubleY)
} 129 103 }
130 104
config.setxAxisTitle("Date") 131 105 config.setxAxisTitle("Date")
config.setyAxisTitle(newValue.first) 132 106 config.setyAxisTitle(newValue.first)
dataViewer.resetPlot() 133 107 dataViewer.resetPlot()
plotData.allTraces.clear() 134 108 plotData.allTraces.clear()
plotData.addTrace(scatterTrace) 135 109 plotData.addTrace(scatterTrace)
dataViewer.updateConfiguration(config) 136 110 dataViewer.updateConfiguration(config)
dataViewer.updatePlot(plotData) 137 111 dataViewer.updatePlot(plotData)
138 112
} 139 113 }
140 114
plotData.allTraces.clear() 141 115 plotData.allTraces.clear()
// plotData.addTrace(createScatterTrace()) 142
config.setxAxisTitle("") 143 116 config.setxAxisTitle("")
config.setyAxisTitle("") 144 117 config.setyAxisTitle("")
config.plotTitle = "No data selected" 145
dataViewer.updateConfiguration(config) 146 118 dataViewer.updateConfiguration(config)
dataViewer.updatePlot(plotData) 147 119 dataViewer.updatePlot(plotData)
148 120
// stackPanePlot.children.add(dataViewer) 149
150
} 151 121 }
152
private fun createScatterTrace(): ScatterTrace<*>? { 153
val scatterTrace = ScatterTrace<Any>() 154
scatterTrace.setxArray(arrayOf("asdf", "fdsa", "asdfffe", "asdfe", "asfee3")) 155
scatterTrace.setyArray(arrayOf("pppp", "koojoi", "pp", "ii", "rty", "ert")) 156
scatterTrace.traceName = "MyScatterTrace" 157
scatterTrace.traceColour = TraceColour.PURPLE 158
scatterTrace.traceMode = TraceMode.MARKERS 159
return scatterTrace 160
} 161
162
fun createLineTrace(): LineTrace<*>? { 163
val lineTrace = LineTrace<Any>() 164
lineTrace.setxArray(arrayOf("asdf", "fdsa", "asdfffe", "asdfe", "asfee3")) 165
lineTrace.setyArray(arrayOf(0.0, 1.0, 2.0, 3.0, 4.0, 5.0)) 166
lineTrace.traceName = "MyLineTrace" 167
lineTrace.traceColour = TraceColour.PURPLE 168
return lineTrace 169
} 170
171
// private fun setChartCategoryVisible() { 172
// scatterChartCategory.isVisible = true 173
// scatterChartNumber.isVisible = false 174
// } 175
// 176
// private fun setChartNumberVisible() { 177
// scatterChartCategory.isVisible = false 178
// scatterChartNumber.isVisible = true 179
// } 180
181 122
private fun setObservableSelectedVesselListener() { 182 123 private fun setObservableSelectedVesselListener() {
observableSelectedVessel.listeners.add(this) 183 124 observableSelectedVessel.listeners.add(this)
} 184 125 }
185 126
private fun populateTime(vessel: Vessel): ArrayList<MessageData?> { 186 127 private fun populateTime(vessel: Vessel): ArrayList<MessageData?> {
val allTime: ArrayList<MessageData?> = vessel.getAllTime() 187 128 val allTime: ArrayList<MessageData?> = vessel.getAllTime()
allTime.sortBy { (it as Time).value } 188 129 allTime.sortBy { (it as Time).value }
189 130
return allTime 190 131 return allTime
} 191 132 }
192 133
private fun populateLatitude(vessel: Vessel): ArrayList<MessageData?> { 193 134 private fun populateLatitude(vessel: Vessel): ArrayList<MessageData?> {
val allLatitude: ArrayList<MessageData?> = vessel.getAllLatitude() 194 135 val allLatitude: ArrayList<MessageData?> = vessel.getAllLatitude()
allLatitude.sortBy { (it as Latitude).value } 195 136 allLatitude.sortBy { (it as Latitude).value }
196 137
return allLatitude 197 138 return allLatitude
} 198 139 }
199 140
private fun populateLongitude(vessel: Vessel): ArrayList<MessageData?> { 200 141 private fun populateLongitude(vessel: Vessel): ArrayList<MessageData?> {
val allLongitude: ArrayList<MessageData?> = vessel.getAllLongitude() 201 142 val allLongitude: ArrayList<MessageData?> = vessel.getAllLongitude()
allLongitude.sortBy { (it as Longitude).value } 202 143 allLongitude.sortBy { (it as Longitude).value }
203 144
return allLongitude 204 145 return allLongitude
} 205 146 }
206 147
private fun populateSpeedOverGround(vessel: Vessel): ArrayList<MessageData?> { 207 148 private fun populateSpeedOverGround(vessel: Vessel): ArrayList<MessageData?> {
val allSpeedOverGround: ArrayList<MessageData?> = vessel.getAllSpeedOverGround() 208 149 val allSpeedOverGround: ArrayList<MessageData?> = vessel.getAllSpeedOverGround()
allSpeedOverGround.sortBy { (it as SpeedOverGround).value } 209 150 allSpeedOverGround.sortBy { (it as SpeedOverGround).value }
210 151
return allSpeedOverGround 211 152 return allSpeedOverGround
} 212 153 }
213 154
private fun populateCourseOverGround(vessel: Vessel): ArrayList<MessageData?> { 214 155 private fun populateCourseOverGround(vessel: Vessel): ArrayList<MessageData?> {
val allCourseOverGround: ArrayList<MessageData?> = vessel.getAllCourseOverGround() 215 156 val allCourseOverGround: ArrayList<MessageData?> = vessel.getAllCourseOverGround()
allCourseOverGround.sortBy { (it as CourseOverGround).value } 216 157 allCourseOverGround.sortBy { (it as CourseOverGround).value }
217 158
return allCourseOverGround 218 159 return allCourseOverGround
} 219 160 }
220 161
private fun populateHeading(vessel: Vessel): ArrayList<MessageData?> { 221 162 private fun populateHeading(vessel: Vessel): ArrayList<MessageData?> {
val allHeading: ArrayList<MessageData?> = vessel.getAllHeading() 222 163 val allHeading: ArrayList<MessageData?> = vessel.getAllHeading()
allHeading.sortBy { (it as Heading).value } 223 164 allHeading.sortBy { (it as Heading).value }
224 165
return allHeading 225 166 return allHeading
} 226 167 }
227 168
private fun populateVesselName(vessel: Vessel): ArrayList<MessageData?> { 228 169 private fun populateVesselName(vessel: Vessel): ArrayList<MessageData?> {
val allVesselName: ArrayList<MessageData?> = vessel.getAllVesselName() 229 170 val allVesselName: ArrayList<MessageData?> = vessel.getAllVesselName()
allVesselName.sortBy { (it as VesselName).value } 230 171 allVesselName.sortBy { (it as VesselName).value }
231 172
return allVesselName 232 173 return allVesselName
} 233 174 }
234 175
private fun populateIMO(vessel: Vessel): ArrayList<MessageData?> { 235 176 private fun populateIMO(vessel: Vessel): ArrayList<MessageData?> {
val allIMO: ArrayList<MessageData?> = vessel.getAllIMO() 236 177 val allIMO: ArrayList<MessageData?> = vessel.getAllIMO()
allIMO.sortBy { (it as IMO).value } 237 178 allIMO.sortBy { (it as IMO).value }
238 179
return allIMO 239 180 return allIMO
} 240 181 }
241 182
private fun populateCallSign(vessel: Vessel): ArrayList<MessageData?> { 242 183 private fun populateCallSign(vessel: Vessel): ArrayList<MessageData?> {
val allCallSign: ArrayList<MessageData?> = vessel.getAllCallSign() 243 184 val allCallSign: ArrayList<MessageData?> = vessel.getAllCallSign()
allCallSign.sortBy { (it as CallSign).value } 244 185 allCallSign.sortBy { (it as CallSign).value }
245 186
return allCallSign 246 187 return allCallSign
} 247 188 }
248 189
private fun populateVesselType(vessel: Vessel): ArrayList<MessageData?> { 249 190 private fun populateVesselType(vessel: Vessel): ArrayList<MessageData?> {
val allVesselType: ArrayList<MessageData?> = vessel.getAllVesselType() 250 191 val allVesselType: ArrayList<MessageData?> = vessel.getAllVesselType()
allVesselType.sortBy { (it as VesselType).value } 251 192 allVesselType.sortBy { (it as VesselType).value }
252 193
return allVesselType 253 194 return allVesselType
src/main/kotlin/application/controller/MapPanelController.kt View file @ f39d90e
package application.controller 1 1 package application.controller
2 2
import application.model.* 3 3 import application.model.*
import application.model.State.* 4 4 import application.model.State.*
import javafx.fxml.FXML 5 5 import javafx.fxml.FXML
import javafx.fxml.Initializable 6 6 import javafx.fxml.Initializable
import javafx.scene.layout.StackPane 7 7 import javafx.scene.layout.StackPane
import map.* 8 8 import map.*
import java.net.URL 9 9 import java.net.URL
import java.util.* 10 10 import java.util.*
11 11
class MapPanelController : Initializable { 12 12 class MapPanelController : Initializable {
13 13
@FXML 14 14 @FXML
private lateinit var map: StackPane 15 15 private lateinit var map: StackPane
16 16
private val mapView = LeafletMapView() 17 17 private val mapView = LeafletMapView()
18 18
19 19
override fun initialize(location: URL?, resources: ResourceBundle?) { 20 20 override fun initialize(location: URL?, resources: ResourceBundle?) {
mapView.displayMap(MapConfig()) 21 21 mapView.displayMap(MapConfig())
setObservableVesselListener() 22 22 setObservableVesselListener()
setObservableSelectedVesselListener() 23 23 setObservableSelectedVesselListener()
setStateListener() 24 24 setStateListener()
/*val completeFutureMap: CompletableFuture<Worker.State> = mapView.displayMap(MapConfig()) 25 25 /*val completeFutureMap: CompletableFuture<Worker.State> = mapView.displayMap(MapConfig())
completeFutureMap.whenComplete{ 26 26 completeFutureMap.whenComplete{
workerState, _ -> 27 27 workerState, _ ->
if (workerState == Worker.State.SUCCEEDED) { 28 28 if (workerState == Worker.State.SUCCEEDED) {
} 29 29 }
}*/ 30 30 }*/
map.children.add(mapView) 31 31 map.children.add(mapView)
map.children 32 32 map.children
} 33 33 }
34 34
private fun setStateListener() { 35 35 private fun setStateListener() {
observableState.listeners.add(object : StateListener { 36 36 observableState.listeners.add(object : StateListener {
override fun onValueChanged(newValue: State) { 37 37 override fun onValueChanged(newValue: State) {
if (observableSelectedVessel.vessel.mmsi != null) { 38 38 if (observableSelectedVessel.vessel.mmsi != null) {
updateMap(observableSelectedVessel.vessel.mmsi!!) 39 39 updateMap(observableSelectedVessel.vessel.mmsi!!)
} else { 40 40 } else {
updateMap() 41 41 updateMap()
} 42 42 }
} 43 43 }
}) 44 44 })
} 45 45 }
46 46
private fun updateMap() { 47 47 private fun updateMap() {
when (observableState.state) { 48 48 when (observableState.state) {
ALL_MESSAGES -> displayAllMessageOnMap(mapView) 49 49 ALL_MESSAGES -> displayAllMessageOnMap(mapView)
CLUSTERED_MESSAGES -> displayClusterMessageOnMap(mapView) 50 50 CLUSTERED_MESSAGES -> displayClusterMessageOnMap(mapView)
HEAT_MAP -> displayHeatMapOnMap(mapView) 51 51 HEAT_MAP -> displayHeatMapOnMap(mapView)
} 52 52 }
} 53 53 }
54 54
private fun updateMap(selectedMMSI: Int) { 55 55 private fun updateMap(selectedMMSI: String) {
when (observableState.state) { 56 56 when (observableState.state) {
ALL_MESSAGES -> displayAllMessageOnMap(mapView, selectedMMSI) 57 57 ALL_MESSAGES -> displayAllMessageOnMap(mapView, selectedMMSI)
CLUSTERED_MESSAGES -> displayClusterMessageOnMap(mapView, selectedMMSI) 58 58 CLUSTERED_MESSAGES -> displayClusterMessageOnMap(mapView, selectedMMSI)
HEAT_MAP -> displayHeatMapOnMap(mapView, selectedMMSI) 59 59 HEAT_MAP -> displayHeatMapOnMap(mapView, selectedMMSI)
} 60 60 }
} 61 61 }
62 62
private fun setObservableVesselListener() { 63 63 private fun setObservableVesselListener() {
observableVessel.listeners.add(object : MessageListener { 64 64 observableVessel.listeners.add(object : MessageListener {
override fun onValueChanged(newValue: MutableMap<Int?, Vessel>) { 65 65 override fun onValueChanged(newValue: MutableMap<String?, Vessel>) {
updateMap() 66 66 updateMap()
} 67 67 }
}) 68 68 })
} 69 69 }
70 70
private fun setObservableSelectedVesselListener() { 71 71 private fun setObservableSelectedVesselListener() {
observableSelectedVessel.listeners.add(object : SelectedVesselListener { 72 72 observableSelectedVessel.listeners.add(object : SelectedVesselListener {
override fun onValueChanged(newValue: Vessel) { 73 73 override fun onValueChanged(newValue: Vessel) {
src/main/kotlin/application/controller/VesselListPanelController.kt View file @ f39d90e
package application.controller 1 1 package application.controller
2 2
import application.model.MessageListener 3 3 import application.model.MessageListener
import application.model.Vessel 4 4 import application.model.Vessel
import application.model.observableVessel 5
import application.model.observableSelectedVessel 6 5 import application.model.observableSelectedVessel
6 import application.model.observableVessel
import javafx.collections.FXCollections 7 7 import javafx.collections.FXCollections
import javafx.collections.ObservableList 8 8 import javafx.collections.ObservableList
9 import javafx.event.EventHandler
import javafx.fxml.FXML 9 10 import javafx.fxml.FXML
import javafx.fxml.Initializable 10 11 import javafx.fxml.Initializable
import javafx.scene.control.ListView 11 12 import javafx.scene.control.*
13 import javafx.scene.input.MouseEvent
import java.net.URL 12 14 import java.net.URL
import java.util.* 13 15 import java.util.*
14 16
17
class VesselListPanelController : Initializable, MessageListener { 15 18 class VesselListPanelController : Initializable, MessageListener {
@FXML 16 19 @FXML
var shipListView: ListView<Int> = ListView() 17 20 var shipListView: ListView<String?> = ListView()
18 21
22 private var shipList: ObservableList<String?> = FXCollections.observableArrayList()
19 23
private var shipList: ObservableList<Int> = FXCollections.observableArrayList() 20
21
override fun initialize(location: URL?, resources: ResourceBundle?) { 22 24 override fun initialize(location: URL?, resources: ResourceBundle?) {
25
26
shipListView.items = shipList 23 27 shipListView.items = shipList
observableVessel.listeners.add(this) 24 28 observableVessel.listeners.add(this)
shipListView.selectionModel.selectedItemProperty().addListener { _, _, newValue -> 25 29 shipListView.selectionModel.selectedItemProperty().addListener { _, _, newValue ->
observableSelectedVessel.vessel = observableVessel.vessels[newValue]!! 26 30 if (newValue == null) {
31 observableSelectedVessel.vessel = Vessel(null)
32 } else {
33 observableSelectedVessel.vessel = observableVessel.vessels[newValue]!!
34 }
} 27 35 }
36 setCellFactory()
} 28 37 }
29 38
override fun onValueChanged(newValue: MutableMap<Int?, Vessel>) { 30 39 override fun onValueChanged(newValue: MutableMap<String?, Vessel>) {
shipList.clear() 31 40 shipList.clear()
shipList.addAll(newValue.keys) 32 41 shipList.addAll(newValue.keys)
} 33 42 }
34 43
44 private fun setCellFactory() {
45 val selectionModel: MultipleSelectionModel<String?>? = shipListView.selectionModel
46 selectionModel?.selectionMode = SelectionMode.SINGLE
47 shipListView.setCellFactory {
48 val cell = ListCell<String?>()
49 cell.textProperty().bind(cell.itemProperty())
50 cell.addEventFilter(MouseEvent.MOUSE_PRESSED) { event: MouseEvent ->
51 shipListView.requestFocus()
52 if (!cell.isEmpty) {
53 val index = cell.index
54 if (selectionModel!!.selectedIndices.contains(index)) {
55 selectionModel.clearSelection()
56 } else {
57 selectionModel.select(index)
58 }
59 event.consume()
60 }
61 }
62 cell
src/main/kotlin/application/model/Message.kt View file @ f39d90e
package application.model 1 1 package application.model
2 2
import java.time.LocalDateTime 3 3 import java.time.LocalDateTime
4 4
class Message(split: List<String>) { 5 5 class Message(split: List<String>) {
val mmsi = MMSI(split[0].toIntOrNull()) 6 6 val mmsi = MMSI(if (split[0] == "") null else split[0])
val time = Time(LocalDateTime.parse(split[1])) 7 7 val time = Time(LocalDateTime.parse(split[1]))
val latitude = Latitude(split[2].toDoubleOrNull()) 8 8 val latitude = Latitude(split[2].toDoubleOrNull())
val longitude = Longitude(split[3].toDoubleOrNull()) 9 9 val longitude = Longitude(split[3].toDoubleOrNull())
val speedOverGround = SpeedOverGround(split[4].toDoubleOrNull()) 10 10 val speedOverGround = SpeedOverGround(split[4].toDoubleOrNull())
val courseOverGround = CourseOverGround(split[5].toDoubleOrNull()) 11 11 val courseOverGround = CourseOverGround(split[5].toDoubleOrNull())
val heading = Heading(split[6].toDoubleOrNull()) 12 12 val heading = Heading(split[6].toDoubleOrNull())
val vesselName = VesselName(if (split[7] == "") null else split[7]) 13 13 val vesselName = VesselName(if (split[7] == "") null else split[7])
val imo = IMO(if (split[8] == "") null else split[8]) 14 14 val imo = IMO(if (split[8] == "") null else split[8])
val callSign = CallSign(if (split[9] == "") null else split[9]) 15 15 val callSign = CallSign(if (split[9] == "") null else split[9])
val vesselType = VesselType(split[10].toIntOrNull()) 16 16 val vesselType = VesselType(split[10].toIntOrNull())
val status = Status(if (split[11] == "") null else split[11]) 17 17 val status = Status(if (split[11] == "") null else split[11])
val length = Length(split[12].toDoubleOrNull()) 18 18 val length = Length(split[12].toDoubleOrNull())
val width = Width(split[13].toDoubleOrNull()) 19 19 val width = Width(split[13].toDoubleOrNull())
val draft = Draft(split[14].toDoubleOrNull()) 20 20 val draft = Draft(split[14].toDoubleOrNull())
val cargo = Cargo(split[15].toIntOrNull()) 21 21 val cargo = Cargo(split[15].toIntOrNull())
22 22
23
fun getHexColorStroke(): String { 24 23 fun getHexColorStroke(): String {
var hex = Integer.toHexString(this.mmsi.value!!) 25 24 var hex = Integer.toHexString(this.mmsi.value?.toInt()!!)
if (hex.length > 6) { 26 25 if (hex.length > 6) {
hex = hex.substring(hex.length - 6) 27 26 hex = hex.substring(hex.length - 6)
} 28 27 }
return hex 29 28 return hex
src/main/kotlin/application/model/MessageData.kt View file @ f39d90e
package application.model 1 1 package application.model
2 2
import java.time.LocalDateTime 3 3 import java.time.LocalDateTime
4 4
interface MessageDataVisitor { 5 5 interface MessageDataVisitor {
fun visit(messageData: MMSI) 6 6 fun visit(messageData: MMSI)
fun visit(messageData: Time) 7 7 fun visit(messageData: Time)
fun visit(messageData: Latitude) 8 8 fun visit(messageData: Latitude)
fun visit(messageData: Longitude) 9 9 fun visit(messageData: Longitude)
fun visit(messageData: SpeedOverGround) 10 10 fun visit(messageData: SpeedOverGround)
fun visit(messageData: CourseOverGround) 11 11 fun visit(messageData: CourseOverGround)
fun visit(messageData: Heading) 12 12 fun visit(messageData: Heading)
fun visit(messageData: VesselName) 13 13 fun visit(messageData: VesselName)
fun visit(messageData: IMO) 14 14 fun visit(messageData: IMO)
fun visit(messageData: CallSign) 15 15 fun visit(messageData: CallSign)
fun visit(messageData: VesselType) 16 16 fun visit(messageData: VesselType)
fun visit(messageData: Status) 17 17 fun visit(messageData: Status)
fun visit(messageData: Length) 18 18 fun visit(messageData: Length)
fun visit(messageData: Width) 19 19 fun visit(messageData: Width)
fun visit(messageData: Draft) 20 20 fun visit(messageData: Draft)
fun visit(messageData: Cargo) 21 21 fun visit(messageData: Cargo)
} 22 22 }
23 23
interface MessageData { 24 24 interface MessageData {
25 25
fun accept(visitor: MessageDataVisitor) 26 26 fun accept(visitor: MessageDataVisitor)
27 27
} 28 28 }
29 29
data class MMSI(val value: Int?) : MessageData { 30 30 data class MMSI(val value: String?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 31 31 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 32 32 }
33 33
data class Time(val value: LocalDateTime) : MessageData { 34 34 data class Time(val value: LocalDateTime) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 35 35 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 36 36 }
37 37
data class Latitude(val value: Double?) : MessageData { 38 38 data class Latitude(val value: Double?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 39 39 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 40 40 }
41 41
data class Longitude(val value: Double?) : MessageData { 42 42 data class Longitude(val value: Double?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 43 43 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 44 44 }
45 45
data class SpeedOverGround(val value: Double?) : MessageData { 46 46 data class SpeedOverGround(val value: Double?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 47 47 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 48 48 }
49 49
data class CourseOverGround(val value: Double?) : MessageData { 50 50 data class CourseOverGround(val value: Double?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 51 51 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 52 52 }
53 53
data class Heading(val value: Double?) : MessageData { 54 54 data class Heading(val value: Double?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 55 55 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 56 56 }
57 57
data class VesselName(val value: String?) : MessageData { 58 58 data class VesselName(val value: String?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 59 59 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 60 60 }
61 61
data class IMO(val value: String?) : MessageData { 62 62 data class IMO(val value: String?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 63 63 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 64 64 }
65 65
data class CallSign(val value: String?) : MessageData { 66 66 data class CallSign(val value: String?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 67 67 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 68 68 }
69 69
data class VesselType(val value: Int?) : MessageData { 70 70 data class VesselType(val value: Int?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 71 71 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 72 72 }
73 73
data class Status(val value: String?) : MessageData { 74 74 data class Status(val value: String?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 75 75 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 76 76 }
77 77
data class Length(val value: Double?) : MessageData { 78 78 data class Length(val value: Double?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 79 79 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 80 80 }
81 81
data class Width(val value: Double?) : MessageData { 82 82 data class Width(val value: Double?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 83 83 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 84 84 }
85 85
data class Draft(val value: Double?) : MessageData { 86 86 data class Draft(val value: Double?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 87 87 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 88 88 }
89 89
data class Cargo(val value: Int?) : MessageData { 90 90 data class Cargo(val value: Int?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 91 91 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 92 92 }
93 93
class GetValueVisitor() : MessageDataVisitor { 94 94 class GetValueVisitor() : MessageDataVisitor {
var value: String = "" 95 95 var value: String = ""
96 96
override fun visit(messageData: MMSI) { 97 97 override fun visit(messageData: MMSI) {
value = messageData.value.toString() 98 98 value = messageData.value.toString()
} 99 99 }
100 100
override fun visit(messageData: Time) { 101 101 override fun visit(messageData: Time) {
value = messageData.value.toString() 102 102 value = messageData.value.toString()
} 103 103 }
104 104
override fun visit(messageData: Latitude) { 105 105 override fun visit(messageData: Latitude) {
value = messageData.value.toString() 106 106 value = messageData.value.toString()
} 107 107 }
108 108
override fun visit(messageData: Longitude) { 109 109 override fun visit(messageData: Longitude) {
value = messageData.value.toString() 110 110 value = messageData.value.toString()
} 111 111 }
112 112
override fun visit(messageData: SpeedOverGround) { 113 113 override fun visit(messageData: SpeedOverGround) {
value = messageData.value.toString() 114 114 value = messageData.value.toString()
} 115 115 }
116 116
override fun visit(messageData: CourseOverGround) { 117 117 override fun visit(messageData: CourseOverGround) {
value = messageData.value.toString() 118 118 value = messageData.value.toString()
} 119 119 }
120 120
override fun visit(messageData: Heading) { 121 121 override fun visit(messageData: Heading) {
value = messageData.value.toString() 122 122 value = messageData.value.toString()
} 123 123 }
src/main/kotlin/application/model/MessageListener.kt View file @ f39d90e
package application.model 1 1 package application.model
2 2
interface MessageListener { 3 3 interface MessageListener {
fun onValueChanged(newValue: MutableMap<Int?, Vessel>) 4 4 fun onValueChanged(newValue: MutableMap<String?, Vessel>)
} 5 5 }
src/main/kotlin/application/model/ObservableVessel.kt View file @ f39d90e
package application.model 1 1 package application.model
2 2
import kotlin.properties.Delegates 3 3 import kotlin.properties.Delegates
4 4
class ObservableVessel { 5 5 class ObservableVessel {
val listeners: MutableList<MessageListener> = mutableListOf() 6 6 val listeners: MutableList<MessageListener> = mutableListOf()
7 7
var vessels: MutableMap<Int?, Vessel> by Delegates.observable( 8 8 var vessels: MutableMap<String?, Vessel> by Delegates.observable(
initialValue = mutableMapOf(), 9 9 initialValue = mutableMapOf(),
onChange = { _, _, new -> 10 10 onChange = { _, _, new ->
run { 11 11 run {
observableSelectedVessel.vessel = Vessel(null) 12 12 observableSelectedVessel.vessel = Vessel(null)
listeners.forEach { 13 13 listeners.forEach {
it.onValueChanged(new) 14 14 it.onValueChanged(new)
} 15 15 }
} 16 16 }
} 17 17 }
src/main/kotlin/application/model/Vessel.kt View file @ f39d90e
package application.model 1 1 package application.model
2 2
import java.time.LocalDateTime 3 3 import java.time.LocalDateTime
import java.time.ZoneOffset 4 4 import java.time.ZoneOffset
import java.util.* 5 5 import java.util.*
6 6
7 7
class Vessel(val mmsi: Int?) { 8 8 class Vessel(val mmsi: String?) {
val messages: SortedMap<LocalDateTime, Message> = sortedMapOf() 9 9 val messages: SortedMap<LocalDateTime, Message> = sortedMapOf()
10
fun getAllTimeInMilliSeconde(): ArrayList<Long> { 11
val timeList = arrayListOf<Long>() 12
var timeInMilliSeconde: Long 13
messages.forEach { 14
timeInMilliSeconde = it.value.time.value.toEpochSecond(ZoneOffset.UTC).toInt().toLong() 15
timeList.add(timeInMilliSeconde) 16
} 17
return timeList 18
} 19
20 10
fun getAllTime(): ArrayList<MessageData?> { 21 11 fun getAllTime(): ArrayList<MessageData?> {
val timeList = arrayListOf<MessageData?>() 22 12 val timeList = arrayListOf<MessageData?>()
messages.forEach { 23 13 messages.forEach {
timeList.add(it.value.time) 24 14 timeList.add(it.value.time)
} 25 15 }
26 16
return timeList 27 17 return timeList
} 28 18 }
29 19
fun getAllLatitude(): ArrayList<MessageData?> { 30 20 fun getAllLatitude(): ArrayList<MessageData?> {
val latitudeList = arrayListOf<MessageData?>() 31 21 val latitudeList = arrayListOf<MessageData?>()
messages.forEach { 32 22 messages.forEach {
latitudeList.add(it.value.latitude) 33 23 latitudeList.add(it.value.latitude)
} 34 24 }
35 25
return latitudeList 36 26 return latitudeList
} 37 27 }
38 28
fun getAllLongitude(): ArrayList<MessageData?> { 39 29 fun getAllLongitude(): ArrayList<MessageData?> {
val longitudeList = arrayListOf<MessageData?>() 40 30 val longitudeList = arrayListOf<MessageData?>()
messages.forEach { 41 31 messages.forEach {
longitudeList.add(it.value.longitude) 42 32 longitudeList.add(it.value.longitude)
} 43 33 }
44 34
return longitudeList 45 35 return longitudeList
} 46 36 }
47 37
fun getAllSpeedOverGround(): ArrayList<MessageData?> { 48 38 fun getAllSpeedOverGround(): ArrayList<MessageData?> {
val speedOverGroundList = arrayListOf<MessageData?>() 49 39 val speedOverGroundList = arrayListOf<MessageData?>()
messages.forEach { 50 40 messages.forEach {
speedOverGroundList.add(it.value.speedOverGround) 51 41 speedOverGroundList.add(it.value.speedOverGround)
} 52 42 }
53 43
return speedOverGroundList 54 44 return speedOverGroundList
} 55 45 }
56 46
fun getAllCourseOverGround(): ArrayList<MessageData?> { 57 47 fun getAllCourseOverGround(): ArrayList<MessageData?> {
val res = arrayListOf<MessageData?>() 58 48 val res = arrayListOf<MessageData?>()
messages.forEach { 59 49 messages.forEach {
res.add(it.value.courseOverGround) 60 50 res.add(it.value.courseOverGround)
} 61 51 }
62 52
return res 63 53 return res
} 64 54 }
65 55
fun getAllHeading(): ArrayList<MessageData?> { 66 56 fun getAllHeading(): ArrayList<MessageData?> {
val res = arrayListOf<MessageData?>() 67 57 val res = arrayListOf<MessageData?>()
messages.forEach { 68 58 messages.forEach {
res.add(it.value.heading) 69 59 res.add(it.value.heading)
} 70 60 }
71 61
return res 72 62 return res
} 73 63 }
74 64
fun getAllVesselName(): ArrayList<MessageData?> { 75 65 fun getAllVesselName(): ArrayList<MessageData?> {
val res = arrayListOf<MessageData?>() 76 66 val res = arrayListOf<MessageData?>()
messages.forEach { 77 67 messages.forEach {
res.add(it.value.vesselName) 78 68 res.add(it.value.vesselName)
} 79 69 }
return res 80 70 return res
} 81 71 }
82 72
fun getAllIMO(): ArrayList<MessageData?> { 83 73 fun getAllIMO(): ArrayList<MessageData?> {
val res = arrayListOf<MessageData?>() 84 74 val res = arrayListOf<MessageData?>()
messages.forEach { 85 75 messages.forEach {
res.add(it.value.imo) 86 76 res.add(it.value.imo)
} 87 77 }
return res 88 78 return res
} 89 79 }
90 80
fun getAllCallSign(): ArrayList<MessageData?> { 91 81 fun getAllCallSign(): ArrayList<MessageData?> {
val res = arrayListOf<MessageData?>() 92 82 val res = arrayListOf<MessageData?>()
messages.forEach { 93 83 messages.forEach {
res.add(it.value.callSign) 94 84 res.add(it.value.callSign)
} 95 85 }
return res 96 86 return res
} 97 87 }
98 88
fun getAllVesselType(): ArrayList<MessageData?> { 99 89 fun getAllVesselType(): ArrayList<MessageData?> {
val res = arrayListOf<MessageData?>() 100 90 val res = arrayListOf<MessageData?>()
messages.forEach { 101 91 messages.forEach {
res.add(it.value.vesselType) 102 92 res.add(it.value.vesselType)
} 103 93 }
return res 104 94 return res
} 105 95 }
106 96
fun getAllStatus(): ArrayList<MessageData?> { 107 97 fun getAllStatus(): ArrayList<MessageData?> {
val res = arrayListOf<MessageData?>() 108 98 val res = arrayListOf<MessageData?>()
messages.forEach { 109 99 messages.forEach {
res.add(it.value.status) 110 100 res.add(it.value.status)
} 111 101 }
return res 112 102 return res
} 113 103 }
114 104
fun getAllLength(): ArrayList<MessageData?> { 115 105 fun getAllLength(): ArrayList<MessageData?> {
val res = arrayListOf<MessageData?>() 116 106 val res = arrayListOf<MessageData?>()
messages.forEach { 117 107 messages.forEach {
res.add(it.value.length) 118 108 res.add(it.value.length)
} 119 109 }
return res 120 110 return res
} 121 111 }
122 112
src/main/kotlin/application/model/VesselGenerator.kt View file @ f39d90e
package application.model 1 1 package application.model
2 2
import java.io.File 3 3 import java.io.File
import java.util.* 4 4 import java.util.*
import kotlin.collections.ArrayList 5 5 import kotlin.collections.ArrayList
6 6
fun createVesselCollection(file: File) : SortedMap<Int, Vessel> { 7 7 fun createVesselCollection(file: File) : SortedMap<String, Vessel> {
val messages : ArrayList<Message> = arrayListOf() 8 8 val messages : ArrayList<Message> = arrayListOf()
val vessels: SortedMap<Int, Vessel> = sortedMapOf() 9 9 val vessels: SortedMap<String, Vessel> = sortedMapOf()
10 10
file.forEachLine { 11 11 file.forEachLine {
val arrayMessage = it.split(",") 12 12 val arrayMessage = it.split(",")
if (arrayMessage[0].toIntOrNull() !== null) { 13 13 if (arrayMessage[0].toIntOrNull() !== null) {
val message = Message(arrayMessage) 14 14 val message = Message(arrayMessage)
messages.add(message) 15 15 messages.add(message)
if (!vessels.containsKey(message.mmsi.value)){ 16 16 if (!vessels.containsKey(message.mmsi.value)){
vessels[message.mmsi.value] = Vessel(message.mmsi.value!!) 17 17 vessels[message.mmsi.value] = Vessel(message.mmsi.value!!)
} 18 18 }
vessels[message.mmsi.value]?.messages?.set(message.time.value, message) 19 19 vessels[message.mmsi.value]?.messages?.set(message.time.value, message)
} 20 20 }
21 21
} 22 22 }
src/main/kotlin/map/MapDisplayer.kt View file @ f39d90e
package map 1 1 package map
2 2
import application.model.observableVessel 3 3 import application.model.observableVessel
4 4
fun clearMap(map: LeafletMapView) { 5 5 fun clearMap(map: LeafletMapView) {
clearMapCanvas(map) 6 6 clearMapCanvas(map)
clearMapCluster(map) 7 7 clearMapCluster(map)
clearHeatMap(map) 8 8 clearHeatMap(map)
} 9 9 }
10 10
fun clearMapCluster(map: LeafletMapView) { 11 11 fun clearMapCluster(map: LeafletMapView) {
map.execScript( 12 12 map.execScript(
""" 13 13 """
|myMap.removeLayer(markerClusters); 14 14 |myMap.removeLayer(markerClusters);
|var markerClusters = L.markerClusterGroup({spiderfyOnMaxZoom: false, disableClusteringAtZoom: 10}); 15 15 |var markerClusters = L.markerClusterGroup({spiderfyOnMaxZoom: false, disableClusteringAtZoom: 10});
""".trimMargin() 16 16 """.trimMargin()
) 17 17 )
} 18 18 }
19 19
fun clearMapCanvas(map: LeafletMapView) { 20 20 fun clearMapCanvas(map: LeafletMapView) {
map.execScript( 21 21 map.execScript(
""" 22 22 """
|myRenderer.removeFrom(myMap); 23 23 |myRenderer.removeFrom(myMap);
|var myRenderer = L.canvas({ padding: 0.5 }); 24 24 |var myRenderer = L.canvas({ padding: 0.5 });
""".trimMargin() 25 25 """.trimMargin()
) 26 26 )
} 27 27 }
28 28
fun clearHeatMap(map: LeafletMapView) { 29 29 fun clearHeatMap(map: LeafletMapView) {
map.execScript( 30 30 map.execScript(
""" 31 31 """
|heatLayer.removeFrom(myMap); 32 32 |heatLayer.removeFrom(myMap);
|var heatLayer = L.heatLayer([]).addTo(myMap); 33 33 |var heatLayer = L.heatLayer([]).addTo(myMap);
""".trimMargin() 34 34 """.trimMargin()
) 35 35 )
} 36 36 }
37 37
fun displayAllMessageOnMap(map: LeafletMapView) { 38 38 fun displayAllMessageOnMap(map: LeafletMapView) {
clearMap(map) 39 39 clearMap(map)
observableVessel.vessels.forEach { (_, value) -> 40 40 observableVessel.vessels.forEach { (_, value) ->
value.messages.forEach { (_, message) -> 41 41 value.messages.forEach { (_, message) ->
map.execScript("L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {renderer: myRenderer, radius: 0.01, color: '#${message.getHexColorStroke()}'}).addTo(myMap)") 42 42 map.execScript("L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {renderer: myRenderer, radius: 0.01, color: '#${message.getHexColorStroke()}'}).addTo(myMap)")
} 43 43 }
} 44 44 }
} 45 45 }
46 46
fun displayAllMessageOnMap(map: LeafletMapView, selectedMMSI: Int) { 47 47 fun displayAllMessageOnMap(map: LeafletMapView, selectedMMSI: String) {
clearMap(map) 48 48 clearMap(map)
observableVessel.vessels.forEach { (_, value) -> 49 49 observableVessel.vessels.forEach { (_, value) ->
value.messages.forEach { (_, message) -> 50 50 value.messages.forEach { (_, message) ->
if (selectedMMSI == message.mmsi.value) { 51 51 if (selectedMMSI == message.mmsi.value) {
map.execScript("L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {renderer: myRenderer, radius: 2, color: '#ff4040'}).addTo(myMap)") 52 52 map.execScript("L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {renderer: myRenderer, radius: 2, color: '#ff4040'}).addTo(myMap)")
} else { 53 53 } else {
map.execScript("L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {renderer: myRenderer, radius: 0.01, color: '#${message.getHexColorStroke()}'}).addTo(myMap)") 54 54 map.execScript("L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {renderer: myRenderer, radius: 0.01, color: '#${message.getHexColorStroke()}'}).addTo(myMap)")
} 55 55 }
} 56 56 }
} 57 57 }
} 58 58 }
59 59
fun displayClusterMessageOnMap(map: LeafletMapView) { 60 60 fun displayClusterMessageOnMap(map: LeafletMapView) {
clearMap(map) 61 61 clearMap(map)
observableVessel.vessels.forEach { (_, value) -> 62 62 observableVessel.vessels.forEach { (_, value) ->
value.messages.forEach { (_, message) -> 63 63 value.messages.forEach { (_, message) ->
map.execScript("markerClusters.addLayer(L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {renderer: myRenderer, radius: 0.01, color: '#${message.getHexColorStroke()}'}));") 64 64 map.execScript("markerClusters.addLayer(L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {renderer: myRenderer, radius: 0.01, color: '#${message.getHexColorStroke()}'}));")
} 65 65 }
} 66 66 }
map.execScript("myMap.addLayer(markerClusters);") 67 67 map.execScript("myMap.addLayer(markerClusters);")
} 68 68 }
69 69
fun displayClusterMessageOnMap(map: LeafletMapView, selectedMMSI: Int) { 70 70 fun displayClusterMessageOnMap(map: LeafletMapView, selectedMMSI: String) {
clearMap(map) 71 71 clearMap(map)
observableVessel.vessels.forEach { (_, value) -> 72 72 observableVessel.vessels.forEach { (_, value) ->
value.messages.forEach { (_, message) -> 73 73 value.messages.forEach { (_, message) ->
if (selectedMMSI == message.mmsi.value) { 74 74 if (selectedMMSI == message.mmsi.value) {
map.execScript("L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {renderer: myRenderer, radius: 2, color: '#ff4040'}).addTo(myMap);") 75 75 map.execScript("L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {renderer: myRenderer, radius: 2, color: '#ff4040'}).addTo(myMap);")
} else { 76 76 } else {
map.execScript("markerClusters.addLayer(L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {renderer: myRenderer, radius: 0.01, color: '#${message.getHexColorStroke()}'}));") 77 77 map.execScript("markerClusters.addLayer(L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {renderer: myRenderer, radius: 0.01, color: '#${message.getHexColorStroke()}'}));")
} 78 78 }
} 79 79 }
} 80 80 }
map.execScript("myMap.addLayer(markerClusters);") 81 81 map.execScript("myMap.addLayer(markerClusters);")
} 82 82 }
83 83
fun displayHeatMapOnMap(map: LeafletMapView) { 84 84 fun displayHeatMapOnMap(map: LeafletMapView) {
clearMap(map) 85 85 clearMap(map)
observableVessel.vessels.forEach { (_, value) -> 86 86 observableVessel.vessels.forEach { (_, value) ->
value.messages.forEach { (_, message) -> 87 87 value.messages.forEach { (_, message) ->
map.execScript("heatLayer.addLatLng([${message.latitude.value}, ${message.longitude.value}]);") 88 88 map.execScript("heatLayer.addLatLng([${message.latitude.value}, ${message.longitude.value}]);")
} 89 89 }
} 90 90 }
} 91 91 }
92 92
fun displayHeatMapOnMap(map: LeafletMapView, selectedMMSI: Int) { 93 93 fun displayHeatMapOnMap(map: LeafletMapView, selectedMMSI: String) {
clearMap(map) 94 94 clearMap(map)
observableVessel.vessels.forEach { (_, value) -> 95 95 observableVessel.vessels.forEach { (_, value) ->
value.messages.forEach { (_, message) -> 96 96 value.messages.forEach { (_, message) ->
if (selectedMMSI == message.mmsi.value) { 97 97 if (selectedMMSI == message.mmsi.value) {
src/main/resources/gui/vesselListPanel.fxml View file @ f39d90e
<?xml version="1.0" encoding="UTF-8"?> 1 1 <?xml version="1.0" encoding="UTF-8"?>
2 2
3 <?import javafx.geometry.*?>
<?import javafx.scene.control.*?> 3 4 <?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?> 4 5 <?import javafx.scene.layout.*?>
6 <?import javafx.scene.text.*?>
5 7
<BorderPane prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.controller.VesselListPanelController"> 6 8 <BorderPane prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.controller.VesselListPanelController">
7
<top> 8
<AnchorPane prefHeight="33.0" prefWidth="200.0" BorderPane.alignment="CENTER"> 9
<children> 10
<Button layoutX="74.0" layoutY="2.0" mnemonicParsing="false" text="Button" fx:id="button"/> 11
</children></AnchorPane> 12
</top> 13
<center> 14 9 <center>
<ListView fx:id="shipListView" prefHeight="105.0" prefWidth="200.0" /> 15 10 <ListView fx:id="shipListView" prefHeight="50.0" prefWidth="200.0" />
</center> 16 11 </center>
12 <top>
13 <TextFlow prefHeight="28.0" prefWidth="200.0" style="-fx-font-weight: bold;" textAlignment="CENTER" BorderPane.alignment="CENTER">
14 <children>
15 <Text scaleX="1.5" scaleY="1.5" strokeType="OUTSIDE" strokeWidth="0.0" text="MMSI" textAlignment="CENTER" />
16 </children>
17 <BorderPane.margin>
18 <Insets />
19 </BorderPane.margin>
20 <padding>
21 <Insets top="5.0" />
22 </padding>
23 </TextFlow>
24 </top>