<commit_before>/***************************************************************************
 *   Copyright (c) 2006 Werner Mayer <wmayer[at]users.sourceforge.net>     *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   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., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"

#ifndef _PreComp_
#endif

#include <Mod/Mesh/App/MeshFeature.h>
#include "PropertyEditorMesh.h"

using namespace MeshGui;
using MeshCore::MeshKernel;

TYPESYSTEM_SOURCE(MeshGui::PropertyMeshKernelItem, Gui::PropertyEditor::PropertyItem);

PropertyMeshKernelItem::PropertyMeshKernelItem()
{
    m_p = static_cast<Gui::PropertyEditor::PropertyIntegerItem*>
        (Gui::PropertyEditor::PropertyIntegerItem::create());
    m_p->setParent(this);
    m_p->setPropertyName(QLatin1String("Points"));
    this->appendChild(m_p);
    m_e = static_cast<Gui::PropertyEditor::PropertyIntegerItem*>
        (Gui::PropertyEditor::PropertyIntegerItem::create());
    m_e->setParent(this);
    m_e->setPropertyName(QLatin1String("Edges"));
    this->appendChild(m_e);
    m_f = static_cast<Gui::PropertyEditor::PropertyIntegerItem*>
        (Gui::PropertyEditor::PropertyIntegerItem::create());
    m_f->setParent(this);
    m_f->setPropertyName(QLatin1String("Faces"));
    this->appendChild(m_f);
}

void PropertyMeshKernelItem::initialize()
{
    this->setReadOnly(true);
}

QVariant PropertyMeshKernelItem::value(const App::Property*) const
{
    int ctP = 0;
    int ctE = 0;
    int ctF = 0;

    const std::vector<App::Property*>& props = getPropertyData();
    for (std::vector<App::Property*>::const_iterator pt = props.begin(); pt != props.end(); ++pt) {
        Mesh::PropertyMeshKernel* pPropMesh = (Mesh::PropertyMeshKernel*)(*pt);
        const MeshKernel& rMesh = pPropMesh->getValue().getKernel();
        ctP += (int)rMesh.CountPoints();
        ctE += (int)rMesh.CountEdges();
        ctF += (int)rMesh.CountFacets();
    }

    QString  str = QObject::tr("[Points: %1, Edges: %2 Faces: %3]").arg(ctP).arg(ctE).arg(ctF);
    return QVariant(str);
}

QVariant PropertyMeshKernelItem::toolTip(const App::Property* prop) const
{
    return value(prop);
}

void PropertyMeshKernelItem::setValue(const QVariant& value)
{
}

QWidget* PropertyMeshKernelItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const
{
    return 0;
}

void PropertyMeshKernelItem::setEditorData(QWidget *editor, const QVariant& data) const
{
}

QVariant PropertyMeshKernelItem::editorData(QWidget *editor) const
{
    return QVariant();
}

int PropertyMeshKernelItem::countPoints() const
{
    int ctP = 0;
    const std::vector<App::Property*>& props = getPropertyData();
    for (std::vector<App::Property*>::const_iterator pt = props.begin(); pt != props.end(); ++pt) {
        Mesh::PropertyMeshKernel* pPropMesh = (Mesh::PropertyMeshKernel*)(*pt);
        const MeshKernel& rMesh = pPropMesh->getValue().getKernel();
        ctP += (int)rMesh.CountPoints();
    }

    return ctP;
}

int PropertyMeshKernelItem::countEdges() const
{
    int ctE = 0;
    const std::vector<App::Property*>& props = getPropertyData();
    for (std::vector<App::Property*>::const_iterator pt = props.begin(); pt != props.end(); ++pt) {
        Mesh::PropertyMeshKernel* pPropMesh = (Mesh::PropertyMeshKernel*)(*pt);
        const MeshKernel& rMesh = pPropMesh->getValue().getKernel();
        ctE += (int)rMesh.CountEdges();
    }

    return ctE;
}

int PropertyMeshKernelItem::countFaces() const
{
    int ctF = 0;
    const std::vector<App::Property*>& props = getPropertyData();
    for (std::vector<App::Property*>::const_iterator pt = props.begin(); pt != props.end(); ++pt) {
        Mesh::PropertyMeshKernel* pPropMesh = (Mesh::PropertyMeshKernel*)(*pt);
        const MeshKernel& rMesh = pPropMesh->getValue().getKernel();
        ctF += (int)rMesh.CountFacets();
    }

    return ctF;
}

#include "moc_PropertyEditorMesh.cpp"
<commit_msg>+ add missing comma in property item<commit_after>/***************************************************************************
 *   Copyright (c) 2006 Werner Mayer <wmayer[at]users.sourceforge.net>     *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   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., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"

#ifndef _PreComp_
#endif

#include <Mod/Mesh/App/MeshFeature.h>
#include "PropertyEditorMesh.h"

using namespace MeshGui;
using MeshCore::MeshKernel;

TYPESYSTEM_SOURCE(MeshGui::PropertyMeshKernelItem, Gui::PropertyEditor::PropertyItem);

PropertyMeshKernelItem::PropertyMeshKernelItem()
{
    m_p = static_cast<Gui::PropertyEditor::PropertyIntegerItem*>
        (Gui::PropertyEditor::PropertyIntegerItem::create());
    m_p->setParent(this);
    m_p->setPropertyName(QLatin1String("Points"));
    this->appendChild(m_p);
    m_e = static_cast<Gui::PropertyEditor::PropertyIntegerItem*>
        (Gui::PropertyEditor::PropertyIntegerItem::create());
    m_e->setParent(this);
    m_e->setPropertyName(QLatin1String("Edges"));
    this->appendChild(m_e);
    m_f = static_cast<Gui::PropertyEditor::PropertyIntegerItem*>
        (Gui::PropertyEditor::PropertyIntegerItem::create());
    m_f->setParent(this);
    m_f->setPropertyName(QLatin1String("Faces"));
    this->appendChild(m_f);
}

void PropertyMeshKernelItem::initialize()
{
    this->setReadOnly(true);
}

QVariant PropertyMeshKernelItem::value(const App::Property*) const
{
    int ctP = 0;
    int ctE = 0;
    int ctF = 0;

    const std::vector<App::Property*>& props = getPropertyData();
    for (std::vector<App::Property*>::const_iterator pt = props.begin(); pt != props.end(); ++pt) {
        Mesh::PropertyMeshKernel* pPropMesh = (Mesh::PropertyMeshKernel*)(*pt);
        const MeshKernel& rMesh = pPropMesh->getValue().getKernel();
        ctP += (int)rMesh.CountPoints();
        ctE += (int)rMesh.CountEdges();
        ctF += (int)rMesh.CountFacets();
    }

    QString  str = QObject::tr("[Points: %1, Edges: %2, Faces: %3]").arg(ctP).arg(ctE).arg(ctF);
    return QVariant(str);
}

QVariant PropertyMeshKernelItem::toolTip(const App::Property* prop) const
{
    return value(prop);
}

void PropertyMeshKernelItem::setValue(const QVariant& value)
{
}

QWidget* PropertyMeshKernelItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const
{
    return 0;
}

void PropertyMeshKernelItem::setEditorData(QWidget *editor, const QVariant& data) const
{
}

QVariant PropertyMeshKernelItem::editorData(QWidget *editor) const
{
    return QVariant();
}

int PropertyMeshKernelItem::countPoints() const
{
    int ctP = 0;
    const std::vector<App::Property*>& props = getPropertyData();
    for (std::vector<App::Property*>::const_iterator pt = props.begin(); pt != props.end(); ++pt) {
        Mesh::PropertyMeshKernel* pPropMesh = (Mesh::PropertyMeshKernel*)(*pt);
        const MeshKernel& rMesh = pPropMesh->getValue().getKernel();
        ctP += (int)rMesh.CountPoints();
    }

    return ctP;
}

int PropertyMeshKernelItem::countEdges() const
{
    int ctE = 0;
    const std::vector<App::Property*>& props = getPropertyData();
    for (std::vector<App::Property*>::const_iterator pt = props.begin(); pt != props.end(); ++pt) {
        Mesh::PropertyMeshKernel* pPropMesh = (Mesh::PropertyMeshKernel*)(*pt);
        const MeshKernel& rMesh = pPropMesh->getValue().getKernel();
        ctE += (int)rMesh.CountEdges();
    }

    return ctE;
}

int PropertyMeshKernelItem::countFaces() const
{
    int ctF = 0;
    const std::vector<App::Property*>& props = getPropertyData();
    for (std::vector<App::Property*>::const_iterator pt = props.begin(); pt != props.end(); ++pt) {
        Mesh::PropertyMeshKernel* pPropMesh = (Mesh::PropertyMeshKernel*)(*pt);
        const MeshKernel& rMesh = pPropMesh->getValue().getKernel();
        ctF += (int)rMesh.CountFacets();
    }

    return ctF;
}

#include "moc_PropertyEditorMesh.cpp"
<|endoftext|>


<commit_before>// @(#)root/base:$Id$
// Author: Fons Rademakers   25/10/95

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// Using a TBrowser one can browse all ROOT objects. It shows in a list //
// on the left side of the window all browsable ROOT classes. Selecting //
// one of the classes displays, in the iconbox on the right side, all   //
// objects in the class. Selecting one of the objects in the iconbox,   //
// will place all browsable objects in a new list and draws the         //
// contents of the selected class in the iconbox. And so on....         //
//                                                                      //
//Begin_Html  End_Html                       //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TBrowser.h"
#include "TGuiFactory.h"
#include "TROOT.h"
#include "TSystem.h"
#include "TStyle.h"
#include "TTimer.h"
#include "TContextMenu.h"
#include "TInterpreter.h"
#include "TVirtualMutex.h"
#include "TClass.h"
#include "TApplication.h"

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TBrowserTimer                                                        //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

class TBrowserTimer : public TTimer {

protected:
   TBrowser *fBrowser;
   Bool_t    fActivate;

public:
   TBrowserTimer(TBrowser *b, Long_t ms = 1000)
      : TTimer(ms, kTRUE), fBrowser(b), fActivate(kFALSE) { }
   Bool_t Notify();
};

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TBrowserObject                                                       //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

class TBrowserObject : public TNamed
{
   // This class is designed to wrap a Foreign object in order to
   // inject it into the Browse sub-system.

public:

   TBrowserObject(void *obj, TClass *cl, const char *brname);
   ~TBrowserObject(){;}

   void    Browse(TBrowser* b);
   Bool_t  IsFolder() const;
   TClass *IsA() const { return fClass; }

private:
   void     *fObj;   //! pointer to the foreign object
   TClass   *fClass; //! pointer to class of the foreign object

};

ClassImp(TBrowser)

//______________________________________________________________________________
TBrowser::TBrowser(const char *name, const char *title, TBrowserImp *extimp,
                   Option_t *opt)
   : TNamed(name, title), fLastSelectedObject(0), fImp(extimp), fTimer(0),
     fContextMenu(0), fNeedRefresh(kFALSE)
{
   // Create a new browser with a name, title. Width and height are by
   // default set to 640x400 and (optionally) adjusted by the screen factor
   // (depending on Rint.Canvas.UseScreenFactor to be true or false, default
   // is true).

   // make sure that the Gpad and GUI libs are loaded
   TApplication::NeedGraphicsLibs();
   gApplication->InitializeGraphics();
   if (TClass::IsCallingNew()) {
      fImp = 0;
   } else {
      Float_t cx = gStyle->GetScreenFactor();
      UInt_t w = UInt_t(cx*800);
      UInt_t h = UInt_t(cx*500);
      if (!fImp) fImp = gGuiFactory->CreateBrowserImp(this, title, w, h, opt);
      Create();
   }
}

//______________________________________________________________________________
TBrowser::TBrowser(const char *name, const char *title, UInt_t width,
                   UInt_t height, TBrowserImp *extimp, Option_t *opt)
   : TNamed(name, title), fLastSelectedObject(0), fImp(extimp), fTimer(0), fContextMenu(0),
     fNeedRefresh(kFALSE)
{
   // Create a new browser with a name, title, width and height.

   // make sure that the Gpad and GUI libs are loaded
   TApplication::NeedGraphicsLibs();
   gApplication->InitializeGraphics();
   if (!fImp) fImp = gGuiFactory->CreateBrowserImp(this, title, width, height, opt);
   Create();
}

//______________________________________________________________________________
TBrowser::TBrowser(const char *name, const char *title, Int_t x, Int_t y,
                   UInt_t width, UInt_t height, TBrowserImp *extimp, Option_t *opt)
   : TNamed(name, title), fLastSelectedObject(0), fImp(extimp), fTimer(0), fContextMenu(0),
     fNeedRefresh(kFALSE)
{
   // Create a new browser with a name, title, position, width and height.

   // make sure that the Gpad and GUI libs are loaded
   TApplication::NeedGraphicsLibs();
   gApplication->InitializeGraphics();
   fImp = gGuiFactory->CreateBrowserImp(this, title, x, y, width, height, opt);
   Create();
}

//______________________________________________________________________________
TBrowser::TBrowser(const char *name, TObject *obj, const char *title, Option_t *opt)
   : TNamed(name, title), fLastSelectedObject(0), fTimer(0), fContextMenu(0),
     fNeedRefresh(kFALSE)
{
   // Create a new browser with a name, title, width and height for TObject *obj.

   // make sure that the Gpad and GUI libs are loaded
   TApplication::NeedGraphicsLibs();
   gApplication->InitializeGraphics();
   Float_t cx = gStyle->GetScreenFactor();
   UInt_t w = UInt_t(cx*800);
   UInt_t h = UInt_t(cx*500);

   if (!fImp) fImp = gGuiFactory->CreateBrowserImp(this, title, w, h, opt);
   Create(obj);
}

//______________________________________________________________________________
TBrowser::TBrowser(const char *name, TObject *obj, const char *title,
                   UInt_t width, UInt_t height, Option_t *opt)
   : TNamed(name, title), fLastSelectedObject(0), fTimer(0), fContextMenu(0),
     fNeedRefresh(kFALSE)
{
   // Create a new browser with a name, title, width and height for TObject *obj.

   // make sure that the Gpad and GUI libs are loaded
   TApplication::NeedGraphicsLibs();
   gApplication->InitializeGraphics();
   fImp = gGuiFactory->CreateBrowserImp(this, title, width, height, opt);
   Create(obj);
}

//______________________________________________________________________________
TBrowser::TBrowser(const char *name, TObject *obj, const char *title,
                   Int_t x, Int_t y,
                   UInt_t width, UInt_t height, Option_t *opt)
   : TNamed(name, title), fLastSelectedObject(0), fTimer(0), fContextMenu(0),
     fNeedRefresh(kFALSE)
{
   // Create a new browser with a name, title, width and height for TObject *obj.

   // make sure that the Gpad and GUI libs are loaded
   TApplication::NeedGraphicsLibs();
   gApplication->InitializeGraphics();
   fImp = gGuiFactory->CreateBrowserImp(this, title, x, y, width, height, opt);
   Create(obj);
}

//______________________________________________________________________________
TBrowser::TBrowser(const char *name, void *obj, TClass *cl,
                   const char *objname, const char *title, Option_t *opt)
   : TNamed(name, title), fLastSelectedObject(0), fTimer(0), fContextMenu(0),
     fNeedRefresh(kFALSE)
{
   // Create a new browser with a name, title, width and height for TObject *obj.

   // make sure that the Gpad and GUI libs are loaded
   TApplication::NeedGraphicsLibs();
   gApplication->InitializeGraphics();
   Float_t cx = gStyle->GetScreenFactor();
   UInt_t w = UInt_t(cx*800);
   UInt_t h = UInt_t(cx*500);

   fImp = gGuiFactory->CreateBrowserImp(this, title, w, h, opt);

   Create(new TBrowserObject(obj,cl,objname));
}

//______________________________________________________________________________
TBrowser::TBrowser(const char *name, void *obj, TClass *cl,
                   const char *objname, const char *title,
                   UInt_t width, UInt_t height, Option_t *opt)
   : TNamed(name, title), fLastSelectedObject(0), fTimer(0), fContextMenu(0),
     fNeedRefresh(kFALSE)
{
   // Create a new browser with a name, title, width and height for TObject *obj.

   // make sure that the Gpad and GUI libs are loaded
   TApplication::NeedGraphicsLibs();
   gApplication->InitializeGraphics();
   fImp = gGuiFactory->CreateBrowserImp(this, title, width, height, opt);
   Create(new TBrowserObject(obj,cl,objname));
}

//______________________________________________________________________________
TBrowser::TBrowser(const char *name,void *obj,  TClass *cl,
                   const char *objname, const char *title,
                   Int_t x, Int_t y,
                   UInt_t width, UInt_t height, Option_t *opt)
   : TNamed(name, title), fLastSelectedObject(0), fTimer(0), fContextMenu(0),
     fNeedRefresh(kFALSE)
{
   // Create a new browser with a name, title, width and height for TObject *obj.

   // make sure that the Gpad and GUI libs are loaded
   TApplication::NeedGraphicsLibs();
   gApplication->InitializeGraphics();
   fImp = gGuiFactory->CreateBrowserImp(this, title, x, y, width, height, opt);
   Create(new TBrowserObject(obj,cl,objname));
}

//______________________________________________________________________________
TBrowser::TBrowser(const TBrowser& br) :
   TNamed(br),
   fLastSelectedObject(br.fLastSelectedObject),
   fImp(br.fImp),
   fTimer(br.fTimer),
   fContextMenu(br.fContextMenu),
   fNeedRefresh(br.fNeedRefresh)
{
   // Copy constructor.
}

//______________________________________________________________________________
TBrowser& TBrowser::operator=(const TBrowser& br)
{
   // Assignment operator.

   if (this != &br) {
      TNamed::operator=(br);
      fLastSelectedObject=br.fLastSelectedObject;
      fImp=br.fImp;
      fTimer=br.fTimer;
      fContextMenu=br.fContextMenu;
      fNeedRefresh=br.fNeedRefresh;
   }
   return *this;
}

//______________________________________________________________________________
TBrowser::~TBrowser()
{
   // Delete the browser.

   R__LOCKGUARD2(gROOTMutex);
   gROOT->GetListOfBrowsers()->Remove(this);
   delete fContextMenu;
   delete fTimer;
   delete fImp;
}

//______________________________________________________________________________
void TBrowser::Add(TObject *obj, const char *name, Int_t check)
{
   // Add object with name to browser. If name not set the objects GetName()
   // is used. If check < 0 (default) no check box is drawn, if 0 then
   // unchecked checkbox is added, if 1 checked checkbox is added.

   if (obj && fImp) {
      fImp->Add(obj, name, check);
      obj->SetBit(kMustCleanup);
   }
}

//______________________________________________________________________________
void TBrowser::Add(void *obj, TClass *cl, const char *name, Int_t check)
{
   // Add foreign object with name to browser.
   // 'cl' is the type use to store the value of obj.
   // So literally the following pseudo code should be correct:
   //    `cl->GetName()` * ptr = (`cl->GetName()`*) obj;
   // and the value of obj is not necessarily the start of the object.
   // If check < 0 (default) no check box is drawn, if 0 then
   // unchecked checkbox is added, if 1 checked checkbox is added.

   if (!obj || !cl) return;
   TObject *to;
   if (cl->IsTObject()) to = (TObject*)cl->DynamicCast(TObject::Class(),obj,kTRUE);
   else                 to = new TBrowserObject(obj,cl,name);

   if (!to) return;
   Add(to,name,check);
}

//______________________________________________________________________________
void TBrowser::AddCheckBox(TObject *obj, Bool_t check)
{
   // Add checkbox for this item.

   if (obj && fImp) {
      fImp->AddCheckBox(obj, check);
   }
}

//______________________________________________________________________________
void TBrowser::CheckObjectItem(TObject *obj, Bool_t check)
{
   // Change status of checkbox for this item.

   if (obj && fImp) {
      fImp->CheckObjectItem(obj, check);
   }
}

//______________________________________________________________________________
void TBrowser::RemoveCheckBox(TObject *obj)
{
   // Remove checkbox for this item.

   if (obj && fImp) {
      fImp->RemoveCheckBox(obj);
   }
}

//______________________________________________________________________________
void TBrowser::Create(TObject *obj)
{
   // Create the browser, called by the ctors.

   fNeedRefresh = kFALSE;

   fTimer = new TBrowserTimer(this);
   gSystem->AddTimer(fTimer);

   R__LOCKGUARD2(gROOTMutex);
   gROOT->GetListOfBrowsers()->Add(this);

   // Get the list of globals
   gROOT->GetListOfGlobals(kTRUE);
   gROOT->GetListOfGlobalFunctions(kTRUE);

   fContextMenu = new TContextMenu("BrowserContextMenu") ;

   // Fill the first list from the present TObject obj
   if (obj) {
      Add(obj);
      if (fImp) fImp->BrowseObj(obj);
   } else if (fImp) {
      // Fill the first list with all browsable classes from TROOT
      fImp->BrowseObj(gROOT);
   }

   // The first list will be filled by TWin32BrowserImp ctor
   // with all browsable classes from TROOT
}

//______________________________________________________________________________
void TBrowser::ExecuteDefaultAction(TObject *obj)
{
   // Execute default action for selected object (action is specified
   // in the $HOME/.root.mimes or $ROOTSYS/etc/root.mimes file).

   if (obj && fImp)
      fImp->ExecuteDefaultAction(obj);
}

//______________________________________________________________________________
void TBrowser::RecursiveRemove(TObject *obj)
{
   // Recursively remove obj from browser.

   if (fImp && obj) {
      fImp->RecursiveRemove(obj);
      fNeedRefresh = kTRUE;
   }
}

//______________________________________________________________________________
void TBrowser::Refresh()
{
   // Refresh browser contents.

   fNeedRefresh = kTRUE;
   if (fImp) fImp->Refresh();
   fNeedRefresh = kFALSE;
}

//______________________________________________________________________________
void TBrowser::SetSelected(TObject *clickedObject)
{
   // Assign the last selected object.

   fLastSelectedObject = clickedObject;
}

//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  TBrowserTimer                                                       //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

//______________________________________________________________________________
Bool_t TBrowserTimer::Notify()
{
   // Called whenever timer times out.

   if (fBrowser) {
      if (fBrowser->GetRefreshFlag()) {
         fBrowser->SetRefreshFlag(kFALSE);
         fActivate = kTRUE;
      } else if (fActivate) {
         fActivate = kFALSE;
         fBrowser->Refresh();
      }
   }
   Reset();

   return kFALSE;
}

//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  TBrowserObject                                                      //
//                                                                      //
//  This is a wrapper class to emulate the TObject interface            //
//  around an object of a non-TObject class                             //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

//______________________________________________________________________________
TBrowserObject::TBrowserObject(void *obj, TClass *cl, const char *brname)
   : TNamed(brname,cl->GetName()), fObj(obj), fClass(cl)
{
   // Constructor.

   if (cl==0) Fatal("Constructor","Class parameter should not be null");
   SetBit(kCanDelete);
}

//______________________________________________________________________________
Bool_t TBrowserObject::IsFolder() const
{
   // Return kTRUE if the object is a folder (contains browsable objects).

   return fClass->IsFolder(fObj);
}

//______________________________________________________________________________
void TBrowserObject::Browse(TBrowser* b)
{
   // Browse the content of the underlying object.

   fClass->Browse(fObj, b);
}

<commit_msg>prevent uninitialize memory read (was crashing root.exe -b tutorials/math/principal.C on linux/icc 8<commit_after>// @(#)root/base:$Id$
// Author: Fons Rademakers   25/10/95

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// Using a TBrowser one can browse all ROOT objects. It shows in a list //
// on the left side of the window all browsable ROOT classes. Selecting //
// one of the classes displays, in the iconbox on the right side, all   //
// objects in the class. Selecting one of the objects in the iconbox,   //
// will place all browsable objects in a new list and draws the         //
// contents of the selected class in the iconbox. And so on....         //
//                                                                      //
//Begin_Html  End_Html                       //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TBrowser.h"
#include "TGuiFactory.h"
#include "TROOT.h"
#include "TSystem.h"
#include "TStyle.h"
#include "TTimer.h"
#include "TContextMenu.h"
#include "TInterpreter.h"
#include "TVirtualMutex.h"
#include "TClass.h"
#include "TApplication.h"

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TBrowserTimer                                                        //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

class TBrowserTimer : public TTimer {

protected:
   TBrowser *fBrowser;
   Bool_t    fActivate;

public:
   TBrowserTimer(TBrowser *b, Long_t ms = 1000)
      : TTimer(ms, kTRUE), fBrowser(b), fActivate(kFALSE) { }
   Bool_t Notify();
};

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TBrowserObject                                                       //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

class TBrowserObject : public TNamed
{
   // This class is designed to wrap a Foreign object in order to
   // inject it into the Browse sub-system.

public:

   TBrowserObject(void *obj, TClass *cl, const char *brname);
   ~TBrowserObject(){;}

   void    Browse(TBrowser* b);
   Bool_t  IsFolder() const;
   TClass *IsA() const { return fClass; }

private:
   void     *fObj;   //! pointer to the foreign object
   TClass   *fClass; //! pointer to class of the foreign object

};

ClassImp(TBrowser)

//______________________________________________________________________________
TBrowser::TBrowser(const char *name, const char *title, TBrowserImp *extimp,
                   Option_t *opt)
   : TNamed(name, title), fLastSelectedObject(0), fImp(extimp), fTimer(0),
     fContextMenu(0), fNeedRefresh(kFALSE)
{
   // Create a new browser with a name, title. Width and height are by
   // default set to 640x400 and (optionally) adjusted by the screen factor
   // (depending on Rint.Canvas.UseScreenFactor to be true or false, default
   // is true).

   // make sure that the Gpad and GUI libs are loaded
   TApplication::NeedGraphicsLibs();
   gApplication->InitializeGraphics();
   if (TClass::IsCallingNew()) {
      fImp = 0;
   } else {
      Float_t cx = gStyle->GetScreenFactor();
      UInt_t w = UInt_t(cx*800);
      UInt_t h = UInt_t(cx*500);
      if (!fImp) fImp = gGuiFactory->CreateBrowserImp(this, title, w, h, opt);
      Create();
   }
}

//______________________________________________________________________________
TBrowser::TBrowser(const char *name, const char *title, UInt_t width,
                   UInt_t height, TBrowserImp *extimp, Option_t *opt)
   : TNamed(name, title), fLastSelectedObject(0), fImp(extimp), fTimer(0), fContextMenu(0),
     fNeedRefresh(kFALSE)
{
   // Create a new browser with a name, title, width and height.

   // make sure that the Gpad and GUI libs are loaded
   TApplication::NeedGraphicsLibs();
   gApplication->InitializeGraphics();
   if (!fImp) fImp = gGuiFactory->CreateBrowserImp(this, title, width, height, opt);
   Create();
}

//______________________________________________________________________________
TBrowser::TBrowser(const char *name, const char *title, Int_t x, Int_t y,
                   UInt_t width, UInt_t height, TBrowserImp *extimp, Option_t *opt)
   : TNamed(name, title), fLastSelectedObject(0), fImp(extimp), fTimer(0), fContextMenu(0),
     fNeedRefresh(kFALSE)
{
   // Create a new browser with a name, title, position, width and height.

   // make sure that the Gpad and GUI libs are loaded
   TApplication::NeedGraphicsLibs();
   gApplication->InitializeGraphics();
   fImp = gGuiFactory->CreateBrowserImp(this, title, x, y, width, height, opt);
   Create();
}

//______________________________________________________________________________
TBrowser::TBrowser(const char *name, TObject *obj, const char *title, Option_t *opt)
   : TNamed(name, title), fLastSelectedObject(0), fImp(0), fTimer(0), fContextMenu(0),
     fNeedRefresh(kFALSE)
{
   // Create a new browser with a name, title, width and height for TObject *obj.

   // make sure that the Gpad and GUI libs are loaded
   TApplication::NeedGraphicsLibs();
   gApplication->InitializeGraphics();
   Float_t cx = gStyle->GetScreenFactor();
   UInt_t w = UInt_t(cx*800);
   UInt_t h = UInt_t(cx*500);

   if (!fImp) fImp = gGuiFactory->CreateBrowserImp(this, title, w, h, opt);
   Create(obj);
}

//______________________________________________________________________________
TBrowser::TBrowser(const char *name, TObject *obj, const char *title,
                   UInt_t width, UInt_t height, Option_t *opt)
   : TNamed(name, title), fLastSelectedObject(0), fTimer(0), fContextMenu(0),
     fNeedRefresh(kFALSE)
{
   // Create a new browser with a name, title, width and height for TObject *obj.

   // make sure that the Gpad and GUI libs are loaded
   TApplication::NeedGraphicsLibs();
   gApplication->InitializeGraphics();
   fImp = gGuiFactory->CreateBrowserImp(this, title, width, height, opt);
   Create(obj);
}

//______________________________________________________________________________
TBrowser::TBrowser(const char *name, TObject *obj, const char *title,
                   Int_t x, Int_t y,
                   UInt_t width, UInt_t height, Option_t *opt)
   : TNamed(name, title), fLastSelectedObject(0), fTimer(0), fContextMenu(0),
     fNeedRefresh(kFALSE)
{
   // Create a new browser with a name, title, width and height for TObject *obj.

   // make sure that the Gpad and GUI libs are loaded
   TApplication::NeedGraphicsLibs();
   gApplication->InitializeGraphics();
   fImp = gGuiFactory->CreateBrowserImp(this, title, x, y, width, height, opt);
   Create(obj);
}

//______________________________________________________________________________
TBrowser::TBrowser(const char *name, void *obj, TClass *cl,
                   const char *objname, const char *title, Option_t *opt)
   : TNamed(name, title), fLastSelectedObject(0), fTimer(0), fContextMenu(0),
     fNeedRefresh(kFALSE)
{
   // Create a new browser with a name, title, width and height for TObject *obj.

   // make sure that the Gpad and GUI libs are loaded
   TApplication::NeedGraphicsLibs();
   gApplication->InitializeGraphics();
   Float_t cx = gStyle->GetScreenFactor();
   UInt_t w = UInt_t(cx*800);
   UInt_t h = UInt_t(cx*500);

   fImp = gGuiFactory->CreateBrowserImp(this, title, w, h, opt);

   Create(new TBrowserObject(obj,cl,objname));
}

//______________________________________________________________________________
TBrowser::TBrowser(const char *name, void *obj, TClass *cl,
                   const char *objname, const char *title,
                   UInt_t width, UInt_t height, Option_t *opt)
   : TNamed(name, title), fLastSelectedObject(0), fTimer(0), fContextMenu(0),
     fNeedRefresh(kFALSE)
{
   // Create a new browser with a name, title, width and height for TObject *obj.

   // make sure that the Gpad and GUI libs are loaded
   TApplication::NeedGraphicsLibs();
   gApplication->InitializeGraphics();
   fImp = gGuiFactory->CreateBrowserImp(this, title, width, height, opt);
   Create(new TBrowserObject(obj,cl,objname));
}

//______________________________________________________________________________
TBrowser::TBrowser(const char *name,void *obj,  TClass *cl,
                   const char *objname, const char *title,
                   Int_t x, Int_t y,
                   UInt_t width, UInt_t height, Option_t *opt)
   : TNamed(name, title), fLastSelectedObject(0), fTimer(0), fContextMenu(0),
     fNeedRefresh(kFALSE)
{
   // Create a new browser with a name, title, width and height for TObject *obj.

   // make sure that the Gpad and GUI libs are loaded
   TApplication::NeedGraphicsLibs();
   gApplication->InitializeGraphics();
   fImp = gGuiFactory->CreateBrowserImp(this, title, x, y, width, height, opt);
   Create(new TBrowserObject(obj,cl,objname));
}

//______________________________________________________________________________
TBrowser::TBrowser(const TBrowser& br) :
   TNamed(br),
   fLastSelectedObject(br.fLastSelectedObject),
   fImp(br.fImp),
   fTimer(br.fTimer),
   fContextMenu(br.fContextMenu),
   fNeedRefresh(br.fNeedRefresh)
{
   // Copy constructor.
}

//______________________________________________________________________________
TBrowser& TBrowser::operator=(const TBrowser& br)
{
   // Assignment operator.

   if (this != &br) {
      TNamed::operator=(br);
      fLastSelectedObject=br.fLastSelectedObject;
      fImp=br.fImp;
      fTimer=br.fTimer;
      fContextMenu=br.fContextMenu;
      fNeedRefresh=br.fNeedRefresh;
   }
   return *this;
}

//______________________________________________________________________________
TBrowser::~TBrowser()
{
   // Delete the browser.

   R__LOCKGUARD2(gROOTMutex);
   gROOT->GetListOfBrowsers()->Remove(this);
   delete fContextMenu;
   delete fTimer;
   delete fImp;
}

//______________________________________________________________________________
void TBrowser::Add(TObject *obj, const char *name, Int_t check)
{
   // Add object with name to browser. If name not set the objects GetName()
   // is used. If check < 0 (default) no check box is drawn, if 0 then
   // unchecked checkbox is added, if 1 checked checkbox is added.

   if (obj && fImp) {
      fImp->Add(obj, name, check);
      obj->SetBit(kMustCleanup);
   }
}

//______________________________________________________________________________
void TBrowser::Add(void *obj, TClass *cl, const char *name, Int_t check)
{
   // Add foreign object with name to browser.
   // 'cl' is the type use to store the value of obj.
   // So literally the following pseudo code should be correct:
   //    `cl->GetName()` * ptr = (`cl->GetName()`*) obj;
   // and the value of obj is not necessarily the start of the object.
   // If check < 0 (default) no check box is drawn, if 0 then
   // unchecked checkbox is added, if 1 checked checkbox is added.

   if (!obj || !cl) return;
   TObject *to;
   if (cl->IsTObject()) to = (TObject*)cl->DynamicCast(TObject::Class(),obj,kTRUE);
   else                 to = new TBrowserObject(obj,cl,name);

   if (!to) return;
   Add(to,name,check);
}

//______________________________________________________________________________
void TBrowser::AddCheckBox(TObject *obj, Bool_t check)
{
   // Add checkbox for this item.

   if (obj && fImp) {
      fImp->AddCheckBox(obj, check);
   }
}

//______________________________________________________________________________
void TBrowser::CheckObjectItem(TObject *obj, Bool_t check)
{
   // Change status of checkbox for this item.

   if (obj && fImp) {
      fImp->CheckObjectItem(obj, check);
   }
}

//______________________________________________________________________________
void TBrowser::RemoveCheckBox(TObject *obj)
{
   // Remove checkbox for this item.

   if (obj && fImp) {
      fImp->RemoveCheckBox(obj);
   }
}

//______________________________________________________________________________
void TBrowser::Create(TObject *obj)
{
   // Create the browser, called by the ctors.

   fNeedRefresh = kFALSE;

   fTimer = new TBrowserTimer(this);
   gSystem->AddTimer(fTimer);

   R__LOCKGUARD2(gROOTMutex);
   gROOT->GetListOfBrowsers()->Add(this);

   // Get the list of globals
   gROOT->GetListOfGlobals(kTRUE);
   gROOT->GetListOfGlobalFunctions(kTRUE);

   fContextMenu = new TContextMenu("BrowserContextMenu") ;

   // Fill the first list from the present TObject obj
   if (obj) {
      Add(obj);
      if (fImp) fImp->BrowseObj(obj);
   } else if (fImp) {
      // Fill the first list with all browsable classes from TROOT
      fImp->BrowseObj(gROOT);
   }

   // The first list will be filled by TWin32BrowserImp ctor
   // with all browsable classes from TROOT
}

//______________________________________________________________________________
void TBrowser::ExecuteDefaultAction(TObject *obj)
{
   // Execute default action for selected object (action is specified
   // in the $HOME/.root.mimes or $ROOTSYS/etc/root.mimes file).

   if (obj && fImp)
      fImp->ExecuteDefaultAction(obj);
}

//______________________________________________________________________________
void TBrowser::RecursiveRemove(TObject *obj)
{
   // Recursively remove obj from browser.

   if (fImp && obj) {
      fImp->RecursiveRemove(obj);
      fNeedRefresh = kTRUE;
   }
}

//______________________________________________________________________________
void TBrowser::Refresh()
{
   // Refresh browser contents.

   fNeedRefresh = kTRUE;
   if (fImp) fImp->Refresh();
   fNeedRefresh = kFALSE;
}

//______________________________________________________________________________
void TBrowser::SetSelected(TObject *clickedObject)
{
   // Assign the last selected object.

   fLastSelectedObject = clickedObject;
}

//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  TBrowserTimer                                                       //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

//______________________________________________________________________________
Bool_t TBrowserTimer::Notify()
{
   // Called whenever timer times out.

   if (fBrowser) {
      if (fBrowser->GetRefreshFlag()) {
         fBrowser->SetRefreshFlag(kFALSE);
         fActivate = kTRUE;
      } else if (fActivate) {
         fActivate = kFALSE;
         fBrowser->Refresh();
      }
   }
   Reset();

   return kFALSE;
}

//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  TBrowserObject                                                      //
//                                                                      //
//  This is a wrapper class to emulate the TObject interface            //
//  around an object of a non-TObject class                             //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

//______________________________________________________________________________
TBrowserObject::TBrowserObject(void *obj, TClass *cl, const char *brname)
   : TNamed(brname,cl->GetName()), fObj(obj), fClass(cl)
{
   // Constructor.

   if (cl==0) Fatal("Constructor","Class parameter should not be null");
   SetBit(kCanDelete);
}

//______________________________________________________________________________
Bool_t TBrowserObject::IsFolder() const
{
   // Return kTRUE if the object is a folder (contains browsable objects).

   return fClass->IsFolder(fObj);
}

//______________________________________________________________________________
void TBrowserObject::Browse(TBrowser* b)
{
   // Browse the content of the underlying object.

   fClass->Browse(fObj, b);
}

<|endoftext|>


<commit_before><commit_msg>including build/build_config to fix bustage<commit_after><|endoftext|>


<commit_before>//
// Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//

//
// bench.cpp : spdlog benchmarks
//
#include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/spdlog.h"
#include "utils.h"
#include <atomic>
#include <iostream>
#include <memory>
#include <string>
#include <thread>

using namespace std;
using namespace std::chrono;
using namespace spdlog;
using namespace spdlog::sinks;
using namespace utils;

void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count);

int count_lines(const char *filename)
{
    int counter = 0;
    auto *infile = fopen(filename, "r");
    int ch;
    while (EOF != (ch = getc(infile)))
    {
        if ('\n' == ch)
            counter++;
    }

    return counter;
}
int main(int argc, char *argv[])
{

    int howmany = 1000000;
    int queue_size = howmany + 2;
    int threads = 10;
    int iters = 3;

    try
    {
        auto console = spdlog::stdout_color_mt("console");
        if (argc == 1)
        {
            console->set_pattern("%v");
            console->info("Usage: {} <message_count> <threads> <q_size> <iterations>", argv[0]);
            return 0;
        }

        if (argc > 1)
            howmany = atoi(argv[1]);
        if (argc > 2)
            threads = atoi(argv[2]);
        if (argc > 3)
            queue_size = atoi(argv[3]);

        if (argc > 4)
            iters = atoi(argv[4]);

        console->info("-------------------------------------------------");
        console->info("Messages: {:14n}", howmany);
        console->info("Threads : {:14n}", threads);
        console->info("Queue   : {:14n}", queue_size);
        console->info("Iters   : {:>14n}", iters);
        console->info("-------------------------------------------------");

        const char *filename = "logs/basic_async.log";

        for (int i = 0; i < iters; i++)
        {
            auto tp = std::make_shared<details::thread_pool>(queue_size, 1);
            auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
            auto logger = std::make_shared<async_logger>("async_logger", std::move(file_sink), std::move(tp), async_overflow_policy::block);
            bench_mt(howmany, std::move(logger), threads);
            auto count = count_lines(filename);

            if (count != howmany)
            {
                console->error("Test failed. {} has {:n} lines instead of {:n}", filename, count, howmany);
                exit(1);
            }
            else
            {
                console->info("Line count OK ({:n})\n", count);
            }
        }
    }
    catch (std::exception &ex)
    {
        std::cerr << "Error: " << ex.what() << std::endl;
        perror("Last error");
        return 1;
    }
    return 0;
}

void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count)
{
    using std::chrono::high_resolution_clock;
    vector<thread> threads;
    auto start = high_resolution_clock::now();
    for (int t = 0; t < thread_count; ++t)
    {
        threads.push_back(std::thread([&]() {
            for (int j = 0; j < howmany / thread_count; j++)
            {
                log->info("Hello logger: msg number {}", j);
            }
        }));
    }

    for (auto &t : threads)
    {
        t.join();
    };

    auto delta = high_resolution_clock::now() - start;
    auto delta_d = duration_cast<duration<double>>(delta).count();
    spdlog::get("console")->info("Elapsed: {} secs\t {:n}/sec", delta_d, int(howmany / delta_d));
}
<commit_msg>Fixed async_bench<commit_after>//
// Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//

//
// bench.cpp : spdlog benchmarks
//
#include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/spdlog.h"
#include "utils.h"
#include <atomic>
#include <iostream>
#include <memory>
#include <string>
#include <thread>

using namespace std;
using namespace std::chrono;
using namespace spdlog;
using namespace spdlog::sinks;
using namespace utils;

void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count);

int count_lines(const char *filename)
{
    int counter = 0;
    auto *infile = fopen(filename, "r");
    int ch;
    while (EOF != (ch = getc(infile)))
    {
        if ('\n' == ch)
            counter++;
    }

    return counter;
}
int main(int argc, char *argv[])
{

    int howmany = 1000000;
    int queue_size = howmany + 2;
    int threads = 10;
    int iters = 3;

    try
    {
        auto console = spdlog::stdout_color_mt("console");
        if (argc == 1)
        {
            console->set_pattern("%v");
            console->info("Usage: {} <message_count> <threads> <q_size> <iterations>", argv[0]);
            return 0;
        }

        if (argc > 1)
            howmany = atoi(argv[1]);
        if (argc > 2)
            threads = atoi(argv[2]);
        if (argc > 3)
            queue_size = atoi(argv[3]);

        if (argc > 4)
            iters = atoi(argv[4]);

        console->info("-------------------------------------------------");
        console->info("Messages: {:14n}", howmany);
        console->info("Threads : {:14n}", threads);
        console->info("Queue   : {:14n}", queue_size);
        console->info("Iters   : {:>14n}", iters);
        console->info("-------------------------------------------------");

        const char *filename = "logs/basic_async.log";

        for (int i = 0; i < iters; i++)
        {
            auto tp = std::make_shared<details::thread_pool>(queue_size, 1);
            auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
            auto logger = std::make_shared<async_logger>("async_logger", std::move(file_sink), std::move(tp), async_overflow_policy::block);
            bench_mt(howmany, std::move(logger), threads);
            auto count = count_lines(filename);

            if (count != howmany)
            {
                console->error("Test failed. {} has {:n} lines instead of {:n}", filename, count, howmany);
                exit(1);
            }
            else
            {
                console->info("Line count OK ({:n})\n", count);
            }
        }
    }
    catch (std::exception &ex)
    {
        std::cerr << "Error: " << ex.what() << std::endl;
        perror("Last error");
        return 1;
    }
    return 0;
}

void thread_fun(std::shared_ptr<spdlog::logger> logger, int howmany)
{
    for (int i = 0; i < howmany; i++)
    {
        logger->info("Hello logger: msg number {}", i);
    }
}

void bench_mt(int howmany, std::shared_ptr<spdlog::logger> logger, int thread_count)
{
    using std::chrono::high_resolution_clock;
    vector<thread> threads;
    auto start = high_resolution_clock::now();

    int msgs_per_thread = howmany / thread_count;
    int msgs_per_thread_mod = howmany % thread_count;
    for (int t = 0; t < thread_count; ++t)
    {
        if (t == 0 && msgs_per_thread_mod)
            threads.push_back(std::thread(thread_fun, logger, msgs_per_thread + msgs_per_thread_mod));
        else
            threads.push_back(std::thread(thread_fun, logger, msgs_per_thread));
    }

    for (auto &t : threads)
    {
        t.join();
    };

    auto delta = high_resolution_clock::now() - start;
    auto delta_d = duration_cast<duration<double>>(delta).count();
    spdlog::get("console")->info("Elapsed: {} secs\t {:n}/sec", delta_d, int(howmany / delta_d));
}
<|endoftext|>


<commit_before>//! \file WikimediaJsonToArticleConverter.cpp

#include "WikimediaJsonToArticleConverter.h"

#include <cassert>
#include <sstream>

#include <json/json.h>

#include "Article.h"
#include "WalkerException.h"

namespace WikiWalker
{
  //! \todo really ugly workaround, passing in the
  //! CollectionUtils::ArticleCollection instance...
  //! :/
  WikimediaJsonToArticleConverter::ContinuationStatus
  WikimediaJsonToArticleConverter::convert(
      const std::string& json,
      CollectionUtils::ArticleCollection& articleCache)
  {
    Json::Value document;
    Json::CharReaderBuilder crb;
    crb.strictMode(&crb.settings_);
    std::istringstream jsonStream(json);
    bool success = Json::parseFromStream(crb, jsonStream, &document, nullptr);

    if(!success) {
      throw WalkerException("Error parsing JSON");
    }

    auto allPages = document.get("query", Json::Value::nullSingleton())
                        .get("pages", Json::Value::nullSingleton());

    for(auto& onePage : allPages) {
      //! get normalized title not necessary, "title" is already
      std::string oneTitle =
          onePage.get("title", Json::Value::nullSingleton()).asString();

      //! \todo find a better solution than get-compare-add
      auto wantedArticle = CollectionUtils::get(articleCache, oneTitle);

      if(wantedArticle == nullptr) {
        wantedArticle = std::make_shared<Article>(oneTitle);
        CollectionUtils::add(articleCache, wantedArticle);
      }

      if(onePage.isMember("missing") || onePage.isMember("invalid")) {
        wantedArticle->marked(true);
        wantedArticle->analyzed(true);
        continue;
      }

      // add links
      std::shared_ptr<Article> par;
      for(const auto& linked :
          onePage.get("links", Json::Value::nullSingleton())) {
        auto linkedPageTitle =
            linked.get("title", Json::Value::nullSingleton()).asString();
        par = CollectionUtils::get(articleCache, linkedPageTitle);

        if(par == nullptr) {
          par = std::make_shared<Article>(linkedPageTitle);
          CollectionUtils::add(articleCache, par);
        }

        wantedArticle->addLink(par);
      }

      wantedArticle->analyzed(true);
    }

    bool moreData;

    // always clear, otherwise insert won't happen
    continuationData_.clear();

    if(!document.isMember("continue")) {
      moreData = true;
      const auto contData =
          document.get("continue", Json::Value::nullSingleton());
      assert(contData.isObject());

      for(auto it = contData.begin(); it != contData.end(); it++) {
        continuationData_.emplace(it.name(), it->asString());
      }
    } else {
      moreData = false;
    }

    return moreData ? ContinuationStatus::ConversionNeedsMoreData
                    : ContinuationStatus::ConversionCompleted;
  }
}  // namespace WikiWalker
<commit_msg>Add TODO item<commit_after>//! \file WikimediaJsonToArticleConverter.cpp

#include "WikimediaJsonToArticleConverter.h"

#include <cassert>
#include <sstream>

#include <json/json.h>

#include "Article.h"
#include "WalkerException.h"

namespace WikiWalker
{
  //! \todo really ugly workaround, passing in the
  //! CollectionUtils::ArticleCollection instance...
  //! :/
  WikimediaJsonToArticleConverter::ContinuationStatus
  WikimediaJsonToArticleConverter::convert(
      const std::string& json,
      CollectionUtils::ArticleCollection& articleCache)
  {
    Json::Value document;
    Json::CharReaderBuilder crb;
    crb.strictMode(&crb.settings_);
    std::istringstream jsonStream(json);
    bool success = Json::parseFromStream(crb, jsonStream, &document, nullptr);

    if(!success) {
      throw WalkerException("Error parsing JSON");
    }

    auto allPages = document.get("query", Json::Value::nullSingleton())
                        .get("pages", Json::Value::nullSingleton());

    for(auto& onePage : allPages) {
      //! get normalized title not necessary, "title" is already
      std::string oneTitle =
          onePage.get("title", Json::Value::nullSingleton()).asString();

      //! \todo find a better solution than get-compare-add
      auto wantedArticle = CollectionUtils::get(articleCache, oneTitle);

      if(wantedArticle == nullptr) {
        wantedArticle = std::make_shared<Article>(oneTitle);
        CollectionUtils::add(articleCache, wantedArticle);
      }

      if(onePage.isMember("missing") || onePage.isMember("invalid")) {
        wantedArticle->marked(true);
        wantedArticle->analyzed(true);
        continue;
      }

      // add links
      //! \todo support linkshere
      std::shared_ptr<Article> par;
      for(const auto& linked :
          onePage.get("links", Json::Value::nullSingleton())) {
        auto linkedPageTitle =
            linked.get("title", Json::Value::nullSingleton()).asString();
        par = CollectionUtils::get(articleCache, linkedPageTitle);

        if(par == nullptr) {
          par = std::make_shared<Article>(linkedPageTitle);
          CollectionUtils::add(articleCache, par);
        }

        wantedArticle->addLink(par);
      }

      wantedArticle->analyzed(true);
    }

    bool moreData;

    // always clear, otherwise insert won't happen
    continuationData_.clear();

    if(!document.isMember("continue")) {
      moreData = true;
      const auto contData =
          document.get("continue", Json::Value::nullSingleton());
      assert(contData.isObject());

      for(auto it = contData.begin(); it != contData.end(); it++) {
        continuationData_.emplace(it.name(), it->asString());
      }
    } else {
      moreData = false;
    }

    return moreData ? ContinuationStatus::ConversionNeedsMoreData
                    : ContinuationStatus::ConversionCompleted;
  }
}  // namespace WikiWalker
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_META_FORWARD_AS_HPP
#define STAN_MATH_PRIM_META_FORWARD_AS_HPP

#include <stan/math/prim/meta.hpp>
#include <type_traits>

namespace stan {
namespace math {

namespace internal {
template <typename T1, typename T2>
constexpr bool eigen_static_size_match(T1 desired, T2 actual) {
  return static_cast<int>(desired) == Eigen::Dynamic
         || static_cast<int>(desired) == static_cast<int>(actual);
}
}  // namespace internal

/** \ingroup type_trait
 * Assume which type we get. If actual type is convertible to assumed type or in
 * case of eigen types compile time rows and columns also match or desired sizes
 * are dynamic this is a no-op. Otherwise it throws std::runtime_error, which
 * should never happen if used as intended.
 *
 * This is intended to be used in compile time branches that would otherwise
 * trigger compile error even though they are never executed.
 *
 * @tparam T_desired type of output we need to avoid compile time errors
 * @tparam T_actual actual type of the argument
 * @param a input value
 * @return the input value a
 */
