Rework attachment loading. Construct a DocumentLoadingContext in

GenericLoader and pass into both OpenRocketLoader and RocksimLoader. 
the DocumentLoadingContext contains the OpenRocketDocument, MotorFinder,
and AttachmentFactory.
This commit is contained in:
kruland2607 2013-01-10 21:11:57 -06:00
parent 48adc0b7bf
commit 593c639a06
52 changed files with 1963 additions and 1923 deletions

View File

@ -1,7 +0,0 @@
package net.sf.openrocket.document;
public interface AttachmentFactory<T extends Attachment> {
public T getAttachment(String name);
}

View File

@ -19,53 +19,51 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.sf.openrocket.appearance.DecalImage;
import net.sf.openrocket.document.attachments.FileSystemAttachment;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.FileUtils;
public class DecalRegistry implements AttachmentFactory<DecalImage> {
public class DecalRegistry {
private static LogHelper log = Application.getLogger();
private final AttachmentFactory baseFactory;
DecalRegistry() {
public DecalRegistry(AttachmentFactory baseFactory) {
this.baseFactory = baseFactory;
}
private Map<String, DecalImageImpl> registeredDecals = new HashMap<String, DecalImageImpl>();
public DecalImage getAttachment(String decalName) {
DecalImageImpl d = registeredDecals.get(decalName);
if (d == null) {
Attachment attachment = baseFactory.getAttachment(decalName);
d = new DecalImageImpl(attachment);
public DecalImage getDecalImage(Attachment attachment) {
String decalName = attachment.getName();
DecalImageImpl d;
if (attachment instanceof FileSystemAttachment) {
File location = ((FileSystemAttachment) attachment).getLocation();
d = findDecalForFile(location);
if (d != null) {
return d;
}
// It's a new file, generate a name for it.
decalName = makeUniqueName(location.getName());
d = new DecalImageImpl(decalName, attachment);
d.setFileSystemLocation(location);
registeredDecals.put(decalName, d);
return d;
} else {
d = registeredDecals.get(decalName);
if (d != null) {
return d;
}
}
d = new DecalImageImpl(attachment);
registeredDecals.put(decalName, d);
return d;
}
public DecalImage getAttachment(File file) {
// See if this file is being used already
DecalImageImpl decal = findDecalForFile(file);
if (decal != null) {
return decal;
}
// It's a new file, generate a name for it.
String decalName = makeUniqueName(file.getName());
Attachment attachment = baseFactory.getAttachment(decalName);
decal = new DecalImageImpl(attachment);
decal.setFileSystemLocation(file);
registeredDecals.put(decalName, decal);
return decal;
}
public Collection<DecalImage> getDecalList() {
Set<DecalImage> decals = new TreeSet<DecalImage>();
@ -79,25 +77,31 @@ public class DecalRegistry implements AttachmentFactory<DecalImage> {
private final Attachment delegate;
private String name;
private File fileSystemLocation;
private DecalImageImpl(String name, Attachment delegate) {
this.name = name;
this.delegate = delegate;
}
private DecalImageImpl(Attachment delegate) {
this.delegate = delegate;
}
@Override
public String getName() {
return delegate.getName();
return name != null ? name : delegate.getName();
}
@Override
public InputStream getBytes() throws FileNotFoundException, IOException {
return DecalRegistry.this.getDecal(this);
return DecalRegistry.getDecal(this);
}
@Override
public void exportImage(File file, boolean watchForChanges) throws IOException {
DecalRegistry.this.exportDecal(this, file);
DecalRegistry.exportDecal(this, file);
this.fileSystemLocation = file;
}
@ -111,7 +115,7 @@ public class DecalRegistry implements AttachmentFactory<DecalImage> {
@Override
public String toString() {
return delegate.toString();
return getName();
}
@Override
@ -119,7 +123,7 @@ public class DecalRegistry implements AttachmentFactory<DecalImage> {
if (!(o instanceof DecalImageImpl)) {
return -1;
}
return delegate.compareTo(((DecalImageImpl) o).delegate);
return getName().compareTo(o.getName());
}
}
@ -133,7 +137,7 @@ public class DecalRegistry implements AttachmentFactory<DecalImage> {
* @throws FileNotFoundException
* @throws IOException
*/
private InputStream getDecal(DecalImageImpl decal) throws FileNotFoundException, IOException {
private static InputStream getDecal(DecalImageImpl decal) throws FileNotFoundException, IOException {
// First check if the decal is located on the file system
File exportedFile = decal.getFileSystemLocation();
@ -152,7 +156,7 @@ public class DecalRegistry implements AttachmentFactory<DecalImage> {
}
private void exportDecal(DecalImageImpl decal, File selectedFile) throws IOException {
private static void exportDecal(DecalImageImpl decal, File selectedFile) throws IOException {
try {
InputStream is = decal.getBytes();

View File

@ -1,14 +1,14 @@
package net.sf.openrocket.document;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import net.sf.openrocket.appearance.DecalImage;
import net.sf.openrocket.document.events.DocumentChangeEvent;
import net.sf.openrocket.document.events.DocumentChangeListener;
import net.sf.openrocket.document.events.SimulationChangeEvent;
@ -60,9 +60,6 @@ public class OpenRocketDocument implements ComponentChangeListener {
private final ArrayList<Simulation> simulations = new ArrayList<Simulation>();
private ArrayList<CustomExpression> customExpressions = new ArrayList<CustomExpression>();
private final AttachmentFactory attachmentFactory;
private final DecalRegistry decalRegistry;
/*
* The undo/redo variables and mechanism are documented in doc/undo-redo-flow.*
*/
@ -95,36 +92,13 @@ public class OpenRocketDocument implements ComponentChangeListener {
private final StorageOptions storageOptions = new StorageOptions();
private final DecalRegistry decalRegistry = new DecalRegistry();
private final List<DocumentChangeListener> listeners = new ArrayList<DocumentChangeListener>();
OpenRocketDocument(Rocket rocket, File fileName, boolean isContainer) {
OpenRocketDocument(Rocket rocket) {
this.configuration = rocket.getDefaultConfiguration();
this.rocket = rocket;
AttachmentFactory attachments;
if (isContainer) {
try {
attachments = new ZipFileAttachmentFactory(fileName.toURI().toURL());
} catch (MalformedURLException mex) {
attachments = new FileSystemAttachmentFactory(null);
}
} else {
if (fileName == null) {
attachments = new FileSystemAttachmentFactory(null);
} else {
attachments = new FileSystemAttachmentFactory(fileName.getParentFile());
}
}
this.attachmentFactory = attachments;
this.decalRegistry = new DecalRegistry(this.attachmentFactory);
init();
}
OpenRocketDocument(Rocket rocket, URL jarURL, boolean isContainer) {
this.configuration = rocket.getDefaultConfiguration();
this.rocket = rocket;
this.attachmentFactory = isContainer ? new ZipFileAttachmentFactory(jarURL) : new FileSystemAttachmentFactory(null);
this.decalRegistry = new DecalRegistry(this.attachmentFactory);
init();
}
@ -197,10 +171,6 @@ public class OpenRocketDocument implements ComponentChangeListener {
return configuration;
}
public DecalRegistry getDecalRegistry() {
return decalRegistry;
}
public File getFile() {
return file;
}
@ -209,7 +179,6 @@ public class OpenRocketDocument implements ComponentChangeListener {
this.file = file;
}
public boolean isSaved() {
return rocket.getModID() == savedID;
}
@ -231,8 +200,15 @@ public class OpenRocketDocument implements ComponentChangeListener {
}
public Collection<DecalImage> getDecalList() {
return decalRegistry.getDecalList();
}
public DecalImage getDecalImage(Attachment a) {
return decalRegistry.getDecalImage(a);
}
public List<Simulation> getSimulations() {
return simulations.clone();

View File

@ -1,8 +1,5 @@
package net.sf.openrocket.document;
import java.io.File;
import java.net.URL;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.Stage;
@ -18,25 +15,19 @@ public class OpenRocketDocumentFactory {
//// Sustainer
stage.setName(trans.get("BasicFrame.StageName.Sustainer"));
rocket.addChild(stage);
OpenRocketDocument doc = new OpenRocketDocument(rocket, (File) null, false);
OpenRocketDocument doc = new OpenRocketDocument(rocket);
doc.setSaved(true);
return doc;
}
public static OpenRocketDocument createDocumentFromRocket(Rocket r) {
OpenRocketDocument doc = new OpenRocketDocument(r, (File) null, false);
OpenRocketDocument doc = new OpenRocketDocument(r);
return doc;
}
public static OpenRocketDocument createDocumentForFile(File filename, boolean isContainer) {
public static OpenRocketDocument createEmptyRocket() {
Rocket rocket = new Rocket();
OpenRocketDocument doc = new OpenRocketDocument(rocket, filename, isContainer);
return doc;
}
public static OpenRocketDocument createDocumentForUrl(URL filename, boolean isContainer) {
Rocket rocket = new Rocket();
OpenRocketDocument doc = new OpenRocketDocument(rocket, filename, isContainer);
OpenRocketDocument doc = new OpenRocketDocument(rocket);
return doc;
}

View File

@ -17,6 +17,10 @@ public class FileSystemAttachment extends BaseAttachment implements Attachment {
this.location = location;
}
public File getLocation() {
return location;
}
@Override
public InputStream getBytes() throws FileNotFoundException, IOException {
return new FileInputStream(location);

View File

@ -4,7 +4,6 @@ import java.io.IOException;
import java.io.InputStream;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
public abstract class AbstractRocketLoader implements RocketLoader {
@ -15,11 +14,11 @@ public abstract class AbstractRocketLoader implements RocketLoader {
* Loads a rocket from the specified InputStream.
*/
@Override
public final void load(OpenRocketDocument doc, InputStream source, MotorFinder motorFinder) throws RocketLoadException {
public final void load(DocumentLoadingContext context, InputStream source) throws RocketLoadException {
warnings.clear();
try {
loadFromStream(doc, source, motorFinder);
loadFromStream(context, source);
} catch (RocketLoadException e) {
throw e;
} catch (IOException e) {
@ -35,8 +34,7 @@ public abstract class AbstractRocketLoader implements RocketLoader {
*
* @throws RocketLoadException if an error occurs during loading.
*/
protected abstract void loadFromStream(OpenRocketDocument doc, InputStream source, MotorFinder motorFinder) throws IOException,
RocketLoadException;
protected abstract void loadFromStream(DocumentLoadingContext context, InputStream source) throws IOException, RocketLoadException;

View File

@ -0,0 +1,9 @@
package net.sf.openrocket.file;
import net.sf.openrocket.document.Attachment;
public interface AttachmentFactory {
public Attachment getAttachment(String name);
}

View File

@ -1,12 +1,12 @@
package net.sf.openrocket.file.openrocket.importt;
package net.sf.openrocket.file;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.MotorFinder;
public class DocumentLoadingContext {
private int fileVersion;
private MotorFinder motorFinder;
private AttachmentFactory attachmentFactory = new FileSystemAttachmentFactory();
private OpenRocketDocument document;
public int getFileVersion() {
@ -33,4 +33,12 @@ public class DocumentLoadingContext {
this.document = document;
}
public AttachmentFactory getAttachmentFactory() {
return attachmentFactory;
}
public void setAttachmentFactory(AttachmentFactory attachmentFactory) {
this.attachmentFactory = attachmentFactory;
}
}

View File

@ -1,11 +1,11 @@
package net.sf.openrocket.document;
package net.sf.openrocket.file;
import java.io.File;
import net.sf.openrocket.document.attachments.BaseAttachment;
import net.sf.openrocket.document.Attachment;
import net.sf.openrocket.document.attachments.FileSystemAttachment;
public class FileSystemAttachmentFactory implements AttachmentFactory<BaseAttachment> {
public class FileSystemAttachmentFactory implements AttachmentFactory {
private final File baseDirectory;
@ -22,8 +22,12 @@ public class FileSystemAttachmentFactory implements AttachmentFactory<BaseAttach
this.baseDirectory = baseDirectory;
}
public Attachment getAttachment(File file) {
return new FileSystemAttachment(file.getName(), file);
}
@Override
public BaseAttachment getAttachment(String name) {
public Attachment getAttachment(String name) {
File file = new File(name);

View File

@ -5,6 +5,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.zip.GZIPInputStream;
@ -44,8 +45,11 @@ public class GeneralRocketLoader {
private File baseFile;
private URL jarURL;
private boolean isContainer;
private final MotorFinder motorFinder;
private AttachmentFactory attachmentFactory;
private final OpenRocketDocument doc = OpenRocketDocumentFactory.createEmptyRocket();
public GeneralRocketLoader(File file) {
this.baseFile = file;
@ -69,7 +73,7 @@ public class GeneralRocketLoader {
try {
stream = new BufferedInputStream(new FileInputStream(baseFile));
OpenRocketDocument doc = load(stream);
load(stream);
return doc;
} catch (Exception e) {
@ -87,7 +91,7 @@ public class GeneralRocketLoader {
public final OpenRocketDocument load(InputStream source) throws RocketLoadException {
try {
OpenRocketDocument doc = loadFromStream(source);
loadStep1(source);
return doc;
} catch (Exception e) {
throw new RocketLoadException("Exception loading stream", e);
@ -98,8 +102,20 @@ public class GeneralRocketLoader {
return warnings;
}
private OpenRocketDocument loadFromStream(InputStream source) throws IOException,
RocketLoadException {
/**
* This method determines the type file contained in the stream then calls the appropriate loading mecahnism.
*
* If the stream is a gzip file, the argument is wrapped in a GzipInputStream and the rocket loaded.
*
* If the stream is a zip container, the first zip entry with name ending in .ork or .rkt is loaded as the rocket.
*
* If the stream is neither, then it is assumed to be an xml file containing either an ork or rkt format rocket.
*
* @param source
* @throws IOException
* @throws RocketLoadException
*/
private void loadStep1(InputStream source) throws IOException, RocketLoadException {
// Check for mark() support
if (!source.markSupported()) {
@ -122,19 +138,17 @@ public class GeneralRocketLoader {
// Check for GZIP
if (buffer[0] == GZIP_SIGNATURE[0] && buffer[1] == GZIP_SIGNATURE[1]) {
OpenRocketDocument doc = OpenRocketDocumentFactory.createDocumentForFile(baseFile, false);
loadFromStream(doc, new GZIPInputStream(source));
return doc;
isContainer = false;
setAttachmentFactory();
loadRocket(new GZIPInputStream(source));
return;
}
// Check for ZIP (for future compatibility)
if (buffer[0] == ZIP_SIGNATURE[0] && buffer[1] == ZIP_SIGNATURE[1]) {
OpenRocketDocument doc;
if (baseFile != null) {
doc = OpenRocketDocumentFactory.createDocumentForFile(baseFile, true);
} else {
doc = OpenRocketDocumentFactory.createDocumentForUrl(jarURL, true);
}
isContainer = true;
setAttachmentFactory();
// Search for entry with name *.ork
ZipInputStream in = new ZipInputStream(source);
while (true) {
@ -143,27 +157,25 @@ public class GeneralRocketLoader {
throw new RocketLoadException("Unsupported or corrupt file.");
}
if (entry.getName().matches(".*\\.[oO][rR][kK]$")) {
loadFromStream(doc, in);
return doc;
loadRocket(in);
return;
} else if (entry.getName().matches(".*\\.[rR][kK][tT]$")) {
loadFromStream(doc, in);
return doc;
loadRocket(in);
return;
}
}
// FIXME should throw here because the zip file didn't contain either ork or rkt file.
}
OpenRocketDocument doc = null;
if (baseFile != null) {
doc = OpenRocketDocumentFactory.createDocumentForFile(baseFile, false);
} else {
doc = OpenRocketDocumentFactory.createDocumentForUrl(jarURL, false);
}
loadFromStream(doc, source);
return doc;
isContainer = false;
setAttachmentFactory();
loadRocket(source);
return;
}
private void loadFromStream(OpenRocketDocument doc, InputStream source) throws IOException, RocketLoadException {
private void loadRocket(InputStream source) throws IOException, RocketLoadException {
// Check for mark() support
if (!source.markSupported()) {
@ -187,7 +199,7 @@ public class GeneralRocketLoader {
if (buffer[i] == OPENROCKET_SIGNATURE[match]) {
match++;
if (match == OPENROCKET_SIGNATURE.length) {
loadUsing(doc, openRocketLoader, source);
loadUsing(openRocketLoader, source);
return;
}
} else {
@ -197,16 +209,36 @@ public class GeneralRocketLoader {
byte[] typeIdentifier = ArrayUtils.copyOf(buffer, ROCKSIM_SIGNATURE.length);
if (Arrays.equals(ROCKSIM_SIGNATURE, typeIdentifier)) {
loadUsing(doc, rocksimLoader, source);
loadUsing(rocksimLoader, source);
return;
}
throw new RocketLoadException("Unsupported or corrupt file.");
}
private void loadUsing(OpenRocketDocument doc, RocketLoader loader, InputStream source) throws RocketLoadException {
private void setAttachmentFactory() {
attachmentFactory = new FileSystemAttachmentFactory(null);
if (jarURL != null && isContainer) {
attachmentFactory = new ZipFileAttachmentFactory(jarURL);
} else {
if (isContainer) {
try {
attachmentFactory = new ZipFileAttachmentFactory(baseFile.toURI().toURL());
} catch (MalformedURLException mex) {
}
} else if (baseFile != null) {
attachmentFactory = new FileSystemAttachmentFactory(baseFile.getParentFile());
}
}
}
private void loadUsing(RocketLoader loader, InputStream source) throws RocketLoadException {
warnings.clear();
loader.load(doc, source, motorFinder);
DocumentLoadingContext context = new DocumentLoadingContext();
context.setOpenRocketDocument(doc);
context.setMotorFinder(motorFinder);
context.setAttachmentFactory(attachmentFactory);
loader.load(context, source);
warnings.addAll(loader.getWarnings());
}
}

View File

@ -3,11 +3,10 @@ package net.sf.openrocket.file;
import java.io.InputStream;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
public interface RocketLoader {
public void load(OpenRocketDocument doc, InputStream source, MotorFinder motorFinder) throws RocketLoadException;
public void load(DocumentLoadingContext context, InputStream source) throws RocketLoadException;
public WarningSet getWarnings();

View File

@ -1,10 +1,11 @@
package net.sf.openrocket.document;
package net.sf.openrocket.file;
import java.net.URL;
import net.sf.openrocket.document.Attachment;
import net.sf.openrocket.document.attachments.ZipFileAttachment;
public class ZipFileAttachmentFactory implements AttachmentFactory<Attachment> {
public class ZipFileAttachmentFactory implements AttachmentFactory {
private final URL zipFile;

View File

@ -5,6 +5,8 @@ import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.appearance.AppearanceBuilder;
import net.sf.openrocket.appearance.Decal.EdgeMode;
import net.sf.openrocket.document.Attachment;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;
@ -14,7 +16,6 @@ import net.sf.openrocket.util.Color;
import org.xml.sax.SAXException;
class AppearanceHandler extends AbstractElementHandler {
@SuppressWarnings("unused")
private final DocumentLoadingContext context;
private final RocketComponent component;
@ -31,7 +32,8 @@ class AppearanceHandler extends AbstractElementHandler {
throws SAXException {
if ("decal".equals(element)) {
String name = attributes.remove("name");
builder.setImage(context.getOpenRocketDocument().getDecalRegistry().getAttachment(name));
Attachment a = context.getAttachmentFactory().getAttachment(name);
builder.setImage(context.getOpenRocketDocument().getDecalImage(a));
double rotation = Double.parseDouble(attributes.remove("rotation"));
builder.setRotation(rotation);
String edgeModeName = attributes.remove("edgemode");

View File

@ -3,6 +3,7 @@ package net.sf.openrocket.file.openrocket.importt;
import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;

View File

@ -6,6 +6,7 @@ import java.util.HashMap;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.rocketcomponent.RocketComponent;

View File

@ -4,6 +4,7 @@ import java.util.HashMap;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;

View File

@ -3,6 +3,7 @@ package net.sf.openrocket.file.openrocket.importt;
import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.simulation.customexpression.CustomExpression;

View File

@ -4,6 +4,7 @@ import java.util.HashMap;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;

View File

@ -4,6 +4,7 @@ import java.util.HashMap;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;

View File

@ -5,6 +5,7 @@ import java.util.HashMap;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;

View File

@ -3,6 +3,7 @@ package net.sf.openrocket.file.openrocket.importt;
import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;

View File

@ -6,6 +6,7 @@ import java.util.List;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;

View File

@ -4,6 +4,7 @@ import java.util.HashMap;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;

View File

@ -5,6 +5,7 @@ import java.util.Locale;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;

View File

@ -5,6 +5,7 @@ import java.util.Locale;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;

View File

@ -5,6 +5,7 @@ import java.util.HashMap;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;

View File

@ -7,6 +7,7 @@ import java.util.regex.Pattern;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;

View File

@ -8,7 +8,7 @@ import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.document.StorageOptions;
import net.sf.openrocket.file.AbstractRocketLoader;
import net.sf.openrocket.file.MotorFinder;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.RocketLoadException;
import net.sf.openrocket.file.simplesax.SimpleSAX;
import net.sf.openrocket.logging.LogHelper;
@ -35,16 +35,14 @@ public class OpenRocketLoader extends AbstractRocketLoader {
@Override
public void loadFromStream(OpenRocketDocument doc, InputStream source, MotorFinder motorFinder) throws RocketLoadException,
public void loadFromStream(DocumentLoadingContext context, InputStream source) throws RocketLoadException,
IOException {
log.info("Loading .ork file");
DocumentLoadingContext context = new DocumentLoadingContext();
context.setMotorFinder(motorFinder);
context.setOpenRocketDocument(doc);
InputSource xmlSource = new InputSource(source);
OpenRocketHandler handler = new OpenRocketHandler(context);
OpenRocketDocument doc = context.getOpenRocketDocument();
try {
SimpleSAX.readXML(xmlSource, handler, warnings);

View File

@ -3,6 +3,7 @@ package net.sf.openrocket.file.openrocket.importt;
import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;

View File

@ -4,6 +4,7 @@ import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.simulation.customexpression.CustomExpression;

View File

@ -8,6 +8,7 @@ import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.document.Simulation.Status;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;

View File

@ -4,6 +4,7 @@ import java.util.HashMap;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;

View File

@ -6,7 +6,7 @@ package net.sf.openrocket.file.rocksim.importt;
import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
@ -16,65 +16,64 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
* A SAX handler for the Rocksim AttachedParts XML type.
*/
class AttachedPartsHandler extends AbstractElementHandler {
private final OpenRocketDocument document;
private final DocumentLoadingContext context;
/** The parent component. */
private final RocketComponent component;
/** The parent component. */
private final RocketComponent component;
/**
* Constructor.
*
* @param c the parent
*
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public AttachedPartsHandler(OpenRocketDocument document, RocketComponent c) throws IllegalArgumentException {
if (c == null) {
throw new IllegalArgumentException("The parent component of any attached part may not be null.");
}
this.document = document;
component = c;
}
/**
* Constructor.
*
* @param c the parent
*
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public AttachedPartsHandler(DocumentLoadingContext context, RocketComponent c) throws IllegalArgumentException {
if (c == null) {
throw new IllegalArgumentException("The parent component of any attached part may not be null.");
}
this.context = context;
component = c;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
if (RocksimCommonConstants.FIN_SET.equals(element)) {
return new FinSetHandler(document, component);
}
if (RocksimCommonConstants.CUSTOM_FIN_SET.equals(element)) {
return new FinSetHandler(document, component);
}
if (RocksimCommonConstants.LAUNCH_LUG.equals(element)) {
return new LaunchLugHandler(document, component, warnings);
}
if (RocksimCommonConstants.PARACHUTE.equals(element)) {
return new ParachuteHandler(document, component, warnings);
}
if (RocksimCommonConstants.STREAMER.equals(element)) {
return new StreamerHandler(document, component, warnings);
}
if (RocksimCommonConstants.MASS_OBJECT.equals(element)) {
return new MassObjectHandler(document, component, warnings);
}
if (RocksimCommonConstants.RING.equals(element)) {
return new RingHandler(document, component, warnings);
}
if (RocksimCommonConstants.BODY_TUBE.equals(element)) {
return new InnerBodyTubeHandler(document, component, warnings);
}
if (RocksimCommonConstants.TRANSITION.equals(element)) {
return new TransitionHandler(document, component, warnings);
}
if (RocksimCommonConstants.TUBE_FIN_SET.equals(element)) {
warnings.add("Tube fins are not currently supported. Ignoring.");
}
if (RocksimCommonConstants.RING_TAIL.equals(element)) {
warnings.add("Ring tails are not currently supported. Ignoring.");
}
if (RocksimCommonConstants.EXTERNAL_POD.equals(element)) {
warnings.add("Pods are not currently supported. Ignoring.");
}
return null;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
if (RocksimCommonConstants.FIN_SET.equals(element)) {
return new FinSetHandler(context, component);
}
if (RocksimCommonConstants.CUSTOM_FIN_SET.equals(element)) {
return new FinSetHandler(context, component);
}
if (RocksimCommonConstants.LAUNCH_LUG.equals(element)) {
return new LaunchLugHandler(context, component, warnings);
}
if (RocksimCommonConstants.PARACHUTE.equals(element)) {
return new ParachuteHandler(context, component, warnings);
}
if (RocksimCommonConstants.STREAMER.equals(element)) {
return new StreamerHandler(context, component, warnings);
}
if (RocksimCommonConstants.MASS_OBJECT.equals(element)) {
return new MassObjectHandler(context, component, warnings);
}
if (RocksimCommonConstants.RING.equals(element)) {
return new RingHandler(context, component, warnings);
}
if (RocksimCommonConstants.BODY_TUBE.equals(element)) {
return new InnerBodyTubeHandler(context, component, warnings);
}
if (RocksimCommonConstants.TRANSITION.equals(element)) {
return new TransitionHandler(context, component, warnings);
}
if (RocksimCommonConstants.TUBE_FIN_SET.equals(element)) {
warnings.add("Tube fins are not currently supported. Ignoring.");
}
if (RocksimCommonConstants.RING_TAIL.equals(element)) {
warnings.add("Ring tails are not currently supported. Ignoring.");
}
if (RocksimCommonConstants.EXTERNAL_POD.equals(element)) {
warnings.add("Pods are not currently supported. Ignoring.");
}
return null;
}
}

View File

@ -9,7 +9,7 @@ import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.database.Databases;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
import net.sf.openrocket.file.rocksim.RocksimDensityType;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
@ -53,13 +53,13 @@ public abstract class BaseHandler<C extends RocketComponent> extends AbstractEle
*/
private String materialName = "";
protected final OpenRocketDocument document;
private final RockSimAppearanceBuilder appearanceBuilder;
protected final DocumentLoadingContext context;
private final RockSimAppearanceBuilder appearanceBuilder;
public BaseHandler( OpenRocketDocument document ) {
this.document = document;
appearanceBuilder = new RockSimAppearanceBuilder( document );
}
public BaseHandler(DocumentLoadingContext context) {
this.context = context;
appearanceBuilder = new RockSimAppearanceBuilder(context);
}
/**
* The SAX method called when the closing element tag is reached.
@ -115,15 +115,15 @@ public abstract class BaseHandler<C extends RocketComponent> extends AbstractEle
density = computeDensity(densityType, density);
RocketComponent component = getComponent();
//TODO - What RockSim components can have Appearances?
if ( component instanceof ExternalComponent ){
//If a symmetric component is set to PreventSeam then it is repeated
//twice as many times around the rocket.
if ( component instanceof SymmetricComponent && appearanceBuilder.isPreventSeam() ){
appearanceBuilder.setScaleU(appearanceBuilder.getScaleU()*2);
//TODO - What RockSim components can have Appearances?
if (component instanceof ExternalComponent) {
//If a symmetric component is set to PreventSeam then it is repeated
//twice as many times around the rocket.
if (component instanceof SymmetricComponent && appearanceBuilder.isPreventSeam()) {
appearanceBuilder.setScaleU(appearanceBuilder.getScaleU() * 2);
}
component.setAppearance(appearanceBuilder.getAppearance());
}
component.setAppearance(appearanceBuilder.getAppearance());
}
updateComponentMaterial(component, materialName, getMaterialType(), density);
}

View File

@ -6,7 +6,7 @@ package net.sf.openrocket.file.rocksim.importt;
import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
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;
@ -21,88 +21,86 @@ import org.xml.sax.SAXException;
* A SAX handler for Rocksim Body Tubes.
*/
class BodyTubeHandler extends BaseHandler<BodyTube> {
/**
* The OpenRocket BodyTube.
*/
private final BodyTube bodyTube;
/**
* The OpenRocket BodyTube.
*/
private final BodyTube bodyTube;
/**
* Constructor.
*
* @param c parent component
* @param warnings the warning set
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public BodyTubeHandler(OpenRocketDocument document, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
super(document);
if (c == null) {
throw new IllegalArgumentException("The parent component of a body tube may not be null.");
}
bodyTube = new BodyTube();
if (isCompatible(c, BodyTube.class, warnings)) {
c.addChild(bodyTube);
}
}
/**
* Constructor.
*
* @param c parent component
* @param warnings the warning set
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public BodyTubeHandler(DocumentLoadingContext context, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
super(context);
if (c == null) {
throw new IllegalArgumentException("The parent component of a body tube may not be null.");
}
bodyTube = new BodyTube();
if (isCompatible(c, BodyTube.class, warnings)) {
c.addChild(bodyTube);
}
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
if (RocksimCommonConstants.ATTACHED_PARTS.equals(element)) {
return new AttachedPartsHandler(document, bodyTube);
}
return PlainTextHandler.INSTANCE;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
if (RocksimCommonConstants.ATTACHED_PARTS.equals(element)) {
return new AttachedPartsHandler(context, bodyTube);
}
return PlainTextHandler.INSTANCE;
}
@Override
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
throws SAXException {
super.closeElement(element, attributes, content, warnings);
@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)) {
bodyTube.setOuterRadius(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS);
}
if (RocksimCommonConstants.ID.equals(element)) {
final double r = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS;
bodyTube.setInnerRadius(r);
}
if (RocksimCommonConstants.LEN.equals(element)) {
bodyTube.setLength(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
}
if (RocksimCommonConstants.FINISH_CODE.equals(element)) {
bodyTube.setFinish(RocksimFinishCode.fromCode(Integer.parseInt(content)).asOpenRocket());
}
if (RocksimCommonConstants.IS_MOTOR_MOUNT.equals(element)) {
bodyTube.setMotorMount("1".equals(content));
}
if (RocksimCommonConstants.ENGINE_OVERHANG.equals(element)) {
bodyTube.setMotorOverhang(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
}
if (RocksimCommonConstants.MATERIAL.equals(element)) {
setMaterialName(content);
}
}
catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
try {
if (RocksimCommonConstants.OD.equals(element)) {
bodyTube.setOuterRadius(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS);
}
if (RocksimCommonConstants.ID.equals(element)) {
final double r = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS;
bodyTube.setInnerRadius(r);
}
if (RocksimCommonConstants.LEN.equals(element)) {
bodyTube.setLength(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
}
if (RocksimCommonConstants.FINISH_CODE.equals(element)) {
bodyTube.setFinish(RocksimFinishCode.fromCode(Integer.parseInt(content)).asOpenRocket());
}
if (RocksimCommonConstants.IS_MOTOR_MOUNT.equals(element)) {
bodyTube.setMotorMount("1".equals(content));
}
if (RocksimCommonConstants.ENGINE_OVERHANG.equals(element)) {
bodyTube.setMotorOverhang(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
}
if (RocksimCommonConstants.MATERIAL.equals(element)) {
setMaterialName(content);
}
} catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
/**
* Get the component this handler is working upon.
*
* @return a component
*/
@Override
public BodyTube getComponent() {
return bodyTube;
}
/**
* Get the component this handler is working upon.
*
* @return a component
*/
@Override
public BodyTube getComponent() {
return bodyTube;
}
/**
* Get the required type of material for this component.
*
* @return BULK
*/
public Material.Type getMaterialType() {
return Material.Type.BULK;
}
/**
* Get the required type of material for this component.
*
* @return BULK
*/
public Material.Type getMaterialType() {
return Material.Type.BULK;
}
}

View File

@ -9,7 +9,7 @@ import java.util.HashMap;
import java.util.List;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
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.rocksim.RocksimLocationMode;
@ -35,372 +35,368 @@ import org.xml.sax.SAXException;
* to construct the corresponding OpenRocket FinSet.
*/
class FinSetHandler extends AbstractElementHandler {
/**
* The parent component.
*/
private final RocketComponent component;
/**
* The parent component.
*/
private final RocketComponent component;
/**
* The name of the fin.
*/
private String name;
/**
* The Rocksim fin shape code.
*/
private int shapeCode;
/**
* The location of the fin on its parent.
*/
private double location = 0.0d;
/**
* The OpenRocket Position which gives the absolute/relative positioning for location.
*/
private RocketComponent.Position position;
/**
* The number of fins in this fin set.
*/
private int finCount;
/**
* The length of the root chord.
*/
private double rootChord = 0.0d;
/**
* The length of the tip chord.
*/
private double tipChord = 0.0d;
/**
* The length of the mid-chord (aka height).
*/
private double midChordLen = 0.0d;
/**
* The distance of the leading edge from root to top.
*/
private double sweepDistance = 0.0d;
/**
* The angle the fins have been rotated from the y-axis, if looking down the tube, in radians.
*/
private double radialAngle = 0.0d;
/**
* The thickness of the fins.
*/
private double thickness;
/**
* The finish of the fins.
*/
private ExternalComponent.Finish finish;
/**
* The shape of the tip.
*/
private int tipShapeCode;
/**
* The length of the TTW tab.
*/
private double tabLength = 0.0d;
/**
* The depth of the TTW tab.
*/
private double tabDepth = 0.0d;
/**
* The offset of the tab, from the front of the fin.
*/
private double taboffset = 0.0d;
/**
* The elliptical semi-span (height).
*/
private double semiSpan;
/**
* The list of custom points.
*/
private String pointList;
/**
* Override the Cg and mass.
*/
private boolean override = false;
/**
* The overridden mass.
*/
private Double mass = 0d;
/**
* The overridden Cg.
*/
private Double cg = 0d;
/**
* The density of the material in the component.
*/
private Double density = 0d;
/**
* The material name.
*/
private String materialName = "";
/**
* The Rocksim calculated mass.
*/
private Double calcMass = 0d;
/**
* The Rocksim calculated cg.
*/
private Double calcCg = 0d;
/**
* The name of the fin.
*/
private String name;
/**
* The Rocksim fin shape code.
*/
private int shapeCode;
/**
* The location of the fin on its parent.
*/
private double location = 0.0d;
/**
* The OpenRocket Position which gives the absolute/relative positioning for location.
*/
private RocketComponent.Position position;
/**
* The number of fins in this fin set.
*/
private int finCount;
/**
* The length of the root chord.
*/
private double rootChord = 0.0d;
/**
* The length of the tip chord.
*/
private double tipChord = 0.0d;
/**
* The length of the mid-chord (aka height).
*/
private double midChordLen = 0.0d;
/**
* The distance of the leading edge from root to top.
*/
private double sweepDistance = 0.0d;
/**
* The angle the fins have been rotated from the y-axis, if looking down the tube, in radians.
*/
private double radialAngle = 0.0d;
/**
* The thickness of the fins.
*/
private double thickness;
/**
* The finish of the fins.
*/
private ExternalComponent.Finish finish;
/**
* The shape of the tip.
*/
private int tipShapeCode;
/**
* The length of the TTW tab.
*/
private double tabLength = 0.0d;
/**
* The depth of the TTW tab.
*/
private double tabDepth = 0.0d;
/**
* The offset of the tab, from the front of the fin.
*/
private double taboffset = 0.0d;
/**
* The elliptical semi-span (height).
*/
private double semiSpan;
/**
* The list of custom points.
*/
private String pointList;
/**
* Override the Cg and mass.
*/
private boolean override = false;
/**
* The overridden mass.
*/
private Double mass = 0d;
/**
* The overridden Cg.
*/
private Double cg = 0d;
/**
* The density of the material in the component.
*/
private Double density = 0d;
/**
* The material name.
*/
private String materialName = "";
/**
* The Rocksim calculated mass.
*/
private Double calcMass = 0d;
/**
* The Rocksim calculated cg.
*/
private Double calcCg = 0d;
private final RockSimAppearanceBuilder appearanceBuilder;
private final RockSimAppearanceBuilder appearanceBuilder;
/**
* Constructor.
*
* @param c the parent
*
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public FinSetHandler (OpenRocketDocument document, RocketComponent c) throws IllegalArgumentException {
if (c == null) {
throw new IllegalArgumentException("The parent component of a fin set may not be null.");
}
appearanceBuilder = new RockSimAppearanceBuilder( document );
component = c;
}
/**
* Constructor.
*
* @param c the parent
*
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public FinSetHandler(DocumentLoadingContext context, RocketComponent c) throws IllegalArgumentException {
if (c == null) {
throw new IllegalArgumentException("The parent component of a fin set may not be null.");
}
appearanceBuilder = new RockSimAppearanceBuilder(context);
component = c;
}
@Override
public ElementHandler openElement (String element, HashMap<String, String> attributes, WarningSet warnings) {
return PlainTextHandler.INSTANCE;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
return PlainTextHandler.INSTANCE;
}
@Override
public void closeElement (String element, HashMap<String, String> attributes, String content, WarningSet warnings)
throws SAXException {
try {
if (RocksimCommonConstants.NAME.equals(element)) {
name = content;
}
if (RocksimCommonConstants.MATERIAL.equals(element)) {
materialName = content;
}
if (RocksimCommonConstants.FINISH_CODE.equals(element)) {
finish = RocksimFinishCode.fromCode(Integer.parseInt(content)).asOpenRocket();
}
if (RocksimCommonConstants.XB.equals(element)) {
location = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.LOCATION_MODE.equals(element)) {
position = RocksimLocationMode.fromCode(Integer.parseInt(content)).asOpenRocket();
}
if (RocksimCommonConstants.FIN_COUNT.equals(element)) {
finCount = Integer.parseInt(content);
}
if (RocksimCommonConstants.ROOT_CHORD.equals(element)) {
rootChord = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.TIP_CHORD.equals(element)) {
tipChord = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.SEMI_SPAN.equals(element)) {
semiSpan = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if ("MidChordLen".equals(element)) {
midChordLen = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.SWEEP_DISTANCE.equals(element)) {
sweepDistance = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.THICKNESS.equals(element)) {
thickness = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.TIP_SHAPE_CODE.equals(element)) {
tipShapeCode = Integer.parseInt(content);
}
if (RocksimCommonConstants.TAB_LENGTH.equals(element)) {
tabLength = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.TAB_DEPTH.equals(element)) {
tabDepth = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.TAB_OFFSET.equals(element)) {
taboffset = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.RADIAL_ANGLE.equals(element)) {
radialAngle = Double.parseDouble(content);
}
if (RocksimCommonConstants.SHAPE_CODE.equals(element)) {
shapeCode = Integer.parseInt(content);
}
if (RocksimCommonConstants.POINT_LIST.equals(element)) {
pointList = content;
}
if (RocksimCommonConstants.KNOWN_MASS.equals(element)) {
mass = Math.max(0d, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_MASS);
}
if (RocksimCommonConstants.DENSITY.equals(element)) {
density = Math.max(0d, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_BULK_DENSITY);
}
if (RocksimCommonConstants.KNOWN_CG.equals(element)) {
cg = Math.max(0d, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_MASS);
}
if (RocksimCommonConstants.USE_KNOWN_CG.equals(element)) {
override = "1".equals(content);
}
if (RocksimCommonConstants.CALC_MASS.equals(element)) {
calcMass = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_MASS;
}
if (RocksimCommonConstants.CALC_CG.equals(element)) {
calcCg = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
@Override
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
throws SAXException {
try {
if (RocksimCommonConstants.NAME.equals(element)) {
name = content;
}
if (RocksimCommonConstants.MATERIAL.equals(element)) {
materialName = content;
}
if (RocksimCommonConstants.FINISH_CODE.equals(element)) {
finish = RocksimFinishCode.fromCode(Integer.parseInt(content)).asOpenRocket();
}
if (RocksimCommonConstants.XB.equals(element)) {
location = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.LOCATION_MODE.equals(element)) {
position = RocksimLocationMode.fromCode(Integer.parseInt(content)).asOpenRocket();
}
if (RocksimCommonConstants.FIN_COUNT.equals(element)) {
finCount = Integer.parseInt(content);
}
if (RocksimCommonConstants.ROOT_CHORD.equals(element)) {
rootChord = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.TIP_CHORD.equals(element)) {
tipChord = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.SEMI_SPAN.equals(element)) {
semiSpan = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if ("MidChordLen".equals(element)) {
midChordLen = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.SWEEP_DISTANCE.equals(element)) {
sweepDistance = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.THICKNESS.equals(element)) {
thickness = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.TIP_SHAPE_CODE.equals(element)) {
tipShapeCode = Integer.parseInt(content);
}
if (RocksimCommonConstants.TAB_LENGTH.equals(element)) {
tabLength = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.TAB_DEPTH.equals(element)) {
tabDepth = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.TAB_OFFSET.equals(element)) {
taboffset = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.RADIAL_ANGLE.equals(element)) {
radialAngle = Double.parseDouble(content);
}
if (RocksimCommonConstants.SHAPE_CODE.equals(element)) {
shapeCode = Integer.parseInt(content);
}
if (RocksimCommonConstants.POINT_LIST.equals(element)) {
pointList = content;
}
if (RocksimCommonConstants.KNOWN_MASS.equals(element)) {
mass = Math.max(0d, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_MASS);
}
if (RocksimCommonConstants.DENSITY.equals(element)) {
density = Math.max(0d, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_BULK_DENSITY);
}
if (RocksimCommonConstants.KNOWN_CG.equals(element)) {
cg = Math.max(0d, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_MASS);
}
if (RocksimCommonConstants.USE_KNOWN_CG.equals(element)) {
override = "1".equals(content);
}
if (RocksimCommonConstants.CALC_MASS.equals(element)) {
calcMass = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_MASS;
}
if (RocksimCommonConstants.CALC_CG.equals(element)) {
calcCg = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
appearanceBuilder.processElement(element, content, warnings);
}
catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
appearanceBuilder.processElement(element, content, warnings);
} catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
@Override
public void endHandler (String element, HashMap<String, String> attributes,
String content, WarningSet warnings) throws SAXException {
//Create the fin set and correct for overrides and actual material densities
final FinSet finSet = asOpenRocket(warnings);
@Override
public void endHandler(String element, HashMap<String, String> attributes,
String content, WarningSet warnings) throws SAXException {
//Create the fin set and correct for overrides and actual material densities
final FinSet finSet = asOpenRocket(warnings);
finSet.setAppearance(appearanceBuilder.getAppearance());
finSet.setAppearance(appearanceBuilder.getAppearance());
if (component.isCompatible(finSet)) {
BaseHandler.setOverride(finSet, override, mass, cg);
if (!override && finSet.getCrossSection().equals(FinSet.CrossSection.AIRFOIL)) {
//Override mass anyway. This is done only for AIRFOIL because Rocksim does not compute different
//mass/cg for different cross sections, but OpenRocket does. This can lead to drastic differences
//in mass. To counteract that, the cross section value is retained but the mass/cg is overridden
//with the calculated values from Rocksim. This will best approximate the Rocksim design in OpenRocket.
BaseHandler.setOverride(finSet, true, calcMass, calcCg);
}
BaseHandler.updateComponentMaterial(finSet, materialName, Material.Type.BULK, density);
component.addChild(finSet);
}
else {
warnings.add(finSet.getComponentName() + " can not be attached to "
+ component.getComponentName() + ", ignoring component.");
}
}
if (component.isCompatible(finSet)) {
BaseHandler.setOverride(finSet, override, mass, cg);
if (!override && finSet.getCrossSection().equals(FinSet.CrossSection.AIRFOIL)) {
//Override mass anyway. This is done only for AIRFOIL because Rocksim does not compute different
//mass/cg for different cross sections, but OpenRocket does. This can lead to drastic differences
//in mass. To counteract that, the cross section value is retained but the mass/cg is overridden
//with the calculated values from Rocksim. This will best approximate the Rocksim design in OpenRocket.
BaseHandler.setOverride(finSet, true, calcMass, calcCg);
}
BaseHandler.updateComponentMaterial(finSet, materialName, Material.Type.BULK, density);
component.addChild(finSet);
}
else {
warnings.add(finSet.getComponentName() + " can not be attached to "
+ component.getComponentName() + ", ignoring component.");
}
}
/**
* Convert the parsed Rocksim data values in this object to an instance of OpenRocket's FinSet.
*
* @param warnings the warning set to convey incompatibilities to the user
*
* @return a FinSet instance
*/
public FinSet asOpenRocket (WarningSet warnings) {
FinSet result;
/**
* Convert the parsed Rocksim data values in this object to an instance of OpenRocket's FinSet.
*
* @param warnings the warning set to convey incompatibilities to the user
*
* @return a FinSet instance
*/
public FinSet asOpenRocket(WarningSet warnings) {
FinSet result;
if (shapeCode == 0) {
//Trapezoidal
result = new TrapezoidFinSet();
((TrapezoidFinSet) result).setFinShape(rootChord, tipChord, sweepDistance, semiSpan, thickness);
}
else if (shapeCode == 1) {
//Elliptical
result = new EllipticalFinSet();
((EllipticalFinSet) result).setHeight(semiSpan);
((EllipticalFinSet) result).setLength(rootChord);
}
else if (shapeCode == 2) {
if (shapeCode == 0) {
//Trapezoidal
result = new TrapezoidFinSet();
((TrapezoidFinSet) result).setFinShape(rootChord, tipChord, sweepDistance, semiSpan, thickness);
}
else if (shapeCode == 1) {
//Elliptical
result = new EllipticalFinSet();
((EllipticalFinSet) result).setHeight(semiSpan);
((EllipticalFinSet) result).setLength(rootChord);
}
else if (shapeCode == 2) {
result = new FreeformFinSet();
try {
((FreeformFinSet) result).setPoints(toCoordinates(pointList, warnings));
}
catch (IllegalFinPointException e) {
warnings.add("Illegal fin point set. " + e.getMessage() + " Ignoring.");
}
}
else {
return null;
}
result.setThickness(thickness);
result.setName(name);
result.setFinCount(finCount);
result.setFinish(finish);
//All TTW tabs in Rocksim are relative to the front of the fin.
result.setTabRelativePosition(FinSet.TabRelativePosition.FRONT);
result.setTabHeight(tabDepth);
result.setTabLength(tabLength);
result.setTabShift(taboffset);
result.setBaseRotation(radialAngle);
result.setCrossSection(convertTipShapeCode(tipShapeCode));
result.setRelativePosition(position);
PositionDependentHandler.setLocation(result, position, location);
return result;
result = new FreeformFinSet();
try {
((FreeformFinSet) result).setPoints(toCoordinates(pointList, warnings));
} catch (IllegalFinPointException e) {
warnings.add("Illegal fin point set. " + e.getMessage() + " Ignoring.");
}
}
else {
return null;
}
result.setThickness(thickness);
result.setName(name);
result.setFinCount(finCount);
result.setFinish(finish);
//All TTW tabs in Rocksim are relative to the front of the fin.
result.setTabRelativePosition(FinSet.TabRelativePosition.FRONT);
result.setTabHeight(tabDepth);
result.setTabLength(tabLength);
result.setTabShift(taboffset);
result.setBaseRotation(radialAngle);
result.setCrossSection(convertTipShapeCode(tipShapeCode));
result.setRelativePosition(position);
PositionDependentHandler.setLocation(result, position, location);
return result;
}
}
/**
* Convert a Rocksim string that represents fin plan points into an array of OpenRocket coordinates.
*
* @param pointList a comma and pipe delimited string of X,Y coordinates from Rocksim. This is of the format:
* <pre>x0,y0|x1,y1|x2,y2|... </pre>
* @param warnings the warning set to convey incompatibilities to the user
*
* @return an array of OpenRocket Coordinates
*/
private Coordinate[] toCoordinates (String pointList, WarningSet warnings) {
List<Coordinate> result = new ArrayList<Coordinate>();
if (pointList != null && pointList.length() > 0) {
String[] points = pointList.split("\\Q|\\E");
for (String point : points) {
String[] aPoint = point.split(",");
try {
if (aPoint.length > 1) {
Coordinate c = new Coordinate(
Double.parseDouble(aPoint[0]) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH,
Double.parseDouble(aPoint[1]) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
result.add(c);
}
else {
warnings.add("Invalid fin point pair.");
}
}
catch (NumberFormatException nfe) {
warnings.add("Fin point not in numeric format.");
}
}
if (!result.isEmpty()) {
//OpenRocket requires fin plan points be ordered from leading root chord to trailing root chord in the
//Coordinate array.
Coordinate last = result.get(result.size() - 1);
if (last.x == 0 && last.y == 0) {
Collections.reverse(result);
}
}
}
final Coordinate[] coords = new Coordinate[result.size()];
return result.toArray(coords);
}
/**
* Convert a Rocksim string that represents fin plan points into an array of OpenRocket coordinates.
*
* @param pointList a comma and pipe delimited string of X,Y coordinates from Rocksim. This is of the format:
* <pre>x0,y0|x1,y1|x2,y2|... </pre>
* @param warnings the warning set to convey incompatibilities to the user
*
* @return an array of OpenRocket Coordinates
*/
private Coordinate[] toCoordinates(String pointList, WarningSet warnings) {
List<Coordinate> result = new ArrayList<Coordinate>();
if (pointList != null && pointList.length() > 0) {
String[] points = pointList.split("\\Q|\\E");
for (String point : points) {
String[] aPoint = point.split(",");
try {
if (aPoint.length > 1) {
Coordinate c = new Coordinate(
Double.parseDouble(aPoint[0]) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH,
Double.parseDouble(aPoint[1]) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
result.add(c);
}
else {
warnings.add("Invalid fin point pair.");
}
} catch (NumberFormatException nfe) {
warnings.add("Fin point not in numeric format.");
}
}
if (!result.isEmpty()) {
//OpenRocket requires fin plan points be ordered from leading root chord to trailing root chord in the
//Coordinate array.
Coordinate last = result.get(result.size() - 1);
if (last.x == 0 && last.y == 0) {
Collections.reverse(result);
}
}
}
final Coordinate[] coords = new Coordinate[result.size()];
return result.toArray(coords);
}
/**
* Convert a Rocksim tip shape to an OpenRocket CrossSection.
*
* @param tipShape the tip shape code from Rocksim
*
* @return a CrossSection instance
*/
public static FinSet.CrossSection convertTipShapeCode (int tipShape) {
switch (tipShape) {
case 0:
return FinSet.CrossSection.SQUARE;
case 1:
return FinSet.CrossSection.ROUNDED;
case 2:
return FinSet.CrossSection.AIRFOIL;
default:
return FinSet.CrossSection.SQUARE;
}
}
/**
* Convert a Rocksim tip shape to an OpenRocket CrossSection.
*
* @param tipShape the tip shape code from Rocksim
*
* @return a CrossSection instance
*/
public static FinSet.CrossSection convertTipShapeCode(int tipShape) {
switch (tipShape) {
case 0:
return FinSet.CrossSection.SQUARE;
case 1:
return FinSet.CrossSection.ROUNDED;
case 2:
return FinSet.CrossSection.AIRFOIL;
default:
return FinSet.CrossSection.SQUARE;
}
}
public static int convertTipShapeCode (FinSet.CrossSection cs) {
if (FinSet.CrossSection.ROUNDED.equals(cs)) {
return 1;
}
if (FinSet.CrossSection.AIRFOIL.equals(cs)) {
return 2;
}
return 0;
}
public static int convertTipShapeCode(FinSet.CrossSection cs) {
if (FinSet.CrossSection.ROUNDED.equals(cs)) {
return 1;
}
if (FinSet.CrossSection.AIRFOIL.equals(cs)) {
return 2;
}
return 0;
}
}

View File

@ -6,7 +6,7 @@ package net.sf.openrocket.file.rocksim.importt;
import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;
@ -21,103 +21,102 @@ import org.xml.sax.SAXException;
*/
class InnerBodyTubeHandler extends PositionDependentHandler<InnerTube> {
/**
* The OpenRocket InnerTube instance.
*/
private final InnerTube bodyTube;
/**
* The OpenRocket InnerTube instance.
*/
private final InnerTube bodyTube;
/**
* Constructor.
*
* @param c the parent component
* @param warnings the warning set
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public InnerBodyTubeHandler(OpenRocketDocument document, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
super(document);
if (c == null) {
throw new IllegalArgumentException("The parent component of an inner tube may not be null.");
}
bodyTube = new InnerTube();
if (isCompatible(c, InnerTube.class, warnings)) {
c.addChild(bodyTube);
}
}
/**
* Constructor.
*
* @param c the parent component
* @param warnings the warning set
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public InnerBodyTubeHandler(DocumentLoadingContext context, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
super(context);
if (c == null) {
throw new IllegalArgumentException("The parent component of an inner tube may not be null.");
}
bodyTube = new InnerTube();
if (isCompatible(c, InnerTube.class, warnings)) {
c.addChild(bodyTube);
}
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
if (RocksimCommonConstants.ATTACHED_PARTS.equals(element)) {
return new AttachedPartsHandler(document, bodyTube);
}
return PlainTextHandler.INSTANCE;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
if (RocksimCommonConstants.ATTACHED_PARTS.equals(element)) {
return new AttachedPartsHandler(context, bodyTube);
}
return PlainTextHandler.INSTANCE;
}
@Override
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
throws SAXException {
super.closeElement(element, attributes, content, warnings);
@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)) {
bodyTube.setOuterRadius(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS);
}
if (RocksimCommonConstants.ID.equals(element)) {
final double r = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS;
bodyTube.setInnerRadius(r);
}
if (RocksimCommonConstants.LEN.equals(element)) {
bodyTube.setLength(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
}
if (RocksimCommonConstants.IS_MOTOR_MOUNT.equals(element)) {
bodyTube.setMotorMount("1".equals(content));
}
if (RocksimCommonConstants.ENGINE_OVERHANG.equals(element)) {
bodyTube.setMotorOverhang(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
}
if (RocksimCommonConstants.MATERIAL.equals(element)) {
setMaterialName(content);
}
if (RocksimCommonConstants.RADIAL_ANGLE.equals(element)) {
bodyTube.setRadialDirection(Double.parseDouble(content));
}
if (RocksimCommonConstants.RADIAL_LOC.equals(element)) {
bodyTube.setRadialPosition(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
}
}
catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
try {
if (RocksimCommonConstants.OD.equals(element)) {
bodyTube.setOuterRadius(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS);
}
if (RocksimCommonConstants.ID.equals(element)) {
final double r = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS;
bodyTube.setInnerRadius(r);
}
if (RocksimCommonConstants.LEN.equals(element)) {
bodyTube.setLength(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
}
if (RocksimCommonConstants.IS_MOTOR_MOUNT.equals(element)) {
bodyTube.setMotorMount("1".equals(content));
}
if (RocksimCommonConstants.ENGINE_OVERHANG.equals(element)) {
bodyTube.setMotorOverhang(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
}
if (RocksimCommonConstants.MATERIAL.equals(element)) {
setMaterialName(content);
}
if (RocksimCommonConstants.RADIAL_ANGLE.equals(element)) {
bodyTube.setRadialDirection(Double.parseDouble(content));
}
if (RocksimCommonConstants.RADIAL_LOC.equals(element)) {
bodyTube.setRadialPosition(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
}
} catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
/**
* Get the InnerTube component this handler is working upon.
*
* @return an InnerTube component
*/
@Override
public InnerTube getComponent() {
return bodyTube;
}
/**
* Get the InnerTube component this handler is working upon.
*
* @return an InnerTube component
*/
@Override
public InnerTube getComponent() {
return bodyTube;
}
/**
* Set the relative position onto the component. This cannot be done directly because setRelativePosition is not
* public in all components.
*
* @param position the OpenRocket position
*/
@Override
public void setRelativePosition(RocketComponent.Position position) {
bodyTube.setRelativePosition(position);
}
/**
* Set the relative position onto the component. This cannot be done directly because setRelativePosition is not
* public in all components.
*
* @param position the OpenRocket position
*/
@Override
public void setRelativePosition(RocketComponent.Position position) {
bodyTube.setRelativePosition(position);
}
/**
* Get the required type of material for this component.
*
* @return BULK
*/
@Override
public Material.Type getMaterialType() {
return Material.Type.BULK;
}
/**
* Get the required type of material for this component.
*
* @return BULK
*/
@Override
public Material.Type getMaterialType() {
return Material.Type.BULK;
}
}

View File

@ -6,7 +6,7 @@ package net.sf.openrocket.file.rocksim.importt;
import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
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;
@ -22,94 +22,92 @@ import org.xml.sax.SAXException;
*/
class LaunchLugHandler extends PositionDependentHandler<LaunchLug> {
/**
* The OpenRocket LaunchLug instance.
*/
private final LaunchLug lug;
/**
* The OpenRocket LaunchLug instance.
*/
private final LaunchLug lug;
/**
* Constructor.
*
* @param c the parent
* @param warnings the warning set
*
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public LaunchLugHandler(OpenRocketDocument document, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
super(document);
if (c == null) {
throw new IllegalArgumentException("The parent component of a launch lug may not be null.");
}
lug = new LaunchLug();
if (isCompatible(c, LaunchLug.class, warnings)) {
c.addChild(lug);
}
}
/**
* Constructor.
*
* @param c the parent
* @param warnings the warning set
*
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public LaunchLugHandler(DocumentLoadingContext context, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
super(context);
if (c == null) {
throw new IllegalArgumentException("The parent component of a launch lug may not be null.");
}
lug = new LaunchLug();
if (isCompatible(c, LaunchLug.class, warnings)) {
c.addChild(lug);
}
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
return PlainTextHandler.INSTANCE;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
return PlainTextHandler.INSTANCE;
}
@Override
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
throws SAXException {
super.closeElement(element, attributes, content, warnings);
@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)) {
lug.setOuterRadius(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
}
if (RocksimCommonConstants.ID.equals(element)) {
lug.setInnerRadius(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
}
if (RocksimCommonConstants.LEN.equals(element)) {
lug.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)) {
lug.setRadialDirection(Double.parseDouble(content));
}
if (RocksimCommonConstants.FINISH_CODE.equals(element)) {
lug.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.");
}
}
try {
if (RocksimCommonConstants.OD.equals(element)) {
lug.setOuterRadius(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
}
if (RocksimCommonConstants.ID.equals(element)) {
lug.setInnerRadius(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
}
if (RocksimCommonConstants.LEN.equals(element)) {
lug.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)) {
lug.setRadialDirection(Double.parseDouble(content));
}
if (RocksimCommonConstants.FINISH_CODE.equals(element)) {
lug.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.");
}
}
/**
* Get the LaunchLug component this handler is working upon.
*
* @return a LaunchLug component
*/
@Override
public LaunchLug getComponent() {
return lug;
}
/**
* Get the LaunchLug component this handler is working upon.
*
* @return a LaunchLug component
*/
@Override
public LaunchLug getComponent() {
return lug;
}
/**
* Set the relative position onto the component. This cannot be done directly because setRelativePosition is not
* public in all components.
*
* @param position the OpenRocket position
*/
@Override
public void setRelativePosition(RocketComponent.Position position) {
lug.setRelativePosition(position);
}
/**
* Set the relative position onto the component. This cannot be done directly because setRelativePosition is not
* public in all components.
*
* @param position the OpenRocket position
*/
@Override
public void setRelativePosition(RocketComponent.Position position) {
lug.setRelativePosition(position);
}
/**
* Get the required type of material for this component.
*
* @return BULK
*/
@Override
public Material.Type getMaterialType() {
return Material.Type.BULK;
}
/**
* Get the required type of material for this component.
*
* @return BULK
*/
@Override
public Material.Type getMaterialType() {
return Material.Type.BULK;
}
}

View File

@ -6,7 +6,7 @@ package net.sf.openrocket.file.rocksim.importt;
import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
import net.sf.openrocket.file.rocksim.RocksimDensityType;
import net.sf.openrocket.file.simplesax.ElementHandler;
@ -25,184 +25,183 @@ import org.xml.sax.SAXException;
*/
class MassObjectHandler extends PositionDependentHandler<MassObject> {
/**
* 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
* render in the OpenRocket UI with it's bounds mostly inside it's parent. The odd thing about it is that Rocksim
* does not expose the length of a mass object in the UI and actually treats mass objects as point objects - not 3
* or even 2 dimensional.
*/
public static final int MASS_LEN_FUDGE_FACTOR = 100;
/**
* 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
* render in the OpenRocket UI with it's bounds mostly inside it's parent. The odd thing about it is that Rocksim
* does not expose the length of a mass object in the UI and actually treats mass objects as point objects - not 3
* or even 2 dimensional.
*/
public static final int MASS_LEN_FUDGE_FACTOR = 100;
/**
* The OpenRocket MassComponent - counterpart to the RS MassObject.
*/
private final MassComponent mass;
/**
* The OpenRocket MassComponent - counterpart to the RS MassObject.
*/
private final MassComponent mass;
/**
* Reference to answer for getComponent().
*/
private MassObject current;
/**
* Reference to answer for getComponent().
*/
private MassObject current;
/**
* Parent.
*/
private RocketComponent parent;
/**
* Parent.
*/
private RocketComponent parent;
/**
* 0 == General, 1 == Shock Cord
*/
private int typeCode = 0;
/**
* 0 == General, 1 == Shock Cord
*/
private int typeCode = 0;
/**
* Constructor. l
*
* @param c the parent component
* @param warnings the warning set
*
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public MassObjectHandler(OpenRocketDocument document, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
super(document);
if (c == null) {
throw new IllegalArgumentException("The parent component of a mass component may not be null.");
}
mass = new MassComponent();
current = mass;
parent = c;
}
/**
* Constructor. l
*
* @param c the parent component
* @param warnings the warning set
*
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public MassObjectHandler(DocumentLoadingContext context, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
super(context);
if (c == null) {
throw new IllegalArgumentException("The parent component of a mass component may not be null.");
}
mass = new MassComponent();
current = mass;
parent = c;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
return PlainTextHandler.INSTANCE;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
return PlainTextHandler.INSTANCE;
}
@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.LEN.equals(element)) {
mass.setLength(Double.parseDouble(content) / (RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if (RocksimCommonConstants.KNOWN_MASS.equals(element)) {
mass.setComponentMass(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_MASS);
}
if (RocksimCommonConstants.KNOWN_CG.equals(element)) {
//Setting the CG of the Mass Object to 0 is important because of the different ways that Rocksim and
//OpenRocket treat mass objects. Rocksim treats them as points (even though the data file contains a
//length) and because Rocksim sets the CG of the mass object to really be relative to the front of
//the parent. But that value is already assumed in the position and position value for the component.
//Thus it needs to be set to 0 to say that the mass object's CG is at the point of the mass object.
super.setCG(0);
}
if (RocksimCommonConstants.TYPE_CODE.equals(element)) {
typeCode = Integer.parseInt(content);
}
if (RocksimCommonConstants.MATERIAL.equals(element)) {
setMaterialName(content);
}
}
catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
@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.LEN.equals(element)) {
mass.setLength(Double.parseDouble(content) / (RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if (RocksimCommonConstants.KNOWN_MASS.equals(element)) {
mass.setComponentMass(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_MASS);
}
if (RocksimCommonConstants.KNOWN_CG.equals(element)) {
//Setting the CG of the Mass Object to 0 is important because of the different ways that Rocksim and
//OpenRocket treat mass objects. Rocksim treats them as points (even though the data file contains a
//length) and because Rocksim sets the CG of the mass object to really be relative to the front of
//the parent. But that value is already assumed in the position and position value for the component.
//Thus it needs to be set to 0 to say that the mass object's CG is at the point of the mass object.
super.setCG(0);
}
if (RocksimCommonConstants.TYPE_CODE.equals(element)) {
typeCode = Integer.parseInt(content);
}
if (RocksimCommonConstants.MATERIAL.equals(element)) {
setMaterialName(content);
}
} catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
@Override
public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws
SAXException {
if (inferAsShockCord(typeCode, warnings)) { //Shock Cord
mapMassObjectAsShockCord(element, attributes, content, warnings);
}
else { // typeCode == 0 General Mass Object
if (isCompatible(parent, MassComponent.class, warnings)) {
parent.addChild(mass);
}
super.endHandler(element, attributes, content, warnings);
}
}
@Override
public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws
SAXException {
if (inferAsShockCord(typeCode, warnings)) { //Shock Cord
mapMassObjectAsShockCord(element, attributes, content, warnings);
}
else { // typeCode == 0 General Mass Object
if (isCompatible(parent, MassComponent.class, warnings)) {
parent.addChild(mass);
}
super.endHandler(element, attributes, content, warnings);
}
}
/**
* 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);
}
/**
* 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();
current = cord;
if (isCompatible(parent, ShockCord.class, warnings)) {
parent.addChild(cord);
}
super.endHandler(element, attributes, content, warnings);
cord.setName(mass.getName());
/**
* 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();
current = cord;
if (isCompatible(parent, ShockCord.class, warnings)) {
parent.addChild(cord);
}
super.endHandler(element, attributes, content, warnings);
cord.setName(mass.getName());
setOverride(cord, mass.isMassOverridden(), mass.getOverrideMass(), mass.getOverrideCGX());
setOverride(cord, mass.isMassOverridden(), mass.getOverrideMass(), mass.getOverrideCGX());
cord.setRadialDirection(mass.getRadialDirection());
cord.setRadialPosition(mass.getRadialPosition());
cord.setRadius(mass.getRadius());
cord.setRadialDirection(mass.getRadialDirection());
cord.setRadialPosition(mass.getRadialPosition());
cord.setRadius(mass.getRadius());
//Rocksim does not distinguish between total length of the cord and the packed length. Fudge the
//packed length and set the real length.
cord.setCordLength(mass.getLength());
cord.setLength(cord.getCordLength() / MASS_LEN_FUDGE_FACTOR);
if (parent instanceof Coaxial) {
Coaxial parentCoaxial = (Coaxial) parent;
cord.setRadius(parentCoaxial.getInnerRadius());
}
}
//Rocksim does not distinguish between total length of the cord and the packed length. Fudge the
//packed length and set the real length.
cord.setCordLength(mass.getLength());
cord.setLength(cord.getCordLength() / MASS_LEN_FUDGE_FACTOR);
if (parent instanceof Coaxial) {
Coaxial parentCoaxial = (Coaxial) parent;
cord.setRadius(parentCoaxial.getInnerRadius());
}
}
/**
* Get the component this handler is working upon. This changes depending upon the type of mass object.
*
* @return a component
*/
@Override
public MassObject getComponent() {
return current;
}
/**
* Get the component this handler is working upon. This changes depending upon the type of mass object.
*
* @return a component
*/
@Override
public MassObject getComponent() {
return current;
}
/**
* Set the relative position onto the component. This cannot be done directly because setRelativePosition is not
* public in all components.
*
* @param position the OpenRocket position
*/
public void setRelativePosition(RocketComponent.Position position) {
current.setRelativePosition(position);
}
/**
* Set the relative position onto the component. This cannot be done directly because setRelativePosition is not
* public in all components.
*
* @param position the OpenRocket position
*/
public void setRelativePosition(RocketComponent.Position position) {
current.setRelativePosition(position);
}
/**
* Get the required type of material for this component. Does not apply to MassComponents, but does apply to Shock
* Cords.
*
* @return LINE
*/
@Override
public Material.Type getMaterialType() {
return Material.Type.LINE;
}
/**
* Get the required type of material for this component. Does not apply to MassComponents, but does apply to Shock
* Cords.
*
* @return LINE
*/
@Override
public Material.Type getMaterialType() {
return Material.Type.LINE;
}
}

View File

@ -6,7 +6,7 @@ package net.sf.openrocket.file.rocksim.importt;
import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
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.rocksim.RocksimNoseConeCode;
@ -24,134 +24,133 @@ import org.xml.sax.SAXException;
*/
class NoseConeHandler extends BaseHandler<NoseCone> {
/**
* The OpenRocket NoseCone.
*/
private final NoseCone noseCone = new NoseCone();
/**
* The OpenRocket NoseCone.
*/
private final NoseCone noseCone = new NoseCone();
/**
* The wall thickness. Used for hollow nose cones.
*/
private double thickness = 0d;
/**
* The wall thickness. Used for hollow nose cones.
*/
private double thickness = 0d;
/**
* Constructor.
*
* @param c the parent component to the nosecone
* @param warnings the warning set
*
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public NoseConeHandler(OpenRocketDocument document, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
super(document);
if (c == null) {
throw new IllegalArgumentException("The parent component of a nose cone may not be null.");
}
if (isCompatible(c, NoseCone.class, warnings)) {
c.addChild(noseCone);
noseCone.setAftRadiusAutomatic(false);
}
}
/**
* Constructor.
*
* @param c the parent component to the nosecone
* @param warnings the warning set
*
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public NoseConeHandler(DocumentLoadingContext context, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
super(context);
if (c == null) {
throw new IllegalArgumentException("The parent component of a nose cone may not be null.");
}
if (isCompatible(c, NoseCone.class, warnings)) {
c.addChild(noseCone);
noseCone.setAftRadiusAutomatic(false);
}
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
//Nose cones in Rocksim may have attached parts - namely Mass Objects - as children.
if (RocksimCommonConstants.ATTACHED_PARTS.equals(element)) {
return new AttachedPartsHandler(document, noseCone);
}
return PlainTextHandler.INSTANCE;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
//Nose cones in Rocksim may have attached parts - namely Mass Objects - as children.
if (RocksimCommonConstants.ATTACHED_PARTS.equals(element)) {
return new AttachedPartsHandler(context, noseCone);
}
return PlainTextHandler.INSTANCE;
}
@Override
public void closeElement(String element, HashMap<String, String> attributes,
String content, WarningSet warnings) throws SAXException {
super.closeElement(element, attributes, content, warnings);
@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.SHAPE_CODE.equals(element)) {
noseCone.setType(RocksimNoseConeCode.fromCode(Integer.parseInt(content)).asOpenRocket());
}
if (RocksimCommonConstants.LEN.equals(element)) {
noseCone.setLength(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if (RocksimCommonConstants.BASE_DIA.equals(element)) {
noseCone.setAftRadius(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
}
if (RocksimCommonConstants.WALL_THICKNESS.equals(element)) {
thickness = Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
}
if (RocksimCommonConstants.SHOULDER_OD.equals(element)) {
noseCone.setAftShoulderRadius(Math.max(0, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
}
if (RocksimCommonConstants.SHOULDER_LEN.equals(element)) {
noseCone.setAftShoulderLength(Math.max(0, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if (RocksimCommonConstants.SHAPE_PARAMETER.equals(element)) {
//The Rocksim ShapeParameter only applies to certain shapes, although it is included
//in the design file for all nose cones. Applying it when it should not be causes oddities so
//a check is made for the allowable shapes.
if (Transition.Shape.POWER.equals(noseCone.getType()) ||
Transition.Shape.HAACK.equals(noseCone.getType()) ||
Transition.Shape.PARABOLIC.equals(noseCone.getType())) {
noseCone.setShapeParameter(Double.parseDouble(content));
}
}
if (RocksimCommonConstants.CONSTRUCTION_TYPE.equals(element)) {
int typeCode = Integer.parseInt(content);
if (typeCode == 0) {
//SOLID
noseCone.setFilled(true);
}
else if (typeCode == 1) {
//HOLLOW
noseCone.setFilled(false);
}
}
if (RocksimCommonConstants.FINISH_CODE.equals(element)) {
noseCone.setFinish(RocksimFinishCode.fromCode(Integer.parseInt(content)).asOpenRocket());
}
if (RocksimCommonConstants.MATERIAL.equals(element)) {
setMaterialName(content);
}
}
catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
try {
if (RocksimCommonConstants.SHAPE_CODE.equals(element)) {
noseCone.setType(RocksimNoseConeCode.fromCode(Integer.parseInt(content)).asOpenRocket());
}
if (RocksimCommonConstants.LEN.equals(element)) {
noseCone.setLength(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if (RocksimCommonConstants.BASE_DIA.equals(element)) {
noseCone.setAftRadius(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
}
if (RocksimCommonConstants.WALL_THICKNESS.equals(element)) {
thickness = Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
}
if (RocksimCommonConstants.SHOULDER_OD.equals(element)) {
noseCone.setAftShoulderRadius(Math.max(0, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
}
if (RocksimCommonConstants.SHOULDER_LEN.equals(element)) {
noseCone.setAftShoulderLength(Math.max(0, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if (RocksimCommonConstants.SHAPE_PARAMETER.equals(element)) {
//The Rocksim ShapeParameter only applies to certain shapes, although it is included
//in the design file for all nose cones. Applying it when it should not be causes oddities so
//a check is made for the allowable shapes.
if (Transition.Shape.POWER.equals(noseCone.getType()) ||
Transition.Shape.HAACK.equals(noseCone.getType()) ||
Transition.Shape.PARABOLIC.equals(noseCone.getType())) {
noseCone.setShapeParameter(Double.parseDouble(content));
}
}
if (RocksimCommonConstants.CONSTRUCTION_TYPE.equals(element)) {
int typeCode = Integer.parseInt(content);
if (typeCode == 0) {
//SOLID
noseCone.setFilled(true);
}
else if (typeCode == 1) {
//HOLLOW
noseCone.setFilled(false);
}
}
if (RocksimCommonConstants.FINISH_CODE.equals(element)) {
noseCone.setFinish(RocksimFinishCode.fromCode(Integer.parseInt(content)).asOpenRocket());
}
if (RocksimCommonConstants.MATERIAL.equals(element)) {
setMaterialName(content);
}
} catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
@Override
public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
throws SAXException {
super.endHandler(element, attributes, content, warnings);
@Override
public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
throws SAXException {
super.endHandler(element, attributes, content, warnings);
if (noseCone.isFilled()) {
noseCone.setAftShoulderThickness(noseCone.getAftShoulderRadius());
}
else {
noseCone.setThickness(thickness);
noseCone.setAftShoulderThickness(thickness);
}
}
if (noseCone.isFilled()) {
noseCone.setAftShoulderThickness(noseCone.getAftShoulderRadius());
}
else {
noseCone.setThickness(thickness);
noseCone.setAftShoulderThickness(thickness);
}
}
/**
* Get the nose cone component this handler is working upon.
*
* @return a nose cone component
*/
@Override
public NoseCone getComponent() {
return noseCone;
}
/**
* Get the nose cone component this handler is working upon.
*
* @return a nose cone component
*/
@Override
public NoseCone getComponent() {
return noseCone;
}
/**
* Get the required type of material for this component.
*
* @return BULK
*/
public Material.Type getMaterialType() {
return Material.Type.BULK;
}
/**
* Get the required type of material for this component.
*
* @return BULK
*/
public Material.Type getMaterialType() {
return Material.Type.BULK;
}
}

View File

@ -6,7 +6,7 @@ package net.sf.openrocket.file.rocksim.importt;
import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;
@ -22,103 +22,101 @@ import org.xml.sax.SAXException;
* A SAX handler for Rocksim's Parachute XML type.
*/
class ParachuteHandler extends RecoveryDeviceHandler<Parachute> {
/**
* The OpenRocket Parachute instance
*/
private final Parachute chute;
/**
* The shroud line density.
*/
private double shroudLineDensity = 0.0d;
/**
* The OpenRocket Parachute instance
*/
private final Parachute chute;
/**
* The shroud line density.
*/
private double shroudLineDensity = 0.0d;
/**
* Constructor.
*
* @param c the parent component
* @param warnings the warning set
*
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public ParachuteHandler(OpenRocketDocument document, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
super(document);
if (c == null) {
throw new IllegalArgumentException("The parent of a parachute may not be null.");
}
chute = new Parachute();
if (isCompatible(c, Parachute.class, warnings)) {
c.addChild(chute);
}
}
/**
* Constructor.
*
* @param c the parent component
* @param warnings the warning set
*
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public ParachuteHandler(DocumentLoadingContext context, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
super(context);
if (c == null) {
throw new IllegalArgumentException("The parent of a parachute may not be null.");
}
chute = new Parachute();
if (isCompatible(c, Parachute.class, warnings)) {
c.addChild(chute);
}
}
/**
* {@inheritDoc}
*/
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
return PlainTextHandler.INSTANCE;
}
/**
* {@inheritDoc}
*/
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
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.DIAMETER.equals(element)) {
chute.setDiameter(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
/* Rocksim doesn't have a packed parachute radius, so we approximate it. */
double packed;
RocketComponent parent = chute.getParent();
if (parent instanceof BodyTube) {
packed = ((BodyTube) parent).getOuterRadius() * 0.9;
}
else if (parent instanceof InnerTube) {
packed = ((InnerTube) parent).getInnerRadius() * 0.9;
}
else {
packed = chute.getDiameter() * 0.025;
}
chute.setRadius(packed);
}
if (RocksimCommonConstants.SHROUD_LINE_COUNT.equals(element)) {
chute.setLineCount(Math.max(0, Integer.parseInt(content)));
}
if (RocksimCommonConstants.SHROUD_LINE_LEN.equals(element)) {
chute.setLineLength(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if (RocksimCommonConstants.SPILL_HOLE_DIA.equals(element)) {
//Not supported in OpenRocket
double spillHoleRadius = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS;
warnings.add("Parachute spill holes are not supported. Ignoring.");
}
if (RocksimCommonConstants.SHROUD_LINE_MASS_PER_MM.equals(element)) {
shroudLineDensity = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LINE_DENSITY;
}
if (RocksimCommonConstants.SHROUD_LINE_MATERIAL.equals(element)) {
chute.setLineMaterial(createCustomMaterial(Material.Type.LINE, content, shroudLineDensity));
}
if (RocksimCommonConstants.DRAG_COEFFICIENT.equals(element)) {
chute.setCD(Double.parseDouble(content));
}
if (RocksimCommonConstants.MATERIAL.equals(element)) {
setMaterialName(content);
}
}
catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
/**
* {@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.DIAMETER.equals(element)) {
chute.setDiameter(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
/* Rocksim doesn't have a packed parachute radius, so we approximate it. */
double packed;
RocketComponent parent = chute.getParent();
if (parent instanceof BodyTube) {
packed = ((BodyTube) parent).getOuterRadius() * 0.9;
}
else if (parent instanceof InnerTube) {
packed = ((InnerTube) parent).getInnerRadius() * 0.9;
}
else {
packed = chute.getDiameter() * 0.025;
}
chute.setRadius(packed);
}
if (RocksimCommonConstants.SHROUD_LINE_COUNT.equals(element)) {
chute.setLineCount(Math.max(0, Integer.parseInt(content)));
}
if (RocksimCommonConstants.SHROUD_LINE_LEN.equals(element)) {
chute.setLineLength(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if (RocksimCommonConstants.SPILL_HOLE_DIA.equals(element)) {
//Not supported in OpenRocket
double spillHoleRadius = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS;
warnings.add("Parachute spill holes are not supported. Ignoring.");
}
if (RocksimCommonConstants.SHROUD_LINE_MASS_PER_MM.equals(element)) {
shroudLineDensity = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LINE_DENSITY;
}
if (RocksimCommonConstants.SHROUD_LINE_MATERIAL.equals(element)) {
chute.setLineMaterial(createCustomMaterial(Material.Type.LINE, content, shroudLineDensity));
}
if (RocksimCommonConstants.DRAG_COEFFICIENT.equals(element)) {
chute.setCD(Double.parseDouble(content));
}
if (RocksimCommonConstants.MATERIAL.equals(element)) {
setMaterialName(content);
}
} catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
/**
* Get the component this handler is working upon.
*
* @return a component
*/
public Parachute getComponent() {
return chute;
}
/**
* Get the component this handler is working upon.
*
* @return a component
*/
public Parachute getComponent() {
return chute;
}
}

View File

@ -6,7 +6,7 @@ package net.sf.openrocket.file.rocksim.importt;
import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
import net.sf.openrocket.file.rocksim.RocksimLocationMode;
import net.sf.openrocket.rocketcomponent.RocketComponent;
@ -21,72 +21,73 @@ import org.xml.sax.SAXException;
*/
public abstract class PositionDependentHandler<C extends RocketComponent> extends BaseHandler<C> {
/** Temporary position value. */
private Double positionValue = 0d;
/** Temporary position value. */
private Double positionValue = 0d;
/** Temporary position. */
private RocketComponent.Position position = RocketComponent.Position.TOP;
/** Temporary position. */
private RocketComponent.Position position = RocketComponent.Position.TOP;
public PositionDependentHandler( OpenRocketDocument document ) {
super(document);
}
/**
* {@inheritDoc}
*/
@Override
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
throws SAXException {
super.closeElement(element, attributes, content, warnings);
if (RocksimCommonConstants.XB.equals(element)) {
positionValue = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.LOCATION_MODE.equals(element)) {
position = RocksimLocationMode.fromCode(Integer.parseInt(
content)).asOpenRocket();
}
}
public PositionDependentHandler(DocumentLoadingContext context) {
super(context);
}
/**
* This method sets the position information onto the component. Rocksim splits the location/position
* information into two disparate data elements. Both pieces of data are necessary to map into OpenRocket's
* position model.
*
* @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
*/
@Override
public void endHandler(String element, HashMap<String, String> attributes,
String content, WarningSet warnings) throws SAXException {
super.endHandler(element, attributes, content, warnings);
setRelativePosition(position);
setLocation(getComponent(), position, positionValue);
}
/**
* {@inheritDoc}
*/
@Override
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
throws SAXException {
super.closeElement(element, attributes, content, warnings);
if (RocksimCommonConstants.XB.equals(element)) {
positionValue = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.LOCATION_MODE.equals(element)) {
position = RocksimLocationMode.fromCode(Integer.parseInt(
content)).asOpenRocket();
}
}
/**
* Set the relative position onto the component. This cannot be done directly because setRelativePosition is not
* public in all components.
*
* @param position the OpenRocket position
*/
protected abstract void setRelativePosition(RocketComponent.Position position);
/**
* This method sets the position information onto the component. Rocksim splits the location/position
* information into two disparate data elements. Both pieces of data are necessary to map into OpenRocket's
* position model.
*
* @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
*/
@Override
public void endHandler(String element, HashMap<String, String> attributes,
String content, WarningSet warnings) throws SAXException {
super.endHandler(element, attributes, content, warnings);
setRelativePosition(position);
setLocation(getComponent(), position, positionValue);
}
/**
* Set the position of a component.
*
* @param component the component
* @param position the relative position
* @param location the actual position value
*/
public static void setLocation(RocketComponent component, RocketComponent.Position position, double location) {
if (position.equals(RocketComponent.Position.BOTTOM)) {
component.setPositionValue(-1d * location);
}
else {
component.setPositionValue(location);
}
}
/**
* Set the relative position onto the component. This cannot be done directly because setRelativePosition is not
* public in all components.
*
* @param position the OpenRocket position
*/
protected abstract void setRelativePosition(RocketComponent.Position position);
/**
* Set the position of a component.
*
* @param component the component
* @param position the relative position
* @param location the actual position value
*/
public static void setLocation(RocketComponent component, RocketComponent.Position position, double location) {
if (position.equals(RocketComponent.Position.BOTTOM)) {
component.setPositionValue(-1d * location);
}
else {
component.setPositionValue(location);
}
}
}

View File

@ -6,7 +6,7 @@ package net.sf.openrocket.file.rocksim.importt;
import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
import net.sf.openrocket.file.rocksim.RocksimDensityType;
import net.sf.openrocket.material.Material;
@ -24,99 +24,98 @@ import org.xml.sax.SAXException;
*/
public abstract class RecoveryDeviceHandler<C extends RecoveryDevice> extends PositionDependentHandler<C> {
/**
* The thickness. Not used by every component, and some component handlers may parse it for their own purposes.
*/
private double thickness = 0d;
/**
* The Rocksim calculated mass. Used only when not overridden and when Rocksim says density == 0 (Rocksim bug).
*/
private Double calcMass = 0d;
/**
* The thickness. Not used by every component, and some component handlers may parse it for their own purposes.
*/
private double thickness = 0d;
/**
* The Rocksim calculated mass. Used only when not overridden and when Rocksim says density == 0 (Rocksim bug).
*/
private Double calcMass = 0d;
public RecoveryDeviceHandler( OpenRocketDocument document ) {
super(document);
}
public RecoveryDeviceHandler(DocumentLoadingContext context) {
super(context);
}
/**
* {@inheritDoc}
*/
@Override
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
throws SAXException {
super.closeElement(element, attributes, content, warnings);
/**
* {@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.THICKNESS.equals(element)) {
thickness = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.CALC_MASS.equals(element)) {
calcMass = Math.max(0d, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_MASS);
}
}
catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
try {
if (RocksimCommonConstants.THICKNESS.equals(element)) {
thickness = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
}
if (RocksimCommonConstants.CALC_MASS.equals(element)) {
calcMass = Math.max(0d, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_MASS);
}
} catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
/**
* 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.
*
* @param type the rocksim density
* @param rawDensity the density as specified in the Rocksim design file
* @return a value in OpenRocket SURFACE density units
*/
protected double computeDensity(RocksimDensityType type, double rawDensity) {
/**
* 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.
*
* @param type the rocksim density
* @param rawDensity the density as specified in the Rocksim design file
* @return a value in OpenRocket SURFACE density units
*/
protected double computeDensity(RocksimDensityType type, double rawDensity) {
double result;
double result;
if (rawDensity > 0d) {
//ROCKSIM_SURFACE is a square area density; compute normally
//ROCKSIM_LINE is a single length dimension (kg/m) but Rocksim ignores thickness for this type and treats
//it like a SURFACE.
if (RocksimDensityType.ROCKSIM_SURFACE.equals(type) || RocksimDensityType.ROCKSIM_LINE.equals(type)) {
result = rawDensity / RocksimDensityType.ROCKSIM_SURFACE.asOpenRocket();
}
//ROCKSIM_BULK is a cubic area density; multiple by thickness to make per square area; the result, when
//multiplied by the area will then equal Rocksim's computed mass.
else {
result = (rawDensity / type.asOpenRocket()) * thickness;
}
}
else {
result = calcMass / getComponent().getArea();
//A Rocksim bug on streamers/parachutes results in a 0 density at times. When that is detected, try
//to compute an approximate density from Rocksim's computed mass.
if (RocksimDensityType.ROCKSIM_BULK.equals(type)) {
//ROCKSIM_BULK is a cubic area density; multiple by thickness to make per square area
result *= thickness;
}
}
return result;
}
if (rawDensity > 0d) {
//ROCKSIM_SURFACE is a square area density; compute normally
//ROCKSIM_LINE is a single length dimension (kg/m) but Rocksim ignores thickness for this type and treats
//it like a SURFACE.
if (RocksimDensityType.ROCKSIM_SURFACE.equals(type) || RocksimDensityType.ROCKSIM_LINE.equals(type)) {
result = rawDensity / RocksimDensityType.ROCKSIM_SURFACE.asOpenRocket();
}
//ROCKSIM_BULK is a cubic area density; multiple by thickness to make per square area; the result, when
//multiplied by the area will then equal Rocksim's computed mass.
else {
result = (rawDensity / type.asOpenRocket()) * thickness;
}
}
else {
result = calcMass / getComponent().getArea();
//A Rocksim bug on streamers/parachutes results in a 0 density at times. When that is detected, try
//to compute an approximate density from Rocksim's computed mass.
if (RocksimDensityType.ROCKSIM_BULK.equals(type)) {
//ROCKSIM_BULK is a cubic area density; multiple by thickness to make per square area
result *= thickness;
}
}
return result;
}
/**
* Set the relative position onto the component. This cannot be done directly because setRelativePosition is not
* public in all components.
*
* @param position the OpenRocket position
*/
@Override
public void setRelativePosition(RocketComponent.Position position) {
getComponent().setRelativePosition(position);
}
/**
* Set the relative position onto the component. This cannot be done directly because setRelativePosition is not
* public in all components.
*
* @param position the OpenRocket position
*/
@Override
public void setRelativePosition(RocketComponent.Position position) {
getComponent().setRelativePosition(position);
}
/**
* Get the required type of material for this component. This is the OpenRocket type, which does NOT always
* correspond to Rocksim. Some streamer material is defined as BULK in the Rocksim file. In those cases
* it is adjusted in this handler.
*
* @return SURFACE
*/
@Override
public Material.Type getMaterialType() {
return Material.Type.SURFACE;
}
/**
* Get the required type of material for this component. This is the OpenRocket type, which does NOT always
* correspond to Rocksim. Some streamer material is defined as BULK in the Rocksim file. In those cases
* it is adjusted in this handler.
*
* @return SURFACE
*/
@Override
public Material.Type getMaterialType() {
return Material.Type.SURFACE;
}
}

View File

@ -6,7 +6,7 @@ package net.sf.openrocket.file.rocksim.importt;
import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;
@ -25,213 +25,213 @@ import org.xml.sax.SAXException;
*/
class RingHandler extends PositionDependentHandler<CenteringRing> {
/**
* The OpenRocket Ring.
*/
private final CenteringRing ring = new CenteringRing();
/**
* The OpenRocket Ring.
*/
private final CenteringRing ring = new CenteringRing();
/**
* The parent component.
*/
private final RocketComponent parent;
/**
* The parent component.
*/
private final RocketComponent parent;
/**
* The parsed Rocksim UsageCode.
*/
private int usageCode = 0;
/**
* The parsed Rocksim UsageCode.
*/
private int usageCode = 0;
/**
* Constructor.
*
* @param theParent the parent component
* @param warnings the warning set
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public RingHandler(OpenRocketDocument document, RocketComponent theParent, WarningSet warnings) throws IllegalArgumentException {
super(document);
if (theParent == null) {
throw new IllegalArgumentException("The parent of a ring may not be null.");
}
parent = theParent;
}
/**
* Constructor.
*
* @param theParent the parent component
* @param warnings the warning set
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public RingHandler(DocumentLoadingContext context, RocketComponent theParent, WarningSet warnings) throws IllegalArgumentException {
super(context);
if (theParent == null) {
throw new IllegalArgumentException("The parent of a ring may not be null.");
}
parent = theParent;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
return PlainTextHandler.INSTANCE;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
return PlainTextHandler.INSTANCE;
}
@Override
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
throws SAXException {
super.closeElement(element, attributes, content, warnings);
@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)) {
ring.setOuterRadius(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS);
}
if (RocksimCommonConstants.ID.equals(element)) {
ring.setInnerRadius(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS);
}
if (RocksimCommonConstants.LEN.equals(element)) {
ring.setLength(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
}
if (RocksimCommonConstants.MATERIAL.equals(element)) {
setMaterialName(content);
}
if (RocksimCommonConstants.USAGE_CODE.equals(element)) {
usageCode = Integer.parseInt(content);
}
} catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
try {
if (RocksimCommonConstants.OD.equals(element)) {
ring.setOuterRadius(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS);
}
if (RocksimCommonConstants.ID.equals(element)) {
ring.setInnerRadius(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS);
}
if (RocksimCommonConstants.LEN.equals(element)) {
ring.setLength(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
}
if (RocksimCommonConstants.MATERIAL.equals(element)) {
setMaterialName(content);
}
if (RocksimCommonConstants.USAGE_CODE.equals(element)) {
usageCode = Integer.parseInt(content);
}
} catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
/**
* Get the ring component this handler is working upon.
*
* @return a component
*/
@Override
public CenteringRing getComponent() {
return ring;
}
/**
* Get the ring component this handler is working upon.
*
* @return a component
*/
@Override
public CenteringRing getComponent() {
return ring;
}
/**
* This method adds the CenteringRing as a child of the parent rocket component.
*
* @param warnings the warning set
*/
public void asCenteringRing(WarningSet warnings) {
/**
* This method adds the CenteringRing as a child of the parent rocket component.
*
* @param warnings the warning set
*/
public void asCenteringRing(WarningSet warnings) {
if (isCompatible(parent, CenteringRing.class, warnings)) {
parent.addChild(ring);
}
}
if (isCompatible(parent, CenteringRing.class, warnings)) {
parent.addChild(ring);
}
}
/**
* Convert the parsed Rocksim data values in this object to an instance of OpenRocket's Bulkhead.
* <p/>
* Side Effect Warning: This method adds the resulting Bulkhead as a child of the parent rocket component!
*
* @param warnings the warning set
*/
public void asBulkhead(WarningSet warnings) {
/**
* Convert the parsed Rocksim data values in this object to an instance of OpenRocket's Bulkhead.
* <p/>
* Side Effect Warning: This method adds the resulting Bulkhead as a child of the parent rocket component!
*
* @param warnings the warning set
*/
public void asBulkhead(WarningSet warnings) {
Bulkhead result = new Bulkhead();
Bulkhead result = new Bulkhead();
copyValues(result);
copyValues(result);
if (isCompatible(parent, Bulkhead.class, warnings)) {
parent.addChild(result);
}
}
if (isCompatible(parent, Bulkhead.class, warnings)) {
parent.addChild(result);
}
}
/**
* Convert the parsed Rocksim data values in this object to an instance of OpenRocket's TubeCoupler.
* <p/>
* Side Effect Warning: This method adds the resulting TubeCoupler as a child of the parent rocket component!
*
* @param warnings the warning set
*/
public void asTubeCoupler(WarningSet warnings) {
/**
* Convert the parsed Rocksim data values in this object to an instance of OpenRocket's TubeCoupler.
* <p/>
* Side Effect Warning: This method adds the resulting TubeCoupler as a child of the parent rocket component!
*
* @param warnings the warning set
*/
public void asTubeCoupler(WarningSet warnings) {
TubeCoupler result = new TubeCoupler();
TubeCoupler result = new TubeCoupler();
copyValues(result);
copyValues(result);
if (isCompatible(parent, TubeCoupler.class, warnings)) {
parent.addChild(result);
}
}
if (isCompatible(parent, TubeCoupler.class, warnings)) {
parent.addChild(result);
}
}
/**
* Convert the parsed Rocksim data values in this object to an instance of OpenRocket's Engine Block.
* <p/>
* Side Effect Warning: This method adds the resulting EngineBlock as a child of the parent rocket component!
*
* @param warnings the warning set
*/
public void asEngineBlock(WarningSet warnings) {
/**
* Convert the parsed Rocksim data values in this object to an instance of OpenRocket's Engine Block.
* <p/>
* Side Effect Warning: This method adds the resulting EngineBlock as a child of the parent rocket component!
*
* @param warnings the warning set
*/
public void asEngineBlock(WarningSet warnings) {
EngineBlock result = new EngineBlock();
EngineBlock result = new EngineBlock();
copyValues(result);
copyValues(result);
if (isCompatible(parent, EngineBlock.class, warnings)) {
parent.addChild(result);
}
}
if (isCompatible(parent, EngineBlock.class, warnings)) {
parent.addChild(result);
}
}
/**
* Copy values from the base ring to the specific component.
*
* @param result the target to which ring values will be copied
*/
private void copyValues(RingComponent result) {
result.setOuterRadius(ring.getOuterRadius());
result.setInnerRadius(ring.getInnerRadius());
result.setLength(ring.getLength());
result.setName(ring.getName());
setOverride(result, ring.isOverrideSubcomponentsEnabled(), ring.getOverrideMass(), ring.getOverrideCGX());
result.setRelativePosition(ring.getRelativePosition());
result.setPositionValue(ring.getPositionValue());
result.setMaterial(ring.getMaterial());
result.setThickness(result.getThickness());
}
/**
* Copy values from the base ring to the specific component.
*
* @param result the target to which ring values will be copied
*/
private void copyValues(RingComponent result) {
result.setOuterRadius(ring.getOuterRadius());
result.setInnerRadius(ring.getInnerRadius());
result.setLength(ring.getLength());
result.setName(ring.getName());
setOverride(result, ring.isOverrideSubcomponentsEnabled(), ring.getOverrideMass(), ring.getOverrideCGX());
result.setRelativePosition(ring.getRelativePosition());
result.setPositionValue(ring.getPositionValue());
result.setMaterial(ring.getMaterial());
result.setThickness(result.getThickness());
}
/**
* Set the relative position onto the component. This cannot be done directly because setRelativePosition is not
* public in all components.
*
* @param position the OpenRocket position
*/
@Override
public void setRelativePosition(RocketComponent.Position position) {
ring.setRelativePosition(position);
}
/**
* Set the relative position onto the component. This cannot be done directly because setRelativePosition is not
* public in all components.
*
* @param position the OpenRocket position
*/
@Override
public void setRelativePosition(RocketComponent.Position position) {
ring.setRelativePosition(position);
}
@Override
public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
super.endHandler(element, attributes, content, warnings);
@Override
public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
super.endHandler(element, attributes, content, warnings);
// The <Ring> XML element in Rocksim design file is used for many types of components, unfortunately.
// Additional subelements are used to indicate the type of the rocket component. When parsing using SAX
// this poses a problem because we can't "look ahead" to see what type is being represented at the start
// of parsing - something that would be nice to do so that we can instantiate the correct OR component
// at the start, then just call setters for the appropriate data.
// The <Ring> XML element in Rocksim design file is used for many types of components, unfortunately.
// Additional subelements are used to indicate the type of the rocket component. When parsing using SAX
// this poses a problem because we can't "look ahead" to see what type is being represented at the start
// of parsing - something that would be nice to do so that we can instantiate the correct OR component
// at the start, then just call setters for the appropriate data.
// To overcome that, a CenteringRing is instantiated at the start of parsing, it's mutators are called,
// and then at the end (this method) converts the CenteringRing to a more appropriate type. CenteringRing
// is generic enough to support the representation of all similar types without loss of data.
// To overcome that, a CenteringRing is instantiated at the start of parsing, it's mutators are called,
// and then at the end (this method) converts the CenteringRing to a more appropriate type. CenteringRing
// is generic enough to support the representation of all similar types without loss of data.
//UsageCode
// 0 == Centering Ring
// 1 == Bulkhead
// 2 == Engine Block
// 3 == Sleeve
// 4 == Tube Coupler
//UsageCode
// 0 == Centering Ring
// 1 == Bulkhead
// 2 == Engine Block
// 3 == Sleeve
// 4 == Tube Coupler
if (usageCode == 1) {
//Bulkhead
asBulkhead(warnings);
} else if (usageCode == 2) {
asEngineBlock(warnings);
} else if (usageCode == 4) {
//TubeCoupler
asTubeCoupler(warnings);
} else {
//Default
asCenteringRing(warnings);
}
}
if (usageCode == 1) {
//Bulkhead
asBulkhead(warnings);
} else if (usageCode == 2) {
asEngineBlock(warnings);
} else if (usageCode == 4) {
//TubeCoupler
asTubeCoupler(warnings);
} else {
//Default
asCenteringRing(warnings);
}
}
/**
* Get the required type of material for this component.
*
* @return BULK
*/
@Override
public Material.Type getMaterialType() {
return Material.Type.BULK;
}
/**
* Get the required type of material for this component.
*
* @return BULK
*/
@Override
public Material.Type getMaterialType() {
return Material.Type.BULK;
}
}

View File

@ -7,7 +7,8 @@ import java.net.MalformedURLException;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.appearance.AppearanceBuilder;
import net.sf.openrocket.appearance.Decal.EdgeMode;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.Attachment;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
import net.sf.openrocket.util.Color;
@ -16,10 +17,10 @@ public class RockSimAppearanceBuilder extends AppearanceBuilder {
boolean preventSeam = false;
boolean repeat = false;
private final OpenRocketDocument document;
private final DocumentLoadingContext context;
public RockSimAppearanceBuilder(OpenRocketDocument document) {
this.document = document;
public RockSimAppearanceBuilder(DocumentLoadingContext context) {
this.context = context;
}
public void processElement(String element, String content, WarningSet warnings) {
@ -68,7 +69,8 @@ public class RockSimAppearanceBuilder extends AppearanceBuilder {
//Find out how to get path of current rocksim file
//so I can look in it's directory
}
setImage(document.getDecalRegistry().getAttachment(value));
Attachment a = context.getAttachmentFactory().getAttachment(name);
setImage(context.getOpenRocketDocument().getDecalImage(a));
}
} else if ("repeat".equals(name)) {
repeat = "1".equals(value);

View File

@ -9,6 +9,7 @@ import java.util.HashMap;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
@ -33,11 +34,11 @@ public class RocksimHandler extends AbstractElementHandler {
*/
private RocksimContentHandler handler = null;
private final OpenRocketDocument document;
private final DocumentLoadingContext context;
public RocksimHandler(OpenRocketDocument document) {
public RocksimHandler(DocumentLoadingContext context) {
super();
this.document = document;
this.context = context;
}
/**
@ -47,7 +48,7 @@ public class RocksimHandler extends AbstractElementHandler {
* @return the document read, or null.
*/
public OpenRocketDocument getDocument() {
return document;
return context.getOpenRocketDocument();
}
@Override
@ -67,7 +68,7 @@ public class RocksimHandler extends AbstractElementHandler {
return null;
}
handler = new RocksimContentHandler(document);
handler = new RocksimContentHandler(context);
return handler;
}
@ -78,9 +79,9 @@ public class RocksimHandler extends AbstractElementHandler {
*/
class RocksimContentHandler extends AbstractElementHandler {
/**
* The OpenRocketDocument that is the container for the rocket.
* The DocumentLoadingContext
*/
private final OpenRocketDocument doc;
private final DocumentLoadingContext context;
/**
* The top-level component, from which all child components are added.
@ -92,10 +93,10 @@ class RocksimContentHandler extends AbstractElementHandler {
*/
private String version;
public RocksimContentHandler(OpenRocketDocument doc) {
public RocksimContentHandler(DocumentLoadingContext context) {
super();
this.doc = doc;
this.rocket = doc.getRocket();
this.context = context;
this.rocket = context.getOpenRocketDocument().getRocket();
}
/**
@ -104,7 +105,7 @@ class RocksimContentHandler extends AbstractElementHandler {
* @return the instantiated OpenRocketDocument
*/
public OpenRocketDocument getDocument() {
return doc;
return context.getOpenRocketDocument();
}
@Override
@ -119,7 +120,7 @@ class RocksimContentHandler extends AbstractElementHandler {
return PlainTextHandler.INSTANCE;
}
if (RocksimCommonConstants.ROCKET_DESIGN.equals(element)) {
return new RocketDesignHandler(doc, rocket);
return new RocketDesignHandler(context, rocket);
}
return null;
}
@ -153,7 +154,7 @@ class RocksimContentHandler extends AbstractElementHandler {
* structures. If that invariant is not true, then behavior will be unpredictable.
*/
class RocketDesignHandler extends AbstractElementHandler {
private final OpenRocketDocument document;
private final DocumentLoadingContext context;
/**
* The parent component.
*/
@ -192,8 +193,8 @@ class RocketDesignHandler extends AbstractElementHandler {
*
* @param c the parent component
*/
public RocketDesignHandler(OpenRocketDocument document, RocketComponent c) {
this.document = document;
public RocketDesignHandler(DocumentLoadingContext context, RocketComponent c) {
this.context = context;
component = c;
}
@ -216,7 +217,7 @@ class RocketDesignHandler extends AbstractElementHandler {
stage.setOverrideCGX(stage3CG);
}
component.addChild(stage);
return new StageHandler(document, stage);
return new StageHandler(context, stage);
}
if ("Stage2Parts".equals(element)) {
if (stageCount >= 2) {
@ -232,7 +233,7 @@ class RocketDesignHandler extends AbstractElementHandler {
stage.setOverrideCGX(stage2CG);
}
component.addChild(stage);
return new StageHandler(document, stage);
return new StageHandler(context, stage);
}
}
if ("Stage1Parts".equals(element)) {
@ -249,7 +250,7 @@ class RocketDesignHandler extends AbstractElementHandler {
stage.setOverrideCGX(stage1CG);
}
component.addChild(stage);
return new StageHandler(document, stage);
return new StageHandler(context, stage);
}
}
if (RocksimCommonConstants.NAME.equals(element)) {
@ -318,7 +319,7 @@ class RocketDesignHandler extends AbstractElementHandler {
* A SAX handler for a Rocksim stage.
*/
class StageHandler extends AbstractElementHandler {
private final OpenRocketDocument document;
private final DocumentLoadingContext context;
/**
* The parent OpenRocket component.
*/
@ -330,24 +331,24 @@ class StageHandler extends AbstractElementHandler {
* @param c the parent component
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public StageHandler(OpenRocketDocument document, RocketComponent c) throws IllegalArgumentException {
public StageHandler(DocumentLoadingContext context, RocketComponent c) throws IllegalArgumentException {
if (c == null) {
throw new IllegalArgumentException("The stage component may not be null.");
}
this.document = document;
this.context = context;
component = c;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
if (RocksimCommonConstants.NOSE_CONE.equals(element)) {
return new NoseConeHandler(document, component, warnings);
return new NoseConeHandler(context, component, warnings);
}
if (RocksimCommonConstants.BODY_TUBE.equals(element)) {
return new BodyTubeHandler(document, component, warnings);
return new BodyTubeHandler(context, component, warnings);
}
if (RocksimCommonConstants.TRANSITION.equals(element)) {
return new TransitionHandler(document, component, warnings);
return new TransitionHandler(context, component, warnings);
}
return null;
}

View File

@ -6,9 +6,8 @@ package net.sf.openrocket.file.rocksim.importt;
import java.io.IOException;
import java.io.InputStream;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.AbstractRocketLoader;
import net.sf.openrocket.file.MotorFinder;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.RocketLoadException;
import net.sf.openrocket.file.simplesax.SimpleSAX;
@ -39,11 +38,11 @@ public class RocksimLoader extends AbstractRocketLoader {
* if an error occurs during loading.
*/
@Override
protected void loadFromStream(OpenRocketDocument doc, InputStream source, MotorFinder motorFinder) throws IOException, RocketLoadException {
protected void loadFromStream(DocumentLoadingContext context, InputStream source) throws IOException, RocketLoadException {
InputSource xmlSource = new InputSource(source);
RocksimHandler handler = new RocksimHandler(doc);
RocksimHandler handler = new RocksimHandler(context);
try {
SimpleSAX.readXML(xmlSource, handler, warnings);
@ -51,7 +50,7 @@ public class RocksimLoader extends AbstractRocketLoader {
throw new RocketLoadException("Malformed XML in input.", e);
}
doc.setFile(null);
doc.clearUndo();
context.getOpenRocketDocument().setFile(null);
context.getOpenRocketDocument().clearUndo();
}
}

View File

@ -6,7 +6,7 @@ package net.sf.openrocket.file.rocksim.importt;
import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;
@ -20,71 +20,70 @@ import org.xml.sax.SAXException;
*/
class StreamerHandler extends RecoveryDeviceHandler<Streamer> {
/**
* The OpenRocket Streamer.
*/
private final Streamer streamer;
/**
* The OpenRocket Streamer.
*/
private final Streamer streamer;
/**
* Constructor.
*
* @param c the parent component
* @param warnings the warning set
*
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public StreamerHandler(OpenRocketDocument document, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
super(document);
if (c == null) {
throw new IllegalArgumentException("The parent of a streamer may not be null.");
}
streamer = new Streamer();
if (isCompatible(c, Streamer.class, warnings)) {
c.addChild(streamer);
}
}
/**
* Constructor.
*
* @param c the parent component
* @param warnings the warning set
*
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public StreamerHandler(DocumentLoadingContext context, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
super(context);
if (c == null) {
throw new IllegalArgumentException("The parent of a streamer may not be null.");
}
streamer = new Streamer();
if (isCompatible(c, Streamer.class, warnings)) {
c.addChild(streamer);
}
}
/**
* {@inheritDoc}
*/
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
return PlainTextHandler.INSTANCE;
}
/**
* {@inheritDoc}
*/
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
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);
/**
* {@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.WIDTH.equals(element)) {
streamer.setStripWidth(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if (RocksimCommonConstants.LEN.equals(element)) {
streamer.setStripLength(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if (RocksimCommonConstants.DRAG_COEFFICIENT.equals(element)) {
streamer.setCD(Double.parseDouble(content));
}
if (RocksimCommonConstants.MATERIAL.equals(element)) {
setMaterialName(content);
}
}
catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
try {
if (RocksimCommonConstants.WIDTH.equals(element)) {
streamer.setStripWidth(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if (RocksimCommonConstants.LEN.equals(element)) {
streamer.setStripLength(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if (RocksimCommonConstants.DRAG_COEFFICIENT.equals(element)) {
streamer.setCD(Double.parseDouble(content));
}
if (RocksimCommonConstants.MATERIAL.equals(element)) {
setMaterialName(content);
}
} catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
/**
* {@inheritDoc}
*/
@Override
public Streamer getComponent() {
return streamer;
}
/**
* {@inheritDoc}
*/
@Override
public Streamer getComponent() {
return streamer;
}
}

View File

@ -6,7 +6,7 @@ package net.sf.openrocket.file.rocksim.importt;
import java.util.HashMap;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
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.rocksim.RocksimNoseConeCode;
@ -22,142 +22,140 @@ import org.xml.sax.SAXException;
* The SAX handler for Transition components.
*/
class TransitionHandler extends BaseHandler<Transition> {
/**
* The OpenRocket Transition.
*/
private final Transition transition = new Transition();
/**
* The OpenRocket Transition.
*/
private final Transition transition = new Transition();
/**
* The wall thickness. Used for hollow nose cones.
*/
private double thickness = 0d;
/**
* The wall thickness. Used for hollow nose cones.
*/
private double thickness = 0d;
/**
* Constructor.
*
* @param c the parent component
* @param warnings the warning set
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public TransitionHandler(OpenRocketDocument document, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
super(document);
if (c == null) {
throw new IllegalArgumentException("The parent of a transition may not be null.");
}
if (isCompatible(c, Transition.class, warnings)) {
c.addChild(transition);
}
}
/**
* Constructor.
*
* @param c the parent component
* @param warnings the warning set
* @throws IllegalArgumentException thrown if <code>c</code> is null
*/
public TransitionHandler(DocumentLoadingContext context, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
super(context);
if (c == null) {
throw new IllegalArgumentException("The parent of a transition may not be null.");
}
if (isCompatible(c, Transition.class, warnings)) {
c.addChild(transition);
}
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
if (RocksimCommonConstants.ATTACHED_PARTS.equals(element)) {
return new AttachedPartsHandler(document, transition);
}
return PlainTextHandler.INSTANCE;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
if (RocksimCommonConstants.ATTACHED_PARTS.equals(element)) {
return new AttachedPartsHandler(context, transition);
}
return PlainTextHandler.INSTANCE;
}
@Override
public void closeElement(String element, HashMap<String, String> attributes,
String content, WarningSet warnings) throws SAXException {
super.closeElement(element, attributes, content, warnings);
@Override
public void closeElement(String element, HashMap<String, String> attributes,
String content, WarningSet warnings) throws SAXException {
super.closeElement(element, attributes, content, warnings);
try {
if ("ShapeCode".equals(element)) {
transition.setType(RocksimNoseConeCode.fromCode(Integer.parseInt(content)).asOpenRocket());
}
if ("Len".equals(element)) {
transition.setLength(Math.max(0, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if ("FrontDia".equals(element)) {
transition.setForeRadius(Math.max(0, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
}
if ("RearDia".equals(element)) {
transition.setAftRadius(Math.max(0, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
}
if ("WallThickness".equals(element)) {
thickness = Math.max(0d, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
}
if ("FrontShoulderDia".equals(element)) {
transition.setForeShoulderRadius(Math.max(0d, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
}
if ("RearShoulderDia".equals(element)) {
transition.setAftShoulderRadius(Math.max(0d, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
}
if ("FrontShoulderLen".equals(element)) {
transition.setForeShoulderLength(Math.max(0d, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if ("RearShoulderLen".equals(element)) {
transition.setAftShoulderLength(Math.max(0d, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if ("ShapeParameter".equals(element)) {
if (Transition.Shape.POWER.equals(transition.getType()) ||
Transition.Shape.HAACK.equals(transition.getType()) ||
Transition.Shape.PARABOLIC.equals(transition.getType())) {
transition.setShapeParameter(Double.parseDouble(content));
}
}
if ("ConstructionType".equals(element)) {
int typeCode = Integer.parseInt(content);
if (typeCode == 0) {
//SOLID
transition.setFilled(true);
}
else if (typeCode == 1) {
//HOLLOW
transition.setFilled(false);
}
}
if ("FinishCode".equals(element)) {
transition.setFinish(RocksimFinishCode.fromCode(Integer.parseInt(content)).asOpenRocket());
}
if ("Material".equals(element)) {
setMaterialName(content);
}
}
catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
try {
if ("ShapeCode".equals(element)) {
transition.setType(RocksimNoseConeCode.fromCode(Integer.parseInt(content)).asOpenRocket());
}
if ("Len".equals(element)) {
transition.setLength(Math.max(0, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if ("FrontDia".equals(element)) {
transition.setForeRadius(Math.max(0, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
}
if ("RearDia".equals(element)) {
transition.setAftRadius(Math.max(0, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
}
if ("WallThickness".equals(element)) {
thickness = Math.max(0d, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
}
if ("FrontShoulderDia".equals(element)) {
transition.setForeShoulderRadius(Math.max(0d, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
}
if ("RearShoulderDia".equals(element)) {
transition.setAftShoulderRadius(Math.max(0d, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS));
}
if ("FrontShoulderLen".equals(element)) {
transition.setForeShoulderLength(Math.max(0d, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if ("RearShoulderLen".equals(element)) {
transition.setAftShoulderLength(Math.max(0d, Double.parseDouble(
content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
}
if ("ShapeParameter".equals(element)) {
if (Transition.Shape.POWER.equals(transition.getType()) ||
Transition.Shape.HAACK.equals(transition.getType()) ||
Transition.Shape.PARABOLIC.equals(transition.getType())) {
transition.setShapeParameter(Double.parseDouble(content));
}
}
if ("ConstructionType".equals(element)) {
int typeCode = Integer.parseInt(content);
if (typeCode == 0) {
//SOLID
transition.setFilled(true);
}
else if (typeCode == 1) {
//HOLLOW
transition.setFilled(false);
}
}
if ("FinishCode".equals(element)) {
transition.setFinish(RocksimFinishCode.fromCode(Integer.parseInt(content)).asOpenRocket());
}
if ("Material".equals(element)) {
setMaterialName(content);
}
} catch (NumberFormatException nfe) {
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
}
}
@Override
public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
throws SAXException {
super.endHandler(element, attributes, content, warnings);
@Override
public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
throws SAXException {
super.endHandler(element, attributes, content, warnings);
if (transition.isFilled()) {
transition.setAftShoulderThickness(transition.getAftShoulderRadius());
transition.setForeShoulderThickness(transition.getForeShoulderRadius());
}
else {
transition.setThickness(thickness);
transition.setAftShoulderThickness(thickness);
transition.setForeShoulderThickness(thickness);
}
}
if (transition.isFilled()) {
transition.setAftShoulderThickness(transition.getAftShoulderRadius());
transition.setForeShoulderThickness(transition.getForeShoulderRadius());
}
else {
transition.setThickness(thickness);
transition.setAftShoulderThickness(thickness);
transition.setForeShoulderThickness(thickness);
}
}
@Override
public Transition getComponent() {
return transition;
}
@Override
public Transition getComponent() {
return transition;
}
/**
* Get the required type of material for this component.
*
* @return BULK
*/
public Material.Type getMaterialType() {
return Material.Type.BULK;
}
/**
* Get the required type of material for this component.
*
* @return BULK
*/
public Material.Type getMaterialType() {
return Material.Type.BULK;
}
}

View File

@ -40,7 +40,7 @@ public class ExportDecalDialog extends JDialog {
JLabel label = new JLabel(trans.get("ExportDecalDialog.decalList.lbl"));
panel.add(label);
Collection<DecalImage> exportableDecals = document.getDecalRegistry().getDecalList();
Collection<DecalImage> exportableDecals = document.getDecalList();
decalComboBox = new JComboBox(exportableDecals.toArray(new DecalImage[0]));
decalComboBox.setEditable(false);

View File

@ -10,7 +10,9 @@ import javax.swing.SwingUtilities;
import net.sf.openrocket.appearance.AppearanceBuilder;
import net.sf.openrocket.appearance.DecalImage;
import net.sf.openrocket.document.Attachment;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.FileSystemAttachmentFactory;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.startup.Application;
@ -34,7 +36,7 @@ public class DecalModel extends AbstractListModel implements ComboBoxModel {
this.document = document;
this.parent = parent;
this.ab = ab;
decals = document.getDecalRegistry().getDecalList().toArray(new DecalImage[0]);
decals = document.getDecalList().toArray(new DecalImage[0]);
}
@Override
@ -71,7 +73,8 @@ public class DecalModel extends AbstractListModel implements ComboBoxModel {
if (action == JFileChooser.APPROVE_OPTION) {
((SwingPreferences) Application.getPreferences()).setDefaultDirectory(fc.getCurrentDirectory());
File file = fc.getSelectedFile();
setSelectedItem(document.getDecalRegistry().getAttachment(file));
Attachment a = (new FileSystemAttachmentFactory().getAttachment(file));
setSelectedItem(document.getDecalImage(a));
}
}
});

View File

@ -11,6 +11,7 @@ import java.io.InputStream;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.OpenRocketDocumentFactory;
import net.sf.openrocket.file.DatabaseMotorFinder;
import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.RocketLoadException;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.LaunchLug;
@ -35,9 +36,11 @@ public class RocksimLoaderTest {
InputStream stream = this.getClass().getResourceAsStream("PodFins.rkt");
Assert.assertNotNull("Could not open PodFins.rkt", stream);
try {
OpenRocketDocument doc = OpenRocketDocumentFactory.createDocumentForFile(null, false);
loader.loadFromStream(doc, new BufferedInputStream(stream), new DatabaseMotorFinder());
Assert.assertNotNull(doc);
OpenRocketDocument doc = OpenRocketDocumentFactory.createEmptyRocket();
DocumentLoadingContext context = new DocumentLoadingContext();
context.setOpenRocketDocument(doc);
context.setMotorFinder(new DatabaseMotorFinder());
loader.loadFromStream(context, new BufferedInputStream(stream));
Rocket rocket = doc.getRocket();
Assert.assertNotNull(rocket);
} catch (IllegalStateException ise) {
@ -67,8 +70,11 @@ public class RocksimLoaderTest {
stream = this.getClass().getResourceAsStream("rocksimTestRocket2.rkt");
Assert.assertNotNull("Could not open rocksimTestRocket2.rkt", stream);
doc = OpenRocketDocumentFactory.createDocumentForFile(null, false);
loader.loadFromStream(doc, new BufferedInputStream(stream), new DatabaseMotorFinder());
doc = OpenRocketDocumentFactory.createEmptyRocket();
DocumentLoadingContext context = new DocumentLoadingContext();
context.setOpenRocketDocument(doc);
context.setMotorFinder(new DatabaseMotorFinder());
loader.loadFromStream(context, new BufferedInputStream(stream));
Assert.assertNotNull(doc);
rocket = doc.getRocket();
@ -92,8 +98,11 @@ public class RocksimLoaderTest {
stream = this.getClass().getResourceAsStream("rocksimTestRocket3.rkt");
Assert.assertNotNull("Could not open rocksimTestRocket3.rkt", stream);
doc = OpenRocketDocumentFactory.createDocumentForFile(null, false);
loader.loadFromStream(doc, new BufferedInputStream(stream), new DatabaseMotorFinder());
doc = OpenRocketDocumentFactory.createEmptyRocket();
context = new DocumentLoadingContext();
context.setOpenRocketDocument(doc);
context.setMotorFinder(new DatabaseMotorFinder());
loader.loadFromStream(context, new BufferedInputStream(stream));
Assert.assertNotNull(doc);
rocket = doc.getRocket();
@ -139,8 +148,11 @@ public class RocksimLoaderTest {
InputStream stream = RocksimLoaderTest.class.getResourceAsStream("rocksimTestRocket1.rkt");
try {
Assert.assertNotNull("Could not open rocksimTestRocket1.rkt", stream);
OpenRocketDocument doc = OpenRocketDocumentFactory.createDocumentForFile(null, false);
theLoader.loadFromStream(doc, new BufferedInputStream(stream), new DatabaseMotorFinder());
OpenRocketDocument doc = OpenRocketDocumentFactory.createEmptyRocket();
DocumentLoadingContext context = new DocumentLoadingContext();
context.setOpenRocketDocument(doc);
context.setMotorFinder(new DatabaseMotorFinder());
theLoader.loadFromStream(context, new BufferedInputStream(stream));
return doc;
} finally {
stream.close();
@ -151,8 +163,11 @@ public class RocksimLoaderTest {
InputStream stream = RocksimLoaderTest.class.getResourceAsStream("rocksimTestRocket3.rkt");
try {
Assert.assertNotNull("Could not open rocksimTestRocket3.rkt", stream);
OpenRocketDocument doc = OpenRocketDocumentFactory.createDocumentForFile(null, false);
theLoader.loadFromStream(doc, new BufferedInputStream(stream), new DatabaseMotorFinder());
OpenRocketDocument doc = OpenRocketDocumentFactory.createEmptyRocket();
DocumentLoadingContext context = new DocumentLoadingContext();
context.setOpenRocketDocument(doc);
context.setMotorFinder(new DatabaseMotorFinder());
theLoader.loadFromStream(context, new BufferedInputStream(stream));
return doc;
} finally {
stream.close();