public int countImagesInSector(Sector sector, int levelNumber) {
    if (sector == null) {
      String msg = Logging.getMessage("nullValue.SectorIsNull");
      Logging.logger().severe(msg);
      throw new IllegalArgumentException(msg);
    }

    Level targetLevel = this.levels.getLastLevel();
    if (levelNumber >= 0) {
      for (int i = levelNumber; i < this.getLevels().getLastLevel().getLevelNumber(); i++) {
        if (this.levels.isLevelEmpty(i)) continue;

        targetLevel = this.levels.getLevel(i);
        break;
      }
    }

    // Collect all the tiles intersecting the input sector.
    LatLon delta = targetLevel.getTileDelta();
    Angle latOrigin = this.levels.getTileOrigin().getLatitude();
    Angle lonOrigin = this.levels.getTileOrigin().getLongitude();
    final int nwRow = Tile.computeRow(delta.getLatitude(), sector.getMaxLatitude(), latOrigin);
    final int nwCol = Tile.computeColumn(delta.getLongitude(), sector.getMinLongitude(), lonOrigin);
    final int seRow = Tile.computeRow(delta.getLatitude(), sector.getMinLatitude(), latOrigin);
    final int seCol = Tile.computeColumn(delta.getLongitude(), sector.getMaxLongitude(), lonOrigin);

    int numRows = nwRow - seRow + 1;
    int numCols = seCol - nwCol + 1;

    return numRows * numCols;
  }
예제 #2
0
  protected int determineAdjustmentSide(Movable dragObject, double factor) {
    if (dragObject instanceof SurfaceSector) {
      SurfaceSector quad = (SurfaceSector) dragObject;
      Sector s = quad.getSector(); // TODO: go over all sectors
      Position p = this.getWwd().getCurrentPosition();

      if (p == null) {
        return NONE;
      }

      double dN = abs(s.getMaxLatitude().subtract(p.getLatitude()).degrees);
      double dS = abs(s.getMinLatitude().subtract(p.getLatitude()).degrees);
      double dW = abs(s.getMinLongitude().subtract(p.getLongitude()).degrees);
      double dE = abs(s.getMaxLongitude().subtract(p.getLongitude()).degrees);

      double sLat = factor * s.getDeltaLatDegrees();
      double sLon = factor * s.getDeltaLonDegrees();

      if (dN < sLat && dW < sLon) return NORTHWEST;
      if (dN < sLat && dE < sLon) return NORTHEAST;
      if (dS < sLat && dW < sLon) return SOUTHWEST;
      if (dS < sLat && dE < sLon) return SOUTHEAST;
      if (dN < sLat) return NORTH;
      if (dS < sLat) return SOUTH;
      if (dW < sLon) return WEST;
      if (dE < sLon) return EAST;
    }

    return NONE;
  }
 public static String makeSectorDescription(Sector sector) {
   return String.format(
       "S %7.4f\u00B0 W %7.4f\u00B0 N %7.4f\u00B0 E %7.4f\u00B0",
       sector.getMinLatitude().degrees,
       sector.getMinLongitude().degrees,
       sector.getMaxLatitude().degrees,
       sector.getMaxLongitude().degrees);
 }
