Index: applications/editors/josm/plugins/gpsblam/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- applications/editors/josm/plugins/gpsblam/.settings/org.eclipse.jdt.core.prefs	(revision 30760)
+++ applications/editors/josm/plugins/gpsblam/.settings/org.eclipse.jdt.core.prefs	(revision 30761)
@@ -9,4 +9,5 @@
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
 org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
 org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
@@ -32,4 +33,9 @@
 org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
 org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public
 org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
 org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
@@ -38,4 +44,12 @@
 org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
 org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
 org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
 org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
Index: applications/editors/josm/plugins/gpsblam/.settings/org.eclipse.jdt.ui.prefs
===================================================================
--- applications/editors/josm/plugins/gpsblam/.settings/org.eclipse.jdt.ui.prefs	(revision 30761)
+++ applications/editors/josm/plugins/gpsblam/.settings/org.eclipse.jdt.ui.prefs	(revision 30761)
@@ -0,0 +1,60 @@
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=false
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+sp_cleanup.use_type_arguments=false
Index: applications/editors/josm/plugins/gpsblam/src/org/openstreetmap/josm/plugins/gpsblam/GPSBlamInputData.java
===================================================================
--- applications/editors/josm/plugins/gpsblam/src/org/openstreetmap/josm/plugins/gpsblam/GPSBlamInputData.java	(revision 30760)
+++ applications/editors/josm/plugins/gpsblam/src/org/openstreetmap/josm/plugins/gpsblam/GPSBlamInputData.java	(revision 30761)
@@ -1,17 +1,3 @@
-/** GPSBlam JOSM Plugin
- * Copyright (C) 2012 Russell Edwards
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// License: GPL. Copyright (C) 2012 Russell Edwards
 package org.openstreetmap.josm.plugins.gpsblam;
 
@@ -31,83 +17,70 @@
 import org.openstreetmap.josm.gui.layer.Layer;
 
-public class GPSBlamInputData extends LinkedList<CachedLatLon> {
-	private Collection<Calendar> datesSeen = new HashSet<>();
+class GPSBlamInputData extends LinkedList<CachedLatLon> {
+    private final Collection<Calendar> datesSeen = new HashSet<>();
 
-	public int getNDays() { return datesSeen.size(); }
+    public int getNDays() {
+        return datesSeen.size();
+    }
 
-	// select a set of GPX points and count how many tracks they have come from,
-	// within given radius of line between given points
-	public GPSBlamInputData(Point p1, Point p2, int radius)
-	{
-		// Build a list of waypoints in all visible layers -
-		//	Collection<WayPoint> wayPoints = new LinkedList<WayPoint>();
+    // select a set of GPX points and count how many tracks they have come from,
+    // within given radius of line between given points
+    GPSBlamInputData(Point p1, Point p2, int radius) {
+        Collection<Layer> layers = Main.map.mapView.getAllLayers();
+        for (Layer l : layers) {
+            if (l.isVisible() && l instanceof GpxLayer) {
+                for (GpxTrack track : ((GpxLayer)l).data.tracks) {
+                    for (GpxTrackSegment segment: track.getSegments()) {
+                        for (WayPoint wayPoint : segment.getWayPoints()) {
 
-		Collection<Layer> layers = Main.map.mapView.getAllLayers();
-		for (Layer l : layers) 
-		{      
-			if (l.isVisible() && l instanceof GpxLayer)
-			{
-				for (GpxTrack track : ((GpxLayer)l).data.tracks)
-				{
-					//		 			System.out.println("TRACK");
-					for (GpxTrackSegment segment: track.getSegments()) 
-					{
-						//		 				wayPoints.addAll(segment.getWayPoints());/*
-						for (WayPoint wayPoint : segment.getWayPoints())
-						{
-							// 					points.add(Main.map.mapView.getPoint(wayPoint.getCoor().getEastNorth()));
-							//		 					wayPoints.add(Main.map.mapView.getPoint(wayPoint.getCoor().getEastNorth()));
+                            if (p2.equals(p1)) {
+                                // circular selection
+                                CachedLatLon cll = new CachedLatLon(wayPoint.getCoor());
+                                Point p = Main.map.mapView.getPoint(cll.getEastNorth());
+                                if (p.distance(p1) < radius) {
+                                    this.add(cll, wayPoint);
+                                }
+                            } else {
+                                // selection based on distance from line from p1 to p2
+                                // hack to work for zero length
+                                double length = Math.sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y))+1e-5;
+                                // unit direction vector from p1.x,p1.y to p2.x, p2.y
+                                double dirX = (p2.x-p1.x)/length, dirY = (p2.y-p1.y)/length;
+                                // unit vector 90deg CW from direction vector
+                                double perpdirX = dirY, perpdirY = -dirX;
 
-							if (p2.equals(p1)) // circular selection
-							{
-								CachedLatLon cll = new CachedLatLon(wayPoint.getCoor());
-								Point p = Main.map.mapView.getPoint(cll.getEastNorth());
-								if (p.distance(p1) < radius)
-								{
-									this.add(cll, wayPoint);
-								}
-							}
-							else  // selection based on distance from line from p1 to p2
-							{
-								double length = Math.sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y))+1e-5; // hack to work for zero length            
-								double dir_x = (p2.x-p1.x)/length, dir_y = (p2.y-p1.y)/length; // unit direction vector from p1.x,p1.y to p2.x, p2.y
-								double perpdir_x = dir_y, perpdir_y = -dir_x; // unit vector 90deg CW from direction vector
+                                CachedLatLon cll = new CachedLatLon(wayPoint.getCoor());
+                                Point p = Main.map.mapView.getPoint(cll.getEastNorth());
+                                double pX = p.x-p1.x, pY=p.y-p1.y; // vector from point clicked to waypoint
+                                double pPar = pX*dirX + pY*dirY; // parallel component
+                                double pPerp = pX*perpdirX + pY*perpdirY; // perpendicular component
+                                double pardist = 0.0;
 
-								CachedLatLon cll = new CachedLatLon(wayPoint.getCoor());
-								Point p = Main.map.mapView.getPoint(cll.getEastNorth());
-								double p_x = p.x-p1.x, p_y=p.y-p1.y; // vector from point clicked to waypoint
-								double p_par = p_x*dir_x + p_y*dir_y; // parallel component
-								double p_perp = p_x*perpdir_x + p_y*perpdir_y; // perpendicular component
-								double pardist = 0.0;
+                                if (pPar < 0)
+                                    pardist = -pPar;
+                                else if (pPar > length)
+                                    pardist = pPar-length;
 
-								if (p_par < 0)
-									pardist = -p_par;
-								else if (p_par > length)
-									pardist = p_par-length;
+                                double distsq = pardist*pardist + pPerp*pPerp;
 
-								double distsq = pardist*pardist + p_perp*p_perp;
+                                if (distsq < radius*radius) {
+                                    this.add(cll, wayPoint);
+                                }
+                            } // end if circular else line based selection
+                        } // end loop over wayponts in segment
+                    } // end loop over segments in track
+                } // end loop over tracks in layer
+            } // end if layer visible
+        } // end loop over layers
+    } // end constructor
 
-								//        	System.out.printf("dist %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f\n", Math.sqrt(distsq), p_x, p_y, p1.x, p1.y, p_par, p_perp, dir_x, dir_y);
-								if (distsq < radius*radius)
-								{
-									this.add(cll, wayPoint);
-								}
-							} // end if circular else line based selection
-						}// end loop over wayponts in segment
-					} // end loop over segments in track
-					
-				}	// end loop over tracks in layer
-			} // end if layer visible
-		} // end loop over layers
-	} // end constructor
-
-	private void add(CachedLatLon cll, WayPoint wayPoint) {
-		this.add(cll);
-		Calendar day = new GregorianCalendar();
-		day.setTimeInMillis((long)wayPoint.time*1000);
-		day.set(Calendar.HOUR_OF_DAY, 0);
-		day.set(Calendar.MINUTE, 0);
-		day.set(Calendar.SECOND, 0);
-		datesSeen.add(day);		
-	}
+    private void add(CachedLatLon cll, WayPoint wayPoint) {
+        this.add(cll);
+        Calendar day = new GregorianCalendar();
+        day.setTimeInMillis((long)wayPoint.time*1000);
+        day.set(Calendar.HOUR_OF_DAY, 0);
+        day.set(Calendar.MINUTE, 0);
+        day.set(Calendar.SECOND, 0);
+        datesSeen.add(day);
+    }
 }
Index: applications/editors/josm/plugins/gpsblam/src/org/openstreetmap/josm/plugins/gpsblam/GPSBlamLayer.java
===================================================================
--- applications/editors/josm/plugins/gpsblam/src/org/openstreetmap/josm/plugins/gpsblam/GPSBlamLayer.java	(revision 30760)
+++ applications/editors/josm/plugins/gpsblam/src/org/openstreetmap/josm/plugins/gpsblam/GPSBlamLayer.java	(revision 30761)
@@ -1,3 +1,6 @@
+// License: GPL. Copyright (C) 2012 Russell Edwards
 package org.openstreetmap.josm.plugins.gpsblam;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Graphics2D;
@@ -6,8 +9,7 @@
 import java.util.LinkedList;
 
-import javax.swing.ImageIcon;
-
 import javax.swing.Action;
 import javax.swing.Icon;
+import javax.swing.ImageIcon;
 
 import org.openstreetmap.josm.data.Bounds;
@@ -17,64 +19,64 @@
 import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
 import org.openstreetmap.josm.gui.layer.Layer;
-import static org.openstreetmap.josm.tools.I18n.tr;
 
-public class GPSBlamLayer extends Layer {
-	
-	private Collection<GPSBlamMarker> blamMarkers;
-	
-    public GPSBlamLayer(String name) {
-		super(name);
-		blamMarkers = new LinkedList<>();
-	}
+class GPSBlamLayer extends Layer {
 
-	private static Icon icon = new ImageIcon(Toolkit.getDefaultToolkit().createImage(GPSBlamPlugin.class.getResource("/images/gpsblam_layer.png")));
+    private final Collection<GPSBlamMarker> blamMarkers;
 
-	@Override
-	public Icon getIcon() {
-        return icon;
-	}
+    GPSBlamLayer(String name) {
+        super(name);
+        blamMarkers = new LinkedList<>();
+    }
 
-	@Override
-	public Object getInfoComponent() {
-		return getToolTipText();
-	}
+    private static final Icon ICON = new ImageIcon(Toolkit.getDefaultToolkit().createImage(
+            GPSBlamPlugin.class.getResource("/images/gpsblam_layer.png")));
 
-	@Override
-	public Action[] getMenuEntries() {
+    @Override
+    public Icon getIcon() {
+        return ICON;
+    }
+
+    @Override
+    public Object getInfoComponent() {
+        return getToolTipText();
+    }
+
+    @Override
+    public Action[] getMenuEntries() {
         return new Action[] {
                 LayerListDialog.getInstance().createShowHideLayerAction(),
                 LayerListDialog.getInstance().createDeleteLayerAction(),
                 new LayerListPopup.InfoAction(this)};
-	}
+    }
 
-	@Override
-	public String getToolTipText() {
-		return tr("GPS Blams");
-	}
+    @Override
+    public String getToolTipText() {
+        return tr("GPS Blams");
+    }
 
-	@Override
-	public boolean isMergable(Layer arg0) {
-		return false;
-	}
+    @Override
+    public boolean isMergable(Layer arg0) {
+        return false;
+    }
 
-	@Override
-	public void mergeFrom(Layer arg0) {
+    @Override
+    public void mergeFrom(Layer arg0) {
+        // Do nothing
+    }
 
-	}
+    @Override
+    public void paint(Graphics2D g, MapView mv, Bounds bounds) {
+        for (GPSBlamMarker blamMarker : blamMarkers){
+            blamMarker.paint(g, mv);
+        }
+    }
 
-	@Override
-	public void paint(Graphics2D g, MapView mv, Bounds bounds) {
-		for (GPSBlamMarker blamMarker : blamMarkers){
-			blamMarker.paint(g, mv);
-		}
-	}
+    @Override
+    public void visitBoundingBox(BoundingXYVisitor arg0) {
+        // Do nothing
+    }
 
-	@Override
-	public void visitBoundingBox(BoundingXYVisitor arg0) {
-	}
-
-	public void addBlamMarker(GPSBlamMarker blamMarker) {
-		blamMarkers.add(blamMarker);	
-	}
-	
+    void addBlamMarker(GPSBlamMarker blamMarker) {
+        blamMarkers.add(blamMarker);
+    }
 }
Index: applications/editors/josm/plugins/gpsblam/src/org/openstreetmap/josm/plugins/gpsblam/GPSBlamMarker.java
===================================================================
--- applications/editors/josm/plugins/gpsblam/src/org/openstreetmap/josm/plugins/gpsblam/GPSBlamMarker.java	(revision 30760)
+++ applications/editors/josm/plugins/gpsblam/src/org/openstreetmap/josm/plugins/gpsblam/GPSBlamMarker.java	(revision 30761)
@@ -1,17 +1,3 @@
-/** GPSBlam JOSM Plugin
- * Copyright (C) 2012 Russell Edwards
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// License: GPL. Copyright (C) 2012 Russell Edwards
 package org.openstreetmap.josm.plugins.gpsblam;
 
@@ -31,101 +17,97 @@
 import org.openstreetmap.josm.gui.MapView;
 
-public class GPSBlamMarker {
-	private CachedLatLon mean;
-	private CachedLatLon hair1Coord1, hair1Coord2, hair2Coord1, hair2Coord2;
-	private CachedLatLon ellipseCoord1, ellipseCoord2, ellipseCoord3; // 1=TL 2=TR 3=BL, where main axis = +R, minor +U 
-	static final double fac = 2.45; // 2.45 gives 95% CI for 2D
-	
-	// construct a blammarker by analysis of selected GPS points
-	public GPSBlamMarker(GPSBlamInputData inputData)
-	    {
-	        // get mean east, north
-	        double mean_east=0.0, mean_north=0.0;
-	        for (CachedLatLon cll : inputData)
-	        {
-	        	EastNorth en = cll.getEastNorth();
-	        	mean_east += en.east();
-	        	mean_north += en.north();
-	        }
-	        double n = (double)inputData.size();
-	        mean_east /= n;
-	        mean_north /= n;
-	        
-	        // get covariance matrix
-	        double ca=0.0, cb=0.0, cc=0.0, cd=0.0;
-	        double deast, dnorth;
-	        for (CachedLatLon cll : inputData)
-	        {
-	        	EastNorth en = cll.getEastNorth();
-	        	deast = en.east()-mean_east;
-	        	dnorth = en.north()-mean_north;
-	        	ca += deast*deast;
-	        	cb += deast*dnorth;
-	        	cd += dnorth*dnorth;
-	        }
-	        cc = cb;
-	        ca /= n;
-	        cb /= n;
-	        cc /= n;
-	        cd /= n;
-	        
-	        // direction and spread analysis
-	        double T = ca+cd, D = ca*cd-cb*cc; // trace, determinant
-	        double variance1 = 0.5*T + Math.sqrt(0.25*T*T-D); // Eigenvalue 1
-	        double variance2 = 0.5*T - Math.sqrt(0.25*T*T-D); // Eigenvalue 2
-	        double evec1_east = (variance1-cd), evec1_north = cc; // eigenvec1
-	        double evec2_east = (variance2-cd), evec2_north = cc; // eigenvec2
-	        
-	        double evec1_fac = Math.sqrt(variance1)/Math.sqrt(evec1_east*evec1_east+evec1_north*evec1_north);
-	        double evec2_fac = Math.sqrt(variance2)/Math.sqrt(evec2_east*evec2_east+evec2_north*evec2_north);
-	        double sigma1_east = evec1_east * evec1_fac, sigma1_north = evec1_north * evec1_fac;
-	        double sigma2_east = evec2_east * evec2_fac, sigma2_north = evec2_north * evec2_fac;                     
-	      
-	       // save latlon coords of the mean and the ends of the crosshairs
-	       Projection proj = Main.getProjection();
-	       mean = new CachedLatLon(proj.eastNorth2latlon(new EastNorth(mean_east, mean_north)));
-	       hair1Coord1 = new CachedLatLon(proj.eastNorth2latlon(
-	    		   new EastNorth(mean_east-sigma1_east*fac, mean_north-sigma1_north*fac)));
-	       hair1Coord2 = new CachedLatLon(proj.eastNorth2latlon(
-	    		   new EastNorth(mean_east+sigma1_east*fac, mean_north+sigma1_north*fac)));
-	       hair2Coord1 = new CachedLatLon(proj.eastNorth2latlon(
-	    		   new EastNorth(mean_east-sigma2_east*fac, mean_north-sigma2_north*fac)));
-	       hair2Coord2 = new CachedLatLon(proj.eastNorth2latlon(
-	    		   new EastNorth(mean_east+sigma2_east*fac, mean_north+sigma2_north*fac)));
-	       double efac = fac/Math.sqrt(inputData.getNDays());
-	       // TopLeft, TopRight, BottomLeft in frame where sigma1=R sigma2=Top
-	       ellipseCoord1 = new CachedLatLon(proj.eastNorth2latlon(
-	    		   new EastNorth(mean_east+(-sigma1_east+sigma2_east)*efac, mean_north+(-sigma1_north+sigma2_north)*efac))); // 
-	       ellipseCoord2 = new CachedLatLon(proj.eastNorth2latlon(
-	    		   new EastNorth(mean_east+(sigma1_east+sigma2_east)*efac, mean_north+(sigma1_north+sigma2_north)*efac))); // 
-	       ellipseCoord3 = new CachedLatLon(proj.eastNorth2latlon(
-	    		   new EastNorth(mean_east+(-sigma1_east-sigma2_east)*efac, mean_north+(-sigma1_north-sigma2_north)*efac))); // 
-	}
+class GPSBlamMarker {
+    private final CachedLatLon mean;
+    private final CachedLatLon hair1Coord1, hair1Coord2, hair2Coord1, hair2Coord2;
+    private final CachedLatLon ellipseCoord1, ellipseCoord2, ellipseCoord3; // 1=TL 2=TR 3=BL, where main axis = +R, minor +U
+    private static final double FAC = 2.45; // 2.45 gives 95% CI for 2D
 
-	public void paint(Graphics2D g, MapView mv)
-	{
-		g.setColor(Color.GREEN);
-		g.setPaintMode();
+    /** construct a blammarker by analysis of selected GPS points */
+    GPSBlamMarker(GPSBlamInputData inputData) {
+        // get mean east, north
+        double meanEast=0.0, meanNorth=0.0;
+        for (CachedLatLon cll : inputData) {
+            EastNorth en = cll.getEastNorth();
+            meanEast += en.east();
+            meanNorth += en.north();
+        }
+        double n = inputData.size();
+        meanEast /= n;
+        meanNorth /= n;
+
+        // get covariance matrix
+        double ca=0.0, cb=0.0, cc=0.0, cd=0.0;
+        double deast, dnorth;
+        for (CachedLatLon cll : inputData) {
+            EastNorth en = cll.getEastNorth();
+            deast = en.east()-meanEast;
+            dnorth = en.north()-meanNorth;
+            ca += deast*deast;
+            cb += deast*dnorth;
+            cd += dnorth*dnorth;
+        }
+        cc = cb;
+        ca /= n;
+        cb /= n;
+        cc /= n;
+        cd /= n;
+
+        // direction and spread analysis
+        double t = ca+cd, d = ca*cd-cb*cc; // trace, determinant
+        double variance1 = 0.5*t + Math.sqrt(0.25*t*t-d); // Eigenvalue 1
+        double variance2 = 0.5*t - Math.sqrt(0.25*t*t-d); // Eigenvalue 2
+        double evec1East = variance1-cd, evec1North = cc; // eigenvec1
+        double evec2East = variance2-cd, evec2North = cc; // eigenvec2
+
+        double evec1Fac = Math.sqrt(variance1)/Math.sqrt(evec1East*evec1East+evec1North*evec1North);
+        double evec2Fac = Math.sqrt(variance2)/Math.sqrt(evec2East*evec2East+evec2North*evec2North);
+        double sigma1East = evec1East * evec1Fac, sigma1North = evec1North * evec1Fac;
+        double sigma2East = evec2East * evec2Fac, sigma2North = evec2North * evec2Fac;
+
+        // save latlon coords of the mean and the ends of the crosshairs
+        Projection proj = Main.getProjection();
+        mean = new CachedLatLon(proj.eastNorth2latlon(new EastNorth(meanEast, meanNorth)));
+        hair1Coord1 = new CachedLatLon(proj.eastNorth2latlon(
+                   new EastNorth(meanEast-sigma1East*FAC, meanNorth-sigma1North*FAC)));
+        hair1Coord2 = new CachedLatLon(proj.eastNorth2latlon(
+                   new EastNorth(meanEast+sigma1East*FAC, meanNorth+sigma1North*FAC)));
+        hair2Coord1 = new CachedLatLon(proj.eastNorth2latlon(
+                   new EastNorth(meanEast-sigma2East*FAC, meanNorth-sigma2North*FAC)));
+        hair2Coord2 = new CachedLatLon(proj.eastNorth2latlon(
+                   new EastNorth(meanEast+sigma2East*FAC, meanNorth+sigma2North*FAC)));
+        double efac = FAC/Math.sqrt(inputData.getNDays());
+        // TopLeft, TopRight, BottomLeft in frame where sigma1=R sigma2=Top
+        ellipseCoord1 = new CachedLatLon(proj.eastNorth2latlon(
+                   new EastNorth(meanEast+(-sigma1East+sigma2East)*efac, meanNorth+(-sigma1North+sigma2North)*efac))); //
+        ellipseCoord2 = new CachedLatLon(proj.eastNorth2latlon(
+                   new EastNorth(meanEast+(sigma1East+sigma2East)*efac, meanNorth+(sigma1North+sigma2North)*efac))); //
+        ellipseCoord3 = new CachedLatLon(proj.eastNorth2latlon(
+                   new EastNorth(meanEast+(-sigma1East-sigma2East)*efac, meanNorth+(-sigma1North-sigma2North)*efac))); //
+    }
+
+    void paint(Graphics2D g, MapView mv) {
+        g.setColor(Color.GREEN);
+        g.setPaintMode();
         g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
         g.setStroke(new BasicStroke(2.0f));
-		Point hair1Point1 = mv.getPoint(hair1Coord1.getEastNorth());
-		Point hair1Point2 = mv.getPoint(hair1Coord2.getEastNorth());
-		Point hair2Point1 = mv.getPoint(hair2Coord1.getEastNorth());
-		Point hair2Point2 = mv.getPoint(hair2Coord2.getEastNorth());		
-		g.drawLine(hair1Point1.x, hair1Point1.y, hair1Point2.x, hair1Point2.y);
-		g.drawLine(hair2Point1.x, hair2Point1.y, hair2Point2.x, hair2Point2.y);
-		
-		Point2D meanPoint = mv.getPoint2D(mean.getEastNorth());
-		Point2D ellipsePoint1 = mv.getPoint2D(ellipseCoord1.getEastNorth());
-		Point2D ellipsePoint2 = mv.getPoint2D(ellipseCoord2.getEastNorth());
-		Point2D ellipsePoint3 = mv.getPoint2D(ellipseCoord3.getEastNorth());
-		double majorAxis = ellipsePoint2.distance(ellipsePoint1);
-		double minorAxis = ellipsePoint3.distance(ellipsePoint1);		
-		double angle = -Math.atan2(-(ellipsePoint2.getY()-ellipsePoint1.getY()), ellipsePoint2.getX()-ellipsePoint1.getX());
-	    Shape e = new Ellipse2D.Double(meanPoint.getX()-majorAxis*0.5, meanPoint.getY()-minorAxis*0.5,
-	    								majorAxis, minorAxis);
-	    g.rotate(angle, meanPoint.getX(), meanPoint.getY());
-	    g.draw(e);
-	    g.rotate(-angle, meanPoint.getX(), meanPoint.getY());
-	}
+        Point hair1Point1 = mv.getPoint(hair1Coord1.getEastNorth());
+        Point hair1Point2 = mv.getPoint(hair1Coord2.getEastNorth());
+        Point hair2Point1 = mv.getPoint(hair2Coord1.getEastNorth());
+        Point hair2Point2 = mv.getPoint(hair2Coord2.getEastNorth());
+        g.drawLine(hair1Point1.x, hair1Point1.y, hair1Point2.x, hair1Point2.y);
+        g.drawLine(hair2Point1.x, hair2Point1.y, hair2Point2.x, hair2Point2.y);
+
+        Point2D meanPoint = mv.getPoint2D(mean.getEastNorth());
+        Point2D ellipsePoint1 = mv.getPoint2D(ellipseCoord1.getEastNorth());
+        Point2D ellipsePoint2 = mv.getPoint2D(ellipseCoord2.getEastNorth());
+        Point2D ellipsePoint3 = mv.getPoint2D(ellipseCoord3.getEastNorth());
+        double majorAxis = ellipsePoint2.distance(ellipsePoint1);
+        double minorAxis = ellipsePoint3.distance(ellipsePoint1);
+        double angle = -Math.atan2(-(ellipsePoint2.getY()-ellipsePoint1.getY()), ellipsePoint2.getX()-ellipsePoint1.getX());
+        Shape e = new Ellipse2D.Double(meanPoint.getX()-majorAxis*0.5, meanPoint.getY()-minorAxis*0.5,
+                                        majorAxis, minorAxis);
+        g.rotate(angle, meanPoint.getX(), meanPoint.getY());
+        g.draw(e);
+        g.rotate(-angle, meanPoint.getX(), meanPoint.getY());
+    }
 }
