Merge pull request #1674 from SiboVG/issue-1662

[#1662] Fix scaling of pod axial offset + fix ThicknessRingComponent scaling down
This commit is contained in:
SiboVG 2022-09-13 15:15:10 +02:00 committed by GitHub
commit 9b2780d378
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 88 additions and 80 deletions

View File

@ -1,17 +1,14 @@
package net.sf.openrocket.rocketcomponent; package net.sf.openrocket.rocketcomponent;
import java.util.ArrayList;
import java.util.Collection;
import jdk.jshell.spi.ExecutionControl;
import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.position.AngleMethod; import net.sf.openrocket.rocketcomponent.position.AngleMethod;
import net.sf.openrocket.rocketcomponent.position.AxialMethod; import net.sf.openrocket.rocketcomponent.position.AxialMethod;
import net.sf.openrocket.rocketcomponent.position.RadiusMethod; import net.sf.openrocket.rocketcomponent.position.RadiusMethod;
import net.sf.openrocket.startup.Application; import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.BoundingBox;
import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil;
public class PodSet extends ComponentAssembly implements RingInstanceable { public class PodSet extends ComponentAssembly implements RingInstanceable {
@ -124,7 +121,7 @@ public class PodSet extends ComponentAssembly implements RingInstanceable {
@Override @Override
public double getAxialOffset() { public double getAxialOffset() {
double returnValue = Double.NaN; double returnValue;
if (this.isAfter()){ if (this.isAfter()){
// remember the implicit (this instanceof Stage) // remember the implicit (this instanceof Stage)
@ -133,7 +130,7 @@ public class PodSet extends ComponentAssembly implements RingInstanceable {
returnValue = super.getAxialOffset(this.axialMethod); returnValue = super.getAxialOffset(this.axialMethod);
} }
if (0.000001 > Math.abs(returnValue)) { if (MathUtil.EPSILON > Math.abs(returnValue)) {
returnValue = 0.0; returnValue = 0.0;
} }

View File

@ -10,8 +10,6 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JCheckBox; import javax.swing.JCheckBox;
@ -135,7 +133,6 @@ public class ScaleDialog extends JDialog {
list = new ArrayList<>(1); list = new ArrayList<>(1);
list.add(new MassObjectScaler()); list.add(new MassObjectScaler());
SCALERS_NO_OFFSET.put(MassObject.class, list); SCALERS_NO_OFFSET.put(MassObject.class, list);
//addScaler(MassObject.class, "LengthNoAuto", SCALERS_NO_OFFSET);
addScaler(MassObject.class, "Radius", "isRadiusAutomatic", SCALERS_NO_OFFSET); addScaler(MassObject.class, "Radius", "isRadiusAutomatic", SCALERS_NO_OFFSET);
addScaler(MassObject.class, "RadialPosition", SCALERS_OFFSET); addScaler(MassObject.class, "RadialPosition", SCALERS_OFFSET);
@ -160,8 +157,9 @@ public class ScaleDialog extends JDialog {
addScaler(RingComponent.class, "RadialPosition", SCALERS_OFFSET); addScaler(RingComponent.class, "RadialPosition", SCALERS_OFFSET);
// ThicknessRingComponent // ThicknessRingComponent
addScaler(ThicknessRingComponent.class, "OuterRadius", "isOuterRadiusAutomatic", SCALERS_NO_OFFSET); list = new ArrayList<>(1);
addScaler(ThicknessRingComponent.class, "Thickness", SCALERS_NO_OFFSET); list.add(new ThicknessRingComponentScaler());
SCALERS_NO_OFFSET.put(ThicknessRingComponent.class, list);
// InnerTube // InnerTube
addScaler(InnerTube.class, "MotorOverhang", SCALERS_NO_OFFSET); addScaler(InnerTube.class, "MotorOverhang", SCALERS_NO_OFFSET);
@ -240,7 +238,7 @@ public class ScaleDialog extends JDialog {
super(parent, trans.get("title"), ModalityType.APPLICATION_MODAL); super(parent, trans.get("title"), ModalityType.APPLICATION_MODAL);
this.document = document; this.document = document;
this.selection = selection; this.selection = new ArrayList<>(selection);
this.onlySelection = onlySelection; this.onlySelection = onlySelection;
init(); init();
@ -507,60 +505,42 @@ public class ScaleDialog extends JDialog {
} }
boolean scaleMass = scaleMassValues.isSelected(); boolean scaleMass = scaleMassValues.isSelected();
// Apply the selected scaling mode
Iterable<RocketComponent> scaleComponents = selection;
Object item = selectionOption.getSelectedItem(); Object item = selectionOption.getSelectedItem();
log.info(Markers.USER_MARKER, "Scaling design by factor " + mul + ", option=" + item); log.info(Markers.USER_MARKER, "Scaling design by factor " + mul + ", option=" + item);
if (SCALE_ROCKET.equals(item)) { if (SCALE_ROCKET.equals(item)) {
document.startUndo(trans.get("undo.scaleRocket"));
// Scale the entire rocket design // Scale the entire rocket design
try { scaleComponents = document.getRocket();
document.startUndo(trans.get("undo.scaleRocket"));
for (RocketComponent c : document.getRocket()) {
scale(c, mul, scaleMass, scaleOffsets.isSelected());
}
} finally {
document.stopUndo();
}
} else if (SCALE_SUBSELECTION.equals(item)) { } else if (SCALE_SUBSELECTION.equals(item)) {
document.startUndo(trans.get("undo.scaleComponents"));
// Scale component and subcomponents for (RocketComponent component : new ArrayList<>(selection)) {
try { addChildrenToSelection(component);
document.startUndo(trans.get("undo.scaleComponents"));
// Keep track of which components are already scaled so that we don't scale children multiple times (if
// they were also part of selection)
List<RocketComponent> scaledComponents = new ArrayList<>();
for (RocketComponent component : selection) {
if (!scaledComponents.contains(component)) {
scale(component, mul, scaleMass, scaleOffsets.isSelected());
scaledComponents.add(component);
}
if (component.getChildCount() > 0) {
scaleChildren(component, scaledComponents, mul, scaleMass);
}
}
} finally {
document.stopUndo();
} }
} else if (SCALE_SELECTION.equals(item)) { } else if (SCALE_SELECTION.equals(item)) {
document.startUndo(trans.get("undo.scaleComponent"));
// Scale only the selected components
try {
document.startUndo(trans.get("undo.scaleComponent"));
for (RocketComponent component : selection) {
scale(component, mul, scaleMass, scaleOffsets.isSelected());
}
} finally {
document.stopUndo();
}
} else { } else {
throw new BugException("Unknown item selected, item=" + item); throw new BugException("Unknown item selected, item=" + item);
} }
// Perform the scaling
try {
// Scale the offsets
if (scaleOffsets.isSelected()) {
for (RocketComponent component : scaleComponents) {
scaleOffset(component, mul, scaleMass);
}
}
// Scale the components
for (RocketComponent component : scaleComponents) {
scale(component, mul, scaleMass);
}
} finally {
document.stopUndo();
}
} }
@ -569,9 +549,8 @@ public class ScaleDialog extends JDialog {
* @param component component to be scaled * @param component component to be scaled
* @param mul scaling factor * @param mul scaling factor
* @param scaleMass flag to check if the mass should be scaled as well * @param scaleMass flag to check if the mass should be scaled as well
* @param scaleOffset flag to check if the axial/radial offsets should be scaled as well
*/ */
private void scale(RocketComponent component, double mul, boolean scaleMass, boolean scaleOffset) { private void scale(RocketComponent component, double mul, boolean scaleMass) {
Class<?> clazz = component.getClass(); Class<?> clazz = component.getClass();
List<Class<?>> classes = new ArrayList<>(); List<Class<?>> classes = new ArrayList<>();
while (clazz != null) { while (clazz != null) {
@ -580,16 +559,8 @@ public class ScaleDialog extends JDialog {
} }
Collections.reverse(classes); // Always do the super component scales first (can cause problems otherwise in the scale order) Collections.reverse(classes); // Always do the super component scales first (can cause problems otherwise in the scale order)
for (Class<?> cl : classes) { for (Class<?> cl : classes) {
List<Scaler> list; List<Scaler> list = SCALERS_NO_OFFSET.get(cl);
if (scaleOffset) { if (list != null && list.size() > 0) {
Stream<Scaler> strm_no_offset = SCALERS_NO_OFFSET.get(cl) == null ? Stream.empty() : SCALERS_NO_OFFSET.get(cl).stream();
Stream<Scaler> strm_offset = SCALERS_OFFSET.get(cl) == null ? Stream.empty() : SCALERS_OFFSET.get(cl).stream();
list = Stream.concat(strm_no_offset, strm_offset).distinct().collect(Collectors.toList());
}
else {
list = SCALERS_NO_OFFSET.get(cl);
}
if (list != null) {
for (Scaler s : list) { for (Scaler s : list) {
s.scale(component, mul, scaleMass); s.scale(component, mul, scaleMass);
} }
@ -598,20 +569,41 @@ public class ScaleDialog extends JDialog {
} }
/** /**
* Iteratively scale the children of component. If one of the children was already present in scaledComponents, * Perform scaling of the axial/radial offsets a single component.
* don't scale it. * @param component component to be scaled
* @param component component whose children need to be scaled * @param mul scaling factor
* @param scaledComponents list of components that were already scaled * @param scaleMass flag to check if the mass should be scaled as well
*/ */
private void scaleChildren(RocketComponent component, List<RocketComponent> scaledComponents, double mul, boolean scaleMass) { private void scaleOffset(RocketComponent component, double mul, boolean scaleMass) {
for (RocketComponent child : component.getChildren()) { Class<?> clazz = component.getClass();
if (!scaledComponents.contains(child)) { List<Class<?>> classes = new ArrayList<>();
scale(child, mul, scaleMass, scaleOffsets.isSelected()); while (clazz != null) {
scaledComponents.add(child); classes.add(clazz);
scaleChildren(child, scaledComponents, mul, scaleMass); clazz = clazz.getSuperclass();
}
Collections.reverse(classes); // Always do the super component scales first (can cause problems otherwise in the scaleNoOffset order)
for (Class<?> cl : classes) {
List<Scaler> list = SCALERS_OFFSET.get(cl);
if (list != null && list.size() > 0) {
for (Scaler s : list) {
s.scale(component, mul, scaleMass);
}
} }
} }
} }
/**
* Iteratively add the children of component to the component selection list.
* @param component component whose children need to be added
*/
private void addChildrenToSelection(RocketComponent component) {
for (RocketComponent child : component.getChildren()) {
if (!selection.contains(child)) {
selection.add(child);
}
addChildrenToSelection(child);
}
}
private void updateToField() { private void updateToField() {
@ -777,8 +769,28 @@ public class ScaleDialog extends JDialog {
} }
private static class RailButtonScaler implements Scaler { private static class ThicknessRingComponentScaler implements Scaler {
@Override
public void scale(RocketComponent component, double multiplier, boolean scaleMass) {
final Map<Class<? extends RocketComponent>, List<Scaler>> scalers = new HashMap<>();
// We need to specify this particular order, otherwise scale the inner/outer radius may clip the dimensions of the other outer/inner radius
if (multiplier >= 1) { // Scale up
addScaler(ThicknessRingComponent.class, "OuterRadius", "isOuterRadiusAutomatic", scalers);
addScaler(ThicknessRingComponent.class, "Thickness", scalers);
} else { // Scale down
addScaler(ThicknessRingComponent.class, "Thickness", scalers);
addScaler(ThicknessRingComponent.class, "OuterRadius", "isOuterRadiusAutomatic", scalers);
}
for (List<Scaler> foo : scalers.values()) {
for (Scaler s : foo) {
s.scale(component, multiplier, scaleMass);
}
}
}
}
private static class RailButtonScaler implements Scaler {
@Override @Override
public void scale(RocketComponent component, double multiplier, boolean scaleMass) { public void scale(RocketComponent component, double multiplier, boolean scaleMass) {
final Map<Class<? extends RocketComponent>, List<Scaler>> scalers = new HashMap<>(); final Map<Class<? extends RocketComponent>, List<Scaler>> scalers = new HashMap<>();
@ -803,7 +815,6 @@ public class ScaleDialog extends JDialog {
} }
} }
} }
} }
} }