<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: server.C,v 1.4 2003/09/19 18:17:59 amoll Exp $

#include <BALL/VIEW/KERNEL/server.h>
#include <BALL/VIEW/KERNEL/mainControl.h>
#include <BALL/VIEW/KERNEL/message.h>
#include <BALL/VIEW/DIALOGS/preferences.h>
#include <BALL/VIEW/DIALOGS/serverPreferences.h>
#include <BALL/SYSTEM/socket.h>
#include <BALL/FORMAT/INIFile.h>

#include <qstatusbar.h>
#include <qpixmap.h>
#include <qtooltip.h>
#include <qstring.h>
#include <qlabel.h>

using namespace std;

namespace BALL
{
	namespace VIEW
	{
		const char* Server::mini_ray_xpm_[] =
		{
        "16 14 4 1",
        "   c None",
        ".  c black",
        "X  c yellow",
        "o  c gray50",
        "     .........  ",
        "     .XXXXXX.o  ",
        "    .XXXXXX.o   ",
        "    .XXXXX.o    ",
        "   .XXXXX.o     ",
        "   .XXXX.....   ",
        "  .XXXXXXXX.o   ",
        "  .....XXX.o    ",
        "   oo.XXX.o     ",
        "     .XX.o      ",
        "    .XX.o       ",
        "    .X.o        ",
        "   .X.o         ",
        "   ..o          "
		};

		Server::NotCompositeObject::NotCompositeObject(const char* file, int line)
			throw()
			:	Exception::GeneralException(file, line, string("NotCompositeObject"), string("received an non composite object!"))
		{
		}

		Server::Server(QWidget* parent, const char* name)
				throw()
			:	QTTimer(parent, name),
				ModularWidget(name),
				object_creator_(0),
				composite_hashmap_(),
				iostream_socket_(0),
				sock_inet_buf_(0),
				port_(VIEW_DEFAULT_PORT),
				server_preferences_(0),
				server_icon_(0)
		{

#ifdef BALL_VIEW_DEBUG
	Log.error() << "new Server " << this << std::endl;
#endif
			// register ModularWidget
			registerWidget(this);

			unregisterObjectCreator();
		}

		Server::~Server()
			throw()
		{
			#ifdef BALL_VIEW_DEBUG
				Log.error() << "Destructing object " << this << " Server" << std::endl;
			#endif

			ConnectionObject::destroy();
		}

		void Server::clear()
			throw()
		{
			QTTimer::clear();
			ConnectionObject::clear();
		}

		// initializes a new socket and starts the timer
		void Server::activate()
				throw()
		{
			static SockInetBuf sock_inet_buf(SocketBuf::sock_stream);

			// if the timer is already running, clear it and close the
			// socket first
			if (isTimerEnabled())
			{
				stopTimer();
				sock_inet_buf.close();
			}

			if (sock_inet_buf.bind(0, port_) != 0)
			{
				Log.error() << "VIEW::Server: cannot bind to port " << port_ << endl;
				return;
			}

			sock_inet_buf_ = &sock_inet_buf;

			Log.info() << "VIEW::Server: listening at port "
								 << sock_inet_buf_->localhost() << ":"
								 << sock_inet_buf_->localport() << endl;

			sock_inet_buf_->listen();

			// check once per second
			setInterval(1000);
			startTimer();
		}

		void Server::deactivate()
				throw()
		{
			if (isTimerEnabled())
			{
				Log.info() << "VIEW::Server: stopped." << endl;
				stopTimer();
				sock_inet_buf_->close();
			}
		}

		int Server::getPort() const
				throw()
		{
			return port_;
		}

		void Server::setPort(const int port)
				throw()
		{
			port_ = port;
		}

		void Server::initializeWidget(MainControl& main_control)
				throw()
		{
			server_icon_ = new QLabel(main_control.statusBar());
			main_control.statusBar()->addWidget(server_icon_, 1, TRUE );
			QToolTip::add(server_icon_, "VIEW server status");
			QPixmap icon(mini_ray_xpm_);

			server_icon_->setPixmap(icon);
			server_icon_->show();
 		}

		void Server::finalizeWidget(MainControl& main_control)
				throw()
		{
			main_control.statusBar()->removeWidget(server_icon_);
			delete server_icon_;
		}

		void Server::checkMenu(MainControl& /* main_control */)
				throw()
		{
		}

		void Server::initializePreferencesTab(Preferences &preferences)
				throw()
		{
			server_preferences_ = new ServerPreferences();
			CHECK_PTR(server_preferences_);

			preferences.insertTab(server_preferences_, "Server");
		}

		void Server::finalizePreferencesTab(Preferences &preferences)
				throw()
		{
			if (server_preferences_ != 0)
			{
				preferences.removeTab(server_preferences_);

				delete server_preferences_;
				server_preferences_ = 0;
			}
		}

		void Server::applyPreferences(Preferences & /* preferences */)
				throw()
		{
			if (server_preferences_ == 0) return;

			// get server mode
			if (server_preferences_->getServerStatus())
			{
				// retrieve the port number
				int port = server_preferences_->getPort();

				// set the port and active the server
				setPort(port);
				activate();

				// adjust the tool tip and update the server icon
				QString tip;
				tip.sprintf("VIEW Server listening on port %d", port);
				QToolTip::add(server_icon_, tip);
				server_icon_->show();
			}
			else
			{
				// stop the server
				deactivate();

				// hide the icon
				server_icon_->hide();
				QToolTip::add(server_icon_, "VIEW Server disabled");
			}

			setStatusbarText("");
		}

		void Server::fetchPreferences(INIFile &inifile)
				throw()
		{
			// the default preferences tab (if existent)
			if (server_preferences_ != 0)
			{
				server_preferences_->fetchPreferences(inifile);
			}
		}

		void Server::writePreferences(INIFile &inifile)
				throw()
		{
			// the default preferences tab (if existent)
			if (server_preferences_ != 0)
			{
				server_preferences_->writePreferences(inifile);
			}
		}

		bool Server::isValid() const
			throw()
		{
			return (ConnectionObject::isValid());
		}

		void Server::dump(ostream& s, Size depth) const
			throw()
		{
			BALL_DUMP_STREAM_PREFIX(s);

			BALL_DUMP_DEPTH(s, depth);
			BALL_DUMP_HEADER(s, this, this);

			QTTimer::dump(s, depth + 1);
			ConnectionObject::dump(s, depth + 1);

			BALL_DUMP_STREAM_SUFFIX(s);
		}

		// main event loop
	  void Server::timer()
		{
			unsigned int command;

			// wait until socket is read ready
			if (!sock_inet_buf_->is_readready(0,20))
			{
				return;
			}

			// open stream socket
			IOStreamSocket iostream_socket(sock_inet_buf_->accept());

			// reading command
			iostream_socket >> command;

			// process commands
			switch (command)
			{
  			case COMMAND__SEND_OBJECT:
					sendObject(iostream_socket);
				break;

   			default:
					Log.info() << "Server: unkown command." << endl;
					break;
			}
		}

	  void Server::sendObject(IOStreamSocket &iostream_socket)
				throw(Server::NotCompositeObject)
    {
			Log.info() << "Server: receiving object ... " << endl;

			unsigned long object_handle;

			// get object handle
			iostream_socket >> object_handle;

			Composite *new_composite_ptr = 0;

			Log.info() << "creating object: object_creator_ = " << object_creator_ << endl;

			// use specified object creator for inserting the object in the scene
			new_composite_ptr = object_creator_->operator()(iostream_socket);

			if (new_composite_ptr == 0)
			{
				throw NotCompositeObject(__FILE__, __LINE__);
			}

			received_composite_ = new_composite_ptr;

			// get composite with handle
 			CompositeHashMap::Iterator iterator = composite_hashmap_.find(object_handle);

	 		Composite* inserted_composite_ptr = 0;

		 	// already in hashmap ?
			if (iterator != composite_hashmap_.end())
			{
			 	// get it
				inserted_composite_ptr = iterator->second;
 			}

			// composite already exists ?
			if (inserted_composite_ptr != 0)
			{
				try
				{
					// remove old composite
					CompositeMessage* message = new CompositeMessage;
					message->setComposite(*inserted_composite_ptr);
					message->setType(CompositeMessage::REMOVED_COMPOSITE);
					message->setDeletable(false);
					notify_(message);

					// remove composite from hashmap
					composite_hashmap_.erase(object_handle);

					// delete old composite
					delete inserted_composite_ptr;
				}
				catch (...)
				{
					Log.info() << "> Server: error deleting old composite!" << endl;
				}
			}

			// insert into hashmap
			composite_hashmap_.insert(CompositeHashMap::ValueType(object_handle, new_composite_ptr));

			// notify main window
			CompositeMessage* new_message = new CompositeMessage;
			new_message->setComposite(*new_composite_ptr);
			new_message->setType(CompositeMessage::NEW_COMPOSITE);
			new_message->setDeletable(false);
			notify_(new_message);
    }

#		ifdef BALL_NO_INLINE_FUNCTIONS
#			include <BALL/VIEW/KERNEL/server.iC>
#		endif

} } // namespaces
<commit_msg>now creating all messages on the heap<commit_after>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: server.C,v 1.5 2003/09/22 11:26:03 amoll Exp $

#include <BALL/VIEW/KERNEL/server.h>
#include <BALL/VIEW/KERNEL/mainControl.h>
#include <BALL/VIEW/KERNEL/message.h>
#include <BALL/VIEW/DIALOGS/preferences.h>
#include <BALL/VIEW/DIALOGS/serverPreferences.h>
#include <BALL/SYSTEM/socket.h>
#include <BALL/FORMAT/INIFile.h>

#include <qstatusbar.h>
#include <qpixmap.h>
#include <qtooltip.h>
#include <qstring.h>
#include <qlabel.h>

using namespace std;

namespace BALL
{
	namespace VIEW
	{
		const char* Server::mini_ray_xpm_[] =
		{
        "16 14 4 1",
        "   c None",
        ".  c black",
        "X  c yellow",
        "o  c gray50",
        "     .........  ",
        "     .XXXXXX.o  ",
        "    .XXXXXX.o   ",
        "    .XXXXX.o    ",
        "   .XXXXX.o     ",
        "   .XXXX.....   ",
        "  .XXXXXXXX.o   ",
        "  .....XXX.o    ",
        "   oo.XXX.o     ",
        "     .XX.o      ",
        "    .XX.o       ",
        "    .X.o        ",
        "   .X.o         ",
        "   ..o          "
		};

