private void makeDefaultDetailLevels() {
    List<DetailLevel> levels = new ArrayList<DetailLevel>();
    double[] ramp = ScreenSizeDetailLevel.computeDefaultScreenSizeRamp(5);

    DetailLevel level;
    level = new ScreenSizeDetailLevel(ramp[0], "Detail-Level-0");
    level.setValue(SUBDIVISIONS, 4);
    level.setValue(DISABLE_TERRAIN_CONFORMANCE, false);
    levels.add(level);

    level = new ScreenSizeDetailLevel(ramp[1], "Detail-Level-1");
    level.setValue(SUBDIVISIONS, 3);
    level.setValue(DISABLE_TERRAIN_CONFORMANCE, false);
    levels.add(level);

    level = new ScreenSizeDetailLevel(ramp[2], "Detail-Level-2");
    level.setValue(SUBDIVISIONS, 2);
    level.setValue(DISABLE_TERRAIN_CONFORMANCE, false);
    levels.add(level);

    level = new ScreenSizeDetailLevel(ramp[3], "Detail-Level-3");
    level.setValue(SUBDIVISIONS, 1);
    level.setValue(DISABLE_TERRAIN_CONFORMANCE, false);
    levels.add(level);

    level = new ScreenSizeDetailLevel(ramp[4], "Detail-Level-4");
    level.setValue(SUBDIVISIONS, 0);
    level.setValue(DISABLE_TERRAIN_CONFORMANCE, true);
    levels.add(level);

    this.setDetailLevels(levels);
  }
  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);
    }
  }
  protected void doRenderGeometry(
      DrawContext dc, String drawStyle, List<LatLon> locations, List<Boolean> edgeFlags) {
    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);
    }
    if (locations == null) {
      String message = "nullValue.LocationsIsNull";
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    if (locations.size() == 0) return;

    double[] altitudes = this.getAltitudes(dc.getVerticalExaggeration());
    boolean[] terrainConformant = this.isTerrainConforming();
    boolean enableCaps = this.isEnableCaps();
    int subdivisions = this.subdivisions;

    if (this.getAltitudeDatum()[0].equals(AVKey.ABOVE_GROUND_REFERENCE)
        || this.getAltitudeDatum()[1].equals(AVKey.ABOVE_GROUND_REFERENCE)) {
      this.adjustForGroundReference(dc, terrainConformant, altitudes);
    }

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

      Object o = level.getValue(SUBDIVISIONS);
      if (o != null && o instanceof Integer) subdivisions = (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_FILL.equals(drawStyle)) {
        if (enableCaps && !this.isAirspaceCollapsed()) {
          ogsh.pushAttrib(gl, GL.GL_POLYGON_BIT);
          gl.glEnable(GL.GL_CULL_FACE);
          gl.glFrontFace(GL.GL_CCW);
        }

        this.drawPolygonFill(
            dc,
            locations,
            edgeFlags,
            altitudes,
            terrainConformant,
            enableCaps,
            subdivisions,
            referenceCenter);
      } else if (Airspace.DRAW_STYLE_OUTLINE.equals(drawStyle)) {
        this.drawPolygonOutline(
            dc,
            locations,
            edgeFlags,
            altitudes,
            terrainConformant,
            enableCaps,
            subdivisions,
            referenceCenter);
      }
    } finally {
      dc.getView().popReferenceCenter(dc);
      ogsh.pop(gl);
    }
  }