824
** converts from map coordinates to image coordinates
826
void msTransformShapeToPixel(shapeObj *shape, rectObj extent, double cellsize)
828
int i,j,k; /* loop counters */
829
double inv_cs = 1.0 / cellsize; /* invert and multiply much faster */
831
if(shape->numlines == 0) return; /* nothing to transform */
833
if(shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON) { /* remove duplicate vertices */
834
for(i=0; i<shape->numlines; i++) { /* for each part */
835
shape->line[i].point[0].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[0].x, extent.minx, inv_cs);
836
shape->line[i].point[0].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[0].y, extent.maxy, inv_cs);
837
for(j=1, k=1; j < shape->line[i].numpoints; j++ ) {
838
shape->line[i].point[k].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[j].x, extent.minx, inv_cs);
839
shape->line[i].point[k].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[j].y, extent.maxy, inv_cs);
840
if(shape->line[i].point[k].x!=shape->line[i].point[k-1].x || shape->line[i].point[k].y!=shape->line[i].point[k-1].y)
843
shape->line[i].numpoints = k; /* save actual number kept */
845
} else { /* points or untyped shapes */
846
for(i=0; i<shape->numlines; i++) { /* for each part */
847
for(j=1; j < shape->line[i].numpoints; j++ ) {
848
shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[j].x, extent.minx, inv_cs);
849
shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[j].y, extent.maxy, inv_cs);
828
void msTransformShapeSimplify(shapeObj *shape, rectObj extent, double cellsize)
830
int i,j,k,beforelast; /* loop counters */
833
double inv_cs = 1.0 / cellsize; /* invert and multiply much faster */
834
if(shape->numlines == 0) return; /* nothing to transform */
836
if(shape->type == MS_SHAPE_LINE) {
838
* loop through the shape's lines, and do naive simplification
839
* to discard the points that are too close to one another.
840
* currently the threshold is to discard points if they fall
841
* less than a pixel away from their predecessor.
842
* the simplified line is guaranteed to contain at
843
* least its first and last point
845
for(i=0; i<shape->numlines; i++) { /* for each part */
846
if(shape->line[i].numpoints<2) {
847
shape->line[i].numpoints=0;
848
continue; /*skip degenerate lines*/
850
point=shape->line[i].point;
851
/*always keep first point*/
852
point[0].x = MS_MAP2IMAGE_X_IC_DBL(point[0].x, extent.minx, inv_cs);
853
point[0].y = MS_MAP2IMAGE_Y_IC_DBL(point[0].y, extent.maxy, inv_cs);
854
beforelast=shape->line[i].numpoints-1;
855
for(j=1,k=1; j < beforelast; j++ ) { /*loop from second point to first-before-last point*/
856
point[k].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs);
857
point[k].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs);
858
dx=(point[k].x-point[k-1].x);
859
dy=(point[k].y-point[k-1].y);
863
/*try to keep last point*/
864
point[k].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs);
865
point[k].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs);
866
/*discard last point if equal to the one before it*/
867
if(point[k].x!=point[k-1].x || point[k].y!=point[k-1].y) {
868
shape->line[i].numpoints=k+1;
870
shape->line[i].numpoints=k;
872
//skip degenerate line once more
873
if(shape->line[i].numpoints<2)
874
shape->line[i].numpoints=0;
877
else if(shape->type == MS_SHAPE_POLYGON) {
879
* loop through the shape's lines, and do naive simplification
880
* to discard the points that are too close to one another.
881
* currently the threshold is to discard points if they fall
882
* less than a pixel away from their predecessor.
883
* the simplified polygon is guaranteed to contain at
884
* least its first, second and last point
886
for(i=0; i<shape->numlines; i++) { /* for each part */
887
if(shape->line[i].numpoints<3) {
888
shape->line[i].numpoints=0;
889
continue; /*skip degenerate lines*/
891
point=shape->line[i].point;
892
/*always keep first and second point*/
893
point[0].x = MS_MAP2IMAGE_X_IC_DBL(point[0].x, extent.minx, inv_cs);
894
point[0].y = MS_MAP2IMAGE_Y_IC_DBL(point[0].y, extent.maxy, inv_cs);
895
point[1].x = MS_MAP2IMAGE_X_IC_DBL(point[1].x, extent.minx, inv_cs);
896
point[1].y = MS_MAP2IMAGE_Y_IC_DBL(point[1].y, extent.maxy, inv_cs);
897
beforelast=shape->line[i].numpoints-1;
898
for(j=2,k=2; j < beforelast; j++ ) { /*loop from second point to first-before-last point*/
899
point[k].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs);
900
point[k].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs);
901
dx=(point[k].x-point[k-1].x);
902
dy=(point[k].y-point[k-1].y);
906
/*always keep last point*/
907
point[k].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs);
908
point[k].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs);
909
shape->line[i].numpoints=k+1;
912
else { /* only for untyped shapes, as point layers don't go through this function */
913
for(i=0; i<shape->numlines; i++) {
914
point=shape->line[i].point;
915
for(j=0;j<shape->line[i].numpoints;j++) {
916
point[j].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs);
917
point[j].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs);
924
* Generic function to transorm the shape coordinates to output coordinates
926
void msTransformShape(shapeObj *shape, rectObj extent, double cellsize, imageObj *image)
928
if (image != NULL && MS_RENDERER_PLUGIN(image->format)) {
929
rendererVTableObj *renderer = MS_IMAGE_RENDERER(image);
930
if(renderer->transform_mode == MS_TRANSFORM_SNAPTOGRID) {
931
msTransformShapeToPixelSnapToGrid(shape, extent, cellsize, renderer->approximation_scale);
932
} else if(renderer->transform_mode == MS_TRANSFORM_SIMPLIFY) {
933
msTransformShapeSimplify(shape, extent, cellsize);
934
} else if(renderer->transform_mode == MS_TRANSFORM_ROUND) {
935
msTransformShapeToPixelRound(shape, extent, cellsize);
936
} else if(renderer->transform_mode == MS_TRANSFORM_FULLRESOLUTION) {
937
msTransformShapeToPixelDoublePrecision(shape,extent,cellsize);
938
} else if(renderer->transform_mode == MS_TRANSFORM_NONE) {
942
/* unknown, do nothing */
945
msTransformShapeToPixelRound(shape, extent, cellsize);
948
void msTransformShapeToPixelSnapToGrid(shapeObj *shape, rectObj extent, double cellsize, double grid_resolution)
950
int i,j,k; /* loop counters */
952
if(shape->numlines == 0) return;
953
inv_cs = 1.0 / cellsize; /* invert and multiply much faster */
956
if(shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON) { /* remove duplicate vertices */
957
for(i=0; i<shape->numlines; i++) { /* for each part */
959
double x0,y0,x1,y1,x2,y2;
960
/*do a quick heuristic: will we risk having a degenerate shape*/
961
if(shape->type == MS_SHAPE_LINE) {
962
/*a line is degenerate if it has a single pixel. we check that the first and last pixel are different*/
963
x0 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[0].x, extent.minx, inv_cs, grid_resolution);
964
y0 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[0].y, extent.maxy, inv_cs, grid_resolution);
965
x1 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[shape->line[i].numpoints-1].x, extent.minx, inv_cs, grid_resolution);
966
y1 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[shape->line[i].numpoints-1].y, extent.maxy, inv_cs, grid_resolution);
967
if(x0 == x1 && y0 == y1) {
970
} else if(shape->type == MS_SHAPE_POLYGON) {
971
x0 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[0].x, extent.minx, inv_cs, grid_resolution);
972
y0 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[0].y, extent.maxy, inv_cs, grid_resolution);
973
x1 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3].x, extent.minx, inv_cs, grid_resolution);
974
y1 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3].y, extent.maxy, inv_cs, grid_resolution);
975
x2 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3*2].x, extent.minx, inv_cs, grid_resolution);
976
y2 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3*2].y, extent.maxy, inv_cs, grid_resolution);
977
if((x0 == x1 && y0 == y1) ||
978
(x0 == x2 && y0 == y2) ||
979
(x1 == x2 && y1 == y2)) {
984
shape->line[i].point[0].x = x0;
985
shape->line[i].point[0].y = y0;
986
for(j=1, k=1; j < shape->line[i].numpoints; j++ ) {
987
shape->line[i].point[k].x = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[j].x, extent.minx, inv_cs, grid_resolution);
988
shape->line[i].point[k].y = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[j].y, extent.maxy, inv_cs, grid_resolution);
989
if(shape->line[i].point[k].x!=shape->line[i].point[k-1].x || shape->line[i].point[k].y!=shape->line[i].point[k-1].y)
992
shape->line[i].numpoints=k;
994
if(shape->type == MS_SHAPE_LINE) {
995
shape->line[i].point[0].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[0].x, extent.minx, inv_cs);
996
shape->line[i].point[0].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[0].y, extent.maxy, inv_cs);
997
shape->line[i].point[1].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[shape->line[i].numpoints-1].x, extent.minx, inv_cs);
998
shape->line[i].point[1].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[shape->line[i].numpoints-1].y, extent.maxy, inv_cs);
999
shape->line[i].numpoints = 2;
1001
for(j=0; j < shape->line[i].numpoints; j++ ) {
1002
shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[j].x, extent.minx, inv_cs);
1003
shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[j].y, extent.maxy, inv_cs);
1008
} else { /* points or untyped shapes */
1009
for(i=0; i<shape->numlines; i++) { /* for each part */
1010
for(j=1; j < shape->line[i].numpoints; j++ ) {
1011
shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[j].x, extent.minx, inv_cs);
1012
shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[j].y, extent.maxy, inv_cs);
1019
void msTransformShapeToPixelRound(shapeObj *shape, rectObj extent, double cellsize)
1021
int i,j,k; /* loop counters */
1023
if(shape->numlines == 0) return;
1024
inv_cs = 1.0 / cellsize; /* invert and multiply much faster */
1025
if(shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON) { /* remove duplicate vertices */
1026
for(i=0; i<shape->numlines; i++) { /* for each part */
1027
shape->line[i].point[0].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[0].x, extent.minx, inv_cs);;
1028
shape->line[i].point[0].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[0].y, extent.maxy, inv_cs);
1029
for(j=1, k=1; j < shape->line[i].numpoints; j++ ) {
1030
shape->line[i].point[k].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[j].x, extent.minx, inv_cs);
1031
shape->line[i].point[k].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[j].y, extent.maxy, inv_cs);
1032
if(shape->line[i].point[k].x!=shape->line[i].point[k-1].x || shape->line[i].point[k].y!=shape->line[i].point[k-1].y)
1035
shape->line[i].numpoints=k;
1037
} else { /* points or untyped shapes */
1038
for(i=0; i<shape->numlines; i++) { /* for each part */
1039
for(j=1; j < shape->line[i].numpoints; j++ ) {
1040
shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[j].x, extent.minx, inv_cs);
1041
shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[j].y, extent.maxy, inv_cs);
1048
void msTransformShapeToPixelDoublePrecision(shapeObj *shape, rectObj extent, double cellsize)
1050
int i,j; /* loop counters */
1051
double inv_cs = 1.0 / cellsize; /* invert and multiply much faster */
1052
for(i=0; i<shape->numlines; i++) {
1053
for(j=0;j<shape->line[i].numpoints;j++) {
1054
shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[j].x, extent.minx, inv_cs);
1055
shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[j].y, extent.maxy, inv_cs);
856
1063
** Converts from map coordinates to image coordinates