From 5c68fda00e47bd5db763d563c8a70fa7b826893d Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 9 Sep 2023 12:36:04 +0200 Subject: [PATCH 1/5] [#2316] Add warning for zero-thickness component OBJ export --- core/resources/l10n/messages.properties | 3 ++- .../export/OBJExporterFactory.java | 16 ++++++++----- .../export/components/BodyTubeExporter.java | 10 ++++++-- .../export/components/FinSetExporter.java | 10 ++++++-- .../export/components/LaunchLugExporter.java | 10 ++++++-- .../export/components/MassObjectExporter.java | 5 ++-- .../export/components/MotorExporter.java | 5 +++- .../export/components/RailButtonExporter.java | 5 ++-- .../components/RingComponentExporter.java | 10 ++++++-- .../components/RocketComponentExporter.java | 6 ++++- .../export/components/TransitionExporter.java | 10 ++++++-- .../export/components/TubeFinSetExporter.java | 10 ++++++-- .../net/sf/openrocket/logging/Warning.java | 2 ++ .../export/OBJExporterFactoryTest.java | 24 +++++++++++++------ .../sf/openrocket/gui/main/BasicFrame.java | 18 +++++++++++--- 15 files changed, 109 insertions(+), 35 deletions(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index d5b1f3809..b65b8b3f5 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -89,7 +89,7 @@ BasicFrame.WarningDialog.txt2 = Some design features may not have been loaded co BasicFrame.WarningDialog.saving.txt1 = The following problems were encountered while saving BasicFrame.WarningDialog.saving.txt2 = Some design features may not have exported correctly. BasicFrame.WarningDialog.title = Warnings while opening file -BasicFrame.WarningDialog.saving.title = Warnings while opening file +BasicFrame.WarningDialog.saving.title = Warnings while saving file BasicFrame.ErrorWarningDialog.txt1 = Please correct the errors. BasicFrame.ErrorWarningDialog.saving.title = Errors/Warnings while saving file BasicFrame.lbl.SaveRocketInfo = Save Design Info @@ -2097,6 +2097,7 @@ Warning.TUBE_OVERLAP = Overlapping tube fins may not simulate accurately. Warning.EMPTY_BRANCH = Simulation branch contains no data Warning.SEPARATION_ORDER = Stages separated in an unreasonable order Warning.EARLY_SEPARATION = Stages separated before clearing launch rod/rail +Warning.OBJ_ZERO_THICKNESS = Zero-thickness component can cause issues for 3D printing ! Scale dialog ScaleDialog.lbl.scaleRocket = Entire rocket diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/OBJExporterFactory.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/OBJExporterFactory.java index 8e856cc64..a71739583 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/OBJExporterFactory.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/OBJExporterFactory.java @@ -18,6 +18,7 @@ import net.sf.openrocket.file.wavefrontobj.export.components.RocketComponentExpo import net.sf.openrocket.file.wavefrontobj.export.components.RingComponentExporter; import net.sf.openrocket.file.wavefrontobj.export.components.TransitionExporter; import net.sf.openrocket.file.wavefrontobj.export.components.TubeFinSetExporter; +import net.sf.openrocket.logging.WarningSet; import net.sf.openrocket.motor.Motor; import net.sf.openrocket.motor.MotorConfiguration; import net.sf.openrocket.rocketcomponent.BodyTube; @@ -69,6 +70,7 @@ public class OBJExporterFactory { private final FlightConfiguration configuration; private final OBJExportOptions options; private final File file; + private final WarningSet warnings; private static final Logger log = LoggerFactory.getLogger(OBJExporterFactory.class); @@ -93,11 +95,12 @@ public class OBJExporterFactory { * @param file The file to export the OBJ to */ public OBJExporterFactory(List components, FlightConfiguration configuration, File file, - OBJExportOptions options) { + OBJExportOptions options, WarningSet warnings) { this.components = components; this.configuration = configuration; this.file = file; this.options = options; + this.warnings = warnings; } /** @@ -152,7 +155,7 @@ public class OBJExporterFactory { // Component exporting String groupName = idx + "_" + component.getName(); handleComponent(obj, this.configuration, this.options.getTransformer(), component, groupName, - materials.get(obj), this.options.getLOD(), options); + materials.get(obj), this.options.getLOD(), options, warnings); // If separate export, add this object to the map of objects to export if (exportAsSeparateFiles) { @@ -225,7 +228,8 @@ public class OBJExporterFactory { @SuppressWarnings("unchecked") // This is safe because of the structure we set up. private void handleComponent(DefaultObj obj, FlightConfiguration config, CoordTransform transformer, T component, String groupName, List materials, - ObjUtils.LevelOfDetail LOD, OBJExportOptions options) { + ObjUtils.LevelOfDetail LOD, OBJExportOptions options, + WarningSet warnings) { ExporterFactory factory = null; Class currentClass = component.getClass(); @@ -254,7 +258,7 @@ public class OBJExporterFactory { } // Export component - final RocketComponentExporter exporter = factory.create(obj, config, transformer, component, groupName, LOD); + final RocketComponentExporter exporter = factory.create(obj, config, transformer, component, groupName, LOD, warnings); exporter.addToObj(); // Export motor @@ -272,7 +276,7 @@ public class OBJExporterFactory { } // Export the motor geometry - MotorExporter motorExporter = new MotorExporter(obj, config, transformer, component, groupName, LOD); + MotorExporter motorExporter = new MotorExporter(obj, config, transformer, component, groupName, LOD, warnings); motorExporter.addToObj(); } } @@ -300,6 +304,6 @@ public class OBJExporterFactory { interface ExporterFactory { RocketComponentExporter create(DefaultObj obj, FlightConfiguration config, CoordTransform transformer, - T component, String groupName, ObjUtils.LevelOfDetail LOD); + T component, String groupName, ObjUtils.LevelOfDetail LOD, WarningSet warnings); } } diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/BodyTubeExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/BodyTubeExporter.java index d6a482b87..f40b53d2e 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/BodyTubeExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/BodyTubeExporter.java @@ -4,6 +4,8 @@ import net.sf.openrocket.file.wavefrontobj.CoordTransform; import net.sf.openrocket.file.wavefrontobj.DefaultObj; import net.sf.openrocket.file.wavefrontobj.ObjUtils; import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter; +import net.sf.openrocket.logging.Warning; +import net.sf.openrocket.logging.WarningSet; import net.sf.openrocket.rocketcomponent.BodyTube; import net.sf.openrocket.rocketcomponent.FlightConfiguration; import net.sf.openrocket.rocketcomponent.InstanceContext; @@ -11,8 +13,8 @@ import net.sf.openrocket.util.Coordinate; public class BodyTubeExporter extends RocketComponentExporter { public BodyTubeExporter(DefaultObj obj, FlightConfiguration config, CoordTransform transformer, BodyTube component, - String groupName, ObjUtils.LevelOfDetail LOD) { - super(obj, config, transformer, component, groupName, LOD); + String groupName, ObjUtils.LevelOfDetail LOD, WarningSet warnings) { + super(obj, config, transformer, component, groupName, LOD, warnings); } @Override @@ -24,6 +26,10 @@ public class BodyTubeExporter extends RocketComponentExporter { final float length = (float) component.getLength(); final boolean isFilled = component.isFilled(); + if (Double.compare(component.getThickness(), 0) == 0) { + warnings.add(Warning.OBJ_ZERO_THICKNESS, component.getName()); + } + // Generate the mesh for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) { generateMesh(outerRadius, innerRadius, length, isFilled, context); diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/FinSetExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/FinSetExporter.java index abfb6ca8f..7176857cf 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/FinSetExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/FinSetExporter.java @@ -6,6 +6,8 @@ import net.sf.openrocket.file.wavefrontobj.CoordTransform; import net.sf.openrocket.file.wavefrontobj.DefaultObj; import net.sf.openrocket.file.wavefrontobj.ObjUtils; import net.sf.openrocket.file.wavefrontobj.export.shapes.PolygonExporter; +import net.sf.openrocket.logging.Warning; +import net.sf.openrocket.logging.WarningSet; import net.sf.openrocket.rocketcomponent.FinSet; import net.sf.openrocket.rocketcomponent.FlightConfiguration; import net.sf.openrocket.rocketcomponent.InstanceContext; @@ -16,8 +18,8 @@ import java.util.List; public class FinSetExporter extends RocketComponentExporter { public FinSetExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer, - FinSet component, String groupName, ObjUtils.LevelOfDetail LOD) { - super(obj, config, transformer, component, groupName, LOD); + FinSet component, String groupName, ObjUtils.LevelOfDetail LOD, WarningSet warnings) { + super(obj, config, transformer, component, groupName, LOD, warnings); } @Override @@ -35,6 +37,10 @@ public class FinSetExporter extends RocketComponentExporter { final float thickness = (float) component.getThickness(); boolean hasTabs = component.getTabLength() > 0 && component.getTabHeight() > 0; + if (Float.compare(thickness, 0) == 0) { + warnings.add(Warning.OBJ_ZERO_THICKNESS, component.getName()); + } + // Generate the fin meshes for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) { generateMesh(floatPoints, floatTabPoints, thickness, hasTabs, context); diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/LaunchLugExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/LaunchLugExporter.java index ddd5351d3..af88edcf4 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/LaunchLugExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/LaunchLugExporter.java @@ -5,6 +5,8 @@ import net.sf.openrocket.file.wavefrontobj.CoordTransform; import net.sf.openrocket.file.wavefrontobj.DefaultObj; import net.sf.openrocket.file.wavefrontobj.ObjUtils; import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter; +import net.sf.openrocket.logging.Warning; +import net.sf.openrocket.logging.WarningSet; import net.sf.openrocket.rocketcomponent.FlightConfiguration; import net.sf.openrocket.rocketcomponent.InstanceContext; import net.sf.openrocket.rocketcomponent.LaunchLug; @@ -12,8 +14,8 @@ import net.sf.openrocket.util.Coordinate; public class LaunchLugExporter extends RocketComponentExporter { public LaunchLugExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer, - LaunchLug component, String groupName, ObjUtils.LevelOfDetail LOD) { - super(obj, config, transformer, component, groupName, LOD); + LaunchLug component, String groupName, ObjUtils.LevelOfDetail LOD, WarningSet warnings) { + super(obj, config, transformer, component, groupName, LOD, warnings); } @Override @@ -24,6 +26,10 @@ public class LaunchLugExporter extends RocketComponentExporter { final float innerRadius = (float) component.getInnerRadius(); final float length = (float) component.getLength(); + if (Double.compare(component.getThickness(), 0) == 0) { + warnings.add(Warning.OBJ_ZERO_THICKNESS, component.getName()); + } + // Generate the mesh for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) { generateMesh(outerRadius, innerRadius, length, context); diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/MassObjectExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/MassObjectExporter.java index 4eb2e43f3..470aac6bf 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/MassObjectExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/MassObjectExporter.java @@ -5,6 +5,7 @@ import net.sf.openrocket.file.wavefrontobj.CoordTransform; import net.sf.openrocket.file.wavefrontobj.DefaultObj; import net.sf.openrocket.file.wavefrontobj.DefaultObjFace; import net.sf.openrocket.file.wavefrontobj.ObjUtils; +import net.sf.openrocket.logging.WarningSet; import net.sf.openrocket.rocketcomponent.FlightConfiguration; import net.sf.openrocket.rocketcomponent.InstanceContext; import net.sf.openrocket.rocketcomponent.MassObject; @@ -13,8 +14,8 @@ import net.sf.openrocket.util.RocketComponentUtils; public class MassObjectExporter extends RocketComponentExporter { public MassObjectExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer, - MassObject component, String groupName, ObjUtils.LevelOfDetail LOD) { - super(obj, config, transformer, component, groupName, LOD); + MassObject component, String groupName, ObjUtils.LevelOfDetail LOD, WarningSet warnings) { + super(obj, config, transformer, component, groupName, LOD, warnings); } @Override diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/MotorExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/MotorExporter.java index cbf07bff9..d04dbae94 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/MotorExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/MotorExporter.java @@ -6,6 +6,7 @@ import net.sf.openrocket.file.wavefrontobj.DefaultObjFace; import net.sf.openrocket.file.wavefrontobj.ObjUtils; import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter; import net.sf.openrocket.file.wavefrontobj.export.shapes.DiskExporter; +import net.sf.openrocket.logging.WarningSet; import net.sf.openrocket.motor.Motor; import net.sf.openrocket.motor.MotorConfiguration; import net.sf.openrocket.rocketcomponent.FlightConfiguration; @@ -24,6 +25,7 @@ public class MotorExporter { protected final String groupName; protected final ObjUtils.LevelOfDetail LOD; protected final CoordTransform transformer; + protected final WarningSet warnings; /** * Wavefront OBJ exporter for a rocket component. @@ -36,7 +38,7 @@ public class MotorExporter { * @param LOD Level of detail to use for the export (e.g. '80') */ public MotorExporter(DefaultObj obj, FlightConfiguration config, CoordTransform transformer, RocketComponent mount, - String groupName, ObjUtils.LevelOfDetail LOD) { + String groupName, ObjUtils.LevelOfDetail LOD, WarningSet warnings) { if (!(mount instanceof MotorMount)) { throw new IllegalArgumentException("Motor exporter can only be used for motor mounts"); } @@ -46,6 +48,7 @@ public class MotorExporter { this.mount = mount; this.groupName = groupName; this.LOD = LOD; + this.warnings = warnings; } public void addToObj() { diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/RailButtonExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/RailButtonExporter.java index 36a16a70b..475b8563c 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/RailButtonExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/RailButtonExporter.java @@ -8,6 +8,7 @@ import net.sf.openrocket.file.wavefrontobj.DefaultObjFace; import net.sf.openrocket.file.wavefrontobj.ObjUtils; import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter; import net.sf.openrocket.file.wavefrontobj.export.shapes.DiskExporter; +import net.sf.openrocket.logging.WarningSet; import net.sf.openrocket.rocketcomponent.FlightConfiguration; import net.sf.openrocket.rocketcomponent.InstanceContext; import net.sf.openrocket.rocketcomponent.RailButton; @@ -26,8 +27,8 @@ public class RailButtonExporter extends RocketComponentExporter { * @param LOD Level of detail to use for the export (e.g. '80') */ public RailButtonExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer, - RailButton component, String groupName, ObjUtils.LevelOfDetail LOD) { - super(obj, config, transformer, component, groupName, LOD); + RailButton component, String groupName, ObjUtils.LevelOfDetail LOD, WarningSet warnings) { + super(obj, config, transformer, component, groupName, LOD, warnings); } @Override diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/RingComponentExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/RingComponentExporter.java index 798a82169..08c3f7751 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/RingComponentExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/RingComponentExporter.java @@ -5,6 +5,8 @@ import net.sf.openrocket.file.wavefrontobj.CoordTransform; import net.sf.openrocket.file.wavefrontobj.DefaultObj; import net.sf.openrocket.file.wavefrontobj.ObjUtils; import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter; +import net.sf.openrocket.logging.Warning; +import net.sf.openrocket.logging.WarningSet; import net.sf.openrocket.rocketcomponent.FlightConfiguration; import net.sf.openrocket.rocketcomponent.InstanceContext; import net.sf.openrocket.rocketcomponent.RingComponent; @@ -12,8 +14,8 @@ import net.sf.openrocket.util.Coordinate; public class RingComponentExporter extends RocketComponentExporter { public RingComponentExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer, - RingComponent component, String groupName, ObjUtils.LevelOfDetail LOD) { - super(obj, config, transformer, component, groupName, LOD); + RingComponent component, String groupName, ObjUtils.LevelOfDetail LOD, WarningSet warnings) { + super(obj, config, transformer, component, groupName, LOD, warnings); } @Override @@ -24,6 +26,10 @@ public class RingComponentExporter extends RocketComponentExporter { protected final String groupName; protected final ObjUtils.LevelOfDetail LOD; protected final CoordTransform transformer; + protected final WarningSet warnings; /** * Wavefront OBJ exporter for a rocket component. @@ -31,13 +33,15 @@ public abstract class RocketComponentExporter { * @param LOD Level of detail to use for the export (e.g. '80') */ public RocketComponentExporter(@NotNull DefaultObj obj, @NotNull FlightConfiguration config, @NotNull CoordTransform transformer, - T component, String groupName, ObjUtils.LevelOfDetail LOD) { + T component, String groupName, ObjUtils.LevelOfDetail LOD, + WarningSet warnings) { this.obj = obj; this.config = config; this.component = component; this.groupName = groupName; this.LOD = LOD; this.transformer = transformer; + this.warnings = warnings; } public abstract void addToObj(); diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java index 2157a17d1..5be6ddb7f 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java @@ -9,6 +9,8 @@ import net.sf.openrocket.file.wavefrontobj.ObjUtils; import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter; import net.sf.openrocket.file.wavefrontobj.export.shapes.DiskExporter; import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter; +import net.sf.openrocket.logging.Warning; +import net.sf.openrocket.logging.WarningSet; import net.sf.openrocket.rocketcomponent.FlightConfiguration; import net.sf.openrocket.rocketcomponent.InstanceContext; import net.sf.openrocket.rocketcomponent.Transition; @@ -22,8 +24,8 @@ public class TransitionExporter extends RocketComponentExporter { private final int nrOfSides; public TransitionExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer, - Transition component, String groupName, ObjUtils.LevelOfDetail LOD) { - super(obj, config, transformer, component, groupName, LOD); + Transition component, String groupName, ObjUtils.LevelOfDetail LOD, WarningSet warnings) { + super(obj, config, transformer, component, groupName, LOD, warnings); this.nrOfSides = LOD.getNrOfSides(Math.max(component.getForeRadius(), component.getAftRadius())); } @@ -31,6 +33,10 @@ public class TransitionExporter extends RocketComponentExporter { public void addToObj() { obj.setActiveGroupNames(groupName); + if (Double.compare(component.getThickness(), 0) == 0) { + warnings.add(Warning.OBJ_ZERO_THICKNESS, component.getName()); + } + // Generate the mesh for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) { generateMesh(context); diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TubeFinSetExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TubeFinSetExporter.java index 30175d809..68eb6a6ba 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TubeFinSetExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TubeFinSetExporter.java @@ -5,6 +5,8 @@ import net.sf.openrocket.file.wavefrontobj.CoordTransform; import net.sf.openrocket.file.wavefrontobj.DefaultObj; import net.sf.openrocket.file.wavefrontobj.ObjUtils; import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter; +import net.sf.openrocket.logging.Warning; +import net.sf.openrocket.logging.WarningSet; import net.sf.openrocket.rocketcomponent.FlightConfiguration; import net.sf.openrocket.rocketcomponent.InstanceContext; import net.sf.openrocket.rocketcomponent.TubeFinSet; @@ -12,8 +14,8 @@ import net.sf.openrocket.util.Coordinate; public class TubeFinSetExporter extends RocketComponentExporter { public TubeFinSetExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer, - TubeFinSet component, String groupName, ObjUtils.LevelOfDetail LOD) { - super(obj, config, transformer, component, groupName, LOD); + TubeFinSet component, String groupName, ObjUtils.LevelOfDetail LOD, WarningSet warnings) { + super(obj, config, transformer, component, groupName, LOD, warnings); } @Override @@ -24,6 +26,10 @@ public class TubeFinSetExporter extends RocketComponentExporter { final float innerRadius = (float) component.getInnerRadius(); final float length = (float) component.getLength(); + if (Double.compare(component.getThickness(), 0) == 0) { + warnings.add(Warning.OBJ_ZERO_THICKNESS, component.getName()); + } + // Generate the fin meshes for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) { generateMesh(outerRadius, innerRadius, length, context); diff --git a/core/src/net/sf/openrocket/logging/Warning.java b/core/src/net/sf/openrocket/logging/Warning.java index 23c4bcb90..c3b9db1fb 100644 --- a/core/src/net/sf/openrocket/logging/Warning.java +++ b/core/src/net/sf/openrocket/logging/Warning.java @@ -386,6 +386,8 @@ public abstract class Warning extends Message { public static final Warning TUBE_SEPARATION = new Other(trans.get("Warning.TUBE_SEPARATION")); public static final Warning TUBE_OVERLAP = new Other(trans.get("Warning.TUBE_OVERLAP")); + public static final Warning OBJ_ZERO_THICKNESS = new Other(trans.get("Warning.OBJ_ZERO_THICKNESS")); + /** A Warning that stage separation occurred at other than the last stage */ public static final Warning SEPARATION_ORDER = new Other(trans.get("Warning.SEPARATION_ORDER")); diff --git a/core/test/net/sf/openrocket/file/wavefrontobj/export/OBJExporterFactoryTest.java b/core/test/net/sf/openrocket/file/wavefrontobj/export/OBJExporterFactoryTest.java index f8dca2bb2..af5f5dd5c 100644 --- a/core/test/net/sf/openrocket/file/wavefrontobj/export/OBJExporterFactoryTest.java +++ b/core/test/net/sf/openrocket/file/wavefrontobj/export/OBJExporterFactoryTest.java @@ -8,16 +8,12 @@ import com.google.inject.util.Modules; import net.sf.openrocket.ServicesForTesting; import net.sf.openrocket.database.ComponentPresetDao; import net.sf.openrocket.database.motor.MotorDatabase; -import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.document.OpenRocketDocumentFactory; -import net.sf.openrocket.file.GeneralRocketLoader; -import net.sf.openrocket.file.RocketLoadException; import net.sf.openrocket.file.openrocket.OpenRocketSaverTest; -import net.sf.openrocket.file.wavefrontobj.CoordTransform; -import net.sf.openrocket.file.wavefrontobj.DefaultCoordTransform; import net.sf.openrocket.file.wavefrontobj.ObjUtils; import net.sf.openrocket.l10n.DebugTranslator; import net.sf.openrocket.l10n.Translator; +import net.sf.openrocket.logging.WarningSet; import net.sf.openrocket.plugin.PluginModule; import net.sf.openrocket.rocketcomponent.AxialStage; import net.sf.openrocket.rocketcomponent.BodyTube; @@ -43,6 +39,7 @@ import java.nio.file.Path; import java.util.List; import static org.junit.Assert.fail; +import static org.junit.Assert.assertEquals; public class OBJExporterFactoryTest { private static final File TMP_DIR = new File("./tmp/"); @@ -165,8 +162,11 @@ public class OBJExporterFactoryTest { options.setScaling(30); options.setExportChildren(true); options.setRemoveOffset(true); - OBJExporterFactory exporterFactory = new OBJExporterFactory(components, rocket.getSelectedConfiguration(), tempFile.toFile(), options); + WarningSet warnings = new WarningSet(); + OBJExporterFactory exporterFactory = new OBJExporterFactory(components, rocket.getSelectedConfiguration(), tempFile.toFile(), options, warnings); exporterFactory.doExport(); + //// Just hope for no exceptions :) + assertEquals(warnings.size(), 0); // Test with other parameters @@ -180,8 +180,18 @@ public class OBJExporterFactoryTest { options.setScaling(1000); options.setLOD(ObjUtils.LevelOfDetail.LOW_QUALITY); - exporterFactory = new OBJExporterFactory(components, rocket.getSelectedConfiguration(), tempFile.toFile(), options); + exporterFactory = new OBJExporterFactory(components, rocket.getSelectedConfiguration(), tempFile.toFile(), options, warnings); exporterFactory.doExport(); + //// Just hope for no exceptions :) + assertEquals(warnings.size(), 0); + + // Test zero-thickness nose cone + noseCone.setThickness(0); + + exporterFactory = new OBJExporterFactory(components, rocket.getSelectedConfiguration(), tempFile.toFile(), options, warnings); + exporterFactory.doExport(); + //// Just hope for no exceptions :) + assertEquals(warnings.size(), 1); // Clean up Files.delete(tempFile); diff --git a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java index 08870e1ab..4a10abb00 100644 --- a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java +++ b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java @@ -1530,8 +1530,9 @@ public class BasicFrame extends JFrame { // // Some design features may not have been exported correctly. trans.get("BasicFrame.WarningDialog.saving.txt2") }, - // // Warnings while opening file - trans.get("BasicFrame.WarningDialog.saving.title"), warnings); + //// Warnings while saving file + trans.get("BasicFrame.WarningDialog.saving.title"), + warnings); } else if (!errors.isEmpty()) { ErrorWarningDialog.showErrorsAndWarnings(BasicFrame.this, new Object[]{ @@ -1677,10 +1678,21 @@ public class BasicFrame extends JFrame { * @return true if the file was written */ private boolean saveWavefrontOBJFile(File file, OBJExportOptions options) { + WarningSet warnings = new WarningSet(); OBJExporterFactory exporter = new OBJExporterFactory(getSelectedComponents(), rocket.getSelectedConfiguration(), - file, options); + file, options, warnings); exporter.doExport(); + // Show warning dialog + if (!warnings.isEmpty()) { + WarningDialog.showWarnings(this, + //// The following problems were encountered while saving + trans.get("BasicFrame.WarningDialog.saving.txt1") + " '" + file.getName() + "'.", + //// Warnings while saving file + trans.get("BasicFrame.WarningDialog.saving.title"), + warnings); + } + return true; } From 08c002ed576020c03372dc5a472ee789f064e197 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 9 Sep 2023 14:05:27 +0200 Subject: [PATCH 2/5] Add shoulder margin --- .../wavefrontobj/export/components/TransitionExporter.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java index 5be6ddb7f..b91d3b069 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java @@ -133,8 +133,11 @@ public class TransitionExporter extends RocketComponentExporter { final double actualLength = estimateActualLength(offsetRadius, dxBase); // Actual length of the transition (due to reduced step size near the fore/aft end) // Get the location where the fore/aft shoulder would end (due to its thickness) - final double xForeShoulder = component.getForeShoulderThickness(); - final double xAftShoulder = component.getLength() - component.getAftShoulderThickness(); + final double shoulderMargin = 0.001; // Margin to prevent the shoulder from being too close to the transition end + final double foreShoulderMargin = hasForeShoulder ? shoulderMargin : 0; + final double aftShoulderMargin = hasAftShoulder ? shoulderMargin : 0; + final double xForeShoulder = component.getForeShoulderThickness() + foreShoulderMargin; + final double xAftShoulder = component.getLength() - component.getAftShoulderThickness() - aftShoulderMargin; // Generate vertices and normals float x = 0; // Distance from the fore end From 74cd0e963697f1030076bea86dcc79dff4dd6102 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 9 Sep 2023 14:11:18 +0200 Subject: [PATCH 3/5] Warn for zero-thickness shoulder --- core/resources/l10n/messages.properties | 2 +- core/resources/l10n/messages_ar.properties | 2 +- core/resources/l10n/messages_cs.properties | 2 +- core/resources/l10n/messages_de.properties | 2 +- core/resources/l10n/messages_es.properties | 2 +- core/resources/l10n/messages_fr.properties | 2 +- core/resources/l10n/messages_it.properties | 2 +- core/resources/l10n/messages_ja.properties | 2 +- core/resources/l10n/messages_nl.properties | 2 +- core/resources/l10n/messages_pl.properties | 2 +- core/resources/l10n/messages_pt.properties | 2 +- core/resources/l10n/messages_ru.properties | 2 +- core/resources/l10n/messages_uk_UA.properties | 2 +- core/resources/l10n/messages_zh_CN.properties | 2 +- .../export/components/TransitionExporter.java | 13 +++++++++++++ .../gui/configdialog/RocketComponentConfig.java | 2 +- 16 files changed, 28 insertions(+), 15 deletions(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index b65b8b3f5..43dca9b4c 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -1048,7 +1048,7 @@ RocketCompCfg.lbl.Length = Length: RocketCompCfg.lbl.Thickness = Thickness: RocketCompCfg.checkbox.Endcapped = End capped RocketCompCfg.checkbox.Endcapped.ttip = Caps (closes) the end of the shoulder. -RocketCompCfg.title.Aftshoulder = Aft shoulder +RocketCompCfg.border.Aftshoulder = Aft shoulder RocketCompCfg.border.Foreshoulder = Fore shoulder RocketCompCfg.tab.Outside = Outside RocketCompCfg.tab.Inside = Inside diff --git a/core/resources/l10n/messages_ar.properties b/core/resources/l10n/messages_ar.properties index 5a957d4cc..363b0bd02 100644 --- a/core/resources/l10n/messages_ar.properties +++ b/core/resources/l10n/messages_ar.properties @@ -951,7 +951,7 @@ RocketCompCfg.lbl.Length = :الطول RocketCompCfg.lbl.Thickness = :السماكة RocketCompCfg.checkbox.Endcapped = نهاية مغلقة RocketCompCfg.checkbox.Endcapped.ttip = .يغلق نهاية الكتف -RocketCompCfg.title.Aftshoulder = مؤخرة الكتف +RocketCompCfg.border.Aftshoulder = مؤخرة الكتف RocketCompCfg.border.Foreshoulder = مقدمة الكتف !RocketCompCfg.lbl.Length = :الطول RocketCompCfg.tab.Outside = من الخارج diff --git a/core/resources/l10n/messages_cs.properties b/core/resources/l10n/messages_cs.properties index a1b326463..04106b5b8 100644 --- a/core/resources/l10n/messages_cs.properties +++ b/core/resources/l10n/messages_cs.properties @@ -651,7 +651,7 @@ RocketCompCfg.lbl.Length = D RocketCompCfg.lbl.Thickness = Tlou\u0161tka: RocketCompCfg.checkbox.Endcapped = Zslepka RocketCompCfg.ttip.Endcapped = Zdali je konec ramene zaslepen. -RocketCompCfg.title.Aftshoulder = Dr\u017Ek zdi +RocketCompCfg.border.Aftshoulder = Dr\u017Ek zdi RocketCompCfg.border.Foreshoulder = Dr\u017Ek prdi !RocketCompCfg.lbl.Length = Dlka: diff --git a/core/resources/l10n/messages_de.properties b/core/resources/l10n/messages_de.properties index 007a46da3..e888f8944 100644 --- a/core/resources/l10n/messages_de.properties +++ b/core/resources/l10n/messages_de.properties @@ -708,7 +708,7 @@ RocketCompCfg.lbl.Length = L RocketCompCfg.lbl.Thickness = Wandstrke: RocketCompCfg.checkbox.Endcapped = Verschlossenes Ende RocketCompCfg.ttip.Endcapped = Gibt an, ob das Ende der Schulter geschlossen ist. -RocketCompCfg.title.Aftshoulder = Schulter hinten +RocketCompCfg.border.Aftshoulder = Schulter hinten RocketCompCfg.border.Foreshoulder = Schulter vorn !RocketCompCfg.lbl.Length = Length: diff --git a/core/resources/l10n/messages_es.properties b/core/resources/l10n/messages_es.properties index db5dc37d1..49c52554e 100644 --- a/core/resources/l10n/messages_es.properties +++ b/core/resources/l10n/messages_es.properties @@ -857,7 +857,7 @@ RocketCompCfg.tab.Figure = Estilo RocketCompCfg.tab.Override.ttip = Especificar la Masa y el CG del componente. RocketCompCfg.tab.Override = Masa y CG RocketCompCfg.tab.Comment.ttip = Especifique un comentario para el componente -RocketCompCfg.title.Aftshoulder = Trasera del acople +RocketCompCfg.border.Aftshoulder = Trasera del acople RocketCompCfg.ttip.Endcapped = Si el extremo del soporte est\u00e1 truncado. RocketCompCfg.lbl.Componentname.ttip = El nombre del componente. diff --git a/core/resources/l10n/messages_fr.properties b/core/resources/l10n/messages_fr.properties index fbbdd38e5..65686aca6 100644 --- a/core/resources/l10n/messages_fr.properties +++ b/core/resources/l10n/messages_fr.properties @@ -849,7 +849,7 @@ RocketCompCfg.tab.Figure = Forme RocketCompCfg.tab.Override.ttip = For\u00E7age de la Masse et du CG RocketCompCfg.tab.Override = Forcer la valeur RocketCompCfg.tab.Comment.ttip = Commentaires concernant la pi\u00E8ce -RocketCompCfg.title.Aftshoulder = Epaulement arri\u00E8re +RocketCompCfg.border.Aftshoulder = Epaulement arri\u00E8re RocketCompCfg.ttip.Endcapped = Pr\u00E9cise si l'arri\u00E8re du c\u00F4ne est clos. RocketCompCfg.lbl.Componentname.ttip = Le nom de la pi\u00E8ce. diff --git a/core/resources/l10n/messages_it.properties b/core/resources/l10n/messages_it.properties index 58d24f634..14fa090db 100644 --- a/core/resources/l10n/messages_it.properties +++ b/core/resources/l10n/messages_it.properties @@ -709,7 +709,7 @@ RocketCompCfg.lbl.Length = Lunghezza: RocketCompCfg.lbl.Thickness = Spessore: RocketCompCfg.checkbox.Endcapped = Chiuso RocketCompCfg.ttip.Endcapped = Se la fine della spalla e' chiusa. -RocketCompCfg.title.Aftshoulder = Spalla posteriore +RocketCompCfg.border.Aftshoulder = Spalla posteriore RocketCompCfg.border.Foreshoulder = Spalla anteriore !RocketCompCfg.lbl.Length = Lunghezza: diff --git a/core/resources/l10n/messages_ja.properties b/core/resources/l10n/messages_ja.properties index a593c4c62..bba01aa9b 100644 --- a/core/resources/l10n/messages_ja.properties +++ b/core/resources/l10n/messages_ja.properties @@ -739,7 +739,7 @@ RocketCompCfg.lbl.Length = \u9577\u3055\uFF1A RocketCompCfg.lbl.Thickness = \u539A\u3055\uFF1A RocketCompCfg.checkbox.Endcapped = \u7AEF\u306B\u30D5\u30BF\u3092\u3059\u308B RocketCompCfg.ttip.Endcapped = \u30D5\u30BF\u304C\u3042\u308B\u304B\u3069\u3046\u304B -RocketCompCfg.title.Aftshoulder = \u5F8C\u65B9\u30B7\u30E7\u30EB\u30C0\u30FC +RocketCompCfg.border.Aftshoulder = \u5F8C\u65B9\u30B7\u30E7\u30EB\u30C0\u30FC RocketCompCfg.border.Foreshoulder = \u524D\u65B9\u30B7\u30E7\u30EB\u30C0\u30FC !RocketCompCfg.lbl.Length diff --git a/core/resources/l10n/messages_nl.properties b/core/resources/l10n/messages_nl.properties index 9b9615c49..2b45dbd5f 100644 --- a/core/resources/l10n/messages_nl.properties +++ b/core/resources/l10n/messages_nl.properties @@ -898,7 +898,7 @@ RocketCompCfg.lbl.Length = Lengte: RocketCompCfg.lbl.Thickness = Dikte: RocketCompCfg.checkbox.Endcapped = Einde afgetopt RocketCompCfg.ttip.Endcapped = Of het einde van de schouder is afgedekt. -RocketCompCfg.title.Aftshoulder = Achterschouder +RocketCompCfg.border.Aftshoulder = Achterschouder RocketCompCfg.border.Foreshoulder = Voorschouder !RocketCompCfg.lbl.Length = Lengte: RocketCompCfg.tab.Outside = Buitenkant diff --git a/core/resources/l10n/messages_pl.properties b/core/resources/l10n/messages_pl.properties index 69ba91cdb..f75ac3382 100644 --- a/core/resources/l10n/messages_pl.properties +++ b/core/resources/l10n/messages_pl.properties @@ -653,7 +653,7 @@ update.dlg.latestVersion = Korzystasz z najnowszej wersji OpenRocket: %s. RocketCompCfg.lbl.Thickness = Grubo\u015B\u0107: RocketCompCfg.checkbox.Endcapped = Zasklepiony koniec RocketCompCfg.ttip.Endcapped = Czy koniec wpustu jest zasklepiony. - RocketCompCfg.title.Aftshoulder = Wpust tylny + RocketCompCfg.border.Aftshoulder = Wpust tylny RocketCompCfg.border.Foreshoulder = Wpust przedni !RocketCompCfg.lbl.Length diff --git a/core/resources/l10n/messages_pt.properties b/core/resources/l10n/messages_pt.properties index 89feaa3e6..f4984a407 100644 --- a/core/resources/l10n/messages_pt.properties +++ b/core/resources/l10n/messages_pt.properties @@ -832,7 +832,7 @@ RocketCompCfg.tab.Figure = Figura RocketCompCfg.tab.Override.ttip = Op\u00e7\u00f5es de modifica\u00e7\u00e3o de massa e CG RocketCompCfg.tab.Override = Modificar RocketCompCfg.tab.Comment.ttip = Especifique um coment\u00e1rio para o componente -RocketCompCfg.title.Aftshoulder = Ressalto traseiro +RocketCompCfg.border.Aftshoulder = Ressalto traseiro RocketCompCfg.ttip.Endcapped = Quando a extremidade do ressalto \u00e9 limitada. RocketCompCfg.lbl.Componentname.ttip = Nome do componente. diff --git a/core/resources/l10n/messages_ru.properties b/core/resources/l10n/messages_ru.properties index 7da3fd403..6b4db81ef 100644 --- a/core/resources/l10n/messages_ru.properties +++ b/core/resources/l10n/messages_ru.properties @@ -929,7 +929,7 @@ RocketCompCfg.lbl.Length = \u0414\u043B\u0438\u043D\u0430: RocketCompCfg.lbl.Thickness = \u0422\u043E\u043B\u0449\u0438\u043D\u0430: RocketCompCfg.checkbox.Endcapped = \u0422\u043E\u0440\u0435\u0446 \u0437\u0430\u0433\u043B\u0443\u0448\u0435\u043D RocketCompCfg.checkbox.Endcapped.ttip = \u0417\u0430\u0433\u043B\u0443\u0448\u0430\u0435\u0442 \u0442\u043E\u0440\u0435\u0446 \u043A\u0440\u044B\u0448\u043A\u043E\u0439. -RocketCompCfg.title.Aftshoulder = \u0417\u0430\u0434\u043D\u0438\u0439 \u0432\u044B\u0441\u0442\u0443\u043F +RocketCompCfg.border.Aftshoulder = \u0417\u0430\u0434\u043D\u0438\u0439 \u0432\u044B\u0441\u0442\u0443\u043F RocketCompCfg.border.Foreshoulder = \u041F\u0435\u0440\u0435\u0434\u043D\u0438\u0439 \u0432\u044B\u0441\u0442\u0443\u043F !RocketCompCfg.lbl.Length = \u0414\u043B\u0438\u043D\u0430: RocketCompCfg.tab.Outside = \u0421\u043D\u0430\u0440\u0443\u0436\u0438 diff --git a/core/resources/l10n/messages_uk_UA.properties b/core/resources/l10n/messages_uk_UA.properties index 08550fd70..e2c53e030 100644 --- a/core/resources/l10n/messages_uk_UA.properties +++ b/core/resources/l10n/messages_uk_UA.properties @@ -811,7 +811,7 @@ RocketCompCfg.lbl.Length = Length: RocketCompCfg.lbl.Thickness = Thickness: RocketCompCfg.checkbox.Endcapped = End capped RocketCompCfg.ttip.Endcapped = Whether the end of the shoulder is capped. -RocketCompCfg.title.Aftshoulder = Aft shoulder +RocketCompCfg.border.Aftshoulder = Aft shoulder RocketCompCfg.border.Foreshoulder = Fore shoulder !RocketCompCfg.lbl.Length = Length: diff --git a/core/resources/l10n/messages_zh_CN.properties b/core/resources/l10n/messages_zh_CN.properties index 0a6180ad8..f3c543eae 100644 --- a/core/resources/l10n/messages_zh_CN.properties +++ b/core/resources/l10n/messages_zh_CN.properties @@ -921,7 +921,7 @@ RocketCompCfg.tab.Figure = \u6837\u5F0F RocketCompCfg.tab.Override.ttip = \u8D28\u91CF\u53CA\u91CD\u5FC3\u9009\u9879 RocketCompCfg.tab.Override = \u8986\u5199 RocketCompCfg.tab.Comment.ttip = \u7EC4\u4EF6\u6CE8\u91CA -RocketCompCfg.title.Aftshoulder = \u524D\u8FDE\u63A5\u5904 +RocketCompCfg.border.Aftshoulder = \u524D\u8FDE\u63A5\u5904 RocketCompCfg.ttip.Endcapped = \u8FDE\u63A5\u5904\u7EC8\u7AEF\u662F\u5426\u6709\u76D6. RocketCompCfg.lbl.Componentname.ttip = \u7EC4\u4EF6\u540D\u79F0. diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java index b91d3b069..b49ebcd66 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java @@ -9,11 +9,13 @@ import net.sf.openrocket.file.wavefrontobj.ObjUtils; import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter; import net.sf.openrocket.file.wavefrontobj.export.shapes.DiskExporter; import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter; +import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.logging.Warning; import net.sf.openrocket.logging.WarningSet; import net.sf.openrocket.rocketcomponent.FlightConfiguration; import net.sf.openrocket.rocketcomponent.InstanceContext; import net.sf.openrocket.rocketcomponent.Transition; +import net.sf.openrocket.startup.Application; import net.sf.openrocket.util.Coordinate; import java.util.ArrayList; @@ -22,6 +24,7 @@ import java.util.List; public class TransitionExporter extends RocketComponentExporter { private static final double RADIUS_EPSILON = 1e-4; private final int nrOfSides; + private static final Translator trans = Application.getTranslator(); public TransitionExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer, Transition component, String groupName, ObjUtils.LevelOfDetail LOD, WarningSet warnings) { @@ -56,6 +59,16 @@ public class TransitionExporter extends RocketComponentExporter { (Double.compare(component.getForeRadius(), component.getThickness()) <= 0 && Double.compare(component.getAftRadius(), component.getThickness()) <= 0); + // Warn for zero-thickness shoulders + if (hasForeShoulder && Double.compare(component.getForeShoulderThickness(), 0) == 0) { + warnings.add(Warning.OBJ_ZERO_THICKNESS, component.getName() + + " (" + trans.get("RocketCompCfg.border.Foreshoulder") + ")"); + } + if (hasAftShoulder && Double.compare(component.getAftShoulderThickness(), 0) == 0) { + warnings.add(Warning.OBJ_ZERO_THICKNESS, component.getName() + + " (" + trans.get("RocketCompCfg.border.Aftshoulder") + ")"); + } + final List outsideForeRingVertices = new ArrayList<>(); final List outsideAftRingVertices = new ArrayList<>(); final List insideForeRingVertices = new ArrayList<>(); diff --git a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java index 6a8dad3ef..e5a985341 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java @@ -836,7 +836,7 @@ public class RocketComponentConfig extends JPanel { sub.setBorder(null); } else { //// Aft shoulder - sub.setBorder(BorderFactory.createTitledBorder(trans.get("RocketCompCfg.title.Aftshoulder"))); + sub.setBorder(BorderFactory.createTitledBorder(trans.get("RocketCompCfg.border.Aftshoulder"))); } From a7a2f4acc9368697c21b0b197e8e5cf65105a632 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 9 Sep 2023 22:23:33 +0200 Subject: [PATCH 4/5] Don't export transition inside when filled due to shoulder --- .../export/components/TransitionExporter.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java index b49ebcd66..537afaa33 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java @@ -49,15 +49,20 @@ public class TransitionExporter extends RocketComponentExporter { private void generateMesh(InstanceContext context) { int startIdx = obj.getNumVertices(); - final boolean hasForeShoulder = Double.compare(component.getForeShoulderRadius(), 0) > 0 - && Double.compare(component.getForeShoulderLength(), 0) > 0 + final boolean hasForeShoulder = Double.compare(component.getForeShoulderLength(), 0) > 0 && component.getForeRadius() > 0; - final boolean hasAftShoulder = Double.compare(component.getAftShoulderRadius(), 0) > 0 - && Double.compare(component.getAftShoulderLength(), 0) > 0 + final boolean hasAftShoulder = Double.compare(component.getAftShoulderLength(), 0) > 0 && component.getAftRadius() > 0; + + final boolean foreSmallerThickn = Double.compare(component.getForeRadius(), component.getThickness()) <= 0; + final boolean aftSmallerThickn = Double.compare(component.getAftRadius(), component.getThickness()) <= 0; + final boolean foreShoulderCapped = hasForeShoulder && component.isForeShoulderCapped(); + final boolean aftShoulderCapped = hasAftShoulder && component.isAftShoulderCapped(); final boolean isFilled = component.isFilled() || - (Double.compare(component.getForeRadius(), component.getThickness()) <= 0 && - Double.compare(component.getAftRadius(), component.getThickness()) <= 0); + (foreSmallerThickn && aftSmallerThickn) || + (foreSmallerThickn && aftShoulderCapped) || + (aftSmallerThickn && foreShoulderCapped) || + (foreShoulderCapped && aftShoulderCapped); // Warn for zero-thickness shoulders if (hasForeShoulder && Double.compare(component.getForeShoulderThickness(), 0) == 0) { From e9264d9dcf8fa53e4e4d519959506187ea5fd7db Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 9 Sep 2023 22:24:39 +0200 Subject: [PATCH 5/5] Clamp shoulder thickness when radius changes --- .../openrocket/importt/DocumentConfig.java | 6 ++-- .../rocketcomponent/Transition.java | 30 +++++++++++++++---- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java b/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java index 6995c8210..2984b3505 100644 --- a/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java +++ b/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java @@ -234,7 +234,8 @@ class DocumentConfig { false)); setters.put("Transition:foreshoulderradius", new DoubleSetter( - Reflection.findMethod(Transition.class, "setForeShoulderRadius", double.class))); + Reflection.findMethod(Transition.class, "setForeShoulderRadius", double.class, boolean.class), + null, null, false)); setters.put("Transition:foreshoulderlength", new DoubleSetter( Reflection.findMethod(Transition.class, "setForeShoulderLength", double.class))); setters.put("Transition:foreshoulderthickness", new DoubleSetter( @@ -243,7 +244,8 @@ class DocumentConfig { Reflection.findMethod(Transition.class, "setForeShoulderCapped", boolean.class))); setters.put("Transition:aftshoulderradius", new DoubleSetter( - Reflection.findMethod(Transition.class, "setAftShoulderRadius", double.class))); + Reflection.findMethod(Transition.class, "setAftShoulderRadius", double.class, boolean.class), + null, null, false)); setters.put("Transition:aftshoulderlength", new DoubleSetter( Reflection.findMethod(Transition.class, "setAftShoulderLength", double.class))); setters.put("Transition:aftshoulderthickness", new DoubleSetter( diff --git a/core/src/net/sf/openrocket/rocketcomponent/Transition.java b/core/src/net/sf/openrocket/rocketcomponent/Transition.java index bba87bd3a..bc1679f09 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/Transition.java +++ b/core/src/net/sf/openrocket/rocketcomponent/Transition.java @@ -119,7 +119,7 @@ public class Transition extends SymmetricComponent implements InsideColorCompone clearPreset(); fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); - setForeShoulderRadius(getForeShoulderRadius()); + setForeShoulderRadius(getForeShoulderRadius(), doClamping); } public void setForeRadius(double radius) { @@ -396,21 +396,31 @@ public class Transition extends SymmetricComponent implements InsideColorCompone return foreShoulderRadius; } - public void setForeShoulderRadius(double foreShoulderRadius) { + public void setForeShoulderRadius(double foreShoulderRadius, boolean doClamping) { for (RocketComponent listener : configListeners) { if (listener instanceof Transition) { - ((Transition) listener).setForeShoulderRadius(foreShoulderRadius); + ((Transition) listener).setForeShoulderRadius(foreShoulderRadius, doClamping); } } foreShoulderRadius = Math.min(foreShoulderRadius, getForeRadius()); if (MathUtil.equals(this.foreShoulderRadius, foreShoulderRadius)) return; + this.foreShoulderRadius = foreShoulderRadius; + + if (doClamping) { + this.foreShoulderThickness = Math.min(this.foreShoulderRadius, this.foreShoulderThickness); + } + clearPreset(); fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE); } + public void setForeShoulderRadius(double foreShoulderRadius) { + setForeShoulderRadius(foreShoulderRadius, true); + } + public double getForeShoulderThickness() { return foreShoulderThickness; } @@ -469,10 +479,10 @@ public class Transition extends SymmetricComponent implements InsideColorCompone return aftShoulderRadius; } - public void setAftShoulderRadius(double aftShoulderRadius) { + public void setAftShoulderRadius(double aftShoulderRadius, boolean doClamping) { for (RocketComponent listener : configListeners) { if (listener instanceof Transition) { - ((Transition) listener).setAftShoulderRadius(aftShoulderRadius); + ((Transition) listener).setAftShoulderRadius(aftShoulderRadius, doClamping); } } @@ -480,11 +490,21 @@ public class Transition extends SymmetricComponent implements InsideColorCompone if (MathUtil.equals(this.aftShoulderRadius, aftShoulderRadius)) return; + this.aftShoulderRadius = aftShoulderRadius; + + if (doClamping) { + this.aftShoulderThickness = Math.min(this.aftShoulderRadius, this.aftShoulderThickness); + } + clearPreset(); fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE); } + public void setAftShoulderRadius(double aftShoulderRadius) { + setAftShoulderRadius(aftShoulderRadius, true); + } + public double getAftShoulderThickness() { return aftShoulderThickness; }