		Server::NotCompositeObject::NotCompositeObject(const char* file, int line)
			throw()
			:	Exception::GeneralException(file, line, string("NotCompositeObject"), string("received an non composite object!"))
		{
		}

		Server::Server(QWidget* parent, const char* name)
				throw()
			:	QTTimer(parent, name),
				ModularWidget(name),
				object_creator_(0),
				composite_hashmap_(),
				iostream_socket_(0),
				sock_inet_buf_(0),
				port_(VIEW_DEFAULT_PORT),
				server_preferences_(0),
				server_icon_(0)
		{

#ifdef BALL_VIEW_DEBUG
	Log.error() << "new Server " << this << std::endl;
#endif
			// register ModularWidget
			registerWidget(this);

			unregisterObjectCreator();
		}

		Server::~Server()
			throw()
		{
			#ifdef BALL_VIEW_DEBUG
				Log.error() << "Destructing object " << this << " Server" << std::endl;
			#endif

			ConnectionObject::destroy();
		}

		void Server::clear()
			throw()
		{
			QTTimer::clear();
			ConnectionObject::clear();
		}

		// initializes a new socket and starts the timer
		void Server::activate()
				throw()
		{
			static SockInetBuf sock_inet_buf(SocketBuf::sock_stream);

			// if the timer is already running, clear it and close the
			// socket first
			if (isTimerEnabled())
			{
				stopTimer();
				sock_inet_buf.close();
			}

			if (sock_inet_buf.bind(0, port_) != 0)
			{
				Log.error() << "VIEW::Server: cannot bind to port " << port_ << endl;
				return;
			}

			sock_inet_buf_ = &sock_inet_buf;

			Log.info() << "VIEW::Server: listening at port "
								 << sock_inet_buf_->localhost() << ":"
								 << sock_inet_buf_->localport() << endl;

			sock_inet_buf_->listen();

			// check once per second
			setInterval(1000);
			startTimer();
		}

		void Server::deactivate()
				throw()
		{
			if (isTimerEnabled())
			{
				Log.info() << "VIEW::Server: stopped." << endl;
				stopTimer();
				sock_inet_buf_->close();
			}
		}

		int Server::getPort() const
				throw()
		{
			return port_;
		}

		void Server::setPort(const int port)
				throw()
		{
			port_ = port;
		}

		void Server::initializeWidget(MainControl& main_control)
				throw()
		{
			server_icon_ = new QLabel(main_control.statusBar());
			main_control.statusBar()->addWidget(server_icon_, 1, TRUE );
			QToolTip::add(server_icon_, "VIEW server status");
			QPixmap icon(mini_ray_xpm_);

			server_icon_->setPixmap(icon);
			server_icon_->show();
 		}

		void Server::finalizeWidget(MainControl& main_control)
				throw()
		{
			main_control.statusBar()->removeWidget(server_icon_);
			delete server_icon_;
		}

		void Server::checkMenu(MainControl& /* main_control */)
				throw()
		{
		}

		void Server::initializePreferencesTab(Preferences &preferences)
				throw()
		{
			server_preferences_ = new ServerPreferences();
			CHECK_PTR(server_preferences_);

			preferences.insertTab(server_preferences_, "Server");
		}

		void Server::finalizePreferencesTab(Preferences &preferences)
				throw()
		{
			if (server_preferences_ != 0)
			{
				preferences.removeTab(server_preferences_);

				delete server_preferences_;
				server_preferences_ = 0;
			}
		}

		void Server::applyPreferences(Preferences & /* preferences */)
				throw()
		{
			if (server_preferences_ == 0) return;

			// get server mode
			if (server_preferences_->getServerStatus())
			{
				// retrieve the port number
				int port = server_preferences_->getPort();

				// set the port and active the server
				setPort(port);
				activate();

				// adjust the tool tip and update the server icon
				QString tip;
				tip.sprintf("VIEW Server listening on port %d", port);
				QToolTip::add(server_icon_, tip);
				server_icon_->show();
			}
			else
			{
				// stop the server
				deactivate();

				// hide the icon
				server_icon_->hide();
				QToolTip::add(server_icon_, "VIEW Server disabled");
			}

			setStatusbarText("");
		}

		void Server::fetchPreferences(INIFile &inifile)
				throw()
		{
			// the default preferences tab (if existent)
			if (server_preferences_ != 0)
			{
				server_preferences_->fetchPreferences(inifile);
			}
		}

		void Server::writePreferences(INIFile &inifile)
				throw()
		{
			// the default preferences tab (if existent)
			if (server_preferences_ != 0)
			{
				server_preferences_->writePreferences(inifile);
			}
		}

		bool Server::isValid() const
			throw()
		{
			return (ConnectionObject::isValid());
		}

		void Server::dump(ostream& s, Size depth) const
			throw()
		{
			BALL_DUMP_STREAM_PREFIX(s);

			BALL_DUMP_DEPTH(s, depth);
			BALL_DUMP_HEADER(s, this, this);

			QTTimer::dump(s, depth + 1);
			ConnectionObject::dump(s, depth + 1);

			BALL_DUMP_STREAM_SUFFIX(s);
		}

		// main event loop
	  void Server::timer()
		{
			unsigned int command;

			// wait until socket is read ready
			if (!sock_inet_buf_->is_readready(0,20))
			{
				return;
			}

			// open stream socket
			IOStreamSocket iostream_socket(sock_inet_buf_->accept());

			// reading command
			iostream_socket >> command;

			// process commands
			switch (command)
			{
  			case COMMAND__SEND_OBJECT:
					sendObject(iostream_socket);
				break;

   			default:
					Log.info() << "Server: unkown command." << endl;
					break;
			}
		}

	  void Server::sendObject(IOStreamSocket &iostream_socket)
				throw(Server::NotCompositeObject)
    {
			Log.info() << "Server: receiving object ... " << endl;

			unsigned long object_handle;

			// get object handle
			iostream_socket >> object_handle;

			Composite *new_composite_ptr = 0;

			Log.info() << "creating object: object_creator_ = " << object_creator_ << endl;

			// use specified object creator for inserting the object in the scene
			new_composite_ptr = object_creator_->operator()(iostream_socket);

			if (new_composite_ptr == 0)
			{
				throw NotCompositeObject(__FILE__, __LINE__);
			}

			received_composite_ = new_composite_ptr;

			// get composite with handle
 			CompositeHashMap::Iterator iterator = composite_hashmap_.find(object_handle);

	 		Composite* inserted_composite_ptr = 0;

		 	// already in hashmap ?
			if (iterator != composite_hashmap_.end())
			{
			 	// get it
				inserted_composite_ptr = iterator->second;
 			}

			// composite already exists ?
			if (inserted_composite_ptr != 0)
			{
				try
				{
					// remove old composite
					CompositeMessage* message = new CompositeMessage;
					message->setComposite(*inserted_composite_ptr);
					message->setType(CompositeMessage::REMOVED_COMPOSITE);
					//message->setDeletable(false);
					message->setDeletable(true);
					notify_(message);

					// remove composite from hashmap
					composite_hashmap_.erase(object_handle);

					// delete old composite
					delete inserted_composite_ptr;
				}
				catch (...)
				{
					Log.info() << "> Server: error deleting old composite!" << endl;
				}
			}

			// insert into hashmap
			composite_hashmap_.insert(CompositeHashMap::ValueType(object_handle, new_composite_ptr));

			// notify main window
			CompositeMessage* new_message = new CompositeMessage;
			new_message->setComposite(*new_composite_ptr);
			new_message->setType(CompositeMessage::NEW_COMPOSITE);
			//new_message->setDeletable(false);
			new_message->setDeletable(true);
			notify_(new_message);
    }

#		ifdef BALL_NO_INLINE_FUNCTIONS
#			include <BALL/VIEW/KERNEL/server.iC>
#		endif

} } // namespaces
<|endoftext|>


<commit_before>// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
//
// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
// This library 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 2.1 of the License.
//
// 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//

//  File   : SALOMEDS_SimanStudy_i.cxx
//  Author : Mikhail PONIKAROV
//  Module : SALOME
//
#include "SALOMEDS_SimanStudy_i.hxx"
#include "SALOMEDS_Study_i.hxx"
#include "SALOMEDS_Study.hxx"
#include "SALOMEDS_Tool.hxx"
#include "SALOME_DataContainer_i.hxx"
#include "SALOME_NamingService.hxx"
#include "SALOME_LifeCycleCORBA.hxx"
#include "Basics_Utils.hxx"
#include "Basics_DirUtils.hxx"
#include "utilities.h"

#ifdef WITH_SIMANIO
#include <SimanIO_Link.hxx>
#include <SimanIO_Activity.hxx>
#endif

#include <SALOMEconfig.h>
#include CORBA_SERVER_HEADER(SALOME_Component)

//============================================================================
/*! Function : SALOMEDS_SimanStudy_i
 *  Purpose  : standard constructor
 */
//============================================================================
SALOMEDS_SimanStudy_i::SALOMEDS_SimanStudy_i(/*SALOMEDSImpl_SimanStudy* theImpl,*/ CORBA::ORB_ptr orb)
{
  _orb = CORBA::ORB::_duplicate(orb);
  _name_service = new SALOME_NamingService(_orb);
#ifdef WITH_SIMANIO
  _checkedOut = new SimanIO_Configuration;
#endif
}

//============================================================================
/*! Function : ~SALOMEDS_SimanStudy_i
 *  Purpose  : standard destructor
 */
//============================================================================
SALOMEDS_SimanStudy_i::~SALOMEDS_SimanStudy_i()
{
#ifdef WITH_SIMANIO
  if (_checkedOut) {
    SimanIO_Configuration::ActivitiesIterator actIter(*_checkedOut);
    for(; actIter.More(); actIter.Next()) {
      SimanIO_Activity::DocumentsIterator aDocIter(actIter.Activity());
      for(; aDocIter.More(); aDocIter.Next()) {
        SimanIO_Document& aDoc = aDocIter.Document();
        SimanIO_Document::FilesIterator aFileIter(aDoc);
        for(; aFileIter.More(); aFileIter.Next()) {
	  std::string aURL = aFileIter.URL();
          std::string aDir = Kernel_Utils::GetDirName(aURL);
          aDir += "/";
          std::string aFileName = aURL.substr(aDir.size());
          SALOMEDS::ListOfFileNames aTmpFiles;
          aTmpFiles.length(1);
          aTmpFiles[0] = aFileName.c_str();
          // try to remove temporary directory that contains this file if directory becomes empty
          SALOMEDS_Tool::RemoveTemporaryFiles(aDir, aTmpFiles, true);
        }
      }
    }
    delete _checkedOut;
  }
#endif
  delete _name_service;
}

