protected double[] computeAngles() {
    // Compute the start and sweep angles such that the partial cylinder shape tranverses a
    // clockwise path from
    // the start angle to the stop angle.
    Angle startAngle, stopAngle, sweepAngle;
    startAngle = normalizedAzimuth(this.leftAzimuth);
    stopAngle = normalizedAzimuth(this.rightAzimuth);

    int i = startAngle.compareTo(stopAngle);
    // Angles are equal, fallback to building a closed cylinder.
    if (i == 0) return null;

    if (i < 0) sweepAngle = stopAngle.subtract(startAngle);
    else // (i > 0)
    sweepAngle = Angle.POS360.subtract(startAngle).add(stopAngle);

    double[] array = new double[3];
    array[0] = startAngle.radians;
    array[1] = stopAngle.radians;
    array[2] = sweepAngle.radians;
    return array;
  }
  /**
   * Indicates the transform matrix applied to this document.
   *
   * @return Transform matrix.
   */
  protected Matrix getMatrix() {
    // If the matrix has already been computed then just return the cached value.
    if (this.matrix != null) return this.matrix;

    Matrix m = Matrix.IDENTITY;

    if (this.heading != null)
      m = m.multiply(Matrix.fromRotationZ(Angle.POS360.subtract(this.heading)));

    if (this.pitch != null) m = m.multiply(Matrix.fromRotationX(this.pitch));

    if (this.roll != null) m = m.multiply(Matrix.fromRotationY(this.roll));

    // Apply scaling factor to convert file units to meters.
    double scale = this.getScale();
    m = m.multiply(Matrix.fromScale(scale));

    if (this.modelScale != null) m = m.multiply(Matrix.fromScale(this.modelScale));

    this.matrix = m;
    return m;
  }