Exemple #1
0
/*!
  \brief Get area boundary points (native format)
  
  Used by Vect_build_line_area() and Vect_get_area_points().
  
  \param Map pointer to Map_info struct
  \param lines array of boundary lines
  \param n_lines number of lines in array
  \param[out] APoints pointer to output line_pnts struct

  \return number of points
  \return -1 on error
*/
int Vect__get_area_points_nat(const struct Map_info *Map, const plus_t *lines, int n_lines,
                              struct line_pnts *BPoints)
{
    int i, line, aline, dir;
    static struct line_pnts *Points;
    
    if (!Points)
        Points = Vect_new_line_struct();
    
    Vect_reset_line(BPoints);
    for (i = 0; i < n_lines; i++) {
        line = lines[i];
        aline = abs(line);
        G_debug(5, "  append line(%d) = %d", i, line);
        
        if (0 > Vect_read_line(Map, Points, NULL, aline))
            return -1;
        
        dir = line > 0 ? GV_FORWARD : GV_BACKWARD;
        Vect_append_points(BPoints, Points, dir);
        BPoints->n_points--;    /* skip last point, avoids duplicates */
    }
    BPoints->n_points++;        /* close polygon */

    return BPoints->n_points;
}
Exemple #2
0
/*!
  \brief Get area boundary points (PostGIS Topology)
  
  Used by Vect_build_line_area() and Vect_get_area_points().

  \param Map pointer to Map_info struct
  \param lines array of boundary lines
  \param n_lines number of lines in array
  \param[out] APoints pointer to output line_pnts struct

  \return number of points
  \return -1 on error
*/
int Vect__get_area_points_pg(const struct Map_info *Map, const plus_t *lines, int n_lines,
                             struct line_pnts *APoints)
{
    int i, direction;
    
    struct Format_info_pg *pg_info;
    
    PGresult *res;
    
    pg_info = (struct Format_info_pg *)&(Map->fInfo.pg);
   
    Vect_reset_line(APoints);

    res = build_stmt(&(Map->plus), pg_info, lines, n_lines);
    if (!res)
        return -1;
    
    for (i = 0; i < n_lines; i++) {
        Vect__cache_feature_pg(PQgetvalue(res, i, 0), FALSE, FALSE,
                               &(pg_info->cache), NULL); /* do caching in readable way */
	direction = lines[i] > 0 ? GV_FORWARD : GV_BACKWARD;
	Vect_append_points(APoints, pg_info->cache.lines[0], direction);
	APoints->n_points--;	/* skip last point, avoids duplicates */
    }
    APoints->n_points++;	/* close polygon */

    PQclear(res);
    
    return APoints->n_points;
}
Exemple #3
0
/*!
   \brief Returns polygon array of points for given isle

   \param Map pointer to Map_info structure
   \param isle island id
   \param[out] BPoints points array

   \return number of points
   \return -1 on error
 */
