Tube fin component, configuration, viewing, file io.
This commit is contained in:
parent
279420dd46
commit
4e766c73d1
@ -617,6 +617,7 @@ compaddbuttons.Transition = Transition
|
|||||||
compaddbuttons.Trapezoidal = Trapezoidal
|
compaddbuttons.Trapezoidal = Trapezoidal
|
||||||
compaddbuttons.Elliptical = Elliptical
|
compaddbuttons.Elliptical = Elliptical
|
||||||
compaddbuttons.Freeform = Freeform
|
compaddbuttons.Freeform = Freeform
|
||||||
|
compaddbuttons.Tubefin = Tube fins
|
||||||
compaddbuttons.Launchlug = Launch lug
|
compaddbuttons.Launchlug = Launch lug
|
||||||
compaddbuttons.Innercomponent = Inner component
|
compaddbuttons.Innercomponent = Inner component
|
||||||
compaddbuttons.Innertube = Inner tube
|
compaddbuttons.Innertube = Inner tube
|
||||||
@ -1326,6 +1327,8 @@ InnerTube.InnerTube = Inner Tube
|
|||||||
TrapezoidFinSet.TrapezoidFinSet = Trapezoidal fin set
|
TrapezoidFinSet.TrapezoidFinSet = Trapezoidal fin set
|
||||||
! FreeformFinSet
|
! FreeformFinSet
|
||||||
FreeformFinSet.FreeformFinSet = Freeform fin set
|
FreeformFinSet.FreeformFinSet = Freeform fin set
|
||||||
|
! TubeFinSEt
|
||||||
|
TubeFinSet.TubeFinSet = Tube fin set
|
||||||
!MassComponent
|
!MassComponent
|
||||||
MassComponent.MassComponent = Mass component
|
MassComponent.MassComponent = Mass component
|
||||||
! Parachute
|
! Parachute
|
||||||
@ -1369,6 +1372,7 @@ ComponentIcons.Transition = Transition
|
|||||||
ComponentIcons.Trapezoidalfinset = Trapezoidal fin set
|
ComponentIcons.Trapezoidalfinset = Trapezoidal fin set
|
||||||
ComponentIcons.Ellipticalfinset = Elliptical fin set
|
ComponentIcons.Ellipticalfinset = Elliptical fin set
|
||||||
ComponentIcons.Freeformfinset = Freeform fin set
|
ComponentIcons.Freeformfinset = Freeform fin set
|
||||||
|
ComponentIcons.Tubefinset = Tube fin set
|
||||||
ComponentIcons.Launchlug = Launch lug
|
ComponentIcons.Launchlug = Launch lug
|
||||||
ComponentIcons.Innertube = Inner tube
|
ComponentIcons.Innertube = Inner tube
|
||||||
ComponentIcons.Tubecoupler = Tube coupler
|
ComponentIcons.Tubecoupler = Tube coupler
|
||||||
|
|||||||
BIN
core/resources/pix/componenticons/tubefin-large.png
Normal file
BIN
core/resources/pix/componenticons/tubefin-large.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
BIN
core/resources/pix/componenticons/tubefin-small.png
Normal file
BIN
core/resources/pix/componenticons/tubefin-small.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 553 B |
@ -0,0 +1,27 @@
|
|||||||
|
package net.sf.openrocket.aerodynamics.barrowman;
|
||||||
|
|
||||||
|
import net.sf.openrocket.aerodynamics.AerodynamicForces;
|
||||||
|
import net.sf.openrocket.aerodynamics.FlightConditions;
|
||||||
|
import net.sf.openrocket.aerodynamics.WarningSet;
|
||||||
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
|
|
||||||
|
public class TubeFinSetCalc extends RocketComponentCalc {
|
||||||
|
|
||||||
|
public TubeFinSetCalc(RocketComponent component) {
|
||||||
|
super(component);
|
||||||
|
// TODO Auto-generated constructor stub
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void calculateNonaxialForces(FlightConditions conditions, AerodynamicForces forces, WarningSet warnings) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double calculatePressureDragForce(FlightConditions conditions, double stagnationCD, double baseCD, WarningSet warnings) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -18,6 +18,7 @@ import net.sf.openrocket.rocketcomponent.RadiusRingComponent;
|
|||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.rocketcomponent.Transition;
|
import net.sf.openrocket.rocketcomponent.Transition;
|
||||||
import net.sf.openrocket.rocketcomponent.TubeCoupler;
|
import net.sf.openrocket.rocketcomponent.TubeCoupler;
|
||||||
|
import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
||||||
import net.sf.openrocket.util.Color;
|
import net.sf.openrocket.util.Color;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ public class DefaultAppearance {
|
|||||||
public static Appearance getDefaultAppearance(RocketComponent c) {
|
public static Appearance getDefaultAppearance(RocketComponent c) {
|
||||||
if (c instanceof BodyTube)
|
if (c instanceof BodyTube)
|
||||||
return ESTES_BT;
|
return ESTES_BT;
|
||||||
if (c instanceof InnerTube || c instanceof TubeCoupler)
|
if (c instanceof InnerTube || c instanceof TubeCoupler || c instanceof TubeFinSet)
|
||||||
return ESTES_IT;
|
return ESTES_IT;
|
||||||
if (c instanceof FinSet)
|
if (c instanceof FinSet)
|
||||||
return BALSA;
|
return BALSA;
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import net.sf.openrocket.rocketcomponent.Rocket;
|
|||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.rocketcomponent.Stage;
|
import net.sf.openrocket.rocketcomponent.Stage;
|
||||||
import net.sf.openrocket.rocketcomponent.TubeCoupler;
|
import net.sf.openrocket.rocketcomponent.TubeCoupler;
|
||||||
|
import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
||||||
import net.sf.openrocket.simulation.FlightData;
|
import net.sf.openrocket.simulation.FlightData;
|
||||||
import net.sf.openrocket.simulation.FlightDataBranch;
|
import net.sf.openrocket.simulation.FlightDataBranch;
|
||||||
import net.sf.openrocket.simulation.FlightDataType;
|
import net.sf.openrocket.simulation.FlightDataType;
|
||||||
@ -217,6 +218,9 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
*/
|
*/
|
||||||
private int calculateNecessaryFileVersion(OpenRocketDocument document, StorageOptions opts) {
|
private int calculateNecessaryFileVersion(OpenRocketDocument document, StorageOptions opts) {
|
||||||
/*
|
/*
|
||||||
|
* File version 1.7 is required for:
|
||||||
|
* - saving tube fins.
|
||||||
|
*
|
||||||
* File version 1.6 is required for:
|
* File version 1.6 is required for:
|
||||||
* - saving files using appearances and textures, flight configurations.
|
* - saving files using appearances and textures, flight configurations.
|
||||||
*
|
*
|
||||||
@ -236,6 +240,18 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
* Otherwise use version 1.0.
|
* Otherwise use version 1.0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/////////////////
|
||||||
|
// Version 1.7 //
|
||||||
|
/////////////////
|
||||||
|
|
||||||
|
// Search the rocket for any TubeFinSet objects (version 1.7)
|
||||||
|
for (RocketComponent c : document.getRocket()) {
|
||||||
|
if (c instanceof TubeFinSet) {
|
||||||
|
return FILE_VERSION_DIVISOR + 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/////////////////
|
/////////////////
|
||||||
// Version 1.6 //
|
// Version 1.6 //
|
||||||
/////////////////
|
/////////////////
|
||||||
|
|||||||
@ -40,6 +40,7 @@ import net.sf.openrocket.rocketcomponent.ThicknessRingComponent;
|
|||||||
import net.sf.openrocket.rocketcomponent.Transition;
|
import net.sf.openrocket.rocketcomponent.Transition;
|
||||||
import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
|
import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
|
||||||
import net.sf.openrocket.rocketcomponent.TubeCoupler;
|
import net.sf.openrocket.rocketcomponent.TubeCoupler;
|
||||||
|
import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
||||||
import net.sf.openrocket.util.BugException;
|
import net.sf.openrocket.util.BugException;
|
||||||
import net.sf.openrocket.util.Color;
|
import net.sf.openrocket.util.Color;
|
||||||
import net.sf.openrocket.util.LineStyle;
|
import net.sf.openrocket.util.LineStyle;
|
||||||
@ -48,7 +49,7 @@ import net.sf.openrocket.util.Reflection;
|
|||||||
class DocumentConfig {
|
class DocumentConfig {
|
||||||
|
|
||||||
/* Remember to update OpenRocketSaver as well! */
|
/* Remember to update OpenRocketSaver as well! */
|
||||||
public static final String[] SUPPORTED_VERSIONS = { "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6" };
|
public static final String[] SUPPORTED_VERSIONS = { "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7" };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Divisor used in converting an integer version to the point-represented version.
|
* Divisor used in converting an integer version to the point-represented version.
|
||||||
@ -69,6 +70,7 @@ class DocumentConfig {
|
|||||||
constructors.put("trapezoidfinset", TrapezoidFinSet.class.getConstructor(new Class<?>[0]));
|
constructors.put("trapezoidfinset", TrapezoidFinSet.class.getConstructor(new Class<?>[0]));
|
||||||
constructors.put("ellipticalfinset", EllipticalFinSet.class.getConstructor(new Class<?>[0]));
|
constructors.put("ellipticalfinset", EllipticalFinSet.class.getConstructor(new Class<?>[0]));
|
||||||
constructors.put("freeformfinset", FreeformFinSet.class.getConstructor(new Class<?>[0]));
|
constructors.put("freeformfinset", FreeformFinSet.class.getConstructor(new Class<?>[0]));
|
||||||
|
constructors.put("tubefinset", TubeFinSet.class.getConstructor(new Class<?>[0]));
|
||||||
constructors.put("launchlug", LaunchLug.class.getConstructor(new Class<?>[0]));
|
constructors.put("launchlug", LaunchLug.class.getConstructor(new Class<?>[0]));
|
||||||
|
|
||||||
// Internal components
|
// Internal components
|
||||||
@ -226,6 +228,20 @@ class DocumentConfig {
|
|||||||
|
|
||||||
// FreeformFinSet points handled as a special handler
|
// FreeformFinSet points handled as a special handler
|
||||||
|
|
||||||
|
// TubeFinSet
|
||||||
|
setters.put("TubeFinSet:fincount", new IntSetter(
|
||||||
|
Reflection.findMethod(TubeFinSet.class, "setFinCount", int.class)));
|
||||||
|
setters.put("TubeFinSet:rotation", new DoubleSetter(
|
||||||
|
Reflection.findMethod(TubeFinSet.class, "setBaseRotation", double.class), Math.PI / 180.0));
|
||||||
|
setters.put("TubeFinSet:thickness", new DoubleSetter(
|
||||||
|
Reflection.findMethod(TubeFinSet.class, "setThickness", double.class)));
|
||||||
|
setters.put("TubeFinSet:length", new DoubleSetter(
|
||||||
|
Reflection.findMethod(TubeFinSet.class, "setLength", double.class)));
|
||||||
|
setters.put("TubeFinSet:radius", new DoubleSetter(
|
||||||
|
Reflection.findMethod(TubeFinSet.class, "setOuterRadius", double.class),
|
||||||
|
"auto",
|
||||||
|
Reflection.findMethod(TubeFinSet.class, "setOuterRadiusAutomatic", boolean.class)));
|
||||||
|
|
||||||
// LaunchLug
|
// LaunchLug
|
||||||
setters.put("LaunchLug:radius", new DoubleSetter(
|
setters.put("LaunchLug:radius", new DoubleSetter(
|
||||||
Reflection.findMethod(LaunchLug.class, "setOuterRadius", double.class)));
|
Reflection.findMethod(LaunchLug.class, "setOuterRadius", double.class)));
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import net.sf.openrocket.rocketcomponent.InternalComponent;
|
|||||||
import net.sf.openrocket.rocketcomponent.LaunchLug;
|
import net.sf.openrocket.rocketcomponent.LaunchLug;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent.Position;
|
import net.sf.openrocket.rocketcomponent.RocketComponent.Position;
|
||||||
|
import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
||||||
|
|
||||||
class PositionSetter implements Setter {
|
class PositionSetter implements Setter {
|
||||||
|
|
||||||
@ -40,6 +41,9 @@ class PositionSetter implements Setter {
|
|||||||
} else if (c instanceof InternalComponent) {
|
} else if (c instanceof InternalComponent) {
|
||||||
((InternalComponent) c).setRelativePosition(type);
|
((InternalComponent) c).setRelativePosition(type);
|
||||||
c.setPositionValue(pos);
|
c.setPositionValue(pos);
|
||||||
|
} else if (c instanceof TubeFinSet) {
|
||||||
|
((TubeFinSet) c).setRelativePosition(type);
|
||||||
|
c.setPositionValue(pos);
|
||||||
} else {
|
} else {
|
||||||
warnings.add(Warning.FILE_INVALID_PARAMETER);
|
warnings.add(Warning.FILE_INVALID_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,38 @@
|
|||||||
|
package net.sf.openrocket.file.openrocket.savers;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
||||||
|
|
||||||
|
|
||||||
|
public class TubeFinSetSaver extends ExternalComponentSaver {
|
||||||
|
|
||||||
|
private static final TubeFinSetSaver instance = new TubeFinSetSaver();
|
||||||
|
|
||||||
|
public static List<String> getElements(net.sf.openrocket.rocketcomponent.RocketComponent c) {
|
||||||
|
List<String> list = new ArrayList<String>();
|
||||||
|
|
||||||
|
list.add("<tubefinset>");
|
||||||
|
instance.addParams(c, list);
|
||||||
|
list.add("</tubefinset>");
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addParams(net.sf.openrocket.rocketcomponent.RocketComponent c, List<String> elements) {
|
||||||
|
super.addParams(c, elements);
|
||||||
|
TubeFinSet fins = (TubeFinSet) c;
|
||||||
|
|
||||||
|
elements.add("<fincount>" + fins.getFinCount() + "</fincount>");
|
||||||
|
elements.add("<rotation>" + (fins.getBaseRotation() * 180.0 / Math.PI) + "</rotation>");
|
||||||
|
if (fins.isOuterRadiusAutomatic())
|
||||||
|
elements.add("<radius>auto</radius>");
|
||||||
|
else
|
||||||
|
elements.add("<radius>" + fins.getOuterRadius() + "</radius>");
|
||||||
|
elements.add("<length>" + fins.getLength() + "</length>");
|
||||||
|
elements.add("<thickness>" + fins.getThickness() + "</thickness>");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
316
core/src/net/sf/openrocket/rocketcomponent/TubeFinSet.java
Normal file
316
core/src/net/sf/openrocket/rocketcomponent/TubeFinSet.java
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
package net.sf.openrocket.rocketcomponent;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.sf.openrocket.l10n.Translator;
|
||||||
|
import net.sf.openrocket.preset.ComponentPreset;
|
||||||
|
import net.sf.openrocket.preset.ComponentPreset.Type;
|
||||||
|
import net.sf.openrocket.startup.Application;
|
||||||
|
import net.sf.openrocket.util.Coordinate;
|
||||||
|
import net.sf.openrocket.util.MathUtil;
|
||||||
|
import net.sf.openrocket.util.Transformation;
|
||||||
|
|
||||||
|
public class TubeFinSet extends ExternalComponent {
|
||||||
|
private static final Translator trans = Application.getTranslator();
|
||||||
|
|
||||||
|
private final static double DEFAULT_RADIUS = 0.025;
|
||||||
|
|
||||||
|
private boolean autoRadius = true; // Radius chosen automatically based on parent component
|
||||||
|
private double outerRadius = DEFAULT_RADIUS;
|
||||||
|
protected double thickness = 0.002;
|
||||||
|
|
||||||
|
protected int fins = 6;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotation angle of the first fin. Zero corresponds to the positive y-axis.
|
||||||
|
*/
|
||||||
|
protected double rotation = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotation about the x-axis by angle this.rotation.
|
||||||
|
*/
|
||||||
|
protected Transformation baseRotation = Transformation.rotate_x(rotation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotation about the x-axis by 2*PI/fins.
|
||||||
|
*/
|
||||||
|
protected Transformation finRotation = Transformation.rotate_x(2 * Math.PI / fins);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New FinSet with given number of fins and given base rotation angle.
|
||||||
|
* Sets the component relative position to POSITION_RELATIVE_BOTTOM,
|
||||||
|
* i.e. fins are positioned at the bottom of the parent component.
|
||||||
|
*/
|
||||||
|
public TubeFinSet() {
|
||||||
|
super(RocketComponent.Position.BOTTOM);
|
||||||
|
length = 0.10;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLength(double length) {
|
||||||
|
if (MathUtil.equals(this.length, length))
|
||||||
|
return;
|
||||||
|
this.length = length;
|
||||||
|
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isOuterRadiusAutomatic() {
|
||||||
|
return autoRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the outer radius of the body tube.
|
||||||
|
*
|
||||||
|
* @return the outside radius of the tube
|
||||||
|
*/
|
||||||
|
public double getOuterRadius() {
|
||||||
|
if (autoRadius) {
|
||||||
|
// Return auto radius from front or rear
|
||||||
|
double r = -1;
|
||||||
|
RocketComponent c = this.getParent();
|
||||||
|
if (c != null) {
|
||||||
|
if (c instanceof SymmetricComponent) {
|
||||||
|
r = ((SymmetricComponent) c).getAftRadius();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (r < 0)
|
||||||
|
r = DEFAULT_RADIUS;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
return outerRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the outer radius of the body tube. If the radius is less than the wall thickness,
|
||||||
|
* the wall thickness is decreased accordingly of the value of the radius.
|
||||||
|
* This method sets the automatic radius off.
|
||||||
|
*
|
||||||
|
* @param radius the outside radius in standard units
|
||||||
|
*/
|
||||||
|
public void setOuterRadius(double radius) {
|
||||||
|
if ((this.outerRadius == radius) && (autoRadius == false))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.autoRadius = false;
|
||||||
|
this.outerRadius = Math.max(radius, 0);
|
||||||
|
|
||||||
|
if (this.thickness > this.outerRadius)
|
||||||
|
this.thickness = this.outerRadius;
|
||||||
|
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||||
|
clearPreset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the radius is selected automatically or not.
|
||||||
|
*/
|
||||||
|
public void setOuterRadiusAutomatic(boolean auto) {
|
||||||
|
if (autoRadius == auto)
|
||||||
|
return;
|
||||||
|
|
||||||
|
autoRadius = auto;
|
||||||
|
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||||
|
clearPreset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getInnerRadius() {
|
||||||
|
return Math.max(getOuterRadius() - thickness, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInnerRadius(double r) {
|
||||||
|
setThickness(getOuterRadius() - r);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the component wall thickness.
|
||||||
|
*/
|
||||||
|
public double getThickness() {
|
||||||
|
return Math.min(thickness, getOuterRadius());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the component wall thickness. Values greater than the maximum radius are not
|
||||||
|
* allowed, and will result in setting the thickness to the maximum radius.
|
||||||
|
*/
|
||||||
|
public void setThickness(double thickness) {
|
||||||
|
if ((this.thickness == thickness))
|
||||||
|
return;
|
||||||
|
this.thickness = MathUtil.clamp(thickness, 0, getOuterRadius());
|
||||||
|
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
||||||
|
clearPreset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the number of fins in the set.
|
||||||
|
* @return The number of fins.
|
||||||
|
*/
|
||||||
|
public int getFinCount() {
|
||||||
|
return fins;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the number of fins in the set.
|
||||||
|
* @param n The number of fins, greater of equal to one.
|
||||||
|
*/
|
||||||
|
public void setFinCount(int n) {
|
||||||
|
if (fins == n)
|
||||||
|
return;
|
||||||
|
if (n < 1)
|
||||||
|
n = 1;
|
||||||
|
if (n > 8)
|
||||||
|
n = 8;
|
||||||
|
fins = n;
|
||||||
|
finRotation = Transformation.rotate_x(2 * Math.PI / fins);
|
||||||
|
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the base rotation amount of the first fin.
|
||||||
|
* @return The base rotation amount.
|
||||||
|
*/
|
||||||
|
public double getBaseRotation() {
|
||||||
|
return rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getFinRotation() {
|
||||||
|
return 2 * Math.PI / fins;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the base rotation amount of the first fin.
|
||||||
|
* @param r The base rotation amount.
|
||||||
|
*/
|
||||||
|
public void setBaseRotation(double r) {
|
||||||
|
r = MathUtil.reduce180(r);
|
||||||
|
if (MathUtil.equals(r, rotation))
|
||||||
|
return;
|
||||||
|
rotation = r;
|
||||||
|
baseRotation = Transformation.rotate_x(rotation);
|
||||||
|
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Transformation getBaseRotationTransformation() {
|
||||||
|
return baseRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Transformation getFinRotationTransformation() {
|
||||||
|
return finRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRelativePosition(RocketComponent.Position position) {
|
||||||
|
super.setRelativePosition(position);
|
||||||
|
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPositionValue(double value) {
|
||||||
|
super.setPositionValue(value);
|
||||||
|
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getComponentVolume() {
|
||||||
|
double or = getOuterRadius();
|
||||||
|
double ir = getInnerRadius();
|
||||||
|
double volume = or * or - ir * ir;
|
||||||
|
volume *= Math.PI;
|
||||||
|
volume *= length;
|
||||||
|
volume *= fins;
|
||||||
|
return volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getComponentName() {
|
||||||
|
//// Tube Fin Set
|
||||||
|
return trans.get("TubeFinSet.TubeFinSet");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Coordinate getComponentCG() {
|
||||||
|
double mass = getComponentMass(); // safe
|
||||||
|
double halflength = length / 2;
|
||||||
|
|
||||||
|
if (fins == 1) {
|
||||||
|
return baseRotation.transform(
|
||||||
|
new Coordinate(halflength, getOuterRadius() + getBodyRadius(), 0, mass));
|
||||||
|
} else {
|
||||||
|
return new Coordinate(halflength, 0, 0, mass);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getLongitudinalUnitInertia() {
|
||||||
|
// FIXME - this is very likely completely wrong
|
||||||
|
// 1/12 * (3 * (r1^2 + r2^2) + h^2)
|
||||||
|
return (3 * (MathUtil.pow2(getInnerRadius())) + MathUtil.pow2(getOuterRadius()) + MathUtil.pow2(getLength())) / 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getRotationalUnitInertia() {
|
||||||
|
// The rotational inertia of a single fin about its center.
|
||||||
|
// 1/2 * (r1^2 + r2^2)
|
||||||
|
double icentermass = (MathUtil.pow2(getInnerRadius()) + MathUtil.pow2(getOuterRadius())) / 2;
|
||||||
|
if (fins == 1) {
|
||||||
|
return icentermass;
|
||||||
|
} else {
|
||||||
|
// Use parallel axis rule and multiply by number of fins.
|
||||||
|
return fins * (icentermass + MathUtil.pow2(getOuterRadius()) + getBodyRadius());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allowsChildren() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getPresetType() {
|
||||||
|
return ComponentPreset.Type.BODY_TUBE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCompatible(Class<? extends RocketComponent> type) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Coordinate> getComponentBounds() {
|
||||||
|
List<Coordinate> bounds = new ArrayList<Coordinate>();
|
||||||
|
double r = getBodyRadius();
|
||||||
|
|
||||||
|
addBound(bounds, 0, 2 * (r + outerRadius));
|
||||||
|
addBound(bounds, length, 2 * (r + outerRadius));
|
||||||
|
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the radius of the BodyComponent the fin set is situated on. Currently
|
||||||
|
* only supports SymmetricComponents and returns the radius at the starting point of the
|
||||||
|
* root chord.
|
||||||
|
*
|
||||||
|
* @return radius of the underlying BodyComponent or 0 if none exists.
|
||||||
|
*/
|
||||||
|
public double getBodyRadius() {
|
||||||
|
RocketComponent s;
|
||||||
|
|
||||||
|
s = this.getParent();
|
||||||
|
while (s != null) {
|
||||||
|
if (s instanceof SymmetricComponent) {
|
||||||
|
double x = this.toRelative(new Coordinate(0, 0, 0), s)[0].x;
|
||||||
|
return ((SymmetricComponent) s).getRadius(x);
|
||||||
|
}
|
||||||
|
s = s.getParent();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -14,6 +14,7 @@ import net.sf.openrocket.rocketcomponent.LaunchLug;
|
|||||||
import net.sf.openrocket.rocketcomponent.MassObject;
|
import net.sf.openrocket.rocketcomponent.MassObject;
|
||||||
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
|
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
|
import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
||||||
import net.sf.openrocket.util.BugException;
|
import net.sf.openrocket.util.BugException;
|
||||||
import net.sf.openrocket.util.BuildProperties;
|
import net.sf.openrocket.util.BuildProperties;
|
||||||
import net.sf.openrocket.util.Color;
|
import net.sf.openrocket.util.Color;
|
||||||
@ -414,6 +415,7 @@ public abstract class Preferences {
|
|||||||
private static final HashMap<Class<?>, String> DEFAULT_COLORS = new HashMap<Class<?>, String>();
|
private static final HashMap<Class<?>, String> DEFAULT_COLORS = new HashMap<Class<?>, String>();
|
||||||
static {
|
static {
|
||||||
DEFAULT_COLORS.put(BodyComponent.class, "0,0,240");
|
DEFAULT_COLORS.put(BodyComponent.class, "0,0,240");
|
||||||
|
DEFAULT_COLORS.put(TubeFinSet.class, "0,0,200");
|
||||||
DEFAULT_COLORS.put(FinSet.class, "0,0,200");
|
DEFAULT_COLORS.put(FinSet.class, "0,0,200");
|
||||||
DEFAULT_COLORS.put(LaunchLug.class, "0,0,180");
|
DEFAULT_COLORS.put(LaunchLug.class, "0,0,180");
|
||||||
DEFAULT_COLORS.put(InternalComponent.class, "170,0,100");
|
DEFAULT_COLORS.put(InternalComponent.class, "170,0,100");
|
||||||
|
|||||||
@ -0,0 +1,166 @@
|
|||||||
|
package net.sf.openrocket.gui.configdialog;
|
||||||
|
|
||||||
|
|
||||||
|
import javax.swing.JComboBox;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JSpinner;
|
||||||
|
|
||||||
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
import net.sf.openrocket.document.OpenRocketDocument;
|
||||||
|
import net.sf.openrocket.gui.SpinnerEditor;
|
||||||
|
import net.sf.openrocket.gui.adaptors.DoubleModel;
|
||||||
|
import net.sf.openrocket.gui.adaptors.EnumModel;
|
||||||
|
import net.sf.openrocket.gui.adaptors.IntegerModel;
|
||||||
|
import net.sf.openrocket.gui.components.BasicSlider;
|
||||||
|
import net.sf.openrocket.gui.components.UnitSelector;
|
||||||
|
import net.sf.openrocket.l10n.Translator;
|
||||||
|
import net.sf.openrocket.material.Material;
|
||||||
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
|
import net.sf.openrocket.startup.Application;
|
||||||
|
import net.sf.openrocket.unit.UnitGroup;
|
||||||
|
|
||||||
|
public class TubeFinSetConfig extends RocketComponentConfig {
|
||||||
|
|
||||||
|
private MotorConfig motorConfigPane = null;
|
||||||
|
private static final Translator trans = Application.getTranslator();
|
||||||
|
|
||||||
|
public TubeFinSetConfig(OpenRocketDocument d, RocketComponent c) {
|
||||||
|
super(d, c);
|
||||||
|
|
||||||
|
JPanel primary = new JPanel(new MigLayout("fill"));
|
||||||
|
|
||||||
|
|
||||||
|
JPanel panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::][]", ""));
|
||||||
|
|
||||||
|
//// Number of fins
|
||||||
|
panel.add(new JLabel(trans.get("EllipticalFinSetCfg.Nbroffins")));
|
||||||
|
|
||||||
|
IntegerModel im = new IntegerModel(component, "FinCount", 1, 8);
|
||||||
|
|
||||||
|
JSpinner spin = new JSpinner(im.getSpinnerModel());
|
||||||
|
spin.setEditor(new SpinnerEditor(spin));
|
||||||
|
panel.add(spin, "growx, wrap");
|
||||||
|
|
||||||
|
//// Length:
|
||||||
|
panel.add(new JLabel(trans.get("LaunchLugCfg.lbl.Length")));
|
||||||
|
|
||||||
|
DoubleModel m = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0);
|
||||||
|
|
||||||
|
spin = new JSpinner(m.getSpinnerModel());
|
||||||
|
spin.setEditor(new SpinnerEditor(spin));
|
||||||
|
panel.add(spin, "growx");
|
||||||
|
|
||||||
|
panel.add(new UnitSelector(m), "growx");
|
||||||
|
panel.add(new BasicSlider(m.getSliderModel(0, 0.02, 0.1)), "w 100lp, wrap para");
|
||||||
|
|
||||||
|
|
||||||
|
//// Outer diameter:
|
||||||
|
panel.add(new JLabel(trans.get("LaunchLugCfg.lbl.Outerdiam")));
|
||||||
|
|
||||||
|
DoubleModel od = new DoubleModel(component, "OuterRadius", 2, UnitGroup.UNITS_LENGTH, 0);
|
||||||
|
// Diameter = 2*Radius
|
||||||
|
|
||||||
|
spin = new JSpinner(od.getSpinnerModel());
|
||||||
|
spin.setEditor(new SpinnerEditor(spin));
|
||||||
|
panel.add(spin, "growx");
|
||||||
|
|
||||||
|
panel.add(new UnitSelector(od), "growx");
|
||||||
|
panel.add(new BasicSlider(od.getSliderModel(0, 0.04, 0.2)), "w 100lp, wrap rel");
|
||||||
|
|
||||||
|
|
||||||
|
//// Inner diameter:
|
||||||
|
panel.add(new JLabel(trans.get("LaunchLugCfg.lbl.Innerdiam")));
|
||||||
|
|
||||||
|
// Diameter = 2*Radius
|
||||||
|
m = new DoubleModel(component, "InnerRadius", 2, UnitGroup.UNITS_LENGTH, 0);
|
||||||
|
|
||||||
|
|
||||||
|
spin = new JSpinner(m.getSpinnerModel());
|
||||||
|
spin.setEditor(new SpinnerEditor(spin));
|
||||||
|
panel.add(spin, "growx");
|
||||||
|
|
||||||
|
panel.add(new UnitSelector(m), "growx");
|
||||||
|
panel.add(new BasicSlider(m.getSliderModel(new DoubleModel(0), od)), "w 100lp, wrap rel");
|
||||||
|
|
||||||
|
|
||||||
|
//// Wall thickness
|
||||||
|
//// Thickness:
|
||||||
|
panel.add(new JLabel(trans.get("LaunchLugCfg.lbl.Thickness")));
|
||||||
|
|
||||||
|
m = new DoubleModel(component, "Thickness", UnitGroup.UNITS_LENGTH, 0);
|
||||||
|
|
||||||
|
spin = new JSpinner(m.getSpinnerModel());
|
||||||
|
spin.setEditor(new SpinnerEditor(spin));
|
||||||
|
panel.add(spin, "growx");
|
||||||
|
|
||||||
|
panel.add(new UnitSelector(m), "growx");
|
||||||
|
panel.add(new BasicSlider(m.getSliderModel(0, 0.01)), "w 100lp, wrap 20lp");
|
||||||
|
|
||||||
|
|
||||||
|
//// Base rotation
|
||||||
|
//// Fin rotation:
|
||||||
|
JLabel label = new JLabel(trans.get("TrapezoidFinSetCfg.lbl.Finrotation"));
|
||||||
|
//// The angle of the first fin in the fin set.
|
||||||
|
label.setToolTipText(trans.get("TrapezoidFinSetCfg.lbl.ttip.Finrotation"));
|
||||||
|
panel.add(label);
|
||||||
|
|
||||||
|
m = new DoubleModel(component, "BaseRotation", UnitGroup.UNITS_ANGLE);
|
||||||
|
|
||||||
|
spin = new JSpinner(m.getSpinnerModel());
|
||||||
|
spin.setEditor(new SpinnerEditor(spin));
|
||||||
|
panel.add(spin, "growx");
|
||||||
|
|
||||||
|
panel.add(new UnitSelector(m), "growx");
|
||||||
|
panel.add(new BasicSlider(m.getSliderModel(-Math.PI, Math.PI)), "w 100lp, wrap");
|
||||||
|
|
||||||
|
primary.add(panel, "grow, gapright 20lp");
|
||||||
|
panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::][]", ""));
|
||||||
|
|
||||||
|
//// Position relative to:
|
||||||
|
panel.add(new JLabel(trans.get("LaunchLugCfg.lbl.Posrelativeto")));
|
||||||
|
|
||||||
|
JComboBox combo = new JComboBox(
|
||||||
|
new EnumModel<RocketComponent.Position>(component, "RelativePosition",
|
||||||
|
new RocketComponent.Position[] {
|
||||||
|
RocketComponent.Position.TOP,
|
||||||
|
RocketComponent.Position.MIDDLE,
|
||||||
|
RocketComponent.Position.BOTTOM,
|
||||||
|
RocketComponent.Position.ABSOLUTE
|
||||||
|
}));
|
||||||
|
panel.add(combo, "spanx, growx, wrap");
|
||||||
|
|
||||||
|
//// plus
|
||||||
|
panel.add(new JLabel(trans.get("LaunchLugCfg.lbl.plus")), "right");
|
||||||
|
|
||||||
|
m = new DoubleModel(component, "PositionValue", UnitGroup.UNITS_LENGTH);
|
||||||
|
spin = new JSpinner(m.getSpinnerModel());
|
||||||
|
spin.setEditor(new SpinnerEditor(spin));
|
||||||
|
panel.add(spin, "growx");
|
||||||
|
|
||||||
|
panel.add(new UnitSelector(m), "growx");
|
||||||
|
panel.add(new BasicSlider(m.getSliderModel(
|
||||||
|
new DoubleModel(component.getParent(), "Length", -1.0, UnitGroup.UNITS_NONE),
|
||||||
|
new DoubleModel(component.getParent(), "Length"))),
|
||||||
|
"w 100lp, wrap para");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//// Material
|
||||||
|
materialPanel(panel, Material.Type.BULK);
|
||||||
|
|
||||||
|
|
||||||
|
primary.add(panel, "grow");
|
||||||
|
|
||||||
|
//// General and General properties
|
||||||
|
tabbedPane.insertTab(trans.get("LaunchLugCfg.tab.General"), null, primary,
|
||||||
|
trans.get("LaunchLugCfg.tab.Generalprop"), 0);
|
||||||
|
tabbedPane.setSelectedIndex(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateFields() {
|
||||||
|
super.updateFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -17,6 +17,7 @@ import net.sf.openrocket.rocketcomponent.RingComponent;
|
|||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.rocketcomponent.Transition;
|
import net.sf.openrocket.rocketcomponent.Transition;
|
||||||
import net.sf.openrocket.rocketcomponent.Transition.Shape;
|
import net.sf.openrocket.rocketcomponent.Transition.Shape;
|
||||||
|
import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@ -28,28 +29,28 @@ import org.slf4j.LoggerFactory;
|
|||||||
public class ComponentRenderer {
|
public class ComponentRenderer {
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static final Logger log = LoggerFactory.getLogger(ComponentRenderer.class);
|
private static final Logger log = LoggerFactory.getLogger(ComponentRenderer.class);
|
||||||
|
|
||||||
private int LOD = 80;
|
private int LOD = 80;
|
||||||
|
|
||||||
GLU glu;
|
GLU glu;
|
||||||
GLUquadric q;
|
GLUquadric q;
|
||||||
FinRenderer fr = new FinRenderer();
|
FinRenderer fr = new FinRenderer();
|
||||||
|
|
||||||
public ComponentRenderer() {
|
public ComponentRenderer() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(GLAutoDrawable drawable) {
|
public void init(GLAutoDrawable drawable) {
|
||||||
glu = new GLU();
|
glu = new GLU();
|
||||||
q = glu.gluNewQuadric();
|
q = glu.gluNewQuadric();
|
||||||
glu.gluQuadricTexture(q, true);
|
glu.gluQuadricTexture(q, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void updateFigure(GLAutoDrawable drawable) {
|
public void updateFigure(GLAutoDrawable drawable) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Geometry getGeometry(final RocketComponent c, final Surface which) {
|
public Geometry getGeometry(final RocketComponent c, final Surface which) {
|
||||||
return new Geometry() {
|
return new Geometry() {
|
||||||
@Override
|
@Override
|
||||||
@ -64,7 +65,7 @@ public class ComponentRenderer {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public Geometry getGeometry(final Motor motor, Surface which) {
|
public Geometry getGeometry(final Motor motor, Surface which) {
|
||||||
return new Geometry() {
|
return new Geometry() {
|
||||||
@Override
|
@Override
|
||||||
@ -73,20 +74,20 @@ public class ComponentRenderer {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void renderGeometry(GL2 gl, RocketComponent c, Surface which) {
|
protected void renderGeometry(GL2 gl, RocketComponent c, Surface which) {
|
||||||
if (glu == null)
|
if (glu == null)
|
||||||
throw new IllegalStateException(this + " Not Initialized");
|
throw new IllegalStateException(this + " Not Initialized");
|
||||||
|
|
||||||
glu.gluQuadricNormals(q, GLU.GLU_SMOOTH);
|
glu.gluQuadricNormals(q, GLU.GLU_SMOOTH);
|
||||||
|
|
||||||
Coordinate[] oo = c.toAbsolute(new Coordinate(0, 0, 0));
|
Coordinate[] oo = c.toAbsolute(new Coordinate(0, 0, 0));
|
||||||
|
|
||||||
for (Coordinate o : oo) {
|
for (Coordinate o : oo) {
|
||||||
gl.glPushMatrix();
|
gl.glPushMatrix();
|
||||||
|
|
||||||
gl.glTranslated(o.x, o.y, o.z);
|
gl.glTranslated(o.x, o.y, o.z);
|
||||||
|
|
||||||
if (c instanceof BodyTube) {
|
if (c instanceof BodyTube) {
|
||||||
renderTube(gl, (BodyTube) c, which);
|
renderTube(gl, (BodyTube) c, which);
|
||||||
} else if (c instanceof LaunchLug) {
|
} else if (c instanceof LaunchLug) {
|
||||||
@ -102,14 +103,16 @@ public class ComponentRenderer {
|
|||||||
} else if (c instanceof FinSet) {
|
} else if (c instanceof FinSet) {
|
||||||
if (which == Surface.OUTSIDE)
|
if (which == Surface.OUTSIDE)
|
||||||
fr.renderFinSet(gl, (FinSet) c);
|
fr.renderFinSet(gl, (FinSet) c);
|
||||||
|
} else if (c instanceof TubeFinSet) {
|
||||||
|
renderTubeFins( gl, (TubeFinSet) c, which);
|
||||||
} else {
|
} else {
|
||||||
renderOther(gl, c);
|
renderOther(gl, c);
|
||||||
}
|
}
|
||||||
gl.glPopMatrix();
|
gl.glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderOther(GL2 gl, RocketComponent c) {
|
private void renderOther(GL2 gl, RocketComponent c) {
|
||||||
gl.glBegin(GL.GL_LINES);
|
gl.glBegin(GL.GL_LINES);
|
||||||
for (Coordinate cc : c.getComponentBounds()) {
|
for (Coordinate cc : c.getComponentBounds()) {
|
||||||
@ -120,9 +123,9 @@ public class ComponentRenderer {
|
|||||||
}
|
}
|
||||||
gl.glEnd();
|
gl.glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderTransition(GL2 gl, Transition t, Surface which) {
|
private void renderTransition(GL2 gl, Transition t, Surface which) {
|
||||||
|
|
||||||
if (which == Surface.OUTSIDE || which == Surface.INSIDE) {
|
if (which == Surface.OUTSIDE || which == Surface.INSIDE) {
|
||||||
gl.glPushMatrix();
|
gl.glPushMatrix();
|
||||||
gl.glRotated(90, 0, 1.0, 0);
|
gl.glRotated(90, 0, 1.0, 0);
|
||||||
@ -135,7 +138,7 @@ public class ComponentRenderer {
|
|||||||
}
|
}
|
||||||
gl.glPopMatrix();
|
gl.glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (which == Surface.EDGES || which == Surface.INSIDE) {
|
if (which == Surface.EDGES || which == Surface.INSIDE) {
|
||||||
//Render aft edge
|
//Render aft edge
|
||||||
gl.glPushMatrix();
|
gl.glPushMatrix();
|
||||||
@ -148,7 +151,7 @@ public class ComponentRenderer {
|
|||||||
glu.gluDisk(q, Math.max(0, t.getAftRadius() - t.getThickness()), t.getAftRadius(), LOD, 2);
|
glu.gluDisk(q, Math.max(0, t.getAftRadius() - t.getThickness()), t.getAftRadius(), LOD, 2);
|
||||||
}
|
}
|
||||||
gl.glPopMatrix();
|
gl.glPopMatrix();
|
||||||
|
|
||||||
// Render AFT shoulder
|
// Render AFT shoulder
|
||||||
if (t.getAftShoulderLength() > 0) {
|
if (t.getAftShoulderLength() > 0) {
|
||||||
gl.glPushMatrix();
|
gl.glPushMatrix();
|
||||||
@ -161,7 +164,7 @@ public class ComponentRenderer {
|
|||||||
gl.glRotated(90, 0, 1.0, 0);
|
gl.glRotated(90, 0, 1.0, 0);
|
||||||
glu.gluDisk(q, t.getAftShoulderRadius(), t.getAftRadius(), LOD, 2);
|
glu.gluDisk(q, t.getAftShoulderRadius(), t.getAftRadius(), LOD, 2);
|
||||||
gl.glPopMatrix();
|
gl.glPopMatrix();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
renderTube(gl, Surface.INSIDE, t.getAftShoulderRadius(), iR, t.getAftShoulderLength());
|
renderTube(gl, Surface.INSIDE, t.getAftShoulderRadius(), iR, t.getAftShoulderLength());
|
||||||
gl.glPushMatrix();
|
gl.glPushMatrix();
|
||||||
@ -171,7 +174,7 @@ public class ComponentRenderer {
|
|||||||
}
|
}
|
||||||
gl.glPopMatrix();
|
gl.glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Render Fore edge
|
//Render Fore edge
|
||||||
gl.glPushMatrix();
|
gl.glPushMatrix();
|
||||||
gl.glRotated(180, 0, 1.0, 0);
|
gl.glRotated(180, 0, 1.0, 0);
|
||||||
@ -183,7 +186,7 @@ public class ComponentRenderer {
|
|||||||
glu.gluDisk(q, Math.max(0, t.getForeRadius() - t.getThickness()), t.getForeRadius(), LOD, 2);
|
glu.gluDisk(q, Math.max(0, t.getForeRadius() - t.getThickness()), t.getForeRadius(), LOD, 2);
|
||||||
}
|
}
|
||||||
gl.glPopMatrix();
|
gl.glPopMatrix();
|
||||||
|
|
||||||
// Render Fore shoulder
|
// Render Fore shoulder
|
||||||
if (t.getForeShoulderLength() > 0) {
|
if (t.getForeShoulderLength() > 0) {
|
||||||
gl.glPushMatrix();
|
gl.glPushMatrix();
|
||||||
@ -197,7 +200,7 @@ public class ComponentRenderer {
|
|||||||
gl.glRotated(90, 0, 1.0, 0);
|
gl.glRotated(90, 0, 1.0, 0);
|
||||||
glu.gluDisk(q, t.getForeShoulderRadius(), t.getForeRadius(), LOD, 2);
|
glu.gluDisk(q, t.getForeShoulderRadius(), t.getForeRadius(), LOD, 2);
|
||||||
gl.glPopMatrix();
|
gl.glPopMatrix();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
renderTube(gl, Surface.INSIDE, t.getForeShoulderRadius(), iR, t.getForeShoulderLength());
|
renderTube(gl, Surface.INSIDE, t.getForeShoulderRadius(), iR, t.getForeShoulderLength());
|
||||||
gl.glPushMatrix();
|
gl.glPushMatrix();
|
||||||
@ -207,28 +210,28 @@ public class ComponentRenderer {
|
|||||||
}
|
}
|
||||||
gl.glPopMatrix();
|
gl.glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderTube(final GL2 gl, final Surface which, final double oR, final double iR, final double len) {
|
private void renderTube(final GL2 gl, final Surface which, final double oR, final double iR, final double len) {
|
||||||
gl.glPushMatrix();
|
gl.glPushMatrix();
|
||||||
//outside
|
//outside
|
||||||
gl.glRotated(90, 0, 1.0, 0);
|
gl.glRotated(90, 0, 1.0, 0);
|
||||||
if (which == Surface.OUTSIDE)
|
if (which == Surface.OUTSIDE)
|
||||||
glu.gluCylinder(q, oR, oR, len, LOD, 1);
|
glu.gluCylinder(q, oR, oR, len, LOD, 1);
|
||||||
|
|
||||||
//edges
|
//edges
|
||||||
gl.glRotated(180, 0, 1.0, 0);
|
gl.glRotated(180, 0, 1.0, 0);
|
||||||
if (which == Surface.EDGES)
|
if (which == Surface.EDGES)
|
||||||
glu.gluDisk(q, iR, oR, LOD, 2);
|
glu.gluDisk(q, iR, oR, LOD, 2);
|
||||||
|
|
||||||
gl.glRotated(180, 0, 1.0, 0);
|
gl.glRotated(180, 0, 1.0, 0);
|
||||||
gl.glTranslated(0, 0, len);
|
gl.glTranslated(0, 0, len);
|
||||||
if (which == Surface.EDGES)
|
if (which == Surface.EDGES)
|
||||||
glu.gluDisk(q, iR, oR, LOD, 2);
|
glu.gluDisk(q, iR, oR, LOD, 2);
|
||||||
|
|
||||||
//inside
|
//inside
|
||||||
if (which == Surface.INSIDE) {
|
if (which == Surface.INSIDE) {
|
||||||
glu.gluQuadricOrientation(q, GLU.GLU_INSIDE);
|
glu.gluQuadricOrientation(q, GLU.GLU_INSIDE);
|
||||||
@ -237,59 +240,74 @@ public class ComponentRenderer {
|
|||||||
}
|
}
|
||||||
gl.glPopMatrix();
|
gl.glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderTube(GL2 gl, BodyTube t, Surface which) {
|
private void renderTube(GL2 gl, BodyTube t, Surface which) {
|
||||||
renderTube(gl, which, t.getOuterRadius(), t.getInnerRadius(), t.getLength());
|
renderTube(gl, which, t.getOuterRadius(), t.getInnerRadius(), t.getLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderRing(GL2 gl, RingComponent r) {
|
private void renderRing(GL2 gl, RingComponent r) {
|
||||||
|
|
||||||
gl.glRotated(90, 0, 1.0, 0);
|
gl.glRotated(90, 0, 1.0, 0);
|
||||||
glu.gluCylinder(q, r.getOuterRadius(), r.getOuterRadius(),
|
glu.gluCylinder(q, r.getOuterRadius(), r.getOuterRadius(),
|
||||||
r.getLength(), LOD, 1);
|
r.getLength(), LOD, 1);
|
||||||
|
|
||||||
gl.glRotated(180, 0, 1.0, 0);
|
gl.glRotated(180, 0, 1.0, 0);
|
||||||
glu.gluDisk(q, r.getInnerRadius(), r.getOuterRadius(), LOD, 2);
|
glu.gluDisk(q, r.getInnerRadius(), r.getOuterRadius(), LOD, 2);
|
||||||
|
|
||||||
gl.glRotated(180, 0, 1.0, 0);
|
gl.glRotated(180, 0, 1.0, 0);
|
||||||
gl.glTranslated(0, 0, r.getLength());
|
gl.glTranslated(0, 0, r.getLength());
|
||||||
glu.gluDisk(q, r.getInnerRadius(), r.getOuterRadius(), LOD, 2);
|
glu.gluDisk(q, r.getInnerRadius(), r.getOuterRadius(), LOD, 2);
|
||||||
|
|
||||||
glu.gluQuadricOrientation(q, GLU.GLU_INSIDE);
|
glu.gluQuadricOrientation(q, GLU.GLU_INSIDE);
|
||||||
glu.gluCylinder(q, r.getInnerRadius(), r.getInnerRadius(),
|
glu.gluCylinder(q, r.getInnerRadius(), r.getInnerRadius(),
|
||||||
-r.getLength(), LOD, 1);
|
-r.getLength(), LOD, 1);
|
||||||
glu.gluQuadricOrientation(q, GLU.GLU_OUTSIDE);
|
glu.gluQuadricOrientation(q, GLU.GLU_OUTSIDE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderLug(GL2 gl, LaunchLug t, Surface which) {
|
private void renderLug(GL2 gl, LaunchLug t, Surface which) {
|
||||||
renderTube(gl, which, t.getOuterRadius(), t.getInnerRadius(), t.getLength());
|
renderTube(gl, which, t.getOuterRadius(), t.getInnerRadius(), t.getLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void renderTubeFins(GL2 gl, TubeFinSet fs, Surface which) {
|
||||||
|
gl.glPushMatrix();
|
||||||
|
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
|
||||||
|
System.out.println(fs.getBaseRotation());
|
||||||
|
gl.glRotated(fs.getBaseRotation() * (180.0 / Math.PI), 1, 0, 0);
|
||||||
|
for( int i = 0; i< fs.getFinCount(); i++ ) {
|
||||||
|
gl.glPushMatrix();
|
||||||
|
gl.glTranslated(0, fs.getOuterRadius() + fs.getBodyRadius(), 0);
|
||||||
|
renderTube(gl, which, fs.getOuterRadius(), fs.getInnerRadius(), fs.getLength());
|
||||||
|
gl.glPopMatrix();
|
||||||
|
gl.glRotated(360.0 / fs.getFinCount(), 1, 0, 0);
|
||||||
|
}
|
||||||
|
gl.glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
private void renderMassObject(GL2 gl, MassObject o) {
|
private void renderMassObject(GL2 gl, MassObject o) {
|
||||||
gl.glRotated(90, 0, 1.0, 0);
|
gl.glRotated(90, 0, 1.0, 0);
|
||||||
|
|
||||||
MassObjectRenderer.drawMassObject(gl, o, LOD / 2, LOD / 2);
|
MassObjectRenderer.drawMassObject(gl, o, LOD / 2, LOD / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderMotor(final GL2 gl, Motor motor) {
|
private void renderMotor(final GL2 gl, Motor motor) {
|
||||||
double l = motor.getLength();
|
double l = motor.getLength();
|
||||||
double r = motor.getDiameter() / 2;
|
double r = motor.getDiameter() / 2;
|
||||||
|
|
||||||
gl.glPushMatrix();
|
gl.glPushMatrix();
|
||||||
|
|
||||||
gl.glRotated(90, 0, 1.0, 0);
|
gl.glRotated(90, 0, 1.0, 0);
|
||||||
|
|
||||||
gl.glMatrixMode(GL.GL_TEXTURE);
|
gl.glMatrixMode(GL.GL_TEXTURE);
|
||||||
gl.glPushMatrix();
|
gl.glPushMatrix();
|
||||||
gl.glTranslated(0, .125, 0);
|
gl.glTranslated(0, .125, 0);
|
||||||
gl.glScaled(1, .75, 0);
|
gl.glScaled(1, .75, 0);
|
||||||
|
|
||||||
glu.gluCylinder(q, r, r, l, LOD, 1);
|
glu.gluCylinder(q, r, r, l, LOD, 1);
|
||||||
|
|
||||||
gl.glPopMatrix();
|
gl.glPopMatrix();
|
||||||
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
|
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
|
||||||
|
|
||||||
{
|
{
|
||||||
final double da = (2.0f * Math.PI) / LOD;
|
final double da = (2.0f * Math.PI) / LOD;
|
||||||
final double dt = 1.0 / LOD;
|
final double dt = 1.0 / LOD;
|
||||||
@ -300,14 +318,14 @@ public class ComponentRenderer {
|
|||||||
gl.glVertex3d(r * Math.cos(da * i), r * Math.sin(da * i), 0);
|
gl.glVertex3d(r * Math.cos(da * i), r * Math.sin(da * i), 0);
|
||||||
gl.glTexCoord2d(i * dt, 0);
|
gl.glTexCoord2d(i * dt, 0);
|
||||||
gl.glVertex3d(0, 0, 0);
|
gl.glVertex3d(0, 0, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
gl.glEnd();
|
gl.glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.glTranslated(0, 0, l);
|
gl.glTranslated(0, 0, l);
|
||||||
gl.glRotated(180, 0, 1.0, 0);
|
gl.glRotated(180, 0, 1.0, 0);
|
||||||
|
|
||||||
{
|
{
|
||||||
final double da = (2.0f * Math.PI) / LOD;
|
final double da = (2.0f * Math.PI) / LOD;
|
||||||
final double dt = 1.0 / LOD;
|
final double dt = 1.0 / LOD;
|
||||||
@ -321,7 +339,7 @@ public class ComponentRenderer {
|
|||||||
}
|
}
|
||||||
gl.glEnd();
|
gl.glEnd();
|
||||||
gl.glBegin(GL.GL_TRIANGLE_STRIP);
|
gl.glBegin(GL.GL_TRIANGLE_STRIP);
|
||||||
|
|
||||||
for (int i = 0; i < LOD + 1; i++) {
|
for (int i = 0; i < LOD + 1; i++) {
|
||||||
gl.glNormal3d(-Math.cos(da * i), -Math.sin(da * i), -1);
|
gl.glNormal3d(-Math.cos(da * i), -Math.sin(da * i), -1);
|
||||||
gl.glTexCoord2d(i * dt, .9);
|
gl.glTexCoord2d(i * dt, .9);
|
||||||
|
|||||||
@ -25,9 +25,6 @@ import javax.swing.event.TreeSelectionListener;
|
|||||||
import javax.swing.tree.TreePath;
|
import javax.swing.tree.TreePath;
|
||||||
import javax.swing.tree.TreeSelectionModel;
|
import javax.swing.tree.TreeSelectionModel;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
import net.sf.openrocket.document.OpenRocketDocument;
|
import net.sf.openrocket.document.OpenRocketDocument;
|
||||||
import net.sf.openrocket.gui.components.StyledLabel;
|
import net.sf.openrocket.gui.components.StyledLabel;
|
||||||
@ -54,12 +51,16 @@ import net.sf.openrocket.rocketcomponent.Streamer;
|
|||||||
import net.sf.openrocket.rocketcomponent.Transition;
|
import net.sf.openrocket.rocketcomponent.Transition;
|
||||||
import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
|
import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
|
||||||
import net.sf.openrocket.rocketcomponent.TubeCoupler;
|
import net.sf.openrocket.rocketcomponent.TubeCoupler;
|
||||||
|
import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.startup.Preferences;
|
import net.sf.openrocket.startup.Preferences;
|
||||||
import net.sf.openrocket.util.BugException;
|
import net.sf.openrocket.util.BugException;
|
||||||
import net.sf.openrocket.util.Pair;
|
import net.sf.openrocket.util.Pair;
|
||||||
import net.sf.openrocket.util.Reflection;
|
import net.sf.openrocket.util.Reflection;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A component that contains addition buttons to add different types of rocket components
|
* A component that contains addition buttons to add different types of rocket components
|
||||||
* to a rocket. It enables and disables buttons according to the current selection of a
|
* to a rocket. It enables and disables buttons according to the current selection of a
|
||||||
@ -122,6 +123,8 @@ public class ComponentAddButtons extends JPanel implements Scrollable {
|
|||||||
new FinButton(EllipticalFinSet.class, trans.get("compaddbuttons.Elliptical")),
|
new FinButton(EllipticalFinSet.class, trans.get("compaddbuttons.Elliptical")),
|
||||||
//// Freeform
|
//// Freeform
|
||||||
new FinButton(FreeformFinSet.class, trans.get("compaddbuttons.Freeform")),
|
new FinButton(FreeformFinSet.class, trans.get("compaddbuttons.Freeform")),
|
||||||
|
//// Freeform
|
||||||
|
new FinButton(TubeFinSet.class, trans.get("compaddbuttons.Tubefin")),
|
||||||
//// Launch lug
|
//// Launch lug
|
||||||
new FinButton(LaunchLug.class, trans.get("compaddbuttons.Launchlug")));
|
new FinButton(LaunchLug.class, trans.get("compaddbuttons.Launchlug")));
|
||||||
|
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import net.sf.openrocket.rocketcomponent.Streamer;
|
|||||||
import net.sf.openrocket.rocketcomponent.Transition;
|
import net.sf.openrocket.rocketcomponent.Transition;
|
||||||
import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
|
import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
|
||||||
import net.sf.openrocket.rocketcomponent.TubeCoupler;
|
import net.sf.openrocket.rocketcomponent.TubeCoupler;
|
||||||
|
import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
|
|
||||||
|
|
||||||
@ -56,6 +57,8 @@ public class ComponentIcons {
|
|||||||
load("ellipticalfin", trans.get("ComponentIcons.Ellipticalfinset"), EllipticalFinSet.class);
|
load("ellipticalfin", trans.get("ComponentIcons.Ellipticalfinset"), EllipticalFinSet.class);
|
||||||
//// Freeform fin set
|
//// Freeform fin set
|
||||||
load("freeformfin", trans.get("ComponentIcons.Freeformfinset"), FreeformFinSet.class);
|
load("freeformfin", trans.get("ComponentIcons.Freeformfinset"), FreeformFinSet.class);
|
||||||
|
//// Tube fin set
|
||||||
|
load("tubefin", trans.get("ComponentIcons.Tubefinset"), TubeFinSet.class);
|
||||||
//// Launch lug
|
//// Launch lug
|
||||||
load("launchlug", trans.get("ComponentIcons.Launchlug"), LaunchLug.class);
|
load("launchlug", trans.get("ComponentIcons.Launchlug"), LaunchLug.class);
|
||||||
//// Inner tube
|
//// Inner tube
|
||||||
|
|||||||
@ -0,0 +1,70 @@
|
|||||||
|
package net.sf.openrocket.gui.rocketfigure;
|
||||||
|
|
||||||
|
import net.sf.openrocket.util.Coordinate;
|
||||||
|
import net.sf.openrocket.util.Transformation;
|
||||||
|
|
||||||
|
import java.awt.Shape;
|
||||||
|
import java.awt.geom.Ellipse2D;
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
|
|
||||||
|
|
||||||
|
public class TubeFinSetShapes extends RocketComponentShapes {
|
||||||
|
|
||||||
|
public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component,
|
||||||
|
Transformation transformation) {
|
||||||
|
net.sf.openrocket.rocketcomponent.TubeFinSet finset = (net.sf.openrocket.rocketcomponent.TubeFinSet)component;
|
||||||
|
|
||||||
|
int fins = finset.getFinCount();
|
||||||
|
double length = finset.getLength();
|
||||||
|
double outerradius = finset.getOuterRadius();
|
||||||
|
double bodyradius = finset.getBodyRadius();
|
||||||
|
|
||||||
|
Coordinate[] start = finset.toAbsolute(new Coordinate(0,0,0));
|
||||||
|
|
||||||
|
Transformation baseRotation = finset.getBaseRotationTransformation();
|
||||||
|
Transformation finRotation = finset.getFinRotationTransformation();
|
||||||
|
|
||||||
|
// Translate & rotate the coordinates
|
||||||
|
for (int i=0; i<start.length; i++) {
|
||||||
|
start[i] = baseRotation.transform(transformation.transform(start[i].add(0,bodyradius+outerradius,0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//start = baseRotation.transform(start);
|
||||||
|
|
||||||
|
Shape[] s = new Shape[fins];
|
||||||
|
for (int i=0; i<fins; i++) {
|
||||||
|
s[i] = new Rectangle2D.Double(start[0].x*S,(start[0].y-outerradius)*S,length*S,2*outerradius*S);
|
||||||
|
start = finRotation.transform(start);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Shape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component,
|
||||||
|
Transformation transformation) {
|
||||||
|
net.sf.openrocket.rocketcomponent.TubeFinSet finset = (net.sf.openrocket.rocketcomponent.TubeFinSet)component;
|
||||||
|
|
||||||
|
int fins = finset.getFinCount();
|
||||||
|
double outerradius = finset.getOuterRadius();
|
||||||
|
double bodyradius = finset.getBodyRadius();
|
||||||
|
|
||||||
|
Coordinate[] start = finset.toAbsolute(new Coordinate(0,0,0));
|
||||||
|
|
||||||
|
Transformation baseRotation = finset.getBaseRotationTransformation();
|
||||||
|
Transformation finRotation = finset.getFinRotationTransformation();
|
||||||
|
|
||||||
|
// Translate & rotate the coordinates
|
||||||
|
for (int i=0; i<start.length; i++) {
|
||||||
|
start[i] = baseRotation.transform(transformation.transform(start[i].add(0,bodyradius+outerradius,0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Shape[] s = new Shape[fins];
|
||||||
|
for (int i=0; i < fins; i++) {
|
||||||
|
s[i] = new Ellipse2D.Double((start[0].z-outerradius)*S,(start[0].y-outerradius)*S,2*outerradius*S,2*outerradius*S);
|
||||||
|
start = finRotation.transform(start);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user