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