@Override
  protected void doGetRestorableState(RestorableSupport rs, RestorableSupport.StateObject context) {
    super.doGetRestorableState(rs, context);

    rs.addStateValueAsDouble(context, "leftAzimuthDegrees", this.leftAzimuth.degrees);
    rs.addStateValueAsDouble(context, "rightAzimuthDegrees", this.rightAzimuth.degrees);
  }
  @Override
  protected void doRestoreState(RestorableSupport rs, RestorableSupport.StateObject context) {
    super.doRestoreState(rs, context);

    Double la = rs.getStateValueAsDouble(context, "leftAzimuthDegrees");
    if (la == null) la = this.leftAzimuth.degrees;

    Double ra = rs.getStateValueAsDouble(context, "rightAzimuthDegrees");
    if (ra == null) ra = this.rightAzimuth.degrees;

    this.setAzimuths(Angle.fromDegrees(la), Angle.fromDegrees(ra));
  }
  protected void doRenderGeometry(DrawContext dc, String drawStyle) {
    if (dc == null) {
      String message = Logging.getMessage("nullValue.DrawContextIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }
    if (dc.getGL() == null) {
      String message = Logging.getMessage("nullValue.DrawingContextGLIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    double[] angles = this.computeAngles();
    // Angles are equal, fallback to drawing a closed cylinder.
    if (angles == null) {
      super.doRenderGeometry(dc, drawStyle);
      return;
    }

    double[] altitudes = this.getAltitudes(dc.getVerticalExaggeration());
    boolean[] terrainConformant = this.isTerrainConforming();
    double[] radii = this.getRadii();
    int slices = this.getSlices();
    int stacks = this.getStacks();
    int loops = this.getLoops();

    if (this.isEnableLevelOfDetail()) {
      DetailLevel level = this.computeDetailLevel(dc);

      Object o = level.getValue(SLICES);
      if (o != null && o instanceof Integer) slices = (Integer) o;

      o = level.getValue(STACKS);
      if (o != null && o instanceof Integer) stacks = (Integer) o;

      o = level.getValue(LOOPS);
      if (o != null && o instanceof Integer) loops = (Integer) o;

      o = level.getValue(DISABLE_TERRAIN_CONFORMANCE);
      if (o != null && o instanceof Boolean && ((Boolean) o))
        terrainConformant[0] = terrainConformant[1] = false;
    }

    Vec4 referenceCenter = this.computeReferenceCenter(dc);
    this.setExpiryTime(this.nextExpiryTime(dc, terrainConformant));
    this.clearElevationMap();

    GL gl = dc.getGL();
    OGLStackHandler ogsh = new OGLStackHandler();
    try {
      dc.getView().pushReferenceCenter(dc, referenceCenter);

      if (Airspace.DRAW_STYLE_OUTLINE.equals(drawStyle)) {
        this.drawRadialWallOutline(
            dc,
            radii,
            angles[0],
            altitudes,
            terrainConformant,
            loops,
            stacks,
            GeometryBuilder.INSIDE,
            referenceCenter);
        this.drawRadialWallOutline(
            dc,
            radii,
            angles[1],
            altitudes,
            terrainConformant,
            loops,
            stacks,
            GeometryBuilder.OUTSIDE,
            referenceCenter);

        // Outer cylinder isn't rendered if outer radius is zero.
        if (radii[1] != 0.0) {
          this.drawPartialCylinderOutline(
              dc,
              radii[1],
              altitudes,
              terrainConformant,
              slices,
              stacks,
              GeometryBuilder.OUTSIDE,
              angles[0],
              angles[2],
              referenceCenter);
        }
        // Inner cylinder isn't rendered if inner radius is zero.
        if (radii[0] != 0.0) {
          this.drawPartialCylinderOutline(
              dc,
              radii[0],
              altitudes,
              terrainConformant,
              slices,
              stacks,
              GeometryBuilder.INSIDE,
              angles[0],
              angles[2],
              referenceCenter);
        }
      } else if (Airspace.DRAW_STYLE_FILL.equals(drawStyle)) {
        if (this.isEnableCaps()) {
          ogsh.pushAttrib(gl, GL.GL_POLYGON_BIT);
          gl.glEnable(GL.GL_CULL_FACE);
          gl.glFrontFace(GL.GL_CCW);
        }

        if (this.isEnableCaps()) {
          // Caps aren't rendered if radii are equal.
          if (radii[0] != radii[1]) {
            this.drawPartialDisk(
                dc,
                radii,
                altitudes[1],
                terrainConformant[1],
                slices,
                loops,
                GeometryBuilder.OUTSIDE,
                angles[0],
                angles[2],
                referenceCenter);
            // Bottom cap isn't rendered if airspace is collapsed.
            if (!this.isAirspaceCollapsed()) {
              this.drawPartialDisk(
                  dc,
                  radii,
                  altitudes[0],
                  terrainConformant[0],
                  slices,
                  loops,
                  GeometryBuilder.INSIDE,
                  angles[0],
                  angles[2],
                  referenceCenter);
            }
          }
        }

        // Cylinders aren't rendered if airspace is collapsed.
        if (!this.isAirspaceCollapsed()) {
          this.drawRadialWall(
              dc,
              radii,
              angles[0],
              altitudes,
              terrainConformant,
              loops,
              stacks,
              GeometryBuilder.INSIDE,
              referenceCenter);
          this.drawRadialWall(
              dc,
              radii,
              angles[1],
              altitudes,
              terrainConformant,
              loops,
              stacks,
              GeometryBuilder.OUTSIDE,
              referenceCenter);

          // Outer cylinder isn't rendered if outer radius is zero.
          if (radii[1] != 0.0) {
            this.drawPartialCylinder(
                dc,
                radii[1],
                altitudes,
                terrainConformant,
                slices,
                stacks,
                GeometryBuilder.OUTSIDE,
                angles[0],
                angles[2],
                referenceCenter);
          }
          // Inner cylinder isn't rendered if inner radius is zero.
          if (radii[0] != 0.0) {
            this.drawPartialCylinder(
                dc,
                radii[0],
                altitudes,
                terrainConformant,
                slices,
                stacks,
                GeometryBuilder.INSIDE,
                angles[0],
                angles[2],
                referenceCenter);
          }
        }
      }
    } finally {
      dc.getView().popReferenceCenter(dc);
      ogsh.pop(gl);
    }
  }