Added inference of Rocksim shock cords to try to be a little more predictive when a Rocksim file uses a buggy shock

cord from their component database.
This commit is contained in:
Doug Pedrick 2012-07-11 22:06:23 +00:00
parent c8f7665177
commit 960555c108
2 changed files with 131 additions and 63 deletions

View File

@ -55,6 +55,7 @@ public abstract class BaseHandler<C extends RocketComponent> extends AbstractEle
* @param attributes attributes of the element. * @param attributes attributes of the element.
* @param content the textual content of the element. * @param content the textual content of the element.
* @param warnings the warning set to store warnings in. * @param warnings the warning set to store warnings in.
*
* @throws SAXException * @throws SAXException
*/ */
@ -70,7 +71,7 @@ public abstract class BaseHandler<C extends RocketComponent> extends AbstractEle
mass = Math.max(0d, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_MASS); mass = Math.max(0d, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_MASS);
} }
if (RocksimCommonConstants.DENSITY.equals(element)) { if (RocksimCommonConstants.DENSITY.equals(element)) {
density = Math.max(0d, Double.parseDouble(content) ); density = Math.max(0d, Double.parseDouble(content));
} }
if (RocksimCommonConstants.KNOWN_CG.equals(element)) { if (RocksimCommonConstants.KNOWN_CG.equals(element)) {
cg = Math.max(0d, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH); cg = Math.max(0d, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
@ -105,13 +106,14 @@ public abstract class BaseHandler<C extends RocketComponent> extends AbstractEle
/** /**
* Compute the density. Rocksim does strange things with densities. For some streamer material it's in cubic, * Compute the density. Rocksim does strange things with densities. For some streamer material it's in cubic,
* rather than square, units. In those cases it needs to be converted to an appropriate SURFACE material density. * rather than square, units. In those cases it needs to be converted to an appropriate SURFACE material density.
* Some G10 fiberglass materials are in cubic units, other G10 fiberglass is in square units. And due to a * Some G10 fiberglass materials are in cubic units, other G10 fiberglass is in square units. And due to a Rocksim
* Rocksim bug, some densities are 0 when they clearly should not be. * bug, some densities are 0 when they clearly should not be.
* * <p/>
* This may be overridden for specific component density computations. * This may be overridden for specific component density computations.
* *
* @param type the rocksim density * @param type the rocksim density
* @param rawDensity the density as specified in the Rocksim design file * @param rawDensity the density as specified in the Rocksim design file
*
* @return a value in OpenRocket SURFACE density units * @return a value in OpenRocket SURFACE density units
*/ */
protected double computeDensity(RocksimDensityType type, double rawDensity) { protected double computeDensity(RocksimDensityType type, double rawDensity) {
@ -119,14 +121,14 @@ public abstract class BaseHandler<C extends RocketComponent> extends AbstractEle
} }
/** /**
* If the Rocksim component does not override the mass, then create a Material based upon the density defined * If the Rocksim component does not override the mass, then create a Material based upon the density defined for
* for that component. This *should* result in a consistent representation of Cg between Rocksim and OpenRocket. * that component. This *should* result in a consistent representation of Cg between Rocksim and OpenRocket.
* *
* @param component the component * @param component the component
* @param type the type of the material * @param type the type of the material
* @param density the density in g/cm^3 * @param density the density in g/cm^3
* @param definedMaterial the material that is currently defined on the component; used only to get the name * @param definedMaterial the material that is currently defined on the component; used only to get the name as it
* as it appears in Rocksim * appears in Rocksim
*/ */
public static void updateComponentMaterial(RocketComponent component, String definedMaterial, Material.Type type, public static void updateComponentMaterial(RocketComponent component, String definedMaterial, Material.Type type,
double density) { double density) {
@ -186,6 +188,15 @@ public abstract class BaseHandler<C extends RocketComponent> extends AbstractEle
materialName = content; materialName = content;
} }
/**
* Get the Rocksim enum of the component's density type.
*
* @return a Rocksim density type
*/
protected RocksimDensityType getDensityType() {
return densityType;
}
/** /**
* Add child to parent only if the child is compatible. Otherwise add to warning set. * Add child to parent only if the child is compatible. Otherwise add to warning set.
* *
@ -196,9 +207,27 @@ public abstract class BaseHandler<C extends RocketComponent> extends AbstractEle
* @return true if the child is compatible with parent * @return true if the child is compatible with parent
*/ */
protected static boolean isCompatible(RocketComponent parent, Class<? extends RocketComponent> child, WarningSet warnings) { protected static boolean isCompatible(RocketComponent parent, Class<? extends RocketComponent> child, WarningSet warnings) {
return isCompatible(parent, child, warnings, false);
}
/**
* Add child to parent only if the child is compatible. Otherwise add to warning set.
*
* @param parent the parent component
* @param child the child component
* @param warnings the warning set
* @param suppressWarnings suppress warnings, just return the boolean
*
* @return true if the child is compatible with parent
*/
protected static boolean isCompatible(RocketComponent parent, Class<? extends RocketComponent> child,
WarningSet warnings,
boolean suppressWarnings) {
if (!parent.isCompatible(child)) { if (!parent.isCompatible(child)) {
if (!suppressWarnings) {
warnings.add(child.getName() + " can not be attached to " warnings.add(child.getName() + " can not be attached to "
+ parent.getComponentName() + ", ignoring component."); + parent.getComponentName() + ", ignoring component.");
}
return false; return false;
} }
else { else {
@ -207,8 +236,8 @@ public abstract class BaseHandler<C extends RocketComponent> extends AbstractEle
} }
/** /**
* Create a custom material based on the density. The name of the material is prepended with 'RS: ' to * Create a custom material based on the density. The name of the material is prepended with 'RS: ' to indicate it
* indicate it came from a RockSim material. * came from a RockSim material.
* *
* @param type the type of the material * @param type the type of the material
* @param name the name of the component * @param name the name of the component
@ -243,7 +272,7 @@ public abstract class BaseHandler<C extends RocketComponent> extends AbstractEle
/** /**
* Find a method by name and argument list. * Find a method by name and argument list.
* *
* @param component the component who's material is to be seta * @param component the component who's material is to be set
* @param name the method name * @param name the method name
* @param args the class types of the parameters * @param args the class types of the parameters
* *

View File

@ -5,9 +5,11 @@ package net.sf.openrocket.file.rocksim.importt;
import net.sf.openrocket.aerodynamics.WarningSet; import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.rocksim.RocksimCommonConstants; import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
import net.sf.openrocket.file.rocksim.RocksimDensityType;
import net.sf.openrocket.file.simplesax.ElementHandler; import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler; import net.sf.openrocket.file.simplesax.PlainTextHandler;
import net.sf.openrocket.material.Material; import net.sf.openrocket.material.Material;
import net.sf.openrocket.rocketcomponent.Coaxial;
import net.sf.openrocket.rocketcomponent.MassComponent; import net.sf.openrocket.rocketcomponent.MassComponent;
import net.sf.openrocket.rocketcomponent.MassObject; import net.sf.openrocket.rocketcomponent.MassObject;
import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.RocketComponent;
@ -24,9 +26,9 @@ class MassObjectHandler extends PositionDependentHandler<MassObject> {
/** /**
* The Rocksim Mass length fudge factor. Rocksim completely exaggerates the length of a mass object to the point * The Rocksim Mass length fudge factor. Rocksim completely exaggerates the length of a mass object to the point
* that it looks ridiculous in OpenRocket. This fudge factor is here merely to get the typical mass object to * that it looks ridiculous in OpenRocket. This fudge factor is here merely to get the typical mass object to
* render in the OpenRocket UI with it's bounds mostly inside it's parent. The odd thing about it is that * render in the OpenRocket UI with it's bounds mostly inside it's parent. The odd thing about it is that Rocksim
* Rocksim does not expose the length of a mass object in the UI and actually treats mass objects as point objects - * does not expose the length of a mass object in the UI and actually treats mass objects as point objects - not 3
* not 3 or even 2 dimensional. * or even 2 dimensional.
*/ */
public static final int MASS_LEN_FUDGE_FACTOR = 100; public static final int MASS_LEN_FUDGE_FACTOR = 100;
@ -51,8 +53,8 @@ class MassObjectHandler extends PositionDependentHandler<MassObject> {
private int typeCode = 0; private int typeCode = 0;
/** /**
* Constructor. * Constructor. l
*l *
* @param c the parent component * @param c the parent component
* @param warnings the warning set * @param warnings the warning set
* *
@ -104,14 +106,47 @@ class MassObjectHandler extends PositionDependentHandler<MassObject> {
} }
@Override @Override
public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException { public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws
if (typeCode == 0) { //General Mass Object SAXException {
if (inferAsShockCord(typeCode, warnings)) { //Shock Cord
mapMassObjectAsShockCord(element, attributes, content, warnings);
}
else { // typeCode == 0 General Mass Object
if (isCompatible(parent, MassComponent.class, warnings)) { if (isCompatible(parent, MassComponent.class, warnings)) {
parent.addChild(mass); parent.addChild(mass);
} }
super.endHandler(element, attributes, content, warnings); super.endHandler(element, attributes, content, warnings);
} }
else if (typeCode == 1) { //Shock Cord }
/**
* Rocksim does not have a separate entity for Shock Cords. It has to be inferred. Sometimes the typeCode
* indicates it's a shock cord, but most times it does not. This is due to bugs in the Rocksim Component and
* Material databases. Try to infer a shock cord based on it's length and it's material type. It's somewhat
* arbitrary, but if the mass object's length is more than twice the length of it's parent component and it's a LINE
* material, then assume a shock cord.
*
* @param theTypeCode the code from the RKT XML file
*
* @return true if we think it's a shock cord
*/
private boolean inferAsShockCord(int theTypeCode, WarningSet warnings) {
return (theTypeCode == 1 || (mass.getLength() >= 2 * parent.getLength() && RocksimDensityType.ROCKSIM_LINE
.equals(getDensityType()))) && isCompatible(parent, ShockCord.class, warnings, true);
}
/**
* If it appears that the mass object is a shock cord, then create an OR shock cord instance.
*
* @param element the element name
* @param attributes the attributes
* @param content the content of the element
* @param warnings the warning set to store warnings in.
*
* @throws org.xml.sax.SAXException not thrown
*/
private void mapMassObjectAsShockCord(final String element, final HashMap<String, String> attributes,
final String content, final WarningSet warnings) throws SAXException {
ShockCord cord = new ShockCord(); ShockCord cord = new ShockCord();
current = cord; current = cord;
if (isCompatible(parent, ShockCord.class, warnings)) { if (isCompatible(parent, ShockCord.class, warnings)) {
@ -129,7 +164,10 @@ class MassObjectHandler extends PositionDependentHandler<MassObject> {
//Rocksim does not distinguish between total length of the cord and the packed length. Fudge the //Rocksim does not distinguish between total length of the cord and the packed length. Fudge the
//packed length and set the real length. //packed length and set the real length.
cord.setCordLength(mass.getLength()); cord.setCordLength(mass.getLength());
cord.setLength(cord.getCordLength()/MASS_LEN_FUDGE_FACTOR); cord.setLength(cord.getCordLength() / MASS_LEN_FUDGE_FACTOR);
if (parent instanceof Coaxial) {
Coaxial parentCoaxial = (Coaxial) parent;
cord.setRadius(parentCoaxial.getInnerRadius());
} }
} }
@ -154,7 +192,8 @@ class MassObjectHandler extends PositionDependentHandler<MassObject> {
} }
/** /**
* Get the required type of material for this component. Does not apply to MassComponents, but does apply to Shock Cords. * Get the required type of material for this component. Does not apply to MassComponents, but does apply to Shock
* Cords.
* *
* @return LINE * @return LINE
*/ */