예제 #4
0
  protected Sector resizeShape(Movable dragObject, int side) {
    if (dragObject instanceof SurfaceSector) {
      SurfaceSector quad = (SurfaceSector) dragObject;
      Sector s = quad.getSector(); // TODO: go over all sectors
      Position p = this.getWwd().getCurrentPosition();

      if (p == null || this.getPreviousPosition() == null) {
        return null;
      }

      Angle dLat = p.getLatitude().subtract(this.getPreviousPosition().getLatitude());
      Angle dLon = p.getLongitude().subtract(this.getPreviousPosition().getLongitude());

      Angle newMinLat = s.getMinLatitude();
      Angle newMinLon = s.getMinLongitude();
      Angle newMaxLat = s.getMaxLatitude();
      Angle newMaxLon = s.getMaxLongitude();

      if (side == NORTH) {
        newMaxLat = s.getMaxLatitude().add(dLat);
      } else if (side == SOUTH) {
        newMinLat = s.getMinLatitude().add(dLat);
      } else if (side == EAST) {
        newMaxLon = s.getMaxLongitude().add(dLon);
      } else if (side == WEST) {
        newMinLon = s.getMinLongitude().add(dLon);
      } else if (side == NORTHWEST) {
        newMaxLat = s.getMaxLatitude().add(dLat);
        newMinLon = s.getMinLongitude().add(dLon);
      } else if (side == NORTHEAST) {
        newMaxLat = s.getMaxLatitude().add(dLat);
        newMaxLon = s.getMaxLongitude().add(dLon);
      } else if (side == SOUTHWEST) {
        newMinLat = s.getMinLatitude().add(dLat);
        newMinLon = s.getMinLongitude().add(dLon);
      } else if (side == SOUTHEAST) {
        newMinLat = s.getMinLatitude().add(dLat);
        newMaxLon = s.getMaxLongitude().add(dLon);
      }

      return new Sector(newMinLat, newMaxLat, newMinLon, newMaxLon);
    }

    return null;
  }
 private static AffineTransform createTransform(Sector source, MeshCoords destination) {
   java.awt.geom.AffineTransform transform = new java.awt.geom.AffineTransform();
   transform.translate(destination.left, destination.bottom);
   transform.scale(
       (destination.right - destination.left) / source.getDeltaLonDegrees(),
       (destination.top - destination.bottom) / source.getDeltaLatDegrees());
   transform.translate(-source.getMinLongitude().degrees, -source.getMinLatitude().degrees);
   return transform;
 }
