"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 //---------------------------------------------------------