<commit_before>/*!
 * \file painter_enums.hpp
 * \brief file painter_enums.hpp
 *
 * Copyright 2016 by Intel.
 *
 * Contact: kevin.rogovin@intel.com
 *
 * This Source Code Form is subject to the
 * terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with
 * this file, You can obtain one at
 * http://mozilla.org/MPL/2.0/.
 *
 * \author Kevin Rogovin <kevin.rogovin@intel.com>
 *
 */

#pragma once

namespace fastuidraw
{
/*!\addtogroup Painter
 * @{
 */

  /*!
   * \brief Class to encapsulate enumerations used in Painter
   *        interface, part of the main library libFastUIDraw.
   */
  class PainterEnums
  {
  public:
    /*!
     * \brief
     * Enumeration to indicate in what direction the
     * y-coordinate increases
     */
    enum screen_orientation
      {
        y_increases_downwards, /*!< y-coordinate increases downwards */
        y_increases_upwards /*!< y-coordinate increases upwards */
      };

    /*!
     * \brief
     * Enumeration to specify orientation of a rotation
     */
    enum rotation_orientation_t
      {
        clockwise, /*!< indicates clockwise */
        counter_clockwise /*!< indicates counter-clockwise */
      };

    /*!
     * \brief
     * Enumeration to indicate if glyph layout is horizontal
     * or vertical
     */
    enum glyph_layout_type
      {
        /*!
         * Glyphs are layed out horizontally, thus will use
         * \ref GlyphMetrics::horizontal_layout_offset()
         * to offset the glyphs.
         */
        glyph_layout_horizontal,

        /*!
         * Glyphs are layed out vertically, thus will use
         * \ref GlyphMetrics::vertical_layout_offset()
         * to offset the glyphs.
         */
        glyph_layout_vertical
      };

    /*!
     * \brief
     * Enumeration specifying if and how to draw caps when stroking.
     */
    enum cap_style
      {
        flat_caps,      /*!< indicates to have flat (i.e. no) caps when stroking */
        rounded_caps,   /*!< indicates to have rounded caps when stroking */
        square_caps,    /*!< indicates to have square caps when stroking */

        number_cap_styles /*!< number of cap styles */
      };

    /*!
     * \brief
     * Enumeration specifying if and how to draw joins when stroking
     */
    enum join_style
      {
        /*!
         * indicates to stroke without joins
         */
        no_joins,

        /*!
         * indicates to stroke with rounded joins
         */
        rounded_joins,

        /*!
         * indicates to stroke with bevel joins
         */
        bevel_joins,

        /*!
         * indicates to stroke with miter joins where if miter distance
         * is exceeded then the miter join is clipped to the miter
         * distance.
         */
        miter_clip_joins,

        /*!
         * indicates to stroke with miter joins where if miter distance
         * is exceeded then the miter join is drawn as a bevel join.
         */
        miter_bevel_joins,

        /*!
         * indicates to stroke with miter joins where if miter distance
         * is exceeded then the miter-tip is truncated to the miter
         * distance.
         */
        miter_joins,

        number_join_styles, /*!< number of join styles */
      };

    /*!
     * \brief
     * Enumerations specifying common fill rules.
     */
    enum fill_rule_t
      {
        odd_even_fill_rule, /*!< indicates to use odd-even fill rule */
        complement_odd_even_fill_rule, /*!< indicates to give the complement of the odd-even fill rule */
        nonzero_fill_rule, /*!< indicates to use the non-zero fill rule */
        complement_nonzero_fill_rule, /*!< indicates to give the complement of the non-zero fill rule */

        fill_rule_data_count /*!< count of enums */
      };

    /*!
     * Enumeration to describe high quality shader
     * anti-aliasing support in \ref PainterFillShader
     * and \ref PainterStrokeShader.
     */
    enum hq_anti_alias_support_t
      {
        /*!
         * Indicates that high quality anti-aliasing is NOT
         * supported.
         */
        hq_anti_alias_no_support,

        /*!
         * Indicates that high quality anti-aliasing is
         * supported with significant performance impact.
         */
        hq_anti_alias_slow,

        /*!
         * Indicates that high quality anti-aliasing is
         * supported with no or minimal performance impact.
         */
        hq_anti_alias_fast,
      };

    /*!
     * Enumeration to specify the anti-aliasing quality
     * to apply when performing path fills or strokes.
     */
    enum shader_anti_alias_t
      {
        /*!
         * Do not apply any shader based anti-aliasing
         * to the fill.
         */
        shader_anti_alias_none,

        /*!
         * Applies simpler anti-aliasing shading to path
         * fill or stroke. This will potentially give under
         * coverage to fragments (typically where the path
         * crosses itself or when the path is filled or
         * stroke highly minified).
         */
        shader_anti_alias_simple,

        /*!
         * Applies higher quality anti-aliasing shading
         * that avoids the issues that come from \ref
         * shader_anti_alias_simple. This option will give
         * the highest quality anti-aliasing at the
         * potential cost of performance. The shader works
         * in two passes: the first pass renders to the
         * IMMEDIATE coverage buffer and the 2nd pass reads
         * from it and uses that as the coverage value.
         */
        shader_anti_alias_high_quality,

        /*!
         * Applies higher quality anti-aliasing shading
         * that avoids the issues that come from \ref
         * shader_anti_alias_simple.  This option will give
         * the highest quality anti-aliasing at the
         * potential cost of performance. The shader works
         * in two passes: the first pass renders to the
         * IMMEDIATE coverage buffer and the 2nd pass reads
         * from it and uses that as the coverage value.
         */
        shader_anti_alias_deferred_coverage,

        /* make the modes that indicate for Painter to choose
         * to come after the modes that precisely specify a
         * choice.
         */

        /*!
         * Represents to use \ref shader_anti_alias_high_quality
         * if using it does not have a large performance impact
         * and otherwise to use \ref shader_anti_alias_simple.
         */
        shader_anti_alias_auto,

        /*!
         * Represents to use the fastest anti-alias mode
         * (which is not shader_anti_alias_none).
         */
        shader_anti_alias_fastest,

        /*!
         * Number of shader-anti-alias enums present.
         */
        number_shader_anti_alias_enums,
      };

    /*!
     * Enumeration to specify how to stroke
     */
    enum stroking_method_t
      {
        /*!
         * Use linear stroking taken directly from the
         * Path. Thus the passed \ref StrokedPath only
         * consists of line segments.
         */
        stroking_method_linear,

        /*!
         * Use arc-stroking, i.e. the passed \ref
         * StrokedPath has both arc-segments and
         * line segments. This results in fewer
         * vertices with the fragment shader
         * computing per-pixel coverage.
         */
        stroking_method_arc,

        /* make the modes that indicate to choose to come
         * after the modes that precisely specify a value.
         */

        /*!
         * Choose for optimal performance.
         */
        stroking_method_auto,
      };

    /*!
     * \brief
     * Enumeration specifying composite modes
     */
    enum composite_mode_t
      {
        composite_porter_duff_clear, /*!< Clear mode of Porter-Duff */
        composite_porter_duff_src, /*!< Source mode of Porter-Duff */
        composite_porter_duff_dst, /*!< Destination mode of Porter-Duff */
        composite_porter_duff_src_over, /*!< Source over mode of Porter-Duff */
        composite_porter_duff_dst_over, /*!< Destination over mode of Porter-Duff */
        composite_porter_duff_src_in, /*!< Source In mode of Porter-Duff */
        composite_porter_duff_dst_in, /*!< Destination In mode of Porter-Duff */
        composite_porter_duff_src_out, /*!< Source Out mode of Porter-Duff */
        composite_porter_duff_dst_out, /*!< Destination Out mode of Porter-Duff */
        composite_porter_duff_src_atop, /*!< Source Atop mode of Porter-Duff */
        composite_porter_duff_dst_atop, /*!< Destination Atop mode of Porter-Duff */
        composite_porter_duff_xor, /*!< Xor mode of Porter-Duff */
        composite_porter_duff_plus, /*!< Plus operator mode of Porter-Duff */
        composite_porter_duff_modulate, /*! < Modulate operator mode of Porter-Duff */
      };

    /*!
     * \brief
     * Enumeration specifying W3C blending modes
     */
    enum blend_w3c_mode_t
      {
        blend_w3c_normal, /*!< W3C multiply mode: Src, i.e. no blending operation */
        blend_w3c_multiply, /*!< W3C multiply mode: Dest * Src */
        blend_w3c_screen, /*!< W3C screen mode: 1 - (1 - Dest) * (1 - Src) */

        /*!
         * W3C overlay mode: for each channel,
         * (Dst <= 0.5) ?
         *    2.0 * Dest * Src :
         *    1 - 2 * (1 - Dst) * (1 - Src)
         */
        blend_w3c_overlay,
        blend_w3c_darken, /*!< W3C darken mode: min(Src, Dest) */
        blend_w3c_lighten, /*!< W3C lighten mode: max(Src, Dest) */

        /*!
         * W3C color-dodge mode: for each channel
         * (Dest == 0) ? 0 : (Src == 1) ? 1 : min(1, Dst / (1 - Src) )
         * i.e. if Dest is 0, write 0. If Src is 1, write 1. Otherwise
         * write Dst / (1 - Src)
         */
        blend_w3c_color_dodge,

        /*!
         * W3C color-burn mode: for each channel
         * (Dest == 1) ? 1 : (Src == 0) ? 0 : 1 - min(1, (1 - Dst) / Src)
         * i.e. if Dest is 1, write 1. If Src is 0, write 0. Otherwise
         * write (1 - Dst ) / Src
         */
        blend_w3c_color_burn,

        /*!
         * W3C hardlight mode: for each channel,
         * (Src <= 0.5) ?
         *    2.0 * Dest * Src :
         *    1 - 2 * (1 - Dst) * (1 - Src)
         */
        blend_w3c_hardlight,

        /*!
         * W3C soft light mode: for each channel:
         * (Src <= 0.5) ?
         *   Dst - (1 - 2 * Src) * Dst * (1 - Dst) :
         *   Dst + (2 * Src - 1) * (Z - Dst)
         * where
         *   Z = (Dst <= 0.25) ?
         *     ((16 * Dst - 12) * Dst + 4) * Dst :
         *     sqrt(Dst)
         */
        blend_w3c_softlight,

        blend_w3c_difference, /*!< W3C difference mode: for each channel, abs(Dest - Src) */
        blend_w3c_exclusion, /*!< W3C exclusion mode: for each channel, Dest + Src - 2 * Dest * Src */

        /*!
         * w3c hue mode, see w3c for formula
         */
        blend_w3c_hue,

        /*!
         * w3c saturation mode, see w3c for formula
         */
        blend_w3c_saturation,

        /*!
         * w3c color mode, see w3c for formula
         */
        blend_w3c_color,

