<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#ifndef __itkMinimumMaximumImageFilter_hxx
#define __itkMinimumMaximumImageFilter_hxx
#include "itkMinimumMaximumImageFilter.h"

#include "itkImageRegionIterator.h"
#include "itkProgressReporter.h"

#include <vector>

namespace itk
{
template< class TInputImage >
MinimumMaximumImageFilter< TInputImage >
::MinimumMaximumImageFilter()
{
  this->SetNumberOfRequiredOutputs(3);
  // first output is a copy of the image, DataObject created by
  // superclass
  //
  // allocate the data objects for the remaining outputs which are
  // just decorators around floating point types
  for ( int i = 1; i < 3; ++i )
    {
    typename PixelObjectType::Pointer output =
      static_cast< PixelObjectType * >( this->MakeOutput(i).GetPointer() );
    this->ProcessObject::SetNthOutput( i, output.GetPointer() );
    }

  this->GetMinimumOutput()->Set( NumericTraits< PixelType >::max() );
  this->GetMaximumOutput()->Set( NumericTraits< PixelType >::NonpositiveMin() );
}

template< class TInputImage >
DataObject::Pointer
MinimumMaximumImageFilter< TInputImage >
::MakeOutput(DataObjectPointerArraySizeType output)
{
  switch ( output )
    {
    case 0:
      return static_cast< DataObject * >( TInputImage::New().GetPointer() );
      break;
    case 1:
    case 2:
      return static_cast< DataObject * >( PixelObjectType::New().GetPointer() );
      break;
    default:
      // might as well make an image
      return static_cast< DataObject * >( TInputImage::New().GetPointer() );
      break;
    }
}

template< class TInputImage >
typename MinimumMaximumImageFilter< TInputImage >::PixelObjectType *
MinimumMaximumImageFilter< TInputImage >
::GetMinimumOutput()
{
  return static_cast< PixelObjectType * >( this->ProcessObject::GetOutput(1) );
}

template< class TInputImage >
const typename MinimumMaximumImageFilter< TInputImage >::PixelObjectType *
MinimumMaximumImageFilter< TInputImage >
::GetMinimumOutput() const
{
  return static_cast< const PixelObjectType * >( this->ProcessObject::GetOutput(1) );
}

template< class TInputImage >
typename MinimumMaximumImageFilter< TInputImage >::PixelObjectType *
MinimumMaximumImageFilter< TInputImage >
::GetMaximumOutput()
{
  return static_cast< PixelObjectType * >( this->ProcessObject::GetOutput(2) );
}

template< class TInputImage >
const typename MinimumMaximumImageFilter< TInputImage >::PixelObjectType *
MinimumMaximumImageFilter< TInputImage >
::GetMaximumOutput() const
{
  return static_cast< const PixelObjectType * >( this->ProcessObject::GetOutput(2) );
}

template< class TInputImage >
void
MinimumMaximumImageFilter< TInputImage >
::GenerateInputRequestedRegion()
{
  Superclass::GenerateInputRequestedRegion();
  if ( this->GetInput() )
    {
    InputImagePointer image =
      const_cast< typename Superclass::InputImageType * >( this->GetInput() );
    image->SetRequestedRegionToLargestPossibleRegion();
    }
}

template< class TInputImage >
void
MinimumMaximumImageFilter< TInputImage >
::EnlargeOutputRequestedRegion(DataObject *data)
{
  Superclass::EnlargeOutputRequestedRegion(data);
  data->SetRequestedRegionToLargestPossibleRegion();
}

template< class TInputImage >
void
MinimumMaximumImageFilter< TInputImage >
::AllocateOutputs()
{
  // Pass the input through as the output
  InputImagePointer image =
    const_cast< TInputImage * >( this->GetInput() );

  this->GraftOutput(image);

  // Nothing that needs to be allocated for the remaining outputs
}

template< class TInputImage >
void
MinimumMaximumImageFilter< TInputImage >
::BeforeThreadedGenerateData()
{
  ThreadIdType numberOfThreads = this->GetNumberOfThreads();

  // Create the thread temporaries
  m_ThreadMin = std::vector< PixelType >( numberOfThreads,
                                          NumericTraits< PixelType >::max() );
  m_ThreadMax = std::vector< PixelType >( numberOfThreads,
                                          NumericTraits< PixelType >::NonpositiveMin() );
}

template< class TInputImage >
void
MinimumMaximumImageFilter< TInputImage >
::AfterThreadedGenerateData()
{
  ThreadIdType i;
  ThreadIdType numberOfThreads = this->GetNumberOfThreads();

  PixelType minimum, maximum;

  // Find the min/max over all threads
  minimum = NumericTraits< PixelType >::max();
  maximum = NumericTraits< PixelType >::NonpositiveMin();
  for ( i = 0; i < numberOfThreads; i++ )
    {
    if ( m_ThreadMin[i] < minimum )
      {
      minimum = m_ThreadMin[i];
      }
    if ( m_ThreadMax[i] > maximum )
      {
      maximum = m_ThreadMax[i];
      }
    }

  // Set the outputs
  this->GetMinimumOutput()->Set(minimum);
  this->GetMaximumOutput()->Set(maximum);
}

template< class TInputImage >
void
MinimumMaximumImageFilter< TInputImage >
::ThreadedGenerateData(const RegionType & outputRegionForThread,
                       ThreadIdType threadId)
{
  PixelType value;

  ImageRegionConstIterator< TInputImage > it (this->GetInput(), outputRegionForThread);

  // support progress methods/callbacks
  ProgressReporter progress( this, threadId, outputRegionForThread.GetNumberOfPixels() );

  // do the work
  while ( !it.IsAtEnd() )
    {
    value = static_cast< PixelType >( it.Get() );
    if ( value < m_ThreadMin[threadId] )
      {
      m_ThreadMin[threadId] = value;
      }
    if ( value > m_ThreadMax[threadId] )
      {
      m_ThreadMax[threadId] = value;
      }
    ++it;
    progress.CompletedPixel();
    }
}

template< class TImage >
void
MinimumMaximumImageFilter< TImage >
::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  os << indent << "Minimum: "
     << static_cast< typename NumericTraits< PixelType >::PrintType >( this->GetMinimum() )
     << std::endl;
  os << indent << "Maximum: "
     << static_cast< typename NumericTraits< PixelType >::PrintType >( this->GetMaximum() )
     << std::endl;
}
} // end namespace itk
#endif
<commit_msg>PERF: eliminate false sharing, improved algorithm<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#ifndef __itkMinimumMaximumImageFilter_hxx
#define __itkMinimumMaximumImageFilter_hxx
#include "itkMinimumMaximumImageFilter.h"

#include "itkImageRegionIterator.h"
#include "itkProgressReporter.h"

#include <vector>