예제 #6
0
  protected Angle computeIconRadius(DrawContext dc, double regionPixelSize, Sector drawSector) {
    double minCosLat =
        Math.min(drawSector.getMinLatitude().cos(), drawSector.getMaxLatitude().cos());
    if (minCosLat < 0.001) return Angle.POS180;

    Rectangle2D iconDimension = this.computeDrawDimension(regionPixelSize); // Meter
    double dLat = iconDimension.getHeight() / dc.getGlobe().getRadius();
    double dLon = iconDimension.getWidth() / dc.getGlobe().getRadius() / minCosLat;
    return Angle.fromRadians(Math.sqrt(dLat * dLat + dLon * dLon) / 2);
  }
  public Sector(Sector sector) {
    if (sector == null) {
      throw new IllegalArgumentException("Sector Is Null");
    }

    this.minLatitude = new Angle(sector.getMinLatitude());
    this.maxLatitude = new Angle(sector.getMaxLatitude());
    this.minLongitude = new Angle(sector.getMinLongitude());
    this.maxLongitude = new Angle(sector.getMaxLongitude());
    this.deltaLat = Angle.fromDegrees(this.maxLatitude.degrees - this.minLatitude.degrees);
    this.deltaLon = Angle.fromDegrees(this.maxLongitude.degrees - this.minLongitude.degrees);
  }
  /**
   * Compares this sector to a specified sector according to their minimum latitude, minimum
   * longitude, maximum latitude, and maximum longitude, respectively.
   *
   * @param that the <code>Sector</code> to compareTo with <code>this</code>.
   * @return -1 if this sector compares less than that specified, 0 if they're equal, and 1 if it
   *     compares greater.
   * @throws IllegalArgumentException if <code>that</code> is null
   */
  public int compareTo(Sector that) {
    if (that == null) {
      throw new IllegalArgumentException("Sector Is Null");
    }

    if (this.getMinLatitude().compareTo(that.getMinLatitude()) < 0) {
      return -1;
    }

    if (this.getMinLatitude().compareTo(that.getMinLatitude()) > 0) {
      return 1;
    }

    if (this.getMinLongitude().compareTo(that.getMinLongitude()) < 0) {
      return -1;
    }

    if (this.getMinLongitude().compareTo(that.getMinLongitude()) > 0) {
      return 1;
    }

    if (this.getMaxLatitude().compareTo(that.getMaxLatitude()) < 0) {
      return -1;
    }

    if (this.getMaxLatitude().compareTo(that.getMaxLatitude()) > 0) {
      return 1;
    }

    if (this.getMaxLongitude().compareTo(that.getMaxLongitude()) < 0) {
      return -1;
    }

    if (this.getMaxLongitude().compareTo(that.getMaxLongitude()) > 0) {
      return 1;
    }

    return 0;
  }
  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;
  }
  public static VirtualEarthTile[] createTiles(
      Sector bbox /*int wwLevel, int wwRow, int wwCol*/, VirtualEarthLayer layer)
      throws WWRuntimeException {
    if (null == bbox) {
      String message = Logging.getMessage("nullValue.SectorIsNull");
      Logging.logger().severe(message);
      throw new WWRuntimeException(message);
    }

    if (null == layer) {
      String message = Logging.getMessage("nullValue.LayerIsNull");
      Logging.logger().severe(message);
      throw new WWRuntimeException(message);
    }

    int level = getZoomLevelByTrueViewRange(bbox.getDeltaLatDegrees());

    Point startPixel =
        LatLongToPixelXY(bbox.getMaxLatitude().degrees, bbox.getMinLongitude().degrees, level);
    Point endPixel =
        LatLongToPixelXY(bbox.getMinLatitude().degrees, bbox.getMaxLongitude().degrees, level);

    Point startTile = PixelXYToTileXY(startPixel.x, startPixel.y);
    Point endTile = PixelXYToTileXY(endPixel.x, endPixel.y);

    ArrayList<VirtualEarthTile> tileList = new ArrayList<VirtualEarthTile>();

    for (int y = startTile.y; y <= endTile.y; y++) {
      for (int x = startTile.x; x <= endTile.x; x++) {
        try {
          int ulPixelX = x * VE_MAX_TILE_SIZE;
          int ulPixelY = y * VE_MAX_TILE_SIZE;
          LatLon ul = PixelXYToLatLong(ulPixelX, ulPixelY, level);

          int lrPixelX = ulPixelX + VE_MAX_TILE_SIZE;
          int lrPixelY = ulPixelY + VE_MAX_TILE_SIZE;
          LatLon lr = PixelXYToLatLong(lrPixelX, lrPixelY, level);

          Sector tileSector = Sector.boundingSector(ul, lr);

          tileList.add(new VirtualEarthTile(x, y, level, layer, tileSector));
        } catch (Exception ex) {
          Logging.logger().log(Level.SEVERE, ex.getMessage(), ex);
        }
      }
    }

    VirtualEarthTile[] tiles = new VirtualEarthTile[tileList.size()];
    return tileList.toArray(tiles);
  }
