<commit_before>#ifndef QUAD_TREE_HPP
#define QUAD_TREE_HPP

#include <functional>
#include <map>
#include <vector>

struct Rectangle
{
	std::size_t topLeftX;
	std::size_t topLeftY;
	std::size_t width;
	std::size_t height;
};

class QuadTree
{
	public:
		using ObjectsArray = std::vector<std::reference_wrapper<const Rectangle>>;

		QuadTree();
		QuadTree(std::size_t w, std::size_t h);
		QuadTree(std::size_t tlx, std::size_t tly, std::size_t w, std::size_t h);

		void add(const Rectangle& rect);

		ObjectsArray& objects();

	private:
		enum class Corner : std::size_t
		{
			TopLeft,
			TopRight,
			BotRight,
			BotLeft,
			Parent,
		};

		Corner index(const Rectangle& rect);
		void split();

		static constexpr std::size_t maxObjects = 4;

		std::size_t topLeftX;
		std::size_t topLeftY;
		std::size_t width;
		std::size_t height;

		// 0 = top left, 1 = top right, 2 = bottom right, 3 = bottom left
		std::map<Corner, QuadTree> children;

		ObjectsArray objectsArr;
};

#endif
<commit_msg>Gave access to sub-QuadTrees<commit_after>#ifndef QUAD_TREE_HPP
#define QUAD_TREE_HPP

#include <functional>
#include <map>
#include <vector>

struct Rectangle
{
	std::size_t topLeftX;
	std::size_t topLeftY;
	std::size_t width;
	std::size_t height;
};

class QuadTree
{
	public:
		enum class Corner : std::size_t
		{
			TopLeft,
			TopRight,
			BotRight,
			BotLeft,
			Parent,
		};

		using ObjectsArray = std::vector<std::reference_wrapper<const Rectangle>>;
		using Children = std::map<Corner, QuadTree>;

		QuadTree();
		QuadTree(std::size_t w, std::size_t h);
		QuadTree(std::size_t tlx, std::size_t tly, std::size_t w, std::size_t h);

		void add(const Rectangle& rect);

		const ObjectsArray& objects();
		const Children& children();

	private:
		Corner index(const Rectangle& rect);
		void split();

		static constexpr std::size_t maxObjects = 4;

		std::size_t topLeftX;
		std::size_t topLeftY;
		std::size_t width;
		std::size_t height;

		Children childrenMap;

		ObjectsArray objectsArr;
};

#endif
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkSemaphore.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#ifndef __itkSemaphore_cxx_
#define __itkSemaphore_cxx_

#include "itkConfigure.h"
#include "itkSemaphore.h"

#ifdef __APPLE__
extern "C" {
#include <stdio.h>
#include <time.h>
}
#endif

/// DEBUG
extern "C" {
#include <stdio.h>
#include <errno.h>
}
///

namespace itk {

#ifdef __APPLE__
int Semaphore::m_SemaphoreCount = 0;
#endif

#ifdef ITK_USE_UNIX_IPC_SEMAPHORES
int Semaphore::m_IPCSemaphoreKey = 12345;
SimpleMutexLock Semaphore::m_Mutex;
#endif

#ifdef __APPLE__
std::string Semaphore::GetUniqueName()
{
  char s[255];
  time_t t = time(0);
  snprintf(s,255,"MACSEM%d%d\0",t,m_SemaphoreCount);
  return std::string(s);
}
#endif

Semaphore::Semaphore ()
{
#ifdef ITK_USE_UNIX_IPC_SEMAPHORES
  m_Sema= -1;
#endif

#ifdef __APPLE__
  m_Sema = 0;
  m_SemaphoreCount++;
  m_SemaphoreName = Semaphore::GetUniqueName();
#endif

#ifndef ITK_USE_UNIX_IPC_SEMAPHORES

#ifdef ITK_USE_SPROC
  m_Sema = 0;
#endif

#endif

#ifdef ITK_USE_WIN32_THREADS
  m_Sema = 0;
#endif
}

void Semaphore::Initialize(unsigned int value)
{

#ifdef ITK_USE_UNIX_IPC_SEMAPHORES
  // Obtain a lock over the m_IPCSemaphoreKey so that the new semaphore is
  // created with a unique unix_semaphore_key
  Semaphore::m_Mutex.Lock();
  m_Sema = Semaphore::UnixIpcSemaphoreCreate(Semaphore::m_IPCSemaphoreKey);

  // by default the semaphore created has value 0
  Semaphore::m_IPCSemaphoreKey++;
  Semaphore::m_Mutex.Unlock();

  for (unsigned int i = 0; i < value; i++)
    {
    this->Up();
    }
#endif

#ifndef ITK_USE_UNIX_IPC_SEMAPHORES
#ifdef ITK_USE_SPROC
  if (MultiThreader::GetInitialized() == false)
    {
      MultiThreader::Initialize();
    }

  m_Sema = usnewsema(MultiThreader::GetThreadArena(), static_cast<int>(value));
  if ( ! m_Sema )
    {
      itkExceptionMacro( << " sem_init call failed with code " << m_Sema );
    }

#endif
#ifdef ITK_USE_PTHREADS

#if defined sun
  if ( sema_init(&m_Sema, 0, value, NULL ) != 0 )
    {
    itkExceptionMacro( << "sema_init call failed" );
    }
#elif defined  __APPLE__
  m_Sema  = sem_open( m_SemaphoreName.c_str(), O_CREAT, 0x0644, value );
  if ( m_Sema == (sem_t *)SEM_FAILED )
    {
    //  perror("FAILED WITH ERROR:" );
    itkExceptionMacro( << "sem_open call failed on " << m_SemaphoreName.c_str() );
    }
#else
  if ( sem_init(&m_Sema, 0, value) != 0 )
    {
      itkExceptionMacro( << "sem_init call failed" );
    }
#endif // if defined sun

#endif // ifdef ITK_USE_PTHREADS
#endif // ifndef ITK_USE_UNIX_IPC_SEMAPHORES

#ifdef ITK_USE_WIN32_THREADS
  m_Sema = CreateSemaphore( 0, value, 0x7FFFFFFF, 0);
  if (m_Sema == 0)
    {
      itkExceptionMacro( << "CreateSemaphore call failed" );
    }
#endif
}

void Semaphore::Up()
{
#ifdef ITK_USE_UNIX_IPC_SEMAPHORES
  Semaphore::UnixIpcSemaphoreUp(m_Sema);
#endif

#ifndef ITK_USE_UNIX_IPC_SEMAPHORES

#ifdef ITK_USE_SPROC
  if (usvsema(m_Sema) == -1)
    {
      itkExceptionMacro( << "usvsema call failed." );
    }
#endif
#ifdef ITK_USE_PTHREADS
#ifdef sun
  if ( sema_post(&m_Sema) != 0 )
    {
      itkExceptionMacro( << "sema_post call failed." );
    }
#else
#ifdef __APPLE__
  if ( sem_post(m_Sema) != 0 )
    {
    itkExceptionMacro( << "sem_post call failed." );
    }
#else
  if ( sem_post(&m_Sema) != 0 )
    {
      itkExceptionMacro( << "sem_post call failed." );
    }
#endif
#endif // ifdef sun
#endif

#endif  // ITK_USE_UNIX_SEMAPHORES

#ifdef ITK_USE_WIN32_THREADS
  if ( ! ReleaseSemaphore ((HANDLE) m_Sema, 1 , 0) )
    {
      itkExceptionMacro( << "Semaphore post call failed." );
    }
#endif
}

void Semaphore::Down()
{
#ifdef ITK_USE_UNIX_IPC_SEMAPHORES
  Semaphore::UnixIpcSemaphoreDown (m_Sema);
#endif

#ifndef ITK_USE_UNIX_IPC_SEMAPHORES
#ifdef ITK_USE_SPROC
  if (uspsema(m_Sema) == -1)
    {
      itkExceptionMacro( << "uspsema call failed." );
    }
#endif
#ifdef ITK_USE_PTHREADS
#ifdef sun
  if (sema_wait(&m_Sema) != 0)
    {
    itkExceptionMacro( << "sema_wait call failed." );
    }
#else
#ifdef __APPLE__
  if (sem_wait(m_Sema) != 0)
    {
      itkExceptionMacro( << "sem_wait call failed." );
    }
#else

  if (sem_wait(&m_Sema) != 0)
    {
      itkExceptionMacro( << "sem_wait call failed." );
    }
#endif
#endif
#endif
#endif

#ifdef ITK_USE_WIN32_THREADS
  if ( WaitForSingleObject(m_Sema, INFINITE) == WAIT_FAILED )
    {
      itkExceptionMacro( << "WaitForSingleObject call failed. ");
    }
#endif
}

Semaphore::~Semaphore()
{
#ifdef ITK_USE_UNIX_IPC_SEMAPHORES
  if (m_Sema != -1)
    {
      this->Remove();
    }
#endif

#ifndef ITK_USE_UNIX_IPC_SEMAPHORES
#ifdef ITK_USE_SPROC
  if (m_Sema != 0)
    {
      this->Remove();
    }
#endif
#ifdef ITK_USE_PTHREADS
  this->Remove();
#endif
#endif

#ifdef ITK_USE_WIN32_THREADS
  if (m_Sema != 0)
    {
      this->Remove();
    }
#endif
}

void Semaphore::Remove()
{
#ifdef ITK_USE_UNIX_IPC_SEMAPHORES
  if (m_Sema != -1)
    {
      Semaphore::UnixIpcSemaphoreRemove(m_Sema);
      m_Sema= -1;
    }
#endif

#ifndef ITK_USE_UNIX_IPC_SEMAPHORES

#ifdef ITK_USE_SPROC
  if (MultiThreader::GetThreadArena() != 0)
    {
    if (m_Sema != 0)
      {
      usfreesema(m_Sema, MultiThreader::GetThreadArena());
      }
    m_Sema = 0;
    }
#endif

#ifdef ITK_USE_PTHREADS

#ifdef sun
  if ( sema_destroy(&m_Sema) != 0 )
    {
    itkExceptionMacro( << "sema_destroy call failed. " );
    }
#else

#ifndef __sgi
#ifndef __APPLE__
  // IRIX pthreads implementation of sem_destroy is buggy
  if ( sem_destroy(&m_Sema) != 0 )
    {
    itkExceptionMacro( << "sem_destroy call failed. " );
    }
#endif
#endif

#endif  // sun
#endif // pthreads

#endif // semaphores
  //#endif

#ifdef ITK_USE_WIN32_THREADS
  if (m_Sema != 0)
    {
    CloseHandle(m_Sema);
    }
  m_Sema= 0;
#endif
}

#ifdef ITK_USE_UNIX_IPC_SEMAPHORES

// UnixIpcSemaphoreCreate: will return the semaphore id (system wide)
// of the semaphore number (key) you give.
// If no semaphore has been established for this number, one is created.
int Semaphore::UnixIpcSemaphoreCreate(int unix_semaphore_key)
{
  int sid = -1;
  std::string s;

  if( (sid = semget( (key_t)unix_semaphore_key, 1, 0666 | IPC_CREAT )) == -1 )
    {
    s =  "Error# %i in function UnixIpcSemaphoreCreate. - ";
    switch (errno)
      {
      case EEXIST:
        s += "Semaphore already exists. - ";
        break;
      case ENOSPC:
        s+= "System imposed limit on the number of semaphores is exceeded - ";
        break;
      case EACCES:
        s+= "Permission is denied - ";
        break;
      }
    itkExceptionMacro( << s.c_str() );
    }

  return( sid );
}

// UnixIpcSemaphoreDown: the semaphore signal operation.
// sid must be the system wide semaphore number
// returned by UnixIpcSemaphoreCreate above
void Semaphore::UnixIpcSemaphoreDown(int sid)
{
  Semaphore::UnixIpcSemaphoreCall(sid, -1);
}

// UnixIpcSemaphoreUp: the semaphore release operation.
// sid must be the system wide semaphore number
// returned by UnixIpcSemaphoreCreate above
void Semaphore::UnixIpcSemaphoreUp(int sid)
{
  Semaphore::UnixIpcSemaphoreCall(sid, 1);
}

// UixIpcSemaphoreRemove: remove a semaphore from the system.
// sid must be the system wide semaphore number
// returned from UnixIpcSemaphoreCreate
void Semaphore::UnixIpcSemaphoreRemove(int sid)
{
  std::string s;

  if( semctl( sid, 0, IPC_RMID, 0 ) == -1 )
    {
    s =  "Error removing semaphore %i - ";
    switch (errno)
      {
      case EINVAL:
        s +=  "Semaphore id# is not valid. - ";
        break;
      case EACCES:
        s+=  "Permission is denied - ";
        break;
      case EPERM:
        s+= "Permission is denied - ";
        break;
      }
    itkExceptionMacro ( << s.c_str() );
    }
}

// UnixIpcSemaphoreCall: makes the system call semop for your given
// semaphore and operation.
void Semaphore::UnixIpcSemaphoreCall (int sid, int op)
{
  struct sembuf sb;
  std::string s;

  sb.sem_num = 0;
  sb.sem_op = op;
  sb.sem_flg = 0;
  if( semop( sid, &sb, 1 ) == -1 )
    {

    if( op == -1 )
      {
      s =  "Error %i in UnixIpcSemaphoreDown call for semaphore %i - ";
      }
    else
      {
      s =  "Error %i in UnixIpcSemaphoreUp call for semaphore %i - ";
      }
    switch (errno)
      {
      case EINVAL:
        s +=  "Semaphore id# is not valid. -";
        break;
      case EFBIG:
        s +=  "Invalid sem_num for semaphore - ";
        break;
      case EACCES:
        s += "Permission denied for semaphore - ";
        break;
      case EAGAIN:
        s += "The operation would result in suspension of the calling process but NOWAIT is true.";
        break;
      case EIDRM:
        s += "The semid is removed from the system.";
        break;
      }
    itkExceptionMacro( << s.c_str() );
    }
}

#endif

}//end if namespace itk

