/**
   * Select the visible grid elements
   *
   * @param dc the current <code>DrawContext</code>.
   */
  protected void selectRenderables(DrawContext dc) {
    if (dc == null) {
      String message = Logging.getMessage("nullValue.DrawContextIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }
    Sector vs = dc.getVisibleSector();
    OrbitView view = (OrbitView) dc.getView();
    // Compute labels offset from view center
    Position centerPos = view.getCenterPosition();
    Double pixelSizeDegrees =
        Angle.fromRadians(
                view.computePixelSizeAtDistance(view.getZoom())
                    / dc.getGlobe().getEquatorialRadius())
            .degrees;
    Double labelOffsetDegrees = pixelSizeDegrees * view.getViewport().getWidth() / 4;
    Position labelPos =
        Position.fromDegrees(
            centerPos.getLatitude().degrees - labelOffsetDegrees,
            centerPos.getLongitude().degrees - labelOffsetDegrees,
            0);
    Double labelLatDegrees = labelPos.getLatitude().normalizedLatitude().degrees;
    labelLatDegrees = Math.min(Math.max(labelLatDegrees, -76), 78);
    labelPos =
        new Position(
            Angle.fromDegrees(labelLatDegrees), labelPos.getLongitude().normalizedLongitude(), 0);

    if (vs != null) {
      for (GridElement ge : this.gridElements) {
        if (ge.isInView(dc)) {
          if (ge.renderable instanceof GeographicText) {
            GeographicText gt = (GeographicText) ge.renderable;
            if (labelPos.getLatitude().degrees < 72
                || "*32*34*36*".indexOf("*" + gt.getText() + "*") == -1) {
              // Adjust label position according to eye position
              Position pos = gt.getPosition();
              if (ge.type.equals(GridElement.TYPE_LATITUDE_LABEL))
                pos =
                    Position.fromDegrees(
                        pos.getLatitude().degrees,
                        labelPos.getLongitude().degrees,
                        pos.getElevation());
              else if (ge.type.equals(GridElement.TYPE_LONGITUDE_LABEL))
                pos =
                    Position.fromDegrees(
                        labelPos.getLatitude().degrees,
                        pos.getLongitude().degrees,
                        pos.getElevation());

              gt.setPosition(pos);
            }
          }

          this.graticuleSupport.addRenderable(ge.renderable, GRATICULE_UTM);
        }
      }
      // System.out.println("Total elements: " + count + " visible sector: " + vs);
    }
  }
  protected static ArrayList<Position> readReferencePositions(String filePath)
      throws FileNotFoundException {
    ArrayList<Position> positions = new ArrayList<Position>();
    Scanner scanner = new Scanner(new File(filePath));

    while (scanner.hasNextDouble()) {
      double lat = scanner.nextDouble();
      double lon = scanner.nextDouble();
      double elevation = scanner.nextDouble();
      positions.add(Position.fromDegrees(lat, lon, elevation));
    }

    return positions;
  }
  protected static ArrayList<Position> generateReferenceLocations(
      Sector sector, int numLats, int numLons) {
    ArrayList<Position> locations = new ArrayList<Position>();
    double dLat =
        (sector.getMaxLatitude().degrees - sector.getMinLatitude().degrees) / (numLats - 1);
    double dLon =
        (sector.getMaxLongitude().degrees - sector.getMinLongitude().degrees) / (numLons - 1);
    for (int j = 0; j < numLats; j++) {
      double lat = sector.getMinLatitude().degrees + j * dLat;

      for (int i = 0; i < numLons; i++) {
        double lon = sector.getMinLongitude().degrees + i * dLon;

        // Specify angles to five decimal places.
        locations.add(
            Position.fromDegrees(
                Math.round(lat * 100000.0) / 100000.0, Math.round(lon * 100000.0) / 100000.0, 0));
      }
    }

    return locations;
  }
    protected List<Position> buildGrid(Sector sector, double height, int nLatCells, int nLonCells) {
      List<Position> grid = new ArrayList<Position>((nLatCells + 1) * (nLonCells + 1));

      double dLat = sector.getDeltaLatDegrees() / nLatCells;
      double dLon = sector.getDeltaLonDegrees() / nLonCells;

      for (int j = 0; j <= nLatCells; j++) {
        double lat =
            j == nLatCells
                ? sector.getMaxLatitude().degrees
                : sector.getMinLatitude().degrees + j * dLat;

        for (int i = 0; i <= nLonCells; i++) {
          double lon =
              i == nLonCells
                  ? sector.getMaxLongitude().degrees
                  : sector.getMinLongitude().degrees + i * dLon;

          grid.add(Position.fromDegrees(lat, lon, height));
        }
      }

      return grid;
    }
  /** 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;
    }
  }
 protected Position getPosition(int index) {
   int latlonIndex = 2 * index;
   return Position.fromDegrees(latlonArray[latlonIndex], latlonArray[latlonIndex + 1], 0);
 }