Changeset 31708


Ignore:
Timestamp:
Jun 13, 2008, 10:30:18 AM (16 years ago)
Author:
rmatev
Message:

Changed cmd options and implemented round corners feature

Location:
grass-addons/vector/v.parallel2
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • grass-addons/vector/v.parallel2/main.c

    r31651 r31708  
    2828    struct Option *in_opt, *out_opt, *dista_opt;
    2929    struct Option *distb_opt, *angle_opt, *side_opt;
     30    struct Option *tol_opt;
    3031    struct Flag *round_flag, *loops_flag;
    3132    struct Map_info In, Out;
     
    4748   
    4849    dista_opt = G_define_option();
    49     dista_opt->key = "dista";
     50    dista_opt->key = "distance";
    5051    dista_opt->type =  TYPE_DOUBLE;
    5152    dista_opt->required = YES;
     
    5455
    5556    distb_opt = G_define_option();
    56     distb_opt->key = "distb";
     57    distb_opt->key = "minordistance";
    5758    distb_opt->type =  TYPE_DOUBLE;
    58     distb_opt->required = YES;
     59    distb_opt->required = NO;
    5960    distb_opt->multiple = NO;
    6061    distb_opt->description = _("Offset along minor axis in map units");
     
    6364    angle_opt->key = "angle";
    6465    angle_opt->type =  TYPE_DOUBLE;
    65     angle_opt->required = YES;
     66    angle_opt->required = NO;
    6667    angle_opt->answer = "0";
    6768    angle_opt->multiple = NO;
     
    7677    side_opt->options = "left,right";
    7778    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");
    7886
    7987    round_flag = G_define_flag();
     
    9098    /* layer = atoi ( layer_opt->answer ); */
    9199    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)
    96117        side = 1;
    97     else if (strcmp(side_opt->answer, "left"))
     118    else if (strcmp(side_opt->answer, "left") == 0)
    98119        side = -1;
    99120
  • grass-addons/vector/v.parallel2/vlib_buffer.c

    r31651 r31708  
    11/* Functions: nearest, adjust_line, parallel_line
    22**
    3 ** Author: Radim Blazek Feb 2000
     3** Author: Radim Blazek, Rosen Matev; June 2008
    44**
    55**
     
    1010#include <grass/gis.h>
    1111
    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)
    1315#define PI M_PI
    1416
     
    314316#endif
    315317
     318static 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
    316324/*
    317 * (x, y) shoud be normalized vector; This func transforms it to a vector corresponding to da, db, dalpha params
     325* (x, y) shoud be normalized vector for common transforms; This func transforms it to a vector corresponding to da, db, dalpha params
    318326*/
    319327static void elliptic_transform(double x, double y, double da, double db, double dalpha, double *nx, double *ny) {
    320328    double cosa = cos(dalpha);
    321329    double sina = sin(dalpha);
    322     double cc = cosa*cosa;
     330/*    double cc = cosa*cosa;
    323331    double ss = sina*sina;
    324332    double t = (da-db)*sina*cosa;
     
    326334    *nx = (da*cc + db*ss)*x + t*y;
    327335    *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*/
     351static 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
    330368
    331369/*
     
    365403}
    366404
     405static 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
    367415/*
    368416* This function generates parallel line (with loops, but not like the old ones).
     
    380428void parallel_line(struct line_pnts *Points, double da, double db, double dalpha, int side, int round, double tol, struct line_pnts *nPoints)
    381429{
    382     int i, j, res, np, na;
     430    int i, j, res, np;
    383431    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;
    385434    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;
    388439
    389440    G_debug(4, "parallel_line2()");
    390 
    391     dalpha *= 180/PI;
     441   
     442   
    392443    Vect_reset_line ( nPoints );
    393444
     
    397448    y = Points->y;
    398449
    399     if ( np == 0 )
     450    if ((np == 0) || (np == 1))
    400451        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     }
    406452
    407453    if ((da == 0) && (db == 0)) {
     
    410456    }
    411457
    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   
    415463    for (i = 0; i < np-1; i++)
    416464    {
     465        wx = vx; /* save the old values */
     466        wy = vy;
     467       
    417468        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);
    419471       
    420472        nx = x[i] + vx;
    421473        ny = y[i] + vy;
    422            
     474       
    423475        mx = x[i+1] + vx;
    424476        my = y[i+1] + vy;
     
    430482        }
    431483        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 */
    437504            }
    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                }
    440528            }
    441             /* else if (res == 2) do nothing */
    442529        }
    443530       
     
    449536        b0 = b1;
    450537        c0 = c1;
    451        
    452     /*   
    453         if ( i < np-2 ) {   /*use polyline instead of arc between line segments
    454             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 error
    463             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         }*/
    476538    }
    477539    Vect_line_prune ( nPoints );
Note: See TracChangeset for help on using the changeset viewer.