namespace itk
{
template< class TInputImage >
MinimumMaximumImageFilter< TInputImage >
::MinimumMaximumImageFilter()
{
  this->SetNumberOfRequiredOutputs(3);
  // first output is a copy of the image, DataObject created by
  // superclass
  //
  // allocate the data objects for the remaining outputs which are
  // just decorators around floating point types
  for ( int i = 1; i < 3; ++i )
    {
    typename PixelObjectType::Pointer output =
      static_cast< PixelObjectType * >( this->MakeOutput(i).GetPointer() );
    this->ProcessObject::SetNthOutput( i, output.GetPointer() );
    }

  this->GetMinimumOutput()->Set( NumericTraits< PixelType >::max() );
  this->GetMaximumOutput()->Set( NumericTraits< PixelType >::NonpositiveMin() );
}

template< class TInputImage >
DataObject::Pointer
MinimumMaximumImageFilter< TInputImage >
::MakeOutput(DataObjectPointerArraySizeType output)
{
  switch ( output )
    {
    case 0:
      return static_cast< DataObject * >( TInputImage::New().GetPointer() );
      break;
    case 1:
    case 2:
      return static_cast< DataObject * >( PixelObjectType::New().GetPointer() );
      break;
    default:
      // might as well make an image
      return static_cast< DataObject * >( TInputImage::New().GetPointer() );
      break;
    }
}

template< class TInputImage >
typename MinimumMaximumImageFilter< TInputImage >::PixelObjectType *
MinimumMaximumImageFilter< TInputImage >
::GetMinimumOutput()
{
  return static_cast< PixelObjectType * >( this->ProcessObject::GetOutput(1) );
}

template< class TInputImage >
const typename MinimumMaximumImageFilter< TInputImage >::PixelObjectType *
MinimumMaximumImageFilter< TInputImage >
::GetMinimumOutput() const
{
  return static_cast< const PixelObjectType * >( this->ProcessObject::GetOutput(1) );
}

template< class TInputImage >
typename MinimumMaximumImageFilter< TInputImage >::PixelObjectType *
MinimumMaximumImageFilter< TInputImage >
::GetMaximumOutput()
{
  return static_cast< PixelObjectType * >( this->ProcessObject::GetOutput(2) );
}

template< class TInputImage >
const typename MinimumMaximumImageFilter< TInputImage >::PixelObjectType *
MinimumMaximumImageFilter< TInputImage >
::GetMaximumOutput() const
{
  return static_cast< const PixelObjectType * >( this->ProcessObject::GetOutput(2) );
}

template< class TInputImage >
void
MinimumMaximumImageFilter< TInputImage >
::GenerateInputRequestedRegion()
{
  Superclass::GenerateInputRequestedRegion();
  if ( this->GetInput() )
    {
    InputImagePointer image =
      const_cast< typename Superclass::InputImageType * >( this->GetInput() );
    image->SetRequestedRegionToLargestPossibleRegion();
    }
}

template< class TInputImage >
void
MinimumMaximumImageFilter< TInputImage >
::EnlargeOutputRequestedRegion(DataObject *data)
{
  Superclass::EnlargeOutputRequestedRegion(data);
  data->SetRequestedRegionToLargestPossibleRegion();
}

template< class TInputImage >
void
MinimumMaximumImageFilter< TInputImage >
::AllocateOutputs()
{
  // Pass the input through as the output
  InputImagePointer image =
    const_cast< TInputImage * >( this->GetInput() );

  this->GraftOutput(image);

  // Nothing that needs to be allocated for the remaining outputs
}

template< class TInputImage >
void
MinimumMaximumImageFilter< TInputImage >
::BeforeThreadedGenerateData()
{
  ThreadIdType numberOfThreads = this->GetNumberOfThreads();

  // Create the thread temporaries
  m_ThreadMin = std::vector< PixelType >( numberOfThreads,
                                          NumericTraits< PixelType >::max() );
  m_ThreadMax = std::vector< PixelType >( numberOfThreads,
                                          NumericTraits< PixelType >::NonpositiveMin() );
}

template< class TInputImage >
void
MinimumMaximumImageFilter< TInputImage >
::AfterThreadedGenerateData()
{
  ThreadIdType i;
  ThreadIdType numberOfThreads = this->GetNumberOfThreads();

  PixelType minimum, maximum;

  // Find the min/max over all threads
  minimum = NumericTraits< PixelType >::max();
  maximum = NumericTraits< PixelType >::NonpositiveMin();
  for ( i = 0; i < numberOfThreads; i++ )
    {
    if ( m_ThreadMin[i] < minimum )
      {
      minimum = m_ThreadMin[i];
      }
    if ( m_ThreadMax[i] > maximum )
      {
      maximum = m_ThreadMax[i];
      }
    }

  // Set the outputs
  this->GetMinimumOutput()->Set(minimum);
  this->GetMaximumOutput()->Set(maximum);
}

template< class TInputImage >
void
MinimumMaximumImageFilter< TInputImage >
::ThreadedGenerateData(const RegionType & outputRegionForThread,
                       ThreadIdType threadId)
{
  if ( outputRegionForThread.GetNumberOfPixels() == 0 )
    return;

  PixelType localMin = m_ThreadMin[threadId];
  PixelType localMax = m_ThreadMax[threadId];

  ImageRegionConstIterator< TInputImage > it (this->GetInput(), outputRegionForThread);

  // support progress methods/callbacks
  ProgressReporter progress( this, threadId, outputRegionForThread.GetNumberOfPixels()/2 );

  // Handle the odd pixel separately
  if ( outputRegionForThread.GetNumberOfPixels()%2 == 1 )
    {
    const PixelType value = it.Get();
    localMin = localMax = value;
    ++it;
    }

  // do the work for the even number of pixels 2 at a time
  while ( !it.IsAtEnd() )
    {
    const PixelType value1 = it.Get();
    ++it;
    const PixelType value2 = it.Get();
    ++it;

    if (value1 > value2)
      {
      localMax = std::max(value1,localMax);
      localMin = std::min(value2,localMin);
      }
    else
      {
      localMax = std::max(value2,localMax);
      localMin = std::min(value1,localMin);
      }
    progress.CompletedPixel();
    }

  m_ThreadMin[threadId] = localMin;
  m_ThreadMax[threadId] = localMax;
}

template< class TImage >
void
MinimumMaximumImageFilter< TImage >
::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  os << indent << "Minimum: "
     << static_cast< typename NumericTraits< PixelType >::PrintType >( this->GetMinimum() )
     << std::endl;
  os << indent << "Maximum: "
     << static_cast< typename NumericTraits< PixelType >::PrintType >( this->GetMaximum() )
     << std::endl;
}
} // end namespace itk
#endif
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License

#ifndef __PROCESS_NETWORK_HPP__
#define __PROCESS_NETWORK_HPP__

#include <process/address.hpp>

#include <stout/net.hpp>
#include <stout/try.hpp>

namespace process {
namespace network {

/**
 * Returns a socket file descriptor for the specified options.
 *
 * **NOTE:** on OS X, the returned socket will have the SO_NOSIGPIPE
 * option set.
 */
inline Try<int> socket(int family, int type, int protocol)
{
  int s;
  if ((s = ::socket(family, type, protocol)) == -1) {
    return ErrnoError();
  }

#ifdef __APPLE__
  // Disable SIGPIPE via setsockopt because OS X does not support
  // the MSG_NOSIGNAL flag on send(2).
  const int enable = 1;
  if (setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, &enable, sizeof(int)) == -1) {
    return ErrnoError();
  }
#endif // __APPLE__

  return s;
}

// TODO(benh): Remove and defer to Socket::accept.
inline Try<int> accept(int s)
{
  struct sockaddr_storage storage;
  socklen_t storagelen = sizeof(storage);

  int accepted = ::accept(s, (struct sockaddr*) &storage, &storagelen);
  if (accepted < 0) {
    return ErrnoError("Failed to accept");
  }

  return accepted;
}

// TODO(benh): Remove and defer to Socket::bind.
inline Try<int> bind(int s, const Address& address)
{
  struct sockaddr_storage storage =
    net::createSockaddrStorage(address.ip, address.port);

  int error = ::bind(s, (struct sockaddr*) &storage, address.size());
  if (error < 0) {
    return ErrnoError("Failed to bind on " + stringify(address));
  }

  return error;
}

// TODO(benh): Remove and defer to Socket::connect.
inline Try<int> connect(int s, const Address& address)
{
  struct sockaddr_storage storage =
    net::createSockaddrStorage(address.ip, address.port);

  int error = ::connect(s, (struct sockaddr*) &storage, address.size());
  if (error < 0) {
    return ErrnoError("Failed to connect to " + stringify(address));
  }

  return error;
}

/**
 * Returns the `Address` with the assigned ip and assigned port.
 *
 * @return An `Address` or an error if the `getsockname` system call
 *     fails or the family type is not supported.
 */
inline Try<Address> address(int s)
{
  struct sockaddr_storage storage;
  socklen_t storagelen = sizeof(storage);

  if (::getsockname(s, (struct sockaddr*) &storage, &storagelen) < 0) {
    return ErrnoError("Failed to getsockname");
  }

  return Address::create(storage);
}

/**
 * Returns the peer's `Address` for the accepted or connected socket.
 *
 * @return An `Address` or an error if the `getpeername` system call
 *     fails or the family type is not supported.
 */
inline Try<Address> peer(int s)
{
  struct sockaddr_storage storage;
  socklen_t storagelen = sizeof(storage);

  if (::getpeername(s, (struct sockaddr*) &storage, &storagelen) < 0) {
    return ErrnoError("Failed to getpeername");
  }

  return Address::create(storage);
}

} // namespace network {
} // namespace process {

#endif // __PROCESS_NETWORK_HPP__
<commit_msg>Windows: [2/2] Lifted socket API into Stout.<commit_after>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License

#ifndef __PROCESS_NETWORK_HPP__
#define __PROCESS_NETWORK_HPP__

#include <process/address.hpp>

#include <stout/net.hpp>
#include <stout/try.hpp>

#include <stout/os/socket.hpp>

namespace process {
namespace network {

using net::socket;

// TODO(benh): Remove and defer to Socket::accept.
inline Try<int> accept(int s)
{
  struct sockaddr_storage storage;
  socklen_t storagelen = sizeof(storage);

  int accepted = ::accept(s, (struct sockaddr*) &storage, &storagelen);
  if (accepted < 0) {
    return ErrnoError("Failed to accept");
  }

  return accepted;
}

// TODO(benh): Remove and defer to Socket::bind.
inline Try<int> bind(int s, const Address& address)
{
  struct sockaddr_storage storage =
    net::createSockaddrStorage(address.ip, address.port);

  int error = ::bind(s, (struct sockaddr*) &storage, address.size());
  if (error < 0) {
    return ErrnoError("Failed to bind on " + stringify(address));
  }

  return error;
}

// TODO(benh): Remove and defer to Socket::connect.
inline Try<int> connect(int s, const Address& address)
{
  struct sockaddr_storage storage =
    net::createSockaddrStorage(address.ip, address.port);

  int error = ::connect(s, (struct sockaddr*) &storage, address.size());
  if (error < 0) {
    return ErrnoError("Failed to connect to " + stringify(address));
  }

  return error;
}

/**
 * Returns the `Address` with the assigned ip and assigned port.
 *
 * @return An `Address` or an error if the `getsockname` system call
 *     fails or the family type is not supported.
 */
inline Try<Address> address(int s)
{
  struct sockaddr_storage storage;
  socklen_t storagelen = sizeof(storage);

  if (::getsockname(s, (struct sockaddr*) &storage, &storagelen) < 0) {
    return ErrnoError("Failed to getsockname");
  }

  return Address::create(storage);
}

/**
 * Returns the peer's `Address` for the accepted or connected socket.
 *
 * @return An `Address` or an error if the `getpeername` system call
 *     fails or the family type is not supported.
 */
inline Try<Address> peer(int s)
{
  struct sockaddr_storage storage;
  socklen_t storagelen = sizeof(storage);

  if (::getpeername(s, (struct sockaddr*) &storage, &storagelen) < 0) {
    return ErrnoError("Failed to getpeername");
  }

  return Address::create(storage);
}

} // namespace network {
} // namespace process {

#endif // __PROCESS_NETWORK_HPP__
<|endoftext|>


<commit_before>/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/

#ifndef __PROCESS_NETWORK_HPP__
#define __PROCESS_NETWORK_HPP__

#include <process/address.hpp>

#include <stout/net.hpp>
#include <stout/try.hpp>

namespace process {
namespace network {

/**
 * Returns a socket file descriptor for the specified options.
 *
 * **NOTE:** on OS X, the returned socket will have the SO_NOSIGPIPE
 * option set.
 */
inline Try<int> socket(int family, int type, int protocol)
{
  int s;
  if ((s = ::socket(family, type, protocol)) == -1) {
    return ErrnoError();
  }

#ifdef __APPLE__
  // Disable SIGPIPE via setsockopt because OS X does not support
  // the MSG_NOSIGNAL flag on send(2).
  const int enable = 1;
  if (setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, &enable, sizeof(int)) == -1) {
    return ErrnoError();
  }
#endif // __APPLE__

