Fix the motor cg computation. Partial fix to barrowman aero.

This commit is contained in:
Kevin Ruland 2015-12-31 09:57:36 -06:00
parent 4c00a20653
commit f8cfebe5f5
8 changed files with 258 additions and 188 deletions

View File

@ -192,27 +192,27 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
// With the implementation of ParallelStages and Pods, this is no longer true. -Daniel Williams // With the implementation of ParallelStages and Pods, this is no longer true. -Daniel Williams
// //
// // Check for discontinuities // // Check for discontinuities
// if (component instanceof SymmetricComponent) { if (component instanceof SymmetricComponent) {
// SymmetricComponent sym = (SymmetricComponent) component; SymmetricComponent sym = (SymmetricComponent) component;
// // TODO:LOW: Ignores other cluster components (not clusterable) // TODO:LOW: Ignores other cluster components (not clusterable)
// double x = component.toAbsolute(Coordinate.NUL)[0].x; double x = component.toAbsolute(Coordinate.NUL)[0].x;
//
// // Check for lengthwise discontinuity // Check for lengthwise discontinuity
// if (x > componentX + 0.0001) { if (x > componentX + 0.0001) {
// if (!MathUtil.equals(radius, 0)) { if (!MathUtil.equals(radius, 0)) {
// warnings.add(Warning.DISCONTINUITY); warnings.add(Warning.DISCONTINUITY);
// radius = 0; radius = 0;
// } }
// } }
// componentX = component.toAbsolute(new Coordinate(component.getLength()))[0].x; componentX = component.toAbsolute(new Coordinate(component.getLength()))[0].x;
//
// // Check for radius discontinuity // Check for radius discontinuity
// if (!MathUtil.equals(sym.getForeRadius(), radius)) { if (!MathUtil.equals(sym.getForeRadius(), radius)) {
// warnings.add(Warning.DISCONTINUITY); warnings.add(Warning.DISCONTINUITY);
// // TODO: MEDIUM: Apply correction to values to cp and to map // TODO: MEDIUM: Apply correction to values to cp and to map
// } }
// radius = sym.getAftRadius(); radius = sym.getAftRadius();
// } }
// Call calculation method // Call calculation method
forces.zero(); forces.zero();

View File

