1    /*
2    Copyright 2002 by Ralph Hartley
3    This software is licenced under the terms of the
4    Gnu Public Licence
5    */
6    import java.awt.*;
7    import java.text.*;
8    import java.awt.geom.*;
9    import java.util.*;
10   import java.io.*;
11   import javax.swing.*;
12   
13   public class Survey extends Symbol implements Element {
14   
15     private static final long serialVersionUID = Version.getSUID();
16   
17   /* These variables are part of the old implementation they remain for
18      backwards compatability */
19     Vector stationlist = null;
20     Hashtable dict = null;
21     Vector shotlist = null;
22   
23   /* stations replaces the two structures above */
24     TreeSet stations = null;
25     TreeSet shots = null;
26   
27   //  File file;
28   
29     Survey old = null;
30     Survey next = null;
31   
32   //  public String name = null;
33   
34     static public Size shotsize =null;
35   
36     private void readObject(java.io.ObjectInputStream stream)
37         throws java.io.IOException,java.lang.ClassNotFoundException {
38       stream.defaultReadObject();
39       if (stations==null)
40         stations = new TreeSet(stationlist);
41       if (shots==null) 
42         shots = new TreeSet(shotlist);
43   
44       //This is for backwards compatability - the order has been changed
45       //make sure they are  re sorted.
46       TreeSet oldstations = stations;
47       stations = new TreeSet();
48       for (Iterator it=oldstations.iterator();it.hasNext();stations.add(it.next()));
49       TreeSet oldshots = shots;
50       shots = new TreeSet();
51       for (Iterator it=oldshots.iterator();it.hasNext();shots.add(it.next()));
52     }
53   
54     public static Survey open(Survey older) {
55       JFileChooser choose = Persist.current.getFileChooser();
56       choose.setDialogTitle("Choose survey file");
57       choose.setFileFilter(new FileTypes(FileTypes.SURVEY));
58       choose.rescanCurrentDirectory();
59   
60       try {
61         if (choose.showOpenDialog(null)==choose.APPROVE_OPTION) {
62           try {
63             if (older == null) older = new Survey();
64             older.update(choose.getSelectedFile());
65           } catch (IOException e) {
66             JOptionPane.showMessageDialog(null,
67           				"Could not read survey file: "+choose.getSelectedFile(),
68           				"Survey File",
69           				JOptionPane.ERROR_MESSAGE);
70             return(null);
71           }
72         }
73         else return(null);
74       } finally {
75         Persist.current.clearChooser();
76         Persist.save();
77       }
78   
79       return(older);
80     }
81   
82     public Survey() {
83       stations = new TreeSet();
84       shots = new TreeSet();
85       name = "empty survey";
86     }
87   
88     public Survey(String name,Survey older) {
89       stations = new TreeSet();
90       shots = new TreeSet();
91       this.name = name;
92       old = older;
93     }
94   
95     public Symbol importSym(Carto dest,Carto source) {
96       if (dest.survey!=null) return(dest.survey);
97       dest.survey = this;
98       return(this);
99     }
100  
101    public void purge(Carto user) {
102      if (JOptionPane.showConfirmDialog(null,"Deletes all Stations and shots not in the given file.\n"+
103          			      "You should already have done an update.\n"+
104          			      "Purging the survey cannot be undone.\n"+
105          			      "All previous surveys will become unavailable."
106          			      ,"Purge",JOptionPane.OK_CANCEL_OPTION) ==
107          JOptionPane.OK_OPTION) {
108  
109        Survey res = open(new Survey(name,null));
110        if (res==null) {
111          JOptionPane.showMessageDialog(null,
112          			      "Purge did not take place",
113          			      "Purge aborted",
114          			      JOptionPane.ERROR_MESSAGE);
115          return;
116        }
117  
118        for (Iterator it = stations.iterator();it.hasNext();) {
119          Vertex v = (Vertex)it.next();
120          if (res.stations.contains(v)) {
121            res.stations.remove(v);
122            res.stations.add(v);
123          } else {
124            String use = user.used(v);
125            if (use!=null) {
126              if (JOptionPane.showConfirmDialog(null,"Station "+v+" is used\n"+use+
127          				      "\nClick OK to purge anyway (risky)."
128          				      ,"Station Used",JOptionPane.OK_CANCEL_OPTION) ==
129          	JOptionPane.OK_OPTION) {
130                user.remove(v);
131              } else
132                return;
133            }
134          }
135        }
136        for (Iterator it = shots.iterator();it.hasNext();) {
137          Line line = (Line)it.next();
138          if (res.shots.contains(line)) {
139            res.shots.remove(line);
140            res.shots.add(line);
141          }
142        }
143        stations = res.stations;
144        shots = res.shots;
145        old = next = null;
146      }
147    }
148  
149    public void update(File file) throws java.io.IOException {
150      if (old == null)
151        old = new Survey();
152      else
153        old = new Survey(name,old);
154  
155      old.next = this;
156  
157      this.name = file.getName()+" "+DateFormat.getDateTimeInstance(DateFormat.SHORT,DateFormat.SHORT).format(new Date());
158  
159      if (file.getName().endsWith(".XYZ")) {     // cmap output
160        Vector seqlist = new Vector();
161        String line;
162        StringTokenizer tokens;
163        BufferedReader input = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
164  
165  //      shots = new TreeSet();
166        
167        do { line = input.readLine();
168        } while (line.length()>0 && line.charAt(0)!='-');
169        for (tokens = new StringTokenizer(input.readLine());
170             tokens.countTokens()==6;
171             tokens = new StringTokenizer(input.readLine())) {
172          String lab=tokens.nextToken();
173          Vertex p = new Vertex(new Vect(Double.valueOf(tokens.nextToken()).doubleValue(),
174          			       Double.valueOf(tokens.nextToken()).doubleValue(),
175          			       Double.valueOf(tokens.nextToken()).doubleValue()),
176          		      lab);
177          seqlist.addElement(addStation(p,old));
178          addShot(
179            new Line((Vertex)seqlist.elementAt(Integer.valueOf(tokens.nextToken()).intValue()-1),
180          	   (Vertex)seqlist.elementAt(Integer.valueOf(tokens.nextToken()).intValue()-1)));
181        }
182        input.close();
183      }
184      else if (file.getName().endsWith(".plt")||file.getName().endsWith(".PLT")) {     // compass output
185        String line;
186        StringTokenizer tokens;
187        BufferedReader input = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
188        Vertex currentPos = null;
189        double northing = 0;
190  
191  //      shots = new TreeSet();
192        
193        for (line = input.readLine();line!=null;line = input.readLine()) {
194          tokens = new StringTokenizer(line);
195          String command = tokens.nextToken();
196          if (command.charAt(0)=='D' ||command.charAt(0)=='M') {
197            northing = Double.valueOf(tokens.nextToken()).doubleValue();
198            Vect pos = new Vect(Double.valueOf(tokens.nextToken()).doubleValue(),
199          		      northing,
200          		      Double.valueOf(tokens.nextToken()).doubleValue());
201            String lab=tokens.nextToken().substring(1);
202            Vertex newpos = addStation(new Vertex(pos,lab),old);
203  //          addStation(newpos,old);
204            if (command.charAt(0)=='D')
205              addShot(new Line(currentPos,newpos));
206            currentPos = newpos;
207          }
208        }
209        input.close();
210      }
211  
212      else if (file.getName().endsWith(".3D")||file.getName().endsWith(".3d")) {  // Survex output
213  
214        Input3d input = new Reader3d().Reader3d(new FileInputStream(file));
215        
216        ErrorLog.log("Code for reading Survex files is not finished");
217        
218      }
219    }
220  
221    Vertex addStation(Vertex v,Survey undo) {
222      if (stations.contains(v)) {
223        Vertex oldsta = (Vertex)stations.tailSet(v).first();
224        if (!v.position.equals(oldsta.position)) {
225          undo.stations.add(new Vertex(oldsta));
226          oldsta.position.copyVal(v.position);
227        }
228        return(oldsta);
229      }
230      else {
231        stations.add(v);
232        return(v);
233      }
234    }
235  
236    public Vertex getStation(Vertex old) {
237      if (stations.contains(old))
238        return((Vertex)stations.tailSet(old).first());
239      else {
240        stations.add(old);
241        return(old);
242      }
243    }
244  
245    void undo() {
246      if (old==null) return;
247      Survey mynext = new Survey(name,this);
248      mynext.next = next;
249      if (next!=null) next.old = mynext;
250      next = mynext;
251      
252      Survey edits = old;
253      old = old.old;
254      if (old!=null) old.next = this;
255  
256      this.name = edits.name;
257      for (Iterator it=edits.stations.iterator();it.hasNext();)
258        addStation((Vertex)it.next(),next);
259    }
260  
261    void redo() {
262      if (next==null) return;
263      Survey myold = new Survey(name,old);
264      myold.next = this;
265      if (old!=null) old.next = myold;
266      old = myold;
267      
268      Survey edits = next;
269      next = next.next;
270      if (next!=null) next.old = this;
271  
272      this.name = edits.name;
273      for (Iterator it=edits.stations.iterator();it.hasNext();)
274        addStation((Vertex)it.next(),old);
275    }
276  
277    void addShot(Line s) {
278      if (shots.contains(s)) shots.remove(s);
279      shots.add(s);
280    }
281  
282    public String getName() {
283      return(name);
284    }
285  
286    public void draw(Graphics g, AffineTransform trans) {
287      for (Iterator it=stations.iterator();it.hasNext();)
288        ((Vertex)it.next()).mapdraw(g,trans);
289      for (Iterator it=shots.iterator();it.hasNext();)
290        ((Line)it.next()).mapdraw(g,trans);
291    }
292  
293  /*
294    public Vertex get(String name) {
295      if (name!=null)
296        return((Vertex)(dict.get(name)));
297      else return(null);
298    }
299  */
300    
301    public int shotnum() {
302      return shots.size();
303    }
304  /*
305    public Enumeration stationNames( ) {
306      return dict.keys();
307    }
308  */
309    public int vertexnum() {
310      return stations.size();
311    }
312  
313    public Rectangle2D getBounds(AffineTransform trans) {
314      if (stations.size()==0) return(null);
315  
316      Point2D.Double pos = new Point2D.Double();
317      trans.transform(new Point2D.Double(((Vertex)stations.first()).position.X[0],
318          			       ((Vertex)stations.first()).position.X[1]),pos);
319      Point2D.Double min = (Point2D.Double)pos.clone();
320      Point2D.Double max = (Point2D.Double)pos.clone();
321  
322      for (Iterator it = stations.iterator(); it.hasNext();) {
323        Vertex vert = (Vertex)it.next();
324        trans.transform(new Point2D.Double(vert.position.X[0],vert.position.X[1]),pos);
325        if (pos.x<min.x) min.x = pos.x;
326        if (pos.y<min.y) min.y = pos.y;
327        if (pos.x>max.x) max.x = pos.x;
328        if (pos.y>max.y) max.y = pos.y;
329      }
330      return(new Rectangle2D.Double(min.x,min.y,max.x-min.x,max.y-min.y));
331    }
332  
333    public void paint(View view) {
334      if (!view.visible.isMember(this)) return;
335  
336      if (shotsize==null)
337        shotsize = (Size)FileDefaultable.lookup(Size.class,Size.SHOTLINE);
338  
339      Stroke oldstroke = view.draw.getStroke();
340  
341      view.draw.setStroke(new BasicStroke((float)shotsize.getSize(view.mapscale)));
342  
343      Vertex.paintAll(stations.iterator(),view);
344  
345      for (Iterator e = shots.iterator();e.hasNext();)
346        ((Line)e.next()).paint(view);
347  
348      view.draw.setStroke(oldstroke);
349    }
350  }
351