Q:

GridGeometry2D's world to grid function translating wrong

Using geotools version 11.2
import java.awt.Rectangle

import com.vividsolutions.jts.geom.Envelope
import org.geotools.coverage.grid.{GeneralGridEnvelope, GridGeometry2D}
import org.geotools.geometry.jts.ReferencedEnvelope
import org.geotools.referencing.crs.DefaultGeographicCRS.WGS84

val minX = -78.523
val minY = 38.010
val maxX = -78.451
val maxY = 38.069
val width = 400
val height = 300

val bounds = new ReferencedEnvelope(new Envelope(minX, maxX, minY, maxY), WGS84)
val rect = new Rectangle(0, 0, width, height)
val ggEnvelope = new GeneralGridEnvelope(rect, bounds.getDimension)
val gm = new GridGeometry2D(ggEnvelope, bounds)
////////////////// This should be [0, 299] but is [-1, 299]//////////////////////////////
gm.worldToGrid(bounds.getLowerCorner)

A:

Ended up using this function. You can see something similar for maxX and minY in the source code for GridGeometry2D.java worldToGrid function
  val TOL = 1.0E-6
  val values = Array(0.0)

  def safeWorldAccess(grid: GridCoverage2D, point: DirectPosition2D): Double = {
    val trPoint = point.clone()
    val gridGeom = grid.getGridGeometry
    if (Math.abs(trPoint.getX - gridGeom.getEnvelope2D.getMinX) <= TOL) {
      trPoint.setLocation(trPoint.getX + TOL, trPoint.getY)
    }

    if (Math.abs(trPoint.getY - gridGeom.getEnvelope2D.getMaxY) <= TOL) {
     trPoint.setLocation(trPoint.getX, trPoint.getY - TOL)
    }
    val gc: GridCoordinates2D = gridGeom.worldToGrid(trPoint)
    grid.evaluate(gc, values).head
  }

