1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
 * MOAB, a Mesh-Oriented datABase, is a software component for creating,
 * storing and accessing finite element mesh data.
 *
 * Copyright 2004 Sandia Corporation.  Under the terms of Contract
 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
 * retains certain rights in this software.
 *
 * This library 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.1 of the License, or (at your option) any later version.
 *
 */

/**\file RangeSeqIntersectIter.hpp
 *\author Jason Kraftcheck ([email protected])
 *\date 2006-08-11
 *\date 2007-11-06
 */

#ifndef MB_RANGE_SEQ_INTERSECT_ITER_HPP
#define MB_RANGE_SEQ_INTERSECT_ITER_HPP

#include "moab/Types.hpp"
#include "moab/Range.hpp"

namespace moab
{

class SequenceManager;
class EntitySequence;

#define MB_RANGE_SEQ_INTERSECT_ITER_STATS 0

/** \brief Iterate over the blocks of EntityHandles in an Range that
 *         are in the same EntitySequence.
 *
 * Iterate over an Range, returning blocks of entities that are the
 * largest ranges of contiguous handles that meet one of the following
 * conditions:
 *  - All are valid handles belonging to the same EntitySequence
 *  - All are invalid handles of the same EntityType
 *
 * The return type from init() or step() indicates whether or not the
 * current range contains valid entities.  If the handles are either
 * all valid or all holes in an EntitySequence, that sequence can
 * be obtained with get_sequence().  get_sequence() will return NULL if
 * there is no corresponding EntitySequence for the block of handles.
 *
 * This class keeps a data related to the 'current' EntitySequence and
 * references to the Range pasesd to init().  Changing either of these
 * while an instance of this class is in use would be bad.
 */
class RangeSeqIntersectIter
{
  public:
    RangeSeqIntersectIter( SequenceManager* sequences )
        : mSequenceManager( sequences ), mSequence( 0 ), mStartHandle( 0 ), mEndHandle( 0 ), mLastHandle( 0 )
    {
    }

    /** Initialize iterator to first valid subset
     *\return - MB_SUCCESS : initial position of iterator is valid
     *        - MB_ENITITY_NOT_FOUND : range contains invalid handle -- can step past by calling
     *again
     *        - MB_FAILURE : No entities (start == end)
     */
    ErrorCode init( Range::const_iterator start, Range::const_iterator end );

    /** Step iterator to next range.
     *\return - MB_SUCCESS : there is another range, and iter has been changed to it
     *        - MB_ENITITY_NOT_FOUND : range contains invalid handle -- can step past by calling
     *again
     *        - MB_FAILURE : at end.
     */
    ErrorCode step();

    /**\brief Check if next call to step() will return MB_FAILURE.
     *
     * Check if the iterator cannot be advanced any further.
     * If this method returns true, then the *next* call to step()
     * will return MB_FAILURE.
     */
    bool is_at_end() const
    {
        return mEndHandle == mLastHandle;
    }

    /** Get the EntitySequence for the current block.
     *  May be NULL for invaild handles.
     */
    EntitySequence* get_sequence() const
    {
        return mSequence;
    }

    /** Get first handle in block */
    EntityHandle get_start_handle() const
    {
        return mStartHandle;
    }

    /** Get last handle in block */
    EntityHandle get_end_handle() const
    {
        return mEndHandle;
    }

#if MB_RANGE_SEQ_INTERSECT_ITER_STATS
    static double fragmentation()
    {
        return ( doubleNumCalls + intNumCalls ) / ( doubleEntCount + intEntCount );
    }
#endif

  private:
    /** Update entity sequence data (mSequence and freeIndex) for current
     *  mStartHandle.  If mEndHandle is past end of sequence, trim it.
     *  Called by step() and init().  step() handles iterating over the pairs
     *  in the Range.  This method handles iterating over the set of
     *  EntitySequences that intersect the pair.
     */
    ErrorCode update_entity_sequence();

    /** Handle error case where we encountered an EntityHandle w/out
     *  a corresponding EntitySequence.  Trim mEndHandle such that it
     *  is before the next valid EntityHandle of the same type.
     *\return Always returns MB_ENTITY_NOT_FOUND
     */
    ErrorCode find_invalid_range();

    SequenceManager* mSequenceManager;      //!< THE EntitySequenceManager
    EntitySequence* mSequence;              //!< EntitySequence corresponding to current location
    Range::const_pair_iterator rangeIter;   //!< Current position in Range.
    EntityHandle mStartHandle, mEndHandle;  //!< Subset of current EntitySequence
    EntityHandle mLastHandle;               //!< The last of the list of all handles in the Range

#if MB_RANGE_SEQ_INTERSECT_ITER_STATS
    static double doubleNumCalls, doubleEntCount;
    static unsigned long intNumCalls, intEntCount;
    static void update_stats( unsigned long num_ents );
#endif
};

}  // namespace moab

#endif