Skip to content

Package: MapViewExampleController$1

MapViewExampleController$1

nameinstructionbranchcomplexitylinemethod
call()
M: 0 C: 26
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
{...}
M: 0 C: 6
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%

Coverage

1: /*
2: * *************************************************************************************************************************************************************
3: *
4: * MapView: a JavaFX map renderer for tile-based servers
5: * http://tidalwave.it/projects/mapview
6: *
7: * Copyright (C) 2024 - 2025 by Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *************************************************************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
12: * You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
17: * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
18: *
19: * *************************************************************************************************************************************************************
20: *
21: * git clone https://bitbucket.org/tidalwave/mapview-src
22: * git clone https://github.com/tidalwave-it/mapview-src
23: *
24: * *************************************************************************************************************************************************************
25: */
26: package it.tidalwave.mapview.javafx.example;
27:
28: import jakarta.annotation.Nonnull;
29: import java.util.Collection;
30: import java.util.List;
31: import java.util.concurrent.ExecutionException;
32: import java.util.concurrent.ExecutorService;
33: import java.util.concurrent.Executors;
34: import java.io.IOException;
35: import java.io.UncheckedIOException;
36: import java.nio.file.Path;
37: import javafx.concurrent.Task;
38: import javafx.fxml.FXML;
39: import javafx.scene.Node;
40: import javafx.scene.control.Button;
41: import javafx.scene.control.Label;
42: import javafx.scene.control.Slider;
43: import javafx.scene.layout.AnchorPane;
44: import javafx.scene.paint.Color;
45: import javafx.scene.shape.Circle;
46: import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
47: import io.jenetics.jpx.GPX;
48: import io.jenetics.jpx.Track;
49: import io.jenetics.jpx.TrackSegment;
50: import io.jenetics.jpx.WayPoint;
51: import it.tidalwave.mapview.MapArea;
52: import it.tidalwave.mapview.MapCoordinates;
53: import it.tidalwave.mapview.OpenStreetMapTileSource;
54: import it.tidalwave.mapview.OpenTopoMapTileSource;
55: import it.tidalwave.mapview.TileSource;
56: import it.tidalwave.mapview.javafx.MapView;
57: import lombok.Getter;
58: import lombok.extern.slf4j.Slf4j;
59: import static lombok.AccessLevel.PROTECTED;
60:
61: /***************************************************************************************************************************************************************
62: *
63: * @author Fabrizio Giudici
64: *
65: **************************************************************************************************************************************************************/
66: @Getter(PROTECTED) @Slf4j
67: public class MapViewExampleController
68: {
69: private static final Path CACHE_FOLDER = Path.of("target/tile-cache");
70:
71: private static final String TRACK_OVERLAY_NAME = "track";
72: private static final MapCoordinates START = MapCoordinates.of(44.4072, 8.9340);
73: private static final double START_ZOOM = 8;
74: private static final MapArea ITALY = MapArea.of(47.115, 18.480, 36.6199, 6.749);
75: private static final MapArea FRANCE = MapArea.of(51.148, 9.560, 2.053, -54.524);
76: private static final MapArea SWITZERLAND = MapArea.of(47.830, 10.442, 45.776, 6.022);
77: private static final MapArea ALEUTIAN = MapArea.of(62.67, -147.38, 46.32, 161.64 );
78: private static final TileSource osm = new OpenStreetMapTileSource();
79: private static final TileSource otm = new OpenTopoMapTileSource();
80:
81: @FXML
82: private AnchorPane apAnchorPane;
83:
84: @FXML
85: private Slider slZoom;
86:
87: @FXML
88: private Button btZoomIn;
89:
90: @FXML
91: private Button btZoomOut;
92:
93: @FXML
94: private Button btReset;
95:
96: @FXML
97: private Button btShowItaly;
98:
99: @FXML
100: private Button btShowFrance;
101:
102: @FXML
103: private Button btShowSwitzerland;
104:
105: @FXML
106: private Button btShowAleutian;
107:
108: @FXML
109: private Button btZeroZero;
110:
111: @FXML
112: private Button btTrack;
113:
114: @FXML
115: private Button btOSM;
116:
117: @FXML
118: private Button btOTM;
119:
120: @FXML
121: private Label lbCoordinates;
122:
123: @FXML
124: private Label lbArea;
125:
126: @FXML
127: private Label lbCenterCoordinates;
128:
129: @FXML
130: private Label lbZoom;
131:
132: private MapView mapView;
133:
134: @Nonnull
135: private final ExecutorService executorService = Executors.newFixedThreadPool(1);
136:
137: /***********************************************************************************************************************************************************
138: *
139: **********************************************************************************************************************************************************/
140: public void initialize()
141: {
142: mapView = new MapView(MapView.options().withCacheFolder(CACHE_FOLDER));
143: mapView.setZoom(START_ZOOM);
144: mapView.setCenter(START);
145: mapView.setDoubleClickBehaviour(MapView.RECENTER);
146: AnchorPane.setLeftAnchor(mapView, 0.0);
147: AnchorPane.setRightAnchor(mapView, 0.0);
148: AnchorPane.setTopAnchor(mapView, 0.0);
149: AnchorPane.setBottomAnchor(mapView, 0.0);
150: apAnchorPane.getChildren().add(mapView);
151: slZoom.minProperty().bind(mapView.minZoomProperty());
152: slZoom.maxProperty().bind(mapView.maxZoomProperty());
153: slZoom.valueProperty().bindBidirectional(mapView.zoomProperty());
154: mapView.centerProperty().addListener((_1, _2, coordinates) -> lbCenterCoordinates.setText(coordinates.toFormattedString()));
155: mapView.zoomProperty().addListener((_1, _2, zoom) -> lbZoom.setText(Integer.toString(zoom.intValue())));
156: mapView.areaProperty().addListener((_1, _2, area) -> lbArea.setText(area.toFormattedString()));
157: mapView.mouseCoordinatesProperty().addListener((_1, _2, coordinates) -> lbCoordinates.setText(coordinates.toFormattedString()));
158: btZoomIn.setOnAction(event -> mapView.setZoom(mapView.getZoom() + 1));
159: btZoomOut.setOnAction(event -> mapView.setZoom(mapView.getZoom() - 1));
160: btReset.setOnAction(event -> { mapView.setCenter(START); mapView.setZoom(START_ZOOM); });
161: btShowItaly.setOnAction(event -> mapView.fitArea(ITALY));
162: btShowFrance.setOnAction(event -> mapView.fitArea(FRANCE));
163: btShowSwitzerland.setOnAction(event -> mapView.fitArea(SWITZERLAND));
164: btShowAleutian.setOnAction(event -> mapView.fitArea(ALEUTIAN));
165: btZeroZero.setOnAction(event -> mapView.setCenter(MapCoordinates.of(0, 0)));
166: btOSM.setOnAction(event -> mapView.setTileSource(osm));
167: btOTM.setOnAction(event -> mapView.setTileSource(otm));
168: btTrack.setOnAction(event -> renderTrack());
169: }
170:
171: /***********************************************************************************************************************************************************
172: *
173: **********************************************************************************************************************************************************/
174: @SuppressFBWarnings("RV_RETURN_VALUE_IGNORED_BAD_PRACTICE")
175: public void renderTrack()
176: {
177: record PointsAndArea(List<WayPoint> points, MapArea area) {}
178:
179: final var task = new Task<PointsAndArea>()
180: {
181: @Override @Nonnull
182: protected PointsAndArea call()
183: {
184: final var track = loadTrack();
185: final var points = track.segments().flatMap(TrackSegment::points).toList();
186: final var area = computeFitArea(points);
187: log.info("track with {} points, fit area: {}", points.size(), area);
188: return new PointsAndArea(points, area);
189: }
190: };
191:
192: task.setOnSucceeded(event ->
193: {
194: try
195: {
196: final var pointsAndArea = task.get();
197: mapView.removeOverlay(TRACK_OVERLAY_NAME);
198: mapView.addOverlay(TRACK_OVERLAY_NAME, helper ->
199: helper.addAll(pointsAndArea.points.stream().map(wp -> createPoint(helper, wp)).toList()));
200: mapView.fitArea(pointsAndArea.area);
201: }
202: catch (InterruptedException e)
203: {
204: log.error("", e);
205: Thread.currentThread().interrupt();
206: }
207: catch (ExecutionException e)
208: {
209: log.error("", e);
210: }
211: });
212:
213: executorService.submit(task);
214: }
215:
216: /***********************************************************************************************************************************************************
217: *
218: **********************************************************************************************************************************************************/
219: @Nonnull
220: private static Node createPoint (@Nonnull final MapView.OverlayHelper helper, @Nonnull final WayPoint wp)
221: {
222: final var point = helper.toOverlayPoint(MapCoordinates.of(wp.getLatitude().doubleValue(), wp.getLongitude().doubleValue()));
223: return new Circle(point.getX(), point.getY(), 2.5, Color.RED);
224: }
225:
226: /***********************************************************************************************************************************************************
227: *
228: **********************************************************************************************************************************************************/
229: @Nonnull
230: private static MapArea computeFitArea (@Nonnull final Collection<WayPoint> points)
231: {
232: // quick and dirty, just for this example
233: var north = -999d;
234: var south = 999d;
235: var east = -999d;
236: var west = 999d;
237:
238: for (final var point : points)
239: {
240: north = Math.max(north, point.getLatitude().doubleValue());
241: south = Math.min(south, point.getLatitude().doubleValue());
242: east = Math.max(east, point.getLongitude().doubleValue());
243: west = Math.min(west, point.getLongitude().doubleValue());
244: }
245:
246: return MapArea.of(north, east, south, west);
247: }
248:
249: /***********************************************************************************************************************************************************
250: *
251: **********************************************************************************************************************************************************/
252: @Nonnull
253: private Track loadTrack()
254: {
255: try (final var is = MapViewExampleController.class.getResourceAsStream("/2014-04-10 1800__20140410_1800.gpx"))
256: {
257: return GPX.Reader.of(GPX.Reader.Mode.LENIENT).read(is).getTracks().getFirst();
258: }
259: catch (IOException e)
260: {
261: log.error(e.toString());
262: throw new UncheckedIOException(e);
263: }
264: }
265: }