//============================================================================
/*! Function : CheckOut
 *  Purpose  : Get data from SIMAN and put it to the given study
 */
//============================================================================
void SALOMEDS_SimanStudy_i::CheckOut(SALOMEDS::Study_ptr theTarget)
{
  // SimanStudy and Study must be located at the same place anyway
  SALOMEDS_Study aStudy(theTarget);
  _study = aStudy.GetLocalImpl();
  if (_study) {
#ifdef WITH_SIMANIO
    int aLocked = _study->GetProperties()->IsLocked();
    if (aLocked) _study->GetProperties()->SetLocked(false);

    SimanIO_Link aLink(_studyId.c_str(), _scenarioId.c_str(), _userId.c_str());
    if (aLink.IsConnected()) {
      // Set "C" locale temporarily to avoid possible localization problems
      Kernel_Utils::Localizer loc;
      *_checkedOut = aLink.RetrieveConf();
      SimanIO_Configuration::ActivitiesIterator actIter(*_checkedOut);
      for(; actIter.More(); actIter.Next()) {
        Engines::EngineComponent_var aComp =
          SALOME_LifeCycleCORBA(_name_service).FindOrLoad_Component("FactoryServerPy", actIter.Activity().Module());
        if (CORBA::is_nil(aComp)) // it is not python container, try to find in C++ container
          SALOME_LifeCycleCORBA(_name_service).FindOrLoad_Component("FactoryServer", actIter.Activity().Module());
        if (CORBA::is_nil(aComp)) {
          MESSAGE("Checkout: component "<<actIter.Activity().Module()<<" is nil");
        } else {
          SimanIO_Activity::DocumentsIterator aDocIter(actIter.Activity());
          for(; aDocIter.More(); aDocIter.Next()) {
            if (_filesId.find(aDocIter.DocId()) == _filesId.end())
              _filesId[aDocIter.DocId()] = std::map<std::string, int>();
            SimanIO_Document& aDoc = aDocIter.Document();
            SimanIO_Document::FilesIterator aFileIter(aDoc);
            for(; aFileIter.More(); aFileIter.Next()) {
              if (aFileIter.GetProcessing() == FILE_IMPORT) {
                // files provided by SIMAN will be removed later, on study close
                Engines::DataContainer_var aData = (new Engines_DataContainer_i(
                  aFileIter.URL(), aDoc.Name(), "", false))->_this();
                Engines::ListOfOptions anEmptyOpts;
                Engines::ListOfIdentifiers_var anIds = aComp->importData(_study->StudyId(), aData, anEmptyOpts);
                for(int anIdNum = 0; anIdNum < anIds->length(); anIdNum++) {
                  const char* anId = anIds[anIdNum];
                  _filesId[aDocIter.DocId()][anId] = aFileIter.Id();
                }
              } else {
                MESSAGE("!!! File just downloaded, not imported:"<<aFileIter.Id());
              }
            }
          }
        }
      }
    } else {
      MESSAGE("There is no connection to SIMAN!");
    }

    if (aLocked) _study->GetProperties()->SetLocked(true);
#endif
  }
}

//============================================================================
/*! Function : CheckIn
 *  Purpose  : Get data from SIMAN study and stores to SIMAN
 */
//============================================================================
void SALOMEDS_SimanStudy_i::CheckIn(const char* theModuleName)
{
  if (_study) {
#ifdef WITH_SIMANIO
    std::string aModuleName(theModuleName);
    SimanIO_Link aLink(_studyId.c_str(), _scenarioId.c_str(), _userId.c_str());
    if (aLink.IsConnected()) {
      // Set "C" locale temporarily to avoid possible localization problems
      Kernel_Utils::Localizer loc;
      SimanIO_Configuration aToStore; // here create and store data in this configuration to check in to SIMAN
      std::string aTmpDir = SALOMEDS_Tool::GetTmpDir(); // temporary directory for checked in files
      int aFileIndex = 0; // for unique file name generation
      std::list<std::string> aTemporaryFileNames;
      SimanIO_Configuration::ActivitiesIterator actIter(*_checkedOut);
      for(; actIter.More(); actIter.Next()) {
        int aDocId = actIter.Activity().DocumentMaxID();
        //if (aDocId < 0) continue; // no documents => no check in
        if (!aModuleName.empty() && aModuleName != actIter.Activity().Module()) {
          continue;
        }
        Engines::EngineComponent_var aComp =
          SALOME_LifeCycleCORBA(_name_service).FindOrLoad_Component("FactoryServerPy", actIter.Activity().Module());
        if (CORBA::is_nil(aComp)) // it is not python container, try to find in C++ container
          SALOME_LifeCycleCORBA(_name_service).FindOrLoad_Component("FactoryServer", actIter.Activity().Module());
        if (CORBA::is_nil(aComp)) {
          MESSAGE("Checkin: component "<<actIter.Activity().Module()<<" is nil");
        } else {
          SimanIO_Document aDoc;
          if (aDocId != -1) // get document is at least one exists in this action, "-1" is the Id of the new document otherwise
            aDoc = actIter.Activity().Document(aDocId);
          Engines::ListOfData_var aList = aComp->getModifiedData(_study->StudyId());
          int aNumData = aList->length();
          for(int aDataIndex = 0; aDataIndex < aNumData; aDataIndex++) {
            Engines::DataContainer_var aData = aList[aDataIndex];
            // store this in the configuration
            SimanIO_Activity& aStoreActivity = aToStore.GetOrCreateActivity(actIter.ActivityId());
            aStoreActivity.SetName(actIter.Activity().Name());
            aStoreActivity.SetModule(actIter.Activity().Module());
            SimanIO_Document& aStoreDoc = aStoreActivity.GetOrCreateDocument(aDocId);
            aStoreDoc.SetName(aDoc.Name());
            // prepare a file to store
            SimanIO_File aStoreFile;

            std::stringstream aNumStore;
            aNumStore<<"file"<<(++aFileIndex);
            std::string aFileName(aNumStore.str());
            std::string anExtension(aData->extension());
            aFileName += "." + anExtension;
            std::string aFullPath = aTmpDir + aFileName;
            Engines::TMPFile* aFileStream = aData->get();
            const char *aBuffer = (const char*)aFileStream->NP_data();
#ifdef WIN32
            std::ofstream aFile(aFullPath.c_str(), std::ios::binary);
#else
            std::ofstream aFile(aFullPath.c_str());
#endif
            aFile.write(aBuffer, aFileStream->length());
            aFile.close();
            aTemporaryFileNames.push_back(aFileName);

            aStoreFile.url = aFullPath;
            if (_filesId[aDocId].find(aData->identifier()) != _filesId[aDocId].end()) { // file is already exists
              aStoreFile.id = _filesId[aDocId][aData->identifier()];
              aStoreFile.result = aDoc.File(aStoreFile.id).result;
            } else {
              aStoreFile.id = -1; // to be created as new
              aStoreFile.result = true; // new is always result
            }

            aStoreDoc.AddFile(aStoreFile);
          }
        }
      }
      aLink.StoreConf(aToStore);
      // after files have been stored, remove them from the temporary directory
      SALOMEDS::ListOfFileNames aTmpFiles;
      aTmpFiles.length(aTemporaryFileNames.size());
      std::list<std::string>::const_iterator aFilesIter = aTemporaryFileNames.begin();
      for(int a = 0; aFilesIter != aTemporaryFileNames.end(); aFilesIter++, a++) {
        aTmpFiles[a] = aFilesIter->c_str();
      }
      SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir, aTmpFiles, true);
    } else {
      MESSAGE("There is no connection to SIMAN!")
    }
#endif
  }
}

//============================================================================
/*! Function : getReferencedStudy
 *  Purpose  : Returns the %Study with checked out data
 */
//============================================================================
SALOMEDS::Study_ptr SALOMEDS_SimanStudy_i::getReferencedStudy()
{
  SALOMEDS::Study_var aStudy = (new SALOMEDS_Study_i(_study, _orb))->_this();
  return aStudy._retn();
}

//============================================================================
/*! Function : StudyId
 *  Purpose  : The ID of the study in SIMAN server
 */
//============================================================================
char* SALOMEDS_SimanStudy_i::StudyId()
{
  return CORBA::string_dup(_studyId.c_str());
}

//============================================================================
/*! Function : StudyId
 *  Purpose  : The ID of the study in SIMAN server
 */
//============================================================================
void SALOMEDS_SimanStudy_i::StudyId(const char* theId)
{
  _studyId = theId;
}

//============================================================================
/*! Function : ScenarioId
 *  Purpose  : The ID of the scenario in SIMAN server
 */
//============================================================================
char* SALOMEDS_SimanStudy_i::ScenarioId()
{
  return CORBA::string_dup(_scenarioId.c_str());
}

//============================================================================
/*! Function : ScenarioId
 *  Purpose  : The ID of the scenario in SIMAN server
 */
//============================================================================
void SALOMEDS_SimanStudy_i::ScenarioId(const char* theId)
{
  _scenarioId = theId;
}

//============================================================================
/*! Function : UserId
 *  Purpose  : The ID of the user in SIMAN server
 */
//============================================================================
char* SALOMEDS_SimanStudy_i::UserId()
{
  return CORBA::string_dup(_userId.c_str());
}

//============================================================================
/*! Function : UserId
 *  Purpose  : The ID of the user in SIMAN server
 */
//============================================================================
void SALOMEDS_SimanStudy_i::UserId(const char* theId)
{
  _userId = theId;
}

SALOMEDS_SimanStudy_i* SALOMEDS_SimanStudy_i::GetSimanServant(CORBA::ORB_ptr orb)
{
  static SALOMEDS_SimanStudy_i* aServant = 0;
  if (aServant == 0) {
    aServant = new SALOMEDS_SimanStudy_i(orb);
  }
  return aServant;
}

