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:
parent
48adc0b7bf
commit
593c639a06
@ -1,7 +0,0 @@
|
||||
package net.sf.openrocket.document;
|
||||
|
||||
public interface AttachmentFactory<T extends Attachment> {
|
||||
|
||||
public T getAttachment(String name);
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
public DecalRegistry(AttachmentFactory baseFactory) {
|
||||
this.baseFactory = baseFactory;
|
||||
DecalRegistry() {
|
||||
|
||||
}
|
||||
|
||||
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();
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
||||
|
9
core/src/net/sf/openrocket/file/AttachmentFactory.java
Normal file
9
core/src/net/sf/openrocket/file/AttachmentFactory.java
Normal file
@ -0,0 +1,9 @@
|
||||
package net.sf.openrocket.file;
|
||||
|
||||
import net.sf.openrocket.document.Attachment;
|
||||
|
||||
public interface AttachmentFactory {
|
||||
|
||||
public Attachment getAttachment(String name);
|
||||
|
||||
}
|
@ -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() {
|
||||
@ -24,13 +24,21 @@ public class DocumentLoadingContext {
|
||||
public void setMotorFinder(MotorFinder motorFinder) {
|
||||
this.motorFinder = motorFinder;
|
||||
}
|
||||
|
||||
|
||||
public OpenRocketDocument getOpenRocketDocument() {
|
||||
return document;
|
||||
}
|
||||
|
||||
|
||||
public void setOpenRocketDocument(OpenRocketDocument document) {
|
||||
this.document = document;
|
||||
}
|
||||
|
||||
public AttachmentFactory getAttachmentFactory() {
|
||||
return attachmentFactory;
|
||||
}
|
||||
|
||||
public void setAttachmentFactory(AttachmentFactory attachmentFactory) {
|
||||
this.attachmentFactory = attachmentFactory;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
/** The parent component. */
|
||||
private final RocketComponent component;
|
||||
|
||||
/**
|
||||
* 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(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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,14 +53,14 @@ public abstract class BaseHandler<C extends RocketComponent> extends AbstractEle
|
||||
*/
|
||||
private String materialName = "";
|
||||
|
||||
protected final OpenRocketDocument document;
|
||||
private final RockSimAppearanceBuilder appearanceBuilder;
|
||||
|
||||
public BaseHandler( OpenRocketDocument document ) {
|
||||
this.document = document;
|
||||
appearanceBuilder = new RockSimAppearanceBuilder( document );
|
||||
}
|
||||
|
||||
protected final DocumentLoadingContext context;
|
||||
private final RockSimAppearanceBuilder appearanceBuilder;
|
||||
|
||||
public BaseHandler(DocumentLoadingContext context) {
|
||||
this.context = context;
|
||||
appearanceBuilder = new RockSimAppearanceBuilder(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* The SAX method called when the closing element tag is reached.
|
||||
*
|
||||
@ -114,17 +114,17 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
@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 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.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
/**
|
||||
* 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(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(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);
|
||||
|
||||
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 required type of material for this component.
|
||||
*
|
||||
* @return BULK
|
||||
*/
|
||||
public Material.Type getMaterialType() {
|
||||
return Material.Type.BULK;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
|
||||
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 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
private final RockSimAppearanceBuilder appearanceBuilder;
|
||||
|
||||
/**
|
||||
* 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 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.");
|
||||
}
|
||||
}
|
||||
|
||||
@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());
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -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,104 +20,103 @@ import org.xml.sax.SAXException;
|
||||
* A SAX handler for Rocksim inside tubes.
|
||||
*/
|
||||
class InnerBodyTubeHandler extends PositionDependentHandler<InnerTube> {
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
@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 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.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the required type of material for this component.
|
||||
*
|
||||
* @return BULK
|
||||
*/
|
||||
@Override
|
||||
public Material.Type getMaterialType() {
|
||||
return Material.Type.BULK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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(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(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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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,95 +21,93 @@ import org.xml.sax.SAXException;
|
||||
* The SAX handler for Rocksim Launch Lugs.
|
||||
*/
|
||||
class LaunchLugHandler extends PositionDependentHandler<LaunchLug> {
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
@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.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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(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 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.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the required type of material for this component.
|
||||
*
|
||||
* @return BULK
|
||||
*/
|
||||
@Override
|
||||
public Material.Type getMaterialType() {
|
||||
return Material.Type.BULK;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
@ -24,185 +24,184 @@ import org.xml.sax.SAXException;
|
||||
* A SAX handler for Rocksim's MassObject XML type.
|
||||
*/
|
||||
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 OpenRocket MassComponent - counterpart to the RS MassObject.
|
||||
*/
|
||||
private final MassComponent mass;
|
||||
|
||||
/**
|
||||
* Reference to answer for getComponent().
|
||||
*/
|
||||
private MassObject current;
|
||||
|
||||
/**
|
||||
* Parent.
|
||||
*/
|
||||
private RocketComponent parent;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
@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 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Reference to answer for getComponent().
|
||||
*/
|
||||
private MassObject current;
|
||||
|
||||
/**
|
||||
* Parent.
|
||||
*/
|
||||
private RocketComponent parent;
|
||||
|
||||
/**
|
||||
* 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(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 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
|
||||
setOverride(cord, mass.isMassOverridden(), mass.getOverrideMass(), mass.getOverrideCGX());
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
@ -23,135 +23,134 @@ import org.xml.sax.SAXException;
|
||||
* The SAX nose cone handler for Rocksim NoseCones.
|
||||
*/
|
||||
class NoseConeHandler extends BaseHandler<NoseCone> {
|
||||
|
||||
/**
|
||||
* The OpenRocket NoseCone.
|
||||
*/
|
||||
private final NoseCone noseCone = new NoseCone();
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
@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 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.");
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The OpenRocket NoseCone.
|
||||
*/
|
||||
private final NoseCone noseCone = new NoseCone();
|
||||
|
||||
/**
|
||||
* 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(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(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);
|
||||
|
||||
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);
|
||||
|
||||
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 required type of material for this component.
|
||||
*
|
||||
* @return BULK
|
||||
*/
|
||||
public Material.Type getMaterialType() {
|
||||
return Material.Type.BULK;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the component this handler is working upon.
|
||||
*
|
||||
* @return a component
|
||||
*/
|
||||
public Parachute getComponent() {
|
||||
return chute;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(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 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
@ -20,73 +20,74 @@ import org.xml.sax.SAXException;
|
||||
* @param <C> the specific position dependent RocketComponent subtype for which the concrete handler can create
|
||||
*/
|
||||
public abstract class PositionDependentHandler<C extends RocketComponent> extends BaseHandler<C> {
|
||||
|
||||
/** Temporary position value. */
|
||||
private Double positionValue = 0d;
|
||||
|
||||
/** 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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Temporary position value. */
|
||||
private Double positionValue = 0d;
|
||||
|
||||
/** Temporary position. */
|
||||
private RocketComponent.Position position = RocketComponent.Position.TOP;
|
||||
|
||||
public PositionDependentHandler(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);
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
@ -23,100 +23,99 @@ import org.xml.sax.SAXException;
|
||||
* @param <C> either a Streamer or Parachute
|
||||
*/
|
||||
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;
|
||||
|
||||
public RecoveryDeviceHandler( 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);
|
||||
|
||||
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) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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(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);
|
||||
|
||||
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) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
@ -24,214 +24,214 @@ import org.xml.sax.SAXException;
|
||||
* A SAX handler for centering rings, tube couplers, and bulkheads.
|
||||
*/
|
||||
class RingHandler extends PositionDependentHandler<CenteringRing> {
|
||||
|
||||
/**
|
||||
* The OpenRocket Ring.
|
||||
*/
|
||||
private final CenteringRing ring = new CenteringRing();
|
||||
|
||||
/**
|
||||
* The parent component.
|
||||
*/
|
||||
private final RocketComponent parent;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
@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.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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
copyValues(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) {
|
||||
|
||||
TubeCoupler result = new TubeCoupler();
|
||||
|
||||
copyValues(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) {
|
||||
|
||||
EngineBlock result = new EngineBlock();
|
||||
|
||||
copyValues(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());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
// 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.
|
||||
|
||||
//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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the required type of material for this component.
|
||||
*
|
||||
* @return BULK
|
||||
*/
|
||||
@Override
|
||||
public Material.Type getMaterialType() {
|
||||
return Material.Type.BULK;
|
||||
}
|
||||
|
||||
/**
|
||||
* The OpenRocket Ring.
|
||||
*/
|
||||
private final CenteringRing ring = new CenteringRing();
|
||||
|
||||
/**
|
||||
* The parent component.
|
||||
*/
|
||||
private final RocketComponent parent;
|
||||
|
||||
/**
|
||||
* 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(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 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.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
|
||||
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) {
|
||||
|
||||
Bulkhead result = new Bulkhead();
|
||||
|
||||
copyValues(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) {
|
||||
|
||||
TubeCoupler result = new TubeCoupler();
|
||||
|
||||
copyValues(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) {
|
||||
|
||||
EngineBlock result = new EngineBlock();
|
||||
|
||||
copyValues(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());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
// 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.
|
||||
|
||||
//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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the required type of material for this component.
|
||||
*
|
||||
* @return BULK
|
||||
*/
|
||||
@Override
|
||||
public Material.Type getMaterialType() {
|
||||
return Material.Type.BULK;
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
@ -19,72 +19,71 @@ import org.xml.sax.SAXException;
|
||||
* A SAX handler for Streamer components.
|
||||
*/
|
||||
class StreamerHandler extends RecoveryDeviceHandler<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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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.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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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(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 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.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Streamer getComponent() {
|
||||
return streamer;
|
||||
}
|
||||
|
||||
}
|
@ -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 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);
|
||||
}
|
||||
}
|
||||
|
||||
@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 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.");
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The OpenRocket Transition.
|
||||
*/
|
||||
private final Transition transition = new Transition();
|
||||
|
||||
/**
|
||||
* 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(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(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);
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the required type of material for this component.
|
||||
*
|
||||
* @return BULK
|
||||
*/
|
||||
public Material.Type getMaterialType() {
|
||||
return Material.Type.BULK;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user