<commit_before>/******************************************************************************\
* File:          configdlg.cpp
* Purpose:       Implementation of wxExtension config dialog class
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <functional>
#include <algorithm>
#include <wx/filepicker.h>
#include <wx/notebook.h>
#include <wx/extension/configdlg.h>
#include <wx/extension/frame.h>

#if wxUSE_GUI

wxExConfigDialog* wxExConfigComboBoxDialog(wxWindow* parent,
  const wxString& title,
  const wxString& item,
  long flags,
  wxWindowID id,
  long style)
{
  std::vector<wxExConfigItem> v;

  v.push_back(wxExConfigItem(
    item,
    CONFIG_COMBOBOX_NONAME));

  return new wxExConfigDialog(
    parent,
    v,
    title,
    0,
    1,
    flags,
    id,
    style);
}

BEGIN_EVENT_TABLE(wxExConfigDialog, wxExDialog)
  EVT_BUTTON(wxID_APPLY, wxExConfigDialog::OnCommand)
  EVT_BUTTON(wxID_CANCEL, wxExConfigDialog::OnCommand)
  EVT_BUTTON(wxID_CLOSE, wxExConfigDialog::OnCommand)
  EVT_BUTTON(wxID_OK, wxExConfigDialog::OnCommand)
  EVT_UPDATE_UI(wxID_APPLY, wxExConfigDialog::OnUpdateUI)
  EVT_UPDATE_UI(wxID_OK, wxExConfigDialog::OnUpdateUI)
END_EVENT_TABLE()

// wxPropertySheetDialog has been tried as well,
// then you always have a notebook, and apply button is not supported.
wxExConfigDialog::wxExConfigDialog(wxWindow* parent,
  const std::vector<wxExConfigItem>& v,
  const wxString& title,
  int rows,
  int cols,
  long flags,
  wxWindowID id,
  long style)
  : wxExDialog(parent, title, flags, id, style)
  , m_ForceCheckBoxChecked(false)
  , m_Page(wxEmptyString)
  , m_ConfigItems(v)
{
  Layout(rows, cols);

  for_each (m_ConfigItems.begin(), m_ConfigItems.end(),
    std::bind2nd(std::mem_fun_ref(&wxExConfigItem::ToConfig), false)); // read
}

wxExConfigItem wxExConfigDialog::FindConfigItem(int id) const
{
  for (
    std::vector<wxExConfigItem>::const_iterator it = m_ConfigItems.begin();
    it != m_ConfigItems.end();
    ++it)
  {
    if (it->GetId() == id)
    {
      return *it;
    }
  }

  return wxExConfigItem();
}

void wxExConfigDialog::ForceCheckBoxChecked(
  const wxString& contains,
  const wxString& page)
{
  m_ForceCheckBoxChecked = true;
  m_Contains = contains;
  m_Page = page;
}

void wxExConfigDialog::Layout(int rows, int cols)
{
  bool first_time = true;
  wxFlexGridSizer* sizer = NULL;
  wxNotebook* notebook = NULL;
  wxString previous_page = "XXXXXX";
  wxPanel* page_panel = NULL;

  for (
    std::vector<wxExConfigItem>::iterator it = m_ConfigItems.begin();
    it != m_ConfigItems.end();
    ++it)
  {
    // Check if we need a notebook.
    if (it == m_ConfigItems.begin() && !it->GetPage().empty())
    {
      notebook = new wxNotebook(this, wxID_ANY);
    }

    if (first_time ||
        (it->GetPage() != previous_page &&
         it->GetPage() != wxEmptyString))
    {
      first_time = false;

      if (notebook != NULL && it->GetType() != CONFIG_SPACER)
      {
        // Finish the current page.
        if (sizer != NULL)
        {
          page_panel->SetSizerAndFit(sizer);
        }

        // And make a new one.
        page_panel = new wxPanel(notebook);
        notebook->AddPage(page_panel, it->GetPage());
      }

      previous_page = it->GetPage();

      if (rows != 0)
        sizer = new wxFlexGridSizer(rows, cols, 0, 0);
      else
        sizer = new wxFlexGridSizer(cols);

      if (cols == 2)
      {
        sizer->AddGrowableCol(1);
      }
      else
      {
        for (int i = 0; i < cols; i++)
        {
          sizer->AddGrowableCol(i);
        }
      }
    }

    it->Layout(
      (page_panel != NULL ? (wxWindow*)page_panel: this),
      sizer,
      GetButtonFlags() == wxCANCEL);

    if (it->GetType() == CONFIG_COMBOBOXDIR)
    {
      Bind(wxEVT_COMMAND_BUTTON_CLICKED, &wxExConfigDialog::OnCommand, this, it->GetId());
    }

    if ( sizer->GetRows() > 0 &&
        !sizer->IsRowGrowable(sizer->GetRows() - 1))
    {
      sizer->AddGrowableRow(sizer->GetRows() - 1);
    }
  }

  if (page_panel != NULL)
  {
    page_panel->SetSizerAndFit(sizer);

    AddUserSizer(notebook);
  }
  else
  {
    AddUserSizer(sizer);
  }

  LayoutSizers(notebook == NULL); // add separator line if no notebook
}

void wxExConfigDialog::OnCommand(wxCommandEvent& command)
{
  if (command.GetId() < wxID_LOWEST)
  {
    wxComboBox* browse = (wxComboBox*)FindConfigItem(command.GetId()).GetControl();

    if (browse != NULL)
    {
      wxDirDialog dir_dlg(
        this,
        wxDirSelectorPromptStr,
        browse->GetValue(),
        wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);

      if (dir_dlg.ShowModal() == wxID_OK)
      {
        browse->SetValue(dir_dlg.GetPath());
      }
    }

    return;
  }

  switch (command.GetId())
  {
  case wxID_CANCEL:
    // For wxID_CANCEL reload from config.
    for_each (m_ConfigItems.begin(), m_ConfigItems.end(),
      std::bind2nd(std::mem_fun_ref(&wxExConfigItem::ToConfig), false));
    break;

  default:
    // For rest of the buttons (wxID_OK, wxID_APPLY, wxID_CLOSE)
    // save to config.
    for_each (m_ConfigItems.begin(), m_ConfigItems.end(),
      std::bind2nd(std::mem_fun_ref(&wxExConfigItem::ToConfig), true));
  }

  if ( command.GetId() == wxID_APPLY ||
      ((command.GetId() == wxID_OK ||
        command.GetId() == wxID_CANCEL) && !IsModal()))
  {
    wxASSERT(wxTheApp != NULL);
    wxWindow* window = wxTheApp->GetTopWindow();
    wxASSERT(window != NULL);
    wxExFrame* frame = wxDynamicCast(window, wxExFrame);
    wxASSERT(frame != NULL);

    frame->OnCommandConfigDialog(GetId(), command.GetId());
  }

  command.Skip();
}

void wxExConfigDialog::OnUpdateUI(wxUpdateUIEvent& event)
{
  bool one_checkbox_checked = false;

  for (
    std::vector<wxExConfigItem>::const_iterator it = m_ConfigItems.begin();
    it != m_ConfigItems.end();
    ++it)
  {
    switch (it->GetType())
    {
    case CONFIG_CHECKBOX:
      if (m_ForceCheckBoxChecked)
      {
        wxCheckBox* cb = (wxCheckBox*)it->GetControl();

        if (it->GetName().Lower().Contains(m_Contains.Lower()) &&
            cb->GetValue() &&
            it->GetPage() == m_Page)
        {
          one_checkbox_checked = true;
        }
      }
      break;

    case CONFIG_CHECKLISTBOX_NONAME:
      if (m_ForceCheckBoxChecked)
      {
        wxCheckListBox* clb = (wxCheckListBox*)it->GetControl();

        for (
          size_t i = 0;
          i < clb->GetCount();
          i++)
        {
          if (clb->GetString(i).Lower().Contains(m_Contains.Lower()) &&
              clb->IsChecked(i) &&
              it->GetPage() == m_Page)
          {
            one_checkbox_checked = true;
          }
        }
      }
      break;

    case CONFIG_COMBOBOX:
    case CONFIG_COMBOBOXDIR:
    case CONFIG_COMBOBOX_NONAME:
      {
      wxComboBox* cb = (wxComboBox*)it->GetControl();
      if (it->GetIsRequired())
      {
        if (cb->GetValue().empty())
        {
          event.Enable(false);
          return;
        }
      }
      }
      break;

    case CONFIG_INT:
    case CONFIG_STRING:
      {
      wxTextCtrl* tc = (wxTextCtrl*)it->GetControl();
      if (it->GetIsRequired())
      {
        if (tc->GetValue().empty())
        {
          event.Enable(false);
          return;
        }
      }
      }
      break;

    case CONFIG_DIRPICKERCTRL:
      {
      wxDirPickerCtrl* pc = (wxDirPickerCtrl*)it->GetControl();
      if (it->GetIsRequired())
      {
        if (pc->GetPath().empty())
        {
          event.Enable(false);
          return;
        }
      }
      }
      break;

    case CONFIG_FILEPICKERCTRL:
      {
      wxFilePickerCtrl* pc = (wxFilePickerCtrl*)it->GetControl();
      if (it->GetIsRequired())
      {
        if (pc->GetPath().empty())
        {
          event.Enable(false);
          return;
        }
      }
      }
      break;
    }
  }

  if (m_ForceCheckBoxChecked)
  {
    event.Enable(one_checkbox_checked);
  }
  else
  {
    event.Enable(true);
  }
}
#endif // wxUSE_GUI
<commit_msg>minor update<commit_after>/******************************************************************************\
* File:          configdlg.cpp
* Purpose:       Implementation of wxExtension config dialog class
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <functional>
#include <algorithm>
#include <wx/filepicker.h>
#include <wx/notebook.h>
#include <wx/extension/configdlg.h>
#include <wx/extension/frame.h>

#if wxUSE_GUI

wxExConfigDialog* wxExConfigComboBoxDialog(wxWindow* parent,
  const wxString& title,
  const wxString& item,
  long flags,
  wxWindowID id,
  long style)
{
  std::vector<wxExConfigItem> v;

  v.push_back(wxExConfigItem(
    item,
    CONFIG_COMBOBOX_NONAME));

  return new wxExConfigDialog(
    parent,
    v,
    title,
    0,
    1,
    flags,
    id,
    style);
}

BEGIN_EVENT_TABLE(wxExConfigDialog, wxExDialog)
  EVT_BUTTON(wxID_APPLY, wxExConfigDialog::OnCommand)
  EVT_BUTTON(wxID_CANCEL, wxExConfigDialog::OnCommand)
  EVT_BUTTON(wxID_CLOSE, wxExConfigDialog::OnCommand)
  EVT_BUTTON(wxID_OK, wxExConfigDialog::OnCommand)
  EVT_UPDATE_UI(wxID_APPLY, wxExConfigDialog::OnUpdateUI)
  EVT_UPDATE_UI(wxID_OK, wxExConfigDialog::OnUpdateUI)
END_EVENT_TABLE()

// wxPropertySheetDialog has been tried as well,
// then you always have a notebook, and apply button is not supported.
wxExConfigDialog::wxExConfigDialog(wxWindow* parent,
  const std::vector<wxExConfigItem>& v,
  const wxString& title,
  int rows,
  int cols,
  long flags,
  wxWindowID id,
  long style)
  : wxExDialog(parent, title, flags, id, style)
  , m_ForceCheckBoxChecked(false)
  , m_Page(wxEmptyString)
  , m_ConfigItems(v)
{
  Layout(rows, cols);

  for_each (m_ConfigItems.begin(), m_ConfigItems.end(),
    std::bind2nd(std::mem_fun_ref(&wxExConfigItem::ToConfig), false)); // read
}

wxExConfigItem wxExConfigDialog::FindConfigItem(int id) const
{
  for (
    std::vector<wxExConfigItem>::const_iterator it = m_ConfigItems.begin();
    it != m_ConfigItems.end();
    ++it)
  {
    if (it->GetId() == id)
    {
      return *it;
    }
  }

  return wxExConfigItem();
}

void wxExConfigDialog::ForceCheckBoxChecked(
  const wxString& contains,
  const wxString& page)
{
  m_ForceCheckBoxChecked = true;
  m_Contains = contains;
  m_Page = page;
}

void wxExConfigDialog::Layout(int rows, int cols)
{
  bool first_time = true;
  wxFlexGridSizer* sizer = NULL;
  wxNotebook* notebook = NULL;
  wxString previous_page = "XXXXXX";
  wxPanel* page_panel = NULL;

  for (
    std::vector<wxExConfigItem>::iterator it = m_ConfigItems.begin();
    it != m_ConfigItems.end();
    ++it)
  {
    // Check if we need a notebook.
    if (it == m_ConfigItems.begin() && !it->GetPage().empty())
    {
      notebook = new wxNotebook(this, wxID_ANY);
    }

    if (first_time ||
        (it->GetPage() != previous_page &&
         it->GetPage() != wxEmptyString))
    {
      first_time = false;

      if (notebook != NULL)
      {
        // Finish the current page.
        page_panel->SetSizerAndFit(sizer);

        // And make a new one.
        page_panel = new wxPanel(notebook);
        notebook->AddPage(page_panel, it->GetPage());
      }

      previous_page = it->GetPage();

      if (rows != 0)
        sizer = new wxFlexGridSizer(rows, cols, 0, 0);
      else
        sizer = new wxFlexGridSizer(cols);

      if (cols == 2)
      {
        sizer->AddGrowableCol(1);
      }
      else
      {
        for (int i = 0; i < cols; i++)
        {
          sizer->AddGrowableCol(i);
        }
      }
    }

    it->Layout(
      (page_panel != NULL ? (wxWindow*)page_panel: this),
      sizer,
      GetButtonFlags() == wxCANCEL);

    if (it->GetType() == CONFIG_COMBOBOXDIR)
    {
      Bind(wxEVT_COMMAND_BUTTON_CLICKED, &wxExConfigDialog::OnCommand, this, it->GetId());
    }

    if ( sizer->GetRows() > 0 &&
        !sizer->IsRowGrowable(sizer->GetRows() - 1))
    {
      sizer->AddGrowableRow(sizer->GetRows() - 1);
    }
  }

  if (notebook != NULL)
  {
    page_panel->SetSizerAndFit(sizer);

    AddUserSizer(notebook);
  }
  else
  {
    AddUserSizer(sizer);
  }

  LayoutSizers(notebook == NULL); // add separator line if no notebook
}

void wxExConfigDialog::OnCommand(wxCommandEvent& command)
{
  if (command.GetId() < wxID_LOWEST)
  {
    wxComboBox* browse = (wxComboBox*)FindConfigItem(command.GetId()).GetControl();

    if (browse != NULL)
    {
      wxDirDialog dir_dlg(
        this,
        wxDirSelectorPromptStr,
        browse->GetValue(),
        wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);

      if (dir_dlg.ShowModal() == wxID_OK)
      {
        browse->SetValue(dir_dlg.GetPath());
      }
    }

    return;
  }

  switch (command.GetId())
  {
  case wxID_CANCEL:
    // For wxID_CANCEL reload from config.
    for_each (m_ConfigItems.begin(), m_ConfigItems.end(),
      std::bind2nd(std::mem_fun_ref(&wxExConfigItem::ToConfig), false));
    break;

  default:
    // For rest of the buttons (wxID_OK, wxID_APPLY, wxID_CLOSE)
    // save to config.
    for_each (m_ConfigItems.begin(), m_ConfigItems.end(),
      std::bind2nd(std::mem_fun_ref(&wxExConfigItem::ToConfig), true));
  }

  if ( command.GetId() == wxID_APPLY ||
      ((command.GetId() == wxID_OK ||
        command.GetId() == wxID_CANCEL) && !IsModal()))
  {
    wxASSERT(wxTheApp != NULL);
    wxWindow* window = wxTheApp->GetTopWindow();
    wxASSERT(window != NULL);
    wxExFrame* frame = wxDynamicCast(window, wxExFrame);
    wxASSERT(frame != NULL);

    frame->OnCommandConfigDialog(GetId(), command.GetId());
  }

  command.Skip();
}

void wxExConfigDialog::OnUpdateUI(wxUpdateUIEvent& event)
{
  bool one_checkbox_checked = false;

  for (
    std::vector<wxExConfigItem>::const_iterator it = m_ConfigItems.begin();
    it != m_ConfigItems.end();
    ++it)
  {
    switch (it->GetType())
    {
    case CONFIG_CHECKBOX:
      if (m_ForceCheckBoxChecked)
      {
        wxCheckBox* cb = (wxCheckBox*)it->GetControl();

        if (it->GetName().Lower().Contains(m_Contains.Lower()) &&
            cb->GetValue() &&
            it->GetPage() == m_Page)
        {
          one_checkbox_checked = true;
        }
      }
      break;

    case CONFIG_CHECKLISTBOX_NONAME:
      if (m_ForceCheckBoxChecked)
      {
        wxCheckListBox* clb = (wxCheckListBox*)it->GetControl();

        for (
          size_t i = 0;
          i < clb->GetCount();
          i++)
        {
          if (clb->GetString(i).Lower().Contains(m_Contains.Lower()) &&
              clb->IsChecked(i) &&
              it->GetPage() == m_Page)
          {
            one_checkbox_checked = true;
          }
        }
      }
      break;

    case CONFIG_COMBOBOX:
    case CONFIG_COMBOBOXDIR:
    case CONFIG_COMBOBOX_NONAME:
      {
      wxComboBox* cb = (wxComboBox*)it->GetControl();
      if (it->GetIsRequired())
      {
        if (cb->GetValue().empty())
        {
          event.Enable(false);
          return;
        }
      }
      }
      break;

    case CONFIG_INT:
    case CONFIG_STRING:
      {
      wxTextCtrl* tc = (wxTextCtrl*)it->GetControl();
      if (it->GetIsRequired())
      {
        if (tc->GetValue().empty())
        {
          event.Enable(false);
          return;
        }
      }
      }
      break;

    case CONFIG_DIRPICKERCTRL:
      {
      wxDirPickerCtrl* pc = (wxDirPickerCtrl*)it->GetControl();
      if (it->GetIsRequired())
      {
        if (pc->GetPath().empty())
        {
          event.Enable(false);
          return;
        }
      }
      }
      break;

    case CONFIG_FILEPICKERCTRL:
      {
      wxFilePickerCtrl* pc = (wxFilePickerCtrl*)it->GetControl();
      if (it->GetIsRequired())
      {
        if (pc->GetPath().empty())
        {
          event.Enable(false);
          return;
        }
      }
      }
      break;
    }
  }

  if (m_ForceCheckBoxChecked)
  {
    event.Enable(one_checkbox_checked);
  }
  else
  {
    event.Enable(true);
  }
}
#endif // wxUSE_GUI
<|endoftext|>


<commit_before>// Open a FITS file whose primary array represents
// a spectrum (flux vs wavelength)
void FITS_tutorial5()
{
   TVectorD *v;

   printf("\n\n--------------------------------\n");
   printf("WELCOME TO FITS tutorial #5 !!!!\n");
   printf("--------------------------------\n");
   printf("We're gonna open a FITS file that contains a\n");
   printf("table with 9 rows and 8 columns. Column 4 has name\n");
   printf("'mag' and contains a vector of 6 numeric components.\n");
   printf("The values of vectors in rows 1 and 2 (column 4) are:\n");
   printf("Row1: (99.0, 24.768, 23.215, 21.68, 21.076, 20.857)\n");
   printf("Row2: (99.0, 21.689, 20.206, 18.86, 18.32 , 18.128 )\n");
   printf("WARNING: when coding, row and column indices start from 0\n");

   if (!gROOT->IsBatch()) {
      printf("Press ENTER to start..."); getchar();
      printf("\n");
   }

   //Open the table
   TFITSHDU *hdu = new TFITSHDU("sample4.fits[1]");
   if (hdu == 0) {
      printf("ERROR: could not access the HDU\n"); return;
   }

   //Read vectors at rows 1 and 2 (indices 0 and 1)
   TVectorD *vecs[2];
   vecs[0] = hdu->GetTabRealVectorCell(0, "mag");
   vecs[1] = hdu->GetTabRealVectorCell(1, "mag");
   for (int iVec=0; iVec < 2; iVec++) {
      printf("Vector %d = (", iVec+1);
      v = vecs[iVec];
      for(int i=0; i < v->GetNoElements(); i++) {
         if (i>0) printf(", ");
         printf("%lg", (*v)[i]); //NOTE: the asterisk is for using the overloaded [] operator of the TVectorD object
      }
      printf(")\n");
   }

   printf("\nBONUS EXAMPLE: we're gonna dump all rows using\n");
   printf("the function GetTabRealVectorCells()\n");
   printf("Press ENTER to continue..."); getchar();

   TObjArray *vectorCollection = hdu->GetTabRealVectorCells("mag");

   for (int iVec=0; iVec < vectorCollection->GetEntriesFast(); iVec++) {
      printf("Vector %d = (", iVec+1);
      v = (TVectorD *) (*vectorCollection)[iVec]; //NOTE: the asterisk is for using the overloaded [] operator of the TObjArray object
      for(int i=0; i < v->GetNoElements(); i++) {
         if (i>0) printf(", ");
         printf("%lg", (*v)[i]); //NOTE: the asterisk is for using the overloaded [] operator of the TVectorD object
      }
      printf(")\n");
   }

   //Clean up
   delete vecs[0];
   delete vecs[1];
   delete vectorCollection;
   delete hdu;
}

<commit_msg>no more getchar() so auto doc generation does not fail.<commit_after>// Open a FITS file whose primary array represents
// a spectrum (flux vs wavelength)
void FITS_tutorial5()
{
   TVectorD *v;

   printf("\n\n--------------------------------\n");
   printf("WELCOME TO FITS tutorial #5 !!!!\n");
   printf("--------------------------------\n");
   printf("We're gonna open a FITS file that contains a\n");
   printf("table with 9 rows and 8 columns. Column 4 has name\n");
   printf("'mag' and contains a vector of 6 numeric components.\n");
   printf("The values of vectors in rows 1 and 2 (column 4) are:\n");
   printf("Row1: (99.0, 24.768, 23.215, 21.68, 21.076, 20.857)\n");
   printf("Row2: (99.0, 21.689, 20.206, 18.86, 18.32 , 18.128 )\n");
   printf("WARNING: when coding, row and column indices start from 0\n");

   if (!gROOT->IsBatch()) {
      //printf("Press ENTER to start..."); getchar();
      //printf("\n");
   }

   //Open the table
   TFITSHDU *hdu = new TFITSHDU("sample4.fits[1]");
   if (hdu == 0) {
      printf("ERROR: could not access the HDU\n"); return;
   }

   //Read vectors at rows 1 and 2 (indices 0 and 1)
   TVectorD *vecs[2];
   vecs[0] = hdu->GetTabRealVectorCell(0, "mag");
   vecs[1] = hdu->GetTabRealVectorCell(1, "mag");
   for (int iVec=0; iVec < 2; iVec++) {
      printf("Vector %d = (", iVec+1);
      v = vecs[iVec];
      for(int i=0; i < v->GetNoElements(); i++) {
         if (i>0) printf(", ");
         printf("%lg", (*v)[i]); //NOTE: the asterisk is for using the overloaded [] operator of the TVectorD object
      }
      printf(")\n");
   }

   printf("\nBONUS EXAMPLE: we're gonna dump all rows using\n");
   printf("the function GetTabRealVectorCells()\n");
   //printf("Press ENTER to continue..."); getchar();

   TObjArray *vectorCollection = hdu->GetTabRealVectorCells("mag");

   for (int iVec=0; iVec < vectorCollection->GetEntriesFast(); iVec++) {
      printf("Vector %d = (", iVec+1);
      v = (TVectorD *) (*vectorCollection)[iVec]; //NOTE: the asterisk is for using the overloaded [] operator of the TObjArray object
      for(int i=0; i < v->GetNoElements(); i++) {
         if (i>0) printf(", ");
         printf("%lg", (*v)[i]); //NOTE: the asterisk is for using the overloaded [] operator of the TVectorD object
      }
      printf(")\n");
   }

   //Clean up
   delete vecs[0];
   delete vecs[1];
   delete vectorCollection;
   delete hdu;
}

<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <file.hpp>
#include <system.hpp>
#include <errors.hpp>
#include <print.hpp>

int main(int argc, char* argv[]){
    if(argc == 1){
        print_line("Usage: which executable_path");
        exit(1);
    }

    std::string path(argv[1]);

    if(path[0] != '/'){
        path = "/bin/" + path;
    }

    auto fd = open(path.c_str());

    if(fd.valid()){
        print(path);

        close(*fd);
    } else {
        if(fd.has_error(std::ERROR_NOT_EXISTS)){
            printf("%s not found\n", argv[1]);
        } else {
            printf("which: error: %s\n", std::error_message(fd.error()));
        }
    }

    exit(0);
}<commit_msg>Add new line<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <file.hpp>
#include <system.hpp>
#include <errors.hpp>
#include <print.hpp>

int main(int argc, char* argv[]){
    if(argc == 1){
        print_line("Usage: which executable_path");
        exit(1);
    }

    std::string path(argv[1]);

    if(path[0] != '/'){
        path = "/bin/" + path;
    }

    auto fd = open(path.c_str());

    if(fd.valid()){
        print_line(path);

        close(*fd);
    } else {
        if(fd.has_error(std::ERROR_NOT_EXISTS)){
            printf("%s not found\n", argv[1]);
        } else {
            printf("which: error: %s\n", std::error_message(fd.error()));
        }
    }

    exit(0);
}
<|endoftext|>


<commit_before>/*
    Copyright (c) 2007 Volker Krause <vkrause@kde.org>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

    This library is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "control.h"

#include <kdebug.h>
#include <kstaticdeleter.h>

#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QEventLoop>

#define AKONADI_CONTROL_SERVICE QLatin1String("org.kde.Akonadi.Control")
#define AKONADI_SERVER_SERVICE QLatin1String("org.kde.Akonadi")

using namespace Akonadi;

Control* Control::mInstance = 0;
static KStaticDeleter<Control> sControlDeleter;

void Control::start()
{
  self()->startInternal();
}

Control* Control::self()
{
  if ( !mInstance )
    sControlDeleter.setObject( mInstance, new Control() );
  return mInstance;
}

Control::Control() :
    QObject()
{
  connect( QDBusConnection::sessionBus().interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)),
           SLOT(serviceOwnerChanged(QString,QString,QString)) );
  mEventLoop = 0;
}

void Control::startInternal()
{
  if ( QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_CONTROL_SERVICE ) || mEventLoop )
    return;
 QDBusConnection::sessionBus().interface()->startService( AKONADI_CONTROL_SERVICE );
 mEventLoop = new QEventLoop( this );
 mEventLoop->exec();
}

void Control::serviceOwnerChanged(const QString & name, const QString & oldOwner, const QString & newOwner)
{
  Q_UNUSED( oldOwner );
  if ( name == AKONADI_SERVER_SERVICE && !newOwner.isEmpty() && mEventLoop ) {
    mEventLoop->quit();
    delete mEventLoop;
    mEventLoop = 0;
  }
}

#include "control.moc"
<commit_msg>don't deadlock cornelius<commit_after>/*
    Copyright (c) 2007 Volker Krause <vkrause@kde.org>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

    This library is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "control.h"

#include <kdebug.h>
#include <kstaticdeleter.h>

#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QEventLoop>

#define AKONADI_CONTROL_SERVICE QLatin1String("org.kde.Akonadi.Control")
#define AKONADI_SERVER_SERVICE QLatin1String("org.kde.Akonadi")

using namespace Akonadi;

Control* Control::mInstance = 0;
static KStaticDeleter<Control> sControlDeleter;

void Control::start()
{
  self()->startInternal();
}

Control* Control::self()
{
  if ( !mInstance )
    sControlDeleter.setObject( mInstance, new Control() );
  return mInstance;
}

Control::Control() :
    QObject()
{
  connect( QDBusConnection::sessionBus().interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)),
           SLOT(serviceOwnerChanged(QString,QString,QString)) );
  mEventLoop = 0;
}

void Control::startInternal()
{
  if ( QDBusConnection::sessionBus().interface()->isServiceRegistered( AKONADI_CONTROL_SERVICE ) || mEventLoop )
    return;
 QDBusReply<void> reply = QDBusConnection::sessionBus().interface()->startService( AKONADI_CONTROL_SERVICE );
 if ( !reply.isValid() ) {
   qWarning( "Unable to start Akonadi control process: %s", qPrintable( reply.error().message() ) );
   return;
 }
 mEventLoop = new QEventLoop( this );
 mEventLoop->exec();
}

void Control::serviceOwnerChanged(const QString & name, const QString & oldOwner, const QString & newOwner)
{
  Q_UNUSED( oldOwner );
  if ( name == AKONADI_SERVER_SERVICE && !newOwner.isEmpty() && mEventLoop ) {
    mEventLoop->quit();
    delete mEventLoop;
    mEventLoop = 0;
  }
}

#include "control.moc"
<|endoftext|>


<commit_before>/*
    This file is part of Akregator.

    Copyright (C) 2005 Frank Osterfeld <frank.osterfeld@kdemail.net>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include "akregatorconfig.h"
#include "configdialog.h"
#include "settings_advanced.h"
#include "ui_settings_appearance.h"
#include "ui_settings_archive.h"
#include "ui_settings_browser.h"
#include "ui_settings_general.h"

#include <kcombobox.h>
#include <klocale.h>

#include <QLabel>
#include <QSlider>
#include <QStringList>

namespace Akregator
{
class ConfigDialog::ConfigDialogPrivate
{
    public:
    KConfigSkeleton* config;
    SettingsAdvanced* settingsAdvanced;
    Ui::SettingsAppearance settingsAppearance;
};

ConfigDialog::ConfigDialog(QWidget* parent, const char* name, KConfigSkeleton* config, DialogType dialogType, QFlags<ButtonCode> dialogButtons, ButtonCode defaultButton, bool modal) : KConfigDialog(parent, name, config, dialogType, dialogButtons, defaultButton, modal), d(new ConfigDialogPrivate)
{
    QWidget* generalWidget = new QWidget(this);
    Ui::SettingsGeneral general;
    general.setupUi(generalWidget);

    QWidget* archiveWidget = new QWidget(this);
    Ui::SettingsArchive archive;
    archive.setupUi(archiveWidget);

    QWidget* appearanceWidget = new QWidget(this);
    d->settingsAppearance.setupUi(appearanceWidget);

    QWidget* browserWidget = new QWidget(this);
    Ui::SettingsBrowser browser;
    browser.setupUi(browserWidget);

    d->settingsAdvanced = new SettingsAdvanced(this, "Advanced");

    addPage(generalWidget, i18n("General"), "package_settings");
    addPage(archiveWidget, i18n("Archive"), "package_settings");
    addPage(appearanceWidget, i18n("Appearance"), "fonts");
    addPage(browserWidget, i18n("Browser"), "package_network");
    addPage(d->settingsAdvanced, i18n("Advanced"), "package_network");
    d->settingsAdvanced->selectFactory(Settings::archiveBackend());
    d->config = config;
}

void ConfigDialog::updateSettings()
{
    Settings::setArchiveBackend(d->settingsAdvanced->selectedFactory());
    KConfigDialog::updateSettings();
}

void ConfigDialog::updateWidgets()
{
    d->settingsAdvanced->selectFactory(Settings::archiveBackend());
    d->settingsAppearance.slider_minimumFontSize->setDisabled(d->config->isImmutable("MinimumFontSize"));
    d->settingsAppearance.slider_mediumFontSize->setDisabled(d->config->isImmutable("MediumFontSize"));
    d->settingsAppearance.lbl_MinimumFontSize->setDisabled(d->config->isImmutable("MinimumFontSize"));
    d->settingsAppearance.lbl_MediumFontSize->setDisabled(d->config->isImmutable("MediumFontSize"));
    KConfigDialog::updateSettings();
}

ConfigDialog::~ConfigDialog()
{
    delete d;
    d = 0;
}

} // namespace Akregator

#include "configdialog.moc"
<commit_msg>fix wrong call<commit_after>/*
    This file is part of Akregator.

    Copyright (C) 2005 Frank Osterfeld <frank.osterfeld@kdemail.net>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include "akregatorconfig.h"
#include "configdialog.h"
#include "settings_advanced.h"
#include "ui_settings_appearance.h"
#include "ui_settings_archive.h"
#include "ui_settings_browser.h"
#include "ui_settings_general.h"

#include <kcombobox.h>
#include <klocale.h>

#include <QLabel>
#include <QSlider>
#include <QStringList>

namespace Akregator
{
class ConfigDialog::ConfigDialogPrivate
{
    public:
    KConfigSkeleton* config;
    SettingsAdvanced* settingsAdvanced;
    Ui::SettingsAppearance settingsAppearance;
};

ConfigDialog::ConfigDialog(QWidget* parent, const char* name, KConfigSkeleton* config, DialogType dialogType, QFlags<ButtonCode> dialogButtons, ButtonCode defaultButton, bool modal) : KConfigDialog(parent, name, config, dialogType, dialogButtons, defaultButton, modal), d(new ConfigDialogPrivate)
{
    QWidget* generalWidget = new QWidget(this);
    Ui::SettingsGeneral general;
    general.setupUi(generalWidget);

    QWidget* archiveWidget = new QWidget(this);
    Ui::SettingsArchive archive;
    archive.setupUi(archiveWidget);

    QWidget* appearanceWidget = new QWidget(this);
    d->settingsAppearance.setupUi(appearanceWidget);

    QWidget* browserWidget = new QWidget(this);
    Ui::SettingsBrowser browser;
    browser.setupUi(browserWidget);

    d->settingsAdvanced = new SettingsAdvanced(this, "Advanced");

    addPage(generalWidget, i18n("General"), "package_settings");
    addPage(archiveWidget, i18n("Archive"), "package_settings");
    addPage(appearanceWidget, i18n("Appearance"), "fonts");
    addPage(browserWidget, i18n("Browser"), "package_network");
    addPage(d->settingsAdvanced, i18n("Advanced"), "package_network");
    d->settingsAdvanced->selectFactory(Settings::archiveBackend());
    d->config = config;
}

void ConfigDialog::updateSettings()
{
    Settings::setArchiveBackend(d->settingsAdvanced->selectedFactory());
    KConfigDialog::updateSettings();
}

void ConfigDialog::updateWidgets()
{
    d->settingsAdvanced->selectFactory(Settings::archiveBackend());
    d->settingsAppearance.slider_minimumFontSize->setDisabled(d->config->isImmutable("MinimumFontSize"));
    d->settingsAppearance.slider_mediumFontSize->setDisabled(d->config->isImmutable("MediumFontSize"));
    d->settingsAppearance.lbl_MinimumFontSize->setDisabled(d->config->isImmutable("MinimumFontSize"));
    d->settingsAppearance.lbl_MediumFontSize->setDisabled(d->config->isImmutable("MediumFontSize"));
    KConfigDialog::updateWidgets();
}

ConfigDialog::~ConfigDialog()
{
    delete d;
    d = 0;
}

} // namespace Akregator

#include "configdialog.moc"
<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium team:
http://bohrium.bitbucket.org

Bohrium is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3
of the License, or (at your option) any later version.

Bohrium is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BOHRIUM_BRIDGE_CPP_GENERATOR
#define __BOHRIUM_BRIDGE_CPP_GENERATOR
#include <limits>

namespace bxx {

template <typename T, typename ...Dimensions>
multi_array<T>& value(T val, const Dimensions&... shape)
{
    multi_array<T>* result = new multi_array<T>(shape...);
    result->link();

    *result = val;

    result->setTemp(true);
    return *result;
}

template <typename T, typename ...Dimensions>
multi_array<T>& empty(const Dimensions&... shape)
{
    multi_array<T>* result = new multi_array<T>(shape...);
    result->link();

    result->setTemp(true);
    return *result;
}

template <typename T, typename ...Dimensions>
multi_array<T>& ones(const Dimensions&... shape)
{
    multi_array<T>* result = new multi_array<T>(shape...);
    result->link();

    *result = (T)1;

    result->setTemp(true);
    return *result;
}

template <typename T, typename ...Dimensions>
multi_array<T>& zeros(const Dimensions&... shape)
{
    multi_array<T>* result = new multi_array<T>(shape...);
    result->link();

    *result = (T)0;

    result->setTemp(true);
    return *result;
}

//
// Random number generators
//

//
// Sugar

inline void rand_set_seed(uint64_t seed)
{
    Runtime::instance().setRandSeed(seed);
}

inline uint64_t rand_get_seed(void)
{
    return Runtime::instance().getRandSeed();
}

inline void rand_set_state(uint64_t state)
{
    Runtime::instance().setRandState(state);
}

inline uint64_t rand_get_state(void)
{
    return Runtime::instance().getRandState();
}

template <typename T, typename ...Dimensions>
multi_array<T>& random(const Dimensions&... shape)
{
    int64_t nelements = nelements_shape(shape...);

    uint64_t state  = rand_get_state();
    uint64_t key    = rand_get_seed();

    rand_set_state(state+nelements);
                                                            // Generate numbers
    multi_array<uint64_t>* rand_result = new multi_array<uint64_t>(nelements);
    rand_result->link();
    bh_random(*rand_result, state, key);
    rand_result->setTemp(true);

    multi_array<T>* result = new multi_array<T>(nelements); // Convert their type
    result->link();
    bh_identity(*result, *rand_result);
    result->setTemp(true);

    return view_as(*result, shape...);                      // Reshape them
}

template <typename T, typename ...Dimensions>
multi_array<T>& randu(const Dimensions&... shape)
{
    int64_t nelements = nelements_shape(shape...);

    uint64_t state  = rand_get_state();
    uint64_t key    = rand_get_seed();

    rand_set_state(state+nelements);
                                                            // Generate numbers
    multi_array<uint64_t>* rand_result = new multi_array<uint64_t>(nelements);
    rand_result->link();
    bh_random(*rand_result, state, key);
    rand_result->setTemp(true);

    multi_array<T>* result = new multi_array<T>(nelements); // Convert their type
    result->link();
    bh_identity(*result, *rand_result);

    bh_divide(
        *result,
        *result,
        (T)std::numeric_limits<uint64_t>::max());           // Map to [0,1]

    result->setTemp(true);
    return view_as(*result, shape...);                      // Reshape them
}

//
// End of random number generators.
//

/**
 *  Create a range of values defined as the [start, end[
 *  Each element in the range is seperated by 'skip'.
 */