int Vect_get_isle_points(const struct Map_info *Map,
                         int isle, struct line_pnts *BPoints)
{
    const struct Plus_head *Plus;
    struct P_isle *Isle;

    G_debug(3, "Vect_get_isle_points(): isle = %d", isle);
    Vect_reset_line(BPoints);

    Plus = &(Map->plus);
    Isle = Plus->Isle[isle];
    
    if (Isle == NULL) {		/* dead isle */
	G_warning(_("Attempt to read points of nonexistent isle"));
	return -1;		/* error, because we should not read dead isles */
    }

    G_debug(3, "  n_lines = %d", Isle->n_lines);

    if (Map->format == GV_FORMAT_POSTGIS &&
        Map->fInfo.pg.toposchema_name &&
        Map->fInfo.pg.cache.ctype != CACHE_MAP) {
#ifdef HAVE_POSTGRES
        /* PostGIS Topology */
        return Vect__get_area_points_pg(Map, Isle->lines, Isle->n_lines, BPoints);
#else
        G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
#endif
    }
    /* native format */
    return Vect__get_area_points_nat(Map, Isle->lines, Isle->n_lines, BPoints);
}
Exemple #4
0
void write_point(struct Map_info *Out, double x, double y, double z,
		 int line_cat, double along, int table)
{
    char buf[2000];

    G_debug(3, "write_point()");

    Vect_reset_line(PPoints);
    Vect_reset_cats(PCats);

    /* Write point */
    Vect_append_point(PPoints, x, y, z);
    Vect_cat_set(PCats, 1, line_cat);
    Vect_cat_set(PCats, 2, point_cat);
    Vect_write_line(Out, GV_POINT, PPoints, PCats);

    /* Attributes */
    if (!table) {
	db_zero_string(&stmt);
	sprintf(buf, "insert into %s values ( %d, %d, %.15g )", Fi->table,
		point_cat, line_cat, along);
	db_append_string(&stmt, buf);

	if (db_execute_immediate(driver, &stmt) != DB_OK) {
	    G_warning(_("Unable to insert new record: '%s'"),
		      db_get_string(&stmt));
	}
    }
    point_cat++;
}
Exemple #5
0
void writePolyline( struct Map_info* map, int type, QgsPolyline polyline, struct line_cats *cats )
{
  Vect_reset_line( line );
  foreach ( QgsPoint point, polyline )
  {
    Vect_append_point( line, point.x(), point.y(), 0 );
  }
Exemple #6
0
static int ring2pts(const GEOSGeometry *geom, struct line_pnts *Points)
{
    int i, ncoords;
    double x, y, z;
    const GEOSCoordSequence *seq = NULL;

    G_debug(3, "ring2pts()");

    Vect_reset_line(Points);
    if (!geom) {
	G_warning(_("Invalid GEOS geometry!"));
	return 0;
    }
    z = 0.0;
    ncoords = GEOSGetNumCoordinates(geom);
    if (!ncoords) {
	G_warning(_("No coordinates in GEOS geometry (can be ok for negative distance)!"));
	return 0;
    }
    seq = GEOSGeom_getCoordSeq(geom);
    for (i = 0; i < ncoords; i++) {
	GEOSCoordSeq_getX(seq, i, &x);
	GEOSCoordSeq_getY(seq, i, &y);
	if (x != x || x > DBL_MAX || x < -DBL_MAX)
	    G_fatal_error(_("Invalid x coordinate %f"), x);
	if (y != y || y > DBL_MAX || y < -DBL_MAX)
	    G_fatal_error(_("Invalid y coordinate %f"), y);
	Vect_append_point(Points, x, y, z);
    }

    return 1;
}
Exemple #7
0
/* Writes a site to file open on fptr. */
int G_site_put(struct Map_info *Map, const Site * s)
{
    static struct line_pnts *Points = NULL;
    static struct line_cats *Cats = NULL;

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

    Vect_reset_line(Points);
    Vect_reset_cats(Cats);

    /* no 3D support so far: s->dim[0] */
    Vect_append_point(Points, s->east, s->north, 0.0);

    G_debug(4, "cattype = %d", s->cattype);

    if (s->cattype == FCELL_TYPE || s->cattype == DCELL_TYPE)
	G_fatal_error(_("Category must be integer"));

    if (s->cattype == CELL_TYPE)
	Vect_cat_set(Cats, 1, s->ccat);

    Vect_write_line(Map, GV_POINT, Points, Cats);

    return 0;
}
void QgsGrassEditAddVertex::mouseMove( QgsPoint & newPoint )
{
  if ( e->mSelectedLine > 0 )
  {
    Vect_reset_line( e->mPoints );
    if ( e->mAddVertexEnd )
    {
      Vect_append_point( e->mPoints, e->mEditPoints->x[e->mSelectedPart],
                         e->mEditPoints->y[e->mSelectedPart], 0.0 );
      Vect_append_point( e->mPoints, newPoint.x(), newPoint.y(), 0.0 );
    }
    else
    {
      Vect_append_point( e->mPoints, e->mEditPoints->x[e->mSelectedPart-1],
                         e->mEditPoints->y[e->mSelectedPart-1], 0.0 );
      Vect_append_point( e->mPoints, newPoint.x(), newPoint.y(), 0.0 );
      Vect_append_point( e->mPoints, e->mEditPoints->x[e->mSelectedPart],
                         e->mEditPoints->y[e->mSelectedPart], 0.0 );
    }
    for ( int i = 0; i < e->mPoints->n_points; i++ )
    {
      QgsDebugMsg( QString( "%1 %2" ).arg( e->mPoints->x[i] ).arg( e->mPoints->y[i] ) );
    }

    e->displayDynamic( e->mPoints );
  }
}
Exemple #9
0
void writePolyline( struct Map_info* map, int type, const QgsPolyline& polyline, struct line_cats *cats )
{
  Vect_reset_line( line );
  Q_FOREACH ( const QgsPoint& point, polyline )
  {
    Vect_append_point( line, point.x(), point.y(), 0 );
  }
Exemple #10
0
int
pie(double cx, double cy, int size, double *val, int ncols, COLOR * ocolor,
    COLOR * colors)
{
    int i, j, n;
    double a, end_ang, ang, tot_sum, sum, step, r;
    double x, y;
    struct line_pnts *Points;

    G_debug(4, "pie(): cx = %f cy = %f", cx, cy);

    Points = Vect_new_line_struct();

    /* Calc sum */
    tot_sum = 0;
    for (i = 0; i < ncols; i++)
	tot_sum += val[i];

    step = PI / 180;
    r = (D_d_to_u_col(2) - D_d_to_u_col(1)) * size / 2;	/* do it better */
    /* Draw polygon for each value */
    sum = 0;
    ang = 0;
    for (i = 0; i < ncols; i++) {
	sum += val[i];
	end_ang = 2 * PI * sum / tot_sum;
	Vect_reset_line(Points);

	if (val[0] != tot_sum)	/* all in one slice, don't draw line to center */
	    Vect_append_point(Points, cx, cy, 0);

	n = (int)ceil((end_ang - ang) / step);
	for (j = 0, a = ang; j <= n; j++, a += step) {
	    if (a > end_ang)
		a = end_ang;
	    x = cx + r * cos(a);
	    y = cy + r * sin(a);
	    Vect_append_point(Points, x, y, 0);
	}
	ang = end_ang;

	if (val[0] != tot_sum)
	    Vect_append_point(Points, cx, cy, 0);

	if (!colors[i].none) {
	    D_RGB_color(colors[i].r, colors[i].g, colors[i].b);
	    D_polygon_abs(Points->x, Points->y, Points->n_points);
	}

	D_RGB_color(ocolor->r, ocolor->g, ocolor->b);
	D_polyline_abs(Points->x, Points->y, Points->n_points);
    }

    Vect_destroy_line_struct(Points);

    return 0;
}
Exemple #11
0
/*!
  \brief Read feature from OGR layer at given offset (level 1)
  
  This function implements random access on level 1.

  \param Map pointer to Map_info structure 
  \param[out] line_p container used to store line points within
  \param[out] line_c container used to store line categories within
  \param offset given offset 
  
  \return line type
  \return 0 dead line
  \return -2 no more features
  \return -1 out of memory
*/
int V1_read_line_ogr(struct Map_info *Map,
		     struct line_pnts *line_p, struct line_cats *line_c, off_t offset)
{
    long FID;
    int type;
    OGRGeometryH hGeom;

    G_debug(4, "V1_read_line_ogr() offset = %lu offset_num = %lu",
	    (long) offset, (long) Map->fInfo.ogr.offset_num);

    if (offset >= Map->fInfo.ogr.offset_num)
	return -2;
    
    if (line_p != NULL)
	Vect_reset_line(line_p);
    if (line_c != NULL)
	Vect_reset_cats(line_c);

    FID = Map->fInfo.ogr.offset[offset];
    G_debug(4, "  FID = %ld", FID);
    
    /* coordinates */
    if (line_p != NULL) {
	/* Read feature to cache if necessary */
	if (Map->fInfo.ogr.feature_cache_id != FID) {
	    G_debug(4, "Read feature (FID = %ld) to cache", FID);
	    if (Map->fInfo.ogr.feature_cache) {
		OGR_F_Destroy(Map->fInfo.ogr.feature_cache);
	    }
	    Map->fInfo.ogr.feature_cache =
		OGR_L_GetFeature(Map->fInfo.ogr.layer, FID);
	    if (Map->fInfo.ogr.feature_cache == NULL) {
		G_fatal_error(_("Unable to get feature geometry, FID %ld"),
			      FID);
	    }
	    Map->fInfo.ogr.feature_cache_id = FID;
	}
	
	hGeom = OGR_F_GetGeometryRef(Map->fInfo.ogr.feature_cache);
	if (hGeom == NULL) {
	    G_fatal_error(_("Unable to get feature geometry, FID %ld"),
			  FID);
	}
	
	type = read_line(Map, hGeom, offset + 1, line_p);
    }
    else {
	type = get_line_type(Map, FID);
    }

    /* category */
    if (line_c != NULL) {
	Vect_cat_set(line_c, 1, (int) FID);
    }

    return type;
}
void QgsGrassEditNewLine::mouseMove( QgsPoint & newPoint )
{
  if ( e->mEditPoints->n_points > 0 )
  {
    // Draw the line with new segment
    Vect_reset_line( e->mPoints );
    Vect_append_points( e->mPoints, e->mEditPoints, GV_FORWARD );
    Vect_append_point( e->mPoints, newPoint.x(), newPoint.y(), 0.0 );
    e->displayDynamic( e->mPoints );
  }
}
Exemple #13
0
/*!
   \brief Writes point

   Writes GV_POINT to Out at the position of the node in <em>In</em>.

   \param In pointer to Map_info structure (input vector map)
   \param[in,out] Out pointer to Map_info structure (output vector map)
   \param node node id
   \param Cats pointer to line_cats structures
 */
void NetA_add_point_on_node(struct Map_info *In, struct Map_info *Out,
			    int node, struct line_cats *Cats)
{
    static struct line_pnts *Points;
    double x, y, z;

    Points = Vect_new_line_struct();
    Vect_get_node_coor(In, node, &x, &y, &z);
    Vect_reset_line(Points);
    Vect_append_point(Points, x, y, z);
    Vect_write_line(Out, GV_POINT, Points, Cats);
    Vect_destroy_line_struct(Points);
}
void QgsGrassEditNewLine::deactivate()
{
  // Delete last segment
  if ( e->mEditPoints->n_points > 1 )
  {
    Vect_reset_line( e->mPoints );
    Vect_append_points( e->mPoints, e->mEditPoints, GV_FORWARD );
    e->displayDynamic( e->mPoints );
  }
  e->setCanvasPrompt( tr( "New vertex" ), "", "" );

  QgsGrassEditTool::deactivate(); // call default bahivour
}
Exemple #15
0
/*!
  \brief Reads feature from OGR layer (topology level)
 
  This function implements random access on level 2.
  
  \param Map pointer to Map_info structure
  \param[out] line_p container used to store line points within
  \param[out] line_c container used to store line categories within
  \param line feature id
  
  \return feature type
  \return -2 no more features
  \return -1 out of memory
*/
int V2_read_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
		     struct line_cats *line_c, int line)
{
    struct P_line *Line;
    G_debug(4, "V2_read_line_ogr() line = %d", line);
    
    Line = Map->plus.Line[line];
    
    if (Line == NULL)
	G_fatal_error(_("Attempt to read dead feature %d"), line);

    if (Line->type == GV_CENTROID) {
	G_debug(4, "Centroid");
	
	if (line_p != NULL) {
	    int i, found;
	    struct bound_box box;
	    struct boxlist list;
	    struct P_topo_c *topo = (struct P_topo_c *)Line->topo;
	    
	    /* get area bbox */
	    Vect_get_area_box(Map, topo->area, &box);
	    /* search in spatial index for centroid with area bbox */
	    dig_init_boxlist(&list, 1);
	    Vect_select_lines_by_box(Map, &box, Line->type, &list);
	    
	    found = 0;
	    for (i = 0; i < list.n_values; i++) {
		if (list.id[i] == line) {
		    found = i;
		    break;
		}
	    }

	    Vect_reset_line(line_p);
	    Vect_append_point(line_p, list.box[found].E, list.box[found].N, 0.0);
	}

	if (line_c != NULL) {
	  /* cat = FID and offset = FID for centroid */
	  Vect_reset_cats(line_c);
	  Vect_cat_set(line_c, 1, (int) Line->offset);
	}
	
	return GV_CENTROID;
    }
    
    return V1_read_line_ogr(Map, line_p, line_c, Line->offset);
}
Exemple #16
0
/*!
  \brief Create line segment.
  
  Creates segment of InPoints from start to end measured along the
  line and write it to OutPoints.
  
  If the distance is greater than line length or negative, error is
  returned.
  
  \param InPoints input line
  \param start segment number
  \param end segment number
  \param OutPoints output line
  
  \return 1 success
  \return 0 error when start > length or end < 0 or start < 0 or end > length
*/
int Vect_line_segment(const struct line_pnts *InPoints, double start, double end,
		      struct line_pnts *OutPoints)
{
    int i, seg1, seg2;
    double length, tmp;
    double x1, y1, z1, x2, y2, z2;

    G_debug(3, "Vect_line_segment(): start = %f, end = %f, n_points = %d",
	    start, end, InPoints->n_points);

    Vect_reset_line(OutPoints);

    if (start > end) {
	tmp = start;
	start = end;
	end = tmp;
    }

    /* Check start/end */
    if (end < 0)
	return 0;
    length = Vect_line_length(InPoints);
    if (start > length)
	return 0;

    /* Find coordinates and segments of start/end */
    seg1 = Vect_point_on_line(InPoints, start, &x1, &y1, &z1, NULL, NULL);
    seg2 = Vect_point_on_line(InPoints, end, &x2, &y2, &z2, NULL, NULL);

    G_debug(3, "  -> seg1 = %d seg2 = %d", seg1, seg2);

    if (seg1 == 0 || seg2 == 0) {
	G_warning(_("Segment outside line, no segment created"));
	return 0;
    }

    Vect_append_point(OutPoints, x1, y1, z1);

    for (i = seg1; i < seg2; i++) {
	Vect_append_point(OutPoints, InPoints->x[i], InPoints->y[i],
			  InPoints->z[i]);
    };

    Vect_append_point(OutPoints, x2, y2, z2);
    Vect_line_prune(OutPoints);

    return 1;
}
void QgsGrassEditNewLine::activate()
{
  QgsDebugMsg( "entered." );

  // Display dynamic segment
  if ( e->mEditPoints->n_points > 0 )
  {
    Vect_reset_line( e->mPoints );
    Vect_append_points( e->mPoints, e->mEditPoints, GV_FORWARD );
    QgsPoint point = toMapCoordinates( e->mCanvas->mouseLastXY() );
    Vect_append_point( e->mPoints, point.x(), point.y(), 0.0 );
    e->displayDynamic( e->mPoints );
  }

  QgsGrassEditTool::activate(); // call default bahivour
}
void QgsGrassEditMoveLine::mouseMove( QgsPoint & newPoint )
{
  // Move previously selected line
  if ( e->mSelectedLine > 0 )
  {
    // Transform coordinates
    Vect_reset_line( e->mPoints );
    Vect_append_points( e->mPoints, e->mEditPoints, GV_FORWARD );

    for ( int i = 0; i < e->mPoints->n_points; i++ )
    {
      e->mPoints->x[i] += newPoint.x() - e->mLastPoint.x();
      e->mPoints->y[i] += newPoint.y() - e->mLastPoint.y();
    }

    e->displayDynamic( e->mPoints );
  }
}
Exemple #19
0
/*!
   \brief Returns polygon array of points (outer ring) of given area

   \param Map pointer to Map_info structure
   \param area area id
   \param[out] BPoints points array

   \return number of points
   \return -1 on error
 */
int Vect_get_area_points(const struct Map_info *Map,
			 int area, struct line_pnts *BPoints)
{
    const struct Plus_head *Plus;
    struct P_area *Area;

    G_debug(3, "Vect_get_area_points(): area = %d", area);
    Vect_reset_line(BPoints);

    Plus = &(Map->plus);
    Area = Plus->Area[area];

    if (Area == NULL) {		/* dead area */
	G_warning(_("Attempt to read points of nonexistent area"));
	return -1;		/* error, because we should not read dead areas */
    }

    G_debug(3, "  n_lines = %d", Area->n_lines);
    return Vect__get_area_points(Map, Area->lines, Area->n_lines, BPoints);
}
Exemple #20
0
/* writes binary and ASCII digit files and supplemental file */
static int write_bnd(struct COOR *line_begin, struct COOR *line_end,	/* start and end point of line */
		     int n	/* number of points to write */
    )
{
    static struct line_pnts *points = NULL;
    double x;
    double y;
    struct COOR *p, *last;
    int i;

    if (!points)
	points = Vect_new_line_struct();
    Vect_reset_line(points);

    p = line_begin;
    y = cell_head.north - (double)p->row * cell_head.ns_res;
    x = cell_head.west + (double)p->col * cell_head.ew_res;

    Vect_append_point(points, x, y, 0.0);

    for (i = 0; i < n; i++) {
	last = p;

	/* this should NEVER happen */
	if ((p = move(p)) == NULPTR)
	    G_fatal_error(_("write_bnd:  line terminated unexpectedly\n"
			    "previous (%d) point %p (%d,%d,%d) %p %p"),
			  direction, last, last->row, last->col, last->node,
			  last->fptr, last->bptr);

	y = cell_head.north - p->row * cell_head.ns_res;
	x = cell_head.west + p->col * cell_head.ew_res;

	Vect_append_point(points, x, y, 0.0);
    }

    Vect_write_line(&Map, GV_BOUNDARY, points, Cats);

    return 0;
}
Exemple #21
0
int point_save(double xmm, double ymm, double zmm, double err)




/*
   c  saves point deviations
   c
 */
{
    int cat;

    Vect_reset_line(Pnts);
    Vect_reset_cats(Cats);

    Vect_append_point(Pnts, xmm, ymm, zmm);
    cat = count;
    Vect_cat_set(Cats, 1, cat);
    Vect_write_line(&Map, GV_POINT, Pnts, Cats);

    db_zero_string(&sql);
    sprintf(buf, "insert into %s values ( %d ", f->table, cat);
    db_append_string(&sql, buf);

    sprintf(buf, ", %f", err);
    db_append_string(&sql, buf);
    db_append_string(&sql, ")");
    G_debug(3, "%s", db_get_string(&sql));

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

    return 1;
}
void QgsGrassEditNewPoint::mouseClick( QgsPoint & point, Qt::MouseButton button )
{
  if ( button != Qt::LeftButton )
    return;

  Vect_reset_line( e->mEditPoints );
  e->snap( point );
  Vect_append_point( e->mEditPoints, point.x(), point.y(), 0.0 );

  int type;
  if ( mNewCentroid ) // new centroid or point ?
    type = GV_CENTROID;
  else
    type = GV_POINT;

  int line;
  line = e->writeLine( type, e->mEditPoints );
  e->updateSymb();
  e->displayUpdated();

  if ( e->mAttributes )
  {
    e->mAttributes->setLine( line );
    e->mAttributes->clear();
  }
  else
  {
    e->mAttributes = new QgsGrassAttributes( e, e->mProvider, line, e->mIface->mainWindow() );
  }
  for ( int i = 0; i < e->mCats->n_cats; i++ )
  {
    e->addAttributes( e->mCats->field[i], e->mCats->cat[i] );
  }
  e->mAttributes->show();
  e->mAttributes->raise();
}
Exemple #23
0
/* merge a given line with all other lines of the same type and 
 * with the same categories */
static int merge_line(struct Map_info *Map, int line,
		      struct line_pnts *MPoints, struct line_cats *MCats)
{
    int nlines, i, first, last, next_line, curr_line;
    int merged = 0, newl = 0;
    int next_node, direction, node_n_lines, type, ltype, lines_type;
    static struct ilist *List = NULL;
    static struct line_pnts *Points = NULL;
    static struct line_cats *Cats = NULL;
    type = GV_LINE;

    nlines = Vect_get_num_lines(Map);

    if (!Points)
	Points = Vect_new_line_struct();
    if (!Cats)
	Cats = Vect_new_cats_struct();
    if (!List)
	List = Vect_new_list();

    Vect_reset_line(Points);
    Vect_reset_cats(Cats);
    Vect_reset_cats(MCats);
    Vect_reset_list(List);

    if (!Vect_line_alive(Map, line))
	return 0;

    ltype = Vect_get_line_type(Map, line);

    if (!(ltype & type))
	return 0;
	
    Vect_read_line(Map, MPoints, MCats, line);

    /* special cases:
     *  - loop back to start boundary via several other boundaries
     *  - one boundary forming closed loop
     *  - node with 3 entries but only 2 boundaries, one of them connecting twice,
     *    the other one must then be topologically incorrect in case of boundary */

    /* go backward as long as there is only one other line/boundary at the current node */
    G_debug(3, "go backward");
    Vect_get_line_nodes(Map, line, &next_node, NULL);

    first = -line;
    while (1) {
	node_n_lines = Vect_get_node_n_lines(Map, next_node);
	/* count lines/boundaries at this node */
	lines_type = 0;
	next_line = first;
	for (i = 0; i < node_n_lines; i++) {
	    curr_line = Vect_get_node_line(Map, next_node, i);
	    if ((Vect_get_line_type(Map, abs(curr_line)) & GV_LINES))
		lines_type++;
	    if ((Vect_get_line_type(Map, abs(curr_line)) == ltype)) {
		if (abs(curr_line) != abs(first)) {
		    Vect_read_line(Map, NULL, Cats, abs(curr_line));
		    
		    /* catgories must be identical */
		    if (compare_cats(MCats, Cats) == 0)
			next_line = curr_line;
		}
	    }
	}
	if (lines_type == 2 && abs(next_line) != abs(first) &&
	    abs(next_line) != line) {
	    first = next_line;

	    if (first < 0) {
		Vect_get_line_nodes(Map, -first, &next_node, NULL);
	    }
	    else {
		Vect_get_line_nodes(Map, first, NULL, &next_node);
	    }
	}
	else
	    break;
    }

    /* go forward as long as there is only one other line/boundary at the current node */
    G_debug(3, "go forward");

    /* reverse direction */
    last = -first;

    if (last < 0) {
	Vect_get_line_nodes(Map, -last, &next_node, NULL);
    }
    else {
	Vect_get_line_nodes(Map, last, NULL, &next_node);
    }

    Vect_reset_list(List);
    while (1) {
	G_ilist_add(List, last);
	node_n_lines = Vect_get_node_n_lines(Map, next_node);
	lines_type = 0;
	next_line = last;
	for (i = 0; i < node_n_lines; i++) {
	    curr_line = Vect_get_node_line(Map, next_node, i);
	    if ((Vect_get_line_type(Map, abs(curr_line)) & GV_LINES))
		lines_type++;
	    if ((Vect_get_line_type(Map, abs(curr_line)) == ltype)) {
		if (abs(curr_line) != abs(last)) {
		    Vect_read_line(Map, NULL, Cats, abs(curr_line));
		    
		    if (compare_cats(MCats, Cats) == 0)
			next_line = curr_line;
		}
	    }
	}

	if (lines_type == 2 && abs(next_line) != abs(last) &&
	    abs(next_line) != abs(first)) {
	    last = next_line;

	    if (last < 0) {
		Vect_get_line_nodes(Map, -last, &next_node, NULL);
	    }
	    else {
		Vect_get_line_nodes(Map, last, NULL, &next_node);
	    }
	}
	else
	    break;
    }

    /* merge lines */
    G_debug(3, "merge %d lines", List->n_values);
    Vect_reset_line(MPoints);

    for (i = 0; i < List->n_values; i++) {
	Vect_reset_line(Points);
	Vect_read_line(Map, Points, Cats, abs(List->value[i]));
	direction = (List->value[i] < 0 ? GV_BACKWARD : GV_FORWARD);
	Vect_append_points(MPoints, Points, direction);
	MPoints->n_points--;
	Vect_delete_line(Map, abs(List->value[i]));
    }
    MPoints->n_points++;
    merged += List->n_values;
    newl++;

    return merged;
}
Exemple #24
0
int main(int argc, char *argv[])
{
    int i, cat, with_z, more, ctype, nrows;
    char buf[DB_SQL_MAX];
    int count;
    double coor[3];
    int ncoor;
    struct Option *driver_opt, *database_opt, *table_opt;
    struct Option *xcol_opt, *ycol_opt, *zcol_opt, *keycol_opt, *where_opt,
	*outvect;
    struct Flag *same_table_flag;
    struct GModule *module;
    struct Map_info Map;
    struct line_pnts *Points;
    struct line_cats *Cats;
    dbString sql;
    dbDriver *driver;
    dbCursor cursor;
    dbTable *table;
    dbColumn *column;
    dbValue *value;
    struct field_info *fi;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("vector"));
    G_add_keyword(_("import"));
    G_add_keyword(_("database"));
    G_add_keyword(_("points"));
    module->description =
	_("Creates new vector (points) map from database table containing coordinates.");

    table_opt = G_define_standard_option(G_OPT_DB_TABLE);
    table_opt->required = YES;
    table_opt->description = _("Input table name");

    driver_opt = G_define_standard_option(G_OPT_DB_DRIVER);
    driver_opt->options = db_list_drivers();
    driver_opt->answer = (char *)db_get_default_driver_name();
    driver_opt->guisection = _("Input DB");

    database_opt = G_define_standard_option(G_OPT_DB_DATABASE);
    database_opt->answer = (char *)db_get_default_database_name();
    database_opt->guisection = _("Input DB");

    xcol_opt = G_define_standard_option(G_OPT_DB_COLUMN);
    xcol_opt->key = "x";
    xcol_opt->required = YES;
    xcol_opt->description = _("Name of column containing x coordinate");

    ycol_opt = G_define_standard_option(G_OPT_DB_COLUMN);
    ycol_opt->key = "y";
    ycol_opt->required = YES;
    ycol_opt->description = _("Name of column containing y coordinate");

    zcol_opt = G_define_standard_option(G_OPT_DB_COLUMN);
    zcol_opt->key = "z";
    zcol_opt->description = _("Name of column containing z coordinate");
    zcol_opt->guisection = _("3D output");

    keycol_opt = G_define_standard_option(G_OPT_DB_COLUMN);
    keycol_opt->key = "key";
    keycol_opt->required = NO;
    keycol_opt->label = _("Name of column containing category number");
    keycol_opt->description = _("Must refer to an integer column");

    where_opt = G_define_standard_option(G_OPT_DB_WHERE);
    where_opt->guisection = _("Selection");

    outvect = G_define_standard_option(G_OPT_V_OUTPUT);

    same_table_flag = G_define_flag();
    same_table_flag->key = 't';
    same_table_flag->description =
	_("Use imported table as attribute table for new map");

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

    if (zcol_opt->answer) {
	with_z = WITH_Z;
	ncoor = 3;
    }
    else {
	with_z = WITHOUT_Z;
	ncoor = 2;
    }

    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();
    db_init_string(&sql);

    if (G_get_overwrite()) {
	/* We don't want to delete the input table when overwriting the output
	 * vector. */
	char name[GNAME_MAX], mapset[GMAPSET_MAX];

	if (!G_name_is_fully_qualified(outvect->answer, name, mapset)) {
	    strcpy(name, outvect->answer);
	    strcpy(mapset, G_mapset());
	}

	Vect_set_open_level(1); /* no topo needed */

	if (strcmp(mapset, G_mapset()) == 0 && G_find_vector2(name, mapset) &&
	    Vect_open_old(&Map, name, mapset) >= 0) {
	    int num_dblinks;

	    num_dblinks = Vect_get_num_dblinks(&Map);
	    for (i = 0; i < num_dblinks; i++) {
		if ((fi = Vect_get_dblink(&Map, i)) != NULL &&
		    strcmp(fi->driver, driver_opt->answer) == 0 &&
		    strcmp(fi->database, database_opt->answer) == 0 &&
		    strcmp(fi->table, table_opt->answer) == 0)
		    G_fatal_error(_("Vector map <%s> cannot be overwritten "
				    "because input table <%s> is linked to "
				    "this map."),
				    outvect->answer, table_opt->answer);
	    }
	    Vect_close(&Map);
	}
    }

    if (Vect_open_new(&Map, outvect->answer, with_z) < 0)
	G_fatal_error(_("Unable to create vector map <%s>"),
			outvect->answer);

    Vect_set_error_handler_io(NULL, &Map);
    
    Vect_hist_command(&Map);

    fi = Vect_default_field_info(&Map, 1, NULL, GV_1TABLE);

    /* Open driver */
    driver = db_start_driver_open_database(driver_opt->answer,
					   database_opt->answer);
    if (driver == NULL) {
	G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
		      fi->database, fi->driver);
    }
    db_set_error_handler_driver(driver);
    
    /* check if target table already exists */
    G_debug(3, "Output vector table <%s>, driver: <%s>, database: <%s>",
	    outvect->answer, db_get_default_driver_name(),
	    db_get_default_database_name());

    if (!same_table_flag->answer &&
	db_table_exists(db_get_default_driver_name(),
			db_get_default_database_name(), outvect->answer) == 1)
	G_fatal_error(_("Output vector map, table <%s> (driver: <%s>, database: <%s>) "
		       "already exists"), outvect->answer,
		      db_get_default_driver_name(),
		      db_get_default_database_name());

    if (keycol_opt->answer) {
        int coltype;
        coltype = db_column_Ctype(driver, table_opt->answer, keycol_opt->answer);

        if (coltype == -1)
            G_fatal_error(_("Column <%s> not found in table <%s>"),
                          keycol_opt->answer, table_opt->answer);
        if (coltype != DB_C_TYPE_INT)
            G_fatal_error(_("Data type of key column must be integer"));
    }
    else {
        if (same_table_flag->answer) {
            G_fatal_error(_("Option <%s> must be specified when -%c flag is given"),
                          keycol_opt->key, same_table_flag->key);
        }

        if (strcmp(db_get_default_driver_name(), "sqlite") != 0)
            G_fatal_error(_("Unable to define key column. This operation is not supported "
                            "by <%s> driver. You need to define <%s> option."),
                          fi->driver, keycol_opt->key);
    }

    /* Open select cursor */
    sprintf(buf, "SELECT %s, %s", xcol_opt->answer, ycol_opt->answer);
    db_set_string(&sql, buf);
    if (with_z) {
	sprintf(buf, ", %s", zcol_opt->answer);
	db_append_string(&sql, buf);
    }
    if (keycol_opt->answer) {
	sprintf(buf, ", %s", keycol_opt->answer);
	db_append_string(&sql, buf);
    }
    sprintf(buf, " FROM %s", table_opt->answer);
    db_append_string(&sql, buf);
    
    if (where_opt->answer) {
	sprintf(buf, " WHERE %s", where_opt->answer);
	db_append_string(&sql, buf);
    }
    G_debug(2, "SQL: %s", db_get_string(&sql));

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

    table = db_get_cursor_table(&cursor);
    nrows = db_get_num_rows(&cursor);

    G_debug(2, "%d points selected", nrows);

    count = cat = 0;
    G_message(_("Writing features..."));
    while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) {
	G_percent(count, nrows, 2);
	/* key column */
        if (keycol_opt->answer) {
            column = db_get_table_column(table, with_z ? 3 : 2);
            ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column));
            if (ctype != DB_C_TYPE_INT)
                G_fatal_error(_("Key column must be integer"));
            value = db_get_column_value(column);
            cat = db_get_value_int(value);
        }
        else {
            cat++;
        }

        /* coordinates */
	for (i = 0; i < ncoor; i++) {
	    column = db_get_table_column(table, i);
	    ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column));
	    if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_DOUBLE)
		G_fatal_error(_("x/y/z column must be integer or double"));
	    value = db_get_column_value(column);
	    if (ctype == DB_C_TYPE_INT)
		coor[i] = (double)db_get_value_int(value);
	    else
		coor[i] = db_get_value_double(value);
	}

	Vect_reset_line(Points);
	Vect_reset_cats(Cats);

	Vect_append_point(Points, coor[0], coor[1], coor[2]);

	Vect_cat_set(Cats, 1, cat);

	Vect_write_line(&Map, GV_POINT, Points, Cats);

	count++;
    }
    G_percent(1, 1, 1);

    /* close connection to input DB before copying attributes */
    db_close_database_shutdown_driver(driver);

    /* Copy table */
    if (!same_table_flag->answer) {
        G_message(_("Copying attributes..."));
        
        if (DB_FAILED == db_copy_table_where(driver_opt->answer, database_opt->answer,
                                             table_opt->answer,
                                             fi->driver, fi->database, fi->table,
                                             where_opt->answer)) { /* where can be NULL */
            G_warning(_("Unable to copy table"));
	}
	else {
	    Vect_map_add_dblink(&Map, 1, NULL, fi->table,
                                keycol_opt->answer ? keycol_opt->answer : GV_KEY_COLUMN,
				fi->database, fi->driver);
	}

        if (!keycol_opt->answer) {
            /* TODO: implement for all DB drivers in generic way if
             * possible */
            
            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_set_error_handler_driver(driver);

            /* add key column */
            sprintf(buf, "ALTER TABLE %s ADD COLUMN %s INTEGER",
                    fi->table, GV_KEY_COLUMN);
            db_set_string(&sql, buf);
            
            if (db_execute_immediate(driver, &sql) != DB_OK) {
                G_fatal_error(_("Unable to add key column <%s>: "
                                "SERIAL type is not supported by <%s>"), 
                              GV_KEY_COLUMN, fi->driver);
            }

            /* update key column */
            sprintf(buf, "UPDATE %s SET %s = _ROWID_",
                    fi->table, GV_KEY_COLUMN);
            db_set_string(&sql, buf);
            
            if (db_execute_immediate(driver, &sql) != DB_OK) {
                G_fatal_error(_("Failed to update key column <%s>"),
                              GV_KEY_COLUMN);
            }

        }
    }
    else {
        /* do not copy attributes, link original table */
	Vect_map_add_dblink(&Map, 1, NULL, table_opt->answer,
                            keycol_opt->answer ? keycol_opt->answer : GV_KEY_COLUMN,
                            database_opt->answer, driver_opt->answer);
    }

    Vect_build(&Map);
    Vect_close(&Map);

    G_done_msg(_n("%d point written to vector map.",
                  "%d points written to vector map.",
                  count), count);

    return (EXIT_SUCCESS);
}
Exemple #25
0
/*!
   \brief Create buffer around the line line.

   Buffer is closed counter clockwise polygon.
   Warning: output line may contain loops!

   \param InPoints input line
   \param distance create buffer in distance
   \param tolerance maximum distance between theoretical arc and polygon segments
   \param[out] OutPoints output line
 */
