1 package net.sf.openrocket.aerodynamics;
5 import net.sf.openrocket.logging.LogHelper;
6 import net.sf.openrocket.rocketcomponent.Configuration;
7 import net.sf.openrocket.rocketcomponent.RocketComponent;
8 import net.sf.openrocket.startup.Application;
9 import net.sf.openrocket.util.Coordinate;
13 * An abstract aerodynamic calculator implementation, that offers basic implementation
14 * of some methods and methods for cache validation and purging.
16 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
19 public abstract class AbstractAerodynamicCalculator implements AerodynamicCalculator {
20 private static final LogHelper log = Application.getLogger();
22 /** Number of divisions used when calculating worst CP. */
23 public static final int DIVISIONS = 360;
26 * A <code>WarningSet</code> that can be used if <code>null</code> is passed
27 * to a calculation method.
29 protected WarningSet ignoreWarningSet = new WarningSet();
31 /** The aerodynamic modification ID of the latest rocket */
32 private int rocketAeroModID = -1;
33 private int rocketTreeModID = -1;
38 //////////////// Aerodynamic calculators ////////////////
41 public abstract Coordinate getCP(Configuration configuration, FlightConditions conditions,
45 public abstract Map<RocketComponent, AerodynamicForces> getForceAnalysis(Configuration configuration, FlightConditions conditions,
49 public abstract AerodynamicForces getAerodynamicForces(Configuration configuration,
50 FlightConditions conditions, WarningSet warnings);
55 * The worst theta angle is stored in conditions.
58 public Coordinate getWorstCP(Configuration configuration, FlightConditions conditions,
59 WarningSet warnings) {
60 FlightConditions cond = conditions.clone();
61 Coordinate worst = new Coordinate(Double.MAX_VALUE);
65 for (int i = 0; i < DIVISIONS; i++) {
66 cond.setTheta(2 * Math.PI * i / DIVISIONS);
67 cp = getCP(configuration, cond, warnings);
70 theta = cond.getTheta();
74 conditions.setTheta(theta);
82 * Check the current cache consistency. This method must be called by all
83 * methods that may use any cached data before any other operations are
84 * performed. If the rocket has changed since the previous call to
85 * <code>checkCache()</code>, then {@link #voidAerodynamicCache()} is called.
87 * This method performs the checking based on the rocket's modification IDs,
88 * so that these method may be called from listeners of the rocket itself.
90 * @param configuration the configuration of the current call
92 protected final void checkCache(Configuration configuration) {
93 if (rocketAeroModID != configuration.getRocket().getAerodynamicModID() ||
94 rocketTreeModID != configuration.getRocket().getTreeModID()) {
95 rocketAeroModID = configuration.getRocket().getAerodynamicModID();
96 rocketTreeModID = configuration.getRocket().getTreeModID();
97 log.debug("Voiding the aerodynamic cache");
98 voidAerodynamicCache();
105 * Void cached aerodynamic data. This method is called whenever a change occurs in
106 * the rocket structure that affects the aerodynamics of the rocket and when a new
107 * Rocket is set. This method must be overridden to void any cached data
108 * necessary. The method must call <code>super.voidAerodynamicCache()</code> during
111 protected void voidAerodynamicCache() {