Exemple #1
1
int centroids(int fd,		/* File descriptor of map layer to process */
	      /* This file is assumed to be opened before calling */
	      /*   centroids. */
	      int *e, int *n,	/* Pointers to arrays at least max+1 long */
	      int method,	/* 0, 1, or 2; see above. */
	      int max)
{				/* Highest positive cat number in map layer */
    CELL *cell_buf, v;
    int i, adjusted, numb, left, right;
    int *count;
    int row, col, rows, cols;

    adjusted = 0;

    cell_buf = Rast_allocate_c_buf();
    /* space to accumulate counts */
    count = (int *)G_malloc((max + 1) * sizeof(int));

    /* zero the count totals */
    for (i = 1; i <= max; i++) {
	count[i] = 0;
	e[i] = 0;
	n[i] = 0;
    }

    /* do rows and columns through window and mask */
    /*  to do counting */
    rows = Rast_window_rows();
    cols = Rast_window_cols();
    for (row = 0; row < rows; row++) {
	Rast_get_c_row(fd, cell_buf, row);	/* get a row */
	for (col = 0; col < cols; col++) {
	    v = cell_buf[col];	/* next cell value in row */
	    if (v < 1)
		continue;	/* can't handle 0 or - values */
	    count[v]++;
	    if (method > 0) {	/* acccumulate row, col weights */
		e[v] += col;
		n[v] += row;
	    }
	}
    }

    /* compute averages */
    if (method > 0)
	for (i = 0; i <= max; i++) {
	    if (count[i]) {
		numb = count[i];
		e[i] /= numb;
		n[i] /= numb;
	    }
	}

    /* substitute 'count' centroids for 'weighted' ones, if necessary */
    if (method == 1) {
	for (i = 1; i <= max; i++) {
	    if (count[i]) {
		row = n[i];
		col = e[i];
		/* get cell at row,col */
		Rast_get_c_row(fd, cell_buf, row);
		v = cell_buf[col];
		if (v > 0) {
		    if (v == i)
			count[i] = 0;	/* weighted is acceptable */
		    else
			adjusted++;
		}
	    }
	}
    }

    /* compute middle cell; zeros will remain zeros */
    for (i = 1; i <= max; i++)
	count[i] = (count[i] + 1) / 2;

    /* go through map again */
    for (row = 0; row < rows; row++) {
	Rast_get_c_row(fd, cell_buf, row);
	for (col = 0; col < cols; col++) {
	    v = cell_buf[col];
	    if (v < 1)
		continue;
	    if (count[v] == 0)
		continue;
	    if ((--count[v]) == 0) {	/* then this is middle cell */
		n[v] = row;
		/* find row-center in this clump */
		left = right = col;
		/* left edge first */
		while (left > 0)
		    if (cell_buf[--left] != v) {
			left++;
			break;
		    }
		/* then right edge */
		while (right < cols)
		    if (cell_buf[++right] != v) {
			right--;
			break;
		    }
		e[v] = (left + right) / 2;
	    }
	}
    }
    G_free(cell_buf);
    G_free(count);
    return (adjusted);
}				/* end of centroids() */
Exemple #2
0
/*!
   \brief Converts string of categories and cat ranges separated by commas to cat_list.

   \par Examples of string:
   \verbatim
   5,6,7
   3-9
   2,3,5-9,20\endverbatim
   
   \par Example:
   \code
   ...
   str = "2,3,5-9,20"
   cat_list = Vect_new_cat_list()

   Vect_str_to_cat_list(str, cat_list)
   \endcode
   \verbatim
   cat_list->field = 0
   cat_list->n_ranges = 4
   cat_list->min = {2, 3, 5, 20}
   cat_list->max = {2, 3, 9, 20}
   \endverbatim

   \param str category list as a string
   \param[in,out] list pointer to cat_list structure

   \return number of errors in ranges
 */
int Vect_str_to_cat_list(const char *str, struct cat_list *list)
{
    int i, nr, l, err = 0;
    const char *s, *e;
    char buf[100];
    int min, max;

    G_debug(3, "Vect_str_to_cat_list(): str = %s", str);

    list->n_ranges = 0;
    l = strlen(str);

    /* find number of ranges */
    nr = 1;			/* one range */
    for (i = 0; i < l; i++)
	if (str[i] == ',')
	    nr++;

    /* allocate space */
    if (list->alloc_ranges == 0) {
	list->min = (int *)G_malloc(nr * sizeof(int));
	list->max = (int *)G_malloc(nr * sizeof(int));
    }
    else if (nr > list->alloc_ranges) {
	list->min = (int *)G_realloc((void *)list->min, nr * sizeof(int));
	list->max = (int *)G_realloc((void *)list->max, nr * sizeof(int));
    }

    /* go through string and read ranges */
    i = 0;
    s = str;

    while (s) {
	e = (char *)strchr(s, ',');	/* first comma */
	if (e) {
	    l = e - s;
	    strncpy(buf, s, l);
	    buf[l] = '\0';
	    s = e + 1;
	}
	else {
	    strcpy(buf, s);
	    s = NULL;
	}

	G_debug(3, "  buf = %s", buf);
	if (sscanf(buf, "%d-%d", &min, &max) == 2) {
	}
	else if (sscanf(buf, "%d", &min) == 1)
	    max = min;
	else {			/* error */

	    G_warning(_("Unable to convert category string '%s' (from '%s') to category range"),
		      buf, str);
	    err++;
	    continue;
	}

	list->min[i] = min;
	list->max[i] = max;
	i++;
    }

    list->n_ranges = i;

    return (err);
}
Exemple #3
0
void CalcSurface(void)
{
    int Count, OutRows, OutCols;
    int Row, Row2, Col, Col2, RanRows, RanCols;
    int owC, oeC, onR, osR, wC, eC, nR, sR;
    double **Randoms;

    G_debug(2, "CalcSurface()");

    OutRows = BigF.RowPlus;
    OutCols = BigF.ColPlus;
    RanRows = (2 * OutRows + Rs);
    RanCols = (2 * OutCols + Cs);
    owC = osR = 0;
    wC = OutCols;
    sR = OutRows;
    oeC = RanCols - 1;
    onR = RanRows - 1;

    if (OutCols > 0)
	eC = RanCols - (OutCols + 1);
    else
	eC = oeC;

    if (OutRows > 0)
	nR = RanRows - (OutRows + 1);
    else
	nR = onR;

    Randoms = (double **)G_malloc(sizeof(double *) * RanRows);
    for (Row = 0; Row < RanRows; Row++)
	Randoms[Row] = (double *)G_malloc(RanCols * sizeof(double));

    /* OLD
       for( Row = OutRows; Row < RanRows; Row++) {
       for( Col = OutCols; Col < OutCols + Cs; Col++) {
       Randoms[ Row][ Col] = GasDev();
       }
       }

       for( Row = OutRows - 1; Row >= 0; Row--) {
       for( Col = OutCols; Col < OutCols + Cs; Col++) {
       Randoms[ Row][ Col] = GasDev();
       }
       }

       for( Row = 0; Row < RanRows; Row++) {
       for( Col = 0; Col < OutCols; Col++)
       Randoms[ Row][ Col] = GasDev();
       for( Col = OutCols + Cs; Col < RanCols; Col++)
       Randoms[ Row][ Col] = GasDev();
       }
       end OLD */

    for (Row = sR; Row <= nR; Row++) {
	for (Col = wC; Col <= eC; Col++) {
	    Randoms[Row][Col] = GasDev();
	}
    }

    Col = wC - 1;
    Col2 = eC + 1;
    while (Col >= 0) {
	for (Row = sR; Row <= nR; Row++) {
	    Randoms[Row][Col] = GasDev();
	    Randoms[Row][Col2] = GasDev();
	}
	Col--;
	Col2++;
    }

    Row = sR - 1;
    Row2 = nR + 1;
    while (Row >= 0) {
	for (Col = 0; Col < RanCols; Col++) {
	    Randoms[Row][Col] = GasDev();
	    Randoms[Row2][Col] = GasDev();
	}
	Row--;
	Row2++;
    }

    Count = 0;
    if (FDM == -1) {
	for (Row = 0; Row < Rs; Row++) {
	    if (ODD(Row)) {
		for (Col = Cs - 1; Col >= 0; Col--) {
		    G_percent(Count++, MapCount, 1);
		    Surface[Row][Col] =
			MakePP(Row, Col, OutRows, OutCols, Randoms, BigF);
		}
	    }
	    else {
		for (Col = 0; Col < Cs; Col++) {
		    G_percent(Count++, MapCount, 1);
		    Surface[Row][Col] =
			MakePP(Row, Col, OutRows, OutCols, Randoms, BigF);
		}
	    }
	}
	G_percent(1, 1, 1);
    }
    else {
	for (Row = 0; Row < Rs; Row++) {
	    G_get_map_row_nomask(FDM, CellBuffer, Row);
	    if (ODD(Row)) {
		for (Col = Cs - 1; Col >= 0; Col--) {
		    if (CellBuffer[Col] == 0)
			Surface[Row][Col] = 0.0;
		    else {
			G_percent(Count++, MapCount, 1);
			Surface[Row][Col] =
			    MakePP(Row, Col, OutRows, OutCols, Randoms, BigF);
		    }
		}
	    }
	    else {
		for (Col = 0; Col < Cs; Col++) {
		    if (CellBuffer[Col] == 0)
			Surface[Row][Col] = 0.0;
		    else {
			G_percent(Count++, MapCount, 1);
			Surface[Row][Col] =
			    MakePP(Row, Col, OutRows, OutCols, Randoms, BigF);
		    }
		}
	    }
	}
	G_percent(1, 1, 1);
    }

    G_free(Randoms);
}
Exemple #4
0
static int cell_draw( char *name,
                      char *mapset,
                      struct Colors *colors,
                      RASTER_MAP_TYPE data_type,
                      char *format )
{
  int cellfile;
  void *xarray;
  int row;
  int ncols, nrows;
  static unsigned char *red, *grn, *blu, *set;
  int i;
  void *ptr;
  int big_endian;
  long one = 1;
  FILE *fo;
  size_t raster_size;
#ifdef NAN
  double dnul = NAN;
  float fnul = ( float )( NAN );
#else
  double dnul = strtod( "NAN", 0 );
  float fnul = strtof( "NAN", 0 );
  // another possibility would be nan()/nanf() - C99
  // and 0./0. if all fails
#endif

  assert( dnul != dnul );
  assert( fnul != fnul );

  big_endian = !( *(( char * )( &one ) ) );

  ncols = G_window_cols();
  nrows = G_window_rows();

  /* Make sure map is available */
  if (( cellfile = G_open_cell_old( name, mapset ) ) == -1 )
    G_fatal_error(( "Unable to open raster map <%s>" ), name );

  /* Allocate space for cell buffer */
  xarray = G_allocate_raster_buf( data_type );
  red = G_malloc( ncols );
  grn = G_malloc( ncols );
  blu = G_malloc( ncols );
  set = G_malloc( ncols );

  /* some buggy C libraries require BOTH setmode() and fdopen(bin) */
  // Do not use Q_OS_WIN, we are in C file, no Qt headers
#ifdef WIN32
  if ( _setmode( _fileno( stdout ), _O_BINARY ) == -1 )
    G_fatal_error( "Cannot set stdout mode" );
#endif
  // Unfortunately this is not sufficient on Windows to switch stdout to binary mode
  fo = fdopen( fileno( stdout ), "wb" );

  raster_size = G_raster_size( data_type );
  //fprintf( fo, "%d %d", data_type, raster_size );
  //exit(0);
  /* loop for array rows */
  for ( row = 0; row < nrows; row++ )
  {
    G_get_raster_row( cellfile, xarray, row, data_type );
    ptr = xarray;

    G_lookup_raster_colors( xarray, red, grn, blu, set, ncols, colors,
                            data_type );

    for ( i = 0; i < ncols; i++ )
    {
      unsigned char alpha = 255;
      //G_debug ( 0, "row = %d col = %d", row, i );
      if ( G_is_null_value( ptr, data_type ) )
      {
        alpha = 0;
      }

      if ( strcmp( format, "color" ) == 0 )
      {
        // We need data suitable for QImage 32-bpp
        // the data are stored in QImage as QRgb which is unsigned int.
        // Because it depends on byte order of the platform we have to
        // consider byte order (well, middle endian ignored)
        if ( big_endian )
        {
          // I have never tested this
          fprintf( fo, "%c%c%c%c", alpha, red[i], grn[i], blu[i] );
        }
        else
        {
          fprintf( fo, "%c%c%c%c", blu[i], grn[i], red[i], alpha );
        }
      }
      else
      {
        if ( data_type == CELL_TYPE )
        {
          //G_debug ( 0, "valx = %d", *((CELL *) ptr));
        }
        if ( G_is_null_value( ptr, data_type ) )
        {
          // see comments in QgsGrassRasterProvider::noDataValue()
          if ( data_type == CELL_TYPE )
          {
            //int nul = -2000000000;
            int nul = INT_MIN;
            fwrite( &nul, 4, 1, fo );
          }
          else if ( data_type == DCELL_TYPE )
          {
            //double nul = -1e+300;
            fwrite( &dnul, 8, 1, fo );
          }
          else if ( data_type == FCELL_TYPE )
          {
            //double nul = -1e+30;
            fwrite( &fnul, 4, 1, fo );
          }
        }
        else
        {
          fwrite( ptr, raster_size, 1, fo );
        }
      }
      ptr = G_incr_void_ptr( ptr, raster_size );
    }
  }

  G_close_cell( cellfile );
  fclose( fo );

  return ( 0 );
}
Exemple #5
0
int do_cum_mfd(void)
{
    int r, c, dr, dc;
    CELL is_swale;
    DCELL value, valued, tci_div, sum_contour, cell_size;
    int killer, threshold;

    /* MFD */
    int mfd_cells, stream_cells, swale_cells, astar_not_set, is_null;
    double *dist_to_nbr, *contour, *weight, sum_weight, max_weight;
    int r_nbr, c_nbr, r_max, c_max, ct_dir, np_side;
    CELL ele, ele_nbr, aspect, is_worked;
    double prop, max_val;
    int workedon, edge, flat;
    int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 };
    int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };
    int this_index, down_index, nbr_index;
    
    G_message(_("SECTION 3a: Accumulating Surface Flow with MFD."));
    G_debug(1, "MFD convergence factor set to %d.", c_fac);

    /* distances to neighbours, weights, contour lengths */
    dist_to_nbr = (double *)G_malloc(sides * sizeof(double));
    weight = (double *)G_malloc(sides * sizeof(double));
    contour = (double *)G_malloc(sides * sizeof(double));
    
    cell_size = get_dist(dist_to_nbr, contour);

    flag_clear_all(worked);
    workedon = 0;

    if (bas_thres <= 0)
	threshold = 60;
    else
	threshold = bas_thres;

    for (killer = 1; killer <= do_points; killer++) {
	G_percent(killer, do_points, 1);
	this_index = astar_pts[killer];
	seg_index_rc(alt_seg, this_index, &r, &c);
	FLAG_SET(worked, r, c);
	aspect = asp[this_index];
	if (aspect) {
	    dr = r + asp_r[ABS(aspect)];
	    dc = c + asp_c[ABS(aspect)];
	}
	else
	    dr = dc = -1;
	if (dr >= 0 && dr < nrows && dc >= 0 && dc < ncols) { /* if ((dr = astar_pts[killer].downr) > -1) { */
	    value = wat[this_index];
	    down_index = SEG_INDEX(wat_seg, dr, dc);

	    /* get weights */
	    max_weight = 0;
	    sum_weight = 0;
	    np_side = -1;
	    mfd_cells = 0;
	    astar_not_set = 1;
	    ele = alt[this_index];
	    is_null = 0;
	    edge = 0;
	    /* this loop is needed to get the sum of weights */
	    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
		/* get r, c (r_nbr, c_nbr) for neighbours */
		r_nbr = r + nextdr[ct_dir];
		c_nbr = c + nextdc[ct_dir];
		weight[ct_dir] = -1;

		if (dr == r_nbr && dc == c_nbr)
		    np_side = ct_dir;

		/* check that neighbour is within region */
		if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 &&
		    c_nbr < ncols) {

		    nbr_index = SEG_INDEX(wat_seg, r_nbr, c_nbr);

		    valued = wat[nbr_index];
		    ele_nbr = alt[nbr_index];

		    is_worked = FLAG_GET(worked, r_nbr, c_nbr);
		    if (is_worked == 0) {
			is_null = Rast_is_c_null_value(&ele_nbr);
			edge = is_null;
			if (!is_null && ele_nbr <= ele) {
			    if (ele_nbr < ele) {
				weight[ct_dir] =
				    mfd_pow(((ele -
					      ele_nbr) / dist_to_nbr[ct_dir]),
					    c_fac);
			    }
			    if (ele_nbr == ele) {
				weight[ct_dir] =
				    mfd_pow((0.5 / dist_to_nbr[ct_dir]),
					    c_fac);
			    }
			    sum_weight += weight[ct_dir];
			    mfd_cells++;

			    if (weight[ct_dir] > max_weight) {
				max_weight = weight[ct_dir];
			    }

			    if (dr == r_nbr && dc == c_nbr) {
				astar_not_set = 0;
			    }
			    if (value < 0 && valued > 0)
				wat[nbr_index] = -valued;
			}
		    }
		}
		else
		    edge = 1;
		if (edge)
		    break;
	    }
	    /* do not distribute flow along edges, this causes artifacts */
	    if (edge) {
		continue;
	    }

	    /* honour A * path 
	     * mfd_cells == 0: fine, SFD along A * path
	     * mfd_cells == 1 && astar_not_set == 0: fine, SFD along A * path
	     * mfd_cells > 0 && astar_not_set == 1: A * path not included, add to mfd_cells
	     */

	    /* MFD, A * path not included, add to mfd_cells */
	    if (mfd_cells > 0 && astar_not_set == 1) {
		mfd_cells++;
		sum_weight += max_weight;
		weight[np_side] = max_weight;
	    }

	    /* set flow accumulation for neighbours */
	    max_val = -1;
	    tci_div = sum_contour = 0.;

	    if (mfd_cells > 1) {
		prop = 0.0;
		for (ct_dir = 0; ct_dir < sides; ct_dir++) {
		    r_nbr = r + nextdr[ct_dir];
		    c_nbr = c + nextdc[ct_dir];

		    /* check that neighbour is within region */
		    if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 &&
			c_nbr < ncols && weight[ct_dir] > -0.5) {
			is_worked = FLAG_GET(worked, r_nbr, c_nbr);
			if (is_worked == 0) {

			    nbr_index = SEG_INDEX(wat_seg, r_nbr, c_nbr);

			    weight[ct_dir] = weight[ct_dir] / sum_weight;
			    /* check everything adds up to 1.0 */
			    prop += weight[ct_dir];

			    if (atanb_flag) {
				sum_contour += contour[ct_dir];
				tci_div += get_slope_tci(ele, alt[nbr_index],
				                         dist_to_nbr[ct_dir]) *
					   weight[ct_dir];
			    }

			    valued = wat[nbr_index];
			    if (value > 0) {
				if (valued > 0)
				    valued += value * weight[ct_dir];
				else
				    valued -= value * weight[ct_dir];
			    }
			    else {
				if (valued < 0)
				    valued += value * weight[ct_dir];
				else
				    valued = value * weight[ct_dir] - valued;
			    }
			    wat[nbr_index] = valued;
			}
			else if (ct_dir == np_side) {
			    /* check for consistency with A * path */
			    workedon++;
			}
		    }
		}
		if (ABS(prop - 1.0) > 5E-6f) {
		    G_warning(_("MFD: cumulative proportion of flow distribution not 1.0 but %f"),
			      prop);
		}
	    }
	    /* SFD-like accumulation */
	    else {
		valued = wat[down_index];
		if (value > 0) {
		    if (valued > 0)
			valued += value;
		    else
			valued -= value;
		}
		else {
		    if (valued < 0)
			valued += value;
		    else
			valued = value - valued;
		}
		wat[down_index] = valued;

		if (atanb_flag) {
		    sum_contour = contour[np_side];
		    tci_div = get_slope_tci(ele, alt[down_index],
				            dist_to_nbr[np_side]);
		}
	    }
	    /* topographic wetness index ln(a / tan(beta)) and
	     * stream power index a * tan(beta) */
	    if (atanb_flag) {
		sca[this_index] = fabs(wat[this_index]) *
		                  (cell_size / sum_contour);
		tanb[this_index] = tci_div;
	    }
	}
    }
    if (workedon)
	G_warning(n_("MFD: A * path already processed when distributing flow: %d of %d cell", 
        "MFD: A * path already processed when distributing flow: %d of %d cells", 
        do_points),
		  workedon, do_points);


    G_message(_("SECTION 3b: Adjusting drainage directions."));

    for (killer = 1; killer <= do_points; killer++) {
	G_percent(killer, do_points, 1);
	this_index = astar_pts[killer];
	seg_index_rc(alt_seg, this_index, &r, &c);
	FLAG_UNSET(worked, r, c);
	aspect = asp[this_index];
	if (aspect) {
	    dr = r + asp_r[ABS(aspect)];
	    dc = c + asp_c[ABS(aspect)];
	}
	else
	    dr = dc = -1;
	if (dr >= 0 && dr < nrows && dc >= 0 && dc < ncols) { /* if ((dr = astar_pts[killer].downr) > -1) { */
	    value = wat[this_index];
	    down_index = SEG_INDEX(wat_seg, dr, dc);

	    r_max = dr;
	    c_max = dc;

	    /* get max flow accumulation */
	    max_val = -1;
	    stream_cells = 0;
	    swale_cells = 0;
	    ele = alt[this_index];
	    is_null = 0;
	    edge = 0;
	    flat = 1;

	    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
		/* get r, c (r_nbr, c_nbr) for neighbours */
		r_nbr = r + nextdr[ct_dir];
		c_nbr = c + nextdc[ct_dir];

		/* check that neighbour is within region */
		if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 &&
		    c_nbr < ncols) {

		    nbr_index = SEG_INDEX(wat_seg, r_nbr, c_nbr);

		    /* check for swale or stream cells */
		    is_swale = FLAG_GET(swale, r_nbr, c_nbr);
		    if (is_swale)
			swale_cells++;
		    valued = wat[nbr_index];
		    ele_nbr = alt[nbr_index];
		    edge = Rast_is_c_null_value(&ele_nbr);
		    if ((ABS(valued) + 0.5) >= threshold  &&
		        ele_nbr > ele)
			stream_cells++;

		    is_worked = !(FLAG_GET(worked, r_nbr, c_nbr));
		    if (is_worked == 0) {
			if (ele_nbr != ele)
			    flat = 0;
			is_null = Rast_is_c_null_value(&ele_nbr);
			edge = is_null;
			if (!is_null && ABS(valued) > max_val) {
			    max_val = ABS(valued);
			    r_max = r_nbr;
			    c_max = c_nbr;
			}
		    }
		}
		else
		    edge = 1;
		if (edge)
		    break;
	    }
	    /* do not distribute flow along edges, this causes artifacts */
	    if (edge) {
		is_swale = FLAG_GET(swale, r, c);
		if (is_swale && aspect > 0) {
		    aspect = -1 * drain[r - r_nbr + 1][c - c_nbr + 1];
		    asp[this_index] = aspect;
		}
		continue;
	    }
	    
	    /* update asp */
	    if (dr != r_max || dc != c_max) {
		aspect = drain[r - r_max + 1][c - c_max + 1];
		if (asp[this_index] < 0)
		    aspect = -aspect;
		asp[this_index] = aspect;
	    }
	    is_swale = FLAG_GET(swale, r, c);
	    /* start new stream */
	    value = ABS(value) + 0.5;
	    if (!is_swale && (int)value >= threshold && stream_cells < 1 &&
		swale_cells < 1 && !flat) {
		FLAG_SET(swale, r, c);
		is_swale = 1;
	    }
	    /* continue stream */
	    if (is_swale) {
		FLAG_SET(swale, r_max, c_max);
	    }
	    else {
		if (er_flag && !is_swale)
		    slope_length(r, c, r_max, c_max);
	    }
	}
    }

    G_free(astar_pts);

    flag_destroy(worked);

    G_free(dist_to_nbr);
    G_free(weight);

    return 0;
}
Exemple #6
0
/*!
  \brief Write data to GRASS ASCII vector format

  Prints message if some features without category are skipped.

  \param[out] ascii  pointer to the output ASCII file
  \param[out] att    att file (< version 5 only)
  \param Map    pointer to Map_info structure
  \param ver    version number 4 or 5
  \param format format GV_ASCII_FORMAT_POINT or GV_ASCII_FORMAT_STD
  \param dp     number of significant digits
  \param fs     field separator
  \param region_flag check region
  \param type   feature type filter
  \param field  field number
  \param Clist  list of categories to filter features or NULL
  \param where  SQL select where statement to filter features or NULL
  \param column_names array of columns to be included to the output or NULL
                 "*" as the first item in the array indicates all columns
  \param header TRUE to print also header

  \return number of written features
  \return -1 on error
*/
int Vect_write_ascii(FILE *ascii,
		     FILE *att, struct Map_info *Map, int ver,
		     int format, int dp, char *fs, int region_flag, int type,
		     int field, const struct cat_list *Clist, const char* where,
		     const char **column_names, int header)
{
    int ltype, ctype, i, cat, line, left, right, found;
    double *xptr, *yptr, *zptr, x, y;
    static struct line_pnts *Points;
    struct line_cats *Cats, *ACats;
    char *xstring, *ystring, *zstring;
    size_t xsize, ysize, zsize;
    struct Cell_head window;
    struct ilist *fcats;
    int count, n_skipped;

    /* where || columns */
    struct field_info *Fi;
    dbDriver *driver;
    dbValue value;
    dbHandle handle;
    int *cats, ncats, more;
    dbTable *Table;
    dbString dbstring;
    dbColumn *Column;
    dbValue *Value;
    char *buf;
    size_t bufsize;
    dbCursor cursor;
    /* columns */
    char **columns;
    int *coltypes;
    char *all_columns;
    
    Fi = NULL;
    driver = NULL;
    columns = NULL;
    coltypes = NULL;
    all_columns = NULL;
    
    G_zero(&value, sizeof(dbValue));
    db_init_string(&dbstring);

    xstring = NULL;
    ystring = NULL;
    zstring = NULL;
    xsize = 0;
    ysize = 0;
    zsize = 0;
    buf = NULL;
    bufsize = 0;

    /* get the region */
    G_get_window(&window);

    count = ncats = 0;
    xstring = ystring = zstring = NULL;
    cats = NULL;
    
    if (field > 0 && (where || column_names)) {
	Fi = Vect_get_field(Map, field);
	if (!Fi) {
	    G_fatal_error(_("Database connection not defined for layer %d"),
			  field);
	}

	driver = db_start_driver(Fi->driver);
	if (!driver)
	    G_fatal_error(_("Unable to start driver <%s>"), Fi->driver);
	
	db_init_handle(&handle);
	db_set_handle(&handle, Fi->database, NULL);
	
	if (db_open_database(driver, &handle) != DB_OK)
	    G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
			  Fi->database, Fi->driver);
	
	/* select cats (sorted array) */
	ncats = db_select_int(driver, Fi->table, Fi->key, where, &cats);
	G_debug(3, "%d categories selected from table <%s>", ncats, Fi->table);

	if (!column_names) {
	    db_close_database(driver);
	    db_shutdown_driver(driver);
	}
	else {
	    int icol, ncols;
	    const char *col_name;
            int len_all = 0;
            
	    db_set_string(&dbstring, Fi->table);
	    if (db_describe_table(driver, &dbstring, &Table) != DB_OK) {
		G_warning(_("Unable to describe table <%s>"), Fi->table);
		return -1;
	    }
	    
	    ncols = db_get_table_number_of_columns(Table);
	    columns = (char **) G_malloc((ncols + 1) * sizeof(char *));

            if (column_names[0] && strcmp(column_names[0], "*") == 0) {
                
                /* all columns */
                icol = 0;
                for (i = 0; i < ncols; i++) {
                    col_name = db_get_column_name(db_get_table_column(Table, i));
		    /* key column skipped */
                    if (strcmp(Fi->key, col_name) != 0)
			columns[icol++] = G_store(col_name);
                }
                columns[icol] = NULL;
            }
            else {
		int j;

		icol = 0;
		i = 0;
		while (column_names[i]) {
		    /* key column skipped */
                    if (strcmp(Fi->key, column_names[i]) != 0) {
			found = 0;
			for (j = 0; j < ncols; j++) {
			    col_name = db_get_column_name(db_get_table_column(Table, j));
			    if (strcmp(col_name, column_names[i]) == 0) {
				columns[icol++] = G_store(col_name);
				found = 1;
				break;
			    }
			}
			if (!found) {
			    G_warning(_("Column <%s> does not exist"),
				      column_names[i]);
			    G_important_message(_("Available columns:"));
			    for (j = 0; j < ncols; j++) {
				col_name = db_get_column_name(db_get_table_column(Table, j));
				G_important_message("%s", col_name);
			    }
			    G_warning(_("Export cancelled"));
			    db_close_database(driver);
			    db_shutdown_driver(driver);
			    return -1;
			}
		    }
		    i++;
                }
                columns[icol] = NULL;
            }

	    db_zero_string(&dbstring);
	    db_free_table(Table);
	    Table = NULL;
            
	    if (columns[0]) {
		/* selected columns only */
		i = 0;
		while (columns[i])
		    len_all += strlen(columns[i++]);
		
		coltypes = G_malloc(i * sizeof(int));
		
		all_columns = G_malloc(len_all + i + 2);

		i = 0;
		strcpy(all_columns, columns[0]);
		while (columns[i]) {
		    /* get column types */
		    coltypes[i] = db_column_Ctype(driver, Fi->table, columns[i]);
		    if (coltypes[i] < 0) {
			db_close_database(driver);
			db_shutdown_driver(driver);
			G_warning(_("Unknown type of column <%s>, export cancelled"),
				  columns[i]);
			return -1;
		    }
		    if (i > 0) {
			strcat(all_columns, ",");
			strcat(all_columns, columns[i]);
		    }
		    i++;
		}
	    }
	    else {
		/* no column or only key column selected */
		G_free(columns);
		columns = NULL;

		db_close_database(driver);
		db_shutdown_driver(driver);
	    }
	}
    }

    if (format == GV_ASCII_FORMAT_POINT && header) {

	/* print header */
	if (Map->head.with_z)
	    fprintf(ascii, "east%snorth%sheight%scat", fs, fs, fs);
	else
	    fprintf(ascii, "east%snorth%scat", fs, fs);
	if (columns) {
	    for (i = 0; columns[i]; i++) {
		if (db_select_value
		    (driver, Fi->table, Fi->key, cat,
		     columns[i], &value) < 0)
		    G_fatal_error(_("Unable to select record from table <%s> (key %s, column %s)"),
				  Fi->table, Fi->key, columns[i]);
		if (columns[i])
		    fprintf(ascii, "%s%s", fs, columns[i]);
		else
		    fprintf(ascii, "%s", columns[i]); /* can not happen */
	    }
	}
	fprintf(ascii, "%s", HOST_NEWLINE);
    }

    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();
    ACats = Vect_new_cats_struct();
    fcats = Vect_new_list();

    /* by default, read_next_line will NOT read Dead lines */
    /* but we can override that (in Level I only) by specifying */
    /* the type  -1, which means match all line types */

    Vect_rewind(Map);

    count = n_skipped = line = 0;
    while (TRUE) {
	ltype = Vect_read_next_line(Map, Points, Cats);
	if (ltype == -1 ) {      /* failure */
	    if (columns) {
		db_close_database(driver);
		db_shutdown_driver(driver);

                free_col_arrays(coltypes, all_columns,
                                column_names && strcmp(column_names[0], "*") == 0 ? columns : NULL);
	    }
	    
	    return -1;
	}

	if (ltype == -2)	{	/* EOF */
	    if (columns) {
		db_close_database(driver);
		db_shutdown_driver(driver);
                
                free_col_arrays(coltypes, all_columns,
                                column_names && strcmp(column_names[0], "*") == 0 ? columns : NULL);
	    }
	    break;
	}

	line++;

	if (!(ltype & type))
	    continue;

	if (format == GV_ASCII_FORMAT_POINT && !(ltype & GV_POINTS))
	    continue;

	found = get_cat(Cats, Clist, cats, ncats, field, &cat);

	if (!found && field > 0 && ltype == GV_BOUNDARY &&
	    type & GV_AREA && Vect_level(Map) > 1) {
	    Vect_get_line_areas(Map, line, &left, &right);
	    if (left < 0)
		left = Vect_get_isle_area(Map, abs(left));
	    if (left > 0) {
		Vect_get_area_cats(Map, left, ACats);
		found = get_cat(ACats, Clist, cats, ncats, field, &cat);
	    }
	    if (right < 0)
		right = Vect_get_isle_area(Map, abs(right));
	    if (!found && right > 0) {
		Vect_get_area_cats(Map, right, ACats);
		found = get_cat(ACats, Clist, cats, ncats, field, &cat);
	    }
	}
	
	if (!found) {
            if (Cats->n_cats < 1)
                n_skipped++;
            
	    continue;
	}

	if (ver < 5) {
	    Vect_cat_get(Cats, 1, &cat);
	}

	switch (ltype) {
	case GV_BOUNDARY:
	    if (ver == 5)
		ctype = 'B';
	    else
		ctype = 'A';
	    break;
	case GV_CENTROID:
	    if (ver < 5) {
		if (att != NULL) {
		    if (cat > 0) {
			G_rasprintf(&xstring, &xsize, "%.*f", dp, Points->x[0]);
			G_trim_decimal(xstring);
			G_rasprintf(&ystring, &ysize, "%.*f", dp, Points->y[0]);
			G_trim_decimal(ystring);
			fprintf(att, "A %s %s %d%s", xstring, ystring, cat, HOST_NEWLINE);
		    }
		}
		continue;
	    }
	    ctype = 'C';
	    break;
	case GV_LINE:
	    ctype = 'L';
	    break;
	case GV_POINT:
	    ctype = 'P';
	    break;
	case GV_FACE:
	    ctype = 'F';
	    break;
	case GV_KERNEL:
	    ctype = 'K';
	    break;
	default:
	    ctype = 'X';
	    G_warning(_("Unknown feature type %d"), (int)ltype);
	    break;
	}

	if (format == GV_ASCII_FORMAT_POINT) {
	    if (region_flag) {
		if ((window.east < Points->x[0]) ||
		    (window.west > Points->x[0]))
		    continue;
	    }
	    G_rasprintf(&xstring, &xsize, "%.*f", dp, Points->x[0]);
	    G_trim_decimal(xstring);

	    if (region_flag) {
		if ((window.north < Points->y[0]) ||
		    (window.south > Points->y[0]))
		    continue;
	    }
	    G_rasprintf(&ystring, &ysize, "%.*f", dp, Points->y[0]);
	    G_trim_decimal(ystring);

	    Vect_field_cat_get(Cats, field, fcats);

	    if (Map->head.with_z && ver == 5) {
		if (region_flag) {
		    if ((window.top < Points->z[0]) ||
			(window.bottom > Points->z[0]))
			continue;
		}
		G_rasprintf(&zstring, &zsize, "%.*f", dp, Points->z[0]);
		G_trim_decimal(zstring);
		fprintf(ascii, "%s%s%s%s%s", xstring, fs, ystring, fs,
			zstring);
	    }
	    else {
		fprintf(ascii, "%s%s%s", xstring, fs, ystring);
	    }

	    if (fcats->n_values > 0 && cat > -1) {
		if (fcats->n_values > 1) {
		    G_warning(_("Feature has more categories. Only one category (%d) "
				"is exported."), cat);
		}
		fprintf(ascii, "%s%d", fs, cat);
		
		/* print attributes */
		if (columns) {

		    G_rasprintf(&buf, &bufsize, "SELECT %s FROM %s WHERE %s = %d",
			    all_columns, Fi->table, Fi->key, cat);
		    G_debug(2, "SQL: %s", buf);
		    db_set_string(&dbstring, buf);

		    if (db_open_select_cursor
				    (driver, &dbstring, &cursor, DB_SEQUENTIAL) != DB_OK) {
			db_close_database(driver);
			db_shutdown_driver(driver);
			G_fatal_error(_("Cannot select attributes for cat = %d"),
			  cat);
		    }
		    if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) {
			db_close_database(driver);
			db_shutdown_driver(driver);
			G_fatal_error(_("Unable to fetch data from table"));
		    }

		    Table = db_get_cursor_table(&cursor);


		    for (i = 0; columns[i]; i++) {
			Column = db_get_table_column(Table, i);
			Value = db_get_column_value(Column);

			if (db_test_value_isnull(Value)) {
			    fprintf(ascii, "%s", fs);
			}
			else {
			    switch(coltypes[i])
			    {
			    case DB_C_TYPE_INT: {
				fprintf(ascii, "%s%d", fs, db_get_value_int(Value));
				break;
			    }
			    case DB_C_TYPE_DOUBLE: {
				fprintf(ascii, "%s%.*f", fs, dp, db_get_value_double(Value));
				break;
			    }
			    case DB_C_TYPE_STRING: {
				fprintf(ascii, "%s%s", fs, db_get_value_string(Value));
				break;
			    }
			    case DB_C_TYPE_DATETIME: {
				break;
			    }
			    case -1:
				G_fatal_error(_("Column <%s> not found in table <%s>"),
					      columns[i], Fi->table);
			    default: G_fatal_error(_("Column <%s>: unsupported data type"),
						   columns[i]);
			    }
			}
		    }
		    db_close_cursor(&cursor);
		}
	    }

	    fprintf(ascii, "%s", HOST_NEWLINE);
	}
	else if (format == GV_ASCII_FORMAT_STD) {
	    /* FORMAT_STANDARD */
	    if (ver == 5 && Cats->n_cats > 0)
		fprintf(ascii, "%c  %d %d%s", ctype, Points->n_points,
			Cats->n_cats, HOST_NEWLINE);
	    else
              fprintf(ascii, "%c  %d%s", ctype, Points->n_points, HOST_NEWLINE);

	    xptr = Points->x;
	    yptr = Points->y;
	    zptr = Points->z;

	    while (Points->n_points--) {

		G_rasprintf(&xstring, &xsize, "%.*f", dp, *xptr++);
		G_trim_decimal(xstring);
		G_rasprintf(&ystring, &ysize, "%.*f", dp, *yptr++);
		G_trim_decimal(ystring);

		if (ver == 5) {
		    if (Map->head.with_z) {
			G_rasprintf(&zstring, &zsize, "%.*f", dp, *zptr++);
			G_trim_decimal(zstring);
			fprintf(ascii, " %-12s %-12s %-12s%s", xstring,
				ystring, zstring, HOST_NEWLINE);
		    }
		    else {
                      fprintf(ascii, " %-12s %-12s%s", xstring, ystring, HOST_NEWLINE);
		    }
		}		/*Version 4 */
		else {
                    fprintf(ascii, " %-12s %-12s%s", ystring, xstring, HOST_NEWLINE);
		}
	    }

	    if (ver == 5) {
		for (i = 0; i < Cats->n_cats; i++) {
		    fprintf(ascii, " %-5d %-10d%s", Cats->field[i],
			    Cats->cat[i], HOST_NEWLINE);
		}
	    }
	    else {
		if (cat > -1) {
		    if (ltype == GV_POINT) {
			G_rasprintf(&xstring, &xsize, "%.*f", dp, Points->x[0]);
			G_trim_decimal(xstring);
			G_rasprintf(&ystring, &ysize, "%.*f", dp, Points->y[0]);
			G_trim_decimal(ystring);
			fprintf(att, "P %s %s %d%s", xstring, ystring, cat, HOST_NEWLINE);
		    }
		    else {
			x = (Points->x[1] + Points->x[0]) / 2;
			y = (Points->y[1] + Points->y[0]) / 2;

			G_rasprintf(&xstring, &xsize, "%.*f", dp, x);
			G_trim_decimal(xstring);
			G_rasprintf(&ystring, &ysize, "%.*f", dp, y);
			G_trim_decimal(ystring);
			fprintf(att, "L %s %s %d%s", xstring, ystring, cat, HOST_NEWLINE);
		    }
		}
	    }
	}
	else if (format == GV_ASCII_FORMAT_WKT) {
	    if (ltype & (GV_BOUNDARY | GV_CENTROID | GV_FACE | GV_KERNEL))
		continue;
	    /* Well-Known Text */
	    Vect_sfa_line_astext(Points, ltype, Vect_is_3d(Map), dp, ascii);
	    count++;
	}
	else {
	    G_fatal_error(_("Unknown format"));
	}
	count++;
    }

    if (format == GV_ASCII_FORMAT_WKT) {
	/* process areas - topology required */
	int i, area, nareas, isle, nisles;

	if (Vect_level(Map) < 2) {
	    G_warning(_("Topology not available, unable to process areas"));
	    nareas = 0;
	}
	else {
	    nareas = Vect_get_num_areas(Map);
	}
	for (area = 1; area <= nareas; area++) {
	    if (!Vect_area_alive(Map, area)) /* skip dead areas */
		continue;
	    if (Vect_get_area_cat(Map, area, field) < 0)
		continue;
	    /* get boundary -> linearring */
	    if (Vect_get_area_points(Map, area, Points) < 0) {
		G_warning(_("Unable to get boundary of area id %d"), area);
		continue;
	    }
	    fprintf(ascii, "POLYGON(");
	    /* write outter ring */
	    Vect_sfa_line_astext(Points, GV_BOUNDARY, 0, dp, ascii); /* boundary is always 2D */
	    /* get isles (holes) -> inner rings */
	    nisles = Vect_get_area_num_isles(Map, area);
	    for (i = 0; i < nisles; i++) {
		/* get isle boundary -> linearring */
		isle = Vect_get_area_isle(Map, area, i);
		if (Vect_get_isle_points(Map, isle, Points) < 0) {
		    G_warning(_("Unable to get boundary of isle id %d (area id %d)"), isle, area);
		    continue;
		}
		fprintf(ascii, ", ");
		/* write inner ring */
		Vect_sfa_line_astext(Points, GV_BOUNDARY, 0, dp, ascii); /* boundary is always 2D */
	    }
	    fprintf(ascii, ")%s", HOST_NEWLINE);
	    
	    count++;
	}
    }

    if (n_skipped > 0)
        G_important_message(_("%d features without category skipped. To export also "
                              "features without category use '%s=-1'."), n_skipped, "layer");
    
    Vect_destroy_line_struct(Points);
    Vect_destroy_cats_struct(Cats);
    Vect_destroy_cats_struct(ACats);
    
    return count;
}
Exemple #7
0
struct Map_info *G_sites_open_old(const char *name, const char *mapset)
{
    struct Map_info *Map;
    struct field_info *fi;
    int more, nrows, row, ncols, col, ndbl, nstr, adbl, astr, ctype;
    SITE_ATT *sa;