#endif
<commit_msg>ERR: Fixed warnings.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkSemaphore.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#ifndef __itkSemaphore_cxx_
#define __itkSemaphore_cxx_

#include "itkConfigure.h"
#include "itkSemaphore.h"

#ifdef __APPLE__
extern "C" {
#include <stdio.h>
#include <time.h>
}
#endif

/// DEBUG
extern "C" {
#include <stdio.h>
#include <errno.h>
}
///

namespace itk {

#ifdef __APPLE__
int Semaphore::m_SemaphoreCount = 0;
#endif

#ifdef ITK_USE_UNIX_IPC_SEMAPHORES
int Semaphore::m_IPCSemaphoreKey = 12345;
SimpleMutexLock Semaphore::m_Mutex;
#endif

#ifdef __APPLE__
std::string Semaphore::GetUniqueName()
{
  char s[255];
  time_t t = time(0);
  snprintf(s,254,"MACSEM%d%d",static_cast<int>(t),m_SemaphoreCount);
  return std::string(s);
}
#endif

Semaphore::Semaphore ()
{
#ifdef ITK_USE_UNIX_IPC_SEMAPHORES
  m_Sema= -1;
#endif

#ifdef __APPLE__
  m_Sema = 0;
  m_SemaphoreCount++;
  m_SemaphoreName = Semaphore::GetUniqueName();
#endif

#ifndef ITK_USE_UNIX_IPC_SEMAPHORES

#ifdef ITK_USE_SPROC
  m_Sema = 0;
#endif

#endif

#ifdef ITK_USE_WIN32_THREADS
  m_Sema = 0;
#endif
}

void Semaphore::Initialize(unsigned int value)
{

#ifdef ITK_USE_UNIX_IPC_SEMAPHORES
  // Obtain a lock over the m_IPCSemaphoreKey so that the new semaphore is
  // created with a unique unix_semaphore_key
  Semaphore::m_Mutex.Lock();
  m_Sema = Semaphore::UnixIpcSemaphoreCreate(Semaphore::m_IPCSemaphoreKey);

  // by default the semaphore created has value 0
  Semaphore::m_IPCSemaphoreKey++;
  Semaphore::m_Mutex.Unlock();

  for (unsigned int i = 0; i < value; i++)
    {
    this->Up();
    }
#endif

#ifndef ITK_USE_UNIX_IPC_SEMAPHORES
#ifdef ITK_USE_SPROC
  if (MultiThreader::GetInitialized() == false)
    {
      MultiThreader::Initialize();
    }

  m_Sema = usnewsema(MultiThreader::GetThreadArena(), static_cast<int>(value));
  if ( ! m_Sema )
    {
      itkExceptionMacro( << " sem_init call failed with code " << m_Sema );
    }

#endif
#ifdef ITK_USE_PTHREADS

#if defined sun
  if ( sema_init(&m_Sema, 0, value, NULL ) != 0 )
    {
    itkExceptionMacro( << "sema_init call failed" );
    }
#elif defined  __APPLE__
  m_Sema  = sem_open( m_SemaphoreName.c_str(), O_CREAT, 0x0644, value );
  if ( m_Sema == (sem_t *)SEM_FAILED )
    {
    //  perror("FAILED WITH ERROR:" );
    itkExceptionMacro( << "sem_open call failed on " << m_SemaphoreName.c_str() );
    }
#else
  if ( sem_init(&m_Sema, 0, value) != 0 )
    {
      itkExceptionMacro( << "sem_init call failed" );
    }
#endif // if defined sun

#endif // ifdef ITK_USE_PTHREADS
#endif // ifndef ITK_USE_UNIX_IPC_SEMAPHORES

#ifdef ITK_USE_WIN32_THREADS
  m_Sema = CreateSemaphore( 0, value, 0x7FFFFFFF, 0);
  if (m_Sema == 0)
    {
      itkExceptionMacro( << "CreateSemaphore call failed" );
    }
#endif
}

void Semaphore::Up()
{
#ifdef ITK_USE_UNIX_IPC_SEMAPHORES
  Semaphore::UnixIpcSemaphoreUp(m_Sema);
#endif

#ifndef ITK_USE_UNIX_IPC_SEMAPHORES

#ifdef ITK_USE_SPROC
  if (usvsema(m_Sema) == -1)
    {
      itkExceptionMacro( << "usvsema call failed." );
    }
#endif
#ifdef ITK_USE_PTHREADS
#ifdef sun
  if ( sema_post(&m_Sema) != 0 )
    {
      itkExceptionMacro( << "sema_post call failed." );
    }
#else
#ifdef __APPLE__
  if ( sem_post(m_Sema) != 0 )
    {
    itkExceptionMacro( << "sem_post call failed." );
    }
#else
  if ( sem_post(&m_Sema) != 0 )
    {
      itkExceptionMacro( << "sem_post call failed." );
    }
#endif
#endif // ifdef sun
#endif

#endif  // ITK_USE_UNIX_SEMAPHORES

#ifdef ITK_USE_WIN32_THREADS
  if ( ! ReleaseSemaphore ((HANDLE) m_Sema, 1 , 0) )
    {
      itkExceptionMacro( << "Semaphore post call failed." );
    }
#endif
}

void Semaphore::Down()
{
#ifdef ITK_USE_UNIX_IPC_SEMAPHORES
  Semaphore::UnixIpcSemaphoreDown (m_Sema);
#endif

#ifndef ITK_USE_UNIX_IPC_SEMAPHORES
#ifdef ITK_USE_SPROC
  if (uspsema(m_Sema) == -1)
    {
      itkExceptionMacro( << "uspsema call failed." );
    }
#endif
#ifdef ITK_USE_PTHREADS
#ifdef sun
  if (sema_wait(&m_Sema) != 0)
    {
    itkExceptionMacro( << "sema_wait call failed." );
    }
#else
#ifdef __APPLE__
  if (sem_wait(m_Sema) != 0)
    {
      itkExceptionMacro( << "sem_wait call failed." );
    }
#else

  if (sem_wait(&m_Sema) != 0)
    {
      itkExceptionMacro( << "sem_wait call failed." );
    }
#endif
#endif
#endif
#endif

#ifdef ITK_USE_WIN32_THREADS
  if ( WaitForSingleObject(m_Sema, INFINITE) == WAIT_FAILED )
    {
      itkExceptionMacro( << "WaitForSingleObject call failed. ");
    }
#endif
}

Semaphore::~Semaphore()
{
#ifdef ITK_USE_UNIX_IPC_SEMAPHORES
  if (m_Sema != -1)
    {
      this->Remove();
    }
#endif

#ifndef ITK_USE_UNIX_IPC_SEMAPHORES
#ifdef ITK_USE_SPROC
  if (m_Sema != 0)
    {
      this->Remove();
    }
#endif
#ifdef ITK_USE_PTHREADS
  this->Remove();
#endif
#endif

#ifdef ITK_USE_WIN32_THREADS
  if (m_Sema != 0)
    {
      this->Remove();
    }
#endif
}

void Semaphore::Remove()
{
#ifdef ITK_USE_UNIX_IPC_SEMAPHORES
  if (m_Sema != -1)
    {
      Semaphore::UnixIpcSemaphoreRemove(m_Sema);
      m_Sema= -1;
    }
#endif

#ifndef ITK_USE_UNIX_IPC_SEMAPHORES

#ifdef ITK_USE_SPROC
  if (MultiThreader::GetThreadArena() != 0)
    {
    if (m_Sema != 0)
      {
      usfreesema(m_Sema, MultiThreader::GetThreadArena());
      }
    m_Sema = 0;
    }
#endif

#ifdef ITK_USE_PTHREADS

#ifdef sun
  if ( sema_destroy(&m_Sema) != 0 )
    {
    itkExceptionMacro( << "sema_destroy call failed. " );
    }
#else

#ifndef __sgi
#ifndef __APPLE__
  // IRIX pthreads implementation of sem_destroy is buggy
  if ( sem_destroy(&m_Sema) != 0 )
    {
    itkExceptionMacro( << "sem_destroy call failed. " );
    }
#endif
#endif

#endif  // sun
#endif // pthreads

#endif // semaphores
  //#endif

#ifdef ITK_USE_WIN32_THREADS
  if (m_Sema != 0)
    {
    CloseHandle(m_Sema);
    }
  m_Sema= 0;
#endif
}

#ifdef ITK_USE_UNIX_IPC_SEMAPHORES

// UnixIpcSemaphoreCreate: will return the semaphore id (system wide)
// of the semaphore number (key) you give.
// If no semaphore has been established for this number, one is created.
int Semaphore::UnixIpcSemaphoreCreate(int unix_semaphore_key)
{
  int sid = -1;
  std::string s;

  if( (sid = semget( (key_t)unix_semaphore_key, 1, 0666 | IPC_CREAT )) == -1 )
    {
    s =  "Error# %i in function UnixIpcSemaphoreCreate. - ";
    switch (errno)
      {
      case EEXIST:
        s += "Semaphore already exists. - ";
        break;
      case ENOSPC:
        s+= "System imposed limit on the number of semaphores is exceeded - ";
        break;
      case EACCES:
        s+= "Permission is denied - ";
        break;
      }
    itkExceptionMacro( << s.c_str() );
    }

  return( sid );
}

// UnixIpcSemaphoreDown: the semaphore signal operation.
// sid must be the system wide semaphore number
// returned by UnixIpcSemaphoreCreate above
void Semaphore::UnixIpcSemaphoreDown(int sid)
{
  Semaphore::UnixIpcSemaphoreCall(sid, -1);
}

// UnixIpcSemaphoreUp: the semaphore release operation.
// sid must be the system wide semaphore number
// returned by UnixIpcSemaphoreCreate above
void Semaphore::UnixIpcSemaphoreUp(int sid)
{
  Semaphore::UnixIpcSemaphoreCall(sid, 1);
}

// UixIpcSemaphoreRemove: remove a semaphore from the system.
// sid must be the system wide semaphore number
// returned from UnixIpcSemaphoreCreate
void Semaphore::UnixIpcSemaphoreRemove(int sid)
{
  std::string s;

  if( semctl( sid, 0, IPC_RMID, 0 ) == -1 )
    {
    s =  "Error removing semaphore %i - ";
    switch (errno)
      {
      case EINVAL:
        s +=  "Semaphore id# is not valid. - ";
        break;
      case EACCES:
        s+=  "Permission is denied - ";
        break;
      case EPERM:
        s+= "Permission is denied - ";
        break;
      }
    itkExceptionMacro ( << s.c_str() );
    }
}

// UnixIpcSemaphoreCall: makes the system call semop for your given
// semaphore and operation.
void Semaphore::UnixIpcSemaphoreCall (int sid, int op)
{
  struct sembuf sb;
  std::string s;

  sb.sem_num = 0;
  sb.sem_op = op;
  sb.sem_flg = 0;
  if( semop( sid, &sb, 1 ) == -1 )
    {

    if( op == -1 )
      {
      s =  "Error %i in UnixIpcSemaphoreDown call for semaphore %i - ";
      }
    else
      {
      s =  "Error %i in UnixIpcSemaphoreUp call for semaphore %i - ";
      }
    switch (errno)
      {
      case EINVAL:
        s +=  "Semaphore id# is not valid. -";
        break;
      case EFBIG:
        s +=  "Invalid sem_num for semaphore - ";
        break;
      case EACCES:
        s += "Permission denied for semaphore - ";
        break;
      case EAGAIN:
        s += "The operation would result in suspension of the calling process but NOWAIT is true.";
        break;
      case EIDRM:
        s += "The semid is removed from the system.";
        break;
      }
    itkExceptionMacro( << s.c_str() );
    }
}

#endif

}//end if namespace itk

