Changeset 31708
- Timestamp:
- Jun 13, 2008, 10:30:18 AM (16 years ago)
- Location:
- grass-addons/vector/v.parallel2
- Files:
-
- 2 edited
-
main.c (modified) (6 diffs)
-
vlib_buffer.c (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
grass-addons/vector/v.parallel2/main.c
r31651 r31708 28 28 struct Option *in_opt, *out_opt, *dista_opt; 29 29 struct Option *distb_opt, *angle_opt, *side_opt; 30 struct Option *tol_opt; 30 31 struct Flag *round_flag, *loops_flag; 31 32 struct Map_info In, Out; … … 47 48 48 49 dista_opt = G_define_option(); 49 dista_opt->key = "dista ";50 dista_opt->key = "distance"; 50 51 dista_opt->type = TYPE_DOUBLE; 51 52 dista_opt->required = YES; … … 54 55 55 56 distb_opt = G_define_option(); 56 distb_opt->key = " distb";57 distb_opt->key = "minordistance"; 57 58 distb_opt->type = TYPE_DOUBLE; 58 distb_opt->required = YES;59 distb_opt->required = NO; 59 60 distb_opt->multiple = NO; 60 61 distb_opt->description = _("Offset along minor axis in map units"); … … 63 64 angle_opt->key = "angle"; 64 65 angle_opt->type = TYPE_DOUBLE; 65 angle_opt->required = YES;66 angle_opt->required = NO; 66 67 angle_opt->answer = "0"; 67 68 angle_opt->multiple = NO; … … 76 77 side_opt->options = "left,right"; 77 78 side_opt->description = _("left;Parallel line is on the left;right;Parallel line is on the right;"); 79 80 tol_opt = G_define_option(); 81 tol_opt->key = "tolerance"; 82 tol_opt->type = TYPE_DOUBLE; 83 tol_opt->required = NO; 84 tol_opt->multiple = NO; 85 tol_opt->description = _("Tolerance of arc polylines in map units"); 78 86 79 87 round_flag = G_define_flag(); … … 90 98 /* layer = atoi ( layer_opt->answer ); */ 91 99 da = atof(dista_opt->answer); 92 db = atof(distb_opt->answer); 93 dalpha = atof(angle_opt->answer); 94 tolerance = ((da>db)?da:db)/10.; 95 if (strcmp(side_opt->answer, "right")) 100 101 if (distb_opt->answer) 102 db = atof(distb_opt->answer); 103 else 104 db = da; 105 106 if (angle_opt->answer) 107 dalpha = atof(angle_opt->answer); 108 else 109 dalpha = 0; 110 111 if (tol_opt->answer) 112 tolerance = atof(tol_opt->answer); 113 else 114 tolerance = ((db<da)?db:da)/10.; 115 116 if (strcmp(side_opt->answer, "right") == 0) 96 117 side = 1; 97 else if (strcmp(side_opt->answer, "left") )118 else if (strcmp(side_opt->answer, "left") == 0) 98 119 side = -1; 99 120 -
grass-addons/vector/v.parallel2/vlib_buffer.c
r31651 r31708 1 1 /* Functions: nearest, adjust_line, parallel_line 2 2 ** 3 ** Author: Radim Blazek Feb 20003 ** Author: Radim Blazek, Rosen Matev; June 2008 4 4 ** 5 5 ** … … 10 10 #include <grass/gis.h> 11 11 12 #define LENGTH(DX, DY) ( sqrt( (DX*DX)+(DY*DY) ) ) 12 #define LENGTH(DX, DY) (sqrt((DX*DX)+(DY*DY))) 13 #define MIN(X,Y) ((X<Y)?X:Y) 14 #define MAX(X,Y) ((X>Y)?X:Y) 13 15 #define PI M_PI 14 16 … … 314 316 #endif 315 317 318 static void rotate_vector(double x, double y, double cosa, double sina, double *nx, double *ny) { 319 *nx = x*cosa - y*sina; 320 *ny = x*sina + y*cosa; 321 return; 322 } 323 316 324 /* 317 * (x, y) shoud be normalized vector ; This func transforms it to a vector corresponding to da, db, dalpha params325 * (x, y) shoud be normalized vector for common transforms; This func transforms it to a vector corresponding to da, db, dalpha params 318 326 */ 319 327 static void elliptic_transform(double x, double y, double da, double db, double dalpha, double *nx, double *ny) { 320 328 double cosa = cos(dalpha); 321 329 double sina = sin(dalpha); 322 double cc = cosa*cosa;330 /* double cc = cosa*cosa; 323 331 double ss = sina*sina; 324 332 double t = (da-db)*sina*cosa; … … 326 334 *nx = (da*cc + db*ss)*x + t*y; 327 335 *ny = (da*ss + db*cc)*y + t*x; 328 return; 329 } 336 return;*/ 337 338 double va, vb; 339 va = (x*cosa + y*sina)*da; 340 vb = (x*(-sina) + y*cosa)*db; 341 *nx = va*cosa + vb*(-sina); 342 *ny = va*sina + vb*cosa; 343 return; 344 } 345 346 /* 347 * vect(x,y) must be normalized 348 * gives the tangent point of the tangent to ellpise(da,db,dalpha) parallel to vect(x,y) 349 * ellipse center is in (0,0) 350 */ 351 static void elliptic_tangent(double x, double y, double da, double db, double dalpha, double *px, double *py) { 352 double cosa = cos(dalpha); 353 double sina = sin(dalpha); 354 double u, v, len; 355 /* rotate (x,y) -dalpha radians */ 356 rotate_vector(x, y, cosa, -sina, &x, &y); 357 /*u = (x + da*y/db)/2; 358 v = (y - db*x/da)/2;*/ 359 u = da*da*y; 360 v = -db*db*x; 361 len = da*db/sqrt(da*da*v*v + db*db*u*u); 362 u *= len; 363 v *= len; 364 rotate_vector(u, v, cosa, sina, px, py); 365 return; 366 } 367 330 368 331 369 /* … … 365 403 } 366 404 405 static double angular_tolerance(double tol, double da, double db) { 406 double a = MAX(da, db); 407 double b = MIN(da, db); 408 if (tol > a) 409 tol = a; 410 /* t = b*sqrt(tol*(2*a - tol))/(a*(a-tol)); 411 return 2*atan(t);*/ 412 return 2*acos(1-tol/a); 413 } 414 367 415 /* 368 416 * This function generates parallel line (with loops, but not like the old ones). … … 380 428 void parallel_line(struct line_pnts *Points, double da, double db, double dalpha, int side, int round, double tol, struct line_pnts *nPoints) 381 429 { 382 int i, j, res, np , na;430 int i, j, res, np; 383 431 double *x, *y; 384 double tx, ty, vx, vy, nx, ny, mx, my, rx, ry; 432 double tx, ty, vx, vy, wx, wy, nx, ny, mx, my, rx, ry; 433 double vx1, vy1, wx1, wy1; 385 434 double a0, b0, c0, a1, b1, c1; 386 double ux, uy, wx, wy; 387 double atol, atol2, a, av, aw; 435 double phi1, phi2, delta_phi; 436 double nsegments, angular_tol, angular_step; 437 double cosa, sina, r; 438 int inner_corner; 388 439 389 440 G_debug(4, "parallel_line2()"); 390 391 dalpha *= 180/PI;441 442 392 443 Vect_reset_line ( nPoints ); 393 444 … … 397 448 y = Points->y; 398 449 399 if ( np == 0)450 if ((np == 0) || (np == 1)) 400 451 return; 401 402 if ( np == 1 ) {403 /* Vect_append_point ( nPoints, x[0], y[0], 0 ); /* ? OK, should make circle for points ? */404 return;405 }406 452 407 453 if ((da == 0) && (db == 0)) { … … 410 456 } 411 457 412 side = (side >= 0)?(1):(-1); 413 /* atol = 2 * acos( 1-tol/fabs(d) ); */ 414 458 side = (side >= 0)?(1):(-1); /* normalize variable */ 459 dalpha *= PI/180; /* convert dalpha from degrees to radians */ 460 angular_tol = angular_tolerance(tol, da, db); 461 G_message("tol=%f atol=%f", tol, angular_tol); 462 415 463 for (i = 0; i < np-1; i++) 416 464 { 465 wx = vx; /* save the old values */ 466 wy = vy; 467 417 468 norm_vector(x[i], y[i], x[i+1], y[i+1], &tx, &ty); 418 elliptic_transform(-ty*side, tx*side, da, db, dalpha, &vx, &vy); 469 /* elliptic_transform(ty*side, -tx*side, da, db, dalpha, &vx, &vy); */ 470 elliptic_tangent(side*tx, side*ty, da, db, dalpha, &vx, &vy); 419 471 420 472 nx = x[i] + vx; 421 473 ny = y[i] + vy; 422 474 423 475 mx = x[i+1] + vx; 424 476 my = y[i+1] + vy; … … 430 482 } 431 483 else { 432 res = line_intersection(a0, b0, c0, a1, b1, c1, &rx, &ry); 433 if (res == 0) { 434 /* THIS ISN'T SUPPOSED TO HAPPEN, MUST THROW ERROR*/ 435 G_fatal_error(("Two consequtive line segments are parallel, but not on one straight line!\nThis should never happen.")); 436 return; 484 /* delta_phi = atan2(y[i+1]-y[i],x[i+1]-x[i]) - atan2(y[i]-y[i-1], x[i]-x[i-1])) */ 485 delta_phi = atan2(ty, tx) - atan2(y[i]-y[i-1], x[i]-x[i-1]); 486 if (delta_phi > PI) 487 delta_phi -= 2*PI; 488 else if (delta_phi <= -PI) 489 delta_phi += 2*PI; 490 /* now delta_phi is in (-pi;pi] */ 491 inner_corner = (side*delta_phi <= 0); 492 493 if ((!round) || inner_corner) { 494 res = line_intersection(a0, b0, c0, a1, b1, c1, &rx, &ry); 495 if (res == 0) { 496 /* THIS ISN'T SUPPOSED TO HAPPEN, MUST THROW ERROR*/ 497 G_fatal_error("Two consequtive line segments are parallel, but not on one straight line!\nThis should never happen."); 498 return; 499 } 500 else if (res == 1) { 501 Vect_append_point(nPoints, rx, ry, 0); 502 } 503 /* else if (res == 2) do nothing; we have line segments, which are on one straight line */ 437 504 } 438 else if (res == 1) { 439 Vect_append_point(nPoints, rx, ry, 0); 505 else { 506 /* we should draw elliptical arc for outside corner */ 507 508 /* inverse transforms */ 509 elliptic_transform(wx, wy, 1/da, 1/db, dalpha, &wx1, &wy1); 510 elliptic_transform(vx, vy, 1/da, 1/db, dalpha, &vx1, &vy1); 511 512 phi1 = atan2(wy1, wx1); 513 phi2 = atan2(vy1, vx1); 514 delta_phi = phi2 - phi1; 515 516 /* make delta_phi in [0, 2pi] */ 517 if (delta_phi < 0) 518 delta_phi += 2*PI; 519 520 nsegments = (int)(delta_phi/angular_tol) + 1; 521 angular_step = side*(delta_phi/nsegments); 522 523 for (j = 0; j <= nsegments; j++) { 524 elliptic_transform(cos(phi1), sin(phi1), da, db, dalpha, &tx, &ty); 525 Vect_append_point(nPoints, x[i] + tx, y[i] + ty, 0); 526 phi1 += angular_step; 527 } 440 528 } 441 /* else if (res == 2) do nothing */442 529 } 443 530 … … 449 536 b0 = b1; 450 537 c0 = c1; 451 452 /*453 if ( i < np-2 ) { /*use polyline instead of arc between line segments454 norm_vector( x[i+1], y[i+1], x[i+2], y[i+2], &ux, &uy);455 wx = uy * d;456 wy = -ux * d;457 av = atan2 ( vy, vx );458 aw = atan2 ( wy, wx );459 a = (aw - av) * side;460 if ( a < 0 ) a+=2*PI;461 462 /*TODO: a <= PI can probably fail because of representation error463 if ( a <= PI && a > atol)464 {465 na = (int) (a/atol);466 atol2 = a/(na+1) * side;467 for (j = 0; j < na; j++)468 {469 av+=atol2;470 nx = x[i+1] + fabs(d) * cos(av);471 ny = y[i+1] + fabs(d) * sin(av);472 Vect_append_point ( nPoints, nx, ny, 0 );473 }474 }475 }*/476 538 } 477 539 Vect_line_prune ( nPoints );
Note:
See TracChangeset
for help on using the changeset viewer.