    dbDriver *driver;
    dbString stmt;
    dbCursor cursor;
    dbTable *table;
    dbColumn *column;
    dbValue *value;

    G_message(
	_("Dev note: Adapted sites library used for vector points. "
	  "(module should be updated to GRASS 6 vector library)"));

    Map = (struct Map_info *)G_malloc(sizeof(struct Map_info));

    Vect_set_open_level(1);
    Vect_open_old(Map, name, mapset);

    G_debug(1, "Vector map opened");

    /* Load attributes */
    Map->site_att = NULL;
    Map->n_site_att = 0;
    Map->n_site_dbl = 0;
    Map->n_site_str = 0;

    fi = Vect_get_field(Map, 1);
    if (fi == NULL) {		/* not attribute table */
	G_debug(1, "No attribute table");
	return Map;
    }

    driver = db_start_driver_open_database(fi->driver, fi->database);
    if (driver == NULL)
	G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
		      fi->database,
		      fi->driver);

    db_init_string(&stmt);
    db_set_string(&stmt, "select * from ");
    db_append_string(&stmt, fi->table);

    if (db_open_select_cursor(driver, &stmt, &cursor, DB_SEQUENTIAL) != DB_OK)
	G_fatal_error(_("Unable to open select cursor: '%s'"),
		      db_get_string(&stmt));

    nrows = db_get_num_rows(&cursor);
    G_debug(1, "%d rows selected from vector attribute table", nrows);

    Map->site_att = (SITE_ATT *) malloc(nrows * sizeof(SITE_ATT));
    Map->n_site_att = nrows;

    table = db_get_cursor_table(&cursor);
    ncols = db_get_table_number_of_columns(table);

    row = 0;
    adbl = astr = 0;
    while (1) {
	if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK)
	    G_fatal_error(_("Cannot fetch row"));

	if (!more)
	    break;

	/* Get number of each type */
	if (row == 0) {
	    for (col = 0; col < ncols; col++) {
		column = db_get_table_column(table, col);
		ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column));

		if (strcmp(db_get_column_name(column), fi->key) == 0)
		    continue;

		switch (ctype) {
		case DB_C_TYPE_INT:
		case DB_C_TYPE_DOUBLE:
		    adbl++;
		    break;
		case DB_C_TYPE_STRING:
		case DB_C_TYPE_DATETIME:
		    astr++;
		    break;
		}
	    }
	    Map->n_site_dbl = adbl;
	    Map->n_site_str = astr;
	    G_debug(1, "adbl = %d astr = %d", adbl, astr);
	}

	sa = &(Map->site_att[row]);
	sa->dbl = (double *)malloc(adbl * sizeof(double));
	sa->str = (char **)malloc(astr * sizeof(char *));

	ndbl = nstr = 0;
	for (col = 0; col < ncols; col++) {
	    column = db_get_table_column(table, col);
	    ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column));
	    value = db_get_column_value(column);

	    if (strcmp(db_get_column_name(column), fi->key) == 0) {
		sa->cat = db_get_value_int(value);
	    }
	    else {
		switch (ctype) {
		case DB_C_TYPE_INT:
		    sa->dbl[ndbl] = db_get_value_int(value);
		    ndbl++;
		    break;
		case DB_C_TYPE_DOUBLE:
		    sa->dbl[ndbl] = db_get_value_double(value);
		    ndbl++;
		    break;
		case DB_C_TYPE_STRING:
		    sa->str[nstr] = G_store(db_get_value_string(value));
		    nstr++;
		    break;
		case DB_C_TYPE_DATETIME:
		    sa->str[nstr] = "";	/* TODO */
		    nstr++;
		    break;
		}
	    }
	}
	row++;
    }
    db_close_database_shutdown_driver(driver);

    /* sort attributes */
    qsort((void *)Map->site_att, Map->n_site_att, sizeof(SITE_ATT),
	  site_att_cmp);

    return Map;
}
Exemple #8
0
int main(int argc, char **argv)
{
    int i, ret, centre, line, centre1, centre2;
    int nlines, nnodes, type, ltype, afield, nfield, geo, cat;
    int node, node1, node2;
    double cost, e1cost, e2cost, n1cost, n2cost, s1cost, s2cost, l, l1;
    struct Option *map, *output;
    struct Option *afield_opt, *nfield_opt, *afcol, *abcol, *ncol, *type_opt,
               *term_opt, *cost_opt;
    struct Flag *geo_f;
    struct GModule *module;
    struct Map_info Map, Out;
    struct cat_list *catlist;
    CENTER *Centers = NULL;
    int acentres = 0, ncentres = 0;
    NODE *Nodes;
    struct line_cats *Cats;
    struct line_pnts *Points, *SPoints;
    int niso, aiso;
    double *iso;
    int npnts1, apnts1 = 0, npnts2, apnts2 = 0;
    ISOPOINT *pnts1 = NULL, *pnts2 = NULL;
    int next_iso;

    G_gisinit(argv[0]);

    module = G_define_module();
    module->label = _("Splits net by cost isolines.");
    G_add_keyword(_("vector"));
    G_add_keyword(_("network"));
    G_add_keyword(_("isolines"));
    module->description =
        _("Splits net to bands between cost isolines (direction from centre). "
          "Centre node must be opened (costs >= 0). "
          "Costs of centre node are used in calculation.");

    map = G_define_standard_option(G_OPT_V_INPUT);
    output = G_define_standard_option(G_OPT_V_OUTPUT);

    type_opt = G_define_standard_option(G_OPT_V_TYPE);
    type_opt->options = "line,boundary";
    type_opt->answer = "line,boundary";
    type_opt->description = _("Arc type");

    afield_opt = G_define_standard_option(G_OPT_V_FIELD);
    afield_opt->key = "alayer";
    afield_opt->label = _("Arc layer");

    nfield_opt = G_define_standard_option(G_OPT_V_FIELD);
    nfield_opt->key = "nlayer";
    nfield_opt->answer = "2";
    nfield_opt->label = _("Node layer");

    afcol = G_define_standard_option(G_OPT_DB_COLUMN);
    afcol->key = "afcolumn";
    afcol->description =
        _("Arc forward/both direction(s) cost column (number)");

    abcol = G_define_standard_option(G_OPT_DB_COLUMN);
    abcol->key = "abcolumn";
    abcol->description = _("Arc backward direction cost column (number)");

    ncol = G_define_standard_option(G_OPT_DB_COLUMN);
    ncol->key = "ncolumn";
    ncol->description = _("Node cost column (number)");

    term_opt = G_define_standard_option(G_OPT_V_CATS);
    term_opt->key = "ccats";
    term_opt->required = YES;
    term_opt->description =
        _("Categories of centres (points on nodes) to which net "
          "will be allocated. "
          "Layer for this categories is given by nlayer option.");

    cost_opt = G_define_option();
    cost_opt->key = "costs";
    cost_opt->type = TYPE_INTEGER;
    cost_opt->multiple = YES;
    cost_opt->required = YES;
    cost_opt->description = _("Costs for isolines");

    geo_f = G_define_flag();
    geo_f->key = 'g';
    geo_f->description =
        _("Use geodesic calculation for longitude-latitude locations");

    if (G_parser(argc, argv))
        exit(EXIT_FAILURE);

    Cats = Vect_new_cats_struct();
    Points = Vect_new_line_struct();
    SPoints = Vect_new_line_struct();

    type = Vect_option_to_types(type_opt);
    afield = atoi(afield_opt->answer);
    nfield = atoi(nfield_opt->answer);

    catlist = Vect_new_cat_list();
    Vect_str_to_cat_list(term_opt->answer, catlist);

    Vect_check_input_output_name(map->answer, output->answer, GV_FATAL_EXIT);

    /* Iso costs */
    aiso = 1;
    iso = (double *)G_malloc(aiso * sizeof(double));
    /* Set first iso to 0 */
    iso[0] = 0;
    niso = 1;
    i = 0;
    while (cost_opt->answers[i]) {
        if (niso == aiso) {
            aiso += 1;
            iso = (double *)G_realloc(iso, aiso * sizeof(double));
        }
        iso[niso] = atof(cost_opt->answers[i]);
        if (iso[niso] <= 0)
            G_fatal_error(_("Wrong iso cost: %f"), iso[niso]);

        if (iso[niso] <= iso[niso - 1])
            G_fatal_error(_("Iso cost: %f less than previous"), iso[niso]);

        G_verbose_message(_("Iso cost %d: %f"), niso, iso[niso]);
        niso++;
        i++;
    }

    /* Should not happen: */
    if (niso < 2)
        G_warning(_("Not enough costs, everything reachable falls to first band"));

    if (geo_f->answer)
        geo = 1;
    else
        geo = 0;

    Vect_set_open_level(2);
    Vect_open_old(&Map, map->answer, "");

    /* Build graph */
    Vect_net_build_graph(&Map, type, afield, nfield, afcol->answer,
                         abcol->answer, ncol->answer, geo, 0);

    nnodes = Vect_get_num_nodes(&Map);
    nlines = Vect_get_num_lines(&Map);

    /* Create list of centres based on list of categories */
    for (i = 1; i <= nlines; i++) {
        ltype = Vect_get_line_type(&Map, i);
        if (!(ltype & GV_POINT))
            continue;

        Vect_read_line(&Map, Points, Cats, i);
        node = Vect_find_node(&Map, Points->x[0], Points->y[0], Points->z[0], 0, 0);
        if (!node) {
            G_warning(_("Point is not connected to the network"));
            continue;
        }
        if (!(Vect_cat_get(Cats, nfield, &cat)))
            continue;
        if (Vect_cat_in_cat_list(cat, catlist)) {
            Vect_net_get_node_cost(&Map, node, &n1cost);
            if (n1cost == -1) {	/* closed */
                G_warning(_("Centre at closed node (costs = -1) ignored"));
            }
            else {
                if (acentres == ncentres) {
                    acentres += 1;
                    Centers =
                        (CENTER *) G_realloc(Centers,
                                             acentres * sizeof(CENTER));
                }
                Centers[ncentres].cat = cat;
                Centers[ncentres].node = node;
                G_debug(2, "centre = %d node = %d cat = %d", ncentres,
                        node, cat);
                ncentres++;
            }
        }
    }

    G_message(_("Number of centres: %d (nlayer %d)"), ncentres, nfield);

    if (ncentres == 0)
        G_warning(_("Not enough centres for selected nlayer. Nothing will be allocated."));

    /* alloc and reset space for all nodes */
    Nodes = (NODE *) G_calloc((nnodes + 1), sizeof(NODE));
    for (i = 1; i <= nnodes; i++) {
        Nodes[i].centre = -1;
    }

    apnts1 = 1;
    pnts1 = (ISOPOINT *) G_malloc(apnts1 * sizeof(ISOPOINT));

    apnts2 = 1;
    pnts2 = (ISOPOINT *) G_malloc(apnts2 * sizeof(ISOPOINT));

    /* Fill Nodes by neares centre and costs from that centre */
    for (centre = 0; centre < ncentres; centre++) {
        node1 = Centers[centre].node;
        Vect_net_get_node_cost(&Map, node1, &n1cost);
        G_debug(2, "centre = %d node = %d cat = %d", centre, node1,
                Centers[centre].cat);
        G_message(_("Calculating costs from centre %d..."), centre + 1);
        for (node2 = 1; node2 <= nnodes; node2++) {
            G_percent(node2, nnodes, 1);
            G_debug(5, "  node1 = %d node2 = %d", node1, node2);
            Vect_net_get_node_cost(&Map, node2, &n2cost);
            if (n2cost == -1) {
                continue;
            }			/* closed, left it as not attached */

            ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &cost);
            if (ret == -1) {
                continue;
            }			/* node unreachable */

            /* We must add centre node costs (not calculated by Vect_net_shortest_path() ), but
             *  only if centre and node are not identical, because at the end node cost is add later */
            if (node1 != node2)
                cost += n1cost;
            G_debug(5,
                    "Arc nodes: %d %d cost: %f (x old cent: %d old cost %f",
                    node1, node2, cost, Nodes[node2].centre,
                    Nodes[node2].cost);
            if (Nodes[node2].centre == -1 || cost < Nodes[node2].cost) {
                Nodes[node2].cost = cost;
                Nodes[node2].centre = centre;
            }
        }
    }

    /* Write arcs to new map */
    Vect_open_new(&Out, output->answer, Vect_is_3d(&Map));
    Vect_hist_command(&Out);

    G_message("Generating isolines...");
    nlines = Vect_get_num_lines(&Map);
    for (line = 1; line <= nlines; line++) {
        G_percent(line, nlines, 2);

        ltype = Vect_read_line(&Map, Points, NULL, line);
        if (!(ltype & type)) {
            continue;
        }
        Vect_get_line_nodes(&Map, line, &node1, &node2);
        centre1 = Nodes[node1].centre;
        centre2 = Nodes[node2].centre;
        s1cost = Nodes[node1].cost;
        s2cost = Nodes[node2].cost;
        l = Vect_line_length(Points);

        if (l == 0)
            continue;

        G_debug(3, "Line %d : length = %f", line, l);
        G_debug(3, "Arc centres: %d %d (nodes: %d %d)", centre1, centre2,
                node1, node2);

        Vect_net_get_node_cost(&Map, node1, &n1cost);
        Vect_net_get_node_cost(&Map, node2, &n2cost);

        Vect_net_get_line_cost(&Map, line, GV_FORWARD, &e1cost);
        Vect_net_get_line_cost(&Map, line, GV_BACKWARD, &e2cost);

        G_debug(3, "  s1cost = %f n1cost = %f e1cost = %f", s1cost, n1cost,
                e1cost);
        G_debug(3, "  s2cost = %f n2cost = %f e2cost = %f", s2cost, n2cost,
                e2cost);


        /* First check if arc is reachable from at least one side */
        if ((centre1 != -1 && n1cost != -1 && e1cost != -1) ||
                (centre2 != -1 && n2cost != -1 && e2cost != -1)) {
            /* Line is reachable at least from one side */
            G_debug(3, "  -> arc is reachable");

            /* Add costs of node to starting costs */
            s1cost += n1cost;
            s2cost += n2cost;

            e1cost /= l;
            e2cost /= l;

            /* Find points on isolines along the line in both directions, add them to array,
             *  first point is placed at the beginning/end of line */
            /* Forward */
            npnts1 = 0;		/* in case this direction is closed */
            if (centre1 != -1 && n1cost != -1 && e1cost != -1) {
                /* Find iso for beginning of the line */
                next_iso = 0;
                for (i = niso - 1; i >= 0; i--) {
                    if (iso[i] <= s1cost) {
                        next_iso = i;
                        break;
                    }
                }
                /* Add first */
                pnts1[0].iso = next_iso;
                pnts1[0].distance = 0;
                npnts1++;
                next_iso++;

                /* Calculate distances for points along line */
                while (next_iso < niso) {
                    if (e1cost == 0)
                        break;	/* Outside line */
                    l1 = (iso[next_iso] - s1cost) / e1cost;
                    if (l1 >= l)
                        break;	/* Outside line */

                    if (npnts1 == apnts1) {
                        apnts1 += 1;
                        pnts1 =
                            (ISOPOINT *) G_realloc(pnts1,
                                                   apnts1 * sizeof(ISOPOINT));
                    }
                    pnts1[npnts1].iso = next_iso;
                    pnts1[npnts1].distance = l1;
                    G_debug(3,
                            "  forward %d : iso %d : distance %f : cost %f",
                            npnts1, next_iso, l1, iso[next_iso]);
                    npnts1++;
                    next_iso++;
                }
            }
            G_debug(3, "  npnts1 = %d", npnts1);

            /* Backward */
            npnts2 = 0;
            if (centre2 != -1 && n2cost != -1 && e2cost != -1) {
                /* Find iso for beginning of the line */
                next_iso = 0;
                for (i = niso - 1; i >= 0; i--) {
                    if (iso[i] <= s2cost) {
                        next_iso = i;
                        break;
                    }
                }
                /* Add first */
                pnts2[0].iso = next_iso;
                pnts2[0].distance = l;
                npnts2++;
                next_iso++;

                /* Calculate distances for points along line */
                while (next_iso < niso) {
                    if (e2cost == 0)
                        break;	/* Outside line */
                    l1 = (iso[next_iso] - s2cost) / e2cost;
                    if (l1 >= l)
                        break;	/* Outside line */

                    if (npnts2 == apnts2) {
                        apnts2 += 1;
                        pnts2 =
                            (ISOPOINT *) G_realloc(pnts2,
                                                   apnts2 * sizeof(ISOPOINT));
                    }
                    pnts2[npnts2].iso = next_iso;
                    pnts2[npnts2].distance = l - l1;
                    G_debug(3,
                            "  backward %d : iso %d : distance %f : cost %f",
                            npnts2, next_iso, l - l1, iso[next_iso]);
                    npnts2++;
                    next_iso++;
                }
            }
            G_debug(3, "  npnts2 = %d", npnts2);

            /* Limit number of points by maximum costs in reverse direction, this may remove
             *  also the first point in one direction, but not in both */
            /* Forward */
            if (npnts2 > 0) {
                for (i = 0; i < npnts1; i++) {
                    G_debug(3,
                            "  pnt1 = %d dist1 = %f iso1 = %d max iso2 = %d",
                            i, pnts1[i].distance, pnts1[i].iso,
                            pnts2[npnts2 - 1].iso);
                    if (pnts2[npnts2 - 1].iso < pnts1[i].iso) {
                        G_debug(3, "    -> cut here");
                        npnts1 = i;
                        break;
                    }
                }
            }
            G_debug(3, "  npnts1 cut = %d", npnts1);

            /* Backward */
            if (npnts1 > 0) {
                for (i = 0; i < npnts2; i++) {
                    G_debug(3,
                            "  pnt2 = %d dist2 = %f iso2 = %d max iso1 = %d",
                            i, pnts2[i].distance, pnts2[i].iso,
                            pnts1[npnts1 - 1].iso);
                    if (pnts1[npnts1 - 1].iso < pnts2[i].iso) {
                        G_debug(3, "    -> cut here");
                        npnts2 = i;
                        break;
                    }
                }
            }
            G_debug(3, "  npnts2 cut = %d", npnts2);

            /* Biggest cost shoud be equal if exist (npnts > 0). Cut out overlapping segments,
             *  this can cut only points on line but not first points */
            if (npnts1 > 1 && npnts2 > 1) {
                while (npnts1 > 1 && npnts2 > 1) {
                    if (pnts1[npnts1 - 1].distance >= pnts2[npnts2 - 1].distance) {	/* overlap */
                        npnts1--;
                        npnts2--;
                    }
                    else {
                        break;
                    }
                }
            }
            G_debug(3, "  npnts1 2. cut = %d", npnts1);
            G_debug(3, "  npnts2 2. cut = %d", npnts2);

            /* Now we have points in both directions which may not overlap, npoints in one
             *  direction may be 0 but not both */

            /* Join both arrays, iso of point is for next segment (point is at the beginning) */
            /* In case npnts1 == 0 add point at distance 0 */
            if (npnts1 == 0) {
                G_debug(3,
                        "  npnts1 = 0 -> add first at distance 0, cat = %d",
                        pnts2[npnts2 - 1].iso);
                pnts1[0].iso = pnts2[npnts2 - 1].iso;	/* use last point iso in reverse direction */
                pnts1[0].distance = 0;
                npnts1++;
            }
            for (i = npnts2 - 1; i >= 0; i--) {
                /* Check if identical */
                if (pnts1[npnts1 - 1].distance == pnts2[i].distance)
                    continue;

                if (npnts1 == apnts1) {
                    apnts1 += 1;
                    pnts1 =
                        (ISOPOINT *) G_realloc(pnts1,
                                               apnts1 * sizeof(ISOPOINT));
                }
                pnts1[npnts1].iso = pnts2[i].iso - 1;	/* last may be -1, but it is not used */
                pnts1[npnts1].distance = pnts2[i].distance;
                npnts1++;
            }
            /* In case npnts2 == 0 add point at the end */
            if (npnts2 == 0) {
                pnts1[npnts1].iso = 0;	/* not used */
                pnts1[npnts1].distance = l;
                npnts1++;
            }

            /* Create line segments. */
            for (i = 1; i < npnts1; i++) {
                cat = pnts1[i - 1].iso + 1;
                G_debug(3, "  segment %f - %f cat %d", pnts1[i - 1].distance,
                        pnts1[i].distance, cat);
                ret =
                    Vect_line_segment(Points, pnts1[i - 1].distance,
                                      pnts1[i].distance, SPoints);
                if (ret == 0) {
                    G_warning(_("Cannot get line segment, segment out of line"));
                }
                else {
                    Vect_reset_cats(Cats);
                    Vect_cat_set(Cats, 1, cat);
                    Vect_write_line(&Out, ltype, SPoints, Cats);
                }
            }
        }
        else {
            /* arc is not reachable */
            G_debug(3, "  -> arc is not reachable");
            Vect_reset_cats(Cats);
            Vect_write_line(&Out, ltype, Points, Cats);
        }
    }

    Vect_build(&Out);

    /* Free, ... */
    G_free(Nodes);
    G_free(Centers);
    Vect_close(&Map);
    Vect_close(&Out);

    exit(EXIT_SUCCESS);
}
Exemple #9
0
int PNG_Graph_set(void)
{
    unsigned int red, grn, blu;
    int do_read = 0;
    int do_map = 0;
    char *p;

    G_gisinit("PNG driver");

    p = getenv("GRASS_PNGFILE");
    if (!p || strlen(p) == 0)
	p = FILE_NAME;

    png.file_name = p;

    p = getenv("GRASS_TRUECOLOR");
    png.true_color = !p || strcmp(p, "FALSE") != 0;

    G_verbose_message(_("png: truecolor status %s"),
		      png.true_color ? _("enabled") : _("disabled"));

    p = getenv("GRASS_PNG_MAPPED");
    do_map = p && strcmp(p, "TRUE") == 0;

    if (do_map) {
	char *ext = png.file_name + strlen(png.file_name) - 4;

	if (G_strcasecmp(ext, ".bmp") != 0)
	    do_map = 0;
    }

    p = getenv("GRASS_PNG_READ");
    do_read = p && strcmp(p, "TRUE") == 0;

    if (do_read && access(png.file_name, 0) != 0)
	do_read = 0;

    png.width = screen_width;
    png.height = screen_height;

    png.clip_top = 0;
    png.clip_bot = png.height;
    png.clip_left = 0;
    png.clip_rite = png.width;

    p = getenv("GRASS_TRANSPARENT");
    png.has_alpha = p && strcmp(p, "TRUE") == 0;

    png_init_color_table();

    p = getenv("GRASS_BACKGROUNDCOLOR");
    if (p && *p && 
	(sscanf(p, "%02x%02x%02x", &red, &grn, &blu) == 3 ||
	 G_str_to_color(p, (int *)&red, (int *)&grn, (int *)&blu) == 1)) {
	png.background = png_get_color(red, grn, blu, png.has_alpha ? 255 : 0);
    }
    else {
	/* 0xffffff = white, 0x000000 = black */
	if (strcmp(DEFAULT_FG_COLOR, "white") == 0)
	    /* foreground: white, background: black */
	    png.background = png_get_color(0, 0, 0, png.has_alpha ? 255 : 0);
	else
	    /* foreground: black, background: white */
	    png.background = png_get_color(255, 255, 255, png.has_alpha ? 255 : 0);
    }
    
    G_verbose_message(_("png: collecting to file '%s'"), png.file_name);
    G_verbose_message(_("png: image size %dx%d"),
		      png.width, png.height);

    if (do_read && do_map)
	map_file();

    if (!png.mapped)
	png.grid = G_malloc(png.width * png.height * sizeof(unsigned int));

    if (!do_read) {
	PNG_Erase();
	png.modified = 1;
    }

    if (do_read && !png.mapped)
	read_image();

    if (do_map && !png.mapped) {
	write_image();
	map_file();
    }

    return 0;
}
Exemple #10
0
int main(int argc, char *argv[])
{
    struct GModule *module;
    struct
    {
	struct Option *input, *output, *method, *quantile, *range;
    } parm;
    struct
    {
	struct Flag *nulls;
    } flag;
    int i;
    int num_inputs;
    struct input *inputs;
    int num_outputs;
    struct output *outputs;
    struct History history;
    DCELL *values, *values_tmp;
    int nrows, ncols;
    int row, col;
    double lo, hi;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("series"));
    module->description =
	_("Makes each output cell value a "
	  "function of the values assigned to the corresponding cells "
	  "in the input raster map layers.");

    parm.input = G_define_standard_option(G_OPT_R_INPUTS);

    parm.output = G_define_standard_option(G_OPT_R_OUTPUT);
    parm.output->multiple = YES;

    parm.method = G_define_option();
    parm.method->key = "method";
    parm.method->type = TYPE_STRING;
    parm.method->required = YES;
    parm.method->options = build_method_list();
    parm.method->description = _("Aggregate operation");
    parm.method->multiple = YES;

    parm.quantile = G_define_option();
    parm.quantile->key = "quantile";
    parm.quantile->type = TYPE_DOUBLE;
    parm.quantile->required = NO;
    parm.quantile->description = _("Quantile to calculate for method=quantile");
    parm.quantile->options = "0.0-1.0";
    parm.quantile->multiple = YES;

    parm.range = G_define_option();
    parm.range->key = "range";
    parm.range->type = TYPE_DOUBLE;
    parm.range->key_desc = "lo,hi";
    parm.range->description = _("Ignore values outside this range");

    flag.nulls = G_define_flag();
    flag.nulls->key = 'n';
    flag.nulls->description = _("Propagate NULLs");

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);

    if (parm.range->answer) {
	lo = atof(parm.range->answers[0]);
	hi = atof(parm.range->answers[1]);
    }

    /* process the input maps */
    for (i = 0; parm.input->answers[i]; i++)
	;
    num_inputs = i;

    if (num_inputs < 1)
	G_fatal_error(_("Raster map not found"));

    inputs = G_malloc(num_inputs * sizeof(struct input));

    for (i = 0; i < num_inputs; i++) {
	struct input *p = &inputs[i];

	p->name = parm.input->answers[i];
	G_message(_("Reading raster map <%s>..."), p->name);
	p->fd = Rast_open_old(p->name, "");
	p->buf = Rast_allocate_d_buf();
    }

    /* process the output maps */
    for (i = 0; parm.output->answers[i]; i++)
	;
    num_outputs = i;

    for (i = 0; parm.method->answers[i]; i++)
	;
    if (num_outputs != i)
	G_fatal_error(_("output= and method= must have the same number of values"));

    outputs = G_calloc(num_outputs, sizeof(struct output));

    for (i = 0; i < num_outputs; i++) {
	struct output *out = &outputs[i];
	const char *output_name = parm.output->answers[i];
	const char *method_name = parm.method->answers[i];
	int method = find_method(method_name);

	out->name = output_name;
	out->method_fn = menu[method].method;
	out->quantile = (parm.quantile->answer && parm.quantile->answers[i])
	    ? atof(parm.quantile->answers[i])
	    : 0;
	out->buf = Rast_allocate_d_buf();
	out->fd = Rast_open_new(output_name,
				menu[method].is_int ? CELL_TYPE : DCELL_TYPE);
    }

    /* initialise variables */
    values = G_malloc(num_inputs * sizeof(DCELL));
    values_tmp = G_malloc(num_inputs * sizeof(DCELL));

    nrows = Rast_window_rows();
    ncols = Rast_window_cols();

    /* process the data */
    G_verbose_message(_("Percent complete..."));

    for (row = 0; row < nrows; row++) {
	G_percent(row, nrows, 2);

	for (i = 0; i < num_inputs; i++)
	    Rast_get_d_row(inputs[i].fd, inputs[i].buf, row);

	for (col = 0; col < ncols; col++) {
	    int null = 0;

	    for (i = 0; i < num_inputs; i++) {
		DCELL v = inputs[i].buf[col];

		if (Rast_is_d_null_value(&v))
		    null = 1;
		else if (parm.range->answer && (v < lo || v > hi)) {
		    Rast_set_d_null_value(&v, 1);
		    null = 1;
		}

		values[i] = v;
	    }

	    for (i = 0; i < num_outputs; i++) {
		struct output *out = &outputs[i];

		if (null && flag.nulls->answer)
		    Rast_set_d_null_value(&out->buf[col], 1);
		else {
		    memcpy(values_tmp, values, num_inputs * sizeof(DCELL));
		    (*out->method_fn)(&out->buf[col], values_tmp, num_inputs, &out->quantile);
		}
	    }
	}

	for (i = 0; i < num_outputs; i++)
	    Rast_put_d_row(outputs[i].fd, outputs[i].buf);
    }

    G_percent(row, nrows, 2);

    /* close maps */
    for (i = 0; i < num_outputs; i++) {
	struct output *out = &outputs[i];

	Rast_close(out->fd);

	Rast_short_history(out->name, "raster", &history);
	Rast_command_history(&history);
	Rast_write_history(out->name, &history);
    }

    for (i = 0; i < num_inputs; i++)
	Rast_close(inputs[i].fd);

    exit(EXIT_SUCCESS);
}
Exemple #11
0
int draw_n_arrow(double east, double north, double rotation, char *lbl,
                 int rot_with_text, double fontsize, char *n_arrow_num,
                 double line_width)
{
    double x_pos, y_pos;
    double t, b, l, r;
    double tt, tb, tl, tr;      /* text box */

    SYMBOL *Symb;
    RGBA_Color *line_color, *fill_color;
    int R, G, B;
    double x0, y0;
    char icon[64];
    double symbol_size;


    /* Establish text size */
    if (fontsize > 0)
        D_text_size(fontsize, fontsize);

    D_setup_unity(0);
    D_get_src(&t, &b, &l, &r);

    x_pos = l + (int)(east * (r - l) / 100.);
    y_pos = t + (int)((100. - north) * (b - t) / 100.);

    if (line_width > 0)
        D_line_width(line_width);

    if (fontsize > 0) {
        /* draw the label (default "N") */
        if (rot_with_text)
            D_text_rotation(rotation * 180.0 / M_PI);
        D_get_text_box(lbl, &tt, &tb, &tl, &tr);
        D_use_color(text_color);

        /* positions manually tuned */
        switch (n_arrow_num[0]) {
        case '1':
            D_pos_abs(x_pos - sin(rotation) * 50 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 50 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case '3':
            D_pos_abs(x_pos - sin(rotation) * 60 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 60 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case '4':
            D_pos_abs(x_pos - sin(rotation) * 45 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 45 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case '7':
            D_pos_abs(x_pos - sin(rotation) * 70 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 70 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case '8':
            D_pos_abs(x_pos - sin(rotation) * 60 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 60 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case '9':
            D_pos_abs(x_pos - sin(rotation) * 55 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 55 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case 'f':
            D_pos_abs(x_pos - sin(rotation) * 55 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 55 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case 'b':
            D_pos_abs(x_pos - sin(rotation) * 48.5 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 48.5 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case 'a':
            D_pos_abs(x_pos - sin(rotation) * 50 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 50 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case 's':
            D_pos_abs(x_pos - sin(rotation) * 50 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 50 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case '2':
        case '5':
        case '6':
            break;
        default:
            G_fatal_error(_("Could not parse symbol"));
        }
    }

    /* display the north arrow symbol */
    line_color = G_malloc(sizeof(RGBA_Color));
    fill_color = G_malloc(sizeof(RGBA_Color));

    if (D_color_number_to_RGB(fg_color, &R, &G, &B) == 0)
        line_color->a = RGBA_COLOR_TRANSPARENT;
    else
        line_color->a = RGBA_COLOR_OPAQUE;
    line_color->r = (unsigned char)R;
    line_color->g = (unsigned char)G;
    line_color->b = (unsigned char)B;


    if (D_color_number_to_RGB(bg_color, &R, &G, &B) == 0)
        fill_color->a = RGBA_COLOR_TRANSPARENT;
    else
        fill_color->a = RGBA_COLOR_OPAQUE;
    fill_color->r = (unsigned char)R;
    fill_color->g = (unsigned char)G;
    fill_color->b = (unsigned char)B;

    /* sizes manually tuned */
    switch (n_arrow_num[0]) {
    case '1':
        symbol_size = 35.;
        break;
    case '2':
        symbol_size = 19.;
        break;
    case '3':
        symbol_size = 20.;
        break;
    case '4':
        symbol_size = 15.;
        break;
    case '5':
    case '6':
        symbol_size = 14.;
        break;
    case '7':
        symbol_size = 23.;
        break;
    case '8':
    case '9':
        symbol_size = 17.;
        break;
    case 'b':
        symbol_size = 80.;
        break;
    case 'f':
        symbol_size = 100.;
        break;
    case 'a':
        if (n_arrow_num[5] == '2')
            symbol_size = 53.;
        else
            symbol_size = 70.;
        break;
    case 's':
        symbol_size = 80.;
        break;
    default:
        G_fatal_error(_("Could not parse symbol"));
    }

    x0 = D_d_to_u_col(x_pos);
    y0 = D_d_to_u_row(y_pos);

    if (n_arrow_num[0] == 'b')
        strcpy(icon, "n_arrows/basic_compass");
    else if (n_arrow_num[0] == 'f')
        strcpy(icon, "n_arrows/fancy_compass");
    else if (n_arrow_num[0] == 'a' && n_arrow_num[5] == '1')
        strcpy(icon, "basic/arrow1");
    else if (n_arrow_num[0] == 'a' && n_arrow_num[5] == '2')
        strcpy(icon, "basic/arrow2");
    else if (n_arrow_num[0] == 'a' && n_arrow_num[5] == '3')
        strcpy(icon, "basic/arrow3");
    else if (n_arrow_num[0] == 's')
        strcpy(icon, "extra/4pt_star");
    else {
        strcpy(icon, "n_arrows/n_arrow");
        strncat(icon, n_arrow_num, 32);
    }

    Symb = S_read(icon);

    if (!Symb)
        G_fatal_error(_("Could not read symbol \"%s\""), icon);

    S_stroke(Symb, symbol_size, rotation * (180 / M_PI), 0);
    D_symbol(Symb, x0, y0, line_color, fill_color);


    if (line_width > 0)
        D_line_width(0);

    G_free(Symb);
    G_free(line_color);
    G_free(fill_color);

    return 0;
}
Exemple #12
0
int main(int argc, char *argv[])
{
    unsigned int r, c, rows, cols, n_valid;	/*  totals  */
    int *mapx_fd, mapy_fd, mapres_fd, mapest_fd;
    int i, j, k, n_predictors;
    double *sumX, sumY, *sumsqX, sumsqY, *sumXY;
    double *meanX, meanY, *varX, varY, *sdX, sdY;
    double yest, yres;       /* estimated y, residual */
    double sumYest, *SSerr_without;
    double SE;
    double meanYest, meanYres, varYest, varYres, sdYest, sdYres;
    double SStot, SSerr, SSreg;
    double **a;
    struct MATRIX *m, *m_all;
    double **B, Rsq, Rsqadj, F, t, AIC, AICc, BIC;
    unsigned int count = 0;
    DCELL **mapx_buf, *mapy_buf, *mapx_val, mapy_val, *mapres_buf, *mapest_buf;
    char *name;
    struct Option *input_mapx, *input_mapy, *output_res, *output_est, *output_opt;
    struct Flag *shell_style;
    struct Cell_head region;
    struct GModule *module;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("statistics"));
    G_add_keyword(_("regression"));
    module->description =
	_("Calculates multiple linear regression from raster maps.");

    /* Define the different options */
    input_mapx = G_define_standard_option(G_OPT_R_INPUTS);
    input_mapx->key = "mapx";
    input_mapx->description = (_("Map for x coefficient"));

    input_mapy = G_define_standard_option(G_OPT_R_INPUT);
    input_mapy->key = "mapy";
    input_mapy->description = (_("Map for y coefficient"));

    output_res = G_define_standard_option(G_OPT_R_OUTPUT);
    output_res->key = "residuals";
    output_res->required = NO;
    output_res->description = (_("Map to store residuals"));

    output_est = G_define_standard_option(G_OPT_R_OUTPUT);
    output_est->key = "estimates";
    output_est->required = NO;
    output_est->description = (_("Map to store estimates"));

    output_opt = G_define_standard_option(G_OPT_F_OUTPUT);
    output_opt->key = "output";
    output_opt->required = NO;
    output_opt->description =
	(_("ASCII file for storing regression coefficients (output to screen if file not specified)."));

    shell_style = G_define_flag();
    shell_style->key = 'g';
    shell_style->description = _("Print in shell script style");

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);

    name = output_opt->answer;
    if (name != NULL && strcmp(name, "-") != 0) {
	if (NULL == freopen(name, "w", stdout)) {
	    G_fatal_error(_("Unable to open file <%s> for writing"), name);
	}
    }

    G_get_window(&region);
    rows = region.rows;
    cols = region.cols;

    /* count x maps */
    for (i = 0; input_mapx->answers[i]; i++);
    n_predictors = i;
    
    /* allocate memory for x maps */
    mapx_fd = (int *)G_malloc(n_predictors * sizeof(int));
    sumX = (double *)G_malloc(n_predictors * sizeof(double));
    sumsqX = (double *)G_malloc(n_predictors * sizeof(double));
    sumXY = (double *)G_malloc(n_predictors * sizeof(double));
    SSerr_without = (double *)G_malloc(n_predictors * sizeof(double));
    meanX = (double *)G_malloc(n_predictors * sizeof(double));
    varX = (double *)G_malloc(n_predictors * sizeof(double));
    sdX = (double *)G_malloc(n_predictors * sizeof(double));
    mapx_buf = (DCELL **)G_malloc(n_predictors * sizeof(DCELL *));
    mapx_val = (DCELL *)G_malloc((n_predictors + 1) * sizeof(DCELL));
    
    /* ordinary least squares */
    m = NULL;
    m_all = (struct MATRIX *)G_malloc((n_predictors + 1) * sizeof(struct MATRIX));
    a = (double **)G_malloc((n_predictors + 1) * sizeof(double *));
    B = (double **)G_malloc((n_predictors + 1) * sizeof(double *));

    m = &(m_all[0]);
    m->n = n_predictors + 1;
    m->v = (double *)G_malloc(m->n * m->n * sizeof(double));

    a[0] = (double *)G_malloc(m->n * sizeof(double));
    B[0] = (double *)G_malloc(m->n * sizeof(double));

    for (i = 0; i < m->n; i++) {
	for (j = i; j < m->n; j++)
	    M(m, i, j) = 0.0;
	a[0][i] = 0.0;
	B[0][i] = 0.0;
    }
    
    for (k = 1; k <= n_predictors; k++) {
	m = &(m_all[k]);
	m->n = n_predictors;
	m->v = (double *)G_malloc(m->n * m->n * sizeof(double));
	a[k] = (double *)G_malloc(m->n * sizeof(double));
	B[k] = (double *)G_malloc(m->n * sizeof(double));

	for (i = 0; i < m->n; i++) {
	    for (j = i; j < m->n; j++)
		M(m, i, j) = 0.0;
	    a[k][i] = 0.0;
	    B[k][i] = 0.0;
	}
    }

    /* open maps */
    G_debug(1, "open maps");
    for (i = 0; i < n_predictors; i++) {
	mapx_fd[i] = Rast_open_old(input_mapx->answers[i], "");
    }
    mapy_fd = Rast_open_old(input_mapy->answer, "");

    for (i = 0; i < n_predictors; i++)
	mapx_buf[i] = Rast_allocate_d_buf();
    mapy_buf = Rast_allocate_d_buf();

    for (i = 0; i < n_predictors; i++) {
	sumX[i] = sumsqX[i] = sumXY[i] = 0.0;
	meanX[i] = varX[i] = sdX[i] = 0.0;
	SSerr_without[i] = 0.0;
    }
    sumY = sumsqY = meanY = varY = sdY = 0.0;
    sumYest = meanYest = varYest = sdYest = 0.0;
    meanYres = varYres = sdYres = 0.0;

    /* read input maps */
    G_message(_("First pass..."));
    n_valid = 0;
    mapx_val[0] = 1.0;
    for (r = 0; r < rows; r++) {
	G_percent(r, rows, 2);

	for (i = 0; i < n_predictors; i++)
	    Rast_get_d_row(mapx_fd[i], mapx_buf[i], r);

	Rast_get_d_row(mapy_fd, mapy_buf, r);

	for (c = 0; c < cols; c++) {
	    int isnull = 0;

	    for (i = 0; i < n_predictors; i++) {
		mapx_val[i + 1] = mapx_buf[i][c];
		if (Rast_is_d_null_value(&(mapx_val[i + 1]))) {
		    isnull = 1;
		    break;
		}
	    }
	    if (isnull)
		continue;

	    mapy_val = mapy_buf[c];
	    if (Rast_is_d_null_value(&mapy_val))
		continue;

	    for (i = 0; i <= n_predictors; i++) {
		double val1 = mapx_val[i];

		for (j = i; j <= n_predictors; j++) {
		    double val2 = mapx_val[j];

		    m = &(m_all[0]);
		    M(m, i, j) += val1 * val2;

		    /* linear model without predictor k */
		    for (k = 1; k <= n_predictors; k++) {
			if (k != i && k != j) {
			    int i2 = k > i ? i : i - 1;
			    int j2 = k > j ? j : j - 1;

			    m = &(m_all[k]);
			    M(m, i2, j2) += val1 * val2;
			}
		    }
		}

		a[0][i] += mapy_val * val1;
		for (k = 1; k <= n_predictors; k++) {
		    if (k != i) {
			int i2 = k > i ? i : i - 1;

			a[k][i2] += mapy_val * val1;
		    }
		}

		if (i > 0) {
		    sumX[i - 1] += val1;
		    sumsqX[i - 1] += val1 * val1;
		    sumXY[i - 1] += val1 * mapy_val;
		}
	    }

	    sumY += mapy_val;
	    sumsqY += mapy_val * mapy_val;
	    count++;
	}
    }
    G_percent(rows, rows, 2);
    
    if (count < n_predictors + 1)
	G_fatal_error(_("Not enough valid cells available"));

    for (k = 0; k <= n_predictors; k++) {
	m = &(m_all[k]);

	/* TRANSPOSE VALUES IN UPPER HALF OF M TO OTHER HALF */
	for (i = 1; i < m->n; i++)
	    for (j = 0; j < i; j++)
		M(m, i, j) = M(m, j, i);

	if (!solvemat(m, a[k], B[k])) {
	    for (i = 0; i <= n_predictors; i++) {
		fprintf(stdout, "b%d=0.0\n", i);
	    }
	    G_fatal_error(_("Multiple regression failed"));
	}
    }
    
    /* second pass */
    G_message(_("Second pass..."));

    /* residuals output */
    if (output_res->answer) {
	mapres_fd = Rast_open_new(output_res->answer, DCELL_TYPE);
	mapres_buf = Rast_allocate_d_buf();
    }
    else {
	mapres_fd = -1;
	mapres_buf = NULL;
    }

    /* estimates output */
    if (output_est->answer) {
	mapest_fd = Rast_open_new(output_est->answer, DCELL_TYPE);
	mapest_buf = Rast_allocate_d_buf();
    }
    else {
	mapest_fd = -1;
	mapest_buf = NULL;
    }

    for (i = 0; i < n_predictors; i++)
	meanX[i] = sumX[i] / count;

    meanY = sumY / count;
    SStot = SSerr = SSreg = 0.0;
    for (r = 0; r < rows; r++) {
	G_percent(r, rows, 2);

	for (i = 0; i < n_predictors; i++)
	    Rast_get_d_row(mapx_fd[i], mapx_buf[i], r);

	Rast_get_d_row(mapy_fd, mapy_buf, r);
	
	if (mapres_buf)
	    Rast_set_d_null_value(mapres_buf, cols);
	if (mapest_buf)
	    Rast_set_d_null_value(mapest_buf, cols);

	for (c = 0; c < cols; c++) {
	    int isnull = 0;

	    for (i = 0; i < n_predictors; i++) {
		mapx_val[i + 1] = mapx_buf[i][c];
		if (Rast_is_d_null_value(&(mapx_val[i + 1]))) {
		    isnull = 1;
		    break;
		}
	    }
	    if (isnull)
		continue;

	    yest = 0.0;
	    for (i = 0; i <= n_predictors; i++) {
		yest += B[0][i] * mapx_val[i];
	    }
	    if (mapest_buf)
		mapest_buf[c] = yest;

	    mapy_val = mapy_buf[c];
	    if (Rast_is_d_null_value(&mapy_val))
		continue;

	    yres = mapy_val - yest;
	    if (mapres_buf)
		mapres_buf[c] = yres;

	    SStot += (mapy_val - meanY) * (mapy_val - meanY);
	    SSreg += (yest - meanY) * (yest - meanY);
	    SSerr += yres * yres;

	    for (k = 1; k <= n_predictors; k++) {
		double yesti = 0.0;
		double yresi;

		/* linear model without predictor k */
		for (i = 0; i <= n_predictors; i++) {
		    if (i != k) {
			j = k > i ? i : i - 1;
			yesti += B[k][j] * mapx_val[i];
		    }
		}
		yresi = mapy_val - yesti;

		/* linear model without predictor k */
		SSerr_without[k - 1] += yresi * yresi;

		varX[k - 1] = (mapx_val[k] - meanX[k - 1]) * (mapx_val[k] - meanX[k - 1]);
	    }
	}

	if (mapres_buf)
	    Rast_put_d_row(mapres_fd, mapres_buf);
	if (mapest_buf)
	    Rast_put_d_row(mapest_fd, mapest_buf);
    }
    G_percent(rows, rows, 2);

    fprintf(stdout, "n=%d\n", count);
    /* coefficient of determination aka R squared */
    Rsq = 1 - (SSerr / SStot);
    fprintf(stdout, "Rsq=%f\n", Rsq);
    /* adjusted coefficient of determination */
    Rsqadj = 1 - ((SSerr * (count - 1)) / (SStot * (count - n_predictors - 1)));
    fprintf(stdout, "Rsqadj=%f\n", Rsqadj);
    /* F statistic */
    /* F = ((SStot - SSerr) / (n_predictors)) / (SSerr / (count - n_predictors));
     * , or: */
    F = ((SStot - SSerr) * (count - n_predictors - 1)) / (SSerr * (n_predictors));
    fprintf(stdout, "F=%f\n", F);

    i = 0;
    /* constant aka estimate for intercept in R */
    fprintf(stdout, "b%d=%f\n", i, B[0][i]);
    /* t score for R squared of the full model, unused */
    t = sqrt(Rsq) * sqrt((count - 2) / (1 - Rsq));
    /*
    fprintf(stdout, "t%d=%f\n", i, t);
    */

    /* AIC, corrected AIC, and BIC information criteria for the full model */
    AIC = count * log(SSerr / count) + 2 * (n_predictors + 1);
    fprintf(stdout, "AIC=%f\n", AIC);
    AICc = AIC + (2 * n_predictors * (n_predictors + 1)) / (count - n_predictors - 1);
    fprintf(stdout, "AICc=%f\n", AICc);
    BIC = count * log(SSerr / count) + log(count) * (n_predictors + 1);
    fprintf(stdout, "BIC=%f\n", BIC);

    /* error variance of the model, identical to R */
    SE = SSerr / (count - n_predictors - 1);
    /*
    fprintf(stdout, "SE=%f\n", SE);
    fprintf(stdout, "SSerr=%f\n", SSerr);
    */

    for (i = 0; i < n_predictors; i++) {

	fprintf(stdout, "\npredictor%d=%s\n", i + 1, input_mapx->answers[i]);
	fprintf(stdout, "b%d=%f\n", i + 1, B[0][i + 1]);
	if (n_predictors > 1) {
	    double Rsqi, SEi, sumsqX_corr;

	    /* corrected sum of squares for predictor [i] */
	    sumsqX_corr = sumsqX[i] - sumX[i] * sumX[i] / (count - n_predictors - 1);

	    /* standard error SE for predictor [i] */

	    /* SE[i] with only one predictor: sqrt(SE / sumsqX_corr)
	     * this does not work with more than one predictor */
	    /* in R, SEi is sqrt(diag(R) * resvar) with
	     * R = ???
	     * resvar = rss / rdf = SE global
	     * rss = sum of squares of the residuals
	     * rdf = residual degrees of freedom = count - n_predictors - 1 */
	    SEi = sqrt(SE / (Rsq * sumsqX_corr));
	    /*
	    fprintf(stdout, "SE%d=%f\n", i + 1, SEi);
	    */

	    /* Sum of squares for predictor [i] */
	    /*
	    fprintf(stdout, "SSerr%d=%f\n", i + 1, SSerr_without[i] - SSerr);
	    */

	    /* R squared of the model without predictor [i] */
	    /* Rsqi = 1 - SSerr_without[i] / SStot; */
	    /* the additional amount of variance explained
	     * when including predictor [i] :
	     * Rsq - Rsqi */
	    Rsqi = (SSerr_without[i] - SSerr) / SStot;
	    fprintf(stdout, "Rsq%d=%f\n", i + 1, Rsqi);

	    /* t score for Student's t distribution, unused */
	    t = (B[0][i + 1]) / SEi;
	    /*
	    fprintf(stdout, "t%d=%f\n", i + 1, t);
	    */

	    /* F score for Fisher's F distribution
	     * here: F score to test if including predictor [i]
	     * yields a significant improvement
	     * after Lothar Sachs, Angewandte Statistik:
	     * F = (Rsq - Rsqi) * (count - n_predictors - 1) / (1 - Rsq) */
	    /* same like Sumsq / SE */
	    /* same like (SSerr_without[i] / SSerr - 1) * (count - n_predictors - 1) */
	    /* same like R-stats when entered in R-stats as last predictor */
	    F = (SSerr_without[i] / SSerr - 1) * (count - n_predictors - 1);
	    fprintf(stdout, "F%d=%f\n", i + 1, F);

	    /* AIC, corrected AIC, and BIC information criteria for
	     * the model without predictor [i] */
	    AIC = count * log(SSerr_without[i] / count) + 2 * (n_predictors);
	    fprintf(stdout, "AIC%d=%f\n", i + 1, AIC);
	    AICc = AIC + (2 * (n_predictors - 1) * n_predictors) / (count - n_predictors - 2);
	    fprintf(stdout, "AICc%d=%f\n", i + 1, AICc);
	    BIC = count * log(SSerr_without[i] / count) + (n_predictors - 1) * log(count);
	    fprintf(stdout, "BIC%d=%f\n", i + 1, BIC);
	}
    }
    

    for (i = 0; i < n_predictors; i++) {
	Rast_close(mapx_fd[i]);
	G_free(mapx_buf[i]);
    }
    Rast_close(mapy_fd);
    G_free(mapy_buf);
    
    if (mapres_fd > -1) {
	struct History history;

	Rast_close(mapres_fd);
	G_free(mapres_buf);

	Rast_short_history(output_res->answer, "raster", &history);
	Rast_command_history(&history);
	Rast_write_history(output_res->answer, &history);
    }

    if (mapest_fd > -1) {
	struct History history;

	Rast_close(mapest_fd);
	G_free(mapest_buf);

	Rast_short_history(output_est->answer, "raster", &history);
	Rast_command_history(&history);
	Rast_write_history(output_est->answer, &history);
    }

    exit(EXIT_SUCCESS);
}
Exemple #13
0
int main(int argc, char **argv)
{
    int i, j, k, ret, city, city1;
    int nlines, type, ltype, afield, tfield, geo, cat;
    int node, node1, node2, line;
    struct Option *map, *output, *afield_opt, *tfield_opt, *afcol, *type_opt,
	*term_opt;
    struct Flag *geo_f;
    struct GModule *module;
    char *mapset;
    struct Map_info Map, Out;
    struct ilist *TList;	/* list of terminal nodes */
    struct ilist *List;
    struct ilist *StArcs;	/* list of arcs on Steiner tree */
    struct ilist *StNodes;	/* list of nodes on Steiner tree */
    double cost, tmpcost, tcost;
    struct cat_list *Clist;
    struct line_cats *Cats;
    struct line_pnts *Points;

    /* Initialize the GIS calls */
    G_gisinit(argv[0]);

    module = G_define_module();
    module->keywords = _("vector, network, salesman");
    module->label =
	_("Creates a cycle connecting given nodes (Traveling salesman problem).");
    module->description =
	_("Note that TSP is NP-hard, heuristic algorithm is used by "
	  "this module and created cycle may be sub optimal");

    map = G_define_standard_option(G_OPT_V_INPUT);
    output = G_define_standard_option(G_OPT_V_OUTPUT);

    type_opt = G_define_standard_option(G_OPT_V_TYPE);
    type_opt->options = "line,boundary";
    type_opt->answer = "line,boundary";
    type_opt->description = _("Arc type");

    afield_opt = G_define_standard_option(G_OPT_V_FIELD);
    afield_opt->key = "alayer";
    afield_opt->description = _("Arc layer");

    tfield_opt = G_define_standard_option(G_OPT_V_FIELD);
    tfield_opt->key = "nlayer";
    tfield_opt->answer = "2";
    tfield_opt->description = _("Node layer (used for cities)");

    afcol = G_define_option();
    afcol->key = "acolumn";
    afcol->type = TYPE_STRING;
    afcol->required = NO;
    afcol->description = _("Arcs' cost column (for both directions)");

    term_opt = G_define_standard_option(G_OPT_V_CATS);
    term_opt->key = "ccats";
    term_opt->required = YES;
    term_opt->description = _("Categories of points ('cities') on nodes "
			      "(layer is specified by nlayer)");

    geo_f = G_define_flag();
    geo_f->key = 'g';
    geo_f->description =
	_("Use geodesic calculation for longitude-latitude locations");

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);

    Cats = Vect_new_cats_struct();
    Points = Vect_new_line_struct();

    type = Vect_option_to_types(type_opt);
    afield = atoi(afield_opt->answer);

    TList = Vect_new_list();
    List = Vect_new_list();
    StArcs = Vect_new_list();
    StNodes = Vect_new_list();

    Clist = Vect_new_cat_list();
    tfield = atoi(tfield_opt->answer);
    Vect_str_to_cat_list(term_opt->answer, Clist);

    G_debug(1, "Imput categories:\n");
    for (i = 0; i < Clist->n_ranges; i++) {
	G_debug(1, "%d - %d\n", Clist->min[i], Clist->max[i]);
    }

    if (geo_f->answer)
	geo = 1;
    else
	geo = 0;

    Vect_check_input_output_name(map->answer, output->answer, GV_FATAL_EXIT);

    mapset = G_find_vector2(map->answer, NULL);

    if (mapset == NULL)
	G_fatal_error(_("Vector map <%s> not found"), map->answer);

    Vect_set_open_level(2);
    Vect_open_old(&Map, map->answer, mapset);
    nnodes = Vect_get_num_nodes(&Map);

    /* Create list of terminals based on list of categories */
    for (i = 1; i <= nnodes; i++) {
	nlines = Vect_get_node_n_lines(&Map, i);
	for (j = 0; j < nlines; j++) {
	    line = abs(Vect_get_node_line(&Map, i, j));
	    ltype = Vect_read_line(&Map, NULL, Cats, line);
	    if (!(ltype & GV_POINT))
		continue;
	    if (!(Vect_cat_get(Cats, tfield, &cat)))
		continue;
	    if (Vect_cat_in_cat_list(cat, Clist)) {
		Vect_list_append(TList, i);
	    }
	}
    }
    ncities = TList->n_values;
    G_message(_("Number of cities: [%d]"), ncities);
    if (ncities < 2)
	G_fatal_error(_("Not enough cities (< 2)"));

    /* Alloc memory */
    cities = (int *)G_malloc(ncities * sizeof(int));
    cused = (int *)G_malloc(ncities * sizeof(int));
    for (i = 0; i < ncities; i++) {
	G_debug(1, "%d\n", TList->value[i]);
	cities[i] = TList->value[i];
	cused[i] = 0;		/* not in cycle */
    }

    costs = (COST **) G_malloc(ncities * sizeof(COST *));
    for (i = 0; i < ncities; i++) {
	costs[i] = (COST *) G_malloc(ncities * sizeof(COST));
    }

    cycle = (int *)G_malloc((ncities + 1) * sizeof(int));	/* + 1 is for output cycle */

    /* Build graph */
    Vect_net_build_graph(&Map, type, afield, 0, afcol->answer, NULL, NULL,
			 geo, 0);

    /* Create sorted lists of costs */
    for (i = 0; i < ncities; i++) {
	k = 0;
	for (j = 0; j < ncities; j++) {
	    if (i == j)
		continue;
	    ret =
		Vect_net_shortest_path(&Map, cities[i], cities[j], NULL,
				       &cost);
	    if (ret == -1)
		G_fatal_error(_("Destination node [%d] is unreachable "
				"from node [%d]"), cities[i], cities[j]);

	    costs[i][k].city = j;
	    costs[i][k].cost = cost;
	    k++;
	}
	qsort((void *)costs[i], k, sizeof(COST), cmp);
    }
    /* debug: print sorted */
    for (i = 0; i < ncities; i++) {
	for (j = 0; j < ncities - 1; j++) {
	    city = costs[i][j].city;
	    G_debug(2, "%d -> %d = %f\n", cities[i], cities[city],
		    costs[i][j].cost);
	}
    }

    /* find 2 cities with largest distance */
    cost = -1;
    for (i = 0; i < ncities; i++) {
	tmpcost = costs[i][ncities - 2].cost;
	if (tmpcost > cost) {
	    cost = tmpcost;
	    city = i;
	}
    }
    G_debug(2, "biggest costs %d - %d\n", city,
	    costs[city][ncities - 2].city);

    /* add this 2 cities to array */
    add_city(city, -1);
    add_city(costs[city][ncities - 2].city, 0);

    /* In each step, find not used city, with biggest cost to any used city, and insert 
     *  into cycle between 2 nearest nodes */
    for (i = 0; i < ncities - 2; i++) {
	cost = -1;
	G_debug(2, "---- %d ----\n", i);
	for (j = 0; j < ncities; j++) {
	    if (cused[j] == 1)
		continue;
	    tmpcost = 0;
	    for (k = 0; k < ncities - 1; k++) {
		G_debug(2, "? %d (%d) - %d (%d) \n", j, cnode(j),
			costs[j][k].city, cnode(costs[j][k].city));
		if (!cused[costs[j][k].city])
		    continue;	/* only used */
		tmpcost += costs[j][k].cost;
		break;		/* first nearest */
	    }
	    G_debug(2, "    cost = %f x %f\n", tmpcost, cost);
	    if (tmpcost > cost) {
		cost = tmpcost;
		city = j;
	    }
	}
	G_debug(2, "add %d\n", city);

	/* add to cycle on lovest costs */
	cycle[ncyc] = cycle[0];	/* tmp for cycle */
	cost = PORT_DOUBLE_MAX;
	for (j = 0; j < ncyc; j++) {
	    node1 = cities[cycle[j]];
	    node2 = cities[cycle[j + 1]];
	    ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &tcost);
	    tmpcost = -tcost;
	    node1 = cities[cycle[j]];
	    node2 = cities[city];
	    ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &tcost);
	    tmpcost += tcost;
	    node1 = cities[cycle[j + 1]];
	    node2 = cities[city];
	    ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &tcost);
	    tmpcost += tcost;

	    G_debug(2, "? %d - %d cost = %f x %f\n", node1, node2, tmpcost,
		    cost);
	    if (tmpcost < cost) {
		city1 = j;
		cost = tmpcost;
	    }
	}

	add_city(city, city1);

    }

    /* Print */
    G_debug(2, "Cycle:\n");
    for (i = 0; i < ncities; i++) {
	G_debug(2, "%d: %d: %d\n", i, cycle[i], cities[cycle[i]]);
    }

    /* Create list of arcs */
    cycle[ncities] = cycle[0];
    for (i = 0; i < ncities; i++) {
	node1 = cities[cycle[i]];
	node2 = cities[cycle[i + 1]];
	G_debug(2, " %d -> %d\n", node1, node2);
	ret = Vect_net_shortest_path(&Map, node1, node2, List, NULL);
	for (j = 0; j < List->n_values; j++) {
	    line = abs(List->value[j]);
	    Vect_list_append(StArcs, line);
	    Vect_get_line_nodes(&Map, line, &node1, &node2);
	    Vect_list_append(StNodes, node1);
	    Vect_list_append(StNodes, node2);
	}
    }



    /* Write arcs to new map */
    Vect_open_new(&Out, output->answer, Vect_is_3d(&Map));
    Vect_hist_command(&Out);

    fprintf(stdout, "\nCycle:\n");
    fprintf(stdout, "Arcs' categories (layer %d, %d arcs):\n", afield,
	    StArcs->n_values);
    for (i = 0; i < StArcs->n_values; i++) {
	line = StArcs->value[i];
	ltype = Vect_read_line(&Map, Points, Cats, line);
	Vect_write_line(&Out, ltype, Points, Cats);
	Vect_cat_get(Cats, afield, &cat);
	if (i > 0)
	    printf(",");
	fprintf(stdout, "%d", cat);
    }
    fprintf(stdout, "\n\n");

    fprintf(stdout, "Nodes' categories (layer %d, %d nodes):\n", tfield,
	    StNodes->n_values);
    k = 0;
    for (i = 0; i < StNodes->n_values; i++) {
	node = StNodes->value[i];
	nlines = Vect_get_node_n_lines(&Map, node);
	for (j = 0; j < nlines; j++) {
	    line = abs(Vect_get_node_line(&Map, node, j));
	    ltype = Vect_read_line(&Map, Points, Cats, line);
	    if (!(ltype & GV_POINT))
		continue;
	    if (!(Vect_cat_get(Cats, tfield, &cat)))
		continue;
	    Vect_write_line(&Out, ltype, Points, Cats);
	    if (k > 0)
		fprintf(stdout, ",");
	    fprintf(stdout, "%d", cat);
	    k++;
	}
    }
    fprintf(stdout, "\n\n");

    Vect_build(&Out);

    /* Free, ... */
    Vect_destroy_list(StArcs);
    Vect_destroy_list(StNodes);
    Vect_close(&Map);
    Vect_close(&Out);

    exit(EXIT_SUCCESS);
}
Exemple #14
0
int main(int argc, char *argv[])
{
    char *p;
    int i, j, k;
    int method, half, use_catno;
    const char *mapset;
    struct GModule *module;
    struct Option *point_opt,	/* point vector */
     *area_opt,			/* area vector */
     *point_type_opt,		/* point type */
     *point_field_opt,		/* point layer */
     *area_field_opt,		/* area layer */
     *method_opt,		/* stats method */
     *point_column_opt,		/* point column for stats */
     *count_column_opt,		/* area column for point count */
     *stats_column_opt,		/* area column for stats result */
     *fs_opt;			/* field separator for printed output */
    struct Flag *print_flag;
    char fs[2];
    struct Map_info PIn, AIn;
    int point_type, point_field, area_field;
    struct line_pnts *Points;
    struct line_cats *ACats, *PCats;
    AREA_CAT *Area_cat;
    int pline, ptype, count;
    int area, nareas, nacats, nacatsalloc;
    int ctype, nrec;
    struct field_info *PFi, *AFi;
    dbString stmt;
    dbDriver *Pdriver, *Adriver;
    char buf[2000];
    int update_ok, update_err;
    struct boxlist *List;
    struct bound_box box;
    dbCatValArray cvarr;
    dbColumn *column;
    struct pvalcat
    {
	double dval;
	int catno;
    } *pvalcats;
    int npvalcats, npvalcatsalloc;
    stat_func *statsvalue = NULL;
    double result;

    column = NULL;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("vector"));
    G_add_keyword(_("database"));
    G_add_keyword(_("attribute table"));
    module->description = _("Count points in areas, calculate statistics from point attributes.");

    point_opt = G_define_standard_option(G_OPT_V_INPUT);
    point_opt->key = "points";
    point_opt->description = _("Name of existing vector map with points");
    /* point_opt->guisection = _("Required"); */

    area_opt = G_define_standard_option(G_OPT_V_INPUT);
    area_opt->key = "areas";
    area_opt->description = _("Name of existing vector map with areas");
    /* area_opt->guisection = _("Required"); */

    point_type_opt = G_define_standard_option(G_OPT_V_TYPE);
    point_type_opt->key = "type";
    point_type_opt->options = "point,centroid";
    point_type_opt->answer = "point";
    point_type_opt->label = _("Feature type");
    point_type_opt->required = NO;

    point_field_opt = G_define_standard_option(G_OPT_V_FIELD);
    point_field_opt->key = "player";
    point_field_opt->label = _("Layer number for points map");

    area_field_opt = G_define_standard_option(G_OPT_V_FIELD);
    area_field_opt->key = "alayer";
    area_field_opt->label = _("Layer number for area map");

    method_opt = G_define_option();
    method_opt->key = "method";
    method_opt->type = TYPE_STRING;
    method_opt->required = NO;
    method_opt->multiple = NO;
    p = G_malloc(1024);
    for (i = 0; menu[i].name; i++) {
	if (i)
	    strcat(p, ",");
	else
	    *p = 0;
	strcat(p, menu[i].name);
    }
    method_opt->options = p;
    method_opt->description = _("Method for aggregate statistics");

    point_column_opt = G_define_standard_option(G_OPT_DB_COLUMN);
    point_column_opt->key = "pcolumn";
    point_column_opt->required = NO;
    point_column_opt->multiple = NO;
    point_column_opt->label =
	_("Column name of points map to use for statistics");
    point_column_opt->description = _("Column of points map must be numeric");

    count_column_opt = G_define_option();
    count_column_opt->key = "ccolumn";
    count_column_opt->type = TYPE_STRING;
    count_column_opt->required = NO;
    count_column_opt->multiple = NO;
    count_column_opt->label = _("Column name to upload points count");
    count_column_opt->description =
	_("Column to hold points count, must be of type integer, will be created if not existing");

    stats_column_opt = G_define_option();
    stats_column_opt->key = "scolumn";
    stats_column_opt->type = TYPE_STRING;
    stats_column_opt->required = NO;
    stats_column_opt->multiple = NO;
    stats_column_opt->label = _("Column name to upload statistics");
    stats_column_opt->description =
	_("Column to hold statistics, must be of type double, will be created if not existing");

    fs_opt = G_define_standard_option(G_OPT_F_SEP);
    fs_opt->answer = "|";
    fs_opt->key_desc = "character|space|tab";
    fs_opt->description = _("Output field separator");

    print_flag = G_define_flag();
    print_flag->key = 'p';
    print_flag->label =
	_("Print output to stdout, do not update attribute table");
    print_flag->description = _("First column is always area category");

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);

    point_type = Vect_option_to_types(point_type_opt);

    point_field = atoi(point_field_opt->answer);
    area_field = atoi(area_field_opt->answer);

    strcpy(fs, " ");
    if (print_flag->answer) {
	/* get field separator */
	if (fs_opt->answer) {
	    if (strcmp(fs_opt->answer, "space") == 0)
		*fs = ' ';
	    else if (strcmp(fs_opt->answer, "tab") == 0)
		*fs = '\t';
	    else if (strcmp(fs_opt->answer, "\\t") == 0)
		*fs = '\t';
	    else
		*fs = *fs_opt->answer;
	}
	else
	    *fs = '|';
    }

    /* check for stats */
    if (method_opt->answer) {
	if (!point_column_opt->answer) {
	    G_fatal_error("Method but no point column selected");
	}
	if (!print_flag->answer && !stats_column_opt->answer)
	    G_fatal_error("Name for stats column is missing");
    }

    if (point_column_opt->answer) {
	if (!method_opt->answer)
	    G_fatal_error("No method for statistics selected");
	if (!print_flag->answer && !stats_column_opt->answer)
	    G_fatal_error("Name for stats column is missing");
    }
    
    /* Open points vector */
    if ((mapset = G_find_vector2(point_opt->answer, "")) == NULL)
	G_fatal_error(_("Vector map <%s> not found"), point_opt->answer);

    Vect_set_open_level(2);
    Vect_open_old(&PIn, point_opt->answer, mapset);

    /* Open areas vector */
    if ((mapset = G_find_vector2(area_opt->answer, "")) == NULL)
	G_fatal_error(_("Vector map <%s> not found"), area_opt->answer);
    if (!print_flag->answer && strcmp(mapset, G_mapset()) != 0)
	G_fatal_error(_("Vector map <%s> is not in user mapset and cannot be updated"),
		      area_opt->answer);

    Vect_set_open_level(2);
    Vect_open_old(&AIn, area_opt->answer, mapset);

    method = -1;
    use_catno = 0;
    half = 0;
    if (method_opt->answer) {
	/* get the method */
	for (method = 0; (p = menu[method].name); method++)
	    if ((strcmp(p, method_opt->answer) == 0))
		break;
	if (!p) {
	    G_warning(_("<%s=%s> unknown %s"),
		      method_opt->key, method_opt->answer,
		      method_opt->answer);
	    G_usage();
	    exit(EXIT_FAILURE);
	}

	/* establish the statsvalue routine */
	statsvalue = menu[method].method;

	/* category number of lowest/highest value */
	if ((strcmp(menu[method].name, menu[5].name) == 0) ||
	    (strcmp(menu[method].name, menu[7].name) == 0))
	    use_catno = 1;

	G_debug(1, "method: %s, use cat value: %s", menu[method].name,
		(use_catno == 1 ? "yes" : "no"));
    }

    /* Open database driver */
    db_init_string(&stmt);
    Adriver = NULL;

    if (!print_flag->answer) {

	AFi = Vect_get_field(&AIn, area_field);
	if (AFi == NULL)
	    G_fatal_error(_("Database connection not defined for layer %d"),
			  area_field);

	Adriver = db_start_driver_open_database(AFi->driver, AFi->database);
	if (Adriver == NULL)
	    G_fatal_error(_("Unable to open database <%s> with driver <%s>"),
			  AFi->database, AFi->driver);

	if (!count_column_opt->answer)
	    G_fatal_error(_("ccolumn is required to upload point counts"));

	/* check if count column exists */
	G_debug(1, "check if count column exists");
	db_get_column(Adriver, AFi->table, count_column_opt->answer, &column);
	if (column) {
	    /* check count column type */
	    if (db_column_Ctype(Adriver, AFi->table, count_column_opt->answer)
		!= DB_C_TYPE_INT)
		G_fatal_error(_("ccolumn must be of type integer"));

	    db_free_column(column);
	    column = NULL;
	}
	else {
	    /* create count column */
	    /* db_add_column() exists but is not implemented,
	     * see lib/db/stubs/add_col.c */
	    sprintf(buf, "alter table %s add column %s integer",
	                    AFi->table, count_column_opt->answer);
	    db_set_string(&stmt, buf);
	    if (db_execute_immediate(Adriver, &stmt) != DB_OK)
		G_fatal_error(_("Unable to add column <%s>"),
			      count_column_opt->answer);
	}

	if (method_opt->answer) {
	    if (!stats_column_opt->answer)
		G_fatal_error(_("scolumn is required to upload point stats"));

	    /* check if stats column exists */
	    G_debug(1, "check if stats column exists");
	    db_get_column(Adriver, AFi->table, stats_column_opt->answer,
			  &column);
	    if (column) {
		/* check stats column type */
		if (db_column_Ctype
		    (Adriver, AFi->table,
		     stats_column_opt->answer) != DB_C_TYPE_DOUBLE)
		    G_fatal_error(_("scolumn must be of type double"));

		db_free_column(column);
		column = NULL;
	    }
	    else {
		/* create stats column */
		/* db_add_column() exists but is not implemented,
		 * see lib/db/stubs/add_col.c */
		sprintf(buf, "alter table %s add column %s double",
				AFi->table, stats_column_opt->answer);
		db_set_string(&stmt, buf);
		if (db_execute_immediate(Adriver, &stmt) != DB_OK)
		    G_fatal_error(_("Unable to add column <%s>"),
				  stats_column_opt->answer);
	    }
	}
    }
    else
	AFi = NULL;

    Pdriver = NULL;
    if (method_opt->answer) {

	G_verbose_message(_("collecting attributes from points vector..."));

	PFi = Vect_get_field(&PIn, point_field);
	if (PFi == NULL)
	    G_fatal_error(_("Database connection not defined for layer %d"),
			  point_field);

	Pdriver = db_start_driver_open_database(PFi->driver, PFi->database);
	if (Pdriver == NULL)
	    G_fatal_error(_("Unable to open database <%s> with driver <%s>"),
			  PFi->database, PFi->driver);

	/* check if point column exists */
	db_get_column(Pdriver, PFi->table, point_column_opt->answer, &column);
	if (column) {
	    db_free_column(column);
	    column = NULL;
	}
	else {
	    G_fatal_error(_("Column <%s> not found in table <%s>"),
			  point_column_opt->answer, PFi->table);
	}

	/* Check column type */
	ctype =
	    db_column_Ctype(Pdriver, PFi->table, point_column_opt->answer);

	if (ctype == DB_C_TYPE_INT)
	    half = menu[method].half;
	else if (ctype == DB_C_TYPE_DOUBLE)
	    half = 0;
	else
	    G_fatal_error(_("column for points vector must be numeric"));

	db_CatValArray_init(&cvarr);
	nrec = db_select_CatValArray(Pdriver, PFi->table, PFi->key,
				     point_column_opt->answer, NULL, &cvarr);
	G_debug(1, "selected values = %d", nrec);
	db_close_database_shutdown_driver(Pdriver);
    }

    Points = Vect_new_line_struct();
    ACats = Vect_new_cats_struct();
    PCats = Vect_new_cats_struct();
    List = Vect_new_boxlist(0);

    /* Allocate space ( may be more than needed (duplicate cats and elements without cats) ) */
    if ((nareas = Vect_get_num_areas(&AIn)) <= 0)
	G_fatal_error("No areas in area input vector");

    nacatsalloc = nareas;
    Area_cat = (AREA_CAT *) G_calloc(nacatsalloc, sizeof(AREA_CAT));

    /* Read all cats from 'area' */
    nacats = 0;
    for (area = 1; area <= nareas; area++) {

	Vect_get_area_cats(&AIn, area, ACats);

	if (ACats->n_cats <= 0)
	    continue;
	for (i = 0; i < ACats->n_cats; i++) {

	    if (ACats->field[i] == area_field) {
		Area_cat[nacats].area_cat = ACats->cat[i];
		Area_cat[nacats].count = 0;
		Area_cat[nacats].nvalues = 0;
		Area_cat[nacats].nalloc = 0;
		nacats++;
		if (nacats >= nacatsalloc) {
		    nacatsalloc += 100;
		    Area_cat =
			(AREA_CAT *) G_realloc(Area_cat,
					       nacatsalloc *
					       sizeof(AREA_CAT));
		}
	    }

	}
    }

    G_debug(1, "%d cats loaded from vector (including duplicates)", nacats);

    /* Sort by category */
    qsort((void *)Area_cat, nacats, sizeof(AREA_CAT), cmp_area);

    /* remove duplicate categories */
    for (i = 1; i < nacats; i++) {
	if (Area_cat[i].area_cat == Area_cat[i - 1].area_cat) {
	    for (j = i; j < nacats - 1; j++) {
		Area_cat[j].area_cat = Area_cat[j + 1].area_cat;
	    }
	    nacats--;
	}
    }

    G_debug(1, "%d cats loaded from vector (unique)", nacats);

    /* Go through all areas in area vector and find points in points vector
     * falling into the area */
    npvalcatsalloc = 10;
    npvalcats = 0;
    pvalcats =
	(struct pvalcat *)G_calloc(npvalcatsalloc, sizeof(struct pvalcat));

    G_message(_("Selecting points for each area..."));
    count = 0;
    for (area = 1; area <= nareas; area++) {
	dbCatVal *catval;

	G_debug(3, "area = %d", area);
	G_percent(area, nareas, 2);

	Vect_get_area_cats(&AIn, area, ACats);

	if (ACats->n_cats <= 0)
	    continue;

	/* select points by box */
	Vect_get_area_box(&AIn, area, &box);
	box.T = PORT_DOUBLE_MAX;
	box.B = -PORT_DOUBLE_MAX;

	Vect_select_lines_by_box(&PIn, &box, point_type, List);
	G_debug(4, "%d points selected by box", List->n_values);

	/* For each point in box check if it is in the area */
	for (i = 0; i < List->n_values; i++) {

	    pline = List->id[i];
	    G_debug(4, "%d: point %d", i, pline);

	    ptype = Vect_read_line(&PIn, Points, PCats, pline);
	    if (!(ptype & point_type))
		continue;

	    /* point in area */
	    if (Vect_point_in_area(Points->x[0], Points->y[0], &AIn, area, box)) {
		AREA_CAT *area_info, search_ai;

		int tmp_cat;

		/* stats on point column */
		if (method_opt->answer) {
		    npvalcats = 0;
		    tmp_cat = -1;
		    for (j = 0; j < PCats->n_cats; j++) {
			if (PCats->field[j] == point_field) {
			    if (tmp_cat >= 0)
				G_debug(3,
					"More cats found in point layer (point=%d)",
					pline);
			    tmp_cat = PCats->cat[j];

			    /* find cat in array */
			    db_CatValArray_get_value(&cvarr, tmp_cat,
						     &catval);

			    if (catval) {
				pvalcats[npvalcats].catno = tmp_cat;
				switch (cvarr.ctype) {
				case DB_C_TYPE_INT:
				    pvalcats[npvalcats].dval = catval->val.i;
				    npvalcats++;
				    break;

				case DB_C_TYPE_DOUBLE:
				    pvalcats[npvalcats].dval = catval->val.d;
				    npvalcats++;
				    break;
				}
				if (npvalcats >= npvalcatsalloc) {
				    npvalcatsalloc += 10;
				    pvalcats =
					(struct pvalcat *)G_realloc(pvalcats,
								    npvalcatsalloc
								    *
								    sizeof
								    (struct
								     pvalcat));
				}
			    }
			}
		    }
		}

		/* update count for all area cats of given field */
		search_ai.area_cat = -1;
		for (j = 0; j < ACats->n_cats; j++) {
		    if (ACats->field[j] == area_field) {
			if (search_ai.area_cat >= 0)
			    G_debug(3,
				    "More cats found in area layer (area=%d)",
				    area);
			search_ai.area_cat = ACats->cat[j];

			/* find cat in array */
			area_info =
			    (AREA_CAT *) bsearch((void *)&search_ai, Area_cat,
						 nacats, sizeof(AREA_CAT),
						 cmp_area);
			if (area_info->area_cat != search_ai.area_cat)
			    G_fatal_error(_("could not find area category %d"),
					  search_ai.area_cat);

			/* each point is counted once, also if it has
			 * more than one category or no category
			 * OK? */
			area_info->count++;

			if (method_opt->answer) {
			    /* ensure enough space */
			    if (area_info->nvalues + npvalcats >=
				area_info->nalloc) {
				if (area_info->nalloc == 0) {
				    area_info->nalloc = npvalcats + 10;
				    area_info->values =
					(double *)G_calloc(area_info->nalloc,
							   sizeof(double));
				    area_info->cats =
					(int *)G_calloc(area_info->nalloc,
							sizeof(int));
				}
				else
				    area_info->nalloc +=
					area_info->nvalues + npvalcats + 10;
				area_info->values =
				    (double *)G_realloc(area_info->values,
							area_info->nalloc *
							sizeof(double));
				area_info->cats =
				    (int *)G_realloc(area_info->cats,
						     area_info->nalloc *
						     sizeof(int));
			    }
			    for (k = 0; k < npvalcats; k++) {
				area_info->cats[area_info->nvalues] =
				    pvalcats[k].catno;
				area_info->values[area_info->nvalues] =
				    pvalcats[k].dval;
				area_info->nvalues++;
			    }
			}
		    }
		}
		count++;
	    }
	}			/* next point in box */
    }				/* next area */

    G_debug(1, "count = %d", count);

    /* release catval array */
    if (method_opt->answer)
	db_CatValArray_free(&cvarr);

    Vect_close(&PIn);

    /* Update table or print to stdout */
    if (print_flag->answer) {	/* print header */
	fprintf(stdout, "area_cat%scount", fs);
	if (method_opt->answer)
	    fprintf(stdout, "%s%s", fs, menu[method].name);
	fprintf(stdout, "\n");
    }
    else {
	G_message("Updating attributes for area vector...");
	update_err = update_ok = 0;
    }
    if (Adriver)
	db_begin_transaction(Adriver);

    for (i = 0; i < nacats; i++) {
	if (!print_flag->answer)
	    G_percent(i, nacats, 2);

	result = 0;

	if (Area_cat[i].count > 0 && method_opt->answer) {
	    /* get stats */
	    statsvalue(&result, Area_cat[i].values, Area_cat[i].nvalues,
			NULL);

	    if (half)
		result += 0.5;
	    else if (use_catno)
		result = Area_cat[i].cats[(int)result];
	}
	if (print_flag->answer) {
	    fprintf(stdout, "%d%s%d", Area_cat[i].area_cat, fs,
		    Area_cat[i].count);
	    if (method_opt->answer) {
		if (Area_cat[i].count > 0)
		    fprintf(stdout, "%s%.15g", fs, result);
		else
		    fprintf(stdout, "%snull", fs);
	    }
	    fprintf(stdout, "\n");
	}
	else {
	    sprintf(buf, "update %s set %s = %d", AFi->table,
		    count_column_opt->answer, Area_cat[i].count);
	    db_set_string(&stmt, buf);
	    if (method_opt->answer) {
		if (Area_cat[i].count > 0)
		    sprintf(buf, " , %s = %.15g", stats_column_opt->answer,
			    result);
		else
		    sprintf(buf, " , %s = null", stats_column_opt->answer);
		db_append_string(&stmt, buf);
	    }
	    sprintf(buf, " where %s = %d", AFi->key, Area_cat[i].area_cat);
	    db_append_string(&stmt, buf);
	    G_debug(2, "SQL: %s", db_get_string(&stmt));
	    if (db_execute_immediate(Adriver, &stmt) == DB_OK) {
		update_ok++;
	    }
	    else {
		update_err++;
	    }

	}
    }
    if (Adriver)
	db_commit_transaction(Adriver);

    if (!print_flag->answer) {
	G_percent(nacats, nacats, 2);
	db_close_database_shutdown_driver(Adriver);
	db_free_string(&stmt);
	G_message(_("%d records updated"), update_ok);
	if (update_err > 0)
	    G_message(_("%d update errors"), update_err);

	Vect_set_db_updated(&AIn);
    }

    Vect_close(&AIn);

    G_done_msg(" ");

    exit(EXIT_SUCCESS);
}
Exemple #15
0
/*!
   \brief Load to points to memory

   The other alternative may be to load to a tmp file.

   \param name name of vector map to be loaded
   \param[out] nsites number of loaded points
   \param[out] has_z 2D or 3D points data loaded?

   \return pointer to geopoint struct (array)
   \return NULL on failure
 */
geopoint *Gp_load_sites(const char *name, int *nsites, int *has_z)
{
    struct Map_info map;
    static struct line_pnts *Points = NULL;
    struct line_cats *Cats = NULL;
    geopoint *top, *gpt, *prev;
    int np, ltype, eof;
    struct Cell_head wind;
    int ndim;
    const char *mapset;

    np = 0;
    eof = 0;
    
    mapset = G_find_vector2(name, "");
    if (!mapset) {
	G_warning(_("Vector map <%s> not found"), name);
	return NULL;
    }
    
    Vect_set_open_level(1);
    if (Vect_open_old(&map, name, "") == -1) {
	G_fatal_error(_("Unable to open vector map <%s>"),
		      G_fully_qualified_name(name, mapset));
    }
    
    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();
    
    top = gpt = (geopoint *) G_malloc(sizeof(geopoint));
    G_zero(gpt, sizeof(geopoint));
    if (!top) {
	return NULL;
    }

    G_get_set_window(&wind);
    Vect_set_constraint_region(&map, wind.north, wind.south, wind.east,
			       wind.west, PORT_DOUBLE_MAX, -PORT_DOUBLE_MAX);

    /* get ndim */
    *has_z = 0;
    ndim = 2;
    if (Vect_is_3d(&map)) {
	*has_z = 1;
	ndim = 3;
    }

    while (eof == 0) {
	ltype = Vect_read_next_line(&map, Points, Cats);
	switch (ltype) {
	case -1:
	    {
		G_warning(_("Unable to read vector map <%s>"),
			  G_fully_qualified_name(name, mapset));
		return NULL;
	    }
	case -2:		/* EOF */
	    {
		eof = 1;
		continue;
	    }
	}
	if ((ltype & GV_POINTS)) {
	    np++;
	    gpt->p3[X] = Points->x[0];
	    gpt->p3[Y] = Points->y[0];

	    if (ndim > 2) {
		gpt->dims = 3;
		gpt->p3[Z] = Points->z[0];
	    }
	    else {
		gpt->dims = 2;
	    }

	    /* Store category info for thematic display */
	    if (Cats->n_cats > 0) {
		gpt->cats = Cats;
		Cats = Vect_new_cats_struct();
	    }
	    else {
		Vect_reset_cats(Cats);
	    }
	    /* initialize style */
	    gpt->highlighted = 0;
	    
	    G_debug(5, "loading vector point %d x=%f y=%f ncats=%d",
		    np, Points->x[0], Points->y[0], Cats->n_cats);

	    gpt->next = (geopoint *) G_malloc(sizeof(geopoint));	/* G_fatal_error */
	    G_zero(gpt->next, sizeof(geopoint));
	    if (!gpt->next) {
		return NULL;
	    }

	    prev = gpt;
	    gpt = gpt->next;
	}

    }
    if (np > 0) {
	prev->next = NULL;
	G_free(gpt);
    }

    Vect_close(&map);

    if (!np) {
	G_warning(_("No points from vector map <%s> fall within current region"),
		  G_fully_qualified_name(name, mapset));
	return (NULL);
    }
    else {
	G_message(_("Vector map <%s> loaded (%d points)"),
		  G_fully_qualified_name(name, mapset), np);
    }

    *nsites = np;

    return top;
}
Exemple #16
0
int exec_rectify(char *extension, char *interp_method, char *angle_map)
{
    char *name;
    char *mapset;
    char *result;
    char *type = "raster";
    int n;
    struct Colors colr;
    struct Categories cats;
    struct History hist;
    int colr_ok, cats_ok;
    long start_time, rectify_time;
    double aver_z;
    int elevfd;
    struct cache *ebuffer;

    G_debug(1, "Open elevation raster: ");

    /* open elevation raster */
    select_target_env();
    G_set_window(&target_window);
    G_debug(1, "target window: rs=%d cs=%d n=%f s=%f w=%f e=%f\n",
	    target_window.rows, target_window.cols, target_window.north,
	    target_window.south, target_window.west, target_window.east);

    elevfd = Rast_open_old(elev_name, elev_mapset);
    if (elevfd < 0) {
	G_fatal_error(_("Could not open elevation raster"));
	return 1;
    }
    ebuffer = readcell(elevfd, seg_mb_elev, 1);
    select_target_env();
    Rast_close(elevfd);

    /* get an average elevation of the control points */
    /* this is used only if target cells have no elevation */
    get_aver_elev(&group.control_points, &aver_z);

    G_message("-----------------------------------------------");

    /* rectify each file */
    for (n = 0; n < group.group_ref.nfiles; n++) {
	if (!ref_list[n])
	    continue;

	name = group.group_ref.file[n].name;
	mapset = group.group_ref.file[n].mapset;
	result =
	    G_malloc(strlen(group.group_ref.file[n].name) + strlen(extension) + 1);
	strcpy(result, group.group_ref.file[n].name);
	strcat(result, extension);

	G_debug(2, "ORTHO RECTIFYING:");
	G_debug(2, "NAME %s", name);
	G_debug(2, "MAPSET %s", mapset);
	G_debug(2, "RESULT %s", result);
	G_debug(2, "select_current_env...");

	select_current_env();

	cats_ok = Rast_read_cats(name, mapset, &cats) >= 0;
	colr_ok = Rast_read_colors(name, mapset, &colr) > 0;

	/* Initialze History */
	if (Rast_read_history(name, mapset, &hist) < 0)
	    Rast_short_history(result, type, &hist);
	G_debug(2, "reading was fine...");

	time(&start_time);

	G_debug(2, "Starting the rectification...");

	if (rectify(name, mapset, ebuffer, aver_z, result, interp_method)) {
	    G_debug(2, "Done. Writing results...");
	    select_target_env();
	    if (cats_ok) {
		Rast_write_cats(result, &cats);
		Rast_free_cats(&cats);
	    }
	    if (colr_ok) {
		Rast_write_colors(result, G_mapset(), &colr);
		Rast_free_colors(&colr);
	    }
	    /* Write out History */
	    Rast_command_history(&hist);
	    Rast_write_history(result, &hist);

	    select_current_env();
	    time(&rectify_time);
	    report(rectify_time - start_time, 1);
	}
	else
	    report((long)0, 0);

	G_free(result);
    }
    
    close(ebuffer->fd);
    release_cache(ebuffer);

    if (angle_map) {
	camera_angle(angle_map);
    }
    
    return 0;
}
Exemple #17
0
static void read_png(void)
{
    unsigned char sig_buf[8];
    png_bytep png_buffer;
    png_bytep *png_rows;
    int linesize;
    struct Cell_head cellhd;
    unsigned int y, c;
    png_color_8p sig_bit;
    int sbit, interlace;
    FILE *ifp;

    /* initialize input stream and PNG library */

    ifp = fopen(input, "rb");
    if (!ifp)
	G_fatal_error(_("Unable to open PNG file '%s'"), input);

    if (fread(sig_buf, sizeof(sig_buf), 1, ifp) != 1)
	G_fatal_error(_("Input file empty or too short"));

    if (png_sig_cmp(sig_buf, 0, sizeof(sig_buf)) != 0)
	G_fatal_error(_("Input file not a PNG file"));

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr)
	G_fatal_error(_("Unable to allocate PNG structure"));

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
	G_fatal_error(_("Unable to allocate PNG structure"));

    if (setjmp(png_jmpbuf(png_ptr)))
	G_fatal_error(_("PNG error"));

    png_init_io(png_ptr, ifp);
    png_set_sig_bytes(png_ptr, sizeof(sig_buf));

    png_read_info(png_ptr, info_ptr);

    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
		 &color_type, &interlace_type, &compression_type, &filter_type);

    if (Header || G_verbose() == G_verbose_max())
	print_header();

    if (Header)
    {
	fclose(ifp);    
	exit(0);
    }

    /* read image parameters and set up data conversions */

    if (png_get_bit_depth(png_ptr, info_ptr) < 8)
	png_set_packing(png_ptr);

    sbit = png_get_sBIT(png_ptr, info_ptr, &sig_bit);
    if (sbit)
        png_set_shift(png_ptr, sig_bit);

    if (!png_get_gAMA(png_ptr, info_ptr, &f_gamma))
	f_gamma = 0.0;

    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
	png_set_tRNS_to_alpha(png_ptr);

    if (Float && color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_palette_to_rgb(png_ptr);

    png_read_update_info(png_ptr, info_ptr);

    interlace = (interlace_type != PNG_INTERLACE_NONE);

    ialpha = (int) (alpha * channels[C_A].maxval);

    t_gamma = (f_gamma != 0.0 && d_gamma != 0.0)
	? f_gamma * d_gamma
	: 1.0;

    /* allocate input buffer */

    linesize = png_get_rowbytes(png_ptr, info_ptr);

    png_buffer = G_malloc(interlace
			  ? height * linesize
			  : linesize);

    if (interlace)
    {
	png_rows = G_malloc(height * sizeof(png_bytep));
	for (y = 0; y < height; y++)
	    png_rows[y] = png_buffer + y * linesize;
    }

    /* initialize cell header */

    Rast_get_window(&cellhd);

    cellhd.rows = height;
    cellhd.cols = width;
    cellhd.north = cellhd.rows;
    cellhd.south = 0.0;
    cellhd.east = cellhd.cols;
    cellhd.west = 0.0;
    cellhd.ns_res = 1;
    cellhd.ew_res = 1;

    Rast_set_window(&cellhd);

    /* initialize channel information */

    switch (color_type)
    {
    case PNG_COLOR_TYPE_GRAY:
	init_channel(&channels[C_Y]);
	break;

    case PNG_COLOR_TYPE_GRAY_ALPHA:
	init_channel(&channels[C_Y]);
	init_channel(&channels[C_A]);
	break;

    case PNG_COLOR_TYPE_PALETTE:
	init_channel(&channels[C_P]);
	break;

    case PNG_COLOR_TYPE_RGB:
	init_channel(&channels[C_R]);
	init_channel(&channels[C_G]);
	init_channel(&channels[C_B]);
	break;

    case PNG_COLOR_TYPE_RGB_ALPHA:
	init_channel(&channels[C_R]);
	init_channel(&channels[C_G]);
	init_channel(&channels[C_B]);
	init_channel(&channels[C_A]);
	break;
    }

    if (sbit)
    {
	channels[C_R].maxval = (1 << sig_bit->red  ) - 1;
	channels[C_G].maxval = (1 << sig_bit->green) - 1;
	channels[C_B].maxval = (1 << sig_bit->blue ) - 1;
	channels[C_Y].maxval = (1 << sig_bit->gray ) - 1;
	channels[C_A].maxval = (1 << sig_bit->alpha) - 1;
    }
    else
    {
	channels[C_R].maxval = (1 << bit_depth) - 1;
	channels[C_G].maxval = (1 << bit_depth) - 1;
	channels[C_B].maxval = (1 << bit_depth) - 1;
	channels[C_Y].maxval = (1 << bit_depth) - 1;
	channels[C_A].maxval = (1 << bit_depth) - 1;
    }

    /* read image and write raster layers */

    if (interlace)
	png_read_image(png_ptr, png_rows);

    for (y = 0; y < height; y++)
    {
	png_bytep p;

	if (interlace)
	    p = png_rows[y];
	else
	{
	    png_read_row(png_ptr, png_buffer, NULL);
	    p = png_buffer;
	}

	if (Float)
	    write_row_float(p);
	else
	    write_row_int(p);
    }

    png_read_end(png_ptr, NULL);

    fclose(ifp);

    /* close output files */

    for (c = 0; c < 6; c++)
    {
	channel *ch = &channels[c];

	if (!ch->active)
	    continue;

	Rast_close(ch->fd);

	if (Float)
	    G_free(ch->fbuf);
	else
	    G_free(ch->buf);
    }

    /* write title and color table */

    G_verbose_message(_("Creating support files for <%s>..."), output);

    for (c = 0; c < 6; c++)
    {
	channel *ch = &channels[c];

	if (!ch->active)
	    continue;

	if (title && *title)
	    Rast_put_cell_title(ch->name, title);

	if (Float)
	    write_colors_float(c);
	else
	    write_colors_int(c);
    }

    G_free(png_buffer);
    if (interlace)
	G_free(png_rows);

    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
}
Exemple #18
0
int main(int argc, char *argv[])
{
    char *output, buf[DB_SQL_MAX];
    double (*rng)(void) = G_drand48;
    double zmin, zmax;
    int seed;
    int i, j, k, n, type, usefloat;
    int area, nareas, field;
    struct boxlist *List = NULL;
    BOX_SIZE *size_list = NULL;
    int alloc_size_list = 0;
    struct Map_info In, Out;
    struct line_pnts *Points;
    struct line_cats *Cats;
    struct cat_list *cat_list;
    struct bound_box box;
    struct Cell_head window;
    struct GModule *module;
    struct
    {
	struct Option *input, *field, *cats, *where, *output, *nsites,
		      *zmin, *zmax, *zcol, *ztype, *seed;
    } parm;
    struct
    {
	struct Flag *z, *notopo, *a;
    } flag;
    struct field_info *Fi;
    dbDriver *driver;
    dbTable *table;
    dbString sql;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("vector"));
    G_add_keyword(_("sampling"));
    G_add_keyword(_("statistics"));
    G_add_keyword(_("random"));
    module->description = _("Generates random 2D/3D vector points.");

    parm.output = G_define_standard_option(G_OPT_V_OUTPUT);

    parm.nsites = G_define_option();
    parm.nsites->key = "n";
    parm.nsites->type = TYPE_INTEGER;
    parm.nsites->required = YES;
    parm.nsites->description = _("Number of points to be created");

    parm.input = G_define_standard_option(G_OPT_V_INPUT);
    parm.input->required = NO;
    parm.input->description = _("Restrict points to areas in input vector");
    parm.input->guisection = _("Selection");

    parm.field = G_define_standard_option(G_OPT_V_FIELD_ALL);
    parm.field->guisection = _("Selection");

    parm.cats = G_define_standard_option(G_OPT_V_CATS);
    parm.cats->guisection = _("Selection");
    
    parm.where = G_define_standard_option(G_OPT_DB_WHERE);
    parm.where->guisection = _("Selection");

    parm.zmin = G_define_option();
    parm.zmin->key = "zmin";
    parm.zmin->type = TYPE_DOUBLE;
    parm.zmin->required = NO;
    parm.zmin->description =
	_("Minimum z height (needs -z flag or column name)");
    parm.zmin->answer = "0.0";
    parm.zmin->guisection = _("3D output");

    parm.zmax = G_define_option();
    parm.zmax->key = "zmax";
    parm.zmax->type = TYPE_DOUBLE;
    parm.zmax->required = NO;
    parm.zmax->description =
	_("Maximum z height (needs -z flag or column name)");
    parm.zmax->answer = "0.0";
    parm.zmax->guisection = _("3D output");

    parm.seed = G_define_option();
    parm.seed->key = "seed";
    parm.seed->type = TYPE_INTEGER;
    parm.seed->required = NO;
    parm.seed->description =
	_("The seed to initialize the random generator. If not set the process ID is used");

    parm.zcol = G_define_standard_option(G_OPT_DB_COLUMN);
    parm.zcol->label = _("Name of column for z values");
    parm.zcol->description =
	_("Writes z values to column");
    parm.zcol->guisection = _("3D output");

    parm.ztype = G_define_option();
    parm.ztype->key = "column_type";
    parm.ztype->type = TYPE_STRING;
    parm.ztype->required = NO;
    parm.ztype->multiple = NO;
    parm.ztype->description = _("Type of column for z values");
    parm.ztype->options = "integer,double precision";
    parm.ztype->answer = "double precision";
    parm.ztype->guisection = _("3D output");

    flag.z = G_define_flag();
    flag.z->key = 'z';
    flag.z->description = _("Create 3D output");
    flag.z->guisection = _("3D output");

    flag.a = G_define_flag();
    flag.a->key = 'a';
    flag.a->description = _("Generate n points for each individual area");

    flag.notopo = G_define_standard_flag(G_FLG_V_TOPO);

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);

    output = parm.output->answer;
    n = atoi(parm.nsites->answer);
    
    if(parm.seed->answer)
        seed = atoi(parm.seed->answer);

    if (n <= 0) {
	G_fatal_error(_("Number of points must be > 0 (%d given)"), n);
    }

    nareas = 0;
    cat_list = NULL;
    field = -1;
    if (parm.input->answer) {
	Vect_set_open_level(2); /* topology required */
	if (2 > Vect_open_old2(&In, parm.input->answer, "", parm.field->answer))
	    G_fatal_error(_("Unable to open vector map <%s>"),
			  parm.input->answer);

	if (parm.field->answer)
	    field = Vect_get_field_number(&In, parm.field->answer);

	if ((parm.cats->answer || parm.where->answer) && field == -1) {
	    G_warning(_("Invalid layer number (%d). Parameter '%s' or '%s' specified, assuming layer '1'."),
		      field, parm.cats->key, parm.where->key);
	    field = 1;
	}
	if (field > 0)
	    cat_list = Vect_cats_set_constraint(&In, field, parm.where->answer,
						parm.cats->answer);
	nareas = Vect_get_num_areas(&In);
	if (nareas == 0) {
	    Vect_close(&In);
	    G_fatal_error(_("No areas in vector map <%s>"), parm.input->answer);
	}
    }
    else {
	if (flag.a->answer)
	    G_fatal_error(_("The <-%c> flag requires an input vector with areas"),
	                  flag.a->key);
    }

    /* create new vector map */
    if (-1 == Vect_open_new(&Out, output, flag.z->answer ? WITH_Z : WITHOUT_Z))
        G_fatal_error(_("Unable to create vector map <%s>"), output);
    Vect_set_error_handler_io(NULL, &Out);

    /* Do we need to write random values into attribute table? */
    usefloat = -1;
    if (parm.zcol->answer) {
	Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
	driver =
	    db_start_driver_open_database(Fi->driver,
					  Vect_subst_var(Fi->database, &Out));
	if (driver == NULL) {
	    G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
			  Vect_subst_var(Fi->database, &Out), Fi->driver);
	}
        db_set_error_handler_driver(driver);
        
	db_begin_transaction(driver);

	db_init_string(&sql);
	sprintf(buf, "create table %s (%s integer, %s %s)", Fi->table, GV_KEY_COLUMN,
		parm.zcol->answer, parm.ztype->answer);
	db_set_string(&sql, buf);
	Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
			    Fi->driver);

	/* Create table */
	G_debug(3, db_get_string(&sql));
	if (db_execute_immediate(driver, &sql) != DB_OK) {
	    G_fatal_error(_("Unable to create table: %s"),
			  db_get_string(&sql));
	}

	/* Create index */
	if (db_create_index2(driver, Fi->table, Fi->key) != DB_OK)
	    G_warning(_("Unable to create index"));

	/* Grant */
	if (db_grant_on_table
	    (driver, Fi->table, DB_PRIV_SELECT,
	     DB_GROUP | DB_PUBLIC) != DB_OK) {
	    G_fatal_error(_("Unable to grant privileges on table <%s>"),
			  Fi->table);
	}

	/* OK. Let's check what type of column user has created */
	db_set_string(&sql, Fi->table);
	if (db_describe_table(driver, &sql, &table) != DB_OK) {
	    G_fatal_error(_("Unable to describe table <%s>"), Fi->table);
	}

	if (db_get_table_number_of_columns(table) != 2) {
	    G_fatal_error(_("Table should contain only two columns"));
	}

	type = db_get_column_sqltype(db_get_table_column(table, 1));
	if (type == DB_SQL_TYPE_SMALLINT || type == DB_SQL_TYPE_INTEGER)
	    usefloat = 0;
	if (type == DB_SQL_TYPE_REAL || type == DB_SQL_TYPE_DOUBLE_PRECISION)
	    usefloat = 1;
	if (usefloat < 0) {
	    G_fatal_error(_("You have created unsupported column type. This module supports only INTEGER"
			   " and DOUBLE PRECISION column types."));
	}
    }

    Vect_hist_command(&Out);

    /* Init the random seed */
    if(parm.seed->answer)
	G_srand48(seed);
    else
	G_srand48_auto();

    G_get_window(&window);

    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    if (nareas > 0) {
	int first = 1, count;
	struct bound_box abox, bbox;

	box.W = window.west;
	box.E = window.east;
	box.S = window.south;
	box.N = window.north;
	box.B = -PORT_DOUBLE_MAX;
	box.T = PORT_DOUBLE_MAX;

	count = 0;

	for (i = 1; i <= nareas; i++) {
	    
	    if (!Vect_get_area_centroid(&In, i))
		continue;

	    if (field > 0) {
		if (Vect_get_area_cats(&In, i, Cats))
		    continue;

		if (!Vect_cats_in_constraint(Cats, field, cat_list))
		    continue;
	    }

	    Vect_get_area_box(&In, i, &abox);
	    if (!Vect_box_overlap(&abox, &box))
		continue;

	    if (first) {
		Vect_box_copy(&bbox, &abox);
		first = 0;
	    }
	    else
		Vect_box_extend(&bbox, &abox);
	    count++;
	}
	if (count == 0) {
	    Vect_close(&In);
	    Vect_close(&Out);
	    Vect_delete(output);
	    G_fatal_error(_("Selected areas in input vector <%s> do not overlap with the current region"),
			  parm.input->answer);
	}
	Vect_box_copy(&box, &bbox);

	/* does the vector overlap with the current region ? */
	if (box.W >= window.east || box.E <= window.west ||
	    box.S >= window.north || box.N <= window.south) {

	    Vect_close(&In);
	    Vect_close(&Out);
	    Vect_delete(output);
	    G_fatal_error(_("Input vector <%s> does not overlap with the current region"),
	                  parm.input->answer);
	}

	/* try to reduce the current region */
	if (window.east > box.E)
	    window.east = box.E;
	if (window.west < box.W)
	    window.west = box.W;
	if (window.north > box.N)
	    window.north = box.N;
	if (window.south < box.S)
	    window.south = box.S;

	List = Vect_new_boxlist(1);
	alloc_size_list = 10;
	size_list = G_malloc(alloc_size_list * sizeof(BOX_SIZE));
    }

    zmin = zmax = 0;
    if (flag.z->answer || parm.zcol->answer) {
	zmax = atof(parm.zmax->answer);
	zmin = atof(parm.zmin->answer);
    }

    G_message(_("Generating points..."));
    if (flag.a->answer && nareas > 0) {
	struct bound_box abox, bbox;
	int cat = 1;

	/* n points for each area */
	nareas = Vect_get_num_areas(&In);
	
	G_percent(0, nareas, 1);
	for (area = 1; area <= nareas; area++) {

	    G_percent(area, nareas, 1);

	    if (!Vect_get_area_centroid(&In, area))
		continue;

	    if (field > 0) {
		if (Vect_get_area_cats(&In, area, Cats))
		    continue;

		if (!Vect_cats_in_constraint(Cats, field, cat_list)) {
		    continue;
		}
	    }

	    box.W = window.west;
	    box.E = window.east;
	    box.S = window.south;
	    box.N = window.north;
	    box.B = -PORT_DOUBLE_MAX;
	    box.T = PORT_DOUBLE_MAX;
	    
	    Vect_get_area_box(&In, area, &abox);
	    if (!Vect_box_overlap(&box, &abox))
		continue;
		
	    bbox = abox;
	    if (bbox.W < box.W)
		bbox.W = box.W;
	    if (bbox.E > box.E)
		bbox.E = box.E;
	    if (bbox.S < box.S)
		bbox.S = box.S;
	    if (bbox.N > box.N)
		bbox.N = box.N;

	    for (i = 0; i < n; ++i) {
		double x, y, z;
		int outside = 1;
		int ret;

		Vect_reset_line(Points);
		Vect_reset_cats(Cats);

		while (outside) {
		    x = rng() * (bbox.W - bbox.E) + bbox.E;
		    y = rng() * (bbox.N - bbox.S) + bbox.S;
		    z = rng() * (zmax - zmin) + zmin;

		    ret = Vect_point_in_area(x, y, &In, area, &abox);

		    G_debug(3, "    area = %d Vect_point_in_area() = %d", area, ret);

		    if (ret >= 1) {
			outside = 0;
		    }
		}

		if (flag.z->answer)
		    Vect_append_point(Points, x, y, z);
		else
		    Vect_append_point(Points, x, y, 0.0);

		if (parm.zcol->answer) {
		    sprintf(buf, "insert into %s values ( %d, ", Fi->table, i + 1);
		    db_set_string(&sql, buf);
		    /* Round random value if column is integer type */
		    if (usefloat)
			sprintf(buf, "%f )", z);
		    else
			sprintf(buf, "%.0f )", z);
		    db_append_string(&sql, buf);

		    G_debug(3, db_get_string(&sql));
		    if (db_execute_immediate(driver, &sql) != DB_OK) {
			G_fatal_error(_("Cannot insert new row: %s"),
				      db_get_string(&sql));
		    }
		}

		Vect_cat_set(Cats, 1, cat++);
		Vect_write_line(&Out, GV_POINT, Points, Cats);
	    }
	}
    }
    else {
	/* n points in total */
	for (i = 0; i < n; ++i) {
	    double x, y, z;

	    G_percent(i, n, 4);

	    Vect_reset_line(Points);
	    Vect_reset_cats(Cats);

	    x = rng() * (window.west - window.east) + window.east;
	    y = rng() * (window.north - window.south) + window.south;
	    z = rng() * (zmax - zmin) + zmin;
	    
	    if (nareas) {
		int outside = 1;

		do {
		    /* select areas by box */
		    box.E = x;
		    box.W = x;
		    box.N = y;
		    box.S = y;
		    box.T = PORT_DOUBLE_MAX;
		    box.B = -PORT_DOUBLE_MAX;
		    Vect_select_areas_by_box(&In, &box, List);
		    G_debug(3, "  %d areas selected by box", List->n_values);

		    /* sort areas by size, the smallest is likely to be the nearest */
		    if (alloc_size_list < List->n_values) {
			alloc_size_list = List->n_values;
			size_list = G_realloc(size_list, alloc_size_list * sizeof(BOX_SIZE));
		    }

		    k = 0;
		    for (j = 0; j < List->n_values; j++) {
			area = List->id[j];

			if (!Vect_get_area_centroid(&In, area))
			    continue;

			if (field > 0) {
			    if (Vect_get_area_cats(&In, area, Cats))
				continue;

			    if (!Vect_cats_in_constraint(Cats, field, cat_list)) {
				continue;
			    }
			}

			List->id[k] = List->id[j];
			List->box[k] = List->box[j];
			size_list[k].i = List->id[k];
			box = List->box[k];
			size_list[k].box = List->box[k];
			size_list[k].size = (box.N - box.S) * (box.E - box.W);
			k++;
		    }
		    List->n_values = k;
		    
		    if (List->n_values == 2) {
			/* simple swap */
			if (size_list[1].size < size_list[0].size) {
			    size_list[0].i = List->id[1];
			    size_list[1].i = List->id[0];
			    size_list[0].box = List->box[1];
			    size_list[1].box = List->box[0];
			}
		    }
		    else if (List->n_values > 2)
			qsort(size_list, List->n_values, sizeof(BOX_SIZE), sort_by_size);

		    for (j = 0; j < List->n_values; j++) {
			int ret;

			area = size_list[j].i;
			ret = Vect_point_in_area(x, y, &In, area, &size_list[j].box);

			G_debug(3, "    area = %d Vect_point_in_area() = %d", area, ret);

			if (ret >= 1) {
			    outside = 0;
			    break;
			}
		    }
		    if (outside) {
			x = rng() * (window.west - window.east) + window.east;
			y = rng() * (window.north - window.south) + window.south;
			z = rng() * (zmax - zmin) + zmin;
		    }
		} while (outside);
	    }

	    if (flag.z->answer)
		Vect_append_point(Points, x, y, z);
	    else
		Vect_append_point(Points, x, y, 0.0);

	    if (parm.zcol->answer) {
		sprintf(buf, "insert into %s values ( %d, ", Fi->table, i + 1);
		db_set_string(&sql, buf);
		/* Round random value if column is integer type */
		if (usefloat)
		    sprintf(buf, "%f )", z);
		else
		    sprintf(buf, "%.0f )", z);
		db_append_string(&sql, buf);

		G_debug(3, db_get_string(&sql));
		if (db_execute_immediate(driver, &sql) != DB_OK) {
		    G_fatal_error(_("Cannot insert new row: %s"),
				  db_get_string(&sql));
		}
	    }

	    Vect_cat_set(Cats, 1, i + 1);
	    Vect_write_line(&Out, GV_POINT, Points, Cats);
	}
	G_percent(1, 1, 1);
    }
    
    if (parm.zcol->answer) {
	db_commit_transaction(driver);
	db_close_database_shutdown_driver(driver);
    }

    if (!flag.notopo->answer) {
	Vect_build(&Out);
    }
    Vect_close(&Out);

    exit(EXIT_SUCCESS);
}
Exemple #19
0
char *G_site_format(const Site * s, const char *fs, int id)
/* sprintf analog to G_site_put with the addition of a field separator fs 
   and option of printing site attribute identifiers
 */
{
    char ebuf[MAX_SITE_STRING], nbuf[MAX_SITE_STRING];
    char xbuf[MAX_SITE_STRING];
    const char *nfs;
    char *buf;
    int fmt, i, j, k;

    buf = (char *)G_malloc(MAX_SITE_LEN * sizeof(char));

    fmt = G_projection();

    G_format_northing(s->north, nbuf, fmt);
    G_format_easting(s->east, ebuf, fmt);

    nfs = (char *)((fs == (char *)NULL) ? "|" : fs);

    sprintf(buf, "%s%s%s", ebuf, nfs, nbuf);

    for (i = 0; i < s->dim_alloc; ++i) {
	format_double(s->dim[i], nbuf);
	sprintf(xbuf, "%s%s", nfs, nbuf);
	G_strcat(buf, xbuf);
    }

    nfs = (fs == NULL) ? " " : fs;

    switch (s->cattype) {
    case CELL_TYPE:
	sprintf(xbuf, "%s%s%d ", nfs, ((id == 0) ? "" : "#"), (int)s->ccat);
	G_strcat(buf, xbuf);
	break;
    case FCELL_TYPE:
    case DCELL_TYPE:
	sprintf(xbuf, "%s%s%g ", nfs, ((id == 0) ? "" : "#"), (float)s->fcat);
	G_strcat(buf, xbuf);
	break;
    }

    for (i = 0; i < s->dbl_alloc; ++i) {
	format_double(s->dbl_att[i], nbuf);
	sprintf(xbuf, "%s%s%s", nfs, ((id == 0) ? "" : "%"), nbuf);
	G_strcat(buf, xbuf);
    }

    for (i = 0; i < s->str_alloc; ++i) {
	if (strlen(s->str_att[i]) != 0) {
	    /* escape double quotes */
	    j = k = 0;

	    /* do not uncomment this code because sites file was created
	     * as we want. So it's enough to print them out as it is.
	     *
	     if (G_index (s->str_att[i], DQUOTE) != (char *) NULL)
	     {
	     while (!isnull(s->str_att[i][j]))
	     {
	     if (isquote(s->str_att[i][j]))
	     {
	     xbuf[k++] = BSLASH;
	     xbuf[k++] = DQUOTE;
	     }
	     else
	     xbuf[k++] = s->str_att[i][j];
	     j++;
	     }
	     xbuf[k] = (char) NULL;
	     }
	     else
	     */

	    G_strcpy(xbuf, s->str_att[i]);

	    G_strcpy(s->str_att[i], xbuf);

	    if (G_index(s->str_att[i], SPACE) != (char *)NULL)
		sprintf(xbuf, "%s%s\"%s\"", nfs, ((id == 0) ? "" : "@"),
			s->str_att[i]);
	    else
		sprintf(xbuf, "%s%s%s", nfs, ((id == 0) ? "" : "@"),
			s->str_att[i]);
	    G_strcat(buf, xbuf);
	}
    }
    return buf;
}
Exemple #20
0
int main(int argc, char **argv)
{
    struct GModule *module;
    struct Option *opt_out;
    struct Option *opt_lev;
    struct Flag *flg_d;
    struct Flag *flg_c;
    int dither;
    char *out_name;
    int out_file;
    CELL *out_array;
    struct Colors out_colors;
    int levels;
    int atrow, atcol;
    struct Cell_head window;
    unsigned char *dummy, *nulls;
    int i, j;
    struct History history;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("composite"));
    G_add_keyword("RGB");
    module->description =
	_("Combines red, green and blue raster maps into "
	  "a single composite raster map.");

    for (i = 0; i < 3; i++) {
	struct Option *opt;
	char buff[80];

	B[i].opt_name = opt = G_define_standard_option(G_OPT_R_INPUT);

	sprintf(buff, "%s", color_names[i]);
	opt->key = G_store(buff);

	opt->answer = NULL;

	sprintf(buff, _("Name of raster map to be used for <%s>"),
		color_names[i]);
	opt->description = G_store(buff);
    }

    opt_lev = G_define_option();
    opt_lev->key = "levels";
    opt_lev->type = TYPE_INTEGER;
    opt_lev->required = NO;
    opt_lev->options = "1-256";
    opt_lev->answer = "32";
    opt_lev->description =
	_("Number of levels to be used for each component");
    opt_lev->guisection = _("Levels");

    for (i = 0; i < 3; i++) {
	struct Option *opt;
	char buff[80];

	B[i].opt_levels = opt = G_define_option();

	sprintf(buff, "lev_%s", color_names[i]);
	opt->key = G_store(buff);

	opt->type = TYPE_INTEGER;
	opt->required = NO;
	opt->options = "1-256";

	sprintf(buff, _("Number of levels to be used for <%s>"),
		color_names[i]);
	opt->description = G_store(buff);
	opt->guisection = _("Levels");
    }

    opt_out = G_define_standard_option(G_OPT_R_OUTPUT);

    flg_d = G_define_flag();
    flg_d->key = 'd';
    flg_d->description = _("Dither");

    flg_c = G_define_flag();
    flg_c->key = 'c';
    flg_c->description = _("Use closest color");

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);

    levels = atoi(opt_lev->answer);

    dither = flg_d->answer;
    closest = flg_c->answer;

    /* read in current window */
    G_get_window(&window);

    dummy = G_malloc(window.cols);

    nulls = G_malloc(window.cols);

    for (i = 0; i < 3; i++) {
	struct band *b = &B[i];

	/* Get name of layer to be used */
	b->name = b->opt_name->answer;

	/* Make sure map is available */
	b->file = Rast_open_old(b->name, "");

	b->type = Rast_get_map_type(b->file);

	b->size = Rast_cell_size(b->type);

	/* Reading color lookup table */
	if (Rast_read_colors(b->name, "", &b->colors) == -1)
	    G_fatal_error(_("Unable to read color file of raster map <%s>"), b->name);

	for (j = 0; j < 3; j++)
	    b->array[j] = (i == j)
		? G_malloc(window.cols)
		: dummy;

	b->levels = b->opt_levels->answer ? atoi(b->opt_levels->answer)
	    : levels;
	b->maxlev = b->levels - 1;
	b->offset = 128 / b->maxlev;

	if (dither)
	    for (j = 0; j < 2; j++)
		b->floyd[j] = G_calloc(window.cols + 2, sizeof(short));
    }

    /* open output files */
    out_name = opt_out->answer;

    out_file = Rast_open_c_new(out_name);

    out_array = Rast_allocate_c_buf();

    /* Make color table */
    make_color_cube(&out_colors);

    G_message(_("Writing raster map <%s>..."), out_name);

    for (atrow = 0; atrow < window.rows; atrow++) {
	G_percent(atrow, window.rows, 2);

	for (i = 0; i < 3; i++) {
	    struct band *b = &B[i];

	    Rast_get_row_colors(b->file, atrow, &b->colors,
				b->array[0],
				b->array[1], b->array[2], nulls);

	    if (dither) {
		short *tmp = b->floyd[0];

		b->floyd[0] = b->floyd[1];
		for (atcol = 0; atcol < window.cols + 2; atcol++)
		    tmp[atcol] = 0;
		b->floyd[1] = tmp;
	    }
	}

	for (atcol = 0; atcol < window.cols; atcol++) {
	    int val[3];

	    if (nulls[atcol]) {
		Rast_set_c_null_value(&out_array[atcol], 1);
		continue;
	    }

	    for (i = 0; i < 3; i++) {
		struct band *b = &B[i];
		int v = b->array[i][atcol];

		if (dither) {
		    int r, w, d;

		    v += b->floyd[0][atcol + 1] / 16;
		    v = (v < 0) ? 0 : (v > 255) ? 255 : v;
		    r = quantize(i, v);
		    w = r * 255 / b->maxlev;
		    d = v - w;
		    b->floyd[0][atcol + 2] += 7 * d;
		    b->floyd[1][atcol + 0] += 3 * d;
		    b->floyd[1][atcol + 1] += 5 * d;
		    b->floyd[1][atcol + 2] += 1 * d;
		    val[i] = r;
		}
		else
		    val[i] = quantize(i, v);
	    }

	    out_array[atcol] = (CELL)
		(val[2] * B[1].levels + val[1]) * B[0].levels + val[0];
	}

	Rast_put_row(out_file, out_array, CELL_TYPE);
    }
    G_percent(window.rows, window.rows, 1);

    /* Close the input files */
    for (i = 0; i < 3; i++)
	Rast_close(B[i].file);

    /* Close the output file */
    Rast_close(out_file);
    Rast_write_colors(out_name, G_mapset(), &out_colors);
    Rast_short_history(out_name, "raster", &history);
    Rast_command_history(&history);
    Rast_write_history(out_name, &history);

    G_done_msg(_("Raster map <%s> created."), out_name);

    exit(EXIT_SUCCESS);
}
Exemple #21
0
Site *G_site_new_struct(RASTER_MAP_TYPE cattype,
			int n_dim, int n_s_att, int n_d_att)
