If a set of fins has an overriden mass, then, if the set is split into individual fins, the overridden mass is divided by the number of fins in the set and the quotient is set as the mass override for each individual fin.
create getTubesTouching() method to determine whether tubes are touching (will also return true if they overlap)
fix several places where outerRadius was used instead of getOuterRadius()
Move actual friction CD calculation code into subclasses of RocketComponentCalc()
LaunchLugCalc adds so little wetted area it isn't worth bothering with, so isn't calculated (wasn't calculated before, either)
TubeFinSetCalc also doesn't calculate it; that's coming next.
- Creates PNG file filter
- Adds new file filter to translation file
- Makes Exported Chart's Width & Height as it is displayed
- Changes Button From Print Icon to "Save As Image" text
Note that the lowest point on the fin is guaranteed to be either the first point which is at (0, 0) or the last point, which will have a y coordinate of 0 if on a body tube, greater than 0 if on an increasing transition, or less than 0 on a decreasing transition (boattail).
The original plan was that there would be an InstanceContext for every instance of every RocketComponent, with some active and some not (just as RocketComponents may be active or not). The implementation has resulted in InstanceContexts only being created for active RocketComponents, so the active field is superfluous.
If there are multiple independent motor clusters in a stage, each of them can attempt a separation event. When the second event happens, there is no longer an active upper stage, so the separation results in a simulation branch with no active stages. This causes a NaN exception as the mass is 0.
For parallel stages, this is much more likely to be the user's intent. The previous behavior caused stage separation the moment of ignition, so the booster set essentially flew as a second, independent rocket. With this change, the parallel stage stays with the center stack until the ejection charge files (note that OR treats a rocket with a -0 ejection delay as having an ejection charge at motor burnout).
Note that this change to the default behavior is also applied to axial stages, but is also appropriate in that case. For the vast majority of low power rockets, the booster burnout ignites the next stage, so "next stage ignition" and "current stage ejection charge" are simultaneous. For high power rockets, the next stage ignition has to be customized anyway.
This has been lurking -- we're not actually supposed to be calling getAverageThrustThrust when we're past the end of the thrustcurve (there's a test for whether the motor is active before calling it), but another bug in the parallel staging code exposed it.