Skip to content
Snippets Groups Projects
Commit 03083c58 authored by Eirik Steira's avatar Eirik Steira
Browse files

Merge branch 'feat/map' into 'dev'

Feat/map

See merge request !120
parents 1f8ac880 2fb56bed
No related branches found
No related tags found
2 merge requests!165Weekly merge to Master,!120Feat/map
Pipeline #79046 passed
......@@ -128,6 +128,20 @@
<version>1.56</version>
</dependency>
<!-- Google Maps API -->
<dependency>
<groupId>com.lynden</groupId>
<artifactId>GMapsFX</artifactId>
<version>2.12.0</version>
<exclusions>
<!-- Exclude svf4j found in logback-->
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
......
......@@ -111,8 +111,7 @@ public class ExploreAlbums implements Initializable {
try {
return albumService.getAllAlbums();
} catch (Exception e) {
logger.error("[x] Failed to fetch albums");
e.printStackTrace();
logger.error("[x] Failed to fetch albums", e);
}
return new ArrayList<>();
}
......@@ -165,8 +164,7 @@ public class ExploreAlbums implements Initializable {
try {
return album.getImages();
} catch (Exception e) {
logger.error("[x] Failed to fetch images for album {}", album);
e.printStackTrace();
logger.error("[x] Failed to fetch images for album {}", album, e);
}
return new ArrayList<>();
}
......@@ -229,8 +227,7 @@ public class ExploreAlbums implements Initializable {
try{
switchToViewAlbum(mouseEvent);
} catch (IOException ex) {
logger.error("[x] Failed to switch to Album View");
ex.printStackTrace();
logger.error("[x] Failed to switch to Album View", ex);
}
});
......@@ -291,8 +288,7 @@ public class ExploreAlbums implements Initializable {
try{
switchToViewAlbum(mouseEvent);
} catch (IOException ex) {
logger.error("[x] Failed to switch to Album View");
ex.printStackTrace();
logger.error("[x] Failed to switch to Album View", ex);
}
});
......
package NTNU.IDATT1002.controllers;
import NTNU.IDATT1002.models.Image;
import com.lynden.gmapsfx.GoogleMapView;
import com.lynden.gmapsfx.javascript.object.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.stream.Collectors;
/**
* Class ImageMapFactory. Factory for map creation with markers for given images and default options.
* Default center location is Berlin in order to center the full scale map onto a page.
*
* @author Eirik Steira
*/
public class ImageMapFactory {
private static Logger logger = LoggerFactory.getLogger(ImageMapFactory.class);
private ImageMapFactory() {}
/**
* Create a map from given {@link GoogleMapView} with default options and markers for images in given list.
*
* @param googleMapView the map view to add the map to
* @param images the list of images to place on the map
* @return the {@link GoogleMap} created to enable further customization
*/
public static GoogleMap createMap(GoogleMapView googleMapView, List<Image> images) {
List<LatLong> locations = getLatLongs(images);
MapOptions mapOptions = getMapOptions();
GoogleMap googleMap = googleMapView.createMap(mapOptions);
logger.info("[x] Google map created with {} locations", locations.size());
List<Marker> markers = getMarkers(locations);
googleMap.addMarkers(markers);
logger.info("[x] {} markers added", markers.size());
return googleMap;
}
/**
* Get latitude and longitude ({@link LatLong}) values for given images.
*
* @param images the list of images
* @return a list of {@link LatLong}
*/
private static List<LatLong> getLatLongs(List<Image> images) {
return images.stream()
.map(Image::getGeoLocation)
.map(geoLocation -> {
double latitude = Double.parseDouble(geoLocation.getLatitude());
double longitude = Double.parseDouble(geoLocation.getLongitude());
return new LatLong(latitude, longitude);
})
.collect(Collectors.toList());
}
/**
* Create default {@link MapOptions} to be applied to a map. Extend this for further marker customizations.
* The default center location is Berlin to get a look of the entire map when the zoom is set to fit the window.
*
* @return the default map options
*/
private static MapOptions getMapOptions() {
LatLong berlin = new LatLong(52.520008, 13.404954);
return new MapOptions()
.center(berlin)
.mapType(MapTypeIdEnum.ROADMAP)
.overviewMapControl(false)
.panControl(false)
.rotateControl(false)
.scaleControl(false)
.streetViewControl(false)
.zoomControl(false)
.zoom(3);
}
/**
* Create {@link Marker}s for each location in given list of locations.
*
* @param locations the list containing the locations
* @return the list of markers created
*/
private static List<Marker> getMarkers(List<LatLong> locations) {
return locations.stream()
.map(location -> {
MarkerOptions markerOptions = new MarkerOptions()
.position(location);
logger.info("[x] Marker created for location: {}", location);
return new Marker(markerOptions);
})
.collect(Collectors.toList());
}
}
package NTNU.IDATT1002.controllers;
import NTNU.IDATT1002.App;
import NTNU.IDATT1002.models.Image;
import NTNU.IDATT1002.service.ImageService;
import com.lynden.gmapsfx.GoogleMapView;
import com.lynden.gmapsfx.MapComponentInitializedListener;
import com.lynden.gmapsfx.javascript.object.GoogleMap;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.persistence.EntityManager;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Controls the buttons and changeable elements on map.fxml,
* a page where you can find images by location
* @version 1.0 22.03.2020
*/
public class Map {
public class Map implements Initializable, MapComponentInitializedListener {
public ImageView tbar_logo;
public TextField tbar_search;
public Button tbar_searchBtn;
......@@ -26,8 +43,64 @@ public class Map {
public Button searchBtn;
public Button tbar_albums;
@FXML
private GoogleMapView mapView;
private GoogleMap map;
private ImageService imageService;
private ExecutorService executorService = Executors.newCachedThreadPool();
private static Logger logger = LoggerFactory.getLogger(Map.class);
public Map() {
EntityManager entityManager = App.ex.getEntityManager();
imageService = new ImageService(entityManager);
}
/**
* Register the api key for Google Maps API and listen for map initialization
* in order to update the view once it has been initialized.
*
* @param url
* @param rb
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
mapView.setKey("AIzaSyB_ox5XC8zYBS__aezKumB-KSgKGUjcRx4");
mapView.addMapInializedListener(this);
}
/**
* Fetch all images in a background task and create and display the map on success.
*/
@Override
public void mapInitialized() {
executorService.submit(fetchImages);
fetchImages.setOnSucceeded(workerStateEvent -> {
List<Image> images = fetchImages.getValue();
ImageMapFactory.createMap(mapView, images);
});
}
/**
* Background task for fetching all images.
*/
private Task<List<Image>> fetchImages = new Task<>() {
@Override
protected List<Image> call() {
try {
return imageService.getAllImages();
} catch (Exception e) {
logger.error("[x] Failed to fetch images", e);
}
return new ArrayList<>();
}
};
/**
* Method that changes scene to Main page
* Change scene to Main page
* @param mouseEvent
* @throws IOException
*/
......@@ -36,7 +109,7 @@ public class Map {
}
/**
* Method that changes scene to Search page. It reads the value of the search
* Change scene to Search page. It reads the value of the search
* field and if not empty it is passed to dataexchange
* @param actionEvent
* @throws IOException
......@@ -49,7 +122,7 @@ public class Map {
}
/**
* Method that changes scene to Explore page
* Change scene to Explore page
* @param actionEvent
* @throws IOException
*/
......@@ -58,7 +131,7 @@ public class Map {
}
/**
* Method that changes scene to Albums page
* Change scene to Albums page
* @param actionEvent
* @throws IOException
*/
......@@ -67,7 +140,8 @@ public class Map {
}
/**
* Method that changes scene to Map page
* Change scene to Map page.
*
* @param actionEvent
* @throws IOException
*/
......@@ -76,7 +150,8 @@ public class Map {
}
/**
* Method that changes scene to Upload page
* Change scene to Upload page.
*
* @param actionEvent the mouse has done something
* @throws IOException this page does not exist
*/
......@@ -85,7 +160,8 @@ public class Map {
}
/**
* Method that searches for images on a specific place
* Search for images on a specific place.
*
* @param actionEvent
*/
public void MapSearch(ActionEvent actionEvent) {
......
......@@ -135,6 +135,18 @@ public class Image {
albums.remove(album);
}
/**
* Get Geo Location related to this image.
*
* @return the location the image was taken
*/
public GeoLocation getGeoLocation() {
if (metadata == null)
return new GeoLocation("0","0");
return metadata.getGeoLocation();
}
@Override
public boolean equals(Object o) {
if (this == o) {
......
package NTNU.IDATT1002.service;
import NTNU.IDATT1002.filters.ImageFilter;
import NTNU.IDATT1002.models.*;
import NTNU.IDATT1002.repository.*;
import NTNU.IDATT1002.repository.ImageRepository;
import NTNU.IDATT1002.utils.ImageUtil;
import NTNU.IDATT1002.utils.MetaDataExtractor;
import java.util.Arrays;
import javafx.scene.control.TextField;
import javax.persistence.EntityManager;
import java.io.File;
import java.util.ArrayList;
......@@ -99,6 +98,4 @@ public class ImageService {
.collect(Collectors.toList());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import com.lynden.gmapsfx.GoogleMapView?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<?import javafx.scene.web.WebView?>
<AnchorPane prefHeight="1080.0" prefWidth="1920.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="NTNU.IDATT1002.controllers.Map">
<children>
<VBox prefHeight="1080.0" prefWidth="1920.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
......@@ -58,12 +53,9 @@
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="797.0" prefWidth="1920.0" style="-fx-background-color: #888888;" VBox.vgrow="ALWAYS">
<children>
<WebView prefHeight="717.0" prefWidth="1920.0" AnchorPane.bottomAnchor="80.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
<Text layoutX="598.0" layoutY="378.0" strokeType="OUTSIDE" strokeWidth="0.0" text="MAP WILL BE INTEGRATED LATER." textAlignment="CENTER" AnchorPane.bottomAnchor="406.953125" AnchorPane.topAnchor="326.046875">
<font>
<Font size="48.0" />
</font>
</Text>
<GoogleMapView fx:id="mapView" prefHeight="750.0" prefWidth="761.0" AnchorPane.bottomAnchor="-185.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="-441.0" AnchorPane.topAnchor="0.0"/>
</children>
</AnchorPane>
</children>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment