Created a GeneralRocketSaver object which is analogous to GeneralRocketLoader. Based on the StorageOptions, it determines how to save the file using a RocksimSaver or OpenRocketSaver as appropriate. Modified RocksimSaver and OpenRocketSaver so they only operate on OutputStreams. Removed methods from RocketSaver interface which operated on File. Fixed bug in DecalRegistry where it wouldn't handle absolute filenames. Fixed bug in BasicFrame where it would display ugly stuff for the filename.

This commit is contained in:
Kevin Ruland 2012-07-20 20:13:30 +00:00 committed by U-WINDOWS-C28163E\Administrator
parent 4fe9dc4eef
commit e9060272e4
15 changed files with 2983 additions and 242 deletions

View File

@ -7,7 +7,7 @@ import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.StorageOptions;
import net.sf.openrocket.file.DatabaseMotorFinder;
import net.sf.openrocket.file.GeneralRocketLoader;
import net.sf.openrocket.file.openrocket.OpenRocketSaver;
import net.sf.openrocket.file.GeneralRocketSaver;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.l10n.ResourceBundleTranslator;
@ -51,9 +51,10 @@ public class TextureOutputTest {
new DatabaseMotorFinder());
StorageOptions saver = new StorageOptions();
saver.setFileType(StorageOptions.FileType.OPENROCKET);
saver.setIncludeDecals(true);
new OpenRocketSaver().save(new File("3d-Test-Junk/net/sf/openrocket/startup/Apocalypse-ork.zip"), doc, saver);
new GeneralRocketSaver().save(new File("3d-Test-Junk/net/sf/openrocket/startup/Apocalypse-ork.zip"), doc, saver);
}
}

View File

@ -45,11 +45,21 @@ public class DecalRegistry {
}
}
// Check absolute file name:
{
File decal = new File(name);
if ( decal.isAbsolute() ) {
return new FileInputStream(decal);
}
}
// Try relative to the model file directory.
if( fileInfo.getDirectory() != null ) {
File decal = new File(fileInfo.getDirectory(), name);
// FIXME - update cache
return new FileInputStream(decal);
}
throw new FileNotFoundException( "Unable to locate decal for name " + name );
}

View File