void
Vect_line_buffer(struct line_pnts *InPoints, double distance,
		 double tolerance, struct line_pnts *OutPoints)
{
    double dangle;
    int side, npoints;
    static struct line_pnts *Points = NULL;
    static struct line_pnts *PPoints = NULL;

    distance = fabs(distance);

    dangle = 2 * acos(1 - tolerance / fabs(distance));	/* angle step */

    if (Points == NULL)
	Points = Vect_new_line_struct();

    if (PPoints == NULL)
	PPoints = Vect_new_line_struct();

    /* Copy and prune input */
    Vect_reset_line(Points);
    Vect_append_points(Points, InPoints, GV_FORWARD);
    Vect_line_prune(Points);

    Vect_reset_line(OutPoints);

    npoints = Points->n_points;
    if (npoints <= 0) {
	return;
    }
    else if (npoints == 1) {	/* make a circle */
	double angle, x, y;

	for (angle = 0; angle < 2 * PI; angle += dangle) {
	    x = Points->x[0] + distance * cos(angle);
	    y = Points->y[0] + distance * sin(angle);
	    Vect_append_point(OutPoints, x, y, 0);
	}
	/* Close polygon */
	Vect_append_point(OutPoints, OutPoints->x[0], OutPoints->y[0], 0);
    }
    else {			/* 2 and more points */
	for (side = 0; side < 2; side++) {
	    double angle, sangle;
	    double lx1, ly1, lx2, ly2;
	    double x, y, nx, ny, sx, sy, ex, ey;

	    /* Parallel on one side */
	    if (side == 0) {
		Vect_line_parallel(Points, distance, tolerance, 0, PPoints);
		Vect_append_points(OutPoints, PPoints, GV_FORWARD);
	    }
	    else {
		Vect_line_parallel(Points, -distance, tolerance, 0, PPoints);
		Vect_append_points(OutPoints, PPoints, GV_BACKWARD);
	    }

	    /* Arc at the end */
	    /* 2 points at theend of original line */
	    if (side == 0) {
		lx1 = Points->x[npoints - 2];
		ly1 = Points->y[npoints - 2];
		lx2 = Points->x[npoints - 1];
		ly2 = Points->y[npoints - 1];
	    }
	    else {
		lx1 = Points->x[1];
		ly1 = Points->y[1];
		lx2 = Points->x[0];
		ly2 = Points->y[0];
	    }

	    /* normalized vector */
	    vect(lx1, ly1, lx2, ly2, &nx, &ny);

	    /* starting point */
	    sangle = atan2(-nx, ny);	/* starting angle */
	    sx = lx2 + ny * distance;
	    sy = ly2 - nx * distance;

	    /* end point */
	    ex = lx2 - ny * distance;
	    ey = ly2 + nx * distance;

	    Vect_append_point(OutPoints, sx, sy, 0);

	    /* arc */
	    for (angle = dangle; angle < PI; angle += dangle) {
		x = lx2 + distance * cos(sangle + angle);
		y = ly2 + distance * sin(sangle + angle);
		Vect_append_point(OutPoints, x, y, 0);
	    }

	    Vect_append_point(OutPoints, ex, ey, 0);
	}

	/* Close polygon */
	Vect_append_point(OutPoints, OutPoints->x[0], OutPoints->y[0], 0);
    }
    Vect_line_prune(OutPoints);

    return;
}
Exemple #26
0
/* parallel_line - remove duplicate points from input line and
 *  creates new parallel line in 'd' offset distance;
 *  'tol' is tolerance between arc and polyline;
 *  this function doesn't care about created loops;
 *
 *  New line is written to existing nPoints structure.
 */
