Merge pull request #602 from wolsen/fix-stage-length
[Fixes 452] Reflect length of selected stages
This commit is contained in:
commit
bd8bef2c85
@ -714,11 +714,32 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
|
||||
final double finLength = singleFinBounds.max.x;
|
||||
final double finHeight = singleFinBounds.max.y;
|
||||
|
||||
BoundingBox compBox = new BoundingBox().update(getComponentLocations());
|
||||
Coordinate[] locations = getInstanceLocations();
|
||||
double[] angles = getInstanceAngles();
|
||||
BoundingBox finSetBox = new BoundingBox();
|
||||
|
||||
BoundingBox finSetBox = new BoundingBox( compBox.min.sub( 0, finHeight, finHeight ),
|
||||
compBox.max.add( finLength, finHeight, finHeight ));
|
||||
return finSetBox;
|
||||
/*
|
||||
* The fins themselves will be offset by the location itself to match
|
||||
* the outside radius of a body tube. The bounds encapsulate the outer
|
||||
* portion of all the tips of the fins.
|
||||
*
|
||||
* The height of each fin along the Y axis can be determined by:
|
||||
* yHeight = cos(angle) * finHeight
|
||||
*
|
||||
* The height (depth?) of each fin along the Z axis can be determined by:
|
||||
* zHeight = sin(angle) * finHeight
|
||||
*
|
||||
* The boundingBox should be that box which is the smallest box where
|
||||
* a convex hull will contain all Coordinates.
|
||||
*/
|
||||
for (int i = 0; i < locations.length; i++) {
|
||||
double y = Math.cos(angles[i]) * finHeight;
|
||||
double z = Math.sin(angles[i]) * finHeight;
|
||||
finSetBox.update(locations[i].add(0, y, z));
|
||||
finSetBox.update(locations[i].add(finLength, y, z));
|
||||
}
|
||||
|
||||
return finSetBox;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.sf.openrocket.rocketcomponent;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -551,16 +552,71 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
||||
return cachedBounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the bounds for all the active component instances
|
||||
* in the current configuration.
|
||||
*/
|
||||
private void calculateBounds(){
|
||||
BoundingBox bounds = new BoundingBox();
|
||||
|
||||
for (RocketComponent component : this.getActiveComponents()) {
|
||||
BoundingBox componentBounds = new BoundingBox().update(component.getComponentBounds());
|
||||
bounds.update( componentBounds );
|
||||
}
|
||||
|
||||
InstanceMap map = getActiveInstances();
|
||||
for (Map.Entry<RocketComponent, java.util.ArrayList<InstanceContext>> entry : map.entrySet()) {
|
||||
RocketComponent component = entry.getKey();
|
||||
List<InstanceContext> contexts = entry.getValue();
|
||||
|
||||
Collection<Coordinate> coordinates = new ArrayList<Coordinate>();
|
||||
/* FinSets already provide a bounding box, so let's use that.
|
||||
*/
|
||||
if (component instanceof FinSet) {
|
||||
bounds.update(((FinSet) component).getBoundingBox());
|
||||
continue;
|
||||
} else {
|
||||
coordinates.addAll(component.getComponentBounds());
|
||||
}
|
||||
BoundingBox componentBox = new BoundingBox();
|
||||
List<Coordinate> transformedCoords = new ArrayList<Coordinate>();
|
||||
for (InstanceContext ctxt : contexts) {
|
||||
/*
|
||||
* If the instance is not active in the current context, then
|
||||
* skip the bound calculations. This is mildly confusing since
|
||||
* getActiveInstances() implies that it will only return the
|
||||
* instances that are active, but it returns all instances and
|
||||
* the context indicates if it is active or not.
|
||||
*/
|
||||
if (!ctxt.active) {
|
||||
continue;
|
||||
}
|
||||
for (Coordinate c : coordinates) {
|
||||
Coordinate tc = null;
|
||||
/* These components do not need the transform performed in
|
||||
* order to provide the proper coordinates for length calculation.
|
||||
* The transformation will cause the values to be calculated
|
||||
* incorrectly. This should be fixed in the appropriate places
|
||||
* not handled as one-offs in here.
|
||||
*/
|
||||
if ((component instanceof AxialStage) || (component instanceof BodyTube) ||
|
||||
(component instanceof PodSet)) {
|
||||
tc = c;
|
||||
} else {
|
||||
tc = ctxt.transform.transform(c);
|
||||
}
|
||||
componentBox.update(tc);
|
||||
transformedCoords.add(tc);
|
||||
}
|
||||
}
|
||||
|
||||
bounds.update(componentBox);
|
||||
}
|
||||
|
||||
boundsModID = rocket.getModID();
|
||||
cachedLength = bounds.span().x;
|
||||
/* Special case for the scenario that all of the stages are removed and are
|
||||
* inactive. Its possible that this shouldn't be allowed, but it is currently
|
||||
* so we'll just adjust the length here.
|
||||
*/
|
||||
if (getActiveStages().isEmpty()) {
|
||||
cachedLength = 0;
|
||||
}
|
||||
cachedBounds.update( bounds );
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ public class FlightConfigurationTest extends BaseTestCase {
|
||||
// preconditions
|
||||
assertThat("active stage count doesn't match", config.getActiveStageCount(), equalTo(2));
|
||||
|
||||
final double expectedLength = 0.33;
|
||||
final double expectedLength = 0.335;
|
||||
final double calculatedLength = config.getLength();
|
||||
assertEquals("source config length doesn't match: ", expectedLength, calculatedLength, EPSILON);
|
||||
|
||||
@ -70,7 +70,7 @@ public class FlightConfigurationTest extends BaseTestCase {
|
||||
int expectedMotorCount = 2;
|
||||
int actualMotorCount = config1.getActiveMotors().size();
|
||||
assertThat("active motor count doesn't match", actualMotorCount, equalTo(expectedMotorCount));
|
||||
double expectedLength = 0.33;
|
||||
double expectedLength = 0.335;
|
||||
assertEquals("source config length doesn't match: ", expectedLength, config1.getLength(), EPSILON);
|
||||
double expectedReferenceLength = 0.024;
|
||||
assertEquals("source config reference length doesn't match: ", expectedReferenceLength, config1.getReferenceLength(), EPSILON);
|
||||
|
@ -10,21 +10,17 @@ import javax.swing.JPanel;
|
||||
import javax.swing.JToggleButton;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.rocketcomponent.AxialStage;
|
||||
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
|
||||
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
import net.sf.openrocket.util.StateChangeListener;
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class StageSelector extends JPanel implements StateChangeListener {
|
||||
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
private final Rocket rocket;
|
||||
|
||||
private List<JToggleButton> buttons = new ArrayList<JToggleButton>();
|
||||
@ -41,7 +37,7 @@ public class StageSelector extends JPanel implements StateChangeListener {
|
||||
this.removeAll();
|
||||
for(AxialStage stage : configuration.getRocket().getStageList()){
|
||||
JToggleButton button = new JToggleButton(new StageAction(stage));
|
||||
button.setSelected(true);
|
||||
button.setSelected(configuration.isStageActive(stage.getStageNumber()));
|
||||
this.add(button);
|
||||
buttons.add(button);
|
||||
}
|
||||
|
@ -419,13 +419,14 @@ public class RocketFigure extends AbstractScaleFigure {
|
||||
protected void updateSubjectDimensions() {
|
||||
// calculate bounds, and store in class variables
|
||||
final BoundingBox bounds = rocket.getSelectedConfiguration().getBoundingBox();
|
||||
final double maxR = Math.max(Math.hypot(bounds.min.y, bounds.min.z),
|
||||
Math.hypot(bounds.max.y, bounds.max.z));
|
||||
|
||||
switch (currentViewType) {
|
||||
case SideView:
|
||||
subjectBounds_m = new Rectangle2D.Double(bounds.min.x, bounds.min.y, bounds.span().x, bounds.span().y);
|
||||
subjectBounds_m = new Rectangle2D.Double(bounds.min.x, -maxR, bounds.span().x, 2 * maxR);
|
||||
break;
|
||||
case BackView:
|
||||
final double maxR = Math.max(Math.hypot(bounds.min.y, bounds.min.z), Math.hypot(bounds.max.y, bounds.max.z));
|
||||
subjectBounds_m = new Rectangle2D.Double(-maxR, -maxR, 2 * maxR, 2 * maxR);
|
||||
break;
|
||||
default:
|
||||
|
@ -607,20 +607,8 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
|
||||
figure3d.setCG(cg);
|
||||
figure3d.setCP(cp);
|
||||
|
||||
// Length bound is assumed to be tight
|
||||
double length = 0;
|
||||
Collection<Coordinate> bounds = curConfig.getBounds();
|
||||
if (!bounds.isEmpty()) {
|
||||
double minX = Double.POSITIVE_INFINITY, maxX = Double.NEGATIVE_INFINITY;
|
||||
for (Coordinate c : bounds) {
|
||||
if (c.x < minX)
|
||||
minX = c.x;
|
||||
if (c.x > maxX)
|
||||
maxX = c.x;
|
||||
}
|
||||
length = maxX - minX;
|
||||
}
|
||||
|
||||
double length = curConfig.getLength();
|
||||
|
||||
double diameter = Double.NaN;
|
||||
for (RocketComponent c : curConfig.getCoreComponents()) {
|
||||
if (c instanceof SymmetricComponent) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user