[WIP] Implement RASAero exporting

This commit is contained in:
SiboVG 2023-03-26 21:33:26 +02:00
parent 05b6611730
commit 41a045038e
41 changed files with 1777 additions and 91 deletions

View File

@ -289,6 +289,7 @@ pref.dlg.tab.Design = Design
pref.dlg.tab.Simulation = Simulation
pref.dlg.tab.Launch = Launch
pref.dlg.tab.Miscellaneousoptions = Miscellaneous options
pref.dlg.lbl.RASAeroWarning = Show warning when saving in RASAero format
pref.dlg.lbl.RockSimWarning = Show warning when saving in RockSim format
pref.dlg.but.clearCachedPreferences = Reset all preferences
pref.dlg.but.clearCachedPreferences.ttip = Reset all the preferences, including cached preferences (UI settings, recent files, etc.)
@ -1340,7 +1341,11 @@ TransitionCfg.tab.Generalproperties = General properties
TransitionCfg.tab.Shoulder = Shoulder
TransitionCfg.tab.Shoulderproperties = Shoulder properties
! Save RKT Warning Dialog
! Save RASAero Warning Dialog
SaveRASAeroWarningDialog.txt1 = Exporting to RASAero file format does not support all features of OpenRocket.
SaveRASAeroWarningDialog.donotshow = Do not show this dialog again
! Save RockSim Warning Dialog
SaveRktWarningDialog.txt1=Exporting to RockSim file format does not support all features of OpenRocket.
SaveRktWarningDialog.donotshow=Do not show this dialog again

View File

@ -276,6 +276,7 @@ pref.dlg.tab.Design = Ontwerp
pref.dlg.tab.Simulation = Simulatie
pref.dlg.tab.Launch = Lanceer
pref.dlg.tab.Miscellaneousoptions = Diverse opties
pref.dlg.lbl.RASAeroWarning = Toon waarschuwingen bij opslaan in RASAero-formaat
pref.dlg.lbl.RockSimWarning = Toon waarschuwingen bij opslaan in RockSim-formaat
pref.dlg.but.clearCachedPreferences = Alle voorkeuren opnieuw instellen
pref.dlg.but.clearCachedPreferences.ttip = Alle voorkeuren opnieuw instellen, inclusief voorkeuren in de cache (UI-instellingen, recente bestanden, enz.)
@ -1219,6 +1220,10 @@ FinsetConfig.ttip.Finfillets1 = <HTML>Voegt de voorspelde massa van de vin fille
FinsetConfig.ttip.Finfillets2 = Veronderstelt dat de fillet concaaf is en raakt aan de buis en de vin.<br>
FinsetConfig.ttip.Finfillets3 = Nul radius geeft geen fillet.
! Save RASAero Warning Dialog
SaveRASAeroWarningDialog.txt1 = Exporteren naar RASAero bestandsformaat ondersteunt niet alle functies van OpenRocket.
SaveRASAeroWarningDialog.donotshow = Laat dit dialoogvenster niet meer zien
! Save RKT Warning Dialog
SaveRktWarningDialog.txt1 = Exporteren naar RockSim bestandsformaat ondersteunt niet alle functies van OpenRocket.
SaveRktWarningDialog.donotshow = Laat dit dialoogvenster niet meer zien

View File

@ -276,6 +276,7 @@ pref.dlg.tab.Design = \u0414\u0438\u0437\u0430\u0439\u043D
pref.dlg.tab.Simulation = \u0420\u0430\u0441\u0447\u0435\u0442
pref.dlg.tab.Launch = \u0417\u0430\u043F\u0443\u0441\u043A
pref.dlg.tab.Miscellaneousoptions = \u041F\u0440\u043E\u0447\u0438\u0435 \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438
pref.dlg.lbl.RASAeroWarning = \u041F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u043F\u0440\u0435\u0434\u0443\u043F\u0440\u0435\u0436\u0434\u0435\u043D\u0438\u0435 \u043F\u0440\u0438 \u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0438\u0438 \u0432 \u0444\u043E\u0440\u043C\u0430\u0442\u0435 RASAero
pref.dlg.lbl.RockSimWarning = \u041F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u043F\u0440\u0435\u0434\u0443\u043F\u0440\u0435\u0436\u0434\u0435\u043D\u0438\u0435 \u043F\u0440\u0438 \u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0438\u0438 \u0432 \u0444\u043E\u0440\u043C\u0430\u0442\u0435 RockSim
pref.dlg.tab.Graphics = \u0413\u0440\u0430\u0444\u0438\u043A\u0430
@ -1267,6 +1268,10 @@ FinsetConfig.ttip.Finfillets1 = <HTML>\u0414\u043E\u0431\u0430\u0432\u043B\u044F
FinsetConfig.ttip.Finfillets2 = \u041F\u0440\u0435\u0434\u043F\u043E\u043B\u0430\u0433\u0430\u0435\u0442\u0441\u044F, \u0447\u0442\u043E \u0433\u0430\u043B\u0442\u0435\u043B\u044C \u043A\u0430\u0441\u0430\u0435\u0442\u0441\u044F \u0442\u0440\u0443\u0431\u044B \u043A\u043E\u0440\u043F\u0443\u0441\u0430 \u0438 \u0440\u0435\u0431\u0440\u0430.<br>
FinsetConfig.ttip.Finfillets3 = \u041D\u0443\u043B\u0435\u0432\u043E\u0439 \u0440\u0430\u0434\u0438\u0443\u0441 \u043E\u0437\u043D\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043E \u0433\u0430\u043B\u0442\u0435\u043B\u0435\u0439 \u043D\u0435\u0442.
! Save RASAero Warning Dialog
SaveRASAeroWarningDialog.txt1 = \u042D\u043A\u0441\u043F\u043E\u0440\u0442 \u0432 \u0444\u043E\u0440\u043C\u0430\u0442 \u0444\u0430\u0439\u043B\u0430 RASAero \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0432\u0441\u0435 \u0444\u0443\u043D\u043A\u0446\u0438\u0438 OpenRocket.
SaveRASAeroWarningDialog.donotshow = \u0411\u043E\u043B\u044C\u0448\u0435 \u043D\u0435 \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u044D\u0442\u043E\u0442 \u0434\u0438\u0430\u043B\u043E\u0433
! Save RKT Warning Dialog
SaveRktWarningDialog.txt1 = \u042D\u043A\u0441\u043F\u043E\u0440\u0442 \u0432 \u0444\u043E\u0440\u043C\u0430\u0442 \u0444\u0430\u0439\u043B\u0430 RockSim \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0432\u0441\u0435 \u0444\u0443\u043D\u043A\u0446\u0438\u0438 OpenRocket.
SaveRktWarningDialog.donotshow = \u0411\u043E\u043B\u044C\u0448\u0435 \u043D\u0435 \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u044D\u0442\u043E\u0442 \u0434\u0438\u0430\u043B\u043E\u0433

View File