template <typename T>
multi_array<T>& range(const int64_t start, const int64_t end, const int64_t skip)
{
    int64_t adj_end = end - 1;
    if ((start > end) && (skip>0)) {
        throw std::runtime_error("Error: Invalid range [start>end when skip>0].");
    } else if((start < adj_end) && (skip<0)) {
        throw std::runtime_error("Error: Invalid range [start<end when skip<0].");
    } else if (skip==0) {
        throw std::runtime_error("Error: Invalid range [skip=0].");
    } else if (start==adj_end) {
        throw std::runtime_error("Error: Invalid range [start=end].");
    }

    uint64_t nelem;
    if (skip>0) {
        nelem = (adj_end-start+1)/skip;
    } else {
        nelem = (start-adj_end+1)/abs(skip);
    }

    multi_array<T>* result = new multi_array<T>(nelem);     // Construct the result
    result->link();

    if (nelem >= std::numeric_limits<uint32_t>::max()) {    // Construct the range using uint64
        multi_array<uint64_t>* base_range = new multi_array<uint64_t>(nelem);
        base_range->link();
        bh_range(*base_range);
        base_range->setTemp(true);
        bh_identity(*result, *base_range);                  // Convert the type to T
    } else {                                                // Construct the range using uint32
        multi_array<uint32_t>* base_range = new multi_array<uint32_t>(nelem);
        base_range->link();
        bh_range(*base_range);
        base_range->setTemp(true);
        bh_identity(*result, *base_range);                  // Convert the type to T
    }

    bh_multiply(*result, *result, (T)skip);                 // Expand the range
    bh_add(*result, *result, (T)start);

    result->setTemp(true);
    return *result;
}

