void QgsGrassEditDeleteVertex::mouseClick( QgsPoint & point, Qt::MouseButton button )
{
  double thresh = e->threshold();

  switch ( button )
  {
    case Qt::LeftButton:
      // Delete previously selected vertex
      if ( e->mSelectedLine > 0 )
      {
        e->eraseDynamic();
        e->eraseElement( e->mSelectedLine );

        // Move vertex
        int type = e->mProvider->readLine( e->mPoints, e->mCats, e->mSelectedLine );
        Vect_line_delete_point( e->mPoints, e->mSelectedPart );

        if ( e->mPoints->n_points < 2 ) // delete line
        {
          e->mProvider->deleteLine( e->mSelectedLine );

          // Check orphan records
          for ( int i = 0 ; i < e->mCats->n_cats; i++ )
          {
            e->checkOrphan( e->mCats->field[i], e->mCats->cat[i] );
          }
        }
        else
        {
          e->mProvider->rewriteLine( e->mSelectedLine, type, e->mPoints, e->mCats );
        }

        e->updateSymb();
        e->displayUpdated();

        e->mSelectedLine = 0;
        Vect_reset_line( e->mEditPoints );

        e->setCanvasPrompt( tr( "Select vertex" ), "", "" );
      }
      else
      {
        // Select new/next line
        e->mSelectedLine = e->mProvider->findLine( point.x(), point.y(), GV_LINES, thresh );

        if ( e->mSelectedLine )   // highlite
        {
          e->mProvider->readLine( e->mEditPoints, NULL, e->mSelectedLine );

          e->displayElement( e->mSelectedLine, e->mSymb[QgsGrassEdit::SYMB_HIGHLIGHT], e->mSize );

          double xl, yl; // nearest point on the line

          // Note first segment is 1!
          e->mSelectedPart = Vect_line_distance( e->mEditPoints, point.x(), point.y(), 0.0, 0,
                                                 &xl, &yl, NULL, NULL, NULL, NULL );

          double dist1 = Vect_points_distance( xl, yl, 0.0, e->mEditPoints->x[e->mSelectedPart-1],
                                               e->mEditPoints->y[e->mSelectedPart-1], 0.0, 0 );
          double dist2 = Vect_points_distance( xl, yl, 0.0, e->mEditPoints->x[e->mSelectedPart],
                                               e->mEditPoints->y[e->mSelectedPart], 0.0, 0 );

          if ( dist1 < dist2 )
            e->mSelectedPart--;

          e->displayDynamic( e->mEditPoints->x[e->mSelectedPart], e->mEditPoints->y[e->mSelectedPart],
                             QgsVertexMarker::ICON_BOX, e->mSize );

          e->setCanvasPrompt( tr( "Delete vertex" ), "", tr( "Release vertex" ) );
        }
        else
        {
          e->setCanvasPrompt( tr( "Select vertex" ), "", "" );
        }
      }
      break;

    case Qt::RightButton:
      e->eraseDynamic();
      e->displayElement( e->mSelectedLine, e->mSymb[e->mLineSymb[e->mSelectedLine]], e->mSize );
      e->mSelectedLine = 0;
      Vect_reset_line( e->mEditPoints );

      e->setCanvasPrompt( tr( "Select vertex" ), "", "" );
      break;

    default:
      // ignore others
      break;
  }
}
Esempio n. 2
0
/*
 * This function generates parallel line (with loops, but not like the old ones).
 * It is not to be used directly for creating buffers.
 * + added elliptical buffers/par.lines support
 *
 * dalpha - direction of elliptical buffer major axis in degrees
 * da - distance along major axis
 * db: distance along minor (perp.) axis
 * side: side >= 0 - right side, side < 0 - left side
 * when (da == db) we have plain distances (old case)
 * round - 1 for round corners, 0 for sharp corners. (tol is used only if round == 1)
 */
