From 8b20e3e027058cdf6ff52993ee5576193d08667a Mon Sep 17 00:00:00 2001
From: activityworkshop
Date: Mon, 6 Apr 2020 21:38:26 +0200
Subject: [PATCH] Version 20, March 2020
---
.gitignore | 2 +
README.md | 4 +-
buildtools/build.sh | 3 +-
buildtools/pom.xml | 2 +-
buildtools/version.properties | 2 +-
src/tim/prune/App.java | 42 +-
src/tim/prune/FunctionLibrary.java | 18 +-
src/tim/prune/GpsPrune.java | 16 +-
src/tim/prune/I18nManager.java | 20 +-
src/tim/prune/config/Config.java | 17 +-
src/tim/prune/copyright.txt | 4 +-
src/tim/prune/data/Coordinate.java | 18 +
src/tim/prune/data/FileInfo.java | 4 +-
src/tim/prune/data/RangeStats.java | 248 +++---
.../prune/data/RangeStatsWithGradients.java | 106 +++
src/tim/prune/data/Selection.java | 77 +-
src/tim/prune/data/Timestamp.java | 6 +-
src/tim/prune/function/AboutScreen.java | 2 +-
src/tim/prune/function/AddAltitudeOffset.java | 2 +-
src/tim/prune/function/AddTimeOffset.java | 2 +-
.../function/ConnectToPointFunction.java | 4 +-
.../CreateMarkerWaypointsFunction.java | 234 ++++-
.../function/DistanceTimeLimitFunction.java | 81 +-
src/tim/prune/function/DuplicatePoint.java | 3 +-
src/tim/prune/function/FullRangeDetails.java | 367 --------
.../prune/function/InterpolateFunction.java | 3 +-
.../prune/function/PasteCoordinateList.java | 147 ++++
src/tim/prune/function/PasteCoordinates.java | 6 +-
src/tim/prune/function/PlayAudioFunction.java | 13 +-
src/tim/prune/function/PlusCodeFunction.java | 209 +++++
src/tim/prune/function/ProjectPoint.java | 225 +++++
.../function/RearrangeWaypointsFunction.java | 2 +-
.../function/SearchOpenCachingDeFunction.java | 2 +-
src/tim/prune/function/ShowFullDetails.java | 417 +++++++++
.../compress/CompressTrackFunction.java | 2 +-
.../compress/SingleParameterAlgorithm.java | 6 +-
.../function/distance/DistanceFunction.java | 7 +-
.../function/distance/DistanceTableModel.java | 2 +-
.../prune/function/estimate/EstimateTime.java | 13 +-
.../estimate/EstimationParameters.java | 8 +-
.../function/estimate/LearnParameters.java | 32 +-
src/tim/prune/function/gpsies/FormPoster.java | 162 ----
.../function/gpsies/GetGpsiesFunction.java | 147 ----
.../function/gpsies/GpsiesXmlHandler.java | 85 --
.../function/gpsies/UploadGpsiesFunction.java | 332 --------
src/tim/prune/function/olc/CoordPair.java | 75 ++
src/tim/prune/function/olc/OlcArea.java | 21 +
src/tim/prune/function/olc/OlcDecoder.java | 101 +++
.../search/GenericDownloaderFunction.java | 3 +-
.../prune/function/search/SearchResult.java | 2 +-
.../{gpsies => search}/TrackListModel.java | 5 +-
.../function/search/wikimedia_galleries.txt | 796 ++++++++++--------
.../prune/function/settings/SaveConfig.java | 118 +--
.../function/settings/SetDisplaySettings.java | 39 +
.../prune/function/settings/SetLanguage.java | 5 +-
.../function/settings/SetPathsFunction.java | 4 +-
.../function/sew/SplitSegmentsFunction.java | 2 +-
.../function/srtm/LookupSrtmFunction.java | 110 +--
src/tim/prune/function/srtm/TileFinder.java | 5 +
src/tim/prune/gui/CoordDisplay.java | 58 ++
src/tim/prune/gui/DetailsDisplay.java | 100 +--
src/tim/prune/gui/MenuManager.java | 41 +-
src/tim/prune/gui/StatusBar.java | 3 +-
src/tim/prune/gui/Viewport.java | 2 +-
src/tim/prune/gui/colour/ColourerFactory.java | 2 +-
src/tim/prune/gui/colour/FileColourer.java | 4 +-
src/tim/prune/gui/map/DiskTileCacher.java | 175 +++-
src/tim/prune/gui/map/MapCanvas.java | 4 +-
src/tim/prune/gui/map/MapSourceLibrary.java | 8 +-
src/tim/prune/gui/map/MapTileManager.java | 2 +-
src/tim/prune/gui/map/TileDownloader.java | 18 +
src/tim/prune/gui/profile/ProfileChart.java | 56 +-
src/tim/prune/jpeg/drew/ExifTiffHandler.java | 7 +-
src/tim/prune/lang/prune-texts_af.properties | 41 +-
src/tim/prune/lang/prune-texts_cy.properties | 96 +++
src/tim/prune/lang/prune-texts_cz.properties | 41 +-
src/tim/prune/lang/prune-texts_da.properties | 3 +-
src/tim/prune/lang/prune-texts_de.properties | 63 +-
.../prune/lang/prune-texts_de_CH.properties | 63 +-
src/tim/prune/lang/prune-texts_en.properties | 63 +-
.../prune/lang/prune-texts_en_US.properties | 3 -
src/tim/prune/lang/prune-texts_es.properties | 76 +-
src/tim/prune/lang/prune-texts_fi.properties | 38 +-
src/tim/prune/lang/prune-texts_fr.properties | 43 +-
src/tim/prune/lang/prune-texts_hu.properties | 75 +-
src/tim/prune/lang/prune-texts_it.properties | 61 +-
src/tim/prune/lang/prune-texts_ja.properties | 36 +-
src/tim/prune/lang/prune-texts_ko.properties | 38 +-
src/tim/prune/lang/prune-texts_nl.properties | 109 ++-
src/tim/prune/lang/prune-texts_no.properties | 4 +-
src/tim/prune/lang/prune-texts_pl.properties | 42 +-
src/tim/prune/lang/prune-texts_pt.properties | 42 +-
src/tim/prune/lang/prune-texts_ro.properties | 42 +-
src/tim/prune/lang/prune-texts_ru.properties | 61 +-
src/tim/prune/lang/prune-texts_sv.properties | 5 +-
src/tim/prune/lang/prune-texts_tr.properties | 25 +-
src/tim/prune/lang/prune-texts_uk.properties | 3 -
src/tim/prune/lang/prune-texts_zh.properties | 40 +-
src/tim/prune/load/ContentCacher.java | 90 ++
src/tim/prune/load/FileCacher.java | 87 +-
src/tim/prune/load/FileSplitter.java | 6 +-
src/tim/prune/load/JpegLoader.java | 6 +-
src/tim/prune/load/TextCacher.java | 42 +
src/tim/prune/load/TextFileLoader.java | 126 ++-
src/tim/prune/readme.txt | 49 +-
src/tim/prune/save/BaseImageConfigDialog.java | 2 +-
src/tim/prune/save/ImageExporter.java | 8 +-
107 files changed, 3355 insertions(+), 3044 deletions(-)
create mode 100644 .gitignore
create mode 100644 src/tim/prune/data/RangeStatsWithGradients.java
delete mode 100644 src/tim/prune/function/FullRangeDetails.java
create mode 100644 src/tim/prune/function/PasteCoordinateList.java
create mode 100644 src/tim/prune/function/PlusCodeFunction.java
create mode 100644 src/tim/prune/function/ProjectPoint.java
create mode 100644 src/tim/prune/function/ShowFullDetails.java
delete mode 100644 src/tim/prune/function/gpsies/FormPoster.java
delete mode 100644 src/tim/prune/function/gpsies/GetGpsiesFunction.java
delete mode 100644 src/tim/prune/function/gpsies/GpsiesXmlHandler.java
delete mode 100644 src/tim/prune/function/gpsies/UploadGpsiesFunction.java
create mode 100644 src/tim/prune/function/olc/CoordPair.java
create mode 100644 src/tim/prune/function/olc/OlcArea.java
create mode 100644 src/tim/prune/function/olc/OlcDecoder.java
rename src/tim/prune/function/{gpsies => search}/TrackListModel.java (95%)
create mode 100644 src/tim/prune/gui/CoordDisplay.java
create mode 100644 src/tim/prune/lang/prune-texts_cy.properties
create mode 100644 src/tim/prune/load/ContentCacher.java
create mode 100644 src/tim/prune/load/TextCacher.java
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8e9e794
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.class
+*.jar
diff --git a/README.md b/README.md
index 9e9c08b..1a1aa06 100644
--- a/README.md
+++ b/README.md
@@ -3,5 +3,5 @@ GpsPrune is a map-based application for viewing, editing and converting coordina
It's a cross-platform java application, and its home page is at https://gpsprune.activityworkshop.net .
-Here on github you'll find all the sources from version 1 to the current version 19.2, and in the wiki at https://github.com/activityworkshop/GpsPrune/wiki there's the beginning of a translation effort for anyone to contribute.
-Currently just the Spanish translations are online, to see whether it's a workable idea or not. Please help with this if you can.
+Here on github you'll find all the sources from version 1 to the current version 20, and in the wiki at https://github.com/activityworkshop/GpsPrune/wiki there's the beginning of a translation effort for anyone to contribute.
+Currently just the Spanish translations and some missing French texts are online, to see whether it's a workable idea or not. Please help with these if you can.
diff --git a/buildtools/build.sh b/buildtools/build.sh
index b38e2ce..193244b 100644
--- a/buildtools/build.sh
+++ b/buildtools/build.sh
@@ -1,6 +1,7 @@
# Build script
+set -e
# Version number
-PRUNENAME=gpsprune_19.2
+PRUNENAME=gpsprune_20
# remove compile directory
rm -rf compile
# remove dist directory
diff --git a/buildtools/pom.xml b/buildtools/pom.xml
index 82b29ac..15b6562 100644
--- a/buildtools/pom.xml
+++ b/buildtools/pom.xml
@@ -7,7 +7,7 @@
tim.prune
gpsprune
- 19.2
+ 20
jar
tim.prune.gpsprune
diff --git a/buildtools/version.properties b/buildtools/version.properties
index af25926..fe5699b 100644
--- a/buildtools/version.properties
+++ b/buildtools/version.properties
@@ -1 +1 @@
-version=19.2
+version=20
diff --git a/src/tim/prune/App.java b/src/tim/prune/App.java
index 3a77858..94e10e0 100644
--- a/src/tim/prune/App.java
+++ b/src/tim/prune/App.java
@@ -69,7 +69,7 @@ public class App
private AppMode _appMode = AppMode.NORMAL;
/** Enum for the app mode - currently only two options but may expand later */
- public enum AppMode {NORMAL, DRAWRECT};
+ public enum AppMode {NORMAL, DRAWRECT}
/**
@@ -649,7 +649,8 @@ public class App
loadedTrack.load(inFieldArray, inDataArray, inOptions);
if (loadedTrack.getNumPoints() <= 0)
{
- showErrorMessage("error.load.dialogtitle", "error.load.nopoints");
+ String msgKey = (inSourceInfo == null ? "error.load.nopointsintext" : "error.load.nopoints");
+ showErrorMessage("error.load.dialogtitle", msgKey);
// load next file if there's a queue
loadNextFile();
return;
@@ -715,9 +716,12 @@ public class App
undo.setNumPhotosAudios(_trackInfo.getPhotoList().getNumPhotos(), _trackInfo.getAudioList().getNumAudios());
_undoStack.add(undo);
_track.combine(inLoadedTrack);
- // set source information
- inSourceInfo.populatePointObjects(_track, inLoadedTrack.getNumPoints());
- _trackInfo.getFileInfo().addSource(inSourceInfo);
+ if (inSourceInfo != null)
+ {
+ // set source information
+ inSourceInfo.populatePointObjects(_track, inLoadedTrack.getNumPoints());
+ _trackInfo.getFileInfo().addSource(inSourceInfo);
+ }
}
else if (answer == JOptionPane.NO_OPTION)
{
@@ -732,8 +736,12 @@ public class App
_lastSavePosition = _undoStack.size();
_trackInfo.getSelection().clearAll();
_track.load(inLoadedTrack);
- inSourceInfo.populatePointObjects(_track, _track.getNumPoints());
- _trackInfo.getFileInfo().replaceSource(inSourceInfo);
+ if (inSourceInfo != null)
+ {
+ // set source information
+ inSourceInfo.populatePointObjects(_track, _track.getNumPoints());
+ _trackInfo.getFileInfo().replaceSource(inSourceInfo);
+ }
_trackInfo.getPhotoList().removeCorrelatedPhotos();
_trackInfo.getAudioList().removeCorrelatedAudios();
}
@@ -747,16 +755,22 @@ public class App
_lastSavePosition = _undoStack.size();
_trackInfo.getSelection().clearAll();
_track.load(inLoadedTrack);
- inSourceInfo.populatePointObjects(_track, _track.getNumPoints());
- _trackInfo.getFileInfo().addSource(inSourceInfo);
+ if (inSourceInfo != null)
+ {
+ inSourceInfo.populatePointObjects(_track, _track.getNumPoints());
+ _trackInfo.getFileInfo().addSource(inSourceInfo);
+ }
}
// Update config before subscribers are told
- boolean isRegularLoad = (inSourceInfo.getFileType() != FILE_TYPE.GPSBABEL);
- Config.getRecentFileList().addFile(new RecentFile(inSourceInfo.getFile(), isRegularLoad));
+ if (inSourceInfo != null)
+ {
+ boolean isRegularLoad = (inSourceInfo.getFileType() != FILE_TYPE.GPSBABEL);
+ Config.getRecentFileList().addFile(new RecentFile(inSourceInfo.getFile(), isRegularLoad));
+ // Update status bar
+ UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.loadfile")
+ + " '" + inSourceInfo.getName() + "'");
+ }
UpdateMessageBroker.informSubscribers();
- // Update status bar
- UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.loadfile")
- + " '" + inSourceInfo.getName() + "'");
// update menu
_menuManager.informFileLoaded();
// Remove busy lock
diff --git a/src/tim/prune/FunctionLibrary.java b/src/tim/prune/FunctionLibrary.java
index 0441826..68303ed 100644
--- a/src/tim/prune/FunctionLibrary.java
+++ b/src/tim/prune/FunctionLibrary.java
@@ -18,12 +18,12 @@ import tim.prune.function.DiskCacheConfig;
import tim.prune.function.DownloadOsmFunction;
import tim.prune.function.DuplicatePoint;
import tim.prune.function.FindWaypoint;
-import tim.prune.function.FullRangeDetails;
+import tim.prune.function.ProjectPoint;
+import tim.prune.function.ShowFullDetails;
import tim.prune.function.GetWikipediaFunction;
import tim.prune.function.HelpScreen;
import tim.prune.function.IgnoreExifThumb;
import tim.prune.function.InterpolateFunction;
-import tim.prune.function.PasteCoordinates;
import tim.prune.function.PhotoPopupFunction;
import tim.prune.function.PlayAudioFunction;
import tim.prune.function.RearrangePhotosFunction;
@@ -50,8 +50,6 @@ import tim.prune.function.distance.DistanceFunction;
import tim.prune.function.edit.PointNameEditor;
import tim.prune.function.estimate.EstimateTime;
import tim.prune.function.estimate.LearnParameters;
-import tim.prune.function.gpsies.GetGpsiesFunction;
-import tim.prune.function.gpsies.UploadGpsiesFunction;
import tim.prune.function.settings.SaveConfig;
import tim.prune.function.settings.SetAltitudeTolerance;
import tim.prune.function.settings.SetColours;
@@ -88,6 +86,7 @@ public abstract class FunctionLibrary
public static GenericFunction FUNCTION_IMPORTBABEL = null;
public static GenericFunction FUNCTION_SAVECONFIG = null;
public static GenericFunction FUNCTION_EDIT_WAYPOINT_NAME = null;
+ public static GenericFunction FUNCTION_PROJECT_POINT = null;
public static GenericFunction FUNCTION_REARRANGE_WAYPOINTS = null;
public static GenericFunction FUNCTION_SELECT_SEGMENT = null;
public static GenericFunction FUNCTION_SPLIT_SEGMENTS = null;
@@ -112,7 +111,6 @@ public abstract class FunctionLibrary
public static GenericFunction FUNCTION_ADD_ALTITUDE_OFFSET = null;
public static GenericFunction FUNCTION_CONVERT_NAMES_TO_TIMES = null;
public static GenericFunction FUNCTION_DELETE_FIELD_VALUES = null;
- public static GenericFunction FUNCTION_PASTE_COORDINATES = null;
public static GenericFunction FUNCTION_FIND_WAYPOINT = null;
public static GenericFunction FUNCTION_DUPLICATE_POINT = null;
public static GenericFunction FUNCTION_CONNECT_TO_POINT = null;
@@ -127,12 +125,10 @@ public abstract class FunctionLibrary
public static GenericFunction FUNCTION_CHARTS = null;
public static GenericFunction FUNCTION_3D = null;
public static GenericFunction FUNCTION_DISTANCES = null;
- public static GenericFunction FUNCTION_FULL_RANGE_DETAILS = null;
+ public static GenericFunction FUNCTION_FULL_DETAILS = null;
public static GenericFunction FUNCTION_AUTOPLAY_TRACK = null;
public static GenericFunction FUNCTION_ESTIMATE_TIME = null;
public static GenericFunction FUNCTION_LEARN_ESTIMATION_PARAMS = null;
- public static GenericFunction FUNCTION_GET_GPSIES = null;
- public static GenericFunction FUNCTION_UPLOAD_GPSIES = null;
public static GenericFunction FUNCTION_GET_WEATHER_FORECAST = null;
public static GenericFunction FUNCTION_LOAD_AUDIO = null;
public static GenericFunction FUNCTION_REMOVE_AUDIO = null;
@@ -168,6 +164,7 @@ public abstract class FunctionLibrary
FUNCTION_IMPORTBABEL = new BabelLoadFromFile(inApp);
FUNCTION_SAVECONFIG = new SaveConfig(inApp);
FUNCTION_EDIT_WAYPOINT_NAME = new PointNameEditor(inApp);
+ FUNCTION_PROJECT_POINT = new ProjectPoint(inApp);
FUNCTION_REARRANGE_WAYPOINTS = new RearrangeWaypointsFunction(inApp);
FUNCTION_SELECT_SEGMENT = new SelectSegmentFunction(inApp);
FUNCTION_SPLIT_SEGMENTS = new SplitSegmentsFunction(inApp);
@@ -192,7 +189,6 @@ public abstract class FunctionLibrary
FUNCTION_ADD_ALTITUDE_OFFSET = new AddAltitudeOffset(inApp);
FUNCTION_CONVERT_NAMES_TO_TIMES = new ConvertNamesToTimes(inApp);
FUNCTION_DELETE_FIELD_VALUES = new DeleteFieldValues(inApp);
- FUNCTION_PASTE_COORDINATES = new PasteCoordinates(inApp);
FUNCTION_FIND_WAYPOINT = new FindWaypoint(inApp);
FUNCTION_DUPLICATE_POINT = new DuplicatePoint(inApp);
FUNCTION_CONNECT_TO_POINT = new ConnectToPointFunction(inApp);
@@ -206,12 +202,10 @@ public abstract class FunctionLibrary
FUNCTION_CHARTS = new Charter(inApp);
FUNCTION_3D = new ShowThreeDFunction(inApp);
FUNCTION_DISTANCES = new DistanceFunction(inApp);
- FUNCTION_FULL_RANGE_DETAILS = new FullRangeDetails(inApp);
+ FUNCTION_FULL_DETAILS = new ShowFullDetails(inApp);
FUNCTION_AUTOPLAY_TRACK = new AutoplayFunction(inApp);
FUNCTION_ESTIMATE_TIME = new EstimateTime(inApp);
FUNCTION_LEARN_ESTIMATION_PARAMS = new LearnParameters(inApp);
- FUNCTION_GET_GPSIES = new GetGpsiesFunction(inApp);
- FUNCTION_UPLOAD_GPSIES = new UploadGpsiesFunction(inApp);
FUNCTION_GET_WEATHER_FORECAST = new GetWeatherForecastFunction(inApp);
FUNCTION_LOAD_AUDIO = new AudioLoader(inApp);
FUNCTION_REMOVE_AUDIO = new RemoveAudioFunction(inApp);
diff --git a/src/tim/prune/GpsPrune.java b/src/tim/prune/GpsPrune.java
index f396e9e..874ece5 100644
--- a/src/tim/prune/GpsPrune.java
+++ b/src/tim/prune/GpsPrune.java
@@ -9,9 +9,11 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Locale;
+
import javax.swing.JFrame;
import javax.swing.JSplitPane;
import javax.swing.JToolBar;
+import javax.swing.UIManager;
import javax.swing.WindowConstants;
import tim.prune.config.Config;
@@ -29,16 +31,16 @@ import tim.prune.gui.profile.ProfileChart;
/**
* GpsPrune is a tool to visualize, edit, convert and prune GPS data
* Please see the included readme.txt or https://activityworkshop.net
- * This software is copyright activityworkshop.net 2006-2018 and made available through the Gnu GPL version 2.
+ * This software is copyright activityworkshop.net 2006-2020 and made available through the Gnu GPL version 2.
* For license details please see the included license.txt.
* GpsPrune is the main entry point to the application, including initialisation and launch
*/
public class GpsPrune
{
/** Version number of application, used in about screen and for version check */
- public static final String VERSION_NUMBER = "19.2";
+ public static final String VERSION_NUMBER = "20";
/** Build number, just used for about screen */
- public static final String BUILD_NUMBER = "363d";
+ public static final String BUILD_NUMBER = "378";
/** Static reference to App object */
private static App APP = null;
@@ -149,6 +151,14 @@ public class GpsPrune
Config.setConfigString(Config.KEY_LANGUAGE_FILE, "");
}
}
+
+ // Set look-and-feel
+ try {
+ String windowStyle = Config.getConfigString(Config.KEY_WINDOW_STYLE);
+ UIManager.setLookAndFeel(windowStyle);
+ }
+ catch (Exception e) {}
+
// Set up the window and go
launch(dataFiles);
}
diff --git a/src/tim/prune/I18nManager.java b/src/tim/prune/I18nManager.java
index fbf781e..a271f81 100644
--- a/src/tim/prune/I18nManager.java
+++ b/src/tim/prune/I18nManager.java
@@ -18,10 +18,10 @@ import java.util.ResourceBundle;
public abstract class I18nManager
{
/** Properties object into which all the texts are copied */
- private static Properties LocalTexts = null;
+ private static Properties _localTexts = null;
/** External properties file for developer testing */
- private static Properties ExternalPropsFile = null;
+ private static Properties _externalPropsFile = null;
/**
@@ -33,7 +33,7 @@ public abstract class I18nManager
final String BUNDLE_NAME = "tim.prune.lang.prune-texts";
final Locale BACKUP_LOCALE = new Locale("en", "GB");
- LocalTexts = new Properties();
+ _localTexts = new Properties();
// Load English texts first to use as defaults
loadFromBundle(ResourceBundle.getBundle(BUNDLE_NAME, BACKUP_LOCALE));
@@ -65,7 +65,7 @@ public abstract class I18nManager
while (e.hasMoreElements())
{
String key = e.nextElement();
- LocalTexts.setProperty(key, inBundle.getString(key));
+ _localTexts.setProperty(key, inBundle.getString(key));
}
}
@@ -81,9 +81,9 @@ public abstract class I18nManager
try
{
File file = new File(inFilename);
- ExternalPropsFile = new Properties();
+ _externalPropsFile = new Properties();
fis = new FileInputStream(file);
- ExternalPropsFile.load(fis);
+ _externalPropsFile.load(fis);
fileLoaded = true; // everything worked
}
catch (IOException ioe) {}
@@ -103,17 +103,17 @@ public abstract class I18nManager
public static String getText(String inKey)
{
// look in external props file if available
- if (ExternalPropsFile != null)
+ if (_externalPropsFile != null)
{
- String extText = ExternalPropsFile.getProperty(inKey);
+ String extText = _externalPropsFile.getProperty(inKey);
if (extText != null) return extText;
}
// look in texts if available
- if (LocalTexts != null)
+ if (_localTexts != null)
{
try
{
- String localText = LocalTexts.getProperty(inKey);
+ String localText = _localTexts.getProperty(inKey);
if (localText != null) return localText;
}
catch (MissingResourceException mre) {}
diff --git a/src/tim/prune/config/Config.java b/src/tim/prune/config/Config.java
index 84e5fd7..8c6eefe 100644
--- a/src/tim/prune/config/Config.java
+++ b/src/tim/prune/config/Config.java
@@ -55,6 +55,8 @@ public abstract class Config
public static final String KEY_POVRAY_FONT = "prune.povrayfont";
/** Key for the selected unit set */
public static final String KEY_UNITSET_KEY = "prune.unitsetkey";
+ /** Key for the selected coordinate display format */
+ public static final String KEY_COORD_DISPLAY_FORMAT = "prune.coorddisplay";
/** Key for index of map source */
public static final String KEY_MAPSOURCE_INDEX = "prune.mapsource";
/** Key for number of fixed map sources */
@@ -87,6 +89,8 @@ public abstract class Config
public static final String KEY_ANTIALIAS = "prune.antialias";
/** Key for kml track colour */
public static final String KEY_KML_TRACK_COLOUR = "prune.kmltrackcolour";
+ /** Key for window style (name of look-and-feel) */
+ public static final String KEY_WINDOW_STYLE = "prune.windowstyle";
/** Key for autosaving settings */
public static final String KEY_AUTOSAVE_SETTINGS = "prune.autosavesettings";
/** Key for recently used files */
@@ -170,6 +174,8 @@ public abstract class Config
_unitSet = UnitSetLibrary.getUnitSet(_configValues.getProperty(KEY_UNITSET_KEY));
// Adjust map source index if necessary
adjustSelectedMap();
+ // Reset coord display format
+ setConfigInt(KEY_COORD_DISPLAY_FORMAT, 0);
if (loadFailed) {
throw new ConfigException();
@@ -197,6 +203,7 @@ public abstract class Config
props.put(KEY_ANTIALIAS, "1"); // antialias on by default
props.put(KEY_AUTOSAVE_SETTINGS, "0"); // autosave false by default
props.put(KEY_UNITSET_KEY, "unitset.kilometres"); // metric by default
+ props.put(KEY_COORD_DISPLAY_FORMAT, "0"); // original
props.put(KEY_HEIGHT_EXAGGERATION, "100"); // 100%, no exaggeration
props.put(KEY_TERRAIN_GRID_SIZE, "50");
props.put(KEY_ALTITUDE_TOLERANCE, "0"); // 0, all exact as before
@@ -246,6 +253,14 @@ public abstract class Config
return _configFile;
}
+ /**
+ * Set the file to which config was saved
+ */
+ public static void setConfigFile(File inFile)
+ {
+ _configFile = inFile;
+ }
+
/**
* @return config Properties object to allow all config values to be saved
*/
@@ -379,7 +394,7 @@ public abstract class Config
public static void updatePointColourer(PointColourer inColourer)
{
_pointColourer = inColourer;
- setConfigString(KEY_POINT_COLOURER, ColourerFactory.PointColourerToString(_pointColourer));
+ setConfigString(KEY_POINT_COLOURER, ColourerFactory.pointColourerToString(_pointColourer));
}
/**
diff --git a/src/tim/prune/copyright.txt b/src/tim/prune/copyright.txt
index 3022774..db7f2dd 100644
--- a/src/tim/prune/copyright.txt
+++ b/src/tim/prune/copyright.txt
@@ -1,4 +1,4 @@
-The source code of GpsPrune is copyright 2006-2018 activityworkshop.net
+The source code of GpsPrune is copyright 2006-2020 activityworkshop.net
and is distributed under the terms of the Gnu GPL version 2.
Portions of the package jpeg.drew were taken
@@ -6,4 +6,4 @@ from Drew Noakes' "Metadata extractor" v2.7.2 which is
copyright Drew Noakes 2002-2015 and released under Apache 2.0.
Translations are copyright various contributors, some of whom are named
-in the source code and some preferred to remain anonymous.
\ No newline at end of file
+in the source code and some preferred to remain anonymous.
diff --git a/src/tim/prune/data/Coordinate.java b/src/tim/prune/data/Coordinate.java
index e30fa4a..b668660 100644
--- a/src/tim/prune/data/Coordinate.java
+++ b/src/tim/prune/data/Coordinate.java
@@ -475,4 +475,22 @@ public abstract class Coordinate
return "Coord: " + _cardinal + " (" + _degrees + ") (" + _minutes + ") (" + _seconds + "."
+ formatFraction(_fracs, _fracDenom) + ") = " + _asDouble;
}
+
+ /**
+ * From a saved coordinate format display value, get the corresponding value to use
+ * @param inValue value from config
+ * @return coordinate format as int
+ */
+ public static int getCoordinateFormatForDisplay(int inValue)
+ {
+ switch(inValue)
+ {
+ case FORMAT_DEG:
+ case FORMAT_DEG_MIN:
+ case FORMAT_DEG_MIN_SEC:
+ return inValue;
+ default:
+ return FORMAT_NONE;
+ }
+ }
}
diff --git a/src/tim/prune/data/FileInfo.java b/src/tim/prune/data/FileInfo.java
index 41900cb..0c4ee5f 100644
--- a/src/tim/prune/data/FileInfo.java
+++ b/src/tim/prune/data/FileInfo.java
@@ -51,7 +51,9 @@ public class FileInfo
*/
public void removeSource()
{
- _sources.remove(_sources.size()-1);
+ if (!_sources.isEmpty()) {
+ _sources.remove(_sources.size()-1);
+ }
}
/**
diff --git a/src/tim/prune/data/RangeStats.java b/src/tim/prune/data/RangeStats.java
index 13ecaad..d8461c4 100644
--- a/src/tim/prune/data/RangeStats.java
+++ b/src/tim/prune/data/RangeStats.java
@@ -1,163 +1,133 @@
package tim.prune.data;
-import tim.prune.config.Config;
-
/**
- * Class to do calculations of range statistics such as distances, durations,
- * speeds, gradients etc, and to hold the results of the calculations.
- * Used by FullRangeDetails as well as the EstimateTime functions.
+ * Class to do basic calculations of range statistics such as distances, durations,
+ * and altitude ranges, and to hold the results of the calculations.
*/
public class RangeStats
{
- // MAYBE: Split into basic stats (quick to calculate, for detailsdisplay) and full stats (for other two)
- private boolean _valid = false;
- private int _numPoints = 0;
- private int _startIndex = 0, _endIndex = 0;
- private int _numSegments = 0;
- private AltitudeRange _totalAltitudeRange = null, _movingAltitudeRange = null;
- private AltitudeRange _gentleAltitudeRange = null, _steepAltitudeRange = null;
+ private int _numPoints = 0;
+ private int _numSegments = 0;
+ private boolean _foundTrackPoint = false;
+ protected AltitudeRange _totalAltitudeRange = new AltitudeRange();
+ protected AltitudeRange _movingAltitudeRange = new AltitudeRange();
private Timestamp _earliestTimestamp = null, _latestTimestamp = null;
private long _movingMilliseconds = 0L;
private boolean _timesIncomplete = false;
private boolean _timesOutOfSequence = false;
- private double _totalDistanceRads = 0.0, _movingDistanceRads = 0.0;
- // Note, maximum speed is not calculated here, use the SpeedData class instead
+ protected double _totalDistanceRads = 0.0, _movingDistanceRads = 0.0;
+ protected DataPoint _prevPoint = null;
- private static final double STEEP_ANGLE = 0.15; // gradient steeper than 15% counts as steep
+ /** Constructor */
+ public RangeStats()
+ {}
/**
- * Constructor
- * @param inTrack track to compile data for
- * @param inStartIndex start index of range to examine
- * @param inEndIndex end index (inclusive) of range to examine
+ * Constructor giving Track
+ * @param inTrack track object to calculate with
*/
public RangeStats(Track inTrack, int inStartIndex, int inEndIndex)
{
- if (inTrack != null && inStartIndex >= 0 && inEndIndex > inStartIndex
- && inEndIndex < inTrack.getNumPoints())
+ populateFromTrack(inTrack, inStartIndex, inEndIndex);
+ }
+
+ /**
+ * Add the specified points from the given track to the calculations
+ * @param inTrack track object
+ * @param inStartIndex start index (inclusive)
+ * @param inEndIndex end index (inclusive)
+ */
+ protected void populateFromTrack(Track inTrack, int inStartIndex, int inEndIndex)
+ {
+ for (int i=inStartIndex; i<=inEndIndex; i++)
{
- _valid = calculateStats(inTrack, inStartIndex, inEndIndex);
+ addPoint(inTrack.getPoint(i));
}
}
/**
- * Calculate the statistics and populate the member variables with the results
- * @param inTrack track
- * @param inStartIndex start index of range
- * @param inEndIndex end index (inclusive) of range
- * @return true on success
+ * @param inPoint point to add to the calculations
*/
- private boolean calculateStats(Track inTrack, int inStartIndex, int inEndIndex)
+ public void addPoint(DataPoint inPoint)
{
- _startIndex = inStartIndex;
- _endIndex = inEndIndex;
- _numPoints = inEndIndex - inStartIndex + 1;
- _totalAltitudeRange = new AltitudeRange();
- _movingAltitudeRange = new AltitudeRange();
- _gentleAltitudeRange = new AltitudeRange();
- _steepAltitudeRange = new AltitudeRange();
- DataPoint prevPoint = null;
- Altitude prevAltitude = null;
- _totalDistanceRads = _movingDistanceRads = 0.0;
- double radsSinceLastAltitude = 0.0;
- _movingMilliseconds = 0L;
-
- // Loop over the points in the range
- for (int i=inStartIndex; i<= inEndIndex; i++)
+ if (inPoint == null)
+ {
+ return;
+ }
+ _numPoints++;
+ // ignore all waypoints
+ if (inPoint.isWaypoint()) {
+ return;
+ }
+ if (inPoint.getSegmentStart() || !_foundTrackPoint) {
+ _numSegments++;
+ }
+ _foundTrackPoint = true;
+ // Get the distance to the previous track point
+ if (_prevPoint != null)
{
- DataPoint p = inTrack.getPoint(i);
- if (p == null) return false;
- // ignore all waypoints
- if (p.isWaypoint()) continue;
+ double rads = DataPoint.calculateRadiansBetween(_prevPoint, inPoint);
+ _totalDistanceRads += rads;
+ if (!inPoint.getSegmentStart()) {
+ _movingDistanceRads += rads;
+ }
+ }
- if (p.getSegmentStart()) {
- _numSegments++;
+ // timestamps
+ if (inPoint.hasTimestamp())
+ {
+ Timestamp currTstamp = inPoint.getTimestamp();
+ if (_earliestTimestamp == null || currTstamp.isBefore(_earliestTimestamp)) {
+ _earliestTimestamp = currTstamp;
}
- // Get the distance to the previous track point
- if (prevPoint != null)
- {
- double rads = DataPoint.calculateRadiansBetween(prevPoint, p);
- _totalDistanceRads += rads;
- if (!p.getSegmentStart()) {
- _movingDistanceRads += rads;
- }
- // Keep track of rads since last point with an altitude
- radsSinceLastAltitude += rads;
+ if (_latestTimestamp == null || currTstamp.isAfter(_latestTimestamp)) {
+ _latestTimestamp = currTstamp;
}
- // Get the altitude difference to the previous track point
- if (p.hasAltitude())
+ // Work out duration without segment gaps
+ if (!inPoint.getSegmentStart() && _prevPoint != null && _prevPoint.hasTimestamp())
{
- Altitude altitude = p.getAltitude();
- _totalAltitudeRange.addValue(altitude);
- if (p.getSegmentStart()) {
- _movingAltitudeRange.ignoreValue(altitude);
+ long millisLater = currTstamp.getMillisecondsSince(_prevPoint.getTimestamp());
+ if (millisLater < 0) {
+ _timesOutOfSequence = true;
}
- else
- {
- _movingAltitudeRange.addValue(altitude);
- if (prevAltitude != null)
- {
- // Work out gradient, see whether to ignore/add to gentle or steep
- double heightDiff = altitude.getMetricValue() - prevAltitude.getMetricValue();
- double metricDist = Distance.convertRadiansToDistance(radsSinceLastAltitude, UnitSetLibrary.UNITS_METRES);
- final boolean isSteep = metricDist < 0.001 || (Math.abs(heightDiff / metricDist) > STEEP_ANGLE);
- if (isSteep) {
- _steepAltitudeRange.ignoreValue(prevAltitude);
- _steepAltitudeRange.addValue(altitude);
- }
- else {
- _gentleAltitudeRange.ignoreValue(prevAltitude);
- _gentleAltitudeRange.addValue(altitude);
- }
- }
+ else {
+ _movingMilliseconds += millisLater;
}
- prevAltitude = altitude;
- radsSinceLastAltitude = 0.0;
}
+ }
+ else {
+ _timesIncomplete = true;
+ }
- if (p.hasTimestamp())
- {
- if (_earliestTimestamp == null || p.getTimestamp().isBefore(_earliestTimestamp)) {
- _earliestTimestamp = p.getTimestamp();
- }
- if (_latestTimestamp == null || p.getTimestamp().isAfter(_latestTimestamp)) {
- _latestTimestamp = p.getTimestamp();
- }
- // Work out duration without segment gaps
- if (!p.getSegmentStart() && prevPoint != null && prevPoint.hasTimestamp())
- {
- long millisLater = p.getTimestamp().getMillisecondsSince(prevPoint.getTimestamp());
- if (millisLater < 0) {_timesOutOfSequence = true;}
- else {
- _movingMilliseconds += millisLater;
- }
- }
+ // altitudes
+ if (inPoint.hasAltitude())
+ {
+ Altitude altitude = inPoint.getAltitude();
+ _totalAltitudeRange.addValue(altitude);
+ if (inPoint.getSegmentStart()) {
+ _movingAltitudeRange.ignoreValue(altitude);
}
- else {
- _timesIncomplete = true;
+ else
+ {
+ _movingAltitudeRange.addValue(altitude);
}
-
- prevPoint = p;
}
- return true;
- }
+ // allow child classes to do additional calculations
+ doFurtherCalculations(inPoint);
- /** @return true if results are valid */
- public boolean isValid() {
- return _valid;
+ _prevPoint = inPoint;
}
- /** @return start index of range */
- public int getStartIndex() {
- return _startIndex;
+ /**
+ * Hook for subclasses to do what they want in addition
+ * @param inPoint incoming point
+ */
+ protected void doFurtherCalculations(DataPoint inPoint)
+ {
}
- /** @return end index of range */
- public int getEndIndex() {
- return _endIndex;
- }
/** @return number of points in range */
public int getNumPoints() {
@@ -179,16 +149,6 @@ public class RangeStats
return _movingAltitudeRange;
}
- /** @return altitude range of range just considering low gradient bits */
- public AltitudeRange getGentleAltitudeRange() {
- return _gentleAltitudeRange;
- }
-
- /** @return altitude range of range just considering high gradient bits */
- public AltitudeRange getSteepAltitudeRange() {
- return _steepAltitudeRange;
- }
-
/** @return the earliest timestamp found */
public Timestamp getEarliestTimestamp() {
return _earliestTimestamp;
@@ -239,42 +199,26 @@ public class RangeStats
return Distance.convertRadiansToDistance(_movingDistanceRads, UnitSetLibrary.UNITS_KILOMETRES);
}
- /** @return the total gradient in % (including segment gaps) */
- public double getTotalGradient()
- {
- double dist = Distance.convertRadiansToDistance(_totalDistanceRads, UnitSetLibrary.UNITS_METRES);
- if (dist > 0.0 && _totalAltitudeRange.hasRange()) {
- return _totalAltitudeRange.getMetricHeightDiff() / dist * 100.0;
- }
- return 0.0;
- }
-
- /** @return the moving gradient in % (ignoring segment gaps) */
- public double getMovingGradient()
- {
- double dist = Distance.convertRadiansToDistance(_movingDistanceRads, UnitSetLibrary.UNITS_METRES);
- if (dist > 0.0 && _movingAltitudeRange.hasRange()) {
- return _movingAltitudeRange.getMetricHeightDiff() / dist * 100.0;
- }
- return 0.0;
- }
-
- /** @return the total vertical speed (including segment gaps) in current vspeed units */
+ /**
+ * @return the total vertical speed (including segment gaps) in metric units
+ */
public double getTotalVerticalSpeed()
{
long time = getTotalDurationInSeconds();
if (time > 0 && _totalAltitudeRange.hasRange()) {
- return _totalAltitudeRange.getMetricHeightDiff() / time * Config.getUnitSet().getVerticalSpeedUnit().getMultFactorFromStd();
+ return _totalAltitudeRange.getMetricHeightDiff() / time;
}
return 0.0;
}
- /** @return the moving vertical speed (ignoring segment gaps) in current vspeed units */
+ /**
+ * @return the moving vertical speed (ignoring segment gaps) in metric units
+ */
public double getMovingVerticalSpeed()
{
long time = getMovingDurationInSeconds();
if (time > 0 && _movingAltitudeRange.hasRange()) {
- return _movingAltitudeRange.getMetricHeightDiff() / time * Config.getUnitSet().getVerticalSpeedUnit().getMultFactorFromStd();
+ return _movingAltitudeRange.getMetricHeightDiff() / time;
}
return 0.0;
}
diff --git a/src/tim/prune/data/RangeStatsWithGradients.java b/src/tim/prune/data/RangeStatsWithGradients.java
new file mode 100644
index 0000000..c495c51
--- /dev/null
+++ b/src/tim/prune/data/RangeStatsWithGradients.java
@@ -0,0 +1,106 @@
+package tim.prune.data;
+
+/**
+ * Class to do additional range calculations including gradients
+ * Used by full details display as well as the EstimateTime functions.
+ */
+public class RangeStatsWithGradients extends RangeStats
+{
+ private AltitudeRange _gentleAltitudeRange = new AltitudeRange();
+ private AltitudeRange _steepAltitudeRange = new AltitudeRange();
+ private Altitude _prevAltitude = null;
+ private double _radsSinceLastAltitude = 0.0;
+
+ private static final double STEEP_ANGLE = 0.15; // gradient steeper than 15% counts as steep
+
+
+ /**
+ * Default constructor
+ */
+ public RangeStatsWithGradients()
+ {
+ super();
+ }
+
+ /**
+ * Constructor
+ * @param inTrack track object
+ * @param inStartIndex start index
+ * @param inEndIndex end index
+ */
+ public RangeStatsWithGradients(Track inTrack, int inStartIndex, int inEndIndex)
+ {
+ super();
+ populateFromTrack(inTrack, inStartIndex, inEndIndex);
+ }
+
+ /**
+ * Add the given point to the calculations
+ * @param inPoint incoming point
+ */
+ protected void doFurtherCalculations(DataPoint inPoint)
+ {
+ if (_prevPoint != null)
+ {
+ // Keep track of rads since last point with an altitude
+ double rads = DataPoint.calculateRadiansBetween(_prevPoint, inPoint);
+ _radsSinceLastAltitude += rads;
+ }
+
+ if (inPoint.hasAltitude())
+ {
+ Altitude altitude = inPoint.getAltitude();
+
+ if (!inPoint.getSegmentStart() && _prevAltitude != null)
+ {
+ // Work out gradient, see whether to ignore/add to gentle or steep
+ double heightDiff = altitude.getMetricValue() - _prevAltitude.getMetricValue();
+ double metricDist = Distance.convertRadiansToDistance(_radsSinceLastAltitude, UnitSetLibrary.UNITS_METRES);
+ final boolean isSteep = metricDist < 0.001 || (Math.abs(heightDiff / metricDist) > STEEP_ANGLE);
+ if (isSteep)
+ {
+ _steepAltitudeRange.ignoreValue(_prevAltitude);
+ _steepAltitudeRange.addValue(altitude);
+ }
+ else
+ {
+ _gentleAltitudeRange.ignoreValue(_prevAltitude);
+ _gentleAltitudeRange.addValue(altitude);
+ }
+ }
+ _prevAltitude = altitude;
+ _radsSinceLastAltitude = 0.0;
+ }
+
+ }
+
+ /** @return altitude range of range just considering low gradient bits */
+ public AltitudeRange getGentleAltitudeRange() {
+ return _gentleAltitudeRange;
+ }
+
+ /** @return altitude range of range just considering high gradient bits */
+ public AltitudeRange getSteepAltitudeRange() {
+ return _steepAltitudeRange;
+ }
+
+ /** @return the total gradient in % (including segment gaps) */
+ public double getTotalGradient()
+ {
+ double dist = Distance.convertRadiansToDistance(_totalDistanceRads, UnitSetLibrary.UNITS_METRES);
+ if (dist > 0.0 && _totalAltitudeRange.hasRange()) {
+ return _totalAltitudeRange.getMetricHeightDiff() / dist * 100.0;
+ }
+ return 0.0;
+ }
+
+ /** @return the moving gradient in % (ignoring segment gaps) */
+ public double getMovingGradient()
+ {
+ double dist = Distance.convertRadiansToDistance(_movingDistanceRads, UnitSetLibrary.UNITS_METRES);
+ if (dist > 0.0 && _movingAltitudeRange.hasRange()) {
+ return _movingAltitudeRange.getMetricHeightDiff() / dist * 100.0;
+ }
+ return 0.0;
+ }
+}
diff --git a/src/tim/prune/data/Selection.java b/src/tim/prune/data/Selection.java
index 7b63d70..24fda5d 100644
--- a/src/tim/prune/data/Selection.java
+++ b/src/tim/prune/data/Selection.java
@@ -11,14 +11,11 @@ public class Selection
{
private Track _track = null;
private int _currentPoint = -1;
- private boolean _valid = false;
private int _prevNumPoints = 0;
private int _startIndex = -1, _endIndex = -1;
private int _currentPhotoIndex = -1;
private int _currentAudioIndex = -1;
- private AltitudeRange _altitudeRange = null;
- private long _movingMilliseconds = 0L;
- private double _angMovingDistance = -1.0;
+ private RangeStats _rangeStats = null;
/**
@@ -36,7 +33,7 @@ public class Selection
*/
public void markInvalid()
{
- _valid = false;
+ _rangeStats = null;
}
@@ -63,6 +60,9 @@ public class Selection
*/
private void recalculate()
{
+ if (_rangeStats != null) {
+ return;
+ }
final int numPoints = _track.getNumPoints();
// Recheck if the number of points has changed
if (numPoints != _prevNumPoints)
@@ -72,52 +72,12 @@ public class Selection
}
if (numPoints > 0 && hasRangeSelected())
{
- _altitudeRange = new AltitudeRange();
- Altitude altitude = null;
- Timestamp time = null, previousTime = null;
- DataPoint lastPoint = null, currPoint = null;
- _angMovingDistance = 0.0;
- _movingMilliseconds = 0L;
- // Loop over points in selection
- for (int i=_startIndex; i<=_endIndex; i++)
- {
- currPoint = _track.getPoint(i);
- altitude = currPoint.getAltitude();
- // Ignore waypoints in altitude calculations
- if (!currPoint.isWaypoint() && altitude.isValid())
- {
- if (currPoint.getSegmentStart()) {
- _altitudeRange.ignoreValue(altitude);
- }
- else {
- _altitudeRange.addValue(altitude);
- }
- }
- // Compare timestamps within the segments
- time = currPoint.getTimestamp();
- if (time.isValid())
- {
- // add moving time
- if (!currPoint.getSegmentStart() && previousTime != null && time.isAfter(previousTime)) {
- _movingMilliseconds += time.getMillisecondsSince(previousTime);
- }
- previousTime = time;
- }
- // Calculate distances, again ignoring waypoints
- if (!currPoint.isWaypoint())
- {
- if (lastPoint != null)
- {
- double radians = DataPoint.calculateRadiansBetween(lastPoint, currPoint);
- if (!currPoint.getSegmentStart()) {
- _angMovingDistance += radians;
- }
- }
- lastPoint = currPoint;
- }
- }
+ _rangeStats = new RangeStats(_track, _startIndex, _endIndex);
+ }
+ else
+ {
+ _rangeStats = new RangeStats();
}
- _valid = true;
}
@@ -126,7 +86,7 @@ public class Selection
*/
public int getStart()
{
- if (!_valid) recalculate();
+ recalculate();
return _startIndex;
}
@@ -136,7 +96,7 @@ public class Selection
*/
public int getEnd()
{
- if (!_valid) recalculate();
+ recalculate();
return _endIndex;
}
@@ -145,8 +105,8 @@ public class Selection
*/
public AltitudeRange getAltitudeRange()
{
- if (!_valid) recalculate();
- return _altitudeRange;
+ recalculate();
+ return _rangeStats.getTotalAltitudeRange();
}
@@ -155,8 +115,8 @@ public class Selection
*/
public long getMovingSeconds()
{
- if (!_valid) recalculate();
- return _movingMilliseconds / 1000L;
+ recalculate();
+ return _rangeStats.getMovingDurationInSeconds();
}
/**
@@ -164,7 +124,7 @@ public class Selection
*/
public double getMovingDistance()
{
- return Distance.convertRadiansToDistance(_angMovingDistance);
+ return _rangeStats.getMovingDistance();
}
/**
@@ -176,6 +136,7 @@ public class Selection
selectRange(-1, -1);
_currentPhotoIndex = -1;
_currentAudioIndex = -1;
+ markInvalid();
check();
}
@@ -276,6 +237,7 @@ public class Selection
// Clear selected range
_startIndex = _endIndex = -1;
// Check for consistency and fire update
+ markInvalid();
check();
}
@@ -355,6 +317,7 @@ public class Selection
{
// track is empty, clear selections
_currentPoint = _startIndex = _endIndex = -1;
+ markInvalid();
}
UpdateMessageBroker.informSubscribers(DataSubscriber.SELECTION_CHANGED);
}
diff --git a/src/tim/prune/data/Timestamp.java b/src/tim/prune/data/Timestamp.java
index ac144bb..6083cf6 100644
--- a/src/tim/prune/data/Timestamp.java
+++ b/src/tim/prune/data/Timestamp.java
@@ -22,7 +22,7 @@ public abstract class Timestamp
protected static final DateFormat ISO_8601_FORMAT_WITH_MILLIS
= new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
- private static boolean MillisAddedToTimeFormat = false;
+ private static boolean _millisAddedToTimeFormat = false;
/** Possible formats for parsing and displaying timestamps */
@@ -138,7 +138,7 @@ public abstract class Timestamp
{
if (!isValid()) return "";
// Maybe we should add milliseconds to this format?
- if (hasMilliseconds() && !MillisAddedToTimeFormat)
+ if (hasMilliseconds() && !_millisAddedToTimeFormat)
{
try
{
@@ -147,7 +147,7 @@ public abstract class Timestamp
if (pattern.indexOf("ss") > 0 && pattern.indexOf("SS") < 0)
{
sdf.applyPattern(pattern.replaceFirst("s+", "$0.SSS"));
- MillisAddedToTimeFormat = true;
+ _millisAddedToTimeFormat = true;
}
}
catch (ClassCastException cce) {}
diff --git a/src/tim/prune/function/AboutScreen.java b/src/tim/prune/function/AboutScreen.java
index 80a7983..518b10e 100644
--- a/src/tim/prune/function/AboutScreen.java
+++ b/src/tim/prune/function/AboutScreen.java
@@ -98,7 +98,7 @@ public class AboutScreen extends GenericFunction
descBuffer.append("").append(I18nManager.getText("dialog.about.languages")).append(" : ")
.append("afrikaans, \u010de\u0161tina, deutsch, english, espa\u00F1ol, fran\u00E7ais, italiano,
" +
" magyar, nederlands, polski, portugu\u00EAs, rom\u00E2n\u0103, suomi, \u0440\u0443\u0441\u0441\u043a\u0438\u0439 (russian),
" +
- " \u4e2d\u6587 (chinese), \u65E5\u672C\u8A9E (japanese), \uD55C\uAD6D\uC5B4/\uC870\uC120\uB9D0 (korean), schwiizerd\u00FC\u00FCtsch, ukrainian
");
+ " \u4e2d\u6587 (chinese), \u65E5\u672C\u8A9E (japanese), \uD55C\uAD6D\uC5B4/\uC870\uC120\uB9D0 (korean), schwiizerd\u00FC\u00FCtsch
");
descBuffer.append("").append(I18nManager.getText("dialog.about.translatedby")).append("
");
JEditorPane descPane = new JEditorPane("text/html", descBuffer.toString());
descPane.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
diff --git a/src/tim/prune/function/AddAltitudeOffset.java b/src/tim/prune/function/AddAltitudeOffset.java
index c98ab3e..26849de 100644
--- a/src/tim/prune/function/AddAltitudeOffset.java
+++ b/src/tim/prune/function/AddAltitudeOffset.java
@@ -101,7 +101,7 @@ public class AddAltitudeOffset extends GenericFunction
MouseAdapter mouseListener = new MouseAdapter() {
public void mouseReleased(java.awt.event.MouseEvent arg0) {
_okButton.setEnabled(Math.abs(getOffset()) > 0.001);
- };
+ }
};
_editField.addKeyListener(keyListener);
_editField.addMouseListener(mouseListener);
diff --git a/src/tim/prune/function/AddTimeOffset.java b/src/tim/prune/function/AddTimeOffset.java
index 2e259bb..115bfa5 100644
--- a/src/tim/prune/function/AddTimeOffset.java
+++ b/src/tim/prune/function/AddTimeOffset.java
@@ -126,7 +126,7 @@ public class AddTimeOffset extends GenericFunction
MouseAdapter mouseListener = new MouseAdapter() {
public void mouseReleased(java.awt.event.MouseEvent arg0) {
_okButton.setEnabled(getOffsetSecs() != 0L);
- };
+ }
};
_dayField.addKeyListener(keyListener);
_hourField.addKeyListener(keyListener);
diff --git a/src/tim/prune/function/ConnectToPointFunction.java b/src/tim/prune/function/ConnectToPointFunction.java
index 0998020..9921dc5 100644
--- a/src/tim/prune/function/ConnectToPointFunction.java
+++ b/src/tim/prune/function/ConnectToPointFunction.java
@@ -42,9 +42,9 @@ public class ConnectToPointFunction extends GenericFunction
boolean connectPhoto = (point != null && photo != null && point.getPhoto() == null);
boolean connectAudio = (point != null && audio != null && point.getAudio() == null);
- if (connectPhoto && connectAudio) {
+ // if (connectPhoto && connectAudio) {
// TODO: Let user choose whether to connect photo/audio or both
- }
+ // }
// Make undo object
UndoOperation undo = new UndoConnectMedia(point, connectPhoto?photo.getName():null,
connectAudio?audio.getName():null);
diff --git a/src/tim/prune/function/CreateMarkerWaypointsFunction.java b/src/tim/prune/function/CreateMarkerWaypointsFunction.java
index f3dd1f1..92b4ce5 100644
--- a/src/tim/prune/function/CreateMarkerWaypointsFunction.java
+++ b/src/tim/prune/function/CreateMarkerWaypointsFunction.java
@@ -8,12 +8,14 @@ import tim.prune.UpdateMessageBroker;
import tim.prune.data.DataPoint;
import tim.prune.data.Field;
import tim.prune.data.FieldList;
+import tim.prune.data.RangeStats;
import tim.prune.data.Track;
+import tim.prune.data.UnitSetLibrary;
import tim.prune.undo.UndoAppendPoints;
/**
- * Function to create waypoints marking either
- * at regular distance intervals or time intervals
+ * Function to create waypoints marking regular distance intervals,
+ * regular time intervals, or halfway points
*/
public class CreateMarkerWaypointsFunction extends DistanceTimeLimitFunction
{
@@ -22,12 +24,21 @@ public class CreateMarkerWaypointsFunction extends DistanceTimeLimitFunction
/** Counter of previously used multiple */
private int _previousMultiple = 0;
+ /*
+ * Type of halfway point
+ */
+ private enum HalfwayType
+ {
+ HALF_DISTANCE,
+ HALF_CLIMB,
+ HALF_DESCENT
+ }
/**
* Constructor
*/
public CreateMarkerWaypointsFunction(App inApp) {
- super(inApp);
+ super(inApp, true);
}
/**
@@ -51,55 +62,34 @@ public class CreateMarkerWaypointsFunction extends DistanceTimeLimitFunction
*/
protected void performFunction()
{
- // Distribute either by distance or time
+ // Determine which kind of markers to create
final int timeLimitSeconds = getTimeLimitInSeconds();
final boolean createByTime = (timeLimitSeconds > 0);
- final double distLimitRadians = getDistanceLimitRadians();
- final boolean createByDistance = (distLimitRadians > 0.0);
- if (!createByTime && !createByDistance) {
- return; // neither option selected
- }
-
- // Make undo object
- final int numPoints = _app.getTrackInfo().getTrack().getNumPoints();
- UndoAppendPoints undo = new UndoAppendPoints(numPoints);
+ final double distLimitKm = getDistanceLimitKilometres();
+ final boolean createByDistance = (distLimitKm > 0.0);
+ final boolean createHalves = isHalvesSelected();
// set up the memory from scratch to collect the created points
initMemory();
- // Make new waypoints, looping through the points in the track
- DataPoint currPoint = null, prevPoint = null;
- double currValue = 0.0, prevValue = 0.0;
- for (int i=0; i 0);
+ final boolean createByDistance = (inDistLimitKm > 0.0);
+
+ // Make new waypoints, looping through the points in the track
+ DataPoint currPoint = null, prevPoint = null;
+ double currValue = 0.0, prevValue = 0.0;
+ RangeStats rangeStats = new RangeStats();
+ final int numPoints = _app.getTrackInfo().getTrack().getNumPoints();
+ for (int i=0; i 0.0)
+ {
+ final double currDist = partialStats.getMovingDistanceKilometres();
+ createdDistance = processHalfValue(prevPoint, prevDistance, halfDistance,
+ currPoint, currDist, HalfwayType.HALF_DISTANCE);
+ prevDistance = currDist;
+ }
+ // climb
+ if (!createdClimb && totalClimb > 0.0)
+ {
+ final double currClimb = partialStats.getMovingAltitudeRange().getClimb(UnitSetLibrary.UNITS_METRES);
+ createdClimb = processHalfValue(prevPoint, prevClimb, halfClimb,
+ currPoint, currClimb, HalfwayType.HALF_CLIMB);
+ prevClimb = currClimb;
+ }
+ // descent
+ if (!createdDescent && totalDescent > 0.0)
+ {
+ final double currDescent = partialStats.getMovingAltitudeRange().getDescent(UnitSetLibrary.UNITS_METRES);
+ createdDescent = processHalfValue(prevPoint, prevDescent, halfDescent,
+ currPoint, currDescent, HalfwayType.HALF_DESCENT);
+ prevDescent = currDescent;
+ }
+
+ prevPoint = currPoint;
+ }
+ }
+ }
+
+ /**
+ * Consider a pair of points in the track to see if a new halfway marker should be inserted between them
+ * @param inPrevPoint previous point
+ * @param inPrevValue value of function at this previous point
+ * @param inTargetValue target halfway value
+ * @param inCurrPoint current point
+ * @param inCurrValue value of function at this current point
+ * @param inType type of halfway point
+ */
+ private boolean processHalfValue(DataPoint inPrevPoint, double inPrevValue, double inTargetValue,
+ DataPoint inCurrPoint, double inCurrValue, HalfwayType inType)
+ {
+ if (inPrevValue <= inTargetValue && inCurrValue >= inTargetValue)
+ {
+ // Calculate position of limit between the two points
+ final double valueBeforeBreak = inTargetValue - inPrevValue;
+ final double valueAfterBreak = inCurrValue - inTargetValue;
+ final double fractionFromPrev = valueBeforeBreak / (valueBeforeBreak + valueAfterBreak);
+ DataPoint marker = DataPoint.interpolate(inPrevPoint, inCurrPoint, fractionFromPrev);
+ marker.setFieldValue(Field.WAYPT_NAME, createHalfwayName(inType), false);
+ _pointsToAdd.add(marker);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Create the name of the halfway point according to type
+ * @param inType type of point
+ */
+ private String createHalfwayName(HalfwayType inType)
+ {
+ String typeString = null;
+ switch (inType)
+ {
+ case HALF_DISTANCE:
+ typeString = "distance";
+ break;
+ case HALF_CLIMB:
+ typeString = "climb";
+ break;
+ case HALF_DESCENT:
+ typeString = "descent";
+ break;
+ }
+ if (typeString != null)
+ {
+ return I18nManager.getText("dialog.markers.half." + typeString);
+ }
+ return "half";
+ }
}
diff --git a/src/tim/prune/function/DistanceTimeLimitFunction.java b/src/tim/prune/function/DistanceTimeLimitFunction.java
index eaa7b7d..48075e7 100644
--- a/src/tim/prune/function/DistanceTimeLimitFunction.java
+++ b/src/tim/prune/function/DistanceTimeLimitFunction.java
@@ -10,8 +10,7 @@ import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
-import javax.swing.Box;
-import javax.swing.BoxLayout;
+import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComboBox;
@@ -28,6 +27,7 @@ import tim.prune.data.Field;
import tim.prune.data.TimeDifference;
import tim.prune.data.Unit;
import tim.prune.data.UnitSetLibrary;
+import tim.prune.gui.GuiGridLayout;
import tim.prune.gui.WholeNumberField;
/**
@@ -40,6 +40,10 @@ public abstract class DistanceTimeLimitFunction extends GenericFunction
protected JDialog _dialog = null;
/** Radio buttons for splitting by distance and time */
private JRadioButton _distLimitRadio = null, _timeLimitRadio = null;
+ /** Radio button for splitting by fraction (such as half-distance) */
+ private JRadioButton _halvesRadio = null;
+ /** Flag for whether to offer halves or not */
+ private boolean _showHalves = false;
/** Dropdown for selecting distance units */
private JComboBox _distUnitsDropdown = null;
/** Text field for entering distance */
@@ -52,29 +56,28 @@ public abstract class DistanceTimeLimitFunction extends GenericFunction
/**
- * React to item changes and key presses
+ * React to item changes and key presses by enabling / disabling ok button
*/
- private abstract class ChangeListener extends KeyAdapter implements ItemListener
+ private class ChangeListener extends KeyAdapter implements ItemListener
{
- /** Method to be implemented */
- public abstract void optionsChanged();
-
/** Item changed in ItemListener */
public void itemStateChanged(ItemEvent arg0) {
- optionsChanged();
+ enableOkButton();
}
/** Key released in KeyListener */
public void keyReleased(KeyEvent arg0) {
- optionsChanged();
+ enableOkButton();
}
}
/**
* Constructor
*/
- public DistanceTimeLimitFunction(App inApp) {
+ public DistanceTimeLimitFunction(App inApp, boolean inShowHalves)
+ {
super(inApp);
+ _showHalves = inShowHalves;
}
/**
@@ -112,28 +115,31 @@ public abstract class DistanceTimeLimitFunction extends GenericFunction
JPanel dialogPanel = new JPanel();
dialogPanel.setLayout(new BorderLayout(5, 5));
- // Make radio buttons for three different options
+ // Make radio buttons for the options
_distLimitRadio = new JRadioButton(I18nManager.getText("dialog.correlate.options.distancelimit") + ": ");
_timeLimitRadio = new JRadioButton(I18nManager.getText("dialog.correlate.options.timelimit") + ": ");
+ if (_showHalves) {
+ _halvesRadio = new JRadioButton(I18nManager.getText("dialog.markers.halves"));
+ }
ButtonGroup radioGroup = new ButtonGroup();
radioGroup.add(_distLimitRadio);
radioGroup.add(_timeLimitRadio);
+ if (_showHalves) {
+ radioGroup.add(_halvesRadio);
+ }
// central panel for limits
JPanel limitsPanel = new JPanel();
- limitsPanel.setLayout(new BoxLayout(limitsPanel, BoxLayout.Y_AXIS));
- limitsPanel.add(Box.createVerticalStrut(8));
- ChangeListener optionsChangedListener = new ChangeListener() {
- public void optionsChanged() {
- enableOkButton();
- }
- };
+ limitsPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
+ GuiGridLayout grid = new GuiGridLayout(limitsPanel, new double[] {0.5, 1.0},
+ new boolean[] {false, false});
+ ChangeListener optionsChangedListener = new ChangeListener();
// distance limits
- JPanel distLimitPanel = new JPanel();
- distLimitPanel.setLayout(new FlowLayout());
+ grid.add(_distLimitRadio);
_distLimitRadio.setSelected(true);
_distLimitRadio.addItemListener(optionsChangedListener);
- distLimitPanel.add(_distLimitRadio);
+ JPanel distLimitPanel = new JPanel();
+ distLimitPanel.setLayout(new FlowLayout());
_distanceField = new WholeNumberField(3);
_distanceField.addKeyListener(optionsChangedListener);
distLimitPanel.add(_distanceField);
@@ -143,13 +149,13 @@ public abstract class DistanceTimeLimitFunction extends GenericFunction
_distUnitsDropdown.addItemListener(optionsChangedListener);
distLimitPanel.add(_distUnitsDropdown);
distLimitPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
- limitsPanel.add(distLimitPanel);
+ grid.add(distLimitPanel);
// time limit panel
+ grid.add(_timeLimitRadio);
+ _timeLimitRadio.addItemListener(optionsChangedListener);
JPanel timeLimitPanel = new JPanel();
timeLimitPanel.setLayout(new FlowLayout());
- _timeLimitRadio.addItemListener(optionsChangedListener);
- timeLimitPanel.add(_timeLimitRadio);
_limitHourField = new WholeNumberField(2);
_limitHourField.addKeyListener(optionsChangedListener);
timeLimitPanel.add(_limitHourField);
@@ -159,7 +165,14 @@ public abstract class DistanceTimeLimitFunction extends GenericFunction
timeLimitPanel.add(_limitMinField);
timeLimitPanel.add(new JLabel(I18nManager.getText("units.minutes")));
timeLimitPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
- limitsPanel.add(timeLimitPanel);
+ grid.add(timeLimitPanel);
+
+ // halves
+ if (_showHalves)
+ {
+ grid.add(_halvesRadio);
+ _halvesRadio.addItemListener(optionsChangedListener);
+ }
dialogPanel.add(limitsPanel, BorderLayout.NORTH);
@@ -203,6 +216,9 @@ public abstract class DistanceTimeLimitFunction extends GenericFunction
else if (_timeLimitRadio.isSelected()) {
enabled = _limitHourField.getValue() > 0 || _limitMinField.getValue() > 0;
}
+ else if (_halvesRadio != null && _halvesRadio.isSelected()) {
+ enabled = true;
+ }
_okButton.setEnabled(enabled);
// Also enable/disable the other fields
@@ -245,6 +261,21 @@ public abstract class DistanceTimeLimitFunction extends GenericFunction
return 0.0;
}
+ /**
+ * @return selected distance limit in km, or 0.0
+ */
+ protected double getDistanceLimitKilometres()
+ {
+ return Distance.convertRadiansToDistance(getDistanceLimitRadians(), UnitSetLibrary.UNITS_KILOMETRES);
+ }
+
+ /**
+ * @return true if "halves" option was selected
+ */
+ protected boolean isHalvesSelected() {
+ return _halvesRadio != null && _halvesRadio.isSelected();
+ }
+
/**
* The dialog has been completed and OK pressed, so do the corresponding function
*/
diff --git a/src/tim/prune/function/DuplicatePoint.java b/src/tim/prune/function/DuplicatePoint.java
index 341066a..7739092 100644
--- a/src/tim/prune/function/DuplicatePoint.java
+++ b/src/tim/prune/function/DuplicatePoint.java
@@ -30,7 +30,8 @@ public class DuplicatePoint extends GenericFunction
public void begin()
{
DataPoint point = _app.getTrackInfo().getCurrentPoint();
- if (point != null) {
+ if (point != null)
+ {
// Pass information back to App to complete function
_app.createPoint(point.clonePoint());
}
diff --git a/src/tim/prune/function/FullRangeDetails.java b/src/tim/prune/function/FullRangeDetails.java
deleted file mode 100644
index 07ef39e..0000000
--- a/src/tim/prune/function/FullRangeDetails.java
+++ /dev/null
@@ -1,367 +0,0 @@
-package tim.prune.function;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.FlowLayout;
-import java.awt.GridLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.KeyAdapter;
-import java.awt.event.KeyEvent;
-
-import javax.swing.BorderFactory;
-import javax.swing.JButton;
-import javax.swing.JDialog;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-
-import tim.prune.App;
-import tim.prune.GenericFunction;
-import tim.prune.I18nManager;
-import tim.prune.config.Config;
-import tim.prune.data.RangeStats;
-import tim.prune.data.Selection;
-import tim.prune.data.Unit;
-import tim.prune.gui.DisplayUtils;
-import tim.prune.gui.profile.SpeedData;
-
-/**
- * Class to show the full range details in a separate popup
- */
-public class FullRangeDetails extends GenericFunction
-{
- /** Dialog */
- private JDialog _dialog = null;
- /** Label for number of points */
- private JLabel _numPointsLabel = null;
- /** Label for number of segments */
- private JLabel _numSegsLabel = null;
- /** Label for the maximum speed */
- private JLabel _maxSpeedLabel = null;
-
- /** Label for heading of "total" column */
- private JLabel _colTotalLabel = null;
- /** Label for heading of "segments" column */
- private JLabel _colSegmentsLabel = null;
- /** Labels for distances */
- private JLabel _totalDistanceLabel = null, _movingDistanceLabel = null;
- /** Labels for durations */
- private JLabel _totalDurationLabel = null, _movingDurationLabel = null;
- /** Labels for climbs */
- private JLabel _totalClimbLabel = null, _movingClimbLabel = null;
- /** Labels for descents */
- private JLabel _totalDescentLabel = null, _movingDescentLabel = null;
- /** Labels for pace */
- private JLabel _totalPaceLabel = null, _movingPaceLabel = null;
- /** Labels for gradient */
- private JLabel _totalGradientLabel = null, _movingGradientLabel = null;
- /** Labels for speed */
- private JLabel _totalSpeedLabel, _movingSpeedLabel = null;
- /** Labels for vertical speed */
- private JLabel _totalVertSpeedLabel, _movingVertSpeedLabel = null;
-
-
- /**
- * Constructor
- * @param inApp App object
- */
- public FullRangeDetails(App inApp)
- {
- super(inApp);
- }
-
- /** Get the name key */
- public String getNameKey() {
- return "function.fullrangedetails";
- }
-
- /**
- * Begin the function
- */
- public void begin()
- {
- if (_dialog == null)
- {
- _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
- _dialog.setLocationRelativeTo(_parentFrame);
- _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
- _dialog.getContentPane().add(makeDialogComponents());
- _dialog.pack();
- }
- updateDetails();
- _dialog.setVisible(true);
- }
-
- /**
- * Create dialog components
- * @return Panel containing all gui elements in dialog
- */
- private Component makeDialogComponents()
- {
- JPanel dialogPanel = new JPanel();
- dialogPanel.setLayout(new BorderLayout(5, 5));
- // Label at top
- JLabel topLabel = new JLabel(I18nManager.getText("dialog.fullrangedetails.intro") + ":");
- topLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
- dialogPanel.add(topLabel, BorderLayout.NORTH);
-
- // Details panel in middle
- JPanel midPanel = new JPanel();
- midPanel.setLayout(new GridLayout(0, 3, 6, 2));
- midPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
- // Number of points
- JLabel pointsLabel = new JLabel(I18nManager.getText("details.track.points") + ": ");
- pointsLabel.setHorizontalAlignment(JLabel.RIGHT);
- midPanel.add(pointsLabel);
- _numPointsLabel = new JLabel("100");
- midPanel.add(_numPointsLabel);
- midPanel.add(new JLabel(" "));
- // Number of segments
- JLabel segLabel = new JLabel(I18nManager.getText("details.range.numsegments") + ": ");
- segLabel.setHorizontalAlignment(JLabel.RIGHT);
- midPanel.add(segLabel);
- _numSegsLabel = new JLabel("100");
- midPanel.add(_numSegsLabel);
- midPanel.add(new JLabel(" "));
- // Maximum speed
- JLabel maxSpeedLabel = new JLabel(I18nManager.getText("details.range.maxspeed") + ": ");
- maxSpeedLabel.setHorizontalAlignment(JLabel.RIGHT);
- midPanel.add(maxSpeedLabel);
- _maxSpeedLabel = new JLabel("10 km/h");
- midPanel.add(_maxSpeedLabel);
- midPanel.add(new JLabel(" "));
-
- // blank row
- for (int i=0; i<3; i++) midPanel.add(new JLabel(" "));
-
- // Row for column headings
- midPanel.add(new JLabel(" "));
- _colTotalLabel = new JLabel(I18nManager.getText("dialog.fullrangedetails.coltotal"));
- midPanel.add(_colTotalLabel);
- _colSegmentsLabel = new JLabel(I18nManager.getText("dialog.fullrangedetails.colsegments"));
- midPanel.add(_colSegmentsLabel);
-
- // Distance
- JLabel distLabel = new JLabel(I18nManager.getText("fieldname.distance") + ": ");
- distLabel.setHorizontalAlignment(JLabel.RIGHT);
- midPanel.add(distLabel);
- _totalDistanceLabel = new JLabel("5 km");
- midPanel.add(_totalDistanceLabel);
- _movingDistanceLabel = new JLabel("5 km");
- midPanel.add(_movingDistanceLabel);
-
- // Duration
- JLabel durationLabel = new JLabel(I18nManager.getText("fieldname.duration") + ": ");
- durationLabel.setHorizontalAlignment(JLabel.RIGHT);
- midPanel.add(durationLabel);
- _totalDurationLabel = new JLabel("15 min");
- midPanel.add(_totalDurationLabel);
- _movingDurationLabel = new JLabel("15 min");
- midPanel.add(_movingDurationLabel);
-
- // Speed
- JLabel speedLabel = new JLabel(I18nManager.getText("details.range.avespeed") + ": ");
- speedLabel.setHorizontalAlignment(JLabel.RIGHT);
- midPanel.add(speedLabel);
- _totalSpeedLabel = new JLabel("5.5 km/h");
- midPanel.add(_totalSpeedLabel);
- _movingSpeedLabel = new JLabel("5.5 km/h");
- midPanel.add(_movingSpeedLabel);
-
- // Pace
- JLabel paceLabel = new JLabel(I18nManager.getText("details.range.pace") + ": ");
- paceLabel.setHorizontalAlignment(JLabel.RIGHT);
- midPanel.add(paceLabel);
- _totalPaceLabel = new JLabel("8 min/km");
- midPanel.add(_totalPaceLabel);
- _movingPaceLabel = new JLabel("8 min/km");
- midPanel.add(_movingPaceLabel);
-
- // Climb
- JLabel climbLabel = new JLabel(I18nManager.getText("details.range.climb") + ": ");
- climbLabel.setHorizontalAlignment(JLabel.RIGHT);
- midPanel.add(climbLabel);
- _totalClimbLabel = new JLabel("1000 m");
- midPanel.add(_totalClimbLabel);
- _movingClimbLabel = new JLabel("1000 m");
- midPanel.add(_movingClimbLabel);
- // Descent
- JLabel descentLabel = new JLabel(I18nManager.getText("details.range.descent") + ": ");
- descentLabel.setHorizontalAlignment(JLabel.RIGHT);
- midPanel.add(descentLabel);
- _totalDescentLabel = new JLabel("1000 m");
- midPanel.add(_totalDescentLabel);
- _movingDescentLabel = new JLabel("1000 m");
- midPanel.add(_movingDescentLabel);
-
- // Gradient
- JLabel gradientLabel = new JLabel(I18nManager.getText("details.range.gradient") + ": ");
- gradientLabel.setHorizontalAlignment(JLabel.RIGHT);
- midPanel.add(gradientLabel);
- _totalGradientLabel = new JLabel("10 %");
- midPanel.add(_totalGradientLabel);
- _movingGradientLabel = new JLabel("10 %");
- midPanel.add(_movingGradientLabel);
-
- // Vertical speed
- JLabel vSpeedLabel = new JLabel(I18nManager.getText("fieldname.verticalspeed") + ": ");
- vSpeedLabel.setHorizontalAlignment(JLabel.RIGHT);
- midPanel.add(vSpeedLabel);
- _totalVertSpeedLabel = new JLabel("1 m/s");
- midPanel.add(_totalVertSpeedLabel);
- _movingVertSpeedLabel = new JLabel("1 m/s");
- midPanel.add(_movingVertSpeedLabel);
-
- dialogPanel.add(midPanel, BorderLayout.CENTER);
- // button panel at bottom
- JPanel buttonPanel = new JPanel();
- buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
- JButton closeButton = new JButton(I18nManager.getText("button.close"));
- closeButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e)
- {
- _dialog.dispose();
- }
- });
- closeButton.addKeyListener(new KeyAdapter() {
- public void keyPressed(KeyEvent inE) {
- if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {_dialog.dispose();}
- super.keyPressed(inE);
- }
- });
- buttonPanel.add(closeButton);
- dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
- return dialogPanel;
- }
-
-
- /**
- * Update the labels with the current details
- */
- private void updateDetails()
- {
- Selection selection = _app.getTrackInfo().getSelection();
- // Do the calculations with a separate class
- RangeStats stats = new RangeStats(_app.getTrackInfo().getTrack(), selection.getStart(), selection.getEnd());
-
- // Number of points
- _numPointsLabel.setText("" + stats.getNumPoints());
- // Number of segments
- _numSegsLabel.setText("" + stats.getNumSegments());
- final boolean isMultiSegments = (stats.getNumSegments() > 1);
- // Set visibility of third column accordingly
- _movingDistanceLabel.setVisible(isMultiSegments);
- _movingDurationLabel.setVisible(isMultiSegments || stats.getTimestampsOutOfSequence());
- // FIXME: What to show if timestamps are out of sequence? Warning message?
- _movingClimbLabel.setVisible(isMultiSegments);
- _movingDescentLabel.setVisible(isMultiSegments);
- _movingSpeedLabel.setVisible(isMultiSegments);
- _movingPaceLabel.setVisible(isMultiSegments);
- _movingGradientLabel.setVisible(isMultiSegments);
- _movingVertSpeedLabel.setVisible(isMultiSegments);
-
- // Total and moving distance in current units
- final Unit distUnit = Config.getUnitSet().getDistanceUnit();
- final String distUnitsStr = I18nManager.getText(distUnit.getShortnameKey());
- _totalDistanceLabel.setText(DisplayUtils.roundedNumber(stats.getTotalDistance()) + " " + distUnitsStr);
- _movingDistanceLabel.setText(DisplayUtils.roundedNumber(stats.getMovingDistance()) + " " + distUnitsStr);
-
- // Duration
- _totalDurationLabel.setText(DisplayUtils.buildDurationString(stats.getTotalDurationInSeconds()));
- _movingDurationLabel.setText(DisplayUtils.buildDurationString(stats.getMovingDurationInSeconds()));
-
- // Climb and descent
- final Unit altUnit = Config.getUnitSet().getAltitudeUnit();
- final String altUnitsStr = " " + I18nManager.getText(altUnit.getShortnameKey());
- if (stats.getTotalAltitudeRange().hasRange()) {
- _totalClimbLabel.setText(stats.getTotalAltitudeRange().getClimb(altUnit) + altUnitsStr);
- _totalDescentLabel.setText(stats.getTotalAltitudeRange().getDescent(altUnit) + altUnitsStr);
- }
- else {
- _totalClimbLabel.setText("");
- _totalDescentLabel.setText("");
- }
- if (stats.getMovingAltitudeRange().hasRange()) {
- _movingClimbLabel.setText(stats.getMovingAltitudeRange().getClimb(altUnit) + altUnitsStr);
- _movingDescentLabel.setText(stats.getMovingAltitudeRange().getDescent(altUnit) + altUnitsStr);
- }
- else {
- _movingClimbLabel.setText("");
- _movingDescentLabel.setText("");
- }
-
- // Overall pace and speed
- final String speedUnitsStr = I18nManager.getText(Config.getUnitSet().getSpeedUnit().getShortnameKey());
- long numSecs = stats.getTotalDurationInSeconds();
- double dist = stats.getTotalDistance();
- if (numSecs > 0 && dist > 0)
- {
- _totalSpeedLabel.setText(DisplayUtils.roundedNumber(dist/numSecs*3600.0) + " " + speedUnitsStr);
- _totalPaceLabel.setText(DisplayUtils.buildDurationString((long) (numSecs/dist))
- + " / " + distUnitsStr);
- }
- else {
- _totalSpeedLabel.setText("");
- _totalPaceLabel.setText("");
- }
- // and same for within the segments
- numSecs = stats.getMovingDurationInSeconds();
- dist = stats.getMovingDistance();
- if (numSecs > 0 && dist > 0)
- {
- _movingSpeedLabel.setText(DisplayUtils.roundedNumber(dist/numSecs*3600.0) + " " + speedUnitsStr);
- _movingPaceLabel.setText(DisplayUtils.buildDurationString((long) (numSecs/dist))
- + " / " + distUnitsStr);
- }
- else {
- _movingSpeedLabel.setText("");
- _movingPaceLabel.setText("");
- }
-
- // Gradient
- if (stats.getTotalAltitudeRange().hasRange()) {
- _totalGradientLabel.setText(DisplayUtils.formatOneDp(stats.getTotalGradient()) + " %");
- }
- else {
- _totalGradientLabel.setText("");
- }
- if (stats.getMovingAltitudeRange().hasRange()) {
- _movingGradientLabel.setText(DisplayUtils.formatOneDp(stats.getMovingGradient()) + " %");
- }
- else {
- _movingGradientLabel.setText("");
- }
-
- // Maximum speed
- SpeedData speeds = new SpeedData(_app.getTrackInfo().getTrack());
- speeds.init(Config.getUnitSet());
- double maxSpeed = 0.0;
- for (int i=selection.getStart(); i<=selection.getEnd(); i++)
- {
- if (speeds.hasData(i) && (speeds.getData(i) > maxSpeed)) {
- maxSpeed = speeds.getData(i);
- }
- }
- if (maxSpeed > 0.0) {
- _maxSpeedLabel.setText(DisplayUtils.roundedNumber(maxSpeed) + " " + speedUnitsStr);
- }
- else {
- _maxSpeedLabel.setText("");
- }
-
- // vertical speed
- final String vertSpeedUnitsStr = I18nManager.getText(Config.getUnitSet().getVerticalSpeedUnit().getShortnameKey());
- if (stats.getMovingAltitudeRange().hasRange() && stats.getTotalDurationInSeconds() > 0)
- {
- // got an altitude and time - do totals
- _totalVertSpeedLabel.setText(DisplayUtils.roundedNumber(stats.getTotalVerticalSpeed()) + " " + vertSpeedUnitsStr);
- _movingVertSpeedLabel.setText(DisplayUtils.roundedNumber(stats.getMovingVerticalSpeed()) + " " + vertSpeedUnitsStr);
- }
- else
- {
- // no vertical speed available
- _totalVertSpeedLabel.setText("");
- _movingVertSpeedLabel.setText("");
- }
- }
-}
diff --git a/src/tim/prune/function/InterpolateFunction.java b/src/tim/prune/function/InterpolateFunction.java
index 221fdaf..ce0dad5 100644
--- a/src/tim/prune/function/InterpolateFunction.java
+++ b/src/tim/prune/function/InterpolateFunction.java
@@ -122,7 +122,8 @@ public class InterpolateFunction extends SingleNumericParameterFunction
// Replace track with new points array
if (track.replaceContents(newPoints))
{
- _app.completeFunction(undo, I18nManager.getText("confirm.interpolate"));
+ final String confirmMessage = I18nManager.getTextWithNumber("confirm.pointsadded", totalInserted);
+ _app.completeFunction(undo, confirmMessage);
// Alter selection
_app.getTrackInfo().getSelection().selectRange(startIndex, endIndex + totalInserted);
}
diff --git a/src/tim/prune/function/PasteCoordinateList.java b/src/tim/prune/function/PasteCoordinateList.java
new file mode 100644
index 0000000..9fc259e
--- /dev/null
+++ b/src/tim/prune/function/PasteCoordinateList.java
@@ -0,0 +1,147 @@
+package tim.prune.function;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+import tim.prune.App;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.load.TextFileLoader;
+
+/**
+ * Class to provide the function to paste a list of coordinates
+ * and create points for them as if they were loaded from a text file
+ */
+public class PasteCoordinateList extends GenericFunction
+{
+ private JDialog _dialog = null;
+ private JTextArea _coordArea = null;
+ private JButton _okButton = null;
+
+
+ /**
+ * Constructor
+ * @param inApp application object for callback
+ */
+ public PasteCoordinateList(App inApp)
+ {
+ super(inApp);
+ }
+
+ /** Get the name key */
+ public String getNameKey() {
+ return "function.pastecoordinatelist";
+ }
+
+ /**
+ * Begin the function
+ */
+ public void begin()
+ {
+ // Make dialog window
+ if (_dialog == null)
+ {
+ _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
+ _dialog.setLocationRelativeTo(_parentFrame);
+ _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+ _dialog.getContentPane().add(makeDialogComponents());
+ _dialog.pack();
+ }
+ // MAYBE: Paste clipboard into the edit area
+ _coordArea.setText("");
+ enableOK();
+ _dialog.setVisible(true);
+ }
+
+
+ /**
+ * Create dialog components
+ * @return Panel containing all gui elements in dialog
+ */
+ private Component makeDialogComponents()
+ {
+ JPanel dialogPanel = new JPanel();
+ dialogPanel.setLayout(new BorderLayout(0, 10));
+ dialogPanel.add(new JLabel(I18nManager.getText("dialog.pastecoordinatelist.desc")), BorderLayout.NORTH);
+ _coordArea = new JTextArea(8, 35);
+ _coordArea.setLineWrap(true);
+ _coordArea.setWrapStyleWord(true);
+ JScrollPane coordsPane = new JScrollPane(_coordArea);
+ // Listeners to enable/disable ok button
+ KeyAdapter keyListener = new KeyAdapter() {
+ /** Key released */
+ public void keyReleased(KeyEvent inE) {
+ enableOK();
+ if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {
+ _dialog.dispose();
+ }
+ }
+ };
+ MouseAdapter mouseListener = new MouseAdapter() {
+ public void mouseReleased(MouseEvent inE) {
+ enableOK();
+ }
+ };
+ _coordArea.addKeyListener(keyListener);
+ _coordArea.addMouseListener(mouseListener);
+ dialogPanel.add(coordsPane, BorderLayout.CENTER);
+ // button panel at bottom
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
+ _okButton = new JButton(I18nManager.getText("button.ok"));
+ ActionListener okListener = new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ if (_okButton.isEnabled()) {finish();}
+ }
+ };
+ _okButton.addActionListener(okListener);
+ _okButton.setEnabled(false);
+ buttonPanel.add(_okButton);
+ JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
+ cancelButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ _dialog.dispose();
+ }
+ });
+ buttonPanel.add(cancelButton);
+ dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
+ dialogPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
+ return dialogPanel;
+ }
+
+ /**
+ * Enable or disable the OK button based on the contents of the text field
+ */
+ private void enableOK()
+ {
+ String text = _coordArea.getText();
+ _okButton.setEnabled(text != null && text.length() > 6
+ && (text.indexOf(' ') >= 0 || text.indexOf(',') >= 0));
+ }
+
+ /**
+ * Finish the dialog when OK pressed
+ */
+ private void finish()
+ {
+ new TextFileLoader(_app, _parentFrame).loadText(_coordArea.getText());
+ _dialog.dispose();
+ }
+}
diff --git a/src/tim/prune/function/PasteCoordinates.java b/src/tim/prune/function/PasteCoordinates.java
index c9b2ad1..c60bb85 100644
--- a/src/tim/prune/function/PasteCoordinates.java
+++ b/src/tim/prune/function/PasteCoordinates.java
@@ -183,7 +183,8 @@ public class PasteCoordinates extends GenericFunction
else if (items.length == 3) {
point = parseValues(items[0].trim(), items[1].trim(), items[2].trim());
}
- else {
+ else
+ {
// Splitting with commas didn't work, so try spaces
items = _coordField.getText().split(" ");
if (items.length == 2) {
@@ -211,7 +212,8 @@ public class PasteCoordinates extends GenericFunction
I18nManager.getText("dialog.pastecoordinates.nothingfound"),
I18nManager.getText(getNameKey()), JOptionPane.ERROR_MESSAGE);
}
- else {
+ else
+ {
// See if name was entered
String name = _nameField.getText();
if (name != null && name.length() > 0) {
diff --git a/src/tim/prune/function/PlayAudioFunction.java b/src/tim/prune/function/PlayAudioFunction.java
index 2ac71e9..44b77d9 100644
--- a/src/tim/prune/function/PlayAudioFunction.java
+++ b/src/tim/prune/function/PlayAudioFunction.java
@@ -1,11 +1,11 @@
package tim.prune.function;
+import java.awt.Desktop;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
@@ -146,17 +146,10 @@ public class PlayAudioFunction extends GenericFunction implements Runnable
{
try
{
- Class> d = Class.forName("java.awt.Desktop");
- d.getDeclaredMethod("open", new Class[] {File.class}).invoke(
- d.getDeclaredMethod("getDesktop").invoke(null), new Object[] {inFile});
- //above code mimics: Desktop.getDesktop().open(audioFile);
+ Desktop.getDesktop().open(inFile);
played = true;
}
- catch (InvocationTargetException e) {
- System.err.println("ITE: " + e.getCause().getClass().getName() + " - " + e.getCause().getMessage());
- played = false;
- }
- catch (Exception ignore) {
+ catch (IOException ignore) {
System.err.println(ignore.getClass().getName() + " - " + ignore.getMessage());
played = false;
}
diff --git a/src/tim/prune/function/PlusCodeFunction.java b/src/tim/prune/function/PlusCodeFunction.java
new file mode 100644
index 0000000..b208b7f
--- /dev/null
+++ b/src/tim/prune/function/PlusCodeFunction.java
@@ -0,0 +1,209 @@
+package tim.prune.function;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingConstants;
+
+import tim.prune.App;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.data.Field;
+import tim.prune.function.olc.OlcArea;
+import tim.prune.function.olc.OlcDecoder;
+import tim.prune.gui.GuiGridLayout;
+
+/**
+ * Class to provide the function to parse
+ * OpenLocationCodes, or PlusCodes
+ */
+public class PlusCodeFunction extends GenericFunction
+{
+ private JDialog _dialog = null;
+ private JTextField _codeField = null;
+ private JButton _okButton = null;
+
+
+ /**
+ * Constructor
+ * @param inApp application object for callback
+ */
+ public PlusCodeFunction(App inApp)
+ {
+ super(inApp);
+ }
+
+ /** Get the name key */
+ public String getNameKey() {
+ return "function.enterpluscode";
+ }
+
+ /**
+ * Begin the function
+ */
+ public void begin()
+ {
+ // Make dialog window
+ if (_dialog == null)
+ {
+ _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
+ _dialog.setLocationRelativeTo(_parentFrame);
+ _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+ _dialog.getContentPane().add(makeDialogComponents());
+ _dialog.pack();
+ }
+ // MAYBE: Paste clipboard into the edit field
+ _codeField.setText("");
+ enableOK();
+ _dialog.setVisible(true);
+ }
+
+
+ /**
+ * Create dialog components
+ * @return Panel containing all gui elements in dialog
+ */
+ private Component makeDialogComponents()
+ {
+ JPanel dialogPanel = new JPanel();
+ dialogPanel.setLayout(new BorderLayout(0, 10));
+ dialogPanel.add(new JLabel(I18nManager.getText("dialog.pluscode.desc")), BorderLayout.NORTH);
+ JPanel mainPanel = new JPanel();
+ GuiGridLayout grid = new GuiGridLayout(mainPanel);
+ _codeField = new JTextField("", 12);
+ // Listeners to enable/disable ok button
+ KeyAdapter keyListener = new KeyAdapter() {
+ /** Key released */
+ public void keyReleased(KeyEvent inE) {
+ enableOK();
+ if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {
+ _dialog.dispose();
+ }
+ }
+ };
+ MouseAdapter mouseListener = new MouseAdapter() {
+ public void mouseReleased(MouseEvent inE) {
+ enableOK();
+ }
+ };
+ _codeField.addKeyListener(keyListener);
+ _codeField.addMouseListener(mouseListener);
+ JLabel codeLabel = new JLabel(I18nManager.getText("dialog.pluscode.code"));
+ codeLabel.setHorizontalAlignment(SwingConstants.RIGHT);
+ grid.add(codeLabel);
+ grid.add(_codeField);
+ dialogPanel.add(mainPanel, BorderLayout.CENTER);
+ // button panel at bottom
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
+ _okButton = new JButton(I18nManager.getText("button.ok"));
+ ActionListener okListener = new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ if (_okButton.isEnabled()) {finish();}
+ }
+ };
+ _okButton.addActionListener(okListener);
+ _okButton.setEnabled(false);
+ _codeField.addActionListener(okListener);
+ buttonPanel.add(_okButton);
+ JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
+ cancelButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ _dialog.dispose();
+ }
+ });
+ buttonPanel.add(cancelButton);
+ dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
+ dialogPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
+ return dialogPanel;
+ }
+
+ /**
+ * Enable or disable the OK button based on the contents of the text field
+ */
+ private void enableOK()
+ {
+ String text = _codeField.getText();
+ _okButton.setEnabled(text != null && text.length() > 7
+ && text.indexOf(' ') < 0 && text.indexOf(',') < 0);
+ }
+
+ /**
+ * Finish the dialog when OK pressed
+ */
+ private void finish()
+ {
+ OlcArea area = OlcDecoder.decode(_codeField.getText());
+
+ if (area == null)
+ {
+ JOptionPane.showMessageDialog(_parentFrame,
+ I18nManager.getText("dialog.pluscode.nothingfound"),
+ I18nManager.getText(getNameKey()), JOptionPane.ERROR_MESSAGE);
+ }
+ else if (loadTrack(area))
+ {
+ _dialog.dispose();
+ }
+ }
+
+ /**
+ * Load the generated points from the given area
+ * @param inArea rectangular area
+ * @return true on success
+ */
+ private boolean loadTrack(OlcArea inArea)
+ {
+ if (inArea == null)
+ {
+ return false;
+ }
+
+ final Field[] fields = {Field.LATITUDE, Field.LONGITUDE, Field.WAYPT_NAME};
+ _app.autoAppendNextFile();
+
+ if (inArea.minLat == inArea.maxLat && inArea.minLon == inArea.maxLon)
+ {
+ String[][] pointData = new String[1][];
+ pointData[0] = new String[3]; // lat, long, name
+ pointData[0][0] = "" + inArea.minLat;
+ pointData[0][1] = "" + inArea.minLon;
+ pointData[0][2] = _codeField.getText();
+ _app.informDataLoaded(fields, pointData, null, null);
+ }
+ else
+ {
+ String[][] pointData = new String[6][];
+ for (int i=0; i<5; i++)
+ {
+ pointData[i] = new String[3]; // lat, long, name
+ pointData[i][0] = "" + ((i%4==0 || i==3) ? inArea.minLat : inArea.maxLat);
+ pointData[i][1] = "" + ((i%4==0 || i==1) ? inArea.minLon : inArea.maxLon);
+ pointData[i][2] = null;
+ }
+ // Middle point with name
+ pointData[5] = new String[3]; // lat, long, name
+ pointData[5][0] = "" + ((inArea.minLat + inArea.maxLat) / 2.0);
+ pointData[5][1] = "" + ((inArea.minLon + inArea.maxLon) / 2.0);
+ pointData[5][2] = _codeField.getText();
+ _app.informDataLoaded(fields, pointData, null, null);
+ }
+ return true;
+ }
+}
diff --git a/src/tim/prune/function/ProjectPoint.java b/src/tim/prune/function/ProjectPoint.java
new file mode 100644
index 0000000..10c0675
--- /dev/null
+++ b/src/tim/prune/function/ProjectPoint.java
@@ -0,0 +1,225 @@
+package tim.prune.function;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingConstants;
+
+import tim.prune.App;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.config.Config;
+import tim.prune.data.Coordinate;
+import tim.prune.data.DataPoint;
+import tim.prune.data.Distance;
+import tim.prune.data.Field;
+import tim.prune.data.Latitude;
+import tim.prune.data.Longitude;
+import tim.prune.data.Unit;
+import tim.prune.data.UnitSetLibrary;
+import tim.prune.gui.DecimalNumberField;
+import tim.prune.gui.GuiGridLayout;
+import tim.prune.gui.WholeNumberField;
+
+
+/**
+ * Class to provide the function to project the current point
+ * with a given bearing and distance
+ */
+public class ProjectPoint extends GenericFunction
+{
+ private JDialog _dialog = null;
+ private WholeNumberField _bearingField = null;
+ private JLabel _distanceDescLabel = null;
+ private DecimalNumberField _distanceField = null;
+ private boolean _distanceIsMetric = true;
+ private JTextField _nameField = null;
+ private JButton _okButton = null;
+
+
+ /**
+ * Constructor
+ * @param inApp application object for callback
+ */
+ public ProjectPoint(App inApp)
+ {
+ super(inApp);
+ }
+
+ /** Get the name key */
+ public String getNameKey() {
+ return "function.projectpoint";
+ }
+
+ /**
+ * Begin the function
+ */
+ public void begin()
+ {
+ // Make dialog window
+ if (_dialog == null)
+ {
+ _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
+ _dialog.setLocationRelativeTo(_parentFrame);
+ _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+ _dialog.getContentPane().add(makeDialogComponents());
+ _dialog.pack();
+ }
+
+ // Clear fields
+ _bearingField.setText("");
+ _distanceField.setText("");
+ _nameField.setText("");
+ // Set the units of the distance label
+ setLabelText();
+ enableOK();
+ _dialog.setVisible(true);
+ }
+
+
+ /**
+ * Create dialog components
+ * @return Panel containing all gui elements in dialog
+ */
+ private Component makeDialogComponents()
+ {
+ JPanel dialogPanel = new JPanel();
+ dialogPanel.setLayout(new BorderLayout(0, 10));
+ dialogPanel.add(new JLabel(I18nManager.getText("dialog.projectpoint.desc")), BorderLayout.NORTH);
+ JPanel mainPanel = new JPanel();
+ GuiGridLayout grid = new GuiGridLayout(mainPanel);
+ _bearingField = new WholeNumberField(3);
+ _distanceField = new DecimalNumberField(false);
+ // Listeners to enable/disable ok button
+ KeyAdapter keyListener = new KeyAdapter() {
+ /** Key released */
+ public void keyReleased(KeyEvent inE) {
+ enableOK();
+ if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {
+ _dialog.dispose();
+ }
+ }
+ };
+ MouseAdapter mouseListener = new MouseAdapter() {
+ public void mouseReleased(MouseEvent inE) {
+ enableOK();
+ }
+ };
+ _bearingField.addKeyListener(keyListener);
+ _bearingField.addMouseListener(mouseListener);
+ _distanceField.addKeyListener(keyListener);
+ _distanceField.addMouseListener(mouseListener);
+
+ JLabel bearingLabel = new JLabel(I18nManager.getText("dialog.projectpoint.bearing"));
+ bearingLabel.setHorizontalAlignment(SwingConstants.RIGHT);
+ grid.add(bearingLabel);
+ grid.add(_bearingField);
+
+ // Distance including units
+ _distanceDescLabel = new JLabel(I18nManager.getText("fieldname.distance") + " (ft)");
+ // Note, this label will be reset at each run
+ _distanceDescLabel.setHorizontalAlignment(SwingConstants.RIGHT);
+ grid.add(_distanceDescLabel);
+ grid.add(_distanceField);
+
+ // Waypoint name
+ JLabel nameLabel = new JLabel(I18nManager.getText("dialog.pointnameedit.name"));
+ nameLabel.setHorizontalAlignment(SwingConstants.RIGHT);
+ grid.add(nameLabel);
+ _nameField = new JTextField("", 12);
+ grid.add(_nameField);
+ dialogPanel.add(mainPanel, BorderLayout.CENTER);
+ // button panel at bottom
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
+ _okButton = new JButton(I18nManager.getText("button.ok"));
+ ActionListener okListener = new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ if (_okButton.isEnabled()) {finish();}
+ }
+ };
+ _okButton.addActionListener(okListener);
+ _okButton.setEnabled(false);
+
+ buttonPanel.add(_okButton);
+ JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
+ cancelButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ _dialog.dispose();
+ }
+ });
+ buttonPanel.add(cancelButton);
+ dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
+ dialogPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
+ return dialogPanel;
+ }
+
+ /**
+ * Set the label text according to the current units
+ */
+ private void setLabelText()
+ {
+ Unit distUnit = Config.getUnitSet().getDistanceUnit();
+ _distanceIsMetric = (distUnit == UnitSetLibrary.UNITS_METRES || distUnit == UnitSetLibrary.UNITS_KILOMETRES);
+ distUnit = _distanceIsMetric ? UnitSetLibrary.UNITS_METRES : UnitSetLibrary.UNITS_FEET;
+ final String unitKey = distUnit.getShortnameKey();
+ _distanceDescLabel.setText(I18nManager.getText("fieldname.distance") + " (" + I18nManager.getText(unitKey) + ")");
+ }
+
+ /**
+ * Enable or disable the OK button based on the contents of the input fields
+ */
+ private void enableOK()
+ {
+ final boolean bearingOk = !_bearingField.getText().isEmpty()
+ && _bearingField.getValue() < 360;
+ final boolean distanceOk = _distanceField.getValue() > 0.0;
+ _okButton.setEnabled(bearingOk && distanceOk);
+ }
+
+ /**
+ * Finish the dialog when OK pressed
+ */
+ private void finish()
+ {
+ DataPoint currPoint = _app.getTrackInfo().getCurrentPoint();
+ Unit distUnit = _distanceIsMetric ? UnitSetLibrary.UNITS_METRES : UnitSetLibrary.UNITS_FEET;
+ final double projectRads = Distance.convertDistanceToRadians(_distanceField.getValue(), distUnit);
+ final double origLatRads = Math.toRadians(currPoint.getLatitude().getDouble());
+ final double origLonRads = Math.toRadians(currPoint.getLongitude().getDouble());
+ System.out.println("Project from: " + origLatRads + ", " + origLonRads);
+ final double bearingRads = Math.toRadians(_bearingField.getValue());
+
+ double lat2 = Math.asin(Math.sin(origLatRads) * Math.cos(projectRads)
+ + Math.cos(origLatRads) * Math.sin(projectRads) * Math.cos(bearingRads));
+ double lon2 = origLonRads + Math.atan2(Math.sin(bearingRads) * Math.sin(projectRads) * Math.cos(origLatRads),
+ Math.cos(projectRads) - Math.sin(origLatRads) * Math.sin(lat2));
+
+ double finalLatDeg = Math.toDegrees(lat2);
+ double finalLonDeg = Math.toDegrees(lon2);
+ System.out.println("Result is: lat=" + finalLatDeg + ", lon=" + finalLonDeg);
+
+ // Create point and append to track
+ DataPoint point = new DataPoint(new Latitude(finalLatDeg, Coordinate.FORMAT_DEG),
+ new Longitude(finalLonDeg, Coordinate.FORMAT_DEG), null);
+ point.setFieldValue(Field.WAYPT_NAME, _nameField.getText(), false);
+ _app.createPoint(point);
+
+ _dialog.dispose();
+ }
+}
diff --git a/src/tim/prune/function/RearrangeWaypointsFunction.java b/src/tim/prune/function/RearrangeWaypointsFunction.java
index 17e9370..c62b130 100644
--- a/src/tim/prune/function/RearrangeWaypointsFunction.java
+++ b/src/tim/prune/function/RearrangeWaypointsFunction.java
@@ -119,7 +119,7 @@ public class RearrangeWaypointsFunction extends RearrangeFunction
// Exit if the data is already in the specified order
final boolean wpsToStart = (inRearrangeOption == Rearrange.TO_START);
final boolean doSort = (inSortOption != SortMode.DONT_SORT);
- if (numWaypoints == 0 || numNonWaypoints == 0
+ if (numWaypoints == 0
|| (wpsToStart && !wayAfterNon && nonAfterWay && !doSort)
|| (!wpsToStart && wayAfterNon && !nonAfterWay && !doSort)
|| inRearrangeOption == Rearrange.TO_NEAREST)
diff --git a/src/tim/prune/function/SearchOpenCachingDeFunction.java b/src/tim/prune/function/SearchOpenCachingDeFunction.java
index 20e2fc8..39df30a 100644
--- a/src/tim/prune/function/SearchOpenCachingDeFunction.java
+++ b/src/tim/prune/function/SearchOpenCachingDeFunction.java
@@ -84,7 +84,7 @@ public class SearchOpenCachingDeFunction extends GenericDownloaderFunction
private void submitSearch(double inLat, double inLon)
{
// The only parameters are lat and long from the current point
- String urlString = "http://opencaching.de/search.php?searchto=searchbydistance&showresult=1"
+ String urlString = "https://opencaching.de/search.php?searchto=searchbydistance&showresult=1"
+ "&output=XML&sort=bydistance&lat=" + inLat
+ "&lon=" + inLon + "&distance=" + MAX_DISTANCE + "&unit=km";
// Parse the returned XML with a special handler
diff --git a/src/tim/prune/function/ShowFullDetails.java b/src/tim/prune/function/ShowFullDetails.java
new file mode 100644
index 0000000..8f8289e
--- /dev/null
+++ b/src/tim/prune/function/ShowFullDetails.java
@@ -0,0 +1,417 @@
+package tim.prune.function;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.util.TimeZone;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTextArea;
+
+import tim.prune.App;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.config.Config;
+import tim.prune.config.TimezoneHelper;
+import tim.prune.data.AltitudeRange;
+import tim.prune.data.AudioClip;
+import tim.prune.data.Coordinate;
+import tim.prune.data.DataPoint;
+import tim.prune.data.Field;
+import tim.prune.data.Photo;
+import tim.prune.data.RangeStatsWithGradients;
+import tim.prune.data.Selection;
+import tim.prune.data.SpeedCalculator;
+import tim.prune.data.SpeedValue;
+import tim.prune.data.Track;
+import tim.prune.data.Unit;
+import tim.prune.data.UnitSet;
+import tim.prune.gui.CoordDisplay;
+import tim.prune.gui.DisplayUtils;
+
+
+/**
+ * Class to show the full point/range details in a separate popup
+ */
+public class ShowFullDetails extends GenericFunction
+{
+ private JDialog _dialog = null;
+ private JTabbedPane _tabs = null;
+ private JButton _okButton = null;
+
+ private JTextArea _pointTextArea = null;
+ private JTextArea _rangeTextArea = null;
+
+
+ /**
+ * Constructor
+ * @param inApp App object
+ */
+ public ShowFullDetails(App inApp)
+ {
+ super(inApp);
+ }
+
+ /** Get the name key */
+ public String getNameKey() {
+ return "function.viewfulldetails";
+ }
+
+ /**
+ * Begin the function
+ */
+ public void begin()
+ {
+ if (_dialog == null)
+ {
+ _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
+ _dialog.setLocationRelativeTo(_parentFrame);
+ _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+ _dialog.getContentPane().add(makeDialogComponents());
+ _dialog.pack();
+ }
+ updateDetails();
+ _dialog.setVisible(true);
+ _okButton.requestFocus();
+ }
+
+ /**
+ * Create dialog components
+ * @return Panel containing all gui elements in dialog
+ */
+ private Component makeDialogComponents()
+ {
+ JPanel mainPanel = new JPanel();
+ mainPanel.setLayout(new BorderLayout());
+
+ _tabs = new JTabbedPane();
+ mainPanel.add(_tabs, BorderLayout.CENTER);
+
+ JPanel pointPanel = new JPanel();
+ pointPanel.setLayout(new BorderLayout());
+ _pointTextArea = new JTextArea(I18nManager.getText("details.nopointselection"));
+ _pointTextArea.setEditable(false);
+ _pointTextArea.setLineWrap(true);
+ JScrollPane scrollPane = new JScrollPane(_pointTextArea);
+ scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ scrollPane.setPreferredSize(new Dimension(500, 230));
+ pointPanel.add(scrollPane, BorderLayout.CENTER);
+ _tabs.add(I18nManager.getText("details.pointdetails"), pointPanel);
+
+ JPanel rangePanel = new JPanel();
+ rangePanel.setLayout(new BorderLayout());
+ _rangeTextArea = new JTextArea(I18nManager.getText("details.norangeselection"));
+ _rangeTextArea.setEditable(false);
+ _rangeTextArea.setLineWrap(true);
+ JScrollPane scrollPane2 = new JScrollPane(_rangeTextArea);
+ scrollPane2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ scrollPane2.setPreferredSize(new Dimension(500, 230));
+ rangePanel.add(scrollPane2, BorderLayout.CENTER);
+ _tabs.add(I18nManager.getText("details.rangedetails"), rangePanel);
+
+ // OK button at the bottom
+ JPanel okPanel = new JPanel();
+ okPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
+ _okButton = new JButton(I18nManager.getText("button.ok"));
+ _okButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ _dialog.dispose();
+ }
+ });
+ _okButton.addKeyListener(new KeyListener() {
+ public void keyPressed(KeyEvent e)
+ {
+ if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {_dialog.dispose();}
+ }
+ public void keyTyped(KeyEvent e) {}
+ public void keyReleased(KeyEvent e) {}
+ });
+ okPanel.add(_okButton);
+ mainPanel.add(okPanel, BorderLayout.SOUTH);
+ return mainPanel;
+ }
+
+
+ /**
+ * Update the labels with the current details
+ */
+ private void updateDetails()
+ {
+ if (_app.getTrackInfo().getCurrentPoint() != null)
+ {
+ final String pointString = makePointDescription(_app.getTrackInfo().getTrack(),
+ _app.getTrackInfo().getSelection().getCurrentPointIndex());
+ _pointTextArea.setText(pointString);
+ // Select point tab
+ _tabs.setSelectedIndex(0);
+ }
+ else
+ {
+ _pointTextArea.setText(I18nManager.getText("details.nopointselection"));
+ // Select range tab
+ _tabs.setSelectedIndex(1);
+ }
+
+ Selection selection = _app.getTrackInfo().getSelection();
+ if (selection.hasRangeSelected())
+ {
+ RangeStatsWithGradients stats = new RangeStatsWithGradients(_app.getTrackInfo().getTrack(),
+ selection.getStart(), selection.getEnd());
+ SpeedValue maxSpeed = calculateMaxSpeed(_app.getTrackInfo().getTrack(),
+ selection.getStart(), selection.getEnd());
+ _rangeTextArea.setText(makeRangeDescription(stats, maxSpeed));
+ }
+ else
+ {
+ _rangeTextArea.setText(I18nManager.getText("details.norangeselection"));
+ }
+ }
+
+ /**
+ * Calculate the maximum horizontal speed value in the given selection
+ * @param inTrack track object
+ * @param inStartIndex start of selection
+ * @param inEndIndex end of selection
+ * @return max speed, if any
+ */
+ private static SpeedValue calculateMaxSpeed(Track inTrack, int inStartIndex, int inEndIndex)
+ {
+ SpeedValue maxSpeed = new SpeedValue();
+ SpeedValue currSpeed = new SpeedValue();
+ for (int i=inStartIndex; i<=inEndIndex; i++)
+ {
+ SpeedCalculator.calculateSpeed(inTrack, i, currSpeed);
+ if (currSpeed.isValid() && (!maxSpeed.isValid() || currSpeed.getValue() > maxSpeed.getValue()))
+ {
+ maxSpeed.setValue(currSpeed.getValue());
+ }
+ }
+ return maxSpeed;
+ }
+
+ /**
+ * @param inTrack current track
+ * @param inPointIndex current point index
+ * @return string describing point details
+ */
+ private static String makePointDescription(Track inTrack, int inPointIndex)
+ {
+ DataPoint point = inTrack.getPoint(inPointIndex);
+ if (point == null)
+ {
+ return "";
+ }
+
+ final int coordDisplayFormat = Coordinate.getCoordinateFormatForDisplay(
+ Config.getConfigInt(Config.KEY_COORD_DISPLAY_FORMAT));
+ StringBuffer result = new StringBuffer();
+ final String latStr = CoordDisplay.makeCoordinateLabel(point.getLatitude(), coordDisplayFormat);
+ final String lonStr = CoordDisplay.makeCoordinateLabel(point.getLongitude(), coordDisplayFormat);
+ addTextPair(result, "fieldname.latitude", latStr);
+ addTextPair(result, "fieldname.longitude", lonStr);
+ addTextPair(result, "fieldname.coordinates", latStr + ", " + lonStr);
+
+ if (point.hasAltitude())
+ {
+ final Unit altUnit = Config.getUnitSet().getAltitudeUnit();
+ addTextPair(result, "fieldname.altitude", "" + point.getAltitude().getValue(altUnit),
+ I18nManager.getText(altUnit.getShortnameKey()));
+ }
+ if (point.hasTimestamp())
+ {
+ TimeZone timezone = TimezoneHelper.getSelectedTimezone();
+ addTextPair(result, "fieldname.date", point.getTimestamp().getDateText(timezone));
+ addTextPair(result, "fieldname.timestamp", point.getTimestamp().getTimeText(timezone));
+ }
+
+ addTextPair(result, "fieldname.waypointname", point.getWaypointName());
+
+ addTextPair(result, "fieldname.description", point.getFieldValue(Field.DESCRIPTION));
+
+ addTextPair(result, "fieldname.waypointtype", point.getFieldValue(Field.WAYPT_TYPE));
+
+ // Speed can come from either timestamps and distances, or speed values in data
+ SpeedValue speedValue = new SpeedValue();
+ SpeedCalculator.calculateSpeed(inTrack, inPointIndex, speedValue);
+ UnitSet unitSet = Config.getUnitSet();
+ if (speedValue.isValid())
+ {
+ final String speedUnitsStr = I18nManager.getText(unitSet.getSpeedUnit().getShortnameKey());
+ String speed = DisplayUtils.roundedNumber(speedValue.getValue());
+ addTextPair(result, "fieldname.speed", speed, speedUnitsStr);
+ }
+
+ // Now do the vertical speed in the same way
+ SpeedCalculator.calculateVerticalSpeed(inTrack, inPointIndex, speedValue);
+ if (speedValue.isValid())
+ {
+ final String vSpeedUnitsStr = I18nManager.getText(unitSet.getVerticalSpeedUnit().getShortnameKey());
+ String speed = DisplayUtils.roundedNumber(speedValue.getValue());
+ addTextPair(result, "fieldname.verticalspeed", speed, vSpeedUnitsStr);
+ }
+
+ Photo currentPhoto = point.getPhoto();
+ if (currentPhoto != null)
+ {
+ addTextPair(result, "details.photofile", currentPhoto.getName());
+ addTextPair(result, "details.media.fullpath", currentPhoto.getFullPath());
+ }
+
+ AudioClip currentAudio = point.getAudio();
+ if (currentAudio != null)
+ {
+ addTextPair(result, "details.audio.file", currentAudio.getName());
+ addTextPair(result, "details.media.fullpath", currentAudio.getFullPath());
+ }
+
+ return result.toString();
+ }
+
+ /**
+ * Make the range description text
+ * @param inStats stats object
+ * @param inMaxSpeed maximum speed info
+ * @return string describing range
+ */
+ private static String makeRangeDescription(RangeStatsWithGradients inStats, SpeedValue inMaxSpeed)
+ {
+ StringBuffer result = new StringBuffer();
+ addTextPair(result, "details.track.points", "" + inStats.getNumPoints());
+ addTextPair(result, "details.range.numsegments", "" + inStats.getNumSegments());
+ final boolean hasMultipleSegments = (inStats.getNumSegments() > 1);
+
+ UnitSet unitSet = Config.getUnitSet();
+ final String speedUnitsStr = I18nManager.getText(unitSet.getSpeedUnit().getShortnameKey());
+ if (inMaxSpeed.isValid())
+ {
+ final String maxSpeedStr = DisplayUtils.roundedNumber(inMaxSpeed.getValue()) + " " + speedUnitsStr;
+ addTextPair(result, "details.range.maxspeed", maxSpeedStr);
+ }
+
+ addHeading(result, "dialog.fullrangedetails.colsegments");
+ final Unit distUnit = Config.getUnitSet().getDistanceUnit();
+ final String distUnitsStr = I18nManager.getText(distUnit.getShortnameKey());
+ final double movingDist = inStats.getMovingDistance();
+ addTextPair(result, "fieldname.distance", DisplayUtils.roundedNumber(movingDist),
+ distUnitsStr);
+ long numSecs = inStats.getMovingDurationInSeconds();
+ addTextPair(result, "fieldname.duration", DisplayUtils.buildDurationString(numSecs));
+
+ if (numSecs > 0 && movingDist > 0.0)
+ {
+ addTextPair(result, "details.range.avespeed", DisplayUtils.roundedNumber(movingDist/numSecs*3600.0),
+ speedUnitsStr);
+ addTextPair(result, "details.range.pace", DisplayUtils.buildDurationString((long) (numSecs/movingDist)),
+ "/ " + distUnitsStr);
+ }
+ final Unit altUnit = unitSet.getAltitudeUnit();
+ final String altUnitsStr = I18nManager.getText(altUnit.getShortnameKey());
+ if (inStats.getMovingAltitudeRange().hasRange())
+ {
+ AltitudeRange altRange = inStats.getMovingAltitudeRange();
+ addTextPair(result, "fieldname.altitude", "" + altRange.getMinimum(altUnit) + altUnitsStr + " "
+ + I18nManager.getText("details.altitude.to") + " "
+ + altRange.getMaximum(altUnit) + altUnitsStr);
+ addTextPair(result, "details.range.climb", "" + altRange.getClimb(altUnit), altUnitsStr);
+ addTextPair(result, "details.range.descent", "" + altRange.getDescent(altUnit), altUnitsStr);
+ addTextPair(result, "details.range.gradient", DisplayUtils.formatOneDp(inStats.getMovingGradient()), "%");
+ if (numSecs > 0)
+ {
+ final String vertSpeedUnitsStr = I18nManager.getText(unitSet.getVerticalSpeedUnit().getShortnameKey());
+ final String vertSpeedStr = DisplayUtils.roundedNumber(inStats.getMovingVerticalSpeed());
+ addTextPair(result, "fieldname.verticalspeed", vertSpeedStr, vertSpeedUnitsStr);
+ }
+ }
+
+ if (hasMultipleSegments)
+ {
+ addHeading(result, "dialog.fullrangedetails.coltotal");
+ final double totalDist = inStats.getTotalDistance();
+ addTextPair(result, "fieldname.distance", DisplayUtils.roundedNumber(totalDist), distUnitsStr);
+ long totalSecs = inStats.getTotalDurationInSeconds();
+ addTextPair(result, "fieldname.duration", DisplayUtils.buildDurationString(totalSecs));
+ if (totalSecs > 0 && totalDist > 0.0)
+ {
+ addTextPair(result, "details.range.avespeed", DisplayUtils.roundedNumber(totalDist/totalSecs*3600.0),
+ speedUnitsStr);
+ addTextPair(result, "details.range.pace", DisplayUtils.buildDurationString((long) (totalSecs/totalDist)),
+ "/ " + distUnitsStr);
+ }
+ if (inStats.getTotalAltitudeRange().hasRange())
+ {
+ AltitudeRange altRange = inStats.getTotalAltitudeRange();
+ addTextPair(result, "details.range.climb", "" + altRange.getClimb(altUnit), altUnitsStr);
+ addTextPair(result, "details.range.descent", "" + altRange.getDescent(altUnit), altUnitsStr);
+ addTextPair(result, "details.range.gradient", DisplayUtils.formatOneDp(inStats.getTotalGradient()), "%");
+ if (totalSecs > 0)
+ {
+ final String vertSpeedUnitsStr = I18nManager.getText(unitSet.getVerticalSpeedUnit().getShortnameKey());
+ final String vertSpeedStr = DisplayUtils.roundedNumber(inStats.getTotalVerticalSpeed());
+ addTextPair(result, "fieldname.verticalspeed", vertSpeedStr, vertSpeedUnitsStr);
+ }
+ }
+ }
+ return result.toString();
+ }
+
+ /**
+ * Add the label and value to the buffer
+ * @param inBuffer buffer to append to
+ * @param inLabelKey label key
+ * @param inValue value text
+ */
+ private static void addTextPair(StringBuffer inBuffer, String inLabelKey, String inValue)
+ {
+ addTextPair(inBuffer, inLabelKey, inValue, null);
+ }
+
+ /**
+ * Add the label and value to the buffer
+ * @param inBuffer buffer to append to
+ * @param inLabelKey label key
+ * @param inValue value text
+ * @param inUnits optional units string
+ */
+ private static void addTextPair(StringBuffer inBuffer, String inLabelKey, String inValue, String inUnits)
+ {
+ if (inValue != null && !inValue.equals(""))
+ {
+ inBuffer.append(I18nManager.getText(inLabelKey));
+ inBuffer.append(": ");
+ inBuffer.append(inValue);
+ if (inUnits != null && !inUnits.equals(""))
+ {
+ inBuffer.append(' ');
+ inBuffer.append(inUnits);
+ }
+ inBuffer.append("\n");
+ }
+ }
+
+ /**
+ * Add a heading to the buffer
+ * @param inBuffer buffer to append to
+ * @param inLabelKey key for heading
+ */
+ private static void addHeading(StringBuffer inBuffer, String inLabelKey)
+ {
+ final String heading = I18nManager.getText(inLabelKey);
+ inBuffer.append('\n').append(heading).append('\n');
+ for (int i=0; i d = Class.forName("javax.swing.JTable");
- d.getDeclaredMethod("setAutoCreateRowSorter", new Class[]{Boolean.TYPE}).invoke(distTable, Boolean.TRUE);
- }
- catch (Exception e) {}
+ distTable.setAutoCreateRowSorter(true);
scrollPane = new JScrollPane(distTable);
scrollPane.setPreferredSize(new Dimension(200, 250));
mainPanel.add(scrollPane);
diff --git a/src/tim/prune/function/distance/DistanceTableModel.java b/src/tim/prune/function/distance/DistanceTableModel.java
index 2c1d83d..b0340b9 100644
--- a/src/tim/prune/function/distance/DistanceTableModel.java
+++ b/src/tim/prune/function/distance/DistanceTableModel.java
@@ -37,7 +37,7 @@ public class DistanceTableModel extends GenericTableModel
{
if (inColumnIndex == 0) {return getPointName(inRowIndex);}
if (_distances == null) {return 0.0;}
- return new Double(_distances[inRowIndex]);
+ return Double.valueOf(_distances[inRowIndex]);
}
/**
diff --git a/src/tim/prune/function/estimate/EstimateTime.java b/src/tim/prune/function/estimate/EstimateTime.java
index ef69793..8caad11 100644
--- a/src/tim/prune/function/estimate/EstimateTime.java
+++ b/src/tim/prune/function/estimate/EstimateTime.java
@@ -23,7 +23,7 @@ import tim.prune.App;
import tim.prune.GenericFunction;
import tim.prune.I18nManager;
import tim.prune.config.Config;
-import tim.prune.data.RangeStats;
+import tim.prune.data.RangeStatsWithGradients;
import tim.prune.data.Selection;
import tim.prune.data.Unit;
import tim.prune.gui.DecimalNumberField;
@@ -54,7 +54,7 @@ public class EstimateTime extends GenericFunction
private JLabel _descentParamLabel = null;
private DecimalNumberField _gentleDescentField = null, _steepDescentField = null;
/** Range stats */
- private RangeStats _stats = null;
+ private RangeStatsWithGradients _stats = null;
/**
@@ -78,7 +78,8 @@ public class EstimateTime extends GenericFunction
{
// Get the stats on the selection before launching the dialog
Selection selection = _app.getTrackInfo().getSelection();
- _stats = new RangeStats(_app.getTrackInfo().getTrack(), selection.getStart(), selection.getEnd());
+ _stats = new RangeStatsWithGradients(_app.getTrackInfo().getTrack(),
+ selection.getStart(), selection.getEnd());
if (_stats.getMovingDistance() < 0.01)
{
@@ -297,7 +298,11 @@ public class EstimateTime extends GenericFunction
EstimationParameters estParams = new EstimationParameters(Config.getConfigString(Config.KEY_ESTIMATION_PARAMS));
String[] paramValues = estParams.getStrings();
- if (paramValues == null || paramValues.length != 5) {return;} // TODO: What to do in case of error?
+ if (paramValues == null || paramValues.length != 5)
+ {
+ // TODO: What to do in case of error?
+ return;
+ }
// Flat time is either for 5 km, 3 miles or 3 nm
_flatSpeedLabel.setText(I18nManager.getText("dialog.estimatetime.parameters.timefor") +
" " + EstimationParameters.getStandardDistance() + ": ");
diff --git a/src/tim/prune/function/estimate/EstimationParameters.java b/src/tim/prune/function/estimate/EstimationParameters.java
index 1b80467..afe5938 100644
--- a/src/tim/prune/function/estimate/EstimationParameters.java
+++ b/src/tim/prune/function/estimate/EstimationParameters.java
@@ -6,7 +6,7 @@ import java.util.Locale;
import tim.prune.I18nManager;
import tim.prune.config.Config;
-import tim.prune.data.RangeStats;
+import tim.prune.data.RangeStatsWithGradients;
import tim.prune.data.Unit;
import tim.prune.data.UnitSetLibrary;
@@ -254,9 +254,11 @@ public class EstimationParameters
* @param inStats stats of current range
* @return estimated number of minutes required
*/
- public double applyToStats(RangeStats inStats)
+ public double applyToStats(RangeStatsWithGradients inStats)
{
- if (inStats == null || !inStats.isValid()) return 0.0;
+ if (inStats == null) {
+ return 0.0;
+ }
final Unit METRES = UnitSetLibrary.UNITS_METRES;
final double STANDARD_CLIMB = 100.0; // metres
final double STANDARD_DISTANCE = 5.0; // kilometres
diff --git a/src/tim/prune/function/estimate/LearnParameters.java b/src/tim/prune/function/estimate/LearnParameters.java
index 74021dd..3efaa2f 100644
--- a/src/tim/prune/function/estimate/LearnParameters.java
+++ b/src/tim/prune/function/estimate/LearnParameters.java
@@ -26,7 +26,7 @@ import tim.prune.I18nManager;
import tim.prune.config.Config;
import tim.prune.data.DataPoint;
import tim.prune.data.Distance;
-import tim.prune.data.RangeStats;
+import tim.prune.data.RangeStatsWithGradients;
import tim.prune.data.Track;
import tim.prune.data.Unit;
import tim.prune.data.UnitSetLibrary;
@@ -100,7 +100,7 @@ public class LearnParameters extends GenericFunction implements Runnable
{
_progress.setMaximum(100);
// Go through the track and collect the range stats for each sample
- ArrayList statsList = new ArrayList(20);
+ ArrayList statsList = new ArrayList(20);
Track track = _app.getTrackInfo().getTrack();
final int numPoints = track.getNumPoints();
final int sampleSize = numPoints / 30;
@@ -108,15 +108,15 @@ public class LearnParameters extends GenericFunction implements Runnable
for (int i=0; i<30; i++)
{
int startIndex = i * sampleSize;
- RangeStats stats = getRangeStats(track, startIndex, startIndex + sampleSize, prevStartIndex);
+ RangeStatsWithGradients stats = getRangeStats(track, startIndex, startIndex + sampleSize, prevStartIndex);
if (stats != null && stats.getMovingDistanceKilometres() > 1.0
&& !stats.getTimestampsIncomplete() && !stats.getTimestampsOutOfSequence()
&& stats.getTotalDurationInSeconds() > 100
- && stats.getStartIndex() > prevStartIndex)
+ && startIndex > prevStartIndex)
{
// System.out.println("Got stats for " + stats.getStartIndex() + " to " + stats.getEndIndex());
statsList.add(stats);
- prevStartIndex = stats.getStartIndex();
+ prevStartIndex = startIndex;
}
_progress.setValue(i);
}
@@ -246,7 +246,8 @@ public class LearnParameters extends GenericFunction implements Runnable
* @param inPreviousStartIndex the previously used start index, or -1
* @return range stats object or null if required information missing from this bit of the track
*/
- private RangeStats getRangeStats(Track inTrack, int inStartIndex, int inEndIndex, int inPreviousStartIndex)
+ private RangeStatsWithGradients getRangeStats(Track inTrack, int inStartIndex,
+ int inEndIndex, int inPreviousStartIndex)
{
// Check parameters
if (inTrack == null || inStartIndex < 0 || inEndIndex <= inStartIndex || inStartIndex > inTrack.getNumPoints()) {
@@ -297,7 +298,7 @@ public class LearnParameters extends GenericFunction implements Runnable
// Check moving distance
if (movingRads >= minimumRads) {
- return new RangeStats(inTrack, start, endIndex);
+ return new RangeStatsWithGradients(inTrack, start, endIndex);
}
return null;
}
@@ -307,12 +308,12 @@ public class LearnParameters extends GenericFunction implements Runnable
* @param inStatsList list of (non-null) RangeStats objects
* @return A matrix with n rows and 5 columns
*/
- private static Matrix buildAMatrix(ArrayList inStatsList)
+ private static Matrix buildAMatrix(ArrayList inStatsList)
{
final Unit METRES = UnitSetLibrary.UNITS_METRES;
Matrix result = new Matrix(inStatsList.size(), 5);
int row = 0;
- for (RangeStats stats : inStatsList)
+ for (RangeStatsWithGradients stats : inStatsList)
{
result.setValue(row, 0, stats.getMovingDistanceKilometres());
result.setValue(row, 1, stats.getGentleAltitudeRange().getClimb(METRES));
@@ -329,11 +330,11 @@ public class LearnParameters extends GenericFunction implements Runnable
* @param inStatsList list of (non-null) RangeStats objects
* @return B matrix with single column of n rows
*/
- private static Matrix buildBMatrix(ArrayList inStatsList)
+ private static Matrix buildBMatrix(ArrayList inStatsList)
{
Matrix result = new Matrix(inStatsList.size(), 1);
int row = 0;
- for (RangeStats stats : inStatsList)
+ for (RangeStatsWithGradients stats : inStatsList)
{
result.setValue(row, 0, stats.getMovingDurationInSeconds() / 60.0); // convert seconds to minutes
row++;
@@ -372,12 +373,13 @@ public class LearnParameters extends GenericFunction implements Runnable
* @param inRowToIgnore row index to ignore, or -1 to use them all
* @return true if the samples look ok
*/
- private static boolean isRangeSetSufficient(ArrayList inRangeSet, int inRowToIgnore)
+ private static boolean isRangeSetSufficient(ArrayList inRangeSet, int inRowToIgnore)
{
- int numGC = 0, numSC = 0, numGD = 0, numSD = 0; // number of samples with gentle/steep climb/descent values > 0
+ // number of samples with gentle/steep climb/descent values > 0
+ int numGC = 0, numSC = 0, numGD = 0, numSD = 0;
final Unit METRES = UnitSetLibrary.UNITS_METRES;
int i = 0;
- for (RangeStats stats : inRangeSet)
+ for (RangeStatsWithGradients stats : inRangeSet)
{
if (i != inRowToIgnore)
{
@@ -396,7 +398,7 @@ public class LearnParameters extends GenericFunction implements Runnable
* @param inStatsList list of stats
* @return results in an object
*/
- private MatrixResults reduceSamples(ArrayList inStatsList)
+ private MatrixResults reduceSamples(ArrayList inStatsList)
{
int statsIndexToRemove = -1;
Matrix answer = null;
diff --git a/src/tim/prune/function/gpsies/FormPoster.java b/src/tim/prune/function/gpsies/FormPoster.java
deleted file mode 100644
index 5939e63..0000000
--- a/src/tim/prune/function/gpsies/FormPoster.java
+++ /dev/null
@@ -1,162 +0,0 @@
-package tim.prune.function.gpsies;
-
-import java.net.HttpURLConnection;
-import java.net.URLConnection;
-import java.net.URL;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Random;
-import java.io.OutputStream;
-
-/**
- * Taken from the Client HTTP Request class at com.myjavatools.web
- * and subsequently simplified and modified
- * @author Vlad Patryshev
- */
-public class FormPoster
-{
- private URLConnection _connection = null;
- private OutputStream _os = null;
- private static final Random RANDOM_GEN = new Random();
- private static final String BOUNDARY = "---------------------------"
- + randomString() + randomString() + randomString();
-
-
- /** Connect (if not already connected) */
- protected void connect() throws IOException {
- if (_os == null) _os = _connection.getOutputStream();
- }
-
- /** Write a single character */
- protected void write(char c) throws IOException {
- connect();
- _os.write(c);
- }
-
- /** Write a string */
- protected void write(String s) throws IOException {
- connect();
- _os.write(s.getBytes());
- }
-
- /** Write a -r-n newline sequence */
- protected void newline() throws IOException {
- write("\r\n");
- }
-
- /** Write a string followed by a newline */
- protected void writeln(String s) throws IOException {
- write(s);
- newline();
- }
-
- /** Generate a random alphanumeric string */
- private static String randomString() {
- return Long.toString(RANDOM_GEN.nextLong(), 36);
- }
-
- /** Write a boundary marker */
- private void boundary() throws IOException {
- write("--");
- write(BOUNDARY);
- }
-
-
- /**
- * Creates a new multipart POST HTTP request for a specified URL
- * @param url the URL to send request to
- * @throws IOException
- */
- public FormPoster(URL inUrl) throws IOException
- {
- _connection = inUrl.openConnection();
- _connection.setDoOutput(true);
- _connection.setRequestProperty("Content-Type",
- "multipart/form-data; boundary=" + BOUNDARY);
- }
-
- /** Write a header with the given name */
- private void writeName(String inName) throws IOException
- {
- newline();
- write("Content-Disposition: form-data; name=\"");
- write(inName);
- write('"');
- }
-
- /**
- * adds a string parameter to the request
- * @param name parameter name
- * @param value parameter value
- * @throws IOException
- */
- public void setParameter(String inName, String inValue) throws IOException
- {
- boundary();
- writeName(inName);
- newline(); newline();
- writeln(inValue);
- }
-
- /** Pipe the contents of the input stream to the output stream */
- private static void pipe(InputStream in, OutputStream out) throws IOException
- {
- byte[] buf = new byte[500000];
- int nread;
- synchronized (in) {
- while((nread = in.read(buf, 0, buf.length)) >= 0) {
- out.write(buf, 0, nread);
- }
- }
- out.flush();
- buf = null;
- }
-
- /**
- * adds a file parameter to the request
- * @param inName parameter name
- * @param inFilename the name of the file
- * @param inStream input stream to read the contents of the file from
- * @throws IOException
- */
- public void setParameter(String inName, String inFilename, InputStream inStream) throws IOException
- {
- boundary();
- writeName(inName);
- write("; filename=\"");
- write(inFilename);
- write('"');
- newline();
- write("Content-Type: ");
- String type = URLConnection.guessContentTypeFromName(inFilename);
- if (type == null) {type = "application/octet-stream";}
- writeln(type);
- newline();
- pipe(inStream, _os);
- newline();
- }
-
- /**
- * posts the requests to the server
- * @return input stream with the server response
- * @throws IOException
- */
- public InputStream post() throws IOException
- {
- boundary();
- writeln("--");
- _os.close();
- return _connection.getInputStream();
- }
-
- /**
- * @return the HTTP response code, 200 for success or -1 if not available
- */
- public int getResponseCode() throws IOException
- {
- if (_connection != null && _connection instanceof HttpURLConnection) {
- return ((HttpURLConnection) _connection).getResponseCode();
- }
- return -1;
- }
-}
diff --git a/src/tim/prune/function/gpsies/GetGpsiesFunction.java b/src/tim/prune/function/gpsies/GetGpsiesFunction.java
deleted file mode 100644
index cdcc9a9..0000000
--- a/src/tim/prune/function/gpsies/GetGpsiesFunction.java
+++ /dev/null
@@ -1,147 +0,0 @@
-package tim.prune.function.gpsies;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.ArrayList;
-
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import tim.prune.App;
-import tim.prune.GpsPrune;
-import tim.prune.I18nManager;
-import tim.prune.function.search.GenericDownloaderFunction;
-import tim.prune.function.search.SearchResult;
-import tim.prune.load.xml.XmlFileLoader;
-import tim.prune.load.xml.ZipFileLoader;
-
-/**
- * Function to load track information from Gpsies.com
- * according to the currently viewed area
- */
-public class GetGpsiesFunction extends GenericDownloaderFunction
-{
- /** Number of results per page */
- private static final int RESULTS_PER_PAGE = 20;
- /** Maximum number of results to get */
- private static final int MAX_RESULTS = 60;
- /** New API key (specific to this program) */
- private static final String GPSIES_API_KEY = "oumgvvbckiwpvsnb";
-
-
- /**
- * Constructor
- * @param inApp App object
- */
- public GetGpsiesFunction(App inApp) {
- super(inApp);
- }
-
- /**
- * @return name key
- */
- public String getNameKey() {
- return "function.getgpsies";
- }
-
- /**
- * @param inColNum index of column, 0 or 1
- * @return key for this column
- */
- protected String getColumnKey(int inColNum)
- {
- if (inColNum == 0) return "dialog.gpsies.column.name";
- return "dialog.gpsies.column.length";
- }
-
-
- /**
- * Run method to call gpsies.com in separate thread
- */
- public void run()
- {
- _statusLabel.setText(I18nManager.getText("confirm.running"));
- // Act on callback to update list and send another request if necessary
- double[] coords = _app.getViewport().getBounds();
- int currPage = 1;
-
- ArrayList trackList = null;
- URL url = null;
- String descMessage = "";
- InputStream inStream = null;
- // Loop for each page of the results
- do
- {
- // Example http://ws.gpsies.com/api.do?BBOX=10,51,12,53&limit=20&resultPage=1&key=oumgvvbckiwpvsnb
- String urlString = "http://ws.gpsies.com/api.do?BBOX=" +
- coords[1] + "," + coords[0] + "," + coords[3] + "," + coords[2] +
- "&limit=" + RESULTS_PER_PAGE + "&resultPage=" + currPage +
- "&key=" + GPSIES_API_KEY;
- // Parse the returned XML with a special handler
- GpsiesXmlHandler xmlHandler = new GpsiesXmlHandler();
- try
- {
- url = new URL(urlString);
- SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
- URLConnection conn = url.openConnection();
- conn.setRequestProperty("User-Agent", "GpsPrune v" + GpsPrune.VERSION_NUMBER);
- inStream = conn.getInputStream();
- saxParser.parse(inStream, xmlHandler);
- }
- catch (Exception e) {
- descMessage = e.getClass().getName() + " - " + e.getMessage();
- }
- // Close stream and ignore errors
- try {
- inStream.close();
- } catch (Exception e) {}
- // Add track list to model
- trackList = xmlHandler.getTrackList();
- _trackListModel.addTracks(trackList);
-
- // Compare number of results with results per page and call again if necessary
- currPage++;
- }
- while (trackList != null && trackList.size() == RESULTS_PER_PAGE
- && _trackListModel.getRowCount() < MAX_RESULTS && !_cancelled);
- // Set status label according to error or "none found", leave blank if ok
- if (descMessage.equals("") && (trackList == null || trackList.size() == 0)) {
- descMessage = I18nManager.getText("dialog.gpsies.nonefound");
- }
- _statusLabel.setText(descMessage);
- }
-
- /**
- * Load the selected track(s)
- */
- protected void loadSelected()
- {
- // Find the row(s) selected in the table and get the corresponding track
- int numSelected = _trackTable.getSelectedRowCount();
- if (numSelected < 1) return;
- int[] rowNums = _trackTable.getSelectedRows();
- for (int i=0; i= 0 && rowNum < _trackListModel.getRowCount())
- {
- String url = _trackListModel.getTrack(rowNum).getDownloadLink();
- XmlFileLoader xmlLoader = new XmlFileLoader(_app);
- ZipFileLoader loader = new ZipFileLoader(_app, xmlLoader);
- if (i>0) _app.autoAppendNextFile();
- try
- {
- loader.openStream(new URL(url).openStream());
- }
- catch (IOException ioe) {
- System.err.println("IO Exception : " + ioe.getMessage());
- }
- }
- }
- // Close the dialog
- _cancelled = true;
- _dialog.dispose();
- }
-}
diff --git a/src/tim/prune/function/gpsies/GpsiesXmlHandler.java b/src/tim/prune/function/gpsies/GpsiesXmlHandler.java
deleted file mode 100644
index c549c59..0000000
--- a/src/tim/prune/function/gpsies/GpsiesXmlHandler.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package tim.prune.function.gpsies;
-
-import java.util.ArrayList;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-import tim.prune.function.search.SearchResult;
-
-/**
- * XML handler for dealing with XML returned from gpsies.com
- */
-public class GpsiesXmlHandler extends DefaultHandler
-{
- private String _value = null;
- private ArrayList _trackList = null;
- private SearchResult _track = null;
-
-
- /**
- * React to the start of an XML tag
- */
- public void startElement(String inUri, String inLocalName, String inTagName,
- Attributes inAttributes) throws SAXException
- {
- if (inTagName.equals("tracks")) {
- _trackList = new ArrayList();
- }
- else if (inTagName.equals("track")) {
- _track = new SearchResult();
- }
- _value = null;
- super.startElement(inUri, inLocalName, inTagName, inAttributes);
- }
-
- /**
- * React to the end of an XML tag
- */
- public void endElement(String inUri, String inLocalName, String inTagName)
- throws SAXException
- {
- if (inTagName.equals("track")) {
- _trackList.add(_track);
- }
- else if (inTagName.equals("title")) {
- _track.setTrackName(_value);
- }
- else if (inTagName.equals("description")) {
- _track.setDescription(_value);
- }
- else if (inTagName.equals("fileId")) {
- _track.setWebUrl("https://gpsies.com/map.do?fileId=" + _value);
- }
- else if (inTagName.equals("trackLengthM")) {
- try {
- _track.setLength(Double.parseDouble(_value));
- }
- catch (NumberFormatException nfe) {}
- }
- else if (inTagName.equals("downloadLink")) {
- _track.setDownloadLink(_value);
- }
- super.endElement(inUri, inLocalName, inTagName);
- }
-
- /**
- * React to characters received inside tags
- */
- public void characters(char[] inCh, int inStart, int inLength)
- throws SAXException
- {
- String value = new String(inCh, inStart, inLength);
- _value = (_value==null?value:_value+value);
- super.characters(inCh, inStart, inLength);
- }
-
- /**
- * @return the list of tracks
- */
- public ArrayList getTrackList()
- {
- return _trackList;
- }
-}
diff --git a/src/tim/prune/function/gpsies/UploadGpsiesFunction.java b/src/tim/prune/function/gpsies/UploadGpsiesFunction.java
deleted file mode 100644
index 3cef9db..0000000
--- a/src/tim/prune/function/gpsies/UploadGpsiesFunction.java
+++ /dev/null
@@ -1,332 +0,0 @@
-package tim.prune.function.gpsies;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.FlowLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.KeyAdapter;
-import java.awt.event.KeyEvent;
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import javax.swing.BorderFactory;
-import javax.swing.BoxLayout;
-import javax.swing.JButton;
-import javax.swing.JCheckBox;
-import javax.swing.JDialog;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JPasswordField;
-import javax.swing.JScrollPane;
-import javax.swing.JTextArea;
-import javax.swing.JTextField;
-import javax.swing.border.EtchedBorder;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-
-import tim.prune.App;
-import tim.prune.GenericFunction;
-import tim.prune.I18nManager;
-import tim.prune.function.browser.BrowserLauncher;
-import tim.prune.gui.GuiGridLayout;
-import tim.prune.save.GpxExporter;
-import tim.prune.save.SettingsForExport;
-
-/**
- * Function to upload track information up to Gpsies.com
- */
-public class UploadGpsiesFunction extends GenericFunction
-{
- /** Dialog object */
- private JDialog _dialog = null;
- /** Edit box for user name */
- private JTextField _usernameField = null;
- /** Edit box for password */
- private JPasswordField _passwordField = null;
- /** Name of track */
- private JTextField _nameField = null;
- /** Description */
- private JTextArea _descField = null;
- /** Private checkbox */
- private JCheckBox _privateCheckbox = null;
- /** Activity checkboxes */
- private JCheckBox[] _activityCheckboxes = null;
- /** Writer object for GPX export */
- private OutputStreamWriter _writer = null;
- /** upload button */
- private JButton _uploadButton = null;
-
- /** URL to post form to */
- private static final String GPSIES_URL = "http://www.gpsies.com/upload.do";
- /** Keys for describing activities */
- private static final String[] ACTIVITY_KEYS = {"trekking", "walking", "jogging",
- "biking", "motorbiking", "snowshoe", "sailing", "skating"};
-
- /**
- * Constructor
- * @param inApp App object
- */
- public UploadGpsiesFunction(App inApp) {
- super(inApp);
- }
-
- /**
- * @return name key
- */
- public String getNameKey() {
- return "function.uploadgpsies";
- }
-
- /**
- * Begin the function
- */
- public void begin()
- {
- // Initialise dialog, show empty list
- if (_dialog == null)
- {
- _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
- _dialog.setLocationRelativeTo(_parentFrame);
- _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
- _dialog.getContentPane().add(makeDialogComponents());
- _dialog.pack();
- }
- // Show dialog
- _dialog.setVisible(true);
- }
-
-
- /**
- * Create dialog components
- * @return Panel containing all gui elements in dialog
- */
- private Component makeDialogComponents()
- {
- JPanel dialogPanel = new JPanel();
- dialogPanel.setLayout(new BorderLayout());
-
- JPanel gridPanel = new JPanel();
- GuiGridLayout grid = new GuiGridLayout(gridPanel);
- grid.add(new JLabel(I18nManager.getText("dialog.gpsies.username")));
- _usernameField = new JTextField(15);
- grid.add(_usernameField);
- grid.add(new JLabel(I18nManager.getText("dialog.gpsies.password")));
- _passwordField = new JPasswordField(15);
- grid.add(_passwordField);
- // Track name and description
- grid.add(new JLabel(I18nManager.getText("dialog.gpsies.column.name")));
- _nameField = new JTextField(15);
- grid.add(_nameField);
- grid.add(new JLabel(I18nManager.getText("dialog.gpsies.description")));
- _descField = new JTextArea(5, 15);
- _descField.setLineWrap(true);
- _descField.setWrapStyleWord(true);
- grid.add(new JScrollPane(_descField));
- // Listener on all these text fields to enable/disable the ok button
- KeyAdapter keyListener = new KeyAdapter() {
- /** Key released */
- public void keyReleased(KeyEvent inE) {
- enableOK();
- if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {
- _dialog.dispose();
- }
- }
- };
- _usernameField.addKeyListener(keyListener);
- _passwordField.addKeyListener(keyListener);
- _nameField.addKeyListener(keyListener);
- // Listen for tabs on description field, to change focus not enter tabs
- _descField.addKeyListener(new KeyAdapter() {
- /** Key pressed */
- public void keyPressed(KeyEvent inE) {
- if (inE.getKeyCode() == KeyEvent.VK_TAB) {
- inE.consume();
- if (inE.isShiftDown()) {
- _nameField.requestFocusInWindow();
- }
- else {
- _privateCheckbox.requestFocusInWindow();
- }
- }
- }
- });
- // Listen for Ctrl-backspace on password field (delete contents)
- _passwordField.addKeyListener(new KeyAdapter() {
- /** Key released */
- public void keyReleased(KeyEvent inE) {
- if (inE.isControlDown() && (inE.getKeyCode() == KeyEvent.VK_BACK_SPACE
- || inE.getKeyCode() == KeyEvent.VK_DELETE)) {
- _passwordField.setText("");
- }
- }
- });
- // Checkbox for private / public
- grid.add(new JLabel(I18nManager.getText("dialog.gpsies.keepprivate")));
- _privateCheckbox = new JCheckBox();
- _privateCheckbox.setSelected(true);
- grid.add(_privateCheckbox);
-
- // panel for activity type checkboxes
- JPanel activityPanel = new JPanel();
- activityPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
- ChangeListener checkListener = new ChangeListener() {
- public void stateChanged(ChangeEvent arg0) {
- enableOK();
- }
- };
- // Why not a simple grid layout here?
- GuiGridLayout actGrid = new GuiGridLayout(activityPanel, new double[] {1.0, 1.0}, new boolean[] {false, false});
- final int numActivities = ACTIVITY_KEYS.length;
- _activityCheckboxes = new JCheckBox[numActivities];
- for (int i=0; i 0 && _nameField.getText().length() > 0);
- if (ok) {
- // also check password field
- char[] pass = _passwordField.getPassword();
- ok = pass.length > 0;
- for (int i=0; i 0 && line.endsWith("]")) {
- pageUrl = line.substring(bracketPos + 1, line.length()-1);
- }
- }
- if (pageUrl != null)
- {
- // OK received and managed to extract a Url from the return message.
- int userChoice = JOptionPane.showConfirmDialog(_app.getFrame(),
- I18nManager.getText("dialog.gpsies.confirmopenpage"),
- I18nManager.getText(getNameKey()), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
- if (userChoice == JOptionPane.OK_OPTION) {
- BrowserLauncher.launchBrowser(pageUrl);
- }
- }
- else {
- _app.showErrorMessageNoLookup(getNameKey(), I18nManager.getText("error.gpsies.uploadnotok")
- + ": " + line);
- }
- }
- catch (MalformedURLException e) {}
- catch (IOException ioe) {
- _app.showErrorMessageNoLookup(getNameKey(), I18nManager.getText("error.gpsies.uploadfailed") + ": "
- + ioe.getClass().getName() + " : " + ioe.getMessage());
- }
- finally {
- try {if (reader != null) reader.close();} catch (IOException e) {}
- }
- _dialog.dispose();
- }
-}
diff --git a/src/tim/prune/function/olc/CoordPair.java b/src/tim/prune/function/olc/CoordPair.java
new file mode 100644
index 0000000..778b46d
--- /dev/null
+++ b/src/tim/prune/function/olc/CoordPair.java
@@ -0,0 +1,75 @@
+package tim.prune.function.olc;
+
+class ParseException extends Exception {}
+
+/**
+ * Pair of coordinates
+ */
+class CoordPair
+{
+ /** Alphabet of allowed characters */
+ private static final String ALPHABET = "23456789CFGHJMPQRVWX";
+
+ public double lat = 0.0;
+ public double lon = 0.0;
+
+ /** Constructor */
+ public CoordPair(double inLat, double inLon)
+ {
+ lat = inLat;
+ lon = inLon;
+ }
+
+ /** Constant pair to represent padding */
+ public static CoordPair PADDING = new CoordPair(-1.0, -1.0);
+
+ /**
+ * Try to parse the given pair of characters into a CoordPair
+ * @param inFirst first character of pair
+ * @param inSecond second character of pair
+ * @return CoordPair from (0, 0) to (19/20, 19/20)
+ * @throws ParseException
+ */
+ public static CoordPair decode(char inFirst, char inSecond) throws ParseException
+ {
+ final boolean isFirstPadding = (inFirst == '0');
+ final boolean isSecondPadding = (inSecond == '0');
+ if (isFirstPadding && isSecondPadding) {return CoordPair.PADDING;}
+ if (isFirstPadding || isSecondPadding) {throw new ParseException();}
+ // Try to turn these characters into numbers
+ final double lat = decodeChar(inFirst);
+ final double lon = decodeChar(inSecond);
+ return new CoordPair(lat / 20.0, lon / 20.0);
+ }
+
+ /**
+ * Try to parse the given single character into a CoordPair
+ * @param inChar single character from level 11
+ * @return CoordPair from (0, 0) to (19/20, 19/20)
+ * @throws ParseException
+ */
+ public static CoordPair decode(char inChar) throws ParseException
+ {
+ // Try to turn this character into a number
+ final int charIndex = decodeChar(inChar);
+ final int lat = charIndex / 4;
+ final int lon = charIndex % 4;
+ return new CoordPair(lat / 5.0, lon / 4.0);
+ }
+
+ /**
+ * Get the index from the given character
+ * @param inChar character from OLC
+ * @return index from 0 to 19
+ * @throws ParseException if character not found
+ */
+ private static int decodeChar(char inChar) throws ParseException
+ {
+ final int index = ALPHABET.indexOf(inChar);
+ if (index < 0)
+ {
+ throw new ParseException();
+ }
+ return index;
+ }
+}
diff --git a/src/tim/prune/function/olc/OlcArea.java b/src/tim/prune/function/olc/OlcArea.java
new file mode 100644
index 0000000..bc7a3e8
--- /dev/null
+++ b/src/tim/prune/function/olc/OlcArea.java
@@ -0,0 +1,21 @@
+package tim.prune.function.olc;
+
+/**
+ * Class to represent the result of an OLC decoding
+ */
+public class OlcArea
+{
+ public double minLat = 0.0;
+ public double maxLat = 0.0;
+ public double minLon = 0.0;
+ public double maxLon = 0.0;
+
+ /** Constructor */
+ public OlcArea(double inMinLat, double inMinLon, double inMaxLat, double inMaxLon)
+ {
+ minLat = inMinLat;
+ minLon = inMinLon;
+ maxLat = inMaxLat;
+ maxLon = inMaxLon;
+ }
+}
diff --git a/src/tim/prune/function/olc/OlcDecoder.java b/src/tim/prune/function/olc/OlcDecoder.java
new file mode 100644
index 0000000..122f6fe
--- /dev/null
+++ b/src/tim/prune/function/olc/OlcDecoder.java
@@ -0,0 +1,101 @@
+package tim.prune.function.olc;
+
+
+/**
+ * Decoder of OLC (Open Location Code) strings
+ */
+public class OlcDecoder
+{
+ /**
+ * Decode the given String into an OlcArea object
+ * @param inCode code representing an OLC
+ * @return an OlcArea object, or null if parsing failed
+ */
+ public static OlcArea decode(String inCode)
+ {
+ if (inCode == null || inCode.length() < 8) {
+ return null;
+ }
+ String code = inCode.trim().toUpperCase();
+ if (code.length() < 8 || code.length() > 12) {
+ return null;
+ }
+ double lat = 0.0, lon = 0.0;
+ double resolution = 400.0;
+ int charPos = 0;
+ int numSteps = 0;
+ boolean amPadding = false;
+ try
+ {
+ while (charPos < inCode.length())
+ {
+ if (charPos == 0 || charPos == 2 || charPos == 4 || charPos == 6 || charPos == 9)
+ {
+ // take next two characters, make pair, position += 2
+ CoordPair pair = CoordPair.decode(code.charAt(charPos), code.charAt(charPos+1));
+ if (pair == CoordPair.PADDING) {
+ amPadding = true;
+ }
+ else if (amPadding)
+ {
+ return null;
+ }
+ else
+ {
+ // Add to current lat, lon
+ lat += (pair.lat * resolution);
+ lon += (pair.lon * resolution);
+ numSteps++;
+ resolution /= 20.0;
+ }
+ charPos += 2;
+ }
+ else if (charPos == 8)
+ {
+ if (code.charAt(charPos) != '+')
+ {
+ return null;
+ }
+ charPos += 1;
+ }
+ else if (charPos == 11)
+ {
+ // take next character, make pair
+ CoordPair pair = CoordPair.decode(code.charAt(charPos));
+ // Add to current lat, lon
+ lat += (pair.lat * resolution);
+ lon += (pair.lon * resolution);
+ charPos += 1;
+ numSteps++;
+ resolution /= 20.0;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ // Make OlcArea object and return it
+ if (numSteps < 1)
+ {
+ return null;
+ }
+ else if (numSteps < 6)
+ {
+ // make four points
+ lat -= 90.0;
+ lon -= 180.0;
+ return new OlcArea(lat, lon, lat+resolution, lon+resolution);
+ }
+ else
+ {
+ // make single point:
+ lat -= 90.0;
+ lon -= 180.0;
+ return new OlcArea(lat, lon, lat+resolution*2.5, lon+resolution*2.0);
+ }
+ }
+ catch (ParseException e) {}
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/src/tim/prune/function/search/GenericDownloaderFunction.java b/src/tim/prune/function/search/GenericDownloaderFunction.java
index fa8d4c3..079bf9d 100644
--- a/src/tim/prune/function/search/GenericDownloaderFunction.java
+++ b/src/tim/prune/function/search/GenericDownloaderFunction.java
@@ -25,11 +25,10 @@ import tim.prune.App;
import tim.prune.GenericFunction;
import tim.prune.I18nManager;
import tim.prune.function.browser.BrowserLauncher;
-import tim.prune.function.gpsies.TrackListModel;
/**
* Function to load track information from any source,
- * subclassed for special cases like gpsies, wikipedia or OSM
+ * subclassed for special cases like wikipedia or OSM
*/
public abstract class GenericDownloaderFunction extends GenericFunction implements Runnable
{
diff --git a/src/tim/prune/function/search/SearchResult.java b/src/tim/prune/function/search/SearchResult.java
index d757b01..52b902f 100644
--- a/src/tim/prune/function/search/SearchResult.java
+++ b/src/tim/prune/function/search/SearchResult.java
@@ -1,7 +1,7 @@
package tim.prune.function.search;
/**
- * Class to hold a search result from wikipedia / gpsies etc
+ * Class to hold a search result from wikipedia or other online service
*/
public class SearchResult implements Comparable
{
diff --git a/src/tim/prune/function/gpsies/TrackListModel.java b/src/tim/prune/function/search/TrackListModel.java
similarity index 95%
rename from src/tim/prune/function/gpsies/TrackListModel.java
rename to src/tim/prune/function/search/TrackListModel.java
index 8509213..d9163be 100644
--- a/src/tim/prune/function/gpsies/TrackListModel.java
+++ b/src/tim/prune/function/search/TrackListModel.java
@@ -1,4 +1,4 @@
-package tim.prune.function.gpsies;
+package tim.prune.function.search;
import java.text.NumberFormat;
import java.util.ArrayList;
@@ -9,10 +9,9 @@ import javax.swing.table.AbstractTableModel;
import tim.prune.I18nManager;
import tim.prune.config.Config;
import tim.prune.data.Unit;
-import tim.prune.function.search.SearchResult;
/**
- * Model for list of tracks from a search result (eg gpsies.com, geonames, overpass)
+ * Model for list of tracks from a search result (eg geonames, overpass)
*/
public class TrackListModel extends AbstractTableModel
{
diff --git a/src/tim/prune/function/search/wikimedia_galleries.txt b/src/tim/prune/function/search/wikimedia_galleries.txt
index 3647237..6b1ba55 100644
--- a/src/tim/prune/function/search/wikimedia_galleries.txt
+++ b/src/tim/prune/function/search/wikimedia_galleries.txt
@@ -1,113 +1,116 @@
+116/122/A-180 Z light pillbox 49 57 30.7 N 14 05 23.85 E
+A-4/51/A-200 Y light pillbox Back to 1938 state restored Pillbox Type 37 built in a unique modification into road embankment between Dolnà BezdÄkov and Bratronice, Kladno District, Czech Republic. 50 04 47.94 N 14 02 01.85 E
A Arnoia 42 14 54.95 N 8 08 04.88 W
A Barciela, Oroso 42 57 57.49 N 8 26 31.07 W
-A Cañiza A Cañiza is a municipality in Galicia, in the province of Pontevedra. 42 12 45.46 N 8 16 29.77 W
-A Coruña A Coruña is a Galician city, in north-western Spain. 43 21 58.95 N 8 24 28.71 W
-A Estrada 41 32 35.1 N 2 12 59.63 E
-A Guarda 41 54 09.12 N 8 52 27.15 W
-A Gudiña A Gudiña is a municipality in Galicia, in the province of Ourense. 42 03 40.13 N 7 08 34.19 W
-A Illa de Arousa A Illa de Arousa is a municipality in Galicia, in the province of Pontevedra. 42 33 08.36 N 8 52 06.13 W
-A Merca A Merca is a municipality in Galicia, in the province of Ourense. 42 13 22.53 N 7 54 15.55 W
-A Mezquita 42 00 42.5 N 7 02 43.17 W
-A Pobra de Trives 42 20 19.96 N 7 15 15.88 W
-A Pobra do Brollón 42 33 29.3 N 7 23 40.15 W
-A Pobra do Caramiñal A Pobra do Caramiñal is a municipality in the province of A Coruña, Galicia, Spain. 42 36 12.2 N 8 56 14.25 W
-A Rúa A Rúa is a municipality in Galicia, in the province of Ourense. 42 23 34.93 N 7 06 59.02 W
-A Veiga A Veiga is a municipality in Galicia, in the province of Ourense. 42 15 01.36 N 7 01 30.25 W
-A Walk on Main Street, Ferndale, California Ferndale is a small town in Humboldt County, California. Its Main Street is listed by the National Register of Historic Places as a historic district. 40 34 32.16 N 124 15 54 W
-A Walk up Main Street, Adamstown, Pennsylvania Adamstown is a small, historic town in Lancaster County, Pennsylvania. 40 14 36.96 N 76 03 16.2 W
Abbaye d'Acey 47 15 42 N 5 39 25 E
Abbaye de Bourgueil 47 16 46.2 N 0 10 18.12 E
Abbaye de Cluny The Abbey of Cluny (or Cluni, or Clugny) was founded on 2 September 909 and is located in the modern-day department of Saône-et-Loire in the region of Bourgogne, in east-central France, near Mâcon. 46 26 03 N 4 39 33 E
-Abbaye de Fontenay 47 38 27 N 4 23 23 E
Abbaye de Fontevraud Fontevraud Abbey is located near Saumur in Anjou, France 47 10 53 N 0 03 06 E
Abbaye de La Sauve-Majeure 44 46 07.24 N 0 18 42.41 W
-Abbaye de Montmajour 43 42 20 N 4 39 50 E
+Abbaye de Montmajour 43 42 20.16 N 4 39 50.04 E
Abbaye de Saint-Germain-des-Prés 48 51 14 N 2 20 04 E
Abbaye de Saint-Savin-sur-Gartempe 46 33 51 N 0 51 58 E
Abbaye de Sénanque 43 55 42 N 5 11 13 E
Abbaye de Valmagne 43 29 12.97 N 3 33 44.19 E
Abbaye du Relec 48 26 56 N 3 43 00 W
-Abbaye Saint Wandrille Monastery Saint Wandrille in France 49 31 46.42 N 0 45 59.58 E
Abbaye Saint-Corneille 49 25 02.6 N 2 49 28.57 E
-Abbaye Saint-Florentin, Bonneval 48 10 40.41 N 1 23 04.87 E
-Abeilhan 43 27 02 N 3 17 43 E
+Abbaye Saint Wandrille Monastery Saint Wandrille in France 49 31 46.42 N 0 45 59.58 E
+Abeilhan Abeilhan is a commune of the Hérault département in the Region of Occitanie - France. 43 27 02 N 3 17 43 E
Abri-caverne de l'ouvrage du Haut-Bois 47 35 24.07 N 6 48 34.23 E
Abtei Saint-André (Lavaudieu) 45 15 49 N 3 27 17 E
+A Cañiza A Cañiza is a municipality in Galicia, in the province of Pontevedra. 42 12 45.46 N 8 16 29.77 W
Aceldama Aceldama or Akeldama is the Aramaic name for a place in Jerusalem associated with Judas Iscariot, one of the followers of Jesus. 31 46 05.1 N 35 13 59.51 E
-Adissan 43 32 09.96 N 3 25 45.12 E
-Agadir 30 25 00 N 9 35 00 W
-Agel 43 20 18.96 N 2 51 13.68 E
+Adissan Adissan is a commune of the Hérault département in the Region of Occitanie - France. 43 32 09.96 N 3 25 45.12 E
+Aérodrome de Besançon-Thise 47 16 25.68 N 6 04 59.09 E
+A Estrada A Estrada is a municipality in Galicia, Spain in the province of Pontevedra. 41 32 35.1 N 2 12 59.63 E
+Agel Agel is a commune of the Hérault département - France. 43 20 18.96 N 2 51 13.68 E
Agrón, Ames 42 54 20.32 N 8 41 43.21 W
+A Guarda A Guarda is a municipality in Galicia, in the province of Pontevedra. 41 54 09.12 N 8 52 27.15 W
+A Gudiña A Gudiña is a municipality in Galicia, in the province of Ourense. 42 03 40.13 N 7 08 34.19 W
Aguiño, Ribeira 42 31 24.99 N 9 00 57.6 W
-Aichi prefecture 35 04 59 N 136 58 59 E
Aiguafreda Montseny 41 46 05.2 N 2 15 05.39 E
+A Illa de Arousa A Illa de Arousa is a municipality in Galicia, in the province of Pontevedra. 42 33 08.36 N 8 52 06.13 W
Alagna Valsesia Alagna Valsesia is a village in Piemonte in Italy. 45 51 05.16 N 7 56 16.98 E
Albrechtsburg The Albrechtsburg is the castle that dominates the city centre of MeiÃen, Germany. 51 09 59.65 N 13 28 17.83 E
Aletsch Aletsch region, UNESCO World Heritage Site since 2001, in Bernese Alps, Switzerland 46 27 50.9 N 8 04 20.89 E
Allariz Allariz is a municipality in Galicia, in the province of Ourense. 42 11 20.76 N 7 48 09.71 W
+Alte Kanzlei, Stuttgart 48 46 39.1 N 9 10 42.97 E
Alt Katholische Christuskirche Offenbach 50 06 01.91 N 8 45 52.28 E
+A Merca A Merca is a municipality in Galicia, in the province of Ourense. 42 13 22.53 N 7 54 15.55 W
Ames 42 51 35.95 N 8 38 58.21 W
+A Mezquita 42 00 42.5 N 7 02 43.17 W
Amoeiro 42 24 37.45 N 7 57 15.38 W
Ansemil, Silleda 42 44 21.56 N 8 16 12.47 W
Anta de CasaÃnhos 38 52 50.16 N 9 10 09.91 W
Antwerp Central Station 51 13 02 N 4 25 15.6 E
-Aquis Querquennis Aquis Querquennis was a Roman castra at Os Baños, Bande (Ourense, Galiza). 41 58 27.2 N 7 58 52.1 W
+A Pobra de Trives 42 20 19.96 N 7 15 15.88 W
+A Pobra do Brollón 42 33 29.3 N 7 23 40.15 W
+A Pobra do Caramiñal A Pobra do Caramiñal is a municipality in the province of A Coruña, Galicia, Spain. 42 36 12.2 N 8 56 14.25 W
+Aquis Querquennis 41 58 12 N 7 58 48 W
Arbo 42 06 39.45 N 8 18 57.47 W
-Arc de Triomf de Barcelona The Arc de Triomf (Triumphal Arch) is an archway structure in Barcelona, Spain. 41 23 27 N 2 10 50 E
+Arc de Triomf de Barcelona 41 23 28 N 2 10 50.02 E
Arc de Triomphe du Carrousel The Arc de Triomphe du Carrousel is a triumphal arch in Paris, located in the Place du Carrousel on the site of the former Tuileries Palace. 48 51 43 N 2 19 58 E
-Arch of Constantine 41 53 23 N 12 29 27 E
+Arch of Constantine 41 53 22.92 N 12 29 26.88 E
Arch of Septimius Severus (Rome) The Arch of Septimius Severus is situated in the Forum Romanum in Rome. 41 53 34 N 12 29 05 E
Arch of Titus The Arch of Titus is a triumphal arch with a single arched opening, located on the Summa Sacra Via to the west of the Roman Forum in Rome. 41 53 26 N 12 29 19 E
-Arnhem 51 59 00 N 5 55 00 E
-Arenys de Munt Arenys de Munt is a village in the comarca of Maresme, Catalonia. 41 36 46 N 2 32 25 E
+A Rúa A Rúa is a municipality in Galicia, in the province of Ourense. 42 23 34.93 N 7 06 59.02 W
+Askersund Askersund is a town in Sweden. 58 53 00 N 14 54 00 E
As Neves As Neves is a municipality in Galicia, in the province of Pontevedra. 42 05 10.49 N 8 24 53.43 W
As Pontes de GarcÃa RodrÃguez 43 26 47.63 N 7 51 09.54 W
-Askersund 58 53 00 N 14 54 00 E
Assumption Cathedral in Odessa Assumption Cathedral in Odessa, Ukraine 46 28 49.43 N 30 44 21.24 E
+ÃuÃerer Plauenscher Friedhof Cemetery âÃuÃerer Plauenscher Friedhofâ in Dresden-Plauen 51 01 11.89 N 13 42 26.03 E
Australian Synchrotron The Australian Synchrotron, a synchrotron facility in the suburb of Clayton, in Melbourne, Victoria, Australia. 37 54 51 S 145 08 33 E
+A Veiga A Veiga is a municipality in Galicia, in the province of Ourense. 42 15 01.36 N 7 01 30.25 W
Avión Avión is a municipality in Galicia, in the province of Ourense. 42 22 23.73 N 8 15 02.64 W
+A Walk on Main Street, Ferndale, California Ferndale is a small town in Humboldt County, California. 40 34 32.16 N 124 15 54 W
+A Walk up Main Street, Adamstown, Pennsylvania Adamstown is a small, historic town in Lancaster County, Pennsylvania. 40 14 36.96 N 76 03 16.2 W
Ayasofya The Church of the Holy Wisdom, commonly known as Hagia Sophia in English, is the former Greek Orthodox patriarchal cathedral, converted in 1453 to a mosque, now a museum, in Istanbul. 41 00 30.5 N 28 58 47.7 E
-Aérodrome de Besançon-Thise 47 16 25.68 N 6 04 59.09 E
-AÅgabat 37 57 00 N 58 23 00 E
+B-6/61/A-220 Z light pillbox B-6/61/A-220Z light pillbox, Beroun 49 57 25.96 N 14 05 35.6 E
+B-7/5/A-200 Z light pillbox 49 56 28.3 N 14 07 53.68 E
+B-7/6/A-200 Z light pillbox 49 56 19.34 N 14 07 56.34 E
Bahnhof Dresden-Neustadt Dresden-Neustadt railway station and the four inner city bridges 51 03 56 N 13 44 27 E
Baiona Baiona is a municipality in Galicia, Spain in the province of Pontevedra. 42 07 03.29 N 8 51 01.86 W
+Baker Glacier Chugach National Forest, Alaska 61 04 53 N 148 21 52 W
Baltar Baltar is a municipality in Galicia, in the province of Ourense. 41 57 04.75 N 7 42 56.7 W
Barbadás 42 17 56.03 N 7 53 13.14 W
-Basilique Notre-Dame de la Daurade 43 36 03 N 1 26 23 E
+Basilique Notre-Dame de la Daurade 36 02.88 N 1 26 22.92 E
Basilique Notre-Dame de Thierenbach 47 52 54.12 N 7 11 21.16 E
-Basilique Saint-Sauveur de Rennes 48 06 42 N 1 40 55 W
+Basilique Saint-Sauveur de Rennes 48 06 42 N 1 40 54 W
Beade Beade is a municipality in Galicia, in the province of Ourense. 42 20 06.72 N 8 08 45.05 W
+Bear Lake (Alaska) Kenai Peninsula, Alaska 60 12 03 N 149 21 11 W
Bergfriedhof (Stuttgart) The Bergfriedhof is a cemetery in the Stadtbezirk Stuttgart-Ost in Stuttgart. 48 47 19.16 N 9 12 23.35 E
Bergondo 43 19 15.36 N 8 13 54.04 W
Berlin Anhalter Bahnhof The Anhalter Bahnhof was a large main-line railway station in Berlin. Today it is just a stop on the Berlin S-Bahn. 52 30 11 N 13 22 55 E
Betanzos 43 16 44.24 N 8 12 55.95 W
Bibliothèque Sainte-Geneviève 48 50 49.5 N 2 20 45 E
-Bibracte 46 55 23 N 4 02 15 E
+Bibracte Bibracte est le nom de la cité gauloise, capitale des Eduens, qui était située au sommet du mont Beuvray (France) 46 55 23 N 4 02 15 E
Biella 45 34 05.07 N 8 03 02.61 E
Bienertparks in Dresden Als Bienertpark werden verschiedene Parkanlagen in Dresden bezeichnet, deren Entstehung auf die Familie Gottlieb Traugott Bienert zurückgeht. 51 01 48.29 N 13 42 54.9 E
-Bishkek 42 52 00 N 74 34 00 E
+Billings Glacier Chugach National Forest, Alaska 60 52 55 N 148 34 28 W
+Bishkek 42 52 00.12 N 74 34 00.12 E
Boccadasse Boccadasse è un antico borgo marinaro situato nel levante di Genova. 44 23 23.85 N 8 58 22.71 E
Boettcherstrasse 53 04 30 N 8 48 21 E
Boiro 42 38 13.16 N 8 52 12.31 W
Boke Boke is a small village in the German district Paderborn; it belongs to the city of Delbrück. 51 43 48 N 8 33 43.56 E
Bolongaropalast The Bolongaro Palace is a baroque building in Frankfurt-Höchst. 50 06 04 N 8 33 08 E
Borne des Trois Puissances Dreiländerstein 47 30 10.58 N 7 07 48.76 E
-Borovsk ÐÑа ÑÑÑаниÑа на ÑÑÑÑком: ÐоÑовÑк 55 12 27.19 N 36 29 05.05 E
+Borovsk Borovsk, a town established in 1358, stands between Moscow and Kaluga. 55 12 27.19 N 36 29 05.05 E
Bosco delle Querce The Regional Natural Park Bosco delle Querce (Oaks' Wood), built after the Seveso Disaster on the "A" zone. 45 38 55 N 9 09 10 E
Botanischer Garten Heidelberg 49 25 00 N 8 40 10 E
-Brancion 46 32 51 N 4 47 48.12 E
-Brudermühlbrücke The Brudermühlbrücke is a bridge in Munich across the Isar. 48 06 45.3 N 11 33 36.07 E
-BrudermühlstraÃe The BrudermühlstraÃe is a street in Munich, part of the Mittlerer Ring around the city centre. 48 06 44.2 N 11 33 01.37 E
+Brancion Brancion is a small fortified medieval city in Burgundy, Central France. 46 32 51 N 4 47 48.12 E
+Broad Pass George Parks Highway, Alaska 63 19 22 N 149 10 10 W
+Brudermühlbrücke The Brudermühlbrücke is a bridge in Munich across the Isar. 48 06 45.36 N 11 33 36 E
+BrudermühlstraÃe The BrudermühlstraÃe is a street in Munich, part of the Mittlerer Ring around the city centre. 48 06 43.92 N 11 32 58.56 E
Buenos Aires 34 36 13 S 58 22 54 W
Bueu Bueu is a municipality in Galicia, Spain in the province of Pontevedra. 42 19 24.69 N 8 47 23.1 W
-Buffalo Central Terminal The New York Central Terminal in Buffalo, USA, was a key railroad station from 1929 to 1979. 42 53 22.44 N 78 49 51.08 W
+Bürgerhospital (Stuttgart) 48 47 34.6 N 9 10 45.95 E
Burg Stahleck Stahleck Castle in Bacharach is a 12th century castle occupying a commanding view of the Rhine in the Loreley valley. Nowadays it's a youth hostel. 50 03 29.49 N 7 45 56.46 E
Burj Khalifa The Burj Khalifa ("Khalifa Tower") is a skyscraper in Dubai, United Arab Emirates. 25 11 49.7 N 55 16 26.8 E
-Bürgerhospital (Stuttgart) 48 47 34.6 N 9 10 45.95 E
Cabanas 43 24 50.49 N 8 10 04.15 W
-Cabo Fisterra Cape Finisterre is a rock-bound peninsula on the west coast of Galicia, in Fisterra (Spain). 42 52 50.96 N 9 16 18.27 W
+Cabo Fisterra 42 52 57 N 9 16 19.92 W
Cabrils 41 31 42 N 2 22 09 E
-Cadaqués Cadaqués is a touristic village in Costa Brava, Alt Empordà , Catalonia, Spain. 42 17 19.46 N 3 16 40.96 E
+Cáceres Cáceres is the capital of Cáceres Province, in Extremadura, Spain. 39 28 23 N 6 22 16 W
+Cadaqués 42 17 18.96 N 3 16 40.08 E
Calgary 51 02 42 N 114 03 26 W
Cambados 42 30 52.2 N 8 48 24.89 W
Cambre Cambre is a municipality in the province A Coruña, Galicia, Spain. 43 17 37.32 N 8 20 34.49 W
@@ -117,7 +120,8 @@ Candelabro de Paracas The Paracas Candelabra is a well-known prehistoric geoglyp
Cangas 42 15 47.1 N 8 47 09.5 W
Cape Arkona There are two bunkers at Cape Arkona. 54 40 47 N 13 25 57 E
Cape Horn Cape Horn is often said to be the southernmost point of South America. 55 58 47 S 67 16 18 W
-Capela de São Nicolau Capela de São Nicolau ou Passos da Via Sacra. Em Portugal, Porto. 41 08 27.14 N 8 36 55.49 W
+Capela de São Nicolau 32 41 08 27.15 N 8 36 55.57 W
+Cap Glacier Chugach National Forest, Alaska 60 56 57 N 147 54 57 W
Capriata d'Orba Capriata d'Orba è un comune in provincia di Alessandria, Piemonte, Italia. 44 43 43.93 N 8 41 25.29 E
Carballeda de Avia Carballeda de Avia is a municipality in Galicia, in the province of Ourense. 42 19 12.81 N 8 09 53.03 W
Cariño Cariño is a municipality in the province A Coruña, Galicia, Spain. 43 43 58 N 7 52 39.76 W
@@ -126,8 +130,7 @@ Cartelle Cartelle is a municipality in Galicia, in the province of Ourense. 42 1
Casa Buonarroti (Florence) Casa Buonarroti è un museo di Firenze 43 46 11.64 N 11 15 49 E
Casa de las CarnicerÃas, León The Casa de las CarnicerÃas (butcher's shops), a monument declared as a Bien de Interés Cultural in 1992, is located at San MartÃn square, León (Spain). 42 35 48.84 N 5 34 04.4 W
Casa del esquileo, Cabanillas del Monte The casa del esquileo (shearing shed) is a monument placed at Cabanillas del Monte, Torrecaballeros, Segovia (Spain). 40 58 36 N 4 01 54 W
-Casa Milà Casa Milà , also known as La Pedrera (the open quarry), is a modernist building in Barcelona, Catalonia, Spain 41 23 42.66 N 2 09 42.37 E
-Cassine 44 45 03 N 8 31 44 E
+Casa Milà 41 23 43.08 N 2 09 42.12 E
Castel del Monte Castel del Monte is a castle in Apulia, in Italy. 41 05 05.28 N 16 16 15.57 E
Castellazzo Bormida Castellazzo Bormida is a comune (municipality) in the Province of Alessandria in the Italian region Piedmont 44 50 46 N 8 34 42 E
Castello di Duino Il castello di Duino è un castello situato nel comune di Duino-Aurisina, in provincia di Trieste, Italia. 45 46 18.39 N 13 36 14.3 E
@@ -138,7 +141,7 @@ Castelo da Rocha Forte 42 51 42.29 N 8 34 29.38 W
Castelo de Castro Marim 37 13 07.43 N 7 26 29.69 W
Castelo de Maceda 42 16 13.92 N 7 39 32.36 W
Castelo de Monforte de Lemos 42 31 26.71 N 7 30 38.86 W
-Castelo de Monterreal 42 07 29.82 N 8 50 59.18 W
+Castelo de Monterreal 42 07 32.16 N 8 51 00 W
Castelo de Pambre 42 51 34.87 N 7 56 53.7 W
Castelo de Ribadavia 42 17 12.3 N 8 08 37.49 W
Castelo de San Felipe Castillo de San Felipe is a castle in the county of Ferrol, Galicia 43 27 53 N 8 16 54 W
@@ -146,27 +149,28 @@ Castelo de Santa Cruz 43 20 54.08 N 8 21 00.64 W
Castelo de Santo Antón 43 21 56.6 N 8 23 16.12 W
Castelo de Sobroso The Sobroso Castle is a castle located in Vilasobroso- Mondariz, Provincia of Pontevedra, Galicia (Spain). 42 12 17.31 N 8 27 20.51 W
Castelo de Soutomaior 42 19 46.77 N 8 34 05.54 W
-Castelo de Vilalba 43 17 52.79 N 7 40 56.44 W
+Castelo de Vilalba 43 17 52.8 N 7 40 56.42 W
Castelo de VilamarÃn 42 27 02.87 N 7 54 02.26 W
Castiñeiras, Ribeira 42 31 57.33 N 8 59 44.67 W
Castrelo de Miño Castrelo de Miño is a municipality in Galicia, in the province of Ourense. 42 17 49.63 N 8 04 02.63 W
Castrelo do Val Castrelo do Val is a municipality in Galicia, in the province of Ourense. 41 59 26.73 N 7 25 25.2 W
Castro Caldelas Castro Caldelas is a municipality in Galicia, in the province of Ourense. 42 22 32.62 N 7 24 54 W
-Castro de Baroña O Castro de Baroña está situado na parroquia de Baroña no concello de Porto do Son. 42 41 40.91 N 9 01 54.91 W
+Castro de Baroña 42 41 41.8 N 9 01 55.99 W
Castro de Rei 43 12 32.14 N 7 23 58.38 W
Catacaos 5 16 00 S 80 41 00 W
+Cataract Glacier Chugach National Forest, Alaska 61 01 39 N 148 25 23 W
Catedral de Santiago de Compostela 42 52 51.27 N 8 32 42.17 W
-Cathedral of Justo The Cathedral of Justo is being built by Justo Gallego in Mejorada del Campo (Community of Madrid, Spain). 40 23 38.88 N 3 29 17.99 W
Cathédrale Notre-Dame d'Amiens The cathedral of Our Lady of Amiens (fr: Cathédrale Notre-Dame d'Amiens), or just Amiens Cathedral, is the tallest complete cathedral in France. 49 53 42 N 2 18 08 E
-Cathédrale Notre-Dame de Chartres 48 26 50 N 1 29 16 E
+Cathédrale Notre-Dame de Chartres 48 26 52 N 1 29 16 E
Cathédrale Notre-Dame de Paris 48 51 10.8 N 2 20 59.28 E
Cathédrale Notre-Dame de Reims Cathedral "Notre-Dame de Reims", located in Reims, France 49 15 13.9 N 4 02 02.5 E
Cathédrale Notre-Dame de Strasbourg 48 34 55 N 7 45 03 E
Cathédrale Notre-Dame du Havre 49 29 13 N 0 06 30 E
Cathédrale Saint-André de Bordeaux 44 50 16 N 0 34 39 W
Cathédrale Saint-Bénigne de Dijon 47 19 17 N 5 02 04 E
-Cathédrale Saint-Julien du Mans Interior 48 00 33 N 0 11 56 E
Cathédrale Sainte-Cécile d'Albi 43 55 42.57 N 2 08 34.6 E
+Cathédrale Saint-Julien du Mans Interior 48 00 33 N 0 11 56 E
+Cathedral of Justo The Cathedral of Justo is being built by Justo Gallego in Mejorada del Campo (Community of Madrid, Spain). 40 23 38.88 N 3 29 17.99 W
Catoira Catoira is a municipality in Galicia, Spain in the province of Pontevedra. 42 39 54.98 N 8 43 57.93 W
Cedeira Cedeira is a municipality in the province A Coruña, Galicia, Spain. 43 39 39.53 N 8 03 10.41 W
Celanova Celanova is a municipality in Galicia, in the province of Ourense. 42 09 07.02 N 7 57 24.65 W
@@ -176,56 +180,45 @@ Cesantes, Redondela 42 18 33.05 N 8 36 44.72 W
Champ-de-Mars (Paris) 48 51 22 N 2 17 54 E
Chantada 42 36 27.15 N 7 46 09.2 W
Chapela, Redondela 42 15 53.95 N 8 40 22.71 W
-Chapelle de Languidou Chapel in Plovan / Bretagne 47 54 49.13 N 4 21 09.72 W
+Chapelle de Languidou 47 54 49.13 N 4 21 09.72 W
Chapelle Notre-Dame de Molsheim 48 32 26.16 N 7 29 40.13 E
-Chapelle Notre-Dame du Schaefertal (Soultzmatt) 47 57 06.84 N 7 12 59.4 E
-Chapelle Notre-Dame du Verger Chapelle Notre-Dame du Verger dans l'anse du Verger à Cancale (Ille-et-Vilaine) 48 41 37 N 1 52 51 W
Chapelle Notre-Dame-du-Chêne de Plobsheim 48 27 35.28 N 7 42 49.32 E
Chapelle Notre-Dame-du-Grasweg de Huttenheim 48 21 31.32 N 7 34 33.85 E
+Chapelle Notre-Dame du Schaefertal (Soultzmatt) 47 57 06.84 N 7 12 59.4 E
+Chapelle Notre-Dame du Verger Chapelle Notre-Dame du Verger dans l'anse du Verger à Cancale (Ille-et-Vilaine) 48 41 37 N 1 52 51 W
Chapelle royale Saint-Louis, Dreux 48 44 18 N 1 21 48 E
+Chapelle Sainte-Marguerite d'Epfig 48 21 15.84 N 7 28 40.12 E
+Chapelle Sainte-Marie de l'Assomption d'Obersteigen 48 38 32.28 N 7 18 22.32 E
Chapelle Saint-Gonéry 48 50 29.4 N 3 13 42.38 W
Chapelle Saint-Sébastien de Dambach-la-Ville 48 19 37.56 N 7 25 11.75 E
Chapelle Saint-Théodore de Vienne 45 31 28.56 N 4 52 24.13 E
Chapelle Saint-Ulrich d'Avolsheim 48 33 43.56 N 7 30 01.51 E
-Chapelle Sainte-Marguerite d'Epfig 48 21 15.84 N 7 28 40.12 E
-Chapelle Sainte-Marie de l'Assomption d'Obersteigen 48 38 32.28 N 7 18 22.32 E
Chapelles du Kochersberg 48 38 42 N 7 31 14.88 E
-Château d'Angers 47 28 11.67 N 0 33 33.61 W
-Château de Bugarach 42 52 36.16 N 2 21 05.15 E
-Château de Couiza 42 56 42.68 N 2 15 14.11 E
-Château de Condé 49 00 20 N 3 33 34 E
-Chiesa di Sant'Antonio in Caggiano Church of Saint Anthony in Caggiano. 40 34 04.13 N 15 29 39.47 E
-Chioggia Chioggia is a town in Veneto in Italy. 45 13 04.23 N 12 16 36.76 E
-Chroniques de Jérusalem Jerusalem Mount of Olives Santa Marta Passionists church. 31 46 15.83 N 35 15 08.48 E
-Church of Adelboden The gothic village church of Adelboden was built in the 15th century 46 29 34.1 N 7 33 32.4 E
-Church of Saints Apostles Peter and Paul in Vilnius 54 41 38.82 N 25 18 22.69 E
-Church of St. Johns in Vilnius Organ 54 40 57.5 N 25 17 19.22 E
-Church of São VÃtor (Braga) Igreja de São Victor em Braga 41 33 09.95 N 8 24 47.49 W
Château d'Anet 48 51 29 N 1 26 19 E
+Château d'Angers 47 28 11.67 N 0 33 33.61 W
Château d'Arlay 46 45 32.4 N 5 32 16.44 E
-Château d'Azay-le-Rideau The Château de Azay-le-Rideau is one of the most famous castles in t
-he French Loire Valley. 47 15 33 N 0 27 58 E
-Château d'Effiat The château d'Effiat in Puy de Dôme, Auvergne, France. 46 02 37 N 3 15 06 E
-Château d'If 43 16 47.5 N 5 19 30.5 E
-Château d'Ussé The Château d'Ussé is a château of the Loire Valley in Rigny-Ussé. 47 14 59 N 0 17 28 E
+Château d'Azay-le-Rideau The Château de Azay-le-Rideau is one of the most famous castles in the French Loire Valley. 47 15 33 N 0 27 58 E
Château de Blois The Château de Blois is one of the most renowned châteaux of the Loire Valley. 47 35 07.8 N 1 19 51.42 E
Château de Bressieux 45 19 21 N 5 16 45.01 E
Château de Brest 48 22 52.52 N 4 29 40.95 W
Château de Chambord 47 36 58.22 N 1 31 03.25 E
Château de Chamerolles 48 03 37.08 N 2 09 51.01 E
Château de Chantilly 49 11 38 N 2 29 09 E
+Château de Châteaudun 48 04 14 N 1 19 25 E
Château de Chenonceau 47 19 30 N 1 04 14.16 E
Château de Cheverny 47 30 01 N 1 27 29 E
Château de Chinon 47 10 05 N 0 14 10 E
-Château de Châteaudun 48 04 14 N 1 19 25 E
Château de Cléron 47 05 16 N 6 03 27 E
+Château de Condé 49 00 20 N 3 33 34 E
+Château de Crussol The Château de Crussol is a castle in the Ardèche départment of France. 44 56 18 N 4 51 09 E
Château de Domfront 48 35 39 N 0 39 09 W
+Château d'Effiat The château d'Effiat in Puy de Dôme, Auvergne, France. 46 02 37 N 3 15 06 E
Château de Fontainebleau The Château of Fontainebleau is the largest of the French royal châteaux. 48 24 08 N 2 42 02 E
Château de Frontenay 46 47 08.88 N 5 37 05.88 E
Château de Gevrey-Chambertin 47 13 46 N 4 57 56 E
-Château de l'Arthaudière The Château de l'Arthaudière is a castle in the Isère départment of the Rhône-Alpes région of France. 45 07 09 N 5 13 59 E
Château de Lagarde 43 03 02 N 1 56 08.5 E
Château de Langeais The Château de Langeais in the Loire Valley 47 19 29.28 N 0 24 21.96 E
+Château de l'Arthaudière The Château de l'Arthaudière is a castle in the Isère départment of the Rhône-Alpes région of France. 45 07 09 N 5 13 59 E
Château de Loches The Château de Loches in Loches is a château of the Loire Valley. The castle area, consisting of three buildings, among them one the oldest keeps in France, is one of the best preserved European architecture ensembles of the Middle Ages. 47 07 37 N 0 59 54 E
Château de Maintenon 48 35 08 N 1 34 41 E
Château de Malmaison Château de Malmaison was the place of residence of Joséphine de Beauharnais and Napoleon Bonaparte 48 52 15 N 2 10 01 E
@@ -233,34 +226,49 @@ Château de Montfaucon 47 14 46.32 N 6 04 42.24 E
Château de Murol 45 34 42 N 2 56 43 E
Château de Pagax 44 36 29.88 N 2 15 06.98 E
Château de Puivert 42 55 16.21 N 2 03 17.82 E
+Château des Adhémar 44 33 33.02 N 4 45 15.35 E
Château de Saint-Germain-en-Laye The Château de Saint-Germain-en-Laye is a former royal residence in Saint-Germain-en-Laye, located ca. 19 km to the west of Paris. Nowadays it serves as Musée des Antiquités Nationales. 48 53 53 N 2 05 47 E
Château de Saint-Izaire The Château de Saint-Izaire is a castle in the Saint-Izaire commune of the Aveyron département of France 43 58 31 N 2 43 10 E
+Château de Saissac The Château de Saissac is a Cathar castle in the Saissac commune, Aude département of France. 43 21 25 N 2 10 04.7 E
Château de Suscinio 47 30 46 N 2 43 46 W
Château de Suze-la-Rousse 44 17 14.64 N 4 50 11.62 E
Château de Thorens The Château de Thorens is a castle in the commune of Thorens-Glières in the Haute-Savoie département of France. 45 59 37 N 6 15 20 E
Château de Valençay The Château de Valençay is one of the châteaux of the Loire Valley in the french region Centre. 47 09 27 N 1 33 48 E
+Château de Varillettes The Château de Varillettes is a château in the Cantal. 45 01 26.76 N 3 08 53.16 E
Château de Vaux-le-Vicomte 48 33 53.46 N 2 42 50.4 E
Château de Wangenbourg The castle of Wangenbourg is a mediaeval castle in Wangenbourg-Engental, Bas-Rhin, France. 48 37 15 N 7 18 51 E
-Château des Adhémar 44 33 33.02 N 4 45 15.35 E
+Château d'Harcourt The Château d'Harcourt is a castle located in the commune of Harcourt in the Eure département of France 49 10 26 N 0 47 11 E
+Château d'If 43 16 47.5 N 5 19 30.5 E
Château du Haut-KÅnigsbourg The castle of Haut-KÅnigsbourg is a mediaeval castle located in Orschwiller, France. 48 14 58 N 7 20 39 E
-Château-Gaillard 49 14 17.26 N 1 24 09.91 E
+Château d'Ussé The Château d'Ussé is a château of the Loire Valley in Rigny-Ussé. 47 14 59 N 0 17 28 E
+Château-Gaillard Château-Gaillard is a castle in Les Andelys (Normandie, France). 49 14 17.26 N 1 24 09.91 E
+Chena Hot Springs, Alaska 65 03 10 N 146 03 19 W
+Chiesa di Sant'Antonio in Caggiano Church of Saint Anthony in Caggiano. 40 34 04.13 N 15 29 39.47 E
+Chioggia Chioggia is a town in Veneto in Italy. 45 13 04.23 N 12 16 36.76 E
+Chroniques de Jérusalem Jerusalem Mount of Olives Santa Marta Passionists church. 31 46 15.83 N 35 15 08.48 E
+Church of Adelboden The gothic village church of Adelboden was built in the 15th century 46 29 34.1 N 7 33 32.4 E
+Church of Saints Apostles Peter and Paul in Vilnius 54 41 38.82 N 25 18 22.69 E
+Church of São VÃtor (Braga) Igreja de São Victor em Braga 41 33 09.95 N 8 24 47.49 W
+Church of St. Johns in Vilnius 54 40 57.5 N 25 17 19.22 E
Cimetière du Montparnasse The Montparnasse cemetery (Fr: Cimetière du Montparnasse) is a famous cemetery in the Montparnasse quarter of Paris, France. 48 50 17 N 2 19 37 E
-Cimetière du Père-Lachaise Père Lachaise Cemetery (French: Cimetière du Père-Lachaise) (officially, cimetière de l'Est âeastern cemeteryâ) is the largest cemetery in the city of Paris at 118 acres (48 ha), though there are larger cemeteries in Paris suburbs. 48 51 43 N 2 23 39 E
+Cimetière du Père-Lachaise Père Lachaise Cemetery (French: Cimetière du Père-Lachaise) (officially, cimetière de l'Est âeastern cemeteryâ) is the largest cemetery in the city of Paris at 118 acres (48 ha), though there are larger cemeteries in Paris suburbs. 48 51 42.84 N 2 23 39.12 E
Cinque Terre The Cinque Terre are five coastal villages in the province of La Spezia, Italy. 44 06 37.74 N 9 44 31.35 E
-Ciudad Real 38 59 00 N 3 55 00 W
-Clermont-Ferrand 45 46 47 N 3 05 13 E
-Clos Vougeot 47 10 29.72 N 4 57 19.74 E
-Collingwood Monument A monument to Admiral Collingwood (1748-1810) was erected in Tynemouth, North East England, in 1845. 55 00 52.96 N 1 25 12.14 W
+City Palace (Udaipur) The City Palace in Udaipur was the royal palace of the Maharana of Mewar. The palace is located on the east bank of Lake Pichola in Udaipur, Rajasthan, India. 24 34 37.2 N 73 41 00.96 E
+Ciudad Real 38 58 59.88 N 3 55 00.12 W
+Clos Vougeot Clos Vougeot is a famous vineyard in Burgundy, France. 47 10 29.72 N 4 57 19.74 E
+Cochrane Bay Chugach National Forest, Alaska 60 44 18 N 148 20 06 W
Collégiale Notre-Dame de Melun 48 32 08 N 2 39 37 E
Collégiale Saint-Florent de Niederhaslach 48 32 35 N 7 20 29 E
Collégiale Saint-Martin de Colmar 48 04 38.5 N 7 21 29 E
-Collégiale Saint-Thiébaut de Thann 47 48 40 N 7 06 06 E
Collégiale Saints-Michel-et-Gangolphe de Lautenbach 47 56 27.96 N 7 09 32.94 E
+Collégiale Saint-Thiébaut de Thann 47 48 40 N 7 06 06 E
+Collingwood Monument A monument to Admiral Collingwood (1748-1810) was erected in Tynemouth, North East England, in 1845. 55 00 52.96 N 1 25 12.14 W
Colonia-Haus The Colonia-Haus is a 45-storey, 147 m skyscraper completed in 1973 in the Riehl district of Cologne, Germany. 50 57 38 N 6 58 55 E
Colonne Vendôme 48 52 02.89 N 2 19 45.89 E
Comacchio Comacchio is a town in Emilia Romagna in Italy. 44 41 31.74 N 12 10 55.95 E
Concatedral de Santa MarÃa de Guadalajara 40 38 04.72 N 3 09 45.15 W
Conciergerie The Conciergerie in the Palais de Justice, Paris, France 48 51 23 N 2 20 44 E
+Córdoba (Argentina) Intendancy square 31 24 00 S 64 11 00 W
Corrubedo, Ribeira 42 34 21.64 N 9 04 22.76 W
Cortegada Cortegada is a municipality in Galicia, in the province of Ourense. 42 12 24.86 N 8 10 01.06 W
Coulée verte René-Dumont The Promenade plantée is an elevated park in the 12th arrondissement of Paris, France. 48 50 32 N 2 23 15 E
@@ -269,41 +277,165 @@ Couvent de la Divine Providence de Saint-Jean-de-Bassel 48 48 12.12 N 6 59 32.0
Couvent de Reinacker 48 40 51.96 N 7 24 27.5 E
Crecente Crecente is a municipality in Galicia, in the province of Pontevedra. 42 09 07.02 N 8 13 22.52 W
Credit Lyonnais Head Office 48 52 14.95 N 2 20 11.45 E
-Château de Crussol The Château de Crussol is a castle in the Ardèche départment of France. 44 56 18 N 4 51 09 E
Cualedro 41 59 18.46 N 7 35 40.71 W
Culleredo Culleredo is a municipality in the province A Coruña, Galicia, Spain. 43 17 31.02 N 8 23 08.99 W
Curtis Hall Arboretum 40 04 42 N 75 07 44 W
-Cáceres Cáceres is the capital of Cáceres Province, in Extremadura, Spain. 39 28 23 N 6 22 16 W
-Córdoba (Argentina) Intendancy square 31 24 00 S 64 11 00 W
+Cygnus olor from Carolasee The swans and pond are there since 1882. 51 01 59.16 N 13 45 52.69 E
Dakar 14 43 55 N 17 27 26 W
Dalhems kyrka Die Kirche von Dalhem zählt zu den berühmtesten auf Gotland. Ihr Turm, der im 14. Jahrhundert angefügt wurde, gehört zu den höchsten der Landkirchen Gotlands. 57 33 08.7 N 18 32 03.2 E
Dazaifu Tenman-gū 33 31 17.49 N 130 32 05.45 E
+Delaney Park, Anchorage, Alaska 61 12 47 N 149 54 04 W
Dent du Géant 45 51 43 N 6 57 06 E
Detroit Institute of Arts The Detroit Institute of Arts is a large art museum in Detroit, Michigan in the United States. 42 21 33.5 N 83 03 53.3 W
-Deutsches Museum Verkehrszentrum München 48 07 57.85 N 11 32 40.69 E
+Deutsches Museum Verkehrszentrum GanghoferstraÃe 29, 80339 München 48 07 57.85 N 11 32 40.69 E
Deyrulzaferan 37 17 57.6 N 40 47 33.9 E
+Äình Bảng Bảng Communal House (Äình Bảng in Vietnamese) is one of largest and finest village communal houses in Viá»t Nam. 21 06 29.99 N 105 57 06.31 E
+Doran Strait Chugach National Forest, Alaska 61 04 34 N 148 11 20 W
+Dorfkirche Dabergotz 52 54 10.44 N 12 43 30.42 E
+Dorfkirche Golzow (Barnim) 52 54 41.37 N 13 48 32.69 E
+Dorfkirche Hohenfinow 52 48 38.1 N 13 55 29.08 E
+Dorfkirche Kirchlotheim 51 10 07.83 N 8 53 46.05 E
Dorfkirche Klein HaÃlow Church in Klein HaÃlow, Wittstock municipality, Ostprignitz-Ruppin district, Brandenburg state, Germany 53 10 29.84 N 12 31 28.6 E
Dorfkirche Priort Church in Priort, Wustermark municipality, Havelland district, Brandenburg state, Germany. 52 30 44.61 N 12 57 49.36 E
+Dorfkirche Zechow 53 03 18.01 N 12 54 44.88 E
Dozón 42 34 09.35 N 8 03 08.25 W
Drexel University 39 57 14.68 N 75 11 12.76 W
Duchesse Anne (voilier) 51 02 15.37 N 2 22 20.21 E
Duino-Aurisina 45 45 02.29 N 13 40 29.6 E
Durban 29 53 00 S 31 03 00 E
Dürrenstein (Südtirol) The Dürrenstein is a mountain in the Dolomites in South Tyrol. 46 40 24 N 12 11 04 E
-Effnerplatz The Effnerplatz is a square in the north of Munich, in the Borough Bogenhausen. 48 09 11.79 N 11 36 54.73 E
-Ãglise Saint-Jean-Baptiste de Laure-Minervois 43 16 20.78 N 2 31 12.11 E
-Ãglise Saint-Louis-en-l'Ãle The Saint-Louis-en-l'Ãle Church (lit. "St. Louis on the Island"), is a Catholic church located on Ãle Saint-Louis in the IVe arrondissement of Paris 48 51 4.38 N 2 21 27.47 E
+Ãcole centrale de Lille Ãcole Centrale de Lille is a graduate engineering school located in campus Lille I within Université Lille Nord de France. 50 36 21.62 N 3 08 13.63 E
+Ãcole Jules Ferry de Royan 45 37 38.16 N 1 01 33.66 W
+Effnerplatz The Effnerplatz is a square in the north of Munich in the Borough Bogenhausen. 48 09 09 N 11 36 51.12 E
+Ãglise de la Sainte-Trinité (Lauterbourg) 48 58 30.1 N 8 10 40.77 E
+Ãglise de l'Assomption simultanée (La Petite-Pierre) 48 51 25.2 N 7 18 55.84 E
+Ãglise de Saint-Lothain 46 49 27.84 N 5 38 30.12 E
+Ãglise de Saint-Paul de Frontignan L'Ãglise de Saint-Paul de Frontignan est une église catholique de l'ancien diocèse de Maguelone en Languedoc, France. 43 26 50.47 N 3 45 18.66 E
+Ãglise des Augustins (Ribeauvillé) 48 11 43.44 N 7 19 08.87 E
+Ãglise des Jésuites (Molsheim) 48 32 25.3 N 7 29 45 E
+Ãglise des Saints-Innocents (Blienschwiller) 48 20 25.8 N 7 25 06.17 E
+Ãglise Notre-Dame de la Dalbade 43 35 51.36 N 1 26 32.89 E
+Ãglise Notre-Dame-de-la-Nativité (Saverne) 48 44 28.32 N 7 21 50.36 E
+Ãglise Notre-Dame-de-l'Assomption (Bergheim) 48 12 18 N 7 21 53.28 E
+Ãglise Notre-Dame-de-l'Assomption (Bernardswiller) 48 27 10.08 N 7 27 49.57 E
+Ãglise Notre-Dame-de-l'Assomption (Monswiller) 48 45 17.61 N 7 22 39.66 E
+Ãglise Notre-Dame-de-l'Assomption (Rosenwiller) 48 30 21.96 N 7 26 25.48 E
+Ãglise Notre-Dame-de-l'Assomption (Rouffach) 47 57 24 N 7 18 02 E
+Ãglise Notre-Dame (Guebwiller) 47 54 20.75 N 7 12 52.56 E
+Ãglise protestante (Balbronn) 48 35 05.28 N 7 26 15.97 E
+Ãglise protestante (Baldenheim) 48 14 15 N 7 32 14.35 E
+Ãglise protestante (Berg) 48 53 52.08 N 7 09 24.01 E
+Ãglise protestante (Bischheim) 48 36 55.08 N 7 45 21.89 E
+Ãglise protestante du Temple Neuf (Strasbourg) 48 35 00 N 7 44 54 E
+Ãglise protestante (Fouday) 48 25 17.76 N 7 11 12.95 E
+Ãglise protestante (Harskirchen) 48 56 02.04 N 7 02 20.15 E
+Ãglise protestante (Scharrachbergheim) 48 35 35.52 N 7 29 55.9 E
+Ãglise protestante (Schiltigheim) 48 36 21.96 N 7 45 05.04 E
+Ãglise protestante (Sélestat) 48 15 36.36 N 7 27 11.56 E
+Ãglise protestante (Weiterswiller) 48 51 10.44 N 7 24 50.9 E
+Ãglise Sainte-Marie-Madeleine de Rennes-le-Château 42 55 41.05 N 2 15 45.69 E
+Ãglise Saint-Eustache de Paris 48 51 48 N 2 20 42 E
+Ãglise Saint-Gervais-Saint-Protais 48 51 19.8 N 2 21 16.6 E
+Ãglise Saint-Laurent (Paris) 48 52 29.45 N 2 21 29.92 E
+Ãglise Saint-Louis-en-l'Ãle The Saint-Louis-en-l'Ãle Church (lit. "St. Louis on the Island"), is a Catholic church located on Ãle Saint-Louis in the IVe arrondissement of Paris 48 51 4.38 N 2 21 27.47 E
Ãglise Saint-Martin de Chambonas 44 25 02.45 N 4 07 43.97 E
-Eglise Saint-Pierre des Cuisines 43 36 15.49 N 1 26 08.26 E
+Ãglise Saint-Michel d'Ernolsheim-lès-Saverne Bells 48 47 27.85 N 7 22 47.57 E
+Ãglise Saint-Nicolas-du-Chardonnet St. Nicolas du Chardonnet is a church in the centre of Paris, France located in the 5th arrondissement. 48 50 57 N 2 21 01 E
+Ãglise Saint-Pierre de Montmartre Saint-Pierre de Montmartre is a church in Paris 48 53 12 N 2 20 31 E
+Ãglise Saint-Pierre-de-Rhèdes 43 35 16.22 N 3 04 43.64 E
+Eglise Saint-Pierre des Cuisines L'Ãglise Saint-Pierre des Cuisines, située rue de la Boule, à côté de la place Saint-Pierre à Toulouse, est la plus vieille église du sud-ouest de la France. Elle est construite sur une ancienne nécropole gallo-romaine du IVe siècle. 43 36 15.49 N 1 26 08.26 E
+Ãglise Saint-Pierre-Saint-Paul de Rueil-Malmaison 48 52 35.4 N 2 10 53.15 E
+Ãglise Saints-Pierre-et-Paul (Andlau) 48 23 16.3 N 7 24 54.3 E
+Ãglise Saints-Pierre-et-Paul (Eguisheim) 48 02 32.28 N 7 18 21.2 E
+Ãglise Saints-Pierre-et-Paul (Hohatzenheim) 48 42 44.64 N 7 36 59.11 E
+Ãglise Saints-Pierre-et-Paul (Neuwiller-lès-Saverne) 48 49 25 N 7 24 20 E
+Ãglise Saints-Pierre-et-Paul (Obernai) 48 27 47.88 N 7 28 54.48 E
+Ãglise Saints-Pierre-et-Paul (Ottmarsheim) 47 47 13.2 N 7 30 25.2 E
+Ãglise Saints-Pierre-et-Paul (Rosheim) 48 29 48 N 7 28 14 E
+Ãglise Saints-Pierre-et-Paul (Sigolsheim) 48 08 04.2 N 7 18 03.1 E
+Ãglise Saints-Pierre-et-Paul (Wissembourg) 49 02 14 N 7 56 30 E
+Ãglise Saint-Sulpice 48 51 04 N 2 20 05 E
Ãglise Saint-Vincent-de-Paul (Paris) Saint-Vincent-de-Paul is a church in Paris near the Gare du Nord 48 52 43.7 N 2 21 06.6 E
-El Padul 37 01 27 N 3 37 36 W
+Ãglises St Pierre le Vieux (Strasbourg) protestant church 48 34 58 N 7 44 24 E
+Ãglise St Antoine de Padoue (Saverne) 48 44 29.4 N 7 21 40.82 E
+Ãglise St Arbogast (Offenheim) 48 37 53.76 N 7 36 59.54 E
+Ãglise St Barthélemy (Sarrewerden) 48 55 22.8 N 7 04 56.93 E
+Ãglise St Benoît (Bergholtzzell) 47 55 51.34 N 7 13 54.48 E
+Ãglise St Blaise (Valff) 48 25 12.36 N 7 31 06.96 E
+Ãglise St Cyriaque (Altorf) 48 31 22.7 N 7 31 50 E
+Ãglise Ste Anne (Turckheim) 48 05 15.72 N 7 16 41.12 E
+Ãglise Ste Aurélie protestante (Strasbourg) 48 34 53 N 7 44 00 E
+Ãglise Ste Colombe (Hattstatt) 48 00 44.28 N 7 18 06.01 E
+Ãglise Ste Croix (Kaysersberg) Lamentation of Christ 48 08 20.04 N 7 15 48.56 E
+Ãglise Ste Croix (Rountzenheim) 48 49 08.76 N 8 00 26.39 E
+Ãglise Ste Foy (Sélestat) 48 15 33.67 N 7 27 21.81 E
+Ãglise Ste Lucie (Niederhergheim) 47 59 10.32 N 7 23 48.41 E
+Ãglise Ste Madeleine (Strasbourg) 48 34 48 N 7 45 17 E
+Ãglise Ste Marguerite (Geispolsheim) 48 30 50.4 N 7 38 36.06 E
+Ãglise Ste Odile (Lapoutroie) 48 09 08.64 N 7 10 03.97 E
+Ãglise Ste Odile (Wintzfelden) 47 58 32.88 N 7 11 49.92 E
+Ãglise St Ãtienne (Rosheim) 48 29 43.8 N 7 27 59.72 E
+Ãglise St Ãtienne (Seltz) 48 53 37.32 N 8 06 28.44 E
+Ãglise St Ãtienne simultanée (Wangen) 48 37 01.56 N 7 27 53.68 E
+Ãglise Ste Walburge (Walbourg) 48 53 05.51 N 7 47 21.97 E
+Ãglise St Gall (Niedermorschwihr) 48 05 57.84 N 7 16 26.47 E
+Ãglise St Gall protestante (Domfessel) 48 57 06.48 N 7 09 07.56 E
+Ãglise St Georges (Châtenois) 48 16 09.12 N 7 23 51 E
+Ãglise St Georges (Sélestat) 48 15 36 N 7 27 24.12 E
+Ãglise St Grégoire (Ribeauvillé) 48 11 49.2 N 7 19 00.41 E
+Ãglise St Guillaume protestante (Strasbourg) 48 34 55.5 N 7 45 28 E
+Ãglise St Hippolyte (Saint-Hippolyte) 48 14 01.68 N 7 22 04.01 E
+Ãglise St Jacques-le-Majeur (Kuttolsheim) 48 38 37.32 N 7 31 41.34 E
+Ãglise St Jacques-le-Majeur simultanée (Dettwiller) 48 45 12.6 N 7 27 56.77 E
+Ãglise St Jacques-le-Majeur simultanée (Hunawihr) 48 10 42.24 N 7 18 38.02 E
+Ãglise St Jean-Baptiste (Saint-Jean-Saverne) 48 46 18.7 N 7 21 48.5 E
+Ãglise St Jean-Baptiste simultanée (Hohwiller) 48 45 12.78 N 7 27 56.77 E
+Ãglise St Jean-Baptiste (Surbourg) 48 54 34.2 N 7 50 50.28 E
+Ãglise St Jean-Baptiste (Wattwiller) 47 50 07.72 N 7 10 37.27 E
+Ãglise St Jean protestante (Wissembourg) 49 02 18.96 N 7 56 33.36 E
+Ãglise St Jean (Strasbourg) 48 35 04 N 7 44 25 E
+Ãglise St Laurent (Dieffenbach-au-Val) 48 18 44.64 N 7 19 41.34 E
+Ãglise St Laurent protestante (Dorlisheim) 48 31 30 N 7 29 13.99 E
+Ãglise St Léger (Guebwiller) 47 54 42.1 N 7 12 33.75 E
+Ãglise St Léger (Murbach) 47 55 24 N 7 09 29 E
+Ãglise St Martin (Ammerschwihr) 48 07 37.92 N 7 16 54.01 E
+Ãglise St Martin (Ebersheim) 48 18 14.04 N 7 30 14.08 E
+Ãglise St Martin (Pfaffenheim) 47 59 05.28 N 7 17 08.59 E
+Ãglise St Martin protestante (Barr) 48 24 33.84 N 7 26 51.47 E
+Ãglise St Martin protestante (Westhoffen) 48 36 01.8 N 7 26 30.3 E
+Ãglise St Maurice (Ebersmunster) 48 18 39.5 N 7 31 37 E
+Ãglise St Maurice (Fegersheim) 48 29 23.64 N 7 40 50.27 E
+Ãglise St Maurice (Orschwiller) 48 14 27.24 N 7 22 44.62 E
+Ãglise St Maurice (Soultz-Haut-Rhin) 47 53 13.2 N 7 13 48.29 E
+Ãglise St Maurice (Soultz-les-Bains) 48 34 17.4 N 7 29 09.35 E
+Ãglise St Maurice (Willgottheim) 48 40 14.52 N 7 30 33.23 E
+Ãglise St Médard (BÅrsch) 48 28 40.44 N 7 26 24.4 E
+Ãglise St Michel (Reichshoffen) 48 55 54.84 N 7 39 52.02 E
+Ãglise St Michel (Weyersheim) 48 43 06.24 N 7 48 07.96 E
+Ãglise St Nicolas (Haguenau) 48 49 13 N 7 47 32 E
+Ãglise St Nicolas (Neuve-Ãglise) 48 19 50.88 N 7 18 48.24 E
+Ãglise St Nicolas (Wingersheim) 48 43 18.84 N 7 38 08.02 E
+Ãglise St Pantaléon (Gueberschwihr) 48 00 16.92 N 7 16 29.78 E
+Ãglise St Paul protestante (Strasbourg) 48 35 11 N 7 45 35 E
+Ãglise St Pierre "Dompeter" (Molsheim, Avolsheim) 48 33 24.12 N 7 30 19.59 E
+Ãglise St Pierre le Jeune catholique (Strasbourg) 48 35 18.35 N 7 44 55.75 E
+Ãglise St Pierre le Jeune protestante (Strasbourg) 48 35 08 N 7 44 47 E
+Ãglise St Rémi (Itterswiller) 48 21 51.48 N 7 25 37.42 E
+Ãglise St Sébastien (Soultzmatt) 47 57 37.08 N 7 14 15.36 E
+Ãglise St Thomas protestante (Strasbourg) 48 34 47 N 7 44 44 E
+Ãglise St Trophime (Eschau) 48 29 25.08 N 7 42 57.96 E
+Ãglise St Ulrich (Altenstadt) 49 01 49.8 N 7 58 05.88 E
+Ãglise St Ulrich (Wittersheim) 48 46 53.04 N 7 39 27.47 E
+Eklutna Village Cemetery Anchorage, Alaska 61 27 38 N 149 21 42 W
El Vendrell 41 13 11.72 N 1 32 04.08 E
Empúries Empúries is a town on the Mediterranean coast of the Catalan comarca of Alt Empordà in Catalonia, Spain. 42 08 20.29 N 3 07 11.19 E
Enclos paroissial de Saint-Thégonnec 48 31 13.4 N 3 56 47.44 W
-Erica, Victoria 37 59 00 S 146 22 00 E
+Erica, Victoria 37 59 00 S 146 22 00 E
Erlöserkirche (Bad Homburg) The Church of the Redeemer is a protestant church in Bad Homburg, Germany. 50 13 35.5 N 8 36 42 E
Esgos 42 19 29.71 N 7 41 45.94 W
+Esther Passage Chugach National Forest, Alaska 60 53 20 N 147 56 27 W
European Parliament The European Parliament is the parliament of the European Union. 48 35 51.82 N 7 46 09.82 E
+Explorer Glacier Chugach National Forest, Alaska 60 46 34 N 148 55 03 W
Familistère 49 54 15 N 3 37 31 E
Fangelsbachfriedhof The Fangelsbachfriedhof is one of the most important historical cemeteries in Stuttgart. 48 45 56 N 9 10 28 E
Feldkommandostelle Hegewald (East Prussia) 54 08 05.54 N 21 58 36.02 E
@@ -312,115 +444,129 @@ Ferrol 43 29 21.47 N 8 13 29.94 W
Ferrytoll Park & Ride Ferrytoll Park & Ride is a bus/car interchange in Fife, Scotland, at the northern end of the Forth road crossing. 56 01 21.47 N 3 24 22.97 W
Fieschergletscher 46 30 07.88 N 8 08 30.59 E
Fiesole (area archeologica) 43 48 29.04 N 11 17 39.19 E
+Filialkirche hl. Gotthart in Lansach, WeiÃenstein 46 41 12.84 N 13 42 16.56 E
Fish Creek, Victoria 38 41 00 S 146 05 00 E
Flaucher Flaucher is an area in the south of Munich on the left and right hand side of the Isar (district: Sendling and Thalkirchen). 48 06 27 N 11 33 27 E
Fontaine des Neuf-Canons 43 31 36.12 N 5 26 55.25 E
Fontaine du Palmier 48 51 26.99 N 2 20 50.17 E
+Forêt domaniale de Sète The National Forest of Sète in the commune of Sète, Hérault, France. 43 24 18.74 N 3 40 13.74 E
+Forge d'Ãtueffont 47 43 20.9 N 6 55 15.19 E
+Fortaleza da Nogueirosa 43 23 29.12 N 8 08 09.12 W
+Fortaleza de San Paio de Narla 43 00 25.83 N 7 49 14 W
Fort Boyard Fort Boyard is a fort located between the île d'Aix and the île d'Oléron in the Pertuis d'Antioche straits, on the west coast of France. 45 59 58.71 N 1 12 50.16 W
Fort de Bessoncourt 47 38 58.41 N 6 55 37.74 E
Fort de la Miotte 47 38 53.29 N 6 52 30.33 E
-Fort de Vézelois 47 36 01.67 N 6 54 29.41 E
Fort des Basses Perches 47 37 34.05 N 6 52 06.81 E
+Fort de Vézelois 47 36 01.67 N 6 54 29.41 E
Fort du Bois d'Oye 47 34 27.7 N 6 50 36.55 E
-Fort Ross Fort Ross, a former Russian fur trade outpost, located on the coast of Northern California (United States). 38 30 51.35 N 123 14 36.88 W
-Fortaleza da Nogueirosa 43 23 29.12 N 8 08 09.12 W
-Fortaleza de San Paio de Narla 43 00 25.83 N 7 49 14 W
Forte di Gavi Il Forte di Gavi è una fortezza storica costruita su un preesistente castello di origine medioevale. 44 41 27.95 N 8 48 15.55 E
Fortezza del Priamar La fortezza del Priamar è un antico insediamento storico presente nella città ligure di Savona, Italia. 44 18 16.29 N 8 29 03.44 E
-Forêt domaniale de Sète The National Forest of Sète in the commune of Sète, Hérault, France. 43 24 18.74 N 3 40 13.74 E
+Fort Ross Fort Ross, a former Russian fur trade outpost, located on the coast of Northern California. 38 30 51.35 N 123 14 36.88 W
Fosse De Sessevalle 50 22 11.03 N 3 15 41.09 E
Four solaire d'Odeillo The "Centre du Four Solaire Félix Trombe" is located in Odeillo, France. 42 29 37 N 2 01 45 E
+Fox Island (Alaska) Kenai Peninsula, Alaska 59 54 46 N 149 20 52 W
Francelos, Ribadavia 42 16 35.51 N 8 09 34.88 W
Franciscan Monastery in Katowice Panewniki Neo-Romanesque monastery of the Franciscans in Katowice Panewniki in Poland from the early XX century. 50 13 37 N 18 57 45 E
-Pfarrkirche St. Bartholomäus in Friesach 46 57 04.28 N 14 24 18.19 E
Fubine Fubine è un comune in provincia di Alessandria, Piemonte, Italia. 44 57 55.35 N 8 25 32.75 E
Funkturm Leipzig 51 18 49.02 N 12 23 34.93 E
-Fuzhou Fuzhou, also known as Foochow, is a city in China. 26 04 16 N 119 18 13 E
+Fuzhou 26 04 16 N 119 18 13 E
+Galata Bridge Galata Bridge crosses the Golden Horn in Istanbul, Turkey 41 01 13.1 N 28 58 24.4 E
Gandino 45 48 42 N 9 54 11 E
-Gardens of Nymphenburg Palace Der Nymphenburger Schlosspark ist eines der gröÃten und bedeutendsten Gartenkunstwerke Deutschlands. 48 09 29 N 11 30 13 E
+Gardens of Nymphenburg Palace Der Nymphenburger Schlosspark ist eines der gröÃten und bedeutendsten Gartenkunstwerke Deutschlands. 48 09 28 N 11 29 34 E
Gare de Metz-Ville 49 06 35.28 N 6 10 39 E
-Gare de Paris-Est Literally East Station, Paris, but usually called Gare de l'Est in Paris, France. 48 52 37 N 2 21 33 E
-Gare de Paris-Nord Literally North Station, Paris, but usually called Gare du Nord in Paris, France. 48 52 58 N 2 21 24 E
+Gare de Paris-Est 48 52 36.84 N 2 21 33.12 E
+Gare de Paris-Nord 48 52 58 N 2 21 24 E
Gare de Paris-Saint-Lazare Gare Paris Saint-Lazare is one of the six large terminus railway stations of Paris. 48 52 37 N 2 19 28 E
-Garmischer StraÃe The Garmischer StraÃe is a street in Munich, part of the Mittlerer Ring around the city centre. 48 07 28.03 N 11 31 14.51 E
+Garmischer StraÃe The Garmischer StraÃe is a street in Munich, part of the Mittlerer Ring around the city centre. 48 07 28.2 N 11 31 14.52 E
Garten des Himmlischen Friedens The Garten des Himmlischen Friedens (lit. Garden of Heavenly Peace) is a small walled Chinese garden in the Bethmannpark in Frankfurt-Nordend 50 07 07.57 N 8 41 26.52 E
Gavi Gavi is a town in Piemonte in Italy. 44 41 19.35 N 8 48 10.64 E
Gedankengang Offenbach This is part of a series of tunnels in Offenbach that have been redesigned. 50 05 58.64 N 8 45 49.92 E
-Georg-Brauchle-Ring The Georg-Brauchle-Ring is a street in Munich. 48 10 34.46 N 11 32 35.48 E
Gernikako Arbola The Gernika oak where the lords of Biscay (including several kings of Castile and Spain) came to take the oath of respect to the basques Fueros (Rules and Rights). 43 18 53.43 N 2 40 47.92 W
Giardino dei Semplici di Firenze The Orto Botanico di Firenze (2.3 hectares), also known as the Giardino dei Semplici, is a botanical garden maintained by the University of Florence. 43 46 45 N 11 15 39 E
Giurtelecu Èimleului Giurtelecu Èimleului is a settlement in Romania. 47 18 N 22 48 E
Glanum 43 46 26 N 4 49 57 E
+Godwin Glacier Chugach National Forest, Alaska 60 07 45 N 149 12 52 W
Goethedenkmal (Wien) The Goethe monument at the Opernring in Vienna by Edmund Hellmer 48 12 12.07 N 16 21 57.73 E
Gogar Tram Depot 55 56 22.27 N 3 19 36.44 W
+Göltzschtalbrücke 50 37 21.29 N 12 14 37.46 E
+Goose Lake Park, Anchorage, Alaska 61 11 49 N 149 49 13 W
Gorle 45 42 14 N 9 43 08 E
+Görzig (Rietz-Neuendorf) Train station 52 14 20.25 N 14 11 48.91 E
Government House, Jersey 49 11 41.44 N 2 05 39.78 W
Gradara Gradara is a town in Marche, Italy. 43 56 15.75 N 12 45 59.25 E
+Gråmanstorps kyrka 56 08 59.33 N 13 06 00.4 E
Grand Hôtel de Cabourg 49 17 37.32 N 0 06 59.08 W
Grand Palais The Grand Palais in Paris, France 48 51 58 N 2 18 45 E
-Granollers Granollers is a city near Barcelona, in Catalonia, Spain. 41 32 35.1 N 2 12 59.63 E
-Gromo Gromo is a town in Lombardia in Italy. 45 58 09.91 N 9 55 25.72 E
-Gråmanstorps kyrka 56 08 59.33 N 13 06 00.4 E
+Gromo Gromo is a town in Lombardia in Italy. 45 57 51.84 N 9 55 39 E
+Grouse Lake Kenai Peninsula, Alaska 60 12 05 N 149 22 29 W
+Gulkana Glacier Eastern Alaska Range, Alaska 63 14 26 N 145 28 03 W
Gut Böckel Böckel Castle in Rödinghausen, District of Herford, North Rhine-Westphalia, Germany. 52 13 29.1 N 8 31 02.98 E
Gymnasium Koblenzer StraÃe The Gymnasium Koblenzer StraÃe, also known as Kobi, is a German grammar school in Urdenbach, an urban borough of Düsseldorf. 51 08 58.67 N 6 53 08.95 E
-Göltzschtalbrücke 50 37 21.29 N 12 14 37.46 E
-Hamburg Hamburg is a City-State in the North of Germany and one of the biggest seaports in Europe. 53 34 07 N 10 02 19 E
+Haage Train station 52 40 37.61 N 12 35 48.46 E
Hamburger Rathaus 53 33 01 N 9 59 32 E
+Hamburg Hamburg is a City-State in the North of Germany and one of the biggest seaports in Europe. 53 34 07 N 10 02 19 E
+Hamburg-Moorburg Sprengung Kraftwerk Bursting of the 256 meters high chimney of the deactivated HEW power plant in Hamburg-Moorburg, Germany. The chimney was Hamburg's highest massiv building. The HEW power plant Hamburg-Moorburg was in operation from 1974 untill 2001. It was one of the biggest conventional power plant in Germany and was fired on both with natural gas and fuel oil. 53 29 24 N 9 57 06 E
Hameau de la Reine 48 49 07 N 2 06 46 E
-Hampigny 48 27 21 N 4 35 24 E
-Hansestaden Visby The Hanseatic town Visby was founded in the 10th century, on the then independent Baltic Sea island of Gotland. 57 38 20 N 18 17 40 E
-Château d'Harcourt The Château d'Harcourt is a castle located in the commune of Harcourt in the Eure département of France 49 10 26 N 0 47 11 E
+Hammer (Liebenwalde) Former town hall 52 52 54.39 N 13 26 32.69 E
+Hansestaden Visby The Hanseatic town Visby is the description of Visby, Sweden, from the UNESCO World Heritage Committee. 57 38 20 N 18 17 40 E
+Hans Paasche Hans Paasche (3 April 1881 â 21 May 1920) was a German politician and pacifist. 52 59 48.32 N 15 58 47.1 E
+Harriman Fjord Chugach National Forest, Alaska 61 02 20 N 148 19 17 W
Haus Werburg Haus Werburg is a small water castle in Spenge, Kreis Herford. 52 08 30.78 N 8 28 33.66 E
Hazmburk Hazmburk is a hill with castle in Äeské stÅedohoÅà in Czech Republic. 50 26 03 N 14 00 52 E
-HeckenstallerstraÃe The HeckenstallerstraÃe is a street in Munich, part of the Mittlerer Ring around the city centre. 48 06 35.77 N 11 31 42 E
+HeckenstallerstraÃe The HeckenstallerstraÃe is a street in Munich, part of the Mittlerer Ring around the city centre. 48 06 35.64 N 11 31 41.88 E
Hellig Kors Kirke Hellig Kors Kirke is a church on Nørrebro in Copenhagen, Denmark. 55 41 15.72 N 12 33 05.04 E
Henninger-Turm The 120-m-high Henninger Turm is located in Frankfurt-Sachsenhausen in Germany. 50 05 50.16 N 8 41 36.77 E
Herford Herford is a city in North Rhine-Westphalia, Germany. 52 06 57.81 N 8 40 12.11 E
HMS Otus The HMS Otus is a british Oberon class submarine. It serves today as a museum Sassnitz harbour. 54 30 43.13 N 13 38 29.79 E
-Holy Trinity Cathedral in Odessa 46 28 34.36 N 30 44 18.43 E
+Holgate Arm Kenai Fjords National Park, Alaska 59 49 56 N 149 47 56 W
+Holy Trinity Cathedral in Odessa Holy Trinity Cathedral in Odessa 46 28 33.96 N 30 44 17.16 E
+Hope Highway, Alaska Kenai Peninsula, Alaska 60 46 50 N 149 25 50 W
Hoppenlaufriedhof The Hoppenlaufriedhof is a cemetery in Stuttgart. 48 46 54 N 9 10 05 E
Horyuji HÅryÅ«-ji (æ³é寺, "Temple of the Flourishing Law") is a Buddhist temple in Ikaruga, Nara Prefecture, Japan. 34 36 53.06 N 135 44 03.02 E
Hospitalkirche (Stuttgart) 48 46 40 N 9 10 22 E
-Humprecht Humprecht is a castle on top of a hill near Sobotka in the Hradec Králové region in the Czech Republic. 50 28 13 N 15 10 11 E
Hôtel Biron 48 51 19 N 2 18 57 E
-Hôtel d'Ulmo 43 35 51 N 1 26 59.28 E
Hôtel de Bourgtheroulde 49 26 31.2 N 1 05 17.77 E
Hôtel de Sens 48 51 12 N 2 21 33 E
Hôtel de Soubise 48 51 38 N 2 21 30 E
+Hôtel d'Ulmo 43 35 51 N 1 26 59.28 E
Hôtel Lutetia 48 51 04 N 2 19 39 E
Hôtel Négresco 43 41 40 N 7 15 27 E
-Igreja de São Martinho de Aldoar 41 10 14.58 N 8 40 13.83 W
+Hübners Mühle in Werder (Havel) The fire ruin of the windmill of miller and baker named Hübner in Werder (Havel) 52 22 28.38 N 12 55 15.28 E
+Humprecht Humprecht is a castle on top of a hill near Sobotka in the Hradec Králové region in the Czech Republic. 50 28 13.08 N 15 10 10.92 E
+Igreja de São Martinho de Aldoar 41 10 14.59 N 8 40 13.84 W
Igrexa de San Pedro de Vilanova de Dozón The romanic parochial Church of San Pedro of Dozón 42 35 06.77 N 8 01 27.02 W
-Igrexa de Santa MarÃa de Cambre 43 17 32.03 N 8 20 34.4 W
+Igrexa de Santa MarÃa de Cambre 43 17 31.92 N 8 20 34.08 W
Igrexa de Santo AntolÃn de Toques 42 58 41.36 N 7 58 59.23 W
Illa de Cortegada 42 37 05.87 N 8 47 02.7 W
Iloilo City The City of Iloilo is the capital city of the Provinces of the Philippines of Iloilo. 10 41 24 N 122 33 00 E
Innerer Plauenscher Friedhof Cemetery âInnerer Plauenscher Friedhofâ near church âAuferstehungskircheâ in Dresden-Plauen 51 01 42.38 N 13 42 15.91 E
Institut de théologie orthodoxe Saint-Serge 48 52 59.98 N 2 23 01.23 E
-Isarring The Isarring is a street in Munich, part of the Mittlerer Ring around the city centre. 48 09 36.65 N 11 36 03.89 E
-Isfahan اصÙÙا٠32 39 05 N 51 40 45 E
+Isabel Pass Richardson Highway, Alaska 63 11 15 N 145 33 28 W
+Isarring The Isarring is a street in Munich, part of the Mittlerer Ring around the city centre. 48 09 36.72 N 11 36 03.96 E
Isla San Carlos Isla San Carlos or peninsula of San Carlos, is part of Venezuela and is located north of the island of Toas. 10 59 42.73 N 71 36 43.16 W
Ivrea Ivrea is a town in Piemonte in Italy. 45 27 50.4 N 7 52 42.96 E
Jagdschloss Wermsdorf 51 16 59.52 N 12 56 21.85 E
Jardin de l'Ãtat The Jardin de l'Ãtat is a botanical garden on Réunion island. 20 53 12 S 55 27 04 E
Jardin des Tuileries 48 51 50 N 2 19 34 E
-JaromÄÅ Pond 50 21 22.45 N 15 55 17.21 E
+JaromÄÅ Pond 50 21 21.6 N 15 55 15.6 E
Jesuitenkirche (Wien) The Jesuitenkirche (Jesuit church) is a prominent church in Vienna, Austria. 48 12 32.95 N 16 22 39.48 E
Jin Mao Tower Jin Mao Building 31 14 14 N 121 30 05 E
Johannesburg Johannesburg is the largest city in South Africa. 26 12 16 S 28 02 44 E
+José MarÃa Acuña López José MarÃa Acuña López, born in Pontevedra (Spain) on April 4, 1903 and died on 4 June 1991 in Vigo (Spain), was a spanish sculptor. 42 19 46.38 N 8 34 04.43 W
Jubiläumssäule 48 46 42.85 N 9 10 47.53 E
-Jumkils kyrka Jumkils kyrka tillhör Bälingebygdens församling, Upplands västra kontrakt, Uppsala stift / Diocese of Uppsala. 59 56 33.2 N 17 25 23.7 E
Jüdischer Friedhof Haunetal 50 45 12.6 N 9 41 00.6 E
+Jumkils kyrka Jumkils kyrka tillhör Bälingebygdens församling, Upplands västra kontrakt, Uppsala stift / Diocese of Uppsala. 59 56 33.2 N 17 25 23.7 E
Kaaba 21 25 21.11 N 39 49 34.41 E
Kagawa prefecture Kagawa Prefecture (é¦å·ç, Kagawa-ken?) is a prefecture of Japan located on Shikoku island. The capital is Takamatsu. 34 20 24.4 N 134 02 35.8 E
-Kansai International Airport Kansai International Airport, is an international airport located on an artificial island in the middle of Osaka Bay, off the shore of Sennan district of Osaka, Japan. 34 26 03 N 135 13 58 E
+Kansai International Airport Kansai International Airport is an international airport located on an artificial island in the middle of Osaka Bay, off the shore of Sennan district of Osaka, Japan. 34 26 03 N 135 13 58 E
Karlsfried Karlsfried Castle is situated nearby the town of Zittau in Sachsen, Germany. 50 50 05.05 N 14 47 32.29 E
Katharinenhospital Stuttgart 48 48 01.87 N 9 12 21.6 E
-Kathmandu 27 43 00 N 85 22 00 E
+Kathmandu 27 43 12 N 85 22 12 E
Kiel Kiel is the capital city and most populous city of the northern German state Schleswig-Holstein. 54 19 31 N 10 08 26 E
Kleinmarkthalle Frankfurt Vegetable stall 50 06 45 N 8 41 01 E
Klimkówka - stary dwór 49 35 18.78 N 21 49 50.14 E
Kloster Ettal The monastery of Ettal is a Benedictine monastery in Bavaria/Germany near Oberammergau. 47 34 09.33 N 11 05 40.42 E
+Korsberga kyrka, Småland 57 18 25.2 N 15 07 25.6 E
Kotohira Gu Kotohira Gu in Kotohira, Kagawa prefecture, Japan. 34 11 02.2 N 133 48 34 E
Kreis Herford 52 06 57.54 N 8 39 40.42 E
Kreis Minden-Lübbecke Der Kreis Minden-Lübbecke ist ein Landkreis im Osten des Landes Nordrhein-Westfalen mit Sitz in Minden. 52 16 53.48 N 8 54 41.71 E
@@ -429,32 +575,31 @@ Kriegerdenkmal in Arnsdorf (Ruhland) 51 25 48.02 N 13 51 05.5 E
Kronprinzenpalais (Stuttgart) 48 46 41.56 N 9 10 39.88 E
Krumbach (Schwaben) Krumbach (Schwaben) ist eine Stadt im Landkreis Günzburg, Regierungsbezirk Schwaben, Bayern. 48 14 35 N 10 21 48 E
Krummesse Krummesse is a village in Schleswig-Holstein, Germany, which partly belongs to Kreis Herzogtum Lauenburg and partly to Lübeck. 53 46 45 N 10 38 30 E
-Kuala Lumpur 3 09 35 N 101 42 00 E
+Kuala Lumpur 3 08 52.08 N 101 41 43.08 E
Kunsthalle Bremen 53 04 22 N 8 48 49 E
Kuressaare 58 09 00 N 22 16 48 E
Kusterdingen 48 31 20.28 N 9 07 15.24 E
Lac Blanc (Orbey) Dans le massif des Vosges, près d'Orbey. 48 07 31.32 N 7 05 34.95 E
-Lac Chambon 45 34 13 N 2 55 18 E
Lac de Serre-Ponçon Le Lac de Serre-Ponçon, vallé de l'Ubaye, Hautes-Alpes, France 44 30 33.26 N 6 22 10.8 E
-Lac des Dix 46 03 25.74 N 7 23 51.17 E
+Lake Louise, Alaska Borough di Matanuska-Susitna, Alaska 62 19 26 N 146 32 56 W
LalÃn LalÃn is a municipality in Galicia, Spain in the province of Pontevedra. 42 39 36.8 N 8 06 43.31 W
Langes Tannen 53 41 32.67 N 9 40 28.6 E
-Large Hadron Collider CERN collider near Geneva, Switzerland 46 16 17 N 6 03 48.5 E
+Large Hadron Collider 46 16 17 N 6 03 48.5 E
Larouco Larouco is a municipality in Galicia, in the province of Ourense. 42 20 48.74 N 7 09 37.22 W
Lavoir de Gex 46 20 02.04 N 6 03 30.02 E
Laza Laza is a municipality in Galicia, in the province of Ourense. 42 03 36.68 N 7 27 37.14 W
+Learnard Glacier Chugach National Forest, Alaska 60 48 44 N 148 42 55 W
+Leiro Leiro is a municipality in Galicia, in the province of Ourense. 42 22 11.51 N 8 07 27.42 W
Le Louxor 48 52 00 N 2 20 59 E
Le Sauze-du-Lac Le Sauze-du-Lac est un petit village de les Hautes-Alpes, prés du lac de Serre-Ponçon. 44 28 42.94 N 6 18 52.35 E
-Le Train Bleu 48 50 42 N 2 22 24 E
-Legnano Legnano is a town in the north-west of Lombardy, situated on the flat lands of the Po Valley between Milan and Lake Maggiore. 45 35 48.84 N 8 54 32 E
-Leiro Leiro is a municipality in Galicia, in the province of Ourense. 42 22 11.51 N 8 07 27.42 W
Les Invalides 48 51 18 N 2 18 45 E
+Le Train Bleu 48 50 42 N 2 22 24 E
Levanto Levanto is a village in Liguria in Italy. 44 10 15.82 N 9 36 41.68 E
Lighthouses at Cape Arkona There are two lighthouses and one bearing tower at Cape Arkona. 54 40 47 N 13 25 57 E
-Ligne Aubagne - Fuveau 43 23 41.38 N 5 33 59.44 E
-Lima 12 05 36 S 77 02 48 W
-Loro Parque Puerto de la Cruz, Tenerife, Canarias, España 28 24 30.18 N 16 33 51.25 W
-Loschwitzer Friedhof Cemetery "Loschwitzer Friedhof" in Dresden-Loschwitz 51 02 46 N 13 49 18.98 E
+Lima Lima 12 03 00 S 77 02 00 W
+Loro Parque 28 24 29.88 N 16 33 52.74 W
+Loschwitzer Friedhof Cemetery âLoschwitzer Friedhofâ in Dresden-Loschwitz 51 02 46 N 13 49 18.98 E
+Lowell Point, Alaska Kenai Peninsula, Alaska 60 04 18 N 149 26 37 W
Luise-Kiesselbach-Platz The Luise-Kiesselbach-Platz is a square in the southwest of Munich. 48 06 44.17 N 11 31 03.27 E
Lunds domkyrka Lunds domkyrka or Lund Cathedral is the cathedral of Lund in Skåne in southern Sweden. 55 42 14.59 N 13 11 36.91 E
LWL-Freilichtmuseum Detmold The LWL-Freilichtmuseum Detmold (earlier name: Westfälisches Freilichtmuseum Detmold) is a museum for folklife studies in the town of Detmold, Germany. 51 55 25 N 8 52 12 E
@@ -468,7 +613,10 @@ Maisons de la rue Jeanne-Mance 45 30 31.9 N 73 34 11.02 W
Manneken Pis van Brussel Manneken Pis in Brussels 50 50 42 N 4 21 00 E
Manufacture nationale de Sèvres 48 49 43 N 2 13 21 E
Manzaneda Manzaneda is a municipality in Galicia, in the province of Ourense. 42 18 35.33 N 7 13 58.01 W
+Margaret Eagan Sullivan Park, Anchorage, Alaska 61 12 31 N 149 55 16 W
+Marienkirche Witzwort 54 23 58.86 N 8 59 06.17 E
MarÃn 42 23 31.28 N 8 42 16.58 W
+Mary's Tomb 31 46 48.5 N 35 14 21.41 E
Maside Maside is a municipality in Galicia, in the province of Ourense. 42 24 44.75 N 8 01 31.85 W
Matitone (Genova) Il Matitone è un grattacielo di Genova dalla struttura a forma di lapis. à situato nella zona portuale di San Benigno, a breve distanza dalla torre della Lanterna. 44 24 40.59 N 8 54 25.07 E
Matteus kyrka, Stockholm 59 20 43.08 N 18 02 32.94 E
@@ -476,110 +624,112 @@ Maximiliansbrücke in München 48 08 12.42 N 11 35 31.45 E
Meaño Meaño is a municipality in Galicia, Spain in the province of Pontevedra. 42 26 31.95 N 8 46 46.02 W
Meis Meis is a municipality in Galicia, Spain in the province of Pontevedra. 42 30 49.01 N 8 41 27.14 W
Melón Melón is a municipality in Galicia, in the province of Ourense. 42 15 26.97 N 8 13 01.51 W
+Mérida (Spain) 38 54 56.88 N 6 19 59.88 W
Mii-dera Mii-dera ä¸äºå¯º, formally OnjÅji åå寺, is a Tendai Buddhist temple in the city of Otsu, Shiga Prefecture, Japan. 35 00 48.09 N 135 51 10.26 E
Millennium Town Park The Millennium Town Park is a public park in Saint Helier, Jersey. 49 11 15.01 N 2 06 06.95 W
-Minden Minden is a German city in North Rhine-Westphalia. 52 17 20.18 N 8 55 04.19 E
Mindener Dom Cathedral in Minden, District of Minden-Lübbecke, North Rhine-Westphalia, Germany. 52 17 19.85 N 8 55 09.94 E
Mindener Kreisbahnen Kreisbahnen Minden, ein Unternehmen aus dem 19. Jahrhundert, das in Abwandlungen noch heute besteht. 52 18 01.14 N 8 54 50.98 E
+Minden Minden is a German city in North Rhine-Westphalia. 52 17 20.18 N 8 55 04.19 E
Mittagskogel Mittagskogel is a peak in the Karawanken mountain chain in Carinthia / Austria / EU. 46 30 26.54 N 13 57 08.1 E
Moaña Moaña is a municipality in Galicia, Spain in the province of Pontevedra. 42 17 05.52 N 8 44 57.56 W
Moe, Victoria 38 10 20 S 146 16 04 E
+Möja kyrka 59 24 18.8 N 18 52 53 E
Molino Stucky Il Molino Stucky è uno storico edificio di Venezia. à un esempio di architettura industriale neogotica. 45 25 41.55 N 12 19 11.95 E
Monastery of San Paio de Diomondi 42 36 13.6 N 7 42 34.1 W
Monforte de Lemos 42 31 19.98 N 7 30 46.56 W
-Monte Amiata Il Monte Amiata è un monte situato nella Toscana. 42 54 00 N 11 38 00 E
-Monte Musinè el Monte Musinè es una cima de los Alpes Grayos, en Italia. 45 06 50 N 7 27 16 E
+MoÅki Railway station 53 24 00 N 22 47 00 E
+Monte Amiata Il Monte Amiata è un monte situato nella Toscana. 42 53 15.9 N 11 37 27.73 E
Monterrei Monterrei is a municipality in Galicia, in the province of Ourense. 41 56 51.19 N 7 26 58.52 W
-Montevideo 34 52 01 S 56 10 00 W
-Montmartre Cemetery Montmartre Cemetery (Fr: Cimetière de Montmartre) is a famous cemetery located at 37 Avenue Samson, in the 18th arrondissement of Paris, France. 48 53 16 N 2 19 49 E
+Montevideo Montevideo is the capital and largest city of Uruguay. 34 52 01 S 56 10 00 W
+Montmartre Cemetery Montmartre Cemetery (Fr: Cimetière de Montmartre) is a famous cemetery located at 37 Avenue Samson, in the 18th arrondissement of Paris, France. 48 53 16.08 N 2 19 49.08 E
Monument de Joseph Sec Monument Joseph Sec, 8 avenue Pasteur, Aix-en-Provence, France. 43 31 59.44 N 5 26 46.71 E
Monument international de la Réformation 46 12 00.78 N 6 08 45.19 E
Mos Mos is a municipality in Galicia, Spain in the province of Pontevedra. 42 11 39.08 N 8 39 11.19 W
+Mössingen 48 24 23 N 9 03 27 E
Mosteiro de San Clodio de Leiro 42 22 02.61 N 8 06 54.12 W
Mosteiro de San Salvador de Celanova 42 09 06.55 N 7 57 24.85 W
Mosteiro de Santa MarÃa de Aciveiro 42 37 03 N 8 18 06 W
-MoÅki Railway station 53 24 00 N 22 47 00 E
+Mount Muir, Alaska Chugach Mountains, Alaska 61 06 29 N 148 22 42 W
Mugardos Mugardos is a municipality in the province A Coruña, Galicia, Spain. 43 27 43.7 N 8 15 12.52 W
-Muntic Muntic is a village in Istria, Croatia. 44 55 00 N 13 56 00 E
-Murol 45 34 23 N 2 56 35 E
+Mühlen am Löbauer Wasser 51 12 02.21 N 14 39 21.09 E
Muros 42 46 28.69 N 9 03 23.75 W
Murray House 22 13 05.15 N 114 12 34.96 E
Murviel-lès-Béziers 43 26 29 N 3 08 42 E
+Museo Archeologico Regionale Paolo Orsi Archaeological Museum Paolo Orsi in Syracuse 37 04 34.36 N 15 17 10.89 E
Museo Civico d'Arte Antica di Torino Il Museo Civico d'Arte Antica è un polo museale situato a Torino presso Palazzo Madama. 45 04 15.95 N 7 41 07.72 E
Museo della Storia del Genoa 44 24 37.8 N 8 56 11.39 E
Museo Regionale della Fauna Alpina - Alpenfaunamuseum "Beck-Peccoz" Un museo sulla fauna alpina situato a Gressoney-Saint-Jean, in Valle d'Aosta, Italia. 45 46 35.57 N 7 49 36.84 E
Museum für Moderne Kunst The Museum für Moderne Kunst (MMK) is an art museum in Frankfurt am Main. 50 06 42.56 N 8 41 03.86 E
-Mérida (Spain) 38 54 57 N 6 20 00 W
-Möja kyrka 59 24 18.8 N 18 52 53 E
-Mössingen 48 24 23 N 9 03 27 E
-Mühlen am Löbauer Wasser 51 12 02.21 N 14 39 21.09 E
Narón Narón is a municipality in the province A Coruña, Galicia, Spain. 43 32 14.91 N 8 10 53.28 W
+Naturschutzgebiet âKönigsbrücker Heideâ 51 20 07.58 N 13 52 06.67 E
Necrópole MegalÃtica da Lameira de Cima Necrópole MegalÃtica da Lameira de Cima, freguesia de Antas, Penedono, Portugal. 40 56 09.92 N 7 20 57.52 W
Neda Neda is a municipality in the province A Coruña, Galicia, Spain. 43 29 58.68 N 8 09 21.51 W
-Nedroma 35 00 47.01 N 1 44 51.12 W
Neues Rathaus München 48 08 16.07 N 11 34 33.35 E
Neues Schloss, Stuttgart 48 46 41 N 9 10 55 E
New Mosque in Istanbul New Mosque (Yeni Cami) in Istanbul 41 01 01.05 N 28 58 19.2 E
Niujie Mosque The Niujie Mosque (Chinese: çè¡æ¸
ç寺; pinyin: niújiÄ qÄ«ngzhÄnsì) is the oldest mosque in Beijing, China. It was built in 996 and completely rebuilt under the Kangxi Emperor (1622-1722). 39 53 04 N 116 21 29 E
Nizza-Ufer The Nizza bank is a park with mild microclimate at the Main river bank in Frankfurt am Main. The Park was constructed in 1860. 50 06 15.68 N 8 40 14.37 E
Noorderplantsoen The Noorderplantsoen is a park in the Dutch city of Groningen. 53 13 25 N 6 33 20 E
+Nordwestbahnhof, Vienna Emergency quarters from Northwest Railway Wagon 13 46.81 N 16 22 58.91 E
+Nulbay Park, Anchorage, Alaska 61 12 57 N 149 54 36 W
Nullamunjie Olive Grove, Victoria Nullamunjie olive groves are situated in the mountains of eastern Victoria, Australia on the slopes of Mount Stawell and near the banks of the Tambo River. 37 11 05 S 147 43 58 E
O Barco de Valdeorras 42 24 38.82 N 6 58 33.51 W
-O Bolo O Bolo is a municipality in Galicia, in the province of Ourense. 42 18 27.11 N 7 05 52.28 W
-O Carballiño 42 25 53.18 N 8 04 38.47 W
-O Grove 42 29 34.29 N 8 52 04.9 W
-O Pereiro de Aguiar O Pereiro de Aguiar is a municipality in Galicia, in the province of Ourense. 42 20 47.83 N 7 48 06.62 W
-O Porriño O Porriño is a municipality in Galicia, Spain in the province of Pontevedra. 42 09 41.84 N 8 37 15 W
-O Rosal O Rosal is a municipality in Galicia, Spain in the province of Pontevedra. 41 56 07.3 N 8 50 05.63 W
-O Ãzaro, DumbrÃa 42 54 38.2 N 9 07 54.12 W
Obermillstatt 46 48 36.91 N 13 35 29.41 E
Obervellach 46 55 55.76 N 13 12 06.68 E
+O Bolo O Bolo is a municipality in Galicia, in the province of Ourense. 42 18 27.11 N 7 05 52.28 W
+O Carballiño 42 25 53.18 N 8 04 38.47 W
Ocean Park, Hong Kong 22 14 45.1 N 114 10 33.3 E
+O Ãzaro, DumbrÃa 42 54 38.2 N 9 07 54.12 W
+O Grove 42 29 34.29 N 8 52 04.9 W
Ohr Somayach Synagogue Ohr Somayach Synagogue, the main synagogue in Odessa, Ukraine 46 28 40.55 N 30 44 22.13 E
Oia Oia is a municipality in Galicia, Spain in the province of Pontevedra. 42 00 06.45 N 8 52 30.54 W
+OÃmbra 41 53 07.94 N 7 28 19.78 W
Oleiros Oleiros is a municipality in the province A Coruña, Galicia, Spain. 43 19 57.16 N 8 18 54.38 W
Oleiros, Ribeira 42 36 11.29 N 9 00 20.52 W
OlgastraÃe (Stuttgart) 48 46 04.17 N 9 10 44.23 E
+O Pereiro de Aguiar O Pereiro de Aguiar is a municipality in Galicia, in the province of Ourense. 42 20 47.83 N 7 48 06.62 W
+O Porriño O Porriño is a municipality in Galicia, Spain in the province of Pontevedra. 42 09 41.84 N 8 37 15 W
Oradour-sur-Glane Oradour-sur-Glane was a village in the Limousin region of Vichy France that came under direct German control in 1942. 45 55 55 N 1 01 54 E
-Oran 35 41 49 N 0 37 59 W
Orangerie (Neustrelitz) Die Orangerie in Neustrelitz wurde bereits 1755 erbaut und erfuhr 1840 bis 1842 einen grundlegenden Umbau durch Friedrich Wilhelm Buttel. 53 21 40 N 13 03 27 E
Organización Médica Colegial de España Spanish Medical Colleges Organization 40 24 57.24 N 3 41 49.49 W
+O Rosal O Rosal is a municipality in Galicia, Spain in the province of Pontevedra. 41 56 07.3 N 8 50 05.63 W
Ortigueira Ortigueira is a municipality in the province A Coruña, Galicia, Spain. 43 41 12.94 N 7 51 10.47 W
Os Blancos Os Blancos is a municipality in Galicia, in the province of Ourense. 41 59 50.61 N 7 45 12.34 W
Ouaisné 49 10 45.75 N 2 11 10.77 W
Oza-Cesuras Oza-Cesuras, municipality in the province of A Coruña, in Galicia (Spain). 43 16 44.24 N 8 12 55.95 W
Ozurgeti Ozurgeti is a town and the regional administrative centre of Western Georgian province of Guria, former Macharadze or Makharadze. 41 55 26.26 N 42 00 33.84 E
-OÃmbra 41 53 07.94 N 7 28 19.78 W
Palace and park of Versailles 48 48 15.85 N 2 07 23.38 E
+Palácio de Estói 37 05 47.79 N 7 53 44.05 W
+Palácio Nacional da Pena 38 47 15.24 N 9 23 25.75 W
+Palácio Nacional de Mafra O Palácio Nacional de Mafra é um palácio e mosteiro monumental de estilo neoclássico localizado em Mafra (Portugal) a poucos mais de 50 quilómetros de Lisboa. 38 56 12 N 9 19 35 W
Palais Brongniart The Palais Brongniart was the site of the Paris Stock Exchange until 1987. 48 52 09.01 N 2 20 26.98 E
Palais de justice de Paris Palais de Justice is a building complex on the Ãle-de-la-Cité in Paris. It was built on the site of the Palais de la Cité, the residence of the Kings of France until the 14th century. 48 51 20.6 N 2 20 42.18 E
Palais de l'Ãlysée 48 52 13 N 2 18 59 E
-Palais des Papes The Palais des Papes in Avignon, France was the residency of popes during the 14th and 15th century. 43 57 02 N 4 48 25 E 43.95068 N 4.80704 E 43.95068 4.80704
+Palais des Papes The Palais des Papes in Avignon, France was the residency of popes during the 14th and 15th century. 43 57 02 N 4 48 25 E
+Palais ducal de Nevers The Palais Ducal in Nevers, France 46 59 18 N 3 09 30 E
Palais du parlement de Bretagne 48 06 46.08 N 1 40 40.01 W
Palais du parlement du Dauphiné 45 11 35.97 N 5 43 42.86 E
Palais du Tau 49 15 11 N 4 02 04 E
-Palais ducal de Nevers The Palais Ducal in Nevers, France 46 59 18 N 3 09 30 E
Palais Garnier The Palais Garnier, also known as Opéra Garnier or Opéra national de Paris is an opera house situated at the northern end of the avenue de l'Opera, in Paris. 48 52 19 N 2 19 54 E
-Palais Granvelle (Besançon) 47 14 08.52 N 6 01 35.76 E
Palais Idéal 45 15 22.85 N 5 01 42.74 E
Palais Longchamp 43 18 15.48 N 5 23 40.2 E
Palais Royal 48 51 52.5 N 2 20 15.1 E
Palmenhaus, Vienna Vienna's Palmenhaus ('palm house', a Jugendstil greenhouse built in 1901) is a building in Vienna's 1st district, beneath 'Burggarten' and Hofburg. 48 12 18 N 16 22 01 E
-Palácio de Estói 37 05 47.79 N 7 53 44.05 W
-Palácio Nacional da Pena 38 47 15.24 N 9 23 25.75 W
-Palácio Nacional de Mafra O Palácio Nacional de Mafra é um palácio e mosteiro monumental de estilo neoclássico localizado em Mafra (Portugal) a poucos mais de 50 quilómetros de Lisboa. 38 56 12 N 9 19 35 W
Pamukkale Pamukkale is a natural site and attraction and a UNESCO World Heritage Site in south-western Turkey. 37 55 25 N 29 07 24 E
Panthéon de Paris 48 50 46 N 2 20 45 E
-Parc Astérix 48 27 21 N 4 35 24 E
+Parc Astérix 49 08 07.08 N 2 34 18.12 E
Parc du Thabor 48 06 51 N 1 40 12 W
-Parc Monceau 48 52 45.84 N 2 18 33.23 E
+Parc Monceau Parc Monceau is a public park situated in the 8th and 17th Arrondissements of Paris at the junction of Boulevard de Courcelles, Rue de Prony and Rue Georges Berger. 48 52 45.84 N 2 18 33.23 E
Parc Natural del Delta de l'Ebre Village 40 42 09 N 0 48 32 E
Paris-Gare de Lyon 48 50 41 N 2 22 25 E
-Emin Pasha Emin Pasha (born Eduard Schnitzer, 1840-1892) was a German explorer of Central Africa. 42 12 40.68 N 20 44 28.26 E
+Passage Canal, Alaska Chugach National Forest, Alaska 60 48 53 N 148 31 28 W
+Penniman Glaciers Chugach National Forest, Alaska 61 05 42 N 148 20 24 W
Petit Palais The Petit Palais is a palace in Paris, France built for the Universal Exhibition in 1900. It now houses the Musée des Beaux-Arts de la Ville de Paris (Paris Museum of Fine Arts). 48 51 57.72 N 2 18 52.39 E
Petuelpark 48 10 39.64 N 11 34 45.32 E
Petuelring The Petuelring is a street in Munich, part of the Mittlerer Ring around the city centre. 48 10 40.25 N 11 34 19 E
Petueltunnel The Petueltunnel is a tunnel that runs beneath the Petuelring between the Boroughs Milbertshofen-Am Hart and Schwabing-West in Munich. 48 10 39.9 N 11 34 37.48 E
+Pfaffendorf (Rietz-Neuendorf) 52 15 57.79 N 14 09 46.25 E
+Pfarrkirche St. Bartholomäus in Friesach 46 57 04.28 N 14 24 18.19 E
Phare de Chassiron 46 02 48.12 N 1 24 37.01 W
Philadelphia City Hall Philadelphia City Hall is the seat of government for the city of Philadelphia, Pennsylvania. 39 57 08.28 N 75 09 48.96 W
Piazza Corvetto (Genova) Piazza Corvetto è una delle principali piazze di Genova 44 24 36.1 N 8 56 18.2 E
@@ -588,158 +738,182 @@ Piazza delle Erbe (Verona) 45 26 36.74 N 10 59 48.53 E
Piazza Navona Piazza Navona is a square in Parione, the VI. Rione (district) from Rome, Italy. 41 53 56.21 N 12 28 23.15 E
Piazza Venezia Piazza Venezia is Located in Rome. 41 53 47 N 12 28 57 E
Pieve di San Giorgio di Valpolicella The Pieve di San Giorgio di Valpolicella is a particularly large and elaborate Pieve (ancient church) of the city of Sant'Ambrogio di Valpolicella, Italy. 45 32 07 N 10 51 00 E
-Piode Piode è un comune della Valsesia, in provincia di Vercelli, Piemonte, Italia. 45 46 09.98 N 8 02 57.28 E
+Pigot Glacier Chugach National Forest, Alaska 60 54 12 N 148 28 44 W
Piñor Piñor is a municipality in Galicia, in the province of Ourense. 42 29 50.69 N 8 00 21.39 W
-Place de la Concorde The Place de la Concorde is one of the major public squares in Paris, France. 48 51 56 N 2 19 16 E
+Piode Piode è un comune della Valsesia, in provincia di Vercelli, Piemonte, Italia. 45 46 09.98 N 8 02 57.28 E
+Plaça Catalunya Plaça Catalunya (or Plaza de Cataluña in spanish) is a large square in central Barcelona. 41 23 13.21 N 2 10 12.09 E
+Place de la Concorde The Place de la Concorde is one of the major public squares in Paris, France. 48 51 56.16 N 2 19 15.96 E
Place des Vosges Place des Vosges in Paris, France 48 51 20 N 2 21 56 E
+Placer River Valley Kenai Peninsula, Alaska 60 49 25 N 148 59 47 W
Plaridel Airport 14 53 27.91 N 120 51 09.9 E
-Plaça Catalunya Plaça Catalunya (or Plaza de Cataluña in spanish) is a large square in central Barcelona. 41 23 13.21 N 2 10 12.09 E
Pont Ambroix The Pont Ambroix was a Roman bridge across the Vidourle in Gallargues-le-Montueux, Gard department, and Villetelle, Hérault department, both Languedoc-Roussillon, France. 43 43 02 N 4 09 07 E
Pont Camille-de-Hogues 46 48 49.12 N 0 32 15.32 E
Pont de la Concorde 48 51 47.99 N 2 19 09.98 E
Pont du Gard The Pont du Gard is a Roman aqueduct bridge near Nîmes, France. 43 56 50.28 N 4 32 07.8 E
-Pont Flavien The Pont Flavien is a Roman bridge in Saint-Chamas, Bouches-du-Rhône department, Provence-Alpes-Côte d'Azur, France. 43 32 29 N 5 02 35 E
-Pont Julien The Pont Julien is a Roman bridge near Bonnieux, Vaucluse department, Provence-Alpes-Côte dâAzur, France. 43 51 45 N 5 18 28 E
-Pont Neuf 48 51 26.81 N 2 20 29.82 E
-Pont sur la Laye Roadway 43 55 48 N 5 45 23 E
Ponte de Rande The Rande Bridge is a cable-stayed bridge near Vigo, Galicia, Spain. 42 17 18.66 N 8 39 37.45 W
-Ponte Sant'Angelo (Rome) The Ponte Sant'Angelo is a Roman bridge across the Tiber in Rome, Italy. 41 54 06.46 N 12 27 59.24 E
Pontedeume 43 24 13.68 N 8 09 46.85 W
+Ponte Sant'Angelo (Rome) The Ponte Sant'Angelo is a Roman bridge across the Tiber in Rome, Italy. 41 54 06.46 N 12 27 59.24 E
Pontevedra 42 25 50.84 N 8 38 56.27 W
+Pont Flavien The Pont Flavien is a Roman bridge in Saint-Chamas, Bouches-du-Rhône department, Provence-Alpes-Côte d'Azur, France. 43 32 29 N 5 02 35 E
+Pont Julien The Pont Julien is a Roman bridge near Bonnieux, Vaucluse department, Provence-Alpes-Côte dâAzur, France. 43 51 45 N 5 18 28 E
+Pont Neuf 48 51 26.81 N 2 20 29.82 E
+Pont sur la Laye The Pont sur la Laye is an old bridge across the Laye near Mane, Alpes-de-Haute-Provence department, Provence, France. 43 55 48 N 5 45 23.04 E
Pordoi Pass The Pordoi Pass is an Alpine pass in the Dolomites. 46 29 19.33 N 11 48 52.54 E
-Port of Kobe Port of Kobe in Kobe, HyÅgo Prefecture, Japan 34 40 39.17 N 135 13 36.97 E
Porta Pia 41 54 33 N 12 30 04 E
Porta san Sebastiano 41 52 25 N 12 30 07 E
Porta Soprana (Genova) Porta Soprana a Genova. 44 24 19.76 N 8 56 05.6 E
Porta Westfalica 52 14 22.66 N 8 55 14.31 E
Porto antico di Genova 44 24 34.22 N 8 55 04.26 E
Porto Azzurro 42 46 05.02 N 10 23 48.33 E
+Port of Kobe Port of Kobe in Kobe, HyÅgo Prefecture, Japan 34 40 39.17 N 135 13 36.97 E
Portor, Negreira 42 54 45.44 N 8 41 52.17 W
Potemkin Stairs 46 29 18.75 N 30 44 31.18 E
+Potter Marsh Anchorage 61 04 39 N 149 49 37 W
Praia de Cabanas 43 24 55.21 N 8 10 23.62 W
Prinzenbau Stuttgart 48 46 38.55 N 9 10 40.96 E
Promenade du Peyrou 43 36 40 N 3 52 15 E
Prytanée national militaire 47 42 10.09 N 0 04 35.77 W
-Puerto de Navacerrada 40 47 19.04 N 4 00 13.23 W
+Puerto de Navacerrada El puerto de Navacerrada es un puerto de montaña a 1858 msnm de altitud, que alberga una estación de esquà y que está situado en la sierra de Guadarrama (Sistema Central). 40 47 19.04 N 4 00 13.23 W
Puits Arthur-de-Buyer 47 40 37.23 N 6 36 51.29 E
Punta Manara Manara Bivouac 44 15 19.08 N 9 24 20.88 E
PunxÃn PunxÃn is a municipality in Galicia, in the province of Ourense. 42 22 06.15 N 8 00 03.16 W
Quartier de Beaugrenelle 48 51 03.87 N 2 17 07.61 E
+Radweg Arnsdorf-Guteborn 51 25 49.66 N 13 53 18.08 E
+Rainy Glacier Chugach National Forest, Alaska 60 38 39 N 148 32 37 W
Rairiz de Veiga 42 04 57.65 N 7 49 56.92 W
Ravensberger Bahn Die Ravensberger Bahn ist eine Eisenbahnstrecke von Bielefeld nach Rahden. 52 13 36.48 N 8 31 20.75 E
Regattastrecke OberschleiÃheim Die Regattastrecke OberschleiÃheim ist ein künstlicher, rechteckiger Grundwassersee im Norden von München, angelegt für die Olympischen Sommerspiele 1972. 48 14 33.67 N 11 30 54.38 E
Reggia di Caserta La Reggia di Caserta, Palazzo Reale, è stata la dimora della dinastia dei Borboni, sovrani del Regno delle due Sicilie. à situata a Caserta, in Campania (Italia). 41 04 26.27 N 14 19 36.92 E
Reservoir in Stara Morawa Reservoir in Stara Morawa near Stronie ÅlÄ
skie (Lower Silesian Voivodeship, Poland) 50 16 31.15 N 16 52 47.84 E
+Resurrection Peninsula Kenai Peninsula, Alaska 59 56 53 N 149 16 41 W
Rianxo Rianxo is a port town in Galicia, Spain, in the province of A Coruña. 42 38 38.62 N 8 48 44.67 W
Ribadavia 42 17 13.06 N 8 08 34.54 W
Ribadumia Ribadumia is a municipality in Galicia, Spain in the province of Pontevedra. 42 30 50.38 N 8 45 25.68 W
-Ribeira Ribeira is a municipality in the province A Coruña, Galicia, Spain. 42 32 38.31 N 9 00 06.92 W
Ribeira, Ribeira 42 33 16.32 N 8 59 27.37 W
+Ribeira Ribeira is a municipality in the province A Coruña, Galicia, Spain. 42 32 38.31 N 9 00 06.92 W
Ricetto di Candelo 45 32 46.68 N 8 06 48.96 E
Rio Marina Rio Marina is a village in Isola d'Elba Toscana in Italy 42 48 44.2 N 10 25 39.87 E
-Risiera di San Sabba La Risiera di San Sabba è stato un campo di concentramento nazista, attivo negli ultimi anni della seconda guerra mondiale a Trieste, Italia. 45 37 26.09 N 13 47 22.1 E
Riós Riós is a municipality in Galicia, in the province of Ourense. 41 58 29.53 N 7 16 55.68 W
+RÃo Tambre 42 54 20.32 N 8 41 43.21 W
+Risiera di San Sabba La Risiera di San Sabba è stato un campo di concentramento nazista, attivo negli ultimi anni della seconda guerra mondiale a Trieste, Italia. 45 37 26.09 N 13 47 22.1 E
Robben Island Robben Island, Cape Town, South Africa 33 48 24.24 S 18 21 58.4 E
Rocca Grimalda Rocca Grimalda è un comune dell'Alto Monferrato, in provincia di Alessandria, Piemonte, Italia. 44 40 17.48 N 8 38 55.11 E
Rodeiro Rodeiro is a municipality in Galicia, Spain in the province of Pontevedra. 42 39 00.44 N 7 56 59.94 W
Roman Bridge (Saint-Thibéry) Old mill nearby 43 23 34.39 N 3 25 58.21 E
Roman Bridge (Vaison-la-Romaine) The Roman Bridge at Vaison-la-Romaine is a bridge across the Ouvèze in the Vaucluse department, Provence, France. 44 14 20.3 N 5 04 28.7 E
Roman Theatre of Catania 37 30 10.4 N 15 05 00.9 E
-Roujan 43 30 32.5 N 3 17 15.15 E
-RÃo Tambre 42 54 20.32 N 8 41 43.21 W
+Roujan Roujan is a commune of the Hérault département in the Region of Languedoc-Roussillon - France. 43 30 32.5 N 3 17 15.15 E
+Rudyerd Bay Borough di Ketchikan Gateway, Alaska 55 35 23 N 130 44 45 W
+Ruhlsdorf (Teltow) Former town hall 52 22 28.71 N 13 16 04.56 E
+Russian Jack Springs Park, Anchorage, Alaska 61 12 21 N 149 47 18 W
Sacrario Militare di Redipuglia 45 51 05.58 N 13 29 22.49 E
Sada Sada is a municipality in the province A Coruña, Galicia, Spain. 43 21 01.43 N 8 15 16.23 W
-Safranbolu Safranbolu is a city and World Heritage site of Karabük Province, Turkey. 41 14 41 N 32 41 37 E
-Sagrada FamÃlia 41 24 12.82 N 2 10 27.64 E
-Ãglise Saint-Gervais-Saint-Protais 48 51 19.8 N 2 21 16.6 E
-Saint-Michel de Nahuze Prieuré du XIe siècle, situé sur la commune de Lagrasse (département de l'Aude), dont les ruines ont été inscrites comme monument historique 43 07 56.82 N 2 37 06.38 E
-Saint-Nazaire-de-Ladarez 43 30 37 N 3 04 36 E
+Safranbolu Safranbolu is a city and district of Karabük Province, Turkey. 41 14 41 N 32 41 37 E
+Sagrada FamÃlia 41 24 13 N 2 10 27.05 E
Sainte-Chapelle 48 51 20 N 2 20 41 E
-Château de Saissac The Château de Saissac is a Cathar castle in the Saissac commune, Aude département of France. 43 21 25 N 2 10 04.7 E
-Salt Lake Temple The Salt Lake Temple, the sixth temple built by the church overall, and the fourth operating temple, is the largest and best-known temple of The Church of Jesus Christ of Latter-day Saints. 40 46 14.45 N 111 53 31.18 W
+Saint-Michel de Nahuze Prieuré du XIe siècle, situé sur la commune de Lagrasse (département de l'Aude), dont les ruines ont été inscrites comme monument historique 43 07 56.82 N 2 37 06.38 E
+Saint-Nazaire-de-Ladarez Saint-Nazaire-de-Ladarez is a commune of the Hérault département, France. 43 30 37 N 3 04 36 E
+Salt Lake Temple The Salt Lake Temple, the sixth temple built by the church overall, and the fourth operating temple, is the largest and best-known temple of The Church of Jesus Christ of Latter-day Saints. 40 46 13.69 N 111 53 31.06 W
San Amaro San Amaro is a municipality in Galicia, in the province of Ourense. 42 22 20.07 N 8 04 23.65 W
San Clodio, Leiro 42 22 02.61 N 8 06 54.12 W
San Cristovo de Cea San Cristovo de Cea is a municipality in Galicia, in the province of Ourense. 42 28 33.22 N 7 59 07.24 W
+Sandiás Sandiás is a municipality in Galicia, in the province of Ourense. 42 06 38.53 N 7 45 28.41 W
San Giorgio in Lemine San Giorgio in Lemine is a church in the comune of Almenno San Salvatore, Bergamo, Lombardy, Italy 45 44 46 N 9 35 50 E
+Sankt Martini 53 04 30 N 8 48 15 E
San Marco (Milan) 45 28 23.77 N 9 11 20 E
San Sadurniño San Sadurniño is a municipality of Spain in the province of A Coruña, in the autonomous community of Galicia. 43 33 44.93 N 8 03 17.21 W
-Sandiás Sandiás is a municipality in Galicia, in the province of Ourense. 42 06 38.53 N 7 45 28.41 W
-Sankt Martini 53 04 30 N 8 48 15 E
-Sant'Anastasia Sant'Anastasia è una chiesa di Roma. 41 53 17.6 N 12 29 03 E
Santa Maria degli Scalzi (Venice) 45 26 29.4 N 12 19 19.56 E
Santa Maria dei Servi (Padua) 45 24 16.56 N 11 52 32.63 E
+Sant'Anastasia Sant'Anastasia è una chiesa di Roma. 41 53 17.6 N 12 29 03 E
Santiago de Chile Santiago is the capital of Chile, it is also the country's industrial and commercial center. 33 27 00 S 70 40 00 W
Sanxenxo 42 24 19.2 N 8 48 23.66 W
Sarreaus 42 05 13.93 N 7 36 10.99 W
Sarria 42 46 38.13 N 7 24 54.31 W
Schallenberg 46 49 34 N 7 47 50 E
SchenkendorfstraÃe The SchenkendorfstraÃe is a street in Munich, part of the Mittlerer Ring around the city centre. 48 10 34.21 N 11 35 29.04 E
+Schenkenhorst (Stahnsdorf) Former town hall 52 20 28.05 N 13 11 46.85 E
Schloss Eutin The Castle of Eutin is located in Eutin in Schleswig-Holstein. 54 08 15.75 N 10 37 13.22 E
Schloss Hüffe Schloss Hüffe ist ein Ende des 13. Jahrhunderts errichtetes Wasserschloss in der Ortschaft Lashorst der Stadt PreuÃisch Oldendorf im Kreis Minden-Lübbecke. 52 20 05.99 N 8 30 55.72 E
Schloss Kalkum Schloss Kalkum is a water castle in Kalkum in the north of Düsseldorf, about two kilometers northeast of Kaiserwerth. 51 18 14.9 N 6 45 26.7 E
+Schlosskirche (Neustrelitz) Die Neustrelitzer Schlosskirche wurde durch Friedrich Wilhelm Buttel erbaut und ist dessen Hauptwerk in der Stadt. 53 21 35 N 13 03 32 E
Schloss Nymphenburg Nymphenburg Palace is a château in Munich. 48 09 29 N 11 30 13 E
Schloss Petershagen Das Schloss Petershagen in Petershagen ist ein Wasserschloss im Stil der Weserrenaissance. 52 22 46.16 N 8 58 18.62 E
-Schloss Rosenstein 48 48 15 N 9 11 30 E
-Schlosskirche (Neustrelitz) Die Neustrelitzer Schlosskirche wurde durch Friedrich Wilhelm Buttel erbaut und ist dessen Hauptwerk in der Stadt. 53 21 35 N 13 03 32 E
Schlossplatz Stuttgart 48 46 42.81 N 9 10 47.45 E
-Serres d'Auteuil The Jardin des serres d'Auteuil is a botanical garden in the Bois de Boulogne, Paris 16th, located at 3 avenue de la Porte d'Auteuil and 1 avenue Gordon-Bennett. 48 50 49 N 2 15 8 E
+Schloss Rosenstein 48 48 26 N 9 11 22 E
+Schönflieà (Mühlenbecker Land) 52 39 23.04 N 13 20 21.84 E
+Serpentine Glacier Chugach National Forest, Alaska 61 07 41 N 148 16 02 W
+Serres d'Auteuil The Jardin des serres d'Auteuil is a botanical garden in the Bois de Boulogne, Paris 16th, located at 3 avenue de la Porte d'Auteuil and 1 avenue Gordon-Bennett. 48 50 49 N 2 15 8 E
Sestri Levante Sestri Levante is a town in Liguria in Italy. 44 16 17.76 N 9 23 33 E
Shokeda Shokeda is a religious settlement in Israel, in north-west part of Negev, south to Sderot and east to the Gaza Strip. 31 25 19.56 N 34 31 28.2 E
-Sidi Okba 34 45 00 N 5 54 00 E
Sigüeiro, A Barciela, Oroso 42 58 06.42 N 8 26 33.39 W
Silleda 42 41 49.46 N 8 14 50.28 W
Singapore Singapore is a city state at the southern tip of peninsular Malaysia. It is an island approximately 40 by 20 km in size inhabited by more than five million people. 1 18 00 N 103 48 00 E
-Singapore Zoo 1 24 15.9 N 103 47 28.1 E
+Singapore Zoo Singapore Zoo / Mandai Zoo 1 24 15.9 N 103 47 28.1 E
Sistiana Sistiana is a town near Trieste. 45 46 09.98 N 13 38 01.98 E
Sistine Chapel The Sistine Chapel is located in the Vatican and is decorated with frescoes by Michelangelo. 41 54 11 N 12 27 16 E
+Site des missiles Plutons Bourogne-Meroux 47 34 54.94 N 6 54 17.69 E
+Sixmile Creek (Alaska) Kenai Peninsula, Alaska 60 54 18 N 149 25 36 W
Sohland am Rotstein Sohland am Rotstein is a municipality in Saxony, Germany. 51 07 00 N 14 47 00 E
Sopron Sopron (pronounced "shop-ron"; German: Ãdenburg) is a city in Hungary near the Austrian border. 47 41 12 N 16 34 49 E
Spenge Spenge is a northrhine-westphalian town in the administrative district Kreis Herford. 52 08 33.29 N 8 28 59.9 E
Spišský hrad The ruins of Spiš Castle are situated above the town of Spišské Podhradie and the village of Žehra in the Spiš region in eastern Slovakia. 48 59 58.5 N 20 46 03.3 E
-St. Jürgenskirche (Lilienthal) The church of St. Jürgen is in the same named district of Lilienthal in the county of Osterholz in Lower Saxony, Germany. 53 10 36 N 8 48 29 E
-St. Maria in der Kupfergasse St. Maria in der Kupfergasse is a baroque church in Cologne. 50 56 23.2 N 6 57 01.04 E
+Spreenhagen Village Pub 52 20 28.62 N 13 52 50.12 E
+Sputendorf Former town hall 52 20 20.99 N 13 13 11.05 E
+Stadium of Epidaurus 37 35 51.77 N 23 04 27.8 E
+Städtisches Lapidarium Stuttgart 48 46 03.36 N 9 10 04.58 E
Stadtplatz (Steyr) 48 02 20.42 N 14 25 08.89 E
-Stalis 35 17 47.4 N 25 25 25.9 E
+Staffelde 52 43 47.5 N 12 59 23.57 E
+Stalis Stalis is a small resort village on the island of Crete thirty kilometers from the capital Heraklion, located on the north side of the island. 35 17 47.4 N 25 25 25.9 E
+State Bank of Indiana, Terre Haute branch 39 27 55 N 87 24 52.5 W
Stefanskyrkan, Stockholm 59 20 51.38 N 18 03 16.7 E
Steigfriedhof The Steigfriedhof is a cemetery in the Stadtbezirk Bad Cannstatt in Stuttgart. 48 48 41.9 N 9 12 28.95 E
Stift Göttweig Göttweig Abbey is a Benedictine monastery in Lower Austria. 48 22 00.2 N 15 36 45.5 E
+St. Jürgenskirche (Lilienthal) The church of St. Jürgen is in the same named district of Lilienthal in the county of Osterholz in Lower Saxony, Germany. 53 10 36 N 8 48 29 E
+St. Maria in der Kupfergasse St. Maria in der Kupfergasse is a baroque church in Cologne. 50 56 23.2 N 6 57 01.04 E
Stockholms stadshus 59 19 38.57 N 18 03 15.67 E
Stockholms universitet Stockholm University, founded 1878, with about 37,000 students. 59 21 46.68 N 18 03 31.4 E
-Städtisches Lapidarium Stuttgart 48 46 03.36 N 9 10 04.58 E
-Sultanahmet Camii The Sultan Ahmed Mosque (in Turkish Sultanahmet Camii, in English commonly called the Blue Mosque) is a mosque in Istanbul. 41 00 19.3 N 28 58 36.6 E
-Synchrotron Soleil 48 42 33 N 2 08 41 E
+St. Peter und Paul (Grettstadt) 49 59 06.21 N 10 18 44.87 E
Süleymaniye camii The Mosque of Suleiman I in Istanbul. 41 00 58.3 N 28 57 50 E
+Sultanahmet Camii The Sultan Ahmed Mosque (in Turkish Sultanahmet Camii, in English commonly called the Blue Mosque) is a mosque in Istanbul. 41 00 19.39 N 28 58 36.57 E
+Synchrotron Soleil 48 42 33 N 2 08 41 E
Tarancón Tarancón village and municipality in the province of Cuenca, part of the autonomous community of Castile-La Mancha, Spain. 40 00 45.89 N 3 00 14.85 W
Teixido, Cedeira 43 42 36.72 N 7 59 00.44 W
-Villa romana de Tejada The ancient roman villa of La Tejada is an archaeological site from II to V centuries in Quintanilla de la Cueza, Cervatos de la Cueza (Palencia, Spain). 40 58 36 N 4 48 25 W
Templer Cemetery, Jerusalem Jerusalem, German Colony, Emek Refaim street 39 31 45 47.46 N 35 13 08.68 E
Texas State Capitol The Texas State Capitol, located in Downtown Austin, Texas, is the fourth building to serve as the seat of Texas government. 30 16 29 N 97 44 26 W
-The Dormition Cathedral in Odessa 46 28 31.07 N 30 43 55.42 E
-The Spice Bazaar, Istanbul 41 01 00.7 N 28 58 15.13 E
Théâtre municipal de Besançon 47 14 03.84 N 6 01 33.89 E
+The Dormition Cathedral in Odessa 46 28 30.98 N 30 43 54.89 E
+The Spice Bazaar, Istanbul 41 01 00.7 N 28 58 15.13 E
+Thunderbird Falls Chugach Mountains, Alaska 61 26 31 N 149 21 28 W
Tiberias 32 47 20.04 N 35 31 20.28 E
Toblinger Knoten The Toblinger Knoten is a mountain in the Sexten Dolomites in South Tyrol. 46 38 31 N 12 18 29 E
Tomiño Tomiño is a municipality in Galicia, Spain in the province of Pontevedra. 41 59 31.78 N 8 44 32.54 W
Toosa Toosa is a village in Punjab. 30 44 45.31 N 75 41 14.53 E
Topkapı Sarayı İznik tiles: camp of the Mount Arafat 41 00 45.7 N 28 59 03.25 E
-Torre de San Sadurniño 42 30 25 N 8 49 16 W
+Torre de San Sadurniño 42 30 36 N 8 49 12 W
Torre de Vilanova dos Infantes 42 09 58.36 N 7 57 16.62 W
+Torreón dos Andrade 43 24 27.5 N 8 10 19.25 W
Torres de Altamira 42 52 39.02 N 8 41 15.17 W
Torres de Oeste 42 40 35.81 N 8 43 32.46 W
-Torreón dos Andrade 43 24 27.98 N 8 10 17.88 W
-Toshkent 41 18 00 N 69 16 00 E
+Tour de la Chaîne The tour de la Chaîne (XIVth century) is, with the tour Saint-Nicolas and the tour de la Lanterne, one of the three towers located on the seafront of La Rochelle, and one of the two towers that is representative of the city old harbour. 46 09 21.24 N 1 09 15.52 W
+Tour de la Lanterne The tour de la Lanterne (XVth century) is, with the tour Saint-Nicolas and the tour de la Chaîne, one of the three towers located on the seafront of La Rochelle. It was added to the historical monument list of France in 1879. 46 09 20.88 N 1 09 25.42 W
Tour Eiffel 48 51 30 N 2 17 39 E
Tour Goguin 46 59 03.84 N 3 09 19.91 E
+Tour Saint-Jacques Saint-Jacques Tower is located in the IVe arrondissement of Paris. This gothic tower is all that remains of the former church of Saint-Jacques-de-la-Boucherie. 48 51 27.95 N 2 20 55.6 E
+Tour Saint-Nicolas 46 09 20.88 N 1 09 11.99 W
+Trail Glacier, Alaska Kenai Peninsula, Alaska 60 33 14 N 148 54 32 W
Transfiguration Cathedral in Odessa Odessa Cathedral of God's Transfiguration 46 28 59.44 N 30 43 51.75 E
-TrappentreustraÃe The TrappentreustraÃe is a street in Munich, part of the Mittlerer Ring around the city centre. 48 08 12.34 N 11 32 03.84 E
-Trappentreutunnel The Trappentreutunnel is a tunnel that runs beneath the TrappentreustraÃe in the Borough Schwanthalerhöhe in Munich. 48 08 08.78 N 11 32 03.17 E
+TrappentreustraÃe The TrappentreustraÃe is a street in Munich, part of the Mittlerer Ring around the city centre. 48 08 12.48 N 11 32 03.84 E
+Trappentreutunnel The Trappentreutunnel is a tunnel that runs beneath the TrappentreustraÃe in the Borough Schwanthalerhöhe in Munich. 48 08 08.88 N 11 32 03.12 E
Trastevere Restaurant in Via della Lungaretta 41 53 22.54 N 12 28 12.76 E
Travemünde Travemünde is a part of Lübeck in Germany at the Baltic Sea. 53 58 00 N 10 52 00 E
+TÅebechovice pod Orebem TÅebechovice pod Orebem is a town in Czech Republic in Hradec Králové Region 50 12 07 N 15 59 38 E
+Treskow-Platane The Treskow-Platane is a old hybrid plane and natural monument in Berlin-Friedrichsfelde, so called in memorial of Johann Carl Sigismund von Treskow. 52 30 23.69 N 13 31 17.47 E
+Treuners Altstadtmodell The Treuner brothers' Altstadtmodell is a scale model which shows the oldtown of Frankfurt am Main prior to the air-raid damages in 1943 and 1944. The ruin model shows the destroyed old town of Frankfurt in spring 1945. 50 06 35 N 8 40 57 E
Trinitatisfriedhof, Dresden Cemetery âTrinitatisfriedhofâ in Dresden-Johannstadt 51 03 15.08 N 13 46 20.93 E
Twierdza Osowiec Dry moat around the fort No 3 53 27 44 N 22 37 38 E
-TÅebechovice pod Orebem TÅebechovice pod Orebem is a town in Czech Republic in Hradec Králové Region 50 12 07 N 15 59 38 E
Uetersen 53 41 14 N 9 40 09 E
Université Lille Nord de France 50 36 33.38 N 3 08 29.72 E
+University of Alaska Museum of the North Fairbanks, Alaska 64 51 30 N 147 50 32 W
Upper Darby, Pennsylvania 39 57 40.2 N 75 15 32.06 W
Urgnano 45 35 50 N 9 41 42 E
Valdoviño Valdoviño is a municipality in the province A Coruña, Galicia, Spain. 43 36 32.23 N 8 08 30.84 W
@@ -750,9 +924,9 @@ Varigotti Varigotti è una frazione del comune di Finale Ligure, in provincia di
Verducido, Pontevedra 42 28 35.96 N 8 37 06.66 W
VerÃn VerÃn is a municipality in Galicia, in the province of Ourense. 41 56 22.47 N 7 26 19.59 W
Via dell'Amore (Cinque Terre) The Via dell'Amore (=way of love) is a hiking path above the sea linking the villages of Riomaggiore and Manarola in the Cinque Terre (Liguria, Italia). 44 06 06.07 N 9 44 00.37 E
+Via Dolorosa signs third fall of Jesus (not in the Gospels). 31 46 46.48 N 35 13 56.63 E
Viana do Bolo 42 10 46.42 N 7 06 44.81 W
Vieilles prisons d'Annecy Ancient Jails or the Palais de l'Ãle of Annecy. 45 53 54.89 N 6 07 36.59 E
-Vigo Vigo is a Spanish municipality and the largest city in Galicia. 42 14 00.05 N 8 42 37.59 W
VilagarcÃa de Arousa 42 35 33.08 N 8 46 36.13 W
VilamarÃn VilamarÃn is a municipality in Galicia, in the province of Ourense. 42 27 51.29 N 7 53 23.64 W
Vilanova de Arousa Vilanova de Arousa is a municipality in Galicia, Spain in the province of Pontevedra. 42 33 48.42 N 8 49 26.69 W
@@ -764,203 +938,81 @@ Vilassar de Mar Vilassar de Mar is a village in the county of the Maresme, Catal
Villa Berg 48 47 31.34 N 9 12 27.17 E
Villa d'Este (Tivoli) The Villa d'Este in Tivoli is a masterpiece of Italian architecture and garden design. 41 57 45 N 12 47 46 E
Villa Ephrussi de Rothschild 43 41 48 N 7 19 42.5 E
-Villa Les Glycines 48 40 46 N 6 10 56 E
-Villa Majorelle 48 41 8 N 6 9 50 E
-Villa Schneider Villa Schneider è un palazzo storico di Biella (Piemonte, Italia), servito come quartier generale delle SS durante la seconda guerra mondiale. 45 33 49.52 N 8 03 04.87 E
Village Vanguard The Village Vanguard is a jazzclub in Greenwich Village (New York City). 40 44 09.64 N 74 00 05.81 W
+Villa Les Glycines Villa Les Glycines (1902-1904) 48 40 46 N 6 10 56 E
+Villa Majorelle 48 41 8 N 6 9 50 E
+Villa romana de Tejada The ancient roman villa of La Tejada is an archaeological site from II to V centuries in Quintanilla de la Cueza, Cervatos de la Cueza (Palencia, Spain). 40 58 36 N 4 48 25 W
+Villa Schneider Villa Schneider è un palazzo storico di Biella (Piemonte, Italia), servito come quartier generale delle SS durante la seconda guerra mondiale. 45 33 49.52 N 8 03 04.87 E
Villeneuve-d'Ascq Villeneuve-d'Ascq is a commune within Lille Metropolis, in northern France 50 37 24 N 3 08 42 E
Walhalla, Victoria 37 56 37.43 S 146 27 02.75 E
Walt Disney Concert Hall 34 03 19.36 N 118 14 59.61 W
Wayside Cross VillenstraÃe, Bonn-Dottendorf 50 42 15.73 N 7 06 43.18 E
Weckschnapp 50 56 57.48 N 6 57 55.5 E
+Westchester Lagoon, Anchorage, Alaska 61 12 16 N 149 54 58 W
West Lake 30 15 00 N 120 09 00 E
Whitemarsh Hall 40 04 42 N 75 07 44 W
Wilhelmsstift Tübingen 48 31 16.19 N 9 03 18.53 E
Woodlawn Cemetery (Bronx) Gate on Jerome Avenue 40 53 30 N 73 52 12 W
-Xinzo de Limia Xinzo de Limia is a municipality in Galicia, in the province of Ourense. 42 03 36 N 7 43 19.87 W
XÃ bia XÃ bia is a village in the province of Alicante. 38 47 21 N 0 09 47 E
+Xinzo de Limia Xinzo de Limia is a municipality in Galicia, in the province of Ourense. 42 03 36 N 7 43 19.87 W
Yad Vashem 31 46 23.55 N 35 10 29.2 E
-Yao Yao (å
«å°¾å¸, Yao-shi) is a city in Osaka, Japan. 34 37 36.9 N 135 36 03 E
+Yao Yao (å
«å°¾å¸, Yao-shi) is a city in Osaka, Japan. 34 37 36.9 N 135 36 03 E
Zwehrenturm The Zwehrenturm from 1330 is a remain of Kassel's medieval defensive wall. 51 18 49 N 9 29 54 E
-ÃuÃerer Plauenscher Friedhof Cemetery âÃuÃerer Plauenscher Friedhofâ in Dresden-Plauen 51 01 11.89 N 13 42 26.03 E
-Ãcole centrale de Lille Ãcole Centrale de Lille is a graduate engineering school located in campus Lille I within Université Lille Nord de France. 50 36 21.62 N 3 08 13.63 E
-Ãglise de l'Assomption simultanée (La Petite-Pierre) 48 51 25.2 N 7 18 55.84 E
-Ãglise de la Sainte-Trinité (Lauterbourg) 48 58 30.1 N 8 10 40.77 E
-Ãglise de Saint-Lothain 46 49 27.84 N 5 38 30.12 E
-Ãglise de Saint-Paul de Frontignan 43 26 50.47 N 3 45 18.66 E
-Ãglise des Augustins (Ribeauvillé) 48 11 43.44 N 7 19 08.87 E
-Ãglise des Jésuites (Molsheim) 48 32 25.3 N 7 29 45 E
-Ãglise des Saints-Innocents (Blienschwiller) 48 20 25.8 N 7 25 06.17 E
-Ãglise Notre-Dame (Guebwiller) 47 54 20.75 N 7 12 52.56 E
-Ãglise Notre-Dame de la Dalbade 43 35 51.36 N 1 26 32.89 E
-Ãglise Notre-Dame-de-l'Assomption (Bergheim) 48 12 18 N 7 21 53.28 E
-Ãglise Notre-Dame-de-l'Assomption (Bernardswiller) 48 27 10.08 N 7 27 49.57 E
-Ãglise Notre-Dame-de-l'Assomption (Monswiller) 48 45 17.61 N 7 22 39.66 E
-Ãglise Notre-Dame-de-l'Assomption (Rosenwiller) 48 30 21.96 N 7 26 25.48 E
-Ãglise Notre-Dame-de-l'Assomption (Rouffach) 47 57 24 N 7 18 02 E
-Ãglise Notre-Dame-de-la-Nativité (Saverne) 48 44 28.32 N 7 21 50.36 E
-Ãglise protestante (Balbronn) 48 35 05.28 N 7 26 15.97 E
-Ãglise protestante (Baldenheim) 48 14 15 N 7 32 14.35 E
-Ãglise protestante (Berg) 48 53 52.08 N 7 09 24.01 E
-Ãglise protestante (Bischheim) 48 36 55.08 N 7 45 21.89 E
-Ãglise protestante (Fouday) 48 25 17.76 N 7 11 12.95 E
-Ãglise protestante (Harskirchen) 48 56 02.04 N 7 02 20.15 E
-Ãglise protestante (Scharrachbergheim) 48 35 35.52 N 7 29 55.9 E
-Ãglise protestante (Schiltigheim) 48 36 21.96 N 7 45 05.04 E
-Ãglise protestante (Weiterswiller) 48 51 10.44 N 7 24 50.9 E
-Ãglise protestante du Temple Neuf (Strasbourg) 48 35 00 N 7 44 54 E
-Ãglise Saint-Eustache de Paris 48 51 48 N 2 20 42 E
-Ãglise Saint-Laurent (Paris) 48 52 29.45 N 2 21 29.92 E
-Ãglise Saint-Michel d'Ernolsheim-lès-Saverne Bells 48 47 27.85 N 7 22 47.57 E
-Ãglise Saint-Nicolas-du-Chardonnet St. Nicolas du Chardonnet is a church in the centre of Paris, France located in the 5th arrondissement. 48 50 57 N 2 21 01 E
-Ãglise Saint-Pierre de Montmartre Saint-Pierre de Montmartre is a church in Paris 48 53 12 N 2 20 31 E
-Ãglise Saint-Pierre-de-Rhèdes 43 35 16.22 N 3 04 43.64 E
-Ãglise Saint-Pierre-Saint-Paul de Rueil-Malmaison 48 52 35.4 N 2 10 53.15 E
-Ãglise Saint-Sulpice 48 51 04 N 2 20 05 E
-Ãglise Saint-Ãtienne-du-Mont Saint-Ãtienne-du-Mont church is located in Paris, nearby Panthéon. 48 50 47 N 2 20 52 E
-Ãglise Sainte-Marie-Madeleine de Rennes-le-Château 42 55 41.05 N 2 15 45.69 E
-Ãglise Saints-Pierre-et-Paul (Andlau) 48 23 16.3 N 7 24 54.3 E
-Ãglise Saints-Pierre-et-Paul (Eguisheim) 48 02 32.28 N 7 18 21.2 E
-Ãglise Saints-Pierre-et-Paul (Hohatzenheim) 48 42 44.64 N 7 36 59.11 E
-Ãglise Saints-Pierre-et-Paul (Neuwiller-lès-Saverne) 48 49 25 N 7 24 20 E
-Ãglise Saints-Pierre-et-Paul (Obernai) 48 27 47.88 N 7 28 54.48 E
-Ãglise Saints-Pierre-et-Paul (Ottmarsheim) 47 47 13.2 N 7 30 25.2 E
-Ãglise Saints-Pierre-et-Paul (Rosheim) 48 29 48 N 7 28 14 E
-Ãglise Saints-Pierre-et-Paul (Sigolsheim) 48 08 04.2 N 7 18 03.1 E
-Ãglise Saints-Pierre-et-Paul (Wissembourg) 49 02 14 N 7 56 30 E
-Ãglise St Antoine de Padoue (Saverne) The cloister 48 44 29.4 N 7 21 40.82 E
-Ãglise St Arbogast (Offenheim) 48 37 53.76 N 7 36 59.54 E
-Ãglise St Barthélemy (Sarrewerden) 48 55 22.8 N 7 04 56.93 E
-Ãglise St Benoît (Bergholtzzell) 47 55 51.34 N 7 13 54.48 E
-Ãglise St Blaise (Valff) 48 25 12.36 N 7 31 06.96 E
-Ãglise St Cyriaque (Altorf) 48 31 22.7 N 7 31 50 E
-Ãglise St Gall (Niedermorschwihr) 48 05 57.84 N 7 16 26.47 E
-Ãglise St Gall protestante (Domfessel) 48 57 06.48 N 7 09 07.56 E
-Ãglise St Georges (Châtenois) 48 16 09.12 N 7 23 51 E
-Ãglise St Georges (Sélestat) 48 15 36 N 7 27 24.12 E
-Ãglise St Grégoire (Ribeauvillé) 48 11 49.2 N 7 19 00.41 E
-Ãglise St Guillaume protestante (Strasbourg) 48 34 55.5 N 7 45 28 E
-Ãglise St Hippolyte (Saint-Hippolyte) 48 14 01.68 N 7 22 04.01 E
-Ãglise St Jacques-le-Majeur (Kuttolsheim) 48 38 37.32 N 7 31 41.34 E
-Ãglise St Jacques-le-Majeur simultanée (Dettwiller) 48 45 12.6 N 7 27 56.77 E
-Ãglise St Jacques-le-Majeur simultanée (Hunawihr) 48 10 42.24 N 7 18 38.02 E
-Ãglise St Jean (Strasbourg) 48 35 04 N 7 44 25 E
-Ãglise St Jean protestante (Wissembourg) 49 02 18.96 N 7 56 33.36 E
-Ãglise St Jean-Baptiste (Saint-Jean-Saverne) 48 46 18.7 N 7 21 48.5 E
-Ãglise St Jean-Baptiste (Surbourg) 48 54 34.2 N 7 50 50.28 E
-Ãglise St Jean-Baptiste (Wattwiller) 47 50 07.72 N 7 10 37.27 E
-Ãglise St Jean-Baptiste simultanée (Hohwiller) 48 45 12.78 N 7 27 56.77 E
-Ãglise St Laurent (Dieffenbach-au-Val) 48 18 44.64 N 7 19 41.34 E
-Ãglise St Laurent protestante (Dorlisheim) 48 31 30 N 7 29 13.99 E
-Ãglise St Léger (Guebwiller) 47 54 42.1 N 7 12 33.75 E
-Ãglise St Léger (Murbach) 47 55 24 N 7 09 29 E
-Ãglise St Martin (Ammerschwihr) 48 07 37.92 N 7 16 54.01 E
-Ãglise St Martin (Ebersheim) 48 18 14.04 N 7 30 14.08 E
-Ãglise St Martin (Pfaffenheim) 47 59 05.28 N 7 17 08.59 E
-Ãglise St Martin protestante (Barr) 48 24 33.84 N 7 26 51.47 E
-Ãglise St Martin protestante (Westhoffen) 48 36 01.8 N 7 26 30.3 E
-Ãglise St Maurice (Ebersmunster) 48 18 39.5 N 7 31 37 E
-Ãglise St Maurice (Fegersheim) 48 29 23.64 N 7 40 50.27 E
-Ãglise St Maurice (Orschwiller) 48 14 27.24 N 7 22 44.62 E
-Ãglise St Maurice (Soultz-Haut-Rhin) 47 53 13.2 N 7 13 48.29 E
-Ãglise St Maurice (Soultz-les-Bains) 48 34 17.4 N 7 29 09.35 E
-Ãglise St Maurice (Willgottheim) 48 40 14.52 N 7 30 33.23 E
-Ãglise St Michel (Reichshoffen) 48 55 54.84 N 7 39 52.02 E
-Ãglise St Michel (Weyersheim) 48 43 06.24 N 7 48 07.96 E
-Ãglise St Médard (BÅrsch) 48 28 40.44 N 7 26 24.4 E
-Ãglise St Nicolas (Haguenau) 48 49 13 N 7 47 32 E
-Ãglise St Nicolas (Neuve-Ãglise) 48 19 50.88 N 7 18 48.24 E
-Ãglise St Nicolas (Wingersheim) 48 43 18.84 N 7 38 08.02 E
-Ãglise St Pantaléon (Gueberschwihr) 48 00 16.92 N 7 16 29.78 E
-Ãglise St Paul protestante (Strasbourg) 48 35 11 N 7 45 35 E
-Ãglise St Pierre "Dompeter" (Molsheim, Avolsheim) 48 33 24.12 N 7 30 19.59 E
-Ãglise St Pierre le Jeune catholique (Strasbourg) 48 35 18.35 N 7 44 55.75 E
-Ãglise St Pierre le Jeune protestante (Strasbourg) 48 35 08 N 7 44 47 E
-Ãglise St Rémi (Itterswiller) 48 21 51.48 N 7 25 37.42 E
-Ãglise St Sébastien (Soultzmatt) 47 57 37.08 N 7 14 15.36 E
-Ãglise St Thomas protestante (Strasbourg) 48 34 47 N 7 44 44 E
-Ãglise St Trophime (Eschau) 48 29 25.08 N 7 42 57.96 E
-Ãglise St Ulrich (Altenstadt) 49 01 49.8 N 7 58 05.88 E
-Ãglise St Ulrich (Wittersheim) 48 46 53.04 N 7 39 27.47 E
-Ãglise St Ãtienne (Rosheim) 48 29 43.8 N 7 27 59.72 E
-Ãglise St Ãtienne (Seltz) 48 53 37.32 N 8 06 28.44 E
-Ãglise St Ãtienne simultanée (Wangen) 48 37 01.56 N 7 27 53.68 E
-Ãglise Ste Anne (Turckheim) 48 05 15.72 N 7 16 41.12 E
-Ãglise Ste Aurélie protestante (Strasbourg) 48 34 53 N 7 44 00 E
-Ãglise Ste Colombe (Hattstatt) 48 00 44.28 N 7 18 06.01 E
-Ãglise Ste Croix (Kaysersberg) Lamentation of Christ 48 08 20.04 N 7 15 48.56 E
-Ãglise Ste Croix (Rountzenheim) 48 49 08.76 N 8 00 26.39 E
-Ãglise Ste Foy (Sélestat) 48 15 33.67 N 7 27 21.81 E
-Ãglise Ste Lucie (Niederhergheim) 47 59 10.32 N 7 23 48.41 E
-Ãglise Ste Madeleine (Strasbourg) 48 34 48 N 7 45 17 E
-Ãglise Ste Marguerite (Geispolsheim) 48 30 50.4 N 7 38 36.06 E
-Ãglise Ste Odile (Lapoutroie) 48 09 08.64 N 7 10 03.97 E
-Ãglise Ste Odile (Wintzfelden) 47 58 32.88 N 7 11 49.92 E
-Ãglise Ste Walburge (Walbourg) 48 53 05.51 N 7 47 21.97 E
-Ãglises St Pierre le Vieux (Strasbourg) 48 34 58 N 7 44 24 E
-Äình Bảng Bảng Communal House (Äình Bảng in Vietnamese) is one of largest and finest village communal houses in Viá»t Nam. It is located in Äình Bảng commune, Từ SÆ¡n district, Bắc Ninh province. 21 06 29.99 N 105 57 06.31 E
-ÐÑÑ
ангелÑÑк 64 33 00 N 40 32 00 E
-ÐÑÑана 51 11 00 N 71 24 00 E
-ÐÑÑÑаÑ
Ð°Ð½Ñ 46 20 00 N 48 01 00 E
-ÐаÑнаÑл 53 21 24 N 83 47 14 E
-ÐоÑовÑк Borovsk 55 12 27.19 N 36 29 05.05 E
-ÐÑÑанбе 38 34 23 N 68 47 11 E
-ÐкаÑеÑинбÑÑг 59 57 00 N 30 19 00 E
-ÐоÑква 55 45 21 N 37 37 04 E
-Ðижний ÐовгоÑод 56 19 37 N 44 00 27 E
-СанкÑ-ÐеÑеÑбÑÑг 59 57 00 N 30 19 00 E
-СевеÑодвинÑк 64 34 00 N 39 51 00 E
-à¸à¸£à¸¸à¸à¹à¸à¸à¸¡à¸«à¸²à¸à¸à¸£ Bangkok 13 45 00 N 100 31 00 E
+ÐÑÑ
ангелÑÑк 3 64 33 00 N 40 31 48 E
+ÐÑÑана 1 51 07 48 N 71 25 48 E
+ÐÑÑÑаÑ
Ð°Ð½Ñ 46 19 59.88 N 48 01 00.12 E
+ÐоÑовÑк 55 12 27.19 N 36 29 05.05 E
+ÐÑÑанбе Dushanbe is the capital city of Tajikistan. 38 34 23.16 N 68 47 11.04 E
+ÐкаÑеÑинбÑÑг 56 49 59.88 N 60 34 59.88 E
+ÐоÑква 55 45 20.88 N 37 37 04.08 E
+Ðижний ÐовгоÑод 56 19 36.84 N 44 00 27 E
+СанкÑ-ÐеÑеÑбÑÑг 59 57 00 N 30 19 12 E
á¡ááá¢ááªá®ááááá 41 50 31 N 44 43 16 E
á¯ááá á 41 30 06.84 N 44 26 24.72 E
-鹿å
å³¶å¸ Kagoshimaï¼é¹¿å
島å¸; -shiï¼ is a city in Japan and the capital city of Kagoshima Prefecture. 31 35 48.5 N 130 33 25.7 E
-è©æ©å·å
å¸ Satsumasendai is a city in Kagoshima prefecture, Japan. 31 48 48.5 N 130 18 14.3 E
-ä¸æµ· Shanghai is the largest city in China and is divided into 18 districts and one county (the island in the Yangtze River). It is located on the coast of eastern China at the mouth of the Chang Jiang (Yangtze River), and borders the provinces of Jiangsu and Zhejiang. 31 10 00 N 121 28 00 E
-ä¸å¹³ Daqing River 35 54 30 N 116 18 00 E
+à¦à¦à§à¦à¦à§à¦°à¦¾à¦® 22 19 12 N 91 49 12 E
+ä¸æµ· 1 31 10 12 N 121 28 12 E
ä¸åæµ· Zhongnanhai (Chinese: ä¸åæµ·; pinyin: ZhÅngnánhÄi) is a complex of buildings in Beijing, China which serves as the central headquarters for the Communist Party of China and the government of the People's Republic of China. 39 54 41 N 116 22 50 E
ä¹å¯¨æ² Jiuzhaigou Valley (Chinese: ä¹å¯¨æ²; pinyin: JiÇzhà igÅu; lit. "Nine Stockades Gully") is a nature reserve in Aba(é¿å) Tibetan and Qiang Autonomous District, northern Sichuan province, China. 33 09 34 N 103 52 40 E
äºå Yunnan(äºå) is a Chinese southwest border province, with the most varied nationalities in China. There are 52 nationalities of people living in Yunnan, out of 56 total throughout China. 25 03 00 N 101 52 00 E
-京é½å¸ Kyoto is a city in Japan. It was the capital of Japan from 794 to 1869. 35 00 42 N 135 46 05 E
+京é½å¸ Kyoto is a city in Japan. It was the capital of Japan from 794 to 1869. 35 00 42.12 N 135 46 05.16 E
å
µé¦¬ä¿ Terracotta Army 34 23 05.7 N 109 16 23.1 E
å¥åºå¸ Beppu is a famous onsen city in Oita Prefecture on the island of Kyushu in Japan. 33 17 04.6 N 131 29 28.6 E
åä¹å·å¸ KitakyÅ«shÅ« is a city in Fukuoka Prefecture on the island of Kyushu, Japan. 33 53 00.3 N 130 52 30.7 E
å京å¨ç©å beijing zoo lies west of Xizhimen and is the western part of the Beijing, China. It is one of the largest zoos in mainland china. 39 56 19 N 116 20 00 E
åæµ·å
¬å ä¸æ: åæµ·å
¬åä½äºä¸å½å京å¸ååºçä¸ååé¨ï¼æ
宫åæ¯å±±ç西å侧ï¼å§å»ºäºè¾½ä»£ï¼æ¯ä¸çä¸ç°å建åæ¶é´ææ©çç家宫èã 39 55 28 N 116 22 59 E
-å京 Nanjing (å京) is the capital of Jiangsu Province of China. It was the Chinese capital from 1927-1949. 32 03 00 N 118 46 00 E
+å京 Nanjing (å京) is the capital of Jiangsu Province of China. It was the Chinese capital from 1927-1949. 32 03 00 N 118 46 00.12 E
åæ³è¯å¯º Minamihokke-ji is the Buddhist temple in Takatori, Nara prefecture, Japan. 34 25 35.1 N 135 48 35.5 E
-å°åå¸ 22 59 00 N 120 11 00 E
-åå¤å±å¸ 35 07 00 N 136 56 00 E
-åæå±±å¸ Wakayama (åæå±±å¸, Wakayama-shi) is the capital city of Wakayama Prefecture in the Kansai region of Japan. 34 13 49.3 N 135 10 14.7 E
+å°åå¸ 22 58 59.88 N 120 10 59.88 E
+åæå±±å¸ Wakayama (åæå±±å¸, Wakayama-shi) is the capital city of Wakayama Prefecture in the Kansai region of Japan. 34 13 49.3 N 135 10 14.7 E
åå°æ»¨ Harbin is a sub-provincial city in north-east China and the capital of the Heilongjiang Province. 45 48 05 N 126 31 45 E
-åå· Nature reserve in Aba(é¿å) Tibetan and Qiang Autonomous District, northern Sichuan province, China. It is known for its many multi-level waterfalls and colorful lakes, and was declared a UNESCO World Heritage Site in 1992. 30 08 00 N 102 56 00 E
+åå· Nature reserve in Aba(é¿å) Tibetan and Qiang Autonomous District, northern Sichuan province, China. 30 08 00 N 102 56 00 E
åæå Yuanmingyuan (pinyin: Yuanmingyuan, åæå), or the old Summer Palace in Peking. 40 00 26 N 116 17 33 E
å¤§æ´¥å¸ Åtsu is a city in Japan. It was the capital of Japan from 667 to 672. 35 01 04.1 N 135 51 17 E
-大éªå¸ Osaka 34 41 37.5 N 135 30 07.6 E
+大éªå¸ 34 41 37.5 N 135 30 07.6 E
天å Temple of Heaven in Beijing. 39 52 56.1 N 116 24 23.7 E
天å®é Tiananmen (Gate of Heavenly Peace) in Beijing was the southern gate of the Imperial City in Beijing. 39 54 26.4 N 116 23 27.9 E
天å®é¨å¹¿åº Mausoleum of Mao Zedong 39 54 12 N 116 23 30 E
å®æ²»å¸ Uji is a city in Kyoto prefecture. The Byodoin (an ancient Buddhist temple) and the Ujigami Shrine are famous landmarks in Uji. 34 53 03.7 N 135 47 59.3 E
-å°ç°åå¸ Odawara, Kanagawa 35 15 52.6 N 139 09 08 E
å±ä¹
島 Yakushima island 30 20 00 N 130 30 00 E
å¹¿ä¸ Guangdong (广ä¸) is a coastal province in southern China adjacent to Hongkong and Macao. 23 24 00 N 113 30 00 E
-å¹¿å· Guangzhou is the capital of Guangdong Province in southern China. The city was formerly known internationally as Canton City or simply Canton. 23 07 43.66 N 113 15 32.31 E
-åºå³¶å¸ Hiroshima is one of largest cities in Japan and the capital of Hiroshima prefecture. 34 23 06.9 N 132 27 19.1 E
+å¹¿å· 23 07 43.66 N 113 15 32.31 E
+åºå³¶å¸ Hiroshima is one of largest cities in Japan and the capital of Hiroshima prefecture. During World War II, it was the first city in the world to have an atomic bomb dropped on it. 34 23 06.9 N 132 27 19.1 E
å¾³å³¶å¸ Tokushima is the capital city of Tokushima prefecture on the island of Kyushu in Japan. 34 04 13 N 134 33 17.8 E
-æé½ Chengdu is the capital city and prefecture-level division of Sichuan Province, in southwestern China. 30 39 49 N 104 04 00 E
+æé½ Chengdu is the capital city and prefecture-level division of Sichuan Province, in southwestern China. 30 39 48.96 N 104 04 00.12 E
æ¯å±±å
Œ Jingshan Park, Dongcheng District, Beijing. 39 55 24.5 N 116 23 26.2 E
-æå· Hangzhou (æå·) is a picturesque city in south China. It is the capital of Zhejiang Province and was visited by Marco Polo. 30 15 00 N 120 10 00 E
-æ¦æ± Wuhan is the capital of the Chinese province of Hubei 30 34 21 N 114 16 45 E
-æ·±å³ Shenzhen is a major city in Guangdong Province, China. 22 32 06 N 114 03 14.4 E
-æ»çé The Pavilion of Prince Teng or Tengwang Pavilion is a building in the north west of the city of Nanchang, in Jiangxi province, China. 28 41 02.76 N 115 52 32.88 E
+æå· 30 15 00 N 120 10 03 E
+æ¦æ± Wuhan is the capital of the Chinese province of Hubei 30 35 13.92 N 114 17 17.16 E
+æ»çé 28 41 02.76 N 115 52 32.88 E
ç¸æ¨¡åå¸ Sagamihara, Kanagawa 35 34 17.1 N 139 22 23.3 E
ç¥å Gion (ç¥å) is a district of Kyoto, Japan, originally developed in the middle ages. 35 00 13 N 135 46 30 E
ç¦å²¡å¸ Fukuoka, Fukuoka 33 35 24.5 N 130 24 06.2 E
+ç¦å»º Lu You Statue in Ningdeä¸æï¼ç®ä½ï¼â: å®å¾·çé游éå 25 54 00 N 118 18 00 E
ç´«ç¦å The Forbidden City (ç´«ç¦å), located at the centre of Beijing, China, was the imperial palace of the last two imperial dynasties of China (from 1420 to 1924). 39 54 50.1 N 116 23 27.6 E
-è¥¿å® Xi'an is an ancient city located in north central China. It was the capital of various dynasties from 1046 B.C. to 907 A.D, and it has been known under a number of different names including most notably Chang'an during the Tang dynasty. 34 16 00 N 108 57 00 E
+è©æ©å·å
å¸ Satsumasendai is a city in Kagoshima prefecture, Japan. 31 48 48.5 N 130 18 14.3 E
+è¥¿å® Xi'an is an ancient city located in north central China. It was the capital of various dynasties from 1046 B.C. to 907 A.D, and it has been known under a number of different names including most notably Chang'an during the Tang dynasty. Today it is the capital of Shaanxi province. 34 16 00.12 N 108 54 00 E
éåå¸ Zushi (éåå¸ Zushi-shi) is a city located in Kanagawa, Japan. 35 17 44.2 N 139 34 49.2 E
-éåº Chongqing is located in the southwest of China, is China's largest and most populous municipality. 29 33 00 N 106 33 00 E
-éå Zeniarai Benten shrine 35 19 09.3 N 139 32 48.1 E
+éåº Chongqing is located in the southwest of China, is China's largest and most populous municipality. 29 33 00 N 106 30 24.84 E
é¢åå The Summer Palace is a former imperial palace in northwest of Beijing, China. It has been transformed in a public garden. 39 59 51 N 116 16 08.04 E
-é¦æ¸¯ 22 16 01 N 114 11 17 E
-é«éå¸ Kaohsiung is a city in Taiwan. 22 38 00 N 120 16 00 E
-ìì¸í¹ë³ì Seoul is the capital of South Korea. 37 35 00 N 127 00 00 E
+é¦æ¸¯ 22 16 48 N 114 09 36 E
+é«éå¸ Kaohsiung is a city in Taiwan. 22 37 00.01 N 120 18 00 E
+鹿å
å³¶å¸ Kagoshimaï¼é¹¿å
島å¸; -shiï¼ is a city in Japan and the capital city of Kagoshima Prefecture. 31 35 48.12 N 130 33 25.92 E
diff --git a/src/tim/prune/function/settings/SaveConfig.java b/src/tim/prune/function/settings/SaveConfig.java
index d449051..b737bd2 100644
--- a/src/tim/prune/function/settings/SaveConfig.java
+++ b/src/tim/prune/function/settings/SaveConfig.java
@@ -1,24 +1,11 @@
package tim.prune.function.settings;
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.FlowLayout;
-import java.awt.GridLayout;
import java.awt.Rectangle;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Properties;
-import javax.swing.BorderFactory;
-import javax.swing.JButton;
-import javax.swing.JDialog;
import javax.swing.JFileChooser;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
import tim.prune.App;
import tim.prune.GenericFunction;
@@ -30,8 +17,6 @@ import tim.prune.config.Config;
*/
public class SaveConfig extends GenericFunction
{
- private JDialog _dialog = null;
-
/**
* Constructor
* @param inApp application object for callback
@@ -50,86 +35,6 @@ public class SaveConfig extends GenericFunction
* Begin the function
*/
public void begin()
- {
- // Make new dialog window (don't reuse it)
- _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
- _dialog.setLocationRelativeTo(_parentFrame);
- _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
- _dialog.getContentPane().add(makeDialogComponents());
- _dialog.pack();
- _dialog.setVisible(true);
- }
-
-
- /**
- * Create dialog components
- * @return Panel containing all gui elements in dialog
- */
- private Component makeDialogComponents()
- {
- JPanel dialogPanel = new JPanel();
- dialogPanel.setLayout(new BorderLayout());
- dialogPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
- JLabel descLabel = new JLabel(I18nManager.getText("dialog.saveconfig.desc"));
- dialogPanel.add(descLabel, BorderLayout.NORTH);
-
- // Grid panel in centre
- JPanel mainPanel = new JPanel();
- mainPanel.setLayout(new GridLayout(0, 2, 15, 2));
- mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 15, 5, 15));
- Properties conf = Config.getAllConfig();
- Enumeration