/**
 *  Create a range of values defined as [0, nelem[
 */
template <typename T>
multi_array<T>& range(uint64_t nelem)
{
    return range<T>((int64_t)0, (int64_t)nelem, (int64_t)1);
}

template <typename T>
multi_array<T>& linspace(int64_t begin, int64_t end, uint64_t nelem, bool endpoint)
{
    T dist = std::abs(begin - end);
    T skip = endpoint ? dist/(T)(nelem-1) : dist/(T)nelem;

    multi_array<T>* result = new multi_array<T>(nelem);     // Construct the result
    result->link();

    if (nelem >= std::numeric_limits<uint32_t>::max()) {    // Construct the range using uint64
        multi_array<uint64_t>* base_range = new multi_array<uint64_t>(nelem);
        base_range->link();
        bh_range(*base_range);
        base_range->setTemp(true);
        bh_identity(*result, *base_range);                  // Convert the type to T
    } else {                                                // Construct the range using uint32
        multi_array<uint32_t>* base_range = new multi_array<uint32_t>(nelem);
        base_range->link();
        bh_range(*base_range);
        base_range->setTemp(true);
        bh_identity(*result, *base_range);                  // Convert the type to T
    }

    // Expand the range
    bh_multiply(*result, *result, skip);
    bh_add(*result, *result, (T)begin);

    result->setTemp(true);
    return *result;
}

}
#endif
<commit_msg>Use std::abs<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium team:
http://bohrium.bitbucket.org

