------------------------------------------------------------------------ Function to create a custom hatch symbol based on an arbitrary angle. ------------------------------------------------------------------------
| 846 | // Function to create a custom hatch symbol based on an arbitrary angle. |
| 847 | // ------------------------------------------------------------------------ |
| 848 | static mapserver::path_storage createHatch(int sx, int sy, double angle, double step) |
| 849 | { |
| 850 | mapserver::path_storage path; |
| 851 | //path.start_new_path(); |
| 852 | //restrict the angle to [0 180[ |
| 853 | angle = fmod(angle, 360.0); |
| 854 | if(angle < 0) angle += 360; |
| 855 | if(angle >= 180) angle -= 180; |
| 856 | |
| 857 | //treat 2 easy cases which would cause divide by 0 in generic case |
| 858 | if(angle==0) { |
| 859 | for(double y=step/2.0;y<sy;y+=step) { |
| 860 | path.move_to(0,y); |
| 861 | path.line_to(sx,y); |
| 862 | } |
| 863 | return path; |
| 864 | } |
| 865 | if(angle==90) { |
| 866 | for(double x=step/2.0;x<sx;x+=step) { |
| 867 | path.move_to(x,0); |
| 868 | path.line_to(x,sy); |
| 869 | } |
| 870 | return path; |
| 871 | } |
| 872 | |
| 873 | |
| 874 | double theta = (90-angle)*MS_DEG_TO_RAD; |
| 875 | double ct = cos(theta); |
| 876 | double st = sin(theta); |
| 877 | double rmax = sqrt((double)sx*sx+sy*sy); |
| 878 | |
| 879 | //parametrize each line as r = x.cos(theta) + y.sin(theta) |
| 880 | for(double r=(angle<90)?step/2.:-rmax;r<rmax;r+=step) { |
| 881 | int inter=0; |
| 882 | double x,y; |
| 883 | double pt[8]; //array to store the coordinates of intersection of the line with the sides |
| 884 | //in the general case there will only be two intersections |
| 885 | //so pt[4] should be sufficient to store the coordinates of the intersection, |
| 886 | //but we allocate pt[8] to treat the special and rare/unfortunate case when the |
| 887 | //line is a perfect diagonal (and therfore intersects all four sides) |
| 888 | //note that the order for testing is important in this case so that the first |
| 889 | //two intersection points actually correspond to the diagonal and not a degenerate line |
| 890 | |
| 891 | //test for intersection with each side |
| 892 | |
| 893 | y=r/st;x=0; // test for intersection with top of image |
| 894 | if(y>=0&&y<=sy) { |
| 895 | pt[2*inter]=x;pt[2*inter+1]=y; |
| 896 | inter++; |
| 897 | } |
| 898 | x=sx;y=(r-sx*ct)/st;// test for intersection with bottom of image |
| 899 | if(y>=0&&y<=sy) { |
| 900 | pt[2*inter]=x;pt[2*inter+1]=y; |
| 901 | inter++; |
| 902 | } |
| 903 | y=0;x=r/ct;// test for intersection with left of image |
| 904 | if(x>=0&&x<=sx) { |
| 905 | pt[2*inter]=x;pt[2*inter+1]=y; |
no test coverage detected