]> gitweb.fperrin.net Git - GpsPrune.git/blobdiff - tim/prune/save/PovExporter.java
Version 14, October 2012
[GpsPrune.git] / tim / prune / save / PovExporter.java
index 6f8a32202ef227633ffa533dc62df2f6159e2007..ee30841d6d779f7790b95006a58a75eda7759433 100644 (file)
@@ -12,12 +12,12 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Iterator;
 
+import javax.swing.BorderFactory;
 import javax.swing.BoxLayout;
 import javax.swing.ButtonGroup;
 import javax.swing.JButton;
 import javax.swing.JDialog;
 import javax.swing.JFileChooser;
-import javax.swing.JFrame;
 import javax.swing.JLabel;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
@@ -25,28 +25,29 @@ import javax.swing.JRadioButton;
 import javax.swing.JTextField;
 import javax.swing.SwingConstants;
 
-import tim.prune.Config;
+import tim.prune.App;
 import tim.prune.I18nManager;
 import tim.prune.UpdateMessageBroker;
+import tim.prune.config.Config;
+import tim.prune.data.NumberUtils;
 import tim.prune.data.Track;
+import tim.prune.function.Export3dFunction;
+import tim.prune.gui.DialogCloser;
 import tim.prune.load.GenericFileFilter;
 import tim.prune.threedee.LineDialog;
 import tim.prune.threedee.ThreeDModel;
 
 /**
- * Class to export track information
- * into a specified Pov file
+ * Class to export a 3d scene of the track to a specified Pov file
  */
