diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 801eb18c3..b1719fd2f 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -916,15 +916,14 @@ RocketCompCfg.lbl.longA1 = The component finish affects the aerodynamic dr RocketCompCfg.lbl.longA2 = The value indicated is the average roughness height of the surface. RocketCompCfg.but.Setforall = Set for all RocketCompCfg.but.ttip.Setforall = Set this finish for all components of the rocket. -RocketCompCfg.lbl.Overridemassorcenter = Override the mass or center of gravity of the 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 = Set coefficient of drag: +RocketCompCfg.checkbox.SetDragCoeff = Override coefficient of drag: RocketCompCfg.checkbox.SetDragCoeff.ttip = Overrides the component's coefficient of drag. -RocketCompCfg.checkbox.OverridemassandCG = Override mass and CG of all subcomponents -RocketCompCfg.checkbox.OverridemassandCG.ttip = Overrides the aggregate mass and center of gravity (CG) of this component
and its subcomponents with the mass and CG of this component. +RocketCompCfg.checkbox.OverrideSubcomponents = Override mass, CG, and CD of all subcomponents +RocketCompCfg.checkbox.OverrideSubcomponents.ttip = Overrides the aggregate mass, center of gravity (CG), and coefficient of drag (CD) of this component
and its subcomponents with the mass, CG, and CD of this component. RocketCompCfg.lbl.longB1 = The overridden mass and center of gravity does not include motors.
RocketCompCfg.lbl.longB2 = The center of gravity is measured from the front end of the RocketCompCfg.lbl.Commentsonthe = Comments on the diff --git a/core/resources/l10n/messages_cs.properties b/core/resources/l10n/messages_cs.properties index 3d2ebb086..cbde32398 100644 --- a/core/resources/l10n/messages_cs.properties +++ b/core/resources/l10n/messages_cs.properties @@ -640,10 +640,9 @@ RocketCompCfg.lbl.longA1 = Povrchov RocketCompCfg.lbl.longA2 = Hodnota odpovídá prumerné hrubosti povrchu. RocketCompCfg.but.Setforall = Nastav pro v\u0161echny RocketCompCfg.but.ttip.Setforall = Nastav povrchovou úpravu pro v\u0161echny komponenty rakety. -RocketCompCfg.lbl.Overridemassorcenter = Zmen hmotnost nebo te\u017Ei\u0161te RocketCompCfg.checkbox.Overridemass = Zmen hmotnost: RocketCompCfg.checkbox.Overridecenterofgrav = Zmen te\u017Ei\u0161te: -RocketCompCfg.checkbox.OverridemassandCG = Zmen hmotnost a te\u017Ei\u0161te v\u0161ech komponent +RocketCompCfg.checkbox.OverrideSubcomponents = Zmen hmotnost a te\u017Ei\u0161te v\u0161ech komponent RocketCompCfg.lbl.longB1 = Zmena hmotnosti nezahrnuje motory.
RocketCompCfg.lbl.longB2 = Te\u017Ei\u0161te je mereno od predku RocketCompCfg.lbl.Commentsonthe = Komentár na diff --git a/core/resources/l10n/messages_es.properties b/core/resources/l10n/messages_es.properties index 2b756618a..80f565efa 100644 --- a/core/resources/l10n/messages_es.properties +++ b/core/resources/l10n/messages_es.properties @@ -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.OverridemassandCG = Incluir la masa y el CG de todos los subcomponentes +RocketCompCfg.checkbox.OverrideSubcomponents = Incluir la masa y el CG 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 @@ -847,7 +847,6 @@ RocketCompCfg.lbl.Diameter = Di\u00e1metro: RocketCompCfg.lbl.Figurestyle = Estilo de dibujo: RocketCompCfg.lbl.Length = Longitud: RocketCompCfg.lbl.Mass = Masa: -RocketCompCfg.lbl.Overridemassorcenter = Especificar la masa y el CG del componente RocketCompCfg.lbl.Thickness = Espesor: RocketCompCfg.lbl.longA1 = El Coeficiente de rozamiento depender\u00e1 del acabado del componente.
RocketCompCfg.lbl.longA2 = El valor indicado es el promedio de la rugosidad en altura de la superficie. diff --git a/core/resources/l10n/messages_fr.properties b/core/resources/l10n/messages_fr.properties index 551c474a9..57709d450 100644 --- a/core/resources/l10n/messages_fr.properties +++ b/core/resources/l10n/messages_fr.properties @@ -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.OverridemassandCG = Forcer la masse et le centre de gravit\u00E9 de tous les sous composants +RocketCompCfg.checkbox.OverrideSubcomponents = Forcer la masse et le centre de gravit\u00E9 de 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 @@ -839,7 +839,6 @@ RocketCompCfg.lbl.Diameter = Diam\u00E8tre: RocketCompCfg.lbl.Figurestyle = Mod\u00E8le de forme: RocketCompCfg.lbl.Length = Longueur: RocketCompCfg.lbl.Mass = Masse: -RocketCompCfg.lbl.Overridemassorcenter = Forcer la masse ou le centre de gravit\u00E9 du RocketCompCfg.lbl.Thickness = Epaisseur: RocketCompCfg.lbl.longA1 = La finition de la pi\u00E8ce affecte l'a\u00E9rodynamisme de la pi\u00E8ce.
RocketCompCfg.lbl.longA2 = La valeur indiqu\u00E9e est la hauteur moyenne de la rugosit\u00E9 de la surface. diff --git a/core/resources/l10n/messages_it.properties b/core/resources/l10n/messages_it.properties index d27278f71..30e240111 100644 --- a/core/resources/l10n/messages_it.properties +++ b/core/resources/l10n/messages_it.properties @@ -698,10 +698,9 @@ RocketCompCfg.lbl.longA1 = La finitura del componente influisce sull'aerod RocketCompCfg.lbl.longA2 = Il valore indicato e' la media dell'altezza delle asperita' della superficie. RocketCompCfg.but.Setforall = Imposta per tutti RocketCompCfg.but.ttip.Setforall = Imposta questa finitura per tutti i componenti del razzo. -RocketCompCfg.lbl.Overridemassorcenter = Modifica la massa o il centro di gravita' del RocketCompCfg.checkbox.Overridemass = Modifica la massa: RocketCompCfg.checkbox.Overridecenterofgrav = Sposta il centro di gravita': -RocketCompCfg.checkbox.OverridemassandCG = Modifica la massa ed il CG di tutti i subcomponenti +RocketCompCfg.checkbox.OverrideSubcomponents = Modifica la massa ed il CG di tutti i subcomponenti RocketCompCfg.lbl.longB1 = La massa modificata non include i motori.
RocketCompCfg.lbl.longB2 = Il Centro di Gravita' e' misurato dall'inizio di RocketCompCfg.lbl.Commentsonthe = Commenti sul diff --git a/core/resources/l10n/messages_ja.properties b/core/resources/l10n/messages_ja.properties index 639f7e797..d2b35d286 100644 --- a/core/resources/l10n/messages_ja.properties +++ b/core/resources/l10n/messages_ja.properties @@ -728,10 +728,9 @@ RocketCompCfg.lbl.longA1 = \u4ED5\u4E0A\u3052\u65B9\u306F\u6297\u529B\u4F RocketCompCfg.lbl.longA2 = \u3053\u306E\u5024\u306F\u8868\u9762\u7C97\u3055\u306E\u5E73\u5747\u5024\u3092\u793A\u3059 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.lbl.Overridemassorcenter = \u8CEA\u91CF\u3084\u91CD\u5FC3\u306E\u518D\u5B9A\u7FA9\u3000 RocketCompCfg.checkbox.Overridemass = \u8CEA\u91CF\u306E\u518D\u5B9A\u7FA9\uFF1A RocketCompCfg.checkbox.Overridecenterofgrav = \u91CD\u5FC3\u306E\u518D\u5B9A\u7FA9\uFF1A -RocketCompCfg.checkbox.OverridemassandCG = \u5168\u3066\u306E\u30B5\u30D6\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\u306E\u8CEA\u91CF\u3068CG\u3092\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.lbl.longB1 = \u518D\u5B9A\u7FA9\u3055\u308C\u305F\u8CEA\u91CF\u306B\u306F\u30E2\u30FC\u30BF\u30FC\u306F\u542B\u307E\u308C\u306A\u3044
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 diff --git a/core/resources/l10n/messages_nl.properties b/core/resources/l10n/messages_nl.properties index 743cbfd9d..7c73fb9b1 100644 --- a/core/resources/l10n/messages_nl.properties +++ b/core/resources/l10n/messages_nl.properties @@ -848,11 +848,10 @@ RocketCompCfg.lbl.longA1 = De afwerking van het onderdeel beïnvloedt de l RocketCompCfg.lbl.longA2 = De aangegeven waarde is de gemiddelde ruwheidshoogte van het oppervlak. RocketCompCfg.but.Setforall = Instellen voor alle RocketCompCfg.but.ttip.Setforall = Stel deze afwerking in voor alle onderdelen van de raket. -RocketCompCfg.lbl.Overridemassorcenter = Overschrijf de massa of het zwaartepunt van de RocketCompCfg.checkbox.Overridemass = Overschrijf massa: RocketCompCfg.checkbox.Overridecenterofgrav = Overschrijf zwaartepunt: RocketCompCfg.checkbox.SetDragCoeff = Stel wrijvingscoëfficiënt in: -RocketCompCfg.checkbox.OverridemassandCG = Massa en zwaartepunt van alle subonderdelen overschrijven +RocketCompCfg.checkbox.OverrideSubcomponents = Massa en zwaartepunt van alle subonderdelen overschrijven RocketCompCfg.lbl.longB1 = De overschreven massa omvat geen motoren.
RocketCompCfg.lbl.longB2 = Het zwaartepunt wordt gemeten vanaf de voorkant van de RocketCompCfg.lbl.Commentsonthe = Opmerkingen over de diff --git a/core/resources/l10n/messages_pl.properties b/core/resources/l10n/messages_pl.properties index 14c8d5388..e8311050b 100644 --- a/core/resources/l10n/messages_pl.properties +++ b/core/resources/l10n/messages_pl.properties @@ -642,10 +642,9 @@ update.dlg.latestVersion = Korzystasz z najnowszej wersji OpenRocket: %s. RocketCompCfg.lbl.longA2 = Wskazana warto\u015B\u0107 okre\u015Bla przeci\u0119tn\u0105 chropowato\u015B\u0107 powierzchni. RocketCompCfg.but.Setforall = Ustaw dla wszystkich RocketCompCfg.but.ttip.Setforall = Nadaj to wyko\u0144czenie wszystkim cz\u0119\u015Bci\u0105 sk\u0142adow\u0105 rakiety. - RocketCompCfg.lbl.Overridemassorcenter = Wymu\u015B ci\u0119\u017Car b\u0105d\u017A \u015Brodek ci\u0119\u017Cko\u015Bci dla - RocketCompCfg.checkbox.Overridemass = Wymu\u015B ci\u0119\u017Car: + RocketCompCfg.checkbox.Overridemass = Wymu\u015B ci\u0119\u017Car: RocketCompCfg.checkbox.Overridecenterofgrav = Wymu\u015B \u015Brodek ci\u0119\u017Cko\u015Bci: - RocketCompCfg.checkbox.OverridemassandCG = Wymu\u015B ci\u0119\u017Car oraz \u015Brodek ci\u0119\u017Cko\u015Bci wszystkich dodatkowych cz\u0119\u015Bci sk\u0142adowych + RocketCompCfg.checkbox.OverrideSubcomponents = Wymu\u015B ci\u0119\u017Car oraz \u015Brodek ci\u0119\u017Cko\u015Bci wszystkich dodatkowych cz\u0119\u015Bci sk\u0142adowych RocketCompCfg.lbl.longB1 = Wymuszony ci\u0119\u017Car nie uwzgl\u0119dnia silników.
RocketCompCfg.lbl.longB2 = \u015Arodek ci\u0119\u017Cko\u015Bci jest mierzony od przodu RocketCompCfg.lbl.Commentsonthe = Uwagi - diff --git a/core/resources/l10n/messages_pt.properties b/core/resources/l10n/messages_pt.properties index 3e91ae460..85b28b7e2 100644 --- a/core/resources/l10n/messages_pt.properties +++ b/core/resources/l10n/messages_pt.properties @@ -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.OverridemassandCG = Modificar a massa e o CG de todos os subcomponentes +RocketCompCfg.checkbox.OverrideSubcomponents = Modificar a massa e o CG 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 @@ -825,7 +825,6 @@ RocketCompCfg.lbl.Diameter = Di\u00e2metro: RocketCompCfg.lbl.Figurestyle = Estilo da figura: RocketCompCfg.lbl.Length = Comprimento: RocketCompCfg.lbl.Mass = Massa: -RocketCompCfg.lbl.Overridemassorcenter = Modificar a massa ou o centro de gravidade do RocketCompCfg.lbl.Thickness = Espessura: RocketCompCfg.lbl.longA1 = O acabamento do componente afeta o arrasto aerodin\u00e2mico do componente.
RocketCompCfg.lbl.longA2 = O valor indicado \u00e9 a altura m\u00e9dia da rugosidade da superf\u00edcie. diff --git a/core/resources/l10n/messages_ru.properties b/core/resources/l10n/messages_ru.properties index 03e74fb9b..2903f7242 100644 --- a/core/resources/l10n/messages_ru.properties +++ b/core/resources/l10n/messages_ru.properties @@ -917,7 +917,6 @@ RocketCompCfg.lbl.longA1 = \u041E\u0442\u0434\u0435\u043B\u043A\u0430 \u04 RocketCompCfg.lbl.longA2 = \u0423\u043A\u0430\u0437\u0430\u043D\u043E \u0441\u0440\u0435\u0434\u043D\u0435\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0448\u0435\u0440\u043E\u0445\u043E\u0432\u0430\u0442\u043E\u0441\u0442\u0438. RocketCompCfg.but.Setforall = \u0423\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u0434\u043B\u044F \u0432\u0441\u0435\u0445 RocketCompCfg.but.ttip.Setforall = \u0423\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u044D\u0442\u0443 \u0448\u0435\u0440\u043E\u0445\u043E\u0432\u0430\u0442\u043E\u0441\u0442\u044C \u0434\u043B\u044F \u0432\u0441\u0435\u0445 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u043E\u0432 \u0440\u0430\u043A\u0435\u0442\u044B. -RocketCompCfg.lbl.Overridemassorcenter = \u041F\u0435\u0440\u0435\u043E\u043F\u0440\u0435\u0434\u0435\u043B\u0438\u0442\u044C \u043C\u0430\u0441\u0441\u0443 \u0438\u043B\u0438 \u0446\u0435\u043D\u0442\u0440 \u0442\u044F\u0436\u0435\u0441\u0442\u0438 - RocketCompCfg.checkbox.Overridemass = \u041F\u0435\u0440\u0435\u043E\u043F\u0440\u0435\u0434\u0435\u043B\u0438\u0442\u044C \u043C\u0430\u0441\u0441\u0443: RocketCompCfg.checkbox.Overridemass.ttip = \u041F\u0435\u0440\u0435\u043E\u043F\u0440\u0435\u0434\u0435\u043B\u044F\u0435\u0442 \u043C\u0430\u0441\u0441\u0443 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0430, \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u043D\u043D\u0443\u044E \u043F\u043E \u043E\u0431\u044A\u0435\u043C\u0443 \u0438 \u043F\u043B\u043E\u0442\u043D\u043E\u0441\u0442\u0438 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0430. RocketCompCfg.checkbox.Overridecenterofgrav = \u041F\u0435\u0440\u0435\u043E\u043F\u0440\u0435\u0434\u0435\u043B\u0438\u0442\u044C \u0446\u0435\u043D\u0442\u0440 \u0442\u044F\u0436\u0435\u0441\u0442\u0438: diff --git a/core/resources/l10n/messages_uk_UA.properties b/core/resources/l10n/messages_uk_UA.properties index 4cb554daa..09c8a5319 100644 --- a/core/resources/l10n/messages_uk_UA.properties +++ b/core/resources/l10n/messages_uk_UA.properties @@ -799,11 +799,10 @@ RocketCompCfg.lbl.longA1 = The component finish affects the aerodynamic dr RocketCompCfg.lbl.longA2 = The value indicated is the average roughness height of the surface. RocketCompCfg.but.Setforall = Set for all RocketCompCfg.but.ttip.Setforall = Set this finish for all components of the rocket. -RocketCompCfg.lbl.Overridemassorcenter = Override the mass or center of gravity of the RocketCompCfg.checkbox.Overridemass = Override mass: RocketCompCfg.checkbox.Overridecenterofgrav = Override center of gravity: RocketCompCfg.checkbox.Overridecoeffofdrag = Override coefficient of drag: -RocketCompCfg.checkbox.OverridemassandCG = Override mass and CG of all subcomponents +RocketCompCfg.checkbox.OverrideSubcomponents = Override mass and CG of all subcomponents RocketCompCfg.lbl.longB1 = The overridden mass does not include motors.
RocketCompCfg.lbl.longB2 = The center of gravity is measured from the front end of the RocketCompCfg.lbl.Commentsonthe = Comments on the diff --git a/core/resources/l10n/messages_zh_CN.properties b/core/resources/l10n/messages_zh_CN.properties index 1b326fa08..9049a78c9 100644 --- a/core/resources/l10n/messages_zh_CN.properties +++ b/core/resources/l10n/messages_zh_CN.properties @@ -897,7 +897,7 @@ RocketCompCfg.but.ttip.Setforall = \u5BF9\u6240\u6709\u7684\u7E RocketCompCfg.checkbox.Endcapped = \u6709\u7AEF\u76D6 RocketCompCfg.checkbox.Overridecenterofgrav = \u8986\u5199\u91CD\u5FC3: RocketCompCfg.checkbox.Overridemass = \u8986\u5199\u8D28\u91CF: -RocketCompCfg.checkbox.OverridemassandCG = \u8986\u5199\u6240\u6709\u7EC4\u4EF6\u7684\u91CD\u91CF\u548C\u91CD\u5FC3 +RocketCompCfg.checkbox.OverrideSubcomponents = \u8986\u5199\u6240\u6709\u7EC4\u4EF6\u7684\u91CD\u91CF\u548C\u91CD\u5FC3 RocketCompCfg.checkbox.Usedefaultcolor = \u9ED8\u8BA4\u989C\u8272 RocketCompCfg.combo.ttip.componentmaterialaffects = \u7EC4\u4EF6\u6750\u6599\u5C06\u4F1A\u5F71\u54CD\u5230\u7EC4\u4EF6\u91CD\u91CF. RocketCompCfg.lbl.Choosecolor = \u989C\u8272\u9009\u62E9 @@ -913,7 +913,6 @@ RocketCompCfg.lbl.Diameter = \u76F4\u5F84: RocketCompCfg.lbl.Figurestyle = \u6837\u5F0F: RocketCompCfg.lbl.Length = \u957F\u5EA6: RocketCompCfg.lbl.Mass = \u8D28\u91CF: -RocketCompCfg.lbl.Overridemassorcenter = \u8986\u5199\u91CD\u91CF\u6216\u91CD\u5FC3 RocketCompCfg.lbl.Thickness = \u539A\u5EA6: RocketCompCfg.lbl.longA1 = \u8868\u9762\u5904\u7406\u5C06\u4F1A\u5F71\u54CD\u5230\u7EC4\u4EF6\u7684\u7A7A\u6C14\u52A8\u529B.
RocketCompCfg.lbl.longA2 = \u8BE5\u6570\u503C\u4E3A\u5E73\u5747\u8868\u9762\u7C97\u7CD9\u5EA6. diff --git a/core/src/net/sf/openrocket/aerodynamics/AerodynamicForces.java b/core/src/net/sf/openrocket/aerodynamics/AerodynamicForces.java index a28a95ca0..2979830b1 100644 --- a/core/src/net/sf/openrocket/aerodynamics/AerodynamicForces.java +++ b/core/src/net/sf/openrocket/aerodynamics/AerodynamicForces.java @@ -1,5 +1,6 @@ package net.sf.openrocket.aerodynamics; +import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.Coordinate; @@ -64,7 +65,9 @@ public class AerodynamicForces implements Cloneable, Monitorable { /** Drag coefficient due to friction drag. */ private double frictionCD = Double.NaN; - + + /** Drag coefficient from overrides */ + private double overrideCD = Double.NaN; private double pitchDampingMoment = Double.NaN; private double yawDampingMoment = Double.NaN; @@ -196,8 +199,9 @@ public class AerodynamicForces implements Cloneable, Monitorable { } public double getCD() { - if(component == null) return CD; - if(component.isCDOverridden()) { + if (component == null) return CD; + if (component.isCDOverriddenByAncestor()) return 0; + if (component.isCDOverridden()) { return component.getOverrideCD(); } return CD; @@ -210,7 +214,8 @@ public class AerodynamicForces implements Cloneable, Monitorable { public double getPressureCD() { if(component == null) return pressureCD; - if(component.isCDOverridden()) { + if(component.isCDOverridden() || + component.isCDOverriddenByAncestor()) { return 0; } return pressureCD; @@ -223,8 +228,9 @@ public class AerodynamicForces implements Cloneable, Monitorable { public double getBaseCD() { if(component == null) return baseCD; - if(component.isCDOverridden()) { - return component.getOverrideCD(); + if(component.isCDOverridden() || + component.isCDOverriddenByAncestor()) { + return 0; } return baseCD; } @@ -236,12 +242,26 @@ public class AerodynamicForces implements Cloneable, Monitorable { public double getFrictionCD() { if(component == null) return frictionCD; - if(component.isCDOverridden()) { + if(component.isCDOverridden() || + component.isCDOverriddenByAncestor()) { return 0; } return frictionCD; } + public void setOverrideCD(double overrideCD) { + this.overrideCD = overrideCD; + modID++; + } + + public double getOverrideCD() { + if (component == null) return overrideCD; + if (!(component instanceof Rocket) && + (!component.isCDOverridden() || + component.isCDOverriddenByAncestor())) return 0; + return overrideCD; + } + public void setPitchDampingMoment(double pitchDampingMoment) { this.pitchDampingMoment = pitchDampingMoment; modID++; diff --git a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java index 2df5909c9..65f5cc21b 100644 --- a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java +++ b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java @@ -89,6 +89,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { rocketForces.setFrictionCD(calculateFrictionCD(configuration, conditions, eachMap, warnings)); rocketForces.setPressureCD(calculatePressureCD(configuration, conditions, eachMap, warnings)); rocketForces.setBaseCD(calculateBaseCD(configuration, conditions, eachMap, warnings)); + rocketForces.setOverrideCD(calculateOverrideCD(configuration, conditions, eachMap, assemblyMap, warnings)); Map finalMap = new LinkedHashMap<>(); for(final RocketComponent comp : instMap.keySet()){ @@ -118,7 +119,10 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { if (Double.isNaN(f.getFrictionCD())) f.setFrictionCD(0); - f.setCD(f.getBaseCD() + f.getPressureCD() + f.getFrictionCD()); + if (Double.isNaN(f.getOverrideCD())) + f.setOverrideCD(0); + + f.setCD(f.getBaseCD() + f.getPressureCD() + f.getFrictionCD() + f.getOverrideCD()); f.setCDaxial(calculateAxialCD(conditions, f.getCD())); finalMap.put(comp, f); @@ -187,8 +191,9 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { total.setFrictionCD(calculateFrictionCD(configuration, conditions, null, warnings)); total.setPressureCD(calculatePressureCD(configuration, conditions, null, warnings)); total.setBaseCD(calculateBaseCD(configuration, conditions, null, warnings)); + total.setOverrideCD(calculateOverrideCD(configuration, conditions, null, null, warnings)); - total.setCD(total.getFrictionCD() + total.getPressureCD() + total.getBaseCD()); + total.setCD(total.getFrictionCD() + total.getPressureCD() + total.getBaseCD() + total.getOverrideCD()); total.setCDaxial(calculateAxialCD(conditions, total.getCD())); @@ -342,7 +347,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { * @return friction drag for entire rocket */ private double calculateFrictionCD(FlightConfiguration configuration, FlightConditions conditions, - Map map, WarningSet warningSet) { + Map forceMap, WarningSet warningSet) { double mach = conditions.getMach(); double Re = calculateReynoldsNumber(configuration, conditions); @@ -375,8 +380,8 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { continue; } - // Handle Overriden CD for Whole Rocket - if(c.isCDOverridden()) { + if (c.isCDOverridden() || + c.isCDOverriddenByAncestor()) { continue; } @@ -410,8 +415,8 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { } double componentFrictionCD = calcMap.get(c).calculateFrictionCD(conditions, componentCf, warningSet); - int instanceCount = entry.getValue().size(); + if (c instanceof SymmetricComponent) { SymmetricComponent s = (SymmetricComponent) c; @@ -430,8 +435,8 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { otherFrictionCD += instanceCount * componentFrictionCD; } - if (map != null) { - map.get(c).setFrictionCD(componentFrictionCD); + if (forceMap != null) { + forceMap.get(c).setFrictionCD(componentFrictionCD); } } @@ -440,10 +445,10 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { double correction = (1 + 1.0 / (2 * fB)); // Correct body data in map - if (map != null) { - for (RocketComponent c : map.keySet()) { + if (forceMap != null) { + for (RocketComponent c : forceMap.keySet()) { if (c instanceof SymmetricComponent) { - map.get(c).setFrictionCD(map.get(c).getFrictionCD() * correction); + forceMap.get(c).setFrictionCD(forceMap.get(c).getFrictionCD() * correction); } } } @@ -607,7 +612,8 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { continue; } - if(c.isCDOverridden()) { + if (c.isCDOverridden() || + c.isCDOverriddenByAncestor()) { continue; } @@ -616,7 +622,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { // Pressure drag of this component double cd = calcMap.get(c).calculatePressureCD(conditions, stagnation, base, warningSet); - + if (forceMap != null) { forceMap.get(c).setPressureCD(cd); } @@ -639,13 +645,13 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { cd = stagnation * area / conditions.getRefArea(); total += instanceCount * cd; - if (forceMap != null) { - forceMap.get(c).setPressureCD(forceMap.get(c).getPressureCD() + cd); - } + if (forceMap != null) { + forceMap.get(c).setPressureCD(forceMap.get(c).getPressureCD() + cd); + } } } } - + return total; } @@ -660,7 +666,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { * @return */ private double calculateBaseCD(FlightConfiguration configuration, FlightConditions conditions, - Map map, WarningSet warnings) { + Map forceMap, WarningSet warnings) { double base, total; @@ -682,8 +688,8 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { int instanceCount = entry.getValue().size(); - if(c.isCDOverridden()) { - total += instanceCount * c.getOverrideCD(); + if (c.isCDOverridden() || + c.isCDOverriddenByAncestor()) { continue; } @@ -699,8 +705,8 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { double area = Math.PI * (pow2(radius) - pow2(s.getForeRadius())); double cd = base * area / conditions.getRefArea(); total += instanceCount * cd; - if ((map != null) && (prevComponent != null)) { - map.get(prevComponent).setBaseCD(cd); + if ((forceMap != null) && (prevComponent != null)) { + forceMap.get(prevComponent).setBaseCD(cd); } } @@ -712,8 +718,8 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { double area = Math.PI * pow2(s.getAftRadius()); double cd = base * area / conditions.getRefArea(); total += instanceCount * cd; - if (map != null) { - map.get(s).setBaseCD(cd); + if (forceMap != null) { + forceMap.get(s).setBaseCD(cd); } } } @@ -797,9 +803,50 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { else return -mul * cd; } - - + /** + * add together CD overrides for active components + * + * @param configuration Rocket configuration + * @param conditions Flight conditions taken into account + * @param forceMap + * @param warningSet all current warnings + * @return + */ + private double calculateOverrideCD(FlightConfiguration configuration, FlightConditions conditions, + Map eachMap, + Map assemblyMap, + WarningSet warningSet) { + + if (calcMap == null) + buildCalcMap(configuration); + + double total = 0; + final InstanceMap imap = configuration.getActiveInstances(); + for(Map.Entry> entry: imap.entrySet() ) { + final RocketComponent c = entry.getKey(); + int instanceCount = entry.getValue().size(); + + if (!c.isAerodynamic() && + !(c instanceof ComponentAssembly)) { + continue; + } + + if (c.isCDOverridden() && + !c.isCDOverriddenByAncestor()) { + double cd = instanceCount * c.getOverrideCD(); + Map forceMap = (c instanceof ComponentAssembly) ? assemblyMap : eachMap; + if (forceMap != null) { + forceMap.get(c).setOverrideCD(cd); + } + total += cd; + } + } + + return total; + } + + /** * get damping moments from a rocket in a flight * @param configuration Rocket configuration * @param conditions flight conditions in consideration diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java b/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java index da4978cd4..e9bd33b29 100644 --- a/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java +++ b/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java @@ -130,7 +130,7 @@ class DocumentConfig { Reflection.findMethod(RocketComponent.class, "setOverrideCD", double.class), Reflection.findMethod(RocketComponent.class, "setCDOverridden", boolean.class))); setters.put("RocketComponent:overridesubcomponents", new BooleanSetter( - Reflection.findMethod(RocketComponent.class, "setOverrideSubcomponents", boolean.class))); + Reflection.findMethod(RocketComponent.class, "setSubcomponentsOverridden", boolean.class))); setters.put("RocketComponent:comment", new StringSetter( Reflection.findMethod(RocketComponent.class, "setComment", String.class))); setters.put("RocketComponent:preset", new ComponentPresetSetter( diff --git a/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java b/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java index 182612544..9e45ee05f 100644 --- a/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java +++ b/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java @@ -142,7 +142,7 @@ public class RocketComponentSaver { overridden = true; } if (overridden) { - elements.add("" + c.getOverrideSubcomponents() + elements.add("" + c.isSubcomponentsOverridden() + ""); } diff --git a/core/src/net/sf/openrocket/file/rocksim/importt/BaseHandler.java b/core/src/net/sf/openrocket/file/rocksim/importt/BaseHandler.java index eec02a8ec..9eafaad71 100644 --- a/core/src/net/sf/openrocket/file/rocksim/importt/BaseHandler.java +++ b/core/src/net/sf/openrocket/file/rocksim/importt/BaseHandler.java @@ -175,7 +175,7 @@ public abstract class BaseHandler extends AbstractEle if (override) { component.setCGOverridden(override); component.setMassOverridden(override); - component.setOverrideSubcomponents(false); //Rocksim does not support this type of override + component.setSubcomponentsOverridden(false); //Rocksim does not support this type of override component.setOverrideMass(mass); component.setOverrideCGX(cg); } diff --git a/core/src/net/sf/openrocket/file/rocksim/importt/RocksimHandler.java b/core/src/net/sf/openrocket/file/rocksim/importt/RocksimHandler.java index 5c14afdd4..2dd64e5ea 100644 --- a/core/src/net/sf/openrocket/file/rocksim/importt/RocksimHandler.java +++ b/core/src/net/sf/openrocket/file/rocksim/importt/RocksimHandler.java @@ -208,12 +208,12 @@ class RocketDesignHandler extends AbstractElementHandler { final AxialStage stage = new AxialStage(); if (stage3Mass > 0.0d) { stage.setMassOverridden(true); - stage.setOverrideSubcomponents(true); //Rocksim does not support this type of override + stage.setSubcomponentsOverridden(true); //Rocksim does not support this type of override stage.setOverrideMass(stage3Mass); } if (stage3CG > 0.0d) { stage.setCGOverridden(true); - stage.setOverrideSubcomponents(true); //Rocksim does not support this type of override + stage.setSubcomponentsOverridden(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.setOverrideSubcomponents(true); //Rocksim does not support this type of override + stage.setSubcomponentsOverridden(true); //Rocksim does not support this type of override stage.setOverrideMass(stage2Mass); } if (stage2CG > 0.0d) { stage.setCGOverridden(true); - stage.setOverrideSubcomponents(true); //Rocksim does not support this type of override + stage.setSubcomponentsOverridden(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.setOverrideSubcomponents(true); //Rocksim does not support this type of override + stage.setSubcomponentsOverridden(true); //Rocksim does not support this type of override stage.setOverrideMass(stage1Mass); } if (stage1CG > 0.0d) { stage.setCGOverridden(true); - stage.setOverrideSubcomponents(true); //Rocksim does not support this type of override + stage.setSubcomponentsOverridden(true); //Rocksim does not support this type of override stage.setOverrideCGX(stage1CG); } component.addChild(stage); diff --git a/core/src/net/sf/openrocket/masscalc/MassCalculation.java b/core/src/net/sf/openrocket/masscalc/MassCalculation.java index 28bc0de5b..70c14e1b9 100644 --- a/core/src/net/sf/openrocket/masscalc/MassCalculation.java +++ b/core/src/net/sf/openrocket/masscalc/MassCalculation.java @@ -355,7 +355,7 @@ 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.getOverrideSubcomponents()) { + if (component.isSubcomponentsOverridden()) { if( component.isMassive() ){ // if this component mass, merge it in before overriding: this.addMass( compCM ); diff --git a/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java b/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java index ecdc0084c..dac0541a8 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java +++ b/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java @@ -82,11 +82,6 @@ public abstract class ComponentAssembly extends RocketComponent implements Axial return 0; } - @Override - public boolean getOverrideSubcomponents() { - return true; - } - /** * Null method (ComponentAssembly has no mass of itself). */ @@ -167,16 +162,6 @@ public abstract class ComponentAssembly extends RocketComponent implements Axial fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); } - @Override - public void setOverrideSubcomponents(boolean override) { - // No-op - } - - @Override - public boolean isOverrideSubcomponentsEnabled() { - return false; - } - @Override protected void update() { this.updateBounds(); diff --git a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java index 637d01465..1e165d81e 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java @@ -96,14 +96,17 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab private LineStyle lineStyle = null; - // Override mass/CG + // Override mass/CG/CD protected double overrideMass = 0; protected boolean massOverridden = false; + private double overrideCGX = 0; private boolean cgOverridden = false; + private double overrideCD = 0; private boolean cdOverridden = false; - + + private boolean cdOverriddenByAncestor = false; private boolean overrideSubcomponents = false; @@ -679,10 +682,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab } - /** Return the current override CD. The CD is not necessarily overridden. * - * @return the override CG. + * @return the override CD. */ public final double getOverrideCD() { mutex.verify(); @@ -703,10 +705,15 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab return; checkState(); this.overrideCD = x; - if (isCDOverridden()) - fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE); - else + + if (isCDOverridden()) { + if (isSubcomponentsOverridden()) { + overrideSubcomponentsCD(true); + } + fireComponentChangeEvent(ComponentChangeEvent.AERODYNAMIC_CHANGE); + } else { fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE); + } } @@ -723,9 +730,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab /** - * Set whether the CD is currently overridden. + * Set whether the CD is currently directly overridden. * - * @param o whether the CD is overridden + * @param o whether the CD is currently directly overridden */ public final void setCDOverridden(boolean o) { for (RocketComponent listener : configListeners) { @@ -737,9 +744,27 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab } checkState(); cdOverridden = o; - fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE); + + // if overrideSubcompoents is set, we need to descend the component + // 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()) { + overrideSubcomponentsCD(o); + } + + fireComponentChangeEvent(ComponentChangeEvent.AERODYNAMIC_CHANGE); + } + + /** + * Return whether the CD is currently overridden by an ancestor. + * + * @return whether the CD is overridden by an ancestor + */ + public final boolean isCDOverriddenByAncestor() { + mutex.verify(); + return cdOverriddenByAncestor; } - /** @@ -750,9 +775,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab * also override {@link #isOverrideSubcomponentsEnabled()} to return * false. * - * @return whether the current mass and/or CG override overrides subcomponents as well. + * @return whether the current mass, CG, and/or CD override overrides subcomponents as well. */ - public boolean getOverrideSubcomponents() { + public boolean isSubcomponentsOverridden() { mutex.verify(); return overrideSubcomponents; } @@ -760,13 +785,13 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab /** * Set whether the mass and/or CG override overrides all subcomponent values - * as well. See {@link #getOverrideSubcomponents()} for details. + * as well. See {@link #isSubcomponentsOverridden()} for details. * * @param override whether the mass and/or CG override overrides all subcomponent. */ - public void setOverrideSubcomponents(boolean override) { + public void setSubcomponentsOverridden(boolean override) { for (RocketComponent listener : configListeners) { - listener.setOverrideSubcomponents(override); + listener.setSubcomponentsOverridden(override); } if (overrideSubcomponents == override) { @@ -775,9 +800,42 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab checkState(); overrideSubcomponents = override; - fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE); + overrideSubcomponentsCD(override); + + fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); } - + + /** + * Recursively descend component tree and set descendant CD override values + * + * Logic: + * If we are setting the override true, descend the component tree marking + * every component as overridden by ancestor + * + * 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 + * setting the ancestoroverride from that component + * + * @param override whether setting or clearing overrides + * + */ + void overrideSubcomponentsCD(boolean override) { + for (RocketComponent c: this.children) { + if (c.isCDOverriddenByAncestor() != override) { + + c.cdOverriddenByAncestor = override; + + if (!override && c.isCDOverridden() && c.isSubcomponentsOverridden()) { + c.overrideSubcomponentsCD(true); + } else { + c.overrideSubcomponentsCD(override); + } + } + } + } + /** * Return whether the option to override all subcomponents is enabled or not. * The default implementation returns false if neither mass nor @@ -790,7 +848,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab */ public boolean isOverrideSubcomponentsEnabled() { mutex.verify(); - return isCGOverridden() || isMassOverridden(); + return isCGOverridden() || isMassOverridden() || isCDOverridden(); } /** @@ -2275,6 +2333,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab this.massOverridden = src.massOverridden; this.overrideCGX = src.overrideCGX; this.cgOverridden = src.cgOverridden; + this.cdOverriddenByAncestor = src.cdOverriddenByAncestor; this.overrideSubcomponents = src.overrideSubcomponents; this.name = src.name; this.comment = src.comment; diff --git a/core/src/net/sf/openrocket/util/TestRockets.java b/core/src/net/sf/openrocket/util/TestRockets.java index 632b36a63..13e7c5e45 100644 --- a/core/src/net/sf/openrocket/util/TestRockets.java +++ b/core/src/net/sf/openrocket/util/TestRockets.java @@ -345,7 +345,7 @@ public class TestRockets { c.setMassOverridden(rnd.nextBoolean()); c.setOverrideCGX(rnd(0.2)); c.setOverrideMass(rnd(0.05)); - c.setOverrideSubcomponents(rnd.nextBoolean()); + c.setSubcomponentsOverridden(rnd.nextBoolean()); if (c.isMassive()) { // Only massive components are drawn diff --git a/core/test/net/sf/openrocket/masscalc/MassCalculatorTest.java b/core/test/net/sf/openrocket/masscalc/MassCalculatorTest.java index f04e0f88f..abbef4482 100644 --- a/core/test/net/sf/openrocket/masscalc/MassCalculatorTest.java +++ b/core/test/net/sf/openrocket/masscalc/MassCalculatorTest.java @@ -58,7 +58,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.setOverrideSubcomponents(true); + sustainer.setSubcomponentsOverridden(true); sustainer.setMassOverridden(true); sustainer.setOverrideMass(actualRocketDryMass); @@ -196,7 +196,7 @@ public class MassCalculatorTest extends BaseTestCase { assertEquals(expCMx, actualRocketDryCM.x, EPSILON); } - boosterStage.setOverrideSubcomponents(true); + boosterStage.setSubcomponentsOverridden(true); boosterStage.setCGOverridden(true); boosterStage.setOverrideCGX(0.0); @@ -237,7 +237,7 @@ public class MassCalculatorTest extends BaseTestCase { assertEquals(0.05, actualRocketDryCM.x, EPSILON); } - sustainerStage.setOverrideSubcomponents(true); + sustainerStage.setSubcomponentsOverridden(true); sustainerStage.setMassOverridden(true); sustainerStage.setOverrideMass(0.001); // something small, but not zero @@ -279,7 +279,7 @@ public class MassCalculatorTest extends BaseTestCase { assertEquals(0.10, actualStructure.cm.x, EPSILON); } - boosterStage.setOverrideSubcomponents(true); + boosterStage.setSubcomponentsOverridden(true); boosterStage.setMassOverridden(true); boosterStage.setOverrideMass(0.001); // something small, but not zero @@ -323,7 +323,7 @@ public class MassCalculatorTest extends BaseTestCase { assertEquals(expCMx, actualRocketDryCM.x, EPSILON); } - boosterBody.setOverrideSubcomponents(false); + boosterBody.setSubcomponentsOverridden(false); boosterBody.setCGOverridden(true); boosterBody.setOverrideCGX(0.0); @@ -372,7 +372,7 @@ public class MassCalculatorTest extends BaseTestCase { assertEquals(expCMx, actualRocketDryCM.x, EPSILON); } - boosterBody.setOverrideSubcomponents(false); + boosterBody.setSubcomponentsOverridden(false); boosterBody.setMassOverridden(true); boosterBody.setOverrideMass(0.001); @@ -386,7 +386,7 @@ public class MassCalculatorTest extends BaseTestCase { assertEquals(0.06976699, actualRocketDryCM.x, EPSILON); } - boosterBody.setOverrideSubcomponents(true); // change. Also, this body lacks subcomponents. + boosterBody.setSubcomponentsOverridden(true); // change. Also, this body lacks subcomponents. boosterBody.setMassOverridden(true); // repeat boosterBody.setOverrideMass(0.001); // repeat @@ -950,7 +950,7 @@ 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.setOverrideSubcomponents(true); + boosters.setSubcomponentsOverridden(true); boosters.setMassOverridden(true); boosters.setOverrideMass(overrideMass); boosters.setCGOverridden(true); @@ -1117,7 +1117,7 @@ public class MassCalculatorTest extends BaseTestCase { fins.setName("podFins"); fins.setThickness(0.01); fins.setMassOverridden(true); fins.setOverrideMass(0.02835); - fins.setOverrideSubcomponents(false); + fins.setSubcomponentsOverridden(false); fins.setAxialOffset(-0.01); fins.setAxialMethod(AxialMethod.BOTTOM); podBody.addChild(fins); diff --git a/core/test/net/sf/openrocket/rocketcomponent/FreeformFinSetTest.java b/core/test/net/sf/openrocket/rocketcomponent/FreeformFinSetTest.java index 9a541288c..f8e343832 100644 --- a/core/test/net/sf/openrocket/rocketcomponent/FreeformFinSetTest.java +++ b/core/test/net/sf/openrocket/rocketcomponent/FreeformFinSetTest.java @@ -54,7 +54,7 @@ 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.setOverrideSubcomponents(true); + sourceSet.setSubcomponentsOverridden(true); sourceSet.setAxialMethod(AxialMethod.ABSOLUTE); sourceSet.setAxialOffset(0.1); sourceSet.setTabHeight(0.01); @@ -196,7 +196,7 @@ public class FreeformFinSetTest extends BaseTestCase { } assertEquals(0.012, finSet.getOverrideCGX(), EPSILON); assertEquals(0.0123, finSet.getOverrideMass(), EPSILON); - assertTrue(finSet.getOverrideSubcomponents()); + assertTrue(finSet.isSubcomponentsOverridden()); assertEquals(AxialMethod.ABSOLUTE, finSet.getAxialMethod()); assertEquals(0.1, finSet.getAxialOffset(), EPSILON); @@ -232,7 +232,7 @@ public class FreeformFinSetTest extends BaseTestCase { } assertEquals(0.012, finSet.getOverrideCGX(), EPSILON); assertEquals(0.0123, finSet.getOverrideMass(), EPSILON); - assertTrue(finSet.getOverrideSubcomponents()); + assertTrue(finSet.isSubcomponentsOverridden()); assertEquals(AxialMethod.ABSOLUTE, finSet.getAxialMethod()); assertEquals(0.1, finSet.getAxialOffset(), EPSILON); diff --git a/core/test/net/sf/openrocket/rocketcomponent/OverrideTest.java b/core/test/net/sf/openrocket/rocketcomponent/OverrideTest.java new file mode 100644 index 000000000..36ff91df0 --- /dev/null +++ b/core/test/net/sf/openrocket/rocketcomponent/OverrideTest.java @@ -0,0 +1,112 @@ +package net.sf.openrocket.rocketcomponent; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.junit.Test; + +import net.sf.openrocket.aerodynamics.AerodynamicForces; +import net.sf.openrocket.aerodynamics.BarrowmanCalculator; +import net.sf.openrocket.aerodynamics.FlightConditions; +import net.sf.openrocket.aerodynamics.WarningSet; + +import net.sf.openrocket.rocketcomponent.AxialStage; +import net.sf.openrocket.rocketcomponent.BodyTube; +import net.sf.openrocket.rocketcomponent.FinSet; +import net.sf.openrocket.rocketcomponent.FlightConfiguration; +import net.sf.openrocket.rocketcomponent.NoseCone; +import net.sf.openrocket.rocketcomponent.Rocket; +import net.sf.openrocket.rocketcomponent.RocketComponent; + +import net.sf.openrocket.util.Coordinate; +import net.sf.openrocket.util.MathUtil; +import net.sf.openrocket.util.TestRockets; +import net.sf.openrocket.util.BaseTestCase.BaseTestCase; + +public class OverrideTest extends BaseTestCase { + + @Test + public void testCDAncestorOverrides() { + // create test rocket + Rocket rocket = TestRockets.makeEstesAlphaIII(); + + // obtain sustainer, nose cone, body tube, and fin set + AxialStage sustainer = null; + for (RocketComponent c : rocket.getChildren()){ + if (c instanceof AxialStage) + sustainer = (AxialStage) c; + } + assertNotNull(sustainer); + + NoseCone nosecone = null; + BodyTube bodytube = null; + for (RocketComponent c : sustainer.getChildren()) { + if (c instanceof NoseCone) + nosecone = (NoseCone) c; + + if (c instanceof BodyTube) + bodytube = (BodyTube) c; + } + assertNotNull(nosecone); + assertNotNull(bodytube); + + FinSet finset = null; + for (RocketComponent c : bodytube.getChildren()) { + if (c instanceof FinSet) + finset = (FinSet) c; + } + assertNotNull(finset); + + // We start by just checking the override flags + // Initially no overrides + assertFalse(sustainer.isCDOverridden()); + assertFalse(sustainer.isSubcomponentsOverridden()); + assertFalse(sustainer.isCDOverriddenByAncestor()); + + assertFalse(bodytube.isCDOverridden()); + assertFalse(bodytube.isSubcomponentsOverridden()); + assertFalse(bodytube.isCDOverriddenByAncestor()); + + assertFalse(finset.isCDOverridden()); + assertFalse(finset.isSubcomponentsOverridden()); + assertFalse(finset.isCDOverriddenByAncestor()); + + // Override sustainer CD and subcomponents + sustainer.setSubcomponentsOverridden(true); + sustainer.setCDOverridden(true); + sustainer.setOverrideCD(0.5); + + assertTrue(bodytube.isCDOverriddenByAncestor()); + assertTrue(finset.isCDOverriddenByAncestor()); + + // Set body tube to override subcomponents, override its CD; it's still + // overridden by ancestor + bodytube.setCDOverridden(true); + bodytube.setSubcomponentsOverridden(true); + bodytube.setOverrideCD(0.25); + + assertTrue(bodytube.isCDOverriddenByAncestor()); + + // Now see if it's actually working + FlightConfiguration configuration = rocket.getSelectedConfiguration(); + FlightConditions conditions = new FlightConditions(null); + WarningSet warnings = new WarningSet(); + BarrowmanCalculator calc = new BarrowmanCalculator(); + + // total CD should be overrideCD of sustainer + AerodynamicForces forces = calc.getAerodynamicForces(configuration, conditions, warnings); + 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); + + // CD of rocket should be overridden CD of sustainer plus body tube plus calculated CD of nose cone + Map forceMap = calc.getForceAnalysis(configuration, conditions, warnings); + assertEquals(sustainer.getOverrideCD() + bodytube.getOverrideCD() + forceMap.get(nosecone).getCD(), forceMap.get(rocket).getCD(), MathUtil.EPSILON); + } +} diff --git a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java index c96ed360c..cb856eaf0 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java @@ -236,7 +236,7 @@ public class RocketComponentConfig extends JPanel { } for (RocketComponent c = component.getParent(); c != null; c = c.getParent()) { - if (c.isMassOverridden() && c.getOverrideSubcomponents()) { + if (c.isMassOverridden() && c.isSubcomponentsOverridden()) { overridetext = trans.get("RocketCompCfg.lbl.overriddenby") + " " + c.getName() + ")"; } } @@ -351,16 +351,15 @@ public class RocketComponentConfig extends JPanel { private JPanel overrideTab() { JPanel panel = new JPanel(new MigLayout("align 50% 20%, fillx, gap rel unrel", "[][65lp::][30lp::][]", "")); - //// Override the mass or center of gravity of the - panel.add(new StyledLabel(trans.get("RocketCompCfg.lbl.Overridemassorcenter") + " " + - component.getComponentName() + ":", Style.BOLD), "spanx, wrap 20lp"); + //// Override the mass, center of gravity, or drag coeficient of the component JCheckBox check; BooleanModel bm; UnitSelector us; BasicSlider bs; - //// Mass + // OVERRIDE MASS ---------------------------------- + bm = new BooleanModel(component, "MassOverridden"); check = new JCheckBox(bm); //// Override mass: @@ -385,10 +384,10 @@ public class RocketComponentConfig extends JPanel { bm.addEnableComponent(bs); panel.add(bs, "growx 5, w 100lp, wrap"); + // END OVERRIDE MASS ---------------------------------- - //OVERRIDES CG ---------------------------------- + // OVERRIDE CG ---------------------------------- - //// CG override bm = new BooleanModel(component, "CGOverridden"); check = new JCheckBox(bm); //// Override center of gravity:" @@ -444,21 +443,10 @@ public class RocketComponentConfig extends JPanel { panel.add(bs, "growx 5, w 100lp, wrap"); - //END OVERRIDES CG --------------------------------------------------- - - // Override subcomponents checkbox - bm = new BooleanModel(component, "OverrideSubcomponents"); - check = new JCheckBox(bm); - //// Override mass and CG of all subcomponents - check.setText(trans.get("RocketCompCfg.checkbox.OverridemassandCG")); - check.setToolTipText(trans.get("RocketCompCfg.checkbox.OverridemassandCG.ttip")); - panel.add(check, "spanx, wrap 35lp"); - order.add(check); - - - //BEGIN OVERRIDES CD --------------------------------------------------- + // END OVERRIDE CG --------------------------------------------------- + // BEGIN OVERRIDE CD ------------------------------------------ bm = new BooleanModel(component, "CDOverridden"); check = new JCheckBox(bm); //// Override coefficient of drag: @@ -478,12 +466,22 @@ public class RocketComponentConfig extends JPanel { bs = new BasicSlider(m.getSliderModel(0, 1.0)); bm.addEnableComponent(bs); - panel.add(bs, "growx 5, w 100lp, wrap"); + panel.add(bs, "skip, growx 5, w 100lp, wrap"); + // END OVERRIDE CD -------------------------------------------------- - //END OVERRIDES CP -------------------------------------------------- + // BEGIN OVERRIDE SUBCOMPONENTS -------------------------------------------------- - //// The overridden mass does not include motors. + 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 trans.get("RocketCompCfg.lbl.longB2") + " " +