public Grid extend(PointDouble values) {
      double	minX;
      double	maxX;
      double	minY;
      double	maxY;
      double	distance;
      Grid	result;
      
      // left
      if (Utils.smOrEq(values.getX(), getMinX())) {
	distance = getMinX() - values.getX();
	// exactly on grid point?
	if (Utils.eq(distance, 0))
	  minX = getMinX() - getStepX() * (StrictMath.round(distance / getStepX()) + 1);
	else
	  minX = getMinX() - getStepX() * (StrictMath.round(distance / getStepX()));
      }
      else {
	minX = getMinX();
      }
      
      // right
      if (Utils.grOrEq(values.getX(), getMaxX())) {
	distance = values.getX() - getMaxX();
	// exactly on grid point?
	if (Utils.eq(distance, 0))
	  maxX = getMaxX() + getStepX() * (StrictMath.round(distance / getStepX()) + 1);
	else
	  maxX = getMaxX() + getStepX() * (StrictMath.round(distance / getStepX()));
      }
      else {
	maxX = getMaxX();
      }
      
      // bottom
      if (Utils.smOrEq(values.getY(), getMinY())) {
	distance = getMinY() - values.getY();
	// exactly on grid point?
	if (Utils.eq(distance, 0))
	  minY = getMinY() - getStepY() * (StrictMath.round(distance / getStepY()) + 1);
	else
	  minY = getMinY() - getStepY() * (StrictMath.round(distance / getStepY()));
      }
      else {
	minY = getMinY();
      }
      
      // top
      if (Utils.grOrEq(values.getY(), getMaxY())) {
	distance = values.getY() - getMaxY();
	// exactly on grid point?
	if (Utils.eq(distance, 0))
	  maxY = getMaxY() + getStepY() * (StrictMath.round(distance / getStepY()) + 1);
	else
	  maxY = getMaxY() + getStepY() * (StrictMath.round(distance / getStepY()));
      }
      else {
	maxY = getMaxY();
      }
      
      result = new Grid(minX, maxX, getStepX(), getLabelX(), minY, maxY, getStepY(), getLabelY());
      
      // did the grid really extend?
      if (equals(result))
	throw new IllegalStateException("Grid extension failed!");
      
      return result;
    }