@ -26,6 +26,7 @@ public class MassCalculator implements Monitorable {
public Coordinate getCG(Motor motor) { public Coordinate getCG(Motor motor) {
return Coordinate.NUL; return Coordinate.NUL;
} }
}, },
LAUNCH_MASS { LAUNCH_MASS {
@Override @Override
@ -41,6 +42,25 @@ public class MassCalculator implements Monitorable {
}; };
public abstract Coordinate getCG(Motor motor); public abstract Coordinate getCG(Motor motor);
/**
* Compute the cg contribution of the motor relative to the rocket's coordinates
*
* @param motorConfig
* @return
*/
public Coordinate getCG(MotorConfiguration motorConfig) {
Coordinate cg = getCG(motorConfig.getMotor());
cg = cg.add(motorConfig.getPosition());
RocketComponent motorMount = (RocketComponent) motorConfig.getMount();
Coordinate totalCG = new Coordinate();
for (Coordinate cord : motorMount.toAbsolute(cg) ) {
totalCG = totalCG.average(cord);
}
return totalCG;
}
} }
private static final Logger log = LoggerFactory.getLogger(MassCalculator.class); private static final Logger log = LoggerFactory.getLogger(MassCalculator.class);
@ -146,10 +166,10 @@ public class MassCalculator implements Monitorable {
for (MotorConfiguration inst : config.getActiveMotors() ) { for (MotorConfiguration inst : config.getActiveMotors() ) {
//ThrustCurveMotor motor = (ThrustCurveMotor) inst.getMotor(); //ThrustCurveMotor motor = (ThrustCurveMotor) inst.getMotor();
Coordinate position = inst.getPosition();
Coordinate curMotorCM = type.getCG(inst.getMotor()).add(position);
double Ir = inst.getRotationalInertia(); double Ir = inst.getRotationalInertia();
double It = inst.getLongitudinalInertia(); double It = inst.getLongitudinalInertia();
Coordinate curMotorCM = type.getCG(inst);
MassData instData = new MassData( curMotorCM, Ir, It); MassData instData = new MassData( curMotorCM, Ir, It);
motorData = motorData.add( instData ); motorData = motorData.add( instData );

View File

@ -29,7 +29,6 @@ public class MotorConfiguration implements FlightConfigurableParameter<MotorConf
protected boolean ignitionOveride = false; protected boolean ignitionOveride = false;
protected double ignitionDelay = 0.0; protected double ignitionDelay = 0.0;
protected IgnitionEvent ignitionEvent = IgnitionEvent.NEVER; protected IgnitionEvent ignitionEvent = IgnitionEvent.NEVER;
protected double ignitionTime = 0.0;
protected int modID = 0; protected int modID = 0;
private final List<StateChangeListener> listeners = new ArrayList<StateChangeListener>(); private final List<StateChangeListener> listeners = new ArrayList<StateChangeListener>();
@ -50,13 +49,11 @@ public class MotorConfiguration implements FlightConfigurableParameter<MotorConf
public MotorState getSimulationState() { public MotorState getSimulationState() {
MotorState state = motor.getNewInstance(); MotorState state = motor.getNewInstance();
if( ignitionOveride ) { if( ignitionOveride ) {
state.setIgnitionTime( this.ignitionTime );
state.setIgnitionEvent( this.ignitionEvent ); state.setIgnitionEvent( this.ignitionEvent );
state.setIgnitionDelay( this.ignitionDelay ); state.setIgnitionDelay( this.ignitionDelay );
state.setEjectionDelay( this.ejectionDelay ); state.setEjectionDelay( this.ejectionDelay );
} else { } else {
MotorConfiguration defInstance = mount.getDefaultMotorInstance(); MotorConfiguration defInstance = mount.getDefaultMotorInstance();
state.setIgnitionTime( defInstance.ignitionTime );
state.setIgnitionEvent( defInstance.ignitionEvent ); state.setIgnitionEvent( defInstance.ignitionEvent );
state.setIgnitionDelay( defInstance.ignitionDelay ); state.setIgnitionDelay( defInstance.ignitionDelay );
state.setEjectionDelay( defInstance.ejectionDelay ); state.setEjectionDelay( defInstance.ejectionDelay );
@ -118,21 +115,10 @@ public class MotorConfiguration implements FlightConfigurableParameter<MotorConf
fireChangeEvent(); fireChangeEvent();
} }
public double getIgnitionTime() {
return this.ignitionTime;
}
public void useDefaultIgnition() { public void useDefaultIgnition() {
this.ignitionOveride = false; this.ignitionOveride = false;
} }
public void setIgnitionTime(double _time) {
this.ignitionTime = _time;
this.ignitionOveride = true;
modID++;
fireChangeEvent();
}
public double getIgnitionDelay() { public double getIgnitionDelay() {
return this.ignitionDelay; return this.ignitionDelay;
} }
@ -225,7 +211,6 @@ public class MotorConfiguration implements FlightConfigurableParameter<MotorConf
clone.ignitionOveride = this.ignitionOveride; clone.ignitionOveride = this.ignitionOveride;
clone.ignitionDelay = this.ignitionDelay; clone.ignitionDelay = this.ignitionDelay;
clone.ignitionEvent = this.ignitionEvent; clone.ignitionEvent = this.ignitionEvent;
clone.ignitionTime = this.ignitionTime;
return clone; return clone;
} }

View File

@ -164,6 +164,7 @@ public class FlightEvent implements Comparable<FlightEvent> {
@Override @Override
public String toString() { public String toString() {
return "FlightEvent[type=" + type.name() + ",time=" + time + ",source=" + source + "]"; return "FlightEvent[type=" + type.name() + ",time=" + time + ",source=" + source + ",data=" + String.valueOf(data) + "]";
} }
} }

View File

@ -405,6 +405,7 @@ public class TestRockets {
bodytube.setMaterial(material); bodytube.setMaterial(material);
finset.setMaterial(material); finset.setMaterial(material);
rocket.enableEvents();
return rocket; return rocket;
} }

View File

@ -70,7 +70,7 @@ public class BarrowmanCalculatorTest {
WarningSet warnings = new WarningSet(); WarningSet warnings = new WarningSet();
MotorConfiguration inst = TestRockets.getTestD12Motor(); MotorConfiguration inst = TestRockets.getTestD12Motor();
InnerTube motorTube = (InnerTube)rkt.getChild(0).getChild(1).getChild(1); InnerTube motorTube = (InnerTube)rkt.getChild(0).getChild(1).getChild(2);
motorTube.setMotorInstance(fcid, inst); motorTube.setMotorInstance(fcid, inst);
motorTube.setMotorMount(true); motorTube.setMotorMount(true);
motorTube.setMotorOverhang(0.005); motorTube.setMotorOverhang(0.005);

View File

@ -50,6 +50,7 @@ public class BoosterSetTest extends BaseTestCase {
FinSet coreFins = new TrapezoidFinSet(4, 4, 2, 2, 4); FinSet coreFins = new TrapezoidFinSet(4, 4, 2, 2, 4);
coreFins.setName("Core Fins"); coreFins.setName("Core Fins");
coreLowerBody.addChild(coreFins); coreLowerBody.addChild(coreFins);
rocket.enableEvents();
return rocket; return rocket;
} }

View File

@ -56,6 +56,8 @@ import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.masscalc.MassCalculator; import net.sf.openrocket.masscalc.MassCalculator;
import net.sf.openrocket.masscalc.MassCalculator.MassCalcType; import net.sf.openrocket.masscalc.MassCalculator.MassCalcType;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.FinSet; import net.sf.openrocket.rocketcomponent.FinSet;
import net.sf.openrocket.rocketcomponent.FlightConfiguration; import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.rocketcomponent.Rocket;
@ -71,8 +73,8 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
private static final long serialVersionUID = 9131240570600307935L; private static final long serialVersionUID = 9131240570600307935L;
private static ComponentAnalysisDialog singletonDialog = null; private static ComponentAnalysisDialog singletonDialog = null;
private static final Translator trans = Application.getTranslator(); private static final Translator trans = Application.getTranslator();
private final FlightConditions conditions; private final FlightConditions conditions;
private final FlightConfiguration configuration; private final FlightConfiguration configuration;
private final DoubleModel theta, aoa, mach, roll; private final DoubleModel theta, aoa, mach, roll;
@ -80,37 +82,36 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
private boolean fakeChange = false; private boolean fakeChange = false;
private AerodynamicCalculator aerodynamicCalculator; private AerodynamicCalculator aerodynamicCalculator;
private final MassCalculator massCalculator = new MassCalculator(); private final MassCalculator massCalculator = new MassCalculator();
private final ColumnTableModel cpTableModel; private final ColumnTableModel cpTableModel;
private final ColumnTableModel dragTableModel; private final ColumnTableModel dragTableModel;
private final ColumnTableModel rollTableModel; private final ColumnTableModel rollTableModel;
private final JList warningList; private final JList<Object> warningList;
private final List<AerodynamicForces> cpData = new ArrayList<AerodynamicForces>(); private final List<Object[]> cgData = new ArrayList<Object[]>();
private final List<Coordinate> cgData = new ArrayList<Coordinate>();
private final List<AerodynamicForces> dragData = new ArrayList<AerodynamicForces>(); private final List<AerodynamicForces> dragData = new ArrayList<AerodynamicForces>();
private double totalCD = 0; private double totalCD = 0;
private final List<AerodynamicForces> rollData = new ArrayList<AerodynamicForces>(); private final List<AerodynamicForces> rollData = new ArrayList<AerodynamicForces>();
public ComponentAnalysisDialog(final RocketPanel rocketPanel) { public ComponentAnalysisDialog(final RocketPanel rocketPanel) {
////Component analysis ////Component analysis
super(SwingUtilities.getWindowAncestor(rocketPanel), super(SwingUtilities.getWindowAncestor(rocketPanel),
trans.get("componentanalysisdlg.componentanalysis")); trans.get("componentanalysisdlg.componentanalysis"));
JTable table; JTable table;
JPanel panel = new JPanel(new MigLayout("fill", "[][35lp::][fill][fill]")); JPanel panel = new JPanel(new MigLayout("fill"));
add(panel); add(panel);
this.configuration = rocketPanel.getConfiguration(); this.configuration = rocketPanel.getConfiguration();
this.aerodynamicCalculator = rocketPanel.getAerodynamicCalculator().newInstance(); this.aerodynamicCalculator = rocketPanel.getAerodynamicCalculator().newInstance();
conditions = new FlightConditions(configuration); conditions = new FlightConditions(configuration);
rocketPanel.setCPAOA(0); rocketPanel.setCPAOA(0);
aoa = new DoubleModel(rocketPanel, "CPAOA", UnitGroup.UNITS_ANGLE, 0, Math.PI); aoa = new DoubleModel(rocketPanel, "CPAOA", UnitGroup.UNITS_ANGLE, 0, Math.PI);
rocketPanel.setCPMach(Application.getPreferences().getDefaultMach()); rocketPanel.setCPMach(Application.getPreferences().getDefaultMach());
@ -119,7 +120,7 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
theta = new DoubleModel(rocketPanel, "CPTheta", UnitGroup.UNITS_ANGLE, 0, 2 * Math.PI); theta = new DoubleModel(rocketPanel, "CPTheta", UnitGroup.UNITS_ANGLE, 0, 2 * Math.PI);
rocketPanel.setCPRoll(0); rocketPanel.setCPRoll(0);
roll = new DoubleModel(rocketPanel, "CPRoll", UnitGroup.UNITS_ROLL); roll = new DoubleModel(rocketPanel, "CPRoll", UnitGroup.UNITS_ROLL);
//// Wind direction: //// Wind direction:
panel.add(new JLabel(trans.get("componentanalysisdlg.lbl.winddir")), "width 120lp!"); panel.add(new JLabel(trans.get("componentanalysisdlg.lbl.winddir")), "width 120lp!");
panel.add(new UnitSelector(theta, true), "width 50lp!"); panel.add(new UnitSelector(theta, true), "width 50lp!");
@ -142,60 +143,60 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
} }
}); });
panel.add(worstToggle, ""); panel.add(worstToggle, "");
warningList = new JList(); warningList = new JList<>();
JScrollPane scrollPane = new JScrollPane(warningList); JScrollPane scrollPane = new JScrollPane(warningList);
////Warnings: ////Warnings:
scrollPane.setBorder(BorderFactory.createTitledBorder(trans.get("componentanalysisdlg.TitledBorder.warnings"))); scrollPane.setBorder(BorderFactory.createTitledBorder(trans.get("componentanalysisdlg.TitledBorder.warnings")));
panel.add(scrollPane, "gap paragraph, spany 4, width 300lp!, growy 1, height :100lp:, wrap"); panel.add(scrollPane, "gap paragraph, spany 4, width 300lp!, growy 1, height :100lp:, wrap");
////Angle of attack: ////Angle of attack:
panel.add(new JLabel(trans.get("componentanalysisdlg.lbl.angleofattack")), "width 120lp!"); panel.add(new JLabel(trans.get("componentanalysisdlg.lbl.angleofattack")), "width 120lp!");
panel.add(new UnitSelector(aoa, true), "width 50lp!"); panel.add(new UnitSelector(aoa, true), "width 50lp!");
panel.add(new BasicSlider(aoa.getSliderModel(0, Math.PI)), "growx, wrap"); panel.add(new BasicSlider(aoa.getSliderModel(0, Math.PI)), "growx, wrap");
//// Mach number: //// Mach number:
panel.add(new JLabel(trans.get("componentanalysisdlg.lbl.machnumber")), "width 120lp!"); panel.add(new JLabel(trans.get("componentanalysisdlg.lbl.machnumber")), "width 120lp!");
panel.add(new UnitSelector(mach, true), "width 50lp!"); panel.add(new UnitSelector(mach, true), "width 50lp!");
panel.add(new BasicSlider(mach.getSliderModel(0, 3)), "growx, wrap"); panel.add(new BasicSlider(mach.getSliderModel(0, 3)), "growx, wrap");
//// Roll rate: //// Roll rate:
panel.add(new JLabel(trans.get("componentanalysisdlg.lbl.rollrate")), "width 120lp!"); panel.add(new JLabel(trans.get("componentanalysisdlg.lbl.rollrate")), "width 120lp!");
panel.add(new UnitSelector(roll, true), "width 50lp!"); panel.add(new UnitSelector(roll, true), "width 50lp!");
panel.add(new BasicSlider(roll.getSliderModel(-20 * 2 * Math.PI, 20 * 2 * Math.PI)), panel.add(new BasicSlider(roll.getSliderModel(-20 * 2 * Math.PI, 20 * 2 * Math.PI)),
"growx, wrap paragraph"); "growx, wrap");
// Stage and motor selection: // Stage and motor selection:
//// Active stages: //// Active stages:
panel.add(new JLabel(trans.get("componentanalysisdlg.lbl.activestages")), "spanx, split, gapafter rel"); panel.add(new JLabel(trans.get("componentanalysisdlg.lbl.activestages")), "spanx, split, gapafter rel");
panel.add(new StageSelector(configuration), "gapafter paragraph"); panel.add(new StageSelector(configuration), "gapafter paragraph");
//// Motor configuration: //// Motor configuration:
JLabel label = new JLabel(trans.get("componentanalysisdlg.lbl.motorconf")); JLabel label = new JLabel(trans.get("componentanalysisdlg.lbl.motorconf"));
label.setHorizontalAlignment(JLabel.RIGHT); label.setHorizontalAlignment(JLabel.RIGHT);
panel.add(label, "growx, right"); panel.add(label, "growx, right");
ParameterSetModel<FlightConfiguration> psm = new ParameterSetModel<FlightConfiguration>( configuration.getRocket().getConfigSet()); ParameterSetModel<FlightConfiguration> psm = new ParameterSetModel<FlightConfiguration>( configuration.getRocket().getConfigSet());
JComboBox<FlightConfiguration> combo = new JComboBox<FlightConfiguration>(psm); JComboBox<FlightConfiguration> combo = new JComboBox<FlightConfiguration>(psm);
panel.add(combo, "wrap"); panel.add(combo, "wrap");
// Tabbed pane // Tabbed pane
JTabbedPane tabbedPane = new JTabbedPane(); JTabbedPane tabbedPane = new JTabbedPane();
panel.add(tabbedPane, "spanx, growx, growy"); panel.add(tabbedPane, "spanx, growx, growy");
// Create the CP data table // Create the CP data table
cpTableModel = new ColumnTableModel( cpTableModel = new ColumnTableModel(
//// Component //// Component
new Column(trans.get("componentanalysisdlg.TabStability.Col.Component")) { new Column(trans.get("componentanalysisdlg.TabStability.Col.Component")) {
@Override @Override
public Object getValueAt(int row) { public Object getValueAt(int row) {
RocketComponent c = cpData.get(row).getComponent(); Object c = cgData.get(row)[0];
if (c instanceof Rocket) { if (c instanceof Rocket) {
return trans.get("componentanalysisdlg.TOTAL"); return trans.get("componentanalysisdlg.TOTAL");
} }
@ -212,7 +213,11 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
@Override @Override
public Object getValueAt(int row) { public Object getValueAt(int row) {
return unit.toString(cgData.get(row).x); Coordinate cg = (Coordinate) cgData.get(row)[1];
if ( cg == null ) {
return null;
}
return unit.toString(cg.x);
} }
}, },
new Column(trans.get("componentanalysisdlg.TabStability.Col.Mass") + " / " + UnitGroup.UNITS_MASS.getDefaultUnit().getUnit()) { new Column(trans.get("componentanalysisdlg.TabStability.Col.Mass") + " / " + UnitGroup.UNITS_MASS.getDefaultUnit().getUnit()) {
@ -220,7 +225,11 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
@Override @Override
public Object getValueAt(int row) { public Object getValueAt(int row) {
return unit.toString(cgData.get(row).weight); Coordinate cg = (Coordinate) cgData.get(row)[1];
if ( cg == null ) {
return null;
}
return unit.toString(cg.weight);
} }
}, },
new Column(trans.get("componentanalysisdlg.TabStability.Col.CP") + " / " + UnitGroup.UNITS_LENGTH.getDefaultUnit().getUnit()) { new Column(trans.get("componentanalysisdlg.TabStability.Col.CP") + " / " + UnitGroup.UNITS_LENGTH.getDefaultUnit().getUnit()) {
@ -228,42 +237,56 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
@Override @Override
public Object getValueAt(int row) { public Object getValueAt(int row) {
return unit.toString(cpData.get(row).getCP().x); AerodynamicForces forces = (AerodynamicForces) cgData.get(row)[2];
if ( forces == null ) {
return null;
}
return unit.toString(forces.getCP().x);
} }
}, },
new Column("<html>C<sub>N<sub>" + ALPHA + "</sub></sub>") { new Column("<html>C<sub>N<sub>" + ALPHA + "</sub></sub>") {
@Override @Override
public Object getValueAt(int row) { public Object getValueAt(int row) {
return NOUNIT.toString(cpData.get(row).getCP().weight); AerodynamicForces forces = (AerodynamicForces) cgData.get(row)[2];
if ( forces == null ) {
return null;
}
return NOUNIT.toString(forces.getCP().weight);
} }
} }
) { ) {
@Override /**
public int getRowCount() { *
return cpData.size(); */
} private static final long serialVersionUID = 1L;
};
@Override
public int getRowCount() {
return cgData.size();
}
};
table = new ColumnTable(cpTableModel); table = new ColumnTable(cpTableModel);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setSelectionBackground(Color.LIGHT_GRAY); table.setSelectionBackground(Color.LIGHT_GRAY);
table.setSelectionForeground(Color.BLACK); table.setSelectionForeground(Color.BLACK);
cpTableModel.setColumnWidths(table.getColumnModel()); cpTableModel.setColumnWidths(table.getColumnModel());
table.setDefaultRenderer(Object.class, new CustomCellRenderer()); table.setDefaultRenderer(Object.class, new CustomCellRenderer());
// table.setShowHorizontalLines(false); // table.setShowHorizontalLines(false);
// table.setShowVerticalLines(true); // table.setShowVerticalLines(true);
JScrollPane scrollpane = new JScrollPane(table); JScrollPane scrollpane = new JScrollPane(table);
scrollpane.setPreferredSize(new Dimension(600, 200)); scrollpane.setPreferredSize(new Dimension(600, 200));
//// Stability and Stability information //// Stability and Stability information
tabbedPane.addTab(trans.get("componentanalysisdlg.TabStability"), tabbedPane.addTab(trans.get("componentanalysisdlg.TabStability"),
null, scrollpane, trans.get("componentanalysisdlg.TabStability.ttip")); null, scrollpane, trans.get("componentanalysisdlg.TabStability.ttip"));
// Create the drag data table // Create the drag data table
dragTableModel = new ColumnTableModel( dragTableModel = new ColumnTableModel(
//// Component //// Component
@ -276,7 +299,7 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
} }
return c.toString(); return c.toString();
} }
@Override @Override
public int getDefaultWidth() { public int getDefaultWidth() {
return 200; return 200;
@ -311,33 +334,38 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
} }
} }
) { ) {
@Override /**
public int getRowCount() { *
return dragData.size(); */
} private static final long serialVersionUID = 1L;
};
@Override
public int getRowCount() {
return dragData.size();
}
};
table = new JTable(dragTableModel); table = new JTable(dragTableModel);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setSelectionBackground(Color.LIGHT_GRAY); table.setSelectionBackground(Color.LIGHT_GRAY);
table.setSelectionForeground(Color.BLACK); table.setSelectionForeground(Color.BLACK);
dragTableModel.setColumnWidths(table.getColumnModel()); dragTableModel.setColumnWidths(table.getColumnModel());
table.setDefaultRenderer(Object.class, new DragCellRenderer(new Color(0.5f, 1.0f, 0.5f))); table.setDefaultRenderer(Object.class, new DragCellRenderer(new Color(0.5f, 1.0f, 0.5f)));
// table.setShowHorizontalLines(false); // table.setShowHorizontalLines(false);
// table.setShowVerticalLines(true); // table.setShowVerticalLines(true);
scrollpane = new JScrollPane(table); scrollpane = new JScrollPane(table);
scrollpane.setPreferredSize(new Dimension(600, 200)); scrollpane.setPreferredSize(new Dimension(600, 200));
//// Drag characteristics and Drag characteristics tooltip //// Drag characteristics and Drag characteristics tooltip
tabbedPane.addTab(trans.get("componentanalysisdlg.dragTabchar"), null, scrollpane, tabbedPane.addTab(trans.get("componentanalysisdlg.dragTabchar"), null, scrollpane,
trans.get("componentanalysisdlg.dragTabchar.ttip")); trans.get("componentanalysisdlg.dragTabchar.ttip"));
// Create the roll data table // Create the roll data table
rollTableModel = new ColumnTableModel( rollTableModel = new ColumnTableModel(
//// Component //// Component
@ -373,30 +401,35 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
} }
} }
) { ) {
@Override /**
public int getRowCount() { *
return rollData.size(); */
} private static final long serialVersionUID = 1L;
};
@Override
public int getRowCount() {
return rollData.size();
}
};
table = new JTable(rollTableModel); table = new JTable(rollTableModel);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setSelectionBackground(Color.LIGHT_GRAY); table.setSelectionBackground(Color.LIGHT_GRAY);
table.setSelectionForeground(Color.BLACK); table.setSelectionForeground(Color.BLACK);
rollTableModel.setColumnWidths(table.getColumnModel()); table.setDefaultRenderer(Object.class, new CustomCellRenderer());
scrollpane = new JScrollPane(table); scrollpane = new JScrollPane(table);
scrollpane.setPreferredSize(new Dimension(600, 200)); scrollpane.setPreferredSize(new Dimension(600, 200));
//// Roll dynamics and Roll dynamics tooltip //// Roll dynamics and Roll dynamics tooltip
tabbedPane.addTab(trans.get("componentanalysisdlg.rollTableModel"), null, scrollpane, tabbedPane.addTab(trans.get("componentanalysisdlg.rollTableModel"), null, scrollpane,
trans.get("componentanalysisdlg.rollTableModel.ttip")); trans.get("componentanalysisdlg.rollTableModel.ttip"));
// Add the data updater to listen to changes in aoa and theta // Add the data updater to listen to changes in aoa and theta
mach.addChangeListener(this); mach.addChangeListener(this);
theta.addChangeListener(this); theta.addChangeListener(this);
@ -404,9 +437,9 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
roll.addChangeListener(this); roll.addChangeListener(this);
configuration.addChangeListener(this); configuration.addChangeListener(this);
this.stateChanged(null); this.stateChanged(null);
// Remove listeners when closing window // Remove listeners when closing window
this.addWindowListener(new WindowAdapter() { this.addWindowListener(new WindowAdapter() {
@Override @Override
@ -425,7 +458,7 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
singletonDialog = null; singletonDialog = null;
} }
}); });
//// Reference length: //// Reference length:
panel.add(new StyledLabel(trans.get("componentanalysisdlg.lbl.reflenght"), -1), panel.add(new StyledLabel(trans.get("componentanalysisdlg.lbl.reflenght"), -1),
"span, split, gapleft para, gapright rel"); "span, split, gapleft para, gapright rel");
@ -433,19 +466,19 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
UnitSelector sel = new UnitSelector(dm, true); UnitSelector sel = new UnitSelector(dm, true);
sel.resizeFont(-1); sel.resizeFont(-1);
panel.add(sel, "gapright para"); panel.add(sel, "gapright para");
//// Reference area: //// Reference area:
panel.add(new StyledLabel(trans.get("componentanalysisdlg.lbl.refarea"), -1), "gapright rel"); panel.add(new StyledLabel(trans.get("componentanalysisdlg.lbl.refarea"), -1), "gapright rel");
dm = new DoubleModel(conditions, "RefArea", UnitGroup.UNITS_AREA); dm = new DoubleModel(conditions, "RefArea", UnitGroup.UNITS_AREA);
sel = new UnitSelector(dm, true); sel = new UnitSelector(dm, true);
sel.resizeFont(-1); sel.resizeFont(-1);
panel.add(sel, "wrap"); panel.add(sel, "wrap");
// Buttons // Buttons
JButton button; JButton button;
// TODO: LOW: printing // TODO: LOW: printing
// button = new JButton("Print"); // button = new JButton("Print");
// button.addActionListener(new ActionListener() { // button.addActionListener(new ActionListener() {
@ -460,7 +493,7 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
// } // }
// }); // });
// panel.add(button,"tag ok"); // panel.add(button,"tag ok");
//button = new JButton("Close"); //button = new JButton("Close");
//Close button //Close button
button = new JButton(trans.get("dlg.but.close")); button = new JButton(trans.get("dlg.but.close"));
@ -470,18 +503,18 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
ComponentAnalysisDialog.this.dispose(); ComponentAnalysisDialog.this.dispose();
} }
}); });
panel.add(button, "span, split, tag cancel"); panel.add(button, "span, tag cancel");
this.setLocationByPlatform(true); this.setLocationByPlatform(true);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
pack(); pack();
GUIUtil.setDisposableDialogOptions(this, null); GUIUtil.setDisposableDialogOptions(this, null);
} }
/** /**
* Updates the data in the table and fires a table data change event. * Updates the data in the table and fires a table data change event.
*/ */
@ -494,7 +527,7 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
conditions.setMach(mach.getValue()); conditions.setMach(mach.getValue());
conditions.setRollRate(roll.getValue()); conditions.setRollRate(roll.getValue());
conditions.setReference(configuration); conditions.setReference(configuration);
if (worstToggle.isSelected()) { if (worstToggle.isSelected()) {
aerodynamicCalculator.getWorstCP(configuration, conditions, null); aerodynamicCalculator.getWorstCP(configuration, conditions, null);
if (!MathUtil.equals(conditions.getTheta(), theta.getValue())) { if (!MathUtil.equals(conditions.getTheta(), theta.getValue())) {
@ -504,27 +537,35 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
return; return;
} }
} }
Map<RocketComponent, AerodynamicForces> aeroData = Map<RocketComponent, AerodynamicForces> aeroData =
aerodynamicCalculator.getForceAnalysis(configuration, conditions, set); aerodynamicCalculator.getForceAnalysis(configuration, conditions, set);
Map<RocketComponent, Coordinate> massData = Map<RocketComponent, Coordinate> massData =
massCalculator.getCGAnalysis(configuration, MassCalcType.LAUNCH_MASS); massCalculator.getCGAnalysis(configuration, MassCalcType.LAUNCH_MASS);
cpData.clear();
cgData.clear(); cgData.clear();
dragData.clear(); dragData.clear();
rollData.clear(); rollData.clear();
for (RocketComponent c : configuration.getActiveComponents()) { for (RocketComponent c : configuration.getActiveComponents()) {
forces = aeroData.get(c); if ( c instanceof AxialStage ) {
Coordinate cg = massData.get(c);
if (forces == null)
continue; continue;
if (forces.getCP() != null) {
cpData.add(forces);
cgData.add(cg);
} }
Object[] data = new Object[3];
cgData.add(data);
data[0] = c;
Coordinate cg = massData.get(c);
data[1] = cg;
forces = aeroData.get(c);
if (forces == null) {
continue;
}
if (forces.getCP() != null) {
data[2] = forces;
}
if (!Double.isNaN(forces.getCD())) { if (!Double.isNaN(forces.getCD())) {
dragData.add(forces); dragData.add(forces);
} }
@ -532,17 +573,30 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
rollData.add(forces); rollData.add(forces);
} }
} }
for ( MotorConfiguration motorConfig : configuration.getActiveMotors()) {
Object [] data = new Object[3];
cgData.add(data);
data[0] = motorConfig.getMotor().getDesignation();
data[1] = MassCalcType.LAUNCH_MASS.getCG(motorConfig);
}
forces = aeroData.get(configuration.getRocket()); forces = aeroData.get(configuration.getRocket());
if (forces != null) { if (forces != null) {
cpData.add(forces); Object[] data = new Object[3];
cgData.add(massData.get(configuration.getRocket())); cgData.add(data);
data[0] = configuration.getRocket();
data[1] = massData.get(configuration.getRocket());
data[2] = forces;
dragData.add(forces); dragData.add(forces);
rollData.add(forces); rollData.add(forces);
totalCD = forces.getCD(); totalCD = forces.getCD();
} else { } else {
totalCD = 0; totalCD = 0;
} }
// Set warnings // Set warnings
if (set.isEmpty()) { if (set.isEmpty()) {
warningList.setListData(new String[] { warningList.setListData(new String[] {
@ -551,33 +605,37 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
} else { } else {
warningList.setListData(new Vector<Warning>(set)); warningList.setListData(new Vector<Warning>(set));
} }
cpTableModel.fireTableDataChanged(); cpTableModel.fireTableDataChanged();
dragTableModel.fireTableDataChanged(); dragTableModel.fireTableDataChanged();
rollTableModel.fireTableDataChanged(); rollTableModel.fireTableDataChanged();
} }
private class CustomCellRenderer extends JLabel implements TableCellRenderer { private class CustomCellRenderer extends JLabel implements TableCellRenderer {
/**
*
*/
private static final long serialVersionUID = 1L;
private final Font normalFont; private final Font normalFont;
private final Font boldFont; private final Font boldFont;
public CustomCellRenderer() { public CustomCellRenderer() {
super(); super();
normalFont = getFont(); normalFont = getFont();
boldFont = normalFont.deriveFont(Font.BOLD); boldFont = normalFont.deriveFont(Font.BOLD);
} }
@Override @Override
public Component getTableCellRendererComponent(JTable table, Object value, public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) { boolean isSelected, boolean hasFocus, int row, int column) {
this.setText(value.toString()); this.setText(value == null ? null : value.toString());
if ((row < 0) || (row >= cpData.size())) if ((row < 0) || (row >= cgData.size()))
return this; return this;
if (cpData.get(row).getComponent() instanceof Rocket) { if (cgData.get(row)[0] instanceof Rocket) {
this.setFont(boldFont); this.setFont(boldFont);
} else { } else {
this.setFont(normalFont); this.setFont(normalFont);
@ -585,52 +643,56 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
return this; return this;
} }
} }
private class DragCellRenderer extends JLabel implements TableCellRenderer { private class DragCellRenderer extends JLabel implements TableCellRenderer {
/**
*
*/
private static final long serialVersionUID = 1L;
private final Font normalFont; private final Font normalFont;
private final Font boldFont; private final Font boldFont;
public DragCellRenderer(Color baseColor) { public DragCellRenderer(Color baseColor) {
super(); super();
normalFont = getFont(); normalFont = getFont();
boldFont = normalFont.deriveFont(Font.BOLD); boldFont = normalFont.deriveFont(Font.BOLD);
} }
@Override @Override
public Component getTableCellRendererComponent(JTable table, Object value, public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) { boolean isSelected, boolean hasFocus, int row, int column) {
if (value instanceof Double) { if (value instanceof Double) {
// A drag coefficient // A drag coefficient
double cd = (Double) value; double cd = (Double) value;
this.setText(String.format("%.2f (%.0f%%)", cd, 100 * cd / totalCD)); this.setText(String.format("%.2f (%.0f%%)", cd, 100 * cd / totalCD));
float r = (float) (cd / 1.5); float r = (float) (cd / 1.5);
float hue = MathUtil.clamp(0.3333f * (1 - 2.0f * r), 0, 0.3333f); float hue = MathUtil.clamp(0.3333f * (1 - 2.0f * r), 0, 0.3333f);
float sat = MathUtil.clamp(0.8f * r + 0.1f * (1 - r), 0, 1); float sat = MathUtil.clamp(0.8f * r + 0.1f * (1 - r), 0, 1);
float val = 1.0f; float val = 1.0f;
this.setBackground(Color.getHSBColor(hue, sat, val)); this.setBackground(Color.getHSBColor(hue, sat, val));
this.setOpaque(true); this.setOpaque(true);
this.setHorizontalAlignment(SwingConstants.CENTER); this.setHorizontalAlignment(SwingConstants.CENTER);
} else { } else {
// Other // Other
this.setText(value.toString()); this.setText(value.toString());
this.setOpaque(false); this.setOpaque(false);
this.setHorizontalAlignment(SwingConstants.LEFT); this.setHorizontalAlignment(SwingConstants.LEFT);
} }
if ((row < 0) || (row >= dragData.size())) if ((row < 0) || (row >= dragData.size()))
return this; return this;
if ((dragData.get(row).getComponent() instanceof Rocket) || (column == 4)) { if ((dragData.get(row).getComponent() instanceof Rocket) || (column == 4)) {
this.setFont(boldFont); this.setFont(boldFont);
} else { } else {
@ -639,20 +701,20 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
return this; return this;
} }
} }
///////// Singleton implementation ///////// Singleton implementation
public static void showDialog(RocketPanel rocketpanel) { public static void showDialog(RocketPanel rocketpanel) {
if (singletonDialog != null) if (singletonDialog != null)
singletonDialog.dispose(); singletonDialog.dispose();
singletonDialog = new ComponentAnalysisDialog(rocketpanel); singletonDialog = new ComponentAnalysisDialog(rocketpanel);
singletonDialog.setVisible(true); singletonDialog.setVisible(true);
} }
public static void hideDialog() { public static void hideDialog() {
if (singletonDialog != null) if (singletonDialog != null)
singletonDialog.dispose(); singletonDialog.dispose();
} }
} }