#endif
<|endoftext|>


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
 //
 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
 //
 //  By downloading, copying, installing or using the software you agree to this license.
 //  If you do not agree to this license, do not download, install,
 //  copy or use the software.
 //
 //
 //                        Intel License Agreement
 //                For Open Source Computer Vision Library
 //
 // Copyright (C) 2000, Intel Corporation, all rights reserved.
 // Third party copyrights are property of their respective owners.
 //
 // Redistribution and use in source and binary forms, with or without modification,
 // are permitted provided that the following conditions are met:
 //
 //   * Redistribution's of source code must retain the above copyright notice,
 //     this list of conditions and the following disclaimer.
 //
 //   * Redistribution's in binary form must reproduce the above copyright notice,
 //     this list of conditions and the following disclaimer in the documentation
 //     and/or other materials provided with the distribution.
 //
 //   * The name of Intel Corporation may not be used to endorse or promote products
 //     derived from this software without specific prior written permission.
 //
 // This software is provided by the copyright holders and contributors "as is" and
 // any express or implied warranties, including, but not limited to, the implied
 // warranties of merchantability and fitness for a particular purpose are disclaimed.
 // In no event shall the Intel Corporation or contributors be liable for any direct,
 // indirect, incidental, special, exemplary, or consequential damages
 // (including, but not limited to, procurement of substitute goods or services;
 // loss of use, data, or profits; or business interruption) however caused
 // and on any theory of liability, whether in contract, strict liability,
 // or tort (including negligence or otherwise) arising in any way out of
 // the use of this software, even if advised of the possibility of such damage.
 //
 //M*/

#include "precomp.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/calib3d/calib3d_c.h"

#include <vector>
#include <algorithm>

//#define DEBUG_WINDOWS

#if defined(DEBUG_WINDOWS)
#  include "opencv2/opencv_modules.hpp"
#  ifdef HAVE_OPENCV_HIGHGUI
#    include "opencv2/highgui.hpp"
#  else
#    undef DEBUG_WINDOWS
#  endif
#endif

int cvCheckChessboardBinary(IplImage* src, CvSize size);

static void icvGetQuadrangleHypotheses(CvSeq* contours, std::vector<std::pair<float, int> >& quads, int class_id)
{
    const float min_aspect_ratio = 0.2f;
    const float max_aspect_ratio = 5.0f;
    const float min_box_size = 10.0f;

    for(CvSeq* seq = contours; seq != NULL; seq = seq->h_next)
    {
        CvBox2D box = cvMinAreaRect2(seq);
        float box_size = MAX(box.size.width, box.size.height);
        if(box_size < min_box_size)
        {
            continue;
        }

        float aspect_ratio = box.size.width/MAX(box.size.height, 1);
        if(aspect_ratio < min_aspect_ratio || aspect_ratio > max_aspect_ratio)
        {
            continue;
        }

        quads.push_back(std::pair<float, int>(box_size, class_id));
    }
}

static void countClasses(const std::vector<std::pair<float, int> >& pairs, size_t idx1, size_t idx2, std::vector<int>& counts)
{
    counts.assign(2, 0);
    for(size_t i = idx1; i != idx2; i++)
    {
        counts[pairs[i].second]++;
    }
}

inline bool less_pred(const std::pair<float, int>& p1, const std::pair<float, int>& p2)
{
    return p1.first < p2.first;
}

// does a fast check if a chessboard is in the input image. This is a workaround to
// a problem of cvFindChessboardCorners being slow on images with no chessboard
// - src: input image
// - size: chessboard size
// Returns 1 if a chessboard can be in this image and findChessboardCorners should be called,
// 0 if there is no chessboard, -1 in case of error
int cvCheckChessboard(IplImage* src, CvSize size)
{
    if(src->nChannels > 1)
    {
        cvError(CV_BadNumChannels, "cvCheckChessboard", "supports single-channel images only",
                __FILE__, __LINE__);
    }

    if(src->depth != 8)
    {
        cvError(CV_BadDepth, "cvCheckChessboard", "supports depth=8 images only",
                __FILE__, __LINE__);
    }

    const int erosion_count = 1;
    const float black_level = 20.f;
    const float white_level = 130.f;
    const float black_white_gap = 70.f;

#if defined(DEBUG_WINDOWS)
    cvNamedWindow("1", 1);
    cvShowImage("1", src);
    cvWaitKey(0);
#endif //DEBUG_WINDOWS

    CvMemStorage* storage = cvCreateMemStorage();

    IplImage* white = cvCloneImage(src);
    IplImage* black = cvCloneImage(src);

    cvErode(white, white, NULL, erosion_count);
    cvDilate(black, black, NULL, erosion_count);
    IplImage* thresh = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);

    int result = 0;
    for(float thresh_level = black_level; thresh_level < white_level && !result; thresh_level += 20.0f)
    {
        cvThreshold(white, thresh, thresh_level + black_white_gap, 255, CV_THRESH_BINARY);

#if defined(DEBUG_WINDOWS)
        cvShowImage("1", thresh);
        cvWaitKey(0);
#endif //DEBUG_WINDOWS

        CvSeq* first = 0;
        std::vector<std::pair<float, int> > quads;
        cvFindContours(thresh, storage, &first, sizeof(CvContour), CV_RETR_CCOMP);
        icvGetQuadrangleHypotheses(first, quads, 1);

        cvThreshold(black, thresh, thresh_level, 255, CV_THRESH_BINARY_INV);

#if defined(DEBUG_WINDOWS)
        cvShowImage("1", thresh);
        cvWaitKey(0);
#endif //DEBUG_WINDOWS

        cvFindContours(thresh, storage, &first, sizeof(CvContour), CV_RETR_CCOMP);
        icvGetQuadrangleHypotheses(first, quads, 0);

        const size_t min_quads_count = size.width*size.height/2;
        std::sort(quads.begin(), quads.end(), less_pred);

        // now check if there are many hypotheses with similar sizes
        // do this by floodfill-style algorithm
        const float size_rel_dev = 0.4f;

        for(size_t i = 0; i < quads.size(); i++)
        {
            size_t j = i + 1;
            for(; j < quads.size(); j++)
            {
                if(quads[j].first/quads[i].first > 1.0f + size_rel_dev)
                {
                    break;
                }
            }

            if(j + 1 > min_quads_count + i)
            {
                // check the number of black and white squares
                std::vector<int> counts;
                countClasses(quads, i, j, counts);
                const int black_count = cvRound(ceil(size.width/2.0)*ceil(size.height/2.0));
                const int white_count = cvRound(floor(size.width/2.0)*floor(size.height/2.0));
                if(counts[0] < black_count*0.75 ||
                   counts[1] < white_count*0.75)
                {
                    continue;
                }
                result = 1;
                break;
            }
        }
    }

    cvReleaseImage(&thresh);
    cvReleaseImage(&white);
    cvReleaseImage(&black);
    cvReleaseMemStorage(&storage);

    return result;
}

// does a fast check if a chessboard is in the input image. This is a workaround to
// a problem of cvFindChessboardCorners being slow on images with no chessboard
// - src: input binary image
// - size: chessboard size
// Returns 1 if a chessboard can be in this image and findChessboardCorners should be called,
// 0 if there is no chessboard, -1 in case of error
int cvCheckChessboardBinary(IplImage* src, CvSize size)
{
    if(src->nChannels > 1)
    {
        cvError(CV_BadNumChannels, "cvCheckChessboard", "supports single-channel images only",
                __FILE__, __LINE__);
    }

    if(src->depth != 8)
    {
        cvError(CV_BadDepth, "cvCheckChessboard", "supports depth=8 images only",
                __FILE__, __LINE__);
    }

    CvMemStorage* storage = cvCreateMemStorage();

    IplImage* white = cvCloneImage(src);
    IplImage* black = cvCloneImage(src);
    IplImage* thresh = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);

    int result = 0;

    for ( int erosion_count = 0; erosion_count <= 3; erosion_count++ )
    {
      if ( 1 == result )
        break;

      if ( 0 != erosion_count ) // first iteration keeps original images
      {
        cvErode(white, white, NULL, 1);
        cvDilate(black, black, NULL, 1);
      }

      cvThreshold(white, thresh, 128, 255, CV_THRESH_BINARY);

      CvSeq* first = 0;
      std::vector<std::pair<float, int> > quads;
      cvFindContours(thresh, storage, &first, sizeof(CvContour), CV_RETR_CCOMP);
      icvGetQuadrangleHypotheses(first, quads, 1);

      cvThreshold(black, thresh, 128, 255, CV_THRESH_BINARY_INV);
      cvFindContours(thresh, storage, &first, sizeof(CvContour), CV_RETR_CCOMP);
      icvGetQuadrangleHypotheses(first, quads, 0);

      const size_t min_quads_count = size.width*size.height/2;
      std::sort(quads.begin(), quads.end(), less_pred);

      // now check if there are many hypotheses with similar sizes
      // do this by floodfill-style algorithm
      const float size_rel_dev = 0.4f;

      for(size_t i = 0; i < quads.size(); i++)
      {
          size_t j = i + 1;
          for(; j < quads.size(); j++)
          {
              if(quads[j].first/quads[i].first > 1.0f + size_rel_dev)
              {
                  break;
              }
          }

          if(j + 1 > min_quads_count + i)
          {
              // check the number of black and white squares
              std::vector<int> counts;
              countClasses(quads, i, j, counts);
              const int black_count = cvRound(ceil(size.width/2.0)*ceil(size.height/2.0));
              const int white_count = cvRound(floor(size.width/2.0)*floor(size.height/2.0));
              if(counts[0] < black_count*0.75 ||
                 counts[1] < white_count*0.75)
              {
                continue;
              }
              result = 1;
              break;
          }
      }
    }

    cvReleaseImage(&thresh);
    cvReleaseImage(&white);
    cvReleaseImage(&black);
    cvReleaseMemStorage(&storage);

    return result;
}<commit_msg>Restored check chessboard parameters<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
 //
 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
 //
 //  By downloading, copying, installing or using the software you agree to this license.
 //  If you do not agree to this license, do not download, install,
 //  copy or use the software.
 //
 //
 //                        Intel License Agreement
 //                For Open Source Computer Vision Library
 //
 // Copyright (C) 2000, Intel Corporation, all rights reserved.
 // Third party copyrights are property of their respective owners.
 //
 // Redistribution and use in source and binary forms, with or without modification,
 // are permitted provided that the following conditions are met:
 //
 //   * Redistribution's of source code must retain the above copyright notice,
 //     this list of conditions and the following disclaimer.
 //
 //   * Redistribution's in binary form must reproduce the above copyright notice,
 //     this list of conditions and the following disclaimer in the documentation
 //     and/or other materials provided with the distribution.
 //
 //   * The name of Intel Corporation may not be used to endorse or promote products
 //     derived from this software without specific prior written permission.
 //
 // This software is provided by the copyright holders and contributors "as is" and
 // any express or implied warranties, including, but not limited to, the implied
 // warranties of merchantability and fitness for a particular purpose are disclaimed.
 // In no event shall the Intel Corporation or contributors be liable for any direct,
 // indirect, incidental, special, exemplary, or consequential damages
 // (including, but not limited to, procurement of substitute goods or services;
 // loss of use, data, or profits; or business interruption) however caused
 // and on any theory of liability, whether in contract, strict liability,
 // or tort (including negligence or otherwise) arising in any way out of
 // the use of this software, even if advised of the possibility of such damage.
 //
 //M*/

