/**
   * Compute the layout.
   *
   * @param n the root of the current subtree under consideration
   * @param r the radius, current distance from the center
   * @param theta1 the start (in radians) of this subtree's angular region
   * @param theta2 the end (in radians) of this subtree's angular region
   */
  protected void layout(NodeItem n, double r, double theta1, double theta2) {
    double dtheta = (theta2 - theta1);
    double dtheta2 = dtheta / 2.0;
    double width = ((Params) n.get(PARAMS)).width;
    double cfrac, nfrac = 0.0;

    Iterator childIter = sortedChildren(n);
    while (childIter != null && childIter.hasNext()) {
      NodeItem c = (NodeItem) childIter.next();
      Params cp = (Params) c.get(PARAMS);
      cfrac = cp.width / width;
      if (c.isExpanded() && c.getChildCount() > 0) {
        layout(c, r + m_radiusInc, theta1 + nfrac * dtheta, theta1 + (nfrac + cfrac) * dtheta);
      }
      setPolarLocation(c, n, r, theta1 + nfrac * dtheta + cfrac * dtheta2);

      cp.angle = cfrac * dtheta;
      nfrac += cfrac;
    }
  }
  /**
   * Computes relative measures of the angular widths of each expanded subtree. Node diameters are
   * taken into account to improve space allocation for variable-sized nodes.
   *
   * <p>This method also updates the base angle value for nodes to ensure proper ordering of nodes.
   */
  private double calcAngularWidth(NodeItem n, int d) {
    if (d > m_maxDepth) m_maxDepth = d;
    double aw = 0;

    Rectangle2D bounds = n.getBounds();
    double w = bounds.getWidth(), h = bounds.getHeight();
    double diameter = d == 0 ? 0 : Math.sqrt(w * w + h * h) / d;

    if (n.isExpanded() && n.getChildCount() > 0) {
      Iterator childIter = n.children();
      while (childIter.hasNext()) {
        NodeItem c = (NodeItem) childIter.next();
        aw += calcAngularWidth(c, d + 1);
      }
      aw = Math.max(diameter, aw);
    } else {
      aw = diameter;
    }
    ((Params) n.get(PARAMS)).width = aw;
    return aw;
  }