public void createRenderables() {
      this.gridElements = new ArrayList<GridElement>();
      double gridStep = this.size / 10;
      Position p1, p2;
      ArrayList<Position> positions = new ArrayList<Position>();

      // South-North lines
      for (int i = 1; i <= 9; i++) {
        double easting = this.SWEasting + gridStep * i;
        positions.clear();
        p1 = computePosition(this.UTMZone, this.hemisphere, easting, SWNorthing);
        p2 = computePosition(this.UTMZone, this.hemisphere, easting, SWNorthing + this.size);
        if (this.isTruncated) {
          computeTruncatedSegment(p1, p2, this.UTMZoneSector, positions);
        } else {
          positions.add(p1);
          positions.add(p2);
        }
        if (positions.size() > 0) {
          p1 = positions.get(0);
          p2 = positions.get(1);
          Object polyline = createLineRenderable(positions, Polyline.GREAT_CIRCLE);
          Sector lineSector = Sector.boundingSector(p1, p2);
          GridElement ge = new GridElement(lineSector, polyline, GridElement.TYPE_LINE_EASTING);
          ge.setValue(easting);
          this.gridElements.add(ge);
        }
      }
      // West-East lines
      for (int i = 1; i <= 9; i++) {
        double northing = this.SWNorthing + gridStep * i;
        positions.clear();
        p1 = computePosition(this.UTMZone, this.hemisphere, SWEasting, northing);
        p2 = computePosition(this.UTMZone, this.hemisphere, SWEasting + this.size, northing);
        if (this.isTruncated) {
          computeTruncatedSegment(p1, p2, this.UTMZoneSector, positions);
        } else {
          positions.add(p1);
          positions.add(p2);
        }
        if (positions.size() > 0) {
          p1 = positions.get(0);
          p2 = positions.get(1);
          Object polyline = createLineRenderable(positions, Polyline.GREAT_CIRCLE);
          Sector lineSector = Sector.boundingSector(p1, p2);
          GridElement ge = new GridElement(lineSector, polyline, GridElement.TYPE_LINE_NORTHING);
          ge.setValue(northing);
          this.gridElements.add(ge);
        }
      }
    }
    public SquareSector(
        int UTMZone,
        String hemisphere,
        Sector UTMZoneSector,
        double SWEasting,
        double SWNorthing,
        double size) {
      this.UTMZone = UTMZone;
      this.hemisphere = hemisphere;
      this.UTMZoneSector = UTMZoneSector;
      this.SWEasting = SWEasting;
      this.SWNorthing = SWNorthing;
      this.size = size;

      // Compute corners positions
      this.sw = computePosition(this.UTMZone, this.hemisphere, SWEasting, SWNorthing);
      this.se = computePosition(this.UTMZone, this.hemisphere, SWEasting + size, SWNorthing);
      this.nw = computePosition(this.UTMZone, this.hemisphere, SWEasting, SWNorthing + size);
      this.ne = computePosition(this.UTMZone, this.hemisphere, SWEasting + size, SWNorthing + size);
      this.squareCenter =
          computePosition(
              this.UTMZone, this.hemisphere, SWEasting + size / 2, SWNorthing + size / 2);

      // Compute approximate bounding sector and center point
      if (this.sw != null && this.se != null && this.nw != null && this.ne != null) {
        adjustDateLineCrossingPoints();
        this.boundingSector = Sector.boundingSector(Arrays.asList(sw, se, nw, ne));
        if (!isInsideGridZone())
          this.boundingSector = this.UTMZoneSector.intersection(this.boundingSector);

        this.centroid =
            this.boundingSector != null ? this.boundingSector.getCentroid() : this.squareCenter;
        // this.squareCenter = this.boundingSector.getCentroid();
      }

      // Check whether this square is truncated by the grid zone boundary
      this.isTruncated = !isInsideGridZone();
    }
    public void createRenderables() {
      this.gridElements = new ArrayList<GridElement>();

      ArrayList<Position> positions = new ArrayList<Position>();
      Position p1, p2;
      Object polyline;
      Sector lineSector;

      // left segment
      positions.clear();
      if (this.isTruncated) {
        computeTruncatedSegment(sw, nw, this.UTMZoneSector, positions);
      } else {
        positions.add(sw);
        positions.add(nw);
      }
      if (positions.size() > 0) {
        p1 = positions.get(0);
        p2 = positions.get(1);
        polyline = createLineRenderable(positions, Polyline.GREAT_CIRCLE);
        lineSector = Sector.boundingSector(p1, p2);
        GridElement ge = new GridElement(lineSector, polyline, GridElement.TYPE_LINE_WEST);
        ge.setValue(this.SWEasting);
        this.gridElements.add(ge);
      }

      // right segment
      positions.clear();
      if (this.isTruncated) {
        computeTruncatedSegment(se, ne, this.UTMZoneSector, positions);
      } else {
        positions.add(se);
        positions.add(ne);
      }
      if (positions.size() > 0) {
        p1 = positions.get(0);
        p2 = positions.get(1);
        polyline = createLineRenderable(positions, Polyline.GREAT_CIRCLE);
        lineSector = Sector.boundingSector(p1, p2);
        GridElement ge = new GridElement(lineSector, polyline, GridElement.TYPE_LINE_EAST);
        ge.setValue(this.SWEasting + this.size);
        this.gridElements.add(ge);
      }

      // bottom segment
      positions.clear();
      if (this.isTruncated) {
        computeTruncatedSegment(sw, se, this.UTMZoneSector, positions);
      } else {
        positions.add(sw);
        positions.add(se);
      }
      if (positions.size() > 0) {
        p1 = positions.get(0);
        p2 = positions.get(1);
        polyline = createLineRenderable(positions, Polyline.GREAT_CIRCLE);
        lineSector = Sector.boundingSector(p1, p2);
        GridElement ge = new GridElement(lineSector, polyline, GridElement.TYPE_LINE_SOUTH);
        ge.setValue(this.SWNorthing);
        this.gridElements.add(ge);
      }

      // top segment
      positions.clear();
      if (this.isTruncated) {
        computeTruncatedSegment(nw, ne, this.UTMZoneSector, positions);
      } else {
        positions.add(nw);
        positions.add(ne);
      }
      if (positions.size() > 0) {
        p1 = positions.get(0);
        p2 = positions.get(1);
        polyline = createLineRenderable(positions, Polyline.GREAT_CIRCLE);
        lineSector = Sector.boundingSector(p1, p2);
        GridElement ge = new GridElement(lineSector, polyline, GridElement.TYPE_LINE_NORTH);
        ge.setValue(this.SWNorthing + this.size);
        this.gridElements.add(ge);
      }

      // Label
      if (this.name != null) {
        // Only add a label to squares above some dimension
        if (this.boundingSector.getDeltaLon().degrees
                    * Math.cos(this.centroid.getLatitude().radians)
                > .2
            && this.boundingSector.getDeltaLat().degrees > .2) {
          LatLon labelPos = null;
          if (this.UTMZone != 0) // Not at poles
          {
            labelPos = this.centroid;
          } else if (this.isPositionInside(new Position(this.squareCenter, 0))) {
            labelPos = this.squareCenter;
          } else if (this.squareCenter.getLatitude().degrees
                  <= this.UTMZoneSector.getMaxLatitude().degrees
              && this.squareCenter.getLatitude().degrees
                  >= this.UTMZoneSector.getMinLatitude().degrees) {
            labelPos = this.centroid;
          }
          if (labelPos != null) {
            GeographicText text = new UserFacingText(this.name, new Position(labelPos, 0));
            text.setPriority(this.size * 10);
            this.gridElements.add(
                new GridElement(this.boundingSector, text, GridElement.TYPE_GRIDZONE_LABEL));
          }
        }
      }
    }
 public Extent getExtent(Globe globe, double ve) {
   return Sector.computeBoundingCylinder(globe, ve, this.boundingSector);
 }
  /** Create the graticule grid elements */
  private void createUTMRenderables() {
    this.gridElements = new ArrayList<GridElement>();

    ArrayList<Position> positions = new ArrayList<Position>();

    // Generate meridians and zone labels
    int lon = -180;
    int zoneNumber = 1;
    int maxLat;
    for (int i = 0; i < 60; i++) {
      Angle longitude = Angle.fromDegrees(lon);
      // Meridian
      positions.clear();
      positions.add(new Position(Angle.fromDegrees(-80), longitude, 10e3));
      positions.add(new Position(Angle.fromDegrees(-60), longitude, 10e3));
      positions.add(new Position(Angle.fromDegrees(-30), longitude, 10e3));
      positions.add(new Position(Angle.ZERO, longitude, 10e3));
      positions.add(new Position(Angle.fromDegrees(30), longitude, 10e3));
      if (lon < 6 || lon > 36) {
        // 'regular' UTM meridians
        maxLat = 84;
        positions.add(new Position(Angle.fromDegrees(60), longitude, 10e3));
        positions.add(new Position(Angle.fromDegrees(maxLat), longitude, 10e3));
      } else {
        // Exceptions: shorter meridians around and north-east of Norway
        if (lon == 6) {
          maxLat = 56;
          positions.add(new Position(Angle.fromDegrees(maxLat), longitude, 10e3));
        } else {
          maxLat = 72;
          positions.add(new Position(Angle.fromDegrees(60), longitude, 10e3));
          positions.add(new Position(Angle.fromDegrees(maxLat), longitude, 10e3));
        }
      }
      Object polyline = createLineRenderable(positions, Polyline.GREAT_CIRCLE);
      Sector sector = Sector.fromDegrees(-80, maxLat, lon, lon);
      this.gridElements.add(new GridElement(sector, polyline, GridElement.TYPE_LINE));

      // Zone label
      GeographicText text =
          new UserFacingText(zoneNumber + "", Position.fromDegrees(0, lon + 3, 0));
      sector = Sector.fromDegrees(-90, 90, lon + 3, lon + 3);
      this.gridElements.add(new GridElement(sector, text, GridElement.TYPE_LONGITUDE_LABEL));

      // Increase longitude and zone number
      lon += 6;
      zoneNumber++;
    }

    // Generate special meridian segments for exceptions around and north-east of Norway
    for (int i = 0; i < 5; i++) {
      positions.clear();
      lon = specialMeridians[i][0];
      positions.add(
          new Position(Angle.fromDegrees(specialMeridians[i][1]), Angle.fromDegrees(lon), 10e3));
      positions.add(
          new Position(Angle.fromDegrees(specialMeridians[i][2]), Angle.fromDegrees(lon), 10e3));
      Object polyline = createLineRenderable(positions, Polyline.GREAT_CIRCLE);
      Sector sector = Sector.fromDegrees(specialMeridians[i][1], specialMeridians[i][2], lon, lon);
      this.gridElements.add(new GridElement(sector, polyline, GridElement.TYPE_LINE));
    }

    // Generate parallels - no exceptions
    int lat = -80;
    for (int i = 0; i < 21; i++) {
      Angle latitude = Angle.fromDegrees(lat);
      for (int j = 0; j < 4; j++) {
        // Each prallel is divided into four 90 degrees segments
        positions.clear();
        lon = -180 + j * 90;
        positions.add(new Position(latitude, Angle.fromDegrees(lon), 10e3));
        positions.add(new Position(latitude, Angle.fromDegrees(lon + 30), 10e3));
        positions.add(new Position(latitude, Angle.fromDegrees(lon + 60), 10e3));
        positions.add(new Position(latitude, Angle.fromDegrees(lon + 90), 10e3));
        Object polyline = createLineRenderable(positions, Polyline.LINEAR);
        Sector sector = Sector.fromDegrees(lat, lat, lon, lon + 90);
        this.gridElements.add(new GridElement(sector, polyline, GridElement.TYPE_LINE));
      }
      // Latitude band label
      if (i < 20) {
        GeographicText text =
            new UserFacingText(latBands.charAt(i) + "", Position.fromDegrees(lat + 4, 0, 0));
        Sector sector = Sector.fromDegrees(lat + 4, lat + 4, -180, 180);
        this.gridElements.add(new GridElement(sector, text, GridElement.TYPE_LATITUDE_LABEL));
      }

      // Increase latitude
      lat += lat < 72 ? 8 : 12;
    }
  }