  return s;
}

// TODO(benh): Remove and defer to Socket::accept.
inline Try<int> accept(int s)
{
  struct sockaddr_storage storage;
  socklen_t storagelen = sizeof(storage);

  int accepted = ::accept(s, (struct sockaddr*) &storage, &storagelen);
  if (accepted < 0) {
    return ErrnoError("Failed to accept");
  }

  return accepted;
}

// TODO(benh): Remove and defer to Socket::bind.
inline Try<int> bind(int s, const Address& address)
{
  struct sockaddr_storage storage =
    net::createSockaddrStorage(address.ip, address.port);

  int error = ::bind(s, (struct sockaddr*) &storage, address.size());
  if (error < 0) {
    return ErrnoError("Failed to bind on " + stringify(address));
  }

  return error;
}

// TODO(benh): Remove and defer to Socket::connect.
inline Try<int> connect(int s, const Address& address)
{
  struct sockaddr_storage storage =
    net::createSockaddrStorage(address.ip, address.port);

  int error = ::connect(s, (struct sockaddr*) &storage, address.size());
  if (error < 0) {
    return ErrnoError("Failed to connect to " + stringify(address));
  }

  return error;
}

/**
 * Returns the `Address` with the assigned ip and assigned port.
 *
 * @return An `Address` or an error if the `getsockname` system call
 *     fails or the family type is not supported.
 */
inline Try<Address> address(int s)
{
  struct sockaddr_storage storage;
  socklen_t storagelen = sizeof(storage);

  if(::getsockname(s, (struct sockaddr*) &storage, &storagelen) < 0) {
    return ErrnoError("Failed to getsockname");
  }

  return Address::create(storage);
}

/**
 * Returns the peer's `Address` for the accepted or connected socket.
 *
 * @return An `Address` or an error if the `getpeername` system call
 *     fails or the family type is not supported.
 */
inline Try<Address> peer(int s)
{
  struct sockaddr_storage storage;
  socklen_t storagelen = sizeof(storage);

  if(::getpeername(s, (struct sockaddr*) &storage, &storagelen) < 0) {
    return ErrnoError("Failed to getpeername");
  }

  return Address::create(storage);
}

} // namespace network {
} // namespace process {

#endif // __PROCESS_NETWORK_HPP__
<commit_msg>libprocess: Fixed style issues around control structures.<commit_after>/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/

#ifndef __PROCESS_NETWORK_HPP__
#define __PROCESS_NETWORK_HPP__

#include <process/address.hpp>

#include <stout/net.hpp>
#include <stout/try.hpp>

namespace process {
namespace network {

/**
 * Returns a socket file descriptor for the specified options.
 *
 * **NOTE:** on OS X, the returned socket will have the SO_NOSIGPIPE
 * option set.
 */
inline Try<int> socket(int family, int type, int protocol)
{
  int s;
  if ((s = ::socket(family, type, protocol)) == -1) {
    return ErrnoError();
  }

#ifdef __APPLE__
  // Disable SIGPIPE via setsockopt because OS X does not support
  // the MSG_NOSIGNAL flag on send(2).
  const int enable = 1;
  if (setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, &enable, sizeof(int)) == -1) {
    return ErrnoError();
  }
#endif // __APPLE__

  return s;
}

// TODO(benh): Remove and defer to Socket::accept.
inline Try<int> accept(int s)
{
  struct sockaddr_storage storage;
  socklen_t storagelen = sizeof(storage);

  int accepted = ::accept(s, (struct sockaddr*) &storage, &storagelen);
  if (accepted < 0) {
    return ErrnoError("Failed to accept");
  }

  return accepted;
}

// TODO(benh): Remove and defer to Socket::bind.
inline Try<int> bind(int s, const Address& address)
{
  struct sockaddr_storage storage =
    net::createSockaddrStorage(address.ip, address.port);

  int error = ::bind(s, (struct sockaddr*) &storage, address.size());
  if (error < 0) {
    return ErrnoError("Failed to bind on " + stringify(address));
  }

  return error;
}

// TODO(benh): Remove and defer to Socket::connect.
inline Try<int> connect(int s, const Address& address)
{
  struct sockaddr_storage storage =
    net::createSockaddrStorage(address.ip, address.port);

  int error = ::connect(s, (struct sockaddr*) &storage, address.size());
  if (error < 0) {
    return ErrnoError("Failed to connect to " + stringify(address));
  }

  return error;
}

/**
 * Returns the `Address` with the assigned ip and assigned port.
 *
 * @return An `Address` or an error if the `getsockname` system call
 *     fails or the family type is not supported.
 */
inline Try<Address> address(int s)
{
  struct sockaddr_storage storage;
  socklen_t storagelen = sizeof(storage);

  if (::getsockname(s, (struct sockaddr*) &storage, &storagelen) < 0) {
    return ErrnoError("Failed to getsockname");
  }

  return Address::create(storage);
}

/**
 * Returns the peer's `Address` for the accepted or connected socket.
 *
 * @return An `Address` or an error if the `getpeername` system call
 *     fails or the family type is not supported.
 */
inline Try<Address> peer(int s)
{
  struct sockaddr_storage storage;
  socklen_t storagelen = sizeof(storage);

  if (::getpeername(s, (struct sockaddr*) &storage, &storagelen) < 0) {
    return ErrnoError("Failed to getpeername");
  }

  return Address::create(storage);
}

} // namespace network {
} // namespace process {

#endif // __PROCESS_NETWORK_HPP__
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef __STOUT_OS_POSIX_SHELL_HPP__
#define __STOUT_OS_POSIX_SHELL_HPP__

#include <stdarg.h> // For va_list, va_start, etc.
#include <stdio.h> // For ferror, fgets, FILE, pclose, popen.

#include <sys/wait.h> // For waitpid.

#include <ostream>
#include <string>

#include <glog/logging.h>

#include <stout/error.hpp>
#include <stout/format.hpp>
#include <stout/try.hpp>

#include <stout/os/raw/argv.hpp>

namespace os {

// Import `::execvp` into `os::` namespace.
using ::execvp;

namespace Shell {

// Canonical constants used as platform-dependent args to `exec`
// calls. `name` is the command name, `arg0` is the first argument
// received by the callee, usually the command name and `arg1` is the
// second command argument received by the callee.

constexpr const char* name = "sh";
constexpr const char* arg0 = "sh";
constexpr const char* arg1 = "-c";

} // namespace Shell {

/**
 * Runs a shell command with optional arguments.
 *
 * This assumes that a successful execution will result in the exit code
 * for the command to be `EXIT_SUCCESS`; in this case, the contents
 * of the `Try` will be the contents of `stdout`.
 *
 * If the exit code is non-zero or the process was signaled, we will
 * return an appropriate error message; but *not* `stderr`.
 *
 * If the caller needs to examine the contents of `stderr` it should
 * be redirected to `stdout` (using, e.g., "2>&1 || true" in the command
 * string).  The `|| true` is required to obtain a success exit
 * code in case of errors, and still obtain `stderr`, as piped to
 * `stdout`.
 *
 * @param fmt the formatting string that contains the command to execute
 *   in the underlying shell.
 * @param t optional arguments for `fmt`.
 *
 * @return the output from running the specified command with the shell; or
 *   an error message if the command's exit code is non-zero.
 */
template <typename... T>
Try<std::string> shell(const std::string& fmt, const T&... t)
{
  const Try<std::string> command = strings::internal::format(fmt, t...);
  if (command.isError()) {
    return Error(command.error());
  }

  FILE* file;
  std::ostringstream stdout;

  if ((file = popen(command.get().c_str(), "r")) == nullptr) {
    return Error("Failed to run '" + command.get() + "'");
  }

  char line[1024];
  // NOTE(vinod): Ideally the if and while loops should be interchanged. But
  // we get a broken pipe error if we don't read the output and simply close.
  while (fgets(line, sizeof(line), file) != nullptr) {
    stdout << line;
  }

  if (ferror(file) != 0) {
    pclose(file); // Ignoring result since we already have an error.
    return Error("Error reading output of '" + command.get() + "'");
  }

  int status;
  if ((status = pclose(file)) == -1) {
    return Error("Failed to get status of '" + command.get() + "'");
  }

  if (WIFSIGNALED(status)) {
    return Error(
        "Running '" + command.get() + "' was interrupted by signal '" +
        strsignal(WTERMSIG(status)) + "'");
  } else if ((WEXITSTATUS(status) != EXIT_SUCCESS)) {
    LOG(ERROR) << "Command '" << command.get()
               << "' failed; this is the output:\n" << stdout.str();
    return Error(
        "Failed to execute '" + command.get() + "'; the command was either "
        "not found or exited with a non-zero exit status: " +
        stringify(WEXITSTATUS(status)));
  }

  return stdout.str();
}

// Executes a command by calling "/bin/sh -c <command>", and returns
// after the command has been completed. Returns 0 if succeeds, and
// return -1 on error (e.g., fork/exec/waitpid failed). This function
// is async signal safe. We return int instead of returning a Try
// because Try involves 'new', which is not async signal safe.
inline int system(const std::string& command)
{
  pid_t pid = ::fork();

  if (pid == -1) {
    return -1;
  } else if (pid == 0) {
    // In child process.
    ::execlp(
        Shell::name, Shell::arg0, Shell::arg1, command.c_str(), (char*)nullptr);
    ::exit(127);
  } else {
    // In parent process.
    int status;
    while (::waitpid(pid, &status, 0) == -1) {
      if (errno != EINTR) {
        return -1;
      }
    }

    return status;
  }
}

// Executes a command by calling "<command> <arguments...>", and
// returns after the command has been completed. Returns 0 if
// succeeds, and -1 on error (e.g., fork/exec/waitpid failed). This
// function is async signal safe. We return int instead of returning a
// Try because Try involves 'new', which is not async signal safe.
inline int spawn(
    const std::string& command,
    const std::vector<std::string>& arguments)
{
  pid_t pid = ::fork();

  if (pid == -1) {
    return -1;
  } else if (pid == 0) {
    // In child process.
    ::execvp(command.c_str(), os::raw::Argv(arguments));
    ::exit(127);
  } else {
    // In parent process.
    int status;
    while (::waitpid(pid, &status, 0) == -1) {
      if (errno != EINTR) {
        return -1;
      }
    }

    return status;
  }
}

template<typename... T>
inline int execlp(const char* file, T... t)
{
  return ::execlp(file, t...);
}

} // namespace os {