/* Allocate memory for a Site struct. Returns a properly allocated
   site struct or NULL on error. 
   cattype= -1 (no cat), CELL_TYPE, FCELL_TYPE, or DCELL_TYPE 
 */
{
    int i;
    Site *s;

    if (n_dim < 2 || n_s_att < 0 || n_d_att < 0)
	G_fatal_error(_("G_oldsite_new_struct: invalid # dims or fields"));

    if ((s = (Site *) G_malloc(sizeof(Site))) == NULL)
	return (Site *) NULL;

    s->cattype = cattype;
    s->ccat = s->fcat = s->dcat = 0;

    if (n_dim > 2) {
	if ((s->dim =
	     (double *)G_malloc((n_dim - 2) * sizeof(double))) == NULL) {
	    G_free(s);
	    return (Site *) NULL;
	}
    }
    s->dim_alloc = n_dim - 2;

    if (n_d_att > 0) {
	if ((s->dbl_att =
	     (double *)G_malloc(n_d_att * sizeof(double))) == NULL) {
	    if (n_dim > 2)
		G_free(s->dim);
	    G_free(s);
	    return (Site *) NULL;
	}
    }
    s->dbl_alloc = n_d_att;

    if (n_s_att > 0) {
	if ((s->str_att =
	     (char **)G_malloc(n_s_att * sizeof(char *))) == NULL) {
	    if (n_d_att > 0)
		G_free(s->dbl_att);
	    if (n_dim > 2)
		G_free(s->dim);
	    G_free(s);
	    return (Site *) NULL;
	}
	else
	    for (i = 0; i < n_s_att; ++i)
		if ((s->str_att[i] =
		     (char *)G_malloc(MAX_SITE_STRING * sizeof(char))) ==
		    NULL) {
		    while (--i)
			G_free(s->str_att[i]);
		    G_free(s->str_att);
		    if (n_d_att > 0)
			G_free(s->dbl_att);
		    if (n_dim > 2)
			G_free(s->dim);
		    G_free(s);
		    return (Site *) NULL;
		}
    }
    s->str_alloc = n_s_att;

    return s;
}
Exemple #22
0
/*!
  \brief Get default information about link to database for new dblink
  
  \param Map pointer to Map_info structure
  \param field layer number
  \param field_name layer name
  \param type how many tables are linked to map: GV_1TABLE / GV_MTABLE 

  \return pointer to allocated field_info structure
 */
