Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/PicLayerPlugin.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/PicLayerPlugin.java	(revision 35003)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/PicLayerPlugin.java	(revision 35005)
@@ -36,4 +36,5 @@
 import org.openstreetmap.josm.plugins.piclayer.actions.transform.affine.RemovePointAction;
 import org.openstreetmap.josm.plugins.piclayer.actions.transform.affine.TransformPointAction;
+import org.openstreetmap.josm.plugins.piclayer.actions.transform.autocalibrate.AutoCalibratePictureAction;
 import org.openstreetmap.josm.plugins.piclayer.layer.PicLayerAbstract;
 
@@ -84,4 +85,6 @@
             ScaleYPictureAction scaleYPictureAction = new ScaleYPictureAction();
             ShearPictureAction shearPictureAction = new ShearPictureAction();
+            AutoCalibratePictureAction autoCalibratePictureAction = new AutoCalibratePictureAction();
+
             // Create plugin buttons and add them to the toolbar
 
@@ -96,4 +99,5 @@
             buttonList.add(picLayerActionButtonFactory(scaleYPictureAction));
             buttonList.add(picLayerActionButtonFactory(shearPictureAction));
+            buttonList.add(picLayerActionButtonFactory(autoCalibratePictureAction));
 
             for (IconToggleButton btn : buttonList) {
@@ -120,9 +124,9 @@
 
         if (oldPic) {
-            ((PicLayerAbstract) oldLayer).setDrawPoints(false);
+            ((PicLayerAbstract) oldLayer).setDrawOriginPoints(false);
         }
 
         if (newPic) {
-            ((PicLayerAbstract) newLayer).setDrawPoints(true);
+            ((PicLayerAbstract) newLayer).setDrawOriginPoints(true);
         }
     }
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/GenericPicTransformAction.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/GenericPicTransformAction.java	(revision 35003)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/GenericPicTransformAction.java	(revision 35005)
@@ -103,5 +103,5 @@
         Layer active = MainApplication.getLayerManager().getActiveLayer();
         if (active instanceof PicLayerAbstract) {
-            ((PicLayerAbstract) active).setDrawPoints(value);
+            ((PicLayerAbstract) active).setDrawOriginPoints(value);
             active.invalidate();
         }
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/newlayer/NewLayerFromClipboardAction.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/newlayer/NewLayerFromClipboardAction.java	(revision 35003)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/newlayer/NewLayerFromClipboardAction.java	(revision 35005)
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/newlayer/NewLayerFromFileAction.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/newlayer/NewLayerFromFileAction.java	(revision 35003)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/newlayer/NewLayerFromFileAction.java	(revision 35005)
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/MovePictureAction.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/MovePictureAction.java	(revision 35003)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/MovePictureAction.java	(revision 35005)
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/RotatePictureAction.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/RotatePictureAction.java	(revision 35003)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/RotatePictureAction.java	(revision 35005)
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScaleXPictureAction.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScaleXPictureAction.java	(revision 35003)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScaleXPictureAction.java	(revision 35005)
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScaleXYPictureAction.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScaleXYPictureAction.java	(revision 35003)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScaleXYPictureAction.java	(revision 35005)
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScaleYPictureAction.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScaleYPictureAction.java	(revision 35003)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/ScaleYPictureAction.java	(revision 35005)
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/affine/MovePointAction.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/affine/MovePointAction.java	(revision 35003)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/affine/MovePointAction.java	(revision 35005)
@@ -8,7 +8,12 @@
 import java.awt.geom.Point2D;
 
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.coor.conversion.CoordinateFormatManager;
+import org.openstreetmap.josm.data.coor.conversion.ICoordinateFormat;
+import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.plugins.piclayer.actions.GenericPicTransformAction;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
+
 
 /**
@@ -41,4 +46,6 @@
 
         try {
+        	setLatLonOriginPoints(e.getPoint());	// collect lat/lon data points for auto calibration
+
             Point2D pressed = currentLayer.transformPoint(e.getPoint());
             if (selectedPoint == null)
@@ -62,3 +69,17 @@
         updateDrawPoints(false);
     }
+
+    /**
+     * Method to collect raw data points for additional auto calibration and transforms them into LatLon.
+     * Transformed points will be stored into {@code PictureTransform } attribute to make them accessible for actions.
+     * @param point to collect
+     */
+    private void setLatLonOriginPoints(Point2D point) {
+    	LatLon latLonPoint = MainApplication.getMap().mapView.getLatLon(point.getX(), point.getY());
+        ICoordinateFormat mCoord = CoordinateFormatManager.getDefaultFormat();
+        double latY = Double.parseDouble(mCoord.latToString(latLonPoint));
+        double lonX = Double.parseDouble(mCoord.lonToString(latLonPoint));
+        currentLayer.getTransformer().addLatLonOriginPoint(new Point2D.Double(lonX, latY));
+    }
+
 }
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/affine/RemovePointAction.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/affine/RemovePointAction.java	(revision 35003)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/affine/RemovePointAction.java	(revision 35005)
@@ -25,4 +25,5 @@
 
         if (selectedPoint != null) {
+          	currentLayer.getTransformer().removeLatLonOriginPoint(selectedPoint);
             currentLayer.getTransformer().removeOriginPoint(selectedPoint);
             selectedPoint = null;
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/autocalibrate/AutoCalibrateHandler.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/autocalibrate/AutoCalibrateHandler.java	(revision 35005)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/autocalibrate/AutoCalibrateHandler.java	(revision 35005)
@@ -0,0 +1,553 @@
+package org.openstreetmap.josm.plugins.piclayer.actions.transform.autocalibrate;
+
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Point2D;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+
+import org.openstreetmap.josm.actions.OpenFileAction;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.coor.conversion.CoordinateFormatManager;
+import org.openstreetmap.josm.data.coor.conversion.ICoordinateFormat;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.MapViewState.MapViewPoint;
+import org.openstreetmap.josm.gui.help.HelpBrowser;
+import org.openstreetmap.josm.plugins.piclayer.actions.transform.affine.MovePointAction;
+import org.openstreetmap.josm.plugins.piclayer.actions.transform.autocalibrate.helper.ObservableArrayList;
+import org.openstreetmap.josm.plugins.piclayer.gui.autocalibrate.CalibrationErrorView;
+import org.openstreetmap.josm.plugins.piclayer.gui.autocalibrate.CalibrationWindow;
+import org.openstreetmap.josm.plugins.piclayer.gui.autocalibrate.ReferenceOptionView;
+import org.openstreetmap.josm.plugins.piclayer.gui.autocalibrate.ResultCheckView;
+import org.openstreetmap.josm.plugins.piclayer.layer.PicLayerAbstract;
+
+/**
+ * Class providing functionality of GUIs and also handles connection between {@link AutoCalibratePictureAction}
+ * and GUIs what means is basic class to provide the functionality of calibration.
+ * Info at https://wiki.openstreetmap.org/wiki/User:Rebsc
+ * @author rebsc
+ *
+ */
+public class AutoCalibrateHandler {
+
+	private PicLayerAbstract currentPicLayer;
+	private CalibrationWindow mainWindow;
+	private CalibrationErrorView errorView;
+	private ReferenceOptionView refOptionView;
+	private File referenceFile;
+	private AutoCalibrator calibrator;
+	private ObservableArrayList<Point2D> originPointList;		// points set on picture to calibrate, scaled in LatLon
+	private ObservableArrayList<Point2D> referencePointList;	// points of reference data, scaled in LatLon
+	private double distance1To2;	// in meter
+	private double distance2To3;	// in meter
+
+
+
+	public AutoCalibrateHandler(){
+		this.originPointList = new ObservableArrayList<>(3);
+		this.referencePointList = new ObservableArrayList<>(3);
+		this.distance1To2 = 0.0;
+		this.distance2To3 = 0.0;
+		this.referenceFile = null;
+		this.currentPicLayer = null;
+		this.mainWindow = new CalibrationWindow();
+		addListenerToMainView();
+		this.calibrator = new AutoCalibrator();
+	}
+
+	/**
+	 * Method to call calibrating method for given image.
+	 */
+	private void callCalibrator(){
+		if(currentPicLayer != null && originPointList.size() > 0 && referencePointList.size() > 0
+				&& distance1To2 != 0.0 && distance2To3 != 0.0) {
+					calibrator.setCurrentLayer(currentPicLayer);
+					calibrator.setStartPositions(this.originPointList);
+					calibrator.setEndPositions(this.referencePointList);
+					calibrator.setDistance1To2(distance1To2);
+					calibrator.setDistance2To3(distance2To3);
+					calibrator.calibrate();
+		}
+		else	calibrator.showErrorView(CalibrationErrorView.CALIBRATION_ERROR);
+	}
+
+
+	// MAIN WINDOW LISTENER
+
+	/**
+	* Method adds listener to main view
+	*/
+	private void addListenerToMainView() {
+		if(this.mainWindow != null) {
+			this.mainWindow.addHelpButtonListener(new HelpButtonListener());
+			this.mainWindow.addEdgePointButtonListener(new EdgePointsButtonListener());
+			this.mainWindow.addDistance1FieldListener(new TextField1Listener());
+			this.mainWindow.addDistance2FieldListener(new TextField2Listener());
+			this.mainWindow.addOpenFileButtonListener(new OpenFileButtonListener());
+			this.mainWindow.addReferencePointButtonListener(new RefPointsButtonListener());
+			this.mainWindow.addCancelButtonListener(new CancelButtonListener());
+			this.mainWindow.addRunButtonListener(new RunButtonListener());
+			this.mainWindow.addFrameWindowListener(getToolWindowListener());
+		}
+	}
+
+	/**
+	* Help button listener
+	* @author rebsc
+	*
+	*/
+	private class HelpButtonListener implements ActionListener {
+		@Override
+		public void actionPerformed(ActionEvent e) {
+			String topic = "Plugin/PicLayer";
+	        // open help browser
+	        HelpBrowser.setUrlForHelpTopic(Optional.ofNullable(topic).orElse("/"));
+		}
+	}
+
+	/**
+	* Open file button listener
+	* @author rebsc
+	*
+	*/
+	private class OpenFileButtonListener implements ActionListener {
+		private JButton openButton;
+		private JFileChooser fileChooser;
+
+		@Override
+		public void actionPerformed(ActionEvent event) {
+			mainWindow.setVisible(false);
+			openButton = mainWindow.getOpenButton();
+			fileChooser = mainWindow.getFileChooser();
+
+			if (event.getSource() == openButton) {
+				int openValue = fileChooser.showOpenDialog(mainWindow);
+			    if (openValue == JFileChooser.APPROVE_OPTION) {
+			    	referenceFile = fileChooser.getSelectedFile();
+			    	addFileInNewLayer(referenceFile);
+			    }
+			}
+			if(referenceFile != null) {
+				mainWindow.setReferenceFileNameValue(referenceFile.getName());
+				mainWindow.setVisible(true);
+			}
+			mainWindow.setVisible(true);
+		}
+	}
+
+	/**
+	 * Cancel button listener
+	 * @author rebsc
+	 *
+	 */
+	private class CancelButtonListener implements ActionListener {
+		@Override
+	    public void actionPerformed(ActionEvent e) {
+			reset();
+	    }
+	}
+
+	/**
+	 * Run button listener
+	 * @author rebsc
+	 *
+	 */
+	private class RunButtonListener implements ActionListener {
+		@Override
+	    public void actionPerformed(ActionEvent e) {
+			// calibrate
+			callCalibrator();
+			mainWindow.setVisible(false);
+			currentPicLayer.clearDrawReferencePoints();
+			currentPicLayer.invalidate();
+			MainApplication.getLayerManager().setActiveLayer(currentPicLayer);
+			// let user check calibration
+			ResultCheckView checkView = new ResultCheckView();
+			int selectedValue = checkView.showAndChoose();
+			if(selectedValue == 1) {
+				currentPicLayer.getTransformer().resetCalibration();
+				currentPicLayer.invalidate();
+			}
+	    }
+	}
+
+	/**
+	 * Edge button listener
+	 * @author rebsc
+	 *
+	 */
+	private class EdgePointsButtonListener implements ActionListener {
+		@Override
+	    public void actionPerformed(ActionEvent e) {
+				mainWindow.setVisible(false);
+				MainApplication.getLayerManager().setActiveLayer(currentPicLayer);
+				// switch to select mode
+				MovePointAction selectPointMode = new MovePointAction();
+				MainApplication.getMap().selectMapMode(selectPointMode);
+		}
+	}
+
+	/**
+	* Method to get windowListener for main window
+	* @return adapter
+	*/
+	private WindowAdapter getToolWindowListener() {
+		WindowAdapter adapter = new WindowAdapter() {
+	    	@Override
+		    public void windowDeactivated(WindowEvent wEvt) {
+	    		((JFrame)wEvt.getSource()).toFront();
+		    }
+
+	    	@Override
+	    	public void windowClosing(WindowEvent wEvt) {
+	    		reset();
+	    	}
+		};
+		return adapter;
+	}
+
+	/**
+	 * Origin points list listener
+	 * @author rebsc
+	 *
+	 */
+	private class OriginSizePropertyListener implements PropertyChangeListener {
+	    @Override
+	    public void propertyChange(PropertyChangeEvent event) {
+	    	String propName = event.getPropertyName();
+	    	int size = Integer.parseInt(propName.replaceAll("\\D", ""));
+	    	if(currentPicLayer.getTransformer().getLatLonOriginPoints() != null) {
+	    		originPointList.clear();
+	    		originPointList.addAll(currentPicLayer.getTransformer().getLatLonOriginPoints());
+	    		mainWindow.setOriginPoints(originPointList);
+	    	}
+
+	        if (size == 3) {
+	        	mainWindow.setVisible(true);
+	        	currentPicLayer.getTransformer().getLatLonOriginPoints().removePropertyChangeListener(this);
+	        }
+	    }
+	}
+
+	/**
+	 * Reference points list listener
+	 * @author rebsc
+	 *
+	 */
+	private class RefSizePropertyListener implements PropertyChangeListener {
+	    @Override
+	    public void propertyChange(PropertyChangeEvent event) {
+	    	String propName = event.getPropertyName();
+	    	int size = Integer.parseInt(propName.replaceAll("\\D", ""));
+	        mainWindow.setReferencePoints(referencePointList);
+
+	        if (size == 3) {
+	        	mainWindow.setVisible(true);
+	        	referencePointList.removePropertyChangeListener(this);
+	        }
+	    }
+	}
+
+	/**
+	 * Distance point 1 to point 2 field listener
+	 * @author rebsc
+	 *
+	 */
+	private class TextField1Listener implements FocusListener {
+		@Override
+		public void focusGained(FocusEvent e) {
+			currentPicLayer.setDrawFirstLine(true);
+			currentPicLayer.invalidate();
+			mainWindow.setDistance1Field("");
+		}
+		@Override
+		public void focusLost(FocusEvent e) {
+			currentPicLayer.setDrawFirstLine(false);
+			currentPicLayer.invalidate();
+
+			String value = mainWindow.getDistance1FieldText();
+			if(validValue(value)) {
+				mainWindow.getDistance1Field().selectAll();
+				mainWindow.setDistance1Value(value);
+				mainWindow.refresh();
+				distance1To2 = Double.parseDouble(value);
+			}
+		}
+	}
+
+	/**
+	 * Distance point 2 to point 3 field listener
+	 * @author rebsc
+	 *
+	 */
+	private class TextField2Listener implements FocusListener {
+		@Override
+		public void focusGained(FocusEvent e) {
+			currentPicLayer.setDrawSecLine(true);
+			currentPicLayer.invalidate();
+			mainWindow.setDistance2Field("");
+		}
+		@Override
+		public void focusLost(FocusEvent e) {
+			currentPicLayer.setDrawSecLine(false);
+			currentPicLayer.invalidate();
+
+			String value = mainWindow.getDistance2FieldText();
+			if(validValue(value)) {
+				mainWindow.getDistance2Field().selectAll();
+				mainWindow.setDistance2Value(value);
+				mainWindow.refresh();
+				distance2To3 = Double.parseDouble(value);
+			}
+		}
+	}
+
+	/**
+	 * Reference add points button listener
+	 * @author rebsc
+	 *
+	 */
+	private class RefPointsButtonListener implements ActionListener {
+		@Override
+	    public void actionPerformed(ActionEvent e) {
+			mainWindow.setVisible(false);
+			refOptionView = new ReferenceOptionView();
+			int selectedValue = refOptionView.showAndChoose();
+
+			if(selectedValue == 0) {	// defined
+				MainApplication.getMap().mapView.addMouseListener(new RefDefinedPointsMouseListener());
+			}
+			else if(selectedValue == 1) {	// manual
+				MainApplication.getMap().mapView.addMouseListener(new RefManualPointsMouseListener());
+			}
+	    }
+	}
+
+	/**
+	 * Mouse listener for manual reference selection option
+	 * @author rebsc
+	 *
+	 */
+	private class RefManualPointsMouseListener implements MouseListener {
+		@Override
+		public void mouseClicked(MouseEvent e) {
+			if(referenceFile == null) {
+				MainApplication.getMap().mapView.removeMouseListener(this);
+				return;
+			}
+
+			if(referencePointList.size() < 3) {
+				// add point to reference list in lat/lon scale
+				LatLon latLonPoint = MainApplication.getMap().mapView.getLatLon(e.getPoint().getX(),e.getPoint().getY());
+				ICoordinateFormat mCoord = CoordinateFormatManager.getDefaultFormat();
+				double latY = Double.parseDouble(mCoord.latToString(latLonPoint));
+				double lonX = Double.parseDouble(mCoord.lonToString(latLonPoint));
+				Point2D llPoint = new Point2D.Double(lonX, latY);
+				referencePointList.add(llPoint);
+				// draw point
+				currentPicLayer.setDrawReferencePoints(true, translatePointToPicLayerScale(llPoint));
+				currentPicLayer.invalidate();
+			}
+		}
+
+		@Override
+		public void mousePressed(MouseEvent e) {
+			// do nothing
+		}
+
+		@Override
+		public void mouseReleased(MouseEvent e) {
+			// do nothing
+		}
+
+		@Override
+		public void mouseEntered(MouseEvent e) {
+			// do nothing
+		}
+
+		@Override
+		public void mouseExited(MouseEvent e) {
+			// do nothing
+		}
+	}
+
+	/**
+	 * Mouse listener for defined reference selection option
+	 * @author rebsc
+	 *
+	 */
+	private class RefDefinedPointsMouseListener implements MouseListener {
+		@Override
+		public void mouseClicked(MouseEvent e) {
+			if(referenceFile == null) {
+				MainApplication.getMap().mapView.removeMouseListener(this);
+				return;
+			}
+
+			if(referencePointList.size() < 3) {
+				// get pressed point in lat/lon
+				LatLon latLonPoint = MainApplication.getMap().mapView.getLatLon(e.getPoint().getX(),e.getPoint().getY());
+				ICoordinateFormat mCoord = CoordinateFormatManager.getDefaultFormat();
+				double latY = Double.parseDouble(mCoord.latToString(latLonPoint));
+				double lonX = Double.parseDouble(mCoord.lonToString(latLonPoint));
+				Point2D llPoint = new Point2D.Double(lonX, latY);
+
+				// get current data set and find closest point
+				Point2D closestPoint = null;
+				double shortestDistance = 1000000.0;	// default value
+				double tmpDistance;
+				DataSet data = MainApplication.getLayerManager().getEditDataSet();
+
+				for(Node node : data.getNodes()) {
+					tmpDistance = llPoint.distance(node.lon(), node.lat());
+
+					if(tmpDistance < shortestDistance) {
+						closestPoint = new Point2D.Double(node.lon(), node.lat());
+						shortestDistance = tmpDistance;
+					}
+				}
+
+				if(closestPoint != null) {
+					// add closest point to reference list
+					referencePointList.add(closestPoint);
+					// draw point
+					currentPicLayer.setDrawReferencePoints(true, translatePointToPicLayerScale(closestPoint));
+					currentPicLayer.invalidate();
+				}
+			}
+		}
+
+		@Override
+		public void mousePressed(MouseEvent e) {
+			// do nothing
+		}
+
+		@Override
+		public void mouseReleased(MouseEvent e) {
+			// do nothing
+		}
+
+		@Override
+		public void mouseEntered(MouseEvent e) {
+			// do nothing
+		}
+
+		@Override
+		public void mouseExited(MouseEvent e) {
+			// do nothing
+		}
+	}
+
+
+	// GETTER / SETTER
+
+	public CalibrationWindow getMainWindow() {
+		return this.mainWindow;
+	}
+
+	public CalibrationErrorView getErrorView() {
+		this.errorView = new CalibrationErrorView();
+		return errorView;
+	}
+
+
+	// HELPER
+
+	private void addFileInNewLayer(File file) {
+		List<File> files = new ArrayList<>();
+		files.add(file);
+		OpenFileAction.openFiles(files);
+	}
+
+	public void prepare(PicLayerAbstract layer) {
+		this.currentPicLayer = layer;
+		addListChangedListenerToPointLists();
+		// if origin points, add them
+		ObservableArrayList<Point2D> list = layer.getTransformer().getLatLonOriginPoints();
+		if(list != null && list.size() == 3) {
+			this.originPointList = list;
+			this.mainWindow.setOriginPoints(originPointList);
+		}
+		else {
+			resetLists();
+		}
+	}
+
+	private void addListChangedListenerToPointLists() {
+		OriginSizePropertyListener originListener = new OriginSizePropertyListener();
+		currentPicLayer.getTransformer().getLatLonOriginPoints().addPropertyChangeListener(originListener);
+		RefSizePropertyListener refListener = new RefSizePropertyListener();
+		this.referencePointList.addPropertyChangeListener(refListener);
+	}
+
+	/**
+	 * Method to translate {@code Point2D} to {@link PicLayerAbstract} scale.
+	 * @param point to translate in LatLon
+	 * @return translated point in {@link PicLayerAbstract} scale
+	 */
+	private Point2D translatePointToPicLayerScale(Point2D point) {
+		Point2D translatedPoint = null;
+		LatLon ll;				// LatLon object from raw Point2D
+		MapViewPoint en;		// MapViewPoint object from LatLon(ll) scaled in EastNorth(en)
+
+		// put raw Point2D endPos into LatLon and transform LatLon into MapViewPoint (EastNorth)
+		ll = new LatLon(point.getY(), point.getX());
+		en = MainApplication.getMap().mapView.getState().getPointFor(ll);
+
+		// transform EastNorth into current layer scale
+		try {
+			translatedPoint = currentPicLayer.transformPoint(new Point2D.Double(en.getInViewX(), en.getInViewY()));
+		} catch (NoninvertibleTransformException e) {
+			e.printStackTrace();
+		}
+
+		return translatedPoint;
+	}
+
+	private boolean validValue(String value) {
+		try {
+			Double.parseDouble(value);
+			return true;
+		} catch (NullPointerException | NumberFormatException ex) {
+			return false;
+		}
+	}
+
+	private void reset() {
+		originPointList = new ObservableArrayList<>(3);
+		referencePointList = new ObservableArrayList<>(3);
+		distance1To2 = 0.0;
+		distance2To3 = 0.0;
+		this.referenceFile = null;
+		resetLists();
+		currentPicLayer.clearDrawReferencePoints();
+		currentPicLayer.invalidate();
+		mainWindow.setVisible(false);
+		mainWindow = new CalibrationWindow();
+		addListenerToMainView();
+	}
+
+	private void resetLists() {
+		currentPicLayer.getTransformer().clearOriginPoints();
+		currentPicLayer.getTransformer().clearLatLonOriginPoints();
+	}
+
+}
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/autocalibrate/AutoCalibratePictureAction.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/autocalibrate/AutoCalibratePictureAction.java	(revision 35005)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/autocalibrate/AutoCalibratePictureAction.java	(revision 35005)
@@ -0,0 +1,63 @@
+package org.openstreetmap.josm.plugins.piclayer.actions.transform.autocalibrate;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.MouseEvent;
+import java.util.logging.Logger;
+
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.plugins.piclayer.actions.GenericPicTransformAction;
+import org.openstreetmap.josm.plugins.piclayer.gui.autocalibrate.CalibrationWindow;
+import org.openstreetmap.josm.plugins.piclayer.layer.PicLayerAbstract;
+import org.openstreetmap.josm.tools.ImageProvider;
+
+/**
+ * Class providing auto calibration action.
+ * This class works with {@link AutoCalibrateHandler} class as handler to call calibration action
+ * and manage necessary GUIs.
+ * Info at https://wiki.openstreetmap.org/wiki/User:Rebsc
+ * @author rebsc
+ *
+ */
+public class AutoCalibratePictureAction extends GenericPicTransformAction {
+
+	private static final Logger logger = Logger.getLogger(AutoCalibratePictureAction.class.getName());
+	private AutoCalibrateHandler calibrationHandler;
+	private CalibrationWindow calibrationWindow;
+
+
+	public AutoCalibratePictureAction() {
+		super(tr("PicLayer auto calibration"), tr("Calibrated"),"autoCalibrate", tr("Calibrate picture with outline"),
+				ImageProvider.getCursor("crosshair", null));
+		logger.info(this.getClass().getName() + " has been created.");
+
+    	calibrationHandler = new AutoCalibrateHandler();
+	}
+
+	@Override
+	protected void doAction(MouseEvent e) {
+		// do nothing
+	}
+
+    @Override
+    public void enterMode() {
+    	super.enterMode();
+    	updateDrawPoints(true);
+
+		currentLayer = (PicLayerAbstract) MainApplication.getLayerManager().getActiveLayer();
+
+		if(currentLayer != null && currentLayer instanceof PicLayerAbstract) {
+			calibrationHandler.prepare(currentLayer);
+			calibrationWindow = calibrationHandler.getMainWindow();
+			calibrationWindow.setVisible(true);
+		}
+
+    }
+
+    @Override
+    public void exitMode() {
+        super.exitMode();
+        updateDrawPoints(false);
+    }
+
+}
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/autocalibrate/AutoCalibrator.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/autocalibrate/AutoCalibrator.java	(revision 35005)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/autocalibrate/AutoCalibrator.java	(revision 35005)
@@ -0,0 +1,238 @@
+package org.openstreetmap.josm.plugins.piclayer.actions.transform.autocalibrate;
+
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.MapViewState.MapViewPoint;
+import org.openstreetmap.josm.plugins.piclayer.PicLayerPlugin;
+import org.openstreetmap.josm.plugins.piclayer.actions.transform.autocalibrate.helper.GeoLine;
+import org.openstreetmap.josm.plugins.piclayer.gui.autocalibrate.CalibrationErrorView;
+import org.openstreetmap.josm.plugins.piclayer.layer.PicLayerAbstract;
+
+
+/**
+ * Class for image calibration.
+ * The startPositions, endPositions representing points set on the image with using {@link PicLayerPlugin} actions.
+ * Info at https://wiki.openstreetmap.org/wiki/User:Rebsc
+ * @author rebsc
+ *
+ */
+public class AutoCalibrator {
+
+	private PicLayerAbstract currentLayer;
+	private List<Point2D> startPositions;	// raw data - LatLon scale
+	private List<Point2D> endPositions;		// raw data - LatLon scale
+	private double distance1To2;	// in meter
+	private double distance2To3;	// in meter
+
+
+
+	public AutoCalibrator() {
+		this.currentLayer = null;
+		this.startPositions = new ArrayList<>(3);
+		this.endPositions = new ArrayList<>(3);
+		this.distance1To2 = 0.0;
+		this.distance2To3 = 0.0;
+	}
+
+	/**
+	 * Calibrator - collects raw data for calibration
+	 * @param abstractLayer {@link PicLayerAbstract} - currentLayer
+	 * @param startPoints representing points set on the image with using {@link PicLayerPlugin} actions, raw data - LatLon scale
+	 * @param endPoints representing points set on the image with using {@link PicLayerPlugin} actions, raw data - LatLon scale
+	 * @param distance12 distance from point 1 to point 2 in startPoints - entered with using PicLayerPlugin actions. Scaled in meter.
+	 * @param distance23 distance from point 2 to point 3 in startPoints - entered with using PicLayerPlugin actions. Scaled in meter.
+	 */
+	public AutoCalibrator(PicLayerAbstract abstractLayer, List<Point2D> startPoints, List<Point2D> endPoints,
+			double distance12, double distance23) {
+		this.currentLayer = abstractLayer;
+		this.startPositions = startPoints;
+		this.endPositions = endPoints;
+		this.distance1To2 = distance12;
+		this.distance2To3 = distance23;
+	}
+
+
+	/**
+	 * Calibrates Image with given data.
+	 * Corrects end points by passed real distances between points.
+	 * Sets star points to end points.
+	 */
+	public void calibrate() {
+		// get start / end points
+		List<Point2D> startPointList = currentLayer.getTransformer().getOriginPoints();				// in current layer scale
+		List<Point2D> endPointList = correctedPoints(endPositions, distance1To2, distance2To3);		// in lat/lon scale - translation follows
+
+		// calibrate
+		if(currentLayer != null && startPointList != null && endPointList != null
+				&& startPointList.size() == 3 && endPointList.size() == 3
+				&& distance1To2 != 0.0 && distance2To3 != 0.0) {
+
+			Point2D tsPoint;		// transformed start point
+			Point2D tePoint;		// transformed end point
+			int index;
+
+			// move all points to final state position
+			for(Point2D endPos : endPointList) {
+				// get translated start point suitable to end point
+				index = endPointList.indexOf(endPos);
+				tsPoint = startPointList.get(index);
+
+				// transform end point into current layer scale
+				tePoint = translatePointToCurrentScale(endPos);
+
+				// move start point to end point
+				currentLayer.getTransformer().updatePair(tsPoint, tePoint);
+			}
+
+			// check if image got too distorted after calibration, if, reset and show error.
+			// Input start positions (lat/lon), corrected end positions (lat/lon)
+			if(!checkCalibration(startPositions, endPointList)) {
+				currentLayer.getTransformer().resetCalibration();
+				showErrorView(CalibrationErrorView.DIMENSION_ERROR);
+			}
+		} else {
+			// calibration failed
+			showErrorView(CalibrationErrorView.CALIBRATION_ERROR);
+		}
+
+	}
+
+	/**
+	 * Compare 3 side ratios of first list with 3 side ratios of compare list
+	 * @param list with ratios to compare to other list
+	 * @param compareList with ratios to compare to other list
+	 * @return true if ratios equals in range of (+-)0.5, else false
+	 */
+	private boolean checkCalibration(List<Point2D> list, List<Point2D> compareList) {
+		if(list.size() != 3 || compareList.size() != 3)	return false;
+
+		// check site ratios before and after calibration
+		double dist12 = new GeoLine(list.get(0), list.get(1)).getDistance();
+		double dist23 = new GeoLine(list.get(1), list.get(2)).getDistance();
+		double dist13 = new GeoLine(list.get(0), list.get(2)).getDistance();
+		double[] startRatio = {1, dist23/dist12,  dist13/dist12};
+		double compDist12 = new GeoLine(compareList.get(0), compareList.get(1)).getDistance();
+		double compDist23 = new GeoLine(compareList.get(1), compareList.get(2)).getDistance();
+		double compDist13 = new GeoLine(compareList.get(0), compareList.get(2)).getDistance();
+		double[] compRatio = {1, compDist23/compDist12,  compDist13/compDist12};
+		double epsilon = 0.5;
+
+		if(compRatio[1] >= startRatio[1]-epsilon && compRatio[1] <= startRatio[1]+epsilon
+				&& compRatio[2] >= startRatio[2]-epsilon && compRatio[2] <= startRatio[2]+ epsilon) {
+			return true;
+		}
+		return false;
+	}
+
+
+	/**
+	 * Corrects points with given real distances. Calculates new points on lines
+	 * between given points at given distances.
+	 * @param points need to be corrected
+	 * @param distance12 distance between point 1 and point 2 in meter
+	 * @param distance23 distance between point 2 and point 3 in meter
+	 * @return corrected points
+	 */
+	private List<Point2D> correctedPoints(List<Point2D> points, double distance12, double distance23){
+		if(points != null && points.size() == 3) {
+			List<Point2D> correctedList = new ArrayList<>();
+
+			// get line between point1 and point2
+			GeoLine line12 = new GeoLine(points.get(0), points.get(1));
+			// get line between point2 and point3
+			GeoLine line23 = new GeoLine(points.get(1), points.get(2));
+
+			correctedList.add(points.get(0));	// anchor
+			correctedList.add(line12.pointOnLine(distance12));	// point on line12 at distance12 from start on
+			// get lat/lon offset of line12 point to origin point2
+			double lonOffset = line12.pointOnLine(distance12).getX() - points.get(1).getX();
+			double latOffset = line12.pointOnLine(distance12).getY() - points.get(1).getY();
+			// get point on line23 and add offset - to not deform the image
+			Point2D pointOnLine23 = line23.pointOnLine(distance23);
+			Point2D correctedPointOnLine23 = new Point2D.Double(pointOnLine23.getX()+ lonOffset, pointOnLine23.getY() + latOffset);
+			correctedList.add(correctedPointOnLine23);	// point on line23 at distance23 from start on corrected with offset from point on line12
+
+			return correctedList;
+		}
+		return null;
+	}
+
+	/**
+	 * Method to translate {@code Point2D} to current layer scale.
+	 * @param point to translate in LatLon
+	 * @return translated point in current layer scale
+	 */
+	private Point2D translatePointToCurrentScale(Point2D point) {
+		Point2D translatedPoint = null;
+		LatLon ll;				// LatLon object from raw Point2D
+		MapViewPoint en;		// MapViewPoint object from LatLon(ll) scaled in EastNorth(en)
+
+		// put raw Point2D endPos into LatLon and transform LatLon into MapViewPoint (EastNorth)
+		ll = new LatLon(point.getY(), point.getX());
+		en = MainApplication.getMap().mapView.getState().getPointFor(ll);
+
+		// transform EastNorth into current layer scale
+		try {
+			translatedPoint = currentLayer.transformPoint(new Point2D.Double(en.getInViewX(), en.getInViewY()));
+		} catch (NoninvertibleTransformException e) {
+			e.printStackTrace();
+		}
+
+		return translatedPoint;
+	}
+
+	/**
+	 * Shows error view
+	 * @param msg error msg
+	 */
+	public void showErrorView(String msg) {
+		AutoCalibrateHandler handler = new AutoCalibrateHandler();
+		handler.getErrorView().show(msg);
+	}
+
+
+	// GETTER / SETTER
+
+	public void setCurrentLayer(PicLayerAbstract currentLayer) {
+		this.currentLayer = currentLayer;
+	}
+
+	/**
+	 * Set start positions scaled in Lat/Lon
+	 * @param startPositions calibration start positions
+	 */
+	public void setStartPositions(List<Point2D> startPositions) {
+		this.startPositions = startPositions;
+	}
+
+	/**
+	 * Set end positions scaled in Lat/Lon
+	 * @param endPositions calibration end positions
+	 */
+	public void setEndPositions(List<Point2D> endPositions) {
+		this.endPositions = endPositions;
+	}
+
+	/**
+	 * Set distance from point 1 to point 2 in start positions.
+	 * Scaled in meter.
+	 * @param distance12 distance from point 1 to point 2 in start positions. Scaled in meter.
+	 */
+	public void setDistance1To2(double distance12) {
+		this.distance1To2 = distance12;
+	}
+
+	/**
+	 * Set distance from point 2 to point 3 in start positions.
+	 * Scaled in meter.
+	 * @param distance23 distance from point 1 to point 2 in start positions. Scaled in meter.
+	 */
+	public void setDistance2To3(double distance23) {
+		this.distance2To3 = distance23;
+	}
+}
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/autocalibrate/helper/GeoLine.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/autocalibrate/helper/GeoLine.java	(revision 35005)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/autocalibrate/helper/GeoLine.java	(revision 35005)
@@ -0,0 +1,69 @@
+package org.openstreetmap.josm.plugins.piclayer.actions.transform.autocalibrate.helper;
+
+import java.awt.geom.Point2D;
+
+/**
+ * Class representing GeoLine
+ * Info at https://wiki.openstreetmap.org/wiki/User:Rebsc
+ * @author rebsc
+ *
+ */
+public class GeoLine {
+
+	private double lat1;
+	private double lon1;
+	private double lat2;
+	private double lon2;
+	private double distance;	// in meter
+	private double R = 6371e3;	// earth radius in meter
+
+	public GeoLine(Point2D startPoint, Point2D endPoint) {
+		this.lat1 = startPoint.getY();
+		this.lon1 = startPoint.getX();
+		this.lat2 = endPoint.getY();
+		this.lon2 = endPoint.getX();
+		this.distance = getDistance();
+	}
+
+	public GeoLine(double startLat, double startLon, double endLat, double endLon) {
+		this.lat1 = startLat;
+		this.lon1 = startLon;
+		this.lat2 = endLat;
+		this.lon2 = endLon;
+		this.distance = getDistance();
+	}
+
+	/**
+	 * Method to get point on line at given distance from start point on.
+	 * @param distanceFromStart distance from start point on. Distance in meter.
+	 * @return new point on line.
+	 */
+	public Point2D pointOnLine(double distanceFromStart) {
+		double newLat = lat1 + (lat2 - lat1) * (distanceFromStart / distance);
+		double newLon = lon1 + (lon2 - lon1) * (distanceFromStart / distance);
+		return new Point2D.Double(newLon, newLat);
+	}
+
+	/**
+	 * Haversine formula
+	 * @return distance in meter
+	 */
+	public double getDistance() {
+		double phi1 = degToRad(lat1);
+		double phi2 = degToRad(lat2);
+		double deltaPhi = degToRad(lat2 - lat1);
+		double deltaLambda = degToRad(lon2 - lon1);
+
+		double a = Math.sin(deltaPhi / 2.0) * Math.sin(deltaPhi / 2.0)
+					+ Math.cos(phi1) * Math.cos(phi2) * Math.sin(deltaLambda / 2.0) * Math.sin(deltaLambda / 2.0);
+
+		double c = 2.0 * Math.atan2(Math.sqrt(a), Math.sqrt(1.0-a));
+
+		return R * c;
+	}
+
+	private double degToRad(double x){
+         return x * Math.PI / 180;
+    }
+
+}
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/autocalibrate/helper/ObservableArrayList.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/autocalibrate/helper/ObservableArrayList.java	(revision 35005)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/actions/transform/autocalibrate/helper/ObservableArrayList.java	(revision 35005)
@@ -0,0 +1,87 @@
+package org.openstreetmap.josm.plugins.piclayer.actions.transform.autocalibrate.helper;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javafx.beans.property.SimpleIntegerProperty;
+
+/**
+ * Observable {@link ArrayList}
+ * @author rebsc
+ * @param <E> object type
+ */
+public class ObservableArrayList<E> extends ArrayList<E>{
+
+    private SimpleIntegerProperty sizeProperty;
+    protected PropertyChangeSupport propertyChangeSupport;
+
+	public ObservableArrayList() {
+		super();
+		propertyChangeSupport = new PropertyChangeSupport(this);
+	    sizeProperty = new SimpleIntegerProperty(0);
+	}
+
+	public ObservableArrayList(int initialCapacity) {
+		super(initialCapacity);
+		propertyChangeSupport = new PropertyChangeSupport(this);
+	    sizeProperty = new SimpleIntegerProperty(0);
+	}
+
+	public ObservableArrayList(Collection<? extends E> c) {
+		super(c);
+		propertyChangeSupport = new PropertyChangeSupport(this);
+	    sizeProperty = new SimpleIntegerProperty(0);
+	}
+
+
+	@Override
+	public boolean add(E e) {
+		boolean returnValue = super.add(e);
+        sizeProperty.set(size());
+        propertyChangeSupport.firePropertyChange(sizeProperty.toString(), false, true);
+        return returnValue;
+	}
+
+    @Override
+    public void add(int index, E element) {
+        super.add(index, element);
+        sizeProperty.set(size());
+        propertyChangeSupport.firePropertyChange(sizeProperty.toString(), false, true);
+    }
+
+    @Override
+    public E remove(int index) {
+        E returnValue = super.remove(index);
+        sizeProperty.set(size());
+        propertyChangeSupport.firePropertyChange(sizeProperty.toString(), false, true);
+        return returnValue;
+    }
+
+    @Override
+	public void clear() {
+    	super.clear();
+    	sizeProperty.set(size());
+    	propertyChangeSupport.firePropertyChange(sizeProperty.toString(), false, true);
+    }
+
+    @Override
+    public boolean remove(Object o) {
+        boolean returnValue = super.remove(o);
+        if(returnValue){
+            sizeProperty.set(size());
+            propertyChangeSupport.firePropertyChange(sizeProperty.toString(), false, true);
+        }
+        return returnValue;
+    }
+
+	public void addPropertyChangeListener(PropertyChangeListener listener) {
+        propertyChangeSupport.addPropertyChangeListener(listener);
+    }
+
+	public void removePropertyChangeListener(PropertyChangeListener listener) {
+        propertyChangeSupport.removePropertyChangeListener(listener);
+    }
+
+}
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/gui/autocalibrate/CalibrationErrorView.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/gui/autocalibrate/CalibrationErrorView.java	(revision 35005)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/gui/autocalibrate/CalibrationErrorView.java	(revision 35005)
@@ -0,0 +1,48 @@
+package org.openstreetmap.josm.plugins.piclayer.gui.autocalibrate;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Color;
+
+import javax.swing.JEditorPane;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+
+/**
+ * Class providing error views for calibration action.
+ * Info at https://wiki.openstreetmap.org/wiki/User:Rebsc
+ * @author rebsc
+ *
+ */
+public class CalibrationErrorView {
+
+	public final static String OUTLINE_FILE_ERROR = tr("Could not load outline file!");
+	public final static String CALIBRATION_ERROR = tr("Calibration failed!");
+	public final static String DIMENSION_ERROR = tr("<html> Calibration failed!<br>"
+														+ "There must be a mistake -<br>"
+														+ "Dimension of object differ too much from original.<br>"
+														+ "</html>");
+	private JLabel textLabel;
+
+	public CalibrationErrorView() {
+		textLabel = new JLabel();
+	}
+
+	/**
+	 * Method to show dialog window
+	 * @param errorMsg message to show on GUI
+	 */
+	public void show(String errorMsg) {
+		JEditorPane editor = new JEditorPane();
+		editor.setEditorKit(JEditorPane.createEditorKitForContentType("text/html"));
+		editor.setEditable(false);
+		editor.setBackground(Color.lightGray);
+
+		textLabel.setText(errorMsg );
+		JOptionPane.showMessageDialog(null,
+				textLabel,
+                "PicLayer calibration error",
+                JOptionPane.ERROR_MESSAGE);
+	}
+
+}
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/gui/autocalibrate/CalibrationWindow.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/gui/autocalibrate/CalibrationWindow.java	(revision 35005)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/gui/autocalibrate/CalibrationWindow.java	(revision 35005)
@@ -0,0 +1,656 @@
+package org.openstreetmap.josm.plugins.piclayer.gui.autocalibrate;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowListener;
+import java.awt.geom.Point2D;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.imageio.ImageIO;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.border.EmptyBorder;
+import javax.swing.filechooser.FileNameExtensionFilter;
+
+import org.openstreetmap.josm.plugins.piclayer.PicLayerPlugin;
+import org.openstreetmap.josm.plugins.piclayer.actions.transform.autocalibrate.AutoCalibratePictureAction;
+
+/**
+ * Class providing main window for {@link AutoCalibratePictureAction} in {@link PicLayerPlugin}.
+ * @author rebsc
+ *
+ */
+public class CalibrationWindow extends JFrame {
+
+	 private static final long serialVersionUID = 1L;
+	 private static final int FILES_ONLY = 0;
+
+	 private JFileChooser fileChooser;
+	 private String referenceFileName;
+	 private List<Point2D> originPoints;
+	 private List<Point2D> referencePoints;
+	 private String dist1Value;
+	 private String dist2Value;
+
+	 private JPanel dialogPane;
+	 private JPanel contentPanel;
+	 private JPanel infoBar;
+	 private JPanel buttonBar;
+
+	 private JButton addRefPointsButton;
+	 private JButton addEdgePointsButton;
+	 private JButton helpButton;
+	 private JButton openButton;
+	 private JButton runButton;
+	 private JButton cancelButton;
+
+	 private JLabel infoHeader;
+	 private JLabel edgePointHeader;
+	 private JLabel edgePointNames;
+	 private JLabel edgePointValues;
+	 private JLabel distanceHeader;
+	 private JLabel distance1;
+	 private JLabel distance2;
+	 private JTextField distance1Field;
+	 private JTextField distance2Field;
+	 private JLabel distance1Value;
+	 private JLabel distance2Value;
+	 private JLabel refFileHeader;
+	 private JLabel refFileName;
+	 private JLabel refFileNameValue;
+	 private JLabel refPointHeader;
+	 private JLabel refPointNames;
+	 private JLabel refPointValues;
+
+	 private JLabel edgePointsChecked;
+	 private JLabel distance1Checked;
+	 private JLabel distance2Checked;
+	 private JLabel fileChecked;
+	 private JLabel refPointsChecked;
+
+
+	 public CalibrationWindow() {
+	     fileChooser = new JFileChooser();
+	     referenceFileName = null;
+		 setFileChooser();
+
+		 originPoints = new ArrayList<>();
+		 referencePoints = new ArrayList<>();
+		 dist1Value = null;
+		 dist2Value = null;
+
+		 initComponents();
+		 updateState();
+	 }
+
+	 /**
+	  * initialize components
+	  */
+	  private void initComponents() {
+		  dialogPane = new JPanel();
+	      contentPanel = new JPanel();
+	      infoBar = new JPanel();
+	      buttonBar = new JPanel();
+
+	      addRefPointsButton = new JButton();
+	      addEdgePointsButton = new JButton();
+	      helpButton = new JButton();
+	      openButton = new JButton();
+	      runButton = new JButton();
+	      cancelButton = new JButton();
+
+	      infoHeader = new JLabel();
+	      edgePointHeader = new JLabel();
+	      edgePointNames = new JLabel();
+	      edgePointValues = new JLabel();
+	      distanceHeader = new JLabel();
+	      distance1 = new JLabel();
+	      distance2 = new JLabel();
+	      distance1Field = new JTextField();
+	      distance2Field = new JTextField();
+	      distance1Value = new JLabel();
+	      distance2Value = new JLabel();
+	      refFileHeader = new JLabel();
+	      refFileName = new JLabel();
+	      refFileNameValue = new JLabel();
+	      refPointHeader = new JLabel();
+	      refPointNames = new JLabel();
+	      refPointValues = new JLabel();
+
+	      edgePointsChecked = new JLabel();
+	      distance1Checked = new JLabel();
+	      distance2Checked = new JLabel();
+	      fileChecked = new JLabel();
+	      refPointsChecked = new JLabel();
+
+	      // this
+	      setTitle(tr("AutoCalibration"));
+	      java.awt.Container contentPane = getContentPane();
+	      contentPane.setLayout(new BorderLayout());
+	      this.setMinimumSize(new Dimension(50,100));
+
+	      // dialog pane
+	      dialogPane.setBorder(new EmptyBorder(12, 12, 12, 12));
+	      dialogPane.setLayout(new BorderLayout());
+
+	      // info bar
+	      setInfoBar();
+	      setInfoHeader();
+	      dialogPane.add(infoBar, BorderLayout.NORTH);
+
+	      // content panel
+	      setContentPanel();
+	      setPointHeader();
+		  setEdgePointNamesValues();
+		  setDistanceHeader();
+	      setDistance1();
+	      setDistance1Field();
+	      setDistance2();
+	      setDistance2Field();
+	      setRefFileHeader();
+    	  setRefFileName();
+		  setOpenButton();
+	      setRefPointHeader();
+	      setRefPointNamesValues();
+	      dialogPane.add(contentPanel, BorderLayout.CENTER);
+
+	      // button bar
+	      setButtonBar();
+	      setOKButton();
+	      setCancelButton();
+	      dialogPane.add(buttonBar, BorderLayout.SOUTH);
+
+	      // content Pane
+	      contentPane.add(dialogPane, BorderLayout.CENTER);
+	      pack();
+	      setLocationRelativeTo(getOwner());
+	}
+
+
+	// COMPONENTS
+
+	private void setInfoBar() {
+		infoBar.setBorder(new EmptyBorder(0, 0, 12, 0));
+		infoBar.setLayout(new GridBagLayout());
+		((GridBagLayout) infoBar.getLayout()).columnWidths = new int[] {0, 85, 80};
+		((GridBagLayout) infoBar.getLayout()).columnWeights = new double[] {1.0, 0.0, 0.0};
+	}
+
+	private void setInfoHeader() {
+		 infoHeader.setText(tr("<html>Please enter the required information.</html>"));
+	     infoBar.add(infoHeader, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
+	            GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+	            new Insets(5, 5, 0, 0), 0, 0));
+
+	     String space = "     ";
+	     helpButton = new JButton(tr(space + "help" + space));
+	     infoBar.add(helpButton, new GridBagConstraints(3, 0, 1, 1, 0.0, 0.0,
+	            GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+	            new Insets(0, 0, 0, 0), 0, 0));
+	}
+
+	private void setContentPanel() {
+		contentPanel.setLayout(new GridBagLayout());
+	    contentPanel.setBackground(new Color(200, 200, 200));
+	    ((GridBagLayout) contentPanel.getLayout()).columnWidths = new int[] {0, 0, 0, 0, 0};
+	    ((GridBagLayout) contentPanel.getLayout()).rowHeights = new int[] {0, 0, 0, 0, 0, 0};
+        ((GridBagLayout) contentPanel.getLayout()).columnWeights = new double[] {0.0, 0.0, 0.0, 0.0, 1.0E-4};
+	    ((GridBagLayout) contentPanel.getLayout()).rowWeights = new double[] {0.0, 0.0, 0.0, 0.0, 0.0, 1.0E-4};
+	}
+
+	private void setPointHeader() {
+		edgePointHeader.setText(tr("<html><b><u>Local Edge Points</u></b></html>"));
+	    contentPanel.add(edgePointHeader, new GridBagConstraints(0, 0, 3, 1, 0.0, 0.0,
+	            GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+	            new Insets(5, 5, 5, 30), 0, 0));
+	}
+
+	private void setEdgePointNamesValues() {
+		edgePointNames.setText(tr("<html>"
+				+ "Point 1 (Lat,Lon):<br>"
+				+ "Point 2 (Lat,Lon):<br>"
+				+ "Point 3 (Lat,Lon):<br>"
+						+ "</html>"));
+		contentPanel.add(edgePointNames, new GridBagConstraints(0, 1, 3, 1, 0.0, 0.0,
+	                GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+	                new Insets(5, 5, 5, 30), 0, 0));
+
+		if(!this.originPoints.isEmpty()) {
+			edgePointValuesEntered();
+		}
+		else {
+		    addEdgePointsButton = new JButton(tr("Add Points..."));
+			contentPanel.add(addEdgePointsButton, new GridBagConstraints(3, 1, 3, 1, 0.0, 0.0,
+			          GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+			          new Insets(5, 50, 5, 5), 0, 0));
+		}
+	}
+
+	private void setDistanceHeader() {
+		 distanceHeader.setText(tr("<html><b><u>True Distances</u></b></html>"));
+	     contentPanel.add(distanceHeader, new GridBagConstraints(0, 2, 3, 1, 0.0, 0.0,
+	              GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+	              new Insets(5, 5, 5, 30), 0, 0));
+	}
+
+	private void setDistance1Field() {
+		distance1Field.setText("Click here...");
+	    contentPanel.add(distance1Field, new GridBagConstraints(3, 3, 2, 1, 0.0, 0.0,
+	            GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+	            new Insets(5, 50, 5, 5), 0, 0));
+	}
+
+	private void setDistance2() {
+	    distance2.setText(tr("Point 2 to Point 3 (meter):"));
+	    contentPanel.add(distance2, new GridBagConstraints(0, 4, 3, 1, 0.0, 0.0,
+	          GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+	          new Insets(5, 5, 5, 30), 0, 0));
+	}
+
+	private void setDistance2Field() {
+	    distance2Field.setText("Click here...");
+	    contentPanel.add(distance2Field, new GridBagConstraints(3, 4, 2, 1, 0.0, 0.0,
+	          GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+	          new Insets(5, 50, 5, 5), 0, 0));
+	}
+
+	private void setRefFileHeader() {
+		refFileHeader.setText(tr("<html><b><u>Reference File</u></b></html>"));
+	    contentPanel.add(refFileHeader, new GridBagConstraints(0, 5, 3, 1, 0.0, 0.0,
+	          GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+	          new Insets(5, 5, 5, 30), 0, 0));
+	}
+
+	private void setRefFileName() {
+		refFileName.setText(tr("<html>File Name:"
+		      + "<br>"
+		      + "<br>"
+		      + "<br>"
+		      + "</html>"));
+
+		contentPanel.add(refFileName, new GridBagConstraints(0, 6, 3, 1, 0.0, 0.0,
+				GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+				new Insets(5, 5, 5, 30), 0, 0));
+	}
+
+	private void setOpenButton() {
+		String imageName = "open.png";
+		Image image = null;
+		try {
+			image = ImageIO.read(getClass().getResource("/images/" + imageName));
+		} catch (Exception ex) {
+			System.out.println("Error: Could not load image " + imageName + "," + ex);
+	 	}
+
+	    openButton = new JButton(tr("Open a File..."));
+	    openButton.setIcon(new ImageIcon(image));
+	    contentPanel.add(openButton, new GridBagConstraints(3, 6, 2, 1, 0.0, 0.0,
+	          GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+	          new Insets(5, 50, 5, 5), 0, 0));
+	}
+
+	private void setRefPointHeader() {
+		refPointHeader.setText("<html><b><u>Reference Points</u></b></html>\"");
+	    contentPanel.add(refPointHeader, new GridBagConstraints(0, 7, 3, 1, 0.0, 0.0,
+	          GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+		      new Insets(5, 5, 5, 30), 0, 0));
+	}
+
+	private void setRefPointNamesValues() {
+		 Point2D rp1 = null;
+	     Point2D rp2 = null;
+		 Point2D rp3 = null;
+
+	     if(!this.referencePoints.isEmpty()) {
+		      rp1 = referencePoints.get(0);
+		      rp2 = referencePoints.get(1);
+			  rp3 = referencePoints.get(2);
+	     }
+
+		 refPointNames.setText(tr("<html>"
+				+ "Point 1 (Lat,Lon):<br>"
+				+ "Point 2 (Lat,Lon):<br>"
+				+ "Point 3 (Lat,Lon):<br>"
+						+ "</html>"));
+		 contentPanel.add(refPointNames, new GridBagConstraints(0, 8, 3, 1, 0.0, 0.0,
+	                GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+	                new Insets(5, 5, 5, 30), 0, 0));
+
+		 if(!this.referencePoints.isEmpty()) {
+			  refPointValues.setText(tr("<html>"
+				+ rp1.getY() + ", " + rp1.getX() + "<br>"
+				+ rp2.getY() + ", " + rp2.getX() + "<br>"
+				+ rp3.getY() + ", " + rp3.getX() + "<br>"
+						+ "</html>"));
+
+			  contentPanel.add(refPointValues, new GridBagConstraints(3, 8, 3, 1, 0.0, 0.0,
+					  GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+				      new Insets(5, 5, 5, 30), 0, 0));
+		 }
+		 else {
+		      addRefPointsButton = new JButton(tr("Add Points..."));
+			  contentPanel.add(addRefPointsButton, new GridBagConstraints(3, 8, 3, 1, 0.0, 0.0,
+			            GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+			            new Insets(5, 50, 5, 5), 0, 0));
+		 }
+	}
+
+	private void setButtonBar() {
+		buttonBar.setBorder(new EmptyBorder(12, 0, 0, 0));
+	    buttonBar.setLayout(new GridBagLayout());
+	    ((GridBagLayout) buttonBar.getLayout()).columnWidths = new int[] {0, 85, 80};
+	    ((GridBagLayout) buttonBar.getLayout()).columnWeights = new double[] {1.0, 0.0, 0.0};
+	}
+
+	private void setOKButton() {
+		runButton.setText(tr("Run"));
+	    buttonBar.add(runButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0,
+	          GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+	          new Insets(0, 0, 0, 5), 0, 0));
+	}
+
+	private void setCancelButton() {
+		cancelButton.setText(tr("Cancel"));
+	    buttonBar.add(cancelButton, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0,
+	          GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+	          new Insets(0, 0, 0, 0), 0, 0));
+	}
+
+
+	// DYNAMIC FIELD CHANGES
+
+	private void edgePointValuesEntered() {
+		Point2D p1 = null;
+		Point2D p2 = null;
+		Point2D p3 = null;
+		DecimalFormat df = new DecimalFormat("###.###");
+
+		if(this.originPoints.size() == 3) {
+			p1 = originPoints.get(0);
+			p2 = originPoints.get(1);
+			p3 = originPoints.get(2);
+		}
+		else return;
+
+		edgePointValues.setText(tr("<html>"
+			+ df.format(p1.getY()) + ", " + df.format(p1.getX()) + "<br>"
+			+ df.format(p2.getY()) + ", " + df.format(p2.getX()) + "<br>"
+			+ df.format(p3.getY()) + ", " + df.format(p3.getX()) + "<br>"
+					+ "</html>"));
+
+		contentPanel.remove(addEdgePointsButton);
+		contentPanel.add(edgePointValues, new GridBagConstraints(3, 1, 3, 1, 0.0, 0.0,
+				  GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+			      new Insets(5, 5, 5, 30), 0, 0));
+
+		edgePointsChecked.setIcon(getCheckedIcon());
+		contentPanel.add(edgePointsChecked, new GridBagConstraints(6, 1, 3, 1, 0.0, 0.0,
+				  GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+			      new Insets(5, 5, 5, 5), 0, 0));
+	}
+
+	private void distance1Entered() {
+		contentPanel.remove(distance1Field);
+		distance1Value.setText(dist1Value);
+	    contentPanel.add(distance1Value, new GridBagConstraints(3, 3, 2, 1, 0.0, 0.0,
+	            GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+	            new Insets(5, 5, 5, 30), 0, 0));
+
+		distance1Checked.setIcon(getCheckedIcon());
+		contentPanel.add(distance1Checked, new GridBagConstraints(6, 3, 3, 1, 0.0, 0.0,
+				  GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+			      new Insets(5, 5, 5, 5), 0, 0));
+	}
+
+	private void distance2Entered() {
+		contentPanel.remove(distance2Field);
+		distance2Value.setText(dist2Value);
+	    contentPanel.add(distance2Value, new GridBagConstraints(3, 4, 2, 1, 0.0, 0.0,
+	            GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+	            new Insets(5, 5, 5, 30), 0, 0));
+
+		distance2Checked.setIcon(getCheckedIcon());
+		contentPanel.add(distance2Checked, new GridBagConstraints(6, 4, 3, 1, 0.0, 0.0,
+				  GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+			      new Insets(5, 5, 5, 5), 0, 0));
+	}
+
+	private void refFileEntered() {
+		contentPanel.remove(openButton);
+		refFileName.setText(tr("<html>File Name:</html>"));
+		refFileNameValue.setText(referenceFileName);
+		contentPanel.add(refFileNameValue, new GridBagConstraints(3, 6, 2, 1, 0.0, 0.0,
+		           GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+		           new Insets(5, 5, 5, 30), 0, 0));
+
+		fileChecked.setIcon(getCheckedIcon());
+		contentPanel.add(fileChecked, new GridBagConstraints(6, 6, 3, 1, 0.0, 0.0,
+				  GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+			      new Insets(5, 5, 5, 5), 0, 0));
+	}
+
+	private void refPointValuesEntered() {
+		Point2D p1 = null;
+		Point2D p2 = null;
+		Point2D p3 = null;
+		DecimalFormat df = new DecimalFormat("###.###");
+
+		if(this.referencePoints.size() == 3) {
+			p1 = referencePoints.get(0);
+			p2 = referencePoints.get(1);
+			p3 = referencePoints.get(2);
+		}
+		else return;
+
+		refPointValues.setText(tr("<html>"
+				+ df.format(p1.getY()) + ", " + df.format(p1.getX()) + "<br>"
+				+ df.format(p2.getY()) + ", " + df.format(p2.getX()) + "<br>"
+				+ df.format(p3.getY()) + ", " + df.format(p3.getX()) + "<br>"
+						+ "</html>"));
+
+		contentPanel.remove(addRefPointsButton);
+		contentPanel.add(refPointValues, new GridBagConstraints(3, 8, 3, 1, 0.0, 0.0,
+	            GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+	            new Insets(5, 5, 5, 30), 0, 0));
+
+		refPointsChecked.setIcon(getCheckedIcon());
+		contentPanel.add(refPointsChecked, new GridBagConstraints(6, 8, 3, 1, 0.0, 0.0,
+				GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+			    new Insets(5, 5, 5, 5), 0, 0));
+	}
+
+	private void setDistance1() {
+		 distance1.setText(tr("Point 1 to Point 2 (meter):"));
+	     contentPanel.add(distance1, new GridBagConstraints(0, 3, 3, 1, 0.0, 0.0,
+	            GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+	            new Insets(5, 5, 5, 30), 0, 0));
+	}
+
+
+	// GETTER / SETTER
+
+	public JButton getOpenButton() {
+		return this.openButton;
+	}
+
+	public JTextField getDistance1Field() {
+		return this.distance1Field;
+	}
+
+	public JTextField getDistance2Field() {
+		return this.distance2Field;
+	}
+
+	public String getDistance1FieldText() {
+	    return this.distance1Field.getText();
+	}
+
+	public String getDistance2FieldText() {
+	    return this.distance2Field.getText();
+	}
+
+	public void setOriginPoints(List<Point2D> points) {
+		this.originPoints = points;
+		edgePointValuesEntered();
+		updateState();
+	}
+
+	public void setReferencePoints(List<Point2D> points) {
+		this.referencePoints = points;
+		refPointValuesEntered();
+		updateState();
+	}
+
+	public void setDistance1Field(String s) {
+	    this.distance1Field.setText(s);
+	    updateState();
+	}
+
+	public void setDistance2Field(String s) {
+	    this.distance2Field.setText(s);
+	    updateState();
+	}
+
+	public void setDistance1Value(String valueAsString) {
+		this.dist1Value = valueAsString;
+		if(!valueAsString.equals(""))	distance1Entered();
+	    updateState();
+	}
+
+	public void setDistance2Value(String valueAsString) {
+		this.dist2Value = valueAsString;
+		if(!valueAsString.equals(""))	distance2Entered();
+	    updateState();
+	}
+
+	public void setOkButtonListener(ActionListener l) {
+	    this.runButton.addActionListener(l);
+	}
+
+	public void setCancelButtonListener(ActionListener l) {
+	    this.cancelButton.addActionListener(l);
+	}
+
+	public void setWindowListener(WindowListener l) {
+	    this.addWindowListener(l);
+	}
+
+	public void setReferenceFileName(String name) {
+		  this.referenceFileName = name;
+	}
+
+	private void setFileChooser() {
+		fileChooser.setFileSelectionMode(FILES_ONLY);
+		FileNameExtensionFilter filter = new FileNameExtensionFilter(".osm, .gpx","osm", "gpx");
+		fileChooser.setFileFilter(filter);
+	}
+
+	public void setReferenceFileNameValue(String value) {
+		this.referenceFileName = value;
+		this.refFileNameValue.setText(value);
+		refFileEntered();
+		updateState();
+	}
+
+	public JFileChooser getFileChooser() {
+		return this.fileChooser;
+	}
+
+	public String getFileName() {
+		return this.referenceFileName;
+	}
+
+	// LISTENER
+
+	public void addOpenFileButtonListener(ActionListener l) {
+		this.openButton.addActionListener(l);
+	}
+
+	public void addCancelButtonListener(ActionListener l) {
+		this.cancelButton.addActionListener(l);
+	}
+
+	public void addRunButtonListener(ActionListener l) {
+		this.runButton.addActionListener(l);
+	}
+
+	public void addEdgePointButtonListener(ActionListener l) {
+		this.addEdgePointsButton.addActionListener(l);
+	}
+
+	public void addReferencePointButtonListener(ActionListener l) {
+		this.addRefPointsButton.addActionListener(l);
+	}
+
+	public void addFrameWindowListener(WindowAdapter wAdapter) {
+		this.addWindowListener(wAdapter);
+	}
+
+	public void addDistance1FieldListener(FocusListener l) {
+		this.distance1Field.addFocusListener(l);
+	}
+
+	public void addDistance2FieldListener(FocusListener l) {
+		this.distance2Field.addFocusListener(l);
+	}
+
+	public void addHelpButtonListener(ActionListener l) {
+		this.helpButton.addActionListener(l);
+	}
+
+
+	// HELPER
+
+	private ImageIcon getCheckedIcon() {
+		String imageName = "checked.png";
+		Image image = null;
+		try {
+			image = ImageIO.read(getClass().getResource("/images/" + imageName));
+		} catch (Exception ex) {
+			System.out.println("Error: Could not load image " + imageName + "," + ex);
+	 	}
+		return new ImageIcon(image);
+	}
+
+	public void updateState() {
+		if(originPoints.isEmpty()) {
+			// button blink
+			distance1Field.setEnabled(false);
+			distance2Field.setEnabled(false);
+			openButton.setEnabled(false);
+			addRefPointsButton.setEnabled(false);
+			runButton.setEnabled(false);
+		}
+		else {
+			if(dist1Value == null && dist2Value == null) {
+				distance1Field.setEnabled(true);
+				distance2Field.setEnabled(true);
+			}
+			if(dist1Value != null)			openButton.setEnabled(true);
+			if(referenceFileName != null)	addRefPointsButton.setEnabled(true);
+			if(!referencePoints.isEmpty())	runButton.setEnabled(true);
+		}
+	}
+
+	public void refresh() {
+		this.setVisible(true);
+	}
+
+}
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/gui/autocalibrate/ReferenceOptionView.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/gui/autocalibrate/ReferenceOptionView.java	(revision 35005)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/gui/autocalibrate/ReferenceOptionView.java	(revision 35005)
@@ -0,0 +1,35 @@
+package org.openstreetmap.josm.plugins.piclayer.gui.autocalibrate;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import javax.swing.JOptionPane;
+
+/**
+ *
+ * @author rebsc
+ *
+ */
+public class ReferenceOptionView {
+
+	public ReferenceOptionView() {
+	}
+
+	public int showAndChoose() {
+		Object[] options = {tr("defined"), tr("manual")};
+		String title = tr("AutoCalibration - choose selection type");
+		String msg = tr("<html>Choose the type of selection you want to use.<br><br>"
+				+ "If reference points are defined in shown layer,<br>"
+				+ "choose <b>defined</b>-option and select points.<br>"
+				+ "Else choose <b>manual</b>-option and set the calibration end points manual.</html>");
+
+		int selected = JOptionPane.showOptionDialog(null,
+                                            msg,
+                                            title,
+                                            JOptionPane.DEFAULT_OPTION,
+                                            JOptionPane.INFORMATION_MESSAGE,
+                                            null, options, options[0]);
+
+		return selected;
+	}
+
+}
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/gui/autocalibrate/ResultCheckView.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/gui/autocalibrate/ResultCheckView.java	(revision 35005)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/gui/autocalibrate/ResultCheckView.java	(revision 35005)
@@ -0,0 +1,33 @@
+package org.openstreetmap.josm.plugins.piclayer.gui.autocalibrate;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import javax.swing.JOptionPane;
+
+/**
+ *
+ * @author rebsc
+ *
+ */
+public class ResultCheckView {
+
+	public ResultCheckView() {
+	}
+
+	public int showAndChoose() {
+		Object[] options = {tr("accept"), tr("reset")};
+		String title = tr("AutoCalibration - check calibration");
+		String msg = tr("<html>Is this image calibrated the right way?</html>");
+
+		int selected = JOptionPane.showOptionDialog(null,
+                                            msg,
+                                            title,
+                                            JOptionPane.DEFAULT_OPTION,
+                                            JOptionPane.INFORMATION_MESSAGE,
+                                            null, options, options[0]);
+
+		return selected;
+	}
+
+
+}
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/CalibrationFileFilter.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/CalibrationFileFilter.java	(revision 35003)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/CalibrationFileFilter.java	(revision 35005)
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/PicLayerAbstract.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/PicLayerAbstract.java	(revision 35003)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/PicLayerAbstract.java	(revision 35005)
@@ -4,4 +4,6 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
+
+import java.awt.BasicStroke;
 import java.awt.Color;
 import java.awt.Graphics2D;