#endif // __STOUT_OS_POSIX_SHELL_HPP__
<commit_msg>Made execvp explicit in posix/shell.hpp.<commit_after>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef __STOUT_OS_POSIX_SHELL_HPP__
#define __STOUT_OS_POSIX_SHELL_HPP__

#include <stdarg.h> // For va_list, va_start, etc.
#include <stdio.h> // For ferror, fgets, FILE, pclose, popen.

#include <sys/wait.h> // For waitpid.

#include <ostream>
#include <string>

#include <glog/logging.h>

#include <stout/error.hpp>
#include <stout/format.hpp>
#include <stout/try.hpp>

#include <stout/os/raw/argv.hpp>

namespace os {

namespace Shell {

// Canonical constants used as platform-dependent args to `exec`
// calls. `name` is the command name, `arg0` is the first argument
// received by the callee, usually the command name and `arg1` is the
// second command argument received by the callee.

constexpr const char* name = "sh";
constexpr const char* arg0 = "sh";
constexpr const char* arg1 = "-c";

} // namespace Shell {

/**
 * Runs a shell command with optional arguments.
 *
 * This assumes that a successful execution will result in the exit code
 * for the command to be `EXIT_SUCCESS`; in this case, the contents
 * of the `Try` will be the contents of `stdout`.
 *
 * If the exit code is non-zero or the process was signaled, we will
 * return an appropriate error message; but *not* `stderr`.
 *
 * If the caller needs to examine the contents of `stderr` it should
 * be redirected to `stdout` (using, e.g., "2>&1 || true" in the command
 * string).  The `|| true` is required to obtain a success exit
 * code in case of errors, and still obtain `stderr`, as piped to
 * `stdout`.
 *
 * @param fmt the formatting string that contains the command to execute
 *   in the underlying shell.
 * @param t optional arguments for `fmt`.
 *
 * @return the output from running the specified command with the shell; or
 *   an error message if the command's exit code is non-zero.
 */
template <typename... T>
Try<std::string> shell(const std::string& fmt, const T&... t)
{
  const Try<std::string> command = strings::internal::format(fmt, t...);
  if (command.isError()) {
    return Error(command.error());
  }

  FILE* file;
  std::ostringstream stdout;

  if ((file = popen(command.get().c_str(), "r")) == nullptr) {
    return Error("Failed to run '" + command.get() + "'");
  }

  char line[1024];
  // NOTE(vinod): Ideally the if and while loops should be interchanged. But
  // we get a broken pipe error if we don't read the output and simply close.
  while (fgets(line, sizeof(line), file) != nullptr) {
    stdout << line;
  }

  if (ferror(file) != 0) {
    pclose(file); // Ignoring result since we already have an error.
    return Error("Error reading output of '" + command.get() + "'");
  }

  int status;
  if ((status = pclose(file)) == -1) {
    return Error("Failed to get status of '" + command.get() + "'");
  }

  if (WIFSIGNALED(status)) {
    return Error(
        "Running '" + command.get() + "' was interrupted by signal '" +
        strsignal(WTERMSIG(status)) + "'");
  } else if ((WEXITSTATUS(status) != EXIT_SUCCESS)) {
    LOG(ERROR) << "Command '" << command.get()
               << "' failed; this is the output:\n" << stdout.str();
    return Error(
        "Failed to execute '" + command.get() + "'; the command was either "
        "not found or exited with a non-zero exit status: " +
        stringify(WEXITSTATUS(status)));
  }

  return stdout.str();
}

// Executes a command by calling "/bin/sh -c <command>", and returns
// after the command has been completed. Returns 0 if succeeds, and
// return -1 on error (e.g., fork/exec/waitpid failed). This function
// is async signal safe. We return int instead of returning a Try
// because Try involves 'new', which is not async signal safe.
inline int system(const std::string& command)
{
  pid_t pid = ::fork();

  if (pid == -1) {
    return -1;
  } else if (pid == 0) {
    // In child process.
    ::execlp(
        Shell::name, Shell::arg0, Shell::arg1, command.c_str(), (char*)nullptr);
    ::exit(127);
  } else {
    // In parent process.
    int status;
    while (::waitpid(pid, &status, 0) == -1) {
      if (errno != EINTR) {
        return -1;
      }
    }

    return status;
  }
}

// Executes a command by calling "<command> <arguments...>", and
// returns after the command has been completed. Returns 0 if
// succeeds, and -1 on error (e.g., fork/exec/waitpid failed). This
// function is async signal safe. We return int instead of returning a
// Try because Try involves 'new', which is not async signal safe.
inline int spawn(
    const std::string& command,
    const std::vector<std::string>& arguments)
{
  pid_t pid = ::fork();

  if (pid == -1) {
    return -1;
  } else if (pid == 0) {
    // In child process.
    ::execvp(command.c_str(), os::raw::Argv(arguments));
    ::exit(127);
  } else {
    // In parent process.
    int status;
    while (::waitpid(pid, &status, 0) == -1) {
      if (errno != EINTR) {
        return -1;
      }
    }

    return status;
  }
}

template<typename... T>
inline int execlp(const char* file, T... t)
{
  return ::execlp(file, t...);
}

inline int execvp(const char* file, char* const argv[])
{
  return ::execvp(file, argv);
}

} // namespace os {

#endif // __STOUT_OS_POSIX_SHELL_HPP__
<|endoftext|>


<commit_before>#include <libunittest/all.hpp>
#include "transwarp.h"
#include <fstream>

COLLECTION(test_transwarp) {

std::string make_dot(const std::vector<transwarp::edge>& graph) {
    auto info = [](transwarp::node n) {
        return '"' + std::to_string(n.id) + "_" + n.name + '"';
    };
    std::ostringstream ofile;
    ofile << "digraph transwarp {" << std::endl;
    for (auto pair : graph) {
        ofile << info(pair.parent) << " -> " << info(pair.child) << std::endl;
    }
    ofile << "}" << std::endl;
    return ofile.str();
}

TEST(basic) {
    int value = 42;

    auto f1 = [&value]{ return value; };
    auto task1 = transwarp::make_task("t1", f1);

    auto f2 = [](int v) { return v + 2; };
    auto task2 = transwarp::make_task("t2", f2, task1);

    auto f3 = [](int v, int w) { return v + w + 3; };
    auto root_task = transwarp::make_task("t3", f3, task1, task2);

    root_task->make_ids();
    root_task->set_parallel(4);

    root_task->schedule();
    ASSERT_EQUAL(89, root_task->get_future().get());

    ++value;

    root_task->reset();
    root_task->schedule();
    ASSERT_EQUAL(91, root_task->get_future().get());

    std::ofstream ofile("basic.dot");
    ofile << make_dot(root_task->get_graph());
}

TEST(graph) {
    auto f0 = []{ return 0; };
    auto f1 = [](int){ return 0; };
    auto f2 = [](int, int){ return 0; };
    auto f3 = [](int, int, int){ return 0; };
    auto task1 = transwarp::make_task("task1", f0);
    auto task2 = transwarp::make_task("task2", f1, task1);
    auto task3 = transwarp::make_task("task3", f1, task2);
    auto task5 = transwarp::make_task("task5", f2, task3, task2);
    auto task6 = transwarp::make_task("task6", f3, task1, task2, task5);
    auto task7 = transwarp::make_task("task7", f2, task5, task6);
    auto task8 = transwarp::make_task("task8", f2, task6, task7);
    auto task9 = transwarp::make_task("task9", f2, task8, task7);
    auto task10 = transwarp::make_task("task10", f2, task9, task8);
    auto task11 = transwarp::make_task("task11", f2, task10, task7);
    auto task12 = transwarp::make_task("task12", f2, task11, task6);
    auto root = transwarp::make_task("root", f3, task10, task11, task12);

    root->make_ids();
    std::ofstream ofile("graph.dot");
    ofile << make_dot(root->get_graph());
}

}
<commit_msg>improve test<commit_after>#include <libunittest/all.hpp>
#include "transwarp.h"
#include <fstream>