        /*!
         * w3c luminosity mode, see w3c for formula
         */
        blend_w3c_luminosity,
      };

    /*!
     * \brief
     * Enumeration to query the statistics of how
     * much data has been packed
     */
    enum query_stats_t
      {
        /*!
         * Offset to how many attributes processed
         */
        num_attributes,

        /*!
         * Offset to how many indices processed
         */
        num_indices,

        /*!
         * Offset to how many generic_data values placed
         * onto store buffer(s).
         */
        num_generic_datas,

        /*!
         * Offset to how many PainterDraw objects sent
         */
        num_draws,

        /*!
         * Offset to how many painter headers packed.
         */
        num_headers,

        /*!
         * Number of distinct render targets needed.
         */
        num_render_targets,

        /*!
         * Number of times PainterBackend::end() was called
         */
        num_ends,

        /*!
         * Number of times begin_layer()/end_layer() was called
         */
        num_layers,
      };

    /*!
     * Given a fill rule, return the fill rule for the complement.
     */
    static
    enum fill_rule_t
    complement_fill_rule(enum fill_rule_t f);
  };
/*! @} */
}
<commit_msg>fastuidraw/painter/painter_enums: make enumeration value specifying the number of stroking modes<commit_after>/*!
 * \file painter_enums.hpp
 * \brief file painter_enums.hpp
 *
 * Copyright 2016 by Intel.
 *
 * Contact: kevin.rogovin@intel.com
 *
 * This Source Code Form is subject to the
 * terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with
 * this file, You can obtain one at
 * http://mozilla.org/MPL/2.0/.
 *
 * \author Kevin Rogovin <kevin.rogovin@intel.com>
 *
 */

#pragma once

namespace fastuidraw
{
/*!\addtogroup Painter
 * @{
 */

  /*!
   * \brief Class to encapsulate enumerations used in Painter
   *        interface, part of the main library libFastUIDraw.
   */
  class PainterEnums
  {
  public:
    /*!
     * \brief
     * Enumeration to indicate in what direction the
     * y-coordinate increases
     */
    enum screen_orientation
      {
        y_increases_downwards, /*!< y-coordinate increases downwards */
        y_increases_upwards /*!< y-coordinate increases upwards */
      };

    /*!
     * \brief
     * Enumeration to specify orientation of a rotation
     */
    enum rotation_orientation_t
      {
        clockwise, /*!< indicates clockwise */
        counter_clockwise /*!< indicates counter-clockwise */
      };

    /*!
     * \brief
     * Enumeration to indicate if glyph layout is horizontal
     * or vertical
     */
    enum glyph_layout_type
      {
        /*!
         * Glyphs are layed out horizontally, thus will use
         * \ref GlyphMetrics::horizontal_layout_offset()
         * to offset the glyphs.
         */
        glyph_layout_horizontal,

        /*!
         * Glyphs are layed out vertically, thus will use
         * \ref GlyphMetrics::vertical_layout_offset()
         * to offset the glyphs.
         */
        glyph_layout_vertical
      };

    /*!
     * \brief
     * Enumeration specifying if and how to draw caps when stroking.
     */
    enum cap_style
      {
        flat_caps,      /*!< indicates to have flat (i.e. no) caps when stroking */
        rounded_caps,   /*!< indicates to have rounded caps when stroking */
        square_caps,    /*!< indicates to have square caps when stroking */

        number_cap_styles /*!< number of cap styles */
      };

    /*!
     * \brief
     * Enumeration specifying if and how to draw joins when stroking
     */
    enum join_style
      {
        /*!
         * indicates to stroke without joins
         */
        no_joins,

        /*!
         * indicates to stroke with rounded joins
         */
        rounded_joins,

        /*!
         * indicates to stroke with bevel joins
         */
        bevel_joins,

        /*!
         * indicates to stroke with miter joins where if miter distance
         * is exceeded then the miter join is clipped to the miter
         * distance.
         */
        miter_clip_joins,

        /*!
         * indicates to stroke with miter joins where if miter distance
         * is exceeded then the miter join is drawn as a bevel join.
         */
        miter_bevel_joins,

        /*!
         * indicates to stroke with miter joins where if miter distance
         * is exceeded then the miter-tip is truncated to the miter
         * distance.
         */
        miter_joins,

        number_join_styles, /*!< number of join styles */
      };

    /*!
     * \brief
     * Enumerations specifying common fill rules.
     */
    enum fill_rule_t
      {
        odd_even_fill_rule, /*!< indicates to use odd-even fill rule */
        complement_odd_even_fill_rule, /*!< indicates to give the complement of the odd-even fill rule */
        nonzero_fill_rule, /*!< indicates to use the non-zero fill rule */
        complement_nonzero_fill_rule, /*!< indicates to give the complement of the non-zero fill rule */

        fill_rule_data_count /*!< count of enums */
      };

    /*!
     * Enumeration to describe high quality shader
     * anti-aliasing support in \ref PainterFillShader
     * and \ref PainterStrokeShader.
     */
    enum hq_anti_alias_support_t
      {
        /*!
         * Indicates that high quality anti-aliasing is NOT
         * supported.
         */
        hq_anti_alias_no_support,

        /*!
         * Indicates that high quality anti-aliasing is
         * supported with significant performance impact.
         */
        hq_anti_alias_slow,

        /*!
         * Indicates that high quality anti-aliasing is
         * supported with no or minimal performance impact.
         */
        hq_anti_alias_fast,
      };

    /*!
     * Enumeration to specify the anti-aliasing quality
     * to apply when performing path fills or strokes.
     */
    enum shader_anti_alias_t
      {
        /*!
         * Do not apply any shader based anti-aliasing
         * to the fill.
         */
        shader_anti_alias_none,

        /*!
         * Applies simpler anti-aliasing shading to path
         * fill or stroke. This will potentially give under
         * coverage to fragments (typically where the path
         * crosses itself or when the path is filled or
         * stroke highly minified).
         */
        shader_anti_alias_simple,

        /*!
         * Applies higher quality anti-aliasing shading
         * that avoids the issues that come from \ref
         * shader_anti_alias_simple. This option will give
         * the highest quality anti-aliasing at the
         * potential cost of performance. The shader works
         * in two passes: the first pass renders to the
         * IMMEDIATE coverage buffer and the 2nd pass reads
         * from it and uses that as the coverage value.
         */
        shader_anti_alias_high_quality,

        /*!
         * Applies higher quality anti-aliasing shading
         * that avoids the issues that come from \ref
         * shader_anti_alias_simple.  This option will give
         * the highest quality anti-aliasing at the
         * potential cost of performance. The shader works
         * in two passes: the first pass renders to the
         * IMMEDIATE coverage buffer and the 2nd pass reads
         * from it and uses that as the coverage value.
         */
        shader_anti_alias_deferred_coverage,

        /* make the modes that indicate for Painter to choose
         * to come after the modes that precisely specify a
         * choice.
         */

        /*!
         * Represents to use \ref shader_anti_alias_high_quality
         * if using it does not have a large performance impact
         * and otherwise to use \ref shader_anti_alias_simple.
         */
        shader_anti_alias_auto,

        /*!
         * Represents to use the fastest anti-alias mode
         * (which is not shader_anti_alias_none).
         */
        shader_anti_alias_fastest,

        /*!
         * Number of shader-anti-alias enums present.
         */
        number_shader_anti_alias_enums,
      };

    /*!
     * Enumeration to specify how to stroke
     */
    enum stroking_method_t
      {
        /*!
         * Use linear stroking taken directly from the
         * Path. Thus the passed \ref StrokedPath only
         * consists of line segments.
         */
        stroking_method_linear,

        /*!
         * Use arc-stroking, i.e. the passed \ref
         * StrokedPath has both arc-segments and
         * line segments. This results in fewer
         * vertices with the fragment shader
         * computing per-pixel coverage.
         */
        stroking_method_arc,

        /* make the modes that indicate to choose to come
         * after the modes that precisely specify a value.
         */

        /*!
         * Choose for optimal performance.
         */
        stroking_method_auto,

        /*!
         * Number of stroking enums present.
         */
        number_stroking_methods,
      };

    /*!
     * \brief
     * Enumeration specifying composite modes
     */
    enum composite_mode_t
      {
        composite_porter_duff_clear, /*!< Clear mode of Porter-Duff */
        composite_porter_duff_src, /*!< Source mode of Porter-Duff */
        composite_porter_duff_dst, /*!< Destination mode of Porter-Duff */
        composite_porter_duff_src_over, /*!< Source over mode of Porter-Duff */
        composite_porter_duff_dst_over, /*!< Destination over mode of Porter-Duff */
        composite_porter_duff_src_in, /*!< Source In mode of Porter-Duff */
        composite_porter_duff_dst_in, /*!< Destination In mode of Porter-Duff */
        composite_porter_duff_src_out, /*!< Source Out mode of Porter-Duff */
        composite_porter_duff_dst_out, /*!< Destination Out mode of Porter-Duff */
        composite_porter_duff_src_atop, /*!< Source Atop mode of Porter-Duff */
        composite_porter_duff_dst_atop, /*!< Destination Atop mode of Porter-Duff */
        composite_porter_duff_xor, /*!< Xor mode of Porter-Duff */
        composite_porter_duff_plus, /*!< Plus operator mode of Porter-Duff */
        composite_porter_duff_modulate, /*! < Modulate operator mode of Porter-Duff */
      };

    /*!
     * \brief
     * Enumeration specifying W3C blending modes
     */
    enum blend_w3c_mode_t
      {
        blend_w3c_normal, /*!< W3C multiply mode: Src, i.e. no blending operation */
        blend_w3c_multiply, /*!< W3C multiply mode: Dest * Src */
        blend_w3c_screen, /*!< W3C screen mode: 1 - (1 - Dest) * (1 - Src) */

        /*!
         * W3C overlay mode: for each channel,
         * (Dst <= 0.5) ?
         *    2.0 * Dest * Src :
         *    1 - 2 * (1 - Dst) * (1 - Src)
         */
        blend_w3c_overlay,
        blend_w3c_darken, /*!< W3C darken mode: min(Src, Dest) */
        blend_w3c_lighten, /*!< W3C lighten mode: max(Src, Dest) */

        /*!
         * W3C color-dodge mode: for each channel
         * (Dest == 0) ? 0 : (Src == 1) ? 1 : min(1, Dst / (1 - Src) )
         * i.e. if Dest is 0, write 0. If Src is 1, write 1. Otherwise
         * write Dst / (1 - Src)
         */
        blend_w3c_color_dodge,

        /*!
         * W3C color-burn mode: for each channel
         * (Dest == 1) ? 1 : (Src == 0) ? 0 : 1 - min(1, (1 - Dst) / Src)
         * i.e. if Dest is 1, write 1. If Src is 0, write 0. Otherwise
         * write (1 - Dst ) / Src
         */
        blend_w3c_color_burn,

