Merge pull request #591 from wolsen/fix-print
[Fixes #531] Fix printing/export as pdf
This commit is contained in:
commit
7dbbb6c74d
@ -371,6 +371,11 @@ public class BodyTube extends SymmetricComponent implements MotorMount, Coaxial
|
||||
return this.motors.getDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MotorConfigurationSet getMotorConfigurationSet() {
|
||||
return this.motors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MotorConfiguration getMotorConfig( final FlightConfigurationId fcid){
|
||||
return this.motors.get(fcid);
|
||||
@ -432,7 +437,7 @@ public class BodyTube extends SymmetricComponent implements MotorMount, Coaxial
|
||||
|
||||
@Override
|
||||
public int getMotorCount() {
|
||||
return this.motors.size();
|
||||
return this.getClusterConfiguration().getClusterCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -126,6 +126,32 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
||||
_setStageActive( stageNumber, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates all stages as active starting from the specified component
|
||||
* to the top-most stage in the rocket. Active stages are those stages
|
||||
* which contribute to the mass of the rocket. Given a rocket with the
|
||||
* following stages:
|
||||
*
|
||||
* <ul>
|
||||
* <li>StageA - top most stage, containing nose cone etc.</li>
|
||||
* <li>StageB - middle stage</li>
|
||||
* <li>StageC - bottom stage</li>
|
||||
* </ul>
|
||||
*
|
||||
* invoking <code>FlightConfiguration.activateStagesThrough(StageB)</code>
|
||||
* will cause both StageA and StageB to be marked as active, and StageC
|
||||
* will be marked as inactive.
|
||||
*
|
||||
* @param stage the AxialStage to activate all stages up to (inclusive)
|
||||
*/
|
||||
public void activateStagesThrough(final AxialStage stage) {
|
||||
clearAllStages();
|
||||
for (int i=0; i <= stage.getStageNumber(); i++) {
|
||||
_setStageActive(i, true);
|
||||
}
|
||||
updateMotors();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method flags the specified stage as active, and all other stages as inactive.
|
||||
*
|
||||
|
@ -258,6 +258,11 @@ public class InnerTube extends ThicknessRingComponent implements AxialPositionab
|
||||
return this.motors.getDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MotorConfigurationSet getMotorConfigurationSet() {
|
||||
return this.motors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MotorConfiguration getMotorConfig( final FlightConfigurationId fcid){
|
||||
return this.motors.get(fcid);
|
||||
@ -321,7 +326,7 @@ public class InnerTube extends ThicknessRingComponent implements AxialPositionab
|
||||
|
||||
@Override
|
||||
public int getMotorCount() {
|
||||
return this.motors.size();
|
||||
return this.getClusterConfiguration().getClusterCount();
|
||||
}
|
||||
|
||||
|
||||
|
@ -3,6 +3,7 @@ package net.sf.openrocket.rocketcomponent;
|
||||
import java.util.Iterator;
|
||||
|
||||
import net.sf.openrocket.motor.MotorConfiguration;
|
||||
import net.sf.openrocket.motor.MotorConfigurationSet;
|
||||
import net.sf.openrocket.util.ChangeSource;
|
||||
import net.sf.openrocket.util.Coordinate;
|
||||
|
||||
@ -80,6 +81,13 @@ public interface MotorMount extends ChangeSource, FlightConfigurableComponent {
|
||||
// duplicate of RocketComponent
|
||||
public Coordinate[] getLocations();
|
||||
|
||||
/**
|
||||
* Returns the set of motors configured for flight/simulation in this motor mount.
|
||||
* @return the MotorConfigurationSet containing the set of motors configured in
|
||||
* this motor mount.
|
||||
*/
|
||||
public MotorConfigurationSet getMotorConfigurationSet();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param fcid id for which to return the motor (null retrieves the default)
|
||||
|
@ -201,7 +201,7 @@ public class FlightConfigurationTest extends BaseTestCase {
|
||||
InnerTube smmt = (InnerTube)rkt.getChild(0).getChild(1).getChild(2);
|
||||
|
||||
int expectedMotorCount = 5;
|
||||
int actualMotorCount = smmt.getMotorCount();
|
||||
int actualMotorCount = smmt.getMotorConfigurationSet().size();
|
||||
assertThat("number of motor configurations doesn't match.", actualMotorCount, equalTo(expectedMotorCount));
|
||||
|
||||
}
|
||||
@ -295,6 +295,21 @@ public class FlightConfigurationTest extends BaseTestCase {
|
||||
config.toggleStage(0);
|
||||
assertThat(" toggle stage #0: ", config.isStageActive(0), equalTo(false));
|
||||
|
||||
AxialStage sustainer = rkt.getTopmostStage();
|
||||
AxialStage booster = rkt.getBottomCoreStage();
|
||||
assertThat(" sustainer stage is stage #0: ", sustainer.getStageNumber(), equalTo(0));
|
||||
assertThat(" booster stage is stage #1: ", booster.getStageNumber(), equalTo(1));
|
||||
|
||||
config.clearAllStages();
|
||||
config.activateStagesThrough(sustainer);
|
||||
assertThat(" sustainer stage is active: ", config.isStageActive(sustainer.getStageNumber()), equalTo(true));
|
||||
assertThat(" booster stage is inactive: ", config.isStageActive(booster.getStageNumber()), equalTo(false));
|
||||
|
||||
config.clearAllStages();
|
||||
config.activateStagesThrough(booster);
|
||||
assertThat(" sustainer stage is active: ", config.isStageActive(sustainer.getStageNumber()), equalTo(true));
|
||||
assertThat(" booster stage is active: ", config.isStageActive(booster.getStageNumber()), equalTo(true));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -28,7 +28,9 @@ import net.sf.openrocket.gui.figureelements.FigureElement;
|
||||
import net.sf.openrocket.gui.figureelements.RocketInfo;
|
||||
import net.sf.openrocket.gui.scalefigure.RocketPanel;
|
||||
import net.sf.openrocket.masscalc.MassCalculator;
|
||||
import net.sf.openrocket.masscalc.RigidBody;
|
||||
import net.sf.openrocket.motor.Motor;
|
||||
import net.sf.openrocket.motor.MotorConfiguration;
|
||||
import net.sf.openrocket.rocketcomponent.AxialStage;
|
||||
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
|
||||
@ -162,7 +164,7 @@ public class DesignReport {
|
||||
PrintUtilities.addText(document, PrintUtilities.BIG_BOLD, ROCKET_DESIGN);
|
||||
|
||||
Rocket rocket = rocketDocument.getRocket();
|
||||
final FlightConfiguration configuration = rocket.getSelectedConfiguration();//.clone();
|
||||
final FlightConfiguration configuration = rocket.getSelectedConfiguration();
|
||||
configuration.setAllStages();
|
||||
PdfContentByte canvas = writer.getDirectContent();
|
||||
|
||||
@ -177,8 +179,8 @@ public class DesignReport {
|
||||
|
||||
canvas.beginText();
|
||||
canvas.setFontAndSize(ITextHelper.getBaseFont(), PrintUtilities.NORMAL_FONT_SIZE);
|
||||
int figHeightPts = (int) (PrintUnit.METERS.toPoints(figure.getHeight()) * 0.4 * (scale / PrintUnit.METERS
|
||||
.toPoints(1)));
|
||||
double figureHeightInPoints = PrintUnit.METERS.toPoints(figure.getFigureHeight());
|
||||
int figHeightPts = (int) (figureHeightInPoints * SCALE_FUDGE_FACTOR * (scale / PrintUnit.METERS.toPoints(1)));
|
||||
final int diagramHeight = pageImageableHeight * 2 - 70 - (figHeightPts);
|
||||
canvas.moveText(document.leftMargin() + pageSize.getBorderWidthLeft(), diagramHeight);
|
||||
canvas.moveTextWithLeading(0, -16);
|
||||
@ -190,8 +192,7 @@ public class DesignReport {
|
||||
canvas.newlineShowText(STAGES);
|
||||
canvas.showText("" + rocket.getStageCount());
|
||||
|
||||
|
||||
if ( configuration.hasMotors()){
|
||||
if (configuration.hasMotors()) {
|
||||
if (configuration.getStageCount() > 1) {
|
||||
canvas.newlineShowText(MASS_WITH_MOTORS);
|
||||
} else {
|
||||
@ -213,7 +214,11 @@ public class DesignReport {
|
||||
canvas.endText();
|
||||
|
||||
try {
|
||||
//Move the internal pointer of the document below that of what was just written using the direct byte buffer.
|
||||
/*
|
||||
* Move the internal pointer of the document below the rocket diagram and
|
||||
* the key attributes. The height of the rocket figure is already calculated
|
||||
* as diagramHeigt and the height of the attributes text is finalY - initialY.
|
||||
*/
|
||||
Paragraph paragraph = new Paragraph();
|
||||
float finalY = canvas.getYTLM();
|
||||
int heightOfDiagramAndText = (int) (pageSize.getHeight() - (finalY - initialY + diagramHeight));
|
||||
@ -223,28 +228,26 @@ public class DesignReport {
|
||||
|
||||
List<Simulation> simulations = rocketDocument.getSimulations();
|
||||
|
||||
int motorNumber = 0;
|
||||
for( FlightConfigurationId fcid : rocket.getIds()){
|
||||
|
||||
boolean firstMotor = true;
|
||||
for (FlightConfigurationId fcid : rocket.getIds()) {
|
||||
PdfPTable parent = new PdfPTable(2);
|
||||
parent.setWidthPercentage(100);
|
||||
parent.setHorizontalAlignment(Element.ALIGN_LEFT);
|
||||
parent.setSpacingBefore(0);
|
||||
parent.setWidths(new int[] { 1, 3 });
|
||||
|
||||
|
||||
int leading = 0;
|
||||
//The first motor config is always null. Skip it and the top-most motor, then set the leading.
|
||||
if ( motorNumber > 1) {
|
||||
leading = 25;
|
||||
}
|
||||
/* The first motor information will get no spacing
|
||||
* before it, while each subsequent table will need
|
||||
* a spacing of 25.
|
||||
*/
|
||||
int leading = (firstMotor) ? 0 : 25;
|
||||
|
||||
FlightData flight = findSimulation( fcid, simulations);
|
||||
addFlightData(flight, rocket, fcid, parent, leading);
|
||||
addMotorData(rocket, fcid, parent);
|
||||
document.add(parent);
|
||||
|
||||
motorNumber++;
|
||||
firstMotor = false;
|
||||
}
|
||||
} catch (DocumentException e) {
|
||||
log.error("Could not modify document.", e);
|
||||
@ -274,21 +277,22 @@ public class DesignReport {
|
||||
theFigure.updateFigure();
|
||||
|
||||
double scale =
|
||||
(thePageImageableWidth * 2.2) / theFigure.getWidth();
|
||||
(thePageImageableWidth * 2.2) / theFigure.getFigureWidth();
|
||||
theFigure.setScale(scale);
|
||||
/*
|
||||
* page dimensions are in points-per-inch, which, in Java2D, are the same as pixels-per-inch; thus we don't need any conversion
|
||||
/* Conveniently, page dimensions are in points-per-inch, which, in
|
||||
* Java2D, are the same as pixels-per-inch; thus we don't need any
|
||||
* conversion for the figure size.
|
||||
*/
|
||||
theFigure.setSize(thePageImageableWidth, thePageImageableHeight);
|
||||
theFigure.updateFigure();
|
||||
|
||||
final DefaultFontMapper mapper = new DefaultFontMapper();
|
||||
Graphics2D g2d = theCanvas.createGraphics(thePageImageableWidth, thePageImageableHeight * 2, mapper);
|
||||
final double halfFigureHeight = SCALE_FUDGE_FACTOR * theFigure.getFigureHeightPx() / 2;
|
||||
final double halfFigureHeight = SCALE_FUDGE_FACTOR * theFigure.getFigureHeight() / 2;
|
||||
int y = PrintUnit.POINTS_PER_INCH;
|
||||
//If the y dimension is negative, then it will potentially be drawn off the top of the page. Move the origin
|
||||
//to allow for this.
|
||||
if (theFigure.getHeight() < 0.0d) {
|
||||
if (theFigure.getDimensions().getY() < 0.0d) {
|
||||
y += (int) halfFigureHeight;
|
||||
}
|
||||
g2d.translate(20, y);
|
||||
@ -326,30 +330,26 @@ public class DesignReport {
|
||||
|
||||
DecimalFormat ttwFormat = new DecimalFormat("0.00");
|
||||
|
||||
MassCalculator massCalc = new MassCalculator();
|
||||
|
||||
if( !motorId.hasError() ){
|
||||
if( motorId.hasError() ){
|
||||
throw new IllegalStateException("Attempted to add motor data with an invalid fcid");
|
||||
}
|
||||
rocket.createFlightConfiguration(motorId);
|
||||
FlightConfiguration config = rocket.getFlightConfiguration( motorId);
|
||||
FlightConfiguration config = rocket.getFlightConfiguration(motorId);
|
||||
|
||||
int totalMotorCount = 0;
|
||||
double totalPropMass = 0;
|
||||
double totalImpulse = 0;
|
||||
double totalTTW = 0;
|
||||
|
||||
int stage = 0;
|
||||
double stageMass = 0;
|
||||
|
||||
boolean topBorder = false;
|
||||
for (RocketComponent c : rocket) {
|
||||
|
||||
if (c instanceof AxialStage) {
|
||||
config.clearAllStages();
|
||||
config.setOnlyStage(stage);
|
||||
stage++;
|
||||
stageMass = massCalc.getCGAnalysis( config).get(stage).weight;
|
||||
config.activateStagesThrough((AxialStage) c);
|
||||
RigidBody launchInfo = MassCalculator.calculateLaunch(config);
|
||||
stageMass = launchInfo.getMass();
|
||||
// Calculate total thrust-to-weight from only lowest stage motors
|
||||
totalTTW = 0;
|
||||
topBorder = true;
|
||||
@ -358,11 +358,19 @@ public class DesignReport {
|
||||
if (c instanceof MotorMount && ((MotorMount) c).isMotorMount()) {
|
||||
MotorMount mount = (MotorMount) c;
|
||||
|
||||
// TODO: refactor this... it's redundant with containing if, and could probably be simplified
|
||||
if (mount.isMotorMount() && (mount.getMotorConfig(motorId) != null) &&(null != mount.getMotorConfig(motorId).getMotor())) {
|
||||
Motor motor = mount.getMotorConfig(motorId).getMotor();
|
||||
int motorCount = mount.getMotorCount();
|
||||
MotorConfiguration motorConfig = mount.getMotorConfig(motorId);
|
||||
if (null == motorConfig) {
|
||||
log.warn("Unable to find motorConfig for motorId {}", motorId);
|
||||
continue;
|
||||
}
|
||||
|
||||
Motor motor = motorConfig.getMotor();
|
||||
if (null == motor) {
|
||||
log.warn("Motor instance is null for motorId {}", motorId);
|
||||
continue;
|
||||
}
|
||||
|
||||
int motorCount = mount.getMotorCount();
|
||||
|
||||
int border = Rectangle.NO_BORDER;
|
||||
if (topBorder) {
|
||||
@ -408,7 +416,6 @@ public class DesignReport {
|
||||
totalTTW += ttw * motorCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (totalMotorCount > 1) {
|
||||
int border = Rectangle.TOP;
|
||||
|
@ -3,6 +3,8 @@
|
||||
*/
|
||||
package net.sf.openrocket.gui.print;
|
||||
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
import net.sf.openrocket.gui.scalefigure.RocketFigure;
|
||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||
|
||||
@ -27,7 +29,15 @@ public class PrintFigure extends RocketFigure {
|
||||
updateFigure();
|
||||
}
|
||||
|
||||
public double getFigureHeightPx() {
|
||||
return this.getSize().height;
|
||||
public double getFigureHeight() {
|
||||
return this.subjectBounds_m.getHeight();
|
||||
}
|
||||
|
||||
public double getFigureWidth() {
|
||||
return this.subjectBounds_m.getWidth();
|
||||
}
|
||||
|
||||
public Rectangle2D getDimensions() {
|
||||
return this.subjectBounds_m.getBounds2D();
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,10 @@ public class SymmetricComponentShapes extends RocketComponentShape {
|
||||
// TODO: LOW: Uses only first component of cluster (not currently clusterable)
|
||||
|
||||
public static RocketComponentShape[] getShapesSide( final RocketComponent component, final Transformation transformation) {
|
||||
return getShapesSide(component, transformation, 1.0d);
|
||||
}
|
||||
|
||||
public static RocketComponentShape[] getShapesSide( final RocketComponent component, final Transformation transformation, final double scaleFactor ) {
|
||||
|
||||
|
||||
SymmetricComponent c = (SymmetricComponent) component;
|
||||
@ -82,14 +86,14 @@ public class SymmetricComponentShapes extends RocketComponentShape {
|
||||
|
||||
// TODO: LOW: curved path instead of linear
|
||||
Path2D.Double path = new Path2D.Double();
|
||||
path.moveTo((nose.x + points.get(len - 1).x) , (nose.y+points.get(len - 1).y) );
|
||||
path.moveTo((nose.x + points.get(len - 1).x) * scaleFactor, (nose.y+points.get(len - 1).y) * scaleFactor);
|
||||
for (i = len - 2; i >= 0; i--) {
|
||||
path.lineTo((nose.x+points.get(i).x), (nose.y+points.get(i).y) );
|
||||
path.lineTo((nose.x+points.get(i).x) * scaleFactor, (nose.y+points.get(i).y) * scaleFactor);
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
path.lineTo((nose.x+points.get(i).x) , (nose.y-points.get(i).y) );
|
||||
path.lineTo((nose.x+points.get(i).x) * scaleFactor, (nose.y-points.get(i).y) * scaleFactor);
|
||||
}
|
||||
path.lineTo((nose.x+points.get(len - 1).x) , (nose.y+points.get(len - 1).y) );
|
||||
path.lineTo((nose.x+points.get(len - 1).x) * scaleFactor , (nose.y+points.get(len - 1).y) * scaleFactor);
|
||||
path.closePath();
|
||||
|
||||
//s[len] = path;
|
||||
|
@ -37,15 +37,15 @@ public class TransitionShapes extends RocketComponentShape {
|
||||
double r2 = transition.getAftRadius();
|
||||
|
||||
Path2D.Float path = new Path2D.Float();
|
||||
path.moveTo( (frontCenter.x), (frontCenter.y+ r1));
|
||||
path.lineTo( (frontCenter.x+length), (frontCenter.y+r2));
|
||||
path.lineTo( (frontCenter.x+length), (frontCenter.y-r2));
|
||||
path.lineTo( (frontCenter.x), (frontCenter.y-r1));
|
||||
path.moveTo( (frontCenter.x) * scaleFactor, (frontCenter.y+ r1) * scaleFactor);
|
||||
path.lineTo( (frontCenter.x+length) * scaleFactor, (frontCenter.y+r2) * scaleFactor);
|
||||
path.lineTo( (frontCenter.x+length) * scaleFactor, (frontCenter.y-r2) * scaleFactor);
|
||||
path.lineTo( (frontCenter.x) * scaleFactor, (frontCenter.y-r1) * scaleFactor);
|
||||
path.closePath();
|
||||
|
||||
mainShapes = new RocketComponentShape[] { new RocketComponentShape( path, component) };
|
||||
} else {
|
||||
mainShapes = SymmetricComponentShapes.getShapesSide(component, transformation);
|
||||
mainShapes = SymmetricComponentShapes.getShapesSide(component, transformation, scaleFactor);
|
||||
}
|
||||
|
||||
Shape foreShoulder=null, aftShoulder=null;
|
||||
@ -57,7 +57,7 @@ public class TransitionShapes extends RocketComponentShape {
|
||||
final Transformation offsetTransform = Transformation.getTranslationTransform(-transition.getForeShoulderLength(), 0, 0);
|
||||
final Transformation foreShoulderTransform = transformation.applyTransformation(offsetTransform);
|
||||
|
||||
foreShoulder = TubeShapes.getShapesSide( foreShoulderTransform, shoulderLength, shoulderRadius);
|
||||
foreShoulder = TubeShapes.getShapesSide( foreShoulderTransform, shoulderLength, shoulderRadius, scaleFactor);
|
||||
arrayLength++;
|
||||
}
|
||||
if (transition.getAftShoulderLength() > 0.0005) {
|
||||
@ -66,7 +66,7 @@ public class TransitionShapes extends RocketComponentShape {
|
||||
final Transformation offsetTransform = Transformation.getTranslationTransform(transition.getLength(), 0, 0);
|
||||
final Transformation aftShoulderTransform = transformation.applyTransformation(offsetTransform);
|
||||
|
||||
aftShoulder = TubeShapes.getShapesSide(aftShoulderTransform, shoulderLength, shoulderRadius);
|
||||
aftShoulder = TubeShapes.getShapesSide(aftShoulderTransform, shoulderLength, shoulderRadius, scaleFactor);
|
||||
arrayLength++;
|
||||
}
|
||||
if (foreShoulder==null && aftShoulder==null)
|
||||
|
@ -10,14 +10,19 @@ import net.sf.openrocket.util.Transformation;
|
||||
|
||||
public class TubeShapes extends RocketComponentShape {
|
||||
|
||||
|
||||
public static Shape getShapesSide( final Transformation transformation, final double length, final double radius ){
|
||||
return getShapesSide(transformation, length, radius, 1.0d);
|
||||
}
|
||||
|
||||
public static Shape getShapesSide( final Transformation transformation, final double length, final double radius, final double scaleFactor ){
|
||||
|
||||
final Coordinate instanceAbsoluteLocation = transformation.transform(Coordinate.ZERO);
|
||||
|
||||
return new Rectangle2D.Double((instanceAbsoluteLocation.x), //x - the X coordinate of the upper-left corner of the newly constructed Rectangle2D
|
||||
(instanceAbsoluteLocation.y-radius), // y - the Y coordinate of the upper-left corner of the newly constructed Rectangle2D
|
||||
length, // w - the width of the newly constructed Rectangle2D
|
||||
2*radius); // h - the height of the newly constructed Rectangle2D
|
||||
return new Rectangle2D.Double((instanceAbsoluteLocation.x) * scaleFactor, //x - the X coordinate of the upper-left corner of the newly constructed Rectangle2D
|
||||
(instanceAbsoluteLocation.y-radius) * scaleFactor, // y - the Y coordinate of the upper-left corner of the newly constructed Rectangle2D
|
||||
length * scaleFactor, // w - the width of the newly constructed Rectangle2D
|
||||
2*radius * scaleFactor); // h - the height of the newly constructed Rectangle2D
|
||||
}
|
||||
|
||||
public static Shape getShapesBack( final Transformation transformation, final double radius ) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user