preset component framework

This commit is contained in:
Sampo Niskanen 2011-08-18 05:28:08 +00:00
parent 9efabf5fb2
commit 50e8b972a3
6 changed files with 250 additions and 27 deletions

View File

@ -7,6 +7,17 @@ import java.security.NoSuchAlgorithmException;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.TextUtil;
/**
* A class that generated a "digest" of a motor. A digest is a string value that
* uniquely identifies a motor (like a hash code or checksum). Two motors that have
* the same digest behave similarly with a very high probability. The digest can
* therefore be used to identify motors that otherwise have the same specifications.
* <p>
* The digest only uses a limited amount of precision, so that rounding errors won't
* cause differing digest results.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class MotorDigest {
private static final double EPSILON = 0.00000000001;
@ -27,13 +38,16 @@ public class MotorDigest {
private final int order;
private final int multiplier;
DataType(int order, int multiplier) {
this.order = order;
this.multiplier = multiplier;
}
public int getOrder() {
return order;
}
public int getMultiplier() {
return multiplier;
}
@ -113,8 +127,7 @@ public class MotorDigest {
private byte[] bytes(int value) {
return new byte[] {
(byte) ((value >>> 24) & 0xFF), (byte) ((value >>> 16) & 0xFF),
(byte) ((value>>>8) & 0xFF), (byte) (value & 0xFF)
};
(byte) ((value >>> 8) & 0xFF), (byte) (value & 0xFF) };
}

View File

@ -0,0 +1,29 @@
package net.sf.openrocket.preset;
import net.sf.openrocket.motor.Manufacturer;
import net.sf.openrocket.rocketcomponent.RocketComponent;
public class ExternalComponentPreset extends RocketComponentPreset {
private final double mass;
private final String materialName;
public ExternalComponentPreset(Class<? extends RocketComponent> componentClass, Manufacturer manufacturer, String partName,
String partNo, String partDescription, double mass, String materialName) {
super(componentClass, manufacturer, partName, partNo, partDescription);
this.materialName = materialName;
this.mass = mass;
}
public String getMaterialName() {
return materialName;
}
public double getMass() {
return mass;
}
}

View File

@ -0,0 +1,68 @@
package net.sf.openrocket.preset;
import net.sf.openrocket.motor.Manufacturer;
import net.sf.openrocket.rocketcomponent.RocketComponent;
/**
* A model for a preset component.
* <p>
* A preset component contains a component class type, manufacturer information,
* part information, and getter methods for various properties of the component.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public abstract class RocketComponentPreset {
private final Class<? extends RocketComponent> componentClass;
private final Manufacturer manufacturer;
private final String partName;
private final String partNo;
private final String partDescription;
public RocketComponentPreset(Class<? extends RocketComponent> componentClass, Manufacturer manufacturer,
String partName, String partNo, String partDescription) {
this.componentClass = componentClass;
this.manufacturer = manufacturer;
this.partName = partName;
this.partNo = partNo;
this.partDescription = partDescription;
}
/**
* Return the component class that this preset defines.
*/
public Class<? extends RocketComponent> getComponentClass() {
return componentClass;
}
/**
* Return the manufacturer of this preset component.
*/
public Manufacturer getManufacturer() {
return manufacturer;
}
/**
* Return the part name. This is a short, human-readable name of the part.
*/
public String getPartName() {
return partName;
}
/**
* Return the part number. This is the part identifier (e.g. "BT-50").
*/
public String getPartNo() {
return partNo;
}
/**
* Return the part description. This is a longer description of the component.
*/
public String getPartDescription() {
return partDescription;
}
}

View File

@ -21,7 +21,7 @@ public class ComponentChangeEvent extends ChangeEvent {
public static final int UNDO_CHANGE = 16;
/** A change in the motor configurations or names */
public static final int MOTOR_CHANGE = 32;
/** A change in the events occurring during flight. */
/** A change that affects the events occurring during flight. */
public static final int EVENT_CHANGE = 64;
/** A bit-field that contains all possible change types. */

View File

@ -4,6 +4,9 @@ import java.util.List;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.material.Material.Type;
import net.sf.openrocket.preset.ExternalComponentPreset;
import net.sf.openrocket.preset.RocketComponentPreset;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.unit.UnitGroup;
import net.sf.openrocket.util.Prefs;
@ -111,6 +114,7 @@ public abstract class ExternalComponent extends RocketComponent {
if (material.equals(mat))
return;
material = mat;
clearPreset();
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
}
@ -126,6 +130,27 @@ public abstract class ExternalComponent extends RocketComponent {
}
@Override
protected void loadFromPreset(RocketComponentPreset preset) {
super.loadFromPreset(preset);
ExternalComponentPreset p = (ExternalComponentPreset) preset;
String materialName = p.getMaterialName();
double mass = p.getMass();
double volume = getComponentVolume();
double density;
if (volume > 0.00001) {
density = mass / volume;
} else {
density = 1000;
}
Material mat = Material.newMaterial(Type.BULK, materialName, density, true);
setMaterial(mat);
}
@Override
protected List<RocketComponent> copyFrom(RocketComponent c) {
ExternalComponent src = (ExternalComponent) c;

View File

@ -12,6 +12,7 @@ import javax.swing.event.ChangeListener;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.preset.RocketComponentPreset;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.ArrayList;
import net.sf.openrocket.util.BugException;
@ -123,6 +124,10 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
// Unique ID of the component
private String id = null;
// Preset component this component is based upon
private RocketComponentPreset presetComponent = null;
/**
* Used to invalidate the component after calling {@link #copyFrom(RocketComponent)}.
*/
@ -659,6 +664,89 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
/**
* Return the preset component that this component is based upon.
*
* @return the preset component, or <code>null</code> if this is not based on a preset.
*/
public final RocketComponentPreset getPresetComponent() {
return presetComponent;
}
/**
* Set the preset component this component is based upon and load all of the
* preset values.
*
* @param preset the preset component to load, or <code>null</code> to clear the preset.
*/
public final void loadPreset(RocketComponentPreset preset) {
if (presetComponent == preset) {
return;
}
if (preset == null) {
clearPreset();
return;
}
if (preset.getComponentClass() != this.getClass()) {
throw new IllegalArgumentException("Attempting to load preset of type " + preset.getComponentClass()
+ " into component of type " + this.getClass());
}
RocketComponent root = getRoot();
final Rocket rocket;
if (root instanceof Rocket) {
rocket = (Rocket) root;
} else {
rocket = null;
}
try {
if (rocket != null) {
rocket.freeze();
}
loadFromPreset(preset);
this.presetComponent = preset;
fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
} finally {
if (rocket != null) {
rocket.thaw();
}
}
}
/**
* Load component properties from the specified preset. The preset is guaranteed
* to be of the correct type.
* <p>
* This method should fire the appropriate events related to the changes. The rocket
* is frozen by the caller, so the events will be automatically combined.
*
* @param preset the preset to load from
*/
protected void loadFromPreset(RocketComponentPreset preset) {
// No-op
}
/**
* Clear the current component preset. This does not affect the component properties
* otherwise.
*/
public final void clearPreset() {
if (presetComponent == null)
return;
presetComponent = null;
fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
}
/**
* Returns the unique ID of the component.
*