        /*!
         * W3C hardlight mode: for each channel,
         * (Src <= 0.5) ?
         *    2.0 * Dest * Src :
         *    1 - 2 * (1 - Dst) * (1 - Src)
         */
        blend_w3c_hardlight,

        /*!
         * W3C soft light mode: for each channel:
         * (Src <= 0.5) ?
         *   Dst - (1 - 2 * Src) * Dst * (1 - Dst) :
         *   Dst + (2 * Src - 1) * (Z - Dst)
         * where
         *   Z = (Dst <= 0.25) ?
         *     ((16 * Dst - 12) * Dst + 4) * Dst :
         *     sqrt(Dst)
         */
        blend_w3c_softlight,

        blend_w3c_difference, /*!< W3C difference mode: for each channel, abs(Dest - Src) */
        blend_w3c_exclusion, /*!< W3C exclusion mode: for each channel, Dest + Src - 2 * Dest * Src */

        /*!
         * w3c hue mode, see w3c for formula
         */
        blend_w3c_hue,

        /*!
         * w3c saturation mode, see w3c for formula
         */
        blend_w3c_saturation,

        /*!
         * w3c color mode, see w3c for formula
         */
        blend_w3c_color,

        /*!
         * w3c luminosity mode, see w3c for formula
         */
        blend_w3c_luminosity,
      };

    /*!
     * \brief
     * Enumeration to query the statistics of how
     * much data has been packed
     */
    enum query_stats_t
      {
        /*!
         * Offset to how many attributes processed
         */
        num_attributes,

        /*!
         * Offset to how many indices processed
         */
        num_indices,

        /*!
         * Offset to how many generic_data values placed
         * onto store buffer(s).
         */
        num_generic_datas,

        /*!
         * Offset to how many PainterDraw objects sent
         */
        num_draws,

        /*!
         * Offset to how many painter headers packed.
         */
        num_headers,

        /*!
         * Number of distinct render targets needed.
         */
        num_render_targets,

        /*!
         * Number of times PainterBackend::end() was called
         */
        num_ends,

        /*!
         * Number of times begin_layer()/end_layer() was called
         */
        num_layers,
      };

    /*!
     * Given a fill rule, return the fill rule for the complement.
     */
    static
    enum fill_rule_t
    complement_fill_rule(enum fill_rule_t f);
  };
/*! @} */
}
<|endoftext|>


<commit_before>#ifndef ALEPH_GEOMETRY_WITNESS_COMPLEX_HH__
#define ALEPH_GEOMETRY_WITNESS_COMPLEX_HH__

#include <algorithm>
#include <limits>
#include <iterator>
#include <vector>

#include <aleph/geometry/distances/Traits.hh>

#include <aleph/topology/Simplex.hh>
#include <aleph/topology/SimplicialComplex.hh>

namespace aleph
{

namespace geometry
{

template <class Distance, class Container, class InputIterator> auto buildWitnessComplex(
  const Container& container,
  InputIterator begin, InputIterator end,
  unsigned nu = 2,
  typename Distance::ResultType R = typename Distance::ResultType() ) -> topology::SimplicialComplex< topology::Simplex<typename Distance::ResultType, unsigned> >
{
  using IndexType         = typename std::iterator_traits<InputIterator>::value_type;
  using DataType          = typename Distance::ResultType;
  using Traits            = aleph::distances::Traits<Distance>;
  using VertexType        = unsigned; // TODO: make configurable
  using Simplex           = topology::Simplex<DataType, VertexType>;
  using SimplicialComplex = topology::SimplicialComplex<Simplex>;

  // These are only the *indices* of the landmarks, with respect to the
  // underlying point cloud.
  std::vector<IndexType> landmarkIndices( begin, end );

  auto n = landmarkIndices.size();
  auto N = container.size();
  auto d = container.dimension();

  // Much of the behaviour below will be undefined if we permit such
  // situations to occur.
  if( n == 0 || N == 0 )
    return {};

  // Distance matrix between a set of $n$ landmarks (rows) and $N$ data
  // points.
  std::vector< std::vector<DataType> > D;
  D.reserve( n );

  Distance dist;
  Traits traits;

  for( std::size_t i = 0; i < n; i++ )
  {
    std::vector<DataType> distances;
    distances.reserve( N );

    auto&& landmark = container[ landmarkIndices.at(i) ];

    for( std::size_t j = 0; j < N; j++ )
    {
      auto&& point = container[j];

      distances.emplace_back( traits.from( dist( landmark.begin(), point.begin(), d ) ) );
    }

    D.push_back( distances );
  }

  // Records the appearance times of each potential edge in the witness
  // complex.
  //
  // TODO: this should become a symmetric matrix
  std::vector< std::vector<DataType> > M( n, std::vector<DataType>( n ) );

  for( std::size_t i = 0; i < n; i++ )
  {
    for( std::size_t j = i+1; j < n; j++ )
    {
      auto min = std::numeric_limits<DataType>::max();

      for( std::size_t k = 0; k < N; k++ )
        min = std::min( min, std::max( D[i][k], D[j][k] ) );

      M[i][j] = min;
      M[j][i] = min;
    }
  }

  // Get smallest entries of the distance matrix. This is required for
  // deciding whether a specific edge is valid or not, with respect to
  // the given parameters.

  std::vector<DataType> smallest( N );

  if( nu != 0 )
  {
    for( std::size_t col = 0; col < N; col++ )
    {
      // FIXME: getting the column like this is extremely wasteful;
      // would it not be nicer to store the values differently?
      std::vector<DataType> column( n );
      for( std::size_t i = 0; i < n; i++ )
        column[i] = D[i][col];

      std::nth_element( column.begin(), column.begin() + nu - 1, column.end() );
      smallest[col] = column.at( nu - 1 );
    }
  }

  auto max = *std::max_element( smallest.begin(), smallest.end() );

  std::vector<Simplex> simplices;

  for( std::size_t i = 0; i < n; i++ )
  {
    simplices.push_back( Simplex( static_cast<VertexType>(i) ) );

    for( std::size_t j = i+1; j < n; j++ )
    {
      // Skip pairs that cannot possibly give rise to an edge because of
      // their distance to each other.
      if( M[i][j] > R + max )
        continue;

      for( std::size_t col = 0; col < N; col++ )
      {
        if( M[i][j] <= R + smallest.at(col) )
        {
          auto u = static_cast<VertexType>(i);
          auto v = static_cast<VertexType>(j);

          simplices.push_back( Simplex( {u,v}, M[i][j] ) );
          break;
        }
      }
    }
  }

  return SimplicialComplex( simplices.begin(), simplices.end() );
}

} // namespace geometry

} // namespace aleph

#endif
<commit_msg>Using symmetric matrix class for witness complex calculation<commit_after>#ifndef ALEPH_GEOMETRY_WITNESS_COMPLEX_HH__
#define ALEPH_GEOMETRY_WITNESS_COMPLEX_HH__

#include <algorithm>
#include <limits>
#include <iterator>
#include <vector>

#include <aleph/geometry/distances/Traits.hh>

#include <aleph/math/SymmetricMatrix.hh>

#include <aleph/topology/Simplex.hh>
#include <aleph/topology/SimplicialComplex.hh>

namespace aleph
{

namespace geometry
{

template <class Distance, class Container, class InputIterator> auto buildWitnessComplex(
  const Container& container,
  InputIterator begin, InputIterator end,
  unsigned nu = 2,
  typename Distance::ResultType R = typename Distance::ResultType() ) -> topology::SimplicialComplex< topology::Simplex<typename Distance::ResultType, unsigned> >
{
  using IndexType         = typename std::iterator_traits<InputIterator>::value_type;
  using DataType          = typename Distance::ResultType;
  using Traits            = aleph::distances::Traits<Distance>;
  using VertexType        = unsigned; // TODO: make configurable
  using Simplex           = topology::Simplex<DataType, VertexType>;
  using SimplicialComplex = topology::SimplicialComplex<Simplex>;

  // These are only the *indices* of the landmarks, with respect to the
  // underlying point cloud.
  std::vector<IndexType> landmarkIndices( begin, end );

  auto n = landmarkIndices.size();
  auto N = container.size();
  auto d = container.dimension();

  // Much of the behaviour below will be undefined if we permit such
  // situations to occur.
  if( n == 0 || N == 0 )
    return {};

  // Distance matrix between a set of $n$ landmarks (rows) and $N$ data
  // points.
  std::vector< std::vector<DataType> > D;
  D.reserve( n );

  Distance dist;
  Traits traits;

  for( std::size_t i = 0; i < n; i++ )
  {
    std::vector<DataType> distances;
    distances.reserve( N );

    auto&& landmark = container[ landmarkIndices.at(i) ];

    for( std::size_t j = 0; j < N; j++ )
    {
      auto&& point = container[j];

      distances.emplace_back( traits.from( dist( landmark.begin(), point.begin(), d ) ) );
    }

    D.push_back( distances );
  }

  // Records the appearance times of each potential edge in the witness
  // complex.

  aleph::math::SymmetricMatrix<DataType> M( n );

  for( std::size_t i = 0; i < n; i++ )
  {
    for( std::size_t j = i+1; j < n; j++ )
    {
      auto min = std::numeric_limits<DataType>::max();

      for( std::size_t k = 0; k < N; k++ )
        min = std::min( min, std::max( D[i][k], D[j][k] ) );

      M(i,j) = min;
    }
  }

  // Get smallest entries of the distance matrix. This is required for
  // deciding whether a specific edge is valid or not, with respect to
  // the given parameters.

  std::vector<DataType> smallest( N );

  if( nu != 0 )
  {
    for( std::size_t col = 0; col < N; col++ )
    {
      // FIXME: getting the column like this is extremely wasteful;
      // would it not be nicer to store the values differently?
      std::vector<DataType> column( n );
      for( std::size_t i = 0; i < n; i++ )
        column[i] = D[i][col];

      std::nth_element( column.begin(), column.begin() + nu - 1, column.end() );
      smallest[col] = column.at( nu - 1 );
    }
  }

  auto max = *std::max_element( smallest.begin(), smallest.end() );

  std::vector<Simplex> simplices;

  for( std::size_t i = 0; i < n; i++ )
  {
    simplices.push_back( Simplex( static_cast<VertexType>(i) ) );

    for( std::size_t j = i+1; j < n; j++ )
    {
      // Skip pairs that cannot possibly give rise to an edge because of
      // their distance to each other.
      if( M(i,j) > R + max )
        continue;

      for( std::size_t col = 0; col < N; col++ )
      {
        if( M(i,j) <= R + smallest.at(col) )
        {
          auto u = static_cast<VertexType>(i);
          auto v = static_cast<VertexType>(j);

          simplices.push_back( Simplex( {u,v}, M(i,j) ) );
          break;
        }
      }
    }
  }

  return SimplicialComplex( simplices.begin(), simplices.end() );
}

} // namespace geometry

} // namespace aleph

