diff --git a/core/src/net/sf/openrocket/masscalc/MassCalculation.java b/core/src/net/sf/openrocket/masscalc/MassCalculation.java index cc925053b..173524c0b 100644 --- a/core/src/net/sf/openrocket/masscalc/MassCalculation.java +++ b/core/src/net/sf/openrocket/masscalc/MassCalculation.java @@ -338,14 +338,12 @@ public class MassCalculation { eachChild.prefix = prefix + "...."; eachChild.calculateStructure(); - + // accumulate children's data children.merge( eachChild ); } } - this.merge( children ); - if (this.config.isComponentActive(component) ){ Coordinate compCM = component.getComponentCG(); @@ -355,26 +353,25 @@ 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.isSubcomponentsOverriddenMass() || component.isSubcomponentsOverriddenCG()) { - if (component.isMassive()) { - // if this component mass, merge it in before overriding: - this.addMass( compCM ); + if (component.isMassOverridden()) { + if (!component.isMassive()) { + compCM = children.getCM(); } - if (component.isSubcomponentsOverriddenMass() && component.isMassOverridden()) { - this.setCM( this.getCM().setWeight(component.getOverrideMass()) ); + compCM = compCM.setWeight(component.getOverrideMass()); + + if (component.isSubcomponentsOverriddenMass()) { + children.setCM(children.getCM().setWeight(0)); } - if (component.isSubcomponentsOverriddenCG() && component.isCGOverridden()) { - this.setCM( this.getCM().setX(compZero.x + component.getOverrideCGX())); - } - }else { - if (component.isMassOverridden()) { - compCM = compCM.setWeight( component.getOverrideMass() ); - } - if (component.isCGOverridden()) { - compCM = compCM.setX( compZero.x + component.getOverrideCGX() ); - } - this.addMass( compCM ); } + + if (component.isCGOverridden()) { + compCM = compCM.setX( compZero.x + component.getOverrideCGX() ); + + if (component.isSubcomponentsOverriddenCG()) { + children.setCM(children.getCM().setX(compCM.x)); + } + } + this.addMass(compCM); if(null != analysisMap){ final CMAnalysisEntry entry = analysisMap.get(component.hashCode()); @@ -398,6 +395,8 @@ public class MassCalculation { // System.err.println(String.format( "%s....componentData: %s", prefix, compCM.toPreciseString() )); // } } + + this.merge( children ); // // vvv DEBUG // if( this.config.isComponentActive(component) && 0 < this.getMass() ) { diff --git a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java index b14eeddcb..5a4064c36 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java @@ -855,7 +855,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab /** - * Return whether the mass and/or CG override overrides all subcomponent values + * Return whether the mass 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 @@ -869,7 +869,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab return overrideSubcomponentsMass; } - // TODO: delete when compatibility with OR 15.03 is not needed anymore + // For compatibility with files created with 15.03 public void setSubcomponentsOverridden(boolean override) { setSubcomponentsOverriddenMass(override); setSubcomponentsOverriddenCG(override); @@ -878,10 +878,10 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab /** - * Set whether the mass and/or CG override overrides all subcomponent values + * Set whether the mass override overrides all subcomponent values * as well. See {@link #isSubcomponentsOverriddenMass()} for details. * - * @param override whether the mass and/or CG override overrides all subcomponent. + * @param override whether the mass override overrides all subcomponent. */ public void setSubcomponentsOverriddenMass(boolean override) { for (RocketComponent listener : configListeners) { @@ -916,10 +916,10 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab /** - * Set whether the mass and/or CG override overrides all subcomponent values + * Set whether the 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. + * @param override whether the CG override overrides all subcomponent. */ public void setSubcomponentsOverriddenCG(boolean override) { for (RocketComponent listener : configListeners) { diff --git a/core/test/net/sf/openrocket/masscalc/MassCalculatorTest.java b/core/test/net/sf/openrocket/masscalc/MassCalculatorTest.java index a36109567..e7b7e9c9a 100644 --- a/core/test/net/sf/openrocket/masscalc/MassCalculatorTest.java +++ b/core/test/net/sf/openrocket/masscalc/MassCalculatorTest.java @@ -48,6 +48,68 @@ public class MassCalculatorTest extends BaseTestCase { assertEquals("Empty Rocket Longitudinal MOI calculated incorrectly: ", 0, actualMOIlong, 0); } + @Test + public void testStageOverride() { + Rocket rocket = new Rocket(); + + AxialStage stage = new AxialStage(); + rocket.addChild(stage); + + FlightConfiguration config = rocket.getEmptyConfiguration(); + config.setAllStages(); + rocket.enableEvents(); + + BodyTube tube1 = new BodyTube(); + tube1.setLength(1.0); + tube1.setMassOverridden(true); + tube1.setOverrideMass(1.0); + stage.addChild(tube1); + + BodyTube tube2 = new BodyTube(); + tube2.setLength(2.0); + tube2.setMassOverridden(true); + tube2.setOverrideMass(2.0); + stage.addChild(tube2); + // tube2.setAxialMethod(AxialMethod.ABSOLUTE); + // tube2.setAxialOffset(1.0); + + RigidBody structure = MassCalculator.calculateStructure(config); + assertEquals("No overrides -- mass incorrect", 3.0, structure.cm.weight, EPSILON); + assertEquals("No overrides -- CG incorrect", 1.5, structure.cm.x, EPSILON); + + stage.setMassOverridden(true); + stage.setOverrideMass(1.0); + structure = MassCalculator.calculateStructure(config); + assertEquals("Overrides: mass -- mass incorrect", 4.0, structure.cm.weight, EPSILON); + assertEquals("Overrides: mass -- CG incorrect", 1.5, structure.cm.x, EPSILON); + + stage.setSubcomponentsOverriddenMass(true); + structure = MassCalculator.calculateStructure(config); + assertEquals("Overrides: mass, children mass -- mass incorrect", 1.0, structure.cm.weight, EPSILON); + assertEquals("Overrides: mass, children mass -- CG incorrect", 1.5, structure.cm.x, EPSILON); + + stage.setCGOverridden(true); + stage.setOverrideCGX(1.0); + structure = MassCalculator.calculateStructure(config); + assertEquals("Overrides: mass, children mass, CG -- mass incorrect", 1.0, structure.cm.weight, EPSILON); + assertEquals("Overrides: mass, children mass, CG -- CG incorrect", 1.0, structure.cm.x, EPSILON); + + stage.setSubcomponentsOverriddenCG(true); + structure = MassCalculator.calculateStructure(config); + assertEquals("Overrides: mass, children mass, CG, children CG -- mass incorrect", 1.0, structure.cm.weight, EPSILON); + assertEquals("Overrides: mass, children mass, CG, children CG -- CG incorrect", 1.0, structure.cm.x, EPSILON); + + stage.setSubcomponentsOverriddenMass(false); + structure = MassCalculator.calculateStructure(config); + assertEquals("Overrides: mass, CG, children CG -- mass incorrect", 4.0, structure.cm.weight, EPSILON); + assertEquals("Overrides: mass, CG, children CG -- CG incorrect", 1.0, structure.cm.x, EPSILON); + + stage.setSubcomponentsOverriddenCG(false); + structure = MassCalculator.calculateStructure(config); + assertEquals("Overrides: mass, CG -- mass incorrect", 4.0, structure.cm.weight, EPSILON); + assertEquals("Overrides: mass, CG -- CG incorrect", 1.375, structure.cm.x, EPSILON); + } + @Test public void testAlphaIIIStructure() { Rocket rocket = TestRockets.makeEstesAlphaIII(); @@ -1094,7 +1156,6 @@ public class MassCalculatorTest extends BaseTestCase { mmt.setOverrideCGX(0.395); RigidBody structure = MassCalculator.calculateStructure(config); - final double expMass = 0.6063562096046; double calcTotalMass = structure.getMass(); assertEquals(" Booster Launch Mass is incorrect: ", expMass, calcTotalMass, EPSILON);