private Iterator sortedChildren(final NodeItem n) {
    double base = 0;
    // update base angle for node ordering
    NodeItem p = (NodeItem) n.getParent();
    if (p != null) {
      base = normalize(Math.atan2(p.getY() - n.getY(), p.getX() - n.getX()));
    }
    int cc = n.getChildCount();
    if (cc == 0) return null;

    NodeItem c = (NodeItem) n.getFirstChild();

    if (!c.isStartVisible()) {
      // use natural ordering for previously invisible nodes
      return n.children();
    }

    double angle[] = new double[cc];
    final int idx[] = new int[cc];
    for (int i = 0; i < cc; ++i, c = (NodeItem) c.getNextSibling()) {
      idx[i] = i;
      angle[i] = normalize(-base + Math.atan2(c.getY() - n.getY(), c.getX() - n.getX()));
    }
    ArrayLib.sort(angle, idx);

    // return iterator over sorted children
    return new Iterator() {
      int cur = 0;

      public Object next() {
        return n.getChild(idx[cur++]);
      }

      public boolean hasNext() {
        return cur < idx.length;
      }

      public void remove() {
        throw new UnsupportedOperationException();
      }
    };
  }
  /**
   * Calculates the angular bounds of the layout, attempting to preserve the angular orientation of
   * the display across transitions.
   */
  private void calcAngularBounds(NodeItem r) {
    if (m_prevRoot == null || !m_prevRoot.isValid() || r == m_prevRoot) {
      m_prevRoot = r;
      return;
    }

    // try to find previous parent of root
    NodeItem p = m_prevRoot;
    while (true) {
      NodeItem pp = (NodeItem) p.getParent();
      if (pp == r) {
        break;
      } else if (pp == null) {
        m_prevRoot = r;
        return;
      }
      p = pp;
    }

    // compute offset due to children's angular width
    double dt = 0;
    Iterator iter = sortedChildren(r);
    while (iter.hasNext()) {
      Node n = (Node) iter.next();
      if (n == p) break;
      dt += ((Params) n.get(PARAMS)).width;
    }
    double rw = ((Params) r.get(PARAMS)).width;
    double pw = ((Params) p.get(PARAMS)).width;
    dt = -MathLib.TWO_PI * (dt + pw / 2) / rw;

    // set angular bounds
    m_theta1 = dt + Math.atan2(p.getY() - r.getY(), p.getX() - r.getX());
    m_theta2 = m_theta1 + MathLib.TWO_PI;
    m_prevRoot = r;
  }