@ -19,6 +19,7 @@ import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.StorageOptions;
import net.sf.openrocket.document.StorageOptions.FileType;
import net.sf.openrocket.file.openrocket.OpenRocketSaver;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver;
import net.sf.openrocket.file.rocksim.export.RockSimSaver;
import net.sf.openrocket.rocketcomponent.InsideColorComponent;
import net.sf.openrocket.rocketcomponent.RocketComponent;
@ -142,8 +143,10 @@ public class GeneralRocketSaver {
* @return the estimated number of bytes the storage would take.
*/
public long estimateFileSize(OpenRocketDocument doc, StorageOptions options) {
if (options.getFileType() == StorageOptions.FileType.ROCKSIM) {
if (options.getFileType() == FileType.ROCKSIM) {
return new RockSimSaver().estimateFileSize(doc, options);
} else if (options.getFileType() == FileType.RASAERO) {
return new RASAeroSaver().estimateFileSize(doc, options);
} else {
return new OpenRocketSaver().estimateFileSize(doc, options);
}
@ -151,10 +154,10 @@ public class GeneralRocketSaver {
private void save(String fileName, OutputStream output, OpenRocketDocument document, StorageOptions options) throws IOException, DecalNotFoundException {
// For now, we don't save decal information in ROCKSIM files, so don't do anything
// For now, we don't save decal information in ROCKSIM/RASAero files, so don't do anything
// which follows.
// TODO - add support for decals in ROCKSIM files?
if (options.getFileType() == FileType.ROCKSIM) {
if (options.getFileType() == FileType.ROCKSIM || options.getFileType() == FileType.RASAERO) {
saveInternal(output, document, options);
output.close();
return;
@ -232,8 +235,10 @@ public class GeneralRocketSaver {
private void saveInternal(OutputStream output, OpenRocketDocument document, StorageOptions options)
throws IOException {
if (options.getFileType() == StorageOptions.FileType.ROCKSIM) {
if (options.getFileType() == FileType.ROCKSIM) {
new RockSimSaver().save(output, document, options);
} else if (options.getFileType() == FileType.RASAERO) {
new RASAeroSaver().save(output, document, options);
} else {
new OpenRocketSaver().save(output, document, options);
}

View File

@ -3,11 +3,13 @@ package net.sf.openrocket.file;
import java.io.IOException;
import java.io.OutputStream;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.StorageOptions;
public abstract class RocketSaver {
protected final WarningSet warnings = new WarningSet();
/**
* Save the document to the specified output stream using the default storage options.

View File

@ -0,0 +1,19 @@
package net.sf.openrocket.file.rasaero;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class CustomBooleanAdapter extends XmlAdapter<String, Boolean> {
@Override
public Boolean unmarshal(String s) throws Exception {
return "true".equalsIgnoreCase(s);
}
@Override
public String marshal(Boolean b) throws Exception {
if (b) {
return "True";
}
return "False";
}
}

View File

@ -0,0 +1,22 @@
package net.sf.openrocket.file.rasaero;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
public class CustomDoubleAdapter extends XmlAdapter<String, Double> {
@Override
public Double unmarshal(String s) throws Exception {
return Double.parseDouble(s);
}
@Override
public String marshal(Double aDouble) throws Exception {
if (aDouble == null) {
return null;
}
DecimalFormat df = new DecimalFormat("#.####", new DecimalFormatSymbols(Locale.US)); // RASAero has 4 decimal precision
return df.format(aDouble);
}
}

View File

@ -1,25 +1,36 @@
package net.sf.openrocket.file.rasaero.importt;
package net.sf.openrocket.file.rasaero;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
import net.sf.openrocket.rocketcomponent.ExternalComponent;
import net.sf.openrocket.rocketcomponent.FinSet;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.util.Color;
import net.sf.openrocket.util.MathUtil;
import java.util.HashMap;
import java.util.Map;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
/**
* List of constants used in RASAero files + helper functions to read parameters from it.
*
* @author Sibo Van Gool <sibo.vangool@hotmail.com>
*/
public class RASAeroCommonConstants {
// File settings
public static final String FILE_EXTENSION = "CDX1";
// General settings
public static final String RASAERO_DOCUMENT = "RASAeroDocument";
public static final String FILE_VERSION = "FileVersion";
public static final String ROCKET_DESIGN = "RocketDesign";
// RASAeroDocument settings
public static final String MACH_ALT = "MachAlt";
// Base part settings
public static final String PART_TYPE = "PartType";
public static final String LENGTH = "Length";
public static final String DIAMETER = "Diameter";
@ -37,12 +48,24 @@ public class RASAeroCommonConstants {
public static final String FIN_CAN = "FinCan";
public static final String BOATTAIL = "BoatTail";
// Body tube settings
public static final String OVERHANG = "Overhang";
// Nose cone settings
public static final String SHAPE = "Shape";
public static final String POWER_LAW = "PowerLaw";
//public static final String BLUNT_RADIUS = "BluntRadius";
public static final String BLUNT_RADIUS = "BluntRadius";
private static final Map<String, Transition.Shape> RASAeroNoseConeShapeMap = new HashMap<>();
//// Nose cone shapes
private static final String SHAPE_CONICAL = "Conical";
private static final String SHAPE_TANGENT_OGIVE = "Tangent Ogive";
private static final String SHAPE_VON_KARMAN_OGIVE = "Von Karman Ogive";
private static final String SHAPE_POWER_LAW = "Power Law";
private static final String SHAPE_LVHAACK = "LV-Haack";
private static final String SHAPE_PARABOLIC = "Parabolic";
private static final String SHAPE_ELLIPTICAL = "Elliptical";
// Transition settings
public static final String REAR_DIAMETER = "RearDiameter";
@ -53,6 +76,10 @@ public class RASAeroCommonConstants {
public static final String FIN_SWEEP_DISTANCE = "SweepDistance";
public static final String FIN_TIP_CHORD = "TipChord";
public static final String FIN_THICKNESS = "Thickness";
public static final String FIN_LE_RADIUS = "LERadius";
public static final String FIN_AIRFOIL_SECTION = "AirfoilSection";
public static final String FIN_FX1 = "FX1";
public static final String FIN_FX3 = "FX3";
public static final String AIRFOIL_SECTION = "AirfoilSection";
//// LERadius, FX1 and FX3 not used
public static final String CROSS_SECTION_SQUARE = "Square";
@ -67,6 +94,9 @@ public class RASAeroCommonConstants {
public static final String RAIL_GUIDE_DIAMETER = "RailGuideDiameter";
public static final String RAIL_GUIDE_HEIGHT = "RailGuideHeight";
// Launch shoe settings
public static final String LAUNCH_SHOE_AREA = "LaunchShoeArea";
// Fin can settings
public static final String INSIDE_DIAMETER = "InsideDiameter";
public static final String SHOULDER_LENGTH = "ShoulderLength";
@ -82,8 +112,20 @@ public class RASAeroCommonConstants {
public static final String FINISH_CAST_IRON = "Cast Iron (Very Rough)";
// Booster settings
public static final String BOAT_TAIL_LENGTH = "BoattailLength";
public static final String BOAT_TAIL_REAR_DIAMETER = "BoattailRearDiameter";
public static final String BOATTAIL_LENGTH = "BoattailLength";
public static final String BOATTAIL_REAR_DIAMETER = "BoattailRearDiameter";
public static final String BOATTAIL_OFFSET = "BoattailOffset";
public static final String NOZZLE_EXIT_DIAMETER = "NozzleExitDiameter";
// RocketDesign settings
public static final String CD = "CD";
public static final String MODIFIED_BARROWMAN = "ModifiedBarrowman";
public static final String TURBULENCE = "Turbulence";
public static final String SUSTAINER_NOZZLE = "SustainerNozzle";
public static final String BOOSTER1_NOZZLE = "Booster1Nozzle";
public static final String BOOSTER2_NOZZLE = "Booster2Nozzle";
public static final String USE_BOOSTER1 = "UseBooster1";
public static final String USE_BOOSTER2 = "UseBooster2";
// Launch site settings
public static final String LAUNCH_SITE = "LaunchSite";
@ -126,7 +168,7 @@ public class RASAeroCommonConstants {
/**
* Length conversion from OpenRocket units to RASAero units. RASAero is in inches, OpenRocket in meters.
*/
public static final double OPENROCKET_TO_RASAERO_TO_LENGTH = 39.37;
public static final double OPENROCKET_TO_RASAERO_LENGTH = 39.37;
/**
* Altitude conversion from OpenRocket units to RASAero units. RASAero is in feet, OpenRocket in meters.
*/
@ -154,13 +196,13 @@ public class RASAeroCommonConstants {
}
static {
RASAeroNoseConeShapeMap.put("Conical", Transition.Shape.CONICAL);
RASAeroNoseConeShapeMap.put("Tangent Ogive", Transition.Shape.OGIVE); // = Ogive with shape parameter = 1
RASAeroNoseConeShapeMap.put("Von Karman Ogive", Transition.Shape.HAACK); // = Haack series with shape parameter = 0
RASAeroNoseConeShapeMap.put("Power Law", Transition.Shape.POWER);
RASAeroNoseConeShapeMap.put("LV-Haack", Transition.Shape.HAACK); // = Haack series with shape parameter = 1/3
RASAeroNoseConeShapeMap.put("Parabolic", Transition.Shape.POWER); // = Power law with shape parameter = 1/2
RASAeroNoseConeShapeMap.put("Elliptical", Transition.Shape.ELLIPSOID);
RASAeroNoseConeShapeMap.put(SHAPE_CONICAL, Transition.Shape.CONICAL);
RASAeroNoseConeShapeMap.put(SHAPE_TANGENT_OGIVE, Transition.Shape.OGIVE); // = Ogive with shape parameter = 1
RASAeroNoseConeShapeMap.put(SHAPE_VON_KARMAN_OGIVE, Transition.Shape.HAACK); // = Haack series with shape parameter = 0
RASAeroNoseConeShapeMap.put(SHAPE_POWER_LAW, Transition.Shape.POWER);
RASAeroNoseConeShapeMap.put(SHAPE_LVHAACK, Transition.Shape.HAACK); // = Haack series with shape parameter = 1/3
RASAeroNoseConeShapeMap.put(SHAPE_PARABOLIC, Transition.Shape.POWER); // = Power law with shape parameter = 1/2
RASAeroNoseConeShapeMap.put(SHAPE_ELLIPTICAL, Transition.Shape.ELLIPSOID);
}
/**
@ -168,10 +210,48 @@ public class RASAeroCommonConstants {
* @param shape The RASAero shape string.
* @return The OpenRocket nose cone shape.
*/
public static Transition.Shape getNoseConeShapeFromRASAero(String shape) {
public static Transition.Shape RASAERO_TO_OPENROCKET_SHAPE(String shape) {
return RASAeroNoseConeShapeMap.get(shape);
}
/**
* Returns the OpenRocket nose cone shape from the RASAero shape string.
* @param shape The RASAero shape string.
* @return The OpenRocket nose cone shape object.
*/
public static NoseConeShapeSettings OPENROCKET_TO_RASAERO_SHAPE(Transition.Shape shape, double shapeParameter)
throws RASAeroExportException {
if (shape.equals(Transition.Shape.CONICAL)) {
return new NoseConeShapeSettings(SHAPE_CONICAL);
} else if (shape.equals(Transition.Shape.OGIVE) && MathUtil.equals(shapeParameter, 1)) {
return new NoseConeShapeSettings(SHAPE_TANGENT_OGIVE);
} else if (shape.equals(Transition.Shape.HAACK) && MathUtil.equals(shapeParameter, 0)) {
return new NoseConeShapeSettings(SHAPE_VON_KARMAN_OGIVE);
} else if (shape.equals(Transition.Shape.POWER) && MathUtil.equals(shapeParameter, 0.5, 0.01)) {
return new NoseConeShapeSettings(SHAPE_PARABOLIC);
} else if (shape.equals(Transition.Shape.POWER)) {
return new NoseConeShapeSettings(SHAPE_POWER_LAW, shapeParameter);
} else if (shape.equals(Transition.Shape.HAACK) && MathUtil.equals(shapeParameter, 0.33, 0.01)) {
return new NoseConeShapeSettings(SHAPE_LVHAACK);
} else if (shape.equals(Transition.Shape.ELLIPSOID)) {
return new NoseConeShapeSettings(SHAPE_ELLIPTICAL);
}
// Special cases
else if (shape.equals(Transition.Shape.OGIVE)) {
throw new RASAeroExportException(
String.format("RASAero only supports Ogive nose cones with shape parameter 1, not %.2f", shapeParameter));
} else if (shape.equals(Transition.Shape.HAACK)) {
throw new RASAeroExportException(
String.format("RASAero only supports Haack nose cones with shape parameter 0 or 0.33, not %.2f", shapeParameter));
} else if (shape.equals(Transition.Shape.PARABOLIC)) {
throw new RASAeroExportException("RASAero does not support Parabolic nose cones");
}
throw new RASAeroExportException(
String.format("Invalid shape and shape parameter combination: %s, %.2f", shape.getName(), shapeParameter));
}
/**
* RASAero has a slightly different way of specifying shapes compared to OpenRocket. For instance
* RASAero has an "LV-Haack" shape, which is the same as the OpenRocket "Haack" shape with a shape
@ -180,27 +260,27 @@ public class RASAeroCommonConstants {
* @param shape The RASAero shape string.
* @return The shape parameter for the OpenRocket nose cone.
*/
public static double getNoseConeShapeParameterFromRASAeroShape(String shape) {
if ("Conical".equals(shape)) {
public static double RASAERO_TO_OPENROCKET_SHAPE_PARAMETER(String shape) {
if (SHAPE_CONICAL.equals(shape)) {
return 0.0; // Not really needed, but just to be explicit
} else if ("Tangent Ogive".equals(shape)) {
} else if (SHAPE_TANGENT_OGIVE.equals(shape)) {
return 1.0;
} else if ("Von Karman Ogive".equals(shape)) {
} else if (SHAPE_VON_KARMAN_OGIVE.equals(shape)) {
return 0.0;
} else if ("Power Law".equals(shape)) {
} else if (SHAPE_POWER_LAW.equals(shape)) {
return 0.0; // Not really needed, but just to be explicit (will be overwritten later)
} else if ("LV-Haack".equals(shape)) {
} else if (SHAPE_LVHAACK.equals(shape)) {
return 0.33;
} else if ("Parabolic".equals(shape)) {
} else if (SHAPE_PARABOLIC.equals(shape)) {
return 0.5;
} else if ("Elliptical".equals(shape)) {
} else if (SHAPE_ELLIPTICAL.equals(shape)) {
return 0.0; // Not really needed, but just to be explicit
} else {
return 0.0;
}
}
public static FinSet.CrossSection getFinCrossSectionFromRASAero(String crossSection, WarningSet warnings) {
public static FinSet.CrossSection RASAERO_TO_OPENROCKET_FIN_CROSSSECTION(String crossSection, WarningSet warnings) {
if (CROSS_SECTION_SQUARE.equals(crossSection)) {
return FinSet.CrossSection.SQUARE;
} else if (CROSS_SECTION_ROUNDED.equals(crossSection)) {
@ -213,7 +293,20 @@ public class RASAeroCommonConstants {
}
}
public static ExternalComponent.Finish getSurfaceFinishFromRASAero(String surfaceFinish, WarningSet warnings) {
public static String OPENROCKET_TO_RASAERO_FIN_CROSSSECTION(FinSet.CrossSection crossSection) {
if (FinSet.CrossSection.SQUARE.equals(crossSection)) {
return CROSS_SECTION_SQUARE;
} else if (FinSet.CrossSection.ROUNDED.equals(crossSection)) {
return CROSS_SECTION_ROUNDED;
} else if (FinSet.CrossSection.AIRFOIL.equals(crossSection)) {
return CROSS_SECTION_SUBSONIC_NACA;
} else {
//TODO: warnings.add("Unknown fin cross section: " + crossSection + ".");
return null;
}
}
public static ExternalComponent.Finish RASAERO_TO_OPENROCKET_SURFACE(String surfaceFinish, WarningSet warnings) {
// NOTE: the RASAero surface finishes are not really the same as the OpenRocket surface finishes. There are some
// approximations here.
if (FINISH_SMOOTH.equals(surfaceFinish)) {
@ -238,7 +331,29 @@ public class RASAeroCommonConstants {
}
}
public static DeploymentConfiguration.DeployEvent getDeployEventFromRASAero(String deployEvent, WarningSet warnings) {
public static String OPENROCKET_TO_RASAERO_SURFACE(ExternalComponent.Finish finish) {
if (finish.equals(ExternalComponent.Finish.MIRROR)) {
return FINISH_SMOOTH;
} else if (finish.equals(ExternalComponent.Finish.FINISHPOLISHED)) {
return FINISH_POLISHED;
} else if (finish.equals(ExternalComponent.Finish.OPTIMUM)) {
return FINISH_SHEET_METAL;
} else if (finish.equals(ExternalComponent.Finish.SMOOTH)) {
return FINISH_CAMOUFLAGE;
} else if (finish.equals(ExternalComponent.Finish.NORMAL)) {
return FINISH_ROUGH_CAMOUFLAGE;
} else if (finish.equals(ExternalComponent.Finish.UNFINISHED)) {
return FINISH_GALVANIZED;
} else if (finish.equals(ExternalComponent.Finish.ROUGHUNFINISHED)) {
return FINISH_CAST_IRON;
} else {
// TODO
//warnings.add("Unknown surface finish: " + finish + ", defaulting to Smooth.");
return FINISH_SMOOTH;
}
}
public static DeploymentConfiguration.DeployEvent RASAERO_TO_OPENROCKET_DEPLOY_EVENT(String deployEvent, WarningSet warnings) {
if (DEPLOYMENT_NONE.equals(deployEvent)) {
return DeploymentConfiguration.DeployEvent.NEVER;
} else if (DEPLOYMENT_APOGEE.equals(deployEvent)) {
@ -249,4 +364,39 @@ public class RASAeroCommonConstants {
warnings.add("Unknown deployment event: " + deployEvent + ", defaulting to apogee.");
return DeploymentConfiguration.DeployEvent.APOGEE;
}
public static String OPENROCKET_TO_RASAERO_COLOR(Color color) {
if (color != null) {
if (color.equals(Color.BLACK)) {
return "Black"; // Currently the only officially supported color by RASAero
}
}
return "Blue"; // But we can also apply our own color hehe
}
/**
* Class containing the RASAero nose cone shape and shape parameter settings
*/
public static class NoseConeShapeSettings {
private final String shape;
private final Double shapeParameter;
public NoseConeShapeSettings(String shape, double shapeParameter) {
this.shape = shape;
this.shapeParameter = shapeParameter;
}
public NoseConeShapeSettings(String shape) {
this.shape = shape;
this.shapeParameter = null;
}
public String getShape() {
return shape;
}
public Double getShapeParameter() {
return shapeParameter;
}
}
}

View File

@ -0,0 +1,133 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.NoseCone;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
import net.sf.openrocket.util.MathUtil;
/**
* The base class for most RASAero components.
*/
@XmlRootElement
@XmlType(name="RASAeroBasePartDTO")
@XmlAccessorType(XmlAccessType.FIELD)
public class BasePartDTO {
@XmlElement(name = RASAeroCommonConstants.PART_TYPE)
private String partType;
@XmlElement(name = RASAeroCommonConstants.LENGTH)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double length;
@XmlElement(name = RASAeroCommonConstants.DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double diameter;
@XmlElement(name = RASAeroCommonConstants.LOCATION)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double location;
@XmlElement(name = RASAeroCommonConstants.COLOR)
private String color;
@XmlTransient
private final RocketComponent component;
/**
* We need a default no-args constructor.
*/
public BasePartDTO() {
this.component = null;
}
protected BasePartDTO(RocketComponent component) throws RASAeroExportException {
this.component = component;
if (component instanceof BodyTube) {
setPartType(RASAeroCommonConstants.BODY_TUBE);
setDiameter(((BodyTube) component).getOuterRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
} else if (component instanceof NoseCone) {
setPartType(RASAeroCommonConstants.NOSE_CONE);
NoseCone noseCone = (NoseCone) component;
if (noseCone.isFlipped()) {
throw new RASAeroExportException("Nose cone may not be flipped");
}
setDiameter(((NoseCone) component).getAftRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
} else if (component instanceof Transition) {
setPartType(RASAeroCommonConstants.TRANSITION);
// This is a bit strange: I would expect diameter to be the fore radius, since you also have a rearDiamter
// field for transitions, but okay
setDiameter(((Transition) component).getAftRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
} else if (component instanceof AxialStage) {
setPartType(RASAeroCommonConstants.BOOSTER);
AxialStage stage = (AxialStage) component;
if (stage.getChildCount() == 0 || !(stage.getChild(0) instanceof BodyTube)) {
throw new RASAeroExportException("First component of booster must be body tube");
}
setDiameter(stage.getBoundingRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
} else {
throw new RASAeroExportException("Unsupported component: " + component.getComponentName());
}
setLength(component.getLength() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setLocation(component.getAxialOffset(AxialMethod.ABSOLUTE) * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setColor(RASAeroCommonConstants.OPENROCKET_TO_RASAERO_COLOR(component.getColor()));
}
public String getPartType() {
return partType;
}
public void setPartType(String partType) {
this.partType = partType;
}
public Double getLength() {
return length;
}
public void setLength(Double length) throws RASAeroExportException {
if (MathUtil.equals(length, 0)) {
throw new RASAeroExportException(String.format("Length of '%s' must be greater than 0", component.getName()));
}
this.length = length;
}
public Double getDiameter() {
return diameter;
}
public void setDiameter(Double diameter) throws RASAeroExportException {
if (MathUtil.equals(diameter, 0)) {
throw new RASAeroExportException(String.format("Diameter of '%s' must be greater than 0", component.getName()));
}
this.diameter = diameter;
}
public Double getLocation() {
return location;
}
public void setLocation(Double location) {
this.location = location;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}

View File

@ -0,0 +1,156 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.rocketcomponent.BodyTube;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
import net.sf.openrocket.util.MathUtil;
@XmlRootElement(name = RASAeroCommonConstants.BODY_TUBE)
@XmlAccessorType(XmlAccessType.FIELD)
public class BodyTubeDTO extends BasePartDTO implements BodyTubeDTOAdapter {
@XmlElement(name = RASAeroCommonConstants.LAUNCH_LUG_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double launchLugDiameter = 0d;
@XmlElement(name = RASAeroCommonConstants.LAUNCH_LUG_LENGTH)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double launchLugLength = 0d;
@XmlElement(name = RASAeroCommonConstants.RAIL_GUIDE_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double railGuideDiameter = 0d;
@XmlElement(name = RASAeroCommonConstants.RAIL_GUIDE_HEIGHT)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double railGuideHeight = 0d;
@XmlElement(name = RASAeroCommonConstants.LAUNCH_SHOE_AREA)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double launchShoeArea = 0d; // Currently not available in OR
@XmlElement(name = RASAeroCommonConstants.BOATTAIL_LENGTH)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double boattailLength = 0d;
@XmlElement(name = RASAeroCommonConstants.BOATTAIL_REAR_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double boattailRearDiameter = 0d;
@XmlElement(name = RASAeroCommonConstants.BOATTAIL_OFFSET)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double boattailOffset = 0d;
@XmlElement(name = RASAeroCommonConstants.OVERHANG)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double overhang = 0d;
@XmlElementRef(name = RASAeroCommonConstants.FIN, type = FinDTO.class)
private FinDTO fin;
/**
* We need a default no-args constructor.
*/
public BodyTubeDTO() { }
public BodyTubeDTO(BodyTube bodyTube) throws RASAeroExportException {
super(bodyTube);
applyBodyTubeSettings(bodyTube);
}
public Double getLaunchLugDiameter() {
return launchLugDiameter;
}
public void setLaunchLugDiameter(Double launchLugDiameter) throws RASAeroExportException {
if (MathUtil.equals(launchLugDiameter, 0)) {
throw new RASAeroExportException("Launch lug diameter can not be 0");
}
this.launchLugDiameter = launchLugDiameter;
}
public Double getLaunchLugLength() {
return launchLugLength;
}
public void setLaunchLugLength(Double launchLugLength) throws RASAeroExportException {
if (MathUtil.equals(launchLugLength, 0)) {
throw new RASAeroExportException("Launch lug length can not be 0");
}
this.launchLugLength = launchLugLength;
}
public Double getRailGuideDiameter() {
return railGuideDiameter;
}
public void setRailGuideDiameter(Double railGuideDiameter) throws RASAeroExportException {
if (MathUtil.equals(railGuideDiameter, 0)) {
throw new RASAeroExportException("Rail button diameter can not be 0");
}
this.railGuideDiameter = railGuideDiameter;
}
public Double getRailGuideHeight() {
return railGuideHeight;
}
public void setRailGuideHeight(Double railGuideHeight) throws RASAeroExportException {
if (MathUtil.equals(railGuideHeight, 0)) {
throw new RASAeroExportException("Rail button height can not be 0");
}
this.railGuideHeight = railGuideHeight;
}
public Double getLaunchShoeArea() {
return launchShoeArea;
}
public void setLaunchShoeArea(Double launchShoeArea) throws RASAeroExportException {
if (MathUtil.equals(launchShoeArea, 0)) {
throw new RASAeroExportException("Launch shoe area can not be 0");
}
this.launchShoeArea = launchShoeArea;
}
public Double getBoattailLength() {
return boattailLength;
}
public void setBoattailLength(Double boattailLength) {
this.boattailLength = boattailLength;
}
public Double getBoattailRearDiameter() {
return boattailRearDiameter;
}
public void setBoattailRearDiameter(Double boattailRearDiameter) {
this.boattailRearDiameter = boattailRearDiameter;
}
public Double getBoattailOffset() {
return boattailOffset;
}
public void setBoattailOffset(Double boattailOffset) {
this.boattailOffset = boattailOffset;
}
public Double getOverhang() {
return overhang;
}
public void setOverhang(Double overhang) {
this.overhang = overhang;
}
public FinDTO getFin() {
return fin;
}
public void setFin(FinDTO fin) {
this.fin = fin;
}
}

View File

@ -0,0 +1,90 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.LaunchLug;
import net.sf.openrocket.rocketcomponent.RailButton;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
public interface BodyTubeDTOAdapter {
default void applyBodyTubeSettings(BodyTube bodyTube) throws RASAeroExportException {
for (RocketComponent child : bodyTube.getChildren()) {
if (child instanceof TrapezoidFinSet) {
setFin(new FinDTO((TrapezoidFinSet) child));
} else if (child instanceof LaunchLug) {
if (!MathUtil.equals(getRailGuideDiameter(), 0) || !MathUtil.equals(getRailGuideHeight(), 0)) { // only one check on diameter or length should be sufficient, but just to be safe
//TODO: warning.add(String.format("Already added a rail button, ignoring launch lug '%s'", child.getName());
continue;
}
if (!MathUtil.equals(getLaunchShoeArea(), 0)) {
//TODO: warning.add(String.format("Already added a launch shoe, ignoring launch lug '%s'", child.getName());
continue;
}
LaunchLug lug = (LaunchLug) child;
setLaunchLugDiameter(lug.getOuterRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
if (lug.getInstanceCount() == 2) {
setLaunchLugLength(lug.getLength() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
} else {
//TODO:warnings.add(String.format("Instance count of '%s' not set to 2, defaulting to 2 and adjusting
// launch lug length accordingly.", lug.getName()")
setLaunchLugLength(lug.getLength() * lug.getInstanceCount() / 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
}
} else if (child instanceof RailButton) {
if (!MathUtil.equals(getLaunchLugDiameter(), 0) || !MathUtil.equals(getLaunchLugLength(), 0)) { // only one check on diameter or length should be sufficient, but just to be safe
// TODO: warning.add(String.format("Already added a launch lug, ignoring rail button '%s'", child.getName()));
continue;
}
if (!MathUtil.equals(getLaunchShoeArea(), 0)) {
// TODO: warning.add(String.format("Already added a launch shoe, ignoring rail button '%s'", child.getName()));
continue;
}
RailButton button = (RailButton) child;
setRailGuideDiameter(button.getOuterDiameter() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setRailGuideHeight(button.getTotalHeight() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
if (button.getInstanceCount() != 2) {
//TODO: warnings.add(String.format("Instance count of '%s' equals %d, defaulting to 2", button.getName(), button.getInstanceCount()));
}
} else {
// TODO: warnings.add(String.format("Unsupported component '%s', ignoring.", child.getComponentName()));
}
}
}
Double getLaunchLugDiameter();
void setLaunchLugDiameter(Double launchLugDiameter) throws RASAeroExportException;
Double getLaunchLugLength();
void setLaunchLugLength(Double launchLugLength) throws RASAeroExportException;
Double getRailGuideDiameter();
void setRailGuideDiameter(Double railGuideDiameter) throws RASAeroExportException;
Double getRailGuideHeight();
void setRailGuideHeight(Double railGuideHeight) throws RASAeroExportException;
Double getLaunchShoeArea();
void setLaunchShoeArea(Double launchShoeArea) throws RASAeroExportException;
Double getBoattailLength();
void setBoattailLength(Double boattailLength);
Double getBoattailRearDiameter();
void setBoattailRearDiameter(Double boattailRearDiameter);
FinDTO getFin();
void setFin(FinDTO fin);
}

View File

@ -0,0 +1,285 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.NoseCone;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
import net.sf.openrocket.rocketcomponent.SymmetricComponent;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
import net.sf.openrocket.util.MathUtil;
@XmlRootElement(name = RASAeroCommonConstants.BOOSTER)
@XmlAccessorType(XmlAccessType.FIELD)
public class BoosterDTO implements BodyTubeDTOAdapter {
@XmlElement(name = RASAeroCommonConstants.PART_TYPE)
private String partType;
@XmlElement(name = RASAeroCommonConstants.LENGTH)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double length;
@XmlElement(name = RASAeroCommonConstants.DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double diameter;
@XmlElement(name = RASAeroCommonConstants.INSIDE_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double insideDiameter;
@XmlElement(name = RASAeroCommonConstants.LAUNCH_LUG_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double launchLugDiameter = 0d;
@XmlElement(name = RASAeroCommonConstants.LAUNCH_LUG_LENGTH)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double launchLugLength = 0d;
@XmlElement(name = RASAeroCommonConstants.RAIL_GUIDE_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double railGuideDiameter = 0d;
@XmlElement(name = RASAeroCommonConstants.RAIL_GUIDE_HEIGHT)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double railGuideHeight = 0d;
@XmlElement(name = RASAeroCommonConstants.LAUNCH_SHOE_AREA)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double launchShoeArea = 0d; // Currently not available in OR
@XmlElement(name = RASAeroCommonConstants.LOCATION)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double location;
@XmlElement(name = RASAeroCommonConstants.COLOR)
private String color;
@XmlElement(name = RASAeroCommonConstants.SHOULDER_LENGTH)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double shoulderLength;
@XmlElement(name = RASAeroCommonConstants.NOZZLE_EXIT_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double nozzleExitDiameter;
@XmlElement(name = RASAeroCommonConstants.BOATTAIL_LENGTH)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double boattailLength;
@XmlElement(name = RASAeroCommonConstants.BOATTAIL_REAR_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double boattailRearDiameter;
@XmlElementRef(name = RASAeroCommonConstants.FIN, type = FinDTO.class)
private FinDTO fin;
/**
* We need a default, no-args constructor.
*/
public BoosterDTO() { }
protected BoosterDTO(Rocket rocket, AxialStage stage) throws RASAeroExportException {
int stageNr = rocket.getChildPosition(stage); // Use this instead of stage.getStageNumber() in case there are parallel stages in the design
if (stageNr != 1 && stageNr != 2) {
throw new RASAeroExportException(String.format("Invalid stage number '%d' for booster stage '%s'", stageNr, stage.getName()));
}
if (stage.getChildCount() == 0) {
throw new RASAeroExportException(String.format("Stage '%s' can not be empty", stage.getName()));
}
RocketComponent firstChild = stage.getChild(0);
if (!(firstChild instanceof BodyTube) &&
!(firstChild instanceof Transition && !(firstChild instanceof NoseCone))) {
throw new RASAeroExportException(String.format("First component of stage '%s' must be a body tube or transition", stage.getName()));
}
final BodyTube firstTube;
if (firstChild instanceof Transition) {
if (stage.getChildCount() == 1 || !(stage.getChild(1) instanceof BodyTube)) {
throw new RASAeroExportException(
String.format("When the first component of stage '%s' is a transition, the second one must be a body tube",
stage.getName()));
}
Transition transition = (Transition) firstChild;
SymmetricComponent previousComponent = transition.getPreviousSymmetricComponent();
if (previousComponent == null) {
throw new RASAeroExportException(String.format("No previous component for '%s' in stage '%s'",
firstChild.getName(), stage.getName()));
}
if (!MathUtil.equals(transition.getForeRadius(), previousComponent.getAftRadius())) {
throw new RASAeroExportException(
String.format("Transition '%s' in stage '%s' must have the same fore radius as the aft radius of its previous component '%s'",
transition.getName(), stage.getName(), previousComponent.getName()));
}
firstTube = (BodyTube) stage.getChild(1);
if (!MathUtil.equals(firstTube.getOuterRadius(), transition.getAftRadius())) {
throw new RASAeroExportException(
String.format("Radius of '%s' in stage '%s' must be the same as the aft radius of '%s",
firstTube.getName(), stage.getName(), transition.getName()));
}
setShoulderLength(firstChild.getLength() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setDiameter(firstTube.getOuterRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setInsideDiameter(transition.getForeRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
} else {
firstTube = (BodyTube) stage.getChild(0);
}
applyBodyTubeSettings(firstTube);
TrapezoidFinSet finSet = getFinSetFromBodyTube(firstTube);
if (finSet == null) {
throw new RASAeroExportException(
String.format("Body tube '%s' in stage '%s' must have a TrapezoidFinSet",
firstTube.getName(), stage.getName()));
}
setFin(new FinDTO(finSet));
setPartType(RASAeroCommonConstants.BOOSTER);
setLength(firstTube.getLength() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setDiameter(firstTube.getOuterRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setLocation(firstChild.getAxialOffset(AxialMethod.ABSOLUTE) * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setColor(RASAeroCommonConstants.OPENROCKET_TO_RASAERO_COLOR(firstTube.getColor()));
}
private TrapezoidFinSet getFinSetFromBodyTube(BodyTube bodyTube) {
for (RocketComponent child : bodyTube.getChildren()) {
if (child instanceof TrapezoidFinSet) {
return (TrapezoidFinSet) child;
}
}
return null;
}
public String getPartType() {
return partType;
}
public void setPartType(String partType) {
this.partType = partType;
}
public Double getLength() {
return length;
}
public void setLength(Double length) {
this.length = length;
}
public Double getDiameter() {
return diameter;
}
public void setDiameter(Double diameter) {
this.diameter = diameter;
}
public Double getInsideDiameter() {
return insideDiameter;
}
public void setInsideDiameter(Double insideDiameter) {
this.insideDiameter = insideDiameter;
}
public Double getLaunchLugDiameter() {
return launchLugDiameter;
}
public void setLaunchLugDiameter(Double launchLugDiameter) {
this.launchLugDiameter = launchLugDiameter;
}
public Double getLaunchLugLength() {
return launchLugLength;
}
public void setLaunchLugLength(Double launchLugLength) {
this.launchLugLength = launchLugLength;
}
public Double getRailGuideDiameter() {
return railGuideDiameter;
}
public void setRailGuideDiameter(Double railGuideDiameter) {
this.railGuideDiameter = railGuideDiameter;
}
public Double getRailGuideHeight() {
return railGuideHeight;
}
public void setRailGuideHeight(Double railGuideHeight) {
this.railGuideHeight = railGuideHeight;
}
public Double getLaunchShoeArea() {
return launchShoeArea;
}
public void setLaunchShoeArea(Double launchShoeArea) {
this.launchShoeArea = launchShoeArea;
}
public Double getLocation() {
return location;
}
public void setLocation(Double location) {
this.location = location;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Double getShoulderLength() {
return shoulderLength;
}
public void setShoulderLength(Double shoulderLength) {
this.shoulderLength = shoulderLength;
}
public Double getNozzleExitDiameter() {
return nozzleExitDiameter;
}
public void setNozzleExitDiameter(Double nozzleExitDiameter) {
this.nozzleExitDiameter = nozzleExitDiameter;
}
public Double getBoattailLength() {
return boattailLength;
}
public void setBoattailLength(Double boattailLength) {
this.boattailLength = boattailLength;
}
public Double getBoattailRearDiameter() {
return boattailRearDiameter;
}
public void setBoattailRearDiameter(Double boattailRearDiameter) {
this.boattailRearDiameter = boattailRearDiameter;
}
public FinDTO getFin() {
return fin;
}
public void setFin(FinDTO fin) {
this.fin = fin;
}
}

View File

@ -0,0 +1,160 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement(name = RASAeroCommonConstants.FIN)
@XmlAccessorType(XmlAccessType.FIELD)
public class FinDTO {
@XmlElement(name = RASAeroCommonConstants.FIN_COUNT)
private int count;
@XmlElement(name = RASAeroCommonConstants.FIN_CHORD)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double chord;
@XmlElement(name = RASAeroCommonConstants.FIN_SPAN)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double span;
@XmlElement(name = RASAeroCommonConstants.FIN_SWEEP_DISTANCE)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double sweepDistance;
@XmlElement(name = RASAeroCommonConstants.FIN_TIP_CHORD)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double tipChord;
@XmlElement(name = RASAeroCommonConstants.FIN_THICKNESS)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double thickness;
@XmlElement(name = RASAeroCommonConstants.FIN_LE_RADIUS)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double LERadius = 0d; // Leading edge radius
@XmlElement(name = RASAeroCommonConstants.LOCATION)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double location;
@XmlElement(name = RASAeroCommonConstants.AIRFOIL_SECTION)
private String airfoilSection;
@XmlElement(name = RASAeroCommonConstants.FIN_FX1)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double FX1 = 0d;
@XmlElement(name = RASAeroCommonConstants.FIN_FX3)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double FX3 = 0d;
/**
* We need a default no-args constructor.
*/
public FinDTO() {
}
public FinDTO(TrapezoidFinSet fin) throws RASAeroExportException {
int finCount = fin.getFinCount();
if (finCount < 3 || finCount > 8) {
throw new RASAeroExportException(
String.format("Fin set '%s' must have a fin count between 3 and 8", fin.getName()));
}
setCount(fin.getFinCount());
setChord(fin.getRootChord() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setTipChord(fin.getTipChord() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setSpan(fin.getSpan() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setSweepDistance(fin.getSweep() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setThickness(fin.getThickness() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setAirfoilSection(RASAeroCommonConstants.OPENROCKET_TO_RASAERO_FIN_CROSSSECTION(fin.getCrossSection()));
setLocation((-fin.getAxialOffset(AxialMethod.BOTTOM) + fin.getLength()) * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public Double getChord() {
return chord;
}
public void setChord(Double chord) {
this.chord = chord;
}
public Double getSpan() {
return span;
}
public void setSpan(Double span) {
this.span = span;
}
public Double getSweepDistance() {
return sweepDistance;
}
public void setSweepDistance(Double sweepDistance) {
this.sweepDistance = sweepDistance;
}
public Double getTipChord() {
return tipChord;
}
public void setTipChord(Double tipChord) {
this.tipChord = tipChord;
}
public Double getThickness() {
return thickness;
}
public void setThickness(Double thickness) {
this.thickness = thickness;
}
public Double getLERadius() {
return LERadius;
}
public void setLERadius(Double LERadius) {
this.LERadius = LERadius;
}
public Double getLocation() {
return location;
}
public void setLocation(Double location) {
this.location = location;
}
public String getAirfoilSection() {
return airfoilSection;
}
public void setAirfoilSection(String airfoilSection) {
this.airfoilSection = airfoilSection;
}
public Double getFX1() {
return FX1;
}
public void setFX1(Double FX1) {
this.FX1 = FX1;
}
public Double getFX3() {
return FX3;
}
public void setFX3(Double FX3) {
this.FX3 = FX3;
}
}

View File

@ -0,0 +1,4 @@
package net.sf.openrocket.file.rasaero.export;
public class LaunchSiteDTO {
}

View File

@ -0,0 +1,70 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.rocketcomponent.NoseCone;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants.NoseConeShapeSettings;
@XmlRootElement(name = RASAeroCommonConstants.NOSE_CONE)
@XmlAccessorType(XmlAccessType.FIELD)
public class NoseConeDTO extends BasePartDTO {
@XmlElement(name = RASAeroCommonConstants.SHAPE)
private String shape;
@XmlElement(name = RASAeroCommonConstants.BLUNT_RADIUS)
private double bluntRadius = 0;
@XmlElement(name = RASAeroCommonConstants.POWER_LAW)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double powerLaw;
/**
* We need a default no-args constructor.
*/
public NoseConeDTO() {
}
public NoseConeDTO(NoseCone noseCone) throws RASAeroExportException {
super(noseCone);
NoseConeShapeSettings shapeSettings =
RASAeroCommonConstants.OPENROCKET_TO_RASAERO_SHAPE(noseCone.getShapeType(), noseCone.getShapeParameter());
setShape(shapeSettings.getShape());
Double shapeParameter = shapeSettings.getShapeParameter();
if (shapeParameter != null) {
setPowerLaw(shapeParameter);
}
}
public String getShape() {
return shape;
}
public void setShape(String shape) {
this.shape = shape;
}
public Double getPowerLaw() {
return powerLaw;
}
public void setPowerLaw(Double powerLaw) {
this.powerLaw = powerLaw;
}
public double getBluntRadius() {
return bluntRadius;
}
public void setBluntRadius(double bluntRadius) {
this.bluntRadius = bluntRadius;
}
}

View File

@ -0,0 +1,87 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* The top level RASAero document.
*/
@XmlRootElement(name = RASAeroCommonConstants.RASAERO_DOCUMENT)
@XmlAccessorType(XmlAccessType.FIELD)
public class RASAeroDocumentDTO {
@XmlElement(name = RASAeroCommonConstants.FILE_VERSION)
private final String version = "2";
@XmlElement(name = RASAeroCommonConstants.ROCKET_DESIGN)
private RocketDesignDTO design;
@XmlElement(name = RASAeroCommonConstants.LAUNCH_SITE)
private LaunchSiteDTO launchSite;
@XmlElement(name = RASAeroCommonConstants.RECOVERY)
private RecoveryDTO recovery;
@XmlElement(name = RASAeroCommonConstants.MACH_ALT)
private String machAlt = ""; // Currently not implemented
/*
@XmlElementWrapper(name=RASAeroCommonConstants.SIMULATION_LIST)
@XmlElement(name=RASAeroCommonConstants.SIMULATION)
*/
@XmlElement(name = RASAeroCommonConstants.SIMULATION_LIST)
private SimulationListDTO simulationList = null;
/**
* Get the subordinate design DTO.
*
* @return the RocketDesignDTO
*/
public RocketDesignDTO getDesign() {
return design;
}
public void setDesign(RocketDesignDTO theDesign) {
this.design = theDesign;
}
public LaunchSiteDTO getLaunchSite() {
return launchSite;
}
public void setLaunchSite(LaunchSiteDTO launchSite) {
this.launchSite = launchSite;
}
public RecoveryDTO getRecovery() {
return recovery;
}
public void setRecovery(RecoveryDTO recovery) {
this.recovery = recovery;
}
public SimulationListDTO getSimulationList() {
return simulationList;
}
public void setSimulationList(SimulationListDTO simulationList) {
this.simulationList = simulationList;
}
public String getMachAlt() {
return this.machAlt;
}
public void setMachAlt(String machAlt) {
this.machAlt = machAlt;
}
public String getVersion() {
return version;
}
}

View File

@ -0,0 +1,93 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.StorageOptions;
import net.sf.openrocket.file.RocketSaver;
import net.sf.openrocket.rocketcomponent.Rocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
public class RASAeroSaver extends RocketSaver {
/**
* The logger.
*/
private static final Logger log = LoggerFactory.getLogger(RASAeroSaver.class);
public static class RASAeroExportException extends Exception {
public RASAeroExportException(String errorMessage) {
super(errorMessage);
}
}
/**
* This method marshals an OpenRocketDocument (OR design) to RASAero-compliant XML.
*
* @param doc the OR design
* @return RASAero-compliant XML
*/
public String marshalToRASAero(OpenRocketDocument doc) {
try {
JAXBContext binder = JAXBContext.newInstance(RASAeroDocumentDTO.class);
Marshaller marshaller = binder.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
StringWriter sw = new StringWriter();
marshaller.marshal(toRASAeroDocumentDTO(doc), sw);
return sw.toString();
} catch (RASAeroExportException e) {
throw new RuntimeException(e);
} catch (Exception e) {
log.error("Could not marshall a design to RASAero format. " + e.getMessage());
}
return null;
}
@Override
public void save(OutputStream dest, OpenRocketDocument doc, StorageOptions options) throws IOException {
log.info("Saving .CDX1 file");
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(dest, StandardCharsets.UTF_8));
writer.write(marshalToRASAero(doc));
writer.flush();
}
@Override
public long estimateFileSize(OpenRocketDocument doc, StorageOptions options) {
return marshalToRASAero(doc).length();
}
/**
* Root conversion method. It iterates over all subcomponents.
*
* @param doc the OR design
* @return a corresponding RASAero representation
*/
private RASAeroDocumentDTO toRASAeroDocumentDTO(OpenRocketDocument doc) throws RASAeroExportException {
RASAeroDocumentDTO rad = new RASAeroDocumentDTO();
rad.setDesign(toRocketDesignDTO(doc.getRocket()));
return rad;
}
/**
* Create the RASAero rocket design (containing all the actual rocket components).
* @param rocket the OR rocket to export the components from
* @return the RASAero rocket design
*/
private RocketDesignDTO toRocketDesignDTO(Rocket rocket) throws RASAeroExportException {
RocketDesignDTO result = new RocketDesignDTO(rocket);
return result;
}
}

View File

@ -0,0 +1,4 @@
package net.sf.openrocket.file.rasaero.export;
public class RecoveryDTO {
}

View File

@ -0,0 +1,202 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.CustomBooleanAdapter;
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.NoseCone;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.util.ArrayList;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementRefs;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.List;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
@XmlAccessorType(XmlAccessType.FIELD)
public class RocketDesignDTO {
@XmlElementRefs({
@XmlElementRef(name = RASAeroCommonConstants.BODY_TUBE, type = BodyTubeDTO.class),
@XmlElementRef(name = RASAeroCommonConstants.NOSE_CONE, type = NoseConeDTO.class),
@XmlElementRef(name = RASAeroCommonConstants.TRANSITION, type = TransitionDTO.class),
@XmlElementRef(name = RASAeroCommonConstants.BOOSTER, type = BoosterDTO.class)
})
private final List<BasePartDTO> externalPart = new ArrayList<>();
@XmlElementRefs({
@XmlElementRef(name = RASAeroCommonConstants.BOOSTER, type = BoosterDTO.class),
})
private final List<BoosterDTO> boosters = new ArrayList<>();
@XmlElement(name = RASAeroCommonConstants.SURFACE_FINISH)
private String surface = RASAeroCommonConstants.FINISH_SMOOTH;
@XmlElement(name = RASAeroCommonConstants.CD)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double CD = 0d;
@XmlElement(name = RASAeroCommonConstants.MODIFIED_BARROWMAN)
@XmlJavaTypeAdapter(CustomBooleanAdapter.class)
private Boolean modifiedBarrowman = false;
@XmlElement(name = RASAeroCommonConstants.TURBULENCE)
@XmlJavaTypeAdapter(CustomBooleanAdapter.class)
private Boolean turbulence = false;
@XmlElement(name = RASAeroCommonConstants.SUSTAINER_NOZZLE)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double sustainerNozzle = 0d;
@XmlElement(name = RASAeroCommonConstants.BOOSTER1_NOZZLE)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double booster1Nozzle = 0d;
@XmlElement(name = RASAeroCommonConstants.BOOSTER2_NOZZLE)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double booster2Nozzle = 0d;
@XmlElement(name = RASAeroCommonConstants.USE_BOOSTER1)
@XmlJavaTypeAdapter(CustomBooleanAdapter.class)
private Boolean useBooster1 = false;
@XmlElement(name = RASAeroCommonConstants.USE_BOOSTER2)
@XmlJavaTypeAdapter(CustomBooleanAdapter.class)
private Boolean useBooster2 = false;
@XmlElement(name = RASAeroCommonConstants.COMMENTS)
private String comments = "";
public RocketDesignDTO(Rocket rocket) throws RASAeroExportException {
setComments(rocket.getComment());
if (rocket.getChildCount() > 3) {
throw new RASAeroExportException("Rocket should have no more then 3 stages (excl. boosters) in total");
}
setUseBooster1(rocket.getStageCount() >= 2);
setUseBooster2(rocket.getStageCount() == 3);
AxialStage sustainer = rocket.getStage(0);
// Export components from sustainer
for (int i = 0; i < sustainer.getChildCount(); i++) {
RocketComponent component = sustainer.getChild(i);
if (i == 0 && !(component instanceof NoseCone)) {
throw new RASAeroExportException("First component of the sustainer must be a nose cone");
} else if (i == 1 && !(component instanceof BodyTube)) {
throw new RASAeroExportException("Second component of the sustainer must be a body tube");
}
if (component instanceof BodyTube) {
addExternalPart(new BodyTubeDTO((BodyTube) component));
} else if (component instanceof NoseCone) {
if (i != 0) {
throw new RASAeroExportException("A nose cone can only be the first component of the rocket");
}
addExternalPart(new NoseConeDTO((NoseCone) component));
// Set the global surface finish to that of the first nose cone
setSurface(RASAeroCommonConstants.OPENROCKET_TO_RASAERO_SURFACE(((NoseCone) component).getFinish()));
}
else if (component instanceof Transition) {
addExternalPart(new TransitionDTO((Transition) component));
}
}
// Export components from other stages
for (int i = 1; i < rocket.getChildCount(); i++) {
addBooster(new BoosterDTO(rocket, (AxialStage) rocket.getChild(i)));
}
}
public String getSurface() {
return surface;
}
public void setSurface(String surface) {
this.surface = surface;
}
public double getCD() {
return CD;
}
public void setCD(double CD) {
this.CD = CD;
}
public boolean isModifiedBarrowman() {
return modifiedBarrowman;
}
public void setModifiedBarrowman(boolean modifiedBarrowman) {
this.modifiedBarrowman = modifiedBarrowman;
}
public Boolean isTurbulence() {
return turbulence;
}
public void setTurbulence(Boolean turbulence) {
this.turbulence = turbulence;
}
public Double getSustainerNozzle() {
return sustainerNozzle;
}
public void setSustainerNozzle(Double sustainerNozzle) {
this.sustainerNozzle = sustainerNozzle;
}
public Double getBooster1Nozzle() {
return booster1Nozzle;
}
public void setBooster1Nozzle(Double booster1Nozzle) {
this.booster1Nozzle = booster1Nozzle;
}
public Double getBooster2Nozzle() {
return booster2Nozzle;
}
public void setBooster2Nozzle(Double booster2Nozzle) {
this.booster2Nozzle = booster2Nozzle;
}
public Boolean isUseBooster1() {
return useBooster1;
}
public void setUseBooster1(Boolean useBooster1) {
this.useBooster1 = useBooster1;
}
public Boolean isUseBooster2() {
return useBooster2;
}
public void setUseBooster2(Boolean useBooster2) {
this.useBooster2 = useBooster2;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
public List<BasePartDTO> getExternalPart() {
return externalPart;
}
public void addExternalPart(BasePartDTO theExternalPartDTO) {
externalPart.add(theExternalPartDTO);
}
public List<BoosterDTO> getBoosters() {
return boosters;
}
public void addBooster(BoosterDTO boosterDTO) {
boosters.add(boosterDTO);
}
}

View File

@ -0,0 +1,4 @@
package net.sf.openrocket.file.rasaero.export;
public class SimulationListDTO {
}

View File

@ -0,0 +1,61 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
import net.sf.openrocket.rocketcomponent.SymmetricComponent;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.util.MathUtil;
import java.util.Objects;
@XmlRootElement(name = RASAeroCommonConstants.TRANSITION)
@XmlAccessorType(XmlAccessType.FIELD)
public class TransitionDTO extends BasePartDTO {
@XmlElement(name = RASAeroCommonConstants.REAR_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double rearDiameter;
/**
* We need a default no-args constructor.
*/
public TransitionDTO() {
}
public TransitionDTO(Transition transition) throws RASAeroExportException {
super(transition);
if (!transition.getShapeType().equals(Transition.Shape.CONICAL)) {
throw new RASAeroExportException("RASAero only supports conical transitions");
}
SymmetricComponent previousComp = transition.getPreviousSymmetricComponent();
if (previousComp == null) {
throw new RASAeroExportException(String.format("Transition '%s' has no previous component", transition.getName()));
}
if (!MathUtil.equals(transition.getForeRadius(), previousComp.getAftRadius())) {
throw new RASAeroExportException(
String.format("Transition '%s' should have the same fore radius as the aft radius (%f) of its previous component, not (%f)",
transition.getName(), previousComp.getAftRadius(), transition.getForeRadius()));
}
setRearDiameter(transition.getAftRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
}
public Double getRearDiameter() {
return rearDiameter;
}
public void setRearDiameter(Double rearDiameter) {
this.rearDiameter = rearDiameter;
}
}

View File

@ -2,6 +2,7 @@ package net.sf.openrocket.file.rasaero.importt;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import org.xml.sax.SAXException;

View File

@ -2,6 +2,7 @@ package net.sf.openrocket.file.rasaero.importt;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.PodSet;

View File

@ -2,6 +2,7 @@ package net.sf.openrocket.file.rasaero.importt;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;
import net.sf.openrocket.rocketcomponent.BodyTube;
@ -75,8 +76,8 @@ public class BodyTubeHandler extends BaseHandler<BodyTube> {
@Override
public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
super.endHandler(element, attributes, content, warnings);
this.bodyTube.setLength(length / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH);
this.bodyTube.setOuterRadius(diameter/2 / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH); // Not really useful, but included for completeness
this.bodyTube.setLength(length / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
this.bodyTube.setOuterRadius(diameter/2 / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH); // Not really useful, but included for completeness
this.bodyTube.setOuterRadiusAutomatic(true);
this.bodyTube.setThickness(0.002); // Arbitrary value; RASAero doesn't specify this

View File

@ -2,6 +2,7 @@ package net.sf.openrocket.file.rasaero.importt;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;
import net.sf.openrocket.rocketcomponent.AxialStage;
@ -40,7 +41,7 @@ public class BoosterHandler extends BodyTubeHandler {
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) throws SAXException {
if (RASAeroCommonConstants.BOAT_TAIL_LENGTH.equals(element) || RASAeroCommonConstants.BOAT_TAIL_REAR_DIAMETER.equals(element)
if (RASAeroCommonConstants.BOATTAIL_LENGTH.equals(element) || RASAeroCommonConstants.BOATTAIL_REAR_DIAMETER.equals(element)
|| RASAeroCommonConstants.SHOULDER_LENGTH.equals(element)) {
return PlainTextHandler.INSTANCE;
}
@ -50,12 +51,12 @@ public class BoosterHandler extends BodyTubeHandler {
@Override
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
super.closeElement(element, attributes, content, warnings);
if (RASAeroCommonConstants.BOAT_TAIL_LENGTH.equals(element)) {
this.boatTailLength = Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH;
} else if (RASAeroCommonConstants.BOAT_TAIL_REAR_DIAMETER.equals(element)) {
this.boatTailRearDiameter = Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH;
if (RASAeroCommonConstants.BOATTAIL_LENGTH.equals(element)) {
this.boatTailLength = Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH;
} else if (RASAeroCommonConstants.BOATTAIL_REAR_DIAMETER.equals(element)) {
this.boatTailRearDiameter = Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH;
} else if (RASAeroCommonConstants.SHOULDER_LENGTH.equals(element)) {
this.shoulderLength = Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH;
this.shoulderLength = Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH;
}
}

View File

@ -2,6 +2,7 @@ package net.sf.openrocket.file.rasaero.importt;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.PodSet;
import net.sf.openrocket.rocketcomponent.RocketComponent;
@ -59,9 +60,9 @@ public class FinCanHandler extends BodyTubeHandler {
super.closeElement(element, attributes, content, warnings);
try {
if (RASAeroCommonConstants.INSIDE_DIAMETER.equals(element)) {
insideDiameter = Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH;
insideDiameter = Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH;
} else if (RASAeroCommonConstants.SHOULDER_LENGTH.equals(element)) {
shoulderLength = Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH;
shoulderLength = Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH;
}
} catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");

View File

@ -1,6 +1,7 @@
package net.sf.openrocket.file.rasaero.importt;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;
@ -46,21 +47,21 @@ public class FinHandler extends AbstractElementHandler {
if (RASAeroCommonConstants.FIN_COUNT.equals(element)) {
finSet.setFinCount(Integer.parseInt(content));
} else if (RASAeroCommonConstants.FIN_CHORD.equals(element)) {
finSet.setRootChord(Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH);
finSet.setRootChord(Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
} else if (RASAeroCommonConstants.FIN_SPAN.equals(element)) {
finSet.setHeight(Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH);
finSet.setHeight(Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
} else if (RASAeroCommonConstants.FIN_SWEEP_DISTANCE.equals(element)) {
finSet.setSweep(Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH);
finSet.setSweep(Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
} else if (RASAeroCommonConstants.FIN_TIP_CHORD.equals(element)) {
finSet.setTipChord(Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH);
finSet.setTipChord(Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
} else if (RASAeroCommonConstants.FIN_THICKNESS.equals(element)) {
finSet.setThickness(Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH);
finSet.setThickness(Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
} else if (RASAeroCommonConstants.AIRFOIL_SECTION.equals(element)) {
finSet.setCrossSection(RASAeroCommonConstants.getFinCrossSectionFromRASAero(content, warnings));
finSet.setCrossSection(RASAeroCommonConstants.RASAERO_TO_OPENROCKET_FIN_CROSSSECTION(content, warnings));
} else if (RASAeroCommonConstants.LOCATION.equals(element)) {
// Location is the location of the front of the fin relative to the bottom of the body tube
finSet.setAxialMethod(AxialMethod.BOTTOM);
double location = Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH;
double location = Double.parseDouble(content) / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH;
location = -location + finSet.getLength();
finSet.setAxialOffset(location);
}

View File

@ -1,5 +1,6 @@
package net.sf.openrocket.file.rasaero.importt;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.LaunchLug;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
@ -14,8 +15,8 @@ import net.sf.openrocket.rocketcomponent.position.AxialMethod;
*/
public abstract class LaunchLugHandler {
public static void addLaunchLug(BodyTube parent, double diameter, double length) {
diameter = diameter / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH;
length = length / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH;
diameter = diameter / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH;
length = length / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH;
LaunchLug lug = generateLaunchLugFromRASAeroRailGuide(diameter, length, parent.getLength());
parent.addChild(lug);

View File

@ -1,6 +1,7 @@
package net.sf.openrocket.file.rasaero.importt;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;

View File

@ -2,6 +2,7 @@ package net.sf.openrocket.file.rasaero.importt;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;
import net.sf.openrocket.rocketcomponent.NoseCone;
@ -47,8 +48,8 @@ public class NoseConeHandler extends BaseHandler<NoseCone> {
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
super.closeElement(element, attributes, content, warnings);
if (RASAeroCommonConstants.SHAPE.equals(element)) {
this.noseCone.setShapeType(RASAeroCommonConstants.getNoseConeShapeFromRASAero(content));
this.noseCone.setShapeParameter(RASAeroCommonConstants.getNoseConeShapeParameterFromRASAeroShape(content));
this.noseCone.setShapeType(RASAeroCommonConstants.RASAERO_TO_OPENROCKET_SHAPE(content));
this.noseCone.setShapeParameter(RASAeroCommonConstants.RASAERO_TO_OPENROCKET_SHAPE_PARAMETER(content));
}
try {
if (RASAeroCommonConstants.POWER_LAW.equals(element)) {
@ -63,8 +64,8 @@ public class NoseConeHandler extends BaseHandler<NoseCone> {
@Override
public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
super.endHandler(element, attributes, content, warnings);
this.noseCone.setLength(length / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH);
this.noseCone.setBaseRadius(diameter/2 / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH);
this.noseCone.setLength(length / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
this.noseCone.setBaseRadius(diameter/2 / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
this.noseCone.setThickness(0.002); // Arbitrary value; RASAero doesn't specify this
}

View File

@ -3,6 +3,7 @@ package net.sf.openrocket.file.rasaero.importt;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;

View File

@ -1,5 +1,6 @@
package net.sf.openrocket.file.rasaero.importt;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.RailButton;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
@ -22,8 +23,8 @@ public abstract class RailGuideHandler {
* @param height total height of the rail guide, plus the screw height
*/
public static void addRailGuide(BodyTube parent, double diameter, double height) {
diameter = diameter / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH;
height = height / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH;
diameter = diameter / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH;
height = height / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH;
RailButton button = generateRailButtonFromRASAeroRailGuide(diameter, height, parent.getLength());
parent.addChild(button);

View File

@ -1,6 +1,7 @@
package net.sf.openrocket.file.rasaero.importt;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;
@ -163,7 +164,7 @@ public class RecoveryHandler extends AbstractElementHandler {
recoveryDevice.setName("Recovery Event " + (recoveryDeviceNr+1));
DeploymentConfiguration config = recoveryDevice.getDeploymentConfigurations().getDefault();
recoveryDevice.setDiameter(size / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH);
recoveryDevice.setDiameter(size / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
recoveryDevice.setLineLength(recoveryDevice.getDiameter());
recoveryDevice.setCD(CD);
config.setDeployAltitude(altitude / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_ALTITUDE);
@ -173,7 +174,7 @@ public class RecoveryHandler extends AbstractElementHandler {
eventType = "Altitude";
warnings.add("Recovery device 2 is set to apogee, but recovery device 1 is also set to apogee. Setting recovery device 2 to altitude.");
}
config.setDeployEvent(RASAeroCommonConstants.getDeployEventFromRASAero(eventType, warnings));
config.setDeployEvent(RASAeroCommonConstants.RASAERO_TO_OPENROCKET_DEPLOY_EVENT(eventType, warnings));
// Shroud line count = diameter / 6 inches. 6 inches = 0.1524 meters. Minimum is 6 lines.
recoveryDevice.setLineCount(Math.max(6, (int) Math.round(recoveryDevice.getDiameter() / 0.1524)));

View File

@ -3,6 +3,7 @@ package net.sf.openrocket.file.rasaero.importt;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;

View File

@ -1,6 +1,7 @@
package net.sf.openrocket.file.rasaero.importt;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.rocketcomponent.ExternalComponent;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
@ -12,7 +13,7 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
*/
public abstract class SurfaceFinishHandler {
public static void setSurfaceFinishes(Rocket rocket, String finish, WarningSet warnings) {
ExternalComponent.Finish surfaceFinish = RASAeroCommonConstants.getSurfaceFinishFromRASAero(finish, warnings);
ExternalComponent.Finish surfaceFinish = RASAeroCommonConstants.RASAERO_TO_OPENROCKET_SURFACE(finish, warnings);
for (RocketComponent component : rocket) {
if (component instanceof ExternalComponent) {
((ExternalComponent) component).setFinish(surfaceFinish);

View File

@ -2,6 +2,7 @@ package net.sf.openrocket.file.rasaero.importt;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;
import net.sf.openrocket.rocketcomponent.RocketComponent;
@ -54,7 +55,7 @@ public class TransitionHandler extends BaseHandler<Transition> {
super.closeElement(element, attributes, content, warnings);
try {
if (RASAeroCommonConstants.REAR_DIAMETER.equals(element)) {
this.transition.setAftRadius(Double.parseDouble(content) / 2 / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH);
this.transition.setAftRadius(Double.parseDouble(content) / 2 / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
}
} catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
@ -64,8 +65,8 @@ public class TransitionHandler extends BaseHandler<Transition> {
@Override
public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
super.endHandler(element, attributes, content, warnings);
this.transition.setLength(length / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH);
this.transition.setForeRadius(diameter/2 / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TO_LENGTH); // Not really useful, but adding it for completeness
this.transition.setLength(length / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
this.transition.setForeRadius(diameter/2 / RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH); // Not really useful, but adding it for completeness
this.transition.setForeRadiusAutomatic(true);
this.transition.setThickness(0.002); // Arbitrary value; RASAero doesn't specify this
}

View File

@ -79,6 +79,7 @@ public abstract class Preferences implements ChangeSource {
private static final String SHOW_DISCARD_CONFIRMATION = "IgnoreDiscardEditingWarning";
public static final String MARKER_STYLE_ICON = "MARKER_STYLE_ICON";
private static final String SHOW_MARKERS = "SHOW_MARKERS";
private static final String SHOW_RASAERO_FORMAT_WARNING = "SHOW_RASAERO_FORMAT_WARNING";
private static final String SHOW_ROCKSIM_FORMAT_WARNING = "SHOW_ROCKSIM_FORMAT_WARNING";
//Preferences related to 3D graphics
@ -223,6 +224,14 @@ public abstract class Preferences implements ChangeSource {
public final void setLaunchIntoWind(boolean check) {
this.putBoolean(LAUNCH_INTO_WIND, check);
}
public final boolean getShowRASAeroFormatWarning() {
return this.getBoolean(SHOW_RASAERO_FORMAT_WARNING, true);
}
public final void setShowRASAeroFormatWarning(boolean check) {
this.putBoolean(SHOW_RASAERO_FORMAT_WARNING, check);
}
public final boolean getShowRockSimFormatWarning() {
return this.getBoolean(SHOW_ROCKSIM_FORMAT_WARNING, true);

View File

@ -65,5 +65,16 @@ public class Color {
public java.awt.Color toAWTColor() {
return new java.awt.Color(red, green, blue, alpha);
}
@Override
public boolean equals(Object obj) {
if (super.equals(obj)) {
return true;
}
if (!(obj instanceof Color)) {
return false;
}
Color c = (Color) obj;
return c.getRed() == getRed() && c.getGreen() == getGreen() && c.getBlue() == getBlue() && c.getAlpha() == getAlpha();
}
}

View File

@ -228,6 +228,17 @@ public class GeneralPreferencesPanel extends PreferencesPanel {
}
});
this.add(openRecentOnStartupBox,"spanx, wrap");
//// Save RASAero Format warning dialog
final JCheckBox rasaeroWarningDialogBox = new JCheckBox(trans.get("pref.dlg.lbl.RASAeroWarning"));
rasaeroWarningDialogBox.setSelected(preferences.getShowRASAeroFormatWarning());
rasaeroWarningDialogBox.addActionListener( new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
preferences.setShowRASAeroFormatWarning(rasaeroWarningDialogBox.isSelected());
}
});
this.add(rasaeroWarningDialogBox,"spanx, wrap");
//// Save RockSim Format warning dialog
final JCheckBox rocksimWarningDialogBox = new JCheckBox(trans.get("pref.dlg.lbl.RockSimWarning"));

View File

@ -60,6 +60,7 @@ import net.sf.openrocket.document.events.DocumentChangeEvent;
import net.sf.openrocket.document.events.DocumentChangeListener;
import net.sf.openrocket.file.GeneralRocketSaver;
import net.sf.openrocket.file.RocketLoadException;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.gui.configdialog.ComponentConfigDialog;
import net.sf.openrocket.gui.customexpression.CustomExpressionDialog;
@ -87,7 +88,6 @@ import net.sf.openrocket.gui.util.OpenFileWorker;
import net.sf.openrocket.gui.util.SaveFileWorker;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.gui.util.URLUtil;
import net.sf.openrocket.gui.widgets.SaveFileChooser;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.Markers;
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
@ -407,18 +407,16 @@ public class BasicFrame extends JFrame {
exportSubMenu.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.file.exportAs.desc"));
exportSubMenu.setIcon(Icons.FILE_EXPORT);
/* Pending Future Development
////// Export RASAero
JMenuItem exportRASAero = new JMenuItem(trans.get("main.fileMenu.file.exportAs.RASAero"));
exportRASAero.setIcon(Icons.RASAERO
exportRASAero.getAccessibleContext().setAccessibleDescription(trans.get("main.fileMenu.file.exportAs.RASAero.desc"));
JMenuItem exportRASAero = new JMenuItem(trans.get("main.menu.file.exportAs.RASAero"));
exportRASAero.setIcon(Icons.RASAERO);
exportRASAero.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.file.exportAs.RASAero.desc"));
exportRASAero.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
exportRASAeroAction();}
});
exportSubMenu.add(exportRASAero);
*/
////// Export RockSim
JMenuItem exportRockSim = new JMenuItem(trans.get("main.menu.file.exportAs.RockSim"));
@ -1374,56 +1372,134 @@ public class BasicFrame extends JFrame {
return saveAsOpenRocket(file);
}
/**
* Opens a file chooser dialog for saving a new file, and returns the selected file.
* @param fileType file type to use (e.g. RASAero)
* @return the file selected from the dialog, or null if no file was selected.
*/
private File openFileSaveAsDialog(FileType fileType) {
final DesignFileSaveAsFileChooser chooser = DesignFileSaveAsFileChooser.build(document, fileType);
//// BEGIN RASAERO Export Action *** UNDER CONSTRUCTION -- CURRENTLY FOR TESTING ONLY ***
int option = chooser.showSaveDialog(BasicFrame.this);
if (option != JFileChooser.APPROVE_OPTION) {
log.info(Markers.USER_MARKER, "User decided not to save, option=" + option);
return null;
}
File file = chooser.getSelectedFile();
if (file == null) {
log.info(Markers.USER_MARKER, "User did not select a file");
return null;
}
((SwingPreferences) Application.getPreferences()).setDefaultDirectory(chooser.getCurrentDirectory());
return file;
}
//// BEGIN RASAero Save/Export Action
/**
* MODEL "Export as" RASAero file format
*
* @return true if the file was saved, false otherwise
*/
/*
public boolean exportRASAeroAction() {
Object exportRASAeroAction = ExportFileTranslator_RASAero.exportRASAeroAction;
File file = openFileSaveAsDialog(FileType.RASAERO);
if (file == null) {
return false;
}
file = FileHelper.forceExtension(file, RASAeroCommonConstants.FILE_EXTENSION);
if (FileHelper.confirmWrite(file, this) ) {
return saveAsRASAero(file);
}
return false;
}
*/
//// END RASAERO Export Action
/**
* Perform the writing of the design to the given file in RASAero format.
* @param file the chosen file
* @return true if the file was written
*/
private boolean saveAsRASAero(File file) {
if (prefs.getShowRASAeroFormatWarning()) {
// Show RASAero format warning
JPanel panel = new JPanel(new MigLayout());
panel.add(new StyledLabel(trans.get("SaveRASAeroWarningDialog.txt1")), "wrap");
final JCheckBox check = new JCheckBox(trans.get("SaveRASAeroWarningDialog.donotshow"));
check.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
prefs.setShowRASAeroFormatWarning(!check.isSelected());
}
});
panel.add(check);
int sel = JOptionPane.showOptionDialog(null,
panel,
"", // title
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.WARNING_MESSAGE,
null, // icon
null, // options
null // default option
);
if (sel == 1) {
return false;
}
}
StorageOptions options = new StorageOptions();
options.setFileType(FileType.RASAERO);
return saveRASAeroFile(file, options);
}
/**
* Perform the actual saving of the RASAero file
* @param file file to be stored
* @param options storage options to use
* @return true if the file was written
*/
private boolean saveRASAeroFile(File file, StorageOptions options) {
try {
ROCKET_SAVER.save(file, document, options);
// Do not update the save state of the document.
return true;
} catch (IOException e) {
return false;
} catch (DecalNotFoundException decex) {
DecalImage decal = decex.getDecal();
// Check if the user replaced the source file, if not, just ignore the faulty decal on the next save
if (!DecalNotFoundDialog.showDialog(null, decex) && decal != null) {
decal.setIgnored(true);
}
return saveRASAeroFile(file, options); // Re-save
}
}
//// END RASAero Save/Export Action
//// BEGIN ROCKSIM Export Action
//// BEGIN ROCKSIM Save/Export Action
/**
* MODEL "Export as" RASAero file format
*
* @return true if the file was saved, false otherwise
*/
public boolean exportRockSimAction() {
File file;
final DesignFileSaveAsFileChooser chooser = DesignFileSaveAsFileChooser.build(document, FileType.ROCKSIM);
int option = chooser.showSaveDialog(BasicFrame.this);
if (option != JFileChooser.APPROVE_OPTION) {
log.info(Markers.USER_MARKER, "User decided not to save, option=" + option);
return false;
}
file = chooser.getSelectedFile();
File file = openFileSaveAsDialog(FileType.ROCKSIM);
if (file == null) {
log.info(Markers.USER_MARKER, "User did not select a file");
return false;
}
((SwingPreferences) Application.getPreferences()).setDefaultDirectory(chooser.getCurrentDirectory());
file = FileHelper.forceExtension(file, "rkt");
if (FileHelper.confirmWrite(file, this) ) {
return saveAsRockSim(file);
}
return false;
}
// END ROCKSIM Export Action
/**
* Perform the writing of the design to the given file in RockSim format.
@ -1488,6 +1564,8 @@ public class BasicFrame extends JFrame {
}
}
//// END ROCKSIM Save/Export Action
/**
* "Save As" action.

View File

@ -53,13 +53,13 @@ public class DesignFileSaveAsFileChooser extends SaveFileChooser {
this.addChoosableFileFilter(FileHelper.ROCKSIM_DESIGN_FILTER);
this.setFileFilter(FileHelper.ROCKSIM_DESIGN_FILTER);
break;
/*case RASAERO:
case RASAERO:
defaultFilename = FileHelper.forceExtension(defaultFilename,"CDX1");
this.setDialogTitle(trans.get("saveAs.rasaero.title"));
storageChooser = null;
this.addChoosableFileFilter(FileHelper.RASAERO_DESIGN_FILTER);
this.setFileFilter(FileHelper.RASAERO_DESIGN_FILTER);
break;*/
break;
}
final RememberFilenamePropertyListener listener = new RememberFilenamePropertyListener();