@@ -19,4 +21,6 @@
 import java.io.Reader;
 import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Properties;
 
@@ -58,4 +62,5 @@
     // Tiles of pin images
     private static Image pinTiledImage;
+    private static Image pinTiledImageOrange;
 
     // Initial position of the image in the real world
@@ -68,11 +73,38 @@
     protected double initialImageScale = 1.0;
 
-    // Layer icon
+    // Layer icon / lines
     private Icon layerIcon = null;
 
-    private boolean drawMarkers = true;
-
-    public void setDrawPoints(boolean value) {
-        drawMarkers = value;
+    private boolean drawOriginMarkers = true;
+
+    private boolean drawRefMarkers = false;
+
+    private boolean drawFirstLine = false;
+
+    private boolean drawSecLine = false;
+
+    public void setDrawOriginPoints(boolean value) {
+        drawOriginMarkers = value;
+    }
+
+    private List<Point2D> refPointsBuffer = new ArrayList<>(3);	// only for buffering
+
+    public void setDrawReferencePoints(boolean value, Point2D pointToDraw) {
+        drawRefMarkers = value;
+        if(this.refPointsBuffer == null)	refPointsBuffer = new ArrayList<>(3);
+        if(pointToDraw != null)				this.refPointsBuffer.add(pointToDraw);
+    }
+
+    public void clearDrawReferencePoints() {
+    	drawRefMarkers = false;
+    	this.refPointsBuffer = null;
+    }
+
+    public void setDrawFirstLine(boolean value) {
+    	drawFirstLine = value;
+    }
+
+    public void setDrawSecLine(boolean value) {
+    	drawSecLine = value;
     }
 
@@ -126,4 +158,5 @@
             // allow system to load the image and use it in future
             pinTiledImage = new ImageIcon(Toolkit.getDefaultToolkit().createImage(getClass().getResource("/images/v6_64.png"))).getImage();
+            pinTiledImageOrange = new ImageIcon(Toolkit.getDefaultToolkit().createImage(getClass().getResource("/images/v6_64o.png"))).getImage();
         }
 