#endif
<|endoftext|>


<commit_before>#pragma once
/*
* Covariant Script OS Support
*
* Licensed under the Covariant Innovation General Public License,
* Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://covariant.cn/licenses/LICENSE-1.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.
*
* Copyright (C) 2019 Michael Lee(李登淳)
* Email: mikecovlee@163.com
* Github: https://github.com/mikecovlee
*/
#if defined(_WIN32) || defined(WIN32)

#include "./win32_impl.hpp"

#else

#include "./unix_impl.hpp"

#endif
<commit_msg>Update system.hpp<commit_after>#pragma once
/*
* Covariant Script OS Support
*
* Licensed under the Covariant Innovation General Public License,
* Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://covariant.cn/licenses/LICENSE-1.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.
*
* Copyright (C) 2019 Michael Lee(李登淳)
* Email: mikecovlee@163.com
* Github: https://github.com/mikecovlee
*/
#if defined(_WIN32) || defined(WIN32)

#include "./win32_impl.hpp"

#else

#include "./unix_impl.hpp"

#endif

#include <sys/stat.h>

namespace cs_impl {
    namespace filesystem {
        bool is_directory(const std::string &path) {
            struct stat s{};
            if (stat(path.c_str(), &s) == 0) {
                return S_ISDIR(s.st_mode);
            }
            return false;
        }
    }
}<|endoftext|>


<commit_before>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
Copyright (c) 2009 Aristid Breitkreuz, Ash Berlin, Ruediger Sonderfeld

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#ifndef FLUSSFPERD_CLASS_DESCRIPTION_HPP
#define FLUSSFPERD_CLASS_DESCRIPTION_HPP

#ifndef PREPROC_DEBUG
#include "class.hpp"
#endif
#include <boost/preprocessor.hpp>

#define FLUSSPFERD_PP_GEN_TUPLE2SEQ_PROCESS2(x, y) \
  ((x, y)) \
  FLUSSPFERD_PP_GEN_TUPLE2SEQ_PROCESS

#define FLUSSPFERD_PP_GEN_TUPLE2SEQ_PROCESS(x, y) \
  ((x, y)) \
  FLUSSPFERD_PP_GEN_TUPLE2SEQ_PROCESS2

#define FLUSSPFERD_PP_GEN_TUPLE2SEQ_PROCESS_ELIM
#define FLUSSPFERD_PP_GEN_TUPLE2SEQ_PROCESS2_ELIM

#define FLUSSPFERD_PP_GEN_TUPLE2SEQ(x) \
  BOOST_PP_CAT(BOOST_PP_EXPAND(FLUSSPFERD_PP_GEN_TUPLE2SEQ_PROCESS x), _ELIM)

#define FLUSSPFERD_CD_PARAM_FOLD(s, state, elem) \
  BOOST_PP_ARRAY_REPLACE( \
    state, \
    BOOST_PP_EXPAND( \
      BOOST_PP_CAT(FLUSSPFERD_CD_PARAM__, \
        BOOST_PP_TUPLE_ELEM(2, 0, elem))), \
    BOOST_PP_TUPLE_ELEM(2, 1, elem)) \
  /* */

#define FLUSSPFERD_CD_PARAM_INITIAL \
  (6, ( \
    ~cpp_name~,            /* name */ \
    ~constructor_name~,    /* constructor name */ \
    ~constructor_arity~,   /* constructor arity */ \
    ~full_name~,           /* full name */ \
    BOOST_PP_NIL,          /* methods */ \
    0                      /* augment constructor */ \
  )) \
  /* */

#define FLUSSPFERD_CD_PARAM__cpp_name               0
#define FLUSSPFERD_CD_PARAM__constructor_name       1
#define FLUSSPFERD_CD_PARAM__constructor_arity      2
#define FLUSSPFERD_CD_PARAM__full_name              3
#define FLUSSPFERD_CD_PARAM__methods                4
#define FLUSSPFERD_CD_PARAM__augment_constructor    5

#define FLUSSPFERD_CD_PARAM(tuple_seq) \
  BOOST_PP_SEQ_FOLD_LEFT( \
    FLUSSPFERD_CD_PARAM_FOLD, \
    FLUSSPFERD_CD_PARAM_INITIAL, \
    FLUSSPFERD_PP_GEN_TUPLE2SEQ(tuple_seq) \
  ) \
  /* */

#define FLUSSPFERD_CLASS_DESCRIPTION_A(array) \
  BOOST_PP_EXPAND(FLUSSPFERD_CLASS_DESCRIPTION_P BOOST_PP_ARRAY_DATA(array)) \
  /* */

#define FLUSSPFERD_CLASS_DESCRIPTION_P( \
  p_cpp_name, \
  p_constructor_name, \
  p_constructor_arity, \
  p_full_name, \
  p_methods, \
  p_augment_constructor \
) \
  class p_cpp_name { \
    struct class_info : ::flusspferd::class_info_base { \
      static char const *constructor_name() { \
        return (p_constructor_name); \
      } \
      typedef ::boost::mpl::size_t< (p_constructor_arity) > constructor_arity; \
      static char const *full_name() { \
        return (p_full_name); \
      } \
      static ::flusspferd::object create_prototype() { \
        ::flusspferd::object proto = ::flusspferd::create_object(); \
        BOOST_PP_SEQ_FOR_EACH( \
          FLUSSPFERD_CD_METHOD, \
          p_cpp_name, \
          p_methods) \
      } \
      BOOST_PP_EXPR_IF( \
        p_augment_constructor, \
        static void augment_constructor(::flusspferd::object &); \
      ) \
    }; \
  /* */

#define FLUSSPFERD_CD_METHOD(r, p_cpp_name, element) \
  ::flusspferd::create_native_method( \
      proto, \
      BOOST_PP_STRINGIZE(element), \
      & p_cpp_name :: element); \
  /* */

#define FLUSSPFERD_CLASS_DESCRIPTION(tuple_seq) \
  FLUSSPFERD_CLASS_DESCRIPTION_A(FLUSSPFERD_CD_PARAM(tuple_seq)) \
  /* */

#define FLUSSPFERD_CLASS_DESCRIPTION_END() \
  }; \
  /* */

#endif
<commit_msg>class_macros: add base class and public/private classifiers<commit_after>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
Copyright (c) 2009 Aristid Breitkreuz, Ash Berlin, Ruediger Sonderfeld

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#ifndef FLUSSFPERD_CLASS_DESCRIPTION_HPP
#define FLUSSFPERD_CLASS_DESCRIPTION_HPP

#ifndef PREPROC_DEBUG
#include "class.hpp"
#include "native_object_base.hpp"
#endif
#include <boost/preprocessor.hpp>

#define FLUSSPFERD_PP_GEN_TUPLE2SEQ_PROCESS2(x, y) \
  ((x, y)) \
  FLUSSPFERD_PP_GEN_TUPLE2SEQ_PROCESS

#define FLUSSPFERD_PP_GEN_TUPLE2SEQ_PROCESS(x, y) \
  ((x, y)) \
  FLUSSPFERD_PP_GEN_TUPLE2SEQ_PROCESS2

#define FLUSSPFERD_PP_GEN_TUPLE2SEQ_PROCESS_ELIM
#define FLUSSPFERD_PP_GEN_TUPLE2SEQ_PROCESS2_ELIM

#define FLUSSPFERD_PP_GEN_TUPLE2SEQ(x) \
  BOOST_PP_CAT(BOOST_PP_EXPAND(FLUSSPFERD_PP_GEN_TUPLE2SEQ_PROCESS x), _ELIM)

#define FLUSSPFERD_CD_PARAM_FOLD(s, state, elem) \
  BOOST_PP_ARRAY_REPLACE( \
    state, \
    BOOST_PP_EXPAND( \
      BOOST_PP_CAT(FLUSSPFERD_CD_PARAM__, \
        BOOST_PP_TUPLE_ELEM(2, 0, elem))), \
    BOOST_PP_TUPLE_ELEM(2, 1, elem)) \
  /* */

#define FLUSSPFERD_CD_PARAM_INITIAL \
  (6, ( \
    ~cpp_name~,            /* name */ \
    ~constructor_name~,    /* constructor name */ \
    ~constructor_arity~,   /* constructor arity */ \
    ~full_name~,           /* full name */ \
    BOOST_PP_NIL,          /* methods */ \
    0                      /* augment constructor */ \
  )) \
  /* */

#define FLUSSPFERD_CD_PARAM__cpp_name               0
#define FLUSSPFERD_CD_PARAM__constructor_name       1
#define FLUSSPFERD_CD_PARAM__constructor_arity      2
#define FLUSSPFERD_CD_PARAM__full_name              3
#define FLUSSPFERD_CD_PARAM__methods                4
#define FLUSSPFERD_CD_PARAM__augment_constructor    5

#define FLUSSPFERD_CD_PARAM(tuple_seq) \
  BOOST_PP_SEQ_FOLD_LEFT( \
    FLUSSPFERD_CD_PARAM_FOLD, \
    FLUSSPFERD_CD_PARAM_INITIAL, \
    FLUSSPFERD_PP_GEN_TUPLE2SEQ(tuple_seq) \
  ) \
  /* */

#define FLUSSPFERD_CLASS_DESCRIPTION_A(array) \
  BOOST_PP_EXPAND(FLUSSPFERD_CLASS_DESCRIPTION_P BOOST_PP_ARRAY_DATA(array)) \
  /* */

#define FLUSSPFERD_CLASS_DESCRIPTION_P( \
  p_cpp_name, \
  p_constructor_name, \
  p_constructor_arity, \
  p_full_name, \
  p_methods, \
  p_augment_constructor \
) \
  class p_cpp_name : public ::flusspferd::native_object_base { \
  public: \
    struct class_info : ::flusspferd::class_info_base { \
      static char const *constructor_name() { \
        return (p_constructor_name); \
      } \
      typedef ::boost::mpl::size_t< (p_constructor_arity) > constructor_arity; \
      static char const *full_name() { \
        return (p_full_name); \
      } \
      static ::flusspferd::object create_prototype() { \
        ::flusspferd::object proto = ::flusspferd::create_object(); \
        BOOST_PP_SEQ_FOR_EACH( \
          FLUSSPFERD_CD_METHOD, \
          p_cpp_name, \
          p_methods) \
      } \
      BOOST_PP_EXPR_IF( \
        p_augment_constructor, \
        static void augment_constructor(::flusspferd::object &); \
      ) \
    }; \
  private: \
  /* */

#define FLUSSPFERD_CD_METHOD(r, p_cpp_name, element) \
  ::flusspferd::create_native_method( \
      proto, \
      BOOST_PP_STRINGIZE(element), \
      & p_cpp_name :: element); \
  /* */

#define FLUSSPFERD_CLASS_DESCRIPTION(tuple_seq) \
  FLUSSPFERD_CLASS_DESCRIPTION_A(FLUSSPFERD_CD_PARAM(tuple_seq)) \
  /* */

#define FLUSSPFERD_CLASS_DESCRIPTION_END() \
  }; \
  /* */

