Commit 513c0341c54e1d2ef6dbd1eeb624830faab35ad7
1 parent
07bf03cd80
Exists in
master
and in
1 other branch
add chart
Showing 11 changed files with 670 additions and 55 deletions Inline Diff
- src/main/kotlin/application/VisualisationChart.kt
- src/main/kotlin/application/controller/DataPanelController.kt
- src/main/kotlin/application/controller/VesselListPanelController.kt
- src/main/kotlin/application/model/Message.kt
- src/main/kotlin/application/model/MessageData.kt
- src/main/kotlin/application/model/Vessel.kt
- src/main/kotlin/application/model/VesselGenerator.kt
- src/main/kotlin/map/MapDisplayer.kt
- src/main/resources/gui/dataPanel.fxml
- src/main/resources/gui/vesselListPanel.fxml
- src/main/resources/gui/windows.fxml
src/main/kotlin/application/VisualisationChart.kt
View file @
513c034
| File was created | 1 | package application | ||
| 2 | ||||
| 3 | import javafx.scene.chart.Axis | |||
| 4 | import javafx.scene.chart.ScatterChart | |||
| 5 |
src/main/kotlin/application/controller/DataPanelController.kt
View file @
513c034
| File was created | 1 | package application.controller | ||
| 2 | ||||
| 3 | import application.model.* | |||
| 4 | import javafx.collections.FXCollections | |||
| 5 | import javafx.collections.ObservableList | |||
| 6 | import javafx.fxml.FXML | |||
| 7 | import javafx.fxml.Initializable | |||
| 8 | import javafx.scene.chart.CategoryAxis | |||
| 9 | import javafx.scene.chart.NumberAxis | |||
| 10 | import javafx.scene.chart.ScatterChart | |||
| 11 | import javafx.scene.chart.XYChart.Data | |||
| 12 | import javafx.scene.chart.XYChart.Series | |||
| 13 | import javafx.scene.control.ListCell | |||
| 14 | import javafx.scene.control.ListView | |||
| 15 | import java.net.URL | |||
| 16 | import java.util.* | |||
| 17 | ||||
| 18 | ||||
| 19 | class DataPanelController : Initializable, SelectedVesselListener { | |||
| 20 | private var dataList: ObservableList<Pair<String, ArrayList<MessageData?>>> = FXCollections.observableArrayList() | |||
| 21 | private lateinit var timeData: ArrayList<MessageData?> | |||
| 22 | ||||
| 23 | @FXML | |||
| 24 | var dataListView = ListView<Pair<String, ArrayList<MessageData?>>>() | |||
| 25 | ||||
| 26 | @FXML | |||
| 27 | var xaxisNumber: CategoryAxis = CategoryAxis() | |||
| 28 | ||||
| 29 | @FXML | |||
| 30 | var yaxisNumber: NumberAxis = NumberAxis() | |||
| 31 | ||||
| 32 | @FXML | |||
| 33 | lateinit var scatterChartNumber: ScatterChart<String, Number> | |||
| 34 | ||||
| 35 | @FXML | |||
| 36 | var xaxisCategory: CategoryAxis = CategoryAxis() | |||
| 37 | ||||
| 38 | @FXML | |||
| 39 | var yaxisCategory: CategoryAxis = CategoryAxis() | |||
| 40 | ||||
| 41 | @FXML | |||
| 42 | lateinit var scatterChartCategory: ScatterChart<String, String> | |||
| 43 | ||||
| 44 | override fun initialize(location: URL?, resources: ResourceBundle?) { | |||
| 45 | xaxisNumber.animated = false | |||
| 46 | yaxisNumber.animated = false | |||
| 47 | xaxisCategory.animated = false | |||
| 48 | yaxisCategory.animated = false | |||
| 49 | setObservableSelectedVesselListener() | |||
| 50 | dataListView.items = dataList | |||
| 51 | ||||
| 52 | ||||
| 53 | ||||
| 54 | dataListView.setCellFactory { | |||
| 55 | object : ListCell<Pair<String, ArrayList<MessageData?>>?>() { | |||
| 56 | override fun updateItem(item: Pair<String, ArrayList<MessageData?>>?, empty: Boolean) { | |||
| 57 | super.updateItem(item, empty) | |||
| 58 | text = if (empty) { | |||
| 59 | null | |||
| 60 | } else { | |||
| 61 | item?.first | |||
| 62 | } | |||
| 63 | } | |||
| 64 | } | |||
| 65 | } | |||
| 66 | ||||
| 67 | dataListView.selectionModel.selectedItemProperty().addListener { _, _, newValue -> | |||
| 68 | if (newValue == null){ | |||
| 69 | scatterChartCategory.data.clear() | |||
| 70 | scatterChartNumber.data.clear() | |||
| 71 | return@addListener | |||
| 72 | } | |||
| 73 | val serieNumber = Series<String, Number>() | |||
| 74 | val serieString = Series<String, String>() | |||
| 75 | ||||
| 76 | val getValueVisitorX = GetValueVisitor() | |||
| 77 | val getValueVisitorY = GetValueVisitor() | |||
| 78 | ||||
| 79 | ||||
| 80 | for (x in 0 until newValue?.second?.size!!) { | |||
| 81 | timeData[x]?.accept(getValueVisitorX) | |||
| 82 | newValue.second[x]?.accept(getValueVisitorY) | |||
| 83 | ||||
| 84 | if (getValueVisitorY.value.toDoubleOrNull() == null){ | |||
| 85 | serieString.data.add(Data<String, String>(getValueVisitorX.value, getValueVisitorY.value)) | |||
| 86 | } else{ | |||
| 87 | serieNumber.data.add(Data<String, Number>(getValueVisitorX.value, getValueVisitorY.value.toDouble())) | |||
| 88 | } | |||
| 89 | ||||
| 90 | } | |||
| 91 | ||||
| 92 | scatterChartNumber.data.clear() | |||
| 93 | scatterChartCategory.data.clear() | |||
| 94 | ||||
| 95 | if (getValueVisitorY.value.toDoubleOrNull() == null){ | |||
| 96 | serieString.data.add(Data<String, String>(getValueVisitorX.value, getValueVisitorY.value)) | |||
| 97 | scatterChartCategory.data.addAll(serieString) | |||
| 98 | setChartCategoryVisible() | |||
| 99 | xaxisCategory.label = "Date" | |||
| 100 | yaxisCategory.label = newValue.first | |||
| 101 | } else{ | |||
| 102 | serieNumber.data.add(Data<String, Number>(getValueVisitorX.value, getValueVisitorY.value.toDouble())) | |||
| 103 | scatterChartNumber.data.addAll(serieNumber) | |||
| 104 | setChartNumberVisible() | |||
| 105 | xaxisNumber.label = "Date" | |||
| 106 | yaxisNumber.label = newValue.first | |||
| 107 | } | |||
| 108 | ||||
| 109 | } | |||
| 110 | ||||
| 111 | } | |||
| 112 | ||||
| 113 | private fun setChartCategoryVisible(){ | |||
| 114 | scatterChartCategory.isVisible = true | |||
| 115 | scatterChartNumber.isVisible = false | |||
| 116 | } | |||
| 117 | ||||
| 118 | private fun setChartNumberVisible(){ | |||
| 119 | scatterChartCategory.isVisible = false | |||
| 120 | scatterChartNumber.isVisible = true | |||
| 121 | } | |||
| 122 | ||||
| 123 | private fun setObservableSelectedVesselListener() { | |||
| 124 | observableSelectedVessel.listeners.add(this) | |||
| 125 | } | |||
| 126 | ||||
| 127 | private fun populateTime(vessel: Vessel): ArrayList<MessageData?> { | |||
| 128 | val allTime: ArrayList<MessageData?> = vessel.getAllTime() | |||
| 129 | allTime.sortBy { (it as Time).value } | |||
| 130 | ||||
| 131 | return allTime | |||
| 132 | } | |||
| 133 | ||||
| 134 | private fun populateLatitude(vessel: Vessel): ArrayList<MessageData?> { | |||
| 135 | val allLatitude: ArrayList<MessageData?> = vessel.getAllLatitude() | |||
| 136 | allLatitude.sortBy { (it as Latitude).value } | |||
| 137 | ||||
| 138 | return allLatitude | |||
| 139 | } | |||
| 140 | ||||
| 141 | private fun populateLongitude(vessel: Vessel): ArrayList<MessageData?> { | |||
| 142 | val allLongitude: ArrayList<MessageData?> = vessel.getAllLongitude() | |||
| 143 | allLongitude.sortBy { (it as Longitude).value } | |||
| 144 | ||||
| 145 | return allLongitude | |||
| 146 | } | |||
| 147 | ||||
| 148 | private fun populateSpeedOverGround(vessel: Vessel): ArrayList<MessageData?> { | |||
| 149 | val allSpeedOverGround: ArrayList<MessageData?> = vessel.getAllSpeedOverGround() | |||
| 150 | allSpeedOverGround.sortBy { (it as SpeedOverGround).value } | |||
| 151 | ||||
| 152 | return allSpeedOverGround | |||
| 153 | } | |||
| 154 | ||||
| 155 | private fun populateCourseOverGround(vessel: Vessel): ArrayList<MessageData?> { | |||
| 156 | val allCourseOverGround: ArrayList<MessageData?> = vessel.getAllCourseOverGround() | |||
| 157 | allCourseOverGround.sortBy { (it as CourseOverGround).value } | |||
| 158 | ||||
| 159 | return allCourseOverGround | |||
| 160 | } | |||
| 161 | ||||
| 162 | private fun populateHeading(vessel: Vessel): ArrayList<MessageData?> { | |||
| 163 | val allHeading: ArrayList<MessageData?> = vessel.getAllHeading() | |||
| 164 | allHeading.sortBy { (it as Heading).value } | |||
| 165 | ||||
| 166 | return allHeading | |||
| 167 | } | |||
| 168 | ||||
| 169 | private fun populatVesselName(vessel: Vessel): ArrayList<MessageData?> { | |||
| 170 | val allVesselName: ArrayList<MessageData?> = vessel.getAllVesselName() | |||
| 171 | allVesselName.sortBy { (it as VesselName).value } | |||
| 172 | ||||
| 173 | return allVesselName | |||
| 174 | } | |||
| 175 | ||||
| 176 | private fun populatIMO(vessel: Vessel): ArrayList<MessageData?> { | |||
| 177 | val allIMO: ArrayList<MessageData?> = vessel.getAllIMO() | |||
| 178 | allIMO.sortBy { (it as IMO).value } | |||
| 179 | ||||
| 180 | return allIMO | |||
| 181 | } | |||
| 182 | ||||
| 183 | private fun populatCallSign(vessel: Vessel): ArrayList<MessageData?> { | |||
| 184 | val allCallSign: ArrayList<MessageData?> = vessel.getAllCallSign() | |||
| 185 | allCallSign.sortBy { (it as CallSign).value } | |||
| 186 | ||||
| 187 | return allCallSign | |||
| 188 | } | |||
| 189 | ||||
| 190 | private fun populatVesselType(vessel: Vessel): ArrayList<MessageData?> { | |||
| 191 | val allVesselType: ArrayList<MessageData?> = vessel.getAllVesselType() | |||
| 192 | allVesselType.sortBy { (it as VesselType).value } | |||
| 193 | ||||
| 194 | return allVesselType | |||
| 195 | } | |||
| 196 | ||||
| 197 | private fun populatStatus(vessel: Vessel): ArrayList<MessageData?> { |
src/main/kotlin/application/controller/VesselListPanelController.kt
View file @
513c034
| 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 | 5 | import application.model.observableVessel | |
| import application.model.observableSelectedVessel | 6 | 6 | import application.model.observableSelectedVessel | |
| import javafx.collections.FXCollections | 7 | 7 | import javafx.collections.FXCollections | |
| import javafx.collections.ObservableList | 8 | 8 | import javafx.collections.ObservableList | |
| import javafx.fxml.FXML | 9 | 9 | import javafx.fxml.FXML | |
| import javafx.fxml.Initializable | 10 | 10 | import javafx.fxml.Initializable | |
| import javafx.scene.control.ListView | 11 | 11 | import javafx.scene.control.ListView | |
| import java.net.URL | 12 | 12 | import java.net.URL | |
| import java.util.* | 13 | 13 | import java.util.* | |
| 14 | 14 | |||
| class VesselListPanelController : Initializable, MessageListener { | 15 | 15 | class VesselListPanelController : Initializable, MessageListener { | |
| @FXML | 16 | 16 | @FXML | |
| var shipListView: ListView<Int> = ListView() | 17 | 17 | var shipListView: ListView<Int> = ListView() | |
| 18 | 18 | |||
| 19 | 19 | |||
| var shipList: ObservableList<Int> = FXCollections.observableArrayList() | 20 | 20 | private var shipList: ObservableList<Int> = FXCollections.observableArrayList() | |
| 21 | 21 | |||
| override fun initialize(location: URL?, resources: ResourceBundle?) { | 22 | 22 | override fun initialize(location: URL?, resources: ResourceBundle?) { | |
| shipListView.items = shipList | 23 | 23 | shipListView.items = shipList | |
| observableVessel.listeners.add(this) | 24 | 24 | observableVessel.listeners.add(this) | |
| shipListView.selectionModel.selectedItemProperty().addListener { _, _, newValue -> | 25 | 25 | shipListView.selectionModel.selectedItemProperty().addListener { _, _, newValue -> | |
| observableSelectedVessel.vessel = observableVessel.vessels[newValue]!! | 26 | 26 | observableSelectedVessel.vessel = observableVessel.vessels[newValue]!! | |
| } | 27 | 27 | } | |
| } | 28 | 28 | } | |
| 29 | 29 |
src/main/kotlin/application/model/Message.kt
View file @
513c034
| 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: Int? = split[0].toIntOrNull() | 6 | 6 | val mmsi = MMSI(split[0].toIntOrNull()) | |
| val time: LocalDateTime = LocalDateTime.parse(split[1]) | 7 | 7 | val time = Time(LocalDateTime.parse(split[1])) | |
| val latitude: Double? = split[2].toDoubleOrNull() | 8 | 8 | val latitude = Latitude(split[2].toDoubleOrNull()) | |
| val longitude: Double? = split[3].toDoubleOrNull() | 9 | 9 | val longitude = Longitude(split[3].toDoubleOrNull()) | |
| val speedOverGround: Double? = split[4].toDoubleOrNull() | 10 | 10 | val speedOverGround = SpeedOverGround(split[4].toDoubleOrNull()) | |
| val courseOverGround: Double? = split[5].toDoubleOrNull() | 11 | 11 | val courseOverGround = CourseOverGround(split[5].toDoubleOrNull()) | |
| val heading: Int? = split[6].toIntOrNull() | 12 | 12 | val heading = Heading(split[6].toDoubleOrNull()) | |
| val vesselName: String? = split[7] | 13 | 13 | val vesselName = VesselName(split[7]) | |
| val imo: String? = split[8] | 14 | 14 | val imo = IMO(split[8]) | |
| val callSign: String? = split[9] | 15 | 15 | val callSign = CallSign(split[9]) | |
| val vesselType: Int? = split[10].toIntOrNull() | 16 | 16 | val vesselType = VesselType(split[10].toIntOrNull()) | |
| val status: String? = split[11] | 17 | 17 | val status = Status(split[11]) | |
| val length: Double? = split[12].toDoubleOrNull() | 18 | 18 | val length = Length(split[12].toDoubleOrNull()) | |
| val width: Double? = split[13].toDoubleOrNull() | 19 | 19 | val width = Width(split[13].toDoubleOrNull()) | |
| val draft: Double? = split[14].toDoubleOrNull() | 20 | 20 | val draft = Draft(split[14].toDoubleOrNull()) | |
| val cargo: Int? = split[15].toIntOrNull() | 21 | 21 | val cargo = Cargo(split[15].toIntOrNull()) | |
| 22 | 22 | |||
| fun getHexColorStroke(): String{ | 23 | |||
| var hex = Integer.toHexString(this.mmsi!!) | 24 | |||
| if (hex.length > 6){ | 25 | |||
| hex = hex.substring(hex.length - 6) | 26 | |||
| } | 27 | |||
| return hex | 28 | |||
| } | 29 | |||
| 30 | 23 | |||
| fun getHexColorFill(): String{ | 31 | 24 | fun getHexColorStroke(): String { | |
| var hex = Integer.toHexString(this.mmsi!! - 50) | 32 | 25 | var hex = Integer.toHexString(this.mmsi.value!!) | |
| if (hex.length > 6){ | 33 | 26 | if (hex.length > 6) { | |
| hex = hex.substring(hex.length - 6) | 34 | 27 | hex = hex.substring(hex.length - 6) | |
| } | 35 | 28 | } | |
| return hex | 36 | 29 | return hex | |
| } | 37 | 30 | } | |
| } | 38 | 31 | } | |
src/main/kotlin/application/model/MessageData.kt
View file @
513c034
| File was created | 1 | package application.model | ||
| 2 | ||||
| 3 | import java.time.LocalDateTime | |||
| 4 | ||||
| 5 | interface MessageDataVisitor { | |||
| 6 | fun visit(messageData: MMSI) | |||
| 7 | fun visit(messageData: Time) | |||
| 8 | fun visit(messageData: Latitude) | |||
| 9 | fun visit(messageData: Longitude) | |||
| 10 | fun visit(messageData: SpeedOverGround) | |||
| 11 | fun visit(messageData: CourseOverGround) | |||
| 12 | fun visit(messageData: Heading) | |||
| 13 | fun visit(messageData: VesselName) | |||
| 14 | fun visit(messageData: IMO) | |||
| 15 | fun visit(messageData: CallSign) | |||
| 16 | fun visit(messageData: VesselType) | |||
| 17 | fun visit(messageData: Status) | |||
| 18 | fun visit(messageData: Length) | |||
| 19 | fun visit(messageData: Width) | |||
| 20 | fun visit(messageData: Draft) | |||
| 21 | fun visit(messageData: Cargo) | |||
| 22 | } | |||
| 23 | ||||
| 24 | interface MessageData { | |||
| 25 | ||||
| 26 | fun accept(visitor: MessageDataVisitor) | |||
| 27 | ||||
| 28 | } | |||
| 29 | ||||
| 30 | data class MMSI(val value: Int?) : MessageData { | |||
| 31 | override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) | |||
| 32 | } | |||
| 33 | ||||
| 34 | data class Time(val value: LocalDateTime) : MessageData { | |||
| 35 | override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) | |||
| 36 | } | |||
| 37 | ||||
| 38 | data class Latitude(val value: Double?) : MessageData { | |||
| 39 | override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) | |||
| 40 | } | |||
| 41 | ||||
| 42 | data class Longitude(val value: Double?) : MessageData { | |||
| 43 | override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) | |||
| 44 | } | |||
| 45 | ||||
| 46 | data class SpeedOverGround(val value: Double?) : MessageData { | |||
| 47 | override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) | |||
| 48 | } | |||
| 49 | ||||
| 50 | data class CourseOverGround(val value: Double?) : MessageData { | |||
| 51 | override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) | |||
| 52 | } | |||
| 53 | ||||
| 54 | data class Heading(val value: Double?) : MessageData { | |||
| 55 | override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) | |||
| 56 | } | |||
| 57 | ||||
| 58 | data class VesselName(val value: String?) : MessageData { | |||
| 59 | override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) | |||
| 60 | } | |||
| 61 | ||||
| 62 | data class IMO(val value: String?) : MessageData { | |||
| 63 | override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) | |||
| 64 | } | |||
| 65 | ||||
| 66 | data class CallSign(val value: String?) : MessageData { | |||
| 67 | override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) | |||
| 68 | } | |||
| 69 | ||||
| 70 | data class VesselType(val value: Int?) : MessageData { | |||
| 71 | override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) | |||
| 72 | } | |||
| 73 | ||||
| 74 | data class Status(val value: String?) : MessageData { | |||
| 75 | override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) | |||
| 76 | } | |||
| 77 | ||||
| 78 | data class Length(val value: Double?) : MessageData { | |||
| 79 | override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) | |||
| 80 | } | |||
| 81 | ||||
| 82 | data class Width(val value: Double?) : MessageData { | |||
| 83 | override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) | |||
| 84 | } | |||
| 85 | ||||
| 86 | data class Draft(val value: Double?) : MessageData { | |||
| 87 | override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) | |||
| 88 | } | |||
| 89 | ||||
| 90 | data class Cargo(val value: Int?) : MessageData { | |||
| 91 | override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) | |||
| 92 | } | |||
| 93 | ||||
| 94 | class GetValueVisitor() : MessageDataVisitor { | |||
| 95 | var value: String = "" | |||
| 96 | ||||
| 97 | override fun visit(messageData: MMSI) { | |||
| 98 | value = messageData.value.toString() | |||
| 99 | } | |||
| 100 | ||||
| 101 | override fun visit(messageData: Time) { | |||
| 102 | value = messageData.value.toString() | |||
| 103 | } | |||
| 104 | ||||
| 105 | override fun visit(messageData: Latitude) { | |||
| 106 | value = messageData.value.toString() | |||
| 107 | } | |||
| 108 | ||||
| 109 | override fun visit(messageData: Longitude) { | |||
| 110 | value = messageData.value.toString() | |||
| 111 | } | |||
| 112 | ||||
| 113 | override fun visit(messageData: SpeedOverGround) { | |||
| 114 | value = messageData.value.toString() | |||
| 115 | } | |||
| 116 | ||||
| 117 | override fun visit(messageData: CourseOverGround) { | |||
| 118 | value = messageData.value.toString() | |||
| 119 | } | |||
| 120 | ||||
| 121 | override fun visit(messageData: Heading) { | |||
| 122 | value = messageData.value.toString() |
src/main/kotlin/application/model/Vessel.kt
View file @
513c034
| package application.model | 1 | 1 | package application.model | |
| 2 | 2 | |||
| import java.time.LocalDateTime | 3 | 3 | import java.time.LocalDateTime | |
| 4 | import java.time.ZoneOffset | |||
| import java.util.* | 4 | 5 | import java.util.* | |
| 5 | 6 | |||
| 6 | 7 | |||
| class Vessel(val mmsi : Int?) { | 7 | 8 | class Vessel(val mmsi: Int?) { | |
| val messages: SortedMap<LocalDateTime, Message> = sortedMapOf() | 8 | 9 | val messages: SortedMap<LocalDateTime, Message> = sortedMapOf() | |
| 10 | ||||
| 11 | fun getAllTimeInMilliSeconde(): ArrayList<Long> { | |||
| 12 | val timeList = arrayListOf<Long>() | |||
| 13 | var timeInMilliSeconde: Long | |||
| 14 | messages.forEach { | |||
| 15 | timeInMilliSeconde = it.value.time.value.toEpochSecond(ZoneOffset.UTC).toInt().toLong() | |||
| 16 | timeList.add(timeInMilliSeconde) | |||
| 17 | } | |||
| 18 | return timeList | |||
| 19 | } | |||
| 20 | ||||
| 21 | fun getAllTime(): ArrayList<MessageData?> { | |||
| 22 | val timeList = arrayListOf<MessageData?>() | |||
| 23 | messages.forEach { | |||
| 24 | timeList.add(it.value.time) | |||
| 25 | } | |||
| 26 | ||||
| 27 | return timeList | |||
| 28 | } | |||
| 29 | ||||
| 30 | fun getAllLatitude(): ArrayList<MessageData?> { | |||
| 31 | val latitudeList = arrayListOf<MessageData?>() | |||
| 32 | messages.forEach { | |||
| 33 | latitudeList.add(it.value.latitude) | |||
| 34 | } | |||
| 35 | ||||
| 36 | return latitudeList | |||
| 37 | } | |||
| 38 | ||||
| 39 | fun getAllLongitude(): ArrayList<MessageData?> { | |||
| 40 | val longitudeList = arrayListOf<MessageData?>() | |||
| 41 | messages.forEach { | |||
| 42 | longitudeList.add(it.value.longitude) | |||
| 43 | } | |||
| 44 | ||||
| 45 | return longitudeList | |||
| 46 | } | |||
| 47 | ||||
| 48 | fun getAllSpeedOverGround(): ArrayList<MessageData?> { | |||
| 49 | val speedOverGroundList = arrayListOf<MessageData?>() | |||
| 50 | messages.forEach { | |||
| 51 | speedOverGroundList.add(it.value.speedOverGround) | |||
| 52 | } | |||
| 53 | ||||
| 54 | return speedOverGroundList | |||
| 55 | } | |||
| 56 | ||||
| 57 | fun getAllCourseOverGround(): ArrayList<MessageData?> { | |||
| 58 | val res = arrayListOf<MessageData?>() | |||
| 59 | messages.forEach { | |||
| 60 | res.add(it.value.courseOverGround) | |||
| 61 | } | |||
| 62 | ||||
| 63 | return res | |||
| 64 | } | |||
| 65 | ||||
| 66 | fun getAllHeading(): ArrayList<MessageData?> { | |||
| 67 | val res = arrayListOf<MessageData?>() | |||
| 68 | messages.forEach { | |||
| 69 | res.add(it.value.heading) | |||
| 70 | } | |||
| 71 | ||||
| 72 | return res | |||
| 73 | } | |||
| 74 | ||||
| 75 | fun getAllVesselName(): ArrayList<MessageData?> { | |||
| 76 | val res = arrayListOf<MessageData?>() | |||
| 77 | messages.forEach { | |||
| 78 | res.add(it.value.vesselName) | |||
| 79 | } | |||
| 80 | return res | |||
| 81 | } | |||
| 82 | ||||
| 83 | fun getAllIMO(): ArrayList<MessageData?> { | |||
| 84 | val res = arrayListOf<MessageData?>() | |||
| 85 | messages.forEach { | |||
| 86 | res.add(it.value.imo) | |||
| 87 | } | |||
| 88 | return res | |||
| 89 | } | |||
| 90 | ||||
| 91 | fun getAllCallSign(): ArrayList<MessageData?> { | |||
| 92 | val res = arrayListOf<MessageData?>() | |||
| 93 | messages.forEach { | |||
| 94 | res.add(it.value.callSign) | |||
| 95 | } | |||
| 96 | return res | |||
| 97 | } | |||
| 98 | ||||
| 99 | fun getAllVesselType(): ArrayList<MessageData?> { | |||
| 100 | val res = arrayListOf<MessageData?>() | |||
| 101 | messages.forEach { | |||
| 102 | res.add(it.value.vesselType) | |||
| 103 | } | |||
| 104 | return res | |||
| 105 | } | |||
| 106 | ||||
| 107 | fun getAllStatus(): ArrayList<MessageData?> { | |||
| 108 | val res = arrayListOf<MessageData?>() | |||
| 109 | messages.forEach { | |||
| 110 | res.add(it.value.status) | |||
| 111 | } | |||
| 112 | return res | |||
| 113 | } | |||
| 114 | ||||
| 115 | fun getAllLength(): ArrayList<MessageData?> { | |||
| 116 | val res = arrayListOf<MessageData?>() | |||
| 117 | messages.forEach { | |||
| 118 | res.add(it.value.length) | |||
| 119 | } | |||
| 120 | return res | |||
| 121 | } | |||
| 122 | ||||
| 123 | fun getAllWidth(): ArrayList<MessageData?> { | |||
| 124 | val res = arrayListOf<MessageData?>() | |||
| 125 | messages.forEach { | |||
| 126 | res.add(it.value.width) | |||
| 127 | } | |||
| 128 | return res | |||
| 129 | } | |||
| 130 | ||||
| 131 | fun getAllDraft(): ArrayList<MessageData?> { | |||
| 132 | val res = arrayListOf<MessageData?>() | |||
| 133 | messages.forEach { | |||
| 134 | res.add(it.value.draft) | |||
| 135 | } | |||
| 136 | return res | |||
| 137 | } | |||
| 138 | ||||
| 139 | fun getAllCargo(): ArrayList<MessageData?> { | |||
| 140 | val res = arrayListOf<MessageData?>() | |||
| 141 | messages.forEach { | |||
| 142 | res.add(it.value.cargo) | |||
| 143 | } | |||
| 144 | return res | |||
| 145 | } |
src/main/kotlin/application/model/VesselGenerator.kt
View file @
513c034
| 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<Int, Vessel> { | |
| val messages : ArrayList<Message> = arrayListOf() | 8 | 8 | val messages : ArrayList<Message> = arrayListOf() | |
| val vessels: SortedMap<Int, Vessel> = sortedMapOf() | 9 | 9 | val vessels: SortedMap<Int, 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)){ | 16 | 16 | if (!vessels.containsKey(message.mmsi.value)){ | |
| vessels[message.mmsi] = Vessel(message.mmsi!!) | 17 | 17 | vessels[message.mmsi.value] = Vessel(message.mmsi.value!!) | |
| } | 18 | 18 | } | |
| vessels[message.mmsi]?.messages?.set(message.time, message) | 19 | 19 | vessels[message.mmsi.value]?.messages?.set(message.time.value, message) | |
| } | 20 | 20 | } | |
| 21 | 21 | |||
| } | 22 | 22 | } | |
| 23 | 23 |
src/main/kotlin/map/MapDisplayer.kt
View file @
513c034
| 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}, ${message.longitude}], {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: Int) { | |
| 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) { | 51 | 51 | if (selectedMMSI == message.mmsi.value) { | |
| map.execScript("L.circleMarker([${message.latitude}, ${message.longitude}], {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}, ${message.longitude}], {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}, ${message.longitude}], {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: Int) { | |
| 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) { | 74 | 74 | if (selectedMMSI == message.mmsi.value) { | |
| map.execScript("L.circleMarker([${message.latitude}, ${message.longitude}], {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}, ${message.longitude}], {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}, ${message.longitude}]);") | 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: Int) { | |
| 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) { | 97 | 97 | if (selectedMMSI == message.mmsi.value) { | |
| map.execScript("L.circleMarker([${message.latitude}, ${message.longitude}], {renderer: myRenderer, radius: 2, color: '#ff4040'}).addTo(myMap);") | 98 | 98 | map.execScript("L.circleMarker([${message.latitude.value}, ${message.longitude.value}], {renderer: myRenderer, radius: 2, color: '#ff4040'}).addTo(myMap);") | |
| } else { | 99 | 99 | } else { | |
| map.execScript("heatLayer.addLatLng([${message.latitude}, ${message.longitude}]);") | 100 | 100 | map.execScript("heatLayer.addLatLng([${message.latitude.value}, ${message.longitude.value}]);") | |
| } | 101 | 101 | } | |
| } | 102 | 102 | } | |
| } | 103 | 103 | } | |
| map.execScript("myMap.addLayer(markerClusters);") | 104 | 104 | map.execScript("myMap.addLayer(markerClusters);") | |
| } | 105 | 105 | } | |
src/main/resources/gui/dataPanel.fxml
View file @
513c034
| File was created | 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | ||||
| 3 | <?import javafx.scene.chart.*?> | |||
| 4 | <?import javafx.scene.control.*?> | |||
| 5 | <?import javafx.scene.layout.*?> | |||
| 6 | ||||
| 7 | <AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.241" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.controller.DataPanelController"> | |||
| 8 | <SplitPane dividerPositions="0.1705685618729097" prefHeight="212.0" prefWidth="254.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> | |||
| 9 | <ListView fx:id="dataListView" layoutX="-73.0" layoutY="14.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" /> | |||
| 10 | <StackPane prefHeight="150.0" prefWidth="200.0"> | |||
| 11 | <ScatterChart fx:id="scatterChartNumber"> | |||
| 12 | <xAxis> | |||
| 13 | <CategoryAxis side="BOTTOM" fx:id="xaxisNumber" /> | |||
| 14 | </xAxis> | |||
| 15 | <yAxis> | |||
| 16 | <NumberAxis fx:id="yaxisNumber" side="LEFT" /> | |||
| 17 | </yAxis> | |||
| 18 | </ScatterChart> | |||
| 19 | <ScatterChart fx:id="scatterChartCategory" visible="false"> | |||
| 20 | <xAxis> | |||
| 21 | <CategoryAxis side="BOTTOM" fx:id="xaxisCategory" /> | |||
| 22 | </xAxis> | |||
| 23 | <yAxis> | |||
| 24 | <CategoryAxis fx:id="yaxisCategory" side="LEFT" /> | |||
| 25 | </yAxis> | |||
| 26 | </ScatterChart> | |||
| 27 | </StackPane> |
src/main/resources/gui/vesselListPanel.fxml
View file @
513c034
| <?xml version="1.0" encoding="UTF-8"?> | 1 | 1 | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | 2 | |||
| <?import javafx.scene.control.*?> | 3 | 3 | <?import javafx.scene.control.*?> | |
| <?import javafx.scene.layout.*?> | 4 | 4 | <?import javafx.scene.layout.*?> | |
| 5 | 5 | |||
| <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 | 6 | <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"> | |
| 7 | 7 | |||
| <top> | 8 | 8 | <top> | |
| <AnchorPane prefHeight="33.0" prefWidth="200.0" BorderPane.alignment="CENTER"> | 9 | 9 | <AnchorPane prefHeight="33.0" prefWidth="200.0" BorderPane.alignment="CENTER"> | |
| <children> | 10 | 10 | <children> | |
| <Button layoutX="74.0" layoutY="2.0" mnemonicParsing="false" text="Button" fx:id="buton" /> | 11 | 11 | <Button layoutX="74.0" layoutY="2.0" mnemonicParsing="false" text="Button" fx:id="button"/> | |
| </children></AnchorPane> | 12 | 12 | </children></AnchorPane> | |
| </top> | 13 | 13 | </top> | |
| <center> | 14 | 14 | <center> | |
| <ListView fx:id="shipListView" prefHeight="105.0" prefWidth="200.0" /> | 15 | 15 | <ListView fx:id="shipListView" prefHeight="105.0" prefWidth="200.0" /> |
src/main/resources/gui/windows.fxml
View file @
513c034
| <?xml version="1.0" encoding="UTF-8"?> | 1 | 1 | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | 2 | |||
| <?import javafx.scene.control.*?> | 3 | 3 | <?import javafx.scene.control.SplitPane?> | |
| <?import javafx.scene.layout.*?> | 4 | 4 | <?import javafx.scene.layout.*?> | |
| <?import javafx.scene.shape.*?> | 5 | 5 | <?import javafx.scene.shape.Line?> | |
| 6 | 6 | <AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="900.0" | ||
| <AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="900.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1"> | 7 | 7 | prefWidth="1200.0" xmlns="http://javafx.com/javafx/8.0.241" xmlns:fx="http://javafx.com/fxml/1"> | |
| <children> | 8 | 8 | <children> | |
| <fx:include source="menuBar.fxml" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" /> | 9 | 9 | <fx:include source="menuBar.fxml" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" | |
| <SplitPane dividerPositions="0.29797979797979796" layoutY="39.0" prefHeight="865.0" prefWidth="1194.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="35.0"> | 10 | 10 | AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"/> | |
| 11 | <SplitPane dividerPositions="0.13772954924874792" layoutY="39.0" prefHeight="865.0" prefWidth="1194.0" | |||
| 12 | AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" | |||
| 13 | AnchorPane.topAnchor="35.0"> | |||
| <items> | 11 | 14 | <items> | |
| <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0"> | 12 | 15 | <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0"> | |
| <children> | 13 | 16 | <children> | |
| <fx:include source="vesselListPanel.fxml" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" /> | 14 | 17 | <fx:include source="vesselListPanel.fxml" AnchorPane.leftAnchor="0.0" | |
| 18 | AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"/> | |||
| </children> | 15 | 19 | </children> | |
| </AnchorPane> | 16 | 20 | </AnchorPane> | |
| <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0"> | 17 | 21 | <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0"> | |
| <children> | 18 | 22 | <children> | |
| <SplitPane dividerPositions="0.536" layoutX="127.0" layoutY="74.0" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> | 19 | 23 | <SplitPane dividerPositions="0.536" layoutX="127.0" layoutY="74.0" orientation="VERTICAL" | |
| 24 | prefHeight="200.0" prefWidth="160.0" AnchorPane.bottomAnchor="0.0" | |||
| 25 | AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> | |||
| <items> | 20 | 26 | <items> | |
| <fx:include source="mapPanel.fxml" /> | 21 | 27 | <fx:include source="mapPanel.fxml"/> | |
| <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0" /> | 22 | 28 | <fx:include source="dataPanel.fxml"/> | |
| </items> | 23 | 29 | </items> | |
| </SplitPane> | 24 | 30 | </SplitPane> | |
| </children> | 25 | 31 | </children> | |
| </AnchorPane> | 26 | 32 | </AnchorPane> | |
| </items> | 27 | 33 | </items> | |
| </SplitPane> | 28 | 34 | </SplitPane> | |
| <Line endX="1101.0" endY="1.1444091796875E-5" layoutX="101.0" layoutY="35.0" startX="-100.0" /> | 29 | 35 | <Line endX="1101.0" endY="1.1444091796875E-5" layoutX="101.0" layoutY="35.0" startX="-100.0"/> | |
| </children> | 30 | 36 | </children> | |
| </AnchorPane> | 31 | 37 | </AnchorPane> | |
| 32 | 38 | |||