static void parallel_line(struct line_pnts *Points, double da, double db,
			  double dalpha, int side, int round, int caps, int looped,
			  double tol, struct line_pnts *nPoints)
{
    int i, j, res, np;
    double *x, *y;
    double tx, ty, vx, vy, wx, wy, nx, ny, mx, my, rx, ry;
    double vx1, vy1, wx1, wy1;
    double a0, b0, c0, a1, b1, c1;
    double phi1, phi2, delta_phi;
    double nsegments, angular_tol, angular_step;
    int inner_corner, turns360;

    G_debug(3, "parallel_line()");

    if (looped && 0) {
	/* start point != end point */
	return;
    }

    Vect_reset_line(nPoints);

    if (looped) {
	Vect_append_point(Points, Points->x[1], Points->y[1], Points->z[1]);
    }
    np = Points->n_points;
    x = Points->x;
    y = Points->y;

    if ((np == 0) || (np == 1))
	return;

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

    side = (side >= 0) ? (1) : (-1);	/* normalize variable */
    dalpha *= PI / 180;		/* convert dalpha from degrees to radians */
    angular_tol = angular_tolerance(tol, da, db);

    for (i = 0; i < np - 1; i++) {
	/* save the old values */
	a0 = a1;
	b0 = b1;
	c0 = c1;
	wx = vx;
	wy = vy;


	norm_vector(x[i], y[i], x[i + 1], y[i + 1], &tx, &ty);
	if ((tx == 0) && (ty == 0))
	    continue;

	elliptic_tangent(side * tx, side * ty, da, db, dalpha, &vx, &vy);

	nx = x[i] + vx;
	ny = y[i] + vy;

	mx = x[i + 1] + vx;
	my = y[i + 1] + vy;

	line_coefficients(nx, ny, mx, my, &a1, &b1, &c1);

	if (i == 0) {
	    if (!looped)
		Vect_append_point(nPoints, nx, ny, 0);
	    continue;
	}

	delta_phi = atan2(ty, tx) - atan2(y[i] - y[i - 1], x[i] - x[i - 1]);
	if (delta_phi > PI)
	    delta_phi -= 2 * PI;
	else if (delta_phi <= -PI)
	    delta_phi += 2 * PI;
	/* now delta_phi is in [-pi;pi] */
	turns360 = (fabs(fabs(delta_phi) - PI) < 1e-15);
	inner_corner = (side * delta_phi <= 0) && (!turns360);

	if ((turns360) && (!(caps && round))) {
	    if (caps) {
		norm_vector(0, 0, vx, vy, &tx, &ty);
		elliptic_tangent(side * tx, side * ty, da, db, dalpha, &tx,
				 &ty);
	    }
	    else {
		tx = 0;
		ty = 0;
	    }
	    Vect_append_point(nPoints, x[i] + wx + tx, y[i] + wy + ty, 0);
	    Vect_append_point(nPoints, nx + tx, ny + ty, 0);	/* nx == x[i] + vx, ny == y[i] + vy */
	}
	else if ((!round) || inner_corner) {
	    res = line_intersection(a0, b0, c0, a1, b1, c1, &rx, &ry);
	    /*                if (res == 0) {
	       G_debug(4, "a0=%.18f, b0=%.18f, c0=%.18f, a1=%.18f, b1=%.18f, c1=%.18f", a0, b0, c0, a1, b1, c1);
	       G_fatal_error("Two consequtive line segments are parallel, but not on one straight line! This should never happen.");
	       return;
	       }  */
	    if (res == 1) {
		if (!round)
		    Vect_append_point(nPoints, rx, ry, 0);
		else {
		    /*                    d = dig_distance2_point_to_line(rx, ry, 0, x[i-1], y[i-1], 0, x[i], y[i], 0,
		       0, NULL, NULL, NULL, NULL, NULL);
		       if ( */
		    Vect_append_point(nPoints, rx, ry, 0);
		}
	    }
	}
	else {
	    /* we should draw elliptical arc for outside corner */

	    /* inverse transforms */
	    elliptic_transform(wx, wy, 1 / da, 1 / db, dalpha, &wx1, &wy1);
	    elliptic_transform(vx, vy, 1 / da, 1 / db, dalpha, &vx1, &vy1);

	    phi1 = atan2(wy1, wx1);
	    phi2 = atan2(vy1, vx1);
	    delta_phi = side * (phi2 - phi1);

	    /* make delta_phi in [0, 2pi] */
	    if (delta_phi < 0)
		delta_phi += 2 * PI;

	    nsegments = (int)(delta_phi / angular_tol) + 1;
	    angular_step = side * (delta_phi / nsegments);

	    for (j = 0; j <= nsegments; j++) {
		elliptic_transform(cos(phi1), sin(phi1), da, db, dalpha, &tx,
				   &ty);
		Vect_append_point(nPoints, x[i] + tx, y[i] + ty, 0);
		phi1 += angular_step;
	    }
	}

	if ((!looped) && (i == np - 2)) {
	    Vect_append_point(nPoints, mx, my, 0);
	}
    }

    if (looped) {
	Vect_append_point(nPoints, nPoints->x[0], nPoints->y[0],
			  nPoints->z[0]);
    }

    Vect_line_prune(nPoints);

    if (looped) {
	Vect_line_delete_point(Points, Points->n_points - 1);
    }
}
Esempio n. 3
0
/* Start from the first node on a polyline and walk to the other end,
   collecting the coordinates of each node en route.  */