#endif
<|endoftext|>


<commit_before>// kate: indent-mode cstyle; indent-width 4; tab-width 4; space-indent false;
// vim:ai ts=4 et

#include <iostream>

#include <boost/foreach.hpp>

#include "BallModel.hpp"

using namespace std;

Modeling::BallModel::BallModel(mode_t mode, RobotModel::RobotMap *robotMap) :
	A(6,6), B(6,6), P(6,6), Q(6,6), R(2,2), H(2,6),
	Z(2), U(6), X0(6), _mode(mode), _robotMap(robotMap)
{
	lastObservedTime = 0;
	lastUpdatedTime = 0;

	if (_mode == MODELTESTS) {
		cout << "Running ball model tests..." << endl;
		initKalman();
		initRBPF();
		kalmanTestPosError = 0; kalmanTestVelError = 0;
		rbpfTestPosError = 0; rbpfTestVelError = 0;
	} else if (_mode == KALMAN) {
		initKalman();
	} else if (_mode == RBPF) {
		initRBPF();
	} else if (_mode == ABG) {
		initABG();
	} else {
		cout << "ERROR: Invalid initialization type, defaulting to RPBF!" << endl;
		_mode = RBPF;
		initRBPF();
	}
}

void Modeling::BallModel::initABG() {
	alpha = 1;
	beta = .4;
	gamma = .1;
}

void Modeling::BallModel::initKalman() {
	A.zero();
	B.zero();
	Q.zero();
	R.zero();
	H.zero();
	P.zero();
	X0.zero();

	//Process covariance between position and velocity (E[x,x_dot])
	// 	Q(1,0) = Q(4,3) = 0.01;

	//Process covariance between velocity and acceleration (E[x)dot,x_ddot])
	// 	Q(2,1) = Q(5,4) = 0.001;

	//Process covariance between position and acceleration (E[x,x_ddot])
	// 	Q(2,0) = Q(5,3) = 0.0001;

	//Process covariance (E[x,x], E[x_dot,x_dot], etc)
	Q(0,0) = Q(3,3) = 10;

	Q(1,1) = Q(4,4) = 10;

	Q(2,2) = Q(5,5) = 10;

	//Measurement Covariance for position in the x and the y
	R(0,0) = R(1,1) = 0.84;

	//Measurement Model. We can only measure position
	H(0,0) = H(1,3) = 1;

	//State Model
	A(0,0) = A(1,1) = A(2,2) = A(3,3) = A(4,4) = A(5,5) = 1;

	posKalman = new DifferenceKalmanFilter(&A, &B, &X0, &P, &Q, &R, &H);
}

void Modeling::BallModel::initRBPF() {
	// Construct initial state X (n x 1)
	Vector X(6); X.clear();
	// Construct initial state covariance P (n x n)
	Matrix P(6,6); P.clear(); P(0,0)=P(1,1)= P(2,2)=P(3,3)=P(4,4)=P(5,5)=0.01;
	// Create Rbpf
	int numParticles = 20; // Number of particles in filter
	raoBlackwellizedParticleFilter = new Rbpf(X,P,numParticles);
	// create model graph
	raoBlackwellizedParticleFilter->addModel(new RbpfModelRolling(_robotMap));
	raoBlackwellizedParticleFilter->addModel(new RbpfModelKicked(_robotMap));
	raoBlackwellizedParticleFilter->setTransProb(0,0,0.9);
	raoBlackwellizedParticleFilter->setTransProb(0,1,0.1);
	raoBlackwellizedParticleFilter->setTransProb(1,0,0.9);
	raoBlackwellizedParticleFilter->setTransProb(1,1,0.1);
}

Geometry2d::Point Modeling::BallModel::predictPosAtTime(float dtime)
{
	return pos + vel * dtime + accel * 0.5f * dtime * dtime;
}

void Modeling::BallModel::observation(uint64_t time, const Geometry2d::Point &pos, observation_mode obs_type)
{
	observation_type obs = {time, pos, obs_type};
	_observations.push_back(obs);

	// set lastObservedTime to the last observation's time
	if (time > lastObservedTime)
		lastObservedTime = time;
}

void Modeling::BallModel::kalmanUpdate(float dtime) {
	//Update model
	A(0,1) = dtime;
	A(0,2) = 0.5*dtime*dtime;

	A(1,2) = dtime;

	A(3,4) = dtime;
	A(3,5) = 0.5*dtime*dtime;

	A(4,5) = dtime;

	//Position
	Z(0) = observedPos.x;
	Z(1) = observedPos.y;

	posKalman->predict(&U);
	posKalman->correct(&Z);

	pos.x = (float)posKalman->state()->elt(0);
	vel.x = (float)posKalman->state()->elt(1);
	accel.x = (float)posKalman->state()->elt(2);
	pos.y = (float)posKalman->state()->elt(3);
	vel.y = (float)posKalman->state()->elt(4);
	accel.y = (float)posKalman->state()->elt(5);
}

void Modeling::BallModel::rbpfUpdate(float dtime) {
	raoBlackwellizedParticleFilter->update(observedPos.x,observedPos.y,dtime);
	RbpfState* bestState = raoBlackwellizedParticleFilter->getBestFilterState();
	pos.x = bestState->X(0);
	pos.y = bestState->X(1);
	vel.x = bestState->X(2);
	vel.y = bestState->X(3);
	accel.x = bestState->X(4);
	accel.y = bestState->X(5);
}

void Modeling::BallModel::rbpfUpdateMultipleObs(std::vector<observation_type> &obs){
	int numObs = obs.size();
	double x[numObs];
	double y[numObs];
	double dt[numObs];
	for(int i=obs.size()-1; i>=0; i--){
		x[i] = obs[i].pos.x;
		y[i] = obs[i].pos.y;
		dt[i] = (float)(obs[i].time - lastUpdatedTime) / 1e6;
	}
	raoBlackwellizedParticleFilter->updateMultipleObs(x,y,dt,numObs);
	RbpfState* bestState = raoBlackwellizedParticleFilter->getBestFilterState();
	pos.x = bestState->X(0);
	pos.y = bestState->X(1);
	vel.x = bestState->X(2);
	vel.y = bestState->X(3);
	accel.x = bestState->X(4);
	accel.y = bestState->X(5);
}

void Modeling::BallModel::abgUpdate(float dtime) {
	Geometry2d::Point predictPos = abgPos + vel * dtime + accel * 0.5f * dtime * dtime;
	Geometry2d::Point predictVel = vel + accel * dtime;

	Geometry2d::Point posError = observedPos - predictPos;
	abgPos = predictPos + posError * alpha;
	vel = predictVel + posError * beta / dtime;
	accel += posError * gamma / (dtime * dtime);
}

bool Modeling::BallModel::valid(uint64_t time) {
	//return !_observations.empty() || ((time - lastUpdatedTime) > MaxCoastTime);
	// even with no observations, we can be valid.
	return ((time - lastUpdatedTime) > MaxCoastTime);
}

void Modeling::BallModel::update(uint64_t time)
{
	const bool verbose = false;

	if(_observations.empty()) {
		// coast the ball using simple integrator
		float dtime = (float)(time - lastUpdatedTime) / 1e6;
		pos = predictPosAtTime(dtime);
		vel += accel * 0.5f * dtime * dtime;
		return;
	}

	// loop through the observations and determine if we got vision observations
	bool gotCameraObservation = false;
	BOOST_FOREACH(const observation_type& obs, _observations) {
		if(obs.obs_type == BallModel::VISION){
			gotCameraObservation = true;
			break;
		}
	}

	// If there are camera observations, remove robot sensor observations.
	vector<observation_type> goodObs;
	if(gotCameraObservation){
		BOOST_FOREACH(const observation_type& obs, _observations) {
			if (obs.obs_type == BallModel::VISION) {
				goodObs.push_back(obs);
			}
		}
	} else {
		goodObs = _observations;
	}
	_observations = goodObs;
	if (verbose) cout << " ballModel has " << _observations.size() << " observations, updating..." << endl;

	// TODO: handle non-RBPF filters properly
	if (_mode != RBPF){
		cout << "update() not implemented in ballmodel.cpp" << endl;
	} else if (_mode == RBPF) {
		rbpfUpdateMultipleObs(_observations);
	}

	// remove previous observations after processing them
	_observations.clear();

	// remember last update
	lastUpdatedTime = time;

	/*
	float dtime = (float)(bestObservedTime - lastObservedTime) / 1e6;

	if (missedFrames > 5 || bestError < (0.2 * 0.2))
	{
		lastObservedTime = bestObservedTime;

		// assuming we moved, then update the filter
		if (dtime)
		{
			if (_mode == MODELTESTS){
				Geometry2d::Point posKalmanDiff, posRbpfDiff;
				Geometry2d::Point velKalmanDiff, velRbpfDiff;
				Geometry2d::Point observedVel = (observedPos - prevObservedPos)*(1/dtime);
				float errorPosKalman, errorPosRbpf;
				float errorVelKalman, errorVelRbpf;

				kalmanUpdate(dtime);
				posKalmanDiff = observedPos - pos;
				velKalmanDiff = observedVel - vel;
				rbpfUpdate(dtime);
				posRbpfDiff = observedPos - pos;
				velRbpfDiff = observedVel - vel;

				errorPosKalman = posKalmanDiff.mag();
				errorPosRbpf = posRbpfDiff.mag();
				errorVelKalman = velKalmanDiff.mag();
				errorVelRbpf = velRbpfDiff.mag();

				kalmanTestPosError += errorPosKalman;
				rbpfTestPosError += errorPosRbpf;
				kalmanTestVelError += errorVelKalman;
				rbpfTestVelError += errorVelRbpf;
				//cout << "Total error (Kal, Rbpf): (" << kalmanTesPostError << "," << rbpfTestPosError << "), this obs error (Kal, Rbpf): (" << errorKalman << "," << errorRbpf << ")" << endl;
				cout << "Total pos error (Kal, Rbpf): (" << kalmanTestPosError << "," << rbpfTestPosError << "), total vel error (Kal, Rbpf): (" << kalmanTestVelError << "," << rbpfTestVelError << ")" << endl;
			} else if (_mode == KALMAN) {
				kalmanUpdate(dtime);
			} else if (_mode == ABG) {
				abgUpdate(dtime);
			} else if (_mode == RBPF) {
				rbpfUpdate(dtime);
			}
			prevObservedPos = observedPos;
		}
	} else {
		// Ball moved too far to possibly be a valid track, so just extrapolate from the last known state
		if (dtime)
		{
			if(_mode == MODELTESTS){
				cout << "Ball Model Tests: missed too many frames, extrapolating." << endl;
			}
			pos += vel * dtime + accel * 0.5f * dtime * dtime;
		}

		++missedFrames;
	}
	bestError = -1;
	*/
}
<commit_msg>Fixed coasting error<commit_after>// kate: indent-mode cstyle; indent-width 4; tab-width 4; space-indent false;
// vim:ai ts=4 et