Bohrium is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3
of the License, or (at your option) any later version.

Bohrium is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BOHRIUM_BRIDGE_CPP_GENERATOR
#define __BOHRIUM_BRIDGE_CPP_GENERATOR
#include <limits>

namespace bxx {

template <typename T, typename ...Dimensions>
multi_array<T>& value(T val, const Dimensions&... shape)
{
    multi_array<T>* result = new multi_array<T>(shape...);
    result->link();

    *result = val;

    result->setTemp(true);
    return *result;
}

template <typename T, typename ...Dimensions>
multi_array<T>& empty(const Dimensions&... shape)
{
    multi_array<T>* result = new multi_array<T>(shape...);
    result->link();

    result->setTemp(true);
    return *result;
}

template <typename T, typename ...Dimensions>
multi_array<T>& ones(const Dimensions&... shape)
{
    multi_array<T>* result = new multi_array<T>(shape...);
    result->link();

    *result = (T)1;

    result->setTemp(true);
    return *result;
}

template <typename T, typename ...Dimensions>
multi_array<T>& zeros(const Dimensions&... shape)
{
    multi_array<T>* result = new multi_array<T>(shape...);
    result->link();

    *result = (T)0;

    result->setTemp(true);
    return *result;
}

//
// Random number generators
//

//
// Sugar

inline void rand_set_seed(uint64_t seed)
{
    Runtime::instance().setRandSeed(seed);
}

inline uint64_t rand_get_seed(void)
{
    return Runtime::instance().getRandSeed();
}

inline void rand_set_state(uint64_t state)
{
    Runtime::instance().setRandState(state);
}

inline uint64_t rand_get_state(void)
{
    return Runtime::instance().getRandState();
}

template <typename T, typename ...Dimensions>
multi_array<T>& random(const Dimensions&... shape)
{
    int64_t nelements = nelements_shape(shape...);

    uint64_t state  = rand_get_state();
    uint64_t key    = rand_get_seed();

    rand_set_state(state+nelements);
                                                            // Generate numbers
    multi_array<uint64_t>* rand_result = new multi_array<uint64_t>(nelements);
    rand_result->link();
    bh_random(*rand_result, state, key);
    rand_result->setTemp(true);

    multi_array<T>* result = new multi_array<T>(nelements); // Convert their type
    result->link();
    bh_identity(*result, *rand_result);
    result->setTemp(true);

    return view_as(*result, shape...);                      // Reshape them
}

template <typename T, typename ...Dimensions>
multi_array<T>& randu(const Dimensions&... shape)
{
    int64_t nelements = nelements_shape(shape...);

    uint64_t state  = rand_get_state();
    uint64_t key    = rand_get_seed();

    rand_set_state(state+nelements);
                                                            // Generate numbers
    multi_array<uint64_t>* rand_result = new multi_array<uint64_t>(nelements);
    rand_result->link();
    bh_random(*rand_result, state, key);
    rand_result->setTemp(true);

    multi_array<T>* result = new multi_array<T>(nelements); // Convert their type
    result->link();
    bh_identity(*result, *rand_result);

    bh_divide(
        *result,
        *result,
        (T)std::numeric_limits<uint64_t>::max());           // Map to [0,1]

    result->setTemp(true);
    return view_as(*result, shape...);                      // Reshape them
}

//
// End of random number generators.
//

/**
 *  Create a range of values defined as the [start, end[
 *  Each element in the range is seperated by 'skip'.
 */
template <typename T>
multi_array<T>& range(const int64_t start, const int64_t end, const int64_t skip)
{
    int64_t adj_end = end - 1;
    if ((start > end) && (skip>0)) {
        throw std::runtime_error("Error: Invalid range [start>end when skip>0].");
    } else if((start < adj_end) && (skip<0)) {
        throw std::runtime_error("Error: Invalid range [start<end when skip<0].");
    } else if (skip==0) {
        throw std::runtime_error("Error: Invalid range [skip=0].");
    } else if (start==adj_end) {
        throw std::runtime_error("Error: Invalid range [start=end].");
    }

    uint64_t nelem;
    if (skip>0) {
        nelem = (adj_end-start+1)/skip;
    } else {
        nelem = (start-adj_end+1)/std::abs(skip);
    }

    multi_array<T>* result = new multi_array<T>(nelem);     // Construct the result
    result->link();

    if (nelem >= std::numeric_limits<uint32_t>::max()) {    // Construct the range using uint64
        multi_array<uint64_t>* base_range = new multi_array<uint64_t>(nelem);
        base_range->link();
        bh_range(*base_range);
        base_range->setTemp(true);
        bh_identity(*result, *base_range);                  // Convert the type to T
    } else {                                                // Construct the range using uint32
        multi_array<uint32_t>* base_range = new multi_array<uint32_t>(nelem);
        base_range->link();
        bh_range(*base_range);
        base_range->setTemp(true);
        bh_identity(*result, *base_range);                  // Convert the type to T
    }

    bh_multiply(*result, *result, (T)skip);                 // Expand the range
    bh_add(*result, *result, (T)start);

    result->setTemp(true);
    return *result;
}

/**
 *  Create a range of values defined as [0, nelem[
 */
template <typename T>
multi_array<T>& range(uint64_t nelem)
{
    return range<T>((int64_t)0, (int64_t)nelem, (int64_t)1);
}

template <typename T>
multi_array<T>& linspace(int64_t begin, int64_t end, uint64_t nelem, bool endpoint)
{
    T dist = std::abs(begin - end);
    T skip = endpoint ? dist/(T)(nelem-1) : dist/(T)nelem;

    multi_array<T>* result = new multi_array<T>(nelem);     // Construct the result
    result->link();

    if (nelem >= std::numeric_limits<uint32_t>::max()) {    // Construct the range using uint64
        multi_array<uint64_t>* base_range = new multi_array<uint64_t>(nelem);
        base_range->link();
        bh_range(*base_range);
        base_range->setTemp(true);
        bh_identity(*result, *base_range);                  // Convert the type to T
    } else {                                                // Construct the range using uint32
        multi_array<uint32_t>* base_range = new multi_array<uint32_t>(nelem);
        base_range->link();
        bh_range(*base_range);
        base_range->setTemp(true);
        bh_identity(*result, *base_range);                  // Convert the type to T
    }

    // Expand the range
    bh_multiply(*result, *result, skip);
    bh_add(*result, *result, (T)begin);

    result->setTemp(true);
    return *result;
}

}
#endif
<|endoftext|>