static void parallel_line(struct line_pnts *Points, double d, double tol,
			  struct line_pnts *nPoints)
{
    int i, j, np, na, side;
    double *x, *y, nx, ny, tx, ty, vx, vy, ux, uy, wx, wy;
    double atol, atol2, a, av, aw;

    G_debug(4, "parallel_line()");

    Vect_reset_line(nPoints);

    Vect_line_prune(Points);
    np = Points->n_points;
    x = Points->x;
    y = Points->y;

    if (np == 0)
	return;

    if (np == 1) {
	Vect_append_point(nPoints, x[0], y[0], 0);	/* ? OK, should make circle for points ? */
	return;
    }

    if (d == 0) {
	Vect_copy_xyz_to_pnts(nPoints, x, y, NULL, np);
	return;
    }

    side = (int)(d / fabs(d));
    atol = 2 * acos(1 - tol / fabs(d));

    for (i = 0; i < np - 1; i++) {
	vect(x[i], y[i], x[i + 1], y[i + 1], &tx, &ty);
	vx = ty * d;
	vy = -tx * d;

	nx = x[i] + vx;
	ny = y[i] + vy;
	Vect_append_point(nPoints, nx, ny, 0);

	nx = x[i + 1] + vx;
	ny = y[i + 1] + vy;
	Vect_append_point(nPoints, nx, ny, 0);

	if (i < np - 2) {	/* use polyline instead of arc between line segments */
	    vect(x[i + 1], y[i + 1], x[i + 2], y[i + 2], &ux, &uy);
	    wx = uy * d;
	    wy = -ux * d;
	    av = atan2(vy, vx);
	    aw = atan2(wy, wx);
	    a = (aw - av) * side;
	    if (a < 0)
		a += 2 * PI;

	    /* TODO: a <= PI can probably fail because of representation error */
	    if (a <= PI && a > atol) {
		na = (int)(a / atol);
		atol2 = a / (na + 1) * side;
		for (j = 0; j < na; j++) {
		    av += atol2;
		    nx = x[i + 1] + fabs(d) * cos(av);
		    ny = y[i + 1] + fabs(d) * sin(av);
		    Vect_append_point(nPoints, nx, ny, 0);
		}
	    }
	}
    }
    Vect_line_prune(nPoints);
}
Exemple #27
0
/* clean_parallel - clean parallel line created by parallel_line:
 ** - looking for loops and if loop doesn't contain any other loop
 **   and centroid of loop is in buffer removes this loop (repeated)
 ** - optionally removes all end points in buffer
 *    parameters:
 *      Points - parallel line
 *      origPoints - original line
 *      d - offset
 *      rm_end - remove end points in buffer
 ** note1: on some lines (multiply selfcrossing; lines with end points
 **        in buffer of line other; some shapes of ends ) may create nosense
 ** note2: this function is stupid and slow, somebody more clever
 **        than I am should write paralle_line + clean_parallel
 **        better;    RB March 2000
 */