예제 #11
0
  protected List<Sector> computeSectors(DrawContext dc) {
    if (this.locations == null || !this.locations.iterator().hasNext()) return null;

    // Compute all locations bounding sector, then add some padding for the icon half diagonal
    // extent
    Sector sector = Sector.boundingSector(this.locations);
    // Compute padding
    double minCosLat = Math.min(sector.getMinLatitude().cos(), sector.getMaxLatitude().cos());
    minCosLat = Math.max(minCosLat, .01); // avoids division by zero at the poles
    Rectangle2D iconDimension = this.computeDrawDimension(dc, sector.getCentroid());
    double diagonalLength =
        Math.sqrt(
            iconDimension.getWidth() * iconDimension.getWidth()
                + iconDimension.getHeight() * iconDimension.getHeight());
    double padLatRadians = diagonalLength / 2 / dc.getGlobe().getRadius();
    double padLonRadians = diagonalLength / 2 / dc.getGlobe().getRadius() / minCosLat;
    // Apply padding to sector
    Angle minLat = sector.getMinLatitude().subtractRadians(padLatRadians);
    Angle maxLat = sector.getMaxLatitude().addRadians(padLatRadians);
    Angle minLon = sector.getMinLongitude().subtractRadians(padLonRadians);
    Angle maxLon = sector.getMaxLongitude().addRadians(padLatRadians);

    return this.computeNormalizedSectors(new Sector(minLat, maxLat, minLon, maxLon));
  }
  private static MeshCoords transformSector(AffineTransform transform, Sector sector) {
    java.awt.geom.Point2D p = new java.awt.geom.Point2D.Double();
    java.awt.geom.Point2D ll = new java.awt.geom.Point2D.Double();
    java.awt.geom.Point2D ur = new java.awt.geom.Point2D.Double();

    p.setLocation(sector.getMinLongitude().degrees, sector.getMinLatitude().degrees);
    transform.transform(p, ll);

    p.setLocation(sector.getMaxLongitude().degrees, sector.getMaxLatitude().degrees);
    transform.transform(p, ur);

    return new MeshCoords(
        (float) ur.getY(), // Top
        (float) ll.getX(), // Left
        (float) ll.getY(), // Bottom
        (float) ur.getX()); // Right
  }
