Fix coding style
[survex.git] / src / gfxcore.h
blob992af5fd1b72087a857b435c39b7b122a6865727
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.
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_SURVEY,
97 COLOUR_BY_LIMIT_ // Leave this last.
100 enum {
101 UPDATE_NONE,
102 UPDATE_BLOBS,
103 UPDATE_BLOBS_AND_CROSSES
106 enum {
107 SHOW_HIDE,
108 SHOW_DASHED,
109 SHOW_FADED,
110 SHOW_NORMAL,
113 struct Split {
114 Vector3 vec;
115 glaCoord tx, ty;
117 Split(const Vector3& vec_, glaCoord tx_, glaCoord ty_)
118 : vec(vec_), tx(tx_), ty(ty_) { }
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.
124 const int MAX_FRAMERATE = 50;
126 class GfxCore : public GLACanvas {
127 Double m_Scale;
128 Double initial_scale;
129 int m_ScaleBarWidth;
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;
152 static const int NUM_COLOUR_BANDS = 13;
154 void SetPanBase() {
155 base_pan = m_PanAngle;
156 base_pan_time = timer.Time() - (1000 / MAX_FRAMERATE);
159 void SetTiltBase() {
160 base_tilt = m_TiltAngle;
161 base_tilt_time = timer.Time() - (1000 / MAX_FRAMERATE);
164 int GetCompassWidth() const;
165 int GetClinoWidth() const;
167 public:
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;
180 private:
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;
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;
215 bool m_Degrees;
216 bool m_Metric;
217 bool m_Percent;
219 bool m_HitTestDebug;
220 bool m_RenderStats;
222 list<LabelInfo*> *m_PointGrid;
223 bool m_HitTestGridValid;
225 LabelInfo temp_here;
226 const LabelInfo * m_here;
227 const LabelInfo * m_there;
228 wxString highlighted_survey;
230 wxStopWatch timer;
231 long base_tilt_time;
232 long base_pan_time;
233 Double base_tilt;
234 Double base_pan;
236 GLAPen m_Pens[NUM_COLOUR_BANDS + 1];
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;
246 MovieMaker * movie;
248 cursor current_cursor;
250 int sqrd_measure_threshold;
252 // The legends for each entry in the colour key.
253 wxString key_legends[NUM_COLOUR_BANDS];
255 wxPoint key_lowerleft[COLOUR_BY_LIMIT_];
257 ZoomBox zoombox;
259 // Copied from parent, so we can adjust view when reloading the same
260 // file with the view restricted.
261 Vector3 offsets;
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;
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);
282 void SetColourFrom01(double how_far, Double factor);
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);
291 int GetClinoOffset() const;
292 void DrawTick(int angle_cw);
293 void DrawArrow(gla_colour col1, gla_colour col2);
295 void SkinPassage(vector<XSect> & centreline, bool draw = true);
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();
305 void DrawIndicators();
307 void TryToFreeArrays();
308 void FirstShow();
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();
323 void NattyDrawNames();
324 void SimpleDrawNames();
326 void DefaultParameters();
328 void Repaint();
330 void CreateHitTestGrid();
332 int GetCompassXPosition() const;
333 int GetClinoXPosition() const;
334 int GetIndicatorYPosition() const;
335 int GetIndicatorRadius() const;
337 void ToggleFlag(bool* flag, int update = UPDATE_NONE);
339 const GLAPen& GetPen(int band) const {
340 assert(band >= 0 && band < NUM_COLOUR_BANDS);
341 return m_Pens[band];
344 const GLAPen& GetSurfacePen() const { return m_Pens[NUM_COLOUR_BANDS]; }
346 int GetNumColourBands() const { return NUM_COLOUR_BANDS; }
348 void DrawShadowedBoundingBox();
349 void DrawBoundingBox();
351 public:
352 GfxCore(MainFrm* parent, wxWindow* parent_window, GUIControl* control);
353 ~GfxCore();
355 void Initialise(bool same_file);
357 void UpdateBlobs();
358 void ForceRefresh();
360 void RefreshLine(const Point* a, const Point* b, const Point* c);
362 void SetHereSurvey(const wxString& survey) {
363 if (survey != highlighted_survey) {
364 highlighted_survey = survey;
365 ForceRefresh();
369 void HighlightSurvey();
371 void ZoomToSurvey(const wxString& survey);
373 void SetHereFromTree(const LabelInfo * p);
375 void SetHere(const LabelInfo * p = NULL);
376 void SetThere(const LabelInfo * p = NULL);
378 const LabelInfo* GetThere() const { return m_there; }
380 void CentreOn(const Point &p);
382 void TranslateCave(int dx, int dy);
383 void TiltCave(Double tilt_angle);
384 void TurnCave(Double angle);
385 void TurnCaveTo(Double angle);
387 void OnPaint(wxPaintEvent&);
388 void OnSize(wxSizeEvent& event);
389 void OnIdle(wxIdleEvent& event);
391 void OnMouseMove(wxMouseEvent& event) { m_Control->OnMouseMove(event); }
392 void OnLeaveWindow(wxMouseEvent& event);
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); }
403 void Animate();
404 bool Animating() const {
405 return m_Rotating || m_SwitchingTo || presentation_mode != 0;
408 void ClearCoords();
409 void SetCoords(wxPoint);
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; }
416 bool PointWithinCompass(wxPoint point) const;
417 bool PointWithinClino(wxPoint point) const;
418 bool PointWithinScaleBar(wxPoint point) const;
419 bool PointWithinColourKey(wxPoint point) const;
421 void SetCompassFromPoint(wxPoint point);
422 void SetClinoFromPoint(wxPoint point);
423 void SetScaleBarFromOffset(wxCoord dx);
425 void RedrawIndicators();
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);
435 void SwitchToElevation();
436 void SwitchToPlan();
438 void SetViewTo(Double xmin, Double xmax, Double ymin, Double ymax, Double zmin, Double zmax);
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; }
446 bool CanRaiseViewpoint() const;
447 bool CanLowerViewpoint() const;
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;
456 double GetScale() const { return m_Scale; }
457 void SetScale(Double scale);
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; }
464 int ColouringBy() const { return m_ColourBy; }
466 bool HasUndergroundLegs() const;
467 bool HasSplays() const;
468 bool HasDupes() const;
469 bool HasSurfaceLegs() const;
470 bool HasTubes() const;
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; }
477 bool ShowingColourKey() const { return m_ColourKey; }
478 bool ShowingScaleBar() const { return m_Scalebar; }
480 bool ShowingEntrances() const { return m_Entrances; }
481 bool ShowingFixedPts() const { return m_FixedPts; }
482 bool ShowingExportedPts() const { return m_ExportedPts; }
484 int GetNumEntrances() const;
485 int GetNumFixedPts() const;
486 int GetNumExportedPts() const;
488 void ToggleUndergroundLegs() {
489 ToggleFlag(&m_Legs, UPDATE_BLOBS_AND_CROSSES);
491 void SetSplaysMode(int mode) {
492 m_Splays = mode;
493 UpdateBlobs();
494 InvalidateList(LIST_SURFACE_LEGS);
495 InvalidateList(LIST_UNDERGROUND_LEGS);
496 ForceRefresh();
498 void SetDupesMode(int mode) {
499 m_Dupes = mode;
500 UpdateBlobs();
501 InvalidateList(LIST_SURFACE_LEGS);
502 InvalidateList(LIST_UNDERGROUND_LEGS);
503 ForceRefresh();
505 void ToggleSurfaceLegs() {
506 ToggleFlag(&m_Surface, UPDATE_BLOBS_AND_CROSSES);
508 void ToggleCompass() {
509 ToggleFlag(&m_Compass);
510 InvalidateList(LIST_SCALE_BAR);
512 void ToggleClino() {
513 ToggleFlag(&m_Clino);
514 InvalidateList(LIST_SCALE_BAR);
516 void ToggleScaleBar() { ToggleFlag(&m_Scalebar); }
517 void ToggleEntrances() { ToggleFlag(&m_Entrances, UPDATE_BLOBS); }
518 void ToggleFixedPts() { ToggleFlag(&m_FixedPts, UPDATE_BLOBS); }
519 void ToggleExportedPts() { ToggleFlag(&m_ExportedPts, UPDATE_BLOBS); }
520 void ToggleGrid() { ToggleFlag(&m_Grid); }
521 void ToggleCrosses() { ToggleFlag(&m_Crosses); }
522 void ToggleStationNames() { ToggleFlag(&m_Names); }
523 void ToggleOverlappingNames() { ToggleFlag(&m_OverlappingNames); }
524 void ToggleColourKey() { ToggleFlag(&m_ColourKey); }
525 void ToggleMetric() {
526 ToggleFlag(&m_Metric);
527 InvalidateList(LIST_DEPTH_KEY);
528 InvalidateList(LIST_LENGTH_KEY);
529 InvalidateList(LIST_SCALE_BAR);
531 void ToggleHitTestDebug() {
532 ToggleFlag(&m_HitTestDebug);
534 void ToggleRenderStats() {
535 ToggleFlag(&m_RenderStats);
537 void ToggleDegrees() {
538 ToggleFlag(&m_Degrees);
539 InvalidateList(LIST_GRADIENT_KEY);
541 void TogglePercent() { ToggleFlag(&m_Percent); }
542 void ToggleTubes() { ToggleFlag(&m_Tubes); }
543 void TogglePerspective() { GLACanvas::TogglePerspective(); ForceRefresh(); }
544 void ToggleSmoothShading();
545 bool DisplayingBoundingBox() const { return m_BoundingBox; }
546 void ToggleBoundingBox() { ToggleFlag(&m_BoundingBox); }
547 bool DisplayingTerrain() const { return m_Terrain; }
548 void ToggleTerrain();
549 void ToggleFatFinger();
550 void ToggleTextured() {
551 GLACanvas::ToggleTextured();
552 ForceRefresh();
555 bool GetMetric() const { return m_Metric; }
556 bool GetDegrees() const { return m_Degrees; }
557 bool GetPercent() const { return m_Percent; }
558 bool GetTubes() const { return m_Tubes; }
560 bool CheckHitTestGrid(const wxPoint& point, bool centre);
562 void ClearTreeSelection();
564 void Defaults();
566 void FullScreenMode();
568 bool IsFullScreen() const;
570 bool FullScreenModeShowingMenus() const;
572 void FullScreenModeShowMenus(bool show);
574 void DragFinished();
576 void SplitLineAcrossBands(int band, int band2,
577 const Vector3 &p, const Vector3 &q,
578 Double factor = 1.0);
579 void SplitPolyAcrossBands(vector<vector<Split>>& splits,
580 int band, int band2,
581 const Vector3 &p, const Vector3 &q,
582 glaTexCoord ptx, glaTexCoord pty,
583 glaTexCoord w, glaTexCoord h);
584 int GetDepthColour(Double z) const;
585 Double GetDepthBoundaryBetweenBands(int a, int b) const;
586 void AddPolyline(const traverse & centreline);
587 void AddPolylineDepth(const traverse & centreline);
588 void AddPolylineDate(const traverse & centreline);
589 void AddPolylineError(const traverse & centreline);
590 void AddPolylineGradient(const traverse & centreline);
591 void AddPolylineLength(const traverse & centreline);
592 void AddPolylineSurvey(const traverse & centreline);
593 void AddQuadrilateral(const Vector3 &a, const Vector3 &b,
594 const Vector3 &c, const Vector3 &d);
595 void AddPolylineShadow(const traverse & centreline);
596 void AddQuadrilateralDepth(const Vector3 &a, const Vector3 &b,
597 const Vector3 &c, const Vector3 &d);
598 void AddQuadrilateralDate(const Vector3 &a, const Vector3 &b,
599 const Vector3 &c, const Vector3 &d);
600 void AddQuadrilateralError(const Vector3 &a, const Vector3 &b,
601 const Vector3 &c, const Vector3 &d);
602 void AddQuadrilateralGradient(const Vector3 &a, const Vector3 &b,
603 const Vector3 &c, const Vector3 &d);
604 void AddQuadrilateralLength(const Vector3 &a, const Vector3 &b,
605 const Vector3 &c, const Vector3 &d);
606 void AddQuadrilateralSurvey(const Vector3 &a, const Vector3 &b,
607 const Vector3 &c, const Vector3 &d);
608 void MoveViewer(double forward, double up, double right);
610 void (GfxCore::* AddQuad)(const Vector3 &a, const Vector3 &b,
611 const Vector3 &c, const Vector3 &d);
612 void (GfxCore::* AddPoly)(const traverse & centreline);
614 PresentationMark GetView() const;
615 void SetView(const PresentationMark & p);
616 void PlayPres(double speed, bool change_speed = true);
617 int GetPresentationMode() const { return presentation_mode; }
618 double GetPresentationSpeed() const { return presentation_mode ? pres_speed : 0; }
620 void SetColourBy(int colour_by);
621 bool ExportMovie(const wxString & fnm);
622 void OnPrint(const wxString &filename, const wxString &title,
623 const wxString &datestamp,
624 bool close_after_print = false);
625 void OnExport(const wxString &filename, const wxString &title,
626 const wxString &datestamp);
627 void UpdateCursor(GfxCore::cursor new_cursor);
628 bool MeasuringLineActive() const;
630 bool HandleRClick(wxPoint point);
632 void InvalidateAllLists() {
633 for (int i = 0; i < LIST_LIMIT_; ++i) {
634 InvalidateList(i);
638 void SetZoomBox(wxPoint p1, wxPoint p2, bool centred, bool aspect);
640 void UnsetZoomBox() {
641 if (!zoombox.active()) return;
642 zoombox.unset();
643 ForceRefresh();
646 void ZoomBoxGo();
648 void parse_hgt_filename(const wxString & lc_name);
649 size_t parse_hdr(wxInputStream & is, unsigned long & skipbytes);
650 bool read_bil(wxInputStream & is, size_t size, unsigned long skipbytes);
651 bool LoadDEM(const wxString & file);
653 private:
654 DECLARE_EVENT_TABLE()
657 #endif