static void clean_parallel(struct line_pnts *Points,
			   struct line_pnts *origPoints, double d, int rm_end)
{
    int i, j, np, npn, sa, sb;
    int sa_max = 0;
    int first = 0, current, last, lcount;
    double *x, *y, px, py, ix, iy;
    static struct line_pnts *sPoints = NULL;

    G_debug(4, "clean_parallel(): npoints = %d, d = %f, rm_end = %d",
	    Points->n_points, d, rm_end);

    x = Points->x;
    y = Points->y;
    np = Points->n_points;

    if (sPoints == NULL)
	sPoints = Vect_new_line_struct();

    Vect_reset_line(sPoints);

    npn = 1;

    /* remove loops */
    while (first < np - 2) {
	/* find first loop which doesn't contain any other loop */
	current = first;
	last = Points->n_points - 2;
	lcount = 0;
	while (find_cross
	       (Points, current, last - 1, current + 1, last, &sa,
		&sb) != 0) {
	    if (lcount == 0) {
		first = sa;
	    }			/* move first forward */

	    current = sa + 1;
	    last = sb;
	    lcount++;
	    G_debug(5, "  current = %d, last = %d, lcount = %d", current,
		    last, lcount);
	}
	if (lcount == 0) {
	    break;
	}			/* loop not found */

	/* ensure sa is monotonically increasing, so npn doesn't reset low */
	if (sa > sa_max)
	    sa_max = sa;
	if (sa < sa_max)
	    break;

	/* remove loop if in buffer */
	if ((sb - sa) == 1) {	/* neighbouring lines overlap */
	    j = sb + 1;
	    npn = sa + 1;
	}
	else {
	    Vect_reset_line(sPoints);
	    dig_find_intersection(x[sa], y[sa], x[sa + 1], y[sa + 1], x[sb],
				  y[sb], x[sb + 1], y[sb + 1], &ix, &iy);
	    Vect_append_point(sPoints, ix, iy, 0);
	    for (i = sa + 1; i < sb + 1; i++) {	/* create loop polygon */
		Vect_append_point(sPoints, x[i], y[i], 0);
	    }
	    Vect_find_poly_centroid(sPoints, &px, &py);
	    if (point_in_buf(origPoints, px, py, d)) {	/* is loop in buffer ? */
		npn = sa + 1;
		x[npn] = ix;
		y[npn] = iy;
		j = sb + 1;
		npn++;
		if (lcount == 0) {
		    first = sb;
		}
	    }
	    else {		/* loop is not in buffer */
		first = sb;
		continue;
	    }
	}

	for (i = j; i < Points->n_points; i++) {	/* move points down */
	    x[npn] = x[i];
	    y[npn] = y[i];
	    npn++;
	}
	Points->n_points = npn;
    }