<commit_before>#include "warnings-disable.h"

WARNINGS_DISABLE
#include <QPixmap>
#include <QPushButton>
#include <QtTest/QtTest>
WARNINGS_ENABLE

#include "../qtest-platform.h"

#include "confirmationdialog.h"
#include "elidedannotatedlabel.h"
#include "filepickerdialog.h"
#include "filepickerwidget.h"

#include "TSettings.h"

class TestSmallWidgets : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();
    void cleanupTestCase();

    void elidedAnnotatedLabel();
    void filepickerwidget();
    void filepickerdialog();
    void confirmationDialog();
};

void TestSmallWidgets::initTestCase()
{
    QCoreApplication::setOrganizationName(TEST_NAME);

    // Use a custom message handler to filter out unwanted messages
    IF_NOT_VISUAL { qInstallMessageHandler(offscreenMessageOutput); }
}

void TestSmallWidgets::cleanupTestCase()
{
    TSettings::destroy();

    // Wait up to 5 seconds to delete objects scheduled with ->deleteLater()
    QCoreApplication::processEvents(QEventLoop::AllEvents, 5000);
}

void TestSmallWidgets::elidedAnnotatedLabel()
{
    ElidedAnnotatedLabel *el = new ElidedAnnotatedLabel();

    const QString plain("grey black long piece of text again grey");
    const QString full("grey black long piece of "
                       "text again grey");
    QVector<QString> texts(3);
    texts[0] = "grey";
    texts[1] = " black long piece of text ";
    texts[2] = "again grey";
    QVector<QString> annotations(6, "");
    annotations[0] = "";
    annotations[1] = "";
    annotations[4] = "";
    annotations[5] = "";

    VISUAL_INIT(el);

    // Set up ElidedText.
    el->setElide(Qt::ElideRight);
    el->setAnnotatedText(texts, annotations);

    // The text should be fully visible if there's enough room.
    el->setGeometry(100, 100, 1000, 20);
    QVERIFY(el->text() == plain);
    QVERIFY(el->elideText().count() == full.count());
    VISUAL_WAIT;

    // The text should be elided if the widget is too narrow.
    el->setGeometry(100, 100, 100, 20);
    QVERIFY(el->text() == plain);
    QVERIFY(el->elideText().count() < full.count());
    VISUAL_WAIT;

    delete el;
}

void TestSmallWidgets::filepickerwidget()
{
    FilePickerWidget *fpw = new FilePickerWidget();

    fpw->setSettingShowSystem(true);
    QVERIFY(fpw->settingShowSystem() == true);

    fpw->setSettingHideSymlinks(true);
    QVERIFY(fpw->settingHideSymlinks() == true);

    const QString filename = QString(TEST_DIR) + "/" + "empty-file";
    fpw->setCurrentPath(filename);
    QVERIFY(fpw->getCurrentPath() == filename);

    delete fpw;
}

void TestSmallWidgets::filepickerdialog()
{
    QWidget *         widget = new QWidget();
    FilePickerDialog *fpd    = new FilePickerDialog(widget);

    QList<QUrl> myurls({QUrl("file:///tmp")});
    fpd->setSelectedUrls(myurls);
    QVERIFY(fpd->getSelectedUrls() == myurls);

    delete fpd;
    delete widget;
}

void TestSmallWidgets::confirmationDialog()
{
    ConfirmationDialog *cd = new ConfirmationDialog();
    QSignalSpy          sig_cancel(cd, SIGNAL(cancelled()));
    QSignalSpy          sig_confirmed(cd, SIGNAL(confirmed()));

    // Don't try to ->show() this, because ConfirmationDialog is a
    // QObject (which spawns windows as needed).

    // Launch the window then close it.
    cd->start("text title", "type 'confirm'", "confirm", 1, "countdown title",
              "seconds left %1", "confirmed");
    VISUAL_WAIT;
    cd->_inputDialog.close();
    VISUAL_WAIT;
    QVERIFY((sig_confirmed.count() == 0) && (sig_cancel.count() == 1));
    sig_cancel.clear();

    // Launch the window and accept it (with blank text).
    cd->start("text title", "type 'confirm'", "confirm", 1, "countdown title",
              "seconds left %1", "confirmed");
    VISUAL_WAIT;
    cd->_inputDialog.accept();
    VISUAL_WAIT;
    QVERIFY((sig_confirmed.count() == 0) && (sig_cancel.count() == 1));
    sig_cancel.clear();

    // Launch the window and accept it (with incorrect text).
    cd->start("text title", "type 'confirm'", "confirm", 1, "countdown title",
              "seconds left %1", "confirmed");
    VISUAL_WAIT;
    cd->_inputDialog.setTextValue("some kind of text");
    VISUAL_WAIT;
    cd->_inputDialog.accept();
    VISUAL_WAIT;
    QVERIFY((sig_confirmed.count() == 0) && (sig_cancel.count() == 1));
    sig_cancel.clear();

    delete cd;
}

QTEST_MAIN(TestSmallWidgets)
#include "test-small-widgets.moc"
<commit_msg>tests/small-widgets: check ConfirmationDialog previous text<commit_after>#include "warnings-disable.h"

WARNINGS_DISABLE
#include <QPixmap>
#include <QPushButton>
#include <QtTest/QtTest>
WARNINGS_ENABLE

#include "../qtest-platform.h"

#include "confirmationdialog.h"
#include "elidedannotatedlabel.h"
#include "filepickerdialog.h"
#include "filepickerwidget.h"

#include "TSettings.h"

class TestSmallWidgets : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();
    void cleanupTestCase();

    void elidedAnnotatedLabel();
    void filepickerwidget();
    void filepickerdialog();
    void confirmationDialog();
};

void TestSmallWidgets::initTestCase()
{
    QCoreApplication::setOrganizationName(TEST_NAME);

    // Use a custom message handler to filter out unwanted messages
    IF_NOT_VISUAL { qInstallMessageHandler(offscreenMessageOutput); }
}

void TestSmallWidgets::cleanupTestCase()
{
    TSettings::destroy();

    // Wait up to 5 seconds to delete objects scheduled with ->deleteLater()
    QCoreApplication::processEvents(QEventLoop::AllEvents, 5000);
}

void TestSmallWidgets::elidedAnnotatedLabel()
{
    ElidedAnnotatedLabel *el = new ElidedAnnotatedLabel();

    const QString plain("grey black long piece of text again grey");
    const QString full("grey black long piece of "
                       "text again grey");
    QVector<QString> texts(3);
    texts[0] = "grey";
    texts[1] = " black long piece of text ";
    texts[2] = "again grey";
    QVector<QString> annotations(6, "");
    annotations[0] = "";
    annotations[1] = "";
    annotations[4] = "";
    annotations[5] = "";

    VISUAL_INIT(el);

    // Set up ElidedText.
    el->setElide(Qt::ElideRight);
    el->setAnnotatedText(texts, annotations);

    // The text should be fully visible if there's enough room.
    el->setGeometry(100, 100, 1000, 20);
    QVERIFY(el->text() == plain);
    QVERIFY(el->elideText().count() == full.count());
    VISUAL_WAIT;

    // The text should be elided if the widget is too narrow.
    el->setGeometry(100, 100, 100, 20);
    QVERIFY(el->text() == plain);
    QVERIFY(el->elideText().count() < full.count());
    VISUAL_WAIT;

    delete el;
}

void TestSmallWidgets::filepickerwidget()
{
    FilePickerWidget *fpw = new FilePickerWidget();

    fpw->setSettingShowSystem(true);
    QVERIFY(fpw->settingShowSystem() == true);

    fpw->setSettingHideSymlinks(true);
    QVERIFY(fpw->settingHideSymlinks() == true);

    const QString filename = QString(TEST_DIR) + "/" + "empty-file";
    fpw->setCurrentPath(filename);
    QVERIFY(fpw->getCurrentPath() == filename);

    delete fpw;
}

void TestSmallWidgets::filepickerdialog()
{
    QWidget *         widget = new QWidget();
    FilePickerDialog *fpd    = new FilePickerDialog(widget);

    QList<QUrl> myurls({QUrl("file:///tmp")});
    fpd->setSelectedUrls(myurls);
    QVERIFY(fpd->getSelectedUrls() == myurls);

    delete fpd;
    delete widget;
}

void TestSmallWidgets::confirmationDialog()
{
    ConfirmationDialog *cd = new ConfirmationDialog();
    QSignalSpy          sig_cancel(cd, SIGNAL(cancelled()));
    QSignalSpy          sig_confirmed(cd, SIGNAL(confirmed()));

    // Don't try to ->show() this, because ConfirmationDialog is a
    // QObject (which spawns windows as needed).

    // Launch the window then close it.
    cd->start("text title", "type 'confirm'", "confirm", 1, "countdown title",
              "seconds left %1", "confirmed");
    VISUAL_WAIT;
    cd->_inputDialog.close();
    VISUAL_WAIT;
    QVERIFY((sig_confirmed.count() == 0) && (sig_cancel.count() == 1));
    sig_cancel.clear();

    // Launch the window and accept it (with blank text).
    cd->start("text title", "type 'confirm'", "confirm", 1, "countdown title",
              "seconds left %1", "confirmed");
    VISUAL_WAIT;
    cd->_inputDialog.accept();
    VISUAL_WAIT;
    QVERIFY((sig_confirmed.count() == 0) && (sig_cancel.count() == 1));
    sig_cancel.clear();

    // Launch the window and accept it (with incorrect text).
    cd->start("text title", "type 'confirm'", "confirm", 1, "countdown title",
              "seconds left %1", "confirmed");
    VISUAL_WAIT;
    cd->_inputDialog.setTextValue("some kind of text");
    VISUAL_WAIT;
    cd->_inputDialog.accept();
    VISUAL_WAIT;
    QVERIFY((sig_confirmed.count() == 0) && (sig_cancel.count() == 1));
    sig_cancel.clear();

    // Launch the window and accept it (with too-long text).
    cd->start("text title", "type 'confirm'", "confirm", 1, "countdown title",
              "seconds left %1", "confirmed");
    QVERIFY(cd->_inputDialog.textValue() == "");
    VISUAL_WAIT;
    cd->_inputDialog.setTextValue("confirmnot");
    VISUAL_WAIT;
    cd->_inputDialog.accept();
    VISUAL_WAIT;
    QVERIFY((sig_confirmed.count() == 0) && (sig_cancel.count() == 1));
    sig_cancel.clear();

    delete cd;
}

QTEST_MAIN(TestSmallWidgets)
#include "test-small-widgets.moc"
<|endoftext|>


<commit_before>/* +---------------------------------------------------------------------------+
   |                 The Mobile Robot Programming Toolkit (MRPT)               |
   |                                                                           |
   |                          http://www.mrpt.org/                             |
   |                                                                           |
   | Copyright (c) 2005-2012, Individual contributors, see AUTHORS file        |
   | Copyright (c) 2005-2012, MAPIR group, University of Malaga                |
   | Copyright (c) 2012, University of Almeria                                 |
   | All rights reserved.                                                      |
   |                                                                           |
   | Redistribution and use in source and binary forms, with or without        |
   | modification, are permitted provided that the following conditions are    |
   | met:                                                                      |
   |    * Redistributions of source code must retain the above copyright       |
   |      notice, this list of conditions and the following disclaimer.        |
   |    * Redistributions in binary form must reproduce the above copyright    |
   |      notice, this list of conditions and the following disclaimer in the  |
   |      documentation and/or other materials provided with the distribution. |
   |    * Neither the name of the copyright holders nor the                    |
   |      names of its contributors may be used to endorse or promote products |
   |      derived from this software without specific prior written permission.|
   |                                                                           |
   | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       |
   | 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
   | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR|
   | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE |
   | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL|
   | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR|
   |  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)       |
   | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,       |
   | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN  |
   | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE           |
   | POSSIBILITY OF SUCH DAMAGE.                                               |
   +---------------------------------------------------------------------------+ */

