Added support for Rocksim Tube Fin Set file elements (import and export).
This commit is contained in:
parent
3d64b58144
commit
f1cf8c88bd
@ -84,6 +84,8 @@ public class RocksimCommonConstants {
|
||||
public static final String RING_TAIL = "RingTail";
|
||||
public static final String EXTERNAL_POD = "ExternalPod";
|
||||
public static final String TEXTURE = "Texture";
|
||||
public static final String TUBE_COUNT = "TubeCount";
|
||||
public static final String MAX_TUBES_ALLOWED = "MaxTubesAllowed";
|
||||
|
||||
/**
|
||||
* Length conversion. Rocksim is in millimeters, OpenRocket in meters.
|
||||
|
@ -15,6 +15,7 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.rocketcomponent.Streamer;
|
||||
import net.sf.openrocket.rocketcomponent.Transition;
|
||||
import net.sf.openrocket.rocketcomponent.TubeCoupler;
|
||||
import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
@ -53,10 +54,11 @@ public class BodyTubeDTO extends BasePartDTO implements AttachableParts {
|
||||
@XmlElementRef(name = RocksimCommonConstants.LAUNCH_LUG, type = LaunchLugDTO.class),
|
||||
@XmlElementRef(name = RocksimCommonConstants.FIN_SET, type = FinSetDTO.class),
|
||||
@XmlElementRef(name = RocksimCommonConstants.CUSTOM_FIN_SET, type = CustomFinSetDTO.class),
|
||||
@XmlElementRef(name = RocksimCommonConstants.TUBE_FIN_SET, type = TubeFinSetDTO.class),
|
||||
@XmlElementRef(name = RocksimCommonConstants.STREAMER, type = StreamerDTO.class),
|
||||
@XmlElementRef(name = RocksimCommonConstants.PARACHUTE, type = ParachuteDTO.class),
|
||||
@XmlElementRef(name = RocksimCommonConstants.MASS_OBJECT, type = MassObjectDTO.class)})
|
||||
List<BasePartDTO> attachedParts = new ArrayList<BasePartDTO>();
|
||||
List<BasePartDTO> attachedParts = new ArrayList();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@ -121,6 +123,8 @@ public class BodyTubeDTO extends BasePartDTO implements AttachableParts {
|
||||
attachedParts.add(new CustomFinSetDTO((FreeformFinSet) rocketComponents));
|
||||
} else if (rocketComponents instanceof FinSet) {
|
||||
attachedParts.add(new FinSetDTO((FinSet) rocketComponents));
|
||||
} else if (rocketComponents instanceof TubeFinSet) {
|
||||
attachedParts.add(new TubeFinSetDTO((TubeFinSet) rocketComponents));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,109 @@
|
||||
package net.sf.openrocket.file.rocksim.export;
|
||||
|
||||
import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
|
||||
import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* This class models an XML element for a Rocksim TubeFinSet.
|
||||
*/
|
||||
@XmlRootElement(name = RocksimCommonConstants.TUBE_FIN_SET)
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class TubeFinSetDTO extends BasePartDTO {
|
||||
|
||||
@XmlElement(name = RocksimCommonConstants.OD)
|
||||
private double od = 0d;
|
||||
@XmlElement(name = RocksimCommonConstants.ID)
|
||||
private double id = 0d;
|
||||
@XmlElement(name = RocksimCommonConstants.TUBE_COUNT)
|
||||
private int tubeCount = 0;
|
||||
@XmlElement(name = RocksimCommonConstants.MAX_TUBES_ALLOWED)
|
||||
private int maxTubeCount = 0;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public TubeFinSetDTO() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor. Fully populates this instance with values taken from the OR TubeFinSet.
|
||||
*
|
||||
* @param theORTubeFinSet The OR TubeFinSet component to be serialized in Rocksim format
|
||||
*/
|
||||
public TubeFinSetDTO(TubeFinSet theORTubeFinSet) {
|
||||
super(theORTubeFinSet);
|
||||
setId(theORTubeFinSet.getInnerRadius() * RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS);
|
||||
setOd(theORTubeFinSet.getOuterRadius() * RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS);
|
||||
setRadialAngle(theORTubeFinSet.getBaseRotation());
|
||||
setTubeCount(theORTubeFinSet.getFinCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the outer diameter of the tube fin(s).
|
||||
*
|
||||
* @return diameter in meters
|
||||
*/
|
||||
public double getOd() {
|
||||
return od;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the outer diameter of the tube fin(s).
|
||||
*
|
||||
* @param theOd diameter in meters
|
||||
*/
|
||||
public void setOd(double theOd) {
|
||||
od = theOd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the inner diameter of the tube fin(s).
|
||||
*
|
||||
* @return diameter in meters
|
||||
*/
|
||||
public double getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the inner diameter of the tube fin(s).
|
||||
*
|
||||
* @param theId diameter in meters
|
||||
*/
|
||||
public void setId(double theId) {
|
||||
id = theId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tube fin count.
|
||||
*
|
||||
* @return # tube fins
|
||||
*/
|
||||
public int getTubeCount() {
|
||||
return tubeCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the tube fin count.
|
||||
*
|
||||
* @param theTubeCount # tube fins
|
||||
*/
|
||||
public void setTubeCount(final int theTubeCount) {
|
||||
tubeCount = theTubeCount;
|
||||
maxTubeCount = tubeCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the max tube fin count. Since OR doesn't have this concept, just set it to the actual count.
|
||||
*
|
||||
* @return # tube fins
|
||||
*/
|
||||
public int getMaxTubeCount() {
|
||||
return maxTubeCount;
|
||||
}
|
||||
}
|
@ -77,7 +77,7 @@ class AttachedPartsHandler extends AbstractElementHandler {
|
||||
return new SubAssemblyHandler(context, component);
|
||||
}
|
||||
if (RocksimCommonConstants.TUBE_FIN_SET.equals(element)) {
|
||||
warnings.add("Tube fins are not currently supported. Ignoring.");
|
||||
return new TubeFinSetHandler(context, component, warnings);
|
||||
}
|
||||
if (RocksimCommonConstants.RING_TAIL.equals(element)) {
|
||||
warnings.add("Ring tails are not currently supported. Ignoring.");
|
||||
|
@ -0,0 +1,119 @@
|
||||
package net.sf.openrocket.file.rocksim.importt;
|
||||
|
||||
import net.sf.openrocket.aerodynamics.WarningSet;
|
||||
import net.sf.openrocket.file.DocumentLoadingContext;
|
||||
import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
|
||||
import net.sf.openrocket.file.rocksim.RocksimFinishCode;
|
||||
import net.sf.openrocket.file.simplesax.ElementHandler;
|
||||
import net.sf.openrocket.file.simplesax.PlainTextHandler;
|
||||
import net.sf.openrocket.material.Material;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Rocksim import SAX handler for Tube Fin Sets.
|
||||
*/
|
||||
public class TubeFinSetHandler extends PositionDependentHandler<TubeFinSet> {
|
||||
|
||||
/**
|
||||
* The OpenRocket TubeFinSet instance.
|
||||
*/
|
||||
private final TubeFinSet tubeFin;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param c the parent
|
||||
* @param warnings the warning set
|
||||
*
|
||||
* @throws IllegalArgumentException thrown if <code>c</code> is null
|
||||
*/
|
||||
public TubeFinSetHandler(DocumentLoadingContext context, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
|
||||
super(context);
|
||||
if (c == null) {
|
||||
throw new IllegalArgumentException("The parent component of a tube fin may not be null.");
|
||||
}
|
||||
tubeFin = new TubeFinSet();
|
||||
if (isCompatible(c, TubeFinSet.class, warnings)) {
|
||||
c.addChild(tubeFin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the relative position onto the component.
|
||||
*
|
||||
* @param position the OpenRocket position
|
||||
*/
|
||||
@Override
|
||||
protected void setRelativePosition(final RocketComponent.Position position) {
|
||||
tubeFin.setRelativePosition(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the OR instance after the XML parsing is done.
|
||||
*
|
||||
* @return a TubeFinSet instance
|
||||
*/
|
||||
@Override
|
||||
protected TubeFinSet getComponent() {
|
||||
return tubeFin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of material the tube fins are constructed from.
|
||||
*
|
||||
* @return Material.Type
|
||||
*/
|
||||
@Override
|
||||
protected Material.Type getMaterialType() {
|
||||
return Material.Type.BULK;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public ElementHandler openElement(final String element, final HashMap<String, String> attributes, final WarningSet warnings) throws SAXException {
|
||||
return PlainTextHandler.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
|
||||
throws SAXException {
|
||||
super.closeElement(element, attributes, content, warnings);
|
||||
|
||||
try {
|
||||
if (RocksimCommonConstants.OD.equals(element)) {
|
||||
tubeFin.setOuterRadius(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
|
||||
}
|
||||
if (RocksimCommonConstants.ID.equals(element)) {
|
||||
tubeFin.setInnerRadius(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
|
||||
}
|
||||
if (RocksimCommonConstants.LEN.equals(element)) {
|
||||
tubeFin.setLength(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
|
||||
}
|
||||
if (RocksimCommonConstants.MATERIAL.equals(element)) {
|
||||
setMaterialName(content);
|
||||
}
|
||||
if (RocksimCommonConstants.RADIAL_ANGLE.equals(element)) {
|
||||
tubeFin.setBaseRotation(Double.parseDouble(content));
|
||||
}
|
||||
if (RocksimCommonConstants.TUBE_COUNT.equals(element)) {
|
||||
tubeFin.setFinCount(Integer.parseInt(content));
|
||||
}
|
||||
if (RocksimCommonConstants.FINISH_CODE.equals(element)) {
|
||||
tubeFin.setFinish(RocksimFinishCode.fromCode(Integer.parseInt(content)).asOpenRocket());
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -122,7 +122,7 @@ public class RocksimLoaderTest extends BaseTestCase {
|
||||
Assert.assertEquals(0.185d, stage1.getOverrideMass(), 0.001);
|
||||
Assert.assertTrue(stage1.isCGOverridden());
|
||||
Assert.assertEquals(0.3d, stage1.getOverrideCG().x, 0.001);
|
||||
Assert.assertEquals(4, loader.getWarnings().size());
|
||||
Assert.assertEquals(3, loader.getWarnings().size());
|
||||
|
||||
Assert.assertEquals(1, stage2.getChildCount());
|
||||
Assert.assertEquals("2nd Stage Tube", stage2.getChild(0).getName());
|
||||
|
@ -0,0 +1,84 @@
|
||||
package net.sf.openrocket.file.rocksim.importt;
|
||||
|
||||
import net.sf.openrocket.aerodynamics.WarningSet;
|
||||
import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
|
||||
import net.sf.openrocket.rocketcomponent.BodyTube;
|
||||
import net.sf.openrocket.rocketcomponent.ExternalComponent;
|
||||
import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Test for importing a Rocksim TubeFinSet into OR.
|
||||
*/
|
||||
public class TubeFinSetHandlerTest {
|
||||
|
||||
/**
|
||||
* Method: asOpenRocket(WarningSet warnings)
|
||||
*
|
||||
* @throws Exception thrown if something goes awry
|
||||
*/
|
||||
@org.junit.Test
|
||||
public void testAsOpenRocket() throws Exception {
|
||||
|
||||
WarningSet warnings = new WarningSet();
|
||||
TubeFinSetHandler handler = new TubeFinSetHandler(null, new BodyTube(), warnings);
|
||||
|
||||
HashMap<String, String> attributes = new HashMap<>();
|
||||
|
||||
handler.closeElement("Name", attributes, "The name", warnings);
|
||||
handler.closeElement("TubeCount", attributes, "4", warnings);
|
||||
handler.closeElement("RadialAngle", attributes, ".123", warnings);
|
||||
|
||||
TubeFinSet fins = handler.getComponent();
|
||||
Assert.assertNotNull(fins);
|
||||
Assert.assertEquals(0, warnings.size());
|
||||
|
||||
Assert.assertEquals("The name", fins.getName());
|
||||
Assert.assertEquals(4, fins.getFinCount());
|
||||
|
||||
Assert.assertEquals(.123d, fins.getBaseRotation(), 0d);
|
||||
|
||||
handler.closeElement("OD", attributes, "-1", warnings);
|
||||
Assert.assertEquals(0d, fins.getOuterRadius(), 0.001);
|
||||
handler.closeElement("OD", attributes, "0", warnings);
|
||||
Assert.assertEquals(0d, fins.getOuterRadius(), 0.001);
|
||||
handler.closeElement("OD", attributes, "75", warnings);
|
||||
Assert.assertEquals(75d / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS, fins.getOuterRadius(), 0.001);
|
||||
handler.closeElement("OD", attributes, "foo", warnings);
|
||||
Assert.assertEquals(1, warnings.size());
|
||||
warnings.clear();
|
||||
|
||||
handler.closeElement("ID", attributes, "-1", warnings);
|
||||
Assert.assertEquals(0d, fins.getInnerRadius(), 0.001);
|
||||
handler.closeElement("ID", attributes, "0", warnings);
|
||||
Assert.assertEquals(0d, fins.getInnerRadius(), 0.001);
|
||||
handler.closeElement("ID", attributes, "75", warnings);
|
||||
Assert.assertEquals(75d / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS, fins.getInnerRadius(), 0.001);
|
||||
handler.closeElement("ID", attributes, "foo", warnings);
|
||||
Assert.assertEquals(1, warnings.size());
|
||||
warnings.clear();
|
||||
|
||||
handler.closeElement("Len", attributes, "-1", warnings);
|
||||
Assert.assertEquals(0d, fins.getLength(), 0.001);
|
||||
handler.closeElement("Len", attributes, "10", warnings);
|
||||
Assert.assertEquals(10d / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH, fins.getLength(), 0.001);
|
||||
handler.closeElement("Len", attributes, "10.0", warnings);
|
||||
Assert.assertEquals(10d / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH, fins.getLength(), 0.001);
|
||||
handler.closeElement("Len", attributes, "foo", warnings);
|
||||
Assert.assertEquals(1, warnings.size());
|
||||
warnings.clear();
|
||||
|
||||
handler.closeElement("FinishCode", attributes, "-1", warnings);
|
||||
Assert.assertEquals(ExternalComponent.Finish.NORMAL, fins.getFinish());
|
||||
handler.closeElement("FinishCode", attributes, "100", warnings);
|
||||
Assert.assertEquals(ExternalComponent.Finish.NORMAL, fins.getFinish());
|
||||
handler.closeElement("FinishCode", attributes, "foo", warnings);
|
||||
Assert.assertEquals(1, warnings.size());
|
||||
warnings.clear();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
1127
core/test/net/sf/openrocket/file/rocksim/importt/TubeFins1.rkt
Normal file
1127
core/test/net/sf/openrocket/file/rocksim/importt/TubeFins1.rkt
Normal file
File diff suppressed because it is too large
Load Diff
1127
core/test/net/sf/openrocket/file/rocksim/importt/TubeFins2.rkt
Normal file
1127
core/test/net/sf/openrocket/file/rocksim/importt/TubeFins2.rkt
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user