Cache PJ* for *fix
[survex.git] / src / gfxcore.h
blob758c8d3a0d13d07b312df5f2a7d32c7804e29d05
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_H_ERROR,
95 COLOUR_BY_V_ERROR,
96 COLOUR_BY_GRADIENT,
97 COLOUR_BY_LENGTH,
98 COLOUR_BY_SURVEY,
99 COLOUR_BY_STYLE,
100 COLOUR_BY_LIMIT_ // Leave this last.
103 enum {
104 UPDATE_NONE,
105 UPDATE_BLOBS,
106 UPDATE_BLOBS_AND_CROSSES
109 enum {
110 SHOW_HIDE,
111 SHOW_DASHED,
112 SHOW_FADED,
113 SHOW_NORMAL,
116 struct Split {
117 Vector3 vec;
118 glaCoord tx, ty;
120 Split(const Vector3& vec_, glaCoord tx_, glaCoord ty_)
121 : vec(vec_), tx(tx_), ty(ty_) { }
124 // It's pointless to redraw the screen as often as we can on a fast machine,
125 // since the display hardware will only update so many times per second.
126 // This is the maximum framerate we'll redraw at.
127 const int MAX_FRAMERATE = 50;
129 class GfxCore : public GLACanvas {
130 Double m_Scale;
131 Double initial_scale;
132 int m_ScaleBarWidth;
134 typedef enum {
135 LIST_COMPASS,
136 LIST_CLINO,
137 LIST_CLINO_BACK,
138 LIST_SCALE_BAR,
139 LIST_DEPTH_KEY,
140 LIST_DATE_KEY,
141 LIST_ERROR_KEY,
142 LIST_GRADIENT_KEY,
143 LIST_LENGTH_KEY,
144 LIST_STYLE_KEY,
145 LIST_UNDERGROUND_LEGS,
146 LIST_TUBES,
147 LIST_SURFACE_LEGS,
148 LIST_BLOBS,
149 LIST_CROSSES,
150 LIST_GRID,
151 LIST_SHADOW,
152 LIST_TERRAIN,
153 LIST_LIMIT_ // Leave this last.
154 } drawing_list;
156 static const int NUM_COLOUR_BANDS = 13;
158 void SetPanBase() {
159 base_pan = m_PanAngle;
160 base_pan_time = timer.Time() - (1000 / MAX_FRAMERATE);
163 void SetTiltBase() {
164 base_tilt = m_TiltAngle;
165 base_tilt_time = timer.Time() - (1000 / MAX_FRAMERATE);
168 int GetCompassWidth() const;
169 int GetClinoWidth() const;
171 public:
172 typedef enum {
173 CURSOR_DEFAULT,
174 CURSOR_POINTING_HAND,
175 CURSOR_DRAGGING_HAND,
176 CURSOR_HORIZONTAL_RESIZE,
177 CURSOR_ROTATE_HORIZONTALLY,
178 CURSOR_ROTATE_VERTICALLY,
179 CURSOR_ROTATE_EITHER_WAY,
180 CURSOR_ZOOM,
181 CURSOR_ZOOM_ROTATE
182 } cursor;
184 private:
185 GUIControl* m_Control;
186 char* m_LabelGrid;
187 MainFrm* m_Parent;
188 bool m_DoneFirstShow;
189 Double m_TiltAngle;
190 Double m_PanAngle;
191 bool m_Rotating;
192 Double m_RotationStep;
193 int m_SwitchingTo;
194 bool m_Crosses;
195 bool m_Legs;
196 int m_Splays;
197 int m_Dupes;
198 bool m_Names;
199 bool m_Scalebar;
200 bool m_ColourKey;
201 bool m_OverlappingNames;
202 bool m_Compass;
203 bool m_Clino;
204 bool m_Tubes;
205 int m_ColourBy;
206 int error_type;
208 bool m_HaveData;
209 bool m_HaveTerrain;
210 bool m_MouseOutsideCompass;
211 bool m_MouseOutsideElev;
212 bool m_Surface;
213 bool m_Entrances;
214 bool m_FixedPts;
215 bool m_ExportedPts;
216 bool m_Grid;
217 bool m_BoundingBox;
218 bool m_Terrain;
220 bool m_Degrees;
221 bool m_Metric;
222 bool m_Percent;
224 bool m_HitTestDebug;
225 bool m_RenderStats;
227 list<LabelInfo*> *m_PointGrid;
228 bool m_HitTestGridValid;
230 LabelInfo temp_here;
231 const LabelInfo * m_here;
232 const LabelInfo * m_there;
233 wxString highlighted_survey;
235 wxStopWatch timer;
236 long base_tilt_time;
237 long base_pan_time;
238 Double base_tilt;
239 Double base_pan;
241 GLAPen m_Pens[NUM_COLOUR_BANDS + 1];
243 #define PLAYING 1
244 int presentation_mode; // for now, 0 => off, PLAYING => continuous play
245 bool pres_reverse;
246 double pres_speed;
247 PresentationMark next_mark;
248 double next_mark_time;
249 double this_mark_total;
251 MovieMaker * movie;
253 cursor current_cursor;
255 int sqrd_measure_threshold;
257 // The legends for each entry in the colour key.
258 wxString key_legends[NUM_COLOUR_BANDS];
260 wxPoint key_lowerleft[COLOUR_BY_LIMIT_];
262 ZoomBox zoombox;
264 // Copied from parent, so we can adjust view when reloading the same
265 // file with the view restricted.
266 Vector3 offsets;
268 // DEM:
269 unsigned short * dem;
270 unsigned long dem_width, dem_height;
271 double o_x, o_y, step_x, step_y;
272 long nodata_value;
273 bool bigendian;
274 long last_time;
275 size_t n_tris;
277 void PlaceVertexWithColour(const Vector3 &v, Double factor = 1.0);
278 void PlaceVertexWithColour(const Vector3 & v,
279 glaTexCoord tex_x, glaTexCoord tex_y,
280 Double factor);
281 void SetDepthColour(Double z, Double factor);
282 void PlaceVertexWithDepthColour(const Vector3 & v, Double factor = 1.0);
283 void PlaceVertexWithDepthColour(const Vector3 & v,
284 glaTexCoord tex_x, glaTexCoord tex_y,
285 Double factor);
287 void SetColourFrom01(double how_far, Double factor);
289 void SetColourFromDate(int date, Double factor);
290 void SetColourFromError(double E, Double factor);
291 void SetColourFromGradient(double angle, Double factor);
292 void SetColourFromLength(double len, Double factor);
293 void SetColourFromSurvey(const wxString& survey);
294 void SetColourFromSurveyStation(const wxString& survey, Double factor);
296 int GetClinoOffset() const;
297 void DrawTick(int angle_cw);
298 void DrawArrow(gla_colour col1, gla_colour col2);
300 void SkinPassage(vector<XSect> & centreline);
302 virtual void GenerateList(unsigned int l);
303 void GenerateDisplayList(bool surface);
304 void GenerateDisplayListTubes();
305 void DrawTerrainTriangle(const Vector3 & a, const Vector3 & b, const Vector3 & c);
306 void DrawTerrain();
307 void GenerateDisplayListShadow();
308 void GenerateBlobsDisplayList();
310 void DrawIndicators();
312 void TryToFreeArrays();
313 void FirstShow();
315 void DrawScaleBar();
316 void DrawColourKey(int num_bands, const wxString & other, const wxString & units);
317 void DrawDepthKey();
318 void DrawDateKey();
319 void DrawErrorKey();
320 void DrawGradientKey();
321 void DrawLengthKey();
322 void DrawStyleKey();
323 void DrawCompass();
324 void DrawClino();
325 void DrawClinoBack();
326 void Draw2dIndicators();
327 void DrawGrid();
329 void NattyDrawNames();
330 void SimpleDrawNames();
332 void DefaultParameters();
334 void Repaint();
336 void CreateHitTestGrid();
338 int GetCompassXPosition() const;
339 int GetClinoXPosition() const;
340 int GetIndicatorYPosition() const;
341 int GetIndicatorRadius() const;
343 void ToggleFlag(bool* flag, int update = UPDATE_NONE);
345 const GLAPen& GetPen(int band) const {
346 assert(band >= 0 && band < NUM_COLOUR_BANDS);
347 return m_Pens[band];
350 const GLAPen& GetSurfacePen() const { return m_Pens[NUM_COLOUR_BANDS]; }
352 int GetNumColourBands() const { return NUM_COLOUR_BANDS; }
354 void DrawShadowedBoundingBox();
355 void DrawBoundingBox();
357 public:
358 GfxCore(MainFrm* parent, wxWindow* parent_window, GUIControl* control);
359 ~GfxCore();
361 void Initialise(bool same_file);
363 void UpdateBlobs();
364 void ForceRefresh();
366 void RefreshLine(const Point* a, const Point* b, const Point* c);
368 void SetHereSurvey(const wxString& survey) {
369 if (survey != highlighted_survey) {
370 highlighted_survey = survey;
371 ForceRefresh();
375 void HighlightSurvey();
377 void ZoomToSurvey(const wxString& survey);
379 void SetHereFromTree(const LabelInfo * p);
381 void SetHere(const LabelInfo * p = NULL);
382 void SetThere(const LabelInfo * p = NULL);
384 const LabelInfo* GetThere() const { return m_there; }
386 void CentreOn(const Point &p);
388 void TranslateCave(int dx, int dy);
389 void TiltCave(Double tilt_angle);
390 void TurnCave(Double angle);
391 void TurnCaveTo(Double angle);
393 void OnPaint(wxPaintEvent&);
394 void OnSize(wxSizeEvent& event);
395 void OnIdle(wxIdleEvent& event);
397 void OnMouseMove(wxMouseEvent& event) { m_Control->OnMouseMove(event); }
398 void OnLeaveWindow(wxMouseEvent& event);
400 void OnLButtonDown(wxMouseEvent& event) { SetFocus(); m_Control->OnLButtonDown(event); }
401 void OnLButtonUp(wxMouseEvent& event) { m_Control->OnLButtonUp(event); }
402 void OnMButtonDown(wxMouseEvent& event) { SetFocus(); m_Control->OnMButtonDown(event); }
403 void OnMButtonUp(wxMouseEvent& event) { m_Control->OnMButtonUp(event); }
404 void OnRButtonDown(wxMouseEvent& event) { SetFocus(); m_Control->OnRButtonDown(event); }
405 void OnRButtonUp(wxMouseEvent& event) { m_Control->OnRButtonUp(event); }
406 void OnMouseWheel(wxMouseEvent& event) { SetFocus(); m_Control->OnMouseWheel(event); }
407 void OnKeyPress(wxKeyEvent &event) { m_Control->OnKeyPress(event); }
409 void Animate();
410 bool Animating() const {
411 return m_Rotating || m_SwitchingTo || presentation_mode != 0;
414 void ClearCoords();
415 void SetCoords(wxPoint);
417 // Determine whether the compass is currently shown.
418 bool ShowingCompass() const { return m_Compass; }
419 // Determine whether the clino is currently shown.
420 bool ShowingClino() const { return m_Clino; }
422 bool PointWithinCompass(wxPoint point) const;
423 bool PointWithinClino(wxPoint point) const;
424 bool PointWithinScaleBar(wxPoint point) const;
425 bool PointWithinColourKey(wxPoint point) const;
427 void SetCompassFromPoint(wxPoint point);
428 void SetClinoFromPoint(wxPoint point);
429 void SetScaleBarFromOffset(wxCoord dx);
431 void RedrawIndicators();
433 void StartRotation();
434 void ToggleRotation();
435 void StopRotation();
436 bool IsExtendedElevation() const;
437 void ReverseRotation();
438 void RotateSlower(bool accel);
439 void RotateFaster(bool accel);
441 void SwitchToElevation();
442 void SwitchToPlan();
444 void SetViewTo(Double xmin, Double xmax, Double ymin, Double ymax, Double zmin, Double zmax);
446 double GetCompassValue() const { return m_PanAngle; }
447 bool ShowingPlan() const;
448 bool ShowingElevation() const;
449 bool ShowingMeasuringLine() const;
450 bool HereIsReal() const { return m_here && m_here != &temp_here; }
452 bool CanRaiseViewpoint() const;
453 bool CanLowerViewpoint() const;
455 bool IsRotating() const { return m_Rotating; }
456 bool HasData() const { return m_DoneFirstShow && m_HaveData; }
457 bool HasTerrain() const { return m_DoneFirstShow && m_HaveTerrain; }
458 bool HasDepth() const;
459 bool HasErrorInformation() const;
460 bool HasDateInformation() const;
462 double GetScale() const { return m_Scale; }
463 void SetScale(Double scale);
465 bool ShowingStationNames() const { return m_Names; }
466 bool ShowingOverlappingNames() const { return m_OverlappingNames; }
467 bool ShowingCrosses() const { return m_Crosses; }
468 bool ShowingGrid() const { return m_Grid; }
470 int ColouringBy() const { return m_ColourBy; }
472 bool HasUndergroundLegs() const;
473 bool HasSplays() const;
474 bool HasDupes() const;
475 bool HasSurfaceLegs() const;
476 bool HasTubes() const;
478 bool ShowingUndergroundLegs() const { return m_Legs; }
479 int ShowingSplaysMode() const { return m_Splays; }
480 int ShowingDupesMode() const { return m_Dupes; }
481 bool ShowingSurfaceLegs() const { return m_Surface; }
483 bool ShowingColourKey() const { return m_ColourKey; }
484 bool ShowingScaleBar() const { return m_Scalebar; }
486 bool ShowingEntrances() const { return m_Entrances; }
487 bool ShowingFixedPts() const { return m_FixedPts; }
488 bool ShowingExportedPts() const { return m_ExportedPts; }
490 int GetNumEntrances() const;
491 int GetNumFixedPts() const;
492 int GetNumExportedPts() const;
494 void ToggleUndergroundLegs() {
495 ToggleFlag(&m_Legs, UPDATE_BLOBS_AND_CROSSES);
497 void SetSplaysMode(int mode) {
498 m_Splays = mode;
499 UpdateBlobs();
500 InvalidateList(LIST_SURFACE_LEGS);
501 InvalidateList(LIST_UNDERGROUND_LEGS);
502 InvalidateList(LIST_CROSSES);
503 m_HitTestGridValid = false;
504 ForceRefresh();
506 void SetDupesMode(int mode) {
507 m_Dupes = mode;
508 UpdateBlobs();
509 InvalidateList(LIST_SURFACE_LEGS);
510 InvalidateList(LIST_UNDERGROUND_LEGS);
511 ForceRefresh();
513 void ToggleSurfaceLegs() {
514 ToggleFlag(&m_Surface, UPDATE_BLOBS_AND_CROSSES);
516 void ToggleCompass() {
517 ToggleFlag(&m_Compass);
518 InvalidateList(LIST_SCALE_BAR);
520 void ToggleClino() {
521 ToggleFlag(&m_Clino);
522 InvalidateList(LIST_SCALE_BAR);
524 void ToggleScaleBar() { ToggleFlag(&m_Scalebar); }
525 void ToggleEntrances() { ToggleFlag(&m_Entrances, UPDATE_BLOBS); }
526 void ToggleFixedPts() { ToggleFlag(&m_FixedPts, UPDATE_BLOBS); }
527 void ToggleExportedPts() { ToggleFlag(&m_ExportedPts, UPDATE_BLOBS); }
528 void ToggleGrid() { ToggleFlag(&m_Grid); }
529 void ToggleCrosses() { ToggleFlag(&m_Crosses); }
530 void ToggleStationNames() { ToggleFlag(&m_Names); }
531 void ToggleOverlappingNames() { ToggleFlag(&m_OverlappingNames); }
532 void ToggleColourKey() { ToggleFlag(&m_ColourKey); }
533 void ToggleMetric() {
534 ToggleFlag(&m_Metric);
535 InvalidateList(LIST_DEPTH_KEY);
536 InvalidateList(LIST_LENGTH_KEY);
537 InvalidateList(LIST_SCALE_BAR);
539 void ToggleHitTestDebug() {
540 ToggleFlag(&m_HitTestDebug);
542 void ToggleRenderStats() {
543 ToggleFlag(&m_RenderStats);
545 void ToggleDegrees() {
546 ToggleFlag(&m_Degrees);
547 InvalidateList(LIST_GRADIENT_KEY);
549 void TogglePercent() { ToggleFlag(&m_Percent); }
550 void ToggleTubes() { ToggleFlag(&m_Tubes); }
551 void TogglePerspective() { GLACanvas::TogglePerspective(); ForceRefresh(); }
552 void ToggleSmoothShading();
553 bool DisplayingBoundingBox() const { return m_BoundingBox; }
554 void ToggleBoundingBox() { ToggleFlag(&m_BoundingBox); }
555 bool DisplayingTerrain() const { return m_Terrain; }
556 void ToggleTerrain();
557 void ToggleFatFinger();
558 void ToggleTextured() {
559 GLACanvas::ToggleTextured();
560 ForceRefresh();
563 bool GetMetric() const { return m_Metric; }
564 bool GetDegrees() const { return m_Degrees; }
565 bool GetPercent() const { return m_Percent; }
566 bool GetTubes() const { return m_Tubes; }
568 bool CheckHitTestGrid(const wxPoint& point, bool centre);
570 void ClearTreeSelection();
572 void Defaults();
574 void FullScreenMode();
576 bool IsFullScreen() const;
578 bool FullScreenModeShowingMenus() const;
580 void FullScreenModeShowMenus(bool show);
582 void DragFinished();
584 void SplitLineAcrossBands(int band, int band2,
585 const Vector3 &p, const Vector3 &q,
586 Double factor = 1.0);
587 void SplitPolyAcrossBands(vector<vector<Split>>& splits,
588 int band, int band2,
589 const Vector3 &p, const Vector3 &q,
590 glaTexCoord ptx, glaTexCoord pty,
591 glaTexCoord w, glaTexCoord h);
592 int GetDepthColour(Double z) const;
593 Double GetDepthBoundaryBetweenBands(int a, int b) const;
594 void AddPolyline(const traverse & centreline);
595 void AddPolylineDepth(const traverse & centreline);
596 void AddPolylineDate(const traverse & centreline);
597 void AddPolylineError(const traverse & centreline);
598 void AddPolylineGradient(const traverse & centreline);
599 void AddPolylineLength(const traverse & centreline);
600 void AddPolylineSurvey(const traverse & centreline);
601 void AddPolylineStyle(const traverse & centreline);
602 void AddQuadrilateral(const Vector3 &a, const Vector3 &b,
603 const Vector3 &c, const Vector3 &d);
604 void AddPolylineShadow(const traverse & centreline);
605 void AddQuadrilateralDepth(const Vector3 &a, const Vector3 &b,
606 const Vector3 &c, const Vector3 &d);
607 void AddQuadrilateralDate(const Vector3 &a, const Vector3 &b,
608 const Vector3 &c, const Vector3 &d);
609 void AddQuadrilateralError(const Vector3 &a, const Vector3 &b,
610 const Vector3 &c, const Vector3 &d);
611 void AddQuadrilateralGradient(const Vector3 &a, const Vector3 &b,
612 const Vector3 &c, const Vector3 &d);
613 void AddQuadrilateralLength(const Vector3 &a, const Vector3 &b,
614 const Vector3 &c, const Vector3 &d);
615 void AddQuadrilateralSurvey(const Vector3 &a, const Vector3 &b,
616 const Vector3 &c, const Vector3 &d);
617 void MoveViewer(double forward, double up, double right);
619 void (GfxCore::* AddQuad)(const Vector3 &a, const Vector3 &b,
620 const Vector3 &c, const Vector3 &d);
621 void (GfxCore::* AddPoly)(const traverse & centreline);
623 PresentationMark GetView() const;
624 void SetView(const PresentationMark & p);
625 void PlayPres(double speed, bool change_speed = true);
626 int GetPresentationMode() const { return presentation_mode; }
627 double GetPresentationSpeed() const { return presentation_mode ? pres_speed : 0; }
629 void SetColourBy(int colour_by);
630 bool ExportMovie(const wxString & fnm);
631 void OnPrint(const wxString &filename, const wxString &title,
632 const wxString &datestamp,
633 bool close_after_print = false);
634 void OnExport(const wxString &filename, const wxString &title,
635 const wxString &datestamp);
636 void UpdateCursor(GfxCore::cursor new_cursor);
637 bool MeasuringLineActive() const;
639 bool HandleRClick(wxPoint point);
641 void InvalidateAllLists() {
642 for (int i = 0; i < LIST_LIMIT_; ++i) {
643 InvalidateList(i);
647 void SetZoomBox(wxPoint p1, wxPoint p2, bool centred, bool aspect);
649 void UnsetZoomBox() {
650 if (!zoombox.active()) return;
651 zoombox.unset();
652 ForceRefresh();
655 void ZoomBoxGo();
657 void parse_hgt_filename(const wxString & lc_name);
658 size_t parse_hdr(wxInputStream & is, unsigned long & skipbytes);
659 bool read_bil(wxInputStream & is, size_t size, unsigned long skipbytes);
660 bool LoadDEM(const wxString & file);
662 private:
663 DECLARE_EVENT_TABLE()
666 #endif