#include "precomp.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/calib3d/calib3d_c.h"

#include <vector>
#include <algorithm>

//#define DEBUG_WINDOWS

#if defined(DEBUG_WINDOWS)
#  include "opencv2/opencv_modules.hpp"
#  ifdef HAVE_OPENCV_HIGHGUI
#    include "opencv2/highgui.hpp"
#  else
#    undef DEBUG_WINDOWS
#  endif
#endif

int cvCheckChessboardBinary(IplImage* src, CvSize size);

static void icvGetQuadrangleHypotheses(CvSeq* contours, std::vector<std::pair<float, int> >& quads, int class_id)
{
    const float min_aspect_ratio = 0.3f;
    const float max_aspect_ratio = 3.0f;
    const float min_box_size = 10.0f;

    for(CvSeq* seq = contours; seq != NULL; seq = seq->h_next)
    {
        CvBox2D box = cvMinAreaRect2(seq);
        float box_size = MAX(box.size.width, box.size.height);
        if(box_size < min_box_size)
        {
            continue;
        }

        float aspect_ratio = box.size.width/MAX(box.size.height, 1);
        if(aspect_ratio < min_aspect_ratio || aspect_ratio > max_aspect_ratio)
        {
            continue;
        }

        quads.push_back(std::pair<float, int>(box_size, class_id));
    }
}

static void countClasses(const std::vector<std::pair<float, int> >& pairs, size_t idx1, size_t idx2, std::vector<int>& counts)
{
    counts.assign(2, 0);
    for(size_t i = idx1; i != idx2; i++)
    {
        counts[pairs[i].second]++;
    }
}

inline bool less_pred(const std::pair<float, int>& p1, const std::pair<float, int>& p2)
{
    return p1.first < p2.first;
}

// does a fast check if a chessboard is in the input image. This is a workaround to
// a problem of cvFindChessboardCorners being slow on images with no chessboard
// - src: input image
// - size: chessboard size
// Returns 1 if a chessboard can be in this image and findChessboardCorners should be called,
// 0 if there is no chessboard, -1 in case of error
int cvCheckChessboard(IplImage* src, CvSize size)
{
    if(src->nChannels > 1)
    {
        cvError(CV_BadNumChannels, "cvCheckChessboard", "supports single-channel images only",
                __FILE__, __LINE__);
    }

    if(src->depth != 8)
    {
        cvError(CV_BadDepth, "cvCheckChessboard", "supports depth=8 images only",
                __FILE__, __LINE__);
    }

    const int erosion_count = 1;
    const float black_level = 20.f;
    const float white_level = 130.f;
    const float black_white_gap = 70.f;

#if defined(DEBUG_WINDOWS)
    cvNamedWindow("1", 1);
    cvShowImage("1", src);
    cvWaitKey(0);
#endif //DEBUG_WINDOWS

    CvMemStorage* storage = cvCreateMemStorage();

    IplImage* white = cvCloneImage(src);
    IplImage* black = cvCloneImage(src);

    cvErode(white, white, NULL, erosion_count);
    cvDilate(black, black, NULL, erosion_count);
    IplImage* thresh = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);

    int result = 0;
    for(float thresh_level = black_level; thresh_level < white_level && !result; thresh_level += 20.0f)
    {
        cvThreshold(white, thresh, thresh_level + black_white_gap, 255, CV_THRESH_BINARY);

#if defined(DEBUG_WINDOWS)
        cvShowImage("1", thresh);
        cvWaitKey(0);
#endif //DEBUG_WINDOWS

        CvSeq* first = 0;
        std::vector<std::pair<float, int> > quads;
        cvFindContours(thresh, storage, &first, sizeof(CvContour), CV_RETR_CCOMP);
        icvGetQuadrangleHypotheses(first, quads, 1);

        cvThreshold(black, thresh, thresh_level, 255, CV_THRESH_BINARY_INV);

#if defined(DEBUG_WINDOWS)
        cvShowImage("1", thresh);
        cvWaitKey(0);
#endif //DEBUG_WINDOWS

        cvFindContours(thresh, storage, &first, sizeof(CvContour), CV_RETR_CCOMP);
        icvGetQuadrangleHypotheses(first, quads, 0);

        const size_t min_quads_count = size.width*size.height/2;
        std::sort(quads.begin(), quads.end(), less_pred);

        // now check if there are many hypotheses with similar sizes
        // do this by floodfill-style algorithm
        const float size_rel_dev = 0.4f;

        for(size_t i = 0; i < quads.size(); i++)
        {
            size_t j = i + 1;
            for(; j < quads.size(); j++)
            {
                if(quads[j].first/quads[i].first > 1.0f + size_rel_dev)
                {
                    break;
                }
            }

            if(j + 1 > min_quads_count + i)
            {
                // check the number of black and white squares
                std::vector<int> counts;
                countClasses(quads, i, j, counts);
                const int black_count = cvRound(ceil(size.width/2.0)*ceil(size.height/2.0));
                const int white_count = cvRound(floor(size.width/2.0)*floor(size.height/2.0));
                if(counts[0] < black_count*0.75 ||
                   counts[1] < white_count*0.75)
                {
                    continue;
                }
                result = 1;
                break;
            }
        }
    }

    cvReleaseImage(&thresh);
    cvReleaseImage(&white);
    cvReleaseImage(&black);
    cvReleaseMemStorage(&storage);

    return result;
}

// does a fast check if a chessboard is in the input image. This is a workaround to
// a problem of cvFindChessboardCorners being slow on images with no chessboard
// - src: input binary image
// - size: chessboard size
// Returns 1 if a chessboard can be in this image and findChessboardCorners should be called,
// 0 if there is no chessboard, -1 in case of error
int cvCheckChessboardBinary(IplImage* src, CvSize size)
{
    if(src->nChannels > 1)
    {
        cvError(CV_BadNumChannels, "cvCheckChessboard", "supports single-channel images only",
                __FILE__, __LINE__);
    }

    if(src->depth != 8)
    {
        cvError(CV_BadDepth, "cvCheckChessboard", "supports depth=8 images only",
                __FILE__, __LINE__);
    }

    CvMemStorage* storage = cvCreateMemStorage();

    IplImage* white = cvCloneImage(src);
    IplImage* black = cvCloneImage(src);
    IplImage* thresh = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);

    int result = 0;

    for ( int erosion_count = 0; erosion_count <= 3; erosion_count++ )
    {
      if ( 1 == result )
        break;

      if ( 0 != erosion_count ) // first iteration keeps original images
      {
        cvErode(white, white, NULL, 1);
        cvDilate(black, black, NULL, 1);
      }

      cvThreshold(white, thresh, 128, 255, CV_THRESH_BINARY);

      CvSeq* first = 0;
      std::vector<std::pair<float, int> > quads;
      cvFindContours(thresh, storage, &first, sizeof(CvContour), CV_RETR_CCOMP);
      icvGetQuadrangleHypotheses(first, quads, 1);

      cvThreshold(black, thresh, 128, 255, CV_THRESH_BINARY_INV);
      cvFindContours(thresh, storage, &first, sizeof(CvContour), CV_RETR_CCOMP);
      icvGetQuadrangleHypotheses(first, quads, 0);

      const size_t min_quads_count = size.width*size.height/2;
      std::sort(quads.begin(), quads.end(), less_pred);

      // now check if there are many hypotheses with similar sizes
      // do this by floodfill-style algorithm
      const float size_rel_dev = 0.4f;

      for(size_t i = 0; i < quads.size(); i++)
      {
          size_t j = i + 1;
          for(; j < quads.size(); j++)
          {
              if(quads[j].first/quads[i].first > 1.0f + size_rel_dev)
              {
                  break;
              }
          }

          if(j + 1 > min_quads_count + i)
          {
              // check the number of black and white squares
              std::vector<int> counts;
              countClasses(quads, i, j, counts);
              const int black_count = cvRound(ceil(size.width/2.0)*ceil(size.height/2.0));
              const int white_count = cvRound(floor(size.width/2.0)*floor(size.height/2.0));
              if(counts[0] < black_count*0.75 ||
                 counts[1] < white_count*0.75)
              {
                continue;
              }
              result = 1;
              break;
          }
      }
    }

    cvReleaseImage(&thresh);
    cvReleaseImage(&white);
    cvReleaseImage(&black);
    cvReleaseMemStorage(&storage);

    return result;
}<|endoftext|>


<commit_before>#include "parser/geocoordinatetransformer.h"

#include <citygml/citygmllogger.h>
#include <citygml/citymodel.h>
#include <citygml/cityobject.h>
#include <citygml/implictgeometry.h>
#include <citygml/geometry.h>
#include <citygml/polygon.h>
#include <citygml/linestring.h>
#include <citygml/vecs.hpp>
#include <citygml/envelope.h>

#ifdef USE_GDAL
#include "ogrsf_frmts.h"

#include <stdexcept>

class GeoTransform
{
public:
    GeoTransform( const std::string& destURN, std::shared_ptr<citygml::CityGMLLogger> logger )
		: m_destSRSURN(destURN)
		, m_sourceURN("")
		, m_transformation(nullptr)
		, m_logger(logger)
    {
        OGRErr err = m_destSRS.SetFromUserInput(destURN.c_str());

        if (err != OGRERR_NONE) {
            CITYGML_LOG_ERROR(m_logger, "Could not create OGRSpatialReference for destination SRS " << destURN << ". OGR error code: " << err << ".");
            throw std::runtime_error("Invalid destination spatial reference system.");
        }
    }

    GeoTransform(const GeoTransform& other)
		: m_destSRS(other.m_destSRS)
		, m_destSRSURN(other.m_destSRSURN)
		, m_sourceURN("")
		, m_transformation(nullptr)
		, m_logger(other.m_logger)
	{
    }

    ~GeoTransform()
    {
        if (m_transformation != nullptr) {
            OCTDestroyCoordinateTransformation(m_transformation);
        }
    }

    bool valid() const {
        return m_transformation != nullptr;
    }

    void transform( TVec3d &p ) const
    {
        if (m_transformation == nullptr) {
            return;
        }

        m_transformation->Transform( 1, &p.x, &p.y );
    }

    void transform( TVec2d &p ) const
    {
        if (m_transformation == nullptr) {
            return;
        }

        m_transformation->Transform( 1, &p.x, &p.y );
    }

    bool hasSourceSRS(const std::string& sourceURN) {

        if (m_transformation == nullptr) {
            return false;
        }

        OGRSpatialReference refSys;
        OGRErr err = refSys.SetFromUserInput(sourceURN.c_str());

        if (err != OGRERR_NONE) {
            return false;
        }

        return refSys.IsSame(m_transformation->GetSourceCS());

    }

