updates for 0.9.3
[debian/openrocket] / src / net / sf / openrocket / file / RASPMotorLoader.java
1 package net.sf.openrocket.file;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.Reader;
6 import java.nio.charset.Charset;
7 import java.util.ArrayList;
8 import java.util.Collections;
9 import java.util.List;
10
11 import net.sf.openrocket.rocketcomponent.Motor;
12 import net.sf.openrocket.rocketcomponent.ThrustCurveMotor;
13 import net.sf.openrocket.util.Coordinate;
14
15 public class RASPMotorLoader extends MotorLoader {
16
17         public static final String CHARSET_NAME = "ISO-8859-1";
18         
19         public static final Charset CHARSET = Charset.forName(CHARSET_NAME);
20         
21         
22         
23         
24         @Override
25         protected Charset getDefaultCharset() {
26                 return CHARSET;
27         }
28
29         
30         /**
31          * Load a <code>Motor</code> from a RASP file specified by the <code>Reader</code>.
32          * The <code>Reader</code> is responsible for using the correct charset.
33          * <p>
34          * The CG is assumed to be located at the center of the motor casing and the mass
35          * is calculated from the thrust curve by assuming a constant exhaust velocity.
36          * 
37          * @param reader  the source of the file.
38          * @return                a list of the {@link Motor} objects defined in the file.
39          * @throws IOException  if an I/O error occurs or if the file format is illegal.
40          */
41         @Override
42         public List<Motor> load(Reader reader, String filename) throws IOException {
43                 List<Motor> motors = new ArrayList<Motor>();
44                 BufferedReader in = new BufferedReader(reader);
45
46                 String manufacturer = "";
47                 String designation = "";
48                 String comment = "";
49                 
50                 double length = 0;
51                 double diameter = 0;
52                 ArrayList<Double> delays = null;
53                 
54                 List<Double> time = new ArrayList<Double>();
55                 List<Double> thrust = new ArrayList<Double>();
56                 
57                 double propW = 0;
58                 double totalW = 0;
59                 
60                 try {
61                         String line;
62                         String[] pieces, buf;
63
64                         line = in.readLine();
65                         main: while (line != null) {   // Until EOF
66
67                                 manufacturer = "";
68                                 designation = "";
69                                 comment = "";
70                                 length = 0;
71                                 diameter = 0;
72                                 delays = new ArrayList<Double>();
73                                 propW = 0;
74                                 totalW = 0;
75                                 time.clear();
76                                 thrust .clear();
77                         
78                                 // Read comment
79                                 while (line.length()==0 || line.charAt(0)==';') {
80                                         if (line.length() > 0) {
81                                                 comment += line.substring(1).trim() + "\n";
82                                         }
83                                         line = in.readLine();
84                                         if (line == null)
85                                                 break main;
86                                 }
87                                 comment = comment.trim();
88                                 
89                                 // Parse header line, example:
90                                 // F32 24 124 5-10-15-P .0377 .0695 RV
91                                 // desig diam len delays prop.w tot.w manufacturer
92                                 pieces = split(line);
93                                 if (pieces.length != 7) {
94                                         throw new IOException("Illegal file format.");
95                                 }
96                                 
97                                 designation = pieces[0];
98                                 diameter = Double.parseDouble(pieces[1]) / 1000.0;
99                                 length = Double.parseDouble(pieces[2]) / 1000.0;
100                                 
101                                 if (pieces[3].equalsIgnoreCase("None")) {
102
103                                 } else {
104                                         buf = split(pieces[3],"[-,]+");
105                                         for (int i=0; i < buf.length; i++) {
106                                                 if (buf[i].equalsIgnoreCase("P") || 
107                                                                 buf[i].equalsIgnoreCase("plugged")) {
108                                                         delays.add(Motor.PLUGGED);
109                                                 } else {
110                                                         // Many RASP files have "100" as an only delay
111                                                         double d = Double.parseDouble(buf[i]);
112                                                         if (d < 99)
113                                                                 delays.add(d);
114                                                 }
115                                         }
116                                         Collections.sort(delays);
117                                 }
118                                 
119                                 propW = Double.parseDouble(pieces[4]);
120                                 totalW = Double.parseDouble(pieces[5]);
121                                 manufacturer = convertManufacturer(pieces[6]);
122                                 
123                                 if (propW > totalW) {
124                                         throw new IOException("Propellant weight exceeds total weight in " +
125                                                         "RASP file");
126                                 }
127                                 
128                                 // Read the data
129                                 for (line = in.readLine(); 
130                                          (line != null) && (line.length()==0 || line.charAt(0) != ';');
131                                          line = in.readLine()) {
132                                         
133                                         buf = split(line);
134                                         if (buf.length == 0) {
135                                                 continue;
136                                         } else if (buf.length == 2) {
137                                                 
138                                                 time.add(Double.parseDouble(buf[0]));
139                                                 thrust .add(Double.parseDouble(buf[1]));
140                                                 
141                                         } else {
142                                                 throw new IOException("Illegal file format.");
143                                         }
144                                 }
145                                 
146                                 // Comment of EOF encountered, marks the start of the next motor
147                                 if (time.size() < 2) {
148                                         throw new IOException("Illegal file format, too short thrust-curve.");
149                                 }
150                                 double[] delayArray = new double[delays.size()];
151                                 for (int i=0; i<delays.size(); i++) {
152                                         delayArray[i] = delays.get(i);
153                                 }
154                                 motors.add(createRASPMotor(manufacturer, designation, comment,
155                                                 length, diameter, delayArray, propW, totalW, time, thrust));
156                         }
157                         
158                 } catch (NumberFormatException e) {
159                         
160                         throw new IOException("Illegal file format.");
161                         
162                 } finally {
163                         
164                         in.close();
165                         
166                 }
167                 
168                 return motors;
169         }
170         
171         
172         /**
173          * Create a motor from RASP file data.
174          * @throws IOException  if the data is illegal for a thrust curve
175          */
176         private static Motor createRASPMotor(String manufacturer, String designation,
177                         String comment, double length, double diameter, double[] delays,
178                         double propW, double totalW, List<Double> time, List<Double> thrust) 
179                         throws IOException {
180                 
181                 // Add zero time/thrust if necessary
182                 sortLists(time, thrust);
183                 finalizeThrustCurve(time, thrust);
184                 List<Double> mass = calculateMass(time,thrust,totalW,propW);
185                 
186                 double[] timeArray = new double[time.size()];
187                 double[] thrustArray = new double[time.size()];
188                 Coordinate[] cgArray = new Coordinate[time.size()];
189                 for (int i=0; i < time.size(); i++) {
190                         timeArray[i] = time.get(i);
191                         thrustArray[i] = thrust.get(i);
192                         cgArray[i] = new Coordinate(length/2,0,0,mass.get(i));
193                 }
194                 
195                 designation = removeDelay(designation);
196                 
197                 try {
198                         
199                         return new ThrustCurveMotor(manufacturer, designation, comment, Motor.Type.UNKNOWN,
200                                         delays, diameter, length, timeArray, thrustArray, cgArray);
201                         
202                 } catch (IllegalArgumentException e) {
203                         
204                         // Bad data read from file.
205                         throw new IOException("Illegal file format.", e);
206                         
207                 }
208         }
209 }