#include <iostream>

#include <boost/foreach.hpp>

#include "BallModel.hpp"

using namespace std;

Modeling::BallModel::BallModel(mode_t mode, RobotModel::RobotMap *robotMap) :
	A(6,6), B(6,6), P(6,6), Q(6,6), R(2,2), H(2,6),
	Z(2), U(6), X0(6), _mode(mode), _robotMap(robotMap)
{
	lastObservedTime = 0;
	lastUpdatedTime = 0;

	if (_mode == MODELTESTS) {
		cout << "Running ball model tests..." << endl;
		initKalman();
		initRBPF();
		kalmanTestPosError = 0; kalmanTestVelError = 0;
		rbpfTestPosError = 0; rbpfTestVelError = 0;
	} else if (_mode == KALMAN) {
		initKalman();
	} else if (_mode == RBPF) {
		initRBPF();
	} else if (_mode == ABG) {
		initABG();
	} else {
		cout << "ERROR: Invalid initialization type, defaulting to RPBF!" << endl;
		_mode = RBPF;
		initRBPF();
	}
}

void Modeling::BallModel::initABG() {
	alpha = 1;
	beta = .4;
	gamma = .1;
}

void Modeling::BallModel::initKalman() {
	A.zero();
	B.zero();
	Q.zero();
	R.zero();
	H.zero();
	P.zero();
	X0.zero();

	//Process covariance between position and velocity (E[x,x_dot])
	// 	Q(1,0) = Q(4,3) = 0.01;

	//Process covariance between velocity and acceleration (E[x)dot,x_ddot])
	// 	Q(2,1) = Q(5,4) = 0.001;

	//Process covariance between position and acceleration (E[x,x_ddot])
	// 	Q(2,0) = Q(5,3) = 0.0001;

	//Process covariance (E[x,x], E[x_dot,x_dot], etc)
	Q(0,0) = Q(3,3) = 10;

	Q(1,1) = Q(4,4) = 10;

	Q(2,2) = Q(5,5) = 10;

	//Measurement Covariance for position in the x and the y
	R(0,0) = R(1,1) = 0.84;

	//Measurement Model. We can only measure position
	H(0,0) = H(1,3) = 1;

	//State Model
	A(0,0) = A(1,1) = A(2,2) = A(3,3) = A(4,4) = A(5,5) = 1;

	posKalman = new DifferenceKalmanFilter(&A, &B, &X0, &P, &Q, &R, &H);
}

void Modeling::BallModel::initRBPF() {
	// Construct initial state X (n x 1)
	Vector X(6); X.clear();
	// Construct initial state covariance P (n x n)
	Matrix P(6,6); P.clear(); P(0,0)=P(1,1)= P(2,2)=P(3,3)=P(4,4)=P(5,5)=0.01;
	// Create Rbpf
	int numParticles = 20; // Number of particles in filter
	raoBlackwellizedParticleFilter = new Rbpf(X,P,numParticles);
	// create model graph
	raoBlackwellizedParticleFilter->addModel(new RbpfModelRolling(_robotMap));
	raoBlackwellizedParticleFilter->addModel(new RbpfModelKicked(_robotMap));
	raoBlackwellizedParticleFilter->setTransProb(0,0,0.9);
	raoBlackwellizedParticleFilter->setTransProb(0,1,0.1);
	raoBlackwellizedParticleFilter->setTransProb(1,0,0.9);
	raoBlackwellizedParticleFilter->setTransProb(1,1,0.1);
}

Geometry2d::Point Modeling::BallModel::predictPosAtTime(float dtime)
{
	return pos + vel * dtime + accel * 0.5f * dtime * dtime;
}

void Modeling::BallModel::observation(uint64_t time, const Geometry2d::Point &pos, observation_mode obs_type)
{
	observation_type obs = {time, pos, obs_type};
	_observations.push_back(obs);

	// set lastObservedTime to the last observation's time
	if (time > lastObservedTime)
		lastObservedTime = time;
}

void Modeling::BallModel::kalmanUpdate(float dtime) {
	//Update model
	A(0,1) = dtime;
	A(0,2) = 0.5*dtime*dtime;

	A(1,2) = dtime;

	A(3,4) = dtime;
	A(3,5) = 0.5*dtime*dtime;

	A(4,5) = dtime;

	//Position
	Z(0) = observedPos.x;
	Z(1) = observedPos.y;

	posKalman->predict(&U);
	posKalman->correct(&Z);

	pos.x = (float)posKalman->state()->elt(0);
	vel.x = (float)posKalman->state()->elt(1);
	accel.x = (float)posKalman->state()->elt(2);
	pos.y = (float)posKalman->state()->elt(3);
	vel.y = (float)posKalman->state()->elt(4);
	accel.y = (float)posKalman->state()->elt(5);
}

void Modeling::BallModel::rbpfUpdate(float dtime) {
	raoBlackwellizedParticleFilter->update(observedPos.x,observedPos.y,dtime);
	RbpfState* bestState = raoBlackwellizedParticleFilter->getBestFilterState();
	pos.x = bestState->X(0);
	pos.y = bestState->X(1);
	vel.x = bestState->X(2);
	vel.y = bestState->X(3);
	accel.x = bestState->X(4);
	accel.y = bestState->X(5);
}

void Modeling::BallModel::rbpfUpdateMultipleObs(std::vector<observation_type> &obs){
	int numObs = obs.size();
	double x[numObs];
	double y[numObs];
	double dt[numObs];
	for(int i=obs.size()-1; i>=0; i--){
		x[i] = obs[i].pos.x;
		y[i] = obs[i].pos.y;
		dt[i] = (float)(obs[i].time - lastUpdatedTime) / 1e6;
	}
	raoBlackwellizedParticleFilter->updateMultipleObs(x,y,dt,numObs);
	RbpfState* bestState = raoBlackwellizedParticleFilter->getBestFilterState();
	pos.x = bestState->X(0);
	pos.y = bestState->X(1);
	vel.x = bestState->X(2);
	vel.y = bestState->X(3);
	accel.x = bestState->X(4);
	accel.y = bestState->X(5);
}

void Modeling::BallModel::abgUpdate(float dtime) {
	Geometry2d::Point predictPos = abgPos + vel * dtime + accel * 0.5f * dtime * dtime;
	Geometry2d::Point predictVel = vel + accel * dtime;

	Geometry2d::Point posError = observedPos - predictPos;
	abgPos = predictPos + posError * alpha;
	vel = predictVel + posError * beta / dtime;
	accel += posError * gamma / (dtime * dtime);
}

bool Modeling::BallModel::valid(uint64_t time) {
	return !_observations.empty() || ((time - lastUpdatedTime) < MaxCoastTime);
}

void Modeling::BallModel::update(uint64_t time)
{
	const bool verbose = false;

	if(_observations.empty()) {
		// coast the ball using simple integrator
		float dtime = (float)(time - lastUpdatedTime) / 1e6;
		pos = predictPosAtTime(dtime);
		vel += accel * 0.5f * dtime * dtime;
		return;
	}

	// loop through the observations and determine if we got vision observations
	bool gotCameraObservation = false;
	BOOST_FOREACH(const observation_type& obs, _observations) {
		if(obs.obs_type == BallModel::VISION){
			gotCameraObservation = true;
			break;
		}
	}

	// If there are camera observations, remove robot sensor observations.
	vector<observation_type> goodObs;
	if(gotCameraObservation){
		BOOST_FOREACH(const observation_type& obs, _observations) {
			if (obs.obs_type == BallModel::VISION) {
				goodObs.push_back(obs);
			}
		}
	} else {
		goodObs = _observations;
	}
	_observations = goodObs;
	if (verbose) cout << " ballModel has " << _observations.size() << " observations, updating..." << endl;

	// TODO: handle non-RBPF filters properly
	if (_mode != RBPF){
		cout << "update() not implemented in ballmodel.cpp" << endl;
	} else if (_mode == RBPF) {
		rbpfUpdateMultipleObs(_observations);
	}

	// remove previous observations after processing them
	_observations.clear();

	// remember last update
	lastUpdatedTime = time;

	/*
	float dtime = (float)(bestObservedTime - lastObservedTime) / 1e6;

	if (missedFrames > 5 || bestError < (0.2 * 0.2))
	{
		lastObservedTime = bestObservedTime;

		// assuming we moved, then update the filter
		if (dtime)
		{
			if (_mode == MODELTESTS){
				Geometry2d::Point posKalmanDiff, posRbpfDiff;
				Geometry2d::Point velKalmanDiff, velRbpfDiff;
				Geometry2d::Point observedVel = (observedPos - prevObservedPos)*(1/dtime);
				float errorPosKalman, errorPosRbpf;
				float errorVelKalman, errorVelRbpf;

				kalmanUpdate(dtime);
				posKalmanDiff = observedPos - pos;
				velKalmanDiff = observedVel - vel;
				rbpfUpdate(dtime);
				posRbpfDiff = observedPos - pos;
				velRbpfDiff = observedVel - vel;

				errorPosKalman = posKalmanDiff.mag();
				errorPosRbpf = posRbpfDiff.mag();
				errorVelKalman = velKalmanDiff.mag();
				errorVelRbpf = velRbpfDiff.mag();

				kalmanTestPosError += errorPosKalman;
				rbpfTestPosError += errorPosRbpf;
				kalmanTestVelError += errorVelKalman;
				rbpfTestVelError += errorVelRbpf;
				//cout << "Total error (Kal, Rbpf): (" << kalmanTesPostError << "," << rbpfTestPosError << "), this obs error (Kal, Rbpf): (" << errorKalman << "," << errorRbpf << ")" << endl;
				cout << "Total pos error (Kal, Rbpf): (" << kalmanTestPosError << "," << rbpfTestPosError << "), total vel error (Kal, Rbpf): (" << kalmanTestVelError << "," << rbpfTestVelError << ")" << endl;
			} else if (_mode == KALMAN) {
				kalmanUpdate(dtime);
			} else if (_mode == ABG) {
				abgUpdate(dtime);
			} else if (_mode == RBPF) {
				rbpfUpdate(dtime);
			}
			prevObservedPos = observedPos;
		}
	} else {
		// Ball moved too far to possibly be a valid track, so just extrapolate from the last known state
		if (dtime)
		{
			if(_mode == MODELTESTS){
				cout << "Ball Model Tests: missed too many frames, extrapolating." << endl;
			}
			pos += vel * dtime + accel * 0.5f * dtime * dtime;
		}

		++missedFrames;
	}
	bestError = -1;
	*/
}
<|endoftext|>