@@ -139,5 +172,5 @@
         // First, we initialize the calibration, so that createImage() can rely on it
 
-        transformer = new PictureTransform();
+    	  if(transformer == null)		transformer = new PictureTransform();
 
         // If the map does not exist - we're screwed. We should not get into this situation in the first place!
@@ -181,4 +214,8 @@
      */
     public abstract String getPicLayerName();
+
+    public Image getImage() {
+    	return this.image;
+    }
 
     @Override
@@ -270,5 +307,5 @@
                 );
             }
-            if (drawMarkers) {
+            if (drawOriginMarkers) {
                 // draw markers for selection
                 Graphics2D gPoints = (Graphics2D) g2.create();
@@ -290,4 +327,43 @@
                            pinTileOffsetX[i], pinTileOffsetY[i], pinTileOffsetX[i]+pinWidth, pinTileOffsetY[i]+pinHeight, null);
                 }
+            }
+            if (drawRefMarkers) {
+                // draw markers for selection
+                Graphics2D gPoints = (Graphics2D) g2.create();
+
+                gPoints.translate(pic_offset_x, pic_offset_y);
+
+                gPoints.setColor(Color.RED); // red color for points output
+
+                AffineTransform tr = AffineTransform.getScaleInstance(scalex, scaley);
+                tr.concatenate(transformer.getTransform());
+
+                for (int i = 0; i < refPointsBuffer.size(); i++) {
+                   Point2D trP = tr.transform(refPointsBuffer.get(i), null);
+                   int x = (int) trP.getX(), y = (int) trP.getY();
+
+                   int dstx = x-pinAnchorX;
+                   int dsty = y-pinAnchorY;
+                   gPoints.drawImage(pinTiledImageOrange, dstx, dsty, dstx+pinWidth, dsty+pinHeight,
+                           pinTileOffsetX[i], pinTileOffsetY[i], pinTileOffsetX[i]+pinWidth, pinTileOffsetY[i]+pinHeight, null);
+                }
+            }
+            if (drawFirstLine) {
+            	// set line from point1 to point2
+            	List<Point2D> points = this.getTransformer().getOriginPoints();
+            	Point2D p1 = points.get(0);
+            	Point2D p2 = points.get(1);
+            	g.setColor(Color.green);
+            	g.setStroke(new BasicStroke(5));
+                g.drawLine((int)p1.getX(), (int)p1.getY(), (int)p2.getX(), (int)p2.getY());
+            }
+            if (drawSecLine) {
+            	// set line from point2 to point3
+            	List<Point2D> points = this.getTransformer().getOriginPoints();
+            	Point2D p2 = points.get(1);
+            	Point2D p3 = points.get(2);
+            	g.setColor(Color.green);
+            	g.setStroke(new BasicStroke(5));
+                g.drawLine((int)p2.getX(), (int)p2.getY(), (int)p3.getX(), (int)p3.getY());
             }
         } else {
@@ -523,5 +599,5 @@
     }
 