    void setSourceSRS(const std::string& sourceURN) {

        if (m_transformation != nullptr) {
            OCTDestroyCoordinateTransformation(m_transformation);
            m_transformation = nullptr;
        }

        OGRSpatialReference sourceSRS;
        OGRErr err = sourceSRS.SetFromUserInput(sourceURN.c_str());

        if (err != OGRERR_NONE) {
            CITYGML_LOG_ERROR(m_logger, "Could not create OGRSpatialReference for source SRS " << sourceURN << ". OGR error code: " << err << ".");
            return;
        }

        m_transformation = OGRCreateCoordinateTransformation(&sourceSRS, &m_destSRS);
        if (m_transformation == nullptr) {
            CITYGML_LOG_ERROR(m_logger, "Could not create transformation from source SRS " << sourceURN << " to destination SRS " << m_destSRSURN << ".");
            return;
        }

        m_sourceURN = sourceURN;
    }

    std::string sourceURN() const { return m_sourceURN; }

private:
    OGRSpatialReference m_destSRS;
    std::string m_destSRSURN;
    std::string m_sourceURN;

    OGRCoordinateTransformation* m_transformation;
    std::shared_ptr<citygml::CityGMLLogger> m_logger;
};

namespace citygml {

    GeoCoordinateTransformer::GeoCoordinateTransformer(const std::string& destSRS, std::shared_ptr<CityGMLLogger> logger)
    {
        m_destinationSRS = destSRS;
        m_logger = logger;
    }

    void GeoCoordinateTransformer::transformToDestinationSRS(CityModel* model)
    {
        GeoTransform transformation(m_destinationSRS, m_logger);

        if (!model->getEnvelope().srsName().empty()) {
            transformation.setSourceSRS(model->getEnvelope().srsName());
        }

        for (unsigned int i = 0; i < model->getNumRootCityObjects(); i++) {
            transformRecursive(model->getRootCityObject(i), transformation);
        }
    }

    void GeoCoordinateTransformer::transformRecursive(CityObject& obj, GeoTransform& transformation) {

        if (!obj.getEnvelope().srsName().empty() && !transformation.hasSourceSRS(obj.getEnvelope().srsName())) {
            GeoTransform childTransformation = transformation;
            childTransformation.setSourceSRS(obj.getEnvelope().srsName());

            transformRecursive_helper(obj, childTransformation);
        } else {
            transformRecursive_helper(obj, transformation);
        }

    }

    void  GeoCoordinateTransformer::transformRecursive_helper(CityObject& obj, GeoTransform& transformation) {

        if (obj.getEnvelope().validBounds()) {

            if (transformation.valid()) {
                TVec3d lowerBound = obj.getEnvelope().getLowerBound();
                TVec3d upperBound = obj.getEnvelope().getUpperBound();

                transformation.transform(lowerBound);
                transformation.transform(upperBound);

                Envelope* newEnvelope = new Envelope(m_destinationSRS);
                newEnvelope->setLowerBound(lowerBound);
                newEnvelope->setUpperBound(upperBound);

                obj.setEnvelope(newEnvelope);
            } else {
                CITYGML_LOG_WARN(m_logger, "No valid spatial reference system is given for CityObject with id '" << obj.getId() << "'. Envelope (Bounding Box) is not transformed.");
            }
        }

        for (unsigned int i = 0; i < obj.getChildCityObjectsCount(); i++) {
            transformRecursive(obj.getChildCityObject(i), transformation);
        }

        for (unsigned int i = 0; i < obj.getImplicitGeometryCount(); i++) {
            transformRecursive(obj.getImplicitGeometry(i), transformation);
        }

        for (unsigned int i = 0; i < obj.getGeometriesCount(); i++) {
            transform(obj.getGeometry(i), transformation);
        }
    }

    void GeoCoordinateTransformer::transformRecursive(ImplicitGeometry& obj, GeoTransform& transformation) {

        if (!obj.getSRSName().empty() && !transformation.hasSourceSRS(obj.getSRSName())) {
            GeoTransform childTransformation = transformation;
            childTransformation.setSourceSRS(obj.getSRSName());

            transformRecursive_helper(obj, childTransformation);
        } else {
            transformRecursive_helper(obj, transformation);
        }

    }

    void  GeoCoordinateTransformer::transformRecursive_helper(ImplicitGeometry& obj, GeoTransform& transformation) {

        TVec3d referencePoint = obj.getReferencePoint();
        if (transformation.valid()) {
            transformation.transform(referencePoint);
            obj.setReferencePoint(referencePoint);
            obj.setSRSName(m_destinationSRS);
        } else {
            CITYGML_LOG_WARN(m_logger, "No valid spatial reference system is given for ImplicitGeometry with id '" << obj.getId() << "'. Reference Point is not transformed.");
        }

        // Do not transform the geometry of an ImplicitGeometry object. Implicit Geometries share Geometry objects but each implicit geometry
        // defines its own transformation on the vertices of the shared geometry. Hence those vertices are in a local coordinate system. Read
        // the citygml documentation for more details.
        //for (unsigned int i = 0; i < obj.getGeometriesCount(); i++) {
        //  transform(obj.getGeometry(i), transformation);
        //}
    }

    void GeoCoordinateTransformer::transform(Geometry& obj, GeoTransform& transformation) {

        if (!transformation.valid()) {
            CITYGML_LOG_WARN(m_logger, "No valid spatial reference system is given for Geometry with id '" << obj.getId() << "'. Child Polygons are not transformed"
                                       << "(unless they are shared with another geometry for which a spatial reference system is defined)");
            return;
        }

        for (unsigned int i = 0; i < obj.getPolygonsCount(); i++) {

            const auto poly = obj.getPolygon(i);

            auto it = m_transformedPolygonsSourceURNMap.find(poly.get());

            if (it == m_transformedPolygonsSourceURNMap.end()) {

                for (TVec3d& vertex : poly->getVertices()) {
                    transformation.transform(vertex);
                }

                m_transformedPolygonsSourceURNMap[poly.get()] = transformation.sourceURN();

            } else if (it->second != transformation.sourceURN()) {
                CITYGML_LOG_WARN(m_logger, "Polygon with id '" << poly->getId() << "' was already transformed from " << it->second << " to " << m_destinationSRS
                                 << ". But the spatial reference system of Geometry object with id '" << obj.getId() << "' that also contains the polygon is different "
                                 << "(" << transformation.sourceURN() << "). Ignoring new source SRS.");
            }
        }

        for (unsigned int i = 0; i < obj.getLineStringCount(); i++) {

            const auto lineString = obj.getLineString(i);

            auto it = m_transformedLineStringsSourceURNMap.find(lineString.get());

            if (it == m_transformedLineStringsSourceURNMap.end()) {

                if (lineString->getDimensions() == 2) {
                    for (TVec2d& vertex : lineString->getVertices2D()) {
                        transformation.transform(vertex);
                    }
                } else if (lineString->getDimensions() == 3) {
                    for (TVec3d& vertex : lineString->getVertices3D()) {
                        transformation.transform(vertex);
                    }
                }

                m_transformedLineStringsSourceURNMap[lineString.get()] = transformation.sourceURN();

            } else if (it->second != transformation.sourceURN()) {
                CITYGML_LOG_WARN(m_logger, "LineString with id '" << lineString->getId() << "' was already transformed from " << it->second << " to " << m_destinationSRS
                                 << ". But the spatial reference system of Geometry object with id '" << obj.getId() << "' that also contains the LineString is different "
                                 << "(" << transformation.sourceURN() << "). Ignoring new source SRS.");
            }
        }

        for (unsigned int i = 0; i < obj.getGeometriesCount(); i++) {
            transform(obj.getGeometry(i), transformation);
        }
    }
}
#else
class GeoTransform {
};

namespace citygml {

	GeoCoordinateTransformer::GeoCoordinateTransformer(const std::string& destSRS, std::shared_ptr<CityGMLLogger> logger)
	{
		m_destinationSRS = destSRS;
		m_logger = logger;
	}

    void GeoCoordinateTransformer::transformToDestinationSRS(CityModel* model) {
        CITYGML_LOG_WARN(m_logger, "Coordinate transformation to " << m_destinationSRS << " requested, but libcitygml was build without GDAL. The coordinates will not be transformed.");
    }

    void GeoCoordinateTransformer::transformRecursive(CityObject&, GeoTransform&) {}
    void GeoCoordinateTransformer::transformRecursive_helper(CityObject&, GeoTransform&) {}
    void GeoCoordinateTransformer::transformRecursive(ImplicitGeometry&, GeoTransform&) {}
    void GeoCoordinateTransformer::transformRecursive_helper(ImplicitGeometry&, GeoTransform&) {}
    void GeoCoordinateTransformer::transform(Geometry&, GeoTransform&) {}
}
#endif

<commit_msg>Add destinationSRS transform to model envelope too<commit_after>#include "parser/geocoordinatetransformer.h"

#include <citygml/citygmllogger.h>
#include <citygml/citymodel.h>
#include <citygml/cityobject.h>
#include <citygml/implictgeometry.h>
#include <citygml/geometry.h>
#include <citygml/polygon.h>
#include <citygml/linestring.h>
#include <citygml/vecs.hpp>
#include <citygml/envelope.h>

#ifdef USE_GDAL
#include "ogrsf_frmts.h"

#include <stdexcept>

class GeoTransform
{
public:
    GeoTransform( const std::string& destURN, std::shared_ptr<citygml::CityGMLLogger> logger )
		: m_destSRSURN(destURN)
		, m_sourceURN("")
		, m_transformation(nullptr)
		, m_logger(logger)
    {
        OGRErr err = m_destSRS.SetFromUserInput(destURN.c_str());

        if (err != OGRERR_NONE) {
            CITYGML_LOG_ERROR(m_logger, "Could not create OGRSpatialReference for destination SRS " << destURN << ". OGR error code: " << err << ".");
            throw std::runtime_error("Invalid destination spatial reference system.");
        }
    }

    GeoTransform(const GeoTransform& other)
		: m_destSRS(other.m_destSRS)
		, m_destSRSURN(other.m_destSRSURN)
		, m_sourceURN("")
		, m_transformation(nullptr)
		, m_logger(other.m_logger)
	{
    }

    ~GeoTransform()
    {
        if (m_transformation != nullptr) {
            OCTDestroyCoordinateTransformation(m_transformation);
        }
    }

    bool valid() const {
        return m_transformation != nullptr;
    }

    void transform( TVec3d &p ) const
    {
        if (m_transformation == nullptr) {
            return;
        }

        m_transformation->Transform( 1, &p.x, &p.y );
    }

    void transform( TVec2d &p ) const
    {
        if (m_transformation == nullptr) {
            return;
        }

        m_transformation->Transform( 1, &p.x, &p.y );
    }

    bool hasSourceSRS(const std::string& sourceURN) {

        if (m_transformation == nullptr) {
            return false;
        }

        OGRSpatialReference refSys;
        OGRErr err = refSys.SetFromUserInput(sourceURN.c_str());

        if (err != OGRERR_NONE) {
            return false;
        }

        return refSys.IsSame(m_transformation->GetSourceCS());

    }

    void setSourceSRS(const std::string& sourceURN) {

        if (m_transformation != nullptr) {
            OCTDestroyCoordinateTransformation(m_transformation);
            m_transformation = nullptr;
        }

        OGRSpatialReference sourceSRS;
        OGRErr err = sourceSRS.SetFromUserInput(sourceURN.c_str());

        if (err != OGRERR_NONE) {
            CITYGML_LOG_ERROR(m_logger, "Could not create OGRSpatialReference for source SRS " << sourceURN << ". OGR error code: " << err << ".");
            return;
        }

        m_transformation = OGRCreateCoordinateTransformation(&sourceSRS, &m_destSRS);
        if (m_transformation == nullptr) {
            CITYGML_LOG_ERROR(m_logger, "Could not create transformation from source SRS " << sourceURN << " to destination SRS " << m_destSRSURN << ".");
            return;
        }

        m_sourceURN = sourceURN;
    }

    std::string sourceURN() const { return m_sourceURN; }

private:
    OGRSpatialReference m_destSRS;
    std::string m_destSRSURN;
    std::string m_sourceURN;

    OGRCoordinateTransformation* m_transformation;
    std::shared_ptr<citygml::CityGMLLogger> m_logger;
};

namespace citygml {

    GeoCoordinateTransformer::GeoCoordinateTransformer(const std::string& destSRS, std::shared_ptr<CityGMLLogger> logger)
    {
        m_destinationSRS = destSRS;
        m_logger = logger;
    }