/// PRIVATE FUNCTIONS
/*
CORBA::LongLong SALOMEDS_SimanStudy_i::GetLocalImpl(const char* theHostname, CORBA::Long thePID, CORBA::Boolean& isLocal)
{
#ifdef WIN32
  long pid = (long)_getpid();
#else
  long pid = (long)getpid();
#endif
  isLocal = (strcmp(theHostname, Kernel_Utils::GetHostname().c_str()) == 0 && pid == thePID)?1:0;
  return reinterpret_cast<CORBA::LongLong>(_impl);
}
*/
<commit_msg>Python containers are no more supported<commit_after>// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
//
// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
// This library 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 2.1 of the License.
//
// 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//

//  File   : SALOMEDS_SimanStudy_i.cxx
//  Author : Mikhail PONIKAROV
//  Module : SALOME
//
#include "SALOMEDS_SimanStudy_i.hxx"
#include "SALOMEDS_Study_i.hxx"
#include "SALOMEDS_Study.hxx"
#include "SALOMEDS_Tool.hxx"
#include "SALOME_DataContainer_i.hxx"
#include "SALOME_NamingService.hxx"
#include "SALOME_LifeCycleCORBA.hxx"
#include "Basics_Utils.hxx"
#include "Basics_DirUtils.hxx"
#include "utilities.h"

#ifdef WITH_SIMANIO
#include <SimanIO_Link.hxx>
#include <SimanIO_Activity.hxx>
#endif

#include <SALOMEconfig.h>
#include CORBA_SERVER_HEADER(SALOME_Component)

//============================================================================
/*! Function : SALOMEDS_SimanStudy_i
 *  Purpose  : standard constructor
 */
//============================================================================
SALOMEDS_SimanStudy_i::SALOMEDS_SimanStudy_i(/*SALOMEDSImpl_SimanStudy* theImpl,*/ CORBA::ORB_ptr orb)
{
  _orb = CORBA::ORB::_duplicate(orb);
  _name_service = new SALOME_NamingService(_orb);
#ifdef WITH_SIMANIO
  _checkedOut = new SimanIO_Configuration;
#endif
}

//============================================================================
/*! Function : ~SALOMEDS_SimanStudy_i
 *  Purpose  : standard destructor
 */
//============================================================================
SALOMEDS_SimanStudy_i::~SALOMEDS_SimanStudy_i()
{
#ifdef WITH_SIMANIO
  if (_checkedOut) {
    SimanIO_Configuration::ActivitiesIterator actIter(*_checkedOut);
    for(; actIter.More(); actIter.Next()) {
      SimanIO_Activity::DocumentsIterator aDocIter(actIter.Activity());
      for(; aDocIter.More(); aDocIter.Next()) {
        SimanIO_Document& aDoc = aDocIter.Document();
        SimanIO_Document::FilesIterator aFileIter(aDoc);
        for(; aFileIter.More(); aFileIter.Next()) {
	  std::string aURL = aFileIter.URL();
          std::string aDir = Kernel_Utils::GetDirName(aURL);
          aDir += "/";
          std::string aFileName = aURL.substr(aDir.size());
          SALOMEDS::ListOfFileNames aTmpFiles;
          aTmpFiles.length(1);
          aTmpFiles[0] = aFileName.c_str();
          // try to remove temporary directory that contains this file if directory becomes empty
          SALOMEDS_Tool::RemoveTemporaryFiles(aDir, aTmpFiles, true);
        }
      }
    }
    delete _checkedOut;
  }
#endif
  delete _name_service;
}

//============================================================================
/*! Function : CheckOut
 *  Purpose  : Get data from SIMAN and put it to the given study
 */
//============================================================================
void SALOMEDS_SimanStudy_i::CheckOut(SALOMEDS::Study_ptr theTarget)
{
  // SimanStudy and Study must be located at the same place anyway
  SALOMEDS_Study aStudy(theTarget);
  _study = aStudy.GetLocalImpl();
  if (_study) {
#ifdef WITH_SIMANIO
    int aLocked = _study->GetProperties()->IsLocked();
    if (aLocked) _study->GetProperties()->SetLocked(false);

    SimanIO_Link aLink(_studyId.c_str(), _scenarioId.c_str(), _userId.c_str());
    if (aLink.IsConnected()) {
      // Set "C" locale temporarily to avoid possible localization problems
      Kernel_Utils::Localizer loc;
      *_checkedOut = aLink.RetrieveConf();
      SimanIO_Configuration::ActivitiesIterator actIter(*_checkedOut);
      for(; actIter.More(); actIter.Next()) {
        Engines::EngineComponent_var aComp =
          SALOME_LifeCycleCORBA(_name_service).FindOrLoad_Component("FactoryServer", actIter.Activity().Module());
        if (CORBA::is_nil(aComp)) {
          MESSAGE("Checkout: component "<<actIter.Activity().Module()<<" is nil");
        } else {
          SimanIO_Activity::DocumentsIterator aDocIter(actIter.Activity());
          for(; aDocIter.More(); aDocIter.Next()) {
            if (_filesId.find(aDocIter.DocId()) == _filesId.end())
              _filesId[aDocIter.DocId()] = std::map<std::string, int>();
            SimanIO_Document& aDoc = aDocIter.Document();
            SimanIO_Document::FilesIterator aFileIter(aDoc);
            for(; aFileIter.More(); aFileIter.Next()) {
              if (aFileIter.GetProcessing() == FILE_IMPORT) {
                // files provided by SIMAN will be removed later, on study close
                Engines::DataContainer_var aData = (new Engines_DataContainer_i(
                  aFileIter.URL(), aDoc.Name(), "", false))->_this();
                Engines::ListOfOptions anEmptyOpts;
                Engines::ListOfIdentifiers_var anIds = aComp->importData(_study->StudyId(), aData, anEmptyOpts);
                for(int anIdNum = 0; anIdNum < anIds->length(); anIdNum++) {
                  const char* anId = anIds[anIdNum];
                  _filesId[aDocIter.DocId()][anId] = aFileIter.Id();
                }
              } else {
                MESSAGE("!!! File just downloaded, not imported:"<<aFileIter.Id());
              }
            }
          }
        }
      }
    } else {
      MESSAGE("There is no connection to SIMAN!");
    }

    if (aLocked) _study->GetProperties()->SetLocked(true);
#endif
  }
}

//============================================================================
/*! Function : CheckIn
 *  Purpose  : Get data from SIMAN study and stores to SIMAN
 */
//============================================================================
void SALOMEDS_SimanStudy_i::CheckIn(const char* theModuleName)
{
  if (_study) {
#ifdef WITH_SIMANIO
    std::string aModuleName(theModuleName);
    SimanIO_Link aLink(_studyId.c_str(), _scenarioId.c_str(), _userId.c_str());
    if (aLink.IsConnected()) {
      // Set "C" locale temporarily to avoid possible localization problems
      Kernel_Utils::Localizer loc;
      SimanIO_Configuration aToStore; // here create and store data in this configuration to check in to SIMAN
      std::string aTmpDir = SALOMEDS_Tool::GetTmpDir(); // temporary directory for checked in files
      int aFileIndex = 0; // for unique file name generation
      std::list<std::string> aTemporaryFileNames;
      SimanIO_Configuration::ActivitiesIterator actIter(*_checkedOut);
      for(; actIter.More(); actIter.Next()) {
        int aDocId = actIter.Activity().DocumentMaxID();
        //if (aDocId < 0) continue; // no documents => no check in
        if (!aModuleName.empty() && aModuleName != actIter.Activity().Module()) {
          continue;
        }
        Engines::EngineComponent_var aComp =
          SALOME_LifeCycleCORBA(_name_service).FindOrLoad_Component("FactoryServer", actIter.Activity().Module());
        if (CORBA::is_nil(aComp)) {
          MESSAGE("Checkin: component "<<actIter.Activity().Module()<<" is nil");
        } else {
          SimanIO_Document aDoc;
          if (aDocId != -1) // get document is at least one exists in this action, "-1" is the Id of the new document otherwise
            aDoc = actIter.Activity().Document(aDocId);
          Engines::ListOfData_var aList = aComp->getModifiedData(_study->StudyId());
          int aNumData = aList->length();
          for(int aDataIndex = 0; aDataIndex < aNumData; aDataIndex++) {
            Engines::DataContainer_var aData = aList[aDataIndex];
            // store this in the configuration
            SimanIO_Activity& aStoreActivity = aToStore.GetOrCreateActivity(actIter.ActivityId());
            aStoreActivity.SetName(actIter.Activity().Name());
            aStoreActivity.SetModule(actIter.Activity().Module());
            SimanIO_Document& aStoreDoc = aStoreActivity.GetOrCreateDocument(aDocId);
            aStoreDoc.SetName(aDoc.Name());
            // prepare a file to store
            SimanIO_File aStoreFile;

            std::stringstream aNumStore;
            aNumStore<<"file"<<(++aFileIndex);
            std::string aFileName(aNumStore.str());
            std::string anExtension(aData->extension());
            aFileName += "." + anExtension;
            std::string aFullPath = aTmpDir + aFileName;
            Engines::TMPFile* aFileStream = aData->get();
            const char *aBuffer = (const char*)aFileStream->NP_data();
#ifdef WIN32
            std::ofstream aFile(aFullPath.c_str(), std::ios::binary);
#else
            std::ofstream aFile(aFullPath.c_str());
#endif
            aFile.write(aBuffer, aFileStream->length());
            aFile.close();
            aTemporaryFileNames.push_back(aFileName);

            aStoreFile.url = aFullPath;
            if (_filesId[aDocId].find(aData->identifier()) != _filesId[aDocId].end()) { // file is already exists
              aStoreFile.id = _filesId[aDocId][aData->identifier()];
              aStoreFile.result = aDoc.File(aStoreFile.id).result;
            } else {
              aStoreFile.id = -1; // to be created as new
              aStoreFile.result = true; // new is always result
            }

            aStoreDoc.AddFile(aStoreFile);
          }
        }
      }
      aLink.StoreConf(aToStore);
      // after files have been stored, remove them from the temporary directory
      SALOMEDS::ListOfFileNames aTmpFiles;
      aTmpFiles.length(aTemporaryFileNames.size());
      std::list<std::string>::const_iterator aFilesIter = aTemporaryFileNames.begin();
      for(int a = 0; aFilesIter != aTemporaryFileNames.end(); aFilesIter++, a++) {
        aTmpFiles[a] = aFilesIter->c_str();
      }
      SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir, aTmpFiles, true);
    } else {
      MESSAGE("There is no connection to SIMAN!")
    }
#endif
  }
}

//============================================================================
/*! Function : getReferencedStudy
 *  Purpose  : Returns the %Study with checked out data
 */