    if (rm_end) {
	/* remove points from start in buffer */
	j = 0;
	for (i = 0; i < Points->n_points - 1; i++) {
	    px = (x[i] + x[i + 1]) / 2;
	    py = (y[i] + y[i + 1]) / 2;
	    if (point_in_buf(origPoints, x[i], y[i], d * 0.9999)
		&& point_in_buf(origPoints, px, py, d * 0.9999)) {
		j++;
	    }
	    else {
		break;
	    }
	}
	if (j > 0) {
	    npn = 0;
	    for (i = j; i < Points->n_points; i++) {
		x[npn] = x[i];
		y[npn] = y[i];
		npn++;
	    }
	    Points->n_points = npn;
	}
	/* remove points from end in buffer */
	j = 0;
	for (i = Points->n_points - 1; i >= 1; i--) {
	    px = (x[i] + x[i - 1]) / 2;
	    py = (y[i] + y[i - 1]) / 2;
	    if (point_in_buf(origPoints, x[i], y[i], d * 0.9999)
		&& point_in_buf(origPoints, px, py, d * 0.9999)) {
		j++;
	    }
	    else {
		break;
	    }
	}
	if (j > 0) {
	    Points->n_points -= j;
	}
    }
}
Exemple #28
0
int close_streamvect(char *stream_vect)
{
    int r, c, r_nbr, c_nbr, done;
    GW_LARGE_INT i;
    CELL stream_id, stream_nbr;
    ASP_FLAG af;
    int next_node;
    struct sstack
    {
	int stream_id;
	int next_trib;
    } *nodestack;
    int top = 0, stack_step = 1000;
    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 };
    struct Map_info Out;
    static struct line_pnts *Points;
    struct line_cats *Cats;
    dbDriver *driver;
    dbHandle handle;
    dbString table_name, dbsql, valstr;
    struct field_info *Fi;
    char *cat_col_name = "cat", buf[2000];
    struct Cell_head window;
    double north_offset, west_offset, ns_res, ew_res;
    int next_cat;

    G_message(_("Writing vector map <%s>..."), stream_vect);

    if (Vect_open_new(&Out, stream_vect, 0) < 0)
	G_fatal_error(_("Unable to create vector map <%s>"), stream_vect);
    
    nodestack = (struct sstack *)G_malloc(stack_step * sizeof(struct sstack));

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

    G_get_set_window(&window);
    ns_res = window.ns_res;
    ew_res = window.ew_res;
    north_offset = window.north - 0.5 * ns_res;
    west_offset = window.west + 0.5 * ew_res;

    next_cat = n_stream_nodes + 1;

    for (i = 0; i < n_outlets; i++, next_cat++) {
	G_percent(i, n_outlets, 2);
	r = outlets[i].r;
	c = outlets[i].c;
	cseg_get(&stream, &stream_id, r, c);

	if (!stream_id)
	    continue;

	Vect_reset_line(Points);
	Vect_reset_cats(Cats);

	/* outlet */
	Vect_cat_set(Cats, 1, stream_id);
	Vect_cat_set(Cats, 2, 2);
	Vect_append_point(Points, west_offset + c * ew_res,
			  north_offset - r * ns_res, 0);
	Vect_write_line(&Out, GV_POINT, Points, Cats);

	/* add root node to stack */
	G_debug(3, "add root node");
	top = 0;
	nodestack[top].stream_id = stream_id;
	nodestack[top].next_trib = 0;

	/* depth first post order traversal */
	G_debug(3, "traverse");
	while (top >= 0) {

	    done = 1;
	    stream_id = nodestack[top].stream_id;
	    G_debug(3, "stream_id %d", stream_id);
	    if (nodestack[top].next_trib < stream_node[stream_id].n_trib) {
		/* add to stack */
		next_node =
		    stream_node[stream_id].trib[nodestack[top].next_trib];
		G_debug(3, "add to stack: next %d, trib %d, n trib %d",
			next_node, nodestack[top].next_trib,
			stream_node[stream_id].n_trib);
		nodestack[top].next_trib++;
		top++;
		if (top >= stack_step) {
		    /* need more space */
		    stack_step += 1000;
		    nodestack =
			(struct sstack *)G_realloc(nodestack,
						   stack_step *
						   sizeof(struct sstack));
		}
		nodestack[top].next_trib = 0;
		nodestack[top].stream_id = next_node;
		done = 0;
		G_debug(3, "go further down");
	    }
	    if (done) {
		G_debug(3, "write stream segment");

		Vect_reset_line(Points);
		Vect_reset_cats(Cats);

		r_nbr = stream_node[stream_id].r;
		c_nbr = stream_node[stream_id].c;

		cseg_get(&stream, &stream_nbr, r_nbr, c_nbr);
		if (stream_nbr <= 0)
                    G_fatal_error(_("Stream id %d not set, top is %d, parent is %d"),
                                  stream_id, top, nodestack[top - 1].stream_id);

		Vect_cat_set(Cats, 1, stream_id);
		if (stream_node[stream_id].n_trib == 0)
		    Vect_cat_set(Cats, 2, 0);
		else
		    Vect_cat_set(Cats, 2, 1);

		Vect_append_point(Points, west_offset + c_nbr * ew_res,
				  north_offset - r_nbr * ns_res, 0);

		Vect_write_line(&Out, GV_POINT, Points, Cats);

		seg_get(&aspflag, (char *)&af, r_nbr, c_nbr);
		while (af.asp > 0) {
		    r_nbr = r_nbr + asp_r[(int)af.asp];
		    c_nbr = c_nbr + asp_c[(int)af.asp];
		    
		    cseg_get(&stream, &stream_nbr, r_nbr, c_nbr);
		    if (stream_nbr <= 0)
			G_fatal_error(_("Stream id not set while tracing"));

		    Vect_append_point(Points, west_offset + c_nbr * ew_res,
				      north_offset - r_nbr * ns_res, 0);
		    if (stream_nbr != stream_id) {
			/* first point of parent stream */
			break;
		    }
		    seg_get(&aspflag, (char *)&af, r_nbr, c_nbr);
		}

		Vect_write_line(&Out, GV_LINE, Points, Cats);

		top--;
	    }
	}
    }
    G_percent(n_outlets, n_outlets, 1);	/* finish it */

    G_message(_("Writing attribute data..."));

    /* Prepeare strings for use in db_* calls */
    db_init_string(&dbsql);
    db_init_string(&valstr);
    db_init_string(&table_name);
    db_init_handle(&handle);

    /* Preparing database for use */
    /* Create database for new vector map */
    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 start driver <%s>"), Fi->driver);
    }
    db_set_error_handler_driver(driver);

    G_debug(1, "table: %s", Fi->table);
    G_debug(1, "driver: %s", Fi->driver);
    G_debug(1, "database: %s", Fi->database);

    sprintf(buf,
	    "create table %s (%s integer, stream_type varchar(20), type_code integer)",
	    Fi->table, cat_col_name);
    db_set_string(&dbsql, buf);

    if (db_execute_immediate(driver, &dbsql) != DB_OK) {
	db_close_database(driver);
	db_shutdown_driver(driver);
	G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&dbsql));
    }

    if (db_create_index2(driver, Fi->table, cat_col_name) != DB_OK)
	G_warning(_("Unable to create index on table <%s>"), Fi->table);

    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);

    db_begin_transaction(driver);

    /* stream nodes */
    for (i = 1; i <= n_stream_nodes; i++) {

	sprintf(buf, "insert into %s values ( %lld, \'%s\', %d )",
		Fi->table, i,
		(stream_node[i].n_trib > 0 ? "intermediate" : "start"),
		(stream_node[i].n_trib > 0));

	db_set_string(&dbsql, buf);

	if (db_execute_immediate(driver, &dbsql) != DB_OK) {
	    db_close_database(driver);
	    db_shutdown_driver(driver);
	    G_fatal_error(_("Unable to insert new row: '%s'"),
			  db_get_string(&dbsql));
	}
    }

    db_commit_transaction(driver);
    db_close_database_shutdown_driver(driver);

    Vect_map_add_dblink(&Out, 1, NULL, Fi->table,
			cat_col_name, Fi->database, Fi->driver);

    G_debug(1, "close vector");

    Vect_hist_command(&Out);
    Vect_build(&Out);
    Vect_close(&Out);

    G_free(nodestack);

    return 1;
}
Exemple #29
0
void writePoint( struct Map_info* map, int type, QgsPoint point, struct line_cats *cats )
{
  Vect_reset_line( line );
  Vect_append_point( line, point.x(), point.y(), 0 );
  Vect_write_line( map, type, line, cats );
}
Exemple #30
0
int main(int argc, char *argv[])
{
    struct GModule *module;
    struct Option *in_opt, *layer_opt, *out_opt, *length_opt, *units_opt, *vertices_opt;
    
    struct Map_info In, Out;
    struct line_pnts *Points, *Points2;
    struct line_cats *Cats;

    int line, nlines, layer;
    double length = -1;
    int vertices = 0;
    double (*line_length) ();
    int latlon = 0;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("vector"));
    G_add_keyword(_("geometry"));
    module->description = _("Splits vector lines to shorter segments.");
    
    in_opt = G_define_standard_option(G_OPT_V_INPUT);

    layer_opt = G_define_standard_option(G_OPT_V_FIELD_ALL);

    out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
    
    length_opt = G_define_option();
    length_opt->key = "length";
    length_opt->type = TYPE_DOUBLE;
    length_opt->required = NO;
    length_opt->multiple = NO;
    length_opt->description = _("Maximum segment length");

    units_opt = G_define_option();
    units_opt->key = "units";
    units_opt->type = TYPE_STRING;
    units_opt->required = NO;
    units_opt->multiple = NO;
    units_opt->options = "meters,kilometers,feet,miles,nautmiles";
    units_opt->answer = "meters";
    units_opt->description = _("Length units");
    
    vertices_opt = G_define_option();
    vertices_opt->key = "vertices";
    vertices_opt->type = TYPE_INTEGER;
    vertices_opt->required = NO;
    vertices_opt->multiple = NO;
    vertices_opt->description = _("Maximum number of vertices in segment");
    
    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);
    
    if ((length_opt->answer && vertices_opt->answer) ||
	!(length_opt->answer || vertices_opt->answer))
	G_fatal_error(_("Use either length or vertices"));

    line_length = NULL;

    if (length_opt->answer) {
	length = atof(length_opt->answer);
	if (length <= 0)
	    G_fatal_error(_("Length must be positive but is %g"), length);

	/* convert length to meters */
	if (strcmp(units_opt->answer, "meters") == 0)
	    /* do nothing */ ;
	else if (strcmp(units_opt->answer, "kilometers") == 0)
	    length *= FROM_KILOMETERS;
	else if (strcmp(units_opt->answer, "feet") == 0)
	    length *= FROM_FEET;
	else if (strcmp(units_opt->answer, "miles") == 0)
	    length *= FROM_MILES;
	else if (strcmp(units_opt->answer, "nautmiles") == 0)
	    length *= FROM_NAUTMILES;
	else
	    G_fatal_error(_("Unknown unit %s"), units_opt->answer); 

	/* set line length function */
	if ((latlon = (G_projection() == PROJECTION_LL)) == 1)
	    line_length = Vect_line_geodesic_length;
	else {
	    double factor;
	    
	    line_length = Vect_line_length;
	    
	    /* convert length to map units */
	    if ((factor = G_database_units_to_meters_factor()) == 0)
		G_fatal_error(_("Can not get projection units"));
	    else {
		/* meters to units */
		length = length / factor;
	    }
	}
	G_verbose_message(_("length in %s: %g"), (latlon ? "meters" : "map units"), length);
    }

    if (vertices_opt->answer) {
	vertices = atoi(vertices_opt->answer);
	if (vertices < 2)
	    G_fatal_error(_("Number of vertices must be at least 2"));
    }
    
    Vect_set_open_level(2);
    Vect_open_old2(&In, in_opt->answer, "", layer_opt->answer);
    layer = Vect_get_field_number(&In, layer_opt->answer);
    
    Vect_open_new(&Out, out_opt->answer, Vect_is_3d(&In));
    
    Vect_copy_head_data(&In, &Out);
    Vect_hist_copy(&In, &Out);
    Vect_hist_command(&Out);
    Vect_copy_tables(&In, &Out, layer);
    
    Points = Vect_new_line_struct();
    Points2 = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    nlines = Vect_get_num_lines(&In);

    for (line = 1; line <= nlines; line++) {
	int ltype;

	G_percent(line, nlines, 1);

	if (!Vect_line_alive(&In, line))
	    continue;

	ltype = Vect_read_line(&In, Points, Cats, line);

	if (layer != -1 && !Vect_cat_get(Cats, layer, NULL))
	  continue;

	if (ltype & GV_LINES) {
	    if (length > 0) {
		double l, from, to, step;

		l = line_length(Points);

		if (l <= length) {
		    Vect_write_line(&Out, ltype, Points, Cats);
		}
		else {
		    int n, i;

		    n = ceil(l / length);
		    if (latlon)
			l = Vect_line_length(Points);

		    step = l / n;
		    from = 0.;

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

			if (i == n - 1) {
			    to = l;	/* to be sure that it goes to end */
			}
			else {
			    to = from + step;
			}

			ret = Vect_line_segment(Points, from, to, Points2);
			if (ret == 0) {
			    G_warning(_("Unable to make line segment: %f - %f (line length = %f)"),
				      from, to, l);
			    continue;
			}

			/* To be sure that the coordinates are identical */
			if (i > 0) {
			    Points2->x[0] = x;
			    Points2->y[0] = y;
			    Points2->z[0] = z;
			}
			if (i == n - 1) {
			    Points2->x[Points2->n_points - 1] =
				Points->x[Points->n_points - 1];
			    Points2->y[Points2->n_points - 1] =
				Points->y[Points->n_points - 1];
			    Points2->z[Points2->n_points - 1] =
				Points->z[Points->n_points - 1];
			}

			Vect_write_line(&Out, ltype, Points2, Cats);

			/* last point */
			x = Points2->x[Points2->n_points - 1];
			y = Points2->y[Points2->n_points - 1];
			z = Points2->z[Points2->n_points - 1];

			from += step;
		    }
		}
	    }
	    else {
		int start = 0;	/* number of coordinates written */

		while (start < Points->n_points - 1) {
		    int i, v;

		    Vect_reset_line(Points2);
		    for (i = 0; i < vertices; i++) {
			v = start + i;
			if (v == Points->n_points)
			    break;

			Vect_append_point(Points2, Points->x[v], Points->y[v],
					  Points->z[v]);
		    }

		    Vect_write_line(&Out, ltype, Points2, Cats);

		    start = v;
		}
	    }
	}
	else {
	    Vect_write_line(&Out, ltype, Points, Cats);
	}
    }

    Vect_close(&In);
    Vect_build(&Out);
    Vect_close(&Out);
    
    exit(EXIT_SUCCESS);
}