| 3377 | |
| 3378 | return; |
| 3379 | } // |
| 3380 | |
| 3381 | |
| 3382 | //---------------------------------------------------------------------- |
| 3383 | // vector field |
| 3384 | //---------------------------------------------------------------------- |
| 3385 | |
| 3386 | void plot_vector( std::stringstream &Content, |
| 3387 | const double arrow_origin_x, const double arrow_origin_y, |
| 3388 | const double vector_x, const double vector_y, const double vector_norm2, |
| 3389 | const double alength_scale, const double ahead_scale, |
| 3390 | const double x0, const double y0, const double scale, const double ar, |
| 3391 | const double fmin, const double fmax, |
| 3392 | const bool unit_arrow, const bool logscale, |
| 3393 | const KNM<double> &palette, const bool monochrome ) |
| 3394 | { |
| 3395 | std::stringstream &st = Content; |
| 3396 | const double &r = scale; |
| 3397 | |
| 3398 | const double &ox = arrow_origin_x; |
| 3399 | const double &oy = arrow_origin_y; |
| 3400 | |
| 3401 | const double AH_SIZE = (alength_scale > 0)? (PLOTPDFVAR::DEFAULT_ARROW_HEAD_SIZE * ahead_scale): (PLOTPDFVAR::DEFAULT_ARROW_HEAD_SIZE * (-ahead_scale)); |
| 3402 | const double &AH_ANGLE = PLOTPDFVAR::ARROW_HEAD_ANGLE; |
| 3403 | |
| 3404 | // what happen if (fmin == 0) && logscale ? |
| 3405 | const double favg = logscale? (sqrt(fmax*fmin)): (fmax+fmin)/2; |
| 3406 | |
| 3407 | // scaled arrow length is arrow_scale * cf2, which is truncated if greater than fmax |
| 3408 | const double &as = alength_scale; |
| 3409 | const double alength = (unit_arrow)? (as*favg)/fmax*PLOTPDFVAR::MAX_ARROW_LENGTH: |
| 3410 | ( (logscale)? as*(log(vector_norm2/fmin))/(log(fmax/fmin))*PLOTPDFVAR::MAX_ARROW_LENGTH: as*vector_norm2/fmax*PLOTPDFVAR::MAX_ARROW_LENGTH); |
| 3411 | |
| 3412 | // In logscale, vector_norm2 = fmin*(fmax/fmin)^r <=> r = (log(vector_norm2)-log(fmin))/(log(fmax)-log(fmin)) |
| 3413 | // Then, alength = alength_scale * r * PLOTPDFVAR::MAX_ARROW_LENGTH. |
| 3414 | |
| 3415 | const double arrow_head_x = r*ar*(ox-x0) + alength * ar*vector_x/vector_norm2; |
| 3416 | const double arrow_head_y = r*(oy-y0) + alength * vector_y/vector_norm2; |
| 3417 | |
| 3418 | setrgbcolor(st, vector_norm2, palette, fmin, fmax, monochrome, logscale); |
| 3419 | st << "RG\n"; |
| 3420 | st << r*ar*(ox-x0) << ' ' << r*(oy-y0) << " m "; // arrow origin |
| 3421 | st << arrow_head_x << ' ' << arrow_head_y << " l S" << std::endl; // arrow head |
| 3422 | |
| 3423 | // Need fabs? Yes, if coef = alength < 0, arrows go reverse direction. |
| 3424 | if( fabs(alength) > AH_SIZE/2 ){ |
| 3425 | |
| 3426 | const double theta = atan2( -vector_y, -vector_x ); // reverse of arrow direction |
| 3427 | |
| 3428 | st << arrow_head_x + AH_SIZE*cos(theta-AH_ANGLE) << ' ' << arrow_head_y + AH_SIZE*sin(theta-AH_ANGLE) << " m " |
| 3429 | << arrow_head_x << ' ' << arrow_head_y << " l " |
| 3430 | << arrow_head_x + AH_SIZE*cos(theta+AH_ANGLE) << ' ' << arrow_head_y + AH_SIZE*sin(theta+AH_ANGLE) << " l S" << std::endl; |
no test coverage detected