int walk_forward_and_pick_up_coords(struct Map_info *map,
				    int start_line, int ltype,
				    struct line_pnts *points,
				    int *lines_visited,
				    struct line_cats *Cats, int write_cats)
{
    int cat_idx;
    int line, next_line, n1, n2;
    int type, node, next_node;
    struct line_pnts *pnts;
    struct line_cats *cats_tmp;

    G_debug(2, "  walk_forward() start = %d", start_line);
    line = start_line;
    pnts = Vect_new_line_struct();
    if (write_cats != NO_CATS) {
	cats_tmp = Vect_new_cats_struct();
    }
    else {
	cats_tmp = NULL;
    }

    Vect_reset_line(points);

    /* Pick up first set of coordinates */
    lines_visited[line] = 1;
    if (cats_tmp)
	type = Vect_read_line(map, pnts, Cats, line);
    else
	type = Vect_read_line(map, pnts, NULL, line);

    Vect_get_line_nodes(map, line, &n1, &n2);
    next_line = find_next_line(map, line, n1, ltype);
    if (next_line > 0) {	/* continue at start node */
	Vect_append_points(points, pnts, GV_BACKWARD);
	next_node = n1;
    }
    else {
	Vect_append_points(points, pnts, GV_FORWARD);
	next_line = find_next_line(map, line, n2, ltype);	/* check end node */
	if (next_line > 0) {
	    next_node = n2;	/* continue at end node */
	}
	else {
	    return 1;		/* no other line */
	}
    }

    /* While next line exist append coordinates */
    line = next_line;
    node = next_node;
    while (line != 0 && line != start_line) {
	G_debug(2, "  line = %d", line);
	type = Vect_read_line(map, pnts, cats_tmp, line);
	if (cats_tmp && write_cats == MULTI_CATS) {
	    for (cat_idx = 0; cat_idx < cats_tmp->n_cats; cat_idx++) {
		Vect_cat_set(Cats, cats_tmp->field[cat_idx],
			     cats_tmp->cat[cat_idx]);
	    }
	}
	Vect_get_line_nodes(map, line, &n1, &n2);

	if (node == n1) {
	    Vect_line_delete_point(pnts, 0);	/* delete duplicate nodes */
	    Vect_append_points(points, pnts, GV_FORWARD);
	    next_node = n2;
	}
	else {
	    Vect_line_delete_point(pnts, pnts->n_points - 1);
	    Vect_append_points(points, pnts, GV_BACKWARD);
	    next_node = n1;
	}

	lines_visited[line] = 1;

	/* Find next one */
	next_line = find_next_line(map, line, next_node, ltype);

	line = next_line;
	node = next_node;
    }

    if (cats_tmp)
	Vect_destroy_cats_struct(cats_tmp);

    return 1;
}