source: git/src/gfxcore.h @ a6401ff3

Last change on this file since a6401ff3 was a6401ff3, checked in by Olly Betts <olly@…>, 4 months ago

Improve handling of hidden splay ends

Previously, hidden splay ends still served as "targets" for snapping
the mouse pointer to, and still got crosses when crosses were
enabled.

We don't have a handy flag for "this is the outer end of a splay"
and computing that on demand isn't so easy to do, so for now we
use the "anonymous station" flag so at least these cases now behave
properly for splays to anonymous stations (which is likely to be
what people with huge numbers of splays from disto-x, etc are
using). This does mean that anonymous stations on continuation
passages will incorrectly also be off when splays are hidden, but
that seems an OK trade-off for now.

The snapping of the mouse pointer was reported by Frank Tully in #105.

  • Property mode set to 100644
File size: 18.5 KB
Line 
1//
2//  gfxcore.h
3//
4//  Core drawing code for Aven.
5//
6//  Copyright (C) 2000-2001,2002,2005 Mark R. Shinwell.
7//  Copyright (C) 2001-2004,2005,2006,2007,2010,2011,2012,2013,2014,2015,2016,2017,2018 Olly Betts
8//  Copyright (C) 2005 Martin Green
9//
10//  This program is free software; you can redistribute it and/or modify
11//  it under the terms of the GNU General Public License as published by
12//  the Free Software Foundation; either version 2 of the License, or
13//  (at your option) any later version.
14//
15//  This program is distributed in the hope that it will be useful,
16//  but WITHOUT ANY WARRANTY; without even the implied warranty of
17//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18//  GNU General Public License for more details.
19//
20//  You should have received a copy of the GNU General Public License
21//  along with this program; if not, write to the Free Software
22//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
23//
24
25#ifndef gfxcore_h
26#define gfxcore_h
27
28#include <float.h>
29#include <limits.h>
30#include <time.h>
31
32#include "img_hosted.h"
33
34#include "guicontrol.h"
35#include "labelinfo.h"
36#include "vector3.h"
37#include "wx.h"
38#include "gla.h"
39
40#include <list>
41#include <utility>
42#include <vector>
43
44using namespace std;
45
46class MainFrm;
47class traverse;
48
49class XSect;
50class PointInfo;
51class MovieMaker;
52
53class PresentationMark : public Point {
54  public:
55    Double angle, tilt_angle;
56    Double scale;
57    Double time;
58    PresentationMark() : Point(), angle(0), tilt_angle(0), scale(0), time(0)
59        { }
60    PresentationMark(const Vector3 & v, Double angle_, Double tilt_angle_,
61                     Double scale_, Double time_ = 0)
62        : Point(v), angle(angle_), tilt_angle(tilt_angle_), scale(scale_),
63          time(time_)
64        { }
65    bool is_valid() const { return scale > 0; }
66};
67
68struct ZoomBox {
69  public:
70    int x1, y1, x2, y2;
71
72    ZoomBox()
73        : x1(INT_MAX) { }
74
75    bool active() const { return x1 != INT_MAX; }
76
77    void set(const wxPoint & p1, const wxPoint & p2) {
78        x1 = p1.x;
79        y1 = p1.y;
80        x2 = p2.x;
81        y2 = p2.y;
82    }
83
84    void unset() {
85        x1 = INT_MAX;
86    }
87};
88
89enum {
90    COLOUR_BY_NONE,
91    COLOUR_BY_DEPTH,
92    COLOUR_BY_DATE,
93    COLOUR_BY_ERROR,
94    COLOUR_BY_GRADIENT,
95    COLOUR_BY_LENGTH,
96    COLOUR_BY_SURVEY,
97    COLOUR_BY_LIMIT_ // Leave this last.
98};
99
100enum {
101    UPDATE_NONE,
102    UPDATE_BLOBS,
103    UPDATE_BLOBS_AND_CROSSES
104};
105
106enum {
107    SHOW_HIDE,
108    SHOW_DASHED,
109    SHOW_FADED,
110    SHOW_NORMAL,
111};
112
113struct Split {
114    Vector3 vec;
115    glaCoord tx, ty;
116
117    Split(const Vector3& vec_, glaCoord tx_, glaCoord ty_)
118        : vec(vec_), tx(tx_), ty(ty_) { }
119};
120
121// It's pointless to redraw the screen as often as we can on a fast machine,
122// since the display hardware will only update so many times per second.
123// This is the maximum framerate we'll redraw at.
124const int MAX_FRAMERATE = 50;
125
126class GfxCore : public GLACanvas {
127    Double m_Scale;
128    Double initial_scale;
129    int m_ScaleBarWidth;
130
131    typedef enum {
132        LIST_COMPASS,
133        LIST_CLINO,
134        LIST_CLINO_BACK,
135        LIST_SCALE_BAR,
136        LIST_DEPTH_KEY,
137        LIST_DATE_KEY,
138        LIST_ERROR_KEY,
139        LIST_GRADIENT_KEY,
140        LIST_LENGTH_KEY,
141        LIST_UNDERGROUND_LEGS,
142        LIST_TUBES,
143        LIST_SURFACE_LEGS,
144        LIST_BLOBS,
145        LIST_CROSSES,
146        LIST_GRID,
147        LIST_SHADOW,
148        LIST_TERRAIN,
149        LIST_LIMIT_ // Leave this last.
150    } drawing_list;
151
152    static const int NUM_COLOUR_BANDS = 13;
153
154    void SetPanBase() {
155        base_pan = m_PanAngle;
156        base_pan_time = timer.Time() - (1000 / MAX_FRAMERATE);
157    }
158
159    void SetTiltBase() {
160        base_tilt = m_TiltAngle;
161        base_tilt_time = timer.Time() - (1000 / MAX_FRAMERATE);
162    }
163
164    int GetCompassWidth() const;
165    int GetClinoWidth() const;
166
167public:
168    typedef enum {
169        CURSOR_DEFAULT,
170        CURSOR_POINTING_HAND,
171        CURSOR_DRAGGING_HAND,
172        CURSOR_HORIZONTAL_RESIZE,
173        CURSOR_ROTATE_HORIZONTALLY,
174        CURSOR_ROTATE_VERTICALLY,
175        CURSOR_ROTATE_EITHER_WAY,
176        CURSOR_ZOOM,
177        CURSOR_ZOOM_ROTATE
178    } cursor;
179
180private:
181    GUIControl* m_Control;
182    char* m_LabelGrid;
183    MainFrm* m_Parent;
184    bool m_DoneFirstShow;
185    Double m_TiltAngle;
186    Double m_PanAngle;
187    bool m_Rotating;
188    Double m_RotationStep;
189    int m_SwitchingTo;
190    bool m_Crosses;
191    bool m_Legs;
192    int m_Splays;
193    int m_Dupes;
194    bool m_Names;
195    bool m_Scalebar;
196    bool m_ColourKey;
197    bool m_OverlappingNames;
198    bool m_Compass;
199    bool m_Clino;
200    bool m_Tubes;
201    int m_ColourBy;
202
203    bool m_HaveData;
204    bool m_HaveTerrain;
205    bool m_MouseOutsideCompass;
206    bool m_MouseOutsideElev;
207    bool m_Surface;
208    bool m_Entrances;
209    bool m_FixedPts;
210    bool m_ExportedPts;
211    bool m_Grid;
212    bool m_BoundingBox;
213    bool m_Terrain;
214
215    bool m_Degrees;
216    bool m_Metric;
217    bool m_Percent;
218
219    bool m_HitTestDebug;
220    bool m_RenderStats;
221
222    list<LabelInfo*> *m_PointGrid;
223    bool m_HitTestGridValid;
224
225    LabelInfo temp_here;
226    const LabelInfo * m_here;
227    const LabelInfo * m_there;
228    wxString highlighted_survey;
229
230    wxStopWatch timer;
231    long base_tilt_time;
232    long base_pan_time;
233    Double base_tilt;
234    Double base_pan;
235
236    GLAPen m_Pens[NUM_COLOUR_BANDS + 1];
237
238#define PLAYING 1
239    int presentation_mode; // for now, 0 => off, PLAYING => continuous play
240    bool pres_reverse;
241    double pres_speed;
242    PresentationMark next_mark;
243    double next_mark_time;
244    double this_mark_total;
245
246    MovieMaker * movie;
247
248    cursor current_cursor;
249
250    int sqrd_measure_threshold;
251
252    // The legends for each entry in the colour key.
253    wxString key_legends[NUM_COLOUR_BANDS];
254
255    wxPoint key_lowerleft[COLOUR_BY_LIMIT_];
256
257    ZoomBox zoombox;
258
259    // Copied from parent, so we can adjust view when reloading the same
260    // file with the view restricted.
261    Vector3 offsets;
262
263    // DEM:
264    unsigned short * dem;
265    unsigned long dem_width, dem_height;
266    double o_x, o_y, step_x, step_y;
267    long nodata_value;
268    bool bigendian;
269    long last_time;
270    size_t n_tris;
271
272    void PlaceVertexWithColour(const Vector3 &v, Double factor = 1.0);
273    void PlaceVertexWithColour(const Vector3 & v,
274                               glaTexCoord tex_x, glaTexCoord tex_y,
275                               Double factor);
276    void SetDepthColour(Double z, Double factor);
277    void PlaceVertexWithDepthColour(const Vector3 & v, Double factor = 1.0);
278    void PlaceVertexWithDepthColour(const Vector3 & v,
279                                    glaTexCoord tex_x, glaTexCoord tex_y,
280                                    Double factor);
281
282    void SetColourFrom01(double how_far, Double factor);
283
284    void SetColourFromDate(int date, Double factor);
285    void SetColourFromError(double E, Double factor);
286    void SetColourFromGradient(double angle, Double factor);
287    void SetColourFromLength(double len, Double factor);
288    void SetColourFromSurvey(const wxString& survey);
289    void SetColourFromSurveyStation(const wxString& survey, Double factor);
290
291    int GetClinoOffset() const;
292    void DrawTick(int angle_cw);
293    void DrawArrow(gla_colour col1, gla_colour col2);
294
295    void SkinPassage(vector<XSect> & centreline);
296
297    virtual void GenerateList(unsigned int l);
298    void GenerateDisplayList(bool surface);
299    void GenerateDisplayListTubes();
300    void DrawTerrainTriangle(const Vector3 & a, const Vector3 & b, const Vector3 & c);
301    void DrawTerrain();
302    void GenerateDisplayListShadow();
303    void GenerateBlobsDisplayList();
304
305    void DrawIndicators();
306
307    void TryToFreeArrays();
308    void FirstShow();
309
310    void DrawScaleBar();
311    void DrawColourKey(int num_bands, const wxString & other, const wxString & units);
312    void DrawDepthKey();
313    void DrawDateKey();
314    void DrawErrorKey();
315    void DrawGradientKey();
316    void DrawLengthKey();
317    void DrawCompass();
318    void DrawClino();
319    void DrawClinoBack();
320    void Draw2dIndicators();
321    void DrawGrid();
322
323    void NattyDrawNames();
324    void SimpleDrawNames();
325
326    void DefaultParameters();
327
328    void Repaint();
329
330    void CreateHitTestGrid();
331
332    int GetCompassXPosition() const;
333    int GetClinoXPosition() const;
334    int GetIndicatorYPosition() const;
335    int GetIndicatorRadius() const;
336
337    void ToggleFlag(bool* flag, int update = UPDATE_NONE);
338
339    const GLAPen& GetPen(int band) const {
340        assert(band >= 0 && band < NUM_COLOUR_BANDS);
341        return m_Pens[band];
342    }
343
344    const GLAPen& GetSurfacePen() const { return m_Pens[NUM_COLOUR_BANDS]; }
345
346    int GetNumColourBands() const { return NUM_COLOUR_BANDS; }
347
348    void DrawShadowedBoundingBox();
349    void DrawBoundingBox();
350
351public:
352    GfxCore(MainFrm* parent, wxWindow* parent_window, GUIControl* control);
353    ~GfxCore();
354
355    void Initialise(bool same_file);
356
357    void UpdateBlobs();
358    void ForceRefresh();
359
360    void RefreshLine(const Point* a, const Point* b, const Point* c);
361
362    void SetHereSurvey(const wxString& survey) {
363        if (survey != highlighted_survey) {
364            highlighted_survey = survey;
365            ForceRefresh();
366        }
367    }
368
369    void HighlightSurvey();
370
371    void ZoomToSurvey(const wxString& survey);
372
373    void SetHereFromTree(const LabelInfo * p);
374
375    void SetHere(const LabelInfo * p = NULL);
376    void SetThere(const LabelInfo * p = NULL);
377
378    const LabelInfo* GetThere() const { return m_there; }
379
380    void CentreOn(const Point &p);
381
382    void TranslateCave(int dx, int dy);
383    void TiltCave(Double tilt_angle);
384    void TurnCave(Double angle);
385    void TurnCaveTo(Double angle);
386
387    void OnPaint(wxPaintEvent&);
388    void OnSize(wxSizeEvent& event);
389    void OnIdle(wxIdleEvent& event);
390
391    void OnMouseMove(wxMouseEvent& event) { m_Control->OnMouseMove(event); }
392    void OnLeaveWindow(wxMouseEvent& event);
393
394    void OnLButtonDown(wxMouseEvent& event) { SetFocus(); m_Control->OnLButtonDown(event); }
395    void OnLButtonUp(wxMouseEvent& event) { m_Control->OnLButtonUp(event); }
396    void OnMButtonDown(wxMouseEvent& event) { SetFocus(); m_Control->OnMButtonDown(event); }
397    void OnMButtonUp(wxMouseEvent& event) { m_Control->OnMButtonUp(event); }
398    void OnRButtonDown(wxMouseEvent& event) { SetFocus(); m_Control->OnRButtonDown(event); }
399    void OnRButtonUp(wxMouseEvent& event) { m_Control->OnRButtonUp(event); }
400    void OnMouseWheel(wxMouseEvent& event) { SetFocus(); m_Control->OnMouseWheel(event); }
401    void OnKeyPress(wxKeyEvent &event) { m_Control->OnKeyPress(event); }
402
403    void Animate();
404    bool Animating() const {
405        return m_Rotating || m_SwitchingTo || presentation_mode != 0;
406    }
407
408    void ClearCoords();
409    void SetCoords(wxPoint);
410
411    // Determine whether the compass is currently shown.
412    bool ShowingCompass() const { return m_Compass; }
413    // Determine whether the clino is currently shown.
414    bool ShowingClino() const { return m_Clino; }
415
416    bool PointWithinCompass(wxPoint point) const;
417    bool PointWithinClino(wxPoint point) const;
418    bool PointWithinScaleBar(wxPoint point) const;
419    bool PointWithinColourKey(wxPoint point) const;
420
421    void SetCompassFromPoint(wxPoint point);
422    void SetClinoFromPoint(wxPoint point);
423    void SetScaleBarFromOffset(wxCoord dx);
424
425    void RedrawIndicators();
426
427    void StartRotation();
428    void ToggleRotation();
429    void StopRotation();
430    bool IsExtendedElevation() const;
431    void ReverseRotation();
432    void RotateSlower(bool accel);
433    void RotateFaster(bool accel);
434
435    void SwitchToElevation();
436    void SwitchToPlan();
437
438    void SetViewTo(Double xmin, Double xmax, Double ymin, Double ymax, Double zmin, Double zmax);
439
440    double GetCompassValue() const { return m_PanAngle; }
441    bool ShowingPlan() const;
442    bool ShowingElevation() const;
443    bool ShowingMeasuringLine() const;
444    bool HereIsReal() const { return m_here && m_here != &temp_here; }
445
446    bool CanRaiseViewpoint() const;
447    bool CanLowerViewpoint() const;
448
449    bool IsRotating() const { return m_Rotating; }
450    bool HasData() const { return m_DoneFirstShow && m_HaveData; }
451    bool HasTerrain() const { return m_DoneFirstShow && m_HaveTerrain; }
452    bool HasDepth() const;
453    bool HasErrorInformation() const;
454    bool HasDateInformation() const;
455
456    double GetScale() const { return m_Scale; }
457    void SetScale(Double scale);
458
459    bool ShowingStationNames() const { return m_Names; }
460    bool ShowingOverlappingNames() const { return m_OverlappingNames; }
461    bool ShowingCrosses() const { return m_Crosses; }
462    bool ShowingGrid() const { return m_Grid; }
463
464    int ColouringBy() const { return m_ColourBy; }
465
466    bool HasUndergroundLegs() const;
467    bool HasSplays() const;
468    bool HasDupes() const;
469    bool HasSurfaceLegs() const;
470    bool HasTubes() const;
471
472    bool ShowingUndergroundLegs() const { return m_Legs; }
473    int ShowingSplaysMode() const { return m_Splays; }
474    int ShowingDupesMode() const { return m_Dupes; }
475    bool ShowingSurfaceLegs() const { return m_Surface; }
476
477    bool ShowingColourKey() const { return m_ColourKey; }
478    bool ShowingScaleBar() const { return m_Scalebar; }
479
480    bool ShowingEntrances() const { return m_Entrances; }
481    bool ShowingFixedPts() const { return m_FixedPts; }
482    bool ShowingExportedPts() const { return m_ExportedPts; }
483
484    int GetNumEntrances() const;
485    int GetNumFixedPts() const;
486    int GetNumExportedPts() const;
487
488    void ToggleUndergroundLegs() {
489        ToggleFlag(&m_Legs, UPDATE_BLOBS_AND_CROSSES);
490    }
491    void SetSplaysMode(int mode) {
492        m_Splays = mode;
493        UpdateBlobs();
494        InvalidateList(LIST_SURFACE_LEGS);
495        InvalidateList(LIST_UNDERGROUND_LEGS);
496        InvalidateList(LIST_CROSSES);
497        m_HitTestGridValid = false;
498        ForceRefresh();
499    }
500    void SetDupesMode(int mode) {
501        m_Dupes = mode;
502        UpdateBlobs();
503        InvalidateList(LIST_SURFACE_LEGS);
504        InvalidateList(LIST_UNDERGROUND_LEGS);
505        ForceRefresh();
506    }
507    void ToggleSurfaceLegs() {
508        ToggleFlag(&m_Surface, UPDATE_BLOBS_AND_CROSSES);
509    }
510    void ToggleCompass() {
511        ToggleFlag(&m_Compass);
512        InvalidateList(LIST_SCALE_BAR);
513    }
514    void ToggleClino() {
515        ToggleFlag(&m_Clino);
516        InvalidateList(LIST_SCALE_BAR);
517    }
518    void ToggleScaleBar() { ToggleFlag(&m_Scalebar); }
519    void ToggleEntrances() { ToggleFlag(&m_Entrances, UPDATE_BLOBS); }
520    void ToggleFixedPts() { ToggleFlag(&m_FixedPts, UPDATE_BLOBS); }
521    void ToggleExportedPts() { ToggleFlag(&m_ExportedPts, UPDATE_BLOBS); }
522    void ToggleGrid() { ToggleFlag(&m_Grid); }
523    void ToggleCrosses() { ToggleFlag(&m_Crosses); }
524    void ToggleStationNames() { ToggleFlag(&m_Names); }
525    void ToggleOverlappingNames() { ToggleFlag(&m_OverlappingNames); }
526    void ToggleColourKey() { ToggleFlag(&m_ColourKey); }
527    void ToggleMetric() {
528        ToggleFlag(&m_Metric);
529        InvalidateList(LIST_DEPTH_KEY);
530        InvalidateList(LIST_LENGTH_KEY);
531        InvalidateList(LIST_SCALE_BAR);
532    }
533    void ToggleHitTestDebug() {
534        ToggleFlag(&m_HitTestDebug);
535    }
536    void ToggleRenderStats() {
537        ToggleFlag(&m_RenderStats);
538    }
539    void ToggleDegrees() {
540        ToggleFlag(&m_Degrees);
541        InvalidateList(LIST_GRADIENT_KEY);
542    }
543    void TogglePercent() { ToggleFlag(&m_Percent); }
544    void ToggleTubes() { ToggleFlag(&m_Tubes); }
545    void TogglePerspective() { GLACanvas::TogglePerspective(); ForceRefresh(); }
546    void ToggleSmoothShading();
547    bool DisplayingBoundingBox() const { return m_BoundingBox; }
548    void ToggleBoundingBox() { ToggleFlag(&m_BoundingBox); }
549    bool DisplayingTerrain() const { return m_Terrain; }
550    void ToggleTerrain();
551    void ToggleFatFinger();
552    void ToggleTextured() {
553        GLACanvas::ToggleTextured();
554        ForceRefresh();
555    }
556
557    bool GetMetric() const { return m_Metric; }
558    bool GetDegrees() const { return m_Degrees; }
559    bool GetPercent() const { return m_Percent; }
560    bool GetTubes() const { return m_Tubes; }
561
562    bool CheckHitTestGrid(const wxPoint& point, bool centre);
563
564    void ClearTreeSelection();
565
566    void Defaults();
567
568    void FullScreenMode();
569
570    bool IsFullScreen() const;
571
572    bool FullScreenModeShowingMenus() const;
573
574    void FullScreenModeShowMenus(bool show);
575
576    void DragFinished();
577
578    void SplitLineAcrossBands(int band, int band2,
579                              const Vector3 &p, const Vector3 &q,
580                              Double factor = 1.0);
581    void SplitPolyAcrossBands(vector<vector<Split>>& splits,
582                              int band, int band2,
583                              const Vector3 &p, const Vector3 &q,
584                              glaTexCoord ptx, glaTexCoord pty,
585                              glaTexCoord w, glaTexCoord h);
586    int GetDepthColour(Double z) const;
587    Double GetDepthBoundaryBetweenBands(int a, int b) const;
588    void AddPolyline(const traverse & centreline);
589    void AddPolylineDepth(const traverse & centreline);
590    void AddPolylineDate(const traverse & centreline);
591    void AddPolylineError(const traverse & centreline);
592    void AddPolylineGradient(const traverse & centreline);
593    void AddPolylineLength(const traverse & centreline);
594    void AddPolylineSurvey(const traverse & centreline);
595    void AddQuadrilateral(const Vector3 &a, const Vector3 &b,
596                          const Vector3 &c, const Vector3 &d);
597    void AddPolylineShadow(const traverse & centreline);
598    void AddQuadrilateralDepth(const Vector3 &a, const Vector3 &b,
599                               const Vector3 &c, const Vector3 &d);
600    void AddQuadrilateralDate(const Vector3 &a, const Vector3 &b,
601                              const Vector3 &c, const Vector3 &d);
602    void AddQuadrilateralError(const Vector3 &a, const Vector3 &b,
603                               const Vector3 &c, const Vector3 &d);
604    void AddQuadrilateralGradient(const Vector3 &a, const Vector3 &b,
605                                  const Vector3 &c, const Vector3 &d);
606    void AddQuadrilateralLength(const Vector3 &a, const Vector3 &b,
607                                const Vector3 &c, const Vector3 &d);
608    void AddQuadrilateralSurvey(const Vector3 &a, const Vector3 &b,
609                                const Vector3 &c, const Vector3 &d);
610    void MoveViewer(double forward, double up, double right);
611
612    void (GfxCore::* AddQuad)(const Vector3 &a, const Vector3 &b,
613                              const Vector3 &c, const Vector3 &d);
614    void (GfxCore::* AddPoly)(const traverse & centreline);
615
616    PresentationMark GetView() const;
617    void SetView(const PresentationMark & p);
618    void PlayPres(double speed, bool change_speed = true);
619    int GetPresentationMode() const { return presentation_mode; }
620    double GetPresentationSpeed() const { return presentation_mode ? pres_speed : 0; }
621
622    void SetColourBy(int colour_by);
623    bool ExportMovie(const wxString & fnm);
624    void OnPrint(const wxString &filename, const wxString &title,
625                 const wxString &datestamp,
626                 bool close_after_print = false);
627    void OnExport(const wxString &filename, const wxString &title,
628                  const wxString &datestamp);
629    void UpdateCursor(GfxCore::cursor new_cursor);
630    bool MeasuringLineActive() const;
631
632    bool HandleRClick(wxPoint point);
633
634    void InvalidateAllLists() {
635        for (int i = 0; i < LIST_LIMIT_; ++i) {
636            InvalidateList(i);
637        }
638    }
639
640    void SetZoomBox(wxPoint p1, wxPoint p2, bool centred, bool aspect);
641
642    void UnsetZoomBox() {
643        if (!zoombox.active()) return;
644        zoombox.unset();
645        ForceRefresh();
646    }
647
648    void ZoomBoxGo();
649
650    void parse_hgt_filename(const wxString & lc_name);
651    size_t parse_hdr(wxInputStream & is, unsigned long & skipbytes);
652    bool read_bil(wxInputStream & is, size_t size, unsigned long skipbytes);
653    bool LoadDEM(const wxString & file);
654
655private:
656    DECLARE_EVENT_TABLE()
657};
658
659#endif
Note: See TracBrowser for help on using the repository browser.