<commit_before>
#pragma once

#include <tuple>
#include <utility>

#include "quantities/named_quantities.hpp"

namespace principia {
namespace numerics {
namespace internal_polynomial {

using quantities::Derivative;

// TODO(phl): We would like to define NthDerivative in named_quantities.hpp
// thus:
//
//   template<typename Value, typename Argument, int order>
//   using NthDerivative = typename std::conditional_t<
//       order == 0,
//       Value,
//       Quotient<Difference<Value>,
//                Exponentiation<Difference<Argument>, order>>>;
//
//   template<typename Value, typename Argument>
//   using Derivative = NthDerivative<Value, Argument, 1>;
//
// Unfortunately VS2015 is buggy and this interacts poorly with the
// std::integer_sequence below (we get the wrong types).  Revisit once MSFT has
// fixed their bugs.

template<typename Value, typename Argument, int order>
struct NthDerivativeGenerator {
  using Type = Derivative<
      typename NthDerivativeGenerator<Value, Argument, order - 1>::Type,
      Argument>;
};
template<typename Value, typename Argument>
struct NthDerivativeGenerator<Value, Argument, 0> {
  using Type = Value;
};

template<typename Value, typename Argument, int order>
using NthDerivative =
    typename NthDerivativeGenerator<Value, Argument, order>::Type;

template<typename Value, typename Argument, typename>
struct NthDerivativesGenerator;
template<typename Value, typename Argument, int... orders>
struct NthDerivativesGenerator<Value,
                               Argument,
                               std::integer_sequence<int, orders...>> {
  using Type = std::tuple<NthDerivative<Value, Argument, orders>...>;
};

template<typename Value, typename Argument, typename Sequence>
using NthDerivatives =
    typename NthDerivativesGenerator<Value, Argument, Sequence>::Type;

// |Value| must belong to an affine space.  |Argument| must belong to a vector
// space.
template<typename Value, typename Argument>
class Polynomial {
 public:
  virtual Value Evaluate(Argument const& argument) const = 0;
  virtual Derivative<Value, Argument> EvaluateDerivative(
      Argument const& argument) const = 0;

  // Only useful for benchmarking or analyzing performance.  Do not use in real
  // code.
  virtual int degree() const = 0;

protected:
  virtual ~Polynomial() = default;
};

template<typename Value, typename Argument, int degree_,
         template<typename, typename, int> class Evaluator>
class PolynomialInMonomialBasis : public Polynomial<Value, Argument> {
 public:
  // Equivalent to:
  //   std::tuple<Value,
  //              Derivative<Value, Argument>,
  //              Derivative<Derivative<Value, Argument>>...>
  using Coefficients =
      NthDerivatives<Value,
                     Argument,
                     std::make_integer_sequence<int, degree_ + 1>>;

  explicit PolynomialInMonomialBasis(Coefficients const& coefficients);

  FORCE_INLINE(inline) Value Evaluate(Argument const& argument) const override;
  FORCE_INLINE(inline) Derivative<Value, Argument> EvaluateDerivative(
      Argument const& argument) const override;

  constexpr int degree() const override;

private:
  Coefficients coefficients_;
};

}  // namespace internal_polynomial

using internal_polynomial::NthDerivative;
using internal_polynomial::Polynomial;
using internal_polynomial::PolynomialInMonomialBasis;

}  // namespace numerics
}  // namespace principia

#include "numerics/polynomial_body.hpp"
<commit_msg>Lint.<commit_after>
#pragma once

#include <tuple>
#include <utility>

#include "quantities/named_quantities.hpp"

namespace principia {
namespace numerics {
namespace internal_polynomial {

using quantities::Derivative;

// TODO(phl): We would like to define NthDerivative in named_quantities.hpp
// thus:
//
//   template<typename Value, typename Argument, int order>
//   using NthDerivative = typename std::conditional_t<
//       order == 0,
//       Value,
//       Quotient<Difference<Value>,
//                Exponentiation<Difference<Argument>, order>>>;
//
//   template<typename Value, typename Argument>
//   using Derivative = NthDerivative<Value, Argument, 1>;
//
// Unfortunately VS2015 is buggy and this interacts poorly with the
// std::integer_sequence below (we get the wrong types).  Revisit once MSFT has
// fixed their bugs.

template<typename Value, typename Argument, int order>
struct NthDerivativeGenerator {
  using Type = Derivative<
      typename NthDerivativeGenerator<Value, Argument, order - 1>::Type,
      Argument>;
};
template<typename Value, typename Argument>
struct NthDerivativeGenerator<Value, Argument, 0> {
  using Type = Value;
};

template<typename Value, typename Argument, int order>
using NthDerivative =
    typename NthDerivativeGenerator<Value, Argument, order>::Type;

template<typename Value, typename Argument, typename>
struct NthDerivativesGenerator;
template<typename Value, typename Argument, int... orders>
struct NthDerivativesGenerator<Value,
                               Argument,
                               std::integer_sequence<int, orders...>> {
  using Type = std::tuple<NthDerivative<Value, Argument, orders>...>;
};

template<typename Value, typename Argument, typename Sequence>
using NthDerivatives =
    typename NthDerivativesGenerator<Value, Argument, Sequence>::Type;

// |Value| must belong to an affine space.  |Argument| must belong to a vector
// space.
template<typename Value, typename Argument>
class Polynomial {
 public:
  virtual Value Evaluate(Argument const& argument) const = 0;
  virtual Derivative<Value, Argument> EvaluateDerivative(
      Argument const& argument) const = 0;

  // Only useful for benchmarking or analyzing performance.  Do not use in real
  // code.
  virtual int degree() const = 0;

 protected:
  virtual ~Polynomial() = default;
};

template<typename Value, typename Argument, int degree_,
         template<typename, typename, int> class Evaluator>
class PolynomialInMonomialBasis : public Polynomial<Value, Argument> {
 public:
  // Equivalent to:
  //   std::tuple<Value,
  //              Derivative<Value, Argument>,
  //              Derivative<Derivative<Value, Argument>>...>
  using Coefficients =
      NthDerivatives<Value,
                     Argument,
                     std::make_integer_sequence<int, degree_ + 1>>;

  explicit PolynomialInMonomialBasis(Coefficients const& coefficients);

  FORCE_INLINE(inline) Value Evaluate(Argument const& argument) const override;
  FORCE_INLINE(inline) Derivative<Value, Argument> EvaluateDerivative(
      Argument const& argument) const override;

  constexpr int degree() const override;

 private:
  Coefficients coefficients_;
};

}  // namespace internal_polynomial

using internal_polynomial::NthDerivative;
using internal_polynomial::Polynomial;
using internal_polynomial::PolynomialInMonomialBasis;

}  // namespace numerics
}  // namespace principia

#include "numerics/polynomial_body.hpp"
<|endoftext|>


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

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date: 2009-05-12 19:56:03 +0200 (Di, 12 Mai 2009) $
Version:   $Revision: 17179 $

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html 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 "mitkLabeledImageVolumeCalculator.h"
#include "mitkImageAccessByItk.h"

#include <itkImageRegionConstIteratorWithIndex.h>

