/* compute true world co-ordinate of a pixel * RrowCol2Coords computes the true world co-ordinate from a * row, column index. * The row, column co-ordinate * don't have to be on the map. They are just relative to upper left position. * For example (row,col) = (-1,0) computes the (x,y) co-ordinate of * the pixel that is right above upper left pixel. * * returns * 0 if the co-ordinate is outside the map. * 1 if inside. * -1 in case of an error. * * Merrno * ILL_CELLSIZE */ int RgetCoords( const MAP *m, /* map handle */ int inCellPos, /* nonzero if you want the co-ordinate * at the centre of the cell, 0 if you * want the upper left co-ordinate of the cell */ size_t row, /* Row number (relates to y position). */ size_t col, /* Column number (relates to x position). */ double *x, /* write-only. Returns x of true co-ordinate */ double *y) /* write-only. Returns y of true co-ordinate */ { return RrowCol2Coords(m, (double)row+(inCellPos ? 0.5 : 0.0), (double)col+(inCellPos ? 0.5 : 0.0), x,y); }
/* Calculates one pixel from output map, given the input maps. * Puts all values of input pixels in a list and determines the value of * the output pixel according to these values and the overlapping areas. * Returns 0 if no error occurs, 1 otherwise. */ static int CalcPixel( MAP *out, /* write-only output map */ MAP **in, /* read-only list input maps */ size_t nrCoverCells, /* min. nr. non-MV cells for non-MV */ size_t nrMaps, /* nr. of input maps */ double rOut, /* row number pixel */ double cOut, /* column number pixel */ BOOL aligned, /* maps are aligned */ REAL8 angle) /* angle of output map */ { PTYPE tlX, tlY, trX, trY, brX, brY, blX, blY; double r, c; DATA *list = NULL; /* areas and values of input cells */ size_t i, nrList = 0; /* number of items in list */ POINT2D *outputCell; /* polygon of output cell */ size_t nr = 4; /* nr of points of cell */ CSF_VS vs; /* value scale of first input map */ if(nrCoverCells > 0 && nrMaps > 1) raster = InitRaster(raster); /* initialize the raster */ /* Determine the four corners of output pixel */ RrowCol2Coords(out, rOut, cOut, &tlX, &tlY); /* top left */ RrowCol2Coords(out, rOut, cOut + 1, &trX, &trY); /* top right */ RrowCol2Coords(out, rOut + 1, cOut, &blX, &blY); /* bottom left */ RrowCol2Coords(out, rOut + 1, cOut + 1, &brX, &brY); /* bottom right */ outputCell = PutInPol(tlX, tlY, trX, trY, brX, brY, blX, blY); if(outputCell == NULL) return 1; POSTCOND(outputCell[0].x == outputCell[nr].x); POSTCOND(outputCell[0].y == outputCell[nr].y); /* Get pixel on every input map */ for(i = 0; i < nrMaps; i++) { MAP *X = in[i]; /* input map number i */ PTYPE tlC, tlR, trC, trR, brC, brR, blC, blR; PTYPE tlX2, tlY2, trX2, trY2, brX2, brY2, blX2, blY2; double leftB, belowB, rightB, upperB; /* boundaries */ /* Corners: (tlX, tlY), (trX, trY), (blX, blY) and * (brX, brY). Translate for input map. */ Rcoords2RowCol(X, tlX, tlY, &tlC, &tlR); /* top left */ Rcoords2RowCol(X, trX, trY, &trC, &trR); /* top right */ Rcoords2RowCol(X, blX, blY, &blC, &blR); /* bottom left */ Rcoords2RowCol(X, brX, brY, &brC, &brR); /* bottom right */ /* Boundaries in the input map */ rightB = ceil(MaxPoint(tlR, trR, blR, brR)); belowB = ceil(MaxPoint(tlC, trC, blC, brC)); leftB = floor(MinPoint(tlR, trR, blR, brR)); upperB = floor(MinPoint(tlC, trC, blC, brC)); PRECOND(upperB <= belowB); PRECOND(leftB <= rightB); /* Check all cells between the boundaries */ for(r = upperB; r < belowB; r++) { REAL8 *currRow; if(0 <= r && r <= RgetNrRows(X)) currRow = (REAL8 *)CacheGetRow(in, i, r); for(c = leftB; c < rightB; c++) { /* Cells that might be in pixel */ POINT2D *inputCell; /* polygon input cell */ if(r < 0 || RgetNrRows(X) <= r || c < 0 || RgetNrCols(X) <= c) continue; /* Top left & right, bottom left & right */ RrowCol2Coords(X, r, c, &tlX2, &tlY2); RrowCol2Coords(X, r, c+1, &trX2, &trY2); RrowCol2Coords(X, r+1, c, &blX2, &blY2); RrowCol2Coords(X, r+1, c+1, &brX2, &brY2); inputCell = PutInPol(tlX2, tlY2, trX2, trY2, brX2, brY2, blX2, blY2); if(inputCell == NULL) return 1; POSTCOND(inputCell[0].x == inputCell[nr].x); POSTCOND(inputCell[0].y == inputCell[nr].y); /* Add item to list for cell */ if(AddCell(&list, raster, &nrList, inputCell, outputCell, currRow, X, nrMaps, (size_t)c, nrCoverCells, aligned, angle)) return 1; Free(inputCell); /* deallocate */ } } } /* calculate output value of pixel according value scale */ vs = RgetValueScale(in[0]); if(vs != VS_DIRECTION) CalcScalarOut(out, (size_t)rOut, (size_t)cOut, nrList, list, nrCoverCells, nrMaps); else CalcDirectionOut(out, (size_t) rOut, (size_t) cOut, nrList, list, nrCoverCells, nrMaps); Free(outputCell); /* deallocate */ Free(list); /* deallocate */ return 0; /* successfully terminated */ }
/* Determines smallest rectangle around nonMv values. * The border value can be added around this rectangle. * Returns x0, y0 , nrRows and nrCols for out. */ static int SmallestNonMVRect( REAL8 *X0out, /* write-only X0 */ REAL8 *Y0out, /* write-only Y0 */ size_t *nrRows, /* write-only nr of rows */ size_t *nrCols, /* write-only nr of columns */ MAP **in, /* read-only pointer in maps */ int borderValue, /* border value */ size_t nrMaps, /* number of input maps */ CSF_VS valueScale, /* value scale of output map */ REAL8 cellSize, /* cellSize of map */ REAL8 angle, /* angle of output map */ CSF_PT projection, /* projection of output map */ BOOL contract) /* map should be contracted */ { size_t i; POINT2D leftUpperC, leftLowerC, rightUpperC, rightLowerC; REAL8 upperB=0, leftB=0, rightB=0, belowB=0; /* ^- shut up about use before def */ for(i = 0; i < nrMaps; i++) { MAP *X = in[i]; BOOL first = TRUE; POINT2D polygon[4]; size_t r, c; size_t nrR = RgetNrRows(X); size_t nrC = RgetNrCols(X); for(r = 0; r < nrR; r++) for(c = 0; c < nrC; c++) { INT4 int4Val; REAL8 real8Val; if((AppIsClassified(valueScale) && RgetCell(in[i], r, c, &int4Val) && int4Val != MV_INT4) || (!AppIsClassified(valueScale) && RgetCell(in[i], r, c, &real8Val) && (IsMV(in[i], &real8Val) == FALSE))) { if(first || c < leftB) leftB = c; if(first || c > rightB) rightB = c; if(first || r > belowB) belowB = r; if(first || r < upperB) upperB = r; first = FALSE; } } /* Get coordinates of corners */ RrowCol2Coords(X, upperB, leftB, &polygon[0].x, &polygon[0].y); RrowCol2Coords(X, upperB, rightB + 1 - EPSILON, &polygon[1].x, &polygon[1].y); RrowCol2Coords(X, belowB + 1 - EPSILON, leftB, &polygon[2].x, &polygon[2].y); RrowCol2Coords(X, belowB + 1 - EPSILON, rightB + 1 - EPSILON, &polygon[3].x, &polygon[3].y); /* Rotate all corners of map */ if(angle != 0) { for(c = 0; c < 4; c++) polygon[c] = *RotPoint(polygon + c, angle); } /* Determine boundaries of rotated output map */ for(c = 0; c < 4; c++) { if(polygon[c].y > belowB || (i == 0 && c == 0)) belowB = polygon[c].y; if(polygon[c].y < upperB || (i == 0 && c == 0)) upperB = polygon[c].y; if(polygon[c].x > rightB || (i == 0 && c == 0)) rightB = polygon[c].x; if(polygon[c].x < leftB || (i == 0 && c == 0)) leftB = polygon[c].x; } } leftUpperC.x = leftB; rightUpperC.x = rightB; leftLowerC.x = leftB; rightLowerC.x = rightB; if(projection == PT_YINCT2B) { leftUpperC.y = upperB; rightUpperC.y = upperB; leftLowerC.y = belowB; rightLowerC.y = belowB; } else { leftUpperC.y = belowB; rightUpperC.y = belowB; leftLowerC.y = upperB; rightLowerC.y = upperB; } CalcBound(X0out, Y0out, nrRows, nrCols, &leftUpperC, &rightUpperC, &leftLowerC, &rightLowerC, borderValue, cellSize, angle, projection, contract); return 0; }
/* Determines the smallest fitting rectangle around input maps. * The bordervalue is added. * Returns x0, y0, nrRows and nrCols for out. */ static int SmallestFittingRectangle( REAL8 *X0out, /* write-only X0 */ REAL8 *Y0out, /* write-only Y0 */ size_t *nrRows, /* write-only nr of rows */ size_t *nrCols, /* write-only nr of columns */ MAP **in, /* read-only pointer to input maps */ int borderValue, /* bordervalue */ size_t nrMaps, /* number of input maps */ REAL8 cellSize, /* cell size of output map */ REAL8 angle, /* angle of output map */ CSF_PT projection, /* projection of output map */ BOOL contract) /* map should be contracted */ { size_t i; REAL8 upperB=0, leftB=0, rightB=0, belowB=0; /* ^- shut up about use before def */ POINT2D leftUpperC, rightUpperC, leftLowerC, rightLowerC; /* determine the boundaries for every map */ for(i = 0; i < nrMaps; i++) { MAP *X = in[i]; int c; POINT2D polygon[4]; /* rectangle */ REAL8 X0 = RgetX0(X); REAL8 Y0 = RgetY0(X); REAL8 nrR = (REAL8) RgetNrRows(X); REAL8 nrC = (REAL8) RgetNrCols(X); /* transform corners of map into x- and y-coordinates */ polygon[0].x = X0; polygon[0].y = Y0; RrowCol2Coords(X, 0.0, nrC - EPSILON, &polygon[1].x, &polygon[1].y); RrowCol2Coords(X, nrR - EPSILON, nrC - EPSILON, &polygon[2].x, &polygon[2].y); RrowCol2Coords(X, nrR - EPSILON, 0.0, &polygon[3].x, &polygon[3].y); /* Rotate all corners of map */ if(angle != 0) for(c = 0; c < 4; c++) RotPoint(polygon + c, angle); /* Determine boundaries of rotated output map */ for(c = 0; c < 4; c++) { if((i==0&&c==0)||polygon[c].y > belowB) belowB = polygon[c].y; if((i==0&&c==0)||polygon[c].y < upperB) upperB = polygon[c].y; if((i==0&&c==0)||polygon[c].x > rightB) rightB = polygon[c].x; if((i==0&&c==0)||polygon[c].x < leftB) leftB = polygon[c].x; } } /* Put boundaries in corners of the rotated map */ leftUpperC.x = leftB; rightUpperC.x = rightB; leftLowerC.x = leftB; rightLowerC.x = rightB; if(projection == PT_YINCT2B) { leftUpperC.y = upperB; rightUpperC.y = upperB; leftLowerC.y = belowB; rightLowerC.y = belowB; } else { leftUpperC.y = belowB; rightUpperC.y = belowB; leftLowerC.y = upperB; rightLowerC.y = upperB; } /* calculate the boundary of the output map */ CalcBound(X0out, Y0out, nrRows, nrCols, &leftUpperC, &rightUpperC, &leftLowerC, &rightLowerC, borderValue, cellSize, angle, projection, contract); return 0; }