template <typename T_desired, typename T_actual,
          typename
          = std::enable_if_t<std::is_same<std::decay_t<T_actual>,
                                          std::decay_t<T_desired>>::value
                             && !is_eigen<T_desired>::value>>
inline T_actual&& forward_as(T_actual&& a) {  // NOLINT
  return std::forward<T_actual>(a);
}

/** \ingroup type_trait
 * Assume which type we get. If actual type is not convertible to assumed type
 * or in case of eigen types compile time rows and columns are not the same and
 * desired sizes are not dynamic this has return type of \c T_desired, but it
 * only throws. This version should only be used where it is optimized away so
 * the throw should never happen.
 *
 * This is intended to be used in compile time branches that would otherwise
 * trigger compile error even though they are never executed.
 *
 * @tparam T_desired type of output we need to avoid compile time errors
 * @tparam T_actual actual type of the argument
 * @param a input value
 * @return nothing, this always throws
 * @throw always throws std::runtime_error
 */
template <typename T_desired, typename T_actual,
          typename = std::enable_if_t<
              !std::is_same<std::decay<T_actual>, std::decay<T_desired>>::value
              && !is_eigen<T_desired>::value>>
inline T_desired forward_as(const T_actual& a) {
  throw std::runtime_error("Wrong type assumed! Please file a bug report.");
}