namespace mitk
{

LabeledImageVolumeCalculator::LabeledImageVolumeCalculator()
{
  m_InputTimeSelector = ImageTimeSelector::New();

  m_DummyPoint.Fill( 0.0 );
}

LabeledImageVolumeCalculator::~LabeledImageVolumeCalculator()
{
}

double LabeledImageVolumeCalculator::GetVolume( unsigned int label ) const
{
  if ( label < m_VolumeVector.size() )
    return m_VolumeVector[label];
  else
    return 0.0;
}

const Point3D &LabeledImageVolumeCalculator::GetCentroid( unsigned int label ) const
{
  if ( label < m_CentroidVector.size() )
    return m_CentroidVector[label];
  else
    return m_DummyPoint;
}

const LabeledImageVolumeCalculator::VolumeVector &
LabeledImageVolumeCalculator::GetVolumes() const
{
  return m_VolumeVector;
}

const LabeledImageVolumeCalculator::PointVector &
LabeledImageVolumeCalculator::GetCentroids() const
{
  return m_CentroidVector;
}

void LabeledImageVolumeCalculator::Calculate()
{
  if ( m_Image.IsNull() )
  {
    itkExceptionMacro( << "Image not set!" );
    return;
  }

  m_InputTimeSelector->SetInput( m_Image );

  //const TimeSlicedGeometry *timeSlicedGeometry = m_Image->GetTimeSlicedGeometry();
  //for( unsigned int t = 0; t < timeSlicedGeometry->GetTimeSteps(); ++t )
  //{
  m_InputTimeSelector->SetTimeNr( 0 );
  m_InputTimeSelector->UpdateLargestPossibleRegion();

  AccessByItk_2(
    m_InputTimeSelector->GetOutput(),
    _InternalCalculateVolumes,
    this,
    m_Image->GetGeometry( 0 ) );
  //}
}

template < typename TPixel, unsigned int VImageDimension >
void LabeledImageVolumeCalculator::_InternalCalculateVolumes(
  itk::Image< TPixel, VImageDimension > *image,
  LabeledImageVolumeCalculator *volumeCalculator,
  Geometry3D *geometry )
{
  typedef itk::Image< TPixel, VImageDimension > ImageType;
  typedef typename ImageType::IndexType IndexType;
  typedef itk::ImageRegionConstIteratorWithIndex< ImageType > IteratorType;

  // Reset volume and centroid vectors
  m_VolumeVector.clear();
  m_CentroidVector.clear();

  // Iterate over image and determine number of voxels and centroid
  // per label
  IteratorType it( image, image->GetBufferedRegion() );
  for ( it.GoToBegin(); !it.IsAtEnd(); ++it )
  {
    const IndexType &index = it.GetIndex();
    typename IteratorType::PixelType pixel = it.Get();

    if ( m_VolumeVector.size() <= pixel )
    {
      m_VolumeVector.resize( pixel + 1 );
      m_CentroidVector.resize( pixel + 1 );
    }

    m_VolumeVector[pixel] += 1.0;

    m_CentroidVector[pixel][0] += index[0];
    m_CentroidVector[pixel][1] += index[1];
    m_CentroidVector[pixel][2] += index[2];
  }

  // Calculate voxel volume from spacing
  const Vector3D &spacing = geometry->GetSpacing();
  double voxelVolume = spacing[0] * spacing[1] * spacing[2];

  // Calculate centroid (in world coordinates) and volumes for all labels

  for ( unsigned int i = 0; i < m_VolumeVector.size(); ++i )
  {
    m_CentroidVector[i][0] /= m_VolumeVector[i];
    m_CentroidVector[i][1] /= m_VolumeVector[i];
    m_CentroidVector[i][2] /= m_VolumeVector[i];
    geometry->IndexToWorld( m_CentroidVector[i], m_CentroidVector[i] );

    m_VolumeVector[i] *= voxelVolume;
  }
}

}<commit_msg>FIX (#2483): avoid division by zero for computing volumetry for non-existing labels<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date: 2009-05-12 19:56:03 +0200 (Di, 12 Mai 2009) $
Version:   $Revision: 17179 $

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html 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 "mitkLabeledImageVolumeCalculator.h"
#include "mitkImageAccessByItk.h"

#include <itkImageRegionConstIteratorWithIndex.h>

namespace mitk
{

LabeledImageVolumeCalculator::LabeledImageVolumeCalculator()
{
  m_InputTimeSelector = ImageTimeSelector::New();

  m_DummyPoint.Fill( 0.0 );
}

LabeledImageVolumeCalculator::~LabeledImageVolumeCalculator()
{
}

double LabeledImageVolumeCalculator::GetVolume( unsigned int label ) const
{
  if ( label < m_VolumeVector.size() )
    return m_VolumeVector[label];
  else
    return 0.0;
}

const Point3D &LabeledImageVolumeCalculator::GetCentroid( unsigned int label ) const
{
  if ( label < m_CentroidVector.size() )
    return m_CentroidVector[label];
  else
    return m_DummyPoint;
}

const LabeledImageVolumeCalculator::VolumeVector &
LabeledImageVolumeCalculator::GetVolumes() const
{
  return m_VolumeVector;
}

const LabeledImageVolumeCalculator::PointVector &
LabeledImageVolumeCalculator::GetCentroids() const
{
  return m_CentroidVector;
}

void LabeledImageVolumeCalculator::Calculate()
{
  if ( m_Image.IsNull() )
  {
    itkExceptionMacro( << "Image not set!" );
    return;
  }

  m_InputTimeSelector->SetInput( m_Image );

  //const TimeSlicedGeometry *timeSlicedGeometry = m_Image->GetTimeSlicedGeometry();
  //for( unsigned int t = 0; t < timeSlicedGeometry->GetTimeSteps(); ++t )
  //{
  m_InputTimeSelector->SetTimeNr( 0 );
  m_InputTimeSelector->UpdateLargestPossibleRegion();

  AccessByItk_2(
    m_InputTimeSelector->GetOutput(),
    _InternalCalculateVolumes,
    this,
    m_Image->GetGeometry( 0 ) );
  //}
}

template < typename TPixel, unsigned int VImageDimension >
void LabeledImageVolumeCalculator::_InternalCalculateVolumes(
  itk::Image< TPixel, VImageDimension > *image,
  LabeledImageVolumeCalculator *volumeCalculator,
  Geometry3D *geometry )
{
  typedef itk::Image< TPixel, VImageDimension > ImageType;
  typedef typename ImageType::IndexType IndexType;
  typedef itk::ImageRegionConstIteratorWithIndex< ImageType > IteratorType;

  // Reset volume and centroid vectors
  m_VolumeVector.clear();
  m_CentroidVector.clear();

  // Iterate over image and determine number of voxels and centroid
  // per label
  IteratorType it( image, image->GetBufferedRegion() );
  for ( it.GoToBegin(); !it.IsAtEnd(); ++it )
  {
    const IndexType &index = it.GetIndex();
    typename IteratorType::PixelType pixel = it.Get();

    if ( m_VolumeVector.size() <= pixel )
    {
      m_VolumeVector.resize( pixel + 1 );
      m_CentroidVector.resize( pixel + 1 );
    }

    m_VolumeVector[pixel] += 1.0;

    m_CentroidVector[pixel][0] += index[0];
    m_CentroidVector[pixel][1] += index[1];
    m_CentroidVector[pixel][2] += index[2];
  }

  // Calculate voxel volume from spacing
  const Vector3D &spacing = geometry->GetSpacing();
  double voxelVolume = spacing[0] * spacing[1] * spacing[2];

  // Calculate centroid (in world coordinates) and volumes for all labels
  for ( unsigned int i = 0; i < m_VolumeVector.size(); ++i )
  {
    if ( m_VolumeVector[i] > 0.0 )
    {
      m_CentroidVector[i][0] /= m_VolumeVector[i];
      m_CentroidVector[i][1] /= m_VolumeVector[i];
      m_CentroidVector[i][2] /= m_VolumeVector[i];
      geometry->IndexToWorld( m_CentroidVector[i], m_CentroidVector[i] );

      m_VolumeVector[i] *= voxelVolume;
    }
  }
}

}<|endoftext|>


<commit_before>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You 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.
 ****************************************************************************/

/**
 * @file
 * @brief IronBee++ --- ParserSuite
 *
 * Simple HTTP parsers.
 *
 * XXX
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#ifndef __IBPP__PARSER_SUITE__
#define __IBPP__PARSER_SUITE__

#include <boost/exception/all.hpp>
#include <boost/range/iterator_range.hpp>

#include <vector>

namespace IronBee {

/**
 * Collection of pure HTTP parsers.
 *
 * This namespace defines a variety of HTTP parsers.  All parsers are pure:
 * they store no state and have no side effects.  Every parser parses
 * an input represented as a range of bytes (@ref span_t) and returns a
 * structure with parser results.  It also  modifies the input span to
 * represent the remainder of the data.  E.g.,  calling parse_request_line()
 * on a span representing an entire HTTP request will modify the input to
 * begin just after the request line.  Parsers that require additional
 * context will have additional parameters.
 *
 * Parse results are usually also represented by spans (@ref span_t).  Parsers
 * assume that the underlying memory of the input span will outlive the
 * results.  I.e., freeing the buffer being parsed will invalidate the
 * results.
 *
 * These parsers are intentionally minimal.  For example, parse_request_line()
 * will provide the URI as a result but does not attempt to parse the URI;
 * the URI can be parsed by parse_uri().  This approach has the advantage of
 * code simplicity and not performing unneeded work, but has the disadvantage
 * that deeper parsing require multiple passes.
 *
 * All results are returned by move and support ostream output.  They provide
 * direct results (usually subspans) as public data members and may provide
 * function members for additional logic, e.g.,
 * parse_request_line_result_t::http09().
 **/
namespace ParserSuite {

/**
 * Exception base for all ParserSuite errors.
 **/
struct error : public boost::exception, public std::exception {};

/**
 * Location where error occurred
 **/
using errinfo_location =
    boost::error_info<struct tag_errinfo_location, const char *>;

/**
 * Error message.
 **/
using errinfo_what =
    boost::error_info<struct tag_errinfo_what, std::string>;

/**
 * A span of bytes.
 **/
using span_t = boost::iterator_range<const char*>;

/**
 * A sequence of @ref span_t.
 **/
using span_vec_t = std::vector<span_t>;

//! Result of parse_request_line()
struct parse_request_line_result_t
{
    //! Method.  First of space separated list.
    span_t method;
    //! URI.  Second of space separated list.
    span_t uri;
    //! Version.  Third of space separated list.
    span_t version;

    //! Is this a HTTP 0.9 request, i.e., is @ref version empty?
    bool http09() const
    {
        return version.empty();
    }
};

/**
 * Parse @a input as a request line.
 *
 * @param[in, out] input Span to parse; will be updated such that beginning
 *                       is just after successful parse, i.e., the next line.
 * @return Result.
 * @throw error On any parse error; e.g., less than two items.
 **/
parse_request_line_result_t parse_request_line(span_t& input);

//! Ostream output operator for @ref parse_request_line_result_t.
std::ostream& operator<<(
    std::ostream&                      o,
    const parse_request_line_result_t& R
);

//! Result of parse_response_line()
struct parse_response_line_result_t
{
    //! Version.  First of space separated list.
    span_t version;
    //! Status.  Second of space separated list.
    span_t status;
    //! Message.  Remainder of space separated list.
    span_t message;
};

/**
 * Parse @a input as a response line.
 *
 * @note Early versions of HTTP do not have response lines.
 *
 * @param[in, out] input Span to parse; will be updated such that beginning
 *                       is just after successful parse, i.e., the next line.
 * @return Result.
 * @throw error On any parse error; e.g., less than two items.
 **/
parse_response_line_result_t parse_response_line(span_t& input);

//! Ostream output operator for @ref parse_response_line_result_t.
std::ostream& operator<<(
    std::ostream&                      o,
    const parse_response_line_result_t& R
);

//! Result of parse_uri().
struct parse_uri_result_t
{
    //! Scheme.  Item before first :.
    span_t scheme;
    //! Authority.  Item between // and next / after scheme.
    span_t authority;
    //! Path.  Item after authority (if present) until ?.
    span_t path;
    //! Query.  Item after ? until #.
    span_t query;
    //! Fragment.  Item after #.
    span_t fragment;
};

/**
 * Parse @a input as a URI.
 *
 * @note Will handle schemeless and authorityless URIs.
 *
 * @param[in, out] input Span to parse; will be updated such that beginning
 *                       is just after successful parse, i.e., the first
 *                       whitespace.
 * @return Result.
 * @throw error On any parse error; should not happen.
 **/
parse_uri_result_t parse_uri(span_t& input);

//! Ostream output operator for @ref parse_uri_result_t.
std::ostream& operator<<(
    std::ostream&             o,
    const parse_uri_result_t& R
);

//! Result of parse_headers().
struct parse_headers_result_t
{
    //! A single header.
    struct header_t {
        //! Key.
        span_t key;
        //! Value as sequence of spans: one per line (extended headers).
        span_vec_t value;
    };
    //! Type of @ref headers.
    using headers_t = std::vector<header_t>;

    //! All headers.
    headers_t headers;

    //! True iff a blank line was present after headers.
    bool terminated = false;
};

/**
 * Parse @a input as headers block.
 *
 * @note: Does not require final blank line.  See
 *        parse_headers_result_t::terminated.
 *
 * @param[in, out] input Span to parse; will be updated such that beginning
 *                       is just after successful parse, i.e., the beginning
 *                       of the body.
 * @return Result.
 * @throw error On any parse error; e.g., no key.
 **/
parse_headers_result_t parse_headers(span_t& input);

//! Ostream output operator for @ref parse_headers_result_t
std::ostream& operator<<(
    std::ostream&                 o,
    const parse_headers_result_t& R
);

//! Result of parse_request().
struct parse_request_result_t
{
    //! The request line.
    span_t                      raw_request_line;
    //! The request line as parsed by parse_request_line().
    parse_request_line_result_t request_line;
    //! The URI as parsed by parse_ur().
    parse_uri_result_t          uri;
    //! The headers as parsed by parse_headers().
    parse_headers_result_t      headers;
};

/**
 * Parse @a input as request.
 *
 * @sa parse_request_line()
 * @sa parse_uri()
 * @sa parse_headers()
 *
 * @note Currently does not parse body.  Stay tuned.
 *
 * @param[in, out] input Span to parse; will be updated such that beginning
 *                       is just after successful parse, i.e., the beginning
 *                       of the body.
 * @return Result.
 * @throw error On any parse error.
 **/
parse_request_result_t parse_request(span_t& input);

//! Ostream output operator for @ref parse_request_result_t.
std::ostream& operator<<(
    std::ostream&                 o,
    const parse_request_result_t& R
);

//! Result of parse_response().
struct parse_response_result_t
{
    //! The response line.
    span_t                       raw_response_line;
    //! The reponse line as parsed by parse_response_line().
    parse_response_line_result_t response_line;
    //! The headers as parsed by parse_headers().
    parse_headers_result_t       headers;
};

/**
 * Parse @a input as response.
 *
 * @sa parse_response_line()
 * @sa parse_headers()
 *
 * @note Currently does not parse body.  Stay tuned.
 *
 * @param[in, out] input Span to parse; will be updated such that beginning
 *                       is just after successful parse, i.e., the beginning
 *                       of the body.
 * @return Result.
 * @throw error On any parse error.
 **/
parse_response_result_t parse_response(span_t& input);

//! Ostream output operator for @ref parse_response_result_t
std::ostream& operator<<(
    std::ostream&                  o,
    const parse_response_result_t& R
);

} // ParserSuite
} // IronBee

#endif
<commit_msg>parser_suite: Minor documentation cleanup.<commit_after>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You 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.
 ****************************************************************************/

/**
 * @file
 * @brief IronBee++ --- ParserSuite
 *
 * Simple HTTP parsers.
 *
 * @sa IronBee::ParserSuite.
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#ifndef __IBPP__PARSER_SUITE__
#define __IBPP__PARSER_SUITE__

#include <boost/exception/all.hpp>
#include <boost/range/iterator_range.hpp>

#include <vector>

namespace IronBee {

/**
 * Collection of pure HTTP parsers.
 *
 * This namespace defines a variety of HTTP parsers.  All parsers are pure:
 * they store no state and have no side effects.  Every parser parses
 * an input represented as a range of bytes (@ref span_t) and returns a
 * structure with parser results.  It also  modifies the input span to
 * represent the remainder of the data.  E.g.,  calling parse_request_line()
 * on a span representing an entire HTTP request will modify the input to
 * begin just after the request line.  Parsers that require additional
 * context will have additional parameters.
 *
 * Parse results are usually also represented by spans (@ref span_t).  Parsers
 * assume that the underlying memory of the input span will outlive the
 * results.  I.e., freeing the buffer being parsed will invalidate the
 * results.
 *
 * These parsers are intentionally minimal.  For example, parse_request_line()
 * will provide the URI as a result but does not attempt to parse the URI;
 * the URI can be parsed by parse_uri().  This approach has the advantage of
 * code simplicity and not performing unneeded work, but has the disadvantage
 * that deeper parsing require multiple passes.
 *
 * All results are returned by move and support ostream output.  They provide
 * direct results (usually subspans) as public data members and may provide
 * function members for additional logic, e.g.,
 * parse_request_line_result_t::http09().
 **/