-    public Point2D transformPoint(Point p) throws NoninvertibleTransformException {
+    public Point2D transformPoint(Point2D p) throws NoninvertibleTransformException {
         // Position image at the right graphical place
 
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/PicLayerFromClipboard.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/PicLayerFromClipboard.java	(revision 35003)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/PicLayerFromClipboard.java	(revision 35005)
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/PicLayerFromFile.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/PicLayerFromFile.java	(revision 35003)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/layer/PicLayerFromFile.java	(revision 35005)
Index: applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/transform/PictureTransform.java
===================================================================
--- applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/transform/PictureTransform.java	(revision 35003)
+++ applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/transform/PictureTransform.java	(revision 35005)
@@ -8,4 +8,5 @@
 
 import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.plugins.piclayer.actions.transform.autocalibrate.helper.ObservableArrayList;
 
 public class PictureTransform {
@@ -29,4 +30,5 @@
         cachedTransform = new AffineTransform();
         originPoints = new ArrayList<>(3);
+        latLonOriginPoints = new ObservableArrayList<>(3);
     }
 
@@ -186,5 +188,9 @@
 
     public void setOriginPoints(List<Point2D> list) {
-        this.originPoints = new ArrayList<>(list);
+    	if(originPoints == null)	originPoints = new ArrayList<>(list);
+    	else {
+    		originPoints.clear();
+    		originPoints.addAll(list);
+    	}
     }
 
@@ -192,3 +198,36 @@
         originPoints.remove(selectedPoint);
     }
+
+    public void clearOriginPoints() {
+    	originPoints.clear();
+    }
+
+    // similar to originPointList - points scaled in LatLon, list observable
+    private ObservableArrayList<Point2D> latLonOriginPoints = new ObservableArrayList<>(3);
+
+    public ObservableArrayList<Point2D> getLatLonOriginPoints() {
+    	return this.latLonOriginPoints;
+    }
+
+    public void addLatLonOriginPoint(Point2D p) {
+    	latLonOriginPoints.add(p);
+    }
+
+    public void removeLatLonOriginPoint(Point2D selectedPoint) {
+    	int index = originPoints.indexOf(selectedPoint);
+    	Point2D toDelete = this.latLonOriginPoints.get(index);
+    	this.latLonOriginPoints.remove(toDelete);
+    }
+
+    public void setLatLonOriginPoint(List<Point2D> list) {
+    	if(latLonOriginPoints == null)	latLonOriginPoints = new ObservableArrayList<>(list);
+    	else {
+    		latLonOriginPoints.clear();
+    		latLonOriginPoints.addAll(list);
+    	}
+    }
+
+    public void clearLatLonOriginPoints() {
+    	latLonOriginPoints.clear();
+    }
 }
