Blob Blame Raw
#ifndef LAYOUT_INC_CPP
#define LAYOUT_INC_CPP


#include <cassert>
#include <cstdio>

#include <vector>
#include <algorithm>


struct Layout {
  typedef std::vector<Layout> List;

  int sx, sy, sz;
  int x0, x1;
  int y0, y1;
  int z0, z1;

  inline Layout(): sx(), sy(), sz(), x0(), x1(), y0(), y1(), z0(), z1() { }

  explicit inline Layout(int sx, int sy = 1, int sz = 1):
    sx(sx), sy(sy), sz(sz), x0(), x1(sx), y0(), y1(sy), z0(), z1(sz) { }


  inline Layout& expandX  (int e0, int e1) { return sx += e0+e1, x0 += e0, x1 += e0, *this; }
  inline Layout& expandY  (int e0, int e1) { return sy += e0+e1, y0 += e0, y1 += e0, *this; }
  inline Layout& expandZ  (int e0, int e1) { return sz += e0+e1, z0 += e0, z1 += e0, *this; }
  inline Layout& expandXY (int e0, int e1) { return expandX (e0, e1).expandY(e0, e1); }
  inline Layout& expandXYZ(int e0, int e1) { return expandXY(e0, e1).expandZ(e0, e1); }
  inline Layout& expandX  (int e)          { return expandX  (e, e); }
  inline Layout& expandY  (int e)          { return expandY  (e, e); }
  inline Layout& expandZ  (int e)          { return expandX  (e, e); }
  inline Layout& expandXY (int e)          { return expandXY (e, e); }
  inline Layout& expandXYZ(int e)          { return expandXYZ(e, e); }

  inline Layout& padX  (int p0, int p1) { return x0 += p0, x1 -= p0, *this; }
  inline Layout& padY  (int p0, int p1) { return y0 += p0, y1 -= p0, *this; }
  inline Layout& padZ  (int p0, int p1) { return z0 += p0, z1 -= p0, *this; }
  inline Layout& padXY (int p0, int p1) { return padX (p0, p1).padY(p0, p1); }
  inline Layout& padXYZ(int p0, int p1) { return padXY(p0, p1).padZ(p0, p1); }
  inline Layout& padX  (int p)          { return padX  (p, p); }
  inline Layout& padY  (int p)          { return padY  (p, p); }
  inline Layout& padZ  (int p)          { return padX  (p, p); }
  inline Layout& padXY (int p)          { return padXY (p, p); }
  inline Layout& padXYZ(int p)          { return padXYZ(p, p); }


  inline int getW() const { return x1 - x0; }
  inline int getH() const { return y1 - y0; }
  inline int getD() const { return z1 - z0; }

  inline int getCount() const { return sx*sy*sz; }
  inline int getActiveCount() const { return getW()*getH()*getD(); }


  inline operator bool() const {
    return x0 >= 0 && x0 < x1 && x1 <= sx
        && y0 >= 0 && y0 < y1 && y1 <= sy
        && z0 >= 0 && z0 < z1 && z1 <= sz;
  }

  
  inline bool isSameSizeWith(const Layout &b) const
    { return sx == b.sx && sy == b.sy && sz == b.sz; }
  inline bool isSameActiveSizeWith(const Layout &b) const
    { return getW() == b.getW() && getH() == b.getH() && getD() == b.getD(); }

  inline bool isSubLayoutOf(const Layout &b) const
    { return isSameSizeWith(b) && b.x0 <= x0 && x0 < x1 && x1 <= b.x1; }
  inline bool isParentLayoutOf(const Layout &b) const
    { return b.isSubLayoutOf(*this); }
  

  void splitX(List &list, int count) const {
    if (count <= 0) return list.clear();
    list.resize(count);
    int v = x0, s = x1 - v;
    for(int i = 0; i < count; ++i) {
      Layout &l = list[i] = *this;
      l.x0 = v;
      l.x1 = (v += s/count + (i < s%count));
    }
  }

  void splitY(List &list, int count) const {
    if (count <= 0) return list.clear();
    list.resize(count);
    int v = y0, s = y1 - v;
    for(int i = 0; i < count; ++i) {
      Layout &l = list[i] = *this;
      l.y0 = v;
      l.y1 = (v += s/count + (i < s%count));
    }
  }

  void splitZ(List &list, int count) const {
    if (count <= 0) return list.clear();
    list.resize(count);
    int v = z0, s = z1 - v;
    for(int i = 0; i < count; ++i) {
      Layout &l = list[i] = *this;
      l.z0 = v;
      l.z1 = (v += s/count + (i < s%count));
    }
  }

  void split(List &list, int count) const {
    int h = getH(), w = getW(), d = getD();
    if (h >= w && h >= d) splitY(list, count); else
              if (w >= d) splitX(list, count); else
                          splitZ(list, count);
  }

  void print(const char *prefix = nullptr) const {
    if (prefix && *prefix) printf("%s: ", prefix);
    printf("x: %d (%d-%d), y: %d (%d-%d), z: %d (%d-%d)\n", sx, x0, x1, sy, y0, y1, sz, z0, z1);
  }
  void printYXZ(const char *prefix = nullptr) const {
    if (prefix && *prefix) printf("%s: ", prefix);
    printf("y: %d (%d-%d), x: %d (%d-%d), z: %d (%d-%d)\n", sy, y0, y1, sx, x0, x1, sz, z0, z1);
  }
};





#endif