COLLECTION(test_transwarp) {

std::string make_dot(const std::vector<transwarp::edge>& graph) {
    auto info = [](transwarp::node n) {
        return '"' + std::to_string(n.id) + "_" + n.name + '"';
    };
    std::ostringstream ofile;
    ofile << "digraph transwarp {" << std::endl;
    for (auto pair : graph) {
        ofile << info(pair.parent) << " -> " << info(pair.child) << std::endl;
    }
    ofile << "}" << std::endl;
    return ofile.str();
}

TEST(basic) {
    int value = 42;

    auto f1 = [&value]{ return value; };
    auto task1 = transwarp::make_task("t1", f1);

    auto f2 = [](int v) { return v + 2; };
    auto task2 = transwarp::make_task("t2", f2, task1);

    auto f3 = [](int v, int w) { return v + w + 3; };
    auto root_task = transwarp::make_task("t3", f3, task1, task2);

    root_task->make_ids();
    root_task->set_parallel(4);

    root_task->schedule();
    ASSERT_EQUAL(89, root_task->get_future().get());

    ++value;

    root_task->reset();
    root_task->schedule();
    ASSERT_EQUAL(91, root_task->get_future().get());

    std::ofstream ofile("basic.dot");
    ofile << make_dot(root_task->get_graph());
}

TEST(graph) {
    auto f0 = []{ return 0; };
    auto f1 = [](int){ return 0; };
    auto f2 = [](int, int){ return 0; };
    auto f3 = [](int, int, int){ return 0; };
    auto task0 = transwarp::make_task("task0", f0);
    auto task1 = transwarp::make_task("task1", f0);
    auto task2 = transwarp::make_task("task2", f1, task1);
    auto task3 = transwarp::make_task("task3", f2, task2, task0);
    auto task5 = transwarp::make_task("task5", f2, task3, task2);
    auto task6 = transwarp::make_task("task6", f3, task1, task2, task5);
    auto task7 = transwarp::make_task("task7", f2, task5, task6);
    auto task8 = transwarp::make_task("task8", f2, task6, task7);
    auto task9 = transwarp::make_task("task9", f2, task8, task7);
    auto task10 = transwarp::make_task("task10", f2, task9, task8);
    auto task11 = transwarp::make_task("task11", f2, task10, task7);
    auto task12 = transwarp::make_task("task12", f2, task11, task6);
    auto root = transwarp::make_task("root", f3, task10, task11, task12);

    root->make_ids();
    std::ofstream ofile("graph.dot");
    ofile << make_dot(root->get_graph());
}

}
<|endoftext|>


<commit_before>#include "generatorBase/robotsGeneratorPluginBase.h"

#include <qrutils/inFile.h>
#include <qrgui/mainwindow/qscintillaTextEdit.h>
#include <qrutils/nameNormalizer.h>

using namespace generatorBase;
using namespace qReal;
using namespace gui;
using namespace utils;

RobotsGeneratorPluginBase::RobotsGeneratorPluginBase()
{
	mAppTranslator.load(":/generatorBase_" + QLocale().name());
	QApplication::installTranslator(&mAppTranslator);
}

QString RobotsGeneratorPluginBase::defaultFilePath(QString const &projectName) const
{
	return projectName;
}

QString RobotsGeneratorPluginBase::extension() const
{
	return QString();
}

QString RobotsGeneratorPluginBase::extDescrition() const
{
	return QString();
}

QString RobotsGeneratorPluginBase::generatorName() const
{
	return QString();
}

QString RobotsGeneratorPluginBase::defaultProjectName() const
{
	return QFileInfo(mProjectManager->saveFilePath()).baseName();
}

bool RobotsGeneratorPluginBase::canGenerateTo(QString const &project)
{
	/// @todo: In some scenarios user hand-coded programs will be rewritten with auto-generated
	Q_UNUSED(project)
	return true;
}

QFileInfo RobotsGeneratorPluginBase::srcPath()
{
	Id const &activeDiagram = mMainWindowInterface->activeDiagram();

	int exampleNumber = 0;
	while (!canGenerateTo(NameNormalizer::normalizeStrongly(defaultProjectName(), false)
			+ QString::number(exampleNumber))) {
		++exampleNumber;
	}

	QString const projectName = NameNormalizer::normalizeStrongly(defaultProjectName(), false)
			+ QString::number(exampleNumber);
	QFileInfo fileInfo = QFileInfo(QApplication::applicationDirPath() + "/" + defaultFilePath(projectName));
	QList<QFileInfo> const pathsList = mCodePath.values(activeDiagram);

	if (!pathsList.isEmpty()) {
		foreach (QFileInfo const &path, pathsList) {
			if (mTextManager->isDefaultPath(path.absoluteFilePath())
				&& (!mTextManager->isModifiedEver(path.absoluteFilePath()))
				&& !mTextManager->generatorName(path.absoluteFilePath()).compare(generatorName())) {
				fileInfo = path;
				break;
			}
		}
	}

	return fileInfo;
}

QFileInfo RobotsGeneratorPluginBase::generateCodeForProcessing()
{
	QFileInfo fileInfo;
	Id const &activeDiagram = mMainWindowInterface->activeDiagram();

	if (!activeDiagram.isNull()) {
		if (generateCode(false)) {
			foreach (QFileInfo const &path, mCodePath.values(activeDiagram)) {
				if (mTextManager->isDefaultPath(path.absoluteFilePath())
					&& (!mTextManager->isModifiedEver(path.absoluteFilePath()))
					&& !mTextManager->generatorName(path.absoluteFilePath()).compare(generatorName())) {
					fileInfo = path;
					break;
				}
			}
		} else {
			return QFileInfo();
		}
	} else {
		QScintillaTextEdit *code = static_cast<QScintillaTextEdit *>(mMainWindowInterface->currentTab());
		fileInfo = QFileInfo(mTextManager->path(code));
	}

	return fileInfo;
}

void RobotsGeneratorPluginBase::init(PluginConfigurator const &configurator
		, interpreterBase::robotModel::RobotModelManagerInterface const &robotModelManager)
{
	mProjectManager = &configurator.projectManager();
	mSystemEvents = &configurator.systemEvents();
	mTextManager = &configurator.textManager();

	mMainWindowInterface = &configurator.mainWindowInterpretersInterface();
	mRepo = dynamic_cast<qrRepo::RepoApi const *>(&configurator.logicalModelApi().logicalRepoApi());
	mProjectManager = &configurator.projectManager();
	mRobotModelManager = &robotModelManager;

	connect(mSystemEvents, SIGNAL(codePathChanged(qReal::Id, QFileInfo, QFileInfo))
			, this, SLOT(regenerateCode(qReal::Id, QFileInfo, QFileInfo)));
	connect(mSystemEvents, SIGNAL(newCodeAppeared(qReal::Id, QFileInfo)), this, SLOT(addNewCode(qReal::Id, QFileInfo)));
	connect(mSystemEvents, SIGNAL(diagramClosed(qReal::Id)), this, SLOT(removeDiagram(qReal::Id)));
	connect(mSystemEvents, SIGNAL(codeTabClosed(QFileInfo)), this, SLOT(removeCode(QFileInfo)));
}

bool RobotsGeneratorPluginBase::generateCode(bool openTab)
{
	mProjectManager->save();
	mMainWindowInterface->errorReporter()->clearErrors();

	MasterGeneratorBase * const generator = masterGenerator();
	QFileInfo const path = srcPath();

	generator->initialize();
	generator->setProjectDir(path);

	QString const generatedSrcPath = generator->generate();

	if (mMainWindowInterface->errorReporter()->wereErrors()) {
		delete generator;
		return false;
	}

	Id const activeDiagram = mMainWindowInterface->activeDiagram();

	QString const generatedCode = utils::InFile::readAll(generatedSrcPath);
	if (!generatedCode.isEmpty()) {
		mTextManager->showInTextEditor(path, generatorName());
	}

	if (!openTab) {
		mMainWindowInterface->activateItemOrDiagram(activeDiagram);
	}

	delete generator;
	return true;
}

void RobotsGeneratorPluginBase::regenerateCode(qReal::Id const &diagram
	, QFileInfo const &oldFileInfo
	, QFileInfo const &newFileInfo)
{
	if (!oldFileInfo.completeSuffix().compare(extension())) {
		mCodePath.remove(diagram, oldFileInfo);
		mCodePath.insert(diagram, newFileInfo);
		regenerateExtraFiles(newFileInfo);
	}
}

void RobotsGeneratorPluginBase::addNewCode(Id const &diagram, QFileInfo const &fileInfo)
{
	mCodePath.insert(diagram, fileInfo);
}

void RobotsGeneratorPluginBase::removeDiagram(qReal::Id const &diagram)
{
	mCodePath.remove(diagram);
}

void RobotsGeneratorPluginBase::removeCode(QFileInfo const &fileInfo)
{
	Id const &diagram = mCodePath.key(fileInfo);
	mCodePath.remove(diagram, fileInfo);
}
<commit_msg>generated name doesn't began with 0<commit_after>#include "generatorBase/robotsGeneratorPluginBase.h"

#include <qrutils/inFile.h>
#include <qrgui/mainwindow/qscintillaTextEdit.h>
#include <qrutils/nameNormalizer.h>

using namespace generatorBase;
using namespace qReal;
using namespace gui;
using namespace utils;

RobotsGeneratorPluginBase::RobotsGeneratorPluginBase()
{
	mAppTranslator.load(":/generatorBase_" + QLocale().name());
	QApplication::installTranslator(&mAppTranslator);
}

QString RobotsGeneratorPluginBase::defaultFilePath(QString const &projectName) const
{
	return projectName;
}

QString RobotsGeneratorPluginBase::extension() const
{
	return QString();
}

QString RobotsGeneratorPluginBase::extDescrition() const
{
	return QString();
}

QString RobotsGeneratorPluginBase::generatorName() const
{
	return QString();
}

QString RobotsGeneratorPluginBase::defaultProjectName() const
{
	return QFileInfo(mProjectManager->saveFilePath()).baseName();
}

bool RobotsGeneratorPluginBase::canGenerateTo(QString const &project)
{
	/// @todo: In some scenarios user hand-coded programs will be rewritten with auto-generated
	Q_UNUSED(project)
	return true;
}

QFileInfo RobotsGeneratorPluginBase::srcPath()
{
	Id const &activeDiagram = mMainWindowInterface->activeDiagram();

	int exampleNumber = 0;
	while (!canGenerateTo(NameNormalizer::normalizeStrongly(defaultProjectName(), false)
			+ QString::number(exampleNumber))) {
		++exampleNumber;
	}

	QString const projectName = NameNormalizer::normalizeStrongly(defaultProjectName(), false)
			+ (exampleNumber > 0 ? QString::number(exampleNumber) : "");
	QFileInfo fileInfo = QFileInfo(QApplication::applicationDirPath() + "/" + defaultFilePath(projectName));
	QList<QFileInfo> const pathsList = mCodePath.values(activeDiagram);

	if (!pathsList.isEmpty()) {
		foreach (QFileInfo const &path, pathsList) {
			if (mTextManager->isDefaultPath(path.absoluteFilePath())
				&& (!mTextManager->isModifiedEver(path.absoluteFilePath()))
				&& !mTextManager->generatorName(path.absoluteFilePath()).compare(generatorName())) {
				fileInfo = path;
				break;
			}
		}
	}

	return fileInfo;
}