예제 #13
0
  protected static boolean isSectorVisible(
      DrawContext dc, Sector sector, double minDistanceSquared, double maxDistanceSquared) {

    View view = dc.getView();
    Position eyePos = view.getEyePosition();
    if (eyePos == null) return false;

    Angle lat = clampAngle(eyePos.getLatitude(), sector.getMinLatitude(), sector.getMaxLatitude());
    Angle lon =
        clampAngle(eyePos.getLongitude(), sector.getMinLongitude(), sector.getMaxLongitude());
    Vec4 p = dc.getGlobe().computePointFromPosition(lat, lon, 0d);
    double distSquared = dc.getView().getEyePoint().distanceToSquared3(p);
    //noinspection RedundantIfStatement
    if (minDistanceSquared > distSquared || maxDistanceSquared < distSquared) return false;

    return true;
  }
  private MercatorTextureTile[][] getTilesInSector(Sector sector, int levelNumber) {
    if (sector == null) {
      String msg = Logging.getMessage("nullValue.SectorIsNull");
      Logging.logger().severe(msg);
      throw new IllegalArgumentException(msg);
    }

    Level targetLevel = this.levels.getLastLevel();
    if (levelNumber >= 0) {
      for (int i = levelNumber; i < this.getLevels().getLastLevel().getLevelNumber(); i++) {
        if (this.levels.isLevelEmpty(i)) continue;

        targetLevel = this.levels.getLevel(i);
        break;
      }
    }

    // Collect all the tiles intersecting the input sector.
    LatLon delta = targetLevel.getTileDelta();
    Angle latOrigin = this.levels.getTileOrigin().getLatitude();
    Angle lonOrigin = this.levels.getTileOrigin().getLongitude();
    final int nwRow = Tile.computeRow(delta.getLatitude(), sector.getMaxLatitude(), latOrigin);
    final int nwCol = Tile.computeColumn(delta.getLongitude(), sector.getMinLongitude(), lonOrigin);
    final int seRow = Tile.computeRow(delta.getLatitude(), sector.getMinLatitude(), latOrigin);
    final int seCol = Tile.computeColumn(delta.getLongitude(), sector.getMaxLongitude(), lonOrigin);

    int numRows = nwRow - seRow + 1;
    int numCols = seCol - nwCol + 1;
    MercatorTextureTile[][] sectorTiles = new MercatorTextureTile[numRows][numCols];

    for (int row = nwRow; row >= seRow; row--) {
      for (int col = nwCol; col <= seCol; col++) {
        TileKey key =
            new TileKey(targetLevel.getLevelNumber(), row, col, targetLevel.getCacheName());
        Sector tileSector = this.levels.computeSectorForKey(key);
        MercatorSector mSector = MercatorSector.fromSector(tileSector); // TODO: check
        sectorTiles[nwRow - row][col - nwCol] =
            new MercatorTextureTile(mSector, targetLevel, row, col);
      }
    }

    return sectorTiles;
  }
  private static MeshTile[] createTiles(LevelSet levelSet, int levelNumber, MeshCoords coords) {
    Sector sector = levelSet.getSector();
    Level level = levelSet.getLevel(levelNumber);
    Angle dLat = level.getTileDelta().getLatitude();
    Angle dLon = level.getTileDelta().getLongitude();
    Angle latOrigin = levelSet.getTileOrigin().getLatitude();
    Angle lonOrigin = levelSet.getTileOrigin().getLongitude();

    // Determine the row and column offset from the common World Wind global tiling origin.
    int firstRow = Tile.computeRow(dLat, sector.getMinLatitude(), latOrigin);
    int firstCol = Tile.computeColumn(dLon, sector.getMinLongitude(), lonOrigin);
    int lastRow = Tile.computeRow(dLat, sector.getMaxLatitude(), latOrigin);
    int lastCol = Tile.computeColumn(dLon, sector.getMaxLongitude(), lonOrigin);

    int numLatTiles = lastRow - firstRow + 1;
    int numLonTiles = lastCol - firstCol + 1;

    AffineTransform sectorTransform = createTransform(sector, coords);

    MeshTile[] tiles = new MeshTile[numLatTiles * numLonTiles];
    int index = 0;

    Angle p1 = Tile.computeRowLatitude(firstRow, dLat, latOrigin);

    for (int row = firstRow; row <= lastRow; row++) {
      Angle p2 = p1.add(dLat);

      Angle t1 = Tile.computeColumnLongitude(firstCol, dLon, lonOrigin);

      for (int col = firstCol; col <= lastCol; col++) {
        Angle t2 = t1.add(dLon);

        Sector tileSector = new Sector(p1, p2, t1, t2);
        MeshCoords tileCoords = transformSector(sectorTransform, tileSector);
        tiles[index++] = new MeshTile(tileSector, level, row, col, tileCoords);

        t1 = t2;
      }
      p1 = p2;
    }

    return tiles;
  }
    public URL getURL(Tile tile, String altImageFormat) throws MalformedURLException {
      StringBuffer sb;
      if (this.URLTemplate == null) {
        sb = new StringBuffer(WWXML.fixGetMapString(tile.getLevel().getService()));

        if (!sb.toString().toLowerCase().contains("service=wms")) sb.append("service=WMS");
        sb.append("&request=GetMap");
        sb.append("&version=").append(this.wmsVersion);
        sb.append(this.crs);
        sb.append("&layers=").append(this.layerNames);
        sb.append("&styles=").append(this.styleNames != null ? this.styleNames : "");
        sb.append("&transparent=TRUE");
        if (this.backgroundColor != null) sb.append("&bgcolor=").append(this.backgroundColor);

        this.URLTemplate = sb.toString();
      } else {
        sb = new StringBuffer(this.URLTemplate);
      }

      String format = (altImageFormat != null) ? altImageFormat : this.imageFormat;
      if (null != format) sb.append("&format=").append(format);

      sb.append("&width=").append(tile.getWidth());
      sb.append("&height=").append(tile.getHeight());

      Sector s = tile.getSector();
      sb.append("&bbox=");
      sb.append(s.getMinLongitude().getDegrees());
      sb.append(",");
      sb.append(s.getMinLatitude().getDegrees());
      sb.append(",");
      sb.append(s.getMaxLongitude().getDegrees());
      sb.append(",");
      sb.append(s.getMaxLatitude().getDegrees());
      //            sb.append("&"); // terminate the query string

      return new java.net.URL(sb.toString().replace(" ", "%20"));
    }
    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;
    }
