diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/GeoLocations.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/GeoLocations.java
new file mode 100644
index 0000000000000000000000000000000000000000..c0354a6ebd59fa1a3bda6bcb55d05e2daf94983f
--- /dev/null
+++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/GeoLocations.java
@@ -0,0 +1,87 @@
+package tdt4140.gr1800.app.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+public class GeoLocations implements Iterable<LatLong> {
+
+	private String name;
+	
+	public String getName() {
+		return name;
+	}
+	
+	public void setName(String name) {
+		this.name = name;
+	}
+	
+	private Collection<LatLong> locations = new ArrayList<LatLong>();
+	private boolean path = false;
+	
+	public GeoLocations(LatLong...latLongs) {
+		for (int i = 0; i < latLongs.length; i++) {
+			addLocation(latLongs[i]);
+		}
+	}
+	
+	public GeoLocations(String name, LatLong...latLongs) {
+		this(latLongs);
+		setName(name);
+	}
+	
+	public boolean isPath() {
+		return path;
+	}
+	
+	public void setPath(boolean path) {
+		this.path = path;
+	}
+	
+	public Comparator<? super LatLong> latLongComparator(LatLong latLong) {
+		return (latLong1, latLong2) -> (int) Math.signum(latLong.distance(latLong1) - latLong.distance(latLong2));
+	}
+
+	public Collection<LatLong> findLocationsNearby(LatLong latLong, double distance) {
+		return locations.stream()
+				.filter(latLong2 -> latLong.distance(latLong2) <= distance)
+				.sorted(latLongComparator(latLong))
+				.collect(Collectors.toList());
+	}
+
+	public LatLong findNearestLocation(LatLong latLong) {
+		Optional<LatLong> min = locations.stream()
+				.min(latLongComparator(latLong));
+		return min.isPresent() ? min.get() : null;
+	}
+
+	//
+	
+	public void addLocation(LatLong latLong) {
+		if (! locations.contains(latLong)) {
+			locations.add(latLong);
+		}
+	}
+
+	public void removeLocations(LatLong latLong, double distance) {
+		Iterator<LatLong> it = locations.iterator();
+		while (it.hasNext()) {
+			LatLong latLong2 = it.next();
+			if (latLong.distance(latLong2) <= distance) {
+				it.remove();
+			}
+		}
+	}
+
+	public int size() {
+		return locations.size();
+	}
+	
+	@Override
+	public Iterator<LatLong> iterator() {
+		return locations.iterator();
+	}
+}
diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/LatLong.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/LatLong.java
new file mode 100644
index 0000000000000000000000000000000000000000..7b99cdfc4e11edbc670219190dc3df65a591d8c3
--- /dev/null
+++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/LatLong.java
@@ -0,0 +1,115 @@
+package tdt4140.gr1800.app.core;
+
+public class LatLong {
+	
+	public final double latitude, longitude;
+
+	public LatLong(double latitude, double longitude) {
+		super();
+		this.latitude = latitude;
+		this.longitude = longitude;
+	}
+
+	public double distance(LatLong loc) {
+		return distance(this.latitude, this.longitude, loc.latitude, loc.longitude);
+	}
+
+	public final static String SEPARATOR = ",";
+
+	@Override
+	public String toString() {
+		return latitude + SEPARATOR + longitude;
+	}
+	
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		long temp;
+		temp = Double.doubleToLongBits(latitude);
+		result = prime * result + (int) (temp ^ (temp >>> 32));
+		temp = Double.doubleToLongBits(longitude);
+		result = prime * result + (int) (temp ^ (temp >>> 32));
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj) {
+			return true;
+		}
+		if (obj == null || getClass() != obj.getClass()) {
+			return false;
+		}
+		LatLong other = (LatLong) obj;
+		return (Double.doubleToLongBits(latitude) == Double.doubleToLongBits(other.latitude) &&
+				Double.doubleToLongBits(longitude) == Double.doubleToLongBits(other.longitude));
+	}
+
+	public static LatLong valueOf(String s) {
+		return valueOf(s, SEPARATOR);
+	}
+	
+	public static LatLong valueOf(String s, String sep) {
+		int pos = s.indexOf(sep);
+		if (pos < 0) {
+			throw new IllegalArgumentException("No '" + sep + "' in "  + s);
+		}
+		double lat = Double.valueOf(s.substring(0, pos).trim());
+		double lon = Double.valueOf(s.substring(pos + sep.length()).trim());
+		
+		return new LatLong(lat, lon);
+	}
+	
+	/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+	/*::                                                                         :*/
+	/*::  This routine calculates the distance between two points (given the     :*/
+	/*::  latitude/longitude of those points). It is being used to calculate     :*/
+	/*::  the distance between two locations using GeoDataSource (TM) products   :*/
+	/*::                                                                         :*/
+	/*::  Definitions:                                                           :*/
+	/*::    South latitudes are negative, east longitudes are positive           :*/
+	/*::                                                                         :*/
+	/*::  Passed to function:                                                    :*/
+	/*::    lat1, lon1 = Latitude and Longitude of point 1 (in decimal degrees)  :*/
+	/*::    lat2, lon2 = Latitude and Longitude of point 2 (in decimal degrees)  :*/
+	/*::  Worldwide cities and other features databases with latitude longitude  :*/
+	/*::  are available at http://www.geodatasource.com                          :*/
+	/*::                                                                         :*/
+	/*::  For enquiries, please contact sales@geodatasource.com                  :*/
+	/*::                                                                         :*/
+	/*::  Official Web site: http://www.geodatasource.com                        :*/
+	/*::                                                                         :*/
+	/*::           GeoDataSource.com (C) All Rights Reserved 2015                :*/
+	/*::                                                                         :*/
+	/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+	public static double distance(double lat1, double lon1, double lat2, double lon2) {
+		double theta = lon1 - lon2;
+		double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
+		dist = Math.acos(dist);
+		// convert to degrees
+		dist = rad2deg(dist);
+		dist = dist * 60 * 1.1515;
+		// convert to meters 
+		dist = dist * 1609.344;
+		return dist;
+	}
+
+	public static double distance(LatLong latLong1, LatLong latLong2) {
+		return distance(latLong1.latitude, latLong1.longitude, latLong2.latitude, latLong2.longitude);
+	}
+
+	/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+	/*::	This function converts decimal degrees to radians						 :*/
+	/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+	private static double deg2rad(double deg) {
+		return (deg * Math.PI / 180.0);
+	}
+
+	/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+	/*::	This function converts radians to decimal degrees						 :*/
+	/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+	private static double rad2deg(double rad) {
+		return (rad * 180 / Math.PI);
+	}
+}
diff --git a/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GeoLocationsTest.java b/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GeoLocationsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..aab486beb437ef7bcafc4a4ea80e43e232f84c43
--- /dev/null
+++ b/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GeoLocationsTest.java
@@ -0,0 +1,74 @@
+package tdt4140.gr1800.app.core;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class GeoLocationsTest {
+
+	private GeoLocations geoLocations;
+	
+	@Before
+	public void setUp() {
+		geoLocations = new GeoLocations();
+	}
+
+	@Test
+	public void testGeoLocations() {
+		Assert.assertEquals(0, geoLocations.size());
+		Assert.assertEquals(1, new GeoLocations(new LatLong(0, 0)).size());
+		Assert.assertEquals(1, new GeoLocations(new LatLong(0, 0), new LatLong(0, 0)).size());
+		Assert.assertEquals(2, new GeoLocations(new LatLong(0, 0), new LatLong(1, 1)).size());
+	}
+
+	private void assertGeoLocations(LatLong...latLongs) {
+		assertGeoLocations(geoLocations, latLongs);
+	}
+
+	public static void assertGeoLocations(GeoLocations geoLocations, LatLong...latLongs) {
+		Iterator<LatLong> it = geoLocations.iterator();
+		Assert.assertEquals(latLongs.length, geoLocations.size());
+		int pos = 0;
+		while (it.hasNext()) {
+			Assert.assertEquals(latLongs[pos], it.next());
+			pos++;
+		}
+	}
+
+	@Test
+	public void testAddLocation() {
+		Assert.assertEquals(0, geoLocations.size());
+		LatLong latLong1 = new LatLong(0, 0);
+		geoLocations.addLocation(latLong1);
+		assertGeoLocations(latLong1);
+
+		geoLocations.addLocation(new LatLong(0, 0));
+		assertGeoLocations(latLong1);
+
+		LatLong latLong2 = new LatLong(1, 1);
+		geoLocations.addLocation(latLong2);
+		assertGeoLocations(latLong1, latLong2);
+	}
+
+	@Test
+	public void testFindLocationsNearby() {
+		LatLong latLong = new LatLong(0, 0);
+		Assert.assertTrue(geoLocations.findLocationsNearby(latLong, 0).isEmpty());
+		geoLocations.addLocation(latLong);
+		Collection<LatLong> locationsNearby = geoLocations.findLocationsNearby(latLong, 0);
+		Assert.assertEquals(1, locationsNearby.size());
+		Assert.assertEquals(latLong, geoLocations.iterator().next()); 
+	}
+	
+	@Test
+	public void testFindNearestLocation() {
+		LatLong latLong = new LatLong(0, 0);
+		Assert.assertNull(geoLocations.findNearestLocation(latLong));
+		geoLocations.addLocation(latLong);
+		LatLong nearestlocations = geoLocations.findNearestLocation(latLong);
+		Assert.assertEquals(latLong, nearestlocations); 
+	}	
+}