| Index: cc/base/pyramid_sequence.h
|
| diff --git a/cc/base/pyramid_sequence.h b/cc/base/pyramid_sequence.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8c884a1074e2b9a2c16c0d316daf12434cf9c4ec
|
| --- /dev/null
|
| +++ b/cc/base/pyramid_sequence.h
|
| @@ -0,0 +1,703 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef CC_BASE_PYRAMID_SEQUENCE_H_
|
| +#define CC_BASE_PYRAMID_SEQUENCE_H_
|
| +
|
| +#include <vector>
|
| +
|
| +#include "base/logging.h"
|
| +#include "cc/base/cc_export.h"
|
| +#include "cc/base/index_rect.h"
|
| +
|
| +namespace cc {
|
| +
|
| +// The pyramid sequence covers following 4 directions while iterating, where R
|
| +// is right, T is top, L is left and B is bottom.
|
| +// T
|
| +// L * R
|
| +// B
|
| +enum class CoverageDirection : int {
|
| + NONE = -1,
|
| + RIGHT = 0,
|
| + TOP,
|
| + LEFT,
|
| + BOTTOM,
|
| + SIZE
|
| +};
|
| +
|
| +// This class provides iterating mechanism for numbers between defined bounds.
|
| +// e.g. For interval having bounds 3 as start and 6 as end, represented as
|
| +// [3, 6], the interval returns 3, 4, 5, 6 sequence for Iterator traversal and
|
| +// returns 6, 5, 4, 3 for ReverseIterator traversal.
|
| +//
|
| +// start end
|
| +// | |
|
| +// V V
|
| +// ┌───┬───┬───┬───┐
|
| +// │ 3 │ 4 │ 5 │ 6 │
|
| +// └───┴───┴───┴───┘
|
| +class CC_EXPORT Interval {
|
| + public:
|
| + class Iterator;
|
| + class ReverseIterator;
|
| +
|
| + Interval() : empty_(true) {}
|
| + Interval(int start, int end) : empty_(false), start_(start), end_(end) {}
|
| +
|
| + Iterator Begin();
|
| + ReverseIterator ReverseBegin();
|
| +
|
| + // Return the bounds of the interval.
|
| + int start() const { return start_; }
|
| + int end() const { return end_; }
|
| +
|
| + // Returns true if interval is empty. Empty interval does not return any
|
| + // index on traversing.
|
| + bool IsEmpty() const { return empty_; }
|
| +
|
| + // Returns the distance between |start_| and |end_| which includes both
|
| + // |start_| and |end_|.
|
| + int GetSpan() const;
|
| +
|
| + // Return clamped indices for the given indices.
|
| + int GetForwardClampedIndex(int index) const;
|
| + int GetBackwardClampedIndex(int index) const;
|
| +
|
| + // Clamp this interval to the given interval. For these functions, interval
|
| + // and other interval to which this interval is to be clammped should be in
|
| + // the same direction, i.e. both intervals should have either
|
| + // |start_| <= |end_| or |start_| >= |end_|.
|
| + void ForwardClampTo(const Interval& other);
|
| + void BackwardClampTo(const Interval& other);
|
| +
|
| + // Return the inflated intervals for the given |level|.
|
| + Interval GetForwardInflatedInterval(int level) const;
|
| + Interval GetBackwardInflatedInterval(int level) const;
|
| +
|
| + // Returns true if interval contains the given index.
|
| + bool Contains(int index) const;
|
| +
|
| + // For these functions, interval and other interval to which first one is to
|
| + // be intersected should be in the same direction, i.e. both intervals should
|
| + // have |start_| <= |end_| or |start_| >= |end_|.
|
| + bool Intersects(const Interval& interval) const;
|
| + void Intersect(const Interval& interval);
|
| +
|
| + // Iterators.
|
| + class IteratorBase {
|
| + public:
|
| + IteratorBase();
|
| +
|
| + operator bool() const { return within_bounds_; }
|
| + IteratorBase& operator++();
|
| + int index() { return current_index_; }
|
| +
|
| + protected:
|
| + explicit IteratorBase(Interval* interval);
|
| +
|
| + virtual bool IsWithinBounds() = 0;
|
| +
|
| + Interval* interval_;
|
| + bool within_bounds_;
|
| + int step_;
|
| + int current_index_;
|
| + };
|
| +
|
| + class Iterator : public IteratorBase {
|
| + public:
|
| + Iterator();
|
| +
|
| + private:
|
| + explicit Iterator(Interval* interval);
|
| +
|
| + bool IsWithinBounds() override;
|
| +
|
| + friend class Interval;
|
| + };
|
| +
|
| + class ReverseIterator : public IteratorBase {
|
| + public:
|
| + ReverseIterator();
|
| +
|
| + private:
|
| + explicit ReverseIterator(Interval* interval);
|
| +
|
| + bool IsWithinBounds() override;
|
| +
|
| + friend class Interval;
|
| + };
|
| +
|
| + private:
|
| + bool empty_;
|
| + int start_;
|
| + int end_;
|
| +};
|
| +
|
| +// This class provides affinity based interating mechanism for the given
|
| +// |interval| [start, end] with functionality of inflating the |interval|.
|
| +// The interval inflation means expanding the start and end by n steps forward
|
| +// or backward, based on |forward_direction| argument provided. Suppose the
|
| +// LinearSequence has interval [3, 3] i.e. start = 3 and end = 3, the interval
|
| +// inflated by 1 step in forward direction would be [2, 4] and that of in
|
| +// backward direction would be [4, 2].
|
| +// The affinity based traversing means portion of |interval| that intersects
|
| +// with |affinity_interval| is traversed before remaining two portions of
|
| +// |interval|. Internally the |interval| is split up into three sub-intervals
|
| +// before traversing as |affinity_sub_interval_|, |before_sub_interval_| and
|
| +// |after_sub_interval_|. These sub-intervals are traversed instead of directly
|
| +// traversing |interval|. First |affinity_sub_interval_| is traversed fully,
|
| +// then remaining two sub-intervals are traversed in alternative fashion.
|
| +//
|
| +// e.g. Suppose LinearSequence has interval [0, 9] and affinity interval
|
| +// [4, 6], then the interval is splitted into three sub-intervals viz. [4, 6],
|
| +// [3, 0], [7, 9].
|
| +//
|
| +// affinity_sub_interval
|
| +// ┌─────^─────┐
|
| +// ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
|
| +// │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │
|
| +// └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
|
| +// └───────v───────┘ └─────v─────┘
|
| +// before_sub_interval after_sub_interval
|
| +//
|
| +// On traversal, Iterator returns the sequence as 4, 5, 6, 3, 7, 2, 8, 1, 9, 0
|
| +// and RerverseIterator returns the sequence as 0, 9, 1, 8, 2, 7, 3, 6, 5, 4.
|
| +class CC_EXPORT LinearSequence {
|
| + public:
|
| + class Iterator;
|
| + class ReverseIterator;
|
| +
|
| + LinearSequence();
|
| + // The |interval| is used for actual traversal. The |affinity_interval| is
|
| + // used for defining affinity in the |interval|. While traversing portion of
|
| + // |interval| which intersects |affinity_interval| is traversed before
|
| + // remaining portions of the interval. The |inflate_limit| is used to clamp
|
| + // the |interval|, when it is inflated to any given |level|.
|
| + LinearSequence(bool forward_direction,
|
| + Interval interval,
|
| + Interval affinity_interval,
|
| + Interval inflate_limit);
|
| + LinearSequence(const LinearSequence& other);
|
| + LinearSequence(LinearSequence&& other);
|
| + ~LinearSequence();
|
| +
|
| + LinearSequence& operator=(const LinearSequence& other);
|
| + LinearSequence& operator=(LinearSequence&& other);
|
| +
|
| + Iterator Begin();
|
| + ReverseIterator ReverseBegin();
|
| +
|
| + // This function inflates the original |interval| to the given |level|,
|
| + // where level >= 0.
|
| + void InflateToLevel(int level);
|
| +
|
| + // Iterators.
|
| + class IteratorBase {
|
| + public:
|
| + IteratorBase();
|
| + IteratorBase(const IteratorBase& other);
|
| + IteratorBase(IteratorBase&& other);
|
| + ~IteratorBase();
|
| +
|
| + IteratorBase& operator=(const IteratorBase& other);
|
| + IteratorBase& operator=(IteratorBase&& other);
|
| +
|
| + operator bool() const { return within_bounds_; }
|
| + IteratorBase& operator++();
|
| + int index() { return current_index_; }
|
| +
|
| + protected:
|
| + enum class SubIntervalIteratorType : unsigned int {
|
| + AFFINITY,
|
| + BEFORE,
|
| + AFTER
|
| + };
|
| +
|
| + explicit IteratorBase(LinearSequence* level_sequence);
|
| +
|
| + virtual void Setup() = 0;
|
| + virtual SubIntervalIteratorType GetCurrentSubIntervalIteratorType() = 0;
|
| + virtual bool IsWithinBounds() = 0;
|
| +
|
| + LinearSequence* level_sequence_;
|
| + bool within_bounds_;
|
| + int current_index_;
|
| + Interval::IteratorBase* sub_interval_iterators_[3];
|
| + SubIntervalIteratorType current_sub_interval_iterator_;
|
| + };
|
| +
|
| + class Iterator : public IteratorBase {
|
| + public:
|
| + Iterator();
|
| + Iterator(const Iterator& other);
|
| + Iterator(Iterator&& other);
|
| + ~Iterator();
|
| +
|
| + Iterator& operator=(const Iterator& other);
|
| + Iterator& operator=(Iterator&& other);
|
| +
|
| + private:
|
| + explicit Iterator(LinearSequence* level_sequence);
|
| +
|
| + void Setup() override;
|
| + SubIntervalIteratorType GetCurrentSubIntervalIteratorType() override;
|
| + bool IsWithinBounds() override;
|
| +
|
| + Interval::Iterator affinity_sub_interval_iterator_;
|
| + Interval::Iterator before_sub_interval_iterator_;
|
| + Interval::Iterator after_sub_interval_iterator_;
|
| + bool before_first_;
|
| +
|
| + friend class LinearSequence;
|
| + };
|
| +
|
| + class ReverseIterator : public IteratorBase {
|
| + public:
|
| + ReverseIterator();
|
| + ReverseIterator(const ReverseIterator& other);
|
| + ReverseIterator(ReverseIterator&& other);
|
| + ~ReverseIterator();
|
| +
|
| + ReverseIterator& operator=(const ReverseIterator& other);
|
| + ReverseIterator& operator=(ReverseIterator&& other);
|
| +
|
| + private:
|
| + explicit ReverseIterator(LinearSequence* level_sequence);
|
| +
|
| + void Setup() override;
|
| + SubIntervalIteratorType GetCurrentSubIntervalIteratorType() override;
|
| + bool IsWithinBounds() override;
|
| +
|
| + Interval::ReverseIterator affinity_sub_interval_reverse_iterator_;
|
| + Interval::ReverseIterator before_sub_interval_reverse_iterator_;
|
| + Interval::ReverseIterator after_sub_interval_reverse_iterator_;
|
| + bool after_first_;
|
| + int before_sub_interval_span_;
|
| + int after_sub_interval_span_;
|
| +
|
| + friend class LinearSequence;
|
| + };
|
| +
|
| + private:
|
| + void TrisectInterval();
|
| +
|
| + bool forward_direction_;
|
| + Interval interval_;
|
| + Interval inflate_limit_;
|
| + Interval affinity_interval_;
|
| +
|
| + Interval initial_interval_;
|
| +
|
| + // The |interval_| is split up into following sub-intervals such a way that
|
| + // they are non-intersecting, adjacent and union of these three sub-intervals
|
| + // is |interval_|.
|
| + Interval affinity_sub_interval_;
|
| + Interval before_sub_interval_;
|
| + Interval after_sub_interval_;
|
| +};
|
| +
|
| +// This class implements the 2D sequence (x, y) which uses LinearSequence and
|
| +// Interval to represent the co-ordinates. The linear sequence
|
| +// |traversal_sequence| is used for traversing the actual sequence cross the
|
| +// direction and |level_interval| is used for computing the number of levels in
|
| +// the |traversal_sequence|. The interval in |traversal_sequence| can be
|
| +// inflated max to the levels given by |level_interval|.
|
| +// This class uses LevelDistance structure to represent the distance associated
|
| +// with the level. The first level has distance 0, to represent the minimum
|
| +// distance for the origin level, and increments by the step of |distance|
|
| +// given in LevelDistance for every level. Suppose there are 5 levels and
|
| +// distance is 10, then the levels would have distances as 0, 10, 20, 30, 40.
|
| +// The distances are stored in the sorted order in vector, so that the distance
|
| +// at front is minimum, while the distance at back is maximum. The layout of
|
| +// the level distance vector for the example would be (0, 0), (1, 10), (2, 20),
|
| +// (3, 30), (4, 40).
|
| +//
|
| +// e.g. If traversal sequence has interval [3, 4], number of levels is 3 and
|
| +// distance is 10, then the Iterator would give following data on traversal.
|
| +//
|
| +// traversal_sequence level_index
|
| +// [3, 4] 0
|
| +// [2, 5] 1
|
| +// [1, 6] 2
|
| +//
|
| +// The order of iteration for ReverseIterator would be as given below.
|
| +//
|
| +// traversal_sequence level index
|
| +// [1, 6] 2
|
| +// [2, 5] 1
|
| +// [3, 4] 0
|
| +//
|
| +// The indices (x, y) for the iterator are as given below.
|
| +//
|
| +// (3, 0), (4, 0) (level 1)
|
| +// (2, 1), (3, 1), (4, 1), (5, 1), (level 2)
|
| +// (1, 2), (2, 2), (3, 2), (4, 2), (5, 2), (6, 2) (level 3)
|
| +//
|
| +// In a way the original interval in |traversal_sequence| and inflated
|
| +// intervals form triangular geometry in co-ordinate space as given below,
|
| +// hence the name TriangularSequence.
|
| +//
|
| +// x 0 1 2 3 4 5 6
|
| +// y ┌───┬───┬───┬───┬───┬───┬───┐
|
| +// 0 │ │ │ │ 3 │ 4 │ │ │ (level 1, distance 0)
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// 1 │ │ │ 2 │ 3 │ 4 │ 5 │ │ (level 2, distance 10)
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// 2 │ │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ (level 3, distance 20)
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// 3 │ │ │ │ │ │ │ │
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// 4 │ │ │ │ │ │ │ │
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// 5 │ │ │ │ │ │ │ │
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// 6 │ │ │ │ │ │ │ │
|
| +// └───┴───┴───┴───┴───┴───┴───┘
|
| +class CC_EXPORT TriangularSequence {
|
| + public:
|
| + class Iterator;
|
| + class ReverseIterator;
|
| +
|
| + TriangularSequence();
|
| + // The |traversal_sequence| defines the sequence for traversal and
|
| + // |level_interval| defines the number of levels for |traversal_sequence|.
|
| + // If |should_swap_index_representation| is false, then the indices in
|
| + // |traversal_sequence| represent the x indices and level indices in
|
| + // |level_interval| represent the y indices, otherwise vice-versa. The
|
| + // |levels_to_skip| defines the number of levels which should be skipped to
|
| + // avoid unnecessary traversing. Check PyramidSequence::PyramidSequence() for
|
| + // more details on level skipping. The |distance| defines the length for the
|
| + // index.
|
| + TriangularSequence(CoverageDirection coverage_direction,
|
| + LinearSequence&& traversal_sequence,
|
| + Interval&& level_interval,
|
| + bool should_swap_index_representation,
|
| + int levels_to_skip,
|
| + int distance);
|
| + TriangularSequence(const TriangularSequence& other);
|
| + TriangularSequence(TriangularSequence&& other);
|
| + ~TriangularSequence();
|
| +
|
| + TriangularSequence& operator=(const TriangularSequence& other);
|
| + TriangularSequence& operator=(TriangularSequence&& other);
|
| +
|
| + Iterator Begin();
|
| + ReverseIterator ReverseBegin();
|
| +
|
| + CoverageDirection coverage_direction() const { return coverage_direction_; }
|
| +
|
| + struct LevelDistance {
|
| + LevelDistance(int interval_level, int level_index, int distance)
|
| + : interval_level(interval_level),
|
| + level_index(level_index),
|
| + distance(distance) {}
|
| +
|
| + int interval_level;
|
| + int level_index;
|
| + int distance;
|
| + };
|
| +
|
| + class IteratorBase {
|
| + public:
|
| + IteratorBase();
|
| + IteratorBase(const IteratorBase& other);
|
| + IteratorBase(IteratorBase&& other);
|
| + ~IteratorBase();
|
| +
|
| + IteratorBase& operator=(const IteratorBase& other);
|
| + IteratorBase& operator=(IteratorBase&& other);
|
| +
|
| + operator bool() const { return !level_distances_.empty(); }
|
| + IteratorBase& operator++();
|
| + LinearSequence* traversal_sequence() {
|
| + DCHECK(*this);
|
| + return &traversal_sequence_;
|
| + }
|
| + int level_index() {
|
| + DCHECK(*this);
|
| + return current_level_index_;
|
| + }
|
| +
|
| + bool is_index_representation_swapped() const {
|
| + return should_swap_index_representation_;
|
| + }
|
| +
|
| + virtual int GetNextDistance() const = 0;
|
| +
|
| + protected:
|
| + explicit IteratorBase(TriangularSequence* triangular_sequence);
|
| +
|
| + virtual void Advance() = 0;
|
| + virtual void UpdateCurrent() = 0;
|
| +
|
| + LinearSequence traversal_sequence_;
|
| + bool should_swap_index_representation_;
|
| + std::vector<LevelDistance> level_distances_;
|
| + int current_level_index_;
|
| + };
|
| +
|
| + class Iterator : public IteratorBase {
|
| + public:
|
| + Iterator();
|
| +
|
| + // Returns next minimum distance.
|
| + int GetNextDistance() const override;
|
| +
|
| + private:
|
| + explicit Iterator(TriangularSequence* triangular_sequence);
|
| +
|
| + void Advance() override;
|
| + void UpdateCurrent() override;
|
| +
|
| + friend class TriangularSequence;
|
| + };
|
| +
|
| + class ReverseIterator : public IteratorBase {
|
| + public:
|
| + ReverseIterator();
|
| +
|
| + // Returns next maximum distance.
|
| + int GetNextDistance() const override;
|
| +
|
| + private:
|
| + explicit ReverseIterator(TriangularSequence* triangular_sequence);
|
| +
|
| + void Advance() override;
|
| + void UpdateCurrent() override;
|
| +
|
| + friend class TriangularSequence;
|
| + };
|
| +
|
| + typedef std::vector<TriangularSequence> Vector;
|
| + typedef std::vector<TriangularSequence::IteratorBase> IteratorVector;
|
| +
|
| + private:
|
| + CoverageDirection coverage_direction_;
|
| + LinearSequence traversal_sequence_;
|
| + Interval level_interval_;
|
| + bool should_swap_index_representation_;
|
| + int levels_to_skip_;
|
| + int distance_;
|
| +};
|
| +
|
| +// The pyramid sequence consists of 4 triangular sequences, one for each of
|
| +// the directions considered counter-clockwise or clockwise. The ideal pyramid
|
| +// sequence is as given below where it has all triangular sequences in 4
|
| +// directions.
|
| +//
|
| +// ┌───┬───┬───┬───┬───┬───┬───┐
|
| +// │ L │ T │ T │ T │ T │ T │ R │
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// │ L │ L │ T │ T │ T │ R │ R │
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// │ L │ L │ L │ T │ R │ R │ R │
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// │ L │ L │ L │ * │ R │ R │ R │
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// │ L │ L │ L │ B │ R │ R │ R │
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// │ L │ L │ B │ B │ B │ R │ R │
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// │ L │ B │ B │ B │ B │ B │ R │
|
| +// └───┴───┴───┴───┴───┴───┴───┘
|
| +//
|
| +// The triangular sequences for the above pyramid sequence are shown below.
|
| +// * represents the center.
|
| +//
|
| +// (T = top)
|
| +// ┌───┬───┬───┬───┬───┐
|
| +// │ T │ T │ T │ T │ T │
|
| +// ┌───┐ └───┼───┼───┼───┼───┘ ┌───┐
|
| +// │ L │ │ T │ T │ T │ │ R │
|
| +// ├───┼───┐ └───┼───┼───┘ ┌───┼───┤
|
| +// │ L │ L │ │ T │ │ R │ R │
|
| +// ├───┼───┼───┐ └───┘ ┌───┼───┼───┤
|
| +// │ L │ L │ L │ │ R │ R │ R │
|
| +// ├───┼───┼───┤ ┌───┐ ├───┼───┼───┤
|
| +// (L = left) │ L │ L │ L │ │ * │ │ R │ R │ R │ (R = right)
|
| +// ├───┼───┼───┤ └───┘ ├───┼───┼───┤
|
| +// │ L │ L │ L │ │ R │ R │ R │
|
| +// ├───┼───┼───┘ ┌───┐ └───┼───┼───┤
|
| +// │ L │ L │ │ B │ │ R │ R │
|
| +// ├───┼───┘ ┌───┼───┼───┐ └───┼───┤
|
| +// │ L │ │ B │ B │ B │ │ R │
|
| +// └───┘ ┌───┼───┼───┼───┼───┐ └───┘
|
| +// │ B │ B │ B │ B │ B │
|
| +// └───┴───┴───┴───┴───┘
|
| +// (B = bottom)
|
| +//
|
| +// This sequence iterates over all the underlined triangular sequences level by
|
| +// level in increasing or decreasing order of distances. The increasing order of
|
| +// distances can be iterated using Iterator, while the decreasing order of
|
| +// distances can be iterated using ReverseIterator. The default coverage for
|
| +// internal triangular sequences is R, T, L, B forming spiral order.
|
| +// The iteration sequence generated by Iterator is as given below.
|
| +// (Iteration is considered counter-clockwise.)
|
| +//
|
| +// x 0 1 2 3 4 5 6
|
| +// y ┌───┬───┬───┬───┬───┬───┬───┐
|
| +// 0 │ 42│ 36│ 34│ 32│ 33│ 35│ 31│
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// 1 │ 40│ 20│ 16│ 14│ 15│ 13│ 29│
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// 2 │ 38│ 18│ 6│ 4│ 3│ 11│ 27│
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// 3 │ 37│ 17│ 5│ *│ 1│ 9│ 25│
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// 4 │ 39│ 19│ 7│ 8│ 2│ 10│ 26│
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// 5 │ 41│ 21│ 23│ 22│ 24│ 12│ 28│
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// 6 │ 43│ 47│ 45│ 44│ 46│ 48│ 30│
|
| +// └───┴───┴───┴───┴───┴───┴───┘
|
| +//
|
| +// The iteration sequence generated by ReverseIterator is as given below.
|
| +// (Iteration is considered clockwise.)
|
| +//
|
| +// x 0 1 2 3 4 5 6
|
| +// y ┌───┬───┬───┬───┬───┬───┬───┐
|
| +// 0 │ 7│ 13│ 15│ 17│ 16│ 14│ 18│
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// 1 │ 9│ 29│ 33│ 35│ 34│ 36│ 20│
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// 2 │ 11│ 31│ 43│ 45│ 46│ 38│ 22│
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// 3 │ 12│ 32│ 44│ *│ 48│ 40│ 24│
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// 4 │ 10│ 30│ 42│ 41│ 47│ 39│ 23│
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// 5 │ 8│ 28│ 26│ 27│ 25│ 37│ 21│
|
| +// ├───┼───┼───┼───┼───┼───┼───┤
|
| +// 6 │ 6│ 2│ 4│ 5│ 3│ 1│ 19│
|
| +// └───┴───┴───┴───┴───┴───┴───┘
|
| +class CC_EXPORT PyramidSequence {
|
| + public:
|
| + class Iterator;
|
| + class ReverseIterator;
|
| +
|
| + PyramidSequence();
|
| + // The |around_index_rect| is the index rect computed around some index rect,
|
| + // called as center index rect. In the above example, center index rect is
|
| + // (3, 3, 3, 3), so around index rect for it is (2, 4, 2, 4).
|
| + // The |consider_index_rect| is used to limit the coverage and the
|
| + // |ignore_index_rect| is used to ignore the indices from coverage. For above
|
| + // example consider index rect is (0, 6, 0, 6) and ignore index rect is
|
| + // (-1, -1, -1, -1).
|
| + // The width and height specify the width and height of the single index. This
|
| + // is used for traversing indices based on their distances from center index
|
| + // rect.
|
| + PyramidSequence(const IndexRect& around_index_rect,
|
| + const IndexRect& consider_index_rect,
|
| + const IndexRect& ignore_index_rect,
|
| + int width,
|
| + int height);
|
| + PyramidSequence(const PyramidSequence& other);
|
| + PyramidSequence(PyramidSequence&& other);
|
| + virtual ~PyramidSequence();
|
| +
|
| + PyramidSequence& operator=(const PyramidSequence& other);
|
| + PyramidSequence& operator=(PyramidSequence&& other);
|
| +
|
| + Iterator Begin();
|
| + ReverseIterator ReverseBegin();
|
| +
|
| + class IteratorBase {
|
| + public:
|
| + IteratorBase();
|
| + IteratorBase(const IteratorBase& other);
|
| + IteratorBase(IteratorBase&& other);
|
| + ~IteratorBase();
|
| +
|
| + IteratorBase& operator=(const IteratorBase& other);
|
| + IteratorBase& operator=(IteratorBase&& other);
|
| +
|
| + operator bool() const;
|
| + IteratorBase& operator++();
|
| + int index_x() const { return index_x_; }
|
| + int index_y() const { return index_y_; }
|
| +
|
| + protected:
|
| + explicit IteratorBase(const IndexRect& consider_index_rect,
|
| + const IndexRect& ignore_index_rect);
|
| +
|
| + virtual void Setup() = 0;
|
| + virtual bool IsEmpty() const = 0;
|
| + virtual void Advance() = 0;
|
| + virtual void UpdateCurrent() = 0;
|
| +
|
| + IndexRect consider_index_rect_;
|
| + IndexRect ignore_index_rect_;
|
| + int index_x_;
|
| + int index_y_;
|
| +
|
| + TriangularSequence::IteratorBase* current_triangular_sequence_it_;
|
| + };
|
| +
|
| + class Iterator : public IteratorBase {
|
| + public:
|
| + Iterator();
|
| + Iterator(const Iterator& other);
|
| + Iterator(Iterator&& other);
|
| + ~Iterator();
|
| +
|
| + Iterator& operator=(const Iterator& other);
|
| + Iterator& operator=(Iterator&& other);
|
| +
|
| + private:
|
| + explicit Iterator(PyramidSequence* pyramid_sequence);
|
| +
|
| + void Setup() override;
|
| + bool IsEmpty() const override;
|
| + void Advance() override;
|
| + void UpdateCurrent() override;
|
| +
|
| + TriangularSequence::IteratorBase* GetNextTriangularSequenceIterator();
|
| +
|
| + LinearSequence::Iterator current_traversal_sequence_iterator_;
|
| + std::vector<TriangularSequence::Iterator> triangular_sequence_iterators_;
|
| +
|
| + friend class PyramidSequence;
|
| + };
|
| +
|
| + class ReverseIterator : public IteratorBase {
|
| + public:
|
| + ReverseIterator();
|
| + ReverseIterator(const ReverseIterator& other);
|
| + ReverseIterator(ReverseIterator&& other);
|
| + ~ReverseIterator();
|
| +
|
| + ReverseIterator& operator=(const ReverseIterator& other);
|
| + ReverseIterator& operator=(ReverseIterator&& other);
|
| +
|
| + private:
|
| + explicit ReverseIterator(PyramidSequence* pyramid_sequence);
|
| +
|
| + void Setup() override;
|
| + bool IsEmpty() const override;
|
| + void Advance() override;
|
| + void UpdateCurrent() override;
|
| +
|
| + TriangularSequence::IteratorBase*
|
| + GetNextTriangularSequenceReverseIterator();
|
| +
|
| + LinearSequence::ReverseIterator
|
| + current_traversal_sequence_reverse_iterator_;
|
| + std::vector<TriangularSequence::ReverseIterator>
|
| + triangular_sequence_reverse_iterators_;
|
| +
|
| + friend class PyramidSequence;
|
| + };
|
| +
|
| + private:
|
| + void EmplaceAt(int position, TriangularSequence&& triangular_sequence);
|
| +
|
| + IndexRect consider_index_rect_;
|
| + IndexRect ignore_index_rect_;
|
| + TriangularSequence::Vector triangular_sequences_;
|
| +};
|
| +
|
| +} // namespace cc
|
| +
|
| +#endif // CC_BASE_PYRAMID_SEQUENCE_H_
|
|
|