#include <mrpt/hwdrivers.h>  // Precompiled headers
#include <mrpt/hwdrivers/CRaePID.h>

#include <iostream>
#include <sstream>

#ifdef MRPT_OS_WINDOWS
	#  if defined(__GNUC__)
		// MinGW: Nothing to do here (yet)
	# else

	# endif
//#include <windows.h> // Rly needed?
#endif

using namespace mrpt::utils;
using namespace mrpt::hwdrivers;

IMPLEMENTS_GENERIC_SENSOR(CRaePID,mrpt::hwdrivers)

CRaePID::CRaePID()
{
	m_sensorLabel = "RAE_PID";
}

void  CRaePID::loadConfig_sensorSpecific(
	const mrpt::utils::CConfigFileBase &configSource,
	const std::string			&iniSection )
{
		pose_x = configSource.read_float(iniSection,"pose_x",0,true);
		pose_y = configSource.read_float(iniSection,"pose_y",0,true);
		pose_z = configSource.read_float(iniSection,"pose_z",0,true);
		pose_roll = configSource.read_float(iniSection,"pose_roll",0,true);
		pose_pitch = configSource.read_float(iniSection,"pose_pitch",0,true);
		pose_yaw = configSource.read_float(iniSection,"pose_yaw",0,true);
	#ifdef MRPT_OS_WINDOWS
		com_port = configSource.read_string(iniSection, "COM_port_PID", "COM1", true ) ;
	#else
		com_port = configSource.read_string(iniSection, "COM_port_PID", "/dev/tty0", true );
	#endif
		COM.open(com_port);
		COM.setConfig(9600,0,8,1,true);
		mrpt::system::sleep(10);
		COM.purgeBuffers();
		mrpt::system::sleep(10);
		COM.setTimeouts(50,1,100, 1,20);
	//std::cout << "PASA config" << std::endl;
}

void CRaePID::doProcess()
{
	// Send the command
	COM.purgeBuffers();
	COM.Write("R",1);

	// Read the returned text
	std::string power_reading;
	power_reading = COM.ReadString();

	// Convert the text to a number (ppm)
	const float readnum = atof(power_reading.c_str());
	const float val_ppm = readnum/1000;

	// Fill the observation
	mrpt::slam::CObservationGasSensors::TObservationENose obs;
	obs.readingsVoltage.push_back(val_ppm);

	CObservationGasSensors obsG;
	obsG.sensorLabel = this->getSensorLabel();
	obsG.m_readings.push_back(obs);
	obsG.timestamp = now();

	appendObservation(CObservationGasSensorsPtr(new CObservationGasSensors(obsG)));

}

std::string CRaePID::getFirmware()
{
	// Send the command
	COM.purgeBuffers();
	COM.Write("F",1);

	// Read the returned text
	return COM.ReadString();
}

std::string CRaePID::getModel()
{
	// Send the command
	COM.purgeBuffers();
	COM.Write("M",1);

	// Read the returned text
	return COM.ReadString();
}

std::string CRaePID::getSerialNumber()
{
	// Send the command
	COM.purgeBuffers();
	COM.Write("S",1);

	// Read the returned text
	return COM.ReadString();
}

std::string CRaePID::getName()
{
	// Send the command
	COM.purgeBuffers();
	COM.Write("N",1);

	// Read the returned text
	return COM.ReadString();

}

bool CRaePID::switchPower()
{
	// Send the command
	COM.purgeBuffers();
	COM.Write("P",1);

	// Read the returned text
	std::string reading;
	reading = COM.ReadString();

	if (strcmp(reading.c_str(),"Sleep...")==0)
		return true;
	else
		return false;
}

CObservationGasSensors CRaePID::getFullInfo()
{
	// Send the command
	COM.purgeBuffers();
	COM.Write("C",1);

	// Read the returned text
	std::string reading;
	reading = COM.ReadString();

	// Iterate over each information component (tokenize first)
	// construct a stream from the string (as seen in http://stackoverflow.com/a/53921)
	std::stringstream readings_str(reading);

	// use stream iterators to copy the stream to the vector as whitespace separated strings
	std::istream_iterator<std::string> it(readings_str);
	std::istream_iterator<std::string> endit;
	std::vector<std::string> measurements_text(it, endit);

	// Convert the text to a number (ppm)
	mrpt::slam::CObservationGasSensors::TObservationENose obs;
	CObservationGasSensors obsG;

	for (size_t k=0; k < measurements_text.size(); k++)
	{
		const float readnum = atof(measurements_text[k].c_str());
		const float val_ppm = readnum/1000.f;

		// Fill the observation
		obs.readingsVoltage.push_back(val_ppm);
		obsG.m_readings.push_back(obs);
	}

	obsG.sensorLabel = this->getSensorLabel();
	obsG.timestamp = now();

	return obsG;

}

bool CRaePID::errorStatus(std::string &errorString)
{
	// Send the command
	COM.purgeBuffers();
	COM.Write("E",1);

	// Read the returned text
	std::string reading;
	reading = COM.ReadString();

	// Tokenize to separate the two components:
	// construct a stream from the string (as seen in http://stackoverflow.com/a/53921)
	std::stringstream readings_str(reading);

	// use stream iterators to copy the stream to the vector as whitespace separated strings
	std::istream_iterator<std::string> it(readings_str);
	std::istream_iterator<std::string> endit;
	std::vector<std::string> errors_text(it, endit);

	// Take the first part and check the possible error condition
	if((strcmp(errors_text[0].c_str(),"0")==0) && (strcmp(errors_text[1].c_str(),"0")==0)) // no error
	{
		return false;
	}
	else
	{
		// By the moment, return the raw error; note that if necessary a detailed description of the error can be obtained analyzing the two error strings separately
		errorString = reading;
		return true;
	}
}

void CRaePID::getLimits(float &min, float &max)
{
	// Send the command
	COM.purgeBuffers();
	COM.Write("L",1);

	// Read the returned text
	std::string reading;
	reading = COM.ReadString();

	// Tokenize to separate the two components:
	// construct a stream from the string (as seen in http://stackoverflow.com/a/53921)
	std::stringstream readings_str(reading);

	// use stream iterators to copy the stream to the vector as whitespace separated strings
	std::istream_iterator<std::string> it(readings_str);
	std::istream_iterator<std::string> endit;
	std::vector<std::string> readings_text(it, endit);

	// read min and max
	max = atof(readings_text[0].c_str());
	min = atof(readings_text[1].c_str());

}
<commit_msg>fixed error when wrapping the PID readings to a CObservationGasSensors. It requires to add couples <vqalues - sensor type> sensor type used 0xFFFF<commit_after>/* +---------------------------------------------------------------------------+
   |                 The Mobile Robot Programming Toolkit (MRPT)               |
   |                                                                           |
   |                          http://www.mrpt.org/                             |
   |                                                                           |
   | Copyright (c) 2005-2012, Individual contributors, see AUTHORS file        |
   | Copyright (c) 2005-2012, MAPIR group, University of Malaga                |
   | Copyright (c) 2012, University of Almeria                                 |
   | All rights reserved.                                                      |
   |                                                                           |
   | Redistribution and use in source and binary forms, with or without        |
   | modification, are permitted provided that the following conditions are    |
   | met:                                                                      |
   |    * Redistributions of source code must retain the above copyright       |
   |      notice, this list of conditions and the following disclaimer.        |
   |    * Redistributions in binary form must reproduce the above copyright    |
   |      notice, this list of conditions and the following disclaimer in the  |
   |      documentation and/or other materials provided with the distribution. |
   |    * Neither the name of the copyright holders nor the                    |
   |      names of its contributors may be used to endorse or promote products |
   |      derived from this software without specific prior written permission.|
   |                                                                           |
   | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       |
   | 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
   | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR|
   | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE |
   | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL|
   | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR|
   |  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)       |
   | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,       |
   | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN  |
   | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE           |
   | POSSIBILITY OF SUCH DAMAGE.                                               |
   +---------------------------------------------------------------------------+ */

#include <mrpt/hwdrivers.h>  // Precompiled headers
#include <mrpt/hwdrivers/CRaePID.h>

#include <iostream>
#include <sstream>

#ifdef MRPT_OS_WINDOWS
	#  if defined(__GNUC__)
		// MinGW: Nothing to do here (yet)
	# else

	# endif
//#include <windows.h> // Rly needed?
#endif

using namespace mrpt::utils;
using namespace mrpt::hwdrivers;

IMPLEMENTS_GENERIC_SENSOR(CRaePID,mrpt::hwdrivers)

CRaePID::CRaePID()
{
	m_sensorLabel = "RAE_PID";
}

void  CRaePID::loadConfig_sensorSpecific(
	const mrpt::utils::CConfigFileBase &configSource,
	const std::string			&iniSection )
{
		pose_x = configSource.read_float(iniSection,"pose_x",0,true);
		pose_y = configSource.read_float(iniSection,"pose_y",0,true);
		pose_z = configSource.read_float(iniSection,"pose_z",0,true);
		pose_roll = configSource.read_float(iniSection,"pose_roll",0,true);
		pose_pitch = configSource.read_float(iniSection,"pose_pitch",0,true);
		pose_yaw = configSource.read_float(iniSection,"pose_yaw",0,true);
	#ifdef MRPT_OS_WINDOWS
		com_port = configSource.read_string(iniSection, "COM_port_PID", "COM1", true ) ;
	#else
		com_port = configSource.read_string(iniSection, "COM_port_PID", "/dev/tty0", true );
	#endif
		COM.open(com_port);
		COM.setConfig(9600,0,8,1,true);
		mrpt::system::sleep(10);
		COM.purgeBuffers();
		mrpt::system::sleep(10);
		COM.setTimeouts(50,1,100, 1,20);
	//std::cout << "PASA config" << std::endl;
}

void CRaePID::doProcess()
{
	// Send the command
	COM.purgeBuffers();
	COM.Write("R",1);

	// Read the returned text
	std::string power_reading;
	power_reading = COM.ReadString();

	// Convert the text to a number (ppm)
	const float readnum = atof(power_reading.c_str());
	const float val_ppm = readnum/1000;

	// Fill the observation
	mrpt::slam::CObservationGasSensors::TObservationENose obs;
	obs.readingsVoltage.push_back(val_ppm);
	obs.sensorTypes.push_back(0xFFFF);

	CObservationGasSensors obsG;
	obsG.sensorLabel = this->getSensorLabel();
	obsG.m_readings.push_back(obs);
	obsG.timestamp = now();

	appendObservation(CObservationGasSensorsPtr(new CObservationGasSensors(obsG)));

}

std::string CRaePID::getFirmware()
{
	// Send the command
	COM.purgeBuffers();
	COM.Write("F",1);

	// Read the returned text
	return COM.ReadString();
}

std::string CRaePID::getModel()
{
	// Send the command
	COM.purgeBuffers();
	COM.Write("M",1);

	// Read the returned text
	return COM.ReadString();
}

std::string CRaePID::getSerialNumber()
{
	// Send the command
	COM.purgeBuffers();
	COM.Write("S",1);

	// Read the returned text
	return COM.ReadString();
}

std::string CRaePID::getName()
{
	// Send the command
	COM.purgeBuffers();
	COM.Write("N",1);

	// Read the returned text
	return COM.ReadString();

}

bool CRaePID::switchPower()
{
	// Send the command
	COM.purgeBuffers();
	COM.Write("P",1);

	// Read the returned text
	std::string reading;
	reading = COM.ReadString();

	if (strcmp(reading.c_str(),"Sleep...")==0)
		return true;
	else
		return false;
}