struct field_info *Vect_default_field_info(struct Map_info *Map,
					   int field, const char *field_name, int type)
{
    struct field_info *fi;
    char buf[GNAME_MAX], buf2[GNAME_MAX];
    const char *schema;
    dbConnection connection;

    G_debug(1, "Vect_default_field_info(): map = %s field = %d", Map->name,
	    field);
    
    if (Map->format == GV_FORMAT_OGR_DIRECT) {
	G_zero(&connection, sizeof(dbConnection));
	connection.driverName = G_store("ogr");
	connection.databaseName = G_store(Map->fInfo.ogr.dsn);
    }
    else {
	db_get_connection(&connection);
    }
    
    G_debug(2, "drv = %s db = %s", connection.driverName, connection.databaseName);
    
    if (!connection.driverName && !connection.databaseName) {
	/* Set default values */
	db_set_default_connection();
	db_get_connection(&connection);

	G_important_message(_("Default driver / database set to:\n"
			      "driver: %s\ndatabase: %s"), connection.driverName,
			    connection.databaseName);
    }
    /* they must be a matched pair, so if one is set but not the other
       then give up and let the user figure it out */
    else if (!connection.driverName) {
	G_fatal_error(_("Default driver is not set"));
    }
    else if (!connection.databaseName) {
	G_fatal_error(_("Default database is not set"));
    }

    fi = (struct field_info *)G_malloc(sizeof(struct field_info));

    fi->number = field;

    /* Table name */
    if (type == GV_1TABLE) {
	sprintf(buf, "%s", Map->name);
    }
    else {
	if (field_name != NULL && strlen(field_name) > 0)
	    sprintf(buf, "%s_%s", Map->name, field_name);
	else
	    sprintf(buf, "%s_%d", Map->name, field);
    }
    schema = connection.schemaName;
    if (schema && strlen(schema) > 0) {
	sprintf(buf2, "%s.%s", schema, buf);
	fi->table = G_store(buf2);
    }
    else {
	fi->table = G_store(buf);
    }

    /* Field name */
    if (field_name)
	fi->name = G_store(field_name);
    else
	fi->name = G_store(buf);

    fi->key = G_store(GV_KEY_COLUMN);	/* Should be: id/fid/gfid/... ? */
    fi->database = G_store(connection.databaseName);
    fi->driver = G_store(connection.driverName);

    return fi;
}
Exemple #23
0
int do_cum(void)
{
    int r, c, dr, dc;
    int r_nbr, c_nbr, ct_dir, np_side, edge;
    CELL is_swale, aspect, ele_nbr;
    DCELL value, valued;
    int killer, threshold;
    int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 };
    int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };
    int this_index, down_index, nbr_index;
    double *dist_to_nbr, *contour;
    double cell_size;

    G_message(_("SECTION 3: Accumulating Surface Flow with SFD."));

    /* distances to neighbours, contour lengths */
    dist_to_nbr = (double *)G_malloc(sides * sizeof(double));
    contour = (double *)G_malloc(sides * sizeof(double));

    cell_size = get_dist(dist_to_nbr, contour);

    if (bas_thres <= 0)
	threshold = 60;
    else
	threshold = bas_thres;
    for (killer = 1; killer <= do_points; killer++) {
	G_percent(killer, do_points, 1);
	this_index = astar_pts[killer];
	aspect = asp[this_index];
	seg_index_rc(alt_seg, this_index, &r, &c);
	if (aspect) {
	    dr = r + asp_r[ABS(aspect)];
	    dc = c + asp_c[ABS(aspect)];
	}
	/* skip user-defined depressions */
	else
	    dr = dc = -1;
	if (dr >= 0 && dr < nrows && dc >= 0 && dc < ncols) { /* if ((dr = astar_pts[killer].downr) > -1) { */
	    down_index = SEG_INDEX(wat_seg, dr, dc);
	    value = wat[this_index];
	    if (fabs(value) >= threshold)
		FLAG_SET(swale, r, c);
	    valued = wat[down_index];

	    edge = 0;
	    np_side = -1;
	    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
		/* get r, c (r_nbr, c_nbr) for neighbours */
		r_nbr = r + nextdr[ct_dir];
		c_nbr = c + nextdc[ct_dir];

		if (dr == r_nbr && dc == c_nbr)
		    np_side = ct_dir;

		/* check that neighbour is within region */
		if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 &&
		    c_nbr < ncols) {

		    nbr_index = SEG_INDEX(wat_seg, r_nbr, c_nbr);
		    ele_nbr = alt[nbr_index];
		    if (Rast_is_c_null_value(&ele_nbr))
			edge = 1;
		}
		else
		    edge = 1;
		if (edge)
		    break;
	    }
	    /* do not distribute flow along edges, this causes artifacts */
	    if (edge) {
		is_swale = FLAG_GET(swale, r, c);
		if (is_swale && aspect > 0) {
		    aspect = -1 * drain[r - r_nbr + 1][c - c_nbr + 1];
		    asp[this_index] = aspect;
		}
		if (valued > 0)
		    wat[down_index] = -valued;
		continue;
	    }

	    if (value > 0) {
		if (valued > 0)
		    valued += value;
		else
		    valued -= value;
	    }
	    else {
		if (valued < 0)
		    valued += value;
		else
		    valued = value - valued;
	    }
	    wat[down_index] = valued;

	    /* topographic wetness index ln(a / tan(beta)) and
	     * stream power index a * tan(beta) */
	    if (atanb_flag) {
		sca[this_index] = fabs(wat[this_index]) *
		                  (cell_size / contour[np_side]);
		tanb[this_index] = get_slope_tci(alt[this_index],
		                                 alt[down_index],
						 dist_to_nbr[np_side]);
	    }

	    is_swale = FLAG_GET(swale, r, c);
	    if (is_swale || fabs(valued) >= threshold) {
		FLAG_SET(swale, dr, dc);
	    }
	    else {
		if (er_flag && !is_swale)
		    slope_length(r, c, dr, dc);
	    }
	}
    }
    G_free(astar_pts);

    return 0;
}
Exemple #24
0
int main(int argc, char *argv[])
{
    struct GModule *module;
    struct GParams params;
    struct Map_info Map;
    struct Map_info **BgMap;	/* background vector maps */
    int nbgmaps;		/* number of registrated background maps */
    enum mode action_mode;
    FILE *ascii;

    int i;
    int move_first, snap;
    int ret, layer;
    double move_x, move_y, move_z, thresh[3];

    struct line_pnts *coord;

    struct ilist *List;

    struct cat_list *Clist;

    ascii = NULL;
    List = NULL;
    BgMap = NULL;
    nbgmaps = 0;
    coord = NULL;
    Clist = NULL;

    G_gisinit(argv[0]);

    module = G_define_module();
    module->overwrite = TRUE;
    G_add_keyword(_("vector"));
    G_add_keyword(_("geometry"));
    G_add_keyword(_("editing"));
    G_add_keyword(_("line"));
    G_add_keyword(_("node"));
    G_add_keyword(_("point"));
    G_add_keyword(_("vertex"));
    module->description = _("Edits a vector map, allows adding, deleting "
			    "and modifying selected vector features.");

    if (!parser(argc, argv, &params, &action_mode))
	exit(EXIT_FAILURE);

    /* get list of categories */
    Clist = Vect_new_cat_list();
    if (params.cat->answer && Vect_str_to_cat_list(params.cat->answer, Clist)) {
	G_fatal_error(_("Unable to get category list <%s>"),
		      params.cat->answer);
    }

    /* open input file */
    if (params.in->answer) {
	if (strcmp(params.in->answer, "-") != 0) {
	    ascii = fopen(params.in->answer, "r");
	    if (ascii == NULL)
		G_fatal_error(_("Unable to open file <%s>"),
			      params.in->answer);
	}
	else {
	    ascii = stdin;
	}
    }
    if (!ascii && action_mode == MODE_ADD)
	G_fatal_error(_("Required parameter <%s> not set"), params.in->key);
    
    if (action_mode == MODE_CREATE) {
	int overwrite, map_type;
	
	overwrite = G_check_overwrite(argc, argv);
	if (G_find_vector2(params.map->answer, G_mapset()) &&
	    (!G_find_file("", "OGR", G_mapset()) &&
	     !G_find_file("", "PG", G_mapset()))) {
	    if (!overwrite)
		G_fatal_error(_("Vector map <%s> already exists"),
			      params.map->answer);
	}

	/* 3D vector maps? */
        putenv("GRASS_VECTOR_EXTERNAL_IMMEDIATE=1");
	ret = Vect_open_new(&Map, params.map->answer, WITHOUT_Z);
	if (ret == -1) {
	    G_fatal_error(_("Unable to create vector map <%s>"),
			  params.map->answer);
	}
	Vect_set_error_handler_io(NULL, &Map);

	/* native or external data source ? */
	map_type = Vect_maptype(&Map);
	if (map_type != GV_FORMAT_NATIVE) {
	    int type;
	    type = Vect_option_to_types(params.type);
	    if (type != GV_POINT && !(type & GV_LINES))
		G_fatal_error("%s: point,line,boundary",
                              _("Supported feature types for non-native formats:"));
            /* create OGR or PostGIS layer */
            if (Vect_write_line(&Map, type, NULL, NULL) < 0)
                G_fatal_error(_("Unable to create vector map <%s>"),
			      params.map->answer);
	}
	
	G_debug(1, "Map created");

	if (ascii) {
	    /* also add new vector features */
	    action_mode = MODE_ADD;
	}
    }
    else {			/* open selected vector file */
	if (action_mode == MODE_ADD)	/* write */
	    ret = Vect_open_update2(&Map, params.map->answer, G_mapset(), params.fld->answer);
	else			/* read-only -- select features */
	    ret = Vect_open_old2(&Map, params.map->answer, G_mapset(), params.fld->answer);
	
	if (ret < 2)
	    G_fatal_error(_("Unable to open vector map <%s> on topological level. "
			    "Try to rebuild vector topology by v.build."),
			  params.map->answer);
    }

    G_debug(1, "Map opened");
    
    /* open background maps */
    if (params.bmaps->answer) {
	i = 0;

	while (params.bmaps->answers[i]) {
	    const char *bmap = params.bmaps->answers[i];
	    const char *mapset = G_find_vector2(bmap, "");
	    if (!mapset)
		G_fatal_error(_("Vector map <%s> not found"), bmap);

	    if (strcmp(
		    G_fully_qualified_name(params.map->answer, G_mapset()),
		    G_fully_qualified_name(bmap, mapset)) == 0) {
		G_fatal_error(_("Unable to open vector map <%s> as the background map. "
			       "It is given as vector map to be edited."),
			      bmap);
	    }
	    nbgmaps++;
	    BgMap = (struct Map_info **)G_realloc(
		BgMap, nbgmaps * sizeof(struct Map_info *));
	    BgMap[nbgmaps - 1] =
		(struct Map_info *)G_malloc(sizeof(struct Map_info));
	    if (Vect_open_old(BgMap[nbgmaps - 1], bmap, "") == -1)
		G_fatal_error(_("Unable to open vector map <%s>"), bmap);
	    G_verbose_message(_("Background vector map <%s> registered"), bmap);
	    i++;
	}
    }

    layer = Vect_get_field_number(&Map, params.fld->answer);
    i = 0;
    while (params.maxdist->answers[i]) {
	switch (i) {
	case THRESH_COORDS:
	    thresh[THRESH_COORDS] =
		max_distance(atof(params.maxdist->answers[THRESH_COORDS]));
	    thresh[THRESH_SNAP] = thresh[THRESH_QUERY] =
		thresh[THRESH_COORDS];
	    break;
	case THRESH_SNAP:
	    thresh[THRESH_SNAP] =
		max_distance(atof(params.maxdist->answers[THRESH_SNAP]));
	    break;
	case THRESH_QUERY:
	    thresh[THRESH_QUERY] =
		atof(params.maxdist->answers[THRESH_QUERY]);
	    break;
	default:
	    break;
	}
	i++;
    }

    move_first = params.move_first->answer ? 1 : 0;
    snap = NO_SNAP;
    if (strcmp(params.snap->answer, "node") == 0)
	snap = SNAP;
    else if (strcmp(params.snap->answer, "vertex") == 0)
	snap = SNAPVERTEX;
    if (snap != NO_SNAP && thresh[THRESH_SNAP] <= 0) {
	G_warning(_("Threshold for snapping must be > 0. No snapping applied."));
	snap = NO_SNAP;
    }
    
    if (action_mode != MODE_CREATE && action_mode != MODE_ADD) {
	/* select lines */
	List = Vect_new_list();
	G_message(_("Selecting features..."));
	if (action_mode == MODE_COPY && BgMap && BgMap[0]) {
	    List = select_lines(BgMap[0], action_mode, &params, thresh, List);
	}
	else {
	    List = select_lines(&Map, action_mode, &params, thresh, List);
	}
    }

    if ((action_mode != MODE_CREATE && action_mode != MODE_ADD &&
	 action_mode != MODE_SELECT)) {
	if (List->n_values < 1) {
	    G_warning(_("No features selected, nothing to edit"));
	    action_mode = MODE_NONE;
	    ret = 0;
	}
	else {
	    /* reopen the map for updating */
	    if (action_mode == MODE_ZBULK && !Vect_is_3d(&Map)) {
		Vect_close(&Map);
		G_fatal_error(_("Vector map <%s> is not 3D. Tool '%s' requires 3D vector map. "
			       "Please convert the vector map "
			       "to 3D using e.g. %s."), params.map->answer,
			      params.tool->answer, "v.extrude");
	    }
	    Vect_close(&Map);

	    if (Vect_open_update2(&Map, params.map->answer, G_mapset(), params.fld->answer) < 0)
		G_fatal_error(_("Unable to open vector map <%s>"),
				params.map->answer);
	}
    }

    /* coords option -> array */
    if (params.coord->answers) {
	coord = Vect_new_line_struct();
	int i = 0;
	double east, north;

	while (params.coord->answers[i]) {
	    east = atof(params.coord->answers[i]);
	    north = atof(params.coord->answers[i + 1]);
	    Vect_append_point(coord, east, north, 0.0);
	    i += 2;
	}
    }

    /* perform requested editation */
    switch (action_mode) {
    case MODE_CREATE:
	break;
    case MODE_ADD:
	if (!params.header->answer)
	    Vect_read_ascii_head(ascii, &Map);
	int num_lines;
	num_lines = Vect_get_num_lines(&Map);
	
	ret = Vect_read_ascii(ascii, &Map);
	if (ret > 0) {
	    int iline;
	    struct ilist *List_added;
	    
	    G_message(n_("%d feature added",
                         "%d features added",
                         ret), ret);
	    
	    List_added = Vect_new_list();
	    for (iline = num_lines + 1; iline <= Vect_get_num_lines(&Map); iline++)
		Vect_list_append(List_added, iline);
	    
	    G_verbose_message(_("Threshold value for snapping is %.2f"),
			      thresh[THRESH_SNAP]);
	    if (snap != NO_SNAP) { /* apply snapping */
		/* snap to vertex ? */
		Vedit_snap_lines(&Map, BgMap, nbgmaps, List_added,
				 thresh[THRESH_SNAP],
				 snap == SNAP ? FALSE : TRUE); 
	    }
	    if (params.close->answer) {	/* close boundaries */
		int nclosed;

		nclosed = close_lines(&Map, GV_BOUNDARY, thresh[THRESH_SNAP]);
		G_message(n_("%d boundary closed",
                             "%d boundaries closed",
                             nclosed), nclosed);
	    }
	    Vect_destroy_list(List_added);
	}
	break;
    case MODE_DEL:
	ret = Vedit_delete_lines(&Map, List);
	G_message(n_("%d feature deleted",
                     "%d features deleted",
                     ret), ret);
	break;
    case MODE_MOVE:
	move_x = atof(params.move->answers[0]);
	move_y = atof(params.move->answers[1]);
	move_z = atof(params.move->answers[2]);
	G_verbose_message(_("Threshold value for snapping is %.2f"),
			  thresh[THRESH_SNAP]);
	ret = Vedit_move_lines(&Map, BgMap, nbgmaps, List, move_x, move_y, move_z, snap, thresh[THRESH_SNAP]);
	G_message(n_("%d feature moved",
                     "%d features moved",
                     ret), ret);
	break;
    case MODE_VERTEX_MOVE:
	move_x = atof(params.move->answers[0]);
	move_y = atof(params.move->answers[1]);
	move_z = atof(params.move->answers[2]);
	G_verbose_message(_("Threshold value for snapping is %.2f"),
			  thresh[THRESH_SNAP]);
	ret = Vedit_move_vertex(&Map, BgMap, nbgmaps, List, coord, thresh[THRESH_COORDS], thresh[THRESH_SNAP], move_x, move_y, move_z, move_first, snap);
	G_message(n_("%d vertex moved",
                     "%d vertices moved",
                     ret), ret);
	break;
    case MODE_VERTEX_ADD:
	ret = Vedit_add_vertex(&Map, List, coord, thresh[THRESH_COORDS]);
	G_message(n_("%d vertex added",
                     "%d vertices added",
                     ret), ret);
	break;
    case MODE_VERTEX_DELETE:
	ret = Vedit_remove_vertex(&Map, List, coord, thresh[THRESH_COORDS]);
	G_message(n_("%d vertex removed",
                     "%d vertices removed",
                     ret), ret);
	break;
    case MODE_BREAK:
	if (params.coord->answer) {
	    ret = Vedit_split_lines(&Map, List,
				    coord, thresh[THRESH_COORDS], NULL);
	}
	else {
	    ret = Vect_break_lines_list(&Map, List, NULL, GV_LINES, NULL);
	}
	G_message(n_("%d line broken",
                     "%d lines broken",
                     ret), ret);
	break;
    case MODE_CONNECT:
	G_verbose_message(_("Threshold value for snapping is %.2f"),
			  thresh[THRESH_SNAP]);
	ret = Vedit_connect_lines(&Map, List, thresh[THRESH_SNAP]);
	G_message(n_("%d line connected",
                     "%d lines connected",
                     ret), ret);
	break;
    case MODE_MERGE:
	ret = Vedit_merge_lines(&Map, List);
	G_message(n_("%d line merged",
                     "%d lines merged",
                     ret), ret);
	break;
    case MODE_SELECT:
	ret = print_selected(List);
	break;
    case MODE_CATADD:
	ret = Vedit_modify_cats(&Map, List, layer, 0, Clist);
	G_message(n_("%d feature modified",
                     "%d features modified",
                     ret), ret);
	break;
    case MODE_CATDEL:
	ret = Vedit_modify_cats(&Map, List, layer, 1, Clist);
	G_message(n_("%d feature modified",
                     "%d features modified",
                     ret), ret);
	break;
    case MODE_COPY:
	if (BgMap && BgMap[0]) {
	    if (nbgmaps > 1)
		G_warning(_("Multiple background maps were given. "
			    "Selected features will be copied only from "
			    "vector map <%s>."),
			  Vect_get_full_name(BgMap[0]));

	    ret = Vedit_copy_lines(&Map, BgMap[0], List);
	}
	else {
	    ret = Vedit_copy_lines(&Map, NULL, List);
	}
	G_message(n_("%d feature copied",
                     "%d features copied",
                     ret), ret);
	break;
    case MODE_SNAP:
	G_verbose_message(_("Threshold value for snapping is %.2f"),
			  thresh[THRESH_SNAP]);
	ret = snap_lines(&Map, List, thresh[THRESH_SNAP]);
	break;
    case MODE_FLIP:
	ret = Vedit_flip_lines(&Map, List);
	G_message(n_("%d line flipped",
                     "%d lines flipped",
                     ret), ret);
	break;
    case MODE_NONE:
	break;
    case MODE_ZBULK: {
	double start, step;
	double x1, y1, x2, y2;
	
	start = atof(params.zbulk->answers[0]);
	step = atof(params.zbulk->answers[1]);
	
	x1 = atof(params.bbox->answers[0]);
	y1 = atof(params.bbox->answers[1]);
	x2 = atof(params.bbox->answers[2]);
	y2 = atof(params.bbox->answers[3]);
	
	ret = Vedit_bulk_labeling(&Map, List,
				  x1, y1, x2, y2, start, step);
	
	G_message(n_("%d line labeled",
                     "%d lines labeled",
                     ret), ret);
	break;
    }
    case MODE_CHTYPE:
	ret = Vedit_chtype_lines(&Map, List);
	
	if (ret > 0) {
	    G_message(n_("%d feature converted",
                         "%d features converted",
                         ret), ret);
	}
	else {
	    G_message(_("No feature modified"));
	}
	break;
    case MODE_AREA_DEL: {
	ret = 0;
	for (i = 0; i < List->n_values; i++) {
	    if (Vect_get_line_type(&Map, List->value[i]) != GV_CENTROID) {
		G_warning(_("Select feature %d is not centroid, ignoring..."),
			  List->value[i]);
		continue;
	    }
	    
	    ret += Vedit_delete_area_centroid(&Map, List->value[i]);
	}
	G_message(n_("%d area removed",
                     "%d areas removed",
                     ret), ret);
	break;
    }
    default:
	G_warning(_("Operation not implemented"));
	ret = -1;
	break;
    }
    
    Vect_hist_command(&Map);

    /* build topology only if requested or if tool!=select */
    if (action_mode != MODE_SELECT && action_mode != MODE_NONE &&
		    params.topo->answer != 1) {
	Vect_build_partial(&Map, GV_BUILD_NONE);
	Vect_build(&Map);
    }

    if (List)
	Vect_destroy_list(List);

    Vect_close(&Map);

    G_debug(1, "Map closed");

    /* close background maps */
    for (i = 0; i < nbgmaps; i++) {
	Vect_close(BgMap[i]);
	G_free((void *)BgMap[i]);
    }
    G_free((void *)BgMap);

    if (coord)
	Vect_destroy_line_struct(coord);

    if (Clist)
	Vect_destroy_cat_list(Clist);

    G_done_msg(" ");

    if (ret > -1) {
	exit(EXIT_SUCCESS);
    }
    else {
	exit(EXIT_FAILURE);
    }
}
Exemple #25
0
int main(int argc, char *argv[])
{
    char group[INAME_LEN], extension[INAME_LEN];
    int order;			/* ADDED WITH CRS MODIFICATIONS */
    char *ipolname;		/* name of interpolation method */
    int method;
    int n, i, m, k = 0;
    int got_file = 0, target_overwrite = 0;
    char *overstr;
    struct Cell_head cellhd;

    struct Option *grp,         /* imagery group */
     *val,                      /* transformation order */
     *ifile,			/* input files */
     *ext,			/* extension */
     *tres,			/* target resolution */
     *mem,			/* amount of memory for cache */
     *interpol;			/* interpolation method:
				   nearest neighbor, bilinear, cubic */
    struct Flag *c, *a;
    struct GModule *module;

    G_gisinit(argv[0]);

    module = G_define_module();
    module->keywords = _("imagery, rectify");
    module->description =
	_("Rectifies an image by computing a coordinate "
	  "transformation for each pixel in the image based on the "
	  "control points.");

    grp = G_define_standard_option(G_OPT_I_GROUP);

    ifile = G_define_standard_option(G_OPT_R_INPUTS);
    ifile->required = NO;

    ext = G_define_option();
    ext->key = "extension";
    ext->type = TYPE_STRING;
    ext->required = YES;
    ext->multiple = NO;
    ext->description = _("Output raster map(s) suffix");

    val = G_define_option();
    val->key = "order";
    val->type = TYPE_INTEGER;
    val->required = YES;
    val->description = _("Rectification polynom order (1-3)");

    tres = G_define_option();
    tres->key = "res";
    tres->type = TYPE_DOUBLE;
    tres->required = NO;
    tres->description = _("Target resolution (ignored if -c flag used)");

    mem = G_define_option();
    mem->key = "memory";
    mem->type = TYPE_DOUBLE;
    mem->key_desc = "memory in MB";
    mem->required = NO;
    mem->answer = "300";
    mem->description = _("Amount of memory to use in MB");

    ipolname = make_ipol_list();

    interpol = G_define_option();
    interpol->key = "method";
    interpol->type = TYPE_STRING;
    interpol->required = NO;
    interpol->answer = "nearest";
    interpol->options = ipolname;
    interpol->description = _("Interpolation method to use");

    c = G_define_flag();
    c->key = 'c';
    c->description =
	_("Use current region settings in target location (def.=calculate smallest area)");

    a = G_define_flag();
    a->key = 'a';
    a->description = _("Rectify all raster maps in group");

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);

    /* get the method */
    for (method = 0; (ipolname = menu[method].name); method++)
	if (strcmp(ipolname, interpol->answer) == 0)
	    break;

    if (!ipolname)
	G_fatal_error(_("<%s=%s> unknown %s"),
		      interpol->key, interpol->answer, interpol->key);
    interpolate = menu[method].method;

    G_strip(grp->answer);
    strcpy(group, grp->answer);
    strcpy(extension, ext->answer);
    order = atoi(val->answer);

    seg_mb = NULL;
    if (mem->answer) {
	if (atoi(mem->answer) > 0)
	    seg_mb = mem->answer;
    }

    if (!ifile->answers)
	a->answer = 1;		/* force all */

    /* Find out how many files on command line */
    if (!a->answer) {
	for (m = 0; ifile->answers[m]; m++) {
	    k = m;
	}
	k++;
    }

    if (order < 1 || order > MAXORDER)
	G_fatal_error(_("Invalid order (%d); please enter 1 to %d"), order,
		      MAXORDER);

    /* determine the number of files in this group */
    if (I_get_group_ref(group, &ref) <= 0)
	G_fatal_error(_("Group <%s> does not exist"), grp->answer);

    if (ref.nfiles <= 0) {
	G_important_message(_("Group <%s> contains no raster maps; run i.group"),
			    grp->answer);
	exit(EXIT_SUCCESS);
    }

    ref_list = (int *)G_malloc(ref.nfiles * sizeof(int));

    if (a->answer) {
	for (n = 0; n < ref.nfiles; n++) {
	    ref_list[n] = 1;
	}
    }
    else {
	char xname[GNAME_MAX], xmapset[GMAPSET_MAX], *name, *mapset;

	for (n = 0; n < ref.nfiles; n++)
		ref_list[n] = 0;

	for (m = 0; m < k; m++) {
	    got_file = 0;
	    if (G__name_is_fully_qualified(ifile->answers[m], xname, xmapset)) {
		name = xname;
		mapset = xmapset;
	    }
	    else {
		name = ifile->answers[m];
		mapset = NULL;
	    }

	    got_file = 0;
	    for (n = 0; n < ref.nfiles; n++) {
		if (mapset) {
		    if (strcmp(name, ref.file[n].name) == 0 &&
		        strcmp(mapset, ref.file[n].mapset) == 0) {
			got_file = 1;
			ref_list[n] = 1;
			break;
		    }
		}
		else {
		    if (strcmp(name, ref.file[n].name) == 0) {
			got_file = 1;
			ref_list[n] = 1;
			break;
		    }
		}
	    }
	    if (got_file == 0)
		err_exit(ifile->answers[m], group);
	}
    }

    /* read the control points for the group */
    get_control_points(group, order);

    /* get the target */
    get_target(group);

    /* Check the GRASS_OVERWRITE environment variable */
    if ((overstr = getenv("GRASS_OVERWRITE")))  /* OK ? */
	target_overwrite = atoi(overstr);

    if (!target_overwrite) {
	/* check if output exists in target location/mapset */
	char result[GNAME_MAX];
	
	select_target_env();
	for (i = 0; i < ref.nfiles; i++) {
	    if (!ref_list[i])
		continue;

	    strcpy(result, ref.file[i].name);
	    strcat(result, extension);
	    
	    if (G_legal_filename(result) < 0)
		G_fatal_error(_("Extension <%s> is illegal"), extension);
		
	    if (G_find_cell(result, G_mapset())) {
		G_warning(_("The following raster map already exists in"));
		G_warning(_("target LOCATION %s, MAPSET %s:"),
			  G_location(), G_mapset());
		G_warning("<%s>", result);
		G_fatal_error(_("Orthorectification cancelled."));
	    }
	}
	
	select_current_env();
    }
    else
	G_debug(1, "Overwriting OK");

    /* do not use current region in target location */
    if (!c->answer) {
	double res = -1;
	
	if (tres->answer) {
	    if (!((res = atof(tres->answer)) > 0))
		G_warning(_("Target resolution must be > 0, ignored"));
	}
	/* Calculate smallest region */
	if (a->answer) {
	    if (G_get_cellhd(ref.file[0].name, ref.file[0].mapset, &cellhd) <
		0)
		G_fatal_error(_("Unable to read header of raster map <%s>"),
			      ref.file[0].name);
	}
	else {
	    if (G_get_cellhd(ifile->answers[0], ref.file[0].mapset, &cellhd) <
		0)
		G_fatal_error(_("Unable to read header of raster map <%s>"),
			      ifile->answers[0]);
	}
	georef_window(&cellhd, &target_window, order, res);
    }

    G_verbose_message(_("Using region: N=%f S=%f, E=%f W=%f"), target_window.north,
	      target_window.south, target_window.east, target_window.west);

    exec_rectify(order, extension, interpol->answer);

    G_done_msg(" ");

    exit(EXIT_SUCCESS);
}
Exemple #26
0
void extract(DCELL *** img,	/* multispectral image, img[band][i][j] */
	     struct Region *region,	/* region to extract */
	     LIKELIHOOD *** ll,	/* log likelihood, ll[i][j][class] */
	     struct SigSet *S	/* class signatures */
    )
{
    int i, j;			/* column and row indexes */
    int m;			/* class index */
    int k;			/* subclass index */
    int b1, b2;			/* spectral index */
    int no_data;		/* no data flag */
    int max_nsubclasses;	/* maximum number of subclasses */
    int nbands;			/* number of spectral bands */
    double *subll;		/* log likelihood of subclasses */
    double *diff;
    double maxlike = 0.0L;
    double subsum;
    struct ClassSig *C;
    struct SubSig *SubS;

    nbands = S->nbands;

    /* determine the maximum number of subclasses */
    max_nsubclasses = 0;
    for (m = 0; m < S->nclasses; m++)
	if (S->ClassSig[m].nsubclasses > max_nsubclasses)
	    max_nsubclasses = S->ClassSig[m].nsubclasses;

    /* allocate memory */
    diff = (double *)G_malloc(nbands * sizeof(double));
    subll = (double *)G_malloc(max_nsubclasses * sizeof(double));

    /* Compute log likelihood at each pixel and for every class. */

    /* for each pixel */
    for (i = region->ymin; i < region->ymax; i++)
	for (j = region->xmin; j < region->xmax; j++) {

	    /* Check for no data condition */
	    no_data = 1;
	    for (b1 = 0; (b1 < nbands) && no_data; b1++)
		no_data = no_data && (G_is_d_null_value(&img[b1][i][j]));

	    if (no_data) {
		for (m = 0; m < S->nclasses; m++)
		    ll[i][j][m] = 0.0;
	    }
	    else {
		/* for each class */
		for (m = 0; m < S->nclasses; m++) {
		    C = &(S->ClassSig[m]);

		    /* compute log likelihood for each subclass */
		    for (k = 0; k < C->nsubclasses; k++) {
			SubS = &(C->SubSig[k]);
			subll[k] = SubS->cnst;
			for (b1 = 0; b1 < nbands; b1++) {
			    diff[b1] = img[b1][i][j] - SubS->means[b1];
			    subll[k] -=
				0.5 * diff[b1] * diff[b1] *
				SubS->Rinv[b1][b1];
			}
			for (b1 = 0; b1 < nbands; b1++)
			    for (b2 = b1 + 1; b2 < nbands; b2++)
				subll[k] -=
				    diff[b1] * diff[b2] * SubS->Rinv[b1][b2];
		    }

		    /* shortcut for one subclass */
		    if (C->nsubclasses == 1) {
			ll[i][j][m] = subll[0];
		    }
		    /* compute mixture likelihood */
		    else {
			/* find the most likely subclass */
			for (k = 0; k < C->nsubclasses; k++) {
			    if (k == 0)
				maxlike = subll[k];
			    if (subll[k] > maxlike)
				maxlike = subll[k];
			}

			/* Sum weighted subclass likelihoods */
			subsum = 0;
			for (k = 0; k < C->nsubclasses; k++)
			    subsum +=
				exp(subll[k] - maxlike) * C->SubSig[k].pi;

			ll[i][j][m] = log(subsum) + maxlike;
		    }
		}
	    }
	}
    G_free((char *)diff);
    G_free((char *)subll);
}
Exemple #27
0
int main(int argc, char *argv[])
{
    /* Global variable & function declarations */
    char Cellmap_orig[50];
    FILE *realfp, *imagfp;	/* the input and output file descriptors */
    int outputfd, maskfd;	/* the input and output file descriptors */
    char *realmapset, *imagmapset;	/* the input mapset names */
    struct Cell_head orig_wind, realhead;
    CELL *cell_row, *maskbuf = NULL;

    int i, j;			/* Loop control variables */
    int or, oc;			/* Original dimensions of image */
    int rows, cols;		/* Smallest powers of 2 >= number of rows & columns */
    long totsize;		/* Total number of data points */
    int halfrows, halfcols;
    double *data[2];		/* Data structure containing real & complex values of FFT */
    struct Option *op1, *op2, *op3;
    struct GModule *module;

    G_gisinit(argv[0]);

    /* Set description */
    module = G_define_module();
    module->keywords = _("imagery, FFT");
    module->description =
	_("Inverse Fast Fourier Transform (IFFT) for image processing.");

    /* define options */
    op1 = G_define_standard_option(G_OPT_R_INPUT);
    op1->key = "real_image";
    op1->description = _("Name of input raster map (image fft, real part)");

    op2 = G_define_standard_option(G_OPT_R_INPUT);
    op2->key = "imaginary_image";
    op2->description = _("Name of input raster map (image fft, imaginary part");

    op3 = G_define_standard_option(G_OPT_R_OUTPUT);
    op3->key = "output_image";
    op3->description = _("Name for output raster map");

    /*call parser */
    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);

    strcpy(Cellmap_real, op1->answer);
    strcpy(Cellmap_imag, op2->answer);
    strcpy(Cellmap_orig, op3->answer);

    /* open input raster map */
    if ((realmapset = G_find_cell(Cellmap_real, "")) == NULL)
	G_fatal_error(_("Raster map <%s> not found"),
		      Cellmap_real);

    if ((realfp =
	 G_fopen_old_misc("cell_misc", "fftreal", Cellmap_real,
			  realmapset)) == NULL)
	G_fatal_error(_("Unable to open real-image in the 'cell_misc' directory. "
			"Raster map probably wasn't created by i.fft"));

    if ((imagmapset = G_find_cell(Cellmap_imag, "")) == NULL)
	G_fatal_error(_("Raster map <%s> not found"),
		      Cellmap_imag);

    if ((imagfp =
	 G_fopen_old_misc("cell_misc", "fftimag", Cellmap_imag,
			  imagmapset)) == NULL)
	G_fatal_error(_("Unable to open imaginary-image in the 'cell_misc' directory. "
			"Raster map probably wasn't created by i.fft"));

    /* check command line args for validity */
    if (G_legal_filename(Cellmap_orig) < 0)
	G_fatal_error(_("<%s> is an illegal file name"),
		      Cellmap_orig);

    /* get and compare the original window data */
    get_orig_window(&orig_wind, realmapset, imagmapset);

    or = orig_wind.rows;
    oc = orig_wind.cols;
    G_get_cellhd(Cellmap_real, realmapset, &realhead);
    G_set_window(&realhead);	/* set the window to the whole cell map */

    /* get the rows and columns in the current window */
    rows = G_window_rows();
    cols = G_window_cols();
    totsize = rows * cols;
    halfrows = rows / 2;
    halfcols = cols / 2;

    G_verbose_message(_("Power 2 values: %d rows %d columns"), rows, cols);

    /* Allocate appropriate memory for the structure containing
       the real and complex components of the FFT.  DATA[0] will
       contain the real, and DATA[1] the complex component.
     */
    data[0] = (double *)G_malloc((rows * cols) * sizeof(double));
    data[1] = (double *)G_malloc((rows * cols) * sizeof(double));

    /* Initialize real & complex components to zero */
    G_message(_("Reading raster maps..."));
    {
	fread((char *)data[0], sizeof(double), totsize, realfp);
	fread((char *)data[1], sizeof(double), totsize, imagfp);
    }

    /* Read in cell map values */
    G_message(_("Masking raster maps..."));
    maskfd = G_maskfd();
    if (maskfd >= 0)
	maskbuf = G_allocate_cell_buf();

    if (maskfd >= 0) {
	for (i = 0; i < rows; i++) {
	    double *data0, *data1;

	    data0 = data[0] + i * cols;
	    data1 = data[1] + i * cols;
	    G_get_map_row(maskfd, maskbuf, i);
	    for (j = 0; j < cols; j++, data0++, data1++) {
		if (maskbuf[j] == (CELL) 0) {
		    *(data0) = 0.0;
		    *(data1) = 0.0;
		}
	    }
	}
    }

    G_message(_("Rotating data..."));
    /* rotate the data array for standard display */
    for (i = 0; i < rows; i++) {
	double temp;

	for (j = 0; j < halfcols; j++) {
	    temp = *(data[0] + i * cols + j);
	    *(data[0] + i * cols + j) = *(data[0] + i * cols + j + halfcols);
	    *(data[0] + i * cols + j + halfcols) = temp;
	    temp = *(data[1] + i * cols + j);
	    *(data[1] + i * cols + j) = *(data[1] + i * cols + j + halfcols);
	    *(data[1] + i * cols + j + halfcols) = temp;
	}
    }
    for (i = 0; i < halfrows; i++) {
	double temp;

	for (j = 0; j < cols; j++) {
	    temp = *(data[0] + i * cols + j);
	    *(data[0] + i * cols + j) =
		*(data[0] + (i + halfrows) * cols + j);
	    *(data[0] + (i + halfrows) * cols + j) = temp;
	    temp = *(data[1] + i * cols + j);
	    *(data[1] + i * cols + j) =
		*(data[1] + (i + halfrows) * cols + j);
	    *(data[1] + (i + halfrows) * cols + j) = temp;
	}
    }


    /* close input cell maps and release the row buffers */
    fclose(realfp);
    fclose(imagfp);
    if (maskfd >= 0) {
	G_close_cell(maskfd);
	G_free(maskbuf);
    }

    /* perform inverse FFT */
    G_message(_("Starting Inverse FFT..."));
    fft(1, data, totsize, cols, rows);

    /* set up a window for the transform cell map */
    G_set_window(&orig_wind);

    /* open the output cell map and allocate a cell row buffer */
    if ((outputfd = G_open_cell_new(Cellmap_orig)) < 0)
	G_fatal_error(_("Unable to create raster map <%s>"),
		      Cellmap_orig);

    cell_row = G_allocate_cell_buf();

    /* Write out result to a new cell map */
    G_message(_("Writing data..."));
    for (i = 0; i < or; i++) {
	for (j = 0; j < oc; j++) {
	    *(cell_row + j) = (CELL) (*(data[0] + i * cols + j) + 0.5);
	}
	G_put_raster_row(outputfd, cell_row, CELL_TYPE);

	G_percent(i+1, or, 2);
    }
    G_close_cell(outputfd);

    G_free(cell_row);
    {
	struct Colors colors;
	struct Range range;
	CELL min, max;

	/* make a real component color table */
	G_read_range(Cellmap_orig, G_mapset(), &range);
	G_get_range_min_max(&range, &min, &max);
	G_make_grey_scale_colors(&colors, min, max);
	G_write_colors(Cellmap_orig, G_mapset(), &colors);
    }

    /* Release memory resources */
    G_free(data[0]);
    G_free(data[1]);

    G_done_msg(" ");

    exit(EXIT_SUCCESS);
}
Exemple #28
0
/*!
  \brief Load styles for geopoints based on thematic mapping

  \param gp pointer to geosite structure
  \param colors pointer to Colors structure or NULL
  
  \return number of points defined by thematic mapping
  \return -1 on error
*/
int Gp_load_sites_thematic(geosite *gp, struct Colors *colors)
{
    geopoint *gpt;

    struct Map_info Map;
    struct field_info *Fi;
    
    int nvals, cat, npts, nskipped;
    int red, blu, grn;
    const char *str;
    const char *mapset;

    dbDriver *driver;
    dbValue value;
    
    if(!gp || !gp->tstyle || !gp->filename)
	return -1;

    mapset = G_find_vector2(gp->filename, "");
    if (!mapset) {
	G_fatal_error(_("Vector map <%s> not found"), gp->filename);
    }
    
    Vect_set_open_level(1);
    if (Vect_open_old(&Map, gp->filename, "") == -1) {
	G_fatal_error(_("Unable to open vector map <%s>"),
		      G_fully_qualified_name(gp->filename, mapset));
    }
    
    Fi = Vect_get_field(&Map, gp->tstyle->layer);
    if (!Fi) {
	G_warning(_("Database connection not defined for layer %d"),
		  gp->tstyle->layer);
    }
    else {
	driver = db_start_driver_open_database(Fi->driver, Fi->database);
	if (!driver)
	    G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
			  Fi->database, Fi->driver);
    }
    G_message(_("Loading thematic points layer <%s>..."),
	      G_fully_qualified_name(gp->filename, mapset));
    npts = nskipped = 0;
    for(gpt = gp->points; gpt; gpt = gpt->next) {
	gpt->style = (gvstyle *) G_malloc(sizeof(gvstyle));
	G_zero(gpt->style, sizeof(gvstyle));
	
	/* use default style */
	gpt->style->color  = gp->style->color;
	gpt->style->symbol = gp->style->symbol;
	gpt->style->size   = gp->style->size;
	gpt->style->width  = gp->style->width;
	
	cat = -1;
	if (gpt->cats)
	    Vect_cat_get(gpt->cats, gp->tstyle->layer, &cat);
	if (cat < 0) {
	    nskipped++;
	    continue;
	}

	/* color */
	if (colors) {
	    if (!Rast_get_c_color((const CELL *) &cat, &red, &grn, &blu, colors)) {
		G_warning(_("No color rule defined for category %d"), cat);
		gpt->style->color = gp->style->color;
	    }
	    gpt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) +
		((int)((blu) << 16) & BLU_MASK);
	}
	if (gp->tstyle->color_column) {
	    nvals = db_select_value(driver, Fi->table, Fi->key, cat, gp->tstyle->color_column, &value);
	    if (nvals < 1)
		continue;
	    str = db_get_value_string(&value);
	    if (!str)
		continue;
	    if (G_str_to_color(str, &red, &grn, &blu) != 1) {
		G_warning(_("Invalid color definition (%s)"),
			  str);
		gpt->style->color = gp->style->color;
	    }
	    else {
		gpt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) +
		    ((int)((blu) << 16) & BLU_MASK);
	    }
	}
	
	/* size */
	if (gp->tstyle->size_column) {
	    nvals = db_select_value(driver, Fi->table, Fi->key, cat, gp->tstyle->size_column, &value);
	    if (nvals < 1)
		continue;
	    gpt->style->size = db_get_value_int(&value);
	}

	/* width */
	if (gp->tstyle->width_column) {
	    nvals = db_select_value(driver, Fi->table, Fi->key, cat, gp->tstyle->width_column, &value);
	    if (nvals < 1)
		continue;
	    gpt->style->width = db_get_value_int(&value);
	}

	/* symbol/marker */
	if (gp->tstyle->symbol_column) {
	    nvals = db_select_value(driver, Fi->table, Fi->key, cat, gp->tstyle->symbol_column, &value);
	    if (nvals < 1)
		continue;
	    str = db_get_value_string(&value);
	    gpt->style->symbol = GP_str_to_marker(str);
	}
	
	npts++;
    }
    
    if (nskipped > 0)
	G_warning(_("%d points without category. "
		    "Unable to determine color rules for features without category."),
		  nskipped);
    return npts;
}
Exemple #29
0
void allocate_heap(void)
{
    int row;

    G_debug(1, "Allocating memory: elevation");

    /* 3 elevation buffers needed for precomputing aspects */

    el.buf =
	(DCELL **) G_calloc(region.rows + el.row_offset * 2 + 3,
			    sizeof(DCELL *));
    for (row = 0; row < 3; row++)
	el.buf[row] = ((DCELL *) G_calloc(region.cols + el.col_offset * 2,
					  sizeof(DCELL))) + el.row_offset;
    for (row = 3; row <= region.rows + el.row_offset; row++)
	el.buf[row] = parm.seg ? el.buf[row % 3] :
	    ((DCELL *) G_calloc(region.cols + el.col_offset * 2,
				sizeof(DCELL))) + el.row_offset;
    el.buf += el.col_offset;

    if (parm.seg) {
	G_debug(1, "Allocating memory: segment");
	el.seg = (SEGMENT *) G_malloc(sizeof(SEGMENT));
	Segment_init(el.seg, el.sfd, SEGSINMEM);
	as.seg = (SEGMENT *) G_malloc(sizeof(SEGMENT));
	Segment_init(as.seg, as.sfd, SEGSINMEM);
	if (parm.dsout) {
	    ds.seg = (SEGMENT *) G_malloc(sizeof(SEGMENT));
	    Segment_init(ds.seg, ds.sfd, SEGSINMEM);
	}
    }

    if (!parm.mem) {
	G_debug(1, "Allocating memory: aspect");
	as.buf = (DCELL **) G_calloc(region.rows, sizeof(DCELL *));
	as.buf[0] = (DCELL *) Rast_allocate_buf(DCELL_TYPE);
	for (row = 0; row < region.rows; row++)
	    as.buf[row] = parm.seg ?
		as.buf[0] : (DCELL *) Rast_allocate_buf(DCELL_TYPE);
    }

    if (parm.barin) {
	G_debug(1, "Allocating memory: barrier");
	bitbar = BM_create(region.cols, region.rows);
    }

    if (parm.dsout) {
	G_debug(1, "Allocating memory: density");
	ds.buf = (DCELL **) G_calloc(region.rows, sizeof(DCELL *));
	ds.buf[0] = (DCELL *) Rast_allocate_buf(DCELL_TYPE);
	for (row = 0; row < region.rows; row++)
	    ds.buf[row] = parm.seg ?
		ds.buf[0] : (DCELL *) Rast_allocate_buf(DCELL_TYPE);
    }

    if (parm.flout) {
	G_debug(1, "Allocating memory: flowline header");
	Vect_hist_command(&fl);
    }

    G_debug(1, "Allocating memory: e/w distances");
    ew_dist = (double *)G_calloc(region.rows, sizeof(double));

    G_debug(1, "Allocating memory: quantization tolerances");
    epsilon[HORIZ] = (double *)G_calloc(region.rows, sizeof(double));
    epsilon[VERT] = (double *)G_calloc(region.rows, sizeof(double));

    return;
}
Exemple #30
0
int main(int argc, char *argv[])
{
    int i, iopt;
    int operator;
    int aline, nalines, nskipped;
    int ltype, itype[2], ifield[2];
    int **cats, *ncats, nfields, *fields;
    char *mapset[2], *pre[2];
    struct GModule *module;
    struct GParm parm;
    struct GFlag flag;
    struct Map_info In[2], Out;
    struct field_info *IFi, *OFi;
    struct line_pnts *APoints, *BPoints;
    struct line_cats *ACats, *BCats;
    int *ALines;		/* List of lines: 0 do not output, 1 - write to output */
    struct ilist *List, *TmpList, *BoundList;

    G_gisinit(argv[0]);

    pre[0] = "a";
    pre[1] = "b";

    module = G_define_module();
    module->keywords = _("vector, spatial query");
    module->description =
	_("Selects features from vector map (A) by features from other vector map (B).");

    parse_options(&parm, &flag);
    
    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);
    
    if (parm.operator->answer[0] == 'e')
	operator = OP_EQUALS;
    else if (parm.operator->answer[0] == 'd') {
	/* operator = OP_DISJOINT; */
	operator = OP_INTERSECTS;
	flag.reverse->answer = YES;
    }
    else if (parm.operator->answer[0] == 'i')
	operator = OP_INTERSECTS;
    else if (parm.operator->answer[0] == 't')
	operator = OP_TOUCHES;
    else if (parm.operator->answer[0] == 'c' && parm.operator->answer[1] == 'r')
	operator = OP_CROSSES;
    else if (parm.operator->answer[0] == 'w')
	operator = OP_WITHIN;
    else if (parm.operator->answer[0] == 'c' && parm.operator->answer[1] == 'o')
	operator = OP_CONTAINS;
    else if (parm.operator->answer[0] == 'o') {
	if (strcmp(parm.operator->answer, "overlaps") == 0)
	    operator = OP_OVERLAPS;
	else
	    operator = OP_OVERLAP;
    }
    else if (parm.operator->answer[0] == 'r')
	operator = OP_RELATE;
    else
	G_fatal_error(_("Unknown operator"));
    
    if (operator == OP_RELATE && !parm.relate->answer) {
	G_fatal_error(_("Required parameter <%s> not set"),
		      parm.relate->key);
    }
    
    for (iopt = 0; iopt < 2; iopt++) {
	itype[iopt] = Vect_option_to_types(parm.type[iopt]);
	ifield[iopt] = atoi(parm.field[iopt]->answer);

	Vect_check_input_output_name(parm.input[iopt]->answer, parm.output->answer,
				     GV_FATAL_EXIT);

	if ((mapset[iopt] =
	     G_find_vector2(parm.input[iopt]->answer, NULL)) == NULL) {
	    G_fatal_error(_("Vector map <%s> not found"),
			  parm.input[iopt]->answer);
	}
	
	Vect_set_open_level(2);
	Vect_open_old(&(In[iopt]), parm.input[iopt]->answer, mapset[iopt]);
    }
    
    /* Read field info */
    IFi = Vect_get_field(&(In[0]), ifield[0]);

    APoints = Vect_new_line_struct();
    BPoints = Vect_new_line_struct();
    ACats = Vect_new_cats_struct();
    BCats = Vect_new_cats_struct();
    List = Vect_new_list();
    TmpList = Vect_new_list();
    BoundList = Vect_new_list();

    /* Open output */
    Vect_open_new(&Out, parm.output->answer, Vect_is_3d(&(In[0])));
    Vect_set_map_name(&Out, _("Output from v.select"));
    Vect_set_person(&Out, G_whoami());
    Vect_copy_head_data(&(In[0]), &Out);
    Vect_hist_copy(&(In[0]), &Out);
    Vect_hist_command(&Out);

    nskipped = 0;
    nalines = Vect_get_num_lines(&(In[0]));