QFileInfo RobotsGeneratorPluginBase::generateCodeForProcessing()
{
	QFileInfo fileInfo;
	Id const &activeDiagram = mMainWindowInterface->activeDiagram();

	if (!activeDiagram.isNull()) {
		if (generateCode(false)) {
			foreach (QFileInfo const &path, mCodePath.values(activeDiagram)) {
				if (mTextManager->isDefaultPath(path.absoluteFilePath())
					&& (!mTextManager->isModifiedEver(path.absoluteFilePath()))
					&& !mTextManager->generatorName(path.absoluteFilePath()).compare(generatorName())) {
					fileInfo = path;
					break;
				}
			}
		} else {
			return QFileInfo();
		}
	} else {
		QScintillaTextEdit *code = static_cast<QScintillaTextEdit *>(mMainWindowInterface->currentTab());
		fileInfo = QFileInfo(mTextManager->path(code));
	}

	return fileInfo;
}

void RobotsGeneratorPluginBase::init(PluginConfigurator const &configurator
		, interpreterBase::robotModel::RobotModelManagerInterface const &robotModelManager)
{
	mProjectManager = &configurator.projectManager();
	mSystemEvents = &configurator.systemEvents();
	mTextManager = &configurator.textManager();

	mMainWindowInterface = &configurator.mainWindowInterpretersInterface();
	mRepo = dynamic_cast<qrRepo::RepoApi const *>(&configurator.logicalModelApi().logicalRepoApi());
	mProjectManager = &configurator.projectManager();
	mRobotModelManager = &robotModelManager;

	connect(mSystemEvents, SIGNAL(codePathChanged(qReal::Id, QFileInfo, QFileInfo))
			, this, SLOT(regenerateCode(qReal::Id, QFileInfo, QFileInfo)));
	connect(mSystemEvents, SIGNAL(newCodeAppeared(qReal::Id, QFileInfo)), this, SLOT(addNewCode(qReal::Id, QFileInfo)));
	connect(mSystemEvents, SIGNAL(diagramClosed(qReal::Id)), this, SLOT(removeDiagram(qReal::Id)));
	connect(mSystemEvents, SIGNAL(codeTabClosed(QFileInfo)), this, SLOT(removeCode(QFileInfo)));
}

bool RobotsGeneratorPluginBase::generateCode(bool openTab)
{
	mProjectManager->save();
	mMainWindowInterface->errorReporter()->clearErrors();

	MasterGeneratorBase * const generator = masterGenerator();
	QFileInfo const path = srcPath();

	generator->initialize();
	generator->setProjectDir(path);

	QString const generatedSrcPath = generator->generate();

	if (mMainWindowInterface->errorReporter()->wereErrors()) {
		delete generator;
		return false;
	}

	Id const activeDiagram = mMainWindowInterface->activeDiagram();

	QString const generatedCode = utils::InFile::readAll(generatedSrcPath);
	if (!generatedCode.isEmpty()) {
		mTextManager->showInTextEditor(path, generatorName());
	}

	if (!openTab) {
		mMainWindowInterface->activateItemOrDiagram(activeDiagram);
	}

	delete generator;
	return true;
}

void RobotsGeneratorPluginBase::regenerateCode(qReal::Id const &diagram
	, QFileInfo const &oldFileInfo
	, QFileInfo const &newFileInfo)
{
	if (!oldFileInfo.completeSuffix().compare(extension())) {
		mCodePath.remove(diagram, oldFileInfo);
		mCodePath.insert(diagram, newFileInfo);
		regenerateExtraFiles(newFileInfo);
	}
}

void RobotsGeneratorPluginBase::addNewCode(Id const &diagram, QFileInfo const &fileInfo)
{
	mCodePath.insert(diagram, fileInfo);
}

void RobotsGeneratorPluginBase::removeDiagram(qReal::Id const &diagram)
{
	mCodePath.remove(diagram);
}

void RobotsGeneratorPluginBase::removeCode(QFileInfo const &fileInfo)
{
	Id const &diagram = mCodePath.key(fileInfo);
	mCodePath.remove(diagram, fileInfo);
}
<|endoftext|>


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

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt 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.

=========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbGeoInformationConversion.h"

#include "otbOGRDataSourceWrapper.h"
#include "otbOGRDataSourceToLabelImageFilter.h"
#include "otbGenericRSTransform.h"

namespace otb
{
namespace Wrapper
{

class Rasterization : public Application
{
public:
  /** Standard class typedefs. */
  typedef Rasterization                 Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(Rasterization, otb::Application);

  /** Filters typedef */
  // the application produces a binary mask : no need to use a FloatVectorImageType
  typedef UInt8ImageType::PointType          PointType;
  typedef UInt8ImageType::SizeType           SizeType;
  typedef UInt8ImageType::SpacingType        SpacingType;
  typedef UInt8ImageType::IndexType          IndexType;

  // Misc
  typedef otb::GenericRSTransform<>          RSTransformType;
  typedef otb::PipelineMemoryPrintCalculator MemoryCalculatorType;

  // Exact rasterization mode
  typedef otb::OGRDataSourceToLabelImageFilter<FloatImageType> OGRDataSourceToMapFilterType;

private:
  void DoInit()
    {
    SetName("Rasterization");
    SetDescription("Rasterize a vector dataset.");

    SetDocName("Rasterization");
    SetDocLongDescription("This application allows to reproject and rasterize a vector dataset. The grid of the rasterized output can be set by using a reference image, or by setting all parmeters (origin, size, spacing) by hand. In the latter case, at least the spacing (ground sampling distance) is needed (other parameters are computed automatically). The rasterized output can also be in a different projection reference system than the input dataset.\n There are two rasterize mode available in the application. The first is the binary mode: it allows to render all pixels belonging to a geometry of the input dataset in the foreground color, while rendering the other in background color. The second one allows to render pixels belonging to a geometry woth respect to an attribute of this geometry. The field of the attribute to render can be set by the user. In the second mode, the background value is still used for unassociated pixels.");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso("For now, support of input dataset with multiple layers having different projection reference system is limited.");

    AddDocTag(Tags::Vector);

    AddParameter(ParameterType_InputFilename,  "in",   "Input vector dataset");
    SetParameterDescription( "in", "The input vector dataset to be rasterized" );

    AddParameter(ParameterType_OutputImage,  "out",   "Ouptut image");
    SetParameterDescription( "out", "An output image containing the rasterized vector dataset" );

    AddParameter(ParameterType_InputImage,  "im",   "Input reference image");
    SetParameterDescription( "im", "A reference image from which to import output grid and projection reference system information." );
    MandatoryOff("im");

    AddParameter(ParameterType_Int,  "szx",   "Output size x");
    SetParameterDescription( "szx", "Output size along x axis (useless if support image is given)" );
    MandatoryOff("szx");
    SetMinimumParameterIntValue("szx",1);

    AddParameter(ParameterType_Int,  "szy",   "Output size y");
    SetParameterDescription( "szy", "Output size along y axis (useless if support image is given)" );
    MandatoryOff("szy");
    SetMinimumParameterIntValue("szy",1);

    AddParameter(ParameterType_Int,  "epsg",   "Output EPSG code");
    SetParameterDescription( "epsg", "EPSG code for the output projection reference system (EPSG 4326 for WGS84, 32631 for UTM31N...,useless if support image is given)" );
    MandatoryOff("epsg");

    AddParameter(ParameterType_Float,  "orx",   "Output Upper-left x");
    SetParameterDescription( "orx", "Output upper-left x coordinate (useless if support image is given)" );
    MandatoryOff("orx");

    AddParameter(ParameterType_Float,  "ory",   "Output Upper-left y");
    SetParameterDescription( "ory", "Output upper-left y coordinate (useless if support image is given)" );
    MandatoryOff("ory");

    AddParameter(ParameterType_Float,  "spx",   "Spacing (GSD) x");
    SetParameterDescription( "spx", "Spacing (ground sampling distance) along x axis (useless if support image is given)" );
    MandatoryOff("spx");

    AddParameter(ParameterType_Float,  "spy",   "Spacing (GSD) y");
    SetParameterDescription( "spy", "Spacing (ground sampling distance) along y axis (useless if support image is given)" );
    MandatoryOff("spy");

    AddParameter(ParameterType_Float,"background", "Background value");
    SetParameterDescription("background","Default value for pixels not belonging to any geometry");
    SetDefaultParameterFloat("background",0.);

    AddParameter(ParameterType_Choice,"mode","Rasterization mode");
    SetParameterDescription("mode","Choice of rasterization modes");

    AddChoice("mode.binary","Binary mode");
    SetParameterDescription("mode.binary","In this mode, pixels within a geometry will hold the user-defined foreground value");

    AddParameter(ParameterType_Float,"mode.binary.foreground","Foreground value");
    SetParameterDescription("mode.binary.foreground","Value for pixels inside a geometry");
    SetDefaultParameterFloat("mode.binary.foreground",255);

    AddChoice("mode.attribute","Attribute burning mode");
    SetParameterDescription("mode.attribute","In this mode, pixels within a geometry will hold the value of a user-defined field extracted from this geometry.");

    AddParameter(ParameterType_String,"mode.attribute.field","The attribute field to burn");
    SetParameterDescription("mode.attribute.field","Name of the attribute field to burn");
    SetParameterString("mode.attribute.field","DN");

    AddRAMParameter();

    SetDocExampleParameterValue("in","qb_RoadExtract_classification.shp");
    SetDocExampleParameterValue("out", "rasterImage.tif");
    SetDocExampleParameterValue("spx","1.");
    SetDocExampleParameterValue("spy","1.");
    }

