Fin import updates

This commit is contained in:
Sampo Niskanen 2012-03-17 15:58:41 +00:00
parent 61539df82d
commit 4b6b244772
10 changed files with 63 additions and 43 deletions

View File

@ -28,6 +28,7 @@ Sampo Niskanen, main developer
Doug Pedrick, support for RockSim designs, printing Doug Pedrick, support for RockSim designs, printing
Kevin Ruland, Android version Kevin Ruland, Android version
Richard Graham, geodetic computations Richard Graham, geodetic computations
Jason Blood, freeform fin set import
Boris du Reau, internationalization Boris du Reau, internationalization
Translations contributed by: Translations contributed by:

View File

@ -58,9 +58,6 @@ RocketPanel.lbl.infoMessage = <html>Click to select &nbsp;&nbsp; Shift+click to
! BasicFrame ! BasicFrame
BasicFrame.SimpleFileFilter1 = All rocket designs (*.ork; *.rkt)
BasicFrame.SimpleFileFilter2 = OpenRocket designs (*.ork)
BasicFrame.SimpleFileFilter3 = RockSim designs (*.rkt)
BasicFrame.tab.Rocketdesign = Rocket design BasicFrame.tab.Rocketdesign = Rocket design
BasicFrame.tab.Flightsim = Flight simulations BasicFrame.tab.Flightsim = Flight simulations
BasicFrame.title.Addnewcomp = Add new component BasicFrame.title.Addnewcomp = Add new component
@ -95,7 +92,11 @@ dlg.but.close = Close
! General file type names ! General file type names
filetypes.pdf = PDF files filetypes.pdf = PDF files (*.pdf)
BasicFrame.SimpleFileFilter1 = All rocket designs (*.ork; *.rkt)
BasicFrame.SimpleFileFilter2 = OpenRocket designs (*.ork)
BasicFrame.SimpleFileFilter3 = RockSim designs (*.rkt)
filetypes.images = Image files
! About Dialog ! About Dialog
@ -1574,12 +1575,12 @@ GuidedTourSelectionDialog.btn.start = Start tour!
! Custom Fin BMP Importer ! Custom Fin BMP Importer
CustomFinImport.button.label = Import from BMP CustomFinImport.button.label = Import from image
CustomFinImport.filter = Bitmap Files (*.bmp)
CustomFinImport.badFinImage = Invalid fin image. Must be a black and white image (black for the fin), not touching any side, except the bottom of the image, which is the base of the fin. CustomFinImport.badFinImage = Invalid fin image. Must be a black and white image (black for the fin), not touching any side, except the bottom of the image, which is the base of the fin.
CustomFinImport.errorLoadingFile = Error loading file: CustomFinImport.errorLoadingFile = Error loading file:
CustomFinImport.errorParsingFile = Error parsing fin image: CustomFinImport.errorParsingFile = Error parsing fin image:
CustomFinImport.undo = Import freeform fin set CustomFinImport.undo = Import freeform fin set
CustomFinImport.error.title = Error loading fin profile CustomFinImport.error.title = Error loading fin profile
CustomFinImport.error.badimage = Could not deduce fin shape from image. CustomFinImport.error.badimage = Could not deduce fin shape from image.
CustomFinImport.description = The image must be a black and white image (black for the fin), not touching any side, except the bottom of the image, which is the base of the fin.

View File

