Merge pull request #1759 from SiboVG/issue-1750

[#1750] Separate override subcomponents to mass, CG, and CD subcomponents override
This commit is contained in:
Joe Pfeiffer 2022-10-23 10:16:27 -06:00 committed by GitHub
commit e11fc35794
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 266 additions and 116 deletions

View File

@ -924,12 +924,14 @@ RocketCompCfg.but.Setforall = Set for all
RocketCompCfg.but.ttip.Setforall = Set this finish for all components of the rocket.
RocketCompCfg.checkbox.Overridemass = Override mass:
RocketCompCfg.checkbox.Overridemass.ttip = Overrides the mass of the component calculated by the component's volume and density.
RocketCompCfg.checkbox.Overridecenterofgrav = Override center of gravity:
RocketCompCfg.checkbox.Overridecenterofgrav.ttip = Overrides the component's center of gravity location.
RocketCompCfg.checkbox.SetDragCoeff = Override coefficient of drag:
RocketCompCfg.checkbox.SetDragCoeff.ttip = Overrides the component's coefficient of drag.
RocketCompCfg.checkbox.OverrideSubcomponents = Override mass, CG, and CD of all subcomponents
RocketCompCfg.checkbox.OverrideSubcomponents.ttip = <html>Overrides the aggregate mass, center of gravity (CG), and coefficient of drag (CD) of this component<br>and its subcomponents with the mass, CG, and CD of this component.</html>
RocketCompCfg.checkbox.Overridecenterofgrav = Override center of gravity CG:
RocketCompCfg.checkbox.Overridecenterofgrav.ttip = Overrides the component's center of gravity (CG) location.
RocketCompCfg.checkbox.SetDragCoeff = <html>Override coefficient of drag C<sub>D</sub>:</html>
RocketCompCfg.checkbox.SetDragCoeff.ttip = <html>Overrides the component's coefficient of drag C<sub>D</sub>.</html>
RocketCompCfg.checkbox.OverrideSubcomponents = Override for all subcomponents
RocketCompCfg.checkbox.OverrideSubcomponents.Mass.ttip = <html>Overrides the aggregate mass of this component<br>and its subcomponents with the mass of this component.</html>
RocketCompCfg.checkbox.OverrideSubcomponents.CG.ttip = <html>Overrides the center of gravity (CG) of this component<br>and its subcomponents with the CG of this component.</html>
RocketCompCfg.checkbox.OverrideSubcomponents.CD.ttip = <html>Overrides the coefficient of drag (C<sub>D</sub>) of this component<br>and its subcomponents with the C<sub>D</sub> of this component.</html>
RocketCompCfg.lbl.longB1 = <html>The overridden mass and center of gravity does not include motors.<br>
RocketCompCfg.lbl.longB2 = The center of gravity is measured from the front end of the
RocketCompCfg.lbl.Commentsonthe = Comments on the

View File

@ -642,7 +642,7 @@ RocketCompCfg.but.Setforall = Nastav pro v\u0161echny
RocketCompCfg.but.ttip.Setforall = Nastav povrchovou úpravu pro v\u0161echny komponenty rakety.
RocketCompCfg.checkbox.Overridemass = Zmen hmotnost:
RocketCompCfg.checkbox.Overridecenterofgrav = Zmen te\u017Ei\u0161te:
RocketCompCfg.checkbox.OverrideSubcomponents = Zmen hmotnost a te\u017Ei\u0161te v\u0161ech komponent
RocketCompCfg.checkbox.OverrideSubcomponents = P\u0159eps\u00E1n\u00ED pro v\u0161echny d\u00EDl\u010D\u00ED sou\u010D\u00E1sti
RocketCompCfg.lbl.longB1 = <html> Zmena hmotnosti nezahrnuje motory.<br>
RocketCompCfg.lbl.longB2 = Te\u017Ei\u0161te je mereno od predku
RocketCompCfg.lbl.Commentsonthe = Komentár na

View File

@ -831,7 +831,7 @@ RocketCompCfg.but.ttip.Setforall = Aplicar este acabado a todos
RocketCompCfg.checkbox.Endcapped = Extremo tapado
RocketCompCfg.checkbox.Overridecenterofgrav = Especificar el CG:
RocketCompCfg.checkbox.Overridemass = Especificar la masa:
RocketCompCfg.checkbox.OverrideSubcomponents = Incluir la masa y el CG de todos los subcomponentes
RocketCompCfg.checkbox.OverrideSubcomponents = Incluir de todos los subcomponentes
RocketCompCfg.checkbox.Usedefaultcolor = Usar color por defecto
RocketCompCfg.combo.ttip.componentmaterialaffects = El peso del componente depender\u00e1 del material seleccionado.
RocketCompCfg.lbl.Choosecolor = Elija color

View File

@ -823,7 +823,7 @@ RocketCompCfg.checkbox.Endcapped = Arri\u00E8re clos
RocketCompCfg.checkbox.Overridecenterofgrav = Forcer le centre de gravit\u00E9:
RocketCompCfg.checkbox.Overridecoeffofdrag = Modifier le coefficient de trainee:
RocketCompCfg.checkbox.Overridemass = Forcer la masse:
RocketCompCfg.checkbox.OverrideSubcomponents = Forcer la masse et le centre de gravit\u00E9 de tous les sous composants
RocketCompCfg.checkbox.OverrideSubcomponents = Forcer pour tous les sous composants
RocketCompCfg.checkbox.Usedefaultcolor = Utiliser la couleur par d\u00E9faut
RocketCompCfg.combo.ttip.componentmaterialaffects = Les mat\u00E9riaux utilis\u00E9s pour la pi\u00E8ce affectent le poids de la pi\u00E8ce.
RocketCompCfg.lbl.Choosecolor = Choisir la couleur

View File

@ -700,7 +700,7 @@ RocketCompCfg.but.Setforall = Imposta per tutti
RocketCompCfg.but.ttip.Setforall = Imposta questa finitura per tutti i componenti del razzo.
RocketCompCfg.checkbox.Overridemass = Modifica la massa:
RocketCompCfg.checkbox.Overridecenterofgrav = Sposta il centro di gravita':
RocketCompCfg.checkbox.OverrideSubcomponents = Modifica la massa ed il CG di tutti i subcomponenti
RocketCompCfg.checkbox.OverrideSubcomponents = Modifica di tutti i subcomponenti
RocketCompCfg.lbl.longB1 = <html>La massa modificata non include i motori.<br>
RocketCompCfg.lbl.longB2 = Il Centro di Gravita' e' misurato dall'inizio di
RocketCompCfg.lbl.Commentsonthe = Commenti sul

View File

@ -730,7 +730,7 @@ RocketCompCfg.but.Setforall = \u5168\u3066\u306B\u9069\u7528
RocketCompCfg.but.ttip.Setforall = \u3053\u306E\u4ED5\u4E0A\u3052\u65B9\u3092\u5168\u3066\u306E\u90E8\u54C1\u306B\u9069\u7528\u3059\u308B
RocketCompCfg.checkbox.Overridemass = \u8CEA\u91CF\u306E\u518D\u5B9A\u7FA9\uFF1A
RocketCompCfg.checkbox.Overridecenterofgrav = \u91CD\u5FC3\u306E\u518D\u5B9A\u7FA9\uFF1A
RocketCompCfg.checkbox.OverrideSubcomponents = \u5168\u3066\u306E\u30B5\u30D6\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\u306E\u8CEA\u91CF\u3068CG\u3092\u518D\u5B9A\u7FA9\uFF1A
RocketCompCfg.checkbox.OverrideSubcomponents = \u3059\u3079\u3066\u306e\u30b5\u30d6\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306b\u30aa\u30fc\u30d0\u30fc\u30e9\u30a4\u30c9\u3059\u308b
RocketCompCfg.lbl.longB1 = <html>\u518D\u5B9A\u7FA9\u3055\u308C\u305F\u8CEA\u91CF\u306B\u306F\u30E2\u30FC\u30BF\u30FC\u306F\u542B\u307E\u308C\u306A\u3044<br>
RocketCompCfg.lbl.longB2 = \u91CD\u5FC3\u306F\u90E8\u54C1\u306E\u524D\u65B9\u7AEF\u304B\u3089\u3001\u90E8\u54C1\uFF1A
RocketCompCfg.lbl.Commentsonthe = \u30B3\u30E1\u30F3\u30C8\uFF1A

View File

@ -851,7 +851,7 @@ RocketCompCfg.but.ttip.Setforall = Stel deze afwerking in voor alle onderdelen v
RocketCompCfg.checkbox.Overridemass = Overschrijf massa:
RocketCompCfg.checkbox.Overridecenterofgrav = Overschrijf zwaartepunt:
RocketCompCfg.checkbox.SetDragCoeff = Stel wrijvingscoëfficiënt in:
RocketCompCfg.checkbox.OverrideSubcomponents = Massa en zwaartepunt van alle subonderdelen overschrijven
RocketCompCfg.checkbox.OverrideSubcomponents = Voor alle subonderdelen overschrijven
RocketCompCfg.lbl.longB1 = <html>De overschreven massa omvat geen motoren.<br>
RocketCompCfg.lbl.longB2 = Het zwaartepunt wordt gemeten vanaf de voorkant van de
RocketCompCfg.lbl.Commentsonthe = Opmerkingen over de

View File

@ -644,7 +644,7 @@ update.dlg.latestVersion = Korzystasz z najnowszej wersji OpenRocket: %s.
RocketCompCfg.but.ttip.Setforall = Nadaj to wyko\u0144czenie wszystkim cz\u0119\u015Bci\u0105 sk\u0142adow\u0105 rakiety.
RocketCompCfg.checkbox.Overridemass = Wymu\u015B ci\u0119\u017Car:
RocketCompCfg.checkbox.Overridecenterofgrav = Wymu\u015B \u015Brodek ci\u0119\u017Cko\u015Bci:
RocketCompCfg.checkbox.OverrideSubcomponents = Wymu\u015B ci\u0119\u017Car oraz \u015Brodek ci\u0119\u017Cko\u015Bci wszystkich dodatkowych cz\u0119\u015Bci sk\u0142adowych
RocketCompCfg.checkbox.OverrideSubcomponents = Nadpisanie dla wszystkich podkomponent\u00F3w
RocketCompCfg.lbl.longB1 = <html>Wymuszony ci\u0119\u017Car nie uwzgl\u0119dnia silników.<br>
RocketCompCfg.lbl.longB2 = \u015Arodek ci\u0119\u017Cko\u015Bci jest mierzony od przodu
RocketCompCfg.lbl.Commentsonthe = Uwagi -

View File

@ -809,7 +809,7 @@ RocketCompCfg.checkbox.Endcapped = Fim tampado
RocketCompCfg.checkbox.Overridecenterofgrav = Modificar o centro de gravidade:
RocketCompCfg.checkbox.Overridecoeffofdrag = Modificar o coeficiente de arrasto:
RocketCompCfg.checkbox.Overridemass = Modificar massa:
RocketCompCfg.checkbox.OverrideSubcomponents = Modificar a massa e o CG de todos os subcomponentes
RocketCompCfg.checkbox.OverrideSubcomponents = Modificar de todos os subcomponentes
RocketCompCfg.checkbox.Usedefaultcolor = Use a cor padr\u00e3o
RocketCompCfg.combo.ttip.componentmaterialaffects = O material do componente afeta o peso do componente.
RocketCompCfg.lbl.Choosecolor = Escolha a cor

View File

@ -802,7 +802,7 @@ RocketCompCfg.but.ttip.Setforall = Set this finish for all components of the roc
RocketCompCfg.checkbox.Overridemass = Override mass:
RocketCompCfg.checkbox.Overridecenterofgrav = Override center of gravity:
RocketCompCfg.checkbox.Overridecoeffofdrag = Override coefficient of drag:
RocketCompCfg.checkbox.OverrideSubcomponents = Override mass and CG of all subcomponents
RocketCompCfg.checkbox.OverrideSubcomponents = Override for all subcomponents
RocketCompCfg.lbl.longB1 = <html>The overridden mass does not include motors.<br>
RocketCompCfg.lbl.longB2 = The center of gravity is measured from the front end of the
RocketCompCfg.lbl.Commentsonthe = Comments on the

View File

@ -46,6 +46,7 @@ public class OpenRocketSaver extends RocketSaver {
private static final String METHOD_PACKAGE = "net.sf.openrocket.file.openrocket.savers";
private static final String METHOD_SUFFIX = "Saver";
public static final String INDENT = " ";
// Estimated storage used by different portions
@ -636,10 +637,7 @@ public class OpenRocketSaver extends RocketSaver {
dest.write("\n");
return;
}
String s = "";
for (int i = 0; i < indent; i++)
s = s + " ";
s = s + str + "\n";
String s = INDENT.repeat(Math.max(0, indent)) + str + "\n";
dest.write(s);
}

View File

@ -40,7 +40,8 @@ class ComponentParameterHandler extends AbstractElementHandler {
if ( element.equals("appearance")) {
return new AppearanceHandler(component,context);
}
if (element.equals("inside-appearance")) {
// TODO: delete 'inside-appearance' when backward compatibility with 22.02.beta.01-22.02.beta.05 is not needed anymore
if (element.equals("insideappearance") || element.equals("inside-appearance")) {
return new InsideAppearanceHandler(component, context);
}
if (element.equals("motormount")) {
@ -92,10 +93,11 @@ class ComponentParameterHandler extends AbstractElementHandler {
@Override
public void closeElement(String element, HashMap<String, String> attributes,
String content, WarningSet warnings) {
// TODO: delete 'inside-appearance' when backward compatibility with 22.02.beta.01-22.02.beta.05 is not needed anymore
if (element.equals("subcomponents") || element.equals("motormount") ||
element.equals("finpoints") || element.equals("motorconfiguration") ||
element.equals("appearance") || element.equals("inside-appearance") ||
element.equals("appearance") || element.equals("insideappearance") || element.equals("inside-appearance") ||
element.equals("deploymentconfiguration") || element.equals("separationconfiguration")) {
return;
}

View File

@ -129,8 +129,16 @@ class DocumentConfig {
setters.put("RocketComponent:overridecd", new OverrideSetter(
Reflection.findMethod(RocketComponent.class, "setOverrideCD", double.class),
Reflection.findMethod(RocketComponent.class, "setCDOverridden", boolean.class)));
// TODO: delete overridesubcomponents setters if no compatibility is needed anymore with OR 15.03
setters.put("RocketComponent:overridesubcomponents", new BooleanSetter(
Reflection.findMethod(RocketComponent.class, "setSubcomponentsOverridden", boolean.class)));
setters.put("RocketComponent:overridesubcomponentsmass", new BooleanSetter(
Reflection.findMethod(RocketComponent.class, "setSubcomponentsOverriddenMass", boolean.class)));
setters.put("RocketComponent:overridesubcomponentscg", new BooleanSetter(
Reflection.findMethod(RocketComponent.class, "setSubcomponentsOverriddenCG", boolean.class)));
setters.put("RocketComponent:overridesubcomponentscd", new BooleanSetter(
Reflection.findMethod(RocketComponent.class, "setSubcomponentsOverriddenCD", boolean.class)));
setters.put("RocketComponent:comment", new StringSetter(
Reflection.findMethod(RocketComponent.class, "setComment", String.class)));
setters.put("RocketComponent:preset", new ComponentPresetSetter(

View File

@ -21,13 +21,15 @@ public class InsideAppearanceHandler extends AppearanceHandler {
@Override
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
if ("edgesSameAsInside".equals(element)) {
// TODO: delete 'edgesSameAsInside' when backward compatibility with 22.02.beta.01-22.02.beta.05 is not needed anymore
if ("edgessameasinside".equals(element) || "edgesSameAsInside".equals(element)) {
boolean edgesSameAsInside = Boolean.parseBoolean(content);
if (component instanceof InsideColorComponent)
((InsideColorComponent)component).getInsideColorComponentHandler().setEdgesSameAsInside(edgesSameAsInside);
return;
}
if ("insideSameAsOutside".equals(element)) {
// TODO: delete 'insideSameAsOutside' when backward compatibility with 22.02.beta.01-22.02.beta.05 is not needed anymore
if ("insidesameasoutside".equals(element) || "insideSameAsOutside".equals(element)) {
boolean insideSameAsOutside = Boolean.parseBoolean(content);
if (component instanceof InsideColorComponent)
((InsideColorComponent)component).getInsideColorComponentHandler().setSeparateInsideOutside(insideSameAsOutside);

View File

@ -9,6 +9,7 @@ import java.util.Map;
import net.sf.openrocket.appearance.Appearance;
import net.sf.openrocket.appearance.Decal;
import net.sf.openrocket.appearance.Decal.EdgeMode;
import net.sf.openrocket.file.openrocket.OpenRocketSaver;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.motor.Motor;
@ -56,18 +57,18 @@ public class RocketComponentSaver {
InsideColorComponentHandler handler = ((InsideColorComponent)c).getInsideColorComponentHandler();
Appearance ap_in = handler.getInsideAppearance();
if (ap_in != null) {
elements.add("<inside-appearance>");
elements.add("<edgesSameAsInside>" + handler.isEdgesSameAsInside() + "</edgesSameAsInside>");
elements.add("<insideSameAsOutside>" + handler.isSeparateInsideOutside() + "</insideSameAsOutside>");
elements.add("<insideappearance>");
appendElement(elements, "edgessameasinside", handler.isEdgesSameAsInside(), 1);
appendElement(elements, "insidesameasoutside", handler.isSeparateInsideOutside(), 1);
buildAppearanceElements(elements, ap_in);
elements.add("</inside-appearance>");
elements.add("</insideappearance>");
}
}
// Save color and line style if significant
if (!(c instanceof Rocket || c instanceof ComponentAssembly)) {
Color color = c.getColor();
emitColor("color", elements, color);
emitColor("color", elements, color, 0);
LineStyle style = c.getLineStyle();
if (style != null) {
@ -128,22 +129,20 @@ public class RocketComponentSaver {
}
// Overrides
boolean overridden = false;
if (c.isMassOverridden()) {
elements.add("<overridemass>" + c.getOverrideMass() + "</overridemass>");
overridden = true;
elements.add("<overridesubcomponentsmass>" + c.isSubcomponentsOverriddenMass()
+ "</overridesubcomponentsmass>");
}
if (c.isCGOverridden()) {
elements.add("<overridecg>" + c.getOverrideCGX() + "</overridecg>");
overridden = true;
elements.add("<overridesubcomponentscg>" + c.isSubcomponentsOverriddenCG()
+ "</overridesubcomponentscg>");
}
if (c.isCDOverridden()) {
elements.add("<overridecd>" + c.getOverrideCD() + "</overridecd>");
overridden = true;
}
if (overridden) {
elements.add("<overridesubcomponents>" + c.isSubcomponentsOverridden()
+ "</overridesubcomponents>");
elements.add("<overridesubcomponentscd>" + c.isSubcomponentsOverriddenCD()
+ "</overridesubcomponentscd>");
}
@ -156,21 +155,21 @@ public class RocketComponentSaver {
private void buildAppearanceElements(List<String> elements, Appearance a) {
Color paint = a.getPaint();
emitColor("paint", elements, paint);
elements.add("<shine>" + a.getShine() + "</shine>");
emitColor("paint", elements, paint, 1);
appendElement(elements, "shine", a.getShine(), 1);
Decal decal = a.getTexture();
if (decal != null) {
String name = decal.getImage().getName();
double rotation = decal.getRotation();
EdgeMode edgeMode = decal.getEdgeMode();
elements.add("<decal name=\"" + TextUtil.escapeXML(name) + "\" rotation=\"" + rotation + "\" edgemode=\"" + edgeMode.name() + "\">");
elements.add(OpenRocketSaver.INDENT + "<decal name=\"" + TextUtil.escapeXML(name) + "\" rotation=\"" + rotation + "\" edgemode=\"" + edgeMode.name() + "\">");
Coordinate center = decal.getCenter();
elements.add("<center x=\"" + center.x + "\" y=\"" + center.y + "\"/>");
elements.add(OpenRocketSaver.INDENT.repeat(2) + "<center x=\"" + center.x + "\" y=\"" + center.y + "\"/>");
Coordinate offset = decal.getOffset();
elements.add("<offset x=\"" + offset.x + "\" y=\"" + offset.y + "\"/>");
elements.add(OpenRocketSaver.INDENT.repeat(2) + "<offset x=\"" + offset.x + "\" y=\"" + offset.y + "\"/>");
Coordinate scale = decal.getScale();
elements.add("<scale x=\"" + scale.x + "\" y=\"" + scale.y + "\"/>");
elements.add("</decal>");
elements.add(OpenRocketSaver.INDENT.repeat(2) + "<scale x=\"" + scale.x + "\" y=\"" + scale.y + "\"/>");
elements.add(OpenRocketSaver.INDENT + "</decal>");
}
}
@ -270,12 +269,11 @@ public class RocketComponentSaver {
return elements;
}
private final static void emitColor(String elementName, List<String> elements, Color color) {
private final static void emitColor(String elementName, List<String> elements, Color color, int indents) {
if (color != null) {
elements.add("<" + elementName + " red=\"" + color.getRed() + "\" green=\"" + color.getGreen()
elements.add(OpenRocketSaver.INDENT.repeat(Math.max(0, indents)) + "<" + elementName + " red=\"" + color.getRed() + "\" green=\"" + color.getGreen()
+ "\" blue=\"" + color.getBlue() + "\" alpha=\"" + color.getAlpha() + "\"/>");
}
}
protected static void emitDouble( final List<String> elements, final String enclosingTag, final double value){
@ -302,8 +300,20 @@ public class RocketComponentSaver {
return buf.toString();
}
protected static void appendElement( final List<String> elements, final String openTag, final String closeTag, final String elementValue, final int indents){
elements.add(OpenRocketSaver.INDENT.repeat(Math.max(0, indents)) + "<"+openTag+">" + elementValue + "</"+closeTag+">");
}
protected static void appendElement( final List<String> elements, final String tag, final double elementValue, final int indents){
appendElement(elements, tag, tag, Double.toString(elementValue), indents);
}
protected static void appendElement( final List<String> elements, final String tag, final boolean elementValue, final int indents){
appendElement(elements, tag, tag, Boolean.toString(elementValue), indents);
}
protected static void appendElement( final List<String> elements, final String openTag, final String closeTag, final String elementValue ){
elements.add("<"+openTag+">" + elementValue + "</"+closeTag+">");
appendElement(elements, openTag, closeTag, elementValue, 0);
}
}

View File

@ -175,7 +175,8 @@ public abstract class BaseHandler<C extends RocketComponent> extends AbstractEle
if (override) {
component.setCGOverridden(override);
component.setMassOverridden(override);
component.setSubcomponentsOverridden(false); //Rocksim does not support this type of override
component.setSubcomponentsOverriddenMass(false); //Rocksim does not support this type of override
component.setSubcomponentsOverriddenCG(false); //Rocksim does not support this type of override
component.setOverrideMass(mass);
component.setOverrideCGX(cg);
}

View File

@ -208,12 +208,12 @@ class RocketDesignHandler extends AbstractElementHandler {
final AxialStage stage = new AxialStage();
if (stage3Mass > 0.0d) {
stage.setMassOverridden(true);
stage.setSubcomponentsOverridden(true); //Rocksim does not support this type of override
stage.setSubcomponentsOverriddenMass(true); //Rocksim does not support this type of override
stage.setOverrideMass(stage3Mass);
}
if (stage3CG > 0.0d) {
stage.setCGOverridden(true);
stage.setSubcomponentsOverridden(true); //Rocksim does not support this type of override
stage.setSubcomponentsOverriddenCG(true); //Rocksim does not support this type of override
stage.setOverrideCGX(stage3CG);
}
component.addChild(stage);
@ -224,12 +224,12 @@ class RocketDesignHandler extends AbstractElementHandler {
final AxialStage stage = new AxialStage();
if (stage2Mass > 0.0d) {
stage.setMassOverridden(true);
stage.setSubcomponentsOverridden(true); //Rocksim does not support this type of override
stage.setSubcomponentsOverriddenMass(true); //Rocksim does not support this type of override
stage.setOverrideMass(stage2Mass);
}
if (stage2CG > 0.0d) {
stage.setCGOverridden(true);
stage.setSubcomponentsOverridden(true); //Rocksim does not support this type of override
stage.setSubcomponentsOverriddenCG(true); //Rocksim does not support this type of override
stage.setOverrideCGX(stage2CG);
}
component.addChild(stage);
@ -241,12 +241,12 @@ class RocketDesignHandler extends AbstractElementHandler {
final AxialStage stage = new AxialStage();
if (stage1Mass > 0.0d) {
stage.setMassOverridden(true);
stage.setSubcomponentsOverridden(true); //Rocksim does not support this type of override
stage.setSubcomponentsOverriddenMass(true); //Rocksim does not support this type of override
stage.setOverrideMass(stage1Mass);
}
if (stage1CG > 0.0d) {
stage.setCGOverridden(true);
stage.setSubcomponentsOverridden(true); //Rocksim does not support this type of override
stage.setSubcomponentsOverriddenCG(true); //Rocksim does not support this type of override
stage.setOverrideCGX(stage1CG);
}
component.addChild(stage);

View File

@ -355,16 +355,16 @@ public class MassCalculation {
// setting zero as the CG position means the top of the component, which is component.getPosition()
final Coordinate compZero = parentTransform.transform( component.getPosition() );
if (component.isSubcomponentsOverridden()) {
if( component.isMassive() ){
if (component.isSubcomponentsOverriddenMass() || component.isSubcomponentsOverriddenCG()) {
if (component.isMassive()) {
// if this component mass, merge it in before overriding:
this.addMass( compCM );
}
if (component.isMassOverridden()) {
if (component.isSubcomponentsOverriddenMass() && component.isMassOverridden()) {
this.setCM( this.getCM().setWeight(component.getOverrideMass()) );
}
if (component.isCGOverridden()) {
this.setCM( this.getCM().setX( compZero.x + component.getOverrideCGX()));
if (component.isSubcomponentsOverriddenCG() && component.isCGOverridden()) {
this.setCM( this.getCM().setX(compZero.x + component.getOverrideCGX()));
}
}else {
if (component.isMassOverridden()) {

View File

@ -99,15 +99,17 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
// Override mass/CG/CD
protected double overrideMass = 0;
protected boolean massOverridden = false;
private boolean overrideSubcomponentsMass = false;
private double overrideCGX = 0;
private boolean cgOverridden = false;
private boolean overrideSubcomponentsCG = false;
private double overrideCD = 0;
private boolean cdOverridden = false;
private boolean overrideSubcomponentsCD = false;
private boolean cdOverriddenByAncestor = false;
private boolean overrideSubcomponents = false;
// User-given name of the component
@ -707,7 +709,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
this.overrideCD = x;
if (isCDOverridden()) {
if (isSubcomponentsOverridden()) {
if (isSubcomponentsOverriddenCD()) {
overrideSubcomponentsCD(true);
}
fireComponentChangeEvent(ComponentChangeEvent.AERODYNAMIC_CHANGE);
@ -749,7 +751,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
// tree. If we are overriding our own CD, we need to override all
// our descendants. If we are not overriding our own CD, we are
// also not overriding our descendants
if (isSubcomponentsOverridden()) {
if (isSubcomponentsOverriddenCD()) {
overrideSubcomponentsCD(o);
}
@ -777,28 +779,107 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
*
* @return whether the current mass, CG, and/or CD override overrides subcomponents as well.
*/
public boolean isSubcomponentsOverridden() {
public boolean isSubcomponentsOverriddenMass() {
mutex.verify();
return overrideSubcomponents;
return overrideSubcomponentsMass;
}
// TODO: delete no compatibility is needed anymore with OR 15.03
public void setSubcomponentsOverridden(boolean override) {
setSubcomponentsOverriddenMass(override);
setSubcomponentsOverriddenCG(override);
setSubcomponentsOverriddenCD(override);
}
/**
* Set whether the mass and/or CG override overrides all subcomponent values
* as well. See {@link #isSubcomponentsOverridden()} for details.
* as well. See {@link #isSubcomponentsOverriddenMass()} for details.
*
* @param override whether the mass and/or CG override overrides all subcomponent.
*/
public void setSubcomponentsOverridden(boolean override) {
public void setSubcomponentsOverriddenMass(boolean override) {
for (RocketComponent listener : configListeners) {
listener.setSubcomponentsOverridden(override);
listener.setSubcomponentsOverriddenMass(override);
}
if (overrideSubcomponents == override) {
if (overrideSubcomponentsMass == override) {
return;
}
checkState();
overrideSubcomponents = override;
overrideSubcomponentsMass = override;
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
/**
* Return whether the CG override overrides all subcomponent values
* as well. The default implementation is a normal getter/setter implementation,
* however, subclasses are allowed to override this behavior if some subclass
* always or never overrides subcomponents. In this case the subclass should
* also override {@link #isOverrideSubcomponentsEnabled()} to return
* <code>false</code>.
*
* @return whether the current CG override overrides subcomponents as well.
*/
public boolean isSubcomponentsOverriddenCG() {
mutex.verify();
return overrideSubcomponentsCG;
}
/**
* Set whether the mass and/or CG override overrides all subcomponent values
* as well. See {@link #isSubcomponentsOverriddenCG()} for details.
*
* @param override whether the mass and/or CG override overrides all subcomponent.
*/
public void setSubcomponentsOverriddenCG(boolean override) {
for (RocketComponent listener : configListeners) {
listener.setSubcomponentsOverriddenCG(override);
}
if (overrideSubcomponentsCG == override) {
return;
}
checkState();
overrideSubcomponentsCG = override;
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
/**
* Return whether the CD override overrides all subcomponent values
* as well. The default implementation is a normal getter/setter implementation,
* however, subclasses are allowed to override this behavior if some subclass
* always or never overrides subcomponents. In this case the subclass should
* also override {@link #isOverrideSubcomponentsEnabled()} to return
* <code>false</code>.
*
* @return whether the current CD override overrides subcomponents as well.
*/
public boolean isSubcomponentsOverriddenCD() {
mutex.verify();
return overrideSubcomponentsCD;
}
/**
* Set whether the CD override overrides all subcomponent values
* as well. See {@link #isSubcomponentsOverriddenCD()} for details.
*
* @param override whether the CD override overrides all subcomponent.
*/
public void setSubcomponentsOverriddenCD(boolean override) {
for (RocketComponent listener : configListeners) {
listener.setSubcomponentsOverriddenCD(override);
}
if (overrideSubcomponentsCD == override) {
return;
}
checkState();
overrideSubcomponentsCD = override;
overrideSubcomponentsCD(override);
@ -815,7 +896,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
* If we are setting the override false, descend the component tree marking every
* component as not overridden by ancestor.
* If in the course of descending the tree we encounter a descendant whose direct
* CD override and overridesubcomponents flags are both true, descend from there
* CD override and overrideSubcomponentsCD flags are both true, descend from there
* setting the ancestoroverride from that component
*
* @param override whether setting or clearing overrides
@ -827,7 +908,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
c.cdOverriddenByAncestor = override;
if (!override && c.isCDOverridden() && c.isSubcomponentsOverridden()) {
if (!override && c.isCDOverridden() && c.isSubcomponentsOverriddenCD()) {
c.overrideSubcomponentsCD(true);
} else {
c.overrideSubcomponentsCD(override);
@ -2334,7 +2415,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
this.overrideCGX = src.overrideCGX;
this.cgOverridden = src.cgOverridden;
this.cdOverriddenByAncestor = src.cdOverriddenByAncestor;
this.overrideSubcomponents = src.overrideSubcomponents;
this.overrideSubcomponentsMass = src.overrideSubcomponentsMass;
this.overrideSubcomponentsCG = src.overrideSubcomponentsCG;
this.overrideSubcomponentsCD = src.overrideSubcomponentsCD;
this.name = src.name;
this.comment = src.comment;
this.id = src.id;

View File

@ -345,7 +345,8 @@ public class TestRockets {
c.setMassOverridden(rnd.nextBoolean());
c.setOverrideCGX(rnd(0.2));
c.setOverrideMass(rnd(0.05));
c.setSubcomponentsOverridden(rnd.nextBoolean());
c.setSubcomponentsOverriddenMass(rnd.nextBoolean());
c.setSubcomponentsOverriddenCG(rnd.nextBoolean());
if (c.isMassive()) {
// Only massive components are drawn

View File

@ -81,7 +81,7 @@ public class MassCalculatorTest extends BaseTestCase {
// if we use a mass override, setting to same mass, we should get same result
AxialStage sustainer = (AxialStage) rocket.getChild(0);
sustainer.setSubcomponentsOverridden(true);
sustainer.setSubcomponentsOverriddenMass(true);
sustainer.setMassOverridden(true);
sustainer.setOverrideMass(actualRocketDryMass);
@ -219,7 +219,7 @@ public class MassCalculatorTest extends BaseTestCase {
assertEquals(expCMx, actualRocketDryCM.x, EPSILON);
}
boosterStage.setSubcomponentsOverridden(true);
boosterStage.setSubcomponentsOverriddenCG(true);
boosterStage.setCGOverridden(true);
boosterStage.setOverrideCGX(0.0);
@ -260,7 +260,7 @@ public class MassCalculatorTest extends BaseTestCase {
assertEquals(0.05, actualRocketDryCM.x, EPSILON);
}
sustainerStage.setSubcomponentsOverridden(true);
sustainerStage.setSubcomponentsOverriddenMass(true);
sustainerStage.setMassOverridden(true);
sustainerStage.setOverrideMass(0.001); // something small, but not zero
@ -302,7 +302,7 @@ public class MassCalculatorTest extends BaseTestCase {
assertEquals(0.10, actualStructure.cm.x, EPSILON);
}
boosterStage.setSubcomponentsOverridden(true);
boosterStage.setSubcomponentsOverriddenMass(true);
boosterStage.setMassOverridden(true);
boosterStage.setOverrideMass(0.001); // something small, but not zero
@ -346,7 +346,7 @@ public class MassCalculatorTest extends BaseTestCase {
assertEquals(expCMx, actualRocketDryCM.x, EPSILON);
}
boosterBody.setSubcomponentsOverridden(false);
boosterBody.setSubcomponentsOverriddenCG(false);
boosterBody.setCGOverridden(true);
boosterBody.setOverrideCGX(0.0);
@ -395,7 +395,7 @@ public class MassCalculatorTest extends BaseTestCase {
assertEquals(expCMx, actualRocketDryCM.x, EPSILON);
}
boosterBody.setSubcomponentsOverridden(false);
boosterBody.setSubcomponentsOverriddenMass(false);
boosterBody.setMassOverridden(true);
boosterBody.setOverrideMass(0.001);
@ -409,7 +409,7 @@ public class MassCalculatorTest extends BaseTestCase {
assertEquals(0.06976699, actualRocketDryCM.x, EPSILON);
}
boosterBody.setSubcomponentsOverridden(true); // change. Also, this body lacks subcomponents.
boosterBody.setSubcomponentsOverriddenMass(true); // change. Also, this body lacks subcomponents.
boosterBody.setMassOverridden(true); // repeat
boosterBody.setOverrideMass(0.001); // repeat
@ -973,9 +973,10 @@ public class MassCalculatorTest extends BaseTestCase {
final AxialStage coreStage = (AxialStage) rocket.getChild(1);
final ParallelStage boosters = (ParallelStage) coreStage.getChild(0).getChild(0);
final double overrideMass = 0.5;
boosters.setSubcomponentsOverridden(true);
boosters.setSubcomponentsOverriddenMass(true);
boosters.setMassOverridden(true);
boosters.setOverrideMass(overrideMass);
boosters.setSubcomponentsOverriddenCG(true);
boosters.setCGOverridden(true);
boosters.setOverrideCGX(6.0);
@ -1140,7 +1141,7 @@ public class MassCalculatorTest extends BaseTestCase {
fins.setName("podFins");
fins.setThickness(0.01);
fins.setMassOverridden(true); fins.setOverrideMass(0.02835);
fins.setSubcomponentsOverridden(false);
fins.setSubcomponentsOverriddenMass(false);
fins.setAxialOffset(-0.01); fins.setAxialMethod(AxialMethod.BOTTOM);
podBody.addChild(fins);
@ -1207,12 +1208,12 @@ public class MassCalculatorTest extends BaseTestCase {
// if we use a mass override, setting to same mass, we should get same result
AxialStage sustainerRef = (AxialStage) rocketRef.getChild(0);
sustainerRef.setSubcomponentsOverridden(true);
sustainerRef.setSubcomponentsOverriddenMass(true);
sustainerRef.setMassOverridden(true);
sustainerRef.setOverrideMass(rocketDryMassRef);
AxialStage sustainer = (AxialStage) rocket.getChild(0);
sustainer.setSubcomponentsOverridden(true);
sustainer.setSubcomponentsOverriddenMass(true);
sustainer.setMassOverridden(true);
sustainer.setOverrideMass(rocketDryMass);

View File

@ -54,7 +54,8 @@ public class FreeformFinSetTest extends BaseTestCase {
sourceSet.setMaterial(Material.newMaterial(Type.BULK, "test-material", 0.1, true));
sourceSet.setOverrideCGX(0.012);
sourceSet.setOverrideMass(0.0123);
sourceSet.setSubcomponentsOverridden(true);
sourceSet.setSubcomponentsOverriddenMass(true);
sourceSet.setSubcomponentsOverriddenCG(true);
sourceSet.setAxialMethod(AxialMethod.ABSOLUTE);
sourceSet.setAxialOffset(0.1);
sourceSet.setTabHeight(0.01);
@ -196,7 +197,8 @@ public class FreeformFinSetTest extends BaseTestCase {
}
assertEquals(0.012, finSet.getOverrideCGX(), EPSILON);
assertEquals(0.0123, finSet.getOverrideMass(), EPSILON);
assertTrue(finSet.isSubcomponentsOverridden());
assertTrue(finSet.isSubcomponentsOverriddenMass());
assertTrue(finSet.isSubcomponentsOverriddenCG());
assertEquals(AxialMethod.ABSOLUTE, finSet.getAxialMethod());
assertEquals(0.1, finSet.getAxialOffset(), EPSILON);
@ -232,7 +234,8 @@ public class FreeformFinSetTest extends BaseTestCase {
}
assertEquals(0.012, finSet.getOverrideCGX(), EPSILON);
assertEquals(0.0123, finSet.getOverrideMass(), EPSILON);
assertTrue(finSet.isSubcomponentsOverridden());
assertTrue(finSet.isSubcomponentsOverriddenMass());
assertTrue(finSet.isSubcomponentsOverriddenCG());
assertEquals(AxialMethod.ABSOLUTE, finSet.getAxialMethod());
assertEquals(0.1, finSet.getAxialOffset(), EPSILON);

View File

@ -65,19 +65,19 @@ public class OverrideTest extends BaseTestCase {
// We start by just checking the override flags
// Initially no overrides
assertFalse(sustainer.isCDOverridden());
assertFalse(sustainer.isSubcomponentsOverridden());
assertFalse(sustainer.isSubcomponentsOverriddenCD());
assertFalse(sustainer.isCDOverriddenByAncestor());
assertFalse(bodytube.isCDOverridden());
assertFalse(bodytube.isSubcomponentsOverridden());
assertFalse(bodytube.isSubcomponentsOverriddenCD());
assertFalse(bodytube.isCDOverriddenByAncestor());
assertFalse(finset.isCDOverridden());
assertFalse(finset.isSubcomponentsOverridden());
assertFalse(finset.isSubcomponentsOverriddenCD());
assertFalse(finset.isCDOverriddenByAncestor());
// Override sustainer CD and subcomponents
sustainer.setSubcomponentsOverridden(true);
sustainer.setSubcomponentsOverriddenCD(true);
sustainer.setCDOverridden(true);
sustainer.setOverrideCD(0.5);
@ -87,7 +87,7 @@ public class OverrideTest extends BaseTestCase {
// Set body tube to override subcomponents, override its CD; it's still
// overridden by ancestor
bodytube.setCDOverridden(true);
bodytube.setSubcomponentsOverridden(true);
bodytube.setSubcomponentsOverriddenCD(true);
bodytube.setOverrideCD(0.25);
assertTrue(bodytube.isCDOverriddenByAncestor());
@ -103,7 +103,7 @@ public class OverrideTest extends BaseTestCase {
assertEquals(sustainer.getOverrideCD(), forces.getCD(), MathUtil.EPSILON);
// Turn off sustainer subcomponents override; body tube and nose cone aren't overridden by ancestor but fin set is
sustainer.setSubcomponentsOverridden(false);
sustainer.setSubcomponentsOverriddenCD(false);
// CD of rocket should be overridden CD of sustainer plus body tube plus calculated CD of nose cone
Map<RocketComponent, AerodynamicForces> forceMap = calc.getForceAnalysis(configuration, conditions, warnings);

View File

@ -50,3 +50,14 @@ The following file format versions exist:
1.7: Introduced with OpenRocket 15.03.
Added simulation extensions and related configuration.
Support for TubeFins.
1.8: Introduced with OpenRocket 22.02.
Added new RailButton (<railbutton>, Pods (<podset>), and Booster (<parallelstage>) components
Added separate internal appearance option (<insideappearance>) for Body Tubes, Nose Cones,
Transitions, Inner Tubes, Launch Lugs, and Fins.
Added PhotoStudio settings saving (<photostudio>)
Added override CD parameter (<overridecd>)
Separated <overridesubcomponents> into individual parameters for mass, CG, and CD.
Rename <fincount> to <instancecount> (<fincount> remains for backward compatibility)
Rename <position> to <axialoffset> (<position> remains for backward compatibility)
Rename <rotation> to <angleoffset> (<rotation> remains for backward compatibility)

View File

@ -4,6 +4,7 @@ package net.sf.openrocket.gui.configdialog;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Iterator;
@ -236,7 +237,7 @@ public class RocketComponentConfig extends JPanel {
}
for (RocketComponent c = component.getParent(); c != null; c = c.getParent()) {
if (c.isMassOverridden() && c.isSubcomponentsOverridden()) {
if (c.isMassOverridden() && c.isSubcomponentsOverriddenMass()) {
overridetext = trans.get("RocketCompCfg.lbl.overriddenby") + " " + c.getName() + ")";
}
}
@ -359,14 +360,28 @@ public class RocketComponentConfig extends JPanel {
BasicSlider bs;
// OVERRIDE MASS ----------------------------------
JPanel checkboxes = new JPanel(new MigLayout("inset 0"));
bm = new BooleanModel(component, "MassOverridden");
check = new JCheckBox(bm);
//// Override mass:
check.setText(trans.get("RocketCompCfg.checkbox.Overridemass"));
check.setToolTipText(trans.get("RocketCompCfg.checkbox.Overridemass.ttip"));
panel.add(check, "growx 1, gapright 20lp");
checkboxes.add(check, "wrap");
order.add(check);
////// Override subcomponents
BooleanModel bmSubcomp = new BooleanModel(component, "SubcomponentsOverriddenMass");
check = new JCheckBox(bmSubcomp);
check.setText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents"));
Font smallFont = check.getFont();
smallFont = smallFont.deriveFont(smallFont.getSize2D() - 1);
check.setFont(smallFont);
check.setToolTipText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents.Mass.ttip"));
bm.addEnableComponent(check, true);
checkboxes.add(check, "gapleft 25lp, wrap");
order.add(check);
panel.add(checkboxes, "growx 1, gapright 20lp");
DoubleModel m = new DoubleModel(component, "OverrideMass", UnitGroup.UNITS_MASS, 0);
@ -383,18 +398,30 @@ public class RocketComponentConfig extends JPanel {
bs = new BasicSlider(m.getSliderModel(0, 0.03, 1.0));
bm.addEnableComponent(bs);
panel.add(bs, "growx 5, w 100lp, wrap");
// END OVERRIDE MASS ----------------------------------
// OVERRIDE CG ----------------------------------
checkboxes = new JPanel(new MigLayout("inset 0"));
bm = new BooleanModel(component, "CGOverridden");
check = new JCheckBox(bm);
//// Override center of gravity:"
check.setText(trans.get("RocketCompCfg.checkbox.Overridecenterofgrav"));
check.setToolTipText(trans.get("RocketCompCfg.checkbox.Overridecenterofgrav.ttip"));
panel.add(check, "growx 1, gapright 20lp");
checkboxes.add(check, "wrap");
order.add(check);
////// Override subcomponents
bmSubcomp = new BooleanModel(component, "SubcomponentsOverriddenCG");
check = new JCheckBox(bmSubcomp);
check.setText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents"));
check.setFont(smallFont);
check.setToolTipText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents.CG.ttip"));
bm.addEnableComponent(check, true);
checkboxes.add(check, "gapleft 25lp, wrap");
order.add(check);
panel.add(checkboxes, "growx 1, gapright 20lp");
m = new DoubleModel(component, "OverrideCGX", UnitGroup.UNITS_LENGTH, 0);
// Calculate suitable length for slider
@ -441,46 +468,47 @@ public class RocketComponentConfig extends JPanel {
bs = new BasicSlider(m.getSliderModel(new DoubleModel(0), length));
bm.addEnableComponent(bs);
panel.add(bs, "growx 5, w 100lp, wrap");
// END OVERRIDE CG ---------------------------------------------------
// BEGIN OVERRIDE CD ------------------------------------------
// BEGIN OVERRIDE CD ------------------------------------------
checkboxes = new JPanel(new MigLayout("inset 0"));
bm = new BooleanModel(component, "CDOverridden");
check = new JCheckBox(bm);
//// Override coefficient of drag:
check.setText(trans.get("RocketCompCfg.checkbox.SetDragCoeff"));
check.setToolTipText(trans.get("RocketCompCfg.checkbox.SetDragCoeff.ttip"));
panel.add(check, "growx 1, gapright 20lp");
checkboxes.add(check, "wrap");
order.add(check);
////// Override subcomponents
bmSubcomp = new BooleanModel(component, "SubcomponentsOverriddenCD");
check = new JCheckBox(bmSubcomp);
check.setText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents"));
check.setFont(smallFont);
check.setToolTipText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents.CD.ttip"));
bm.addEnableComponent(check, true);
checkboxes.add(check, "gapleft 25lp, wrap");
order.add(check);
panel.add(checkboxes, "growx 1, gapright 20lp");
m = new DoubleModel(component, "OverrideCD", UnitGroup.UNITS_COEFFICIENT, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
spin = new JSpinner(m.getSpinnerModel());
spin.setEditor(new SpinnerEditor(spin));
bm.addEnableComponent(spin, true);
panel.add(spin, "growx 1");
panel.add(spin, "top, growx 1");
order.add(((SpinnerEditor) spin.getEditor()).getTextField());
bs = new BasicSlider(m.getSliderModel(-1.0, 1.0));
bm.addEnableComponent(bs);
panel.add(bs, "skip, growx 5, w 100lp, wrap");
panel.add(bs, "top, skip, growx 5, w 100lp, wrap");
// END OVERRIDE CD --------------------------------------------------
// BEGIN OVERRIDE SUBCOMPONENTS --------------------------------------------------
bm = new BooleanModel(component, "SubcomponentsOverridden");
check = new JCheckBox(bm);
//// Override mass, CG, and CD of all subcomponents
check.setText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents"));
check.setToolTipText(trans.get("RocketCompCfg.checkbox.OverrideSubcomponents.ttip"));
panel.add(check, "spanx, wrap 35lp");
// END OVERRIDE SUBCOMPONENTS --------------------------------------------------
// OVERRIDE MASS, CG DOESN'T INCLUDE MOTORS --------------------------------------------------
panel.add(new StyledLabel(trans.get("RocketCompCfg.lbl.longB1") +
//// The center of gravity is measured from the front end of the