CObservationGasSensors CRaePID::getFullInfo()
{
	// Send the command
	COM.purgeBuffers();
	COM.Write("C",1);

	// Read the returned text
	std::string reading;
	reading = COM.ReadString();

	// Iterate over each information component (tokenize first)
	// construct a stream from the string (as seen in http://stackoverflow.com/a/53921)
	std::stringstream readings_str(reading);

	// use stream iterators to copy the stream to the vector as whitespace separated strings
	std::istream_iterator<std::string> it(readings_str);
	std::istream_iterator<std::string> endit;
	std::vector<std::string> measurements_text(it, endit);

	// Convert the text to a number (ppm)
	mrpt::slam::CObservationGasSensors::TObservationENose obs;
	CObservationGasSensors obsG;

	for (size_t k=0; k < measurements_text.size(); k++)
	{
		const float readnum = atof(measurements_text[k].c_str());
		const float val_ppm = readnum/1000.f;

		// Fill the observation
		obs.readingsVoltage.push_back(val_ppm);
		obsG.m_readings.push_back(obs);
	}

	obsG.sensorLabel = this->getSensorLabel();
	obsG.timestamp = now();

	return obsG;

}

bool CRaePID::errorStatus(std::string &errorString)
{
	// Send the command
	COM.purgeBuffers();
	COM.Write("E",1);

	// Read the returned text
	std::string reading;
	reading = COM.ReadString();

	// Tokenize to separate the two components:
	// construct a stream from the string (as seen in http://stackoverflow.com/a/53921)
	std::stringstream readings_str(reading);

	// use stream iterators to copy the stream to the vector as whitespace separated strings
	std::istream_iterator<std::string> it(readings_str);
	std::istream_iterator<std::string> endit;
	std::vector<std::string> errors_text(it, endit);

	// Take the first part and check the possible error condition
	if((strcmp(errors_text[0].c_str(),"0")==0) && (strcmp(errors_text[1].c_str(),"0")==0)) // no error
	{
		return false;
	}
	else
	{
		// By the moment, return the raw error; note that if necessary a detailed description of the error can be obtained analyzing the two error strings separately
		errorString = reading;
		return true;
	}
}

void CRaePID::getLimits(float &min, float &max)
{
	// Send the command
	COM.purgeBuffers();
	COM.Write("L",1);

	// Read the returned text
	std::string reading;
	reading = COM.ReadString();

	// Tokenize to separate the two components:
	// construct a stream from the string (as seen in http://stackoverflow.com/a/53921)
	std::stringstream readings_str(reading);

	// use stream iterators to copy the stream to the vector as whitespace separated strings
	std::istream_iterator<std::string> it(readings_str);
	std::istream_iterator<std::string> endit;
	std::vector<std::string> readings_text(it, endit);

	// read min and max
	max = atof(readings_text[0].c_str());
	min = atof(readings_text[1].c_str());

}
<|endoftext|>


<commit_before>/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          https://www.mrpt.org/                         |
   |                                                                        |
   | Copyright (c) 2005-2019, Individual contributors, see AUTHORS file     |
   | See: https://www.mrpt.org/Authors - All rights reserved.               |
   | Released under BSD License. See: https://www.mrpt.org/License          |
   +------------------------------------------------------------------------+ */

#include "opengl-precomp.h"  // Precompiled header

#include <mrpt/math/CMatrixF.h>
#include <mrpt/math/TLine3D.h>
#include <mrpt/math/geometry.h>
#include <mrpt/math/matrix_serialization.h>
#include <mrpt/opengl/CEllipsoid.h>
#include <mrpt/serialization/CArchive.h>
#include <Eigen/Dense>
#include "opengl_internals.h"

using namespace mrpt;
using namespace mrpt::opengl;
using namespace mrpt::math;
using namespace std;

IMPLEMENTS_SERIALIZABLE(CEllipsoid, CRenderizableDisplayList, mrpt::opengl)

/*---------------------------------------------------------------
							render
  ---------------------------------------------------------------*/
void CEllipsoid::render_dl() const
{
#if MRPT_HAS_OPENGL_GLUT
	MRPT_START

	const size_t dim = m_cov.cols();

	if (m_eigVal(0, 0) != 0.0 && m_eigVal(1, 1) != 0.0 &&
		(dim == 2 || m_eigVal(2, 2) != 0.0) && m_quantiles != 0.0)
	{
		glEnable(GL_BLEND);
		checkOpenGLError();
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		checkOpenGLError();
		glLineWidth(m_lineWidth);
		checkOpenGLError();

		if (dim == 2)
		{
			glDisable(GL_LIGHTING);  // Disable lights when drawing lines

			// ---------------------
			//     2D ellipse
			// ---------------------

			/* Equivalent MATLAB code:
			 *
			 * q=1;
			 * [vec val]=eig(C);
			 * M=(q*val*vec)';
			 * R=M*[x;y];
			 * xx=R(1,:);yy=R(2,:);
			 * plot(xx,yy), axis equal;
			 */

			double ang;
			unsigned int i;

			// Compute the new vectors for the ellipsoid:
			auto M = CMatrixDouble(m_eigVal.asEigen() * m_eigVec.transpose());
			M *= double(m_quantiles);

			glBegin(GL_LINE_LOOP);

			// Compute the points of the 2D ellipse:
			for (i = 0, ang = 0; i < m_2D_segments;
				 i++, ang += (M_2PI / m_2D_segments))
			{
				double ccos = cos(ang);
				double ssin = sin(ang);

				const float x = ccos * M(0, 0) + ssin * M(1, 0);
				const float y = ccos * M(0, 1) + ssin * M(1, 1);

				glVertex2f(x, y);
			}  // end for points on ellipse

			glEnd();

			// 2D: Save bounding box:
			const double max_radius =
				m_quantiles * std::max(m_eigVal(0, 0), m_eigVal(1, 1));
			m_bb_min = mrpt::math::TPoint3D(-max_radius, -max_radius, 0);
			m_bb_max = mrpt::math::TPoint3D(max_radius, max_radius, 0);
			// Convert to coordinates of my parent:
			m_pose.composePoint(m_bb_min, m_bb_min);
			m_pose.composePoint(m_bb_max, m_bb_max);

			glEnable(GL_LIGHTING);
		}
		else
		{
			// ---------------------
			//    3D ellipsoid
			// ---------------------
			GLfloat mat[16];

			//  A homogeneous transformation matrix, in this order:
			//
			//     0  4  8  12
			//     1  5  9  13
			//     2  6  10 14
			//     3  7  11 15
			//
			mat[3] = mat[7] = mat[11] = 0;
			mat[15] = 1;
			mat[12] = mat[13] = mat[14] = 0;

			mat[0] = m_eigVec(0, 0);
			mat[1] = m_eigVec(1, 0);
			mat[2] = m_eigVec(2, 0);  // New X-axis
			mat[4] = m_eigVec(0, 1);
			mat[5] = m_eigVec(1, 1);
			mat[6] = m_eigVec(2, 1);  // New X-axis
			mat[8] = m_eigVec(0, 2);
			mat[9] = m_eigVec(1, 2);
			mat[10] = m_eigVec(2, 2);  // New X-axis

			GLUquadricObj* obj = gluNewQuadric();
			checkOpenGLError();

			if (!m_drawSolid3D)
				glDisable(GL_LIGHTING);  // Disable lights when drawing lines

			gluQuadricDrawStyle(obj, m_drawSolid3D ? GLU_FILL : GLU_LINE);

			glPushMatrix();
			glMultMatrixf(mat);
			glScalef(
				m_eigVal(0, 0) * m_quantiles, m_eigVal(1, 1) * m_quantiles,
				m_eigVal(2, 2) * m_quantiles);

			gluSphere(obj, 1, m_3D_segments, m_3D_segments);
			checkOpenGLError();

			glPopMatrix();

			gluDeleteQuadric(obj);
			checkOpenGLError();

			// 3D: Save bounding box:
			const double max_radius =
				m_quantiles *
				std::max(
					m_eigVal(0, 0), std::max(m_eigVal(1, 1), m_eigVal(2, 2)));
			m_bb_min = mrpt::math::TPoint3D(-max_radius, -max_radius, 0);
			m_bb_max = mrpt::math::TPoint3D(max_radius, max_radius, 0);
			// Convert to coordinates of my parent:
			m_pose.composePoint(m_bb_min, m_bb_min);
			m_pose.composePoint(m_bb_max, m_bb_max);
		}

		glDisable(GL_BLEND);

		glEnable(GL_LIGHTING);
	}
	MRPT_END_WITH_CLEAN_UP(cout << "Covariance matrix leading to error is:"
								<< endl
								<< m_cov << endl;);
#endif
}

uint8_t CEllipsoid::serializeGetVersion() const { return 1; }
void CEllipsoid::serializeTo(mrpt::serialization::CArchive& out) const
{
	writeToStreamRender(out);
	out << m_cov << m_drawSolid3D << m_quantiles << (uint32_t)m_2D_segments
		<< (uint32_t)m_3D_segments << m_lineWidth;
}

void CEllipsoid::serializeFrom(
	mrpt::serialization::CArchive& in, uint8_t version)
{
	switch (version)
	{
		case 0:
		case 1:
		{
			uint32_t i;
			readFromStreamRender(in);
			if (version == 0)
			{
				CMatrixF c;
				in >> c;
				m_cov = c.cast_double();
			}
			else
			{
				in >> m_cov;
			}

			in >> m_drawSolid3D >> m_quantiles;
			in >> i;
			m_2D_segments = i;
			in >> i;
			m_3D_segments = i;
			in >> m_lineWidth;

			// Update cov. matrix cache:
			m_prevComputedCov = m_cov;
			setCovMatrix(m_cov);
		}
		break;
		default:
			MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(version);
	};
	CRenderizableDisplayList::notifyChange();
}

bool quickSolveEqn(double a, double b_2, double c, double& t)
{
	double delta = square(b_2) - a * c;
	if (delta == 0)
		return (t = -b_2 / a) >= 0;
	else if (delta > 0)
	{
		delta = sqrt(delta);
		if ((t = (-b_2 - delta) / a) >= 0)
			return true;
		else
			return (t = (-b_2 + delta) / a) >= 0;
	}
	else
		return false;
}

bool CEllipsoid::traceRay(const mrpt::poses::CPose3D& o, double& dist) const
{
	if (m_cov.rows() != 3) return false;
	TLine3D lin, lin2;
	createFromPoseX((o - this->m_pose).asTPose(), lin);
	lin.unitarize();  // By adding this line, distance from any point of the
	// line to its base is exactly equal to the "t".
	for (size_t i = 0; i < 3; i++)
	{
		lin2.pBase[i] = 0;
		lin2.director[i] = 0;
		for (size_t j = 0; j < 3; j++)
		{
			double vji = m_eigVec(j, i);
			lin2.pBase[i] += vji * lin.pBase[j];
			lin2.director[i] += vji * lin.director[j];
		}
	}
	double a = 0, b_2 = 0, c = -square(m_quantiles);
	for (size_t i = 0; i < 3; i++)
	{
		double ev = m_eigVal(i, i);
		a += square(lin2.director[i] / ev);
		b_2 += lin2.director[i] * lin2.pBase[i] / square(ev);
		c += square(lin2.pBase[i] / ev);
	}
	return quickSolveEqn(a, b_2, c, dist);
}