@ -4,9 +4,16 @@ import net.sf.openrocket.util.BugException;
public class StorageOptions implements Cloneable {
public enum FileType {
OPENROCKET,
ROCKSIM
}
public static final double SIMULATION_DATA_NONE = Double.POSITIVE_INFINITY;
public static final double SIMULATION_DATA_ALL = 0;
private FileType fileType = FileType.OPENROCKET;
private boolean includeDecals = false;
private boolean compressionEnabled = true;
@ -15,6 +22,14 @@ public class StorageOptions implements Cloneable {
private boolean explicitlySet = false;
public FileType getFileType() {
return fileType;
}
public void setFileType(FileType fileType) {
this.fileType = fileType;
}
public boolean isIncludeDecals() {
return includeDecals;
}
@ -39,8 +54,6 @@ public class StorageOptions implements Cloneable {
this.simulationTimeSkip = simulationTimeSkip;
}
public boolean isExplicitlySet() {
return explicitlySet;
}
@ -49,8 +62,6 @@ public class StorageOptions implements Cloneable {
this.explicitlySet = explicitlySet;
}
@Override
public StorageOptions clone() {
try {

View File

@ -0,0 +1,261 @@
package net.sf.openrocket.file;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import net.sf.openrocket.appearance.Appearance;
import net.sf.openrocket.appearance.AppearanceBuilder;
import net.sf.openrocket.appearance.Decal;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.StorageOptions;
import net.sf.openrocket.file.openrocket.OpenRocketSaver;
import net.sf.openrocket.file.rocksim.export.RocksimSaver;
import net.sf.openrocket.rocketcomponent.RocketComponent;
public class GeneralRocketSaver {
/**
* Save the document to the specified file using the default storage options.
*
* @param dest the destination file.
* @param document the document to save.
* @throws IOException in case of an I/O error.
*/
public final void save(File dest, OpenRocketDocument document) throws IOException {
save(dest, document, document.getDefaultStorageOptions());
}
/**
* Save the document to the specified file using the given storage options.
*
* @param dest the destination file.
* @param document the document to save.
* @param options the storage options.
* @throws IOException in case of an I/O error.
*/
public void save(File dest, OpenRocketDocument document, StorageOptions options) throws IOException {
OutputStream s = new BufferedOutputStream(new FileOutputStream(dest));
try {
save(dest.getName(), s, document, options);
} finally {
s.close();
}
}
/**
* Save the document to the specified output stream using the default storage options.
*
* @param dest the destination stream.
* @param doc the document to save.
* @throws IOException in case of an I/O error.
*/
public final void save(String fileName, OutputStream dest, OpenRocketDocument doc) throws IOException {
save(fileName, dest, doc, doc.getDefaultStorageOptions());
}
/**
* Provide an estimate of the file size when saving the document with the
* specified options. This is used as an indication to the user and when estimating
* file save progress.
*
* @param doc the document.
* @param options the save options, compression must be taken into account.
* @return the estimated number of bytes the storage would take.
*/
public long estimateFileSize(OpenRocketDocument doc, StorageOptions options) {
if ( options.getFileType() == StorageOptions.FileType.ROCKSIM ) {
return new RocksimSaver().estimateFileSize(doc, options);
} else {
return new OpenRocketSaver().estimateFileSize(doc,options);
}
}
public void save(String fileName, OutputStream output, OpenRocketDocument document, StorageOptions options) throws IOException {
// If we don't include decals, just write the simple file.
if (!options.isIncludeDecals()) {
saveInternal(output,document,options);
return;
}
// We're saving decals, so the result will be a zip file. There's no
// need to gzip the rocket model file in the archive.
options.setCompressionEnabled(false);
// Open a zip stream to write to.
ZipOutputStream zos = new ZipOutputStream(output);
zos.setLevel(9);
/* if we want a directory ...
String path = fileName;
int dotlocation = fileName.lastIndexOf('.');
if ( dotlocation > 1 ) {
path = fileName.substring(dotlocation);
}
*/
// big try block to close the zos.
try {
// grab the set of decal images. We do this up front
// so we can fail early if some resource is missing.
// decalNameNormalization maps the current decal file name
// to the name used in the zip file.
Map<String,String> decalNameNormalization = new HashMap<String,String>();
// decals maintains a mapping from decal file name to an input stream.
Map<String,InputStream> decals = new HashMap<String,InputStream>();
// try block to close streams held in decals if something goes wrong.
try {
// Look for all decals used in the rocket.
for( RocketComponent c : document.getRocket() ) {
if ( c.getAppearance() == null ) {
continue;
}
Appearance ap = c.getAppearance();
if ( ap.getTexture() == null ) {
continue;
}
Decal decal = ap.getTexture();
String decalName = decal.getImage();
// If the decal name is already in the decals map, we've already
// seen it attached to another component.
if ( decals.containsKey(decalName) ) {
continue;
}
// Use the DecalRegistry to get the input stream.
InputStream is = document.getDecalRegistry().getDecal(decalName);
// Add it to the decals map.
decals.put(decalName, is);
// Normalize the name:
File fname = new File(decalName);
String newName = "decals/" + fname.getName();
// If the normalized name is already used, it represents a different
// decal name. We need to change the name slightly to find one which works.
if ( decalNameNormalization.values().contains(newName) ) {
// We'll append integers to the names until we get something which works.
// so if newName is "decals/foo.jpg", we will try "decals/foo (1).jpg"
// "decals/foo (2).jpg", etc.
String newNameTemplate = buildFilenameTemplate(newName);
int i=1;
while( true ) {
newName = MessageFormat.format(newNameTemplate, i);
if ( ! decalNameNormalization.values().contains(newName) ) {
break;
}
i++;
}
}
decalNameNormalization.put(decalName, newName);
}
}
catch (IOException ex) {
for ( InputStream is: decals.values() ) {
try {
is.close();
}
catch ( Throwable t ) {
}
}
throw ex;
}
// Now we have to loop through all the components and update their names.
for( RocketComponent c : document.getRocket() ) {
if ( c.getAppearance() == null ) {
continue;
}
Appearance ap = c.getAppearance();
if ( ap.getTexture() == null ) {
continue;
}
AppearanceBuilder builder = new AppearanceBuilder(ap);
builder.setImage( decalNameNormalization.get(ap.getTexture().getImage()));
c.setAppearance(builder.getAppearance());
}
// Fixme - should probably be the same name? Should we put everything in a directory?
ZipEntry mainFile = new ZipEntry("rocket.ork");
zos.putNextEntry(mainFile);
saveInternal(zos,document,options);
zos.closeEntry();
// Now we write out all the decal images files.
for( Map.Entry<String, InputStream> image : decals.entrySet() ) {
String newName = decalNameNormalization.get(image.getKey());
ZipEntry decal = new ZipEntry(newName);
zos.putNextEntry(decal);
InputStream is = image.getValue();
int bytesRead = 0;
byte[] buffer = new byte[2048];
while( (bytesRead = is.read(buffer)) > 0 ) {
zos.write(buffer, 0, bytesRead);
}
zos.closeEntry();
}
zos.flush();
} finally {
zos.close();
}
}
// package scope for testing.
static String buildFilenameTemplate( String fileName ) {
// We're going to use MessageTemplate for this. If we don't have a dot
// just append "(5)"
String nameTemplate = fileName + " ({0})";
// split up the newName. Look for extension.
int lastDot = fileName.lastIndexOf('.');
if ( lastDot > 0 ) {
String firstPart = fileName.substring(0, lastDot );
String lastPart = fileName.substring(lastDot);
nameTemplate = firstPart + " ({0})" + lastPart;
}
return nameTemplate;
}
private void saveInternal(OutputStream output, OpenRocketDocument document, StorageOptions options)
throws IOException {
if ( options.getFileType() == StorageOptions.FileType.ROCKSIM ) {
new RocksimSaver().save(output, document, options);
} else {
new OpenRocketSaver().save(output, document, options);
}
}
}

View File

@ -1,8 +1,5 @@
package net.sf.openrocket.file;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
@ -12,49 +9,6 @@ import net.sf.openrocket.document.StorageOptions;
public abstract class RocketSaver {
/**
* Save the document to the specified file using the default storage options.
*
* @param dest the destination file.
* @param document the document to save.
* @throws IOException in case of an I/O error.
*/
public final void save(File dest, OpenRocketDocument document) throws IOException {
save(dest, document, document.getDefaultStorageOptions());
}
/**
* Save the document to the specified file using the given storage options.
*
* @param dest the destination file.
* @param document the document to save.
* @param options the storage options.
* @throws IOException in case of an I/O error.
*/
public void save(File dest, OpenRocketDocument document, StorageOptions options)
throws IOException {
OutputStream s = new BufferedOutputStream(new FileOutputStream(dest));
try {
save(dest.getName(), s, document, options);
} finally {
s.close();
}
}
/**
* Save the document to the specified output stream using the default storage options.
*
* @param dest the destination stream.
* @param doc the document to save.
* @throws IOException in case of an I/O error.
*/
public final void save(String fileName, OutputStream dest, OpenRocketDocument doc) throws IOException {
save(fileName, dest, doc, doc.getDefaultStorageOptions());
}
/**
* Save the document to the specified output stream using the given storage options.
*
@ -63,11 +17,9 @@ public abstract class RocketSaver {
* @param options the storage options.
* @throws IOException in case of an I/O error.
*/
public abstract void save(String fileName, OutputStream dest, OpenRocketDocument doc,
public abstract void save(OutputStream dest, OpenRocketDocument doc,
StorageOptions options) throws IOException;
/**
* Provide an estimate of the file size when saving the document with the
* specified options. This is used as an indication to the user and when estimating
@ -79,9 +31,6 @@ public abstract class RocketSaver {
*/
public abstract long estimateFileSize(OpenRocketDocument doc, StorageOptions options);
public static String escapeXML(String s) {
s = s.replace("&", "&amp;");

View File

@ -1,26 +1,17 @@
package net.sf.openrocket.file.openrocket;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.appearance.Appearance;
import net.sf.openrocket.appearance.AppearanceBuilder;
import net.sf.openrocket.appearance.Decal;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.document.StorageOptions;
@ -78,127 +69,7 @@ public class OpenRocketSaver extends RocketSaver {
private Writer dest;
@Override
public void save(String fileName, OutputStream output, OpenRocketDocument document, StorageOptions options)
throws IOException {
if (!options.isIncludeDecals()) {
saveInternal(output,document,options);
return;
}
// tweak the options - no need to double compress:
options.setCompressionEnabled(false);
ZipOutputStream zos = new ZipOutputStream(output);
zos.setLevel(9);
/* if we want a directory ...
String path = fileName;
int dotlocation = fileName.lastIndexOf('.');
if ( dotlocation > 1 ) {
path = fileName.substring(dotlocation);
}
*/
// grab the set of decal images.
Map<String,InputStream> decals = new HashMap<String,InputStream>();
Map<String,String> decalNameNormalization = new HashMap<String,String>();
try {
for( RocketComponent c : document.getRocket() ) {
if ( c.getAppearance() == null ) {
continue;
}
Appearance ap = c.getAppearance();
if ( ap.getTexture() == null ) {
continue;
}
Decal decal = ap.getTexture();
String decalName = decal.getImage();
if ( decals.containsKey(decalName) ) {
continue;
}
InputStream is = document.getDecalRegistry().getDecal(decalName);
decals.put(decalName, is);
// Normalize the name:
File fname = new File(decalName);
String newName = "decals/" + fname.getName();
decalNameNormalization.put(decalName, newName);
}
}
catch (IOException ex) {
for ( InputStream is: decals.values() ) {
try {
is.close();
}
catch ( Throwable t ) {
}
}
throw ex;
}
// Now we have to loop through all the components and update their names.
for( RocketComponent c : document.getRocket() ) {
if ( c.getAppearance() == null ) {
continue;
}
Appearance ap = c.getAppearance();
if ( ap.getTexture() == null ) {
continue;
}
AppearanceBuilder builder = new AppearanceBuilder(ap);
builder.setImage( decalNameNormalization.get(ap.getTexture().getImage()));
c.setAppearance(builder.getAppearance());
}
// Fixme - should probably be the same name? Should we put everything in a directory?
ZipEntry mainFile = new ZipEntry("rocket.ork");
zos.putNextEntry(mainFile);
saveInternal(zos,document,options);
zos.closeEntry();
// Now we write out all the decal images files.
for( Map.Entry<String, InputStream> image : decals.entrySet() ) {
String newName = decalNameNormalization.get(image.getKey());
ZipEntry decal = new ZipEntry(newName);
zos.putNextEntry(decal);
InputStream is = image.getValue();
int bytesRead = 0;
byte[] buffer = new byte[2048];
while( (bytesRead = is.read(buffer)) > 0 ) {
zos.write(buffer, 0, bytesRead);
}
zos.closeEntry();
}
zos.flush();
zos.close();
}
public void saveInternal(OutputStream output, OpenRocketDocument document, StorageOptions options)
throws IOException {
public void save(OutputStream output, OpenRocketDocument document, StorageOptions options) throws IOException {
log.info("Saving .ork file");

View File

@ -56,7 +56,7 @@ public class RocksimSaver extends RocketSaver {
}
@Override
public void save(String fileName, OutputStream dest, OpenRocketDocument doc, StorageOptions options) throws IOException {
public void save(OutputStream dest, OpenRocketDocument doc, StorageOptions options) throws IOException {
log.info("Saving .rkt file");
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(dest, "UTF-8"));

View File

@ -61,11 +61,10 @@ import javax.swing.tree.TreeSelectionModel;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.StorageOptions;
import net.sf.openrocket.file.GeneralRocketLoader;
import net.sf.openrocket.file.GeneralRocketSaver;
import net.sf.openrocket.file.RocketLoadException;
import net.sf.openrocket.file.RocketSaver;
import net.sf.openrocket.file.openrocket.OpenRocketSaver;
import net.sf.openrocket.file.rocksim.export.RocksimSaver;
import net.sf.openrocket.gui.StorageOptionChooser;
import net.sf.openrocket.gui.configdialog.ComponentConfigDialog;
import net.sf.openrocket.gui.customexpression.CustomExpressionDialog;
@ -115,7 +114,7 @@ public class BasicFrame extends JFrame {
*/
private static final GeneralRocketLoader ROCKET_LOADER = new GeneralRocketLoader();
private static final RocketSaver ROCKET_SAVER = new OpenRocketSaver();
private static final GeneralRocketSaver ROCKET_SAVER = new GeneralRocketSaver();
private static final Translator trans = Application.getTranslator();
@ -619,20 +618,20 @@ public class BasicFrame extends JFrame {
//// Edit Component Preset File
if (System.getProperty("openrocket.preseteditor.menu") != null) {
item = new JMenuItem(trans.get("main.menu.edit.editpreset"));
item.addActionListener( new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JFrame dialog = new JFrame();
dialog.getContentPane().add(new ComponentPresetEditor(dialog));
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.pack();
dialog.setVisible(true);
}
});
menu.add(item);
}
if (System.getProperty("openrocket.preseteditor.menu") != null) {
item = new JMenuItem(trans.get("main.menu.edit.editpreset"));
item.addActionListener( new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JFrame dialog = new JFrame();
dialog.getContentPane().add(new ComponentPresetEditor(dialog));
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.pack();
dialog.setVisible(true);
}
});
menu.add(item);
}
//// Analyze
menu = new JMenu(trans.get("main.menu.analyze"));
@ -791,12 +790,12 @@ public class BasicFrame extends JFrame {
log.user("What is this menu? selected");
JOptionPane.showMessageDialog(BasicFrame.this,
new Object[] {
"The 'Debug' menu includes actions for testing and debugging " +
"OpenRocket.", " ",
"The 'Debug' menu includes actions for testing and debugging " +
"OpenRocket.", " ",
"The menu is made visible by defining the system property " +
"'openrocket.debug.menu' when starting OpenRocket.",
"It should not be visible by default." },
"Debug menu", JOptionPane.INFORMATION_MESSAGE);
"It should not be visible by default." },
"Debug menu", JOptionPane.INFORMATION_MESSAGE);
}
});
menu.add(item);
@ -814,9 +813,9 @@ public class BasicFrame extends JFrame {
"Input text key to generate random rocket:",
field
}, "Generate random test rocket", JOptionPane.DEFAULT_OPTION,
JOptionPane.QUESTION_MESSAGE, null, new Object[] {
"Random", "OK"
}, "OK");
JOptionPane.QUESTION_MESSAGE, null, new Object[] {
"Random", "OK"
}, "OK");
Rocket r;
if (sel == 0) {
@ -885,7 +884,7 @@ public class BasicFrame extends JFrame {
if (o == null)
continue;
sb.append("Age ").append(System.currentTimeMillis() - data.getRegistrationTime())
.append(" ms: ").append(o).append('\n');
.append(" ms: ").append(o).append('\n');
count++;
// Explicitly null the strong reference to avoid possibility of invisible references
o = null;
@ -1058,8 +1057,8 @@ public class BasicFrame extends JFrame {
for (File file : files) {
log.info("Opening file: " + file);
if (open(file, this)) {
MRUDesignFile opts = MRUDesignFile.getInstance();
opts.addFile(file.getAbsolutePath());
MRUDesignFile opts = MRUDesignFile.getInstance();
opts.addFile(file.getAbsolutePath());
}
}
}
@ -1085,13 +1084,21 @@ public class BasicFrame extends JFrame {
private static boolean open(URL url, BasicFrame parent) {
String filename = null;
// First figure out the file name from the URL
if ( filename == null ) {
filename = "";
}
// Remove path from filename
if (filename.lastIndexOf('/') >= 0) {
filename = filename.substring(filename.lastIndexOf('/') + 1);
}
// Open the file
log.info("Opening file from url=" + url + " filename=" + filename);
try {
InputStream is = url.openStream();
open(is, url, parent);
open(is, filename, url, parent);
} catch (IOException e) {
log.warn("Error opening file" + e);
JOptionPane.showMessageDialog(parent,
@ -1112,9 +1119,9 @@ public class BasicFrame extends JFrame {
* @param parent the parent component for which a progress dialog is opened.
* @return whether the file was successfully loaded and opened.
*/
private static boolean open(InputStream stream, URL fileURL, Window parent) {
private static boolean open(InputStream stream, String filename, URL fileURL, Window parent) {
OpenFileWorker worker = new OpenFileWorker(stream, fileURL, ROCKET_LOADER);
return open(worker, fileURL.getFile(), null, parent);
return open(worker, filename, null, parent);
}
@ -1178,7 +1185,7 @@ public class BasicFrame extends JFrame {
JOptionPane.showMessageDialog(parent,
"Unable to open file '" + filename + "': "
+ cause.getMessage(),
"Error opening file", JOptionPane.ERROR_MESSAGE);
"Error opening file", JOptionPane.ERROR_MESSAGE);
return false;
} else {
@ -1202,13 +1209,13 @@ public class BasicFrame extends JFrame {
log.info("Warnings while reading file: " + warnings);
WarningDialog.showWarnings(parent,
new Object[] {
//// The following problems were encountered while opening
trans.get("BasicFrame.WarningDialog.txt1") + " " + filename + ".",
//// Some design features may not have been loaded correctly.
trans.get("BasicFrame.WarningDialog.txt2")
},
//// Warnings while opening file
trans.get("BasicFrame.WarningDialog.title"), warnings);
//// The following problems were encountered while opening
trans.get("BasicFrame.WarningDialog.txt1") + " " + filename + ".",
//// Some design features may not have been loaded correctly.
trans.get("BasicFrame.WarningDialog.txt2")
},
//// Warnings while opening file
trans.get("BasicFrame.WarningDialog.title"), warnings);
}
@ -1316,13 +1323,16 @@ public class BasicFrame extends JFrame {
* @return true if the file was written
*/
private boolean saveAsRocksim(File file) {
// FIME - this function can probably go away since the Worker thread can handle rocksim files.
file = FileHelper.forceExtension(file, "rkt");
if (!FileHelper.confirmWrite(file, this)) {
return false;
}
try {
new RocksimSaver().save(file, document);
StorageOptions options = new StorageOptions();
options.setFileType(StorageOptions.FileType.ROCKSIM);
ROCKET_SAVER.save(file,document,options);
return true;
} catch (IOException e) {
return false;
@ -1392,8 +1402,8 @@ public class BasicFrame extends JFrame {
ComponentConfigDialog.hideDialog();
int result = JOptionPane.showConfirmDialog(this,
trans.get("BasicFrame.dlg.lbl1") + rocket.getName() +
trans.get("BasicFrame.dlg.lbl2") + " " +
trans.get("BasicFrame.dlg.lbl3"),
trans.get("BasicFrame.dlg.lbl2") + " " +
trans.get("BasicFrame.dlg.lbl3"),
trans.get("BasicFrame.dlg.title"), JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (result == JOptionPane.YES_OPTION) {
@ -1434,10 +1444,10 @@ public class BasicFrame extends JFrame {
*
*/
public void printAction() {
Double rotation = rocketpanel.getFigure().getRotation();
if (rotation == null) {
rotation = 0d;
}
Double rotation = rocketpanel.getFigure().getRotation();
if (rotation == null) {
rotation = 0d;
}
new PrintDialog(this, document, rotation).setVisible(true);
}

View File

@ -0,0 +1,22 @@
@@ -1087,11 +1086,20 @@
}
}
+ if ( filename == null ) {
+ filename = "";
+ }
+
+ // Remove path from filename
+ if (filename.lastIndexOf('/') >= 0) {
+ filename = filename.substring(filename.lastIndexOf('/') + 1);
+ }
+
// Open the file
log.info("Opening file from url=" + url + " filename=" + filename);
try {
InputStream is = url.openStream();
- if (open(is, url, parent)) {
+ if (open(is, filename, url, parent)) {
// Close previous window if replacing
if (parent.replaceable && parent.document.isSaved()) {
parent.closeAction();

View File

@ -7,16 +7,16 @@ import java.io.FileOutputStream;
import javax.swing.SwingWorker;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.RocketSaver;
import net.sf.openrocket.file.GeneralRocketSaver;
import net.sf.openrocket.startup.Application;
public class SaveFileWorker extends SwingWorker<Void, Void> {
private final OpenRocketDocument document;
private final File file;
private final RocketSaver saver;
private final GeneralRocketSaver saver;
public SaveFileWorker(OpenRocketDocument document, File file, RocketSaver saver) {
public SaveFileWorker(OpenRocketDocument document, File file, GeneralRocketSaver saver) {
this.document = document;
this.file = file;
this.saver = saver;

View File

@ -8,9 +8,8 @@ import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.StorageOptions;
import net.sf.openrocket.file.DatabaseMotorFinder;
import net.sf.openrocket.file.GeneralRocketLoader;
import net.sf.openrocket.file.GeneralRocketSaver;
import net.sf.openrocket.file.RocketLoadException;
import net.sf.openrocket.file.RocketSaver;
import net.sf.openrocket.file.openrocket.OpenRocketSaver;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.l10n.ResourceBundleTranslator;
import net.sf.openrocket.logging.LogLevel;
@ -33,7 +32,7 @@ public class RocksimConverter {
setup();
GeneralRocketLoader loader = new GeneralRocketLoader();
RocketSaver saver = new OpenRocketSaver();
GeneralRocketSaver saver = new GeneralRocketSaver();
for (String inputFile : args) {
System.out.println("Converting " + inputFile + "...");
@ -59,6 +58,7 @@ public class RocksimConverter {
try {
StorageOptions opts = new StorageOptions();
opts.setFileType(StorageOptions.FileType.OPENROCKET);
opts.setCompressionEnabled(true);
opts.setSimulationTimeSkip(StorageOptions.SIMULATION_DATA_NONE);
opts.setExplicitlySet(true);

695
core/test-writing/apocd.ork Normal file
View File

@ -0,0 +1,695 @@
<?xml version='1.0' encoding='utf-8'?>
<openrocket version="1.6" creator="OpenRocket 12.03dev">
<rocket>
<name>apocalypse</name>
<referencetype>maximum</referencetype>
<subcomponents>
<stage>
<name>Stage</name>
<overridemass>4.0</overridemass>
<overridecg>1.05829</overridecg>
<overridesubcomponents>true</overridesubcomponents>
<subcomponents>
<nosecone>
<name>Nose cone</name>
<appearance>
<ambient red="255" green="255" blue="255"/>
<diffuse red="255" green="255" blue="255"/>
<specular red="255" green="255" blue="255"/>
<decal name="decals/Apocalypse_CONE_pointsFrfl.jpg" rotation="0.0" edgemode="MIRROR">
<center x="0.5" y="0.5"/>
<offset x="-1.0" y="-1.0"/>
<scale x="-2.0" y="-1.0"/>
</decal>
</appearance>
<overridemass>0.283495</overridemass>
<overridecg>0.2286</overridecg>
<overridesubcomponents>false</overridesubcomponents>
<finish>smooth</finish>
<material type="bulk" density="1049.21">RS: Polystyrene PS</material>
<length>0.42545</length>
<thickness>0.00318</thickness>
<shape>ogive</shape>
<shapeparameter>1.0</shapeparameter>
<aftradius>0.05</aftradius>
<aftshoulderradius>0.049215</aftshoulderradius>
<aftshoulderlength>0.0762</aftshoulderlength>
<aftshoulderthickness>0.00318</aftshoulderthickness>
<aftshouldercapped>false</aftshouldercapped>
</nosecone>
<bodytube>
<name>Body tube sup</name>
<appearance>
<ambient red="255" green="255" blue="255"/>
<diffuse red="255" green="255" blue="255"/>
<specular red="255" green="255" blue="255"/>
<decal name="decals/Apocalypse_logo_HAUT_fr2.jpg" rotation="0.0" edgemode="REPEAT">
<center x="0.5" y="0.5"/>
<offset x="-1.0" y="-1.0"/>
<scale x="-2.0" y="-1.0"/>
</decal>
</appearance>
<finish>smooth</finish>
<material type="bulk" density="1121.29">RS: Paper</material>
<length>0.6317999999999999</length>
<thickness>9.699999999999986E-4</thickness>
<radius>0.05</radius>
<subcomponents>
<tubecoupler>
<name>Tube coupler</name>
<position type="top">0.3556</position>
<overridemass>0.07370879999999999</overridemass>
<overridecg>0.0</overridecg>
<overridesubcomponents>false</overridesubcomponents>
<material type="bulk" density="958.705">RS: Kraft phenolic</material>
<length>0.1524</length>
<radialposition>0.0</radialposition>
<radialdirection>0.0</radialdirection>
<outerradius>0.049030000000000004</outerradius>
<thickness>0.0010748000000000077</thickness>
</tubecoupler>
<parachute>
<name>Main Parachute</name>
<position type="top">0.0968</position>
<overridemass>0.08788299999999999</overridemass>
<overridecg>0.0</overridecg>
<overridesubcomponents>false</overridesubcomponents>
<packedlength>0.025</packedlength>
<packedradius>0.045000000000000005</packedradius>
<radialposition>0.0</radialposition>
<radialdirection>0.0</radialdirection>
<cd>0.75</cd>
<deployevent>ejection</deployevent>
<deployaltitude>200.0</deployaltitude>
<deploydelay>0.0</deploydelay>
<material type="surface" density="2.7098958420476206E-5">RS: 1.9 oz. Ripstop Nylon (SkyAngle)</material>
<diameter>0.9144</diameter>
<linecount>8</linecount>
<linelength>0.6858</linelength>
<linematerial type="line" density="0.00102">RS: 1/16 In. braided nylon</linematerial>
</parachute>
</subcomponents>
</bodytube>
<bodytube>
<name>Elec Bay</name>
<appearance>
<ambient red="255" green="255" blue="255"/>
<diffuse red="255" green="255" blue="255"/>
<specular red="255" green="255" blue="255"/>
<decal name="decals/Apocalypse_logo_medium2.jpg" rotation="0.0" edgemode="REPEAT">
<center x="0.5" y="0.5"/>
<offset x="-1.0" y="-1.0"/>
<scale x="-2.0" y="-1.0"/>
</decal>
</appearance>
<finish>smooth</finish>
<material type="bulk" density="1121.29">RS: Paper</material>
<length>0.1118</length>
<thickness>9.699999999999986E-4</thickness>
<radius>0.05</radius>
<subcomponents>
<tubecoupler>
<name>Tube coupler</name>
<position type="top">0.3556</position>
<overridemass>0.07370879999999999</overridemass>
<overridecg>0.0</overridecg>
<overridesubcomponents>false</overridesubcomponents>
<material type="bulk" density="958.705">RS: Kraft phenolic</material>
<length>0.1524</length>
<radialposition>0.0</radialposition>
<radialdirection>0.0</radialdirection>
<outerradius>0.049030000000000004</outerradius>
<thickness>0.0010748000000000077</thickness>
</tubecoupler>
</subcomponents>
</bodytube>
<bodytube>
<name>Body tube inf1</name>
<appearance>
<ambient red="255" green="255" blue="255"/>
<diffuse red="255" green="255" blue="255"/>
<specular red="255" green="255" blue="255"/>
<decal name="decals/Apocalypse_logo_bas_coup2.jpg" rotation="0.0" edgemode="REPEAT">
<center x="0.5" y="0.5"/>
<offset x="-1.0" y="-1.0"/>
<scale x="-2.0" y="-1.0"/>
</decal>
</appearance>
<finish>smooth</finish>
<material type="bulk" density="1121.29">RS: Paper</material>
<length>0.2018</length>
<thickness>9.699999999999986E-4</thickness>
<radius>0.05</radius>
<subcomponents>
<tubecoupler>
<name>Tube coupler</name>
<position type="top">0.3556</position>
<overridemass>0.07370879999999999</overridemass>
<overridecg>0.0</overridecg>
<overridesubcomponents>false</overridesubcomponents>
<material type="bulk" density="958.705">RS: Kraft phenolic</material>
<length>0.1524</length>
<radialposition>0.0</radialposition>
<radialdirection>0.0</radialdirection>
<outerradius>0.049030000000000004</outerradius>
<thickness>0.0010748000000000077</thickness>
</tubecoupler>
<parachute>
<name>drogue Parachute</name>
<position type="top">0.12029999999999999</position>
<overridemass>0.08788299999999999</overridemass>
<overridecg>0.0</overridecg>
<overridesubcomponents>false</overridesubcomponents>
<packedlength>0.025</packedlength>
<packedradius>0.045000000000000005</packedradius>
<radialposition>0.0</radialposition>
<radialdirection>0.0</radialdirection>
<cd>0.75</cd>
<deployevent>ejection</deployevent>
<deployaltitude>200.0</deployaltitude>
<deploydelay>0.0</deploydelay>
<material type="surface" density="6.663512241985067E-4">RS: 1.9 oz. Ripstop Nylon (SkyAngle)</material>
<diameter>0.1844</diameter>
<linecount>8</linecount>
<linelength>0.6858</linelength>
<linematerial type="line" density="0.00102">RS: 1/16 In. braided nylon</linematerial>
</parachute>
</subcomponents>
</bodytube>
<bodytube>
<name>Body tube inf2</name>
<appearance>
<ambient red="206" green="198" blue="187"/>
<diffuse red="206" green="198" blue="187"/>
<specular red="206" green="198" blue="187"/>
</appearance>
<finish>smooth</finish>
<material type="bulk" density="1121.29">RS: Paper</material>
<length>0.5636</length>
<thickness>9.699999999999986E-4</thickness>
<radius>0.05</radius>
<subcomponents>
<innertube>
<name>Body tube</name>
<position type="bottom">0.0</position>
<material type="bulk" density="1121.29">RS: Paper</material>
<length>0.4606</length>
<radialposition>0.0</radialposition>
<radialdirection>0.0</radialdirection>
<outerradius>0.02743</outerradius>
<thickness>2.500000000000002E-4</thickness>
<clusterconfiguration>single</clusterconfiguration>
<clusterscale>1.0</clusterscale>
<clusterrotation>0.0</clusterrotation>
<motormount>
<ignitionevent>automatic</ignitionevent>
<ignitiondelay>0.0</ignitiondelay>
<overhang>0.0</overhang>
</motormount>
</innertube>
<freeformfinset>
<name>Custom Fin-1</name>
<appearance>
<ambient red="255" green="255" blue="255"/>
<diffuse red="255" green="255" blue="255"/>
<specular red="255" green="255" blue="255"/>
<decal name="decals/fin rad-test5.jpg" rotation="0.0" edgemode="MIRROR">
<center x="0.5" y="0.5"/>
<offset x="-1.0" y="-1.0"/>
<scale x="-1.0" y="-1.0"/>
</decal>
</appearance>
<position type="top">0.127</position>
<finish>smooth</finish>
<material type="bulk" density="680.785">RS: Birch</material>
<fincount>1</fincount>
<rotation>0.0</rotation>
<thickness>0.00478</thickness>
<crosssection>rounded</crosssection>
<cant>0.0</cant>
<tabheight>0.023370000000000002</tabheight>
<tablength>0.4147</tablength>
<tabposition relativeto="front">0.0</tabposition>
<finpoints>
<point x="0.0" y="0.0"/>
<point x="0.0136306" y="0.0152533"/>
<point x="0.117158" y="0.0253139"/>
<point x="0.2284" y="0.128"/>
<point x="0.258" y="0.119"/>
<point x="0.282" y="0.025"/>
<point x="0.32" y="0.022"/>
<point x="0.354" y="0.067"/>
<point x="0.382" y="0.058"/>
<point x="0.395" y="0.013"/>
<point x="0.398" y="0.011300000000000001"/>
<point x="0.406" y="0.0020"/>
<point x="0.406" y="0.0"/>
</finpoints>
</freeformfinset>
<freeformfinset>
<name>Contre fins 1a</name>
<appearance>
<ambient red="255" green="0" blue="0"/>
<diffuse red="255" green="0" blue="0"/>
<specular red="255" green="0" blue="0"/>
</appearance>
<position type="top">0.1349</position>
<finish>smooth</finish>
<material type="bulk" density="680.785">RS: Birch</material>
<fincount>1</fincount>
<rotation>-2.8650009700383143</rotation>
<thickness>0.00478</thickness>
<crosssection>rounded</crosssection>
<cant>0.0</cant>
<finpoints>
<point x="0.0" y="0.0"/>
<point x="0.0038" y="0.0070"/>
<point x="0.114111" y="0.019915600000000002"/>
<point x="0.272906" y="0.02"/>
<point x="0.381787" y="0.01"/>
<point x="0.38726900000000003" y="0.0090"/>
<point x="0.391" y="0.0040"/>
<point x="0.392101" y="0.0"/>
</finpoints>
</freeformfinset>
<freeformfinset>
<name>Contre fins 1b</name>
<appearance>
<ambient red="255" green="0" blue="0"/>
<diffuse red="255" green="0" blue="0"/>
<specular red="255" green="0" blue="0"/>
</appearance>
<position type="top">0.1349</position>
<finish>smooth</finish>
<material type="bulk" density="680.785">RS: Birch</material>
<fincount>1</fincount>
<rotation>3.009999399252072</rotation>
<thickness>0.00478</thickness>
<crosssection>rounded</crosssection>
<cant>0.0</cant>
<finpoints>
<point x="0.0" y="0.0"/>
<point x="0.0038" y="0.0070"/>
<point x="0.114" y="0.02"/>
<point x="0.272906" y="0.02"/>
<point x="0.381787" y="0.01"/>
<point x="0.38726900000000003" y="0.0090"/>
<point x="0.391" y="0.0040"/>
<point x="0.392101" y="0.0"/>
</finpoints>
</freeformfinset>
<freeformfinset>
<name>Custom Fin-2</name>
<appearance>
<ambient red="255" green="255" blue="255"/>
<diffuse red="255" green="255" blue="255"/>
<specular red="255" green="255" blue="255"/>
<decal name="decals/fin rad-test5.jpg" rotation="0.0" edgemode="MIRROR">
<center x="0.5" y="0.5"/>
<offset x="-1.0" y="-1.0"/>
<scale x="-1.0" y="-1.0"/>
</decal>
</appearance>
<position type="top">0.127</position>
<finish>smooth</finish>
<material type="bulk" density="680.785">RS: Birch</material>
<fincount>1</fincount>
<rotation>90.0002104591497</rotation>
<thickness>0.00478</thickness>
<crosssection>rounded</crosssection>
<cant>0.0</cant>
<tabheight>0.023370000000000002</tabheight>
<tablength>0.3175</tablength>
<tabposition relativeto="front">0.0</tabposition>
<finpoints>
<point x="0.0" y="0.0"/>
<point x="0.0136306" y="0.0152533"/>
<point x="0.117158" y="0.0253139"/>
<point x="0.2284" y="0.128"/>
<point x="0.258" y="0.119"/>
<point x="0.282" y="0.025"/>
<point x="0.32" y="0.022"/>
<point x="0.354" y="0.067"/>
<point x="0.382" y="0.058"/>
<point x="0.395" y="0.013"/>
<point x="0.398" y="0.011300000000000001"/>
<point x="0.406" y="0.0020"/>
<point x="0.406" y="0.0"/>
</finpoints>
</freeformfinset>
<freeformfinset>
<name>Contre fins 2a</name>
<appearance>
<ambient red="255" green="0" blue="0"/>
<diffuse red="255" green="0" blue="0"/>
<specular red="255" green="0" blue="0"/>
</appearance>
<position type="top">0.1349</position>
<finish>smooth</finish>
<material type="bulk" density="680.785">RS: Birch</material>
<fincount>1</fincount>
<rotation>86.13503717319718</rotation>
<thickness>0.00478</thickness>
<crosssection>rounded</crosssection>
<cant>0.0</cant>
<finpoints>
<point x="0.0" y="0.0"/>
<point x="0.0038" y="0.0070"/>
<point x="0.114" y="0.02"/>
<point x="0.272906" y="0.02"/>
<point x="0.381787" y="0.01"/>
<point x="0.38726900000000003" y="0.0090"/>
<point x="0.391" y="0.0040"/>
<point x="0.392101" y="0.0"/>
</finpoints>
</freeformfinset>
<freeformfinset>
<name>Contre fins 2b</name>
<appearance>
<ambient red="255" green="0" blue="0"/>
<diffuse red="255" green="0" blue="0"/>
<specular red="255" green="0" blue="0"/>
</appearance>
<position type="top">0.1349</position>
<finish>smooth</finish>
<material type="bulk" density="680.785">RS: Birch</material>
<fincount>1</fincount>
<rotation>93.38524511278261</rotation>
<thickness>0.00478</thickness>
<crosssection>rounded</crosssection>
<cant>0.0</cant>
<finpoints>
<point x="0.0" y="0.0"/>
<point x="0.0038" y="0.0070"/>
<point x="0.114" y="0.02"/>
<point x="0.272906" y="0.02"/>
<point x="0.381787" y="0.01"/>
<point x="0.38726900000000003" y="0.0090"/>
<point x="0.391" y="0.0040"/>
<point x="0.392101" y="0.0"/>
</finpoints>
</freeformfinset>
<freeformfinset>
<name>Custom Fin-3</name>
<appearance>
<ambient red="255" green="255" blue="255"/>
<diffuse red="255" green="255" blue="255"/>
<specular red="255" green="255" blue="255"/>
<decal name="decals/fin rad-test5.jpg" rotation="0.0" edgemode="MIRROR">
<center x="0.5" y="0.5"/>
<offset x="-1.0" y="-1.0"/>
<scale x="-1.0" y="-1.0"/>
</decal>
</appearance>
<position type="top">0.127</position>
<finish>smooth</finish>
<material type="bulk" density="680.785">RS: Birch</material>
<fincount>1</fincount>
<rotation>179.99984796050427</rotation>
<thickness>0.00478</thickness>
<crosssection>rounded</crosssection>
<cant>0.0</cant>
<tabheight>0.023370000000000002</tabheight>
<tablength>0.3175</tablength>
<tabposition relativeto="front">0.0</tabposition>
<finpoints>
<point x="0.0" y="0.0"/>
<point x="0.0136306" y="0.0152533"/>
<point x="0.117158" y="0.0253139"/>
<point x="0.2284" y="0.128"/>
<point x="0.258" y="0.119"/>
<point x="0.282" y="0.025"/>
<point x="0.32" y="0.022"/>
<point x="0.354" y="0.067"/>
<point x="0.382" y="0.058"/>
<point x="0.395" y="0.013"/>
<point x="0.398" y="0.011300000000000001"/>
<point x="0.406" y="0.0020"/>
<point x="0.406" y="0.0"/>
</finpoints>
</freeformfinset>
<freeformfinset>
<name>Contre fins 3a</name>
<appearance>
<ambient red="255" green="0" blue="0"/>
<diffuse red="255" green="0" blue="0"/>
<specular red="255" green="0" blue="0"/>
</appearance>
<position type="top">0.1349</position>
<finish>smooth</finish>
<material type="bulk" density="680.785">RS: Birch</material>
<fincount>1</fincount>
<rotation>176.00976987521324</rotation>
<thickness>0.00478</thickness>
<crosssection>rounded</crosssection>
<cant>0.0</cant>
<finpoints>
<point x="0.0" y="0.0"/>
<point x="0.0038" y="0.0070"/>
<point x="0.114" y="0.02"/>
<point x="0.272906" y="0.02"/>
<point x="0.381787" y="0.01"/>
<point x="0.38726900000000003" y="0.0090"/>
<point x="0.391" y="0.0040"/>
<point x="0.392101" y="0.0"/>
</finpoints>
</freeformfinset>
<freeformfinset>
<name>Contre fins 3b</name>
<appearance>
<ambient red="255" green="0" blue="0"/>
<diffuse red="255" green="0" blue="0"/>
<specular red="255" green="0" blue="0"/>
</appearance>
<position type="top">0.1349</position>
<finish>smooth</finish>
<material type="bulk" density="680.785">RS: Birch</material>
<fincount>1</fincount>
<rotation>-177.2399102613591</rotation>
<thickness>0.00478</thickness>
<crosssection>rounded</crosssection>
<cant>0.0</cant>
<finpoints>
<point x="0.0" y="0.0"/>
<point x="0.0038" y="0.0070"/>
<point x="0.114" y="0.02"/>
<point x="0.272906" y="0.02"/>
<point x="0.381787" y="0.01"/>
<point x="0.38726900000000003" y="0.0090"/>
<point x="0.391" y="0.0040"/>
<point x="0.392101" y="0.0"/>
</finpoints>
</freeformfinset>
<freeformfinset>
<name>Custom Fin-4</name>
<appearance>
<ambient red="255" green="255" blue="255"/>
<diffuse red="255" green="255" blue="255"/>
<specular red="255" green="255" blue="255"/>
<decal name="decals/fin rad-test5.jpg" rotation="0.0" edgemode="MIRROR">
<center x="0.5" y="0.5"/>
<offset x="-1.0" y="-1.0"/>
<scale x="-1.0" y="-1.0"/>
</decal>
</appearance>
<position type="top">0.127</position>
<finish>smooth</finish>
<material type="bulk" density="680.785">RS: Birch</material>
<fincount>1</fincount>
<rotation>-90.0002104591497</rotation>
<thickness>0.00478</thickness>
<crosssection>rounded</crosssection>
<cant>0.0</cant>
<tabheight>0.023370000000000002</tabheight>
<tablength>0.3175</tablength>
<tabposition relativeto="front">0.0</tabposition>
<finpoints>
<point x="0.0" y="0.0"/>
<point x="0.0136306" y="0.0152533"/>
<point x="0.117158" y="0.0253139"/>
<point x="0.2284" y="0.128"/>
<point x="0.258" y="0.119"/>
<point x="0.282" y="0.025"/>
<point x="0.32" y="0.022"/>
<point x="0.354" y="0.067"/>
<point x="0.382" y="0.058"/>
<point x="0.395" y="0.013"/>
<point x="0.398" y="0.011300000000000001"/>
<point x="0.406" y="0.0020"/>
<point x="0.406" y="0.0"/>
</finpoints>
</freeformfinset>
<freeformfinset>
<name>Contre fins 4a</name>
<appearance>
<ambient red="255" green="0" blue="0"/>
<diffuse red="255" green="0" blue="0"/>
<specular red="255" green="0" blue="0"/>
</appearance>
<position type="top">0.1349</position>
<finish>smooth</finish>
<material type="bulk" density="680.785">RS: Birch</material>
<fincount>1</fincount>
<rotation>-86.49027100617829</rotation>
<thickness>0.00478</thickness>
<crosssection>rounded</crosssection>
<cant>0.0</cant>
<finpoints>
<point x="0.0" y="0.0"/>
<point x="0.0038" y="0.0070"/>
<point x="0.114" y="0.02"/>
<point x="0.272906" y="0.02"/>
<point x="0.381787" y="0.01"/>
<point x="0.38726900000000003" y="0.0090"/>
<point x="0.391" y="0.0040"/>
<point x="0.392101" y="0.0"/>
</finpoints>
</freeformfinset>
<freeformfinset>
<name>Contre fins 4b</name>
<appearance>
<ambient red="255" green="0" blue="0"/>
<diffuse red="255" green="0" blue="0"/>
<specular red="255" green="0" blue="0"/>
</appearance>
<position type="top">0.1349</position>
<finish>smooth</finish>
<material type="bulk" density="680.785">RS: Birch</material>
<fincount>1</fincount>
<rotation>-94.48990774179484</rotation>
<thickness>0.00478</thickness>
<crosssection>rounded</crosssection>
<cant>0.0</cant>
<finpoints>
<point x="0.0" y="0.0"/>
<point x="0.0038" y="0.0070"/>
<point x="0.114" y="0.02"/>
<point x="0.272906" y="0.02"/>
<point x="0.381787" y="0.01"/>
<point x="0.38726900000000003" y="0.0090"/>
<point x="0.391" y="0.0040"/>
<point x="0.392101" y="0.0"/>
</finpoints>
</freeformfinset>
<centeringring>
<name>Ring</name>
<position type="top">0.10790000000000001</position>
<material type="bulk" density="724.996">RS: Aircraft plywood (Birch)</material>
<length>0.00318</length>
<radialposition>0.0</radialposition>
<radialdirection>0.0</radialdirection>
<outerradius>0.049030000000000004</outerradius>
<innerradius>auto</innerradius>
</centeringring>
<centeringring>
<name>Ring</name>
<position type="top">0.5596</position>
<material type="bulk" density="724.996">RS: Aircraft plywood (Birch)</material>
<length>0.00318</length>
<radialposition>0.0</radialposition>
<radialdirection>0.0</radialdirection>
<outerradius>0.049030000000000004</outerradius>
<innerradius>auto</innerradius>
</centeringring>
<bulkhead>
<name>Bulkhead</name>
<position type="top">0.0</position>
<material type="bulk" density="680.785">RS: Birch</material>
<length>0.0030499999999999998</length>
<radialposition>0.0</radialposition>
<radialdirection>0.0</radialdirection>
<outerradius>0.049030000000000004</outerradius>
</bulkhead>
<launchlug>
<name>Launch lug</name>
<appearance>
<ambient red="170" green="170" blue="255"/>
<diffuse red="170" green="170" blue="255"/>
<specular red="170" green="170" blue="255"/>
</appearance>
<position type="top">0.54</position>
<finish>smooth</finish>
<material type="bulk" density="1199.78">RS: Polycarbonate</material>
<radius>0.006715</radius>
<length>0.01</length>
<thickness>0.0010</thickness>
<radialdirection>-134.99974273092943</radialdirection>
</launchlug>
<launchlug>
<name>Launch lug</name>
<appearance>
<ambient red="170" green="170" blue="255"/>
<diffuse red="170" green="170" blue="255"/>
<specular red="170" green="170" blue="255"/>
</appearance>
<position type="top">0.0125</position>
<finish>smooth</finish>
<material type="bulk" density="1199.78">RS: Polycarbonate</material>
<radius>0.006715</radius>
<length>0.01</length>
<thickness>0.0010</thickness>
<radialdirection>-134.99974273092943</radialdirection>
</launchlug>
</subcomponents>
</bodytube>
<transition>
<name>Transition</name>
<appearance>
<ambient red="240" green="240" blue="240"/>
<diffuse red="240" green="240" blue="240"/>
<specular red="240" green="240" blue="240"/>
</appearance>
<finish>polished</finish>
<material type="bulk" density="847.056">RS: Urethane</material>
<length>0.04445</length>
<thickness>0.00521</thickness>
<shape>conical</shape>
<foreradius>0.05</foreradius>
<aftradius>0.03975</aftradius>
<foreshoulderradius>0.049530000000000005</foreshoulderradius>
<foreshoulderlength>0.00635</foreshoulderlength>
<foreshoulderthickness>0.00521</foreshoulderthickness>
<foreshouldercapped>false</foreshouldercapped>
<aftshoulderradius>0.0</aftshoulderradius>
<aftshoulderlength>0.0</aftshoulderlength>
<aftshoulderthickness>0.00521</aftshoulderthickness>
<aftshouldercapped>false</aftshouldercapped>
</transition>
</subcomponents>
</stage>
</subcomponents>
</rocket>
<simulations>
</simulations>
</openrocket>

View File

@ -0,0 +1,830 @@
<RockSimDocument>
<FileVersion>4</FileVersion>
<DesignInformation>
<RocketDesign>
<Name>apocalypse</Name>
<StageCount>1</StageCount>
<DisplayFlags>7</DisplayFlags>
<ViewType>0</ViewType>
<ViewStageCount>3</ViewStageCount>
<ViewTypeEdit>0</ViewTypeEdit>
<ViewStageCountEdit>3</ViewStageCountEdit>
<ZoomFactor>0.0</ZoomFactor>
<ZoomFactorEdit>0.0</ZoomFactorEdit>
<ScrollPosX>0</ScrollPosX>
<ScrollPosY>0</ScrollPosY>
<ScrollPosXEdit>0</ScrollPosXEdit>
<ScrollPosYEdit>0</ScrollPosYEdit>
<ThreeDFlags>0</ThreeDFlags>
<ThreeDFlagsEdit>0</ThreeDFlagsEdit>
<LastSerialNumber>29</LastSerialNumber>
<Stage3Mass>4000.0</Stage3Mass>
<Stage2Mass>0.0</Stage2Mass>
<Stage1Mass>0.0</Stage1Mass>
<Stage3CG>1058.29</Stage3CG>
<Stage2CGAlone>0.0</Stage2CGAlone>
<Stage1CGAlone>0.0</Stage1CGAlone>
<Stage321CG>0.0</Stage321CG>
<Stage32CG>0.0</Stage32CG>
<CPCalcFlags>1</CPCalcFlags>
<CPSimFlags>1</CPSimFlags>
<UseKnownMass>1</UseKnownMass>
<Stage3Parts>
<NoseCone>
<KnownMass>283.495</KnownMass>
<Density>1049.21</Density>
<Material>Polystyrene PS</Material>
<Name>Nose cone</Name>
<KnownCG>228.6</KnownCG>
<UseKnownCG>1</UseKnownCG>
<Xb>0.0</Xb>
<CalcMass>361.54749538948397</CalcMass>
<CalcCG>228.6</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>0.0</RadialAngle>
<LocationMode>0</LocationMode>
<Len>425.45</Len>
<FinishCode>1</FinishCode>
<SerialNo>1</SerialNo>
<ShapeCode>1</ShapeCode>
<ConstructionType>1</ConstructionType>
<WallThickness>3.18</WallThickness>
<ShapeParameter>0.0</ShapeParameter>
<AttachedParts/>
<BaseDia>100.0</BaseDia>
<ShoulderLen>76.2</ShoulderLen>
<ShoulderOD>98.43</ShoulderOD>
</NoseCone>
<BodyTube>
<KnownMass>213.78929571200192</KnownMass>
<Density>1121.29</Density>
<Material>Paper</Material>
<Name>Body tube sup</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>0.0</Xb>
<CalcMass>213.78929571200192</CalcMass>
<CalcCG>315.9</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>0.0</RadialAngle>
<LocationMode>0</LocationMode>
<Len>631.8</Len>
<FinishCode>1</FinishCode>
<SerialNo>2</SerialNo>
<OD>100.0</OD>
<ID>98.06</ID>
<IsMotorMount>0</IsMotorMount>
<MotorDia>98.06</MotorDia>
<EngineOverhang>0.0</EngineOverhang>
<IsInsideTube>0</IsInsideTube>
<AttachedParts>
<Ring>
<KnownMass>73.7088</KnownMass>
<Density>958.705</Density>
<Material>Kraft phenolic</Material>
<Name>Tube coupler</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>1</UseKnownCG>
<Xb>355.6</Xb>
<CalcMass>47.84680640645568</CalcMass>
<CalcCG>0.0</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>0.0</RadialAngle>
<LocationMode>0</LocationMode>
<Len>152.4</Len>
<FinishCode>0</FinishCode>
<SerialNo>3</SerialNo>
<OD>98.06</OD>
<ID>95.9104</ID>
<UsageCode>4</UsageCode>
<AutoSize>0</AutoSize>
</Ring>
<Parachute>
<KnownMass>87.883</KnownMass>
<Density>2.7098958420476207E-6</Density>
<Material>1.9 oz. Ripstop Nylon (SkyAngle)</Material>
<Name>Main Parachute</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>1</UseKnownCG>
<Xb>96.8</Xb>
<CalcMass>5.613923693399999</CalcMass>
<CalcCG>0.0</CalcCG>
<DensityType>1</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>0.0</RadialAngle>
<LocationMode>0</LocationMode>
<Len>25.0</Len>
<FinishCode>0</FinishCode>
<SerialNo>4</SerialNo>
<Dia>914.4</Dia>
<ShroudLineCount>8</ShroudLineCount>
<Thickness>0.0</Thickness>
<ShroudLineLen>685.8</ShroudLineLen>
<ChuteCount>1</ChuteCount>
<ShroudLineMassPerMM>0.00102</ShroudLineMassPerMM>
<ShroudLineMaterial>1/16 In. braided nylon</ShroudLineMaterial>
<DragCoefficient>0.75</DragCoefficient>
</Parachute>
</AttachedParts>
</BodyTube>
<BodyTube>
<KnownMass>37.831027636280204</KnownMass>
<Density>1121.29</Density>
<Material>Paper</Material>
<Name>Elec Bay</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>0.0</Xb>
<CalcMass>37.831027636280204</CalcMass>
<CalcCG>55.9</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>0.0</RadialAngle>
<LocationMode>0</LocationMode>
<Len>111.8</Len>
<FinishCode>1</FinishCode>
<SerialNo>5</SerialNo>
<OD>100.0</OD>
<ID>98.06</ID>
<IsMotorMount>0</IsMotorMount>
<MotorDia>98.06</MotorDia>
<EngineOverhang>0.0</EngineOverhang>
<IsInsideTube>0</IsInsideTube>
<AttachedParts>
<Ring>
<KnownMass>73.7088</KnownMass>
<Density>958.705</Density>
<Material>Kraft phenolic</Material>
<Name>Tube coupler</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>1</UseKnownCG>
<Xb>355.6</Xb>
<CalcMass>47.84680640645568</CalcMass>
<CalcCG>0.0</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>0.0</RadialAngle>
<LocationMode>0</LocationMode>
<Len>152.4</Len>
<FinishCode>0</FinishCode>
<SerialNo>6</SerialNo>
<OD>98.06</OD>
<ID>95.9104</ID>
<UsageCode>4</UsageCode>
<AutoSize>0</AutoSize>
</Ring>
</AttachedParts>
</BodyTube>
<BodyTube>
<KnownMass>68.28534326477062</KnownMass>
<Density>1121.29</Density>
<Material>Paper</Material>
<Name>Body tube inf1</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>0.0</Xb>
<CalcMass>68.28534326477062</CalcMass>
<CalcCG>100.9</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>0.0</RadialAngle>
<LocationMode>0</LocationMode>
<Len>201.8</Len>
<FinishCode>1</FinishCode>
<SerialNo>7</SerialNo>
<OD>100.0</OD>
<ID>98.06</ID>
<IsMotorMount>0</IsMotorMount>
<MotorDia>98.06</MotorDia>
<EngineOverhang>0.0</EngineOverhang>
<IsInsideTube>0</IsInsideTube>
<AttachedParts>
<Ring>
<KnownMass>73.7088</KnownMass>
<Density>958.705</Density>
<Material>Kraft phenolic</Material>
<Name>Tube coupler</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>1</UseKnownCG>
<Xb>355.6</Xb>
<CalcMass>47.84680640645568</CalcMass>
<CalcCG>0.0</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>0.0</RadialAngle>
<LocationMode>0</LocationMode>
<Len>152.4</Len>
<FinishCode>0</FinishCode>
<SerialNo>8</SerialNo>
<OD>98.06</OD>
<ID>95.9104</ID>
<UsageCode>4</UsageCode>
<AutoSize>0</AutoSize>
</Ring>
<Parachute>
<KnownMass>87.883</KnownMass>
<Density>6.663512241985067E-5</Density>
<Material>1.9 oz. Ripstop Nylon (SkyAngle)</Material>
<Name>drogue Parachute</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>1</UseKnownCG>
<Xb>120.3</Xb>
<CalcMass>5.613923693399999</CalcMass>
<CalcCG>0.0</CalcCG>
<DensityType>1</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>0.0</RadialAngle>
<LocationMode>0</LocationMode>
<Len>25.0</Len>
<FinishCode>0</FinishCode>
<SerialNo>9</SerialNo>
<Dia>184.4</Dia>
<ShroudLineCount>8</ShroudLineCount>
<Thickness>0.0</Thickness>
<ShroudLineLen>685.8</ShroudLineLen>
<ChuteCount>1</ChuteCount>
<ShroudLineMassPerMM>0.00102</ShroudLineMassPerMM>
<ShroudLineMaterial>1/16 In. braided nylon</ShroudLineMaterial>
<DragCoefficient>0.75</DragCoefficient>
</Parachute>
</AttachedParts>
</BodyTube>
<BodyTube>
<KnownMass>190.71169209130176</KnownMass>
<Density>1121.29</Density>
<Material>Paper</Material>
<Name>Body tube inf2</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>0.0</Xb>
<CalcMass>190.71169209130176</CalcMass>
<CalcCG>281.8</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>0.0</RadialAngle>
<LocationMode>0</LocationMode>
<Len>563.6</Len>
<FinishCode>1</FinishCode>
<SerialNo>10</SerialNo>
<OD>100.0</OD>
<ID>98.06</ID>
<IsMotorMount>0</IsMotorMount>
<MotorDia>98.06</MotorDia>
<EngineOverhang>0.0</EngineOverhang>
<IsInsideTube>0</IsInsideTube>
<AttachedParts>
<BodyTube>
<KnownMass>22.15154083044647</KnownMass>
<Density>1121.29</Density>
<Material>Paper</Material>
<Name>Body tube</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>-0.0</Xb>
<CalcMass>22.15154083044647</CalcMass>
<CalcCG>230.3</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>0.0</RadialAngle>
<LocationMode>2</LocationMode>
<Len>460.6</Len>
<FinishCode>0</FinishCode>
<SerialNo>11</SerialNo>
<OD>54.86</OD>
<ID>54.36</ID>
<IsMotorMount>1</IsMotorMount>
<MotorDia>54.36</MotorDia>
<EngineOverhang>0.0</EngineOverhang>
<IsInsideTube>1</IsInsideTube>
<AttachedParts/>
</BodyTube>
<CustomFinSet>
<KnownMass>98.30302513638873</KnownMass>
<Density>680.785</Density>
<Material>Birch</Material>
<Name>Custom Fin-1</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>127.0</Xb>
<CalcMass>98.30302513638873</CalcMass>
<CalcCG>220.45869619622917</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>0.0</RadialAngle>
<LocationMode>0</LocationMode>
<Len>0.0</Len>
<FinishCode>1</FinishCode>
<SerialNo>12</SerialNo>
<FinCount>1</FinCount>
<RootChord>0.0</RootChord>
<TipChord>0.0</TipChord>
<SemiSpan>0.0</SemiSpan>
<SweepDistance>0.0</SweepDistance>
<Thickness>4.78</Thickness>
<ShapeCode>2</ShapeCode>
<TipShapeCode>1</TipShapeCode>
<TabLength>414.7</TabLength>
<TabDepth>23.37</TabDepth>
<TabOffset>0.0</TabOffset>
<SweepMode>1</SweepMode>
<CantAngle>0.0</CantAngle>
<PointList>406.0,0.0|406.0,2.0|398.0,11.3|395.0,13.0|382.0,58.0|354.0,67.0|320.0,22.0|282.0,25.0|258.0,119.0|228.4,128.0|117.158,25.3139|13.6306,15.2533|0.0,0.0|</PointList>
</CustomFinSet>
<CustomFinSet>
<KnownMass>20.54997772807576</KnownMass>
<Density>680.785</Density>
<Material>Birch</Material>
<Name>Contre fins 1a</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>134.9</Xb>
<CalcMass>20.54997772807576</CalcMass>
<CalcCG>198.96585221328334</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>-0.0500037</RadialAngle>
<LocationMode>0</LocationMode>
<Len>0.0</Len>
<FinishCode>1</FinishCode>
<SerialNo>13</SerialNo>
<FinCount>1</FinCount>
<RootChord>0.0</RootChord>
<TipChord>0.0</TipChord>
<SemiSpan>0.0</SemiSpan>
<SweepDistance>0.0</SweepDistance>
<Thickness>4.78</Thickness>
<ShapeCode>2</ShapeCode>
<TipShapeCode>1</TipShapeCode>
<TabLength>50.0</TabLength>
<TabDepth>0.0</TabDepth>
<TabOffset>0.0</TabOffset>
<SweepMode>1</SweepMode>
<CantAngle>0.0</CantAngle>
<PointList>392.101,0.0|391.0,4.0|387.269,9.0|381.787,10.0|272.906,20.0|114.111,19.9156|3.8,7.0|0.0,0.0|</PointList>
</CustomFinSet>
<CustomFinSet>
<KnownMass>20.58888761237905</KnownMass>
<Density>680.785</Density>
<Material>Birch</Material>
<Name>Contre fins 1b</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>134.9</Xb>
<CalcMass>20.58888761237905</CalcMass>
<CalcCG>198.83005192727484</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>0.0525344</RadialAngle>
<LocationMode>0</LocationMode>
<Len>0.0</Len>
<FinishCode>1</FinishCode>
<SerialNo>14</SerialNo>
<FinCount>1</FinCount>
<RootChord>0.0</RootChord>
<TipChord>0.0</TipChord>
<SemiSpan>0.0</SemiSpan>
<SweepDistance>0.0</SweepDistance>
<Thickness>4.78</Thickness>
<ShapeCode>2</ShapeCode>
<TipShapeCode>1</TipShapeCode>
<TabLength>50.0</TabLength>
<TabDepth>0.0</TabDepth>
<TabOffset>0.0</TabOffset>
<SweepMode>1</SweepMode>
<CantAngle>0.0</CantAngle>
<PointList>392.101,0.0|391.0,4.0|387.269,9.0|381.787,10.0|272.906,20.0|114.0,20.0|3.8,7.0|0.0,0.0|</PointList>
</CustomFinSet>
<CustomFinSet>
<KnownMass>90.9849300733435</KnownMass>
<Density>680.785</Density>
<Material>Birch</Material>
<Name>Custom Fin-2</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>127.0</Xb>
<CalcMass>90.9849300733435</CalcMass>
<CalcCG>208.74448258434109</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>1.5707999999999998</RadialAngle>
<LocationMode>0</LocationMode>
<Len>0.0</Len>
<FinishCode>1</FinishCode>
<SerialNo>15</SerialNo>
<FinCount>1</FinCount>
<RootChord>0.0</RootChord>
<TipChord>0.0</TipChord>
<SemiSpan>0.0</SemiSpan>
<SweepDistance>0.0</SweepDistance>
<Thickness>4.78</Thickness>
<ShapeCode>2</ShapeCode>
<TipShapeCode>1</TipShapeCode>
<TabLength>317.5</TabLength>
<TabDepth>23.37</TabDepth>
<TabOffset>0.0</TabOffset>
<SweepMode>1</SweepMode>
<CantAngle>0.0</CantAngle>
<PointList>406.0,0.0|406.0,2.0|398.0,11.3|395.0,13.0|382.0,58.0|354.0,67.0|320.0,22.0|282.0,25.0|258.0,119.0|228.4,128.0|117.158,25.3139|13.6306,15.2533|0.0,0.0|</PointList>
</CustomFinSet>
<CustomFinSet>
<KnownMass>20.58888761237905</KnownMass>
<Density>680.785</Density>
<Material>Birch</Material>
<Name>Contre fins 2a</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>134.9</Xb>
<CalcMass>20.58888761237905</CalcMass>
<CalcCG>198.83005192727484</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>1.50334</RadialAngle>
<LocationMode>0</LocationMode>
<Len>0.0</Len>
<FinishCode>1</FinishCode>
<SerialNo>16</SerialNo>
<FinCount>1</FinCount>
<RootChord>0.0</RootChord>
<TipChord>0.0</TipChord>
<SemiSpan>0.0</SemiSpan>
<SweepDistance>0.0</SweepDistance>
<Thickness>4.78</Thickness>
<ShapeCode>2</ShapeCode>
<TipShapeCode>1</TipShapeCode>
<TabLength>50.0</TabLength>
<TabDepth>0.0</TabDepth>
<TabOffset>0.0</TabOffset>
<SweepMode>1</SweepMode>
<CantAngle>0.0</CantAngle>
<PointList>392.101,0.0|391.0,4.0|387.269,9.0|381.787,10.0|272.906,20.0|114.0,20.0|3.8,7.0|0.0,0.0|</PointList>
</CustomFinSet>
<CustomFinSet>
<KnownMass>20.58888761237905</KnownMass>
<Density>680.785</Density>
<Material>Birch</Material>
<Name>Contre fins 2b</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>134.9</Xb>
<CalcMass>20.58888761237905</CalcMass>
<CalcCG>198.83005192727484</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>1.62988</RadialAngle>
<LocationMode>0</LocationMode>
<Len>0.0</Len>
<FinishCode>1</FinishCode>
<SerialNo>17</SerialNo>
<FinCount>1</FinCount>
<RootChord>0.0</RootChord>
<TipChord>0.0</TipChord>
<SemiSpan>0.0</SemiSpan>
<SweepDistance>0.0</SweepDistance>
<Thickness>4.78</Thickness>
<ShapeCode>2</ShapeCode>
<TipShapeCode>1</TipShapeCode>
<TabLength>50.0</TabLength>
<TabDepth>0.0</TabDepth>
<TabOffset>0.0</TabOffset>
<SweepMode>1</SweepMode>
<CantAngle>0.0</CantAngle>
<PointList>392.101,0.0|391.0,4.0|387.269,9.0|381.787,10.0|272.906,20.0|114.0,20.0|3.8,7.0|0.0,0.0|</PointList>
</CustomFinSet>
<CustomFinSet>
<KnownMass>90.9849300733435</KnownMass>
<Density>680.785</Density>
<Material>Birch</Material>
<Name>Custom Fin-3</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>127.0</Xb>
<CalcMass>90.9849300733435</CalcMass>
<CalcCG>208.74448258434109</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>3.1415899999999994</RadialAngle>
<LocationMode>0</LocationMode>
<Len>0.0</Len>
<FinishCode>1</FinishCode>
<SerialNo>18</SerialNo>
<FinCount>1</FinCount>
<RootChord>0.0</RootChord>
<TipChord>0.0</TipChord>
<SemiSpan>0.0</SemiSpan>
<SweepDistance>0.0</SweepDistance>
<Thickness>4.78</Thickness>
<ShapeCode>2</ShapeCode>
<TipShapeCode>1</TipShapeCode>
<TabLength>317.5</TabLength>
<TabDepth>23.37</TabDepth>
<TabOffset>0.0</TabOffset>
<SweepMode>1</SweepMode>
<CantAngle>0.0</CantAngle>
<PointList>406.0,0.0|406.0,2.0|398.0,11.3|395.0,13.0|382.0,58.0|354.0,67.0|320.0,22.0|282.0,25.0|258.0,119.0|228.4,128.0|117.158,25.3139|13.6306,15.2533|0.0,0.0|</PointList>
</CustomFinSet>
<CustomFinSet>
<KnownMass>20.58888761237905</KnownMass>
<Density>680.785</Density>
<Material>Birch</Material>
<Name>Contre fins 3a</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>134.9</Xb>
<CalcMass>20.58888761237905</CalcMass>
<CalcCG>198.83005192727484</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>3.07195</RadialAngle>
<LocationMode>0</LocationMode>
<Len>0.0</Len>
<FinishCode>1</FinishCode>
<SerialNo>19</SerialNo>
<FinCount>1</FinCount>
<RootChord>0.0</RootChord>
<TipChord>0.0</TipChord>
<SemiSpan>0.0</SemiSpan>
<SweepDistance>0.0</SweepDistance>
<Thickness>4.78</Thickness>
<ShapeCode>2</ShapeCode>
<TipShapeCode>1</TipShapeCode>
<TabLength>50.0</TabLength>
<TabDepth>0.0</TabDepth>
<TabOffset>0.0</TabOffset>
<SweepMode>1</SweepMode>
<CantAngle>0.0</CantAngle>
<PointList>392.101,0.0|391.0,4.0|387.269,9.0|381.787,10.0|272.906,20.0|114.0,20.0|3.8,7.0|0.0,0.0|</PointList>
</CustomFinSet>
<CustomFinSet>
<KnownMass>20.58888761237905</KnownMass>
<Density>680.785</Density>
<Material>Birch</Material>
<Name>Contre fins 3b</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>134.9</Xb>
<CalcMass>20.58888761237905</CalcMass>
<CalcCG>198.83005192727484</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>-3.09342</RadialAngle>
<LocationMode>0</LocationMode>
<Len>0.0</Len>
<FinishCode>1</FinishCode>
<SerialNo>20</SerialNo>
<FinCount>1</FinCount>
<RootChord>0.0</RootChord>
<TipChord>0.0</TipChord>
<SemiSpan>0.0</SemiSpan>
<SweepDistance>0.0</SweepDistance>
<Thickness>4.78</Thickness>
<ShapeCode>2</ShapeCode>
<TipShapeCode>1</TipShapeCode>
<TabLength>50.0</TabLength>
<TabDepth>0.0</TabDepth>
<TabOffset>0.0</TabOffset>
<SweepMode>1</SweepMode>
<CantAngle>0.0</CantAngle>
<PointList>392.101,0.0|391.0,4.0|387.269,9.0|381.787,10.0|272.906,20.0|114.0,20.0|3.8,7.0|0.0,0.0|</PointList>
</CustomFinSet>
<CustomFinSet>
<KnownMass>90.9849300733435</KnownMass>
<Density>680.785</Density>
<Material>Birch</Material>
<Name>Custom Fin-4</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>127.0</Xb>
<CalcMass>90.9849300733435</CalcMass>
<CalcCG>208.74448258434109</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>-1.5707999999999998</RadialAngle>
<LocationMode>0</LocationMode>
<Len>0.0</Len>
<FinishCode>1</FinishCode>
<SerialNo>21</SerialNo>
<FinCount>1</FinCount>
<RootChord>0.0</RootChord>
<TipChord>0.0</TipChord>
<SemiSpan>0.0</SemiSpan>
<SweepDistance>0.0</SweepDistance>
<Thickness>4.78</Thickness>
<ShapeCode>2</ShapeCode>
<TipShapeCode>1</TipShapeCode>
<TabLength>317.5</TabLength>
<TabDepth>23.37</TabDepth>
<TabOffset>0.0</TabOffset>
<SweepMode>1</SweepMode>
<CantAngle>0.0</CantAngle>
<PointList>406.0,0.0|406.0,2.0|398.0,11.3|395.0,13.0|382.0,58.0|354.0,67.0|320.0,22.0|282.0,25.0|258.0,119.0|228.4,128.0|117.158,25.3139|13.6306,15.2533|0.0,0.0|</PointList>
</CustomFinSet>
<CustomFinSet>
<KnownMass>20.58888761237905</KnownMass>
<Density>680.785</Density>
<Material>Birch</Material>
<Name>Contre fins 4a</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>134.9</Xb>
<CalcMass>20.58888761237905</CalcMass>
<CalcCG>198.83005192727484</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>-1.50954</RadialAngle>
<LocationMode>0</LocationMode>
<Len>0.0</Len>
<FinishCode>1</FinishCode>
<SerialNo>22</SerialNo>
<FinCount>1</FinCount>
<RootChord>0.0</RootChord>
<TipChord>0.0</TipChord>
<SemiSpan>0.0</SemiSpan>
<SweepDistance>0.0</SweepDistance>
<Thickness>4.78</Thickness>
<ShapeCode>2</ShapeCode>
<TipShapeCode>1</TipShapeCode>
<TabLength>50.0</TabLength>
<TabDepth>0.0</TabDepth>
<TabOffset>0.0</TabOffset>
<SweepMode>1</SweepMode>
<CantAngle>0.0</CantAngle>
<PointList>392.101,0.0|391.0,4.0|387.269,9.0|381.787,10.0|272.906,20.0|114.0,20.0|3.8,7.0|0.0,0.0|</PointList>
</CustomFinSet>
<CustomFinSet>
<KnownMass>20.58888761237905</KnownMass>
<Density>680.785</Density>
<Material>Birch</Material>
<Name>Contre fins 4b</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>134.9</Xb>
<CalcMass>20.58888761237905</CalcMass>
<CalcCG>198.83005192727484</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>-1.64916</RadialAngle>
<LocationMode>0</LocationMode>
<Len>0.0</Len>
<FinishCode>1</FinishCode>
<SerialNo>23</SerialNo>
<FinCount>1</FinCount>
<RootChord>0.0</RootChord>
<TipChord>0.0</TipChord>
<SemiSpan>0.0</SemiSpan>
<SweepDistance>0.0</SweepDistance>
<Thickness>4.78</Thickness>
<ShapeCode>2</ShapeCode>
<TipShapeCode>1</TipShapeCode>
<TabLength>50.0</TabLength>
<TabDepth>0.0</TabDepth>
<TabOffset>0.0</TabOffset>
<SweepMode>1</SweepMode>
<CantAngle>0.0</CantAngle>
<PointList>392.101,0.0|391.0,4.0|387.269,9.0|381.787,10.0|272.906,20.0|114.0,20.0|3.8,7.0|0.0,0.0|</PointList>
</CustomFinSet>
<Ring>
<KnownMass>11.961913235279138</KnownMass>
<Density>724.996</Density>
<Material>Aircraft plywood (Birch)</Material>
<Name>Ring</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>107.9</Xb>
<CalcMass>11.961913235279138</CalcMass>
<CalcCG>1.59</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>0.0</RadialAngle>
<LocationMode>0</LocationMode>
<Len>3.18</Len>
<FinishCode>0</FinishCode>
<SerialNo>24</SerialNo>
<OD>98.06</OD>
<ID>54.86</ID>
<UsageCode>0</UsageCode>
<AutoSize>0</AutoSize>
</Ring>
<Ring>
<KnownMass>11.961913235279138</KnownMass>
<Density>724.996</Density>
<Material>Aircraft plywood (Birch)</Material>
<Name>Ring</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>559.6</Xb>
<CalcMass>11.961913235279138</CalcMass>
<CalcCG>1.59</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>0.0</RadialAngle>
<LocationMode>0</LocationMode>
<Len>3.18</Len>
<FinishCode>0</FinishCode>
<SerialNo>25</SerialNo>
<OD>98.06</OD>
<ID>54.86</ID>
<UsageCode>0</UsageCode>
<AutoSize>0</AutoSize>
</Ring>
<Ring>
<KnownMass>15.681351031672762</KnownMass>
<Density>680.785</Density>
<Material>Birch</Material>
<Name>Bulkhead</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>0.0</Xb>
<CalcMass>15.681351031672762</CalcMass>
<CalcCG>1.525</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>0.0</RadialAngle>
<LocationMode>0</LocationMode>
<Len>3.05</Len>
<FinishCode>0</FinishCode>
<SerialNo>26</SerialNo>
<OD>98.06</OD>
<ID>0.0</ID>
<UsageCode>1</UsageCode>
<AutoSize>0</AutoSize>
</Ring>
<LaunchLug>
<KnownMass>0.4685140502167485</KnownMass>
<Density>1199.78</Density>
<Material>Polycarbonate</Material>
<Name>Launch lug</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>540.0</Xb>
<CalcMass>0.4685140502167485</CalcMass>
<CalcCG>5.0</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>-2.35619</RadialAngle>
<LocationMode>0</LocationMode>
<Len>10.0</Len>
<FinishCode>1</FinishCode>
<SerialNo>27</SerialNo>
<OD>13.43</OD>
<ID>11.43</ID>
</LaunchLug>
<LaunchLug>
<KnownMass>0.4685140502167485</KnownMass>
<Density>1199.78</Density>
<Material>Polycarbonate</Material>
<Name>Launch lug</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>12.5</Xb>
<CalcMass>0.4685140502167485</CalcMass>
<CalcCG>5.0</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>-2.35619</RadialAngle>
<LocationMode>0</LocationMode>
<Len>10.0</Len>
<FinishCode>1</FinishCode>
<SerialNo>28</SerialNo>
<OD>13.43</OD>
<ID>11.43</ID>
</LaunchLug>
</AttachedParts>
</BodyTube>
<Transition>
<KnownMass>61.64272321712273</KnownMass>
<Density>847.056</Density>
<Material>Urethane</Material>
<Name>Transition</Name>
<KnownCG>0.0</KnownCG>
<UseKnownCG>0</UseKnownCG>
<Xb>0.0</Xb>
<CalcMass>61.64272321712273</CalcMass>
<CalcCG>18.041444744426794</CalcCG>
<DensityType>0</DensityType>
<RadialLoc>0.0</RadialLoc>
<RadialAngle>0.0</RadialAngle>
<LocationMode>0</LocationMode>
<Len>44.45</Len>
<FinishCode>0</FinishCode>
<SerialNo>29</SerialNo>
<ShapeCode>0</ShapeCode>
<ConstructionType>1</ConstructionType>
<WallThickness>5.21</WallThickness>
<ShapeParameter>0.0</ShapeParameter>
<AttachedParts/>
<FrontShoulderLen>6.35</FrontShoulderLen>
<RearShoulderLen>0.0</RearShoulderLen>
<FrontShoulderDia>99.06</FrontShoulderDia>
<RearShoulderDia>0.0</RearShoulderDia>
<FrontDia>100.0</FrontDia>
<RearDia>79.5</RearDia>
</Transition>
</Stage3Parts>
<Stage2Parts/>
<Stage1Parts/>
</RocketDesign>
</DesignInformation>
</RockSimDocument>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,31 @@
package net.sf.openrocket.file;
import java.text.MessageFormat;
import org.junit.Test;
import static org.junit.Assert.*;
public class GeneralRocketSaverTest {
@Test
public void testBuildFilenameTemplate() {
assertEquals("abc ({0}).jpg", GeneralRocketSaver.buildFilenameTemplate("abc.jpg"));
assertEquals("a ({0}).jpg", GeneralRocketSaver.buildFilenameTemplate("a.jpg"));
assertEquals("abc ({0})", GeneralRocketSaver.buildFilenameTemplate("abc"));
assertEquals("abc ({0}).", GeneralRocketSaver.buildFilenameTemplate("abc."));
assertEquals(".abc ({0})", GeneralRocketSaver.buildFilenameTemplate(".abc"));
// This one is hideous, but hey so was the original name.
// If anybody wants to change the algorithm when there are multiple leading dots
// go ahead and change these test cases too.
assertEquals(". ({0}).abc", GeneralRocketSaver.buildFilenameTemplate("..abc"));
assertEquals( "abc (15).jpg", MessageFormat.format(GeneralRocketSaver.buildFilenameTemplate("abc.jpg"), 15));
}
}