# include "data.h"

int grid (int argc, char **argv) {
  
  int j, N, MinorTick, MajorTick;
  Vector Xvec, Yvec;
  double range, lrange, factor, mantis, fmantis, power, major, minor, first, next;
  Graphdata graphmode;
  int Ngraph;

  Ngraph = -1;
  if ((N = get_argument (argc, argv, "-n"))) {
    remove_argument (N, &argc, argv);
    Ngraph = atof (argv[N]);
    remove_argument (N, &argc, argv);
  }
  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);

  MajorTick = TRUE;
  MinorTick = FALSE;
  if ((N = get_argument (argc, argv, "-all"))) {
    remove_argument (N, &argc, argv);
    MinorTick = TRUE;
  }

  if (argc > 1) {
    gprint (GP_ERR, "USAGE: grid [-n graph]\n");
    return (FALSE);
  }

  N = 0;
  Xvec.Nelements = 200;
  Yvec.Nelements = 200;
  ALLOCATE (Xvec.elements, float, Xvec.Nelements);
  ALLOCATE (Yvec.elements, float, Yvec.Nelements);

  major = minor = 1;
  range = graphmode.xmax - graphmode.xmin;
  lrange = log10(MAX(fabs(range), 1e-30));
  factor = (int) (lrange);
  if (lrange < 0) { factor -= 1; }
  mantis = lrange - factor;
  power = pow(10.0, factor);
  fmantis = pow(10.0, mantis);
  if ((fmantis >= 1.0) && (fmantis <=  2.0)) {
    major = 0.5 * power;
    minor = 0.1 * power;
  }
  if ((fmantis > 2.0) && (fmantis <=  4.0)) {
    major = 1.0 * power;
    minor = 0.2 * power;
  }
  if ((fmantis > 4.0) && (fmantis <=  6.0)) {
    major = 1.0 * power;
    minor = 0.5 * power;
  }
  if ((fmantis > 6.0) && (fmantis <=  10.0)) {
    major = 2.0 * power;
    minor = 0.5 * power;
  }
  if (graphmode.xmin > 0)
    first = minor + minor*((int)(graphmode.xmin/minor));
  else 
    first = -minor + minor*((int)(graphmode.xmin/minor));
  if (minor*((int)(graphmode.xmin/minor)) == graphmode.xmin) {
    first = graphmode.xmin;
  }
  
  for (j = 0, next = first; next <= graphmode.xmax; j++) {
    if ((fabs((int)(next/major) - (next/major)) < 0.5*(minor/major)) || (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major))) {
      if (MajorTick) {
	/* major tick */
	Xvec.elements[N] = next;
	Yvec.elements[N] = graphmode.ymin;
	N++;
	if (N == Xvec.Nelements) {
	  Xvec.Nelements += 200;
	  Yvec.Nelements += 200;
	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
	}
	Xvec.elements[N] = next;
	Yvec.elements[N] = graphmode.ymax;
	N++;
	if (N == Xvec.Nelements) {
	  Xvec.Nelements += 200;
	  Yvec.Nelements += 200;
	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
	}
      }
    } else {
      if (MinorTick) {
	/* minor tick */
	Xvec.elements[N] = next;
	Yvec.elements[N] = graphmode.ymin;
	N++;
	if (N == Xvec.Nelements) {
	  Xvec.Nelements += 200;
	  Yvec.Nelements += 200;
	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
	}
	Xvec.elements[N] = next;
	Yvec.elements[N] = graphmode.ymax;
	N++;
	if (N == Xvec.Nelements) {
	  Xvec.Nelements += 200;
	  Yvec.Nelements += 200;
	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
	}
      }
    }
    next += minor;
  }

  range = graphmode.ymax - graphmode.ymin;
  lrange = log10(MAX(fabs(range), 1e-30));
  factor = (int) (lrange);
  if (lrange < 0) { factor -= 1; }
  mantis = lrange - factor;
  power = pow(10.0, factor);
  fmantis = pow(10.0, mantis);
  if ((fmantis >= 1.0) && (fmantis <=  2.0)) {
    major = 0.5 * power;
    minor = 0.1 * power;
  }
  if ((fmantis > 2.0) && (fmantis <=  4.0)) {
    major = 1.0 * power;
    minor = 0.2 * power;
  }
  if ((fmantis > 4.0) && (fmantis <=  6.0)) {
    major = 1.0 * power;
    minor = 0.5 * power;
  }
  if ((fmantis > 6.0) && (fmantis <=  10.0)) {
    major = 2.0 * power;
    minor = 0.5 * power;
  }
  if (graphmode.ymin > 0)
    first = minor + minor*((int)(graphmode.ymin/minor));
  else 
    first = -minor + minor*((int)(graphmode.ymin/minor));
  if (minor*((int)(graphmode.ymin/minor)) == graphmode.ymin) {
    first = graphmode.ymin;
  }
  
  for (j = 0, next = first; next <= graphmode.ymax; j++) {
    if ((fabs((int)(next/major) - (next/major)) < 0.5*(minor/major)) || (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major))) {
      if (MajorTick) {
	/* major tick */
	Xvec.elements[N] = graphmode.xmin;
	Yvec.elements[N] = next;
	N++;
	if (N == Xvec.Nelements) {
	  Xvec.Nelements += 200;
	  Yvec.Nelements += 200;
	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
	}
	Xvec.elements[N] = graphmode.xmax;
	Yvec.elements[N] = next;
	N++;
	if (N == Xvec.Nelements) {
	  Xvec.Nelements += 200;
	  Yvec.Nelements += 200;
	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
	}
      }
    } else {
      if (MinorTick) {
	/* minor tick */
	Xvec.elements[N] = graphmode.xmin;
	Yvec.elements[N] = next;
	N++;
	if (N == Xvec.Nelements) {
	  Xvec.Nelements += 200;
	  Yvec.Nelements += 200;
	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
	}
	Xvec.elements[N] = graphmode.xmax;
	Yvec.elements[N] = next;
	N++;
	if (N == Xvec.Nelements) {
	  Xvec.Nelements += 200;
	  Yvec.Nelements += 200;
	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
	}
      }
    }
    next += minor;
  }

  Xvec.Nelements = Yvec.Nelements = N;
  graphmode.style = 2; /* points */
  graphmode.ptype = 100; /* connect a pair */
  graphmode.etype = 0;
  PrepPlotting (N, &graphmode);
  PlotVector (N, Xvec.elements);
  PlotVector (N, Yvec.elements);

  free (Xvec.elements);
  free (Yvec.elements);

  return (TRUE);

}