@ -31,6 +31,7 @@ import net.sf.openrocket.gui.adaptors.DoubleModel;
import net.sf.openrocket.gui.adaptors.EnumModel; import net.sf.openrocket.gui.adaptors.EnumModel;
import net.sf.openrocket.gui.adaptors.IntegerModel; import net.sf.openrocket.gui.adaptors.IntegerModel;
import net.sf.openrocket.gui.components.BasicSlider; import net.sf.openrocket.gui.components.BasicSlider;
import net.sf.openrocket.gui.components.DescriptionArea;
import net.sf.openrocket.gui.components.StyledLabel; import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.gui.components.UnitSelector;
import net.sf.openrocket.gui.dialogs.ScaleDialog; import net.sf.openrocket.gui.dialogs.ScaleDialog;
@ -259,12 +260,15 @@ public class FreeformFinSetConfig extends FinSetConfig {
private void importImage() { private void importImage() {
JFileChooser chooser = new JFileChooser(); JFileChooser chooser = new JFileChooser();
chooser.setFileFilter(FileHelper.getImageFileFilter());
chooser.addChoosableFileFilter(FileHelper.BMP_FILE_FILTER);
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory()); chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory());
int option = chooser.showOpenDialog(this);
JPanel desc = new JPanel(new MigLayout("fill, ins 0 para 0 para"));
desc.add(new DescriptionArea(trans.get("CustomFinImport.description"), 5, 0), "grow, wmin 150lp");
chooser.setAccessory(desc);
int option = chooser.showOpenDialog(this);
if (option == JFileChooser.APPROVE_OPTION) { if (option == JFileChooser.APPROVE_OPTION) {
try { try {
@ -288,7 +292,6 @@ public class FreeformFinSetConfig extends FinSetConfig {
} }
@Override @Override
public void updateFields() { public void updateFields() {
super.updateFields(); super.updateFields();

View File

@ -32,7 +32,8 @@ public class AboutDialog extends JDialog {
"Doug Pedrick (RockSim file format, printing)<br>" + "Doug Pedrick (RockSim file format, printing)<br>" +
"Kevin Ruland (Android version)<br>" + "Kevin Ruland (Android version)<br>" +
"Boris du Reau (internationalization, translation lead)<br>" + "Boris du Reau (internationalization, translation lead)<br>" +
"Richard Graham (geodetic computations)<br><br>" + "Richard Graham (geodetic computations)<br>" +
"Jason Blood (finset import)<br><br>" +
"<b>Translations by:</b><br><br>" + "<b>Translations by:</b><br><br>" +
"Tripoli France (French)<br>" + "Tripoli France (French)<br>" +
"Stefan Lobas / ERIG e.V. (German)<br>" + "Stefan Lobas / ERIG e.V. (German)<br>" +

View File

@ -33,13 +33,12 @@ public class CustomFinImporter {
startX = -1; startX = -1;
facing = FacingDirections.UP; facing = FacingDirections.UP;
if (validateImage(pic)) { if (!validateImage(pic)) {
points.add(Coordinate.NUL);
loadFin(pic, points);
} else {
throw new LocalizedIOException("CustomFinImport.error.badimage"); throw new LocalizedIOException("CustomFinImport.error.badimage");
} }
points.add(Coordinate.NUL);
loadFin(pic, points);
optimizePoints(points); optimizePoints(points);
return points; return points;
} }
@ -48,7 +47,7 @@ public class CustomFinImporter {
private boolean validateImage(BufferedImage pic) { private boolean validateImage(BufferedImage pic) {
int height = pic.getHeight(); int height = pic.getHeight();
int width = pic.getWidth(); int width = pic.getWidth();
Boolean bottomEdgeFound = false; boolean bottomEdgeFound = false;
for (int x = 0; x < width; ++x) { for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) { for (int y = 0; y < height; ++y) {
@ -83,18 +82,18 @@ public class CustomFinImporter {
currentY = pic.getHeight() - 1; currentY = pic.getHeight() - 1;
do { do {
if (CheckLeftIsFin(pic, currentX, currentY)) if (checkLeftIsFin(pic, currentX, currentY))
RotateLeft(); rotateLeft();
else if (CheckForwardIsFin(pic, currentX, currentY)) { else if (checkForwardIsFin(pic, currentX, currentY)) {
// Do nothing // Do nothing
} else if (CheckRightIsFin(pic, currentX, currentY)) } else if (checkRightIsFin(pic, currentX, currentY))
RotateRight(); rotateRight();
else { else {
TurnAround(); turnAround();
calledTurnedAround = true; calledTurnedAround = true;
} }
MoveForward(pic); moveForward(pic);
if (pixelIsFin(pic, currentX, currentY)) { if (pixelIsFin(pic, currentX, currentY)) {
if (!calledTurnedAround) { if (!calledTurnedAround) {
double x = (currentX - startX) * 0.001; double x = (currentX - startX) * 0.001;
@ -119,7 +118,7 @@ public class CustomFinImporter {
return false; return false;
} }
private boolean CheckLeftIsFin(BufferedImage pic, int x, int y) { private boolean checkLeftIsFin(BufferedImage pic, int x, int y) {
if (facing == FacingDirections.DOWN) if (facing == FacingDirections.DOWN)
return pixelIsFin(pic, x + 1, y); return pixelIsFin(pic, x + 1, y);
else if (facing == FacingDirections.UP) else if (facing == FacingDirections.UP)
@ -132,7 +131,7 @@ public class CustomFinImporter {
return false; return false;
} }
private Boolean CheckRightIsFin(BufferedImage pic, int x, int y) { private boolean checkRightIsFin(BufferedImage pic, int x, int y) {
if (facing == FacingDirections.DOWN) if (facing == FacingDirections.DOWN)
return pixelIsFin(pic, x - 1, y); return pixelIsFin(pic, x - 1, y);
else if (facing == FacingDirections.UP) else if (facing == FacingDirections.UP)
@ -145,7 +144,7 @@ public class CustomFinImporter {
return false; return false;
} }
private boolean CheckForwardIsFin(BufferedImage pic, int x, int y) { private boolean checkForwardIsFin(BufferedImage pic, int x, int y) {
if (facing == FacingDirections.DOWN) if (facing == FacingDirections.DOWN)
return pixelIsFin(pic, x, y + 1); return pixelIsFin(pic, x, y + 1);
else if (facing == FacingDirections.UP) else if (facing == FacingDirections.UP)
@ -158,7 +157,7 @@ public class CustomFinImporter {
return false; return false;
} }
private void RotateLeft() { private void rotateLeft() {
if (facing == FacingDirections.UP) if (facing == FacingDirections.UP)
facing = FacingDirections.LEFT; facing = FacingDirections.LEFT;
else if (facing == FacingDirections.RIGHT) else if (facing == FacingDirections.RIGHT)
@ -169,7 +168,7 @@ public class CustomFinImporter {
facing = FacingDirections.DOWN; facing = FacingDirections.DOWN;
} }
private void RotateRight() { private void rotateRight() {
if (facing == FacingDirections.UP) if (facing == FacingDirections.UP)
facing = FacingDirections.RIGHT; facing = FacingDirections.RIGHT;
else if (facing == FacingDirections.RIGHT) else if (facing == FacingDirections.RIGHT)
@ -180,7 +179,7 @@ public class CustomFinImporter {
facing = FacingDirections.UP; facing = FacingDirections.UP;
} }
private void MoveForward(BufferedImage pic) { private void moveForward(BufferedImage pic) {
if (facing == FacingDirections.UP) { if (facing == FacingDirections.UP) {
if (currentY > 0) if (currentY > 0)
currentY--; currentY--;
@ -196,7 +195,7 @@ public class CustomFinImporter {
} }
} }
private void TurnAround() { private void turnAround() {
if (facing == FacingDirections.UP) if (facing == FacingDirections.UP)
facing = FacingDirections.DOWN; facing = FacingDirections.DOWN;
else if (facing == FacingDirections.DOWN) else if (facing == FacingDirections.DOWN)

View File

@ -3,7 +3,9 @@ package net.sf.openrocket.gui.util;
import java.awt.Component; import java.awt.Component;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileFilter;
@ -47,11 +49,6 @@ public final class FileHelper {
public static final FileFilter CSV_FILE_FILTER = public static final FileFilter CSV_FILE_FILTER =
new SimpleFileFilter(trans.get("SimExpPan.desc"), ".csv"); new SimpleFileFilter(trans.get("SimExpPan.desc"), ".csv");
/** File filter for BMP files (*.bmp) */
public static final FileFilter BMP_FILE_FILTER =
new SimpleFileFilter(trans.get("CustomFinImport.filter"), ".bmp");
@ -60,10 +57,26 @@ public final class FileHelper {
} }
// public FileFilter getImageFileFilter() { public static FileFilter getImageFileFilter() {
// String[] extensions = ImageIO.getReaderFileSuffixes(); String[] extensions = ImageIO.getReaderFileSuffixes();
// for (int i = 0; i < extensions.length; i++) {
// } extensions[i] = extensions[i].toLowerCase();
}
Arrays.sort(extensions);
StringBuilder sb = new StringBuilder();
sb.append(trans.get("filetypes.images"));
sb.append(" (");
for (int i = 0; i < extensions.length; i++) {
sb.append("*.").append(extensions[i]);
if (i < extensions.length - 1) {
sb.append("; ");
}
}
sb.append(")");
return new SimpleFileFilter(sb.toString(), extensions);
}
/** /**

View File

@ -59,7 +59,8 @@
stability data and motor files. The Android port is thanks to stability data and motor files. The Android port is thanks to
work by Kevin Ruland.</p> work by Kevin Ruland.</p>
<p>Enhancements in the desktop version include saving designs in RKT <p>Enhancements in the desktop version include saving designs in RKT
format thanks to Doug Pedrick, configurable stage separation format thanks to Doug Pedrick, freeform fin set import form images
by Jason Blood, configurable stage separation
events, guided help tours and displaying the computed motor events, guided help tours and displaying the computed motor
designation class. The application has also been translated to designation class. The application has also been translated to
Italian by Mauro Biasutti and Russian by the Sky Dart Team.</p> Italian by Mauro Biasutti and Russian by the Sky Dart Team.</p>

View File

@ -107,7 +107,8 @@
stability data and motor files. The Android port is thanks to stability data and motor files. The Android port is thanks to
work by Kevin Ruland.</p> work by Kevin Ruland.</p>
<p>Enhancements in the desktop version include saving designs in RKT <p>Enhancements in the desktop version include saving designs in RKT
format thanks to Doug Pedrick, configurable stage separation format thanks to Doug Pedrick, freeform fin set import form images
by Jason Blood, configurable stage separation
events, guided help tours and displaying the computed motor events, guided help tours and displaying the computed motor
designation class. The application has also been translated to designation class. The application has also been translated to
Italian by Mauro Biasutti and Russian by the Sky Dart Team.</p> Italian by Mauro Biasutti and Russian by the Sky Dart Team.</p>

View File

@ -5,5 +5,4 @@ download.htp ../html/download.html
documentation.htp ../html/documentation.html documentation.htp ../html/documentation.html
license.htp ../html/license.html license.htp ../html/license.html
contact.htp ../html/contact.html contact.htp ../html/contact.html
report.htp ../html/report.html
getinvolved.htp ../html/getinvolved.html getinvolved.htp ../html/getinvolved.html

View File

@ -23,7 +23,8 @@
work by Kevin Ruland.</p> work by Kevin Ruland.</p>
<p>Enhancements in the desktop version include saving designs in RKT <p>Enhancements in the desktop version include saving designs in RKT
format thanks to Doug Pedrick, configurable stage separation format thanks to Doug Pedrick, freeform fin set import form images
by Jason Blood, configurable stage separation
events, guided help tours and displaying the computed motor events, guided help tours and displaying the computed motor
designation class. The application has also been translated to designation class. The application has also been translated to
Italian by Mauro Biasutti and Russian by the Sky Dart Team.</p> Italian by Mauro Biasutti and Russian by the Sky Dart Team.</p>