namespace ParserSuite {

/**
 * Exception base for all ParserSuite errors.
 **/
struct error : public boost::exception, public std::exception {};

/**
 * Location where error occurred
 **/
using errinfo_location =
    boost::error_info<struct tag_errinfo_location, const char *>;

/**
 * Error message.
 **/
using errinfo_what =
    boost::error_info<struct tag_errinfo_what, std::string>;

/**
 * A span of bytes.
 **/
using span_t = boost::iterator_range<const char*>;

/**
 * A sequence of @ref span_t.
 **/
using span_vec_t = std::vector<span_t>;

//! Result of parse_request_line()
struct parse_request_line_result_t
{
    //! Method.  First of space separated list.
    span_t method;
    //! URI.  Second of space separated list.
    span_t uri;
    //! Version.  Third of space separated list.
    span_t version;

    //! Is this a HTTP 0.9 request, i.e., is @ref version empty?
    bool http09() const
    {
        return version.empty();
    }
};

/**
 * Parse @a input as a request line.
 *
 * @param[in, out] input Span to parse; will be updated such that beginning
 *                       is just after successful parse, i.e., the next line.
 * @return Result.
 * @throw error On any parse error; e.g., less than two items.
 **/
parse_request_line_result_t parse_request_line(span_t& input);

//! Ostream output operator for @ref parse_request_line_result_t.
std::ostream& operator<<(
    std::ostream&                      o,
    const parse_request_line_result_t& R
);

//! Result of parse_response_line()
struct parse_response_line_result_t
{
    //! Version.  First of space separated list.
    span_t version;
    //! Status.  Second of space separated list.
    span_t status;
    //! Message.  Remainder of space separated list.
    span_t message;
};

/**
 * Parse @a input as a response line.
 *
 * @note Early versions of HTTP do not have response lines.
 *
 * @param[in, out] input Span to parse; will be updated such that beginning
 *                       is just after successful parse, i.e., the next line.
 * @return Result.
 * @throw error On any parse error; e.g., less than two items.
 **/
parse_response_line_result_t parse_response_line(span_t& input);

//! Ostream output operator for @ref parse_response_line_result_t.
std::ostream& operator<<(
    std::ostream&                      o,
    const parse_response_line_result_t& R
);

//! Result of parse_uri().
struct parse_uri_result_t
{
    //! Scheme.  Item before first :.
    span_t scheme;
    //! Authority.  Item between // and next / after scheme.
    span_t authority;
    //! Path.  Item after authority (if present) until ?.
    span_t path;
    //! Query.  Item after ? until #.
    span_t query;
    //! Fragment.  Item after #.
    span_t fragment;
};

/**
 * Parse @a input as a URI.
 *
 * @note Will handle schemeless and authorityless URIs.
 *
 * @param[in, out] input Span to parse; will be updated such that beginning
 *                       is just after successful parse, i.e., the first
 *                       whitespace.
 * @return Result.
 * @throw error On any parse error; should not happen.
 **/
parse_uri_result_t parse_uri(span_t& input);

//! Ostream output operator for @ref parse_uri_result_t.
std::ostream& operator<<(
    std::ostream&             o,
    const parse_uri_result_t& R
);

//! Result of parse_headers().
struct parse_headers_result_t
{
    //! A single header.
    struct header_t {
        //! Key.
        span_t key;
        //! Value as sequence of spans: one per line (extended headers).
        span_vec_t value;
    };
    //! Type of @ref headers.
    using headers_t = std::vector<header_t>;

    //! All headers.
    headers_t headers;

    //! True iff a blank line was present after headers.
    bool terminated = false;
};

/**
 * Parse @a input as headers block.
 *
 * @note: Does not require final blank line.  See
 *        parse_headers_result_t::terminated.
 *
 * @param[in, out] input Span to parse; will be updated such that beginning
 *                       is just after successful parse, i.e., the beginning
 *                       of the body.
 * @return Result.
 * @throw error On any parse error; e.g., no key.
 **/
parse_headers_result_t parse_headers(span_t& input);

//! Ostream output operator for @ref parse_headers_result_t
std::ostream& operator<<(
    std::ostream&                 o,
    const parse_headers_result_t& R
);

//! Result of parse_request().
struct parse_request_result_t
{
    //! The request line.
    span_t                      raw_request_line;
    //! The request line as parsed by parse_request_line().
    parse_request_line_result_t request_line;
    //! The URI as parsed by parse_ur().
    parse_uri_result_t          uri;
    //! The headers as parsed by parse_headers().
    parse_headers_result_t      headers;
};

/**
 * Parse @a input as request.
 *
 * @sa parse_request_line()
 * @sa parse_uri()
 * @sa parse_headers()
 *
 * @note Currently does not parse body.  Stay tuned.
 *
 * @param[in, out] input Span to parse; will be updated such that beginning
 *                       is just after successful parse, i.e., the beginning
 *                       of the body.
 * @return Result.
 * @throw error On any parse error.
 **/
parse_request_result_t parse_request(span_t& input);

//! Ostream output operator for @ref parse_request_result_t.
std::ostream& operator<<(
    std::ostream&                 o,
    const parse_request_result_t& R
);

//! Result of parse_response().
struct parse_response_result_t
{
    //! The response line.
    span_t                       raw_response_line;
    //! The reponse line as parsed by parse_response_line().
    parse_response_line_result_t response_line;
    //! The headers as parsed by parse_headers().
    parse_headers_result_t       headers;
};

/**
 * Parse @a input as response.
 *
 * @sa parse_response_line()
 * @sa parse_headers()
 *
 * @note Currently does not parse body.  Stay tuned.
 *
 * @param[in, out] input Span to parse; will be updated such that beginning
 *                       is just after successful parse, i.e., the beginning
 *                       of the body.
 * @return Result.
 * @throw error On any parse error.
 **/
parse_response_result_t parse_response(span_t& input);

//! Ostream output operator for @ref parse_response_result_t
std::ostream& operator<<(
    std::ostream&                  o,
    const parse_response_result_t& R
);

} // ParserSuite
} // IronBee

#endif
<|endoftext|>


<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.
 *
 *=========================================================================*/

#include "itkListSample.h"
#include "itkStatisticsAlgorithm.h"
#include "itkTestingMacros.h"

#if ( NDEBUG && (_MSC_FULL_VER == 190024215 || _MSC_FULL_VER == 191025017 ) )
#pragma optimize ("g", off) // disable global optimizations
#endif

int itkStatisticsAlgorithmTest( int, char * [] )
{
  std::cout << "StatisticsAlgorithm Test \n \n";

  const unsigned int measurementVectorSize = 2;

  typedef itk::Array< float > MeasurementVectorType;
  typedef itk::Statistics::ListSample< MeasurementVectorType > SampleType;

  SampleType::Pointer sample = SampleType::New();

  SampleType::MeasurementVectorType lower( measurementVectorSize );
  SampleType::MeasurementVectorType upper( measurementVectorSize );

  const SampleType * constSample = sample.GetPointer();

  // Testing the exception throwing for samples of measurement size = 0
  sample->SetMeasurementVectorSize( 0 );

  TRY_EXPECT_EXCEPTION(
      itk::Statistics::Algorithm::FindSampleBound(
      constSample,
      constSample->Begin(), constSample->End(),
      lower, upper)
  );

  // Now set the correct measurement vector size
  sample->SetMeasurementVectorSize( measurementVectorSize );

  // Testing the equivalent of an empty sample by passing
  // the Begin() iterator inlieu of the End() iterator.

  TRY_EXPECT_EXCEPTION(
      itk::Statistics::Algorithm::FindSampleBound(
          constSample,
          constSample->Begin(), constSample->Begin(),
          lower, upper)
  );

  MeasurementVectorType measure( measurementVectorSize );
  MeasurementVectorType realUpper( measurementVectorSize );
  MeasurementVectorType realLower( measurementVectorSize );

  const unsigned int numberOfSamples = 25;

  realLower.Fill( 1000 );
  realUpper.Fill(    0 );

  // Force the first value not to be the min or max.
  measure[0] = 13;
  measure[1] = 39;
  sample->PushBack( measure );

  for( unsigned int i = 1; i < numberOfSamples; i++ )
    {
    float value = i + 3;
    measure[0] = value;
    measure[1] = value * value;
    sample->PushBack( measure );

    for(unsigned int j = 0; j < measurementVectorSize; j++ )
      {
      if( measure[j] < realLower[j] )
        {
        realLower[j] = measure[j];
        }
      if( measure[j] > realUpper[j] )
        {
        realUpper[j] = measure[j];
        }
      }
    }

  // Now testing the real algorithm
  TRY_EXPECT_NO_EXCEPTION(
      itk::Statistics::Algorithm::FindSampleBound(
          constSample,
          constSample->Begin(), constSample->End(),
          lower, upper)
  );

  const float epsilon = 1e-5;

  for(unsigned int j = 0; j < measurementVectorSize; j++ )
    {
    if( itk::Math::abs( lower[j] - realLower[j] ) > epsilon )
      {
      std::cerr << "FindSampleBound() failed" << std::endl;
      std::cerr << "Expected lower = " << realLower << std::endl;
      std::cerr << "Computed lower = " << lower << std::endl;
      return EXIT_FAILURE;
      }
    if( itk::Math::abs( upper[j] - realUpper[j] ) > epsilon )
      {
      std::cerr << "FindSampleBound() failed" << std::endl;
      std::cerr << "Expected upper = " << realUpper << std::endl;
      std::cerr << "Computed upper = " << upper << std::endl;
      return EXIT_FAILURE;
      }
    }

  std::cout << "Test passed." << std::endl;
  return EXIT_SUCCESS;
}
<commit_msg>DOC: Document that workaround MSVC 2017 optimization bug has been corrected<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.
 *
 *=========================================================================*/

#include "itkListSample.h"
#include "itkStatisticsAlgorithm.h"
#include "itkTestingMacros.h"

// Problem has been solved in _MSC_FULL_VER == 191125508
#if ( NDEBUG && (_MSC_FULL_VER == 190024215 || _MSC_FULL_VER == 191025017 ) )
#pragma optimize ("g", off) // disable global optimizations
#endif