    void GeoCoordinateTransformer::transformToDestinationSRS(CityModel* model)
    {
        GeoTransform transformation(m_destinationSRS, m_logger);

        if (!model->getEnvelope().srsName().empty()) {
            transformation.setSourceSRS(model->getEnvelope().srsName());
            if (model->getEnvelope().validBounds()) {
                if (transformation.valid()) {
                    TVec3d lowerBound = model->getEnvelope().getLowerBound();
                    TVec3d upperBound = model->getEnvelope().getUpperBound();

                    transformation.transform(lowerBound);
                    transformation.transform(upperBound);

                    Envelope* newEnvelope = new Envelope(m_destinationSRS);
                    newEnvelope->setLowerBound(lowerBound);
                    newEnvelope->setUpperBound(upperBound);

                    model->setEnvelope(newEnvelope);
                }
                else {
                    CITYGML_LOG_WARN(m_logger, "No valid spatial reference system is given for CityModel with id '" << model->getId() << "'. Envelope (Bounding Box) is not transformed.");
                }
            }
        }

        for (unsigned int i = 0; i < model->getNumRootCityObjects(); i++) {
            transformRecursive(model->getRootCityObject(i), transformation);
        }
    }

    void GeoCoordinateTransformer::transformRecursive(CityObject& obj, GeoTransform& transformation) {

        if (!obj.getEnvelope().srsName().empty() && !transformation.hasSourceSRS(obj.getEnvelope().srsName())) {
            GeoTransform childTransformation = transformation;
            childTransformation.setSourceSRS(obj.getEnvelope().srsName());

            transformRecursive_helper(obj, childTransformation);
        } else {
            transformRecursive_helper(obj, transformation);
        }

    }

    void  GeoCoordinateTransformer::transformRecursive_helper(CityObject& obj, GeoTransform& transformation) {

        if (obj.getEnvelope().validBounds()) {

            if (transformation.valid()) {
                TVec3d lowerBound = obj.getEnvelope().getLowerBound();
                TVec3d upperBound = obj.getEnvelope().getUpperBound();

                transformation.transform(lowerBound);
                transformation.transform(upperBound);

                Envelope* newEnvelope = new Envelope(m_destinationSRS);
                newEnvelope->setLowerBound(lowerBound);
                newEnvelope->setUpperBound(upperBound);

                obj.setEnvelope(newEnvelope);
            } else {
                CITYGML_LOG_WARN(m_logger, "No valid spatial reference system is given for CityObject with id '" << obj.getId() << "'. Envelope (Bounding Box) is not transformed.");
            }
        }

        for (unsigned int i = 0; i < obj.getChildCityObjectsCount(); i++) {
            transformRecursive(obj.getChildCityObject(i), transformation);
        }

        for (unsigned int i = 0; i < obj.getImplicitGeometryCount(); i++) {
            transformRecursive(obj.getImplicitGeometry(i), transformation);
        }

        for (unsigned int i = 0; i < obj.getGeometriesCount(); i++) {
            transform(obj.getGeometry(i), transformation);
        }
    }

    void GeoCoordinateTransformer::transformRecursive(ImplicitGeometry& obj, GeoTransform& transformation) {

        if (!obj.getSRSName().empty() && !transformation.hasSourceSRS(obj.getSRSName())) {
            GeoTransform childTransformation = transformation;
            childTransformation.setSourceSRS(obj.getSRSName());

            transformRecursive_helper(obj, childTransformation);
        } else {
            transformRecursive_helper(obj, transformation);
        }

    }

    void  GeoCoordinateTransformer::transformRecursive_helper(ImplicitGeometry& obj, GeoTransform& transformation) {

        TVec3d referencePoint = obj.getReferencePoint();
        if (transformation.valid()) {
            transformation.transform(referencePoint);
            obj.setReferencePoint(referencePoint);
            obj.setSRSName(m_destinationSRS);
        } else {
            CITYGML_LOG_WARN(m_logger, "No valid spatial reference system is given for ImplicitGeometry with id '" << obj.getId() << "'. Reference Point is not transformed.");
        }

        // Do not transform the geometry of an ImplicitGeometry object. Implicit Geometries share Geometry objects but each implicit geometry
        // defines its own transformation on the vertices of the shared geometry. Hence those vertices are in a local coordinate system. Read
        // the citygml documentation for more details.
        //for (unsigned int i = 0; i < obj.getGeometriesCount(); i++) {
        //  transform(obj.getGeometry(i), transformation);
        //}
    }

    void GeoCoordinateTransformer::transform(Geometry& obj, GeoTransform& transformation) {

        if (!transformation.valid()) {
            CITYGML_LOG_WARN(m_logger, "No valid spatial reference system is given for Geometry with id '" << obj.getId() << "'. Child Polygons are not transformed"
                                       << "(unless they are shared with another geometry for which a spatial reference system is defined)");
            return;
        }

        for (unsigned int i = 0; i < obj.getPolygonsCount(); i++) {

            const auto poly = obj.getPolygon(i);

            auto it = m_transformedPolygonsSourceURNMap.find(poly.get());

            if (it == m_transformedPolygonsSourceURNMap.end()) {

                for (TVec3d& vertex : poly->getVertices()) {
                    transformation.transform(vertex);
                }

                m_transformedPolygonsSourceURNMap[poly.get()] = transformation.sourceURN();

            } else if (it->second != transformation.sourceURN()) {
                CITYGML_LOG_WARN(m_logger, "Polygon with id '" << poly->getId() << "' was already transformed from " << it->second << " to " << m_destinationSRS
                                 << ". But the spatial reference system of Geometry object with id '" << obj.getId() << "' that also contains the polygon is different "
                                 << "(" << transformation.sourceURN() << "). Ignoring new source SRS.");
            }
        }

        for (unsigned int i = 0; i < obj.getLineStringCount(); i++) {

            const auto lineString = obj.getLineString(i);

            auto it = m_transformedLineStringsSourceURNMap.find(lineString.get());

            if (it == m_transformedLineStringsSourceURNMap.end()) {

                if (lineString->getDimensions() == 2) {
                    for (TVec2d& vertex : lineString->getVertices2D()) {
                        transformation.transform(vertex);
                    }
                } else if (lineString->getDimensions() == 3) {
                    for (TVec3d& vertex : lineString->getVertices3D()) {
                        transformation.transform(vertex);
                    }
                }

                m_transformedLineStringsSourceURNMap[lineString.get()] = transformation.sourceURN();

            } else if (it->second != transformation.sourceURN()) {
                CITYGML_LOG_WARN(m_logger, "LineString with id '" << lineString->getId() << "' was already transformed from " << it->second << " to " << m_destinationSRS
                                 << ". But the spatial reference system of Geometry object with id '" << obj.getId() << "' that also contains the LineString is different "
                                 << "(" << transformation.sourceURN() << "). Ignoring new source SRS.");
            }
        }

        for (unsigned int i = 0; i < obj.getGeometriesCount(); i++) {
            transform(obj.getGeometry(i), transformation);
        }
    }
}
#else
class GeoTransform {
};

namespace citygml {

	GeoCoordinateTransformer::GeoCoordinateTransformer(const std::string& destSRS, std::shared_ptr<CityGMLLogger> logger)
	{
		m_destinationSRS = destSRS;
		m_logger = logger;
	}

    void GeoCoordinateTransformer::transformToDestinationSRS(CityModel* model) {
        CITYGML_LOG_WARN(m_logger, "Coordinate transformation to " << m_destinationSRS << " requested, but libcitygml was build without GDAL. The coordinates will not be transformed.");
    }

    void GeoCoordinateTransformer::transformRecursive(CityObject&, GeoTransform&) {}
    void GeoCoordinateTransformer::transformRecursive_helper(CityObject&, GeoTransform&) {}
    void GeoCoordinateTransformer::transformRecursive(ImplicitGeometry&, GeoTransform&) {}
    void GeoCoordinateTransformer::transformRecursive_helper(ImplicitGeometry&, GeoTransform&) {}
    void GeoCoordinateTransformer::transform(Geometry&, GeoTransform&) {}
}
#endif

<|endoftext|>


<commit_before>#include <stan/math/mix/scal.hpp>
#include <gtest/gtest.h>

TEST(AgradFwdLogInvLogitDiff, FvarVar) {
  using stan::math::log_inv_logit_diff;
  using stan::math::fvar;
  using stan::math::var;

  fvar<var> x(0.5, 1.0);
  fvar<var> y(-1.0, 1.0);
  fvar<var> z = log_inv_logit_diff(x, y);
  z.d_.grad();

  EXPECT_FLOAT_EQ(0.664757585587, x.d_.adj());
  EXPECT_FLOAT_EQ(-0.556158338159, y.d_.adj());
  EXPECT_FLOAT_EQ(0.108599247428, z.d_.val());
}

TEST(AgradFwdLogInvLogitDiff, FvarVar_Dbl) {
  using stan::math::log_inv_logit_diff;
  using stan::math::fvar;
  using stan::math::var;

  fvar<var> x(0.5, 1.0);
  double y = -1.0;
  fvar<var> z = log_inv_logit_diff(x, y);
  z.d_.grad();

  EXPECT_FLOAT_EQ(0.664757585587, x.d_.adj());
  EXPECT_FLOAT_EQ(x.d_.adj(), z.d_.val());

  double a = 0.5;
  fvar<var> b(-1.0, 1.0);
  fvar<var> c = log_inv_logit_diff(a, b);
  c.d_.grad();

  EXPECT_FLOAT_EQ(-0.556158338159, b.d_.adj());
  EXPECT_FLOAT_EQ(b.d_.adj(), c.d_.val());
}

TEST(AgradFwdLogInvLogitDiff, FvarFvarVar) {
  using stan::math::log_inv_logit_diff;
  using stan::math::fvar;
  using stan::math::var;

  fvar<fvar<var>> x(0.5, 1.0);
  fvar<fvar<var>> y(-1.0, 1.0);
  fvar<fvar<var>> z = log_inv_logit_diff(x, y);
  z.d_.val_.grad();

  EXPECT_FLOAT_EQ(0.664757585587, x.d_.val_.adj());
  EXPECT_FLOAT_EQ(-0.556158338159, y.d_.val_.adj());
  EXPECT_FLOAT_EQ(0.108599247428, z.d_.val_.val());
}

TEST(AgradFwdLogInvLogitDiff, FvarFVarVar_Dbl) {
  using stan::math::log_inv_logit_diff;
  using stan::math::fvar;
  using stan::math::var;

  fvar<fvar<var>> x(0.5, 1.0);
  double y = -1.0;
  fvar<fvar<var>> z = log_inv_logit_diff(x, y);
  z.d_.val_.grad();

  EXPECT_FLOAT_EQ(0.664757585587, x.d_.val_.adj());
  EXPECT_FLOAT_EQ(x.d_.val_.adj(), z.d_.val_.val());

  double a = 0.5;
  fvar<fvar<var>> b(-1.0, 1.0);
  fvar<fvar<var>> c = log_inv_logit_diff(a, b);
  c.d_.val_.grad();

  EXPECT_FLOAT_EQ(-0.556158338159, b.d_.val_.adj());
  EXPECT_FLOAT_EQ(b.d_.val_.adj(), c.d_.val_.val());
}
<commit_msg>[Jenkins] auto-formatting by clang-format version 5.0.1 (tags/RELEASE_501/final)<commit_after>#include <stan/math/mix/scal.hpp>
#include <gtest/gtest.h>

TEST(AgradFwdLogInvLogitDiff, FvarVar) {
  using stan::math::fvar;
  using stan::math::log_inv_logit_diff;
  using stan::math::var;

  fvar<var> x(0.5, 1.0);
  fvar<var> y(-1.0, 1.0);
  fvar<var> z = log_inv_logit_diff(x, y);
  z.d_.grad();

  EXPECT_FLOAT_EQ(0.664757585587, x.d_.adj());
  EXPECT_FLOAT_EQ(-0.556158338159, y.d_.adj());
  EXPECT_FLOAT_EQ(0.108599247428, z.d_.val());
}