<commit_before>#pragma once

#include <QtWidgets/QWidget>

#include "PortType.hpp"
#include "NodeData.hpp"
#include "Serializable.hpp"
#include "NodeGeometry.hpp"
#include "NodeStyle.hpp"
#include "NodePainterDelegate.hpp"
#include "Export.hpp"
#include "memory.hpp"

namespace QtNodes
{

enum class NodeValidationState
{
  Valid,
  Warning,
  Error
};

class Connection;

class StyleCollection;

class NODE_EDITOR_PUBLIC NodeDataModel
  : public QObject
  , public Serializable
{
  Q_OBJECT

public:

  NodeDataModel();

  virtual
  ~NodeDataModel() = default;

  /// Caption is used in GUI
  virtual QString
  caption() const = 0;

  /// It is possible to hide caption in GUI
  virtual bool
  captionVisible() const { return true; }

  /// Port caption is used in GUI to label individual ports
  virtual QString
  portCaption(PortType, PortIndex) const { return QString(); }

  /// It is possible to hide port caption in GUI
  virtual bool
  portCaptionVisible(PortType, PortIndex) const { return false; }

  /// Name makes this model unique
  virtual QString
  name() const = 0;

public:

  QJsonObject
  save() const override;

public:

  virtual
  unsigned int nPorts(PortType portType) const = 0;

  virtual
  NodeDataType dataType(PortType portType, PortIndex portIndex) const = 0;

public:

  enum class ConnectionPolicy
  {
    One,
    Many,
  };

  virtual
  ConnectionPolicy
  portOutConnectionPolicy(PortIndex) const
  {
    return ConnectionPolicy::Many;
  }

  virtual
  ConnectionPolicy
  portInConnectionPolicy(PortIndex) const
  {
    return ConnectionPolicy::One;
  }

  NodeStyle const&
  nodeStyle() const;

  void
  setNodeStyle(NodeStyle const& style);

public:

  /// Triggers the algorithm
  virtual
  void
  setInData(std::shared_ptr<NodeData> nodeData,
            PortIndex port) = 0;

  // Use this if portInConnectionPolicy returns ConnectionPolicy::Many
  virtual
  void
  setInData(std::shared_ptr<NodeData> nodeData,
            PortIndex port,
            const QUuid& connectionId)
  {
    Q_UNUSED(connectionId);
    setInData(nodeData, port);
  }

  virtual
  std::shared_ptr<NodeData>
  outData(PortIndex port) = 0;

  /**
   * It is recommented to preform a lazy initialization for the
   * embedded widget and create it inside this function, not in the
   * constructor of the current model.
   *
   * Our Model Registry is able to shortly instantiate models in order
   * to call the non-static `Model::name()`. If the embedded widget is
   * allocated in the constructor but not actually embedded into some
   * QGraphicsProxyWidget, we'll gonna have a dangling pointer.
   */
  virtual
  QWidget *
  embeddedWidget() = 0;

  virtual
  bool
  resizable() const { return false; }

  virtual
  NodeValidationState
  validationState() const { return NodeValidationState::Valid; }

  virtual
  QString
  validationMessage() const { return QString(""); }

  virtual
  NodePainterDelegate* painterDelegate() const { return nullptr; }

public Q_SLOTS:

  virtual void
  inputConnectionCreated(Connection const&)
  {
  }

  virtual void
  inputConnectionDeleted(Connection const&)
  {
  }

  virtual void
  outputConnectionCreated(Connection const&)
  {
  }

  virtual void
  outputConnectionDeleted(Connection const&)
  {
  }

Q_SIGNALS:

  /// Triggers the updates in the nodes downstream.
  void
  dataUpdated(PortIndex index);

  /// Triggers the propagation of the empty data downstream.
  void
  dataInvalidated(PortIndex index);

  void
  computingStarted();

  void
  computingFinished();

  void embeddedWidgetSizeUpdated();

private:

  NodeStyle _nodeStyle;
};
}
<commit_msg>Add forward declaration in NodeDataModel.hpp (#323)<commit_after>#pragma once

#include <QtWidgets/QWidget>

#include "PortType.hpp"
#include "NodeData.hpp"
#include "Serializable.hpp"
#include "NodeGeometry.hpp"
#include "NodeStyle.hpp"
#include "NodePainterDelegate.hpp"
#include "Export.hpp"
#include "memory.hpp"

namespace QtNodes
{

class NodePainterDelegate;

enum class NodeValidationState
{
  Valid,
  Warning,
  Error
};

class Connection;

class StyleCollection;

class NODE_EDITOR_PUBLIC NodeDataModel
  : public QObject
  , public Serializable
{
  Q_OBJECT

public:

  NodeDataModel();

  virtual
  ~NodeDataModel() = default;

  /// Caption is used in GUI
  virtual QString
  caption() const = 0;

  /// It is possible to hide caption in GUI
  virtual bool
  captionVisible() const { return true; }

  /// Port caption is used in GUI to label individual ports
  virtual QString
  portCaption(PortType, PortIndex) const { return QString(); }

  /// It is possible to hide port caption in GUI
  virtual bool
  portCaptionVisible(PortType, PortIndex) const { return false; }

  /// Name makes this model unique
  virtual QString
  name() const = 0;

public:

  QJsonObject
  save() const override;

public:

  virtual
  unsigned int nPorts(PortType portType) const = 0;

  virtual
  NodeDataType dataType(PortType portType, PortIndex portIndex) const = 0;

public:

  enum class ConnectionPolicy
  {
    One,
    Many,
  };

  virtual
  ConnectionPolicy
  portOutConnectionPolicy(PortIndex) const
  {
    return ConnectionPolicy::Many;
  }

  virtual
  ConnectionPolicy
  portInConnectionPolicy(PortIndex) const
  {
    return ConnectionPolicy::One;
  }

  NodeStyle const&
  nodeStyle() const;

  void
  setNodeStyle(NodeStyle const& style);

public:

  /// Triggers the algorithm
  virtual
  void
  setInData(std::shared_ptr<NodeData> nodeData,
            PortIndex port) = 0;

  // Use this if portInConnectionPolicy returns ConnectionPolicy::Many
  virtual
  void
  setInData(std::shared_ptr<NodeData> nodeData,
            PortIndex port,
            const QUuid& connectionId)
  {
    Q_UNUSED(connectionId);
    setInData(nodeData, port);
  }

  virtual
  std::shared_ptr<NodeData>
  outData(PortIndex port) = 0;

  /**
   * It is recommented to preform a lazy initialization for the
   * embedded widget and create it inside this function, not in the
   * constructor of the current model.
   *
   * Our Model Registry is able to shortly instantiate models in order
   * to call the non-static `Model::name()`. If the embedded widget is
   * allocated in the constructor but not actually embedded into some
   * QGraphicsProxyWidget, we'll gonna have a dangling pointer.
   */
  virtual
  QWidget *
  embeddedWidget() = 0;

  virtual
  bool
  resizable() const { return false; }

  virtual
  NodeValidationState
  validationState() const { return NodeValidationState::Valid; }

  virtual
  QString
  validationMessage() const { return QString(""); }

  virtual
  NodePainterDelegate* painterDelegate() const { return nullptr; }

public Q_SLOTS:

  virtual void
  inputConnectionCreated(Connection const&)
  {
  }

  virtual void
  inputConnectionDeleted(Connection const&)
  {
  }

  virtual void
  outputConnectionCreated(Connection const&)
  {
  }

  virtual void
  outputConnectionDeleted(Connection const&)
  {
  }

Q_SIGNALS:

  /// Triggers the updates in the nodes downstream.
  void
  dataUpdated(PortIndex index);

  /// Triggers the propagation of the empty data downstream.
  void
  dataInvalidated(PortIndex index);

  void
  computingStarted();

  void
  computingFinished();

  void embeddedWidgetSizeUpdated();

private:

  NodeStyle _nodeStyle;
};
}
<|endoftext|>


<commit_before>/*
Copyright (C) 2007 <SWGEmu>

This File is part of Core3.

This program is free software; you can redistribute
it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software
Foundation; either version 2 of the License,
or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for
more details.

You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to
the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

Linking Engine3 statically or dynamically with other modules
is making a combined work based on Engine3.
Thus, the terms and conditions of the GNU Lesser General Public License
cover the whole combination.

In addition, as a special exception, the copyright holders of Engine3
give you permission to combine Engine3 program with free software
programs or libraries that are released under the GNU LGPL and with
code included in the standard release of Core3 under the GNU LGPL
license (or modified versions of such code, with unchanged license).
You may copy and distribute such a system following the terms of the
GNU LGPL for Engine3 and the licenses of the other code concerned,
provided that you include the source code of that other code when
and as the GNU LGPL requires distribution of source code.

Note that people who make modified versions of Engine3 are not obligated
to grant this special exception for their modified versions;
it is their choice whether to do so. The GNU Lesser General Public License
gives permission to release a modified version without this exception;
this exception also makes it possible to release a modified version
which carries forward this exception.
*/

#include "DeliverMissionScreenHandler.h"
#include "server/zone/objects/mission/DeliverMissionObjective.h"
#include "server/zone/managers/mission/spawnmaps/NpcSpawnPoint.h"

const String DeliverMissionScreenHandler::STARTSCREENHANDLERID = "convoscreenstart";

MissionObject* DeliverMissionScreenHandler::getRelevantMissionObject(CreatureObject* player, CreatureObject* npc) {
	if (player == NULL || npc == NULL) {
		return NULL;
	}

	SceneObject* datapad = player->getSlottedObject("datapad");

	if (datapad == NULL) {
		return NULL;
	}

	int datapadSize = datapad->getContainerObjectsSize();

	for (int i = 0; i < datapadSize; ++i) {
		if (datapad->getContainerObject(i)->isMissionObject()) {
			MissionObject* mission = cast<MissionObject*>(datapad->getContainerObject(i));

			if (mission != NULL && mission->getTypeCRC() == MissionObject::DELIVER) {
				DeliverMissionObjective* objective = cast<DeliverMissionObjective*>(mission->getMissionObjective());
				if (objective != NULL) {
					//Check if it is target or destination NPC
					if (isTargetNpc(objective, npc->getPosition()) ||
							isDestinationNpc(objective, npc->getPosition())) {
						return mission;
					}
				}
			}
		}
	}

	//No relevant mission found.
	return NULL;
}

bool DeliverMissionScreenHandler::isTargetNpc(DeliverMissionObjective* objective, const Vector3& npcPosition) {
	return isSameSpawnPoint(objective->getTargetSpawnPoint()->getPosition()->getX(), objective->getTargetSpawnPoint()->getPosition()->getY(), npcPosition);
}

bool DeliverMissionScreenHandler::isDestinationNpc(DeliverMissionObjective* objective, const Vector3& npcPosition) {
	return isSameSpawnPoint(objective->getDestinationSpawnPoint()->getPosition()->getX(), objective->getDestinationSpawnPoint()->getPosition()->getY(), npcPosition);
}

bool DeliverMissionScreenHandler::isSameSpawnPoint(const float& positionX, const float& positionY, const Vector3& comparisonPosition) {
	if (positionX == comparisonPosition.getX() &&
			positionY == comparisonPosition.getY()) {
		//Spawn point is the same.
		return true;
	}
	return false;
}

ConversationScreen* DeliverMissionScreenHandler::handleScreen(CreatureObject* conversingPlayer, CreatureObject* conversingNPC, int selectedOption, ConversationScreen* conversationScreen) {
	//Get relevant mission object if it exists.
	MissionObject* mission = getRelevantMissionObject(conversingPlayer, conversingNPC);

	if (mission == NULL) {
		//NPC is not related to any mission for this player.
		int randomAnswer = System::random(4);
		conversationScreen->setDialogText("@mission/mission_generic:deliver_incorrect_player_" + String::valueOf(randomAnswer));
	} else {
		//NPC is related to a mission for this player.
		DeliverMissionObjective* objective = cast<DeliverMissionObjective*>(mission->getMissionObjective());
		if (objective != NULL) {
			//Run mission logic.

			String text;
			if (isTargetNpc(objective, conversingNPC->getPosition())) {
				//Target NPC.
				if (objective->getObjectiveStatus() == DeliverMissionObjective::INITSTATUS) {
					objective->updateMissionStatus(conversingPlayer);
					switch (mission->getFaction()) {
					case MissionObject::FACTIONIMPERIAL:
						conversationScreen->setDialogText("@mission/mission_deliver_imperial_easy:m" + String::valueOf(mission->getMissionNumber()) + "p");
						break;
					case MissionObject::FACTIONREBEL:
						conversationScreen->setDialogText("@mission/mission_deliver_rebel_easy:m" + String::valueOf(mission->getMissionNumber()) + "p");
						break;
					default:
						conversationScreen->setDialogText("@mission/mission_deliver_neutral_easy:m" + String::valueOf(mission->getMissionNumber()) + "p");
						break;
					}
				} else {
					text = "@mission/mission_generic:deliver_already_picked_up";
					conversationScreen->setDialogText(text);
				}
			} else {
				//Destination NPC.
				if (objective->getObjectiveStatus() == DeliverMissionObjective::PICKEDUPSTATUS) {
					objective->updateMissionStatus(conversingPlayer);
					switch (mission->getFaction()) {
					case MissionObject::FACTIONIMPERIAL:
						conversationScreen->setDialogText("@mission/mission_deliver_imperial_easy:m" + String::valueOf(mission->getMissionNumber()) + "r");
						break;
					case MissionObject::FACTIONREBEL:
						conversationScreen->setDialogText("@mission/mission_deliver_rebel_easy:m" + String::valueOf(mission->getMissionNumber()) + "r");
						break;
					default:
						conversationScreen->setDialogText("@mission/mission_deliver_neutral_easy:m" + String::valueOf(mission->getMissionNumber()) + "r");
						break;
					}
				} else if (objective->getObjectiveStatus() == DeliverMissionObjective::INITSTATUS) {
					text = "@mission/mission_generic:give_item";
					conversationScreen->setDialogText(text);
				} else {
					text = "@mission/mission_generic:deliver_already_dropped_off";
					conversationScreen->setDialogText(text);
				}
			}
		}
	}
	return conversationScreen;
}
<commit_msg>[fixed] Delivery missions: end NPC will tell you to give him/her an item if you deleted/removed the item you should give him/her from your inventory.<commit_after>/*
Copyright (C) 2007 <SWGEmu>

This File is part of Core3.

This program is free software; you can redistribute
it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software
Foundation; either version 2 of the License,
or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for
more details.

You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to
the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

Linking Engine3 statically or dynamically with other modules
is making a combined work based on Engine3.
Thus, the terms and conditions of the GNU Lesser General Public License
cover the whole combination.

In addition, as a special exception, the copyright holders of Engine3
give you permission to combine Engine3 program with free software
programs or libraries that are released under the GNU LGPL and with
code included in the standard release of Core3 under the GNU LGPL
license (or modified versions of such code, with unchanged license).
You may copy and distribute such a system following the terms of the
GNU LGPL for Engine3 and the licenses of the other code concerned,
provided that you include the source code of that other code when
and as the GNU LGPL requires distribution of source code.

Note that people who make modified versions of Engine3 are not obligated
to grant this special exception for their modified versions;
it is their choice whether to do so. The GNU Lesser General Public License
gives permission to release a modified version without this exception;
this exception also makes it possible to release a modified version
which carries forward this exception.
*/

#include "DeliverMissionScreenHandler.h"
#include "server/zone/objects/mission/DeliverMissionObjective.h"
#include "server/zone/managers/mission/spawnmaps/NpcSpawnPoint.h"

const String DeliverMissionScreenHandler::STARTSCREENHANDLERID = "convoscreenstart";

MissionObject* DeliverMissionScreenHandler::getRelevantMissionObject(CreatureObject* player, CreatureObject* npc) {
	if (player == NULL || npc == NULL) {
		return NULL;
	}

	SceneObject* datapad = player->getSlottedObject("datapad");

	if (datapad == NULL) {
		return NULL;
	}

	int datapadSize = datapad->getContainerObjectsSize();

	for (int i = 0; i < datapadSize; ++i) {
		if (datapad->getContainerObject(i)->isMissionObject()) {
			MissionObject* mission = cast<MissionObject*>(datapad->getContainerObject(i));

			if (mission != NULL && mission->getTypeCRC() == MissionObject::DELIVER) {
				DeliverMissionObjective* objective = cast<DeliverMissionObjective*>(mission->getMissionObjective());
				if (objective != NULL) {
					//Check if it is target or destination NPC
					if (isTargetNpc(objective, npc->getPosition()) ||
							isDestinationNpc(objective, npc->getPosition())) {
						return mission;
					}
				}
			}
		}
	}

	//No relevant mission found.
	return NULL;
}

bool DeliverMissionScreenHandler::isTargetNpc(DeliverMissionObjective* objective, const Vector3& npcPosition) {
	return isSameSpawnPoint(objective->getTargetSpawnPoint()->getPosition()->getX(), objective->getTargetSpawnPoint()->getPosition()->getY(), npcPosition);
}

bool DeliverMissionScreenHandler::isDestinationNpc(DeliverMissionObjective* objective, const Vector3& npcPosition) {
	return isSameSpawnPoint(objective->getDestinationSpawnPoint()->getPosition()->getX(), objective->getDestinationSpawnPoint()->getPosition()->getY(), npcPosition);
}

bool DeliverMissionScreenHandler::isSameSpawnPoint(const float& positionX, const float& positionY, const Vector3& comparisonPosition) {
	if (positionX == comparisonPosition.getX() &&
			positionY == comparisonPosition.getY()) {
		//Spawn point is the same.
		return true;
	}
	return false;
}

ConversationScreen* DeliverMissionScreenHandler::handleScreen(CreatureObject* conversingPlayer, CreatureObject* conversingNPC, int selectedOption, ConversationScreen* conversationScreen) {
	//Get relevant mission object if it exists.
	MissionObject* mission = getRelevantMissionObject(conversingPlayer, conversingNPC);

	if (mission == NULL) {
		//NPC is not related to any mission for this player.
		int randomAnswer = System::random(4);
		conversationScreen->setDialogText("@mission/mission_generic:deliver_incorrect_player_" + String::valueOf(randomAnswer));
	} else {
		//NPC is related to a mission for this player.
		DeliverMissionObjective* objective = cast<DeliverMissionObjective*>(mission->getMissionObjective());
		if (objective != NULL) {
			//Run mission logic.

			String text;
			if (isTargetNpc(objective, conversingNPC->getPosition())) {
				//Target NPC.
				if (objective->getObjectiveStatus() == DeliverMissionObjective::INITSTATUS) {
					objective->updateMissionStatus(conversingPlayer);
					switch (mission->getFaction()) {
					case MissionObject::FACTIONIMPERIAL:
						conversationScreen->setDialogText("@mission/mission_deliver_imperial_easy:m" + String::valueOf(mission->getMissionNumber()) + "p");
						break;
					case MissionObject::FACTIONREBEL:
						conversationScreen->setDialogText("@mission/mission_deliver_rebel_easy:m" + String::valueOf(mission->getMissionNumber()) + "p");
						break;
					default:
						conversationScreen->setDialogText("@mission/mission_deliver_neutral_easy:m" + String::valueOf(mission->getMissionNumber()) + "p");
						break;
					}
				} else {
					text = "@mission/mission_generic:deliver_already_picked_up";
					conversationScreen->setDialogText(text);
				}
			} else {
				//Destination NPC.
				if (objective->getObjectiveStatus() == DeliverMissionObjective::PICKEDUPSTATUS) {
					objective->updateMissionStatus(conversingPlayer);
					if (objective->getObjectiveStatus() == DeliverMissionObjective::DELIVEREDSTATUS) {
						switch (mission->getFaction()) {
						case MissionObject::FACTIONIMPERIAL:
							conversationScreen->setDialogText("@mission/mission_deliver_imperial_easy:m" + String::valueOf(mission->getMissionNumber()) + "r");
							break;
						case MissionObject::FACTIONREBEL:
							conversationScreen->setDialogText("@mission/mission_deliver_rebel_easy:m" + String::valueOf(mission->getMissionNumber()) + "r");
							break;
						default:
							conversationScreen->setDialogText("@mission/mission_deliver_neutral_easy:m" + String::valueOf(mission->getMissionNumber()) + "r");
							break;
						}
					} else {
						text = "@mission/mission_generic:give_item";
						conversationScreen->setDialogText(text);
					}
				} else if (objective->getObjectiveStatus() == DeliverMissionObjective::INITSTATUS) {
					text = "@mission/mission_generic:give_item";
					conversationScreen->setDialogText(text);
				} else {
					text = "@mission/mission_generic:deliver_already_dropped_off";
					conversationScreen->setDialogText(text);
				}
			}
		}
	}
	return conversationScreen;
}
<|endoftext|>