void CEllipsoid::setCovMatrix(
	const mrpt::math::CMatrixDouble& m, int resizeToSize)
{
	MRPT_START

	ASSERT_(m.cols() == m.rows());
	ASSERT_(
		m.rows() == 2 || m.rows() == 3 ||
		(resizeToSize > 0 && (resizeToSize == 2 || resizeToSize == 3)));

	m_cov = m;
	if (resizeToSize > 0 && resizeToSize < (int)m.rows())
		m_cov.setSize(resizeToSize, resizeToSize);

	if (m_cov == m_prevComputedCov) return;  // Done.

	CRenderizableDisplayList::notifyChange();

	// Handle the special case of an ellipsoid of volume = 0
	const double d = m_cov.det();
	if (d == 0 || d != d)  // Note: "d!=d" is a great test for invalid numbers,
	// don't remove!
	{
		// All zeros:
		m_prevComputedCov = m_cov;
		m_eigVec.setZero(3, 3);
		m_eigVal.setZero(3, 3);
	}
	else
	{
		// Not null matrix: compute the eigen-vectors & values:
		m_prevComputedCov = m_cov;
		std::vector<double> eigvals;
		if (m_cov.eig_symmetric(m_eigVec, eigvals))
		{
			// Do the scale at render to avoid recomputing the m_eigVal for
			// different m_quantiles
			m_eigVal.setDiagonal(eigvals);
			m_eigVal.array() = m_eigVal.array().sqrt().matrix();
		}
		else
		{
			m_eigVec.setZero(3, 3);
			m_eigVal.setZero(3, 3);
		}
	}

	MRPT_END
}

void CEllipsoid::setCovMatrix(
	const mrpt::math::CMatrixFloat& m, int resizeToSize)
{
	CRenderizableDisplayList::notifyChange();
	setCovMatrix(CMatrixDouble(m), resizeToSize);
}

/** Evaluates the bounding box of this object (including possible children) in
 * the coordinate frame of the object parent. */
void CEllipsoid::getBoundingBox(
	mrpt::math::TPoint3D& bb_min, mrpt::math::TPoint3D& bb_max) const
{
	bb_min = m_bb_min;
	bb_max = m_bb_max;
}
<commit_msg>fix bug in rendering ellipsoid after deserializing<commit_after>/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          https://www.mrpt.org/                         |
   |                                                                        |
   | Copyright (c) 2005-2019, Individual contributors, see AUTHORS file     |
   | See: https://www.mrpt.org/Authors - All rights reserved.               |
   | Released under BSD License. See: https://www.mrpt.org/License          |
   +------------------------------------------------------------------------+ */

#include "opengl-precomp.h"  // Precompiled header

#include <mrpt/math/CMatrixF.h>
#include <mrpt/math/TLine3D.h>
#include <mrpt/math/geometry.h>
#include <mrpt/math/matrix_serialization.h>
#include <mrpt/opengl/CEllipsoid.h>
#include <mrpt/serialization/CArchive.h>
#include <Eigen/Dense>
#include "opengl_internals.h"

using namespace mrpt;
using namespace mrpt::opengl;
using namespace mrpt::math;
using namespace std;

IMPLEMENTS_SERIALIZABLE(CEllipsoid, CRenderizableDisplayList, mrpt::opengl)

/*---------------------------------------------------------------
							render
  ---------------------------------------------------------------*/
void CEllipsoid::render_dl() const
{
#if MRPT_HAS_OPENGL_GLUT
	MRPT_START

	const size_t dim = m_cov.cols();

	if (m_eigVal(0, 0) != 0.0 && m_eigVal(1, 1) != 0.0 &&
		(dim == 2 || m_eigVal(2, 2) != 0.0) && m_quantiles != 0.0)
	{
		glEnable(GL_BLEND);
		checkOpenGLError();
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		checkOpenGLError();
		glLineWidth(m_lineWidth);
		checkOpenGLError();

		if (dim == 2)
		{
			glDisable(GL_LIGHTING);  // Disable lights when drawing lines

			// ---------------------
			//     2D ellipse
			// ---------------------

			/* Equivalent MATLAB code:
			 *
			 * q=1;
			 * [vec val]=eig(C);
			 * M=(q*val*vec)';
			 * R=M*[x;y];
			 * xx=R(1,:);yy=R(2,:);
			 * plot(xx,yy), axis equal;
			 */

			double ang;
			unsigned int i;

			// Compute the new vectors for the ellipsoid:
			auto M = CMatrixDouble(m_eigVal.asEigen() * m_eigVec.transpose());
			M *= double(m_quantiles);

			glBegin(GL_LINE_LOOP);

			// Compute the points of the 2D ellipse:
			for (i = 0, ang = 0; i < m_2D_segments;
				 i++, ang += (M_2PI / m_2D_segments))
			{
				double ccos = cos(ang);
				double ssin = sin(ang);

				const float x = ccos * M(0, 0) + ssin * M(1, 0);
				const float y = ccos * M(0, 1) + ssin * M(1, 1);

				glVertex2f(x, y);
			}  // end for points on ellipse

			glEnd();

			// 2D: Save bounding box:
			const double max_radius =
				m_quantiles * std::max(m_eigVal(0, 0), m_eigVal(1, 1));
			m_bb_min = mrpt::math::TPoint3D(-max_radius, -max_radius, 0);
			m_bb_max = mrpt::math::TPoint3D(max_radius, max_radius, 0);
			// Convert to coordinates of my parent:
			m_pose.composePoint(m_bb_min, m_bb_min);
			m_pose.composePoint(m_bb_max, m_bb_max);

			glEnable(GL_LIGHTING);
		}
		else
		{
			// ---------------------
			//    3D ellipsoid
			// ---------------------
			GLfloat mat[16];

			//  A homogeneous transformation matrix, in this order:
			//
			//     0  4  8  12
			//     1  5  9  13
			//     2  6  10 14
			//     3  7  11 15
			//
			mat[3] = mat[7] = mat[11] = 0;
			mat[15] = 1;
			mat[12] = mat[13] = mat[14] = 0;

			mat[0] = m_eigVec(0, 0);
			mat[1] = m_eigVec(1, 0);
			mat[2] = m_eigVec(2, 0);  // New X-axis
			mat[4] = m_eigVec(0, 1);
			mat[5] = m_eigVec(1, 1);
			mat[6] = m_eigVec(2, 1);  // New X-axis
			mat[8] = m_eigVec(0, 2);
			mat[9] = m_eigVec(1, 2);
			mat[10] = m_eigVec(2, 2);  // New X-axis

			GLUquadricObj* obj = gluNewQuadric();
			checkOpenGLError();

			if (!m_drawSolid3D)
				glDisable(GL_LIGHTING);  // Disable lights when drawing lines

			gluQuadricDrawStyle(obj, m_drawSolid3D ? GLU_FILL : GLU_LINE);

			glPushMatrix();
			glMultMatrixf(mat);
			glScalef(
				m_eigVal(0, 0) * m_quantiles, m_eigVal(1, 1) * m_quantiles,
				m_eigVal(2, 2) * m_quantiles);

			gluSphere(obj, 1, m_3D_segments, m_3D_segments);
			checkOpenGLError();

			glPopMatrix();

			gluDeleteQuadric(obj);
			checkOpenGLError();

			// 3D: Save bounding box:
			const double max_radius =
				m_quantiles *
				std::max(
					m_eigVal(0, 0), std::max(m_eigVal(1, 1), m_eigVal(2, 2)));
			m_bb_min = mrpt::math::TPoint3D(-max_radius, -max_radius, 0);
			m_bb_max = mrpt::math::TPoint3D(max_radius, max_radius, 0);
			// Convert to coordinates of my parent:
			m_pose.composePoint(m_bb_min, m_bb_min);
			m_pose.composePoint(m_bb_max, m_bb_max);
		}

		glDisable(GL_BLEND);

		glEnable(GL_LIGHTING);
	}
	MRPT_END_WITH_CLEAN_UP(cout << "Covariance matrix leading to error is:"
								<< endl
								<< m_cov << endl;);
#endif
}

uint8_t CEllipsoid::serializeGetVersion() const { return 1; }
void CEllipsoid::serializeTo(mrpt::serialization::CArchive& out) const
{
	writeToStreamRender(out);
	out << m_cov << m_drawSolid3D << m_quantiles << (uint32_t)m_2D_segments
		<< (uint32_t)m_3D_segments << m_lineWidth;
}

void CEllipsoid::serializeFrom(
	mrpt::serialization::CArchive& in, uint8_t version)
{
	switch (version)
	{
		case 0:
		case 1:
		{
			uint32_t i;
			readFromStreamRender(in);
			if (version == 0)
			{
				CMatrixF c;
				in >> c;
				m_cov = c.cast_double();
			}
			else
			{
				in >> m_cov;
			}

			in >> m_drawSolid3D >> m_quantiles;
			in >> i;
			m_2D_segments = i;
			in >> i;
			m_3D_segments = i;
			in >> m_lineWidth;

			// Update cov. matrix cache:
			setCovMatrix(m_cov);
		}
		break;
		default:
			MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(version);
	};
	CRenderizableDisplayList::notifyChange();
}

bool quickSolveEqn(double a, double b_2, double c, double& t)
{
	double delta = square(b_2) - a * c;
	if (delta == 0)
		return (t = -b_2 / a) >= 0;
	else if (delta > 0)
	{
		delta = sqrt(delta);
		if ((t = (-b_2 - delta) / a) >= 0)
			return true;
		else
			return (t = (-b_2 + delta) / a) >= 0;
	}
	else
		return false;
}

bool CEllipsoid::traceRay(const mrpt::poses::CPose3D& o, double& dist) const
{
	if (m_cov.rows() != 3) return false;
	TLine3D lin, lin2;
	createFromPoseX((o - this->m_pose).asTPose(), lin);
	lin.unitarize();  // By adding this line, distance from any point of the
	// line to its base is exactly equal to the "t".
	for (size_t i = 0; i < 3; i++)
	{
		lin2.pBase[i] = 0;
		lin2.director[i] = 0;
		for (size_t j = 0; j < 3; j++)
		{
			double vji = m_eigVec(j, i);
			lin2.pBase[i] += vji * lin.pBase[j];
			lin2.director[i] += vji * lin.director[j];
		}
	}
	double a = 0, b_2 = 0, c = -square(m_quantiles);
	for (size_t i = 0; i < 3; i++)
	{
		double ev = m_eigVal(i, i);
		a += square(lin2.director[i] / ev);
		b_2 += lin2.director[i] * lin2.pBase[i] / square(ev);
		c += square(lin2.pBase[i] / ev);
	}
	return quickSolveEqn(a, b_2, c, dist);
}

void CEllipsoid::setCovMatrix(
	const mrpt::math::CMatrixDouble& m, int resizeToSize)
{
	MRPT_START

	ASSERT_(m.cols() == m.rows());
	ASSERT_(
		m.rows() == 2 || m.rows() == 3 ||
		(resizeToSize > 0 && (resizeToSize == 2 || resizeToSize == 3)));

	m_cov = m;
	if (resizeToSize > 0 && resizeToSize < (int)m.rows())
		m_cov.setSize(resizeToSize, resizeToSize);

	if (m_cov == m_prevComputedCov) return;  // Done.

	m_prevComputedCov = m_cov;

	CRenderizableDisplayList::notifyChange();

	// Handle the special case of an ellipsoid of volume = 0
	const double d = m_cov.det();
	if (d == 0 || d != d)  // Note: "d!=d" is a great test for invalid numbers,
	// don't remove!
	{
		// All zeros:
		m_eigVec.setZero(3, 3);
		m_eigVal.setZero(3, 3);
	}
	else
	{
		// Not null matrix: compute the eigen-vectors & values:
		std::vector<double> eigvals;
		if (m_cov.eig_symmetric(m_eigVec, eigvals))
		{
			// Do the scale at render to avoid recomputing the m_eigVal for
			// different m_quantiles
			m_eigVal.setDiagonal(eigvals);
			m_eigVal.array() = m_eigVal.array().sqrt().matrix();
		}
		else
		{
			m_eigVec.setZero(3, 3);
			m_eigVal.setZero(3, 3);
		}
	}

	MRPT_END
}

void CEllipsoid::setCovMatrix(
	const mrpt::math::CMatrixFloat& m, int resizeToSize)
{
	CRenderizableDisplayList::notifyChange();
	setCovMatrix(CMatrixDouble(m), resizeToSize);
}

/** Evaluates the bounding box of this object (including possible children) in
 * the coordinate frame of the object parent. */
void CEllipsoid::getBoundingBox(
	mrpt::math::TPoint3D& bb_min, mrpt::math::TPoint3D& bb_max) const
{
	bb_min = m_bb_min;
	bb_max = m_bb_max;
}
<|endoftext|>