#ifdef HAVE_GEOS
    initGEOS(G_message, G_fatal_error);
    GEOSGeometry *AGeom = NULL;
#else
    void *AGeom = NULL;
#endif

    /* Alloc space for input lines array */
    ALines = (int *)G_calloc(nalines + 1, sizeof(int));

    G_message(_("Building spatial index..."));
    Vect_build_spatial_index(&In[0]);
    Vect_build_spatial_index(&In[1]);
    
    /* Lines in A. Go through all lines and mark those that meets condition */
    if (itype[0] & (GV_POINTS | GV_LINES)) {
	G_message(_("Processing features..."));
	
	for (aline = 1; aline <= nalines; aline++) {
	    BOUND_BOX abox;

	    G_debug(3, "aline = %d", aline);
	    G_percent(aline, nalines, 2);	/* must be before any continue */

	    /* Check category */
	    if (!flag.cat->answer && Vect_get_line_cat(&(In[0]), aline, ifield[0]) < 0) {
		nskipped++;
		continue;
	    }

	    /* Read line and check type */
	    if (operator != OP_OVERLAP) {
#ifdef HAVE_GEOS
		AGeom = Vect_read_line_geos(&(In[0]), aline, &ltype);
#endif
		if (!(ltype & (GV_POINT | GV_LINE)))
		    continue;

		if (!AGeom)
		    G_fatal_error(_("Unable to read line id %d from vector map <%s>"),
				  aline, Vect_get_full_name(&(In[0])));
	    }
	    else {
		ltype = Vect_read_line(&(In[0]), APoints, NULL, aline);
	    }
	    
	    if (!(ltype & itype[0]))
		continue;
	    
	    Vect_get_line_box(&(In[0]), aline, &abox);
	    abox.T = PORT_DOUBLE_MAX;
	    abox.B = -PORT_DOUBLE_MAX;

	    /* Check if this line overlaps any feature in B */
	    /* x Lines in B */
	    if (itype[1] & (GV_POINTS | GV_LINES)) {
		int i;
		int found = 0;
		
		/* Lines */
		Vect_select_lines_by_box(&(In[1]), &abox, itype[1], List);
		for (i = 0; i < List->n_values; i++) {
		    int bline;
		    
		    bline = List->value[i];
		    G_debug(3, "  bline = %d", bline);
		    
		    /* Check category */
		    if (!flag.cat->answer && Vect_get_line_cat(&(In[1]), bline, ifield[1]) < 0) {
			nskipped++;
			continue;
		    }
		    
		    if (operator != OP_OVERLAP) {
#ifdef HAVE_GEOS
			if(line_relate_geos(&(In[1]), AGeom,
					    bline, operator, parm.relate->answer)) {

			    found = 1;
			    break;
			}
#endif
		    }
		    else {
			Vect_read_line(&(In[1]), BPoints, NULL, bline);

			if (Vect_line_check_intersection(APoints, BPoints, 0)) {
			    found = 1;
			    break;
			}
		    }
		}
		
		if (found) {
		    ALines[aline] = 1;
		    continue;	/* Go to next A line */
		}
	    }
	    
	    /* x Areas in B. */
	    if (itype[1] & GV_AREA) {
		int i;
		
		Vect_select_areas_by_box(&(In[1]), &abox, List);
		for (i = 0; i < List->n_values; i++) {
		    int barea;
		    
		    barea = List->value[i];
		    G_debug(3, "  barea = %d", barea);
		    
		    if (Vect_get_area_cat(&(In[1]), barea, ifield[1]) < 0) {
			nskipped++;
			continue;
		    }

		    if (operator != OP_OVERLAP) {
#ifdef HAVE_GEOS
			if(area_relate_geos(&(In[1]), AGeom,
					    barea, operator, parm.relate->answer)) {
			    ALines[aline] = 1;
			    break;
			}
#endif
		    }
		    else {
			if (line_overlap_area(&(In[0]), aline, &(In[1]), barea)) {
			    ALines[aline] = 1;
			    break;
			}
		    }
		}
	    }
	    if (operator != OP_OVERLAP) {
#ifdef HAVE_GEOS
		GEOSGeom_destroy(AGeom);
#endif
		AGeom = NULL;
	    }
	}
    }
    
    /* Areas in A. */
    if (itype[0] & GV_AREA) {
	int aarea, naareas;

	G_message(_("Processing areas..."));
	
	naareas = Vect_get_num_areas(&(In[0]));

	for (aarea = 1; aarea <= naareas; aarea++) {
	    BOUND_BOX abox;

	    G_percent(aarea, naareas, 2);	/* must be before any continue */

	    if (Vect_get_area_cat(&(In[0]), aarea, ifield[0]) < 0) {
		nskipped++;
		continue;
	    }
	
	    Vect_get_area_box(&(In[0]), aarea, &abox);
	    abox.T = PORT_DOUBLE_MAX;
	    abox.B = -PORT_DOUBLE_MAX;

	    if (operator != OP_OVERLAP) {
#ifdef HAVE_GEOS
		AGeom = Vect_read_area_geos(&(In[0]), aarea);
#endif
		if (!AGeom)
		    G_fatal_error(_("Unable to read area id %d from vector map <%s>"),
				  aline, Vect_get_full_name(&(In[0])));
	    }

	    /* x Lines in B */
	    if (itype[1] & (GV_POINTS | GV_LINES)) {
		Vect_select_lines_by_box(&(In[1]), &abox, itype[1], List);

		for (i = 0; i < List->n_values; i++) {
		    int bline;

		    bline = List->value[i];

		    if (!flag.cat->answer && Vect_get_line_cat(&(In[1]), bline, ifield[1]) < 0) {
			nskipped++;
			continue;
		    }
		    
		    if (operator != OP_OVERLAP) {
#ifdef HAVE_GEOS
			if(line_relate_geos(&(In[1]), AGeom,
					    bline, operator, parm.relate->answer)) {
			    add_aarea(&(In[0]), aarea, ALines);
			    break;
			}
#endif
		    }
		    else {
			if (line_overlap_area(&(In[1]), bline, &(In[0]), aarea)) {
			    add_aarea(&(In[0]), aarea, ALines);
			    continue;
			}
		    }
		}
	    }

	    /* x Areas in B */
	    if (itype[1] & GV_AREA) {
		int naisles;
		int found = 0;

		/* List of areas B */

		/* Make a list of features forming area A */
		Vect_reset_list(List);

		Vect_get_area_boundaries(&(In[0]), aarea, BoundList);
		for (i = 0; i < BoundList->n_values; i++) {
		    Vect_list_append(List, abs(BoundList->value[i]));
		}

		naisles = Vect_get_area_num_isles(&(In[0]), aarea);

		for (i = 0; i < naisles; i++) {
		    int j, aisle;

		    aisle = Vect_get_area_isle(&(In[0]), aarea, i);

		    Vect_get_isle_boundaries(&(In[0]), aisle, BoundList);
		    for (j = 0; j < BoundList->n_values; j++) {
			Vect_list_append(List, BoundList->value[j]);
		    }
		}

		Vect_select_areas_by_box(&(In[1]), &abox, TmpList);

		for (i = 0; i < List->n_values; i++) {
		    int j, aline;

		    aline = abs(List->value[i]);

		    for (j = 0; j < TmpList->n_values; j++) {
			int barea, bcentroid;

			barea = TmpList->value[j];
			G_debug(3, "  barea = %d", barea);

			if (Vect_get_area_cat(&(In[1]), barea, ifield[1]) < 0) {
			    nskipped++;
			    continue;
			}

			/* Check if any centroid of area B is in area A.
			 * This test is important in if area B is completely within area A */
			bcentroid = Vect_get_area_centroid(&(In[1]), barea);
			Vect_read_line(&(In[1]), BPoints, NULL, bcentroid);

			if (operator != OP_OVERLAP) {
#ifdef HAVE_GEOS
			    if(area_relate_geos(&(In[1]), AGeom,
						barea, operator, parm.relate->answer)) {
				found = 1;
				break;
			    }
#endif
			}
			else {
			    if (Vect_point_in_area(&(In[0]), aarea,
						   BPoints->x[0], BPoints->y[0])) {
				found = 1;
				break;
			    }
			    
			    /* Check intersectin of lines from List with area B */
			    if (line_overlap_area(&(In[0]), aline,
						  &(In[1]), barea)) {
				found = 1;
				break;
			    }
			}
		    }
		    if (found) {
			add_aarea(&(In[0]), aarea, ALines);
			break;
		    }
		}
	    }
	    if (operator != OP_OVERLAP) {
#ifdef HAVE_GEOS
		GEOSGeom_destroy(AGeom);
#endif
		AGeom = NULL;
	    }
	}
    }
    
    Vect_close(&(In[1]));

