4 // Core drawing code for Aven.
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
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
32 #include "img_hosted.h"
34 #include "guicontrol.h"
35 #include "labelinfo.h"
53 class PresentationMark
: public Point
{
55 Double angle
, tilt_angle
;
58 PresentationMark() : Point(), angle(0), tilt_angle(0), scale(0), time(0)
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_
),
65 bool is_valid() const { return scale
> 0; }
75 bool active() const { return x1
!= INT_MAX
; }
77 void set(const wxPoint
& p1
, const wxPoint
& p2
) {
100 COLOUR_BY_LIMIT_
// Leave this last.
106 UPDATE_BLOBS_AND_CROSSES
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
{
131 Double initial_scale
;
145 LIST_UNDERGROUND_LEGS
,
153 LIST_LIMIT_
// Leave this last.
156 static const int NUM_COLOUR_BANDS
= 13;
159 base_pan
= m_PanAngle
;
160 base_pan_time
= timer
.Time() - (1000 / MAX_FRAMERATE
);
164 base_tilt
= m_TiltAngle
;
165 base_tilt_time
= timer
.Time() - (1000 / MAX_FRAMERATE
);
168 int GetCompassWidth() const;
169 int GetClinoWidth() const;
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
,
185 GUIControl
* m_Control
;
188 bool m_DoneFirstShow
;
192 Double m_RotationStep
;
201 bool m_OverlappingNames
;
210 bool m_MouseOutsideCompass
;
211 bool m_MouseOutsideElev
;
227 list
<LabelInfo
*> *m_PointGrid
;
228 bool m_HitTestGridValid
;
231 const LabelInfo
* m_here
;
232 const LabelInfo
* m_there
;
233 wxString highlighted_survey
;
241 GLAPen m_Pens
[NUM_COLOUR_BANDS
+ 1];
244 int presentation_mode
; // for now, 0 => off, PLAYING => continuous play
247 PresentationMark next_mark
;
248 double next_mark_time
;
249 double this_mark_total
;
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_
];
264 // Copied from parent, so we can adjust view when reloading the same
265 // file with the view restricted.
269 unsigned short * dem
;
270 unsigned long dem_width
, dem_height
;
271 double o_x
, o_y
, step_x
, step_y
;
277 void PlaceVertexWithColour(const Vector3
&v
, Double factor
= 1.0);
278 void PlaceVertexWithColour(const Vector3
& v
,
279 glaTexCoord tex_x
, glaTexCoord tex_y
,
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
,
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
);
307 void GenerateDisplayListShadow();
308 void GenerateBlobsDisplayList();
310 void DrawIndicators();
312 void TryToFreeArrays();
316 void DrawColourKey(int num_bands
, const wxString
& other
, const wxString
& units
);
320 void DrawGradientKey();
321 void DrawLengthKey();
325 void DrawClinoBack();
326 void Draw2dIndicators();
329 void NattyDrawNames();
330 void SimpleDrawNames();
332 void DefaultParameters();
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
);
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();
358 GfxCore(MainFrm
* parent
, wxWindow
* parent_window
, GUIControl
* control
);
361 void Initialise(bool same_file
);
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
;
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
) { ScaleMouseEvent(event
); m_Control
->OnMouseMove(event
); }
398 void OnLeaveWindow(wxMouseEvent
& event
);
400 void OnLButtonDown(wxMouseEvent
& event
) { ScaleMouseEvent(event
); SetFocus(); m_Control
->OnLButtonDown(event
); }
401 void OnLButtonUp(wxMouseEvent
& event
) { ScaleMouseEvent(event
); m_Control
->OnLButtonUp(event
); }
402 void OnMButtonDown(wxMouseEvent
& event
) { ScaleMouseEvent(event
); SetFocus(); m_Control
->OnMButtonDown(event
); }
403 void OnMButtonUp(wxMouseEvent
& event
) { ScaleMouseEvent(event
); m_Control
->OnMButtonUp(event
); }
404 void OnRButtonDown(wxMouseEvent
& event
) { ScaleMouseEvent(event
); SetFocus(); m_Control
->OnRButtonDown(event
); }
405 void OnRButtonUp(wxMouseEvent
& event
) { ScaleMouseEvent(event
); m_Control
->OnRButtonUp(event
); }
406 void OnMouseWheel(wxMouseEvent
& event
) { ScaleMouseEvent(event
); SetFocus(); m_Control
->OnMouseWheel(event
); }
407 void OnKeyPress(wxKeyEvent
&event
) { m_Control
->OnKeyPress(event
); }
410 bool Animating() const {
411 return m_Rotating
|| m_SwitchingTo
|| presentation_mode
!= 0;
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();
436 bool IsExtendedElevation() const;
437 void ReverseRotation();
438 void RotateSlower(bool accel
);
439 void RotateFaster(bool accel
);
441 void SwitchToElevation();
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
) {
500 InvalidateList(LIST_SURFACE_LEGS
);
501 InvalidateList(LIST_UNDERGROUND_LEGS
);
502 InvalidateList(LIST_CROSSES
);
503 m_HitTestGridValid
= false;
506 void SetDupesMode(int mode
) {
509 InvalidateList(LIST_SURFACE_LEGS
);
510 InvalidateList(LIST_UNDERGROUND_LEGS
);
513 void ToggleSurfaceLegs() {
514 ToggleFlag(&m_Surface
, UPDATE_BLOBS_AND_CROSSES
);
516 void ToggleCompass() {
517 ToggleFlag(&m_Compass
);
518 InvalidateList(LIST_SCALE_BAR
);
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();
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();
574 void FullScreenMode();
576 bool IsFullScreen() const;
578 bool FullScreenModeShowingMenus() const;
580 void FullScreenModeShowMenus(bool show
);
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
,
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
) {
647 void SetZoomBox(wxPoint p1
, wxPoint p2
, bool centred
, bool aspect
);
649 void UnsetZoomBox() {
650 if (!zoombox
.active()) return;
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
);
663 DECLARE_EVENT_TABLE()