version 1.1.3
This commit is contained in:
parent
9e6bea78ad
commit
ea3433f704
10
ChangeLog
10
ChangeLog
@ -1,3 +1,13 @@
|
||||
2010-10-06 Sampo Niskanen
|
||||
|
||||
* Released version 1.1.3
|
||||
|
||||
2010-10-05 Sampo Niskanen
|
||||
|
||||
* Display comment as tooltip in component tree
|
||||
* Limited allowed component attachments to those of the component
|
||||
add buttons
|
||||
|
||||
2010-10-03 Sampo Niskanen
|
||||
|
||||
* Added VBOSE logging level
|
||||
|
@ -1,3 +1,10 @@
|
||||
OpenRocket 1.1.3 (2010-10-06):
|
||||
-------------------------------
|
||||
|
||||
Support for drag-drop moving and copying of components. Fixes a
|
||||
severe bug in the undo system.
|
||||
|
||||
|
||||
OpenRocket 1.1.2 (2010-09-07):
|
||||
-------------------------------
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
# The OpenRocket build version
|
||||
|
||||
build.version=1.1.3pre
|
||||
build.version=1.1.3
|
||||
|
||||
|
||||
# The source of the package. When building a package for a specific
|
||||
|
@ -9,6 +9,7 @@ import javax.swing.event.ChangeListener;
|
||||
import net.sf.openrocket.aerodynamics.AerodynamicCalculator;
|
||||
import net.sf.openrocket.aerodynamics.BarrowmanCalculator;
|
||||
import net.sf.openrocket.aerodynamics.WarningSet;
|
||||
import net.sf.openrocket.logging.LogHelper;
|
||||
import net.sf.openrocket.masscalc.BasicMassCalculator;
|
||||
import net.sf.openrocket.masscalc.MassCalculator;
|
||||
import net.sf.openrocket.rocketcomponent.Configuration;
|
||||
@ -23,11 +24,13 @@ import net.sf.openrocket.simulation.SimulationStepper;
|
||||
import net.sf.openrocket.simulation.exception.SimulationException;
|
||||
import net.sf.openrocket.simulation.exception.SimulationListenerException;
|
||||
import net.sf.openrocket.simulation.listeners.SimulationListener;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
import net.sf.openrocket.util.BugException;
|
||||
import net.sf.openrocket.util.ChangeSource;
|
||||
|
||||
|
||||
public class Simulation implements ChangeSource, Cloneable {
|
||||
private static final LogHelper log = Application.getLogger();
|
||||
|
||||
public static enum Status {
|
||||
/** Up-to-date */
|
||||
@ -238,22 +241,16 @@ public class Simulation implements ChangeSource, Cloneable {
|
||||
throw new SimulationException("Cannot simulate imported simulation.");
|
||||
}
|
||||
|
||||
AerodynamicCalculator aerodynamicCalculator;
|
||||
SimulationEngine simulator;
|
||||
SimulationStepper stepper;
|
||||
MassCalculator massCalculator;
|
||||
|
||||
try {
|
||||
aerodynamicCalculator = aerodynamicCalculatorClass.newInstance();
|
||||
simulator = simulationEngineClass.newInstance();
|
||||
stepper = simulationStepperClass.newInstance();
|
||||
massCalculator = massCalculatorClass.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
throw new IllegalStateException("Cannot instantiate calculator/simulator.", e);
|
||||
throw new IllegalStateException("Cannot instantiate simulator.", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException("Cannot access calc/sim instance?! BUG!", e);
|
||||
throw new IllegalStateException("Cannot access simulator instance?! BUG!", e);
|
||||
} catch (NullPointerException e) {
|
||||
throw new IllegalStateException("Calculator or simulator null", e);
|
||||
throw new IllegalStateException("Simulator null", e);
|
||||
}
|
||||
|
||||
SimulationConditions simulationConditions = conditions.toSimulationConditions();
|
||||
@ -274,12 +271,11 @@ public class Simulation implements ChangeSource, Cloneable {
|
||||
}
|
||||
|
||||
long t1, t2;
|
||||
System.out.println("Simulation: calling simulator");
|
||||
log.debug("Simulation: calling simulator");
|
||||
t1 = System.currentTimeMillis();
|
||||
simulatedData = simulator.simulate(simulationConditions);
|
||||
t2 = System.currentTimeMillis();
|
||||
System.out.println("Simulation: returning from simulator, " +
|
||||
"simulation took " + (t2 - t1) + "ms");
|
||||
log.debug("Simulation: returning from simulator, simulation took " + (t2 - t1) + "ms");
|
||||
|
||||
// Set simulated info after simulation, will not be set in case of exception
|
||||
simulatedConditions = conditions.clone();
|
||||
|
@ -0,0 +1,86 @@
|
||||
package net.sf.openrocket.gui.dialogs.optimization;
|
||||
|
||||
import java.awt.Window;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import javax.swing.JDialog;
|
||||
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
import net.sf.openrocket.optimization.rocketoptimization.RocketOptimizationParameter;
|
||||
import net.sf.openrocket.optimization.rocketoptimization.RocketOptimizationParameterService;
|
||||
import net.sf.openrocket.optimization.rocketoptimization.SimulationModifier;
|
||||
import net.sf.openrocket.optimization.rocketoptimization.SimulationModifierService;
|
||||
import net.sf.openrocket.util.BugException;
|
||||
|
||||
public class GeneralOptimizationDialog extends JDialog {
|
||||
|
||||
private final List<RocketOptimizationParameter> optimizationParameters = new ArrayList<RocketOptimizationParameter>();
|
||||
private final Map<Object, List<SimulationModifier>> simulationModifiers =
|
||||
new HashMap<Object, List<SimulationModifier>>();
|
||||
|
||||
|
||||
private final OpenRocketDocument document;
|
||||
|
||||
public GeneralOptimizationDialog(OpenRocketDocument document, Window parent) {
|
||||
this.document = document;
|
||||
|
||||
loadOptimizationParameters();
|
||||
loadSimulationModifiers();
|
||||
}
|
||||
|
||||
|
||||
private void loadOptimizationParameters() {
|
||||
ServiceLoader<RocketOptimizationParameterService> loader =
|
||||
ServiceLoader.load(RocketOptimizationParameterService.class);
|
||||
|
||||
for (RocketOptimizationParameterService g : loader) {
|
||||
optimizationParameters.addAll(g.getParameters(document));
|
||||
}
|
||||
|
||||
if (optimizationParameters.isEmpty()) {
|
||||
throw new BugException("No rocket optimization parameters found, distribution built wrong.");
|
||||
}
|
||||
|
||||
Collections.sort(optimizationParameters, new Comparator<RocketOptimizationParameter>() {
|
||||
@Override
|
||||
public int compare(RocketOptimizationParameter o1, RocketOptimizationParameter o2) {
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void loadSimulationModifiers() {
|
||||
ServiceLoader<SimulationModifierService> loader = ServiceLoader.load(SimulationModifierService.class);
|
||||
|
||||
for (SimulationModifierService g : loader) {
|
||||
for (SimulationModifier m : g.getModifiers(document)) {
|
||||
Object key = m.getRelatedObject();
|
||||
List<SimulationModifier> list = simulationModifiers.get(key);
|
||||
if (list == null) {
|
||||
list = new ArrayList<SimulationModifier>();
|
||||
simulationModifiers.put(key, list);
|
||||
}
|
||||
list.add(m);
|
||||
}
|
||||
}
|
||||
|
||||
for (Object key : simulationModifiers.keySet()) {
|
||||
List<SimulationModifier> list = simulationModifiers.get(key);
|
||||
Collections.sort(list, new Comparator<SimulationModifier>() {
|
||||
@Override
|
||||
public int compare(SimulationModifier o1, SimulationModifier o2) {
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -9,6 +9,7 @@ import java.awt.Graphics2D;
|
||||
import javax.swing.DropMode;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.ToolTipManager;
|
||||
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
|
||||
@ -41,8 +42,13 @@ public class ComponentTree extends JTree {
|
||||
|
||||
// Expand whole tree by default
|
||||
expandTree();
|
||||
|
||||
// Enable tooltips for this component
|
||||
ToolTipManager.sharedInstance().registerComponent(this);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void expandTree() {
|
||||
for (int i = 0; i < getRowCount(); i++)
|
||||
expandRow(i);
|
||||
|
@ -8,24 +8,38 @@ import javax.swing.JTree;
|
||||
import javax.swing.tree.DefaultTreeCellRenderer;
|
||||
|
||||
import net.sf.openrocket.gui.main.ComponentIcons;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.util.TextUtil;
|
||||
|
||||
public class ComponentTreeRenderer extends DefaultTreeCellRenderer {
|
||||
|
||||
@Override
|
||||
|
||||
@Override
|
||||
public Component getTreeCellRendererComponent(
|
||||
JTree tree,
|
||||
Object value,
|
||||
boolean sel,
|
||||
boolean expanded,
|
||||
boolean leaf,
|
||||
int row,
|
||||
boolean hasFocus) {
|
||||
|
||||
super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
|
||||
|
||||
setIcon(ComponentIcons.getSmallIcon(value.getClass()));
|
||||
|
||||
return this;
|
||||
}
|
||||
JTree tree,
|
||||
Object value,
|
||||
boolean sel,
|
||||
boolean expanded,
|
||||
boolean leaf,
|
||||
int row,
|
||||
boolean hasFocus) {
|
||||
|
||||
super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
|
||||
|
||||
// Set icon
|
||||
setIcon(ComponentIcons.getSmallIcon(value.getClass()));
|
||||
|
||||
// Set tooltip
|
||||
RocketComponent c = (RocketComponent) value;
|
||||
String comment = c.getComment().trim();
|
||||
if (comment.length() > 0) {
|
||||
comment = TextUtil.htmlEncode(comment);
|
||||
comment = "<html>" + comment.replace("\n", "<br>");
|
||||
this.setToolTipText(comment);
|
||||
} else {
|
||||
this.setToolTipText(null);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ public class RocketOptimizationFunction implements Function {
|
||||
return value;
|
||||
}
|
||||
|
||||
// TODO: CRITICAL: is in domain?
|
||||
// TODO: : is in domain?
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,23 @@
|
||||
package net.sf.openrocket.optimization.rocketoptimization;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
|
||||
/**
|
||||
* A service for generating rocket optimization parameters.
|
||||
*
|
||||
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
||||
*/
|
||||
public interface RocketOptimizationParameterService {
|
||||
|
||||
/**
|
||||
* Return all available rocket optimization parameters for this document.
|
||||
* These should be new instances unless the parameter implementation is stateless.
|
||||
*
|
||||
* @param document the design document
|
||||
* @return a collection of the rocket optimization parameters.
|
||||
*/
|
||||
public Collection<RocketOptimizationParameter> getParameters(OpenRocketDocument document);
|
||||
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
package net.sf.openrocket.optimization.rocketoptimization;
|
||||
|
||||
import net.sf.openrocket.document.Simulation;
|
||||
import net.sf.openrocket.unit.UnitGroup;
|
||||
import net.sf.openrocket.util.ChangeSource;
|
||||
|
||||
/**
|
||||
* An interface what modifies a single parameter in a rocket simulation
|
||||
@ -8,14 +10,80 @@ import net.sf.openrocket.document.Simulation;
|
||||
*
|
||||
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
||||
*/
|
||||
public interface SimulationModifier {
|
||||
public interface SimulationModifier extends ChangeSource {
|
||||
|
||||
/**
|
||||
* Return a name describing this modifier.
|
||||
* @return a name describing this modifier.
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
|
||||
/**
|
||||
* Return the object this modifier is related to. This is for example the
|
||||
* rocket component this modifier is modifying. This object can be used by a
|
||||
* UI to group related modifiers.
|
||||
*
|
||||
* @return the object this modifier is related to, or <code>null</code>.
|
||||
*/
|
||||
public Object getRelatedObject();
|
||||
|
||||
|
||||
/**
|
||||
* Return the current value of the modifier in SI units.
|
||||
* @return the current value of this parameter in SI units.
|
||||
*/
|
||||
public double getCurrentValue();
|
||||
|
||||
|
||||
/**
|
||||
* Return the minimum value (corresponding to scaled value 0) in SI units.
|
||||
* @return the value corresponding to scaled value 0.
|
||||
*/
|
||||
public double getMinValue();
|
||||
|
||||
/**
|
||||
* Set the minimum value (corresponding to scaled value 0) in SI units.
|
||||
* @param value the value corresponding to scaled value 0.
|
||||
*/
|
||||
public void setMinValue(double value);
|
||||
|
||||
|
||||
/**
|
||||
* Return the maximum value (corresponding to scaled value 1) in SI units.
|
||||
* @return the value corresponding to scaled value 1.
|
||||
*/
|
||||
public double getMaxValue();
|
||||
|
||||
/**
|
||||
* Set the maximum value (corresponding to scaled value 1) in SI units.
|
||||
* @param value the value corresponding to scaled value 1.
|
||||
*/
|
||||
public void setMaxValue(double value);
|
||||
|
||||
|
||||
/**
|
||||
* Return the unit group used for the values returned by {@link #getCurrentValue()} etc.
|
||||
* @return the unit group
|
||||
*/
|
||||
public UnitGroup getUnitGroup();
|
||||
|
||||
|
||||
/**
|
||||
* Return the current scaled value. This is normally within the range [0...1], but
|
||||
* can be outside the range if the current value is outside of the min and max values.
|
||||
* @return
|
||||
*/
|
||||
public double getCurrentScaledValue();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Modify the specified simulation to the corresponding parameter value.
|
||||
*
|
||||
* @param simulation the simulation to modify
|
||||
* @param value a value in the range [0...1]
|
||||
* @param scaledValue the scaled value in the range [0...1]
|
||||
*/
|
||||
public void modify(Simulation simulation, double value);
|
||||
public void modify(Simulation simulation, double scaledValue);
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
package net.sf.openrocket.optimization.rocketoptimization;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
|
||||
/**
|
||||
* A service for generating simulation modifiers.
|
||||
*
|
||||
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
||||
*/
|
||||
public interface SimulationModifierService {
|
||||
|
||||
/**
|
||||
* Return all available simulation modifiers for this document.
|
||||
*
|
||||
* @param document the design document
|
||||
* @return a collection of the rocket optimization parameters.
|
||||
*/
|
||||
public Collection<SimulationModifier> getModifiers(OpenRocketDocument document);
|
||||
|
||||
|
||||
}
|
@ -64,20 +64,4 @@ public abstract class BodyComponent extends ExternalComponent {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given type can be added to this component. BodyComponents allow any
|
||||
* InternalComponents or ExternalComponents, excluding BodyComponents, to be added.
|
||||
*
|
||||
* @param type The RocketComponent class type to add.
|
||||
* @return Whether such a component can be added.
|
||||
*/
|
||||
@Override
|
||||
public boolean isCompatible(Class<? extends RocketComponent> type) {
|
||||
if (InternalComponent.class.isAssignableFrom(type))
|
||||
return true;
|
||||
if (ExternalComponent.class.isAssignableFrom(type) &&
|
||||
!BodyComponent.class.isAssignableFrom(type))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -281,6 +281,24 @@ public class BodyTube extends SymmetricComponent implements MotorMount {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check whether the given type can be added to this component. BodyTubes allow any
|
||||
* InternalComponents or ExternalComponents, excluding BodyComponents, to be added.
|
||||
*
|
||||
* @param type The RocketComponent class type to add.
|
||||
* @return Whether such a component can be added.
|
||||
*/
|
||||
@Override
|
||||
public boolean isCompatible(Class<? extends RocketComponent> type) {
|
||||
if (InternalComponent.class.isAssignableFrom(type))
|
||||
return true;
|
||||
if (ExternalComponent.class.isAssignableFrom(type) &&
|
||||
!BodyComponent.class.isAssignableFrom(type))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////// Motor mount /////////////////
|
||||
|
||||
@Override
|
||||
|
@ -107,7 +107,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable,
|
||||
private String comment = "";
|
||||
|
||||
// Unique ID of the component
|
||||
// TODO: CRITICAL: Sort out usage of ID and undo defect
|
||||
private String id = null;
|
||||
|
||||
/**
|
||||
|
@ -13,15 +13,15 @@ import net.sf.openrocket.util.MathUtil;
|
||||
public class Transition extends SymmetricComponent {
|
||||
private static final double CLIP_PRECISION = 0.0001;
|
||||
|
||||
|
||||
|
||||
private Shape type;
|
||||
private double shapeParameter;
|
||||
private boolean clipped; // Not to be read - use isClipped(), which may be overriden
|
||||
private boolean clipped; // Not to be read - use isClipped(), which may be overriden
|
||||
|
||||
private double radius1, radius2;
|
||||
private boolean autoRadius1, autoRadius2; // Whether the start radius is automatic
|
||||
|
||||
|
||||
private boolean autoRadius1, autoRadius2; // Whether the start radius is automatic
|
||||
|
||||
|
||||
private double foreShoulderRadius;
|
||||
private double foreShoulderThickness;
|
||||
private double foreShoulderLength;
|
||||
@ -31,9 +31,9 @@ public class Transition extends SymmetricComponent {
|
||||
private double aftShoulderLength;
|
||||
private boolean aftShoulderCapped;
|
||||
|
||||
|
||||
|
||||
// Used to cache the clip length
|
||||
private double clipLength=-1;
|
||||
private double clipLength = -1;
|
||||
|
||||
public Transition() {
|
||||
super();
|
||||
@ -50,11 +50,11 @@ public class Transition extends SymmetricComponent {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////// Fore radius ////////
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public double getForeRadius() {
|
||||
if (isForeRadiusAutomatic()) {
|
||||
@ -76,8 +76,8 @@ public class Transition extends SymmetricComponent {
|
||||
return;
|
||||
|
||||
this.autoRadius1 = false;
|
||||
this.radius1 = Math.max(radius,0);
|
||||
|
||||
this.radius1 = Math.max(radius, 0);
|
||||
|
||||
if (this.thickness > this.radius1 && this.thickness > this.radius2)
|
||||
this.thickness = Math.max(this.radius1, this.radius2);
|
||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||
@ -96,7 +96,7 @@ public class Transition extends SymmetricComponent {
|
||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////// Aft radius /////////
|
||||
|
||||
@Override
|
||||
@ -116,19 +116,19 @@ public class Transition extends SymmetricComponent {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setAftRadius(double radius) {
|
||||
if ((this.radius2 == radius) && (autoRadius2 == false))
|
||||
return;
|
||||
|
||||
this.autoRadius2 = false;
|
||||
this.radius2 = Math.max(radius,0);
|
||||
|
||||
this.radius2 = Math.max(radius, 0);
|
||||
|
||||
if (this.thickness > this.radius1 && this.thickness > this.radius2)
|
||||
this.thickness = Math.max(this.radius1, this.radius2);
|
||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isAftRadiusAutomatic() {
|
||||
return autoRadius2;
|
||||
@ -143,7 +143,7 @@ public class Transition extends SymmetricComponent {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//// Radius automatics
|
||||
|
||||
@Override
|
||||
@ -152,18 +152,18 @@ public class Transition extends SymmetricComponent {
|
||||
return -1;
|
||||
return getAftRadius();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected double getRearAutoRadius() {
|
||||
if (isForeRadiusAutomatic())
|
||||
return -1;
|
||||
return getForeRadius();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////// Type & shape /////////
|
||||
|
||||
public Shape getType() {
|
||||
@ -192,7 +192,7 @@ public class Transition extends SymmetricComponent {
|
||||
this.shapeParameter = MathUtil.clamp(n, type.minParameter(), type.maxParameter());
|
||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||
}
|
||||
|
||||
|
||||
public boolean isClipped() {
|
||||
if (!type.isClippable())
|
||||
return false;
|
||||
@ -209,7 +209,7 @@ public class Transition extends SymmetricComponent {
|
||||
public boolean isClippedEnabled() {
|
||||
return type.isClippable();
|
||||
}
|
||||
|
||||
|
||||
public double getShapeParameterMin() {
|
||||
return type.minParameter();
|
||||
}
|
||||
@ -224,29 +224,29 @@ public class Transition extends SymmetricComponent {
|
||||
public double getForeShoulderRadius() {
|
||||
return foreShoulderRadius;
|
||||
}
|
||||
|
||||
|
||||
public void setForeShoulderRadius(double foreShoulderRadius) {
|
||||
if (MathUtil.equals(this.foreShoulderRadius, foreShoulderRadius))
|
||||
return;
|
||||
this.foreShoulderRadius = foreShoulderRadius;
|
||||
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
||||
}
|
||||
|
||||
|
||||
public double getForeShoulderThickness() {
|
||||
return foreShoulderThickness;
|
||||
}
|
||||
|
||||
|
||||
public void setForeShoulderThickness(double foreShoulderThickness) {
|
||||
if (MathUtil.equals(this.foreShoulderThickness, foreShoulderThickness))
|
||||
return;
|
||||
this.foreShoulderThickness = foreShoulderThickness;
|
||||
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
||||
}
|
||||
|
||||
|
||||
public double getForeShoulderLength() {
|
||||
return foreShoulderLength;
|
||||
}
|
||||
|
||||
|
||||
public void setForeShoulderLength(double foreShoulderLength) {
|
||||
if (MathUtil.equals(this.foreShoulderLength, foreShoulderLength))
|
||||
return;
|
||||
@ -264,36 +264,36 @@ public class Transition extends SymmetricComponent {
|
||||
this.foreShoulderCapped = capped;
|
||||
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public double getAftShoulderRadius() {
|
||||
return aftShoulderRadius;
|
||||
}
|
||||
|
||||
|
||||
public void setAftShoulderRadius(double aftShoulderRadius) {
|
||||
if (MathUtil.equals(this.aftShoulderRadius, aftShoulderRadius))
|
||||
return;
|
||||
this.aftShoulderRadius = aftShoulderRadius;
|
||||
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
||||
}
|
||||
|
||||
|
||||
public double getAftShoulderThickness() {
|
||||
return aftShoulderThickness;
|
||||
}
|
||||
|
||||
|
||||
public void setAftShoulderThickness(double aftShoulderThickness) {
|
||||
if (MathUtil.equals(this.aftShoulderThickness, aftShoulderThickness))
|
||||
return;
|
||||
this.aftShoulderThickness = aftShoulderThickness;
|
||||
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
||||
}
|
||||
|
||||
|
||||
public double getAftShoulderLength() {
|
||||
return aftShoulderLength;
|
||||
}
|
||||
|
||||
|
||||
public void setAftShoulderLength(double aftShoulderLength) {
|
||||
if (MathUtil.equals(this.aftShoulderLength, aftShoulderLength))
|
||||
return;
|
||||
@ -311,10 +311,10 @@ public class Transition extends SymmetricComponent {
|
||||
this.aftShoulderCapped = capped;
|
||||
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/////////// Shape implementations ////////////
|
||||
|
||||
|
||||
@ -324,17 +324,17 @@ public class Transition extends SymmetricComponent {
|
||||
*/
|
||||
@Override
|
||||
public double getRadius(double x) {
|
||||
if (x<0 || x>length)
|
||||
if (x < 0 || x > length)
|
||||
return 0;
|
||||
|
||||
double r1=getForeRadius();
|
||||
double r2=getAftRadius();
|
||||
|
||||
double r1 = getForeRadius();
|
||||
double r2 = getAftRadius();
|
||||
|
||||
if (r1 == r2)
|
||||
return r1;
|
||||
|
||||
if (r1 > r2) {
|
||||
x = length-x;
|
||||
x = length - x;
|
||||
double tmp = r1;
|
||||
r1 = r2;
|
||||
r2 = tmp;
|
||||
@ -343,29 +343,29 @@ public class Transition extends SymmetricComponent {
|
||||
if (isClipped()) {
|
||||
// Check clip calculation
|
||||
if (clipLength < 0)
|
||||
calculateClip(r1,r2);
|
||||
return type.getRadius(clipLength+x, r2, clipLength+length, shapeParameter);
|
||||
calculateClip(r1, r2);
|
||||
return type.getRadius(clipLength + x, r2, clipLength + length, shapeParameter);
|
||||
} else {
|
||||
// Not clipped
|
||||
return r1 + type.getRadius(x, r2-r1, length, shapeParameter);
|
||||
return r1 + type.getRadius(x, r2 - r1, length, shapeParameter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Numerically solve clipLength from the equation
|
||||
* r1 == type.getRadius(clipLength,r2,clipLength+length)
|
||||
* using a binary search. It assumes getRadius() to be monotonically increasing.
|
||||
*/
|
||||
private void calculateClip(double r1, double r2) {
|
||||
double min=0, max=length;
|
||||
double min = 0, max = length;
|
||||
|
||||
if (r1 >= r2) {
|
||||
double tmp=r1;
|
||||
double tmp = r1;
|
||||
r1 = r2;
|
||||
r2 = tmp;
|
||||
}
|
||||
|
||||
if (r1==0) {
|
||||
if (r1 == 0) {
|
||||
clipLength = 0;
|
||||
return;
|
||||
}
|
||||
@ -378,22 +378,22 @@ public class Transition extends SymmetricComponent {
|
||||
// Required:
|
||||
// getR(min,min+length,r2) - r1 < 0
|
||||
// getR(max,max+length,r2) - r1 > 0
|
||||
|
||||
int n=0;
|
||||
while (type.getRadius(max, r2, max+length, shapeParameter) - r1 < 0) {
|
||||
|
||||
int n = 0;
|
||||
while (type.getRadius(max, r2, max + length, shapeParameter) - r1 < 0) {
|
||||
min = max;
|
||||
max *= 2;
|
||||
n++;
|
||||
if (n>10)
|
||||
if (n > 10)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
while (true) {
|
||||
clipLength = (min+max)/2;
|
||||
if ((max-min)<CLIP_PRECISION)
|
||||
clipLength = (min + max) / 2;
|
||||
if ((max - min) < CLIP_PRECISION)
|
||||
return;
|
||||
double val = type.getRadius(clipLength, r2, clipLength+length, shapeParameter);
|
||||
if (val-r1 > 0) {
|
||||
double val = type.getRadius(clipLength, r2, clipLength + length, shapeParameter);
|
||||
if (val - r1 > 0) {
|
||||
max = clipLength;
|
||||
} else {
|
||||
min = clipLength;
|
||||
@ -404,9 +404,9 @@ public class Transition extends SymmetricComponent {
|
||||
|
||||
@Override
|
||||
public double getInnerRadius(double x) {
|
||||
return Math.max(getRadius(x)-thickness,0);
|
||||
return Math.max(getRadius(x) - thickness, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
@ -444,7 +444,7 @@ public class Transition extends SymmetricComponent {
|
||||
|
||||
return mass;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Coordinate getComponentCG() {
|
||||
Coordinate cg = super.getComponentCG();
|
||||
@ -455,25 +455,25 @@ public class Transition extends SymmetricComponent {
|
||||
}
|
||||
if (isForeShoulderCapped()) {
|
||||
final double ir = Math.max(getForeShoulderRadius() - getForeShoulderThickness(), 0);
|
||||
cg = cg.average(ringCG(ir, 0, -getForeShoulderLength(),
|
||||
getForeShoulderThickness()-getForeShoulderLength(),
|
||||
cg = cg.average(ringCG(ir, 0, -getForeShoulderLength(),
|
||||
getForeShoulderThickness() - getForeShoulderLength(),
|
||||
getMaterial().getDensity()));
|
||||
}
|
||||
|
||||
if (getAftShoulderLength() > 0.001) {
|
||||
final double ir = Math.max(getAftShoulderRadius() - getAftShoulderThickness(), 0);
|
||||
cg = cg.average(ringCG(getAftShoulderRadius(), ir, getLength(),
|
||||
getLength()+getAftShoulderLength(), getMaterial().getDensity()));
|
||||
cg = cg.average(ringCG(getAftShoulderRadius(), ir, getLength(),
|
||||
getLength() + getAftShoulderLength(), getMaterial().getDensity()));
|
||||
}
|
||||
if (isAftShoulderCapped()) {
|
||||
final double ir = Math.max(getAftShoulderRadius() - getAftShoulderThickness(), 0);
|
||||
cg = cg.average(ringCG(ir, 0,
|
||||
getLength()+getAftShoulderLength()-getAftShoulderThickness(),
|
||||
getLength()+getAftShoulderLength(), getMaterial().getDensity()));
|
||||
cg = cg.average(ringCG(ir, 0,
|
||||
getLength() + getAftShoulderLength() - getAftShoulderThickness(),
|
||||
getLength() + getAftShoulderLength(), getMaterial().getDensity()));
|
||||
}
|
||||
return cg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The moments of inertia are not explicitly corrected for the shoulders.
|
||||
@ -498,14 +498,29 @@ public class Transition extends SymmetricComponent {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check whether the given type can be added to this component. Transitions allow any
|
||||
* InternalComponents to be added.
|
||||
*
|
||||
* @param type The RocketComponent class type to add.
|
||||
* @return Whether such a component can be added.
|
||||
*/
|
||||
@Override
|
||||
public boolean isCompatible(Class<? extends RocketComponent> type) {
|
||||
if (InternalComponent.class.isAssignableFrom(type))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* An enumeration listing the possible shapes of transitions.
|
||||
*
|
||||
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
||||
*/
|
||||
public static enum Shape {
|
||||
|
||||
|
||||
/**
|
||||
* Conical shape.
|
||||
*/
|
||||
@ -517,10 +532,10 @@ public class Transition extends SymmetricComponent {
|
||||
assert x >= 0;
|
||||
assert x <= length;
|
||||
assert radius >= 0;
|
||||
return radius*x/length;
|
||||
return radius * x / length;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Ogive shape. The shape parameter is the portion of an extended tangent ogive
|
||||
* that will be used. That is, for param==1 a tangent ogive will be produced, and
|
||||
@ -528,21 +543,23 @@ public class Transition extends SymmetricComponent {
|
||||
*/
|
||||
OGIVE("Ogive",
|
||||
"An ogive nose cone has a profile that is a segment of a circle. " +
|
||||
"The shape parameter value 1 produces a <b>tangent ogive</b>, which has " +
|
||||
"a smooth transition to the body tube, values less than 1 produce "+
|
||||
"<b>secant ogives</b>.",
|
||||
"The shape parameter value 1 produces a <b>tangent ogive</b>, which has " +
|
||||
"a smooth transition to the body tube, values less than 1 produce " +
|
||||
"<b>secant ogives</b>.",
|
||||
"An ogive transition has a profile that is a segment of a circle. " +
|
||||
"The shape parameter value 1 produces a <b>tangent ogive</b>, which has " +
|
||||
"a smooth transition to the body tube at the aft end, values less than 1 " +
|
||||
"produce <b>secant ogives</b>.") {
|
||||
"The shape parameter value 1 produces a <b>tangent ogive</b>, which has " +
|
||||
"a smooth transition to the body tube at the aft end, values less than 1 " +
|
||||
"produce <b>secant ogives</b>.") {
|
||||
@Override
|
||||
public boolean usesParameter() {
|
||||
return true; // Range 0...1 is default
|
||||
return true; // Range 0...1 is default
|
||||
}
|
||||
|
||||
@Override
|
||||
public double defaultParameter() {
|
||||
return 1.0; // Tangent ogive by default
|
||||
return 1.0; // Tangent ogive by default
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getRadius(double x, double radius, double length, double param) {
|
||||
assert x >= 0;
|
||||
@ -562,56 +579,58 @@ public class Transition extends SymmetricComponent {
|
||||
return CONICAL.getRadius(x, radius, length, param);
|
||||
|
||||
// Radius of circle is:
|
||||
double R = sqrt((pow2(length)+pow2(radius)) *
|
||||
(pow2((2-param)*length) + pow2(param*radius))/(4*pow2(param*radius)));
|
||||
double L = length/param;
|
||||
// double R = (radius + length*length/(radius*param*param))/2;
|
||||
double y0 = sqrt(R*R - L*L);
|
||||
return sqrt(R*R - (L-x)*(L-x)) - y0;
|
||||
double R = sqrt((pow2(length) + pow2(radius)) *
|
||||
(pow2((2 - param) * length) + pow2(param * radius)) / (4 * pow2(param * radius)));
|
||||
double L = length / param;
|
||||
// double R = (radius + length*length/(radius*param*param))/2;
|
||||
double y0 = sqrt(R * R - L * L);
|
||||
return sqrt(R * R - (L - x) * (L - x)) - y0;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Ellipsoidal shape.
|
||||
*/
|
||||
ELLIPSOID("Ellipsoid",
|
||||
"An ellipsoidal nose cone has a profile of a half-ellipse "+
|
||||
"with major axes of lengths 2×<i>Length</i> and <i>Diameter</i>.",
|
||||
"An ellipsoidal transition has a profile of a half-ellipse "+
|
||||
"with major axes of lengths 2×<i>Length</i> and <i>Diameter</i>. If the "+
|
||||
"transition is not clipped, then the profile is extended at the center by the "+
|
||||
"corresponding radius.",true) {
|
||||
"An ellipsoidal nose cone has a profile of a half-ellipse " +
|
||||
"with major axes of lengths 2×<i>Length</i> and <i>Diameter</i>.",
|
||||
"An ellipsoidal transition has a profile of a half-ellipse " +
|
||||
"with major axes of lengths 2×<i>Length</i> and <i>Diameter</i>. If the " +
|
||||
"transition is not clipped, then the profile is extended at the center by the " +
|
||||
"corresponding radius.", true) {
|
||||
@Override
|
||||
public double getRadius(double x, double radius, double length, double param) {
|
||||
assert x >= 0;
|
||||
assert x <= length;
|
||||
assert radius >= 0;
|
||||
x = x*radius/length;
|
||||
return sqrt(2*radius*x-x*x); // radius/length * sphere
|
||||
x = x * radius / length;
|
||||
return sqrt(2 * radius * x - x * x); // radius/length * sphere
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
POWER("Power series",
|
||||
"A power series nose cone has a profile of "+
|
||||
"<i>Radius</i> × (<i>x</i> / <i>Length</i>)" +
|
||||
"<sup><i>k</i></sup> "+
|
||||
"where <i>k</i> is the shape parameter. For <i>k</i>=0.5 this is a "+
|
||||
"<b>" + FRAC12 +"-power</b> or <b>parabolic</b> nose cone, for <i>k</i>=0.75 a "+
|
||||
"<b>" + FRAC34 +"-power</b>, and for <i>k</i>=1 a <b>conical</b> nose cone.",
|
||||
"A power series transition has a profile of "+
|
||||
"<i>Radius</i> × (<i>x</i> / <i>Length</i>)" +
|
||||
"<sup><i>k</i></sup> "+
|
||||
"where <i>k</i> is the shape parameter. For <i>k</i>=0.5 the transition is "+
|
||||
"<b>" + FRAC12 + "-power</b> or <b>parabolic</b>, for <i>k</i>=0.75 a " +
|
||||
"<b>" + FRAC34 + "-power</b>, and for <i>k</i>=1 <b>conical</b>.",true) {
|
||||
"A power series nose cone has a profile of " +
|
||||
"<i>Radius</i> × (<i>x</i> / <i>Length</i>)" +
|
||||
"<sup><i>k</i></sup> " +
|
||||
"where <i>k</i> is the shape parameter. For <i>k</i>=0.5 this is a " +
|
||||
"<b>" + FRAC12 + "-power</b> or <b>parabolic</b> nose cone, for <i>k</i>=0.75 a " +
|
||||
"<b>" + FRAC34 + "-power</b>, and for <i>k</i>=1 a <b>conical</b> nose cone.",
|
||||
"A power series transition has a profile of " +
|
||||
"<i>Radius</i> × (<i>x</i> / <i>Length</i>)" +
|
||||
"<sup><i>k</i></sup> " +
|
||||
"where <i>k</i> is the shape parameter. For <i>k</i>=0.5 the transition is " +
|
||||
"<b>" + FRAC12 + "-power</b> or <b>parabolic</b>, for <i>k</i>=0.75 a " +
|
||||
"<b>" + FRAC34 + "-power</b>, and for <i>k</i>=1 <b>conical</b>.", true) {
|
||||
@Override
|
||||
public boolean usesParameter() { // Range 0...1
|
||||
public boolean usesParameter() { // Range 0...1
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double defaultParameter() {
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getRadius(double x, double radius, double length, double param) {
|
||||
assert x >= 0;
|
||||
@ -619,40 +638,42 @@ public class Transition extends SymmetricComponent {
|
||||
assert radius >= 0;
|
||||
assert param >= 0;
|
||||
assert param <= 1;
|
||||
if (param<=0.00001) {
|
||||
if (x<=0.00001)
|
||||
if (param <= 0.00001) {
|
||||
if (x <= 0.00001)
|
||||
return 0;
|
||||
else
|
||||
return radius;
|
||||
}
|
||||
return radius*Math.pow(x/length, param);
|
||||
return radius * Math.pow(x / length, param);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
PARABOLIC("Parabolic series",
|
||||
"A parabolic series nose cone has a profile of a parabola. The shape "+
|
||||
"parameter defines the segment of the parabola to utilize. The shape " +
|
||||
"parameter 1.0 produces a <b>full parabola</b> which is tangent to the body " +
|
||||
"tube, 0.75 produces a <b>3/4 parabola</b>, 0.5 procudes a " +
|
||||
"<b>1/2 parabola</b> and 0 produces a <b>conical</b> nose cone.",
|
||||
"A parabolic series transition has a profile of a parabola. The shape "+
|
||||
"parameter defines the segment of the parabola to utilize. The shape " +
|
||||
"parameter 1.0 produces a <b>full parabola</b> which is tangent to the body " +
|
||||
"tube at the aft end, 0.75 produces a <b>3/4 parabola</b>, 0.5 procudes a " +
|
||||
"<b>1/2 parabola</b> and 0 produces a <b>conical</b> transition.") {
|
||||
"A parabolic series nose cone has a profile of a parabola. The shape " +
|
||||
"parameter defines the segment of the parabola to utilize. The shape " +
|
||||
"parameter 1.0 produces a <b>full parabola</b> which is tangent to the body " +
|
||||
"tube, 0.75 produces a <b>3/4 parabola</b>, 0.5 procudes a " +
|
||||
"<b>1/2 parabola</b> and 0 produces a <b>conical</b> nose cone.",
|
||||
"A parabolic series transition has a profile of a parabola. The shape " +
|
||||
"parameter defines the segment of the parabola to utilize. The shape " +
|
||||
"parameter 1.0 produces a <b>full parabola</b> which is tangent to the body " +
|
||||
"tube at the aft end, 0.75 produces a <b>3/4 parabola</b>, 0.5 procudes a " +
|
||||
"<b>1/2 parabola</b> and 0 produces a <b>conical</b> transition.") {
|
||||
|
||||
// In principle a parabolic transition is clippable, but the difference is
|
||||
// negligible.
|
||||
|
||||
@Override
|
||||
public boolean usesParameter() { // Range 0...1
|
||||
public boolean usesParameter() { // Range 0...1
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double defaultParameter() {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getRadius(double x, double radius, double length, double param) {
|
||||
assert x >= 0;
|
||||
@ -660,31 +681,33 @@ public class Transition extends SymmetricComponent {
|
||||
assert radius >= 0;
|
||||
assert param >= 0;
|
||||
assert param <= 1;
|
||||
|
||||
return radius * ((2*x/length - param*pow2(x/length))/(2-param));
|
||||
|
||||
return radius * ((2 * x / length - param * pow2(x / length)) / (2 - param));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
HAACK("Haack series",
|
||||
"The Haack series nose cones are designed to minimize drag. The shape parameter " +
|
||||
"0 produces an <b>LD-Haack</b> or <b>Von Karman</b> nose cone, which minimizes " +
|
||||
"drag for fixed length and diameter, while a value of 0.333 produces an " +
|
||||
"<b>LV-Haack</b> nose cone, which minimizes drag for fixed length and volume.",
|
||||
"0 produces an <b>LD-Haack</b> or <b>Von Karman</b> nose cone, which minimizes " +
|
||||
"drag for fixed length and diameter, while a value of 0.333 produces an " +
|
||||
"<b>LV-Haack</b> nose cone, which minimizes drag for fixed length and volume.",
|
||||
"The Haack series <i>nose cones</i> are designed to minimize drag. " +
|
||||
"These transition shapes are their equivalents, but do not necessarily produce " +
|
||||
"optimal drag for transitions. " +
|
||||
"The shape parameter 0 produces an <b>LD-Haack</b> or <b>Von Karman</b> shape, " +
|
||||
"while a value of 0.333 produces an <b>LV-Haack</b> shape.",true) {
|
||||
"These transition shapes are their equivalents, but do not necessarily produce " +
|
||||
"optimal drag for transitions. " +
|
||||
"The shape parameter 0 produces an <b>LD-Haack</b> or <b>Von Karman</b> shape, " +
|
||||
"while a value of 0.333 produces an <b>LV-Haack</b> shape.", true) {
|
||||
@Override
|
||||
public boolean usesParameter() {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
|
||||
@Override
|
||||
public double maxParameter() {
|
||||
return 1.0/3.0; // Range 0...1/3
|
||||
return 1.0 / 3.0; // Range 0...1/3
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getRadius(double x, double radius, double length, double param) {
|
||||
assert x >= 0;
|
||||
@ -692,58 +715,58 @@ public class Transition extends SymmetricComponent {
|
||||
assert radius >= 0;
|
||||
assert param >= 0;
|
||||
assert param <= 2;
|
||||
|
||||
double theta = Math.acos(1-2*x/length);
|
||||
if (param==0) {
|
||||
return radius*sqrt((theta-sin(2*theta)/2)/Math.PI);
|
||||
|
||||
double theta = Math.acos(1 - 2 * x / length);
|
||||
if (param == 0) {
|
||||
return radius * sqrt((theta - sin(2 * theta) / 2) / Math.PI);
|
||||
}
|
||||
return radius*sqrt((theta-sin(2*theta)/2+param*pow3(sin(theta)))/Math.PI);
|
||||
return radius * sqrt((theta - sin(2 * theta) / 2 + param * pow3(sin(theta))) / Math.PI);
|
||||
}
|
||||
},
|
||||
|
||||
// POLYNOMIAL("Smooth polynomial",
|
||||
// "A polynomial is fitted such that the nose cone profile is horizontal "+
|
||||
// "at the aft end of the transition. The angle at the tip is defined by "+
|
||||
// "the shape parameter.",
|
||||
// "A polynomial is fitted such that the transition profile is horizontal "+
|
||||
// "at the aft end of the transition. The angle at the fore end is defined "+
|
||||
// "by the shape parameter.") {
|
||||
// @Override
|
||||
// public boolean usesParameter() {
|
||||
// return true;
|
||||
// }
|
||||
// @Override
|
||||
// public double maxParameter() {
|
||||
// return 3.0; // Range 0...3
|
||||
// }
|
||||
// @Override
|
||||
// public double defaultParameter() {
|
||||
// return 0.0;
|
||||
// }
|
||||
// public double getRadius(double x, double radius, double length, double param) {
|
||||
// assert x >= 0;
|
||||
// assert x <= length;
|
||||
// assert radius >= 0;
|
||||
// assert param >= 0;
|
||||
// assert param <= 3;
|
||||
// // p(x) = (k-2)x^3 + (3-2k)x^2 + k*x
|
||||
// x = x/length;
|
||||
// return radius*((((param-2)*x + (3-2*param))*x + param)*x);
|
||||
// }
|
||||
// }
|
||||
// POLYNOMIAL("Smooth polynomial",
|
||||
// "A polynomial is fitted such that the nose cone profile is horizontal "+
|
||||
// "at the aft end of the transition. The angle at the tip is defined by "+
|
||||
// "the shape parameter.",
|
||||
// "A polynomial is fitted such that the transition profile is horizontal "+
|
||||
// "at the aft end of the transition. The angle at the fore end is defined "+
|
||||
// "by the shape parameter.") {
|
||||
// @Override
|
||||
// public boolean usesParameter() {
|
||||
// return true;
|
||||
// }
|
||||
// @Override
|
||||
// public double maxParameter() {
|
||||
// return 3.0; // Range 0...3
|
||||
// }
|
||||
// @Override
|
||||
// public double defaultParameter() {
|
||||
// return 0.0;
|
||||
// }
|
||||
// public double getRadius(double x, double radius, double length, double param) {
|
||||
// assert x >= 0;
|
||||
// assert x <= length;
|
||||
// assert radius >= 0;
|
||||
// assert param >= 0;
|
||||
// assert param <= 3;
|
||||
// // p(x) = (k-2)x^3 + (3-2k)x^2 + k*x
|
||||
// x = x/length;
|
||||
// return radius*((((param-2)*x + (3-2*param))*x + param)*x);
|
||||
// }
|
||||
// }
|
||||
;
|
||||
|
||||
|
||||
// Privete fields of the shapes
|
||||
private final String name;
|
||||
private final String transitionDesc;
|
||||
private final String noseconeDesc;
|
||||
private final boolean canClip;
|
||||
|
||||
|
||||
// Non-clippable constructor
|
||||
Shape(String name, String noseconeDesc, String transitionDesc) {
|
||||
this(name,noseconeDesc,transitionDesc,false);
|
||||
this(name, noseconeDesc, transitionDesc, false);
|
||||
}
|
||||
|
||||
|
||||
// Clippable constructor
|
||||
Shape(String name, String noseconeDesc, String transitionDesc, boolean canClip) {
|
||||
this.name = name;
|
||||
@ -773,7 +796,7 @@ public class Transition extends SymmetricComponent {
|
||||
public String getNoseConeDescription() {
|
||||
return noseconeDesc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check whether the shape differs in clipped mode. The clipping should be
|
||||
* enabled by default if possible.
|
||||
@ -788,7 +811,7 @@ public class Transition extends SymmetricComponent {
|
||||
public boolean usesParameter() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the minimum value of the shape parameter. (Default 0.)
|
||||
*/
|
||||
@ -809,7 +832,7 @@ public class Transition extends SymmetricComponent {
|
||||
public double defaultParameter() {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the basic radius of a transition with the given radius, length and
|
||||
* shape parameter at the point x from the tip of the component. It is assumed
|
||||
@ -823,7 +846,7 @@ public class Transition extends SymmetricComponent {
|
||||
* @return The basic radius at the given position.
|
||||
*/
|
||||
public abstract double getRadius(double x, double radius, double length, double param);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the shape (same as getName()).
|
||||
|
@ -2,11 +2,11 @@ package net.sf.openrocket.util;
|
||||
|
||||
|
||||
public class TextUtil {
|
||||
private static final char[] HEX = {
|
||||
'0','1','2','3','4','5','6','7',
|
||||
'8','9','a','b','c','d','e','f'
|
||||
private static final char[] HEX = {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return the bytes formatted as a hexadecimal string. The length of the
|
||||
@ -18,13 +18,13 @@ public class TextUtil {
|
||||
*/
|
||||
public static final String hexString(byte[] bytes) {
|
||||
StringBuilder sb = new StringBuilder(bytes.length * 2);
|
||||
for (byte b: bytes) {
|
||||
for (byte b : bytes) {
|
||||
sb.append(HEX[(b >>> 4) & 0xF]);
|
||||
sb.append(HEX[b & 0xF]);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a string of the double value with suitable precision (5 digits).
|
||||
* The string is the shortest representation of the value including the
|
||||
@ -49,7 +49,7 @@ public class TextUtil {
|
||||
return "Inf";
|
||||
}
|
||||
|
||||
|
||||
|
||||
final String sign = (d < 0) ? "-" : "";
|
||||
double abs = Math.abs(d);
|
||||
|
||||
@ -95,7 +95,7 @@ public class TextUtil {
|
||||
*/
|
||||
private static String decimalFormat(double value) {
|
||||
if (value >= 10000)
|
||||
return "" + (int)(value + 0.5);
|
||||
return "" + (int) (value + 0.5);
|
||||
|
||||
int decimals = 1;
|
||||
double v = value;
|
||||
@ -108,8 +108,8 @@ public class TextUtil {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* value must be positive!
|
||||
*/
|
||||
@ -118,42 +118,50 @@ public class TextUtil {
|
||||
// Calculate rounding and limit values (rounding slightly smaller)
|
||||
int rounding = 1;
|
||||
double limit = 0.5;
|
||||
for (int i=0; i<decimals; i++) {
|
||||
for (int i = 0; i < decimals; i++) {
|
||||
rounding *= 10;
|
||||
limit /= 10;
|
||||
}
|
||||
|
||||
|
||||
// Round value
|
||||
value = (Math.rint(value * rounding)+0.1) / rounding;
|
||||
value = (Math.rint(value * rounding) + 0.1) / rounding;
|
||||
|
||||
|
||||
int whole = (int)value;
|
||||
|
||||
int whole = (int) value;
|
||||
value -= whole;
|
||||
|
||||
|
||||
if (value < limit)
|
||||
return "" + whole;
|
||||
limit *= 10;
|
||||
|
||||
if (value < limit)
|
||||
return "" + whole;
|
||||
limit *= 10;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("" + whole);
|
||||
sb.append('.');
|
||||
|
||||
|
||||
for (int i = 0; i<decimals; i++) {
|
||||
|
||||
for (int i = 0; i < decimals; i++) {
|
||||
|
||||
value *= 10;
|
||||
whole = (int)value;
|
||||
whole = (int) value;
|
||||
value -= whole;
|
||||
sb.append((char)('0' + whole));
|
||||
sb.append((char) ('0' + whole));
|
||||
|
||||
if (value < limit)
|
||||
return sb.toString();
|
||||
limit *= 10;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static String htmlEncode(String s) {
|
||||
s = s.replace("&", "&");
|
||||
s = s.replace("\"", """);
|
||||
s = s.replace("<", "<");
|
||||
s = s.replace(">", ">");
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
@ -80,16 +80,18 @@ header("Content-type: text/plain");
|
||||
$version = $_GET["version"];
|
||||
$updates = "";
|
||||
|
||||
$unstable = "1.1.2";
|
||||
$unstable = "1.1.3";
|
||||
$stable = "1.0.0";
|
||||
|
||||
if (preg_match("/^1\.1\.1/", $version)) {
|
||||
if (preg_match("/^1\.1\.[12]/", $version)) {
|
||||
$updates = "Version: " . $unstable . "\n" .
|
||||
"4: Fixed bug preventing addition of stages\n";
|
||||
"5: Initial drag-and-drop support\n" .
|
||||
"4: Bug fixes\n";
|
||||
} else if (preg_match("/^1\.1\.0/", $version)) {
|
||||
$updates = "Version: " . $unstable . "\n" .
|
||||
"6: Enhanced motor selection\n" .
|
||||
"5: Rewritten simulation code\n" .
|
||||
"5: Drag-and-drop support\n" .
|
||||
"4: Bug fixes";
|
||||
} else if (preg_match("/^0\.9\.6/", $version)) {
|
||||
$updates = "Version: " . $stable . "\n" .
|
||||
|
@ -45,6 +45,12 @@
|
||||
<div class="content">
|
||||
<div class="news">
|
||||
<h2>Recent news:</h2>
|
||||
<p><span class="date">6.10.2010:</span> Version 1.1.3 is
|
||||
<a href="download.html">released</a>!</p>
|
||||
<p>This release includes support for moving and copying components
|
||||
in the component tree using drag-and-drop. Use normal DnD for
|
||||
moving, and control-drag for copy. This release also fixes a
|
||||
severe bug in the undo system.</p>
|
||||
<p><span class="date">7.9.2010:</span> A bug-fix version 1.1.2 is
|
||||
<a href="download.html">released</a>!</p>
|
||||
<p>This release fixes a severe bug in 1.1.1 that prevented adding stages
|
||||
@ -82,13 +88,13 @@
|
||||
<a href="http://sourceforge.net/donate/index.php?group_id=260357"><img src="project-support.jpg" width="88" height="32" alt="Support This Project" /></a>
|
||||
</div>
|
||||
<div class="downloadbox">
|
||||
<a class="main" href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.2/OpenRocket-1.1.2.jar/download">
|
||||
<a class="main" href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.3/OpenRocket-1.1.3.jar/download">
|
||||
<strong>Download now!</strong>
|
||||
<span>OpenRocket-1.1.2.jar</span>
|
||||
<span>OpenRocket-1.1.3.jar</span>
|
||||
</a>
|
||||
<span class="alternative">
|
||||
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.2/ReleaseNotes/view">Release notes</a> |
|
||||
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.2/OpenRocket-1.1.2-src.zip/download">Source code</a>
|
||||
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.3/ReleaseNotes/view">Release notes</a> |
|
||||
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.3/OpenRocket-1.1.3-src.zip/download">Source code</a>
|
||||
</span>
|
||||
</div>
|
||||
<h3>Stable release</h3>
|
||||
@ -105,7 +111,7 @@
|
||||
Windows) by double-clicking the package icon. No installation is
|
||||
required.</p>
|
||||
<p>From the command line OpenRocket can be started by
|
||||
<span class="command">java -jar OpenRocket-1.1.2.jar</span></p>
|
||||
<span class="command">java -jar OpenRocket-1.1.3.jar</span></p>
|
||||
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
|
@ -46,12 +46,12 @@
|
||||
<h2>Introduction</h2>
|
||||
<div class="rightpane">
|
||||
<div class="downloadbox">
|
||||
<a class="main" href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.2/OpenRocket-1.1.2.jar/download">
|
||||
<a class="main" href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.3/OpenRocket-1.1.3.jar/download">
|
||||
<strong>Download now!</strong>
|
||||
<span>OpenRocket-1.1.2.jar</span>
|
||||
<span>OpenRocket-1.1.3.jar</span>
|
||||
</a>
|
||||
<span class="alternative">
|
||||
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.2/ReleaseNotes/view">Release notes</a> |
|
||||
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.3/ReleaseNotes/view">Release notes</a> |
|
||||
<a href="download.html">Other versions</a>
|
||||
</span>
|
||||
</div>
|
||||
@ -88,6 +88,12 @@
|
||||
<div class="clear"></div>
|
||||
<div class="news">
|
||||
<h2>News</h2>
|
||||
<p><span class="date">6.10.2010:</span> Version 1.1.3 is
|
||||
<a href="download.html">released</a>!</p>
|
||||
<p>This release includes support for moving and copying components
|
||||
in the component tree using drag-and-drop. Use normal DnD for
|
||||
moving, and control-drag for copy. This release also fixes a
|
||||
severe bug in the undo system.</p>
|
||||
<p><span class="date">7.9.2010:</span> A bug-fix version 1.1.2 is
|
||||
<a href="download.html">released</a>!</p>
|
||||
<p>This release fixes a severe bug in 1.1.1 that prevented adding stages
|
||||
|
@ -1,5 +1,5 @@
|
||||
<set stableversion="1.0.0">
|
||||
<set developmentversion="1.1.2">
|
||||
<set developmentversion="1.1.3">
|
||||
<set version="${developmentversion}">
|
||||
|
||||
<def name="downloadbox">
|
||||
|
@ -9,6 +9,14 @@
|
||||
|
||||
<!--- Remember to move the position of "onlyrecent" below! --->
|
||||
|
||||
<p><span class="date">6.10.2010:</span> Version 1.1.3 is
|
||||
<a href="download.html">released</a>!</p>
|
||||
|
||||
<p>This release includes support for moving and copying components
|
||||
in the component tree using drag-and-drop. Use normal DnD for
|
||||
moving, and control-drag for copy. This release also fixes a
|
||||
severe bug in the undo system.</p>
|
||||
|
||||
<p><span class="date">7.9.2010:</span> A bug-fix version 1.1.2 is
|
||||
<a href="download.html">released</a>!</p>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user