  void DoUpdateParameters()
    {
    // Nothing to do
    }

  void DoExecute()
    {
    UInt8ImageType::Pointer referenceImage;

    m_OgrDS = otb::ogr::DataSource::New(GetParameterString("in"), otb::ogr::DataSource::Modes::read);

    bool validInputProjRef = false;
    std::string inputProjectionRef = "";

    otb::ogr::DataSource::const_iterator lit = m_OgrDS->begin();

    // Retrieve extent
    double ulx, uly, lrx, lry;
    bool extentAvailable = true;

    try
      {
      inputProjectionRef = m_OgrDS->GetGlobalExtent(ulx,uly,lrx,lry);
      }
    catch(itk::ExceptionObject & err)
      {
      extentAvailable = false;
      }

    if(!extentAvailable &&
       (!(HasValue("spx") && HasValue("spy"))
        || (!(HasValue("orx") && HasValue("ory")))))
      {
      otbAppLogWARNING(<<"Failed to retrieve the spatial extent of the dataset. The application will retry in force mode,  which means it might have to walk the entire dataset to determine extent. This might be a long process for large datasets. Consider setting the orx, ory, spx and spy parameters.");

      try
        {
        inputProjectionRef = m_OgrDS->GetGlobalExtent(ulx,uly,lrx,lry);
        extentAvailable = true;
        }
      catch(itk::ExceptionObject & err)
        {
        extentAvailable = false;

        otbAppLogFATAL(<<"Failed to retrieve the sapatial extent of the dataset in force mode. The spatial extent is mandatory when orx, ory, spx and spy parameters are not set, consider setting them.");
        }
      }

    if(extentAvailable)
      {
      otbAppLogINFO("Input dataset extent is ("<<ulx<<", "<<uly<<") ("<<lrx<<", "<<lry<<")");
      }

    if(inputProjectionRef == "")
      {
      otbAppLogWARNING("Failed to find a valid projection ref in dataset. The application will asume that the given reference image or origin, spacing and size are consistent with the dataset geometry. Output EPSG code will be ignored.");
      validInputProjRef = false;
      }
    else
      {
      validInputProjRef = true;
      otbAppLogINFO("Input dataset projection reference system is: "<<inputProjectionRef);
      }

    // region information
    SizeType size;
    PointType origin;
    SpacingType spacing;

    // reading projection information
    // two choice :
    std::string outputProjectionRef;
    // a reference image is given as input
    if (HasValue("im"))
      {
      if (HasValue("szx") || HasValue("szy") || HasValue("orx") || HasValue("ory")
          || HasValue("spx") || HasValue("spy") || HasValue("epsg"))
        {
        otbAppLogWARNING("A reference image has been given, other parameters "
                         "regarding the output image will be ignored");
        }

      referenceImage = GetParameterUInt8Image("im");
      outputProjectionRef = referenceImage->GetProjectionRef();

      size = referenceImage->GetLargestPossibleRegion().GetSize();

      origin = referenceImage->GetOrigin();

      spacing = referenceImage->GetSpacing();
      }
    else if (HasValue("spx") && HasValue("spy"))
      {
      if (HasValue("epsg"))
        {
        unsigned int RSID = GetParameterInt("epsg");
        outputProjectionRef = otb::GeoInformationConversion::ToWKT(RSID);
        }
      else
        {
        outputProjectionRef = inputProjectionRef;
        }

      spacing[0] = GetParameterFloat("spx");
      spacing[1] = GetParameterFloat("spy");

      if ( HasValue("orx") && HasValue("ory"))
        {
        origin[0] = GetParameterFloat("orx");
        origin[1] = GetParameterFloat("ory");
        }
      else if(extentAvailable)
        {
        origin[0] = ulx;
        origin[1] = uly;

        // Transform to output EPSG

        if(validInputProjRef)
          {
          RSTransformType::Pointer rsTransform = RSTransformType::New();
          rsTransform->SetInputProjectionRef(inputProjectionRef);
          rsTransform->SetOutputProjectionRef(outputProjectionRef);
          rsTransform->InstanciateTransform();

          origin = rsTransform->TransformPoint(origin);
          }
        }
      else
        {
        otbAppLogFATAL(<<"The orx and ory parameters are not set and the dataset extent could not be retrieved. The application can not deterimine the origin of the output raster");
        }

      if (HasValue("szx") && HasValue("szy"))
        {
        size[0] = GetParameterInt("szx");
        size[1] = GetParameterInt("szy");
        }
      else if(extentAvailable)
        {
        // Transform to output EPSG
        PointType lrout;
        lrout[0] = lrx;
        lrout[1] = lry;

        if(validInputProjRef)
          {
          RSTransformType::Pointer rsTransform = RSTransformType::New();
          rsTransform->SetInputProjectionRef(inputProjectionRef);
          rsTransform->SetOutputProjectionRef(outputProjectionRef);
          rsTransform->InstanciateTransform();

          lrout = rsTransform->TransformPoint(lrout);
          }
        size[0]=static_cast<unsigned int>((lrout[0] - origin[0])/spacing[0]);
        size[1]=static_cast<unsigned int>((lrout[1] - origin[1])/spacing[1]);
        }
      else
        {
        otbAppLogFATAL(<<"The szx and szy parameters are not set and the dataset extent could not be retrieved. The application can not deterimine the size of the output raster");

        }
      }
    else
      {
      otbAppLogFATAL("No reference image was given, at least spx and spy parameters must be set.");
      }

      m_OGRDataSourceRendering = OGRDataSourceToMapFilterType::New();
      m_OGRDataSourceRendering->AddOGRDataSource(m_OgrDS);
      m_OGRDataSourceRendering->SetOutputSize(size);
      m_OGRDataSourceRendering->SetOutputOrigin(origin);
      m_OGRDataSourceRendering->SetOutputSpacing(spacing);
      m_OGRDataSourceRendering->SetBackgroundValue(GetParameterFloat("background"));

      if(GetParameterString("mode") == "binary")
        {
        m_OGRDataSourceRendering->SetBurnAttributeMode(false);
        m_OGRDataSourceRendering->SetForegroundValue(GetParameterFloat("mode.binary.foreground"));
        }
      else if(GetParameterString("mode") == "attribute")
        {
        m_OGRDataSourceRendering->SetBurnAttributeMode(true);
        m_OGRDataSourceRendering->SetBurnAttribute(GetParameterString("mode.attribute.field"));
        }

      if(validInputProjRef)
        {
        m_OGRDataSourceRendering->SetOutputProjectionRef(outputProjectionRef);
        }

      otbAppLogINFO("Output projection reference system is: "<<outputProjectionRef);

      otbAppLogINFO("Output origin: "<<origin);
      otbAppLogINFO("Output size: "<<size);
      otbAppLogINFO("Output spacing: "<<spacing);

      SetParameterOutputImage<FloatImageType>("out", m_OGRDataSourceRendering->GetOutput());

    }

  otb::ogr::DataSource::Pointer m_OgrDS;
  OGRDataSourceToMapFilterType::Pointer m_OGRDataSourceRendering;

};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::Rasterization)
<commit_msg>DOC: Small typos<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt 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.

=========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbGeoInformationConversion.h"

#include "otbOGRDataSourceWrapper.h"
#include "otbOGRDataSourceToLabelImageFilter.h"
#include "otbGenericRSTransform.h"

namespace otb
{
namespace Wrapper
{

class Rasterization : public Application
{
public:
  /** Standard class typedefs. */
  typedef Rasterization                 Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(Rasterization, otb::Application);

  /** Filters typedef */
  // the application produces a binary mask : no need to use a FloatVectorImageType
  typedef UInt8ImageType::PointType          PointType;
  typedef UInt8ImageType::SizeType           SizeType;
  typedef UInt8ImageType::SpacingType        SpacingType;
  typedef UInt8ImageType::IndexType          IndexType;

  // Misc
  typedef otb::GenericRSTransform<>          RSTransformType;
  typedef otb::PipelineMemoryPrintCalculator MemoryCalculatorType;

