X-Git-Url: http://gitweb.fperrin.net/?p=GpsPrune.git;a=blobdiff_plain;f=src%2Ftim%2Fprune%2Ffunction%2FProjectPoint.java;fp=src%2Ftim%2Fprune%2Ffunction%2FProjectPoint.java;h=10c067514da8e5ab74fa5cdadff931513bd61684;hp=0000000000000000000000000000000000000000;hb=8b20e3e027058cdf6ff52993ee5576193d08667a;hpb=2302358503c38817e19f6e529f6c9e530aac0e86 diff --git a/src/tim/prune/function/ProjectPoint.java b/src/tim/prune/function/ProjectPoint.java new file mode 100644 index 0000000..10c0675 --- /dev/null +++ b/src/tim/prune/function/ProjectPoint.java @@ -0,0 +1,225 @@ +package tim.prune.function; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingConstants; + +import tim.prune.App; +import tim.prune.GenericFunction; +import tim.prune.I18nManager; +import tim.prune.config.Config; +import tim.prune.data.Coordinate; +import tim.prune.data.DataPoint; +import tim.prune.data.Distance; +import tim.prune.data.Field; +import tim.prune.data.Latitude; +import tim.prune.data.Longitude; +import tim.prune.data.Unit; +import tim.prune.data.UnitSetLibrary; +import tim.prune.gui.DecimalNumberField; +import tim.prune.gui.GuiGridLayout; +import tim.prune.gui.WholeNumberField; + + +/** + * Class to provide the function to project the current point + * with a given bearing and distance + */ +public class ProjectPoint extends GenericFunction +{ + private JDialog _dialog = null; + private WholeNumberField _bearingField = null; + private JLabel _distanceDescLabel = null; + private DecimalNumberField _distanceField = null; + private boolean _distanceIsMetric = true; + private JTextField _nameField = null; + private JButton _okButton = null; + + + /** + * Constructor + * @param inApp application object for callback + */ + public ProjectPoint(App inApp) + { + super(inApp); + } + + /** Get the name key */ + public String getNameKey() { + return "function.projectpoint"; + } + + /** + * Begin the function + */ + public void begin() + { + // Make dialog window + if (_dialog == null) + { + _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true); + _dialog.setLocationRelativeTo(_parentFrame); + _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + _dialog.getContentPane().add(makeDialogComponents()); + _dialog.pack(); + } + + // Clear fields + _bearingField.setText(""); + _distanceField.setText(""); + _nameField.setText(""); + // Set the units of the distance label + setLabelText(); + enableOK(); + _dialog.setVisible(true); + } + + + /** + * Create dialog components + * @return Panel containing all gui elements in dialog + */ + private Component makeDialogComponents() + { + JPanel dialogPanel = new JPanel(); + dialogPanel.setLayout(new BorderLayout(0, 10)); + dialogPanel.add(new JLabel(I18nManager.getText("dialog.projectpoint.desc")), BorderLayout.NORTH); + JPanel mainPanel = new JPanel(); + GuiGridLayout grid = new GuiGridLayout(mainPanel); + _bearingField = new WholeNumberField(3); + _distanceField = new DecimalNumberField(false); + // Listeners to enable/disable ok button + KeyAdapter keyListener = new KeyAdapter() { + /** Key released */ + public void keyReleased(KeyEvent inE) { + enableOK(); + if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) { + _dialog.dispose(); + } + } + }; + MouseAdapter mouseListener = new MouseAdapter() { + public void mouseReleased(MouseEvent inE) { + enableOK(); + } + }; + _bearingField.addKeyListener(keyListener); + _bearingField.addMouseListener(mouseListener); + _distanceField.addKeyListener(keyListener); + _distanceField.addMouseListener(mouseListener); + + JLabel bearingLabel = new JLabel(I18nManager.getText("dialog.projectpoint.bearing")); + bearingLabel.setHorizontalAlignment(SwingConstants.RIGHT); + grid.add(bearingLabel); + grid.add(_bearingField); + + // Distance including units + _distanceDescLabel = new JLabel(I18nManager.getText("fieldname.distance") + " (ft)"); + // Note, this label will be reset at each run + _distanceDescLabel.setHorizontalAlignment(SwingConstants.RIGHT); + grid.add(_distanceDescLabel); + grid.add(_distanceField); + + // Waypoint name + JLabel nameLabel = new JLabel(I18nManager.getText("dialog.pointnameedit.name")); + nameLabel.setHorizontalAlignment(SwingConstants.RIGHT); + grid.add(nameLabel); + _nameField = new JTextField("", 12); + grid.add(_nameField); + dialogPanel.add(mainPanel, BorderLayout.CENTER); + // button panel at bottom + JPanel buttonPanel = new JPanel(); + buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT)); + _okButton = new JButton(I18nManager.getText("button.ok")); + ActionListener okListener = new ActionListener() { + public void actionPerformed(ActionEvent e) + { + if (_okButton.isEnabled()) {finish();} + } + }; + _okButton.addActionListener(okListener); + _okButton.setEnabled(false); + + buttonPanel.add(_okButton); + JButton cancelButton = new JButton(I18nManager.getText("button.cancel")); + cancelButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) + { + _dialog.dispose(); + } + }); + buttonPanel.add(cancelButton); + dialogPanel.add(buttonPanel, BorderLayout.SOUTH); + dialogPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15)); + return dialogPanel; + } + + /** + * Set the label text according to the current units + */ + private void setLabelText() + { + Unit distUnit = Config.getUnitSet().getDistanceUnit(); + _distanceIsMetric = (distUnit == UnitSetLibrary.UNITS_METRES || distUnit == UnitSetLibrary.UNITS_KILOMETRES); + distUnit = _distanceIsMetric ? UnitSetLibrary.UNITS_METRES : UnitSetLibrary.UNITS_FEET; + final String unitKey = distUnit.getShortnameKey(); + _distanceDescLabel.setText(I18nManager.getText("fieldname.distance") + " (" + I18nManager.getText(unitKey) + ")"); + } + + /** + * Enable or disable the OK button based on the contents of the input fields + */ + private void enableOK() + { + final boolean bearingOk = !_bearingField.getText().isEmpty() + && _bearingField.getValue() < 360; + final boolean distanceOk = _distanceField.getValue() > 0.0; + _okButton.setEnabled(bearingOk && distanceOk); + } + + /** + * Finish the dialog when OK pressed + */ + private void finish() + { + DataPoint currPoint = _app.getTrackInfo().getCurrentPoint(); + Unit distUnit = _distanceIsMetric ? UnitSetLibrary.UNITS_METRES : UnitSetLibrary.UNITS_FEET; + final double projectRads = Distance.convertDistanceToRadians(_distanceField.getValue(), distUnit); + final double origLatRads = Math.toRadians(currPoint.getLatitude().getDouble()); + final double origLonRads = Math.toRadians(currPoint.getLongitude().getDouble()); + System.out.println("Project from: " + origLatRads + ", " + origLonRads); + final double bearingRads = Math.toRadians(_bearingField.getValue()); + + double lat2 = Math.asin(Math.sin(origLatRads) * Math.cos(projectRads) + + Math.cos(origLatRads) * Math.sin(projectRads) * Math.cos(bearingRads)); + double lon2 = origLonRads + Math.atan2(Math.sin(bearingRads) * Math.sin(projectRads) * Math.cos(origLatRads), + Math.cos(projectRads) - Math.sin(origLatRads) * Math.sin(lat2)); + + double finalLatDeg = Math.toDegrees(lat2); + double finalLonDeg = Math.toDegrees(lon2); + System.out.println("Result is: lat=" + finalLatDeg + ", lon=" + finalLonDeg); + + // Create point and append to track + DataPoint point = new DataPoint(new Latitude(finalLatDeg, Coordinate.FORMAT_DEG), + new Longitude(finalLonDeg, Coordinate.FORMAT_DEG), null); + point.setFieldValue(Field.WAYPT_NAME, _nameField.getText(), false); + _app.createPoint(point); + + _dialog.dispose(); + } +}