33 int32_t computeNumSegments(AngleInterval 
const & latitudes, 
Angle width) {
 
   35     if (width.asRadians() > 
PI) {
 
   39     if (maxAbsLat.asRadians() > 0.5 * 
PI - 4.85e-6) {
 
   42     double cosWidth = 
cos(width);
 
   43     double sinLat = 
sin(maxAbsLat);
 
   44     double cosLat = 
cos(maxAbsLat);
 
   45     double x = cosWidth - sinLat * sinLat;
 
   46     double u = cosLat * cosLat;
 
   48     return static_cast<int32_t
>(
 
   52 constexpr 
double BOX_EPSILON = 5.0e-12; 
 
   58                  int32_t numSubStripesPerStripe) :
 
   59     _numStripes(numStripes),
 
   60     _numSubStripesPerStripe(numSubStripesPerStripe),
 
   61     _numSubStripes(numStripes * numSubStripesPerStripe),
 
   62     _maxSubChunksPerSubStripeChunk(0),
 
   63     _subStripeHeight(
Angle(
PI) / _numSubStripes)
 
   65     if (numStripes < 1 || numSubStripesPerStripe < 1) {
 
   67                                  "per stripe must be positive");
 
   69     if (numStripes * numSubStripesPerStripe > 180*3600) {
 
   74     _subStripes.
reserve(_numSubStripes);
 
   75     for (int32_t s = 0; s < _numStripes; ++s) {
 
   78                            (s + 1) * stripeHeight - 
Angle(0.5 * 
PI));
 
   80         int32_t 
const nc = computeNumSegments(sLat, stripeHeight);
 
   81         stripe.chunkWidth = 
Angle(2.0 * 
PI) / nc;
 
   82         stripe.numChunksPerStripe = nc;
 
   83         int32_t ss = s * _numSubStripesPerStripe;
 
   84         int32_t 
const ssEnd = ss + _numSubStripesPerStripe;
 
   85         for (; ss < ssEnd; ++ss) {
 
   88                                 (ss + 1) * _subStripeHeight - 
Angle(0.5 * 
PI));
 
   90             int32_t 
const nsc = computeNumSegments(ssLat, _subStripeHeight) / nc;
 
   91             stripe.numSubChunksPerChunk += nsc;
 
   92             subStripe.numSubChunksPerChunk = nsc;
 
   93             if (nsc > _maxSubChunksPerSubStripeChunk) {
 
   94                 _maxSubChunksPerSubStripeChunk = nsc;
 
   96             subStripe.subChunkWidth = 
Angle(2.0 * 
PI) / (nsc * nc);
 
  109     int32_t minSS = 
std::min(
static_cast<int32_t
>(ya), _numSubStripes - 1);
 
  110     int32_t maxSS = 
std::min(
static_cast<int32_t
>(yb), _numSubStripes - 1);
 
  111     int32_t minS = minSS / _numSubStripesPerStripe;
 
  112     int32_t maxS = maxSS / _numSubStripesPerStripe;
 
  113     for (int32_t s = minS; s <= maxS; ++s) {
 
  115         Angle chunkWidth = _stripes[s].chunkWidth;
 
  116         int32_t nc = _stripes[s].numChunksPerStripe;
 
  117         double xa = 
std::floor(
b.getLon().getA() / chunkWidth);
 
  118         double xb = 
std::floor(
b.getLon().getB() / chunkWidth);
 
  119         int32_t ca = 
std::min(
static_cast<int32_t
>(xa), nc - 1);
 
  120         int32_t cb = 
std::min(
static_cast<int32_t
>(xb), nc - 1);
 
  121         if (ca == cb && 
b.getLon().wraps()) {
 
  127             for (int32_t c = ca; c <= cb; ++c) {
 
  128                 if ((r.
relate(_getChunkBoundingBox(s, c)) & DISJOINT) == 0) {
 
  133             for (int32_t c = 0; c <= cb; ++c) {
 
  134                 if ((r.
relate(_getChunkBoundingBox(s, c)) & DISJOINT) == 0) {
 
  138             for (int32_t c = ca; c < nc; ++c) {
 
  139                 if ((r.
relate(_getChunkBoundingBox(s, c)) & DISJOINT) == 0) {
 
  156     int32_t minSS = 
std::min(
static_cast<int32_t
>(ya), _numSubStripes - 1);
 
  157     int32_t maxSS = 
std::min(
static_cast<int32_t
>(yb), _numSubStripes - 1);
 
  158     int32_t minS = minSS / _numSubStripesPerStripe;
 
  159     int32_t maxS = maxSS / _numSubStripesPerStripe;
 
  160     for (int32_t s = minS; s <= maxS; ++s) {
 
  162         Angle chunkWidth = _stripes[s].chunkWidth;
 
  163         int32_t nc = _stripes[s].numChunksPerStripe;
 
  164         double xa = 
std::floor(
b.getLon().getA() / chunkWidth);
 
  165         double xb = 
std::floor(
b.getLon().getB() / chunkWidth);
 
  166         int32_t ca = 
std::min(
static_cast<int32_t
>(xa), nc - 1);
 
  167         int32_t cb = 
std::min(
static_cast<int32_t
>(xb), nc - 1);
 
  168         if (ca == cb && 
b.getLon().wraps()) {
 
  174             for (int32_t c = ca; c <= cb; ++c) {
 
  175                 _getSubChunks(chunks, r, 
b.getLon(), s, c, minSS, maxSS);
 
  178             for (int32_t c = 0; c <= cb; ++c) {
 
  179                 _getSubChunks(chunks, r, 
b.getLon(), s, c, minSS, maxSS);
 
  181             for (int32_t c = ca; c < nc; ++c) {
 
  182                 _getSubChunks(chunks, r, 
b.getLon(), s, c, minSS, maxSS);
 
  198     subChunks.
chunkId = _getChunkId(stripe, chunk);
 
  199     if ((r.
relate(_getChunkBoundingBox(stripe, chunk)) & CONTAINS) != 0) {
 
  205         minSS = 
std::max(minSS, stripe * _numSubStripesPerStripe);
 
  206         maxSS = 
std::min(maxSS, (stripe + 1) * _numSubStripesPerStripe - 1);
 
  207         int32_t 
const nc = _stripes[stripe].numChunksPerStripe;
 
  208         for (int32_t ss = minSS; ss <= maxSS; ++ss) {
 
  210             Angle subChunkWidth = _subStripes[ss].subChunkWidth;
 
  211             int32_t 
const nsc = _subStripes[ss].numSubChunksPerChunk;
 
  214             int32_t sca = 
std::min(
static_cast<int32_t
>(xa), nc * nsc - 1);
 
  215             int32_t scb = 
std::min(
static_cast<int32_t
>(xb), nc * nsc - 1);
 
  216             if (sca == scb && lon.
wraps()) {
 
  220             int32_t minSC = chunk * nsc;
 
  221             int32_t maxSC = (chunk + 1) * nsc - 1;
 
  226                 for (int32_t sc = minSC; sc <= maxSC; ++sc) {
 
  227                     if ((r.
relate(_getSubChunkBoundingBox(ss, sc)) & DISJOINT) == 0) {
 
  229                             _getSubChunkId(stripe, ss, chunk, sc));
 
  235                 for (int32_t sc = sca; sc <= maxSC; ++sc) {
 
  236                     if ((r.
relate(_getSubChunkBoundingBox(ss, sc)) & DISJOINT) == 0) {
 
  238                             _getSubChunkId(stripe, ss, chunk, sc));
 
  241                 for (int32_t sc = minSC; sc <= scb; ++sc) {
 
  242                     if ((r.
relate(_getSubChunkBoundingBox(ss, sc)) & DISJOINT) == 0) {
 
  244                             _getSubChunkId(stripe, ss, chunk, sc));
 
  254         chunks.
back().swap(subChunks);
 
  260     for (int32_t s = 0; s < _numStripes; ++s) {
 
  261         int32_t nc = _stripes[s].numChunksPerStripe;
 
  262         for (int32_t c = 0; c < nc; ++c) {
 
  271     int32_t s = _getStripe(chunkId);
 
  272     subChunkIds.
reserve(_stripes.
at(s).numSubChunksPerChunk);
 
  273     int32_t 
const ssBeg = s * _numSubStripesPerStripe;
 
  274     int32_t 
const ssEnd = ssBeg + _numSubStripesPerStripe;
 
  275     for (int32_t ss = ssBeg; ss < ssEnd; ++ss) {
 
  276         int32_t 
const scEnd = _subStripes[ss].numSubChunksPerChunk;
 
  277         int32_t 
const subChunkIdBase = _maxSubChunksPerSubStripeChunk * (ss - ssBeg);
 
  278         for (int32_t sc = 0; sc < scEnd; ++sc) {
 
  279             subChunkIds.
push_back(subChunkIdBase + sc);
 
  286     int32_t 
const s = _getStripe(chunkId);
 
  287     return s >= 0 and s < _numStripes and
 
  288            _getChunk(chunkId, s) < _stripes.
at(s).numChunksPerStripe;
 
  291 Box Chunker::_getChunkBoundingBox(int32_t stripe, int32_t chunk)
 const {
 
  292     Angle chunkWidth = _stripes[stripe].chunkWidth;
 
  294                                 chunkWidth * (chunk + 1));
 
  295     int32_t ss = stripe * _numSubStripesPerStripe;
 
  296     int32_t ssEnd = ss + _numSubStripesPerStripe;
 
  298                       ssEnd * _subStripeHeight - 
Angle(0.5 * 
PI));
 
  302 Box Chunker::_getSubChunkBoundingBox(int32_t subStripe, int32_t subChunk)
 const {
 
  303     Angle subChunkWidth = _subStripes[subStripe].subChunkWidth;
 
  304     NormalizedAngleInterval lon(subChunkWidth * subChunk,
 
  305                                 subChunkWidth * (subChunk + 1));
 
  306     AngleInterval lat(subStripe * _subStripeHeight - 
Angle(0.5 * 
PI),
 
  307                       (subStripe + 1) * _subStripeHeight - 
Angle(0.5 * 
PI));
 
  308     return Box(lon, lat).dilatedBy(
Angle(BOX_EPSILON));