//============================================================================
SALOMEDS::Study_ptr SALOMEDS_SimanStudy_i::getReferencedStudy()
{
  SALOMEDS::Study_var aStudy = (new SALOMEDS_Study_i(_study, _orb))->_this();
  return aStudy._retn();
}

//============================================================================
/*! Function : StudyId
 *  Purpose  : The ID of the study in SIMAN server
 */
//============================================================================
char* SALOMEDS_SimanStudy_i::StudyId()
{
  return CORBA::string_dup(_studyId.c_str());
}

//============================================================================
/*! Function : StudyId
 *  Purpose  : The ID of the study in SIMAN server
 */
//============================================================================
void SALOMEDS_SimanStudy_i::StudyId(const char* theId)
{
  _studyId = theId;
}

//============================================================================
/*! Function : ScenarioId
 *  Purpose  : The ID of the scenario in SIMAN server
 */
//============================================================================
char* SALOMEDS_SimanStudy_i::ScenarioId()
{
  return CORBA::string_dup(_scenarioId.c_str());
}

//============================================================================
/*! Function : ScenarioId
 *  Purpose  : The ID of the scenario in SIMAN server
 */
//============================================================================
void SALOMEDS_SimanStudy_i::ScenarioId(const char* theId)
{
  _scenarioId = theId;
}

//============================================================================
/*! Function : UserId
 *  Purpose  : The ID of the user in SIMAN server
 */
//============================================================================
char* SALOMEDS_SimanStudy_i::UserId()
{
  return CORBA::string_dup(_userId.c_str());
}

//============================================================================
/*! Function : UserId
 *  Purpose  : The ID of the user in SIMAN server
 */
//============================================================================
void SALOMEDS_SimanStudy_i::UserId(const char* theId)
{
  _userId = theId;
}

SALOMEDS_SimanStudy_i* SALOMEDS_SimanStudy_i::GetSimanServant(CORBA::ORB_ptr orb)
{
  static SALOMEDS_SimanStudy_i* aServant = 0;
  if (aServant == 0) {
    aServant = new SALOMEDS_SimanStudy_i(orb);
  }
  return aServant;
}

/// PRIVATE FUNCTIONS
/*
CORBA::LongLong SALOMEDS_SimanStudy_i::GetLocalImpl(const char* theHostname, CORBA::Long thePID, CORBA::Boolean& isLocal)
{
#ifdef WIN32
  long pid = (long)_getpid();
#else
  long pid = (long)getpid();
#endif
  isLocal = (strcmp(theHostname, Kernel_Utils::GetHostname().c_str()) == 0 && pid == thePID)?1:0;
  return reinterpret_cast<CORBA::LongLong>(_impl);
}
*/
<|endoftext|>


<commit_before>/**
 * @file
 *  Zenderer/Graphics/Light.hpp - An instance of lighting in the game scene.
 *
 * @author      George Kudrayvtsev (halcyon)
 * @version     2.0
 * @copyright   Apache License v2.0
 *  Licensed under the Apache License, Version 2.0 (the "License").         \n
 *  You may not use this file except in compliance with the License.        \n
 *  You may obtain a copy of the License at:
 *  http://www.apache.org/licenses/LICENSE-2.0                              \n
 *  Unless required by applicable law or agreed to in writing, software     \n
 *  distributed under the License is distributed on an "AS IS" BASIS,       \n
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n
 *  See the License for the specific language governing permissions and     \n
 *  limitations under the License.
 *
 * @addtogroup Graphics
 * @{
 **/

#ifndef ZENDERER__GRAPHICS__LIGHT_HPP
#define ZENDERER__GRAPHICS__LIGHT_HPP

#include "Zenderer/Math/Matrix.hpp"
#include "Zenderer/CoreGraphics/Renderer.hpp"
#include "Zenderer/CoreGraphics/ShaderSet.hpp"

namespace zen
{
namespace gfx
{
    /// Lighting types.
    enum class ZEN_API LightType : int16_t
    {
        ZEN_NO_LIGHT = -1,  ///< An invalid light type
        ZEN_AMBIENT,        ///< Uniform ambient light
        ZEN_SPOTLIGHT,      ///< Angled spot light
        ZEN_POINT           ///< Omnidirectional point light
    };

    /// Represents a light object acting on a graphical scene.
    class ZEN_API CLight
    {
    public:
        /**
         * Constructs a light instance.
         *  The window height is required for the shader to perform some weird
         *  offset calculations that would otherwise give bad results in terms
         *  of light positioning. It defaults to 800px.
         *
         * @param   m_Assets    The asset manager to make the effect from
         * @param   Type        The light type you want
         * @param   window_h    The height of the OpenGL context
         **/
        CLight(asset::CAssetManager& m_Assets,
               const LightType& Type,
               const uint16_t window_h = 800);

        ~CLight();

        bool Init();
        bool IsInit() const;

        bool Enable() const;
        bool Disable() const;

        // Sometimes you don't care about the original position.
        void Adjust(const real_t dx, const real_t dy);

        bool SetBrightness(const real_t brightness);
        bool SetColor(const real_t r, const real_t g, const real_t b);
        bool SetColor(const color3f_t& Color);
        bool SetAttenuation(const real_t c, const real_t l, const real_t q);
        bool SetAttenuation(const math::vector_t& Att);
        bool SetPosition(const real_t x, const real_t y);
        bool SetPosition(const math::vector_t& Pos);
        bool SetMaximumAngle(const real_t degrees);
        bool SetMinimumAngle(const real_t degrees);

        real_t                  GetBrightness() const;
        const color3f_t&        GetColor()      const;
        const math::vector_t&   GetPosition()   const;

    private:
        // Default values
        static math::vector_t   s_DefaultAttenuation;
        static math::vector_t   s_DefaultPosition;
        static color3f_t        s_DefaultColor;
        static real_t           s_DefaultBrightness;
        static real_t           s_DefaultMaxAngle;
        static real_t           s_DefaultMinAngle;

        // We don't use the high-level effect to get more control
        // and minimize uniform parameter lookups.
        gfxcore::CShaderSet m_Shader;

        math::vector_t  m_Att, m_Position, m_Max, m_Min;
        color3f_t       m_Color;
        real_t          m_brt;

        LightType m_type;

        // Uniform locations
        GLint m_loccol,     // Color
              m_locbrt,     // Brightness
              m_locpos,     // Position
              m_locatt,     // Attenuation
              m_loctmx,     // Minimum angle ([loc]ation of [t]heta [m]a[x])
              m_loctmn;     // Maximum angle

        // OpenGL context height (in pixels).
        uint16_t m_height;

        bool m_init;
    };

    // Shortcut for light containers.
    typedef std::vector<CLight*> LightSet_t;

}   // namespace gfx
}   // namespace zen

#endif // ZENDERER__GRAPHICS__LIGHT_HPP

/**
 * @class zen::gfx::CLight
 * @details
 *  Each lighting type has its own special variables and parameters
 *  that can be modified and accessed. See the raw shader files to learn
 *  the specific parameter names, or the specification [here](specs.html).
 **/