#ifdef HAVE_GEOS
    finishGEOS();
#endif

    /* Write lines */
    nfields = Vect_cidx_get_num_fields(&(In[0]));
    cats = (int **)G_malloc(nfields * sizeof(int *));
    ncats = (int *)G_malloc(nfields * sizeof(int));
    fields = (int *)G_malloc(nfields * sizeof(int));
    for (i = 0; i < nfields; i++) {
	ncats[i] = 0;
	cats[i] =
	    (int *)G_malloc(Vect_cidx_get_num_cats_by_index(&(In[0]), i) *
			    sizeof(int));
	fields[i] = Vect_cidx_get_field_number(&(In[0]), i);
    }

    G_message(_("Writing selected features..."));
    for (aline = 1; aline <= nalines; aline++) {
	int atype;

	G_debug(4, "aline = %d ALines[aline] = %d", aline, ALines[aline]);
	G_percent(aline, nalines, 2);
	
	if ((!flag.reverse->answer && !(ALines[aline])) ||
	    (flag.reverse->answer && ALines[aline]))
	    continue;

	atype = Vect_read_line(&(In[0]), APoints, ACats, aline);
	Vect_write_line(&Out, atype, APoints, ACats);

	if (!(flag.table->answer) && (IFi != NULL)) {
	    for (i = 0; i < ACats->n_cats; i++) {
		int f, j;

		for (j = 0; j < nfields; j++) {	/* find field */
		    if (fields[j] == ACats->field[i]) {
			f = j;
			break;
		    }
		}
		cats[f][ncats[f]] = ACats->cat[i];
		ncats[f]++;
	    }
	}
    }

    /* Copy tables */
    if (!(flag.table->answer)) {
	int ttype, ntabs = 0;

	G_message(_("Writing attributes..."));

	/* Number of output tabs */
	for (i = 0; i < Vect_get_num_dblinks(&(In[0])); i++) {
	    int f, j;

	    IFi = Vect_get_dblink(&(In[0]), i);

	    for (j = 0; j < nfields; j++) {	/* find field */
		if (fields[j] == IFi->number) {
		    f = j;
		    break;
		}
	    }
	    if (ncats[f] > 0)
		ntabs++;
	}

	if (ntabs > 1)
	    ttype = GV_MTABLE;
	else
	    ttype = GV_1TABLE;

	for (i = 0; i < nfields; i++) {
	    int ret;

	    if (fields[i] == 0)
		continue;

	    /* Make a list of categories */
	    IFi = Vect_get_field(&(In[0]), fields[i]);
	    if (!IFi) {		/* no table */
		G_warning(_("Layer %d - no table"), fields[i]);
		continue;
	    }

	    OFi =
		Vect_default_field_info(&Out, IFi->number, IFi->name, ttype);

	    ret =
		db_copy_table_by_ints(IFi->driver, IFi->database, IFi->table,
				      OFi->driver,
				      Vect_subst_var(OFi->database, &Out),
				      OFi->table, IFi->key, cats[i],
				      ncats[i]);

	    if (ret == DB_FAILED) {
		G_warning(_("Layer %d - unable to copy table"), fields[i]);
	    }
	    else {
		Vect_map_add_dblink(&Out, OFi->number, OFi->name, OFi->table,
				    IFi->key, OFi->database, OFi->driver);
	    }
	}
    }

    Vect_close(&(In[0]));

    Vect_build(&Out);
    Vect_close(&Out);

    if (nskipped > 0) {
      G_warning(_("%d features without category skipped"), nskipped);
    }

    G_done_msg(_("%d features written to output."), Vect_get_num_lines(&Out));

    exit(EXIT_SUCCESS);
}