"Fossies" - the Fresh Open Source Software Archive 
Member "saga-9.0.2/saga-gis/src/tools/visualization/vis_3d_viewer/3d_viewer_pointcloud.cpp" (25 May 2023, 30930 Bytes) of package /linux/misc/saga-9.0.2.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1
2 ///////////////////////////////////////////////////////////
3 // //
4 // SAGA //
5 // //
6 // System for Automated Geoscientific Analyses //
7 // //
8 // Tool Library //
9 // 3d_viewer //
10 // //
11 //-------------------------------------------------------//
12 // //
13 // 3d_viewer_pointcloud.cpp //
14 // //
15 // Copyright (C) 2014 by //
16 // Olaf Conrad //
17 // //
18 //-------------------------------------------------------//
19 // //
20 // This file is part of 'SAGA - System for Automated //
21 // Geoscientific Analyses'. SAGA is free software; you //
22 // can redistribute it and/or modify it under the terms //
23 // of the GNU General Public License as published by the //
24 // Free Software Foundation, either version 2 of the //
25 // License, or (at your option) any later version. //
26 // //
27 // SAGA is distributed in the hope that it will be //
28 // useful, but WITHOUT ANY WARRANTY; without even the //
29 // implied warranty of MERCHANTABILITY or FITNESS FOR A //
30 // PARTICULAR PURPOSE. See the GNU General Public //
31 // License for more details. //
32 // //
33 // You should have received a copy of the GNU General //
34 // Public License along with this program; if not, see //
35 // <http://www.gnu.org/licenses/>. //
36 // //
37 //-------------------------------------------------------//
38 // //
39 // e-mail: oconrad@saga-gis.org //
40 // //
41 // contact: Olaf Conrad //
42 // Institute of Geography //
43 // University of Hamburg //
44 // Germany //
45 // //
46 ///////////////////////////////////////////////////////////
47
48 //---------------------------------------------------------
49 #include <wx/dcclient.h>
50
51 #include "3d_viewer_pointcloud.h"
52
53
54 ///////////////////////////////////////////////////////////
55 // //
56 // //
57 // //
58 ///////////////////////////////////////////////////////////
59
60 //---------------------------------------------------------
61 class C3D_Viewer_PointCloud_Panel : public CSG_3DView_Panel
62 {
63 public:
64 C3D_Viewer_PointCloud_Panel(wxWindow *pParent, CSG_PointCloud *pPoints, int Field_Color);
65
66 static CSG_String Get_Usage (void);
67
68 void Set_Extent (CSG_Rect Extent);
69
70
71 protected:
72
73 virtual int On_Parameters_Enable (CSG_Parameters *pParameters, CSG_Parameter *pParameter);
74
75 virtual void Update_Statistics (void);
76 virtual void Update_Parent (void);
77
78 virtual void On_Key_Down (wxKeyEvent &event);
79
80 virtual bool On_Before_Draw (void);
81 virtual bool On_Draw (void);
82
83 virtual int Get_Color (double Value, double z);
84
85
86 private:
87
88 bool m_Color_bGrad;
89
90 double m_Color_Min, m_Color_Scale, m_Color_Dim_Min, m_Color_Dim_Max;
91
92 CSG_Array m_Selection;
93
94 CSG_Colors m_Colors;
95
96 CSG_Rect m_Extent;
97
98 CSG_PointCloud *m_pPoints;
99
100
101 //-----------------------------------------------------
102 DECLARE_EVENT_TABLE()
103
104 };
105
106
107 ///////////////////////////////////////////////////////////
108 // //
109 ///////////////////////////////////////////////////////////
110
111 //---------------------------------------------------------
112 BEGIN_EVENT_TABLE(C3D_Viewer_PointCloud_Panel, CSG_3DView_Panel)
113 EVT_KEY_DOWN (C3D_Viewer_PointCloud_Panel::On_Key_Down)
114 END_EVENT_TABLE()
115
116
117 ///////////////////////////////////////////////////////////
118 // //
119 ///////////////////////////////////////////////////////////
120
121 //---------------------------------------------------------
122 C3D_Viewer_PointCloud_Panel::C3D_Viewer_PointCloud_Panel(wxWindow *pParent, CSG_PointCloud *pPoints, int Field_Color)
123 : CSG_3DView_Panel(pParent)
124 {
125 m_pPoints = pPoints;
126
127 //-----------------------------------------------------
128 CSG_String Attributes;
129
130 for(int i=0; i<m_pPoints->Get_Field_Count(); i++)
131 {
132 Attributes += m_pPoints->Get_Field_Name(i); Attributes += "|";
133 }
134
135 //-----------------------------------------------------
136 m_Parameters.Add_Double("GENERAL" , "DETAIL" , _TL("Level of Detail" ), _TL(""), 100., 0., true, 100., true);
137
138 m_Parameters.Add_Choice("GENERAL" , "COLORS_ATTR" , _TL("Color Attribute" ), _TL(""), Attributes, Field_Color);
139 m_Parameters.Add_Bool ("COLORS_ATTR", "VAL_AS_RGB" , _TL("RGB Values" ), _TL(""), false);
140 m_Parameters.Add_Colors("COLORS_ATTR", "COLORS" , _TL("Colors" ), _TL(""));
141 m_Parameters.Add_Bool ("COLORS_ATTR", "COLORS_GRAD" , _TL("Graduated" ), _TL(""), true);
142 m_Parameters.Add_Range ("COLORS_ATTR", "COLORS_RANGE" , _TL("Value Range" ), _TL(""));
143
144 m_Parameters.Add_Bool ("GENERAL" , "DIM" , _TL("Dim" ), _TL(""), false);
145 m_Parameters.Add_Range ("DIM" , "DIM_RANGE" , _TL("Distance Range" ), _TL(""), 0., 1., 0., true);
146
147 m_Parameters.Add_Int ("GENERAL" , "SIZE" , _TL("Size" ), _TL(""), 1, 1, true);
148 m_Parameters.Add_Double("GENERAL" , "SIZE_SCALE" , _TL("Size Scaling" ), _TL(""), 0., 0., true);
149
150 m_Parameters.Add_Choice("GENERAL" , "OVERVIEW_ATTR", _TL("Overview Content"), _TL(""),
151 CSG_String::Format("%s|%s",
152 _TL("average value"),
153 _TL("number of points")
154 ), 0
155 );
156
157 //-----------------------------------------------------
158 m_Extent = pPoints->Get_Extent();
159
160 m_Selection.Create(sizeof(sLong), 0, TSG_Array_Growth::SG_ARRAY_GROWTH_2);
161
162 Update_Statistics();
163 }
164
165
166 ///////////////////////////////////////////////////////////
167 // //
168 ///////////////////////////////////////////////////////////
169
170 //---------------------------------------------------------
171 int C3D_Viewer_PointCloud_Panel::On_Parameters_Enable(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
172 {
173 if( pParameter->Cmp_Identifier("VAL_AS_RGB") )
174 {
175 pParameters->Set_Enabled("COLORS" , pParameter->asBool() == false);
176 pParameters->Set_Enabled("COLORS_RANGE", pParameter->asBool() == false);
177 }
178
179 if( pParameter->Cmp_Identifier("DIM") )
180 {
181 pParameters->Set_Enabled("DIM_RANGE" , pParameter->asBool());
182 }
183
184 return( CSG_3DView_Panel::On_Parameters_Enable(pParameters, pParameter) );
185 }
186
187
188 ///////////////////////////////////////////////////////////
189 // //
190 ///////////////////////////////////////////////////////////
191
192 //---------------------------------------------------------
193 void C3D_Viewer_PointCloud_Panel::Set_Extent(CSG_Rect Extent)
194 {
195 if( Extent.Get_XRange() == 0. || Extent.Get_YRange() == 0. )
196 {
197 Extent = m_pPoints->Get_Extent();
198 }
199 else
200 {
201 Extent.Intersect(m_pPoints->Get_Extent());
202 }
203
204 if( Extent.is_Equal(m_Extent) == false )
205 {
206 m_Extent = Extent;
207
208 Update_View(true);
209 }
210 }
211
212 //---------------------------------------------------------
213 void C3D_Viewer_PointCloud_Panel::Update_Statistics(void)
214 {
215 m_Data_Min.x = m_Extent.Get_XMin();
216 m_Data_Max.x = m_Extent.Get_XMax();
217
218 m_Data_Min.y = m_Extent.Get_YMin();
219 m_Data_Max.y = m_Extent.Get_YMax();
220
221 m_Selection.Set_Array(0);
222
223 if( m_Extent.is_Equal(m_pPoints->Get_Extent()) )
224 {
225 int cField = m_Parameters("COLORS_ATTR")->asInt();
226
227 m_Parameters("COLORS_RANGE")->asRange()->Set_Range(
228 m_pPoints->Get_Mean(cField) - 1.5 * m_pPoints->Get_StdDev(cField),
229 m_pPoints->Get_Mean(cField) + 1.5 * m_pPoints->Get_StdDev(cField)
230 );
231
232 m_Data_Min.z = m_pPoints->Get_Minimum(2); // Get_ZMin(); ToDo in CSG_PointCloud class!!!
233 m_Data_Max.z = m_pPoints->Get_Maximum(2); // Get_ZMax(); ToDo in CSG_PointCloud class!!!
234 }
235 else
236 {
237 CSG_Simple_Statistics cStats, zStats;
238
239 int cField = m_Parameters("COLORS_ATTR")->asInt();
240
241 for(sLong i=0; i<m_pPoints->Get_Count(); i++)
242 {
243 m_pPoints->Set_Cursor(i);
244
245 if( m_Extent.Contains(m_pPoints->Get_X(), m_pPoints->Get_Y()) && m_Selection.Inc_Array() )
246 {
247 *((sLong *)m_Selection.Get_Entry(m_Selection.Get_Size() - 1)) = i;
248
249 cStats += m_pPoints->Get_Value(cField);
250 zStats += m_pPoints->Get_Z();
251 }
252 }
253
254 m_Parameters("COLORS_RANGE")->asRange()->Set_Range(
255 cStats.Get_Mean() - 1.5 * cStats.Get_StdDev(),
256 cStats.Get_Mean() + 1.5 * cStats.Get_StdDev()
257 );
258
259 m_Data_Min.z = zStats.Get_Minimum();
260 m_Data_Max.z = zStats.Get_Maximum();
261 }
262 }
263
264 //---------------------------------------------------------
265 void C3D_Viewer_PointCloud_Panel::Update_Parent(void)
266 {
267 ((CSG_3DView_Dialog *)GetParent())->Update_Controls();
268 }
269
270
271 ///////////////////////////////////////////////////////////
272 // //
273 ///////////////////////////////////////////////////////////
274
275 //---------------------------------------------------------
276 CSG_String C3D_Viewer_PointCloud_Panel::Get_Usage(void)
277 {
278 CSG_Table Shortcuts(CSG_3DView_Panel::Get_Shortcuts());
279
280 #define ADD_SHORTCUT(KEY, CMD) { CSG_Table_Record &r = *Shortcuts.Add_Record(); r.Set_Value(0, KEY); r.Set_Value(1, CMD); }
281
282 ADD_SHORTCUT("F3", _TL("Decrease Size" ));
283 ADD_SHORTCUT("F4", _TL("Increase Size" ));
284
285 ADD_SHORTCUT("F5", _TL("Decrease Size Scaling"));
286 ADD_SHORTCUT("F6", _TL("Increase Size Scaling"));
287
288 return( CSG_3DView_Panel::Get_Usage(Shortcuts) );
289 }
290
291 //---------------------------------------------------------
292 void C3D_Viewer_PointCloud_Panel::On_Key_Down(wxKeyEvent &event)
293 {
294 switch( event.GetKeyCode() )
295 {
296 default : CSG_3DView_Panel::On_Key_Down(event); return;
297
298 case WXK_F3: Parameter_Value_Add("SIZE" , -1.); break;
299 case WXK_F4: Parameter_Value_Add("SIZE" , 1.); break;
300
301 case WXK_F5: Parameter_Value_Add("SIZE_SCALE", -10.); break;
302 case WXK_F6: Parameter_Value_Add("SIZE_SCALE", 10.); break;
303 }
304 }
305
306
307 ///////////////////////////////////////////////////////////
308 // //
309 ///////////////////////////////////////////////////////////
310
311 //---------------------------------------------------------
312 bool C3D_Viewer_PointCloud_Panel::On_Before_Draw(void)
313 {
314 if( m_Play_State == SG_3DVIEW_PLAY_STOP )
315 {
316 m_Projector.Set_zScaling(m_Projector.Get_xScaling() * m_Parameters("Z_SCALE")->asDouble());
317 }
318
319 return( true );
320 }
321
322
323 ///////////////////////////////////////////////////////////
324 // //
325 ///////////////////////////////////////////////////////////
326
327 //---------------------------------------------------------
328 int C3D_Viewer_PointCloud_Panel::Get_Color(double Value, double z)
329 {
330 int Color;
331
332 if( m_Color_Scale <= 0. )
333 {
334 Color = (int)Value;
335 }
336 else
337 {
338 double c = m_Color_Scale * (Value - m_Color_Min);
339
340 Color = m_Color_bGrad ? m_Colors.Get_Interpolated(c) : m_Colors[(int)c];
341 }
342
343 //-----------------------------------------------------
344 if( m_Color_Dim_Min < m_Color_Dim_Max )
345 {
346 double dim = 1. - (z - m_Color_Dim_Min) / (m_Color_Dim_Max - m_Color_Dim_Min);
347
348 if( dim < 1. )
349 {
350 Color = Dim_Color(Color, dim < 0.1 ? 0.1 : dim);
351 }
352 }
353
354 return( Color );
355 }
356
357
358 ///////////////////////////////////////////////////////////
359 // //
360 ///////////////////////////////////////////////////////////
361
362 //---------------------------------------------------------
363 bool C3D_Viewer_PointCloud_Panel::On_Draw(void)
364 {
365 int cField = m_Parameters("COLORS_ATTR")->asInt();
366
367 if( m_Parameters("COLORS_RANGE")->asRange()->Get_Min()
368 >= m_Parameters("COLORS_RANGE")->asRange()->Get_Max() )
369 {
370 m_Parameters("COLORS_RANGE")->asRange()->Set_Range(
371 m_pPoints->Get_Mean(cField) - 1.5 * m_pPoints->Get_StdDev(cField),
372 m_pPoints->Get_Mean(cField) + 1.5 * m_pPoints->Get_StdDev(cField)
373 );
374 }
375
376 m_Colors = *m_Parameters("COLORS")->asColors();
377 m_Color_bGrad = m_Parameters("COLORS_GRAD")->asBool();
378 m_Color_Min = m_Parameters("COLORS_RANGE.MIN")->asDouble();
379 m_Color_Scale = m_Parameters("COLORS_RANGE.MAX")->asDouble() - m_Color_Min;
380 m_Color_Scale = m_Parameters("VAL_AS_RGB")->asBool() || m_Color_Scale <= 0. ? 0. : m_Colors.Get_Count() / m_Color_Scale;
381
382 if( m_Parameters("DIM")->asBool() )
383 {
384 m_Color_Dim_Min = m_Parameters("DIM_RANGE")->asRange()->Get_Min() * (m_Data_Max.z - m_Data_Min.z);
385 m_Color_Dim_Max = m_Parameters("DIM_RANGE")->asRange()->Get_Max() * (m_Data_Max.z - m_Data_Min.z);
386 }
387 else
388 {
389 m_Color_Dim_Min = m_Color_Dim_Max = 0.;
390 }
391
392 //-----------------------------------------------------
393 int minSize = m_Parameters("SIZE")->asInt(); double dSize = m_Parameters("SIZE_SCALE")->asDouble() / 100.;
394
395 int nSkip = 1 + (int)(0.001 * m_pPoints->Get_Count() * SG_Get_Square(1. - 0.01 * m_Parameters("DETAIL")->asDouble()));
396
397 sLong nPoints = m_Selection.Get_Size() > 0 ? m_Selection.Get_Size() : m_pPoints->Get_Count();
398
399 #pragma omp parallel for
400 for(sLong iPoint=0; iPoint<nPoints; iPoint+=nSkip)
401 {
402 sLong jPoint = m_Selection.Get_Size() > 0 ? *((sLong *)m_Selection.Get_Entry(iPoint)) : iPoint;
403
404 TSG_Point_3D p = m_pPoints->Get_Point(jPoint); m_Projector.Get_Projection(p);
405
406 double Size = minSize; if( dSize > 0. ) { Size += (int)(50. * exp(-p.z / dSize)); }
407
408 Draw_Point(p.x, p.y, p.z, Get_Color(m_pPoints->Get_Value(jPoint, cField), p.z), Size);
409 }
410
411 //-----------------------------------------------------
412 return( true );
413 }
414
415
416 ///////////////////////////////////////////////////////////
417 // //
418 // //
419 // //
420 ///////////////////////////////////////////////////////////
421
422 //---------------------------------------------------------
423 #define OVERVIEW_AS_PANEL
424
425 //---------------------------------------------------------
426 #ifdef OVERVIEW_AS_PANEL
427 class CPointCloud_Overview : public wxPanel
428 #else
429 class CPointCloud_Overview : public wxDialog
430 #endif
431 {
432 public:
433 CPointCloud_Overview(wxWindow *pParent, CSG_PointCloud *pPoints, C3D_Viewer_PointCloud_Panel *pPanel)
434 #ifdef OVERVIEW_AS_PANEL
435 : wxPanel (pParent, wxID_ANY, wxDefaultPosition, wxSize(200, 200), wxTAB_TRAVERSAL|wxSTATIC_BORDER|wxNO_FULL_REPAINT_ON_RESIZE)
436 #else
437 : wxDialog(pParent, wxID_ANY, _TL("Overview"), wxDefaultPosition, wxDefaultSize, wxCAPTION|wxCLOSE_BOX|wxSTAY_ON_TOP)
438 #endif
439 {
440 m_pPanel = pPanel;
441
442 m_bCount = m_pPanel->m_Parameters("OVERVIEW_ATTR")->asInt() == 1;
443
444 double Ratio = pPoints->Get_Extent().Get_XRange() / pPoints->Get_Extent().Get_YRange();
445
446 int Size = GetClientSize().GetWidth(); CSG_Rect r(pPoints->Get_Extent()); CSG_Grid_System System;
447
448 #ifdef OVERVIEW_AS_PANEL
449 if( Ratio > 1. )
450 {
451 System.Create(r.Get_XRange() / 100.,
452 r.Get_XMin(), r.Get_YCenter() - r.Get_XRange() / 2.,
453 r.Get_XMax(), r.Get_YCenter() + r.Get_XRange() / 2.
454 );
455 }
456 else
457 {
458 System.Create(r.Get_YRange() / 100.,
459 r.Get_XCenter() - r.Get_YRange() / 2., r.Get_YMin(),
460 r.Get_XCenter() + r.Get_YRange() / 2., r.Get_YMax()
461 );
462 }
463 #else
464 System.Create((Ratio > 1. ? r.Get_XRange() : r.Get_YRange()) / 100., pPoints->Get_Extent());
465 #endif
466
467 m_Count.Create(System, SG_DATATYPE_Int );
468 m_Value.Create(System, SG_DATATYPE_Double);
469
470 for(sLong i=0; i<pPoints->Get_Count(); i++)
471 {
472 int x, y;
473
474 if( m_Count.Get_System().Get_World_to_Grid(x, y, pPoints->Get_X(i), pPoints->Get_Y(i)) ) // && m_Count.is_InGrid(x, y, false) )
475 {
476 m_Count.Add_Value(x, y, 1);
477 m_Value.Add_Value(x, y, pPoints->Get_Z(i));
478 }
479 }
480
481 m_Value.Divide(m_Count);
482
483 //-------------------------------------------------
484 #ifdef OVERVIEW_AS_PANEL
485 Set_Size(Size, Size, false);
486 #else
487 if( Ratio > 1. )
488 {
489 Set_Size(Size, (int)(Size / Ratio), false);
490 }
491 else
492 {
493 Set_Size((int)(Size * Ratio), Size, false);
494 }
495 #endif
496 }
497
498 void Set_Mode (void)
499 {
500 bool bCount = m_pPanel->m_Parameters("OVERVIEW_ATTR")->asInt() == 1;
501
502 if( m_bCount != bCount )
503 {
504 m_bCount = bCount;
505
506 Set_Image(true);
507 }
508 }
509
510
511 private:
512
513 bool m_bCount;
514
515 wxPoint m_Mouse_Down;
516
517 CSG_Rect m_Selection;
518
519 wxImage m_Image;
520
521 CSG_Grid m_Count, m_Value;
522
523 C3D_Viewer_PointCloud_Panel *m_pPanel;
524
525
526 //---------------------------------------------------------
527 void On_Mouse_LDown (wxMouseEvent &event)
528 {
529 CaptureMouse();
530
531 m_Mouse_Down = event.GetPosition();
532 }
533
534 //---------------------------------------------------------
535 void On_Mouse_Motion (wxMouseEvent &event)
536 {
537 if( HasCapture() && event.Dragging() && event.LeftIsDown() )
538 {
539 Draw_Inverse(m_Mouse_Down, event.GetPosition());
540 }
541 }
542
543 //---------------------------------------------------------
544 void On_Mouse_LUp (wxMouseEvent &event)
545 {
546 if( HasCapture() )
547 {
548 ReleaseMouse();
549 }
550
551 if( m_Mouse_Down.x != event.GetX() && m_Mouse_Down.y != event.GetY() )
552 {
553 Draw_Inverse(m_Mouse_Down, event.GetPosition());
554
555 m_pPanel->Set_Extent(m_Selection);
556 }
557 else if( m_Selection.Get_XRange() > 0. && m_Selection.Get_YRange() > 0. )
558 {
559 double dx = (m_Count.Get_XMin() + event.GetX() * m_Count.Get_XRange() / GetClientSize().GetWidth ()) - m_Selection.Get_XCenter();
560 double dy = (m_Count.Get_YMax() - event.GetY() * m_Count.Get_YRange() / GetClientSize().GetHeight()) - m_Selection.Get_YCenter();
561
562 m_Selection.Move(dx, dy);
563
564 m_pPanel->Set_Extent(m_Selection);
565 }
566
567 Refresh(false);
568 }
569
570 //---------------------------------------------------------
571 void On_Mouse_MDown (wxMouseEvent &event)
572 {
573 m_pPanel->Parameter_Value_Toggle("OVERVIEW_ATTR");
574 Set_Mode();
575 }
576
577 //---------------------------------------------------------
578 void On_Mouse_RDown (wxMouseEvent &event)
579 {
580 m_Selection.Assign(0., 0., 0., 0.);
581
582 m_pPanel->Set_Extent(m_Selection);
583
584 Refresh(false);
585 }
586
587 //---------------------------------------------------------
588 void On_Key_Down (wxKeyEvent &event)
589 {
590 switch( event.GetKeyCode() )
591 {
592 case WXK_PAGEUP : Set_Size(GetClientSize().GetWidth() * 1.25, GetClientSize().GetHeight() * 1.25, true); break;
593 case WXK_PAGEDOWN: Set_Size(GetClientSize().GetWidth() / 1.25, GetClientSize().GetHeight() / 1.25, true); break;
594
595 case WXK_SPACE:
596 m_pPanel->Parameter_Value_Toggle("OVERVIEW_ATTR");
597 Set_Image(true);
598 break;
599 }
600 }
601
602 //---------------------------------------------------------
603 void On_Close (wxCloseEvent &event)
604 {
605 Hide(); ((CSG_3DView_Dialog *)GetParent())->Update_Controls();
606 }
607
608 //---------------------------------------------------------
609 void Set_Size (int Width, int Height, bool bRefresh)
610 {
611 if( Width >= 100 && Height >= 100 && Width <= 1000 && Height <= 1000 )
612 {
613 SetClientSize(Width, Height);
614
615 if( !m_Image.IsOk() || m_Image.GetWidth() != Width || m_Image.GetWidth() != Width )
616 {
617 m_Image.Create(Width, Height, false);
618
619 Set_Image(bRefresh);
620 }
621 }
622 }
623
624 //---------------------------------------------------------
625 void On_Paint (wxPaintEvent &WXUNUSED(event))
626 {
627 wxPaintDC dc(this);
628
629 if( m_Image.IsOk() )
630 {
631 dc.DrawBitmap(wxBitmap(m_Image), GetClientRect().GetTopLeft());
632 }
633
634 if( m_Selection.Get_XRange() > 0. && m_Selection.Get_YRange() > 0. )
635 {
636 double d = GetClientSize().GetWidth () / m_Count.Get_XRange();
637
638 int ax = (int)(d * (m_Selection.Get_XMin() - m_Count.Get_XMin()));
639 int bx = (int)(d * (m_Selection.Get_XMax() - m_Count.Get_XMin()));
640 int ay = (int)(d * (m_Count.Get_YMax() - m_Selection.Get_YMax()));
641 int by = (int)(d * (m_Count.Get_YMax() - m_Selection.Get_YMin()));
642
643 dc.SetPen(wxPen(*wxBLACK));
644 dc.DrawLine(ax, ay, ax, by); dc.DrawLine(ax, by, bx, by);
645 dc.DrawLine(bx, by, bx, ay); dc.DrawLine(bx, ay, ax, ay);
646
647 dc.SetPen(wxPen(*wxWHITE)); ax--; bx++; ay--; by++;
648 dc.DrawLine(ax, ay, ax, by); dc.DrawLine(ax, by, bx, by);
649 dc.DrawLine(bx, by, bx, ay); dc.DrawLine(bx, ay, ax, ay);
650 }
651 }
652
653 //---------------------------------------------------------
654 void Draw_Inverse (wxPoint A, wxPoint B)
655 {
656 if( A != B )
657 {
658 double d = m_Count.Get_XRange() / GetClientSize().GetWidth();
659
660 m_Selection.Assign(
661 m_Count.Get_XMin() + d * A.x, m_Count.Get_YMax() - d * A.y,
662 m_Count.Get_XMin() + d * B.x, m_Count.Get_YMax() - d * B.y
663 );
664
665 Refresh(false);
666 }
667 }
668
669 //---------------------------------------------------------
670 void Set_Image (bool bRefresh)
671 {
672 if( m_Image.IsOk() && m_Count.is_Valid() )
673 {
674 CSG_Colors Colors(11, SG_COLORS_RAINBOW); Colors.Set_Color(0, m_pPanel->m_Parameters("BGCOLOR")->asColor());
675
676 double dx = m_Count.Get_XRange() / (double)m_Image.GetWidth ();
677 double dy = m_Count.Get_YRange() / (double)m_Image.GetHeight();
678 double dz = (Colors.Get_Count() - 2.) / (m_bCount ? log(1. + m_Count.Get_Max()) : 4. * m_Value.Get_StdDev());
679
680 #pragma omp parallel for
681 for(int y=0; y<m_Image.GetHeight(); y++)
682 {
683 double iz, ix = m_Count.Get_XMin(), iy = m_Count.Get_YMax() - y * dy;
684
685 for(int x=0; x<m_Image.GetWidth(); x++, ix+=dx)
686 {
687 if( m_bCount )
688 {
689 iz = dz * (m_Count.Get_Value(ix, iy, iz) && iz > 0. ? log(1. + iz) : 0.);
690 }
691 else if( m_Value.Get_Value(ix, iy, iz) )
692 {
693 iz = dz * (iz - (m_Value.Get_Mean() - 2. * m_Value.Get_StdDev()));
694 }
695 else
696 {
697 iz = 0.;
698 }
699
700 int ic = Colors.Get_Interpolated(iz);
701
702 m_Image.SetRGB(x, y, SG_GET_R(ic), SG_GET_G(ic), SG_GET_B(ic));
703 }
704 }
705 }
706
707 if( bRefresh )
708 {
709 Refresh(false);
710 }
711 }
712
713 //-----------------------------------------------------
714 DECLARE_EVENT_TABLE()
715 };
716
717 //---------------------------------------------------------
718 #ifdef OVERVIEW_AS_PANEL
719 BEGIN_EVENT_TABLE(CPointCloud_Overview, wxPanel)
720 #else
721 BEGIN_EVENT_TABLE(CPointCloud_Overview, wxDialog)
722 EVT_CLOSE (CPointCloud_Overview::On_Close)
723 #endif
724 EVT_LEFT_DOWN (CPointCloud_Overview::On_Mouse_LDown)
725 EVT_LEFT_UP (CPointCloud_Overview::On_Mouse_LUp)
726 EVT_MIDDLE_DOWN(CPointCloud_Overview::On_Mouse_MDown)
727 EVT_RIGHT_DOWN (CPointCloud_Overview::On_Mouse_RDown)
728 EVT_MOTION (CPointCloud_Overview::On_Mouse_Motion)
729 EVT_KEY_DOWN (CPointCloud_Overview::On_Key_Down)
730 EVT_PAINT (CPointCloud_Overview::On_Paint)
731 END_EVENT_TABLE()
732
733
734 ///////////////////////////////////////////////////////////
735 // //
736 // //
737 // //
738 ///////////////////////////////////////////////////////////
739
740 //---------------------------------------------------------
741 class C3D_Viewer_PointCloud_Dialog : public CSG_3DView_Dialog
742 {
743 public:
744 C3D_Viewer_PointCloud_Dialog(CSG_PointCloud *pPoints, int Field_Color)
745 : CSG_3DView_Dialog(_TL("Point Cloud Viewer"))
746 {
747 Create(new C3D_Viewer_PointCloud_Panel(this, pPoints, Field_Color));
748
749 //-------------------------------------------------
750 Add_Spacer();
751
752 wxArrayString Fields; for(int i=0; i<pPoints->Get_Field_Count(); i++) { Fields.Add(pPoints->Get_Field_Name(i)); }
753
754 m_pField_C = Add_Choice (_TL("Color"), Fields, Field_Color);
755
756 //-------------------------------------------------
757 Add_Spacer();
758
759 m_pDetail = Add_Slider (_TL("Level of Detail"), m_pPanel->m_Parameters("DETAIL")->asDouble(), 0., 100.);
760
761 //-------------------------------------------------
762 Add_Spacer();
763
764 m_pOverview = new CPointCloud_Overview(this, pPoints, (C3D_Viewer_PointCloud_Panel *)m_pPanel);
765
766 #ifdef OVERVIEW_AS_PANEL
767 Add_CustomCtrl("", m_pOverview);
768 #else
769 m_pOverview_Check = Add_CheckBox(_TL("Overview"), false);
770 #endif
771 }
772
773 #ifndef OVERVIEW_AS_PANEL
774 virtual ~C3D_Viewer_PointCloud_Dialog(void)
775 {
776 m_pOverview->Destroy();
777 }
778 #endif
779
780 virtual void Update_Controls (void);
781
782
783 protected:
784
785 wxChoice *m_pField_C;
786
787 CSGDI_Slider *m_pDetail;
788
789 CPointCloud_Overview *m_pOverview;
790
791 #ifndef OVERVIEW_AS_PANEL
792 wxCheckBox *m_pOverview_Check;
793 #endif
794
795
796 //-----------------------------------------------------
797 enum
798 {
799 MENU_SCALE_Z_DEC = MENU_USER_FIRST,
800 MENU_SCALE_Z_INC,
801 MENU_VAL_AS_RGB,
802 MENU_COLORS_GRAD,
803 MENU_SIZE_DEC,
804 MENU_SIZE_INC,
805 MENU_SIZE_SCALE_DEC,
806 MENU_SIZE_SCALE_INC
807 };
808
809 //-----------------------------------------------------
810 virtual void On_Update_Choices (wxCommandEvent &event);
811 virtual void On_Update_Control (wxCommandEvent &event);
812
813 virtual void Set_Menu (wxMenu &Menu);
814 virtual void On_Menu (wxCommandEvent &event);
815 virtual void On_Menu_UI (wxUpdateUIEvent &event);
816
817
818 //-----------------------------------------------------
819 DECLARE_EVENT_TABLE()
820 };
821
822 //---------------------------------------------------------
823 BEGIN_EVENT_TABLE(C3D_Viewer_PointCloud_Dialog, CSG_3DView_Dialog)
824 EVT_CHECKBOX(wxID_ANY, C3D_Viewer_PointCloud_Dialog::On_Update_Control)
825 EVT_CHOICE (wxID_ANY, C3D_Viewer_PointCloud_Dialog::On_Update_Choices)
826 END_EVENT_TABLE()
827
828 //---------------------------------------------------------
829 void C3D_Viewer_PointCloud_Dialog::On_Update_Choices(wxCommandEvent &event)
830 {
831 if( event.GetEventObject() == m_pField_C )
832 {
833 m_pPanel->m_Parameters.Set_Parameter("COLORS_ATTR", m_pField_C->GetSelection());
834 m_pPanel->Update_View(true);
835 }
836
837 CSG_3DView_Dialog::On_Update_Choices(event);
838 }
839
840 //---------------------------------------------------------
841 void C3D_Viewer_PointCloud_Dialog::On_Update_Control(wxCommandEvent &event)
842 {
843 if( event.GetEventObject() == m_pDetail )
844 {
845 m_pPanel->m_Parameters.Set_Parameter("DETAIL", m_pDetail->Get_Value());
846 m_pPanel->Update_View();
847 }
848
849 #ifndef OVERVIEW_AS_PANEL
850 if( event.GetEventObject() == m_pOverview_Check )
851 {
852 #ifdef _SAGA_MSW
853 m_pOverview->Show(m_pOverview_Check->GetValue() == 1 ? true : false); // unluckily this does not work with linux (broken event handler chain, non-modal dialog as subprocess of a modal one!!)
854 #else
855 m_pOverview->ShowModal();
856 #endif
857 }
858 #endif
859
860 CSG_3DView_Dialog::On_Update_Control(event);
861 }
862
863 //---------------------------------------------------------
864 void C3D_Viewer_PointCloud_Dialog::Update_Controls(void)
865 {
866 m_pField_C->SetSelection(m_pPanel->m_Parameters("COLORS_ATTR")->asInt());
867
868 #ifndef OVERVIEW_AS_PANEL
869 m_pOverview_Check->SetValue(m_pOverview->IsShown());
870 #endif
871
872 m_pOverview->Set_Mode();
873
874 CSG_3DView_Dialog::Update_Controls();
875 }
876
877 //---------------------------------------------------------
878 void C3D_Viewer_PointCloud_Dialog::Set_Menu(wxMenu &Menu)
879 {
880 wxMenu *pMenu = Menu.FindChildItem(Menu.FindItem(_TL("Display")))->GetSubMenu();
881
882 pMenu->AppendSeparator();
883 pMenu->Append (MENU_SCALE_Z_DEC , _TL("Decrease Exaggeration [F1]"));
884 pMenu->Append (MENU_SCALE_Z_INC , _TL("Increase Exaggeration [F2]"));
885
886 pMenu->AppendSeparator();
887 pMenu->Append (MENU_SIZE_DEC , _TL("Decrease Size [F5]"));
888 pMenu->Append (MENU_SIZE_INC , _TL("Increase Size [F6]"));
889
890 pMenu->AppendSeparator();
891 pMenu->Append (MENU_SIZE_SCALE_DEC, _TL("Decrease Size Scaling Factor [F7]"));
892 pMenu->Append (MENU_SIZE_SCALE_INC, _TL("Increase Size Scaling Factor [F8]"));
893
894 pMenu->AppendSeparator();
895 pMenu->AppendCheckItem(MENU_VAL_AS_RGB , _TL("Value as RGB"));
896 pMenu->AppendCheckItem(MENU_COLORS_GRAD , _TL("Graduated Colors"));
897 }
898
899 //---------------------------------------------------------
900 void C3D_Viewer_PointCloud_Dialog::On_Menu(wxCommandEvent &event)
901 {
902 switch( event.GetId() )
903 {
904 default: CSG_3DView_Dialog::On_Menu(event); break;
905
906 case MENU_USAGE : SG_UI_Dlg_Info(C3D_Viewer_PointCloud_Panel::Get_Usage(), _TL("Usage")); return;
907
908 case MENU_SCALE_Z_DEC : m_pPanel->Parameter_Value_Add("Z_SCALE" , -0.5); break;
909 case MENU_SCALE_Z_INC : m_pPanel->Parameter_Value_Add("Z_SCALE" , 0.5); break;
910
911 case MENU_SIZE_DEC : m_pPanel->Parameter_Value_Add("SIZE" , -1.0); break;
912 case MENU_SIZE_INC : m_pPanel->Parameter_Value_Add("SIZE" , 1.0); break;
913
914 case MENU_SIZE_SCALE_DEC: m_pPanel->Parameter_Value_Add("SIZE_SCALE", -1.0); break;
915 case MENU_SIZE_SCALE_INC: m_pPanel->Parameter_Value_Add("SIZE_SCALE", 1.0); break;
916
917 case MENU_VAL_AS_RGB : m_pPanel->Parameter_Value_Toggle("VAL_AS_RGB" ); break;
918 case MENU_COLORS_GRAD : m_pPanel->Parameter_Value_Toggle("COLORS_GRAD" ); break;
919 }
920 }
921
922 //---------------------------------------------------------
923 void C3D_Viewer_PointCloud_Dialog::On_Menu_UI(wxUpdateUIEvent &event)
924 {
925 switch( event.GetId() )
926 {
927 default:
928 CSG_3DView_Dialog::On_Menu_UI(event);
929 break;
930
931 case MENU_VAL_AS_RGB : event.Check(m_pPanel->m_Parameters("VAL_AS_RGB" )->asBool()); break;
932 case MENU_COLORS_GRAD: event.Check(m_pPanel->m_Parameters("COLORS_GRAD")->asBool()); break;
933 }
934 }
935
936
937 ///////////////////////////////////////////////////////////
938 // //
939 // //
940 // //
941 ///////////////////////////////////////////////////////////
942
943 //---------------------------------------------------------
944 C3D_Viewer_PointCloud::C3D_Viewer_PointCloud(void)
945 {
946 Set_Name (_TL("Point Cloud Viewer"));
947
948 Set_Author ("O. Conrad (c) 2014");
949
950 Set_Description (_TW(
951 "3D viewer for point clouds."
952 ));
953
954 Set_Description(Get_Description() + C3D_Viewer_PointCloud_Panel::Get_Usage());
955
956 //-----------------------------------------------------
957 Parameters.Add_PointCloud("",
958 "POINTS" , _TL("Point Cloud"),
959 _TL(""),
960 PARAMETER_INPUT
961 );
962
963 Parameters.Add_Table_Field("POINTS",
964 "COLOR" , _TL("Color"),
965 _TL("")
966 );
967 }
968
969
970 ///////////////////////////////////////////////////////////
971 // //
972 ///////////////////////////////////////////////////////////
973
974 //---------------------------------------------------------
975 int C3D_Viewer_PointCloud::On_Parameter_Changed(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
976 {
977 if( pParameter->Cmp_Identifier("POINTS") )
978 {
979 if( pParameter->asPointCloud() )
980 {
981 pParameters->Set_Parameter("COLOR", 2); // let's default to 'Z'
982 }
983 }
984
985 return( CSG_Tool::On_Parameter_Changed(pParameters, pParameter) );
986 }
987
988
989 ///////////////////////////////////////////////////////////
990 // //
991 ///////////////////////////////////////////////////////////
992
993 //---------------------------------------------------------
994 bool C3D_Viewer_PointCloud::On_Execute(void)
995 {
996 CSG_PointCloud *pPoints = Parameters("POINTS")->asPointCloud();
997
998 if( pPoints->Get_Count() <= 0 )
999 {
1000 Message_Add(_TL("point cloud viewer will not be started, because point cloud has no points"));
1001
1002 return( false );
1003 }
1004
1005 C3D_Viewer_PointCloud_Dialog dlg(pPoints, Parameters("COLOR")->asInt());
1006
1007 dlg.ShowModal();
1008
1009 return( true );
1010 }
1011
1012
1013 ///////////////////////////////////////////////////////////
1014 // //
1015 // //
1016 // //
1017 ///////////////////////////////////////////////////////////
1018
1019 //---------------------------------------------------------