예제 #18
0
    protected boolean isNavSectorVisible(
        DrawContext dc, double minDistanceSquared, double maxDistanceSquared) {
      if (!navSector.intersects(dc.getVisibleSector())) return false;

      View view = dc.getView();
      Position eyePos = view.getEyePosition();
      if (eyePos == null) return false;

      // check for eyePos over globe
      if (Double.isNaN(eyePos.getLatitude().getDegrees())
          || Double.isNaN(eyePos.getLongitude().getDegrees())) return false;

      Angle lat =
          clampAngle(eyePos.getLatitude(), navSector.getMinLatitude(), navSector.getMaxLatitude());
      Angle lon =
          clampAngle(
              eyePos.getLongitude(), navSector.getMinLongitude(), navSector.getMaxLongitude());
      Vec4 p = dc.getGlobe().computePointFromPosition(lat, lon, 0d);
      double distSquared = dc.getView().getEyePoint().distanceToSquared3(p);
      //noinspection RedundantIfStatement
      if (minDistanceSquared > distSquared || maxDistanceSquared < distSquared) return false;

      return true;
    }
  private void appendGeoTiff(ArrayList<TiffIFDEntry> ifds, AVList params)
      throws IOException, IllegalArgumentException {
    if (null == params || 0 == params.getEntries().size()) {
      String reason = Logging.getMessage("nullValue.AVListIsNull");
      Logging.logger().finest(Logging.getMessage("GeotiffWriter.GeoKeysMissing", reason));
      return;
    }

    long offset = this.theChannel.position();

    if (params.hasKey(AVKey.DISPLAY_NAME)) {
      String value = params.getStringValue(AVKey.DISPLAY_NAME);
      if (null != value && 0 < value.trim().length()) {
        offset = this.theChannel.position();
        byte[] bytes = value.trim().getBytes();
        this.theChannel.write(ByteBuffer.wrap(bytes));
        ifds.add(new TiffIFDEntry(Tiff.Tag.DOCUMENT_NAME, Tiff.Type.ASCII, bytes.length, offset));
      }
    }

    if (params.hasKey(AVKey.DESCRIPTION)) {
      String value = params.getStringValue(AVKey.DESCRIPTION);
      if (null != value && 0 < value.trim().length()) {
        offset = this.theChannel.position();
        byte[] bytes = value.trim().getBytes();
        this.theChannel.write(ByteBuffer.wrap(bytes));
        ifds.add(
            new TiffIFDEntry(Tiff.Tag.IMAGE_DESCRIPTION, Tiff.Type.ASCII, bytes.length, offset));
      }
    }

    if (params.hasKey(AVKey.VERSION)) {
      String value = params.getStringValue(AVKey.VERSION);
      if (null != value && 0 < value.trim().length()) {
        offset = this.theChannel.position();
        byte[] bytes = value.trim().getBytes();
        this.theChannel.write(ByteBuffer.wrap(bytes));
        ifds.add(
            new TiffIFDEntry(Tiff.Tag.SOFTWARE_VERSION, Tiff.Type.ASCII, bytes.length, offset));
      }
    }

    if (params.hasKey(AVKey.DATE_TIME)) {
      String value = params.getStringValue(AVKey.DATE_TIME);
      if (null != value && 0 < value.trim().length()) {
        offset = this.theChannel.position();
        byte[] bytes = value.getBytes();
        this.theChannel.write(ByteBuffer.wrap(bytes));
        ifds.add(new TiffIFDEntry(Tiff.Tag.DATE_TIME, Tiff.Type.ASCII, bytes.length, offset));
      }
    }

    if (params.hasKey(AVKey.SECTOR)) {
      if (params.hasKey(AVKey.PIXEL_WIDTH) && params.hasKey(AVKey.PIXEL_HEIGHT)) {
        offset = this.theChannel.position();
        double[] values =
            new double[] {
              (Double) params.getValue(AVKey.PIXEL_WIDTH),
              (Double) params.getValue(AVKey.PIXEL_HEIGHT),
              isElevation(params) ? 1d : 0d
            };
        byte[] bytes = this.getBytes(values);
        this.theChannel.write(ByteBuffer.wrap(bytes));
        ifds.add(
            new TiffIFDEntry(
                GeoTiff.Tag.MODEL_PIXELSCALE, Tiff.Type.DOUBLE, values.length, offset));
      }

      if (params.hasKey(AVKey.WIDTH) && params.hasKey(AVKey.HEIGHT)) {
        offset = this.theChannel.position();

        double w = (Integer) params.getValue(AVKey.WIDTH);
        double h = (Integer) params.getValue(AVKey.HEIGHT);

        Sector sec = (Sector) params.getValue(AVKey.SECTOR);

        double[] values =
            new double[] { // i ,  j, k=0, x, y, z=0
              0d,
              0d,
              0d,
              sec.getMinLongitude().degrees,
              sec.getMaxLatitude().degrees,
              0d,
              w - 1,
              0d,
              0d,
              sec.getMaxLongitude().degrees,
              sec.getMaxLatitude().degrees,
              0d,
              w - 1,
              h - 1,
              0d,
              sec.getMaxLongitude().degrees,
              sec.getMinLatitude().degrees,
              0d,
              0d,
              h - 1,
              0d,
              sec.getMinLongitude().degrees,
              sec.getMinLatitude().degrees,
              0d,
            };

        byte[] bytes = this.getBytes(values);
        this.theChannel.write(ByteBuffer.wrap(bytes));
        ifds.add(
            new TiffIFDEntry(GeoTiff.Tag.MODEL_TIEPOINT, Tiff.Type.DOUBLE, values.length, offset));
      }

      // Tiff.Tag.MODEL_TRANSFORMATION excludes Tiff.Tag.MODEL_TIEPOINT & Tiff.Tag.MODEL_PIXELSCALE

      if (params.hasKey(AVKey.MISSING_DATA_SIGNAL)
          || params.hasKey(AVKey.MISSING_DATA_REPLACEMENT)) {
        offset = this.theChannel.position();

        Object nodata =
            params.hasKey(AVKey.MISSING_DATA_SIGNAL)
                ? params.getValue(AVKey.MISSING_DATA_SIGNAL)
                : params.getValue(AVKey.MISSING_DATA_REPLACEMENT);

        String value = "" + nodata + "\0";
        byte[] bytes = value.getBytes();
        this.theChannel.write(ByteBuffer.wrap(bytes));
        ifds.add(new TiffIFDEntry(GeoTiff.Tag.GDAL_NODATA, Tiff.Type.ASCII, bytes.length, offset));
      }

      if (params.hasKey(AVKey.COORDINATE_SYSTEM)) {
        String cs = params.getStringValue(AVKey.COORDINATE_SYSTEM);

        if (AVKey.COORDINATE_SYSTEM_GEOGRAPHIC.equals(cs)) {
          if (isElevation(params)) this.writeGeographicElevationGeoKeys(ifds, params);
          else this.writeGeographicImageGeoKeys(ifds, params);
        } else if (AVKey.COORDINATE_SYSTEM_PROJECTED.equals(cs)) {
          String msg = Logging.getMessage("GeotiffWriter.FeatureNotImplementedd", cs);
          Logging.logger().severe(msg);
          throw new IllegalArgumentException(msg);
          // TODO extract PCS (Projection Coordinate System)
        } else {
          String msg = Logging.getMessage("GeotiffWriter.UnknownCoordinateSystem", cs);
          Logging.logger().severe(msg);
          throw new IllegalArgumentException(msg);
        }
      }
    }
  }