/** @} **/
<commit_msg>#3: Light shader offset todo added.<commit_after>/**
 * @file
 *  Zenderer/Graphics/Light.hpp - An instance of lighting in the game scene.
 *
 * @author      George Kudrayvtsev (halcyon)
 * @version     2.0
 * @copyright   Apache License v2.0
 *  Licensed under the Apache License, Version 2.0 (the "License").         \n
 *  You may not use this file except in compliance with the License.        \n
 *  You may obtain a copy of the License at:
 *  http://www.apache.org/licenses/LICENSE-2.0                              \n
 *  Unless required by applicable law or agreed to in writing, software     \n
 *  distributed under the License is distributed on an "AS IS" BASIS,       \n
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n
 *  See the License for the specific language governing permissions and     \n
 *  limitations under the License.
 *
 * @addtogroup Graphics
 * @{
 **/

#ifndef ZENDERER__GRAPHICS__LIGHT_HPP
#define ZENDERER__GRAPHICS__LIGHT_HPP

#include "Zenderer/Math/Matrix.hpp"
#include "Zenderer/CoreGraphics/Renderer.hpp"
#include "Zenderer/CoreGraphics/ShaderSet.hpp"

namespace zen
{
namespace gfx
{
    /// Lighting types.
    enum class ZEN_API LightType : int16_t
    {
        ZEN_NO_LIGHT = -1,  ///< An invalid light type
        ZEN_AMBIENT,        ///< Uniform ambient light
        ZEN_SPOTLIGHT,      ///< Angled spot light
        ZEN_POINT           ///< Omnidirectional point light
    };

    /// Represents a light object acting on a graphical scene.
    class ZEN_API CLight
    {
    public:
        /**
         * Constructs a light instance.
         *  The window height is required for the shader to perform some weird
         *  offset calculations that would otherwise give bad results in terms
         *  of light positioning. It defaults to 800px.
         *
         * @param   m_Assets    The asset manager to make the effect from
         * @param   Type        The light type you want
         * @param   window_h    The height of the OpenGL context
         **/
        CLight(asset::CAssetManager& m_Assets,
               const LightType& Type,
               const uint16_t window_h = 800);

        ~CLight();

        bool Init();
        bool IsInit() const;

        bool Enable() const;
        bool Disable() const;

        // Sometimes you don't care about the original position.
        void Adjust(const real_t dx, const real_t dy);

        bool SetBrightness(const real_t brightness);
        bool SetColor(const real_t r, const real_t g, const real_t b);
        bool SetColor(const color3f_t& Color);
        bool SetAttenuation(const real_t c, const real_t l, const real_t q);
        bool SetAttenuation(const math::vector_t& Att);
        bool SetPosition(const real_t x, const real_t y);
        bool SetPosition(const math::vector_t& Pos);
        bool SetMaximumAngle(const real_t degrees);
        bool SetMinimumAngle(const real_t degrees);

        real_t                  GetBrightness() const;
        const color3f_t&        GetColor()      const;
        const math::vector_t&   GetPosition()   const;

    private:
        // Default values
        static math::vector_t   s_DefaultAttenuation;
        static math::vector_t   s_DefaultPosition;
        static color3f_t        s_DefaultColor;
        static real_t           s_DefaultBrightness;
        static real_t           s_DefaultMaxAngle;
        static real_t           s_DefaultMinAngle;

        // We don't use the high-level effect to get more control
        // and minimize uniform parameter lookups.
        gfxcore::CShaderSet m_Shader;

        math::vector_t  m_Att, m_Position, m_Max, m_Min;
        color3f_t       m_Color;
        real_t          m_brt;

        LightType m_type;

        // Uniform locations
        GLint m_loccol,     // Color
              m_locbrt,     // Brightness
              m_locpos,     // Position
              m_locatt,     // Attenuation
              m_loctmx,     // Minimum angle ([loc]ation of [t]heta [m]a[x])
              m_loctmn;     // Maximum angle

        // OpenGL context height (in pixels).
        uint16_t m_height;

        bool m_init;
    };

    // Shortcut for light containers.
    typedef std::vector<CLight*> LightSet_t;

}   // namespace gfx
}   // namespace zen

#endif // ZENDERER__GRAPHICS__LIGHT_HPP

/**
 * @class zen::gfx::CLight
 * @details
 *  Each lighting type has its own special variables and parameters
 *  that can be modified and accessed. See the raw shader files to learn
 *  the specific parameter names, or the specification [here](specs.html).
 *
 * @todo    Investigate why the `scr_height` parameter is necessary.
 **/

/** @} **/
<|endoftext|>


<commit_before>#ifndef ALEPH_GEOMETRY_COVER_TREE_HH__
#define ALEPH_GEOMETRY_COVER_TREE_HH__

#include <algorithm>
#include <iterator>
#include <limits>
#include <map>
#include <memory>
#include <ostream>
#include <queue>
#include <stack>
#include <stdexcept>
#include <vector>

// FIXME: remove after debugging
#include <iostream>

#include <cassert>
#include <cmath>

namespace aleph
{

namespace geometry
{

/**
  @class CoverTree
  @brief Generic cover tree data structure

  This class models a cover tree data structure, as described in the
  paper "Cover trees for nearest neighbor" by Beygelzimer et al.; an
  implementation is given at:

    http://hunch.net/~jl/projects/cover_tree/cover_tree.html

  This implementation attempts to be as generic as possible. It uses
  the simplified description of the cover tree, as given by Izbicki,
  Shelton in "Faster Cover Trees".
*/

template <class Point, class Metric> class CoverTree
{
public:

  /**
    Covering constant of the cover tree. It might make sense to change
    this later on in order to improve performance. Some papers set the
    constant to `1.3`.
  */

  constexpr static const double coveringConstant = 2.0;

  class Node
  {
  public:

    /** Creates a new node that stores a point */
    Node( const Point& point, long level )
      : _point( point )
      , _level( level )
    {
    }

    /** Calculates current covering distance of the node */
    double coveringDistance() const noexcept
    {
      return std::pow( coveringConstant, static_cast<double>( _level ) );
    }

    /** Calculates current separating distance of the node */
    double separatingDistance() const noexcept
    {
      return std::pow( coveringConstant, static_cast<double>( _level - 1 ) );
    }

    /** @returns true if the node is a leaf node */
    bool isLeaf() const noexcept
    {
      return _children.empty();
    }

    void insert( const Point& p )
    {
      auto d = Metric()( _point, p );

      std::cerr << __FUNCTION__ << ": Inserting " << p << "\n";
      std::cerr << __FUNCTION__ << ": Covering distance           = " << this->coveringDistance() << "\n";
      std::cerr << __FUNCTION__ << ": Distance from point to root = " << d << "\n";

      if( d > this->coveringDistance() )
      {
        while( d > 2 * this->coveringDistance() )
        {
          std::cerr << __FUNCTION__ << ": Distance is bigger than covering distance; need to raise level of tree\n";

          // -----------------------------------------------------------
          //
          // Find a leaf node that can become the new root node with
          // a raised level. If the tree only contains the root node
          // its level can be adjusted multiple times.

          std::stack<Node*> nodes;
          nodes.push( this );

          Node* leaf   = nullptr;
          Node* parent = nullptr;

          // Special case: the root itself is a leaf node; this happens
          // at the beginning of the insertion process and means that a
          // level adjustment has to be performed.
          if( this->isLeaf() )
          {
            this->_level += 1;
            continue;
          }

          while( !nodes.empty() )
          {
            auto node = nodes.top();
            nodes.pop();

            for( auto&& child : node->_children )
            {
              if( child->isLeaf() )
              {
                leaf   = child.get();
                parent = node;
                break;
              }
              else
                nodes.push( child.get() );
            }
          }

          std::cerr << __FUNCTION__ << ": Found leaf node " << leaf->_point << "\n";

          // There is no leaf, so there is nothing to do and we just
          // skip to the bottom where we add the current node as the
          // new root of the tree.
          if( !leaf )
          {
            std::cerr << __FUNCTION__ << ": Unable to identify leaf node\n";
            break;
          }

          assert( leaf );
          assert( parent );

          // Remove leaf from subtree ----------------------------------
          //
          // The previous tree does not contain the leaf node any more,
          // and it can be added as the new root node.

          std::unique_ptr<Node> leaf_ptr( nullptr );

          parent->_children.erase(
            std::remove_if(
              parent->_children.begin(), parent->_children.end(),
              [&leaf, &leaf_ptr] ( std::unique_ptr<Node>& child )
              {
                if( child.get() == leaf )
                {
                  leaf_ptr = std::move( child );
                  return true;
                }

                return false;
              }
            ),
            parent->_children.end()
          );

          // Make leaf node the new root node --------------------------
          //
          // Notice that this does increase the level of the current
          // root. This has to be adjusted for.

          auto oldRoot
            = std::unique_ptr<Node>( new Node( this->_point, this->_level ) );

          for( auto&& child : _children )
            oldRoot->_children.push_back( std::move( child ) );

          _point = leaf->_point;
          _level = _level + 1;

          _children.clear();
          _children.push_back( std::move( oldRoot ) );

          // Since the root of the tree changed, we also have to update
          // the distance calculation.
          d = Metric()( _point, p );

          std::cerr << __FUNCTION__ << ": " << leaf->_point << " is the new root\n";
        }

        // Make current point the new root -----------------------------
        //
        // So far, the new point has not yet been inserted into the
        // tree. This needs to be done now while the cover is valid
        // again.

        auto oldRoot
          = std::unique_ptr<Node>( new Node( this->_point, this->_level ) );

        for( auto&& child : _children )
          oldRoot->_children.push_back( std::move( child ) );

        _point = p;
        _level = _level + 1;

        _children.clear();
        _children.push_back( std::move( oldRoot ) );

        return;
      }

      return insert_( p );
    }

    /**
      Auxiliary function for performing the recursive insertion of a new
      node into the tree.
    */

    void insert_( const Point& p )
    {
      for( auto&& child : _children )
      {
        auto d = Metric()( child->_point, p );
        if( d <= child->coveringDistance() )
        {
          std::cerr << __PRETTY_FUNCTION__ << ": Recursive enumeration of the tree\n";

          // We found a node in which the new point can be inserted
          // *without* violating the covering invariant.
          child->insert_( p );
          return;
        }
      }

      // Add the new point as a child of the current root node. Note the
      // level adjustment.
      _children.push_back( std::unique_ptr<Node>( new Node( p, _level - 1 ) ) );
    }

    Point _point; //< The point stored in the node
    long  _level; //< The level of the node

    /**
      All children of the node. Their order depends on the insertion
      order into the data set.
    */

    std::vector< std::unique_ptr<Node> > _children;
  };

  /**
    Inserts a new point into the cover tree. If the tree is empty,
    the new point will become the root of the tree. Else, it shall
    be inserted according to the covering invariant.
  */

  void insert( const Point& p )
  {
    if( !_root )
      _root = std::unique_ptr<Node>( new Node(p,0) );
    else
      _root->insert( p );
  }

  // Pretty-printing function for the tree; this is only meant for
  // debugging purposes and could conceivably be implemented using
  // `std::ostream`.
  void print( std::ostream& o )
  {
    std::queue<const Node*> nodes;
    nodes.push( _root.get() );

    while( !nodes.empty() )
    {
      {
        auto n = nodes.size();

        for( decltype(n) i = 0; i < n; i++ )
        {
          auto&& node = nodes.front();

          if( i == 0 )
            o << node->_level << ": ";
          else
            o << " ";

          o << node->_point;

          for( auto&& child : node->_children )
            nodes.push( child.get() );

          nodes.pop();
        }

        o << "\n";
      }
    }
  }

  // Tree access -------------------------------------------------------

  /**
    Gets all nodes according to their corresponding level. The order in
    which they are stored per level is essentially random and shouldn't
    be relied on.
  */

  std::multimap<long, Point> getNodesByLevel() const noexcept
  {
    std::multimap<long, Point> levelMap;

    std::queue<const Node*> nodes;
    nodes.push( _root.get() );

    while( !nodes.empty() )
    {
      auto n = nodes.size();

      for( decltype(n) i = 0; i < n; i++ )
      {
        auto&& node = nodes.front();

        levelMap.insert( std::make_pair( node->_level, node->_point ) );

        for( auto&& child : node->_children )
            nodes.push( child.get() );

        nodes.pop();
      }
    }

    return levelMap;
  }

  // Validity checks ---------------------------------------------------
  //
  // These are called by debug code and tests to ensure that the cover
  // tree is correct.

  /**
    Checks the level invariant in the cover tree. The level invariant
    states that the level \f$l$ of the *direct* child of a node \f$p$
    is the level \f$l'-1$, where \f$l'$ is the level of \f$p$.
  */

  bool checkLevelInvariant() const noexcept
  {
    std::queue<const Node*> nodes;
    nodes.push( _root.get() );

    // Initialize the level artificially in order to simplify the code
    // below.
    long level = _root->_level + 1;

    while( !nodes.empty() )
    {
      auto n = nodes.size();

      for( decltype(n) i = 0; i < n; i++ )
      {
        auto&& node = nodes.front();

        if( node->_level != level - 1 )
          return false;

        for( auto&& child : node->_children )
          nodes.push( child.get() );

        nodes.pop();
      }

      level -= 1;
    }

    return true;
  }

  /**
    Checks the covering invariant in the cover tree. The covering
    invariant states that the distance between a child and parent
    node is bounded by the covering distance.
  */

  bool checkCoveringInvariant() const noexcept
  {
    std::queue<const Node*> nodes;
    nodes.push( _root.get() );

    while( !nodes.empty() )
    {
      auto n = nodes.size();
      for( decltype(n) i = 0; i < n; i++ )
      {
        auto&& parent = nodes.front();

        for( auto&& child : parent->_children )
        {
          auto d = Metric()( parent->_point, child->_point );
          if( d > parent->coveringDistance() )
          {
            std::cerr << __FUNCTION__ << ": Covering invariant is violated by ("
                      << parent->_point << "," << child->_point << "): "
                      << d << " > " << parent->coveringDistance() << "\n";

            return false;
          }

          nodes.push( child.get() );
        }

        // All children of the current parent node have been processed,
        // so we can remove it.
        nodes.pop();
      }
    }

    return true;
  }

  /**
    Checks the separating invariant in the cover tree. The separating
    invariant states that the distance between a child and its parent
    is larger than the separating distance.
  */

  bool checkSeparatingInvariant() const noexcept
  {
    std::queue<const Node*> nodes;
    nodes.push( _root.get() );

    while( !nodes.empty() )
    {
      auto n = nodes.size();
      for( decltype(n) i = 0; i < n; i++ )
      {
        auto&& parent = nodes.front();

        for( auto it1 = parent->_children.begin(); it1 != parent->_children.end(); ++it1 )
        {
          for( auto it2 = std::next(it1); it2 != parent->_children.end(); ++it2 )
          {
            // The distance between the two points must by necessity be
            // larger than the separating distance of their parent node
            // in order to satisfy the separating property.

            auto&& p = (*it1)->_point;
            auto&& q = (*it2)->_point;
            auto d   = Metric()(p, q);

            if( d <= parent->separatingDistance() )
            {
              std::cerr << __FUNCTION__ << ": Separating invariant is violated by ("
                        << p << "," << q << "): "
                        << d << " > " << parent->separatingDistance() << "\n";

              return false;
            }
          }

          // Add the child such that the next level of the tree can be
          // visited.
          nodes.push( it1->get() );
        }

        // All children of the current parent node have been processed,
        // so we can remove it.
        nodes.pop();
      }
    }

    return true;
  }

  /**
    Generic validity check of the tree. Combines *all* validity
    criteria, i.e. the level invariant, the covering invariant,
    and the separating invariant.
  */

  bool isValid() const noexcept
  {
    return    this->checkLevelInvariant()
           && this->checkCoveringInvariant()
           && this->checkSeparatingInvariant();
  }

private:

  /** Root pointer of the tree */
  std::unique_ptr<Node> _root;
};

} // namespace geometry

} // namespace aleph

#endif
<commit_msg>Basic map for associating nodes with levels<commit_after>#ifndef ALEPH_GEOMETRY_COVER_TREE_HH__
#define ALEPH_GEOMETRY_COVER_TREE_HH__

#include <algorithm>
#include <iterator>
#include <limits>
#include <map>
#include <memory>
#include <ostream>
#include <queue>
#include <stack>
#include <stdexcept>
#include <vector>

// FIXME: remove after debugging
#include <iostream>

#include <cassert>
#include <cmath>

namespace aleph
{

namespace geometry
{

/**
  @class CoverTree
  @brief Generic cover tree data structure

  This class models a cover tree data structure, as described in the
  paper "Cover trees for nearest neighbor" by Beygelzimer et al.; an
  implementation is given at:

    http://hunch.net/~jl/projects/cover_tree/cover_tree.html

  This implementation attempts to be as generic as possible. It uses
  the simplified description of the cover tree, as given by Izbicki,
  Shelton in "Faster Cover Trees".
*/

template <class Point, class Metric> class CoverTree
{
public:

  /**
    Covering constant of the cover tree. It might make sense to change
    this later on in order to improve performance. Some papers set the
    constant to `1.3`.
  */

  constexpr static const double coveringConstant = 2.0;

  class Node
  {
  public:

    /** Creates a new node that stores a point */
    Node( const Point& point, long level )
      : _point( point )
      , _level( level )
    {
    }

    /** Calculates current covering distance of the node */
    double coveringDistance() const noexcept
    {
      return std::pow( coveringConstant, static_cast<double>( _level ) );
    }

    /** Calculates current separating distance of the node */
    double separatingDistance() const noexcept
    {
      return std::pow( coveringConstant, static_cast<double>( _level - 1 ) );
    }

    /** @returns true if the node is a leaf node */
    bool isLeaf() const noexcept
    {
      return _children.empty();
    }

    void insert( const Point& p )
    {
      auto d = Metric()( _point, p );

      std::cerr << __FUNCTION__ << ": Inserting " << p << "\n";
      std::cerr << __FUNCTION__ << ": Covering distance           = " << this->coveringDistance() << "\n";
      std::cerr << __FUNCTION__ << ": Distance from point to root = " << d << "\n";

      if( d > this->coveringDistance() )
      {
        while( d > 2 * this->coveringDistance() )
        {
          std::cerr << __FUNCTION__ << ": Distance is bigger than covering distance; need to raise level of tree\n";

          // -----------------------------------------------------------
          //
          // Find a leaf node that can become the new root node with
          // a raised level. If the tree only contains the root node
          // its level can be adjusted multiple times.

          std::stack<Node*> nodes;
          nodes.push( this );

          Node* leaf   = nullptr;
          Node* parent = nullptr;

          // Special case: the root itself is a leaf node; this happens
          // at the beginning of the insertion process and means that a
          // level adjustment has to be performed.
          if( this->isLeaf() )
          {
            this->_level += 1;
            continue;
          }

          while( !nodes.empty() )
          {
            auto node = nodes.top();
            nodes.pop();

            for( auto&& child : node->_children )
            {
              if( child->isLeaf() )
              {
                leaf   = child.get();
                parent = node;
                break;
              }
              else
                nodes.push( child.get() );
            }
          }

          std::cerr << __FUNCTION__ << ": Found leaf node " << leaf->_point << "\n";

          // There is no leaf, so there is nothing to do and we just
          // skip to the bottom where we add the current node as the
          // new root of the tree.
          if( !leaf )
          {
            std::cerr << __FUNCTION__ << ": Unable to identify leaf node\n";
            break;
          }

          assert( leaf );
          assert( parent );

          // Remove leaf from subtree ----------------------------------
          //
          // The previous tree does not contain the leaf node any more,
          // and it can be added as the new root node.

          std::unique_ptr<Node> leaf_ptr( nullptr );

          parent->_children.erase(
            std::remove_if(
              parent->_children.begin(), parent->_children.end(),
              [&leaf, &leaf_ptr] ( std::unique_ptr<Node>& child )
              {
                if( child.get() == leaf )
                {
                  leaf_ptr = std::move( child );
                  return true;
                }

                return false;
              }
            ),
            parent->_children.end()
          );

          // Make leaf node the new root node --------------------------
          //
          // Notice that this does increase the level of the current
          // root. This has to be adjusted for.

          auto oldRoot
            = std::unique_ptr<Node>( new Node( this->_point, this->_level ) );

          for( auto&& child : _children )
            oldRoot->_children.push_back( std::move( child ) );

          _point = leaf->_point;
          _level = _level + 1;

          _children.clear();
          _children.push_back( std::move( oldRoot ) );

          // Since the root of the tree changed, we also have to update
          // the distance calculation.
          d = Metric()( _point, p );

          std::cerr << __FUNCTION__ << ": " << leaf->_point << " is the new root\n";
        }

        // Make current point the new root -----------------------------
        //
        // So far, the new point has not yet been inserted into the
        // tree. This needs to be done now while the cover is valid
        // again.

        auto oldRoot
          = std::unique_ptr<Node>( new Node( this->_point, this->_level ) );

        for( auto&& child : _children )
          oldRoot->_children.push_back( std::move( child ) );

        _point = p;
        _level = _level + 1;

        _children.clear();
        _children.push_back( std::move( oldRoot ) );

        return;
      }

      return insert_( p );
    }

    /**
      Auxiliary function for performing the recursive insertion of a new
      node into the tree.
    */

    void insert_( const Point& p )
    {
      for( auto&& child : _children )
      {
        auto d = Metric()( child->_point, p );
        if( d <= child->coveringDistance() )
        {
          std::cerr << __PRETTY_FUNCTION__ << ": Recursive enumeration of the tree\n";

          // We found a node in which the new point can be inserted
          // *without* violating the covering invariant.
          child->insert_( p );
          return;
        }
      }

      // Add the new point as a child of the current root node. Note the
      // level adjustment.
      _children.push_back( std::unique_ptr<Node>( new Node( p, _level - 1 ) ) );
    }

    Point _point; //< The point stored in the node
    long  _level; //< The level of the node

    /**
      All children of the node. Their order depends on the insertion
      order into the data set.
    */

    std::vector< std::unique_ptr<Node> > _children;
  };

  /**
    Inserts a new point into the cover tree. If the tree is empty,
    the new point will become the root of the tree. Else, it shall
    be inserted according to the covering invariant.
  */

  void insert( const Point& p )
  {
    if( !_root )
      _root = std::unique_ptr<Node>( new Node(p,0) );
    else
      _root->insert( p );
  }

  // Pretty-printing function for the tree; this is only meant for
  // debugging purposes and could conceivably be implemented using
  // `std::ostream`.
  void print( std::ostream& o )
  {
    std::queue<const Node*> nodes;
    nodes.push( _root.get() );

    while( !nodes.empty() )
    {
      {
        auto n = nodes.size();

        for( decltype(n) i = 0; i < n; i++ )
        {
          auto&& node = nodes.front();

          if( i == 0 )
            o << node->_level << ": ";
          else
            o << " ";

          o << node->_point;

          for( auto&& child : node->_children )
            nodes.push( child.get() );

          nodes.pop();
        }

        o << "\n";
      }
    }
  }

  // Tree access -------------------------------------------------------

  /**
    Gets all nodes according to their corresponding level. The order in
    which they are stored per level is essentially random and shouldn't
    be relied on.
  */

  std::multimap<long, Point> getNodesByLevel() const noexcept
  {
    std::multimap<long, Point> levelMap;

    std::queue<const Node*> nodes;
    nodes.push( _root.get() );

    while( !nodes.empty() )
    {
      auto n = nodes.size();

      for( decltype(n) i = 0; i < n; i++ )
      {
        auto&& node = nodes.front();

        levelMap.insert( std::make_pair( node->_level, node->_point ) );

        for( auto&& child : node->_children )
            nodes.push( child.get() );

        nodes.pop();
      }
    }

    return levelMap;
  }

  /**
    Gets all nodes (which are supposed to be unique) and assigns them
    their level.

    TODO: This is essentially the *same* implementation as the function
    above, albeit with switched nodes and labels in the map. This needs
    to be consolidated somehow.
  */

  std::map<Point, long> nodesToLevel() const noexcept
  {
    std::map<Point, long> levelMap;

    std::queue<const Node*> nodes;
    nodes.push( _root.get() );

    while( !nodes.empty() )
    {
      auto n = nodes.size();

      for( decltype(n) i = 0; i < n; i++ )
      {
        auto&& node = nodes.front();

        levelMap.insert( std::make_pair( node->_point, node->_level ) );

        for( auto&& child : node->_children )
            nodes.push( child.get() );

        nodes.pop();
      }
    }

    return levelMap;
  }

  // Validity checks ---------------------------------------------------
  //
  // These are called by debug code and tests to ensure that the cover
  // tree is correct.

  /**
    Checks the level invariant in the cover tree. The level invariant
    states that the level \f$l$ of the *direct* child of a node \f$p$
    is the level \f$l'-1$, where \f$l'$ is the level of \f$p$.
  */

  bool checkLevelInvariant() const noexcept
  {
    std::queue<const Node*> nodes;
    nodes.push( _root.get() );

    // Initialize the level artificially in order to simplify the code
    // below.
    long level = _root->_level + 1;

    while( !nodes.empty() )
    {
      auto n = nodes.size();

      for( decltype(n) i = 0; i < n; i++ )
      {
        auto&& node = nodes.front();

        if( node->_level != level - 1 )
          return false;

        for( auto&& child : node->_children )
          nodes.push( child.get() );

        nodes.pop();
      }

      level -= 1;
    }

    return true;
  }

  /**
    Checks the covering invariant in the cover tree. The covering
    invariant states that the distance between a child and parent
    node is bounded by the covering distance.
  */

  bool checkCoveringInvariant() const noexcept
  {
    std::queue<const Node*> nodes;
    nodes.push( _root.get() );

    while( !nodes.empty() )
    {
      auto n = nodes.size();
      for( decltype(n) i = 0; i < n; i++ )
      {
        auto&& parent = nodes.front();

        for( auto&& child : parent->_children )
        {
          auto d = Metric()( parent->_point, child->_point );
          if( d > parent->coveringDistance() )
          {
            std::cerr << __FUNCTION__ << ": Covering invariant is violated by ("
                      << parent->_point << "," << child->_point << "): "
                      << d << " > " << parent->coveringDistance() << "\n";

            return false;
          }

          nodes.push( child.get() );
        }

        // All children of the current parent node have been processed,
        // so we can remove it.
        nodes.pop();
      }
    }

    return true;
  }

  /**
    Checks the separating invariant in the cover tree. The separating
    invariant states that the distance between a child and its parent
    is larger than the separating distance.
  */

  bool checkSeparatingInvariant() const noexcept
  {
    std::queue<const Node*> nodes;
    nodes.push( _root.get() );

    while( !nodes.empty() )
    {
      auto n = nodes.size();
      for( decltype(n) i = 0; i < n; i++ )
      {
        auto&& parent = nodes.front();

        for( auto it1 = parent->_children.begin(); it1 != parent->_children.end(); ++it1 )
        {
          for( auto it2 = std::next(it1); it2 != parent->_children.end(); ++it2 )
          {
            // The distance between the two points must by necessity be
            // larger than the separating distance of their parent node
            // in order to satisfy the separating property.

            auto&& p = (*it1)->_point;
            auto&& q = (*it2)->_point;
            auto d   = Metric()(p, q);

            if( d <= parent->separatingDistance() )
            {
              std::cerr << __FUNCTION__ << ": Separating invariant is violated by ("
                        << p << "," << q << "): "
                        << d << " > " << parent->separatingDistance() << "\n";

              return false;
            }
          }

          // Add the child such that the next level of the tree can be
          // visited.
          nodes.push( it1->get() );
        }

        // All children of the current parent node have been processed,
        // so we can remove it.
        nodes.pop();
      }
    }

    return true;
  }

  /**
    Generic validity check of the tree. Combines *all* validity
    criteria, i.e. the level invariant, the covering invariant,
    and the separating invariant.
  */

  bool isValid() const noexcept
  {
    return    this->checkLevelInvariant()
           && this->checkCoveringInvariant()
           && this->checkSeparatingInvariant();
  }

private:

  /** Root pointer of the tree */
  std::unique_ptr<Node> _root;
};

} // namespace geometry

} // namespace aleph

#endif
<|endoftext|>


<commit_before>/*
 *
 * Copyright (C) 2019 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 *
 */
#include "ze_loader.h"

namespace loader
{
    ///////////////////////////////////////////////////////////////////////////////
    static const char* known_driver_names[] = {
        MAKE_LIBRARY_NAME( "ze_intel_gpu", "0.4"),
    };

    static const size_t num_known_driver_names =
        sizeof( known_driver_names ) / sizeof( known_driver_names[ 0 ] );

    ///////////////////////////////////////////////////////////////////////////////
    context_t context;

    ///////////////////////////////////////////////////////////////////////////////
    context_t::context_t()
    {
        drivers.reserve( num_known_driver_names );
        for( auto name : known_driver_names )
        {
            auto handle = LOAD_DRIVER_LIBRARY( name );
            if( NULL != handle )
            {
                drivers.emplace_back();
                drivers.rbegin()->handle = handle;
            }

        }

        if( getenv_tobool( "ZE_ENABLE_VALIDATION_LAYER" ) )
        {
            validationLayer = LOAD_DRIVER_LIBRARY( MAKE_VALIDATION_LAYER_NAME( "ze_validation_layer" ) );
        }

        forceIntercept = getenv_tobool( "ZE_ENABLE_LOADER_INTERCEPT" );
    };

    ///////////////////////////////////////////////////////////////////////////////
    context_t::~context_t()
    {
        FREE_DRIVER_LIBRARY( validationLayer );

        for( auto& drv : drivers )
        {
            FREE_DRIVER_LIBRARY( drv.handle );
        }
    };
}
<commit_msg>Updated Intel Vendor supported version<commit_after>/*
 *
 * Copyright (C) 2019 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 *
 */
#include "ze_loader.h"

namespace loader
{
    ///////////////////////////////////////////////////////////////////////////////
    static const char* known_driver_names[] = {
        MAKE_LIBRARY_NAME( "ze_intel_gpu", "0.8"),
    };

    static const size_t num_known_driver_names =
        sizeof( known_driver_names ) / sizeof( known_driver_names[ 0 ] );

    ///////////////////////////////////////////////////////////////////////////////
    context_t context;

    ///////////////////////////////////////////////////////////////////////////////
    context_t::context_t()
    {
        drivers.reserve( num_known_driver_names );
        for( auto name : known_driver_names )
        {
            auto handle = LOAD_DRIVER_LIBRARY( name );
            if( NULL != handle )
            {
                drivers.emplace_back();
                drivers.rbegin()->handle = handle;
            }

        }

        if( getenv_tobool( "ZE_ENABLE_VALIDATION_LAYER" ) )
        {
            validationLayer = LOAD_DRIVER_LIBRARY( MAKE_VALIDATION_LAYER_NAME( "ze_validation_layer" ) );
        }

        forceIntercept = getenv_tobool( "ZE_ENABLE_LOADER_INTERCEPT" );
    };

    ///////////////////////////////////////////////////////////////////////////////
    context_t::~context_t()
    {
        FREE_DRIVER_LIBRARY( validationLayer );

        for( auto& drv : drivers )
        {
            FREE_DRIVER_LIBRARY( drv.handle );
        }
    };
}
<|endoftext|>


<commit_before>#ifndef LUCE_HEADER_RANDOM_WELL_HH
#define LUCE_HEADER_RANDOM_WELL_HH
#include <Luce/Configuration.hh>

#include <Luce/Utility/Integer.hh>
#include <Luce/Utility/NonComparable.hh>

#include <cstddef>

namespace Luce
{
	namespace Random
	{
		template<typename ResultTy_,std::size_t W_, std::size_t R_, std::size_t P_,
			std::size_t M1_, std::size_t M2_, std::size_t M3_>
		class WellEngine LUCE_MACRO_FINAL
			: Utility::NonComparable
		{
			LUCE_MACRO_CANNOT_PARENT(WellEngine)

		private:
			typedef WellEngine<ResultTy_, W_, R_, P_, M1_, M2_, M3_> My_;

		public:
			WellEngine();
			WellEngine(const My_& engine);

		public:
			My_& operator=(const My_& engine);

		private:
			void Init();

		private:
			ResultTy_ Seed_[R_];
			ResultTy_ SeedIndex_;
			ResultTy_ Z_[3];
		};

		typedef WellEngine<Utility::UInt32, 32, 16, 0, 13, 9, 5> Well512;
	}

	using Luce::Random::Well512;
}

#include "Detail/Well.hh"
#endif<commit_msg>Update WellEngine<commit_after>#ifndef LUCE_HEADER_RANDOM_WELL_HH
#define LUCE_HEADER_RANDOM_WELL_HH
#include <Luce/Configuration.hh>

#include <Luce/Utility/Integer.hh>
#include <Luce/Utility/NonComparable.hh>

#include <cstddef>

namespace Luce
{
	namespace Random
	{
		template<typename ResultTy_,std::size_t W_, std::size_t R_, std::size_t P_,
			std::size_t M1_, std::size_t M2_, std::size_t M3_>
		class WellEngine LUCE_MACRO_FINAL
			: Utility::NonComparable
		{
			LUCE_MACRO_CANNOT_PARENT(WellEngine)

		public:
			typedef ResultTy_ Result;

		private:
			typedef WellEngine<ResultTy_, W_, R_, P_, M1_, M2_, M3_> My_;

		public:
			WellEngine();
			WellEngine(const My_& engine);

		public:
			My_& operator=(const My_& engine);

		private:
			void Init();

		public:
			static const std::size_t W = W_;
			static const std::size_t R = R_;
			static const std::size_t P = P_;
			static const std::size_t M1 = M1_;
			static const std::size_t M2 = M2_;
			static const std::size_t M3 = M3_;

		private:
			ResultTy_ Seed_[R_];
			ResultTy_ SeedIndex_;
			ResultTy_ Z_[3];
		};

		typedef WellEngine<Utility::UInt32, 32, 16, 0, 13, 9, 5> Well512;
	}

	using Luce::Random::Well512;
}

#include "Detail/Well.hh"
#endif<|endoftext|>