TEST(AgradFwdLogInvLogitDiff, FvarVar_Dbl) {
  using stan::math::fvar;
  using stan::math::log_inv_logit_diff;
  using stan::math::var;

  fvar<var> x(0.5, 1.0);
  double y = -1.0;
  fvar<var> z = log_inv_logit_diff(x, y);
  z.d_.grad();

  EXPECT_FLOAT_EQ(0.664757585587, x.d_.adj());
  EXPECT_FLOAT_EQ(x.d_.adj(), z.d_.val());

  double a = 0.5;
  fvar<var> b(-1.0, 1.0);
  fvar<var> c = log_inv_logit_diff(a, b);
  c.d_.grad();

  EXPECT_FLOAT_EQ(-0.556158338159, b.d_.adj());
  EXPECT_FLOAT_EQ(b.d_.adj(), c.d_.val());
}

TEST(AgradFwdLogInvLogitDiff, FvarFvarVar) {
  using stan::math::fvar;
  using stan::math::log_inv_logit_diff;
  using stan::math::var;

  fvar<fvar<var>> x(0.5, 1.0);
  fvar<fvar<var>> y(-1.0, 1.0);
  fvar<fvar<var>> z = log_inv_logit_diff(x, y);
  z.d_.val_.grad();

  EXPECT_FLOAT_EQ(0.664757585587, x.d_.val_.adj());
  EXPECT_FLOAT_EQ(-0.556158338159, y.d_.val_.adj());
  EXPECT_FLOAT_EQ(0.108599247428, z.d_.val_.val());
}

