Show duplicate legs as dashed lines
[survex.git] / src / gfxcore.h
blob338ceeef5c78fe5452f1a4e1be89e93c75aa3e0b
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 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.
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.
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
25 #ifndef gfxcore_h
26 #define gfxcore_h
28 #include <float.h>
29 #include <limits.h>
30 #include <time.h>
32 #include "img_hosted.h"
34 #include "guicontrol.h"
35 #include "labelinfo.h"
36 #include "vector3.h"
37 #include "wx.h"
38 #include "gla.h"
40 #include <list>
41 #include <utility>
42 #include <vector>
44 using namespace std;
46 class MainFrm;
47 class traverse;
49 class XSect;
50 class PointInfo;
51 class MovieMaker;
53 class 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; }
68 struct ZoomBox {
69 public:
70 int x1, y1, x2, y2;
72 ZoomBox()
73 : x1(INT_MAX) { }
75 bool active() const { return x1 != INT_MAX; }
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;
84 void unset() {
85 x1 = INT_MAX;
89 enum {
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_LIMIT_ // Leave this last.
99 enum {
100 UPDATE_NONE,
101 UPDATE_BLOBS,
102 UPDATE_BLOBS_AND_CROSSES
105 enum {
106 SPLAYS_HIDE,
107 SPLAYS_SHOW_FADED,
108 SPLAYS_SHOW_NORMAL,
111 enum {
112 DUPES_HIDE,
113 DUPES_SHOW_DASHED,
114 DUPES_SHOW_NORMAL,
117 // It's pointless to redraw the screen as often as we can on a fast machine,
118 // since the display hardware will only update so many times per second.
119 // This is the maximum framerate we'll redraw at.
120 const int MAX_FRAMERATE = 50;
122 class GfxCore : public GLACanvas {
123 Double m_Scale;
124 Double initial_scale;
125 int m_ScaleBarWidth;
127 typedef enum {
128 LIST_COMPASS,
129 LIST_CLINO,
130 LIST_CLINO_BACK,
131 LIST_SCALE_BAR,
132 LIST_DEPTH_KEY,
133 LIST_DATE_KEY,
134 LIST_ERROR_KEY,
135 LIST_GRADIENT_KEY,
136 LIST_LENGTH_KEY,
137 LIST_UNDERGROUND_LEGS,
138 LIST_TUBES,
139 LIST_SURFACE_LEGS,
140 LIST_BLOBS,
141 LIST_CROSSES,
142 LIST_GRID,
143 LIST_SHADOW,
144 LIST_TERRAIN,
145 LIST_LIMIT_ // Leave this last.
146 } drawing_list;
148 static const int NUM_COLOUR_BANDS = 13;
150 void SetPanBase() {
151 base_pan = m_PanAngle;
152 base_pan_time = timer.Time() - (1000 / MAX_FRAMERATE);
155 void SetTiltBase() {
156 base_tilt = m_TiltAngle;
157 base_tilt_time = timer.Time() - (1000 / MAX_FRAMERATE);
160 int GetCompassWidth() const;
161 int GetClinoWidth() const;
163 public:
164 typedef enum {
165 CURSOR_DEFAULT,
166 CURSOR_POINTING_HAND,
167 CURSOR_DRAGGING_HAND,
168 CURSOR_HORIZONTAL_RESIZE,
169 CURSOR_ROTATE_HORIZONTALLY,
170 CURSOR_ROTATE_VERTICALLY,
171 CURSOR_ROTATE_EITHER_WAY,
172 CURSOR_ZOOM,
173 CURSOR_ZOOM_ROTATE
174 } cursor;
176 private:
177 GUIControl* m_Control;
178 char* m_LabelGrid;
179 MainFrm* m_Parent;
180 bool m_DoneFirstShow;
181 Double m_TiltAngle;
182 Double m_PanAngle;
183 bool m_Rotating;
184 Double m_RotationStep;
185 int m_SwitchingTo;
186 bool m_Crosses;
187 bool m_Legs;
188 int m_Splays;
189 int m_Dupes;
190 bool m_Names;
191 bool m_Scalebar;
192 bool m_ColourKey;
193 bool m_OverlappingNames;
194 bool m_Compass;
195 bool m_Clino;
196 bool m_Tubes;
197 int m_ColourBy;
199 bool m_HaveData;
200 bool m_HaveTerrain;
201 bool m_MouseOutsideCompass;
202 bool m_MouseOutsideElev;
203 bool m_Surface;
204 bool m_Entrances;
205 bool m_FixedPts;
206 bool m_ExportedPts;
207 bool m_Grid;
208 bool m_BoundingBox;
209 bool m_Terrain;
211 bool m_Degrees;
212 bool m_Metric;
213 bool m_Percent;
215 bool m_HitTestDebug;
216 bool m_RenderStats;
218 list<LabelInfo*> *m_PointGrid;
219 bool m_HitTestGridValid;
221 LabelInfo temp_here;
222 const LabelInfo * m_here;
223 const LabelInfo * m_there;
225 wxStopWatch timer;
226 long base_tilt_time;
227 long base_pan_time;
228 Double base_tilt;
229 Double base_pan;
231 GLAPen m_Pens[NUM_COLOUR_BANDS + 1];
233 #define PLAYING 1
234 int presentation_mode; // for now, 0 => off, PLAYING => continuous play
235 bool pres_reverse;
236 double pres_speed;
237 PresentationMark next_mark;
238 double next_mark_time;
239 double this_mark_total;
241 MovieMaker * movie;
243 cursor current_cursor;
245 int sqrd_measure_threshold;
247 // The legends for each entry in the colour key.
248 wxString key_legends[NUM_COLOUR_BANDS];
250 wxPoint key_lowerleft[COLOUR_BY_LIMIT_];
252 ZoomBox zoombox;
254 // Copied from parent, so we can adjust view when reloading the same
255 // file with the view restricted.
256 Vector3 offsets;
258 // DEM:
259 unsigned short * dem;
260 unsigned long dem_width, dem_height;
261 double o_x, o_y, step_x, step_y;
262 long nodata_value;
263 bool bigendian;
264 long last_time;
265 size_t n_tris;
267 void PlaceVertexWithColour(const Vector3 &v, Double factor = 1.0);
268 void PlaceVertexWithColour(const Vector3 & v, GLint tex_x, GLint tex_y,
269 Double factor);
270 void SetDepthColour(Double z, Double factor);
271 void PlaceVertexWithDepthColour(const Vector3 & v, Double factor = 1.0);
272 void PlaceVertexWithDepthColour(const Vector3 & v, GLint tex_x, GLint tex_y, Double factor);
274 void SetColourFrom01(double how_far, Double factor);
276 void SetColourFromDate(int date, Double factor);
277 void SetColourFromError(double E, Double factor);
278 void SetColourFromGradient(double angle, Double factor);
279 void SetColourFromLength(double len, Double factor);
281 int GetClinoOffset() const;
282 void DrawTick(int angle_cw);
283 void DrawArrow(gla_colour col1, gla_colour col2);
285 void SkinPassage(vector<XSect> & centreline, bool draw = true);
287 virtual void GenerateList(unsigned int l);
288 void GenerateDisplayList();
289 void GenerateDisplayListTubes();
290 void GenerateDisplayListSurface();
291 void DrawTerrainTriangle(const Vector3 & a, const Vector3 & b, const Vector3 & c);
292 void DrawTerrain();
293 void GenerateDisplayListShadow();
294 void GenerateBlobsDisplayList();
296 void DrawIndicators();
298 void TryToFreeArrays();
299 void FirstShow();
301 void DrawScaleBar();
302 void DrawColourKey(int num_bands, const wxString & other, const wxString & units);
303 void DrawDepthKey();
304 void DrawDateKey();
305 void DrawErrorKey();
306 void DrawGradientKey();
307 void DrawLengthKey();
308 void DrawCompass();
309 void DrawClino();
310 void DrawClinoBack();
311 void Draw2dIndicators();
312 void DrawGrid();
314 void NattyDrawNames();
315 void SimpleDrawNames();
317 void DefaultParameters();
319 void Repaint();
321 void CreateHitTestGrid();
323 int GetCompassXPosition() const;
324 int GetClinoXPosition() const;
325 int GetIndicatorYPosition() const;
326 int GetIndicatorRadius() const;
328 void ToggleFlag(bool* flag, int update = UPDATE_NONE);
330 const GLAPen& GetPen(int band) const {
331 assert(band >= 0 && band < NUM_COLOUR_BANDS);
332 return m_Pens[band];
335 const GLAPen& GetSurfacePen() const { return m_Pens[NUM_COLOUR_BANDS]; }
337 int GetNumColourBands() const { return NUM_COLOUR_BANDS; }
339 void DrawShadowedBoundingBox();
340 void DrawBoundingBox();
342 public:
343 GfxCore(MainFrm* parent, wxWindow* parent_window, GUIControl* control);
344 ~GfxCore();
346 void Initialise(bool same_file);
348 void UpdateBlobs();
349 void ForceRefresh();
351 void RefreshLine(const Point* a, const Point* b, const Point* c);
353 void SetHereFromTree(const LabelInfo * p);
355 void SetHere(const LabelInfo * p = NULL);
356 void SetThere(const LabelInfo * p = NULL);
358 void CentreOn(const Point &p);
360 void TranslateCave(int dx, int dy);
361 void TiltCave(Double tilt_angle);
362 void TurnCave(Double angle);
363 void TurnCaveTo(Double angle);
365 void OnPaint(wxPaintEvent&);
366 void OnSize(wxSizeEvent& event);
367 void OnIdle(wxIdleEvent& event);
369 void OnMouseMove(wxMouseEvent& event) { m_Control->OnMouseMove(event); }
370 void OnLeaveWindow(wxMouseEvent& event);
372 void OnLButtonDown(wxMouseEvent& event) { SetFocus(); m_Control->OnLButtonDown(event); }
373 void OnLButtonUp(wxMouseEvent& event) { m_Control->OnLButtonUp(event); }
374 void OnMButtonDown(wxMouseEvent& event) { SetFocus(); m_Control->OnMButtonDown(event); }
375 void OnMButtonUp(wxMouseEvent& event) { m_Control->OnMButtonUp(event); }
376 void OnRButtonDown(wxMouseEvent& event) { SetFocus(); m_Control->OnRButtonDown(event); }
377 void OnRButtonUp(wxMouseEvent& event) { m_Control->OnRButtonUp(event); }
378 void OnMouseWheel(wxMouseEvent& event) { SetFocus(); m_Control->OnMouseWheel(event); }
379 void OnKeyPress(wxKeyEvent &event) { m_Control->OnKeyPress(event); }
381 void Animate();
382 bool Animating() const {
383 return m_Rotating || m_SwitchingTo || presentation_mode != 0;
386 void ClearCoords();
387 void SetCoords(wxPoint);
389 // Determine whether the compass is currently shown.
390 bool ShowingCompass() const { return m_Compass; }
391 // Determine whether the clino is currently shown.
392 bool ShowingClino() const { return m_Clino; }
394 bool PointWithinCompass(wxPoint point) const;
395 bool PointWithinClino(wxPoint point) const;
396 bool PointWithinScaleBar(wxPoint point) const;
397 bool PointWithinColourKey(wxPoint point) const;
399 void SetCompassFromPoint(wxPoint point);
400 void SetClinoFromPoint(wxPoint point);
401 void SetScaleBarFromOffset(wxCoord dx);
403 void RedrawIndicators();
405 void StartRotation();
406 void ToggleRotation();
407 void StopRotation();
408 bool IsExtendedElevation() const;
409 void ReverseRotation();
410 void RotateSlower(bool accel);
411 void RotateFaster(bool accel);
413 void SwitchToElevation();
414 void SwitchToPlan();
416 void SetViewTo(Double xmin, Double xmax, Double ymin, Double ymax, Double zmin, Double zmax);
418 double GetCompassValue() const { return m_PanAngle; }
419 bool ShowingPlan() const;
420 bool ShowingElevation() const;
421 bool ShowingMeasuringLine() const;
422 bool HereIsReal() const { return m_here && m_here != &temp_here; }
424 bool CanRaiseViewpoint() const;
425 bool CanLowerViewpoint() const;
427 bool IsRotating() const { return m_Rotating; }
428 bool HasData() const { return m_DoneFirstShow && m_HaveData; }
429 bool HasTerrain() const { return m_DoneFirstShow && m_HaveTerrain; }
430 bool HasDepth() const;
431 bool HasErrorInformation() const;
432 bool HasDateInformation() const;
434 double GetScale() const { return m_Scale; }
435 void SetScale(Double scale);
437 bool ShowingStationNames() const { return m_Names; }
438 bool ShowingOverlappingNames() const { return m_OverlappingNames; }
439 bool ShowingCrosses() const { return m_Crosses; }
440 bool ShowingGrid() const { return m_Grid; }
442 int ColouringBy() const { return m_ColourBy; }
444 bool HasUndergroundLegs() const;
445 bool HasSplays() const;
446 bool HasDupes() const;
447 bool HasSurfaceLegs() const;
448 bool HasTubes() const;
450 bool ShowingUndergroundLegs() const { return m_Legs; }
451 int ShowingSplaysMode() const { return m_Splays; }
452 int ShowingDupesMode() const { return m_Dupes; }
453 bool ShowingSurfaceLegs() const { return m_Surface; }
455 bool ShowingColourKey() const { return m_ColourKey; }
456 bool ShowingScaleBar() const { return m_Scalebar; }
458 bool ShowingEntrances() const { return m_Entrances; }
459 bool ShowingFixedPts() const { return m_FixedPts; }
460 bool ShowingExportedPts() const { return m_ExportedPts; }
462 int GetNumEntrances() const;
463 int GetNumFixedPts() const;
464 int GetNumExportedPts() const;
466 void ToggleUndergroundLegs() {
467 ToggleFlag(&m_Legs, UPDATE_BLOBS_AND_CROSSES);
469 void SetSplaysMode(int mode) {
470 m_Splays = mode;
471 UpdateBlobs();
472 InvalidateList(LIST_UNDERGROUND_LEGS);
473 ForceRefresh();
475 void SetDupesMode(int mode) {
476 m_Dupes = mode;
477 UpdateBlobs();
478 InvalidateList(LIST_UNDERGROUND_LEGS);
479 ForceRefresh();
481 void ToggleSurfaceLegs() {
482 ToggleFlag(&m_Surface, UPDATE_BLOBS_AND_CROSSES);
484 void ToggleCompass() {
485 ToggleFlag(&m_Compass);
486 InvalidateList(LIST_SCALE_BAR);
488 void ToggleClino() {
489 ToggleFlag(&m_Clino);
490 InvalidateList(LIST_SCALE_BAR);
492 void ToggleScaleBar() { ToggleFlag(&m_Scalebar); }
493 void ToggleEntrances() { ToggleFlag(&m_Entrances, UPDATE_BLOBS); }
494 void ToggleFixedPts() { ToggleFlag(&m_FixedPts, UPDATE_BLOBS); }
495 void ToggleExportedPts() { ToggleFlag(&m_ExportedPts, UPDATE_BLOBS); }
496 void ToggleGrid() { ToggleFlag(&m_Grid); }
497 void ToggleCrosses() { ToggleFlag(&m_Crosses); }
498 void ToggleStationNames() { ToggleFlag(&m_Names); }
499 void ToggleOverlappingNames() { ToggleFlag(&m_OverlappingNames); }
500 void ToggleColourKey() { ToggleFlag(&m_ColourKey); }
501 void ToggleMetric() {
502 ToggleFlag(&m_Metric);
503 InvalidateList(LIST_DEPTH_KEY);
504 InvalidateList(LIST_LENGTH_KEY);
505 InvalidateList(LIST_SCALE_BAR);
507 void ToggleHitTestDebug() {
508 ToggleFlag(&m_HitTestDebug);
510 void ToggleRenderStats() {
511 ToggleFlag(&m_RenderStats);
513 void ToggleDegrees() {
514 ToggleFlag(&m_Degrees);
515 InvalidateList(LIST_GRADIENT_KEY);
517 void TogglePercent() { ToggleFlag(&m_Percent); }
518 void ToggleTubes() { ToggleFlag(&m_Tubes); }
519 void TogglePerspective() { GLACanvas::TogglePerspective(); ForceRefresh(); }
520 void ToggleSmoothShading();
521 bool DisplayingBoundingBox() const { return m_BoundingBox; }
522 void ToggleBoundingBox() { ToggleFlag(&m_BoundingBox); }
523 bool DisplayingTerrain() const { return m_Terrain; }
524 void ToggleTerrain();
525 void ToggleFatFinger();
527 bool GetMetric() const { return m_Metric; }
528 bool GetDegrees() const { return m_Degrees; }
529 bool GetPercent() const { return m_Percent; }
530 bool GetTubes() const { return m_Tubes; }
532 bool CheckHitTestGrid(const wxPoint& point, bool centre);
534 void ClearTreeSelection();
536 void Defaults();
538 void FullScreenMode();
540 bool IsFullScreen() const;
542 bool FullScreenModeShowingMenus() const;
544 void FullScreenModeShowMenus(bool show);
546 void DragFinished();
548 void SplitLineAcrossBands(int band, int band2,
549 const Vector3 &p, const Vector3 &q,
550 Double factor = 1.0);
551 int GetDepthColour(Double z) const;
552 Double GetDepthBoundaryBetweenBands(int a, int b) const;
553 void AddPolyline(const traverse & centreline);
554 void AddPolylineDepth(const traverse & centreline);
555 void AddPolylineDate(const traverse & centreline);
556 void AddPolylineError(const traverse & centreline);
557 void AddPolylineGradient(const traverse & centreline);
558 void AddPolylineLength(const traverse & centreline);
559 void AddQuadrilateral(const Vector3 &a, const Vector3 &b,
560 const Vector3 &c, const Vector3 &d);
561 void AddPolylineShadow(const traverse & centreline);
562 void AddQuadrilateralDepth(const Vector3 &a, const Vector3 &b,
563 const Vector3 &c, const Vector3 &d);
564 void AddQuadrilateralDate(const Vector3 &a, const Vector3 &b,
565 const Vector3 &c, const Vector3 &d);
566 void AddQuadrilateralError(const Vector3 &a, const Vector3 &b,
567 const Vector3 &c, const Vector3 &d);
568 void AddQuadrilateralGradient(const Vector3 &a, const Vector3 &b,
569 const Vector3 &c, const Vector3 &d);
570 void AddQuadrilateralLength(const Vector3 &a, const Vector3 &b,
571 const Vector3 &c, const Vector3 &d);
572 void MoveViewer(double forward, double up, double right);
574 void (GfxCore::* AddQuad)(const Vector3 &a, const Vector3 &b,
575 const Vector3 &c, const Vector3 &d);
576 void (GfxCore::* AddPoly)(const traverse & centreline);
578 PresentationMark GetView() const;
579 void SetView(const PresentationMark & p);
580 void PlayPres(double speed, bool change_speed = true);
581 int GetPresentationMode() const { return presentation_mode; }
582 double GetPresentationSpeed() const { return presentation_mode ? pres_speed : 0; }
584 void SetColourBy(int colour_by);
585 bool ExportMovie(const wxString & fnm);
586 void OnPrint(const wxString &filename, const wxString &title,
587 const wxString &datestamp, time_t datestamp_numeric,
588 const wxString &cs_proj,
589 bool close_after_print = false);
590 void OnExport(const wxString &filename, const wxString &title,
591 const wxString &datestamp, time_t datestamp_numeric,
592 const wxString &cs_proj);
593 void UpdateCursor(GfxCore::cursor new_cursor);
594 bool MeasuringLineActive() const;
596 bool HandleRClick(wxPoint point);
598 void InvalidateAllLists() {
599 for (int i = 0; i < LIST_LIMIT_; ++i) {
600 InvalidateList(i);
604 void SetZoomBox(wxPoint p1, wxPoint p2, bool centred, bool aspect);
606 void UnsetZoomBox() {
607 if (!zoombox.active()) return;
608 zoombox.unset();
609 ForceRefresh();
612 void ZoomBoxGo();
614 void parse_hgt_filename(const wxString & lc_name);
615 size_t parse_hdr(wxInputStream & is, unsigned long & skipbytes);
616 bool read_bil(wxInputStream & is, size_t size, unsigned long skipbytes);
617 bool LoadDEM(const wxString & file);
619 private:
620 DECLARE_EVENT_TABLE()
623 #endif