Index: applications/editors/josm/plugins/gpsblam/src/org/openstreetmap/josm/plugins/gpsblam/GPSBlamMode.java
===================================================================
--- applications/editors/josm/plugins/gpsblam/src/org/openstreetmap/josm/plugins/gpsblam/GPSBlamMode.java	(revision 30760)
+++ applications/editors/josm/plugins/gpsblam/src/org/openstreetmap/josm/plugins/gpsblam/GPSBlamMode.java	(revision 30761)
@@ -1,17 +1,3 @@
-/** GPSBlam JOSM Plugin
- * Copyright (C) 2012 Russell Edwards
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// License: GPL. Copyright (C) 2012 Russell Edwards
 package org.openstreetmap.josm.plugins.gpsblam;
 
@@ -43,5 +29,5 @@
 import org.openstreetmap.josm.gui.layer.Layer;
 
-public class GPSBlamMode extends MapMode implements LayerChangeListener, MouseWheelListener, AWTEventListener {
+class GPSBlamMode extends MapMode implements LayerChangeListener, MouseWheelListener, AWTEventListener {
 
     Point pointPressed;
@@ -49,13 +35,14 @@
     private Point oldP2;
     int radius;
-    MouseWheelListener mapViewWheelListeners[];
+    MouseWheelListener[] mapViewWheelListeners;
     GPSBlamLayer currentBlamLayer;
 
-    public GPSBlamMode(MapFrame mapFrame, String name, String desc) {
+    GPSBlamMode(MapFrame mapFrame, String name, String desc) {
         super(name, "gpsblam_mode.png", desc, mapFrame, Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
         radius = 10;
     }
 
-    @Override public void enterMode() { 
+    @Override
+    public void enterMode() {
         super.enterMode();
         Main.map.mapView.addMouseListener(this);
@@ -64,9 +51,12 @@
         try {
             Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
-        } catch (SecurityException ex) {}
+        } catch (SecurityException ex) {
+            Main.error(ex);
+        }
 
         MapView.addLayerChangeListener(this);
     }
 
+    @Override
     public void eventDispatched(AWTEvent e) {
         if (e instanceof KeyEvent) {
@@ -79,5 +69,6 @@
     }
 
-    @Override public void exitMode() {
+    @Override
+    public void exitMode() {
         super.exitMode();
         Main.map.mapView.removeMouseListener(this);
@@ -87,5 +78,6 @@
     }
 
-    @Override public void mousePressed(MouseEvent e) {
+    @Override
+    public void mousePressed(MouseEvent e) {
         if (e.getButton() == MouseEvent.BUTTON1) {
             pointPressed = new Point(e.getPoint());
@@ -100,6 +92,7 @@
     }
 
-    @Override public void mouseDragged(MouseEvent e) {
-         if ( (e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) ==  InputEvent.BUTTON1_DOWN_MASK) {
+    @Override
+    public void mouseDragged(MouseEvent e) {
+        if ( (e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) ==  InputEvent.BUTTON1_DOWN_MASK) {
             //if button1 is hold, draw the line
             paintBox(e.getPoint(), radius);
@@ -107,5 +100,6 @@
     }
 
-    @Override public void mouseReleased(MouseEvent e) {
+    @Override
+    public void mouseReleased(MouseEvent e) {
         if (e.getButton() != MouseEvent.BUTTON1) {
             return;
@@ -113,18 +107,17 @@
         // give mapView back its mouse wheel
         for (MouseWheelListener l : mapViewWheelListeners) {
-             if (l != this)
-                 Main.map.mapView.addMouseWheelListener(l);
+            if (l != this)
+                Main.map.mapView.addMouseWheelListener(l);
         }
 
         xorDrawBox(pointPressed, oldP2, radius); // clear box
 
-        // Collection <CachedLatLon> selectedCLLs = getSelectedGPXCLLs(pointPressed, e.getPoint());
         GPSBlamInputData inputData = new GPSBlamInputData(pointPressed, e.getPoint(), radius);
         if (!inputData.isEmpty()) {
             if(currentBlamLayer == null) {
                 currentBlamLayer = new GPSBlamLayer(tr("GPSBlam"));
-                Main.main.addLayer(currentBlamLayer);           
-            }
-             currentBlamLayer.addBlamMarker(new GPSBlamMarker(inputData));
+                Main.main.addLayer(currentBlamLayer);
+            }
+            currentBlamLayer.addBlamMarker(new GPSBlamMarker(inputData));
             Main.map.mapView.repaint();
         }
@@ -133,15 +126,16 @@
     }
 
-    public void changeRadiusBy(int delta) {
+    private void changeRadiusBy(int delta) {
         if (pointPressed != null) {
-            int new_radius = radius + delta;
-            if (new_radius < 1)
-                new_radius = 1;
-            paintBox(oldP2, new_radius);
-            radius = new_radius;
-        }
-    }
-    
-    @Override public void mouseWheelMoved(MouseWheelEvent e) {
+            int newRadius = radius + delta;
+            if (newRadius < 1)
+                newRadius = 1;
+            paintBox(oldP2, newRadius);
+            radius = newRadius;
+        }
+    }
+
+    @Override
+    public void mouseWheelMoved(MouseWheelEvent e) {
         if ( (e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) ==  InputEvent.BUTTON1_DOWN_MASK) {
             changeRadiusBy(-e.getWheelRotation());
@@ -154,21 +148,22 @@
             g.setXORMode(Color.BLACK);
             g.setColor(Color.WHITE);
-            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);// AA+XOR broken in some versions of Java
+            // AA+XOR broken in some versions of Java
+            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
             g.setStroke(new BasicStroke(2.0f));
             if (p2==null)
                 p2 = p1;
-            double length = Math.sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y)); 
+            double length = Math.sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
             if (length > 0) {
-                double dir_x = (p2.x-p1.x)/length, dir_y = (p2.y-p1.y)/length; // unit direction vector from p1.x,p1.y to p2.x, p2.y
-                double perpdir_x = dir_y, perpdir_y = -dir_x; // unit vector 90deg CW from direction vector
-                double angle = Math.atan2(-perpdir_y, perpdir_x); // polar angle of perpdir 
-                double ofs_x = radius * perpdir_x, ofs_y = radius * perpdir_y; // radius vector, 90deg CW from dir vector
+                double dirX = (p2.x-p1.x)/length, dirY = (p2.y-p1.y)/length; // unit direction vector from p1.x,p1.y to p2.x, p2.y
+                double perpdirX = dirY, perpdirY = -dirX; // unit vector 90deg CW from direction vector
+                double angle = Math.atan2(-perpdirY, perpdirX); // polar angle of perpdir
+                double ofsX = radius * perpdirX, ofsY = radius * perpdirY; // radius vector, 90deg CW from dir vector
 
                 Path2D path = new Path2D.Double();
-                path.append(new Line2D.Double(p1.x+ofs_x, p1.y+ofs_y,p2.x+ofs_x, p2.y+ofs_y), false);
-                path.append(new Arc2D.Double(p2.x-radius, p2.y-radius,radius*2, radius*2, 
+                path.append(new Line2D.Double(p1.x+ofsX, p1.y+ofsY,p2.x+ofsX, p2.y+ofsY), false);
+                path.append(new Arc2D.Double(p2.x-radius, p2.y-radius,radius*2, radius*2,
                         Math.toDegrees(angle), -180, Arc2D.OPEN), true);
-                path.append(new Line2D.Double(p2.x-ofs_x, p2.y-ofs_y,p1.x-ofs_x, p1.y-ofs_y), true);
-                path.append(new Arc2D.Double(p1.x-radius, p1.y-radius,radius*2, radius*2, 
+                path.append(new Line2D.Double(p2.x-ofsX, p2.y-ofsY,p1.x-ofsX, p1.y-ofsY), true);
+                path.append(new Arc2D.Double(p1.x-radius, p1.y-radius,radius*2, radius*2,
                         Math.toDegrees(angle)-180, -180, Arc2D.OPEN), true);
                 path.closePath();
@@ -178,6 +173,6 @@
                     g.setXORMode(Color.BLACK);
                     g.setColor(Color.WHITE);
-                    g.drawOval((int)Math.round(p2.x-radius), (int)Math.round(p2.y-radius), 
-                    (int)Math.round(radius*2), (int)Math.round(radius*2));
+                    g.drawOval(Math.round(p2.x-radius), Math.round(p2.y-radius),
+                    Math.round(radius*2), Math.round(radius*2));
                 } catch (InternalError e) {
                     // Robustness against Java bug https://bugs.openjdk.java.net/browse/JDK-8041647
@@ -190,13 +185,13 @@
     }
 
-    private void paintBox(Point p2, int new_radius) {
+    private void paintBox(Point p2, int newRadius) {
         if (frame != null) {
             if (oldP2 != null) {
                 xorDrawBox(pointPressed, oldP2, radius); // clear old box
             }
-            xorDrawBox(pointPressed, p2, new_radius); // draw new box
+            xorDrawBox(pointPressed, p2, newRadius); // draw new box
             oldP2 = p2;
         }
-    }    
+    }
 
     public void setFrame(MapFrame mapFrame) {
@@ -206,8 +201,10 @@
     @Override
     public void activeLayerChange(Layer arg0, Layer arg1) {
+        // Do nothing
     }
 
     @Override
     public void layerAdded(Layer arg0) {
+        // Do nothing
     }
 
Index: applications/editors/josm/plugins/gpsblam/src/org/openstreetmap/josm/plugins/gpsblam/GPSBlamPlugin.java
===================================================================
--- applications/editors/josm/plugins/gpsblam/src/org/openstreetmap/josm/plugins/gpsblam/GPSBlamPlugin.java	(revision 30760)
+++ applications/editors/josm/plugins/gpsblam/src/org/openstreetmap/josm/plugins/gpsblam/GPSBlamPlugin.java	(revision 30761)
@@ -1,25 +1,6 @@
-/** GPSBlam JOSM Plugin
- * Copyright (C) 2012 Russell Edwards
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
+// License: GPL. Copyright (C) 2012 Russell Edwards
 package org.openstreetmap.josm.plugins.gpsblam;
 
 import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.net.URL;
-
-import javax.swing.ImageIcon;
 
 import org.openstreetmap.josm.Main;
@@ -29,9 +10,18 @@
 import org.openstreetmap.josm.plugins.PluginInformation;
 
+/**
+ * GPSBlam is a JOSM plugin designed to exploit the availability of multiple GPS tracks over the same straight-line path,
+ * to obtain a handle on the location and direction of the path with optimal accuracy.
+ * This can be useful to nail down any offsets in existing content or imagery.
+ */
 public class GPSBlamPlugin extends Plugin {
 
-    private IconToggleButton btn;
-    private GPSBlamMode mode;
+    private final IconToggleButton btn;
+    private final GPSBlamMode mode;
 
+    /**
+     * Constructs a new {@code GPSBlamPlugin}.
+     * @param info plugin info
+     */
     public GPSBlamPlugin(PluginInformation info) {
         super(info);
@@ -41,18 +31,11 @@
         btn.setVisible(true);
     }
- 
+
     @Override
     public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
         mode.setFrame(newFrame);
-        if (oldFrame == null && newFrame != null) {
-            if (Main.map != null)
-                Main.map.addMapMode(btn);
+        if (oldFrame == null && newFrame != null && Main.map != null) {
+            Main.map.addMapMode(btn);
         }
     }
-    public static ImageIcon loadIcon(String name) {
-        URL url = GPSBlamPlugin.class.getResource("/images/gpsblam.png");
-        return new ImageIcon(url);
-    }
-
-
 }