/** \ingroup type_trait
 * Assume which type we get. If actual type is convertible to assumed type or in
 * case of eigen types compile time rows and columns also match or desired sizes
 * are dynamic this is a no-op. Otherwise it throws std::runtime_error,
 * which should never happen if used as intended.
 *
 * This is intended to be used in compile time branches that would otherwise
 * trigger compile error even though they are never executed.
 *
 * @tparam T_desired type of output we need to avoid compile time errors
 * @tparam T_actual actual type of the argument
 * @param a input value
 * @return the input value a
 */
template <
    typename T_desired, typename T_actual,
    require_eigen_t<T_desired>* = nullptr,
    std::enable_if_t<
        std::is_same<value_type_t<T_actual>, value_type_t<T_desired>>::value
        && is_eigen<T_desired>::value && is_eigen<T_actual>::value
        && internal::eigen_static_size_match(
               T_desired::RowsAtCompileTime,
               std::decay_t<T_actual>::RowsAtCompileTime)
        && internal::eigen_static_size_match(
               T_desired::ColsAtCompileTime,
               std::decay_t<T_actual>::ColsAtCompileTime)>* = nullptr>
inline T_actual&& forward_as(T_actual&& a) {  // NOLINT
  return std::forward<T_actual>(a);
}

/**
 * Assume which type we get. If actual type is not convertible to assumed type
 * or in case of eigen types compile time rows and columns are not the same and
 * desired sizes are not dynamic this has return type of \c T_desired, but it
 * only throws. This version should only be used where it is optimized away so
 * the throw should never happen.
 *
 * This is intended to be used in compile time branches that would otherwise
 * trigger compile error even though they are never executed.
 *
 * @tparam T_desired type of output we need to avoid compile time errors
 * @tparam T_actual actual type of the argument
 * @param a input value
 * @return nothing, this always throws
 * @throw always throws std::runtime_error
 */