TEST(AgradFwdLogInvLogitDiff, FvarFVarVar_Dbl) {
  using stan::math::fvar;
  using stan::math::log_inv_logit_diff;
  using stan::math::var;

  fvar<fvar<var>> x(0.5, 1.0);
  double y = -1.0;
  fvar<fvar<var>> z = log_inv_logit_diff(x, y);
  z.d_.val_.grad();

  EXPECT_FLOAT_EQ(0.664757585587, x.d_.val_.adj());
  EXPECT_FLOAT_EQ(x.d_.val_.adj(), z.d_.val_.val());

  double a = 0.5;
  fvar<fvar<var>> b(-1.0, 1.0);
  fvar<fvar<var>> c = log_inv_logit_diff(a, b);
  c.d_.val_.grad();

  EXPECT_FLOAT_EQ(-0.556158338159, b.d_.val_.adj());
  EXPECT_FLOAT_EQ(b.d_.val_.adj(), c.d_.val_.val());
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * x11_graphics.cpp
 *****************************************************************************
 * Copyright (C) 2003 VideoLAN
 * $Id$
 *
 * Authors: Cyril Deguet     <asmax@via.ecp.fr>
 *          Olivier Teulire <ipkiss@via.ecp.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

#ifdef X11_SKINS

#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/shape.h>

#include "x11_display.hpp"
#include "x11_graphics.hpp"
#include "x11_window.hpp"
#include "../src/generic_bitmap.hpp"

X11Graphics::X11Graphics( intf_thread_t *pIntf, X11Display &rDisplay,
                          int width, int height ):
    OSGraphics( pIntf ), m_rDisplay( rDisplay ), m_width( width ),
    m_height( height )
{
    // Get the display paramaters
    int screen = DefaultScreen( XDISPLAY );
    int depth = DefaultDepth( XDISPLAY, screen );

    // Create a pixmap
    m_pixmap = XCreatePixmap( XDISPLAY, DefaultRootWindow( XDISPLAY ),
                              width, height, depth);

    // Create the transparency mask (everything is transparent initially)
    m_mask = XCreateRegion();

    // Create a Graphics Context that does not generate GraphicsExpose events
    XGCValues xgcvalues;
    xgcvalues.graphics_exposures = False;
    m_gc = XCreateGC( XDISPLAY, m_pixmap, GCGraphicsExposures, &xgcvalues );
}

X11Graphics::~X11Graphics()
{
    XFreeGC( XDISPLAY, m_gc );
    XDestroyRegion( m_mask );
    XFreePixmap( XDISPLAY, m_pixmap );
}

void X11Graphics::clear()
{
    // Clear the transparency mask
    XDestroyRegion( m_mask );
    m_mask = XCreateRegion();
}

void X11Graphics::drawGraphics( const OSGraphics &rGraphics, int xSrc,
                                int ySrc, int xDest, int yDest, int width,
                                int height )
{
    if( width == -1 )
    {
        width = rGraphics.getWidth();
    }
    if( height == -1 )
    {
        height = rGraphics.getHeight();
    }

    // Source drawable
    Drawable src = ((X11Graphics&)rGraphics).getDrawable();

    // Create the mask for transparency
    Region voidMask = XCreateRegion();
    XRectangle rect;
    rect.x = xSrc;
    rect.y = ySrc;
    rect.width = width;
    rect.height = height;
    Region clipMask = XCreateRegion();
    XUnionRectWithRegion( &rect, voidMask, clipMask );
    Region mask = XCreateRegion();
    XIntersectRegion( ((X11Graphics&)rGraphics).getMask(), clipMask, mask );
    XDestroyRegion( clipMask );
    XDestroyRegion( voidMask );
    XOffsetRegion( mask, xDest - xSrc, yDest - ySrc );

    // Copy the pixmap
    XSetRegion( XDISPLAY, m_gc, mask );
    XCopyArea( XDISPLAY, src, m_pixmap, m_gc, xSrc, ySrc, width, height,
               xDest, yDest );

    // Add the source mask to the mask of the graphics
    Region newMask = XCreateRegion();
    XUnionRegion( m_mask, mask, newMask );
    XDestroyRegion( mask );
    XDestroyRegion( m_mask );
    m_mask = newMask;
}

void X11Graphics::drawBitmap( const GenericBitmap &rBitmap, int xSrc,
                              int ySrc, int xDest, int yDest, int width,
                              int height )
{
    // Get the bitmap size if necessary
    if( width == -1 )
    {
        width = rBitmap.getWidth();
    }
    else if( width > rBitmap.getWidth() )
    {
        msg_Dbg( getIntf(), "Bitmap width too small!" );
        width = rBitmap.getWidth();
    }
    if( height == -1 )
    {
        height = rBitmap.getHeight();
    }
    else if( height > rBitmap.getHeight() )
    {
        msg_Dbg( getIntf(), "Bitmap height too small!" );
        height = rBitmap.getHeight();
    }

    // Nothing to draw if width or height is null
    if( width == 0 || height == 0 )
    {
        return;
    }

    // Safety check for debugging purpose
    if( xDest + width > m_width || yDest + height > m_height )
    {
        msg_Dbg( getIntf(), "Bitmap too large !" );
        return;
    }

    // Get a buffer on the image data
    uint8_t *pBmpData = rBitmap.getData();
    if( pBmpData == NULL )
    {
        // Nothing to draw
        return;
    }

    // Get the image from the pixmap
    XImage *pImage = XGetImage( XDISPLAY, m_pixmap, xDest, yDest, width,
                                height, AllPlanes, ZPixmap );
    if( pImage == NULL )
    {
        msg_Dbg( getIntf(), "XGetImage returned NULL" );
        return;
    }
    char *pData = pImage->data;

    // Get the padding of this image
    int pad = pImage->bitmap_pad >> 3;
    int shift = ( pad - ( (width * XPIXELSIZE) % pad ) ) % pad;

    // Mask for transparency
    Region mask = XCreateRegion();

    // Get a pointer on the right X11Display::makePixel method
    X11Display::MakePixelFunc_t makePixelFunc = m_rDisplay.getMakePixel();

    // Skip the first lines of the image
    pBmpData += 4 * ySrc * rBitmap.getWidth();

    // Copy the bitmap on the image and compute the mask
    for( int y = 0; y < height; y++ )
    {
        // Skip uninteresting bytes at the beginning of the line
        pBmpData += 4 * xSrc;
        // Flag to say whether the previous pixel on the line was visible
        bool wasVisible = false;
        // Beginning of the current visible segment on the line
        int visibleSegmentStart = 0;
        for( int x = 0; x < width; x++ )
        {
            uint8_t b = *(pBmpData++);
            uint8_t g = *(pBmpData++);
            uint8_t r = *(pBmpData++);
            uint8_t a = *(pBmpData++);
            // Draw the pixel
            (m_rDisplay.*makePixelFunc)( (uint8_t*)pData, r, g, b, a );
            pData += XPIXELSIZE;
            if( a > 0 )
            {
                // Pixel is visible
                if( ! wasVisible )
                {
                    // Beginning of a visible segment
                    visibleSegmentStart = x;
                }
                wasVisible = true;
            }
            else
            {
                // Pixel is transparent
                if( wasVisible )
                {
                    // End of a visible segment: add it to the mask
                    addHSegmentInRegion( mask, visibleSegmentStart, x, y );
                }
                wasVisible = false;
            }
        }
        if( wasVisible )
        {
            // End of a visible segment: add it to the mask
            addHSegmentInRegion( mask, visibleSegmentStart, width, y );
        }
        pData += shift;
        // Skip uninteresting bytes at the end of the line
        pBmpData += 4 * (rBitmap.getWidth() - width - xSrc);
    }

    // Apply the mask to the graphics context
    XOffsetRegion( mask, xDest, yDest );
    XSetRegion( XDISPLAY, m_gc, mask );
    // Copy the image on the pixmap
    XPutImage( XDISPLAY, m_pixmap, m_gc, pImage, 0, 0, xDest, yDest, width,
               height);
    XDestroyImage( pImage );

    // Add the bitmap mask to the global graphics mask
    Region newMask = XCreateRegion();
    XUnionRegion( mask, m_mask, newMask );
    XDestroyRegion( m_mask );
    m_mask = newMask;

    XDestroyRegion( mask );
}

void X11Graphics::fillRect( int left, int top, int width, int height,
                            uint32_t color )
{
    // Update the mask with the rectangle area
    Region newMask = XCreateRegion();
    XRectangle rect;
    rect.x = left;
    rect.y = top;
    rect.width = width;
    rect.height = height;
    XUnionRectWithRegion( &rect, m_mask, newMask );
    XDestroyRegion( m_mask );
    m_mask = newMask;

    // Draw the rectangle
    XGCValues gcVal;
    gcVal.foreground = m_rDisplay.getPixelValue( color >> 16, color >> 8, color );
    XChangeGC( XDISPLAY, m_gc, GCForeground,  &gcVal );
    XSetRegion( XDISPLAY, m_gc, m_mask );
    XFillRectangle( XDISPLAY, m_pixmap, m_gc, left, top, width, height );
}

void X11Graphics::drawRect( int left, int top, int width, int height,
                            uint32_t color )
{
    // Update the mask with the rectangle
    addHSegmentInRegion( m_mask, left, left + width, top );
    addHSegmentInRegion( m_mask, left, left + width, top + height );
    addVSegmentInRegion( m_mask, top, top + height, left );
    addVSegmentInRegion( m_mask, top, top + height, left + width );

    // Draw the rectangle
    XGCValues gcVal;
    gcVal.foreground = m_rDisplay.getPixelValue( color >> 16, color >> 8, color );
    XChangeGC( XDISPLAY, m_gc, GCForeground,  &gcVal );
    XSetRegion( XDISPLAY, m_gc, m_mask );
    XDrawRectangle( XDISPLAY, m_pixmap, m_gc, left, top, width - 1, height - 1 );
}

void X11Graphics::applyMaskToWindow( OSWindow &rWindow )
{
    // Get the target window
    Window win = ((X11Window&)rWindow).getDrawable();

    // Change the shape of the window
    XShapeCombineRegion( XDISPLAY, win, ShapeBounding, 0, 0, m_mask,
                         ShapeSet );
}

void X11Graphics::copyToWindow( OSWindow &rWindow, int xSrc,  int ySrc,
                                int width, int height, int xDest, int yDest )
{
    // Destination window
    Drawable dest = ((X11Window&)rWindow).getDrawable();

    XCopyArea( XDISPLAY, m_pixmap, dest, XGC, xSrc, ySrc, width, height,
               xDest, yDest );
}

bool X11Graphics::hit( int x, int y ) const
{
    return XPointInRegion( m_mask, x, y );
}

inline void X11Graphics::addHSegmentInRegion( Region &rMask, int xStart,
                                              int xEnd, int y )
{
    XRectangle rect;
    rect.x = xStart;
    rect.y = y;
    rect.width = xEnd - xStart;
    rect.height = 1;
    Region newMask = XCreateRegion();
    XUnionRectWithRegion( &rect, rMask, newMask );
    XDestroyRegion( rMask );
    rMask = newMask;
}

inline void X11Graphics::addVSegmentInRegion( Region &rMask, int yStart,
                                              int yEnd, int x )
{
    XRectangle rect;
    rect.x = x;
    rect.y = yStart;
    rect.width = 1;
    rect.height = yEnd - yStart;
    Region newMask = XCreateRegion();
    XUnionRectWithRegion( &rect, rMask, newMask );
    XDestroyRegion( rMask );
    rMask = newMask;
}

#endif
<commit_msg>  * x11_graphics: check if the width and height are not null, to avoid     a X11 Bad Value error<commit_after>/*****************************************************************************
 * x11_graphics.cpp
 *****************************************************************************
 * Copyright (C) 2003 VideoLAN
 * $Id$
 *
 * Authors: Cyril Deguet     <asmax@via.ecp.fr>
 *          Olivier Teulire <ipkiss@via.ecp.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

#ifdef X11_SKINS

#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/shape.h>

#include "x11_display.hpp"
#include "x11_graphics.hpp"
#include "x11_window.hpp"
#include "../src/generic_bitmap.hpp"

X11Graphics::X11Graphics( intf_thread_t *pIntf, X11Display &rDisplay,
                          int width, int height ):
    OSGraphics( pIntf ), m_rDisplay( rDisplay ), m_width( width ),
    m_height( height )
{
    // Get the display paramaters
    int screen = DefaultScreen( XDISPLAY );
    int depth = DefaultDepth( XDISPLAY, screen );

    // X11 doesn't accept that !
    if( width == 0 || height == 0 )
    {
        // Avoid a X11 Bad Value error
        width = height = 1;
        msg_Err( getIntf(), "Invalid image size (null width or height)" );
    }

    // Create a pixmap
    m_pixmap = XCreatePixmap( XDISPLAY, DefaultRootWindow( XDISPLAY ),
                              width, height, depth);

    // Create the transparency mask (everything is transparent initially)
    m_mask = XCreateRegion();

    // Create a Graphics Context that does not generate GraphicsExpose events
    XGCValues xgcvalues;
    xgcvalues.graphics_exposures = False;
    m_gc = XCreateGC( XDISPLAY, m_pixmap, GCGraphicsExposures, &xgcvalues );
}

X11Graphics::~X11Graphics()
{
    XFreeGC( XDISPLAY, m_gc );
    XDestroyRegion( m_mask );
    XFreePixmap( XDISPLAY, m_pixmap );
}

void X11Graphics::clear()
{
    // Clear the transparency mask
    XDestroyRegion( m_mask );
    m_mask = XCreateRegion();
}

void X11Graphics::drawGraphics( const OSGraphics &rGraphics, int xSrc,
                                int ySrc, int xDest, int yDest, int width,
                                int height )
{
    if( width == -1 )
    {
        width = rGraphics.getWidth();
    }
    if( height == -1 )
    {
        height = rGraphics.getHeight();
    }

    // Source drawable
    Drawable src = ((X11Graphics&)rGraphics).getDrawable();

    // Create the mask for transparency
    Region voidMask = XCreateRegion();
    XRectangle rect;
    rect.x = xSrc;
    rect.y = ySrc;
    rect.width = width;
    rect.height = height;
    Region clipMask = XCreateRegion();
    XUnionRectWithRegion( &rect, voidMask, clipMask );
    Region mask = XCreateRegion();
    XIntersectRegion( ((X11Graphics&)rGraphics).getMask(), clipMask, mask );
    XDestroyRegion( clipMask );
    XDestroyRegion( voidMask );
    XOffsetRegion( mask, xDest - xSrc, yDest - ySrc );

    // Copy the pixmap
    XSetRegion( XDISPLAY, m_gc, mask );
    XCopyArea( XDISPLAY, src, m_pixmap, m_gc, xSrc, ySrc, width, height,
               xDest, yDest );

    // Add the source mask to the mask of the graphics
    Region newMask = XCreateRegion();
    XUnionRegion( m_mask, mask, newMask );
    XDestroyRegion( mask );
    XDestroyRegion( m_mask );
    m_mask = newMask;
}

void X11Graphics::drawBitmap( const GenericBitmap &rBitmap, int xSrc,
                              int ySrc, int xDest, int yDest, int width,
                              int height )
{
    // Get the bitmap size if necessary
    if( width == -1 )
    {
        width = rBitmap.getWidth();
    }
    else if( width > rBitmap.getWidth() )
    {
        msg_Dbg( getIntf(), "Bitmap width too small!" );
        width = rBitmap.getWidth();
    }
    if( height == -1 )
    {
        height = rBitmap.getHeight();
    }
    else if( height > rBitmap.getHeight() )
    {
        msg_Dbg( getIntf(), "Bitmap height too small!" );
        height = rBitmap.getHeight();
    }

    // Nothing to draw if width or height is null
    if( width == 0 || height == 0 )
    {
        return;
    }

    // Safety check for debugging purpose
    if( xDest + width > m_width || yDest + height > m_height )
    {
        msg_Dbg( getIntf(), "Bitmap too large !" );
        return;
    }

    // Get a buffer on the image data
    uint8_t *pBmpData = rBitmap.getData();
    if( pBmpData == NULL )
    {
        // Nothing to draw
        return;
    }

    // Get the image from the pixmap
    XImage *pImage = XGetImage( XDISPLAY, m_pixmap, xDest, yDest, width,
                                height, AllPlanes, ZPixmap );
    if( pImage == NULL )
    {
        msg_Dbg( getIntf(), "XGetImage returned NULL" );
        return;
    }
    char *pData = pImage->data;

    // Get the padding of this image
    int pad = pImage->bitmap_pad >> 3;
    int shift = ( pad - ( (width * XPIXELSIZE) % pad ) ) % pad;

    // Mask for transparency
    Region mask = XCreateRegion();

    // Get a pointer on the right X11Display::makePixel method
    X11Display::MakePixelFunc_t makePixelFunc = m_rDisplay.getMakePixel();

    // Skip the first lines of the image
    pBmpData += 4 * ySrc * rBitmap.getWidth();

    // Copy the bitmap on the image and compute the mask
    for( int y = 0; y < height; y++ )
    {
        // Skip uninteresting bytes at the beginning of the line
        pBmpData += 4 * xSrc;
        // Flag to say whether the previous pixel on the line was visible
        bool wasVisible = false;
        // Beginning of the current visible segment on the line
        int visibleSegmentStart = 0;
        for( int x = 0; x < width; x++ )
        {
            uint8_t b = *(pBmpData++);
            uint8_t g = *(pBmpData++);
            uint8_t r = *(pBmpData++);
            uint8_t a = *(pBmpData++);
            // Draw the pixel
            (m_rDisplay.*makePixelFunc)( (uint8_t*)pData, r, g, b, a );
            pData += XPIXELSIZE;
            if( a > 0 )
            {
                // Pixel is visible
                if( ! wasVisible )
                {
                    // Beginning of a visible segment
                    visibleSegmentStart = x;
                }
                wasVisible = true;
            }
            else
            {
                // Pixel is transparent
                if( wasVisible )
                {
                    // End of a visible segment: add it to the mask
                    addHSegmentInRegion( mask, visibleSegmentStart, x, y );
                }
                wasVisible = false;
            }
        }
        if( wasVisible )
        {
            // End of a visible segment: add it to the mask
            addHSegmentInRegion( mask, visibleSegmentStart, width, y );
        }
        pData += shift;
        // Skip uninteresting bytes at the end of the line
        pBmpData += 4 * (rBitmap.getWidth() - width - xSrc);
    }

    // Apply the mask to the graphics context
    XOffsetRegion( mask, xDest, yDest );
    XSetRegion( XDISPLAY, m_gc, mask );
    // Copy the image on the pixmap
    XPutImage( XDISPLAY, m_pixmap, m_gc, pImage, 0, 0, xDest, yDest, width,
               height);
    XDestroyImage( pImage );

    // Add the bitmap mask to the global graphics mask
    Region newMask = XCreateRegion();
    XUnionRegion( mask, m_mask, newMask );
    XDestroyRegion( m_mask );
    m_mask = newMask;

    XDestroyRegion( mask );
}

void X11Graphics::fillRect( int left, int top, int width, int height,
                            uint32_t color )
{
    // Update the mask with the rectangle area
    Region newMask = XCreateRegion();
    XRectangle rect;
    rect.x = left;
    rect.y = top;
    rect.width = width;
    rect.height = height;
    XUnionRectWithRegion( &rect, m_mask, newMask );
    XDestroyRegion( m_mask );
    m_mask = newMask;

    // Draw the rectangle
    XGCValues gcVal;
    gcVal.foreground = m_rDisplay.getPixelValue( color >> 16, color >> 8, color );
    XChangeGC( XDISPLAY, m_gc, GCForeground,  &gcVal );
    XSetRegion( XDISPLAY, m_gc, m_mask );
    XFillRectangle( XDISPLAY, m_pixmap, m_gc, left, top, width, height );
}

void X11Graphics::drawRect( int left, int top, int width, int height,
                            uint32_t color )
{
    // Update the mask with the rectangle
    addHSegmentInRegion( m_mask, left, left + width, top );
    addHSegmentInRegion( m_mask, left, left + width, top + height );
    addVSegmentInRegion( m_mask, top, top + height, left );
    addVSegmentInRegion( m_mask, top, top + height, left + width );

    // Draw the rectangle
    XGCValues gcVal;
    gcVal.foreground = m_rDisplay.getPixelValue( color >> 16, color >> 8, color );
    XChangeGC( XDISPLAY, m_gc, GCForeground,  &gcVal );
    XSetRegion( XDISPLAY, m_gc, m_mask );
    XDrawRectangle( XDISPLAY, m_pixmap, m_gc, left, top, width - 1, height - 1 );
}

void X11Graphics::applyMaskToWindow( OSWindow &rWindow )
{
    // Get the target window
    Window win = ((X11Window&)rWindow).getDrawable();

    // Change the shape of the window
    XShapeCombineRegion( XDISPLAY, win, ShapeBounding, 0, 0, m_mask,
                         ShapeSet );
}

void X11Graphics::copyToWindow( OSWindow &rWindow, int xSrc,  int ySrc,
                                int width, int height, int xDest, int yDest )
{
    // Destination window
    Drawable dest = ((X11Window&)rWindow).getDrawable();

    XCopyArea( XDISPLAY, m_pixmap, dest, XGC, xSrc, ySrc, width, height,
               xDest, yDest );
}

bool X11Graphics::hit( int x, int y ) const
{
    return XPointInRegion( m_mask, x, y );
}

inline void X11Graphics::addHSegmentInRegion( Region &rMask, int xStart,
                                              int xEnd, int y )
{
    XRectangle rect;
    rect.x = xStart;
    rect.y = y;
    rect.width = xEnd - xStart;
    rect.height = 1;
    Region newMask = XCreateRegion();
    XUnionRectWithRegion( &rect, rMask, newMask );
    XDestroyRegion( rMask );
    rMask = newMask;
}

inline void X11Graphics::addVSegmentInRegion( Region &rMask, int yStart,
                                              int yEnd, int x )
{
    XRectangle rect;
    rect.x = x;
    rect.y = yStart;
    rect.width = 1;
    rect.height = yEnd - yStart;
    Region newMask = XCreateRegion();
    XUnionRectWithRegion( &rect, rMask, newMask );
    XDestroyRegion( rMask );
    rMask = newMask;
}

#endif
<|endoftext|>