int itkStatisticsAlgorithmTest( int, char * [] )
{
  std::cout << "StatisticsAlgorithm Test \n \n";

  const unsigned int measurementVectorSize = 2;

  typedef itk::Array< float > MeasurementVectorType;
  typedef itk::Statistics::ListSample< MeasurementVectorType > SampleType;

  SampleType::Pointer sample = SampleType::New();

  SampleType::MeasurementVectorType lower( measurementVectorSize );
  SampleType::MeasurementVectorType upper( measurementVectorSize );

  const SampleType * constSample = sample.GetPointer();

  // Testing the exception throwing for samples of measurement size = 0
  sample->SetMeasurementVectorSize( 0 );

  TRY_EXPECT_EXCEPTION(
      itk::Statistics::Algorithm::FindSampleBound(
      constSample,
      constSample->Begin(), constSample->End(),
      lower, upper)
  );

  // Now set the correct measurement vector size
  sample->SetMeasurementVectorSize( measurementVectorSize );

  // Testing the equivalent of an empty sample by passing
  // the Begin() iterator inlieu of the End() iterator.

  TRY_EXPECT_EXCEPTION(
      itk::Statistics::Algorithm::FindSampleBound(
          constSample,
          constSample->Begin(), constSample->Begin(),
          lower, upper)
  );

  MeasurementVectorType measure( measurementVectorSize );
  MeasurementVectorType realUpper( measurementVectorSize );
  MeasurementVectorType realLower( measurementVectorSize );

  const unsigned int numberOfSamples = 25;

  realLower.Fill( 1000 );
  realUpper.Fill(    0 );

  // Force the first value not to be the min or max.
  measure[0] = 13;
  measure[1] = 39;
  sample->PushBack( measure );

  for( unsigned int i = 1; i < numberOfSamples; i++ )
    {
    float value = i + 3;
    measure[0] = value;
    measure[1] = value * value;
    sample->PushBack( measure );

    for(unsigned int j = 0; j < measurementVectorSize; j++ )
      {
      if( measure[j] < realLower[j] )
        {
        realLower[j] = measure[j];
        }
      if( measure[j] > realUpper[j] )
        {
        realUpper[j] = measure[j];
        }
      }
    }

  // Now testing the real algorithm
  TRY_EXPECT_NO_EXCEPTION(
      itk::Statistics::Algorithm::FindSampleBound(
          constSample,
          constSample->Begin(), constSample->End(),
          lower, upper)
  );

  const float epsilon = 1e-5;

  for(unsigned int j = 0; j < measurementVectorSize; j++ )
    {
    if( itk::Math::abs( lower[j] - realLower[j] ) > epsilon )
      {
      std::cerr << "FindSampleBound() failed" << std::endl;
      std::cerr << "Expected lower = " << realLower << std::endl;
      std::cerr << "Computed lower = " << lower << std::endl;
      return EXIT_FAILURE;
      }
    if( itk::Math::abs( upper[j] - realUpper[j] ) > epsilon )
      {
      std::cerr << "FindSampleBound() failed" << std::endl;
      std::cerr << "Expected upper = " << realUpper << std::endl;
      std::cerr << "Computed upper = " << upper << std::endl;
      return EXIT_FAILURE;
      }
    }

  std::cout << "Test passed." << std::endl;
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "routing/async_router.hpp"

#include "platform/platform.hpp"

#include "base/logging.hpp"
#include "base/macros.hpp"
#include "base/string_utils.hpp"
#include "base/timer.hpp"

#include "indexer/mercator.hpp"

#if defined(OMIM_OS_ANDROID)
void AndroidThreadAttachToJVM();
void AndroidThreadDetachFromJVM();
#endif  // defined(OMIM_OS_ANDROID)

namespace routing
{

namespace
{

string ToString(IRouter::ResultCode code)
{
  switch (code)
  {
  case IRouter::NoError: return "NoError";
  case IRouter::Cancelled: return "Cancelled";
  case IRouter::NoCurrentPosition: return "NoCurrentPosition";
  case IRouter::InconsistentMWMandRoute: return "InconsistentMWMandRoute";
  case IRouter::RouteFileNotExist: return "RouteFileNotExist";
  case IRouter::StartPointNotFound: return "StartPointNotFound";
  case IRouter::EndPointNotFound: return "EndPointNotFound";
  case IRouter::PointsInDifferentMWM: return "PointsInDifferentMWM";
  case IRouter::RouteNotFound: return "RouteNotFound";
  case IRouter::InternalError: return "InternalError";
  case IRouter::NeedMoreMaps: return "NeedMoreMaps";
  case IRouter::FileTooOld: return "FileTooOld";
  }
  ASSERT(false, ());
  return "Routing result code case error.";
}

map<string, string> PrepareStatisticsData(string const & routerName,
                                          m2::PointD const & startPoint, m2::PointD const & startDirection,
                                          m2::PointD const & finalPoint)
{
  // Coordinates precision in 5 digits after comma corresponds to metres (0,00001degree ~ 1meter),
  // therefore we round coordinates up to 5 digits after comma.
  int constexpr precision = 5;

  return {{"name", routerName},
          {"startLon", strings::to_string_dac(MercatorBounds::XToLon(startPoint.x), precision)},
          {"startLat", strings::to_string_dac(MercatorBounds::YToLat(startPoint.y), precision)},
          {"startDirectionX", strings::to_string_dac(startDirection.x, precision)},
          {"startDirectionY", strings::to_string_dac(startDirection.y, precision)},
          {"finalLon", strings::to_string_dac(MercatorBounds::XToLon(finalPoint.x), precision)},
          {"finalLat", strings::to_string_dac(MercatorBounds::YToLat(finalPoint.y), precision)}};
}

}  // namespace

// ----------------------------------------------------------------------------------------------------------------------------

AsyncRouter::RouterDelegateProxy::RouterDelegateProxy(TReadyCallback const & onReady,
                                                      RouterDelegate::TPointCheckCallback const & onPointCheck,
                                                      RouterDelegate::TProgressCallback const & onProgress,
                                                      uint32_t timeoutSec)
  : m_onReady(onReady), m_onPointCheck(onPointCheck), m_onProgress(onProgress)
{
  m_delegate.Reset();
  m_delegate.SetPointCheckCallback(bind(&RouterDelegateProxy::OnPointCheck, this, _1));
  m_delegate.SetProgressCallback(bind(&RouterDelegateProxy::OnProgress, this, _1));
  m_delegate.SetTimeout(timeoutSec);
}

void AsyncRouter::RouterDelegateProxy::OnReady(Route & route, IRouter::ResultCode resultCode)
{
  if (!m_onReady)
    return;
  lock_guard<mutex> l(m_guard);
  if (m_delegate.IsCancelled())
    return;
  m_onReady(route, resultCode);
}

void AsyncRouter::RouterDelegateProxy::Cancel()
{
  lock_guard<mutex> l(m_guard);
  m_delegate.Cancel();
}

void AsyncRouter::RouterDelegateProxy::OnProgress(float progress)
{
  if (!m_onProgress)
    return;
  lock_guard<mutex> l(m_guard);
  if (m_delegate.IsCancelled())
    return;
  m_onProgress(progress);
}

void AsyncRouter::RouterDelegateProxy::OnPointCheck(m2::PointD const & pt)
{
  if (!m_onPointCheck)
    return;
  lock_guard<mutex> l(m_guard);
  if (m_delegate.IsCancelled())
    return;
  m_onPointCheck(pt);
}

// ----------------------------------------------------------------------------------------------------------------------------

AsyncRouter::AsyncRouter(TRoutingStatisticsCallback const & routingStatisticsCallback,
                         RouterDelegate::TPointCheckCallback const & pointCheckCallback)
    : m_threadExit(false), m_hasRequest(false), m_clearState(false),
      m_routingStatisticsCallback(routingStatisticsCallback),
      m_pointCheckCallback(pointCheckCallback)
{
  m_thread = thread(bind(&AsyncRouter::ThreadFunc, this));
}

AsyncRouter::~AsyncRouter()
{
  {
    unique_lock<mutex> ul(m_guard);

    ResetDelegate();

    m_threadExit = true;
    m_threadCondVar.notify_one();
  }

  m_thread.join();
}

void AsyncRouter::SetRouter(unique_ptr<IRouter> && router, unique_ptr<IOnlineFetcher> && fetcher)
{
  unique_lock<mutex> ul(m_guard);

  ResetDelegate();

  m_router = move(router);
  m_absentFetcher = move(fetcher);
}

void AsyncRouter::CalculateRoute(m2::PointD const & startPoint, m2::PointD const & direction,
                                 m2::PointD const & finalPoint, TReadyCallback const & readyCallback,
                                 RouterDelegate::TProgressCallback const & progressCallback,
                                 uint32_t timeoutSec)
{
  unique_lock<mutex> ul(m_guard);

  m_startPoint = startPoint;
  m_startDirection = direction;
  m_finalPoint = finalPoint;

  ResetDelegate();

  m_delegate = make_shared<RouterDelegateProxy>(readyCallback, m_pointCheckCallback, progressCallback, timeoutSec);

  m_hasRequest = true;
  m_threadCondVar.notify_one();
}

void AsyncRouter::ClearState()
{
  unique_lock<mutex> ul(m_guard);

  m_clearState = true;

  ResetDelegate();
}

void AsyncRouter::LogCode(IRouter::ResultCode code, double const elapsedSec)
{
  switch (code)
  {
    case IRouter::StartPointNotFound:
      LOG(LWARNING, ("Can't find start or end node"));
      break;
    case IRouter::EndPointNotFound:
      LOG(LWARNING, ("Can't find end point node"));
      break;
    case IRouter::PointsInDifferentMWM:
      LOG(LWARNING, ("Points are in different MWMs"));
      break;
    case IRouter::RouteNotFound:
      LOG(LWARNING, ("Route not found"));
      break;
    case IRouter::RouteFileNotExist:
      LOG(LWARNING, ("There is no routing file"));
      break;
    case IRouter::NeedMoreMaps:
      LOG(LINFO,
          ("Routing can find a better way with additional maps, elapsed seconds:", elapsedSec));
      break;
    case IRouter::Cancelled:
      LOG(LINFO, ("Route calculation cancelled, elapsed seconds:", elapsedSec));
      break;
    case IRouter::NoError:
      LOG(LINFO, ("Route found, elapsed seconds:", elapsedSec));
      break;
    case IRouter::NoCurrentPosition:
      LOG(LINFO, ("No current position"));
      break;
    case IRouter::InconsistentMWMandRoute:
      LOG(LINFO, ("Inconsistent mwm and route"));
      break;
    case IRouter::InternalError:
      LOG(LINFO, ("Internal error"));
      break;
    case IRouter::FileTooOld:
      LOG(LINFO, ("File too old"));
      break;
  }
}

void AsyncRouter::ResetDelegate()
{
  if (m_delegate)
  {
    m_delegate->Cancel();
    m_delegate.reset();
  }
}

void AsyncRouter::ThreadFunc()
{
#if defined(OMIM_OS_ANDROID)
  AndroidThreadAttachToJVM();
#endif  // defined(OMIM_OS_ANDROID)

  while (true)
  {
    {
      unique_lock<mutex> ul(m_guard);
      m_threadCondVar.wait(ul, [this](){ return m_threadExit || m_hasRequest; });

      if (m_threadExit)
        break;
    }

    CalculateRoute();
  }

#if defined(OMIM_OS_ANDROID)
  AndroidThreadDetachFromJVM();
#endif  // defined(OMIM_OS_ANDROID)
}

void AsyncRouter::CalculateRoute()
{
  bool clearState = true;
  shared_ptr<RouterDelegateProxy> delegate;
  m2::PointD startPoint, finalPoint, startDirection;
  shared_ptr<IOnlineFetcher> absentFetcher;
  shared_ptr<IRouter> router;

  {
    unique_lock<mutex> ul(m_guard);

    bool hasRequest = m_hasRequest;
    m_hasRequest = false;
    if (!hasRequest)
      return;
    if (!m_router)
      return;
    if (!m_delegate)
      return;

    startPoint = m_startPoint;
    finalPoint = m_finalPoint;
    startDirection = m_startDirection;
    clearState = m_clearState;
    delegate = m_delegate;
    router = m_router;
    absentFetcher = m_absentFetcher;

    m_clearState = false;
  }

  Route route(router->GetName());
  IRouter::ResultCode code;

  my::Timer timer;
  double elapsedSec = 0.0;

  try
  {
    LOG(LDEBUG, ("Calculating the route from", startPoint, "to", finalPoint, "startDirection", startDirection));

    if (absentFetcher)
      absentFetcher->GenerateRequest(startPoint, finalPoint);

    if (clearState)
      router->ClearState();

    // Run basic request.
    code = router->CalculateRoute(startPoint, startDirection, finalPoint, delegate->GetDelegate(), route);

    elapsedSec = timer.ElapsedSeconds(); // routing time
    LogCode(code, elapsedSec);
  }
  catch (RootException const & e)
  {
    code = IRouter::InternalError;
    LOG(LERROR, ("Exception happened while calculating route:", e.Msg()));
    SendStatistics(startPoint, startDirection, finalPoint, e.Msg());
    delegate->OnReady(route, code);
    return;
  }

  SendStatistics(startPoint, startDirection, finalPoint, code, route, elapsedSec);

  // Draw route without waiting network latency.
  if (code == IRouter::NoError)
    delegate->OnReady(route, code);

  bool const needFetchAbsent = (code != IRouter::Cancelled);

  // Check online response if we have.
  vector<string> absent;
  if (absentFetcher && needFetchAbsent)
  {
    absentFetcher->GetAbsentCountries(absent);
    for (string const & country : absent)
      route.AddAbsentCountry(country);
  }

  if (!absent.empty() && code == IRouter::NoError)
    code = IRouter::NeedMoreMaps;

  elapsedSec = timer.ElapsedSeconds(); // routing time + absents fetch time
  LogCode(code, elapsedSec);

  // Call callback only if we have some new data.
  if (code != IRouter::NoError)
    delegate->OnReady(route, code);
}

void AsyncRouter::SendStatistics(m2::PointD const & startPoint, m2::PointD const & startDirection,
                                 m2::PointD const & finalPoint,
                                 IRouter::ResultCode resultCode,
                                 Route const & route,
                                 double elapsedSec)
{
  if (nullptr == m_routingStatisticsCallback)
    return;

  map<string, string> statistics = PrepareStatisticsData(m_router->GetName(), startPoint, startDirection, finalPoint);
  statistics.emplace("result", ToString(resultCode));
  statistics.emplace("elapsed", strings::to_string(elapsedSec));

  if (IRouter::NoError == resultCode)
    statistics.emplace("distance", strings::to_string(route.GetTotalDistanceMeters()));

  m_routingStatisticsCallback(statistics);
}

void AsyncRouter::SendStatistics(m2::PointD const & startPoint, m2::PointD const & startDirection,
                                 m2::PointD const & finalPoint,
                                 string const & exceptionMessage)
{
  if (nullptr == m_routingStatisticsCallback)
    return;

  map<string, string> statistics = PrepareStatisticsData(m_router->GetName(), startPoint, startDirection, finalPoint);
  statistics.emplace("exception", exceptionMessage);

  m_routingStatisticsCallback(statistics);
}

}  // namespace routing
<commit_msg>Fixed notes<commit_after>#include "routing/async_router.hpp"

#include "platform/platform.hpp"

#include "base/logging.hpp"
#include "base/macros.hpp"
#include "base/string_utils.hpp"
#include "base/timer.hpp"

#include "indexer/mercator.hpp"

#if defined(OMIM_OS_ANDROID)
void AndroidThreadAttachToJVM();
void AndroidThreadDetachFromJVM();
#endif  // defined(OMIM_OS_ANDROID)

namespace routing
{

namespace
{

string ToString(IRouter::ResultCode code)
{
  switch (code)
  {
  case IRouter::NoError: return "NoError";
  case IRouter::Cancelled: return "Cancelled";
  case IRouter::NoCurrentPosition: return "NoCurrentPosition";
  case IRouter::InconsistentMWMandRoute: return "InconsistentMWMandRoute";
  case IRouter::RouteFileNotExist: return "RouteFileNotExist";
  case IRouter::StartPointNotFound: return "StartPointNotFound";
  case IRouter::EndPointNotFound: return "EndPointNotFound";
  case IRouter::PointsInDifferentMWM: return "PointsInDifferentMWM";
  case IRouter::RouteNotFound: return "RouteNotFound";
  case IRouter::InternalError: return "InternalError";
  case IRouter::NeedMoreMaps: return "NeedMoreMaps";
  case IRouter::FileTooOld: return "FileTooOld";
  }
  ASSERT(false, ());
  return "Routing result code case error.";
}

map<string, string> PrepareStatisticsData(string const & routerName,
                                          m2::PointD const & startPoint, m2::PointD const & startDirection,
                                          m2::PointD const & finalPoint)
{
  // Coordinates precision in 5 digits after comma corresponds to metres (0,00001degree ~ 1meter),
  // therefore we round coordinates up to 5 digits after comma.
  int constexpr precision = 5;

  return {{"name", routerName},
          {"startLon", strings::to_string_dac(MercatorBounds::XToLon(startPoint.x), precision)},
          {"startLat", strings::to_string_dac(MercatorBounds::YToLat(startPoint.y), precision)},
          {"startDirectionX", strings::to_string_dac(startDirection.x, precision)},
          {"startDirectionY", strings::to_string_dac(startDirection.y, precision)},
          {"finalLon", strings::to_string_dac(MercatorBounds::XToLon(finalPoint.x), precision)},
          {"finalLat", strings::to_string_dac(MercatorBounds::YToLat(finalPoint.y), precision)}};
}

}  // namespace

// ----------------------------------------------------------------------------------------------------------------------------

AsyncRouter::RouterDelegateProxy::RouterDelegateProxy(TReadyCallback const & onReady,
                                                      RouterDelegate::TPointCheckCallback const & onPointCheck,
                                                      RouterDelegate::TProgressCallback const & onProgress,
                                                      uint32_t timeoutSec)
  : m_onReady(onReady), m_onPointCheck(onPointCheck), m_onProgress(onProgress)
{
  m_delegate.Reset();
  m_delegate.SetPointCheckCallback(bind(&RouterDelegateProxy::OnPointCheck, this, _1));
  m_delegate.SetProgressCallback(bind(&RouterDelegateProxy::OnProgress, this, _1));
  m_delegate.SetTimeout(timeoutSec);
}

void AsyncRouter::RouterDelegateProxy::OnReady(Route & route, IRouter::ResultCode resultCode)
{
  if (!m_onReady)
    return;
  {
    lock_guard<mutex> l(m_guard);
    if (m_delegate.IsCancelled())
      return;
  }
  m_onReady(route, resultCode);
}

void AsyncRouter::RouterDelegateProxy::Cancel()
{
  lock_guard<mutex> l(m_guard);
  m_delegate.Cancel();
}

void AsyncRouter::RouterDelegateProxy::OnProgress(float progress)
{
  if (!m_onProgress)
    return;
  {
    lock_guard<mutex> l(m_guard);
    if (m_delegate.IsCancelled())
      return;
  }
  m_onProgress(progress);
}

void AsyncRouter::RouterDelegateProxy::OnPointCheck(m2::PointD const & pt)
{
  if (!m_onPointCheck)
    return;
  {
    lock_guard<mutex> l(m_guard);
    if (m_delegate.IsCancelled())
      return;
  }
  m_onPointCheck(pt);
}

// ----------------------------------------------------------------------------------------------------------------------------

AsyncRouter::AsyncRouter(TRoutingStatisticsCallback const & routingStatisticsCallback,
                         RouterDelegate::TPointCheckCallback const & pointCheckCallback)
    : m_threadExit(false), m_hasRequest(false), m_clearState(false),
      m_routingStatisticsCallback(routingStatisticsCallback),
      m_pointCheckCallback(pointCheckCallback)
{
  m_thread = thread(bind(&AsyncRouter::ThreadFunc, this));
}

AsyncRouter::~AsyncRouter()
{
  {
    unique_lock<mutex> ul(m_guard);

    ResetDelegate();

    m_threadExit = true;
    m_threadCondVar.notify_one();
  }

  m_thread.join();
}

void AsyncRouter::SetRouter(unique_ptr<IRouter> && router, unique_ptr<IOnlineFetcher> && fetcher)
{
  unique_lock<mutex> ul(m_guard);

  ResetDelegate();

  m_router = move(router);
  m_absentFetcher = move(fetcher);
}

void AsyncRouter::CalculateRoute(m2::PointD const & startPoint, m2::PointD const & direction,
                                 m2::PointD const & finalPoint, TReadyCallback const & readyCallback,
                                 RouterDelegate::TProgressCallback const & progressCallback,
                                 uint32_t timeoutSec)
{
  unique_lock<mutex> ul(m_guard);

  m_startPoint = startPoint;
  m_startDirection = direction;
  m_finalPoint = finalPoint;

  ResetDelegate();

  m_delegate = make_shared<RouterDelegateProxy>(readyCallback, m_pointCheckCallback, progressCallback, timeoutSec);

  m_hasRequest = true;
  m_threadCondVar.notify_one();
}

void AsyncRouter::ClearState()
{
  unique_lock<mutex> ul(m_guard);

  m_clearState = true;

  ResetDelegate();
}

void AsyncRouter::LogCode(IRouter::ResultCode code, double const elapsedSec)
{
  switch (code)
  {
    case IRouter::StartPointNotFound:
      LOG(LWARNING, ("Can't find start or end node"));
      break;
    case IRouter::EndPointNotFound:
      LOG(LWARNING, ("Can't find end point node"));
      break;
    case IRouter::PointsInDifferentMWM:
      LOG(LWARNING, ("Points are in different MWMs"));
      break;
    case IRouter::RouteNotFound:
      LOG(LWARNING, ("Route not found"));
      break;
    case IRouter::RouteFileNotExist:
      LOG(LWARNING, ("There is no routing file"));
      break;
    case IRouter::NeedMoreMaps:
      LOG(LINFO,
          ("Routing can find a better way with additional maps, elapsed seconds:", elapsedSec));
      break;
    case IRouter::Cancelled:
      LOG(LINFO, ("Route calculation cancelled, elapsed seconds:", elapsedSec));
      break;
    case IRouter::NoError:
      LOG(LINFO, ("Route found, elapsed seconds:", elapsedSec));
      break;
    case IRouter::NoCurrentPosition:
      LOG(LINFO, ("No current position"));
      break;
    case IRouter::InconsistentMWMandRoute:
      LOG(LINFO, ("Inconsistent mwm and route"));
      break;
    case IRouter::InternalError:
      LOG(LINFO, ("Internal error"));
      break;
    case IRouter::FileTooOld:
      LOG(LINFO, ("File too old"));
      break;
  }
}

void AsyncRouter::ResetDelegate()
{
  if (m_delegate)
  {
    m_delegate->Cancel();
    m_delegate.reset();
  }
}

void AsyncRouter::ThreadFunc()
{
#if defined(OMIM_OS_ANDROID)
  AndroidThreadAttachToJVM();
#endif  // defined(OMIM_OS_ANDROID)

  while (true)
  {
    {
      unique_lock<mutex> ul(m_guard);
      m_threadCondVar.wait(ul, [this](){ return m_threadExit || m_hasRequest; });

      if (m_threadExit)
        break;
    }

    CalculateRoute();
  }

#if defined(OMIM_OS_ANDROID)
  AndroidThreadDetachFromJVM();
#endif  // defined(OMIM_OS_ANDROID)
}

void AsyncRouter::CalculateRoute()
{
  bool clearState = true;
  shared_ptr<RouterDelegateProxy> delegate;
  m2::PointD startPoint, finalPoint, startDirection;
  shared_ptr<IOnlineFetcher> absentFetcher;
  shared_ptr<IRouter> router;

  {
    unique_lock<mutex> ul(m_guard);

    bool hasRequest = m_hasRequest;
    m_hasRequest = false;
    if (!hasRequest)
      return;
    if (!m_router)
      return;
    if (!m_delegate)
      return;

    startPoint = m_startPoint;
    finalPoint = m_finalPoint;
    startDirection = m_startDirection;
    clearState = m_clearState;
    delegate = m_delegate;
    router = m_router;
    absentFetcher = m_absentFetcher;

    m_clearState = false;
  }

  Route route(router->GetName());
  IRouter::ResultCode code;

  my::Timer timer;
  double elapsedSec = 0.0;

  try
  {
    LOG(LDEBUG, ("Calculating the route from", startPoint, "to", finalPoint, "startDirection", startDirection));

    if (absentFetcher)
      absentFetcher->GenerateRequest(startPoint, finalPoint);

    if (clearState)
      router->ClearState();

    // Run basic request.
    code = router->CalculateRoute(startPoint, startDirection, finalPoint, delegate->GetDelegate(), route);

    elapsedSec = timer.ElapsedSeconds(); // routing time
    LogCode(code, elapsedSec);
  }
  catch (RootException const & e)
  {
    code = IRouter::InternalError;
    LOG(LERROR, ("Exception happened while calculating route:", e.Msg()));
    SendStatistics(startPoint, startDirection, finalPoint, e.Msg());
    delegate->OnReady(route, code);
    return;
  }

  SendStatistics(startPoint, startDirection, finalPoint, code, route, elapsedSec);

  // Draw route without waiting network latency.
  if (code == IRouter::NoError)
    delegate->OnReady(route, code);

  bool const needFetchAbsent = (code != IRouter::Cancelled);

  // Check online response if we have.
  vector<string> absent;
  if (absentFetcher && needFetchAbsent)
  {
    absentFetcher->GetAbsentCountries(absent);
    for (string const & country : absent)
      route.AddAbsentCountry(country);
  }

  if (!absent.empty() && code == IRouter::NoError)
    code = IRouter::NeedMoreMaps;

  elapsedSec = timer.ElapsedSeconds(); // routing time + absents fetch time
  LogCode(code, elapsedSec);

  // Call callback only if we have some new data.
  if (code != IRouter::NoError)
    delegate->OnReady(route, code);
}

void AsyncRouter::SendStatistics(m2::PointD const & startPoint, m2::PointD const & startDirection,
                                 m2::PointD const & finalPoint,
                                 IRouter::ResultCode resultCode,
                                 Route const & route,
                                 double elapsedSec)
{
  if (nullptr == m_routingStatisticsCallback)
    return;

  map<string, string> statistics = PrepareStatisticsData(m_router->GetName(), startPoint, startDirection, finalPoint);
  statistics.emplace("result", ToString(resultCode));
  statistics.emplace("elapsed", strings::to_string(elapsedSec));

  if (IRouter::NoError == resultCode)
    statistics.emplace("distance", strings::to_string(route.GetTotalDistanceMeters()));

  m_routingStatisticsCallback(statistics);
}

void AsyncRouter::SendStatistics(m2::PointD const & startPoint, m2::PointD const & startDirection,
                                 m2::PointD const & finalPoint,
                                 string const & exceptionMessage)
{
  if (nullptr == m_routingStatisticsCallback)
    return;

  map<string, string> statistics = PrepareStatisticsData(m_router->GetName(), startPoint, startDirection, finalPoint);
  statistics.emplace("exception", exceptionMessage);

  m_routingStatisticsCallback(statistics);
}

}  // namespace routing
<|endoftext|>


<commit_before>
#pragma once

#include <tuple>
#include <type_traits>
#include <utility>

#include <proxc/config.hpp>

PROXC_NAMESPACE_BEGIN

namespace traits {

namespace detail {

template<typename T>
using always_void = void;

template<typename Expr, typename Enable = void>
struct is_callable_impl
    : std::false_type
{};

template<typename Fn, typename ... Args>
struct is_callable_impl< Fn(Args ...), always_void< std::result_of_t< Fn(Args ...) > > >
    : std::true_type
{};

} // namespace detail

template<typename Expr>
struct is_callable
    : detail::is_callable_impl< Expr >
{};

template<typename T>
typename std::decay< T >::type
decay_copy(T && t)
{
    return std::forward< T >(t);
}

} // namespace traits

PROXC_NAMESPACE_END

<commit_msg>Added more traits, mostly for implementation of parallel and processes.<commit_after>
#pragma once

#include <tuple>
#include <type_traits>
#include <utility>

#include <proxc/config.hpp>

PROXC_NAMESPACE_BEGIN

namespace traits {

namespace detail {

template<typename T>
using always_void = void;

template<typename Expr, typename Enable = void>
struct is_callable_impl
    : std::false_type
{};

template<typename Fn, typename ... Args>
struct is_callable_impl< Fn(Args ...), always_void< std::result_of_t< Fn(Args ...) > > >
    : std::true_type
{};

} // namespace detail

template<typename Expr>
struct is_callable
    : detail::is_callable_impl< Expr >
{};

template<typename Arg, typename ...>
struct are_callable_with_arg
    : std::true_type
{};

template<typename Arg, typename Fn, typename ... Fns>
struct are_callable_with_arg< Arg, Fn, Fns ... >
    : std::integral_constant< bool,
           is_callable< Fn(Arg) >{}
        && are_callable_with_arg< Arg, Fns ... >{}
    >
{};

template<typename ...>
struct are_move_assigneable
    : std::true_type
{};

template<typename Proc, typename ... Procs>
struct are_move_assigneable< Proc, Procs ... >
    : std::integral_constant< bool,
           std::is_move_assignable< Proc >::value
        && are_move_assigneable< Procs ... >{}
    >
{};

template<typename It, typename = void>
struct is_inputiterator
    : std::false_type
{};

template<typename It>
struct is_inputiterator< It, decltype( *std::declval< It & >(), ++std::declval< It & >(), void() )>
    : std::true_type
{};

template<typename T>
typename std::decay< T >::type
decay_copy(T && t)
{
    return std::forward< T >(t);
}

} // namespace traits

PROXC_NAMESPACE_END

<|endoftext|>


<commit_before>/**
 * @file FieldInfo.cpp
 *
 * Implemention of class FieldInfo
 *
 * @author Xu, Yuan
 */

#include "FieldInfo.h"

FieldInfo::FieldInfo() : ParameterList("FieldInfo")
{
  ballColor = ColorClasses::orange;

  // default values as of SPL rules from 2012
  PARAMETER_REGISTER(ballRadius) = 32.5;

  PARAMETER_REGISTER(xLength) = 6000;
  PARAMETER_REGISTER(yLength) = 4000;

  PARAMETER_REGISTER(xFieldLength) = xLength + 2*700;
  PARAMETER_REGISTER(yFieldLength) = yLength + 2*700;

  PARAMETER_REGISTER(xPenaltyAreaLength) = 600;
  PARAMETER_REGISTER(yPenaltyAreaLength) = 2200;

  PARAMETER_REGISTER(centerCircleRadius) = 600;
  PARAMETER_REGISTER(fieldLinesWidth) = 50;

  PARAMETER_REGISTER(goalWidth) = 1400;
  PARAMETER_REGISTER(goalHeight) = 800;
  PARAMETER_REGISTER(goalpostRadius) = 50;
  PARAMETER_REGISTER(xPenaltyMarkDistance) = 1300;
  syncWithConfig();

  calculateValues();

  // calculate the field lines
  fieldLinesTable.create_closestPoinsTable(xFieldLength,yFieldLength);
  fieldLinesTable.create_closestCornerPoinsTable(xFieldLength,yFieldLength);
}

void FieldInfo::calculateValues()
{
  calculateCrossings();
  createLinesTable();
}//end calculateValues

void FieldInfo::calculateCrossings()
{
  xPosHalfWayLine = 0;

  xPosOpponentGroundline =   xLength / 2.0;
  xPosOwnGroundline =       -xPosOpponentGroundline;

  xPosOpponentGoal =         xPosOpponentGroundline;
  xPosOwnGoal =             -xPosOpponentGoal;

  xPosOpponentPenaltyArea =  xPosOpponentGroundline - xPenaltyAreaLength;
  xPosOwnPenaltyArea =      -xPosOpponentPenaltyArea;

  yPosLeftGoalpost =         goalWidth / 2.0;
  yPosRightGoalpost =       -yPosLeftGoalpost;

  yPosLeftPenaltyArea =      yPenaltyAreaLength / 2.0;
  yPosRightPenaltyArea =    -yPosLeftPenaltyArea;

  yPosLeftSideline =         yLength / 2.0;
  yPosRightSideline =       -yPosLeftSideline;

  carpetRect = Geometry::Rect2d(Vector2d(-xFieldLength*0.5, -yFieldLength*0.5), Vector2d(xFieldLength*0.5, yFieldLength*0.5));
  ownHalfRect = Geometry::Rect2d(Vector2d(-xLength*0.5, -yLength*0.5), Vector2d(0, yLength*0.5));
  fieldRect = Geometry::Rect2d(Vector2d(-xLength*0.5, -yLength*0.5), Vector2d(xLength*0.5, yLength*0.5));
  oppHalfRect = Geometry::Rect2d(Vector2d(0, -yLength*0.5), Vector2d(xLength*0.5, yLength*0.5));

  //Extra stuff for the Simulator
  xThrowInLineOwn = xPosOwnGroundline+1000;
  xThrowInLineOpp = -xThrowInLineOwn;

  yThrowInLineLeft = yPosLeftSideline-400;
  yThrowInLineRight = -yThrowInLineLeft;
  //Calculate Points
  leftThrowInPointOwn = Vector2d(xThrowInLineOwn,yThrowInLineLeft);
  leftThrowInPointOpp = Vector2d(xThrowInLineOpp,yThrowInLineLeft);

  rightThrowInPointOwn = Vector2d(xThrowInLineOwn,yThrowInLineRight);
  rightThrowInPointOpp = Vector2d(xThrowInLineOpp,yThrowInLineRight);

  // L crossings
  crossings[opponentCornerLeft].position          = Vector2d(xPosOpponentGroundline, yPosLeftSideline);
  crossings[opponentCornerRight].position         = Vector2d(xPosOpponentGroundline, yPosRightSideline);
  crossings[ownCornerLeft].position               = Vector2d(xPosOwnGroundline, yPosLeftSideline);
  crossings[ownCornerRight].position              = Vector2d(xPosOwnGroundline, yPosRightSideline);

  crossings[opponentPenaltyCornerLeft].position   = Vector2d(xPosOpponentPenaltyArea, yPosLeftPenaltyArea);
  crossings[opponentPenaltyCornerRight].position  = Vector2d(xPosOpponentPenaltyArea, yPosRightPenaltyArea);
  crossings[ownPenaltyCornerLeft].position        = Vector2d(xPosOwnPenaltyArea, yPosLeftPenaltyArea);
  crossings[ownPenaltyCornerRight].position       = Vector2d(xPosOwnPenaltyArea, yPosRightPenaltyArea);

  // T crossings
  crossings[opponentGoalTCrossingLeft].position   = Vector2d(xPosOpponentGroundline, yPosLeftPenaltyArea);
  crossings[opponentGoalTCrossingRight].position  = Vector2d(xPosOpponentGroundline, yPosRightPenaltyArea);
  crossings[ownGoalTCrossingLeft].position        = Vector2d(xPosOwnGroundline, yPosLeftPenaltyArea);
  crossings[ownGoalTCrossingRight].position       = Vector2d(xPosOwnGroundline, yPosRightPenaltyArea);
  crossings[centerTCrossingLeft].position         = Vector2d(xPosHalfWayLine, yPosLeftSideline);
  crossings[centerTCrossingRight].position        = Vector2d(xPosHalfWayLine, yPosRightSideline);

  // X Crossings
  crossings[crossingCenterCircleLeft].position    = Vector2d(xPosHalfWayLine, -centerCircleRadius);
  crossings[crossingCenterCircleRight].position   = Vector2d(xPosHalfWayLine, centerCircleRadius);

  // goal post positions
  opponentGoalPostLeft  = Vector2d(xPosOpponentGoal+25, yPosLeftGoalpost);
  opponentGoalPostRight = Vector2d(xPosOpponentGoal+25, yPosRightGoalpost);
  opponentGoalCenter    = Vector2d(xPosOpponentGoal+25, 0.0);

  ownGoalPostLeft   = Vector2d(xPosOwnGoal-25, yPosLeftGoalpost);
  ownGoalPostRight  = Vector2d(xPosOwnGoal-25, yPosRightGoalpost);
  ownGoalCenter     = Vector2d(xPosOwnGoal-25, 0.0);

  ////Should be done differently
  // 0 - right side line - sideLineRight
  rightLineSegment = Math::LineSegment(
    crossings[ownCornerRight].position,
    crossings[opponentCornerRight].position
    );

  // 1 - left side line - sideLineLeft
  leftLineSegment = Math::LineSegment(
    crossings[ownCornerLeft].position,
    crossings[opponentCornerLeft].position
    );

  // 2 - own goal line - ownGoalLine
  ownLineSegment = Math::LineSegment(
    crossings[ownCornerRight].position,
    crossings[ownCornerLeft].position
    );

  // 3 - opponent goal line - opponentGoalLine
  oppLineSegment = Math::LineSegment(
    crossings[opponentCornerRight].position,
    crossings[opponentCornerLeft].position
    );
  ////
  //Extra Stuff end
}//end calculateCrossings

/**

    |---------------|---------------|
    |               |               |
    |---|          _|_          |---|
    |   |        /  |  \        |   |
    |   |   +   (   |   )   +   |   |
    |   |        \ _|_ /        |   |
    |---|           |           |---|
    |               |               |
    |---------------|---------------|

*/

void FieldInfo::createLinesTable()
{
  fieldLinesTable = LinesTable();
  // HACK: remove it
  fieldLinesTable.circle_radius = centerCircleRadius;
  fieldLinesTable.penalty_area_width = xPosOpponentGoal - xPosOpponentPenaltyArea;

  // 0 - right side line - sideLineRight
  fieldLinesTable.addLine(
    crossings[ownCornerRight].position,
    crossings[opponentCornerRight].position
    );

  // 1 - left side line - sideLineLeft
  fieldLinesTable.addLine(
    crossings[ownCornerLeft].position,
    crossings[opponentCornerLeft].position
    );

  // 2 - own goal line - ownGoalLine
  fieldLinesTable.addLine(
    crossings[ownCornerRight].position,
    crossings[ownCornerLeft].position
    );

  // 3 - opponent goal line - opponentGoalLine
  fieldLinesTable.addLine(
    crossings[opponentCornerRight].position,
    crossings[opponentCornerLeft].position
    );

  // 4 - center line - centerLine
  fieldLinesTable.addLine(
    crossings[centerTCrossingRight].position,
    crossings[centerTCrossingLeft].position
    );

  // 5 - own penalty line - ownPenaltyLine
  fieldLinesTable.addLine(
    crossings[ownPenaltyCornerRight].position,
    crossings[ownPenaltyCornerLeft].position
    );

  // 6 - own penalty right line - ownPenaltyLineRight
  fieldLinesTable.addLine(
    crossings[ownGoalTCrossingRight].position,
    crossings[ownPenaltyCornerRight].position
    );

  // 7 - own penalty left line - ownPenaltyLineLeft
  fieldLinesTable.addLine(
    crossings[ownGoalTCrossingLeft].position,
    crossings[ownPenaltyCornerLeft].position
    );

  // 8 - opponent penalty line - opponentPenaltyLine
  fieldLinesTable.addLine(
    crossings[opponentPenaltyCornerRight].position,
    crossings[opponentPenaltyCornerLeft].position
    );

  // 9 - opponent penalty right line - opponentPenaltyLineRight
  fieldLinesTable.addLine(
    crossings[opponentPenaltyCornerRight].position,
    crossings[opponentGoalTCrossingRight].position
    );

  // 10 - opponent penalty left line - opponentPenaltyLineLeft
  fieldLinesTable.addLine(
    crossings[opponentPenaltyCornerLeft].position,
    crossings[opponentGoalTCrossingLeft].position
    );

  // white goal box is recognized as lines (opp goal)
  //lengthen line 2.5cm to the left to connect it with other line

  /*
  // HACK: RC14 white goal box is recognized as lines (opp goal)
>>>>>>> develop
  fieldLinesTable.addLine(
    Vector2d(opponentGoalPostLeft.x-25,opponentGoalPostLeft.y),
    Vector2d(opponentGoalPostLeft.x + 500, opponentGoalPostLeft.y)
    );
  fieldLinesTable.addLine(
    Vector2d(opponentGoalPostRight.x-25,opponentGoalPostRight.y),
    Vector2d(opponentGoalPostRight.x + 500, opponentGoalPostRight.y)
    );
  fieldLinesTable.addLine(
    Vector2d(opponentGoalPostLeft.x + 500, opponentGoalPostLeft.y),
    Vector2d(opponentGoalPostRight.x + 500, opponentGoalPostRight.y)
    );

<<<<<<>>>>>> develop
  fieldLinesTable.addLine(
    Vector2d(ownGoalPostLeft.x+25,ownGoalPostLeft.y),
    Vector2d(ownGoalPostLeft.x - 500, ownGoalPostLeft.y)
    );
  fieldLinesTable.addLine(
    Vector2d(ownGoalPostRight.x+25,ownGoalPostRight.y),
    Vector2d(ownGoalPostRight.x - 500, ownGoalPostRight.y)
    );
  fieldLinesTable.addLine(
    Vector2d(ownGoalPostLeft.x - 500, ownGoalPostLeft.y),
    Vector2d(ownGoalPostRight.x - 500, ownGoalPostRight.y)
    );
    */

  // center circle approximated by sequence of lines
  double numberOfSegments = 12;
  double angleStep = Math::pi2 / numberOfSegments;

  // the radius is choosen in a way the centers of line segments are exactly on the circle
  Vector2d x0(centerCircleRadius / cos(angleStep*0.5), 0.0);
  x0.rotate(-angleStep * 0.5); // the middle line should be intersected by only one circle line
  Vector2d x1(x0);

  for (int i = 0; i < numberOfSegments; i++)
  {
    x0.rotate(angleStep);
    fieldLinesTable.addLine(x0, x1);
    x1 = x0;
  }//end for

  fieldLinesTable.findIntersections();
}//end createLinesTable

void FieldInfo::draw(DrawingCanvas2D& canvas) const
{
  fieldLinesTable.draw(canvas);

  // draw throw in lines
  canvas.pen("000000", 1);
  canvas.drawLine(leftThrowInPointOwn.x,leftThrowInPointOwn.y,leftThrowInPointOpp.x,leftThrowInPointOpp.y);
  canvas.drawLine(rightThrowInPointOwn.x,rightThrowInPointOwn.y,rightThrowInPointOpp.x,rightThrowInPointOpp.y);

  // draw goal posts
  canvas.pen("0000FF", 20);

  // Opponent Goal
  canvas.drawCircle(
             opponentGoalPostLeft.x,
             opponentGoalPostLeft.y,
             goalpostRadius - 10);
  canvas.drawCircle(
             opponentGoalPostRight.x,
             opponentGoalPostRight.y,
             goalpostRadius - 10);

  // Own Goal
  canvas.drawCircle(
             ownGoalPostLeft.x,
             ownGoalPostLeft.y,
             goalpostRadius - 10);
  canvas.drawCircle(
             ownGoalPostRight.x,
             ownGoalPostRight.y,
             goalpostRadius - 10);
}

void FieldInfo::print(std::ostream& stream) const
{
  stream << "ballColor = "<< ColorClasses::getColorName( ballColor )<<"\n";

  stream << "//////////////// basic values from configuration ////////////////\n";
  stream << "ballRadius = "<< ballRadius <<"\n";

  stream << "size of the whole field (including the green area outside the lines): \n";
  stream << "xFieldLength = "<< xFieldLength <<"\n";
  stream << "yFieldLength = "<< yFieldLength <<"\n";

  stream << "size of the field lines:\n";
  stream << "xLength = "<< xLength <<"\n";
  stream << "yLength = "<< yLength <<"\n";

  stream << "xPosOpponentPenaltyArea = "<< xPosOpponentPenaltyArea <<"\n";
  stream << "yPosLeftPenaltyArea = "<< yPosLeftPenaltyArea <<"\n";

  stream << "centerCircleRadius = "<< centerCircleRadius <<"\n";
  stream << "fieldLinesWidth = "<< fieldLinesWidth <<"\n";
  stream << "goalWidth = "<< goalWidth <<"\n";
  stream << "goalHeight = "<< goalHeight <<"\n";
  stream << "goalpostRadius = "<< goalpostRadius <<"\n";

  stream << "/////////////// pre-calculated values from basic values //////////////\n";
  stream << "xPosHalfWayLine = "<< xPosHalfWayLine <<"\n";

  stream << "xPosOwnGoal = "<< xPosOwnGoal <<"\n";
  stream << "xPosOpponentGoal = "<< xPosOpponentGoal <<"\n";
  stream << "xPosOwnGroundline = "<< xPosOwnGroundline <<"\n";
  stream << "xPosOpponentGroundline = "<< xPosOpponentGroundline <<"\n";
  stream << "xPosOwnPenaltyArea = "<< xPosOwnPenaltyArea <<"\n";

  stream << "yPosLeftSideline = "<< yPosLeftSideline <<"\n";
  stream << "yPosRightSideline = "<< yPosRightSideline <<"\n";
  stream << "yPosRightPenaltyArea = "<< yPosRightPenaltyArea <<"\n";

  stream << "yPosRightGoalpost = "<< yPosRightGoalpost <<"\n";
  stream << "yPosLeftGoalpost = "<< yPosLeftGoalpost <<"\n";
}
<commit_msg>cleaned a conflict resolution<commit_after>/**
 * @file FieldInfo.cpp
 *
 * Implemention of class FieldInfo
 *
 * @author Xu, Yuan
 */

#include "FieldInfo.h"

FieldInfo::FieldInfo() : ParameterList("FieldInfo")
{
  ballColor = ColorClasses::orange;

  // default values as of SPL rules from 2012
  PARAMETER_REGISTER(ballRadius) = 32.5;

  PARAMETER_REGISTER(xLength) = 6000;
  PARAMETER_REGISTER(yLength) = 4000;

  PARAMETER_REGISTER(xFieldLength) = xLength + 2*700;
  PARAMETER_REGISTER(yFieldLength) = yLength + 2*700;

  PARAMETER_REGISTER(xPenaltyAreaLength) = 600;
  PARAMETER_REGISTER(yPenaltyAreaLength) = 2200;

  PARAMETER_REGISTER(centerCircleRadius) = 600;
  PARAMETER_REGISTER(fieldLinesWidth) = 50;

  PARAMETER_REGISTER(goalWidth) = 1400;
  PARAMETER_REGISTER(goalHeight) = 800;
  PARAMETER_REGISTER(goalpostRadius) = 50;
  PARAMETER_REGISTER(xPenaltyMarkDistance) = 1300;
  syncWithConfig();

  calculateValues();

  // calculate the field lines
  fieldLinesTable.create_closestPoinsTable(xFieldLength,yFieldLength);
  fieldLinesTable.create_closestCornerPoinsTable(xFieldLength,yFieldLength);
}

void FieldInfo::calculateValues()
{
  calculateCrossings();
  createLinesTable();
}//end calculateValues

void FieldInfo::calculateCrossings()
{
  xPosHalfWayLine = 0;

  xPosOpponentGroundline =   xLength / 2.0;
  xPosOwnGroundline =       -xPosOpponentGroundline;

  xPosOpponentGoal =         xPosOpponentGroundline;
  xPosOwnGoal =             -xPosOpponentGoal;

  xPosOpponentPenaltyArea =  xPosOpponentGroundline - xPenaltyAreaLength;
  xPosOwnPenaltyArea =      -xPosOpponentPenaltyArea;

  yPosLeftGoalpost =         goalWidth / 2.0;
  yPosRightGoalpost =       -yPosLeftGoalpost;

  yPosLeftPenaltyArea =      yPenaltyAreaLength / 2.0;
  yPosRightPenaltyArea =    -yPosLeftPenaltyArea;

  yPosLeftSideline =         yLength / 2.0;
  yPosRightSideline =       -yPosLeftSideline;

  carpetRect = Geometry::Rect2d(Vector2d(-xFieldLength*0.5, -yFieldLength*0.5), Vector2d(xFieldLength*0.5, yFieldLength*0.5));
  ownHalfRect = Geometry::Rect2d(Vector2d(-xLength*0.5, -yLength*0.5), Vector2d(0, yLength*0.5));
  fieldRect = Geometry::Rect2d(Vector2d(-xLength*0.5, -yLength*0.5), Vector2d(xLength*0.5, yLength*0.5));
  oppHalfRect = Geometry::Rect2d(Vector2d(0, -yLength*0.5), Vector2d(xLength*0.5, yLength*0.5));

  //Extra stuff for the Simulator
  xThrowInLineOwn = xPosOwnGroundline+1000;
  xThrowInLineOpp = -xThrowInLineOwn;

  yThrowInLineLeft = yPosLeftSideline-400;
  yThrowInLineRight = -yThrowInLineLeft;
  //Calculate Points
  leftThrowInPointOwn = Vector2d(xThrowInLineOwn,yThrowInLineLeft);
  leftThrowInPointOpp = Vector2d(xThrowInLineOpp,yThrowInLineLeft);

  rightThrowInPointOwn = Vector2d(xThrowInLineOwn,yThrowInLineRight);
  rightThrowInPointOpp = Vector2d(xThrowInLineOpp,yThrowInLineRight);

  // L crossings
  crossings[opponentCornerLeft].position          = Vector2d(xPosOpponentGroundline, yPosLeftSideline);
  crossings[opponentCornerRight].position         = Vector2d(xPosOpponentGroundline, yPosRightSideline);
  crossings[ownCornerLeft].position               = Vector2d(xPosOwnGroundline, yPosLeftSideline);
  crossings[ownCornerRight].position              = Vector2d(xPosOwnGroundline, yPosRightSideline);

  crossings[opponentPenaltyCornerLeft].position   = Vector2d(xPosOpponentPenaltyArea, yPosLeftPenaltyArea);
  crossings[opponentPenaltyCornerRight].position  = Vector2d(xPosOpponentPenaltyArea, yPosRightPenaltyArea);
  crossings[ownPenaltyCornerLeft].position        = Vector2d(xPosOwnPenaltyArea, yPosLeftPenaltyArea);
  crossings[ownPenaltyCornerRight].position       = Vector2d(xPosOwnPenaltyArea, yPosRightPenaltyArea);

  // T crossings
  crossings[opponentGoalTCrossingLeft].position   = Vector2d(xPosOpponentGroundline, yPosLeftPenaltyArea);
  crossings[opponentGoalTCrossingRight].position  = Vector2d(xPosOpponentGroundline, yPosRightPenaltyArea);
  crossings[ownGoalTCrossingLeft].position        = Vector2d(xPosOwnGroundline, yPosLeftPenaltyArea);
  crossings[ownGoalTCrossingRight].position       = Vector2d(xPosOwnGroundline, yPosRightPenaltyArea);
  crossings[centerTCrossingLeft].position         = Vector2d(xPosHalfWayLine, yPosLeftSideline);
  crossings[centerTCrossingRight].position        = Vector2d(xPosHalfWayLine, yPosRightSideline);

  // X Crossings
  crossings[crossingCenterCircleLeft].position    = Vector2d(xPosHalfWayLine, -centerCircleRadius);
  crossings[crossingCenterCircleRight].position   = Vector2d(xPosHalfWayLine, centerCircleRadius);

  // goal post positions
  opponentGoalPostLeft  = Vector2d(xPosOpponentGoal+25, yPosLeftGoalpost);
  opponentGoalPostRight = Vector2d(xPosOpponentGoal+25, yPosRightGoalpost);
  opponentGoalCenter    = Vector2d(xPosOpponentGoal+25, 0.0);

  ownGoalPostLeft   = Vector2d(xPosOwnGoal-25, yPosLeftGoalpost);
  ownGoalPostRight  = Vector2d(xPosOwnGoal-25, yPosRightGoalpost);
  ownGoalCenter     = Vector2d(xPosOwnGoal-25, 0.0);

  ////Should be done differently
  // 0 - right side line - sideLineRight
  rightLineSegment = Math::LineSegment(
    crossings[ownCornerRight].position,
    crossings[opponentCornerRight].position
    );

  // 1 - left side line - sideLineLeft
  leftLineSegment = Math::LineSegment(
    crossings[ownCornerLeft].position,
    crossings[opponentCornerLeft].position
    );

  // 2 - own goal line - ownGoalLine
  ownLineSegment = Math::LineSegment(
    crossings[ownCornerRight].position,
    crossings[ownCornerLeft].position
    );

  // 3 - opponent goal line - opponentGoalLine
  oppLineSegment = Math::LineSegment(
    crossings[opponentCornerRight].position,
    crossings[opponentCornerLeft].position
    );
  ////
  //Extra Stuff end
}//end calculateCrossings

/**

    |---------------|---------------|
    |               |               |
    |---|          _|_          |---|
    |   |        /  |  \        |   |
    |   |   +   (   |   )   +   |   |
    |   |        \ _|_ /        |   |
    |---|           |           |---|
    |               |               |
    |---------------|---------------|

*/

void FieldInfo::createLinesTable()
{
  fieldLinesTable = LinesTable();
  // HACK: remove it
  fieldLinesTable.circle_radius = centerCircleRadius;
  fieldLinesTable.penalty_area_width = xPosOpponentGoal - xPosOpponentPenaltyArea;

  // 0 - right side line - sideLineRight
  fieldLinesTable.addLine(
    crossings[ownCornerRight].position,
    crossings[opponentCornerRight].position
    );

  // 1 - left side line - sideLineLeft
  fieldLinesTable.addLine(
    crossings[ownCornerLeft].position,
    crossings[opponentCornerLeft].position
    );

  // 2 - own goal line - ownGoalLine
  fieldLinesTable.addLine(
    crossings[ownCornerRight].position,
    crossings[ownCornerLeft].position
    );

  // 3 - opponent goal line - opponentGoalLine
  fieldLinesTable.addLine(
    crossings[opponentCornerRight].position,
    crossings[opponentCornerLeft].position
    );

  // 4 - center line - centerLine
  fieldLinesTable.addLine(
    crossings[centerTCrossingRight].position,
    crossings[centerTCrossingLeft].position
    );

  // 5 - own penalty line - ownPenaltyLine
  fieldLinesTable.addLine(
    crossings[ownPenaltyCornerRight].position,
    crossings[ownPenaltyCornerLeft].position
    );

  // 6 - own penalty right line - ownPenaltyLineRight
  fieldLinesTable.addLine(
    crossings[ownGoalTCrossingRight].position,
    crossings[ownPenaltyCornerRight].position
    );

  // 7 - own penalty left line - ownPenaltyLineLeft
  fieldLinesTable.addLine(
    crossings[ownGoalTCrossingLeft].position,
    crossings[ownPenaltyCornerLeft].position
    );

  // 8 - opponent penalty line - opponentPenaltyLine
  fieldLinesTable.addLine(
    crossings[opponentPenaltyCornerRight].position,
    crossings[opponentPenaltyCornerLeft].position
    );

  // 9 - opponent penalty right line - opponentPenaltyLineRight
  fieldLinesTable.addLine(
    crossings[opponentPenaltyCornerRight].position,
    crossings[opponentGoalTCrossingRight].position
    );

  // 10 - opponent penalty left line - opponentPenaltyLineLeft
  fieldLinesTable.addLine(
    crossings[opponentPenaltyCornerLeft].position,
    crossings[opponentGoalTCrossingLeft].position
    );

  /*
  // HACK: RC14 white goal box is recognized as lines (opp goal)
  // NOTE: lengthen line 2.5cm to the left to connect it with other line
  fieldLinesTable.addLine(
    Vector2d(opponentGoalPostLeft.x-25,opponentGoalPostLeft.y),
    Vector2d(opponentGoalPostLeft.x + 500, opponentGoalPostLeft.y)
    );
  fieldLinesTable.addLine(
    Vector2d(opponentGoalPostRight.x-25,opponentGoalPostRight.y),
    Vector2d(opponentGoalPostRight.x + 500, opponentGoalPostRight.y)
    );
  fieldLinesTable.addLine(
    Vector2d(opponentGoalPostLeft.x + 500, opponentGoalPostLeft.y),
    Vector2d(opponentGoalPostRight.x + 500, opponentGoalPostRight.y)
    );

  // HACK: RC14 white goal box is recognized as lines (own goal)
  // NOTE: lengthen line 2.5cm to the right to connect it with other line
  fieldLinesTable.addLine(
    Vector2d(ownGoalPostLeft.x+25,ownGoalPostLeft.y),
    Vector2d(ownGoalPostLeft.x - 500, ownGoalPostLeft.y)
    );
  fieldLinesTable.addLine(
    Vector2d(ownGoalPostRight.x+25,ownGoalPostRight.y),
    Vector2d(ownGoalPostRight.x - 500, ownGoalPostRight.y)
    );
  fieldLinesTable.addLine(
    Vector2d(ownGoalPostLeft.x - 500, ownGoalPostLeft.y),
    Vector2d(ownGoalPostRight.x - 500, ownGoalPostRight.y)
    );
  */

  // center circle approximated by sequence of lines
  double numberOfSegments = 12;
  double angleStep = Math::pi2 / numberOfSegments;

  // the radius is choosen in a way the centers of line segments are exactly on the circle
  Vector2d x0(centerCircleRadius / cos(angleStep*0.5), 0.0);
  x0.rotate(-angleStep * 0.5); // the middle line should be intersected by only one circle line
  Vector2d x1(x0);

  for (int i = 0; i < numberOfSegments; i++)
  {
    x0.rotate(angleStep);
    fieldLinesTable.addLine(x0, x1);
    x1 = x0;
  }//end for

  fieldLinesTable.findIntersections();
}//end createLinesTable

void FieldInfo::draw(DrawingCanvas2D& canvas) const
{
  fieldLinesTable.draw(canvas);

  // draw throw in lines
  canvas.pen("000000", 1);
  canvas.drawLine(leftThrowInPointOwn.x,leftThrowInPointOwn.y,leftThrowInPointOpp.x,leftThrowInPointOpp.y);
  canvas.drawLine(rightThrowInPointOwn.x,rightThrowInPointOwn.y,rightThrowInPointOpp.x,rightThrowInPointOpp.y);

  // draw goal posts
  canvas.pen("0000FF", 20);

  // Opponent Goal
  canvas.drawCircle(
             opponentGoalPostLeft.x,
             opponentGoalPostLeft.y,
             goalpostRadius - 10);
  canvas.drawCircle(
             opponentGoalPostRight.x,
             opponentGoalPostRight.y,
             goalpostRadius - 10);

  // Own Goal
  canvas.drawCircle(
             ownGoalPostLeft.x,
             ownGoalPostLeft.y,
             goalpostRadius - 10);
  canvas.drawCircle(
             ownGoalPostRight.x,
             ownGoalPostRight.y,
             goalpostRadius - 10);
}

void FieldInfo::print(std::ostream& stream) const
{
  stream << "ballColor = "<< ColorClasses::getColorName( ballColor )<<"\n";

  stream << "//////////////// basic values from configuration ////////////////\n";
  stream << "ballRadius = "<< ballRadius <<"\n";

  stream << "size of the whole field (including the green area outside the lines): \n";
  stream << "xFieldLength = "<< xFieldLength <<"\n";
  stream << "yFieldLength = "<< yFieldLength <<"\n";

  stream << "size of the field lines:\n";
  stream << "xLength = "<< xLength <<"\n";
  stream << "yLength = "<< yLength <<"\n";

  stream << "xPosOpponentPenaltyArea = "<< xPosOpponentPenaltyArea <<"\n";
  stream << "yPosLeftPenaltyArea = "<< yPosLeftPenaltyArea <<"\n";

  stream << "centerCircleRadius = "<< centerCircleRadius <<"\n";
  stream << "fieldLinesWidth = "<< fieldLinesWidth <<"\n";
  stream << "goalWidth = "<< goalWidth <<"\n";
  stream << "goalHeight = "<< goalHeight <<"\n";
  stream << "goalpostRadius = "<< goalpostRadius <<"\n";

  stream << "/////////////// pre-calculated values from basic values //////////////\n";
  stream << "xPosHalfWayLine = "<< xPosHalfWayLine <<"\n";

  stream << "xPosOwnGoal = "<< xPosOwnGoal <<"\n";
  stream << "xPosOpponentGoal = "<< xPosOpponentGoal <<"\n";
  stream << "xPosOwnGroundline = "<< xPosOwnGroundline <<"\n";
  stream << "xPosOpponentGroundline = "<< xPosOpponentGroundline <<"\n";
  stream << "xPosOwnPenaltyArea = "<< xPosOwnPenaltyArea <<"\n";

  stream << "yPosLeftSideline = "<< yPosLeftSideline <<"\n";
  stream << "yPosRightSideline = "<< yPosRightSideline <<"\n";
  stream << "yPosRightPenaltyArea = "<< yPosRightPenaltyArea <<"\n";

  stream << "yPosRightGoalpost = "<< yPosRightGoalpost <<"\n";
  stream << "yPosLeftGoalpost = "<< yPosLeftGoalpost <<"\n";
}
<|endoftext|>