template <
    typename T_desired, typename T_actual,
    require_all_eigen_t<T_desired, T_actual>* = nullptr,
    std::enable_if_t<
        !std::is_same<value_type_t<T_actual>, value_type_t<T_desired>>::value
        || !internal::eigen_static_size_match(
               T_desired::RowsAtCompileTime,
               std::decay_t<T_actual>::RowsAtCompileTime)
        || !internal::eigen_static_size_match(
               T_desired::ColsAtCompileTime,
               std::decay_t<T_actual>::ColsAtCompileTime)>* = nullptr>
inline T_desired forward_as(const T_actual& a) {
  throw std::runtime_error("Wrong type assumed! Please file a bug report.");
}

}  // namespace math
}  // namespace stan
#endif
<commit_msg>Removed eigen specializations for forward_as (Issue #2018)<commit_after>#ifndef STAN_MATH_PRIM_META_FORWARD_AS_HPP
#define STAN_MATH_PRIM_META_FORWARD_AS_HPP

#include <stan/math/prim/meta.hpp>
#include <type_traits>

namespace stan {
namespace math {

namespace internal {
template <typename T1, typename T2>
constexpr bool eigen_static_size_match(T1 desired, T2 actual) {
  return static_cast<int>(desired) == Eigen::Dynamic
         || static_cast<int>(desired) == static_cast<int>(actual);
}
}  // namespace internal

/** \ingroup type_trait
 * Assume which type we get. If actual type is convertible to assumed type or in
 * case of eigen types compile time rows and columns also match or desired sizes
 * are dynamic this is a no-op. Otherwise it throws std::runtime_error, which
 * should never happen if used as intended.
 *
 * This is intended to be used in compile time branches that would otherwise
 * trigger compile error even though they are never executed.
 *
 * @tparam T_desired type of output we need to avoid compile time errors
 * @tparam T_actual actual type of the argument
 * @param a input value
 * @return the input value a
 */
template <typename T_desired, typename T_actual,
          typename
          = std::enable_if_t<std::is_same<std::decay_t<T_actual>,
                                          std::decay_t<T_desired>>::value>>
inline T_actual&& forward_as(T_actual&& a) {  // NOLINT
  return std::forward<T_actual>(a);
}

/** \ingroup type_trait
 * Assume which type we get. If actual type is not convertible to assumed type
 * or in case of eigen types compile time rows and columns are not the same and
 * desired sizes are not dynamic this has return type of \c T_desired, but it
 * only throws. This version should only be used where it is optimized away so
 * the throw should never happen.
 *
 * This is intended to be used in compile time branches that would otherwise
 * trigger compile error even though they are never executed.
 *
 * @tparam T_desired type of output we need to avoid compile time errors
 * @tparam T_actual actual type of the argument
 * @param a input value
 * @return nothing, this always throws
 * @throw always throws std::runtime_error
 */
template <typename T_desired, typename T_actual,
          typename = std::enable_if_t<
              !std::is_same<std::decay<T_actual>, std::decay<T_desired>>::value>>
inline T_desired forward_as(const T_actual& a) {
  throw std::runtime_error("Wrong type assumed! Please file a bug report.");
}

}  // namespace math
}  // namespace stan
#endif
<|endoftext|>


<commit_before>#include "decoder.h"
#define stepsBufSize 20

Decoder::Decoder(QObject *parent) : QObject(parent)
{
    Xold = 0.0;
    Yold = 0.0;
    Zold = 0.0;
    reversedX = false,
    reversedY = false,
    reversedZ = false;
    byteCounter = 0;
    recCounter = 0;
    useIJ = 1; //important for G02 and G03 commands, driven by G17, G18 and G19
    useIK = 0;
    useJK = 0;
    stepsPerMM = 96;
    invSpeedconst = 3.2; //magic number used to calculate timers
    rapidSpeed = 3.2; //mm/s
    feedSpeed = 0.32;

    posValues.setString(&posVals);
}

void Decoder::decodeCommands(const QStringList lines)
{
    std::vector <double> vals;
    std::vector <QChar> args;
    QChar cmd;
    int number = -1; //numbers fo Gxx

    for (int i = 0; i < lines.count(); i++)
    {
        QString currentLine = lines[i];
        QChar fc = currentLine.at(0); //if the first char in a new line is not G, copy old Gxx and send further
        if (fc != QLatin1Char('G'))
        {
            if (number != -1)
            {
                decodeMovement(number,
                           args, vals);
                vals.clear();
                args.clear();
            }
        }
        //qDebug() << currentLine;

        QStringList cmds = currentLine.split(" ");
        for (int j = 0; j < cmds.count(); j++)
        {
            QString currentCmd = cmds[j];
            //qDebug() << currentCmd;
            QChar c = currentCmd.at(0);

            if (c == QLatin1Char('G'))
            {
                if (number != -1) //send data from previous run
                {
                    decodeMovement(number,
                               args, vals);
                }

                vals.clear(); //preparing for a new packet
                args.clear();

                QString partial;
                for (int s = 1; s < currentCmd.count(); s++)
                {
                    partial += currentCmd.at(s);
                }
                number = partial.toInt();
                //qDebug() << number;
                cmd = c;
            }
            else if(c == QLatin1Char('X') || c == QLatin1Char('Y') || c == QLatin1Char('Z')
                    || c == QLatin1Char('I') || c == QLatin1Char('J') || c == QLatin1Char('K')
                    || c == QLatin1Char('F'))
            {
                QString partial;
                for (int s = 1; s < currentCmd.count(); s++)
                {
                    partial += currentCmd.at(s);
                }
                double value = partial.toDouble();
                //qDebug() << value;
                vals.push_back(value);
                args.push_back(c);
            }

        }
    }
    if (number != -1) //read the last line
    {
        decodeMovement(number,
                   args, vals);
    }
    writePosFile(); //write positions (int) to file
    writeStepsFile();
}
void Decoder::decodeMovement(const int num,
                    const std::vector <QChar> args, const std::vector <double> vals)
{
    /*qDebug() << cmd << num;
    for (uint i = 0; i < args.size(); i++)
    {
        qDebug() << args.at(i) << vals.at(i);
    }*/

    if (num == 17) {useIJ = 1; useIK = 0; useJK = 0;}
    if (num == 18) {useIJ = 0; useIK = 1; useJK = 0;}
    if (num == 19) {useIJ = 0; useIK = 0; useJK = 1;}

    if ((num == 0) || (num == 1)) //G00 rapid linear move and G01 feed linear move
    {
        if (num == 0)
        {
            rapidMode();
        }
        else
        {
            feedMode();
        }
        double X = Xold;
        double Y = Yold;
        double Z = Zold;
        for (uint i = 0; i < args.size(); i++)
        {
            QChar c = args.at(i);
            if (c == QLatin1Char('X')) X = vals.at(i);
            if (c == QLatin1Char('Y')) Y = vals.at(i);
            if (c == QLatin1Char('Z')) Z = vals.at(i);
        }
        renderLine(Xold, Yold, Zold, X, Y, Z);
        Xold = X; Yold = Y; Zold = Z;
    }
    if ((num == 2) || (num == 3)) //feed cw arc and ccw arc
    {
        double X = Xold;
        double Y = Yold;
        double Z = Zold;
        double R = -1.0; //negative radius does not exist, do it can be used as flag
        double I = 0.0;
        double J = 0.0;
        //double K = 0.0;
        double CX, CY;
        bool ccw = 0;

        feedMode();

        if (num == 03) ccw = 1;

        for (uint i = 0; i < args.size(); i++)
        {
            QChar c = args.at(i);

            if (c == QLatin1Char('R')) R = vals.at(i);
            if (c == QLatin1Char('I')) I = vals.at(i);
            if (c == QLatin1Char('J')) J = vals.at(i);
            if (c == QLatin1Char('X')) X = vals.at(i);
            if (c == QLatin1Char('Y')) Y = vals.at(i);
            if (c == QLatin1Char('Z')) Z = vals.at(i);
            //if (c == QLatin1Char('K')) K = vals.at(i);
        }
        if ((useIJ) && (R < 0.0))
        {
            CX = Xold + I;
            CY = Yold + J;
            R = std::sqrt((I * I) + (J * J));
            renderCircleXY(Xold, Yold, Zold, X, Y, CX, CY, R, ccw);
        }

        Xold = X; Yold = Y; Zold = Z;
    }
}

void Decoder::renderLine(double X0, double Y0, double Z0,
           double X1, double Y1, double Z1)
{
    X0 = X0 * stepsPerMM;
    Y0 = Y0 * stepsPerMM;
    Z0 = Z0 * stepsPerMM;
    X1 = X1 * stepsPerMM;
    Y1 = Y1 * stepsPerMM;
    Z1 = Z1 * stepsPerMM;

    int Z = std::round(Z0);
    int X = std::round(X0);
    int Y = std::round(Y0);

    qDebug() << "Line Horizontal XY " << X0 << Y0 << Z0 << X1 << Y1 << Z1;

    if (Z0 == Z1)
    {
        int Xend = std::round(X1);
        int Yend = std::round(Y1);
        int Xprobe[3], Yprobe[3]; //have to test 3 points distance to line, point by point

        int dx, dy;
        (X1 > X0) ? dx = 1 : dx = - 1;
        (Y1 > Y0) ? dy = 1 : dy = - 1;

        if (X1 == X0) dx = 0;
        if (Y1 == Y0) dy = 0;

        while (!((X == Xend) && (Y == Yend)))
        {

            double dist, numerator, denominator, Xtmp = 0, Ytmp = 0;
            double olddist = 10000;
            for (int i = 0; i < 3; i++)
            {
                Xprobe[0] = X + dx;
                if (dx == 0) //avoid step = 0
                {
                    Yprobe[0] = Y + dy;
                }
                else
                {
                    Yprobe[0] = Y;
                }
                if (dy == 0)
                {
                    Xprobe[1] = X + dx;
                }
                else
                {
                    Xprobe[1] = X;
                }
                Yprobe[1] = Y + dy;
                Xprobe[2] = X + dx;
                Yprobe[2] = Y + dy;

                numerator = std::abs((Y1 - Y0) * Xprobe[i] - (X1 - X0) * Yprobe[i] + X1 * Y0 - Y1 * X0);
                denominator = std::sqrt(std::pow((Y1 - Y0), 2) + std::pow((X1 - X0), 2));
                dist = numerator / denominator;

                //qDebug() << X << Y << "dist" << dist;
                if (dist < olddist)
                {
                    olddist = dist;
                    Xtmp = Xprobe[i];
                    Ytmp = Yprobe[i];
                }
            }
            X = Xtmp;
            Y = Ytmp;

            if (dist >= 2) //? for more testing
            {
                qDebug() << "Something went wrong. Distance is: " << dist;
                break;
            }
            //here output point, what about endpoints?
            exportData(X, Y, Z);
        }
    }
    if ((X0 == X1) || (Y0 == Y1))
    {
        int dz;
        int Zend = std::round(Z1);

        qDebug() << "Vertical " << Z0 << Z1;
        (Z1 > Z0) ? dz = 1 : dz = - 1;
        while (Z != Zend)
        {
            Z = Z + dz;
            //here output point
            exportData(X, Y, Z);
        }
    }
}
void Decoder::renderCircleXY(double X0, double Y0, double Z0,
                             double X1, double Y1,
                             double CX, double CY, double R, bool ccw)
{
    X0 = X0 * stepsPerMM;
    Y0 = Y0 * stepsPerMM;
    Z0 = Z0 * stepsPerMM;
    X1 = X1 * stepsPerMM;
    Y1 = Y1 * stepsPerMM;
    CX = CX * stepsPerMM;
    CY = CY * stepsPerMM;
    R = R * stepsPerMM;

    qDebug() << "Circle XY " << X0 << Y0 << X1 << Y1 << CX << CY << R << ccw;
    int X = std::round(X0);
    int Y = std::round(Y0);
    int Xend = std::round(X1);
    int Yend = std::round(Y1);
    int Xprobe[3], Yprobe[3]; //have to test 3 points distance to circle, point by point
    bool fullCircle = false;
    int dx = 0, dy = 0;

    if ((X == Xend) && (Y == Yend)) fullCircle = true;

    while (!((X == Xend) && (Y == Yend) && (!fullCircle)))
    {
        if (ccw)
        {
            if ((X >= CX) && (Y >= CY)) //first quarter
            {
                dx = -1;
                dy = 1;
            }
            if ((X <= CX) && (Y >= CY))
            {
                dx = -1;
                dy = -1;
            }
            if ((X <= CX) && (Y <= CY))
            {
                dx = 1;
                dy = -1;
            }
            if ((X >= CX) && (Y <= CY))
            {
                dx = 1;
                dy = 1;
            }
        }
        else //CW case
        {
            if ((X >= CX) && (Y >= CY)) //first quarter
            {
                dx = 1;
                dy = -1;
            }
            if ((X <= CX) && (Y >= CY))
            {
                dx = 1;
                dy = 1;
            }
            if ((X <= CX) && (Y <= CY))
            {
                dx = -1;
                dy = 1;
            }
            if ((X >= CX) && (Y <= CY))
            {
                dx = -1;
                dy = -1;
            }
        }

        Xprobe[0] = X + dx;
        Yprobe[0] = Y;
        Xprobe[1] = X;
        Yprobe[1] = Y + dy;
        Xprobe[2] = X + dx;
        Yprobe[2] = Y + dy;

        double dist, Xtmp = 0, Ytmp = 0;
        double olddist = 10000;
        for (int i = 0; i < 3; i++)
        {
            dist = std::abs(std::sqrt(std::pow((CX - Xprobe[i]), 2) + std::pow((CY - Yprobe[i]), 2)) - R);
            if (dist < olddist)
            {
                olddist = dist;
                Xtmp = Xprobe[i];
                Ytmp = Yprobe[i];
            }
        }

        X = Xtmp;
        Y = Ytmp;

        fullCircle = false;

        //here output point
        exportData(X, Y, Z0);
    }
}

void Decoder::rapidMode()
{
    quint8 byte = 0b11000000;//0b11 reserved for velocity setup
    int timerVal = round(invSpeedconst / rapidSpeed);
    byte = byte | static_cast<quint8>(timerVal);
    steps.append(byte);
}

void Decoder::feedMode()
{
    quint8 byte = 0b11000000;//0b11 reserved for velocity setup
    int timerVal = round(invSpeedconst / feedSpeed);
    byte = byte | static_cast<quint8>(timerVal);
    steps.append(byte);
}

void Decoder::exportData(double X, double Y, double Z)
{
    posValues << X << " " << Y << " " << Z <<"\n";
    posValNum.push_back(X);
    posValNum.push_back(Y);
    posValNum.push_back(Z);

    if (posValNum.size() > 3)
    {
        quint8 byte = 0;
        // TODO

        int Xstep = (posValNum.at(posValNum.size() - 3) - posValNum.at(posValNum.size() - 6));
        int Ystep = (posValNum.at(posValNum.size() - 2) - posValNum.at(posValNum.size() - 5));
        int Zstep = (posValNum.at(posValNum.size() - 1) - posValNum.at(posValNum.size() - 4));
        //qDebug() << Xstep << " " << Ystep << " " << Zstep;

        if (reversedX) Xstep=-Xstep;
        if (reversedY) Ystep=-Ystep;
        if (reversedZ) Zstep=-Zstep;

        if (Xstep > 0) byte |= 0b00000001;
        if (Ystep > 0) byte |= 0b00000010;
        if (Zstep > 0) byte |= 0b00000100;

        if (Xstep < 0) byte |= 0b00001000;
        if (Ystep < 0) byte |= 0b00010000;
        if (Zstep < 0) byte |= 0b00100000;

        steps.append(byte);
        //qDebug() << byte;
    }
}

void Decoder::writePosFile()
{
    QFile file("output.asc");
    if(file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        qDebug() << "File opened";
        QTextStream stream(&file);
        stream << posValues.readAll();
        file.close();
        qDebug() << "Writing finished";
    }
}

void Decoder::writeStepsFile()
{
    QFile file("steps.dat");
    if(file.open(QIODevice::WriteOnly))
    {
        qDebug() << "Binary file opened";
        file.write(steps);
        file.close();
        qDebug() << "Binary writing finished";
    }
}
void Decoder::getBytes()
{
    while ((byteCounter < steps.length()) && ((byteCounter - recCounter) < stepsBufSize))
    {
        quint8 byte = steps.at(byteCounter);
        emit sendSingleByte(byte);
        byteCounter++;
    }
}

void Decoder::incrRecCounter(int val)
{
    recCounter = recCounter + val;
    //qDebug() << recCounter;
    getBytes();
}

void Decoder::resetBuffs()
{
    posVals.clear();
    posValNum.clear();
    posValues.flush();
    steps.clear();
    byteCounter = 0;
    recCounter = 0;
}
<commit_msg>parse F (feed speed)<commit_after>#include "decoder.h"
#define stepsBufSize 20

Decoder::Decoder(QObject *parent) : QObject(parent)
{
    Xold = 0.0;
    Yold = 0.0;
    Zold = 0.0;
    reversedX = false,
    reversedY = false,
    reversedZ = false;
    byteCounter = 0;
    recCounter = 0;
    useIJ = 1; //important for G02 and G03 commands, driven by G17, G18 and G19
    useIK = 0;
    useJK = 0;
    stepsPerMM = 96;
    invSpeedconst = 3.2; //magic number used to calculate timers
    rapidSpeed = 3.2; //mm/s
    feedSpeed = 0.32;

    posValues.setString(&posVals);
}

void Decoder::decodeCommands(const QStringList lines)
{
    std::vector <double> vals;
    std::vector <QChar> args;
    QChar cmd;
    int number = -1; //numbers fo Gxx

    for (int i = 0; i < lines.count(); i++)
    {
        QString currentLine = lines[i];
        QChar fc = currentLine.at(0); //if the first char in a new line is not G, copy old Gxx and send further
        if (fc != QLatin1Char('G'))
        {
            if (number != -1)
            {
                decodeMovement(number,
                           args, vals);
                vals.clear();
                args.clear();
            }
        }
        //qDebug() << currentLine;

        QStringList cmds = currentLine.split(" ");
        for (int j = 0; j < cmds.count(); j++)
        {
            QString currentCmd = cmds[j];
            //qDebug() << currentCmd;
            QChar c = currentCmd.at(0);

            if (c == QLatin1Char('G'))
            {
                if (number != -1) //send data from previous run
                {
                    decodeMovement(number,
                               args, vals);
                }

                vals.clear(); //preparing for a new packet
                args.clear();

                QString partial;
                for (int s = 1; s < currentCmd.count(); s++)
                {
                    partial += currentCmd.at(s);
                }
                number = partial.toInt();
                //qDebug() << number;
                cmd = c;
            }
            else if(c == QLatin1Char('X') || c == QLatin1Char('Y') || c == QLatin1Char('Z')
                    || c == QLatin1Char('I') || c == QLatin1Char('J') || c == QLatin1Char('K')
                    || c == QLatin1Char('F'))
            {
                QString partial;
                for (int s = 1; s < currentCmd.count(); s++)
                {
                    partial += currentCmd.at(s);
                }
                double value = partial.toDouble();
                //qDebug() << value;
                vals.push_back(value);
                args.push_back(c);
            }

        }
    }
    if (number != -1) //read the last line
    {
        decodeMovement(number,
                   args, vals);
    }
    writePosFile(); //write positions (int) to file
    writeStepsFile();
}
void Decoder::decodeMovement(const int num,
                    const std::vector <QChar> args, const std::vector <double> vals)
{
    /*qDebug() << cmd << num;
    for (uint i = 0; i < args.size(); i++)
    {
        qDebug() << args.at(i) << vals.at(i);
    }*/

    if (num == 17) {useIJ = 1; useIK = 0; useJK = 0;}
    if (num == 18) {useIJ = 0; useIK = 1; useJK = 0;}
    if (num == 19) {useIJ = 0; useIK = 0; useJK = 1;}

    if ((num == 0) || (num == 1)) //G00 rapid linear move and G01 feed linear move
    {
        double X = Xold;
        double Y = Yold;
        double Z = Zold;
        double F = 0.0;
        for (uint i = 0; i < args.size(); i++)
        {
            QChar c = args.at(i);
            if (c == QLatin1Char('X')) X = vals.at(i);
            if (c == QLatin1Char('Y')) Y = vals.at(i);
            if (c == QLatin1Char('Z')) Z = vals.at(i);
            if (c == QLatin1Char('F')) F = vals.at(i);
        }
        if (num == 0)
        {
            if (F!=0.0) rapidSpeed = F;
            rapidMode();
        }
        else
        {
            if (F!=0.0) feedSpeed = F;
            feedMode();
        }
        renderLine(Xold, Yold, Zold, X, Y, Z);
        Xold = X; Yold = Y; Zold = Z;
    }
    if ((num == 2) || (num == 3)) //feed cw arc and ccw arc
    {
        double X = Xold;
        double Y = Yold;
        double Z = Zold;
        double R = -1.0; //negative radius does not exist, do it can be used as flag
        double I = 0.0;
        double J = 0.0;
        double F = 0.0;
        //double K = 0.0;
        double CX, CY;
        bool ccw = 0;

        if (num == 03) ccw = 1;

        for (uint i = 0; i < args.size(); i++)
        {
            QChar c = args.at(i);

            if (c == QLatin1Char('R')) R = vals.at(i);
            if (c == QLatin1Char('I')) I = vals.at(i);
            if (c == QLatin1Char('J')) J = vals.at(i);
            if (c == QLatin1Char('X')) X = vals.at(i);
            if (c == QLatin1Char('Y')) Y = vals.at(i);
            if (c == QLatin1Char('Z')) Z = vals.at(i);
            //if (c == QLatin1Char('K')) K = vals.at(i);
            if (c == QLatin1Char('F')) F = vals.at(i); //feed velocity reading
        }

        if (F!=0.0) feedSpeed = F;
        feedMode();

        if ((useIJ) && (R < 0.0))
        {
            CX = Xold + I;
            CY = Yold + J;
            R = std::sqrt((I * I) + (J * J));
            renderCircleXY(Xold, Yold, Zold, X, Y, CX, CY, R, ccw);
        }

        Xold = X; Yold = Y; Zold = Z;
    }
}

void Decoder::renderLine(double X0, double Y0, double Z0,
           double X1, double Y1, double Z1)
{
    X0 = X0 * stepsPerMM;
    Y0 = Y0 * stepsPerMM;
    Z0 = Z0 * stepsPerMM;
    X1 = X1 * stepsPerMM;
    Y1 = Y1 * stepsPerMM;
    Z1 = Z1 * stepsPerMM;

    int Z = std::round(Z0);
    int X = std::round(X0);
    int Y = std::round(Y0);

    qDebug() << "Line Horizontal XY " << X0 << Y0 << Z0 << X1 << Y1 << Z1;

    if (Z0 == Z1)
    {
        int Xend = std::round(X1);
        int Yend = std::round(Y1);
        int Xprobe[3], Yprobe[3]; //have to test 3 points distance to line, point by point

        int dx, dy;
        (X1 > X0) ? dx = 1 : dx = - 1;
        (Y1 > Y0) ? dy = 1 : dy = - 1;

        if (X1 == X0) dx = 0;
        if (Y1 == Y0) dy = 0;

        while (!((X == Xend) && (Y == Yend)))
        {

            double dist, numerator, denominator, Xtmp = 0, Ytmp = 0;
            double olddist = 10000;
            for (int i = 0; i < 3; i++)
            {
                Xprobe[0] = X + dx;
                if (dx == 0) //avoid step = 0
                {
                    Yprobe[0] = Y + dy;
                }
                else
                {
                    Yprobe[0] = Y;
                }
                if (dy == 0)
                {
                    Xprobe[1] = X + dx;
                }
                else
                {
                    Xprobe[1] = X;
                }
                Yprobe[1] = Y + dy;
                Xprobe[2] = X + dx;
                Yprobe[2] = Y + dy;

                numerator = std::abs((Y1 - Y0) * Xprobe[i] - (X1 - X0) * Yprobe[i] + X1 * Y0 - Y1 * X0);
                denominator = std::sqrt(std::pow((Y1 - Y0), 2) + std::pow((X1 - X0), 2));
                dist = numerator / denominator;

                //qDebug() << X << Y << "dist" << dist;
                if (dist < olddist)
                {
                    olddist = dist;
                    Xtmp = Xprobe[i];
                    Ytmp = Yprobe[i];
                }
            }
            X = Xtmp;
            Y = Ytmp;

            if (dist >= 2) //? for more testing
            {
                qDebug() << "Something went wrong. Distance is: " << dist;
                break;
            }
            //here output point, what about endpoints?
            exportData(X, Y, Z);
        }
    }
    if ((X0 == X1) || (Y0 == Y1))
    {
        int dz;
        int Zend = std::round(Z1);

        qDebug() << "Vertical " << Z0 << Z1;
        (Z1 > Z0) ? dz = 1 : dz = - 1;
        while (Z != Zend)
        {
            Z = Z + dz;
            //here output point
            exportData(X, Y, Z);
        }
    }
}
void Decoder::renderCircleXY(double X0, double Y0, double Z0,
                             double X1, double Y1,
                             double CX, double CY, double R, bool ccw)
{
    X0 = X0 * stepsPerMM;
    Y0 = Y0 * stepsPerMM;
    Z0 = Z0 * stepsPerMM;
    X1 = X1 * stepsPerMM;
    Y1 = Y1 * stepsPerMM;
    CX = CX * stepsPerMM;
    CY = CY * stepsPerMM;
    R = R * stepsPerMM;

    qDebug() << "Circle XY " << X0 << Y0 << X1 << Y1 << CX << CY << R << ccw;
    int X = std::round(X0);
    int Y = std::round(Y0);
    int Xend = std::round(X1);
    int Yend = std::round(Y1);
    int Xprobe[3], Yprobe[3]; //have to test 3 points distance to circle, point by point
    bool fullCircle = false;
    int dx = 0, dy = 0;

    if ((X == Xend) && (Y == Yend)) fullCircle = true;

    while (!((X == Xend) && (Y == Yend) && (!fullCircle)))
    {
        if (ccw)
        {
            if ((X >= CX) && (Y >= CY)) //first quarter
            {
                dx = -1;
                dy = 1;
            }
            if ((X <= CX) && (Y >= CY))
            {
                dx = -1;
                dy = -1;
            }
            if ((X <= CX) && (Y <= CY))
            {
                dx = 1;
                dy = -1;
            }
            if ((X >= CX) && (Y <= CY))
            {
                dx = 1;
                dy = 1;
            }
        }
        else //CW case
        {
            if ((X >= CX) && (Y >= CY)) //first quarter
            {
                dx = 1;
                dy = -1;
            }
            if ((X <= CX) && (Y >= CY))
            {
                dx = 1;
                dy = 1;
            }
            if ((X <= CX) && (Y <= CY))
            {
                dx = -1;
                dy = 1;
            }
            if ((X >= CX) && (Y <= CY))
            {
                dx = -1;
                dy = -1;
            }
        }

        Xprobe[0] = X + dx;
        Yprobe[0] = Y;
        Xprobe[1] = X;
        Yprobe[1] = Y + dy;
        Xprobe[2] = X + dx;
        Yprobe[2] = Y + dy;

        double dist, Xtmp = 0, Ytmp = 0;
        double olddist = 10000;
        for (int i = 0; i < 3; i++)
        {
            dist = std::abs(std::sqrt(std::pow((CX - Xprobe[i]), 2) + std::pow((CY - Yprobe[i]), 2)) - R);
            if (dist < olddist)
            {
                olddist = dist;
                Xtmp = Xprobe[i];
                Ytmp = Yprobe[i];
            }
        }

        X = Xtmp;
        Y = Ytmp;

        fullCircle = false;

        //here output point
        exportData(X, Y, Z0);
    }
}

void Decoder::rapidMode()
{
    quint8 byte = 0b11000000;//0b11 reserved for velocity setup
    int timerVal = round(invSpeedconst / rapidSpeed);
    byte = byte | static_cast<quint8>(timerVal);
    steps.append(byte);
}

void Decoder::feedMode()
{
    quint8 byte = 0b11000000;//0b11 reserved for velocity setup
    int timerVal = round(invSpeedconst / feedSpeed);
    byte = byte | static_cast<quint8>(timerVal);
    steps.append(byte);
}

void Decoder::exportData(double X, double Y, double Z)
{
    posValues << X << " " << Y << " " << Z <<"\n";
    posValNum.push_back(X);
    posValNum.push_back(Y);
    posValNum.push_back(Z);

    if (posValNum.size() > 3)
    {
        quint8 byte = 0;
        // TODO

        int Xstep = (posValNum.at(posValNum.size() - 3) - posValNum.at(posValNum.size() - 6));
        int Ystep = (posValNum.at(posValNum.size() - 2) - posValNum.at(posValNum.size() - 5));
        int Zstep = (posValNum.at(posValNum.size() - 1) - posValNum.at(posValNum.size() - 4));
        //qDebug() << Xstep << " " << Ystep << " " << Zstep;

        if (reversedX) Xstep=-Xstep;
        if (reversedY) Ystep=-Ystep;
        if (reversedZ) Zstep=-Zstep;

        if (Xstep > 0) byte |= 0b00000001;
        if (Ystep > 0) byte |= 0b00000010;
        if (Zstep > 0) byte |= 0b00000100;

        if (Xstep < 0) byte |= 0b00001000;
        if (Ystep < 0) byte |= 0b00010000;
        if (Zstep < 0) byte |= 0b00100000;

        steps.append(byte);
        //qDebug() << byte;
    }
}

void Decoder::writePosFile()
{
    QFile file("output.asc");
    if(file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        qDebug() << "File opened";
        QTextStream stream(&file);
        stream << posValues.readAll();
        file.close();
        qDebug() << "Writing finished";
    }
}

void Decoder::writeStepsFile()
{
    QFile file("steps.dat");
    if(file.open(QIODevice::WriteOnly))
    {
        qDebug() << "Binary file opened";
        file.write(steps);
        file.close();
        qDebug() << "Binary writing finished";
    }
}
void Decoder::getBytes()
{
    while ((byteCounter < steps.length()) && ((byteCounter - recCounter) < stepsBufSize))
    {
        quint8 byte = steps.at(byteCounter);
        emit sendSingleByte(byte);
        byteCounter++;
    }
}

void Decoder::incrRecCounter(int val)
{
    recCounter = recCounter + val;
    //qDebug() << recCounter;
    getBytes();
}

void Decoder::resetBuffs()
{
    posVals.clear();
    posValNum.clear();
    posValues.flush();
    steps.clear();
    byteCounter = 0;
    recCounter = 0;
}
<|endoftext|>