  // Exact rasterization mode
  typedef otb::OGRDataSourceToLabelImageFilter<FloatImageType> OGRDataSourceToMapFilterType;

private:
  void DoInit()
    {
    SetName("Rasterization");
    SetDescription("Rasterize a vector dataset.");

    SetDocName("Rasterization");
    SetDocLongDescription("This application allows to reproject and rasterize a vector dataset. The grid of the rasterized output can be set by using a reference image, or by setting all parmeters (origin, size, spacing) by hand. In the latter case, at least the spacing (ground sampling distance) is needed (other parameters are computed automatically). The rasterized output can also be in a different projection reference system than the input dataset.\n There are two rasterize mode available in the application. The first is the binary mode: it allows to render all pixels belonging to a geometry of the input dataset in the foreground color, while rendering the other in background color. The second one allows to render pixels belonging to a geometry woth respect to an attribute of this geometry. The field of the attribute to render can be set by the user. In the second mode, the background value is still used for unassociated pixels.");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso("For now, support of input dataset with multiple layers having different projection reference system is limited.");

    AddDocTag(Tags::Vector);

    AddParameter(ParameterType_InputFilename,  "in",   "Input vector dataset");
    SetParameterDescription( "in", "The input vector dataset to be rasterized" );

    AddParameter(ParameterType_OutputImage,  "out",   "Ouptut image");
    SetParameterDescription( "out", "An output image containing the rasterized vector dataset" );

    AddParameter(ParameterType_InputImage,  "im",   "Input reference image");
    SetParameterDescription( "im", "A reference image from which to import output grid and projection reference system information." );
    MandatoryOff("im");

    AddParameter(ParameterType_Int,  "szx",   "Output size x");
    SetParameterDescription( "szx", "Output size along x axis (useless if support image is given)" );
    MandatoryOff("szx");
    SetMinimumParameterIntValue("szx",1);

    AddParameter(ParameterType_Int,  "szy",   "Output size y");
    SetParameterDescription( "szy", "Output size along y axis (useless if support image is given)" );
    MandatoryOff("szy");
    SetMinimumParameterIntValue("szy",1);

    AddParameter(ParameterType_Int,  "epsg",   "Output EPSG code");
    SetParameterDescription( "epsg", "EPSG code for the output projection reference system (EPSG 4326 for WGS84, 32631 for UTM31N...,useless if support image is given)" );
    MandatoryOff("epsg");

    AddParameter(ParameterType_Float,  "orx",   "Output Upper-left x");
    SetParameterDescription( "orx", "Output upper-left x coordinate (useless if support image is given)" );
    MandatoryOff("orx");

    AddParameter(ParameterType_Float,  "ory",   "Output Upper-left y");
    SetParameterDescription( "ory", "Output upper-left y coordinate (useless if support image is given)" );
    MandatoryOff("ory");

    AddParameter(ParameterType_Float,  "spx",   "Spacing (GSD) x");
    SetParameterDescription( "spx", "Spacing (ground sampling distance) along x axis (useless if support image is given)" );
    MandatoryOff("spx");

    AddParameter(ParameterType_Float,  "spy",   "Spacing (GSD) y");
    SetParameterDescription( "spy", "Spacing (ground sampling distance) along y axis (useless if support image is given)" );
    MandatoryOff("spy");

    AddParameter(ParameterType_Float,"background", "Background value");
    SetParameterDescription("background","Default value for pixels not belonging to any geometry");
    SetDefaultParameterFloat("background",0.);

    AddParameter(ParameterType_Choice,"mode","Rasterization mode");
    SetParameterDescription("mode","Choice of rasterization modes");

    AddChoice("mode.binary","Binary mode");
    SetParameterDescription("mode.binary","In this mode, pixels within a geometry will hold the user-defined foreground value");

    AddParameter(ParameterType_Float,"mode.binary.foreground","Foreground value");
    SetParameterDescription("mode.binary.foreground","Value for pixels inside a geometry");
    SetDefaultParameterFloat("mode.binary.foreground",255);

    AddChoice("mode.attribute","Attribute burning mode");
    SetParameterDescription("mode.attribute","In this mode, pixels within a geometry will hold the value of a user-defined field extracted from this geometry.");

    AddParameter(ParameterType_String,"mode.attribute.field","The attribute field to burn");
    SetParameterDescription("mode.attribute.field","Name of the attribute field to burn");
    SetParameterString("mode.attribute.field","DN");

    AddRAMParameter();

    SetDocExampleParameterValue("in","qb_RoadExtract_classification.shp");
    SetDocExampleParameterValue("out", "rasterImage.tif");
    SetDocExampleParameterValue("spx","1.");
    SetDocExampleParameterValue("spy","1.");
    }

  void DoUpdateParameters()
    {
    // Nothing to do
    }

  void DoExecute()
    {
    UInt8ImageType::Pointer referenceImage;

    m_OgrDS = otb::ogr::DataSource::New(GetParameterString("in"), otb::ogr::DataSource::Modes::read);

    bool validInputProjRef = false;
    std::string inputProjectionRef = "";

    otb::ogr::DataSource::const_iterator lit = m_OgrDS->begin();

    // Retrieve extent
    double ulx, uly, lrx, lry;
    bool extentAvailable = true;

    try
      {
      inputProjectionRef = m_OgrDS->GetGlobalExtent(ulx,uly,lrx,lry);
      }
    catch(itk::ExceptionObject & err)
      {
      extentAvailable = false;
      }

    if(!extentAvailable &&
       (!(HasValue("spx") && HasValue("spy"))
        || (!(HasValue("orx") && HasValue("ory")))))
      {
      otbAppLogWARNING(<<"Failed to retrieve the spatial extent of the dataset. The application will retry in force mode, which means it might have to walk the entire dataset to determine extent. This might be a long process for large datasets. Consider setting the orx, ory, spx and spy parameters.");

      try
        {
        inputProjectionRef = m_OgrDS->GetGlobalExtent(ulx,uly,lrx,lry);
        extentAvailable = true;
        }
      catch(itk::ExceptionObject & err)
        {
        extentAvailable = false;

        otbAppLogFATAL(<<"Failed to retrieve the spatial extent of the dataset in force mode. The spatial extent is mandatory when orx, ory, spx and spy parameters are not set, consider setting them.");
        }
      }

    if(extentAvailable)
      {
      otbAppLogINFO("Input dataset extent is ("<<ulx<<", "<<uly<<") ("<<lrx<<", "<<lry<<")");
      }

    if(inputProjectionRef == "")
      {
      otbAppLogWARNING("Failed to find a valid projection ref in dataset. The application will assume that the given reference image or origin, spacing and size are consistent with the dataset geometry. Output EPSG code will be ignored.");
      validInputProjRef = false;
      }
    else
      {
      validInputProjRef = true;
      otbAppLogINFO("Input dataset projection reference system is: "<<inputProjectionRef);
      }

    // region information
    SizeType size;
    PointType origin;
    SpacingType spacing;

    // reading projection information
    // two choice :
    std::string outputProjectionRef;
    // a reference image is given as input
    if (HasValue("im"))
      {
      if (HasValue("szx") || HasValue("szy") || HasValue("orx") || HasValue("ory")
          || HasValue("spx") || HasValue("spy") || HasValue("epsg"))
        {
        otbAppLogWARNING("A reference image has been given, other parameters "
                         "regarding the output image will be ignored");
        }

      referenceImage = GetParameterUInt8Image("im");
      outputProjectionRef = referenceImage->GetProjectionRef();

      size = referenceImage->GetLargestPossibleRegion().GetSize();

      origin = referenceImage->GetOrigin();

      spacing = referenceImage->GetSpacing();
      }
    else if (HasValue("spx") && HasValue("spy"))
      {
      if (HasValue("epsg"))
        {
        unsigned int RSID = GetParameterInt("epsg");
        outputProjectionRef = otb::GeoInformationConversion::ToWKT(RSID);
        }
      else
        {
        outputProjectionRef = inputProjectionRef;
        }

      spacing[0] = GetParameterFloat("spx");
      spacing[1] = GetParameterFloat("spy");

      if ( HasValue("orx") && HasValue("ory"))
        {
        origin[0] = GetParameterFloat("orx");
        origin[1] = GetParameterFloat("ory");
        }
      else if(extentAvailable)
        {
        origin[0] = ulx;
        origin[1] = uly;

        // Transform to output EPSG

        if(validInputProjRef)
          {
          RSTransformType::Pointer rsTransform = RSTransformType::New();
          rsTransform->SetInputProjectionRef(inputProjectionRef);
          rsTransform->SetOutputProjectionRef(outputProjectionRef);
          rsTransform->InstanciateTransform();

          origin = rsTransform->TransformPoint(origin);
          }
        }
      else
        {
        otbAppLogFATAL(<<"The orx and ory parameters are not set and the dataset extent could not be retrieved. The application can not determine the origin of the output raster");
        }

      if (HasValue("szx") && HasValue("szy"))
        {
        size[0] = GetParameterInt("szx");
        size[1] = GetParameterInt("szy");
        }
      else if(extentAvailable)
        {
        // Transform to output EPSG
        PointType lrout;
        lrout[0] = lrx;
        lrout[1] = lry;

        if(validInputProjRef)
          {
          RSTransformType::Pointer rsTransform = RSTransformType::New();
          rsTransform->SetInputProjectionRef(inputProjectionRef);
          rsTransform->SetOutputProjectionRef(outputProjectionRef);
          rsTransform->InstanciateTransform();

          lrout = rsTransform->TransformPoint(lrout);
          }
        size[0]=static_cast<unsigned int>((lrout[0] - origin[0])/spacing[0]);
        size[1]=static_cast<unsigned int>((lrout[1] - origin[1])/spacing[1]);
        }
      else
        {
        otbAppLogFATAL(<<"The szx and szy parameters are not set and the dataset extent could not be retrieved. The application can not deterimine the size of the output raster");

        }
      }
    else
      {
      otbAppLogFATAL("No reference image was given, at least spx and spy parameters must be set.");
      }

      m_OGRDataSourceRendering = OGRDataSourceToMapFilterType::New();
      m_OGRDataSourceRendering->AddOGRDataSource(m_OgrDS);
      m_OGRDataSourceRendering->SetOutputSize(size);
      m_OGRDataSourceRendering->SetOutputOrigin(origin);
      m_OGRDataSourceRendering->SetOutputSpacing(spacing);
      m_OGRDataSourceRendering->SetBackgroundValue(GetParameterFloat("background"));

      if(GetParameterString("mode") == "binary")
        {
        m_OGRDataSourceRendering->SetBurnAttributeMode(false);
        m_OGRDataSourceRendering->SetForegroundValue(GetParameterFloat("mode.binary.foreground"));
        }
      else if(GetParameterString("mode") == "attribute")
        {
        m_OGRDataSourceRendering->SetBurnAttributeMode(true);
        m_OGRDataSourceRendering->SetBurnAttribute(GetParameterString("mode.attribute.field"));
        }

      if(validInputProjRef)
        {
        m_OGRDataSourceRendering->SetOutputProjectionRef(outputProjectionRef);
        }

      otbAppLogINFO("Output projection reference system is: "<<outputProjectionRef);

      otbAppLogINFO("Output origin: "<<origin);
      otbAppLogINFO("Output size: "<<size);
      otbAppLogINFO("Output spacing: "<<spacing);

      SetParameterOutputImage<FloatImageType>("out", m_OGRDataSourceRendering->GetOutput());

    }

  otb::ogr::DataSource::Pointer m_OgrDS;
  OGRDataSourceToMapFilterType::Pointer m_OGRDataSourceRendering;

};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::Rasterization)
<|endoftext|>