-public class PovExporter
+public class PovExporter extends Export3dFunction
 {
-       private JFrame _parentFrame = null;
        private Track _track = null;
        private JDialog _dialog = null;
        private JFileChooser _fileChooser = null;
        private String _cameraX = null, _cameraY = null, _cameraZ = null;
        private JTextField _cameraXField = null, _cameraYField = null, _cameraZField = null;
-       private JTextField _fontName = null, _altitudeCapField = null;
-       private int _altitudeCap = ThreeDModel.MINIMUM_ALTITUDE_CAP;
+       private JTextField _fontName = null, _altitudeFactorField = null;
        private JRadioButton _ballsAndSticksButton = null;
 
        // defaults
@@ -55,18 +56,21 @@ public class PovExporter
 
 
        /**
-        * Constructor giving frame and track
-        * @param inParentFrame parent frame
-        * @param inTrack track object to save
+        * Constructor
+        * @param inApp App object
         */
-       public PovExporter(JFrame inParentFrame, Track inTrack)
+       public PovExporter(App inApp)
        {
-               _parentFrame = inParentFrame;
-               _track = inTrack;
+               super(inApp);
+               _track = inApp.getTrackInfo().getTrack();
                // Set default camera coordinates
                _cameraX = "17"; _cameraY = "13"; _cameraZ = "-20";
        }
 
+       /** Get the name key */
+       public String getNameKey() {
+               return "function.exportpov";
+       }
 
        /**
         * Set the coordinates for the camera (can be any scale)
@@ -80,23 +84,10 @@ public class PovExporter
                double cameraDist = Math.sqrt(inX*inX + inY*inY + inZ*inZ);
                if (cameraDist > 0.0)
                {
-                       _cameraX = "" + (inX / cameraDist * DEFAULT_CAMERA_DISTANCE);
-                       _cameraY = "" + (inY / cameraDist * DEFAULT_CAMERA_DISTANCE);
+                       _cameraX = NumberUtils.formatNumber(inX / cameraDist * DEFAULT_CAMERA_DISTANCE, 5);
+                       _cameraY = NumberUtils.formatNumber(inY / cameraDist * DEFAULT_CAMERA_DISTANCE, 5);
                        // Careful! Need to convert from java3d (right-handed) to povray (left-handed) coordinate system!
-                       _cameraZ = "" + (-inZ / cameraDist * DEFAULT_CAMERA_DISTANCE);
-               }
-       }
-
-
-       /**
-        * @param inAltitudeCap altitude cap to use
-        */
-       public void setAltitudeCap(int inAltitudeCap)
-       {
-               _altitudeCap = inAltitudeCap;
-               if (_altitudeCap < ThreeDModel.MINIMUM_ALTITUDE_CAP)
-               {
-                       _altitudeCap = ThreeDModel.MINIMUM_ALTITUDE_CAP;
+                       _cameraZ = NumberUtils.formatNumber(-inZ / cameraDist * DEFAULT_CAMERA_DISTANCE, 5);
                }
        }
 
@@ -104,12 +95,12 @@ public class PovExporter
        /**
         * Show the dialog to select options and export file
         */
-       public void showDialog()
+       public void begin()
        {
                // Make dialog window to select angles, colours etc
                if (_dialog == null)
                {
-                       _dialog = new JDialog(_parentFrame, I18nManager.getText("dialog.exportpov.title"), true);
+                       _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
                        _dialog.setLocationRelativeTo(_parentFrame);
                        _dialog.getContentPane().add(makeDialogComponents());
                }
@@ -118,11 +109,10 @@ public class PovExporter
                _cameraXField.setText(_cameraX);
                _cameraYField.setText(_cameraY);
                _cameraZField.setText(_cameraZ);
-               // Set vertical scale
-               _altitudeCapField.setText("" + _altitudeCap);
+               _altitudeFactorField.setText("" + _altFactor);
                // Show dialog
                _dialog.pack();
-               _dialog.show();
+               _dialog.setVisible(true);
        }
 
 
@@ -134,7 +124,9 @@ public class PovExporter
        {
                JPanel panel = new JPanel();
                panel.setLayout(new BorderLayout());
-               panel.add(new JLabel(I18nManager.getText("dialog.exportpov.text")), BorderLayout.NORTH);
+               JLabel introLabel = new JLabel(I18nManager.getText("dialog.exportpov.text"));
+               introLabel.setBorder(BorderFactory.createEmptyBorder(4, 4, 6, 4));
+               panel.add(introLabel, BorderLayout.NORTH);
                // OK, Cancel buttons
                JPanel buttonPanel = new JPanel();
                buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
@@ -164,12 +156,13 @@ public class PovExporter
                JLabel fontLabel = new JLabel(I18nManager.getText("dialog.exportpov.font"));
                fontLabel.setHorizontalAlignment(SwingConstants.TRAILING);
                centralPanel.add(fontLabel);
-               String defaultFont = Config.getPovrayFont();
+               String defaultFont = Config.getConfigString(Config.KEY_POVRAY_FONT);
                if (defaultFont == null || defaultFont.equals("")) {
                        defaultFont = DEFAULT_FONT_FILE;
                }
                _fontName = new JTextField(defaultFont, 12);
                _fontName.setAlignmentX(Component.LEFT_ALIGNMENT);
+               _fontName.addKeyListener(new DialogCloser(_dialog));
                centralPanel.add(_fontName);
                //coordinates of camera
                JLabel cameraXLabel = new JLabel(I18nManager.getText("dialog.exportpov.camerax"));
@@ -187,12 +180,12 @@ public class PovExporter
                centralPanel.add(cameraZLabel);
                _cameraZField = new JTextField("" + _cameraZ);
                centralPanel.add(_cameraZField);
-               // Altitude capping
-               JLabel altitudeCapLabel = new JLabel(I18nManager.getText("dialog.3d.altitudecap"));
+               // Altitude exaggeration
+               JLabel altitudeCapLabel = new JLabel(I18nManager.getText("dialog.3d.altitudefactor"));
                altitudeCapLabel.setHorizontalAlignment(SwingConstants.TRAILING);
                centralPanel.add(altitudeCapLabel);
-               _altitudeCapField = new JTextField("" + _altitudeCap);
-               centralPanel.add(_altitudeCapField);
+               _altitudeFactorField = new JTextField("1.0");
+               centralPanel.add(_altitudeFactorField);
 
                // Radio buttons for style - balls on sticks or tubes
                JPanel stylePanel = new JPanel();
@@ -262,8 +255,8 @@ public class PovExporter
                        _fileChooser.setFileFilter(new GenericFileFilter("filetype.pov", new String[] {"pov"}));
                        _fileChooser.setAcceptAllFileFilterUsed(false);
                        // start from directory in config which should be set
-                       File configDir = Config.getWorkingDirectory();
-                       if (configDir != null) {_fileChooser.setCurrentDirectory(configDir);}
+                       final String configDir = Config.getConfigString(Config.KEY_TRACK_DIR);
+                       if (configDir != null) {_fileChooser.setCurrentDirectory(new File(configDir));}
                }
 
                // Allow choose again if an existing file is selected
@@ -292,7 +285,7 @@ public class PovExporter
                                        {
                                                // file saved
                                                // Store directory in config for later
-                                               Config.setWorkingDirectory(file.getParentFile());
+                                               Config.setConfigString(Config.KEY_TRACK_DIR, file.getParentFile().getAbsolutePath());
                                        }
                                        else
                                        {
@@ -319,7 +312,7 @@ public class PovExporter
        {
                FileWriter writer = null;
                // find out the line separator for this system
-               String lineSeparator = System.getProperty("line.separator");
+               final String lineSeparator = System.getProperty("line.separator");
                try
                {
                        // create and scale model
@@ -327,10 +320,12 @@ public class PovExporter
                        try
                        {
                                // try to use given altitude cap
-                               _altitudeCap = Integer.parseInt(_altitudeCapField.getText());
-                               model.setAltitudeCap(_altitudeCap);
+                               double altFactor = Double.parseDouble(_altitudeFactorField.getText());
+                               model.setAltitudeFactor(altFactor);
+                       }
+                       catch (NumberFormatException nfe) { // parse failed, reset
+                               _altitudeFactorField.setText("1.0");
                        }
-                       catch (NumberFormatException nfe) {}
                        model.scale();
 
                        // Create file and write basics
@@ -356,7 +351,7 @@ public class PovExporter
                }
                catch (IOException ioe)
                {
-                       JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("error.save.failed") + ioe.getMessage(),
+                       JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("error.save.failed") + " : " + ioe.getMessage(),
                                I18nManager.getText("error.save.dialogtitle"), JOptionPane.ERROR_MESSAGE);
                }
                finally
@@ -382,7 +377,7 @@ public class PovExporter
        private void writeStartOfFile(FileWriter inWriter, double inModelSize, String inLineSeparator)
        throws IOException
        {
-               inWriter.write("// Pov file produced by Prune - see http://activityworkshop.net/");
+               inWriter.write("// Pov file produced by GpsPrune - see http://activityworkshop.net/");
                inWriter.write(inLineSeparator);
                inWriter.write(inLineSeparator);
                // Select font based on user input
@@ -391,6 +386,9 @@ public class PovExporter
                {
                        fontPath = DEFAULT_FONT_FILE;
                }
+               else {
+                       Config.setConfigString(Config.KEY_POVRAY_FONT, fontPath);
+               }
                // Set up output
                String[] outputLines = {
                  "global_settings { ambient_light rgb <4, 4, 4> }", "",
@@ -425,7 +423,7 @@ public class PovExporter
                  "   open",
                  "   pigment { color rgb <0.5 0.5 0.5> }",
                  "  }", "",
-                 // TODO: Export rods to POV?  How to store in data?
+                 // MAYBE: Export rods to POV?  How to store in data?
                  "#declare waypoint_sphere =",
                  "  sphere {",
                  "   <0, 0, 0>, 0.4",
@@ -438,7 +436,7 @@ public class PovExporter
                  "  sphere {",
                  "   <0, 0, 0>, 0.3", // size should depend on model size
                  "   texture {",
-                 "      pigment {color rgb <0.2 1.0 0.2>}",
+                 "      pigment {color rgb <0.1 0.6 0.1>}", // dark green
                  "      finish { phong 1 }",
                  "   }",
                  " }",
@@ -446,7 +444,7 @@ public class PovExporter
                  "  sphere {",
                  "   <0, 0, 0>, 0.3", // size should depend on model size
                  "   texture {",
-                 "      pigment {color rgb <0.6 1.0 0.2>}",
+                 "      pigment {color rgb <0.4 0.9 0.2>}", // green
                  "      finish { phong 1 }",
                  "   }",
                  " }",
@@ -454,7 +452,7 @@ public class PovExporter
                  "  sphere {",
                  "   <0, 0, 0>, 0.3", // size should depend on model size
                  "   texture {",
-                 "      pigment {color rgb <1.0 1.0 0.1>}",
+                 "      pigment {color rgb <0.7 0.8 0.2>}", // yellow
                  "      finish { phong 1 }",
                  "   }",
                  " }",
@@ -462,7 +460,7 @@ public class PovExporter
                  "  sphere {",
                  "   <0, 0, 0>, 0.3", // size should depend on model size
                  "   texture {",
-                 "      pigment {color rgb <1.0 1.0 1.0>}",
+                 "      pigment {color rgb <0.5 0.8 0.6>}", // greeny
                  "      finish { phong 1 }",
                  "   }",
                  " }",
@@ -470,7 +468,15 @@ public class PovExporter
                  "  sphere {",
                  "   <0, 0, 0>, 0.3", // size should depend on model size
                  "   texture {",
-                 "      pigment {color rgb <0.1 1.0 1.0>}",
+                 "      pigment {color rgb <0.2 0.9 0.9>}", // cyan
+                 "      finish { phong 1 }",
+                 "   }",
+                 " }",
+                 "#declare track_sphere5 =",
+                 "  sphere {",
+                 "   <0, 0, 0>, 0.3", // size should depend on model size
+                 "   texture {",
+                 "      pigment {color rgb <1.0 1.0 1.0>}", // white
                  "      finish { phong 1 }",
                  "   }",
                  " }",
@@ -511,7 +517,7 @@ public class PovExporter
                  "  pigment { color rgb <1 1 1> }",
                  "  translate <-" + (inModelSize * 1.03) + ", 0.2, 0>",
                  "}", "",
-                 // TODO: Light positions should relate to model size
+                 // MAYBE: Light positions should relate to model size
                  "// lights",
                  "light_source { <-1, 9, -4> color rgb <0.5 0.5 0.5>}",
                  "light_source { <1, 6, -14> color rgb <0.6 0.6 0.6>}",
@@ -535,7 +541,7 @@ public class PovExporter
         * @param inLineSeparator line separator to use
         * @throws IOException on file writing error
         */
-       private void writeLatLongLines(FileWriter inWriter, ThreeDModel inModel, String inLineSeparator)
+       private static void writeLatLongLines(FileWriter inWriter, ThreeDModel inModel, String inLineSeparator)
        throws IOException
        {
                inWriter.write("// Latitude and longitude lines:");
@@ -565,7 +571,7 @@ public class PovExporter
         * @param inLineSeparator line separator to use
         * @throws IOException on file writing error
         */
-       private void writeDataPointsBallsAndSticks(FileWriter inWriter, ThreeDModel inModel, String inLineSeparator)
+       private static void writeDataPointsBallsAndSticks(FileWriter inWriter, ThreeDModel inModel, String inLineSeparator)
        throws IOException
        {
                inWriter.write("// Data points:");
@@ -607,7 +613,7 @@ public class PovExporter
         * @param inLineSeparator line separator to use
         * @throws IOException on file writing error
         */
-       private void writeDataPointsTubesAndWalls(FileWriter inWriter, ThreeDModel inModel, String inLineSeparator)
+       private static void writeDataPointsTubesAndWalls(FileWriter inWriter, ThreeDModel inModel, String inLineSeparator)
        throws IOException
        {
                inWriter.write("// Data points:");
@@ -636,11 +642,11 @@ public class PovExporter
                inWriter.write(inLineSeparator);
 
                // Loop over all the track segments
-               ArrayList segmentList = getSegmentList(inModel);
-               Iterator segmentIterator = segmentList.iterator();
+               ArrayList<ModelSegment> segmentList = getSegmentList(inModel);
+               Iterator<ModelSegment> segmentIterator = segmentList.iterator();
                while (segmentIterator.hasNext())
                {
-                       ModelSegment segment = (ModelSegment) segmentIterator.next();
+                       ModelSegment segment = segmentIterator.next();
                        int segLength = segment.getNumTrackPoints();
 
                        // if the track segment is long enough, do a cubic spline sphere sweep
@@ -759,7 +765,7 @@ public class PovExporter
         */
        private static byte checkHeightCode(byte inCode)
        {
-               final byte maxHeightCode = 4;
+               final byte maxHeightCode = 5;
                if (inCode < 0) return 0;
                if (inCode > maxHeightCode) return maxHeightCode;
                return inCode;
@@ -787,9 +793,9 @@ public class PovExporter
         * @param inModel model containing data
         * @return list of ModelSegment objects
         */
-       private static ArrayList getSegmentList(ThreeDModel inModel)
+       private static ArrayList<ModelSegment> getSegmentList(ThreeDModel inModel)
        {
-               ArrayList segmentList = new ArrayList();
+               ArrayList<ModelSegment> segmentList = new ArrayList<ModelSegment>();
                if (inModel != null && inModel.getNumPoints() > 0)
                {
                        ModelSegment currSegment = null;