| 1 | // vectorshp.cpp : Defines the entry point for the console application.
|
|---|
| 2 | //
|
|---|
| 3 |
|
|---|
| 4 | #include <iostream>
|
|---|
| 5 | #include <tchar.h>
|
|---|
| 6 | #include <math.h>
|
|---|
| 7 | #include <windows.h>
|
|---|
| 8 |
|
|---|
| 9 | #include "shapefil.h"
|
|---|
| 10 |
|
|---|
| 11 | const DWORD BUF_SIZE = 256*1024;
|
|---|
| 12 |
|
|---|
| 13 | enum DataType { Int8_DataType, Uint8_DataType, Int16_DataType, Uint16_DataType, Int32_DataType, Float_DataType, Double_DataType, };
|
|---|
| 14 |
|
|---|
| 15 | const int DataTypeSizes[] = {1, 1, 2, 2, 4, 4, 8 };
|
|---|
| 16 |
|
|---|
| 17 | static void PrintUsage()
|
|---|
| 18 | {
|
|---|
| 19 | // Do not extend strings past column 91, so they come out properly
|
|---|
| 20 | // in an 80-column CMD shell window.
|
|---|
| 21 |
|
|---|
| 22 | printf("NAME\n");
|
|---|
| 23 | printf("\n");
|
|---|
| 24 | printf(" vectorshp - creates an ESRI shapefile of vectors from two 32-bit floating\n");
|
|---|
| 25 | printf(" point binary rasters that represent x and y components\n");
|
|---|
| 26 | printf("\n");
|
|---|
| 27 | printf("SYNOPSIS\n");
|
|---|
| 28 | printf("\n");
|
|---|
| 29 | printf(" vectorshp xbinary ybinary outfile datatype cols rows cellsize xllcorner\n");
|
|---|
| 30 | printf(" yllcorner [options...]\n");
|
|---|
| 31 | printf("\n");
|
|---|
| 32 | printf(" xbinary Binary raster representing the x components\n");
|
|---|
| 33 | printf(" ybinary Binary raster representing the y components\n");
|
|---|
| 34 | printf(" outfile Shapefile to create (must not exist already)\n");
|
|---|
| 35 | printf(" datatype Data type of the binary rasters, one of: int8, uint8, int16,\n");
|
|---|
| 36 | printf(" uint16, int32, float, or double\n");
|
|---|
| 37 | printf(" cols Number of columns in the binary files\n");
|
|---|
| 38 | printf(" rows Number of rows in the binary files\n");
|
|---|
| 39 | printf(" cellsize Cell size of the binary files\n");
|
|---|
| 40 | printf(" xllcorner X coordinate of the lower left corner of the binary files\n");
|
|---|
| 41 | printf(" yllcorner Y coordinate of the lower left corner of the binary files\n");
|
|---|
| 42 | printf("\n");
|
|---|
| 43 | printf("DESCRIPTION\n");
|
|---|
| 44 | printf("\n");
|
|---|
| 45 | printf(" vectorshp accepts as input two binary rasters having the same data type\n");
|
|---|
| 46 | printf(" and dimensions. The first raster represents the X component of vectors\n");
|
|---|
| 47 | printf(" and the second represents the Y component. vectorshp outputs an ESRI\n");
|
|---|
| 48 | printf(" shapefile containing lines representing the vectors. The shapefile is\n");
|
|---|
| 49 | printf(" useful for visualizing vector fields, like a quiver plot in matlab. In\n");
|
|---|
| 50 | printf(" oceanography, vectorshp has been used to visualize geostrophic currents\n");
|
|---|
| 51 | printf(" estimated from sea surface height data and sea surface winds estimated by\n");
|
|---|
| 52 | printf(" the QuickSCAT satellite.\n");
|
|---|
| 53 | printf("\n");
|
|---|
| 54 | printf(" The output shapefile contains two attributes, Magnitude and Direction,\n");
|
|---|
| 55 | printf(" which describe the vector in a polar coordinate system. Magnitude is in\n");
|
|---|
| 56 | printf(" the units of the original X and Y components. Direction is in degrees,\n");
|
|---|
| 57 | printf(" with 0 being due east, +90 due north, -90 due south, and +180 being due\n");
|
|---|
| 58 | printf(" west.\n");
|
|---|
| 59 | printf("\n");
|
|---|
| 60 | printf(" The lines originate at the coordinates of the centers of the raster\n");
|
|---|
| 61 | printf(" cells, allowing you to overlay the shapefile on the original rasters.\n");
|
|---|
| 62 | printf("\n");
|
|---|
| 63 | printf(" A special situation arises when your rasters are in a geographic\n");
|
|---|
| 64 | printf(" projection but the vector components are in something other than degrees.\n");
|
|---|
| 65 | printf(" For example, Aviso produces geostrophic current rasters projected in the\n");
|
|---|
| 66 | printf(" Topex/Poseidon geographic projection with 0.25 degree cell size. The\n");
|
|---|
| 67 | printf(" cells give current velocity in cm/s. You must consider three things when\n");
|
|---|
| 68 | printf(" you create vector shapefiles.\n");
|
|---|
| 69 | printf("\n");
|
|---|
| 70 | printf(" First, the length of shapefile lines are computed as cm/s using simple\n");
|
|---|
| 71 | printf(" Pythagorean math. They are not computed as degrees/s, even though the\n");
|
|---|
| 72 | printf(" shapefile is in a geographic projection, not a cartesian projection\n");
|
|---|
| 73 | printf(" such as Albers Equal Area. As a result, a 2 cm/s vector will span 2\n");
|
|---|
| 74 | printf(" degrees. The current is clearly not moving at 2 degrees/s. If you want\n");
|
|---|
| 75 | printf(" the lines to be scaled according to the projection, you must first\n");
|
|---|
| 76 | printf(" project your input rasters to a cartesian system that uses the same\n");
|
|---|
| 77 | printf(" units as the vector components (e.g. Albers Equal Area with cm units).\n");
|
|---|
| 78 | printf("\n");
|
|---|
| 79 | printf(" Second, depending on the cell size of and units of your rasters, the\n");
|
|---|
| 80 | printf(" shapefile lines may be excessively long, resulting in a scrambled mess.\n");
|
|---|
| 81 | printf(" Use the -s option to reduce the length of the lines. For example, for\n");
|
|---|
| 82 | printf(" Aviso geostrophic currents, I typically use -s 0.01.\n");
|
|---|
| 83 | printf("\n");
|
|---|
| 84 | printf(" Finally, vectorshp does not define the ArcGIS projection of the\n");
|
|---|
| 85 | printf(" shapefile. You must do this yourself (or wrap vectorshp in a\n");
|
|---|
| 86 | printf(" geoprocessing script, as is done by Marine Geospatial Ecology Tools).\n");
|
|---|
| 87 | printf(" After defining the projection and loading the shapefiles into ArcMap, you\n");
|
|---|
| 88 | printf(" will get a warning saying the shapefile extends beyond the normal extent\n");
|
|---|
| 89 | printf(" for geographic projections (+/-180 longitude, +/- 90 latitude). This is\n");
|
|---|
| 90 | printf(" not a problem; it is expected.\n");
|
|---|
| 91 | printf("\n");
|
|---|
| 92 | printf("OPTIONS\n");
|
|---|
| 93 | printf("\n");
|
|---|
| 94 | printf(" -n val Specifies that val is the \"NODATA\" value. Lines will not be\n");
|
|---|
| 95 | printf(" created if either the X or Y component has this value.\n");
|
|---|
| 96 | printf("\n");
|
|---|
| 97 | printf(" -s fac Specifies that lines should be scaled by fac (for example,\n");
|
|---|
| 98 | printf(" -s 10 will create lines 10 times longer than normal). Use\n");
|
|---|
| 99 | printf(" this option to create vectors that can be overlaid on maps\n");
|
|---|
| 100 | printf(" without appearing too cluttered or too small to be visible.\n");
|
|---|
| 101 | printf(" The -s option does not affect the Magnitude attribute of the\n");
|
|---|
| 102 | printf(" lines; that attribute will still contain the unscaled values.\n");
|
|---|
| 103 | printf("\n");
|
|---|
| 104 | printf(" -u Specifies that lengths of the lines should not be\n");
|
|---|
| 105 | printf(" proportional to the magnitude; instead, all lines will have\n");
|
|---|
| 106 | printf(" the same length. By default, this will be the cell size. If\n");
|
|---|
| 107 | printf(" the -s parameter is also specified, it scales this length\n");
|
|---|
| 108 | printf(" (e.g. -s 0.5 will create lines with a length of 1/2 of the\n");
|
|---|
| 109 | printf(" cell size. The -u parameter does not affect the Magnitude\n");
|
|---|
| 110 | printf(" attribute of the lines; that attribute will still contain the.\n");
|
|---|
| 111 | printf(" unscaled magnitude of each line.\n");
|
|---|
| 112 | printf("\n");
|
|---|
| 113 | printf("RELEASE HISTORY\n");
|
|---|
| 114 | printf("\n");
|
|---|
| 115 | printf(" 1.1.0 (3-Feb-2012) - Added -u option.\n");
|
|---|
| 116 | printf(" 1.0.0 (2-Aug-2006) - Initial version.\n");
|
|---|
| 117 | printf("\n");
|
|---|
| 118 | printf("COPYRIGHT AND LICENSE\n");
|
|---|
| 119 | printf("\n");
|
|---|
| 120 | printf(" Copyright (c) 2012 Jason J. Roberts.\n");
|
|---|
| 121 | printf("\n");
|
|---|
| 122 | printf(" Compiled with portions of shapelib 1.2.10 Copyright (c) 1999, Frank\n");
|
|---|
| 123 | printf(" Warmerdam.\n");
|
|---|
| 124 | printf("\n");
|
|---|
| 125 | printf(" Thanks Frank, and to your contributors, for a great library!\n");
|
|---|
| 126 | printf("\n");
|
|---|
| 127 | printf(" Permission is hereby granted, free of charge, to any person obtaining a\n");
|
|---|
| 128 | printf(" copy of this software (the \"Software\"), to deal in the Software without\n");
|
|---|
| 129 | printf(" restriction, including without limitation the rights to use, copy, modify,\n");
|
|---|
| 130 | printf(" merge, publish, distribute, sublicense, and/or sell copies of the\n");
|
|---|
| 131 | printf(" Software, and to permit persons to whom the Software is furnished to do\n");
|
|---|
| 132 | printf(" so, subject to the following conditions:\n");
|
|---|
| 133 | printf("\n");
|
|---|
| 134 | printf(" The above copyright notice and this permission notice shall be included in\n");
|
|---|
| 135 | printf(" all copies or substantial portions of the Software.\n");
|
|---|
| 136 | printf("\n");
|
|---|
| 137 | printf(" THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n");
|
|---|
| 138 | printf(" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n");
|
|---|
| 139 | printf(" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n");
|
|---|
| 140 | printf(" THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n");
|
|---|
| 141 | printf(" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n");
|
|---|
| 142 | printf(" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n");
|
|---|
| 143 | printf(" DEALINGS IN THE SOFTWARE.\n");
|
|---|
| 144 | printf("\n");
|
|---|
| 145 | printf("CONTACT INFORMATION\n");
|
|---|
| 146 | printf("\n");
|
|---|
| 147 | printf(" Please email questions or feedback to jason.roberts@duke.edu.\n");
|
|---|
| 148 | }
|
|---|
| 149 |
|
|---|
| 150 | static bool ParseInteger(const char *pszStr, int *pValue)
|
|---|
| 151 | {
|
|---|
| 152 | if (*pszStr == '\0')
|
|---|
| 153 | return 0;
|
|---|
| 154 |
|
|---|
| 155 | char *pEnd = "z";
|
|---|
| 156 | int i = strtol(pszStr, &pEnd, 0);
|
|---|
| 157 |
|
|---|
| 158 | if (*pEnd != '\0' || (i == LONG_MAX || i == LONG_MIN) && errno == ERANGE)
|
|---|
| 159 | return false;
|
|---|
| 160 |
|
|---|
| 161 | *pValue = i;
|
|---|
| 162 |
|
|---|
| 163 | return true;
|
|---|
| 164 | }
|
|---|
| 165 |
|
|---|
| 166 | static bool ParseDouble(const char *pszStr, double *pValue)
|
|---|
| 167 | {
|
|---|
| 168 | if (*pszStr == '\0')
|
|---|
| 169 | return 0;
|
|---|
| 170 |
|
|---|
| 171 | // Parse the value.
|
|---|
| 172 |
|
|---|
| 173 | char *pEnd = "z";
|
|---|
| 174 | double f = strtod(pszStr, &pEnd);
|
|---|
| 175 |
|
|---|
| 176 | if (*pEnd != '\0' || (f == HUGE_VAL || f == -HUGE_VAL) && errno == ERANGE)
|
|---|
| 177 | return false;
|
|---|
| 178 |
|
|---|
| 179 | *pValue = f;
|
|---|
| 180 |
|
|---|
| 181 | return true;
|
|---|
| 182 | }
|
|---|
| 183 |
|
|---|
| 184 | static bool ParseFloat(const char *pszStr, float *pValue)
|
|---|
| 185 | {
|
|---|
| 186 | double d;
|
|---|
| 187 |
|
|---|
| 188 | bool retval = ParseDouble(pszStr, &d);
|
|---|
| 189 |
|
|---|
| 190 | *pValue = (float) d;
|
|---|
| 191 |
|
|---|
| 192 | return retval;
|
|---|
| 193 | }
|
|---|
| 194 |
|
|---|
| 195 | static char *ParseCommandLineArguments(int argc, char *argv[], char **pXBinary, char **pYBinary, char **pOutFile, DataType *pDataType, int *pCols, int *pRows, double *pCellSize, double *pXLowerLeftCorner, double *pYLowerLeftCorner, int *pUseNoData, int *piNoDataValue, double *pdNoDataValue, double *pScaleFactor, int *pUniformLines)
|
|---|
| 196 | {
|
|---|
| 197 | // Perform basic range checks.
|
|---|
| 198 |
|
|---|
| 199 | if (argc < 10)
|
|---|
| 200 | return "ERROR: Too few command line arguments specified.\n";
|
|---|
| 201 |
|
|---|
| 202 | if (argc > 15)
|
|---|
| 203 | return "ERROR: Too many command line arguments specified.\n";
|
|---|
| 204 |
|
|---|
| 205 | // If the files are invalid, we will detect it when we fail to open them.
|
|---|
| 206 |
|
|---|
| 207 | *pXBinary = argv[1];
|
|---|
| 208 | *pYBinary = argv[2];
|
|---|
| 209 | *pOutFile = argv[3];
|
|---|
| 210 |
|
|---|
| 211 | // Extract the remaining arguments.
|
|---|
| 212 |
|
|---|
| 213 | int iArgIndex = 4;
|
|---|
| 214 |
|
|---|
| 215 | if (_stricmp(argv[iArgIndex], "int8") == 0)
|
|---|
| 216 | *pDataType = Int8_DataType;
|
|---|
| 217 | else if (_stricmp(argv[iArgIndex], "uint8") == 0)
|
|---|
| 218 | *pDataType = Uint8_DataType;
|
|---|
| 219 | else if (_stricmp(argv[iArgIndex], "int16") == 0)
|
|---|
| 220 | *pDataType = Int16_DataType;
|
|---|
| 221 | else if (_stricmp(argv[iArgIndex], "uint16") == 0)
|
|---|
| 222 | *pDataType = Uint16_DataType;
|
|---|
| 223 | else if (_stricmp(argv[iArgIndex], "int32") == 0)
|
|---|
| 224 | *pDataType = Int32_DataType;
|
|---|
| 225 | else if (_stricmp(argv[iArgIndex], "float") == 0)
|
|---|
| 226 | *pDataType = Float_DataType;
|
|---|
| 227 | else if (_stricmp(argv[iArgIndex], "double") == 0)
|
|---|
| 228 | *pDataType = Double_DataType;
|
|---|
| 229 | else
|
|---|
| 230 | return "ERROR: An invalid data type was specified. The valid data types are int8, uint8, int16, uint16, int32, float and double.";
|
|---|
| 231 | iArgIndex++;
|
|---|
| 232 |
|
|---|
| 233 | if (!ParseInteger(argv[iArgIndex], pCols) || *pCols < 1)
|
|---|
| 234 | return "ERROR: An invalid number of columns was specified. The number of columns must be an integer greater than or equal to 1 and less than or equal to 2147483647.";
|
|---|
| 235 | iArgIndex++;
|
|---|
| 236 |
|
|---|
| 237 | if (!ParseInteger(argv[iArgIndex], pRows) || *pRows < 1)
|
|---|
| 238 | return "ERROR: An invalid number of rows was specified. The number of rows must be an integer greater than or equal to 1 and less than or equal to 2147483647.";
|
|---|
| 239 | iArgIndex++;
|
|---|
| 240 |
|
|---|
| 241 | if (!ParseDouble(argv[iArgIndex], pCellSize) || *pCellSize < 0.0)
|
|---|
| 242 | return "ERROR: An invalid cell size was specified. The cell size must be the decimal representation of a double-precision (64-bit) floating point number greater than zero.";
|
|---|
| 243 | iArgIndex++;
|
|---|
| 244 |
|
|---|
| 245 | if (!ParseDouble(argv[iArgIndex], pXLowerLeftCorner))
|
|---|
| 246 | return "ERROR: An invalid X coordinate of the lower-left corner was specified. The coordinate must be the decimal representation of a double-precision (64-bit) floating point number.";
|
|---|
| 247 | iArgIndex++;
|
|---|
| 248 |
|
|---|
| 249 | if (!ParseDouble(argv[iArgIndex], pYLowerLeftCorner))
|
|---|
| 250 | return "ERROR: An invalid X coordinate of the lower-left corner was specified. The coordinate must be the decimal representation of a double-precision (64-bit) floating point number.";
|
|---|
| 251 | iArgIndex++;
|
|---|
| 252 |
|
|---|
| 253 | *pUseNoData = 0;
|
|---|
| 254 | *pScaleFactor = 1.0;
|
|---|
| 255 |
|
|---|
| 256 | while (iArgIndex < argc)
|
|---|
| 257 | {
|
|---|
| 258 | if (argv[iArgIndex][0] != '-' || argv[iArgIndex][1] == 0 || argv[iArgIndex][2] != 0 )
|
|---|
| 259 | return "ERROR: Unrecognized command line argument.\n";
|
|---|
| 260 |
|
|---|
| 261 | switch (argv[iArgIndex][1])
|
|---|
| 262 | {
|
|---|
| 263 | case 'n':
|
|---|
| 264 | case 'N':
|
|---|
| 265 | iArgIndex++;
|
|---|
| 266 | if (*pDataType == Int8_DataType || *pDataType == Uint8_DataType || *pDataType == Int16_DataType || *pDataType == Uint16_DataType || *pDataType == Int32_DataType)
|
|---|
| 267 | {
|
|---|
| 268 | if (!ParseInteger(argv[iArgIndex], piNoDataValue))
|
|---|
| 269 | return "ERROR: An invalid NODATA value was specified. The NODATA value must be an integer.";
|
|---|
| 270 | if (*pDataType == Int8_DataType && (*piNoDataValue < -128 || *piNoDataValue > 127))
|
|---|
| 271 | return "ERROR: An invalid NODATA value was specified. The NODATA value must be an integer between -128 and 127, inclusive.";
|
|---|
| 272 | if (*pDataType == Uint8_DataType && (*piNoDataValue < 0 || *piNoDataValue > 255))
|
|---|
| 273 | return "ERROR: An invalid NODATA value was specified. The NODATA value must be an integer between 0 and 255, inclusive.";
|
|---|
| 274 | if (*pDataType == Int16_DataType && (*piNoDataValue < -32768 || *piNoDataValue > 32767))
|
|---|
| 275 | return "ERROR: An invalid NODATA value was specified. The NODATA value must be an integer between -32768 and 32767, inclusive.";
|
|---|
| 276 | if (*pDataType == Uint16_DataType && (*piNoDataValue < 0 || *piNoDataValue > 65535))
|
|---|
| 277 | return "ERROR: An invalid NODATA value was specified. The NODATA value must be an integer between 0 and 65535, inclusive.";
|
|---|
| 278 | if (*pDataType == Int32_DataType && (*piNoDataValue < (0-2147483648) || *piNoDataValue > 2147483647))
|
|---|
| 279 | return "ERROR: An invalid NODATA value was specified. The NODATA value must be an integer between -2147483648 and 2147483647, inclusive.";
|
|---|
| 280 | }
|
|---|
| 281 | else
|
|---|
| 282 | {
|
|---|
| 283 | if (!ParseDouble(argv[iArgIndex], pdNoDataValue))
|
|---|
| 284 | return "ERROR: An invalid NODATA value was specified. The NODATA value must be a decimal number.";
|
|---|
| 285 | }
|
|---|
| 286 | *pUseNoData = 1;
|
|---|
| 287 | iArgIndex++;
|
|---|
| 288 | break;
|
|---|
| 289 |
|
|---|
| 290 | case 's':
|
|---|
| 291 | case 'S':
|
|---|
| 292 | iArgIndex++;
|
|---|
| 293 | if (!ParseDouble(argv[iArgIndex], pScaleFactor) || *pScaleFactor <= 0.0)
|
|---|
| 294 | return "ERROR: An invalid scale factor was specified. The scale factor must be the decimal representation of a single-precision (32-bit) floating point number greater than zero.";
|
|---|
| 295 | iArgIndex++;
|
|---|
| 296 | break;
|
|---|
| 297 |
|
|---|
| 298 | case 'u':
|
|---|
| 299 | case 'U':
|
|---|
| 300 | iArgIndex++;
|
|---|
| 301 | *pUniformLines = 1;
|
|---|
| 302 | break;
|
|---|
| 303 |
|
|---|
| 304 | default:
|
|---|
| 305 | return "ERROR: Unrecognized command line argument.\n";
|
|---|
| 306 | }
|
|---|
| 307 | }
|
|---|
| 308 |
|
|---|
| 309 | // Return successfully.
|
|---|
| 310 |
|
|---|
| 311 | return NULL;
|
|---|
| 312 | }
|
|---|
| 313 |
|
|---|
| 314 | int main(int argc, char *argv[])
|
|---|
| 315 | {
|
|---|
| 316 | printf("vectorshp version 1.1.0 (3-Feb-2012)\n");
|
|---|
| 317 | printf("\n");
|
|---|
| 318 |
|
|---|
| 319 | // Parse the command line arguments.
|
|---|
| 320 |
|
|---|
| 321 | if (argc == 1 || argc == 2 && argv[1][0] == '-' && argv[1][1] == '?' && argv[1][2] == 0)
|
|---|
| 322 | {
|
|---|
| 323 | PrintUsage();
|
|---|
| 324 | return 1;
|
|---|
| 325 | }
|
|---|
| 326 |
|
|---|
| 327 | char *pszXBinary = NULL;
|
|---|
| 328 | char *pszYBinary = NULL;
|
|---|
| 329 | char *pszOutFile = NULL;
|
|---|
| 330 | DataType iDataType = Int8_DataType;
|
|---|
| 331 | int iCols = 0;
|
|---|
| 332 | int iRows = 0;
|
|---|
| 333 | double dCellSize = 0.0;
|
|---|
| 334 | double dXLowerLeftCorner = 0.0;
|
|---|
| 335 | double dYLowerLeftCorner = 0.0;
|
|---|
| 336 | int bUseNoData = 0;
|
|---|
| 337 | int iNoDataValue = 0;
|
|---|
| 338 | double dNoDataValue = 0;
|
|---|
| 339 | double dScaleFactor = 1.0;
|
|---|
| 340 | int iUniformLines = 0;
|
|---|
| 341 |
|
|---|
| 342 | char *pszErrorMessage = ParseCommandLineArguments(argc, argv, &pszXBinary, &pszYBinary, &pszOutFile, &iDataType, &iCols, &iRows, &dCellSize, &dXLowerLeftCorner, &dYLowerLeftCorner, &bUseNoData, &iNoDataValue, &dNoDataValue, &dScaleFactor, &iUniformLines);
|
|---|
| 343 | if (pszErrorMessage != NULL)
|
|---|
| 344 | {
|
|---|
| 345 | printf(pszErrorMessage);
|
|---|
| 346 | printf("\n");
|
|---|
| 347 | printf("Type \"vectorshp -?\" for help.\n");
|
|---|
| 348 | return 1;
|
|---|
| 349 | }
|
|---|
| 350 |
|
|---|
| 351 | // Make sure the output shapefile does not exist already.
|
|---|
| 352 |
|
|---|
| 353 | size_t iLen = strlen(pszOutFile);
|
|---|
| 354 |
|
|---|
| 355 | if (iLen >= 4 &&
|
|---|
| 356 | pszOutFile[iLen - 4] == '.' &&
|
|---|
| 357 | (pszOutFile[iLen - 3] == 's' || pszOutFile[iLen - 3] == 'S') &&
|
|---|
| 358 | (pszOutFile[iLen - 2] == 'h' || pszOutFile[iLen - 2] == 'H') &&
|
|---|
| 359 | (pszOutFile[iLen - 1] == 'p' || pszOutFile[iLen - 1] == 'P'))
|
|---|
| 360 | {
|
|---|
| 361 | char *pszNewOutFile = (char *) calloc(iLen - 3, 1);
|
|---|
| 362 | if (pszNewOutFile == NULL)
|
|---|
| 363 | {
|
|---|
| 364 | printf("ERROR: Out of memory.\n");
|
|---|
| 365 | return 1;
|
|---|
| 366 | }
|
|---|
| 367 | pszOutFile = strncpy(pszNewOutFile, pszOutFile, iLen - 4);
|
|---|
| 368 | }
|
|---|
| 369 |
|
|---|
| 370 | iLen = strlen(pszOutFile);
|
|---|
| 371 | char *pszTemp = (char *) calloc(iLen + 5, 1);
|
|---|
| 372 | if (pszTemp == NULL)
|
|---|
| 373 | {
|
|---|
| 374 | printf("ERROR: Out of memory.\n");
|
|---|
| 375 | return 1;
|
|---|
| 376 | }
|
|---|
| 377 | strcpy(pszTemp, pszOutFile);
|
|---|
| 378 | pszTemp[iLen] = '.';
|
|---|
| 379 |
|
|---|
| 380 | pszTemp[iLen + 1] = 's';
|
|---|
| 381 | pszTemp[iLen + 2] = 'h';
|
|---|
| 382 | pszTemp[iLen + 3] = 'p';
|
|---|
| 383 | FILE *pTempFile = fopen(pszTemp, "r");
|
|---|
| 384 | if (pTempFile != NULL)
|
|---|
| 385 | {
|
|---|
| 386 | printf("ERROR: The file \"%s\" already exists. Please delete it or specify a different output file name.\n", pszTemp);
|
|---|
| 387 | return 1;
|
|---|
| 388 | }
|
|---|
| 389 |
|
|---|
| 390 | pszTemp[iLen + 1] = 's';
|
|---|
| 391 | pszTemp[iLen + 2] = 'h';
|
|---|
| 392 | pszTemp[iLen + 3] = 'x';
|
|---|
| 393 | pTempFile = fopen(pszTemp, "r");
|
|---|
| 394 | if (pTempFile != NULL)
|
|---|
| 395 | {
|
|---|
| 396 | printf("ERROR: The file \"%s\" already exists. Please delete it or specify a different output file name.\n", pszTemp);
|
|---|
| 397 | return 1;
|
|---|
| 398 | }
|
|---|
| 399 |
|
|---|
| 400 | pszTemp[iLen + 1] = 'd';
|
|---|
| 401 | pszTemp[iLen + 2] = 'b';
|
|---|
| 402 | pszTemp[iLen + 3] = 'f';
|
|---|
| 403 | pTempFile = fopen(pszTemp, "r");
|
|---|
| 404 | if (pTempFile != NULL)
|
|---|
| 405 | {
|
|---|
| 406 | printf("ERROR: The file \"%s\" already exists. Please delete it or specify a different output file name.\n", pszTemp);
|
|---|
| 407 | return 1;
|
|---|
| 408 | }
|
|---|
| 409 |
|
|---|
| 410 | // Open the binary files file for reading.
|
|---|
| 411 |
|
|---|
| 412 | HANDLE hXFile = CreateFile(pszXBinary, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, 0);
|
|---|
| 413 |
|
|---|
| 414 | if (hXFile == INVALID_HANDLE_VALUE)
|
|---|
| 415 | {
|
|---|
| 416 | DWORD dwError = GetLastError();
|
|---|
| 417 | LPSTR lpMsgBuf = NULL;
|
|---|
| 418 | FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &lpMsgBuf, 0, NULL);
|
|---|
| 419 | if (lpMsgBuf != NULL)
|
|---|
| 420 | printf("ERROR: Failed to open file \"%s\" for reading. The operating system returned error %d: %s\n", pszXBinary, dwError, lpMsgBuf);
|
|---|
| 421 | else
|
|---|
| 422 | printf("ERROR: Failed to open file \"%s\" for reading.\n", pszXBinary);
|
|---|
| 423 | return 1;
|
|---|
| 424 | }
|
|---|
| 425 |
|
|---|
| 426 | printf("Opened \"%s\" for reading.\n", pszXBinary);
|
|---|
| 427 |
|
|---|
| 428 | HANDLE hYFile = CreateFile(pszYBinary, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, 0);
|
|---|
| 429 |
|
|---|
| 430 | if (hYFile == INVALID_HANDLE_VALUE)
|
|---|
| 431 | {
|
|---|
| 432 | DWORD dwError = GetLastError();
|
|---|
| 433 | LPSTR lpMsgBuf = NULL;
|
|---|
| 434 | FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &lpMsgBuf, 0, NULL);
|
|---|
| 435 | if (lpMsgBuf != NULL)
|
|---|
| 436 | printf("ERROR: Failed to open file \"%s\" for reading. The operating system returned error %d: %s\n", pszYBinary, dwError, lpMsgBuf);
|
|---|
| 437 | else
|
|---|
| 438 | printf("ERROR: Failed to open file \"%s\" for reading.\n", pszYBinary);
|
|---|
| 439 | return 1;
|
|---|
| 440 | }
|
|---|
| 441 |
|
|---|
| 442 | printf("Opened \"%s\" for reading.\n", pszYBinary);
|
|---|
| 443 |
|
|---|
| 444 | // Verify that the binary files are the right sizes.
|
|---|
| 445 |
|
|---|
| 446 | LONGLONG liExpectedSize = (LONGLONG) iCols * (LONGLONG) iRows * (LONGLONG) DataTypeSizes[iDataType];
|
|---|
| 447 | LARGE_INTEGER liFileSize;
|
|---|
| 448 |
|
|---|
| 449 | if (!GetFileSizeEx(hXFile, &liFileSize))
|
|---|
| 450 | {
|
|---|
| 451 | DWORD dwError = GetLastError();
|
|---|
| 452 | LPSTR lpMsgBuf = NULL;
|
|---|
| 453 | FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &lpMsgBuf, 0, NULL);
|
|---|
| 454 | if (lpMsgBuf != NULL)
|
|---|
| 455 | printf("ERROR: Failed to retrieve the size of the file \"%s\". The operating system returned error %d: %s\n", pszXBinary, dwError, lpMsgBuf);
|
|---|
| 456 | else
|
|---|
| 457 | printf("ERROR: Failed to retrieve the size of the file \"%s\".\n", pszXBinary);
|
|---|
| 458 | return 1;
|
|---|
| 459 | }
|
|---|
| 460 |
|
|---|
| 461 | if (liFileSize.QuadPart != liExpectedSize)
|
|---|
| 462 | {
|
|---|
| 463 | printf("ERROR: The size of file \"%s\" is %I64i bytes, but it was expected to be %I64i bytes, given that it has %i columns, %i rows, and its data type requires %i bytes. Please check your parameters.\n", pszXBinary, liFileSize.QuadPart, liExpectedSize, iCols, iRows, DataTypeSizes[iDataType]);
|
|---|
| 464 | return 1;
|
|---|
| 465 | }
|
|---|
| 466 |
|
|---|
| 467 | if (!GetFileSizeEx(hYFile, &liFileSize))
|
|---|
| 468 | {
|
|---|
| 469 | DWORD dwError = GetLastError();
|
|---|
| 470 | LPSTR lpMsgBuf = NULL;
|
|---|
| 471 | FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &lpMsgBuf, 0, NULL);
|
|---|
| 472 | if (lpMsgBuf != NULL)
|
|---|
| 473 | printf("ERROR: Failed to retrieve the size of the file \"%s\". The operating system returned error %d: %s\n", pszYBinary, dwError, lpMsgBuf);
|
|---|
| 474 | else
|
|---|
| 475 | printf("ERROR: Failed to retrieve the size of the file \"%s\".\n", pszYBinary);
|
|---|
| 476 | return 1;
|
|---|
| 477 | }
|
|---|
| 478 |
|
|---|
| 479 | if (liFileSize.QuadPart != liExpectedSize)
|
|---|
| 480 | {
|
|---|
| 481 | printf("ERROR: The size of file \"%s\" is %I64i bytes, but it was expected to be %I64i bytes, given that it has %i columns, %i rows, and its data type requires %i bytes. Please check your parameters.\n", pszYBinary, liFileSize.QuadPart, liExpectedSize, iCols, iRows, DataTypeSizes[iDataType]);
|
|---|
| 482 | return 1;
|
|---|
| 483 | }
|
|---|
| 484 |
|
|---|
| 485 | // Create the output shapefile.
|
|---|
| 486 |
|
|---|
| 487 | printf("Writing lines to output shapefile \"%s\"...\n", pszOutFile);
|
|---|
| 488 |
|
|---|
| 489 | errno = 0;
|
|---|
| 490 | SHPHandle hOutShapeFile = NULL;
|
|---|
| 491 |
|
|---|
| 492 | hOutShapeFile = SHPCreate(pszOutFile, SHPT_ARC);
|
|---|
| 493 |
|
|---|
| 494 | if (hOutShapeFile == NULL)
|
|---|
| 495 | {
|
|---|
| 496 | if (errno != 0)
|
|---|
| 497 | printf("ERROR: Failed to create the output shapefile \"%s\". The shapelib.dll function SHPCreate() failed. On exit of that function, the global error number was set to %d: %s\n", pszOutFile, errno, strerror(errno));
|
|---|
| 498 | else
|
|---|
| 499 | printf("ERROR: Failed to create the output shapefile \"%s\". The shapelib.dll function SHPCreate() failed. Unfortunately that function does not return any detailed error information, and the global error number was set to zero (no error).\n", pszOutFile);
|
|---|
| 500 | return 1;
|
|---|
| 501 | }
|
|---|
| 502 |
|
|---|
| 503 | // Create the output DBF file.
|
|---|
| 504 |
|
|---|
| 505 | DBFHandle hOutDBFFile = DBFCreate(pszOutFile);
|
|---|
| 506 | if (hOutDBFFile == NULL)
|
|---|
| 507 | {
|
|---|
| 508 | if (errno != 0)
|
|---|
| 509 | printf("ERROR: Failed to create the output DBF file \"%s.dbf\". The shapelib.dll function DBFCreate() failed. On exit of that function, the global error number was set to %d: %s\n", pszOutFile, errno, strerror(errno));
|
|---|
| 510 | else
|
|---|
| 511 | printf("ERROR: Failed to create the output DBF file \"%s.dbf\". The shapelib.dll function DBFCreate() failed. Unfortunately that function does not return any detailed error information, and the global error number was set to zero (no error).\n", pszOutFile);
|
|---|
| 512 | SHPClose(hOutShapeFile);
|
|---|
| 513 | return 1;
|
|---|
| 514 | }
|
|---|
| 515 |
|
|---|
| 516 | DBFAddField(hOutDBFFile, "Magnitude", FTDouble, 19, 11);
|
|---|
| 517 | DBFAddField(hOutDBFFile, "Direction", FTDouble, 19, 11);
|
|---|
| 518 |
|
|---|
| 519 | // Read cells from the binary files and write lines to the shapefile.
|
|---|
| 520 |
|
|---|
| 521 | BYTE pXReadBuf[BUF_SIZE];
|
|---|
| 522 | BYTE pYReadBuf[BUF_SIZE];
|
|---|
| 523 | DWORD dwBytesToRead = sizeof(pXReadBuf);
|
|---|
| 524 | DWORD dwBytesRead = 0;
|
|---|
| 525 | DWORD dwReadIndex = 0;
|
|---|
| 526 |
|
|---|
| 527 | for (INT32 row = 0; row < iRows; row++)
|
|---|
| 528 | {
|
|---|
| 529 | for (INT32 col = 0; col < iCols; col++)
|
|---|
| 530 | {
|
|---|
| 531 | // If we exhausted the read buffers, refill them from the binary
|
|---|
| 532 | // files.
|
|---|
| 533 |
|
|---|
| 534 | if (dwReadIndex >= dwBytesRead)
|
|---|
| 535 | {
|
|---|
| 536 | if (!ReadFile(hXFile, pXReadBuf, dwBytesToRead, &dwBytesRead, NULL))
|
|---|
| 537 | {
|
|---|
| 538 | DWORD dwError = GetLastError();
|
|---|
| 539 | LPSTR lpMsgBuf = NULL;
|
|---|
| 540 | FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &lpMsgBuf, 0, NULL);
|
|---|
| 541 | if (lpMsgBuf != NULL)
|
|---|
| 542 | printf("ERROR: Failed to read from the file \"%s\". The operating system returned error %d: %s\n", pszXBinary, dwError, lpMsgBuf);
|
|---|
| 543 | else
|
|---|
| 544 | printf("ERROR: Failed to read from the file \"%s\".\n", pszXBinary);
|
|---|
| 545 | SHPClose(hOutShapeFile);
|
|---|
| 546 | DBFClose(hOutDBFFile);
|
|---|
| 547 | return 1;
|
|---|
| 548 | }
|
|---|
| 549 | if (dwBytesRead == 0)
|
|---|
| 550 | {
|
|---|
| 551 | printf("ERROR: Reached the end of file \"%s\" prematurely. It is too small for the number of columns and rows and the data type specified.\n", pszXBinary);
|
|---|
| 552 | SHPClose(hOutShapeFile);
|
|---|
| 553 | DBFClose(hOutDBFFile);
|
|---|
| 554 | return 1;
|
|---|
| 555 | }
|
|---|
| 556 |
|
|---|
| 557 | DWORD dwBytesRead2 = 0;
|
|---|
| 558 | if (!ReadFile(hYFile, pYReadBuf, dwBytesRead, &dwBytesRead2, NULL))
|
|---|
| 559 | {
|
|---|
| 560 | DWORD dwError = GetLastError();
|
|---|
| 561 | LPSTR lpMsgBuf = NULL;
|
|---|
| 562 | FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &lpMsgBuf, 0, NULL);
|
|---|
| 563 | if (lpMsgBuf != NULL)
|
|---|
| 564 | printf("ERROR: Failed to read from the file \"%s\". The operating system returned error %d: %s\n", pszYBinary, dwError, lpMsgBuf);
|
|---|
| 565 | else
|
|---|
| 566 | printf("ERROR: Failed to read from the file \"%s\".\n", pszYBinary);
|
|---|
| 567 | SHPClose(hOutShapeFile);
|
|---|
| 568 | DBFClose(hOutDBFFile);
|
|---|
| 569 | return 1;
|
|---|
| 570 | }
|
|---|
| 571 | if (dwBytesRead2 == 0)
|
|---|
| 572 | {
|
|---|
| 573 | printf("ERROR: Reached the end of file \"%s\" prematurely. It is too small for the number of columns and rows and the data type specified.\n", pszYBinary);
|
|---|
| 574 | SHPClose(hOutShapeFile);
|
|---|
| 575 | DBFClose(hOutDBFFile);
|
|---|
| 576 | return 1;
|
|---|
| 577 | }
|
|---|
| 578 | if (dwBytesRead2 != dwBytesRead)
|
|---|
| 579 | {
|
|---|
| 580 | printf("ERROR: Reached the end of file \"%s\" prematurely. It is not the same size as file \"%s\".\n", pszYBinary, pszXBinary);
|
|---|
| 581 | SHPClose(hOutShapeFile);
|
|---|
| 582 | DBFClose(hOutDBFFile);
|
|---|
| 583 | return 1;
|
|---|
| 584 | }
|
|---|
| 585 |
|
|---|
| 586 | dwReadIndex = 0;
|
|---|
| 587 | }
|
|---|
| 588 |
|
|---|
| 589 | // Only create a line if neither cell is NODATA.
|
|---|
| 590 |
|
|---|
| 591 | bool bNoData = false;
|
|---|
| 592 |
|
|---|
| 593 | if (bUseNoData)
|
|---|
| 594 | switch (iDataType)
|
|---|
| 595 | {
|
|---|
| 596 | case Int8_DataType:
|
|---|
| 597 | bNoData = ((INT32) *((INT8 *) (pXReadBuf + dwReadIndex))) == iNoDataValue || ((INT32) *((INT8 *) (pYReadBuf + dwReadIndex))) == iNoDataValue;
|
|---|
| 598 | break;
|
|---|
| 599 |
|
|---|
| 600 | case Uint8_DataType:
|
|---|
| 601 | bNoData = ((INT32) *((UINT8 *) (pXReadBuf + dwReadIndex))) == iNoDataValue || ((INT32) *((UINT8 *) (pYReadBuf + dwReadIndex))) == iNoDataValue;
|
|---|
| 602 | break;
|
|---|
| 603 |
|
|---|
| 604 | case Int16_DataType:
|
|---|
| 605 | bNoData = ((INT32) *((INT16 *) (pXReadBuf + dwReadIndex))) == iNoDataValue || ((INT32) *((INT16 *) (pYReadBuf + dwReadIndex))) == iNoDataValue;
|
|---|
| 606 | break;
|
|---|
| 607 |
|
|---|
| 608 | case Uint16_DataType:
|
|---|
| 609 | bNoData = ((INT32) *((UINT16 *) (pXReadBuf + dwReadIndex))) == iNoDataValue || ((INT32) *((UINT16 *) (pYReadBuf + dwReadIndex))) == iNoDataValue;
|
|---|
| 610 | break;
|
|---|
| 611 |
|
|---|
| 612 | case Int32_DataType:
|
|---|
| 613 | bNoData = *((INT32 *) (pXReadBuf + dwReadIndex)) == iNoDataValue || *((INT32 *) (pYReadBuf + dwReadIndex)) == iNoDataValue;
|
|---|
| 614 | break;
|
|---|
| 615 |
|
|---|
| 616 | case Float_DataType:
|
|---|
| 617 | bNoData = ((DOUBLE) *((FLOAT *) (pXReadBuf + dwReadIndex))) == dNoDataValue || ((DOUBLE) *((FLOAT *) (pYReadBuf + dwReadIndex))) == dNoDataValue;
|
|---|
| 618 | break;
|
|---|
| 619 |
|
|---|
| 620 | case Double_DataType:
|
|---|
| 621 | bNoData = *((DOUBLE *) (pXReadBuf + dwReadIndex)) == dNoDataValue || *((DOUBLE *) (pYReadBuf + dwReadIndex)) == dNoDataValue;
|
|---|
| 622 | break;
|
|---|
| 623 |
|
|---|
| 624 | default:
|
|---|
| 625 | printf("ERROR: Programming error in this tool. Invalid DataType. Please contact the author of this tool for assistance.\n");
|
|---|
| 626 | SHPClose(hOutShapeFile);
|
|---|
| 627 | DBFClose(hOutDBFFile);
|
|---|
| 628 | return 1;
|
|---|
| 629 | }
|
|---|
| 630 |
|
|---|
| 631 | if (!bNoData)
|
|---|
| 632 | {
|
|---|
| 633 | // Calculate the starting coordinates of the vector.
|
|---|
| 634 |
|
|---|
| 635 | double dXStart = dXLowerLeftCorner + dCellSize * (double) col + dCellSize / 2;
|
|---|
| 636 | double dYStart = dYLowerLeftCorner + dCellSize * (double) (iRows - row - 1) + dCellSize / 2;
|
|---|
| 637 |
|
|---|
| 638 | // Calculate the ending coordinates of the vector.
|
|---|
| 639 |
|
|---|
| 640 | double dXEnd = dXStart;
|
|---|
| 641 | double dYEnd = dYStart;
|
|---|
| 642 |
|
|---|
| 643 | switch (iDataType)
|
|---|
| 644 | {
|
|---|
| 645 | case Int8_DataType:
|
|---|
| 646 | dXEnd += ((DOUBLE) *((INT8 *) (pXReadBuf + dwReadIndex))) * dScaleFactor;
|
|---|
| 647 | dYEnd += ((DOUBLE) *((INT8 *) (pYReadBuf + dwReadIndex))) * dScaleFactor;
|
|---|
| 648 | break;
|
|---|
| 649 |
|
|---|
| 650 | case Uint8_DataType:
|
|---|
| 651 | dXEnd += ((DOUBLE) *((UINT8 *) (pXReadBuf + dwReadIndex))) * dScaleFactor;
|
|---|
| 652 | dYEnd += ((DOUBLE) *((UINT8 *) (pYReadBuf + dwReadIndex))) * dScaleFactor;
|
|---|
| 653 | break;
|
|---|
| 654 |
|
|---|
| 655 | case Int16_DataType:
|
|---|
| 656 | dXEnd += ((DOUBLE) *((INT16 *) (pXReadBuf + dwReadIndex))) * dScaleFactor;
|
|---|
| 657 | dYEnd += ((DOUBLE) *((INT16 *) (pYReadBuf + dwReadIndex))) * dScaleFactor;
|
|---|
| 658 | break;
|
|---|
| 659 |
|
|---|
| 660 | case Uint16_DataType:
|
|---|
| 661 | dXEnd += ((DOUBLE) *((UINT16 *) (pXReadBuf + dwReadIndex))) * dScaleFactor;
|
|---|
| 662 | dYEnd += ((DOUBLE) *((UINT16 *) (pYReadBuf + dwReadIndex))) * dScaleFactor;
|
|---|
| 663 | break;
|
|---|
| 664 |
|
|---|
| 665 | case Int32_DataType:
|
|---|
| 666 | dXEnd += ((DOUBLE) *((INT32 *) (pXReadBuf + dwReadIndex))) * dScaleFactor;
|
|---|
| 667 | dYEnd += ((DOUBLE) *((INT32 *) (pYReadBuf + dwReadIndex))) * dScaleFactor;
|
|---|
| 668 | break;
|
|---|
| 669 |
|
|---|
| 670 | case Float_DataType:
|
|---|
| 671 | dXEnd += ((DOUBLE) *((FLOAT *) (pXReadBuf + dwReadIndex))) * dScaleFactor;
|
|---|
| 672 | dYEnd += ((DOUBLE) *((FLOAT *) (pYReadBuf + dwReadIndex))) * dScaleFactor;
|
|---|
| 673 | break;
|
|---|
| 674 |
|
|---|
| 675 | case Double_DataType:
|
|---|
| 676 | dXEnd += *((DOUBLE *) (pXReadBuf + dwReadIndex)) * dScaleFactor;
|
|---|
| 677 | dYEnd += *((DOUBLE *) (pYReadBuf + dwReadIndex)) * dScaleFactor;
|
|---|
| 678 | break;
|
|---|
| 679 |
|
|---|
| 680 | default:
|
|---|
| 681 | printf("ERROR: Programming error in this tool. Invalid DataType. Please contact the author of this tool for assistance.\n");
|
|---|
| 682 | SHPClose(hOutShapeFile);
|
|---|
| 683 | DBFClose(hOutDBFFile);
|
|---|
| 684 | return 1;
|
|---|
| 685 | }
|
|---|
| 686 |
|
|---|
| 687 | // Write the vector to the shapefile.
|
|---|
| 688 |
|
|---|
| 689 | double dMagnitude = sqrt(pow((dXEnd - dXStart) / dScaleFactor, 2) + pow((dYEnd - dYStart) / dScaleFactor, 2));
|
|---|
| 690 | double dDirection = atan2(dYEnd - dYStart, dXEnd - dXStart) / 3.1415926535897931 * 180.0;
|
|---|
| 691 |
|
|---|
| 692 | double fX[2] = {dXStart, dXEnd};
|
|---|
| 693 | double fY[2] = {dYStart, dYEnd};
|
|---|
| 694 |
|
|---|
| 695 | if (iUniformLines)
|
|---|
| 696 | {
|
|---|
| 697 | double dLineLength = dCellSize * dScaleFactor;
|
|---|
| 698 | fX[1] = dXStart + (dXEnd - dXStart) * (dLineLength / dMagnitude);
|
|---|
| 699 | fY[1] = dYStart + (dYEnd - dYStart) * (dLineLength / dMagnitude);
|
|---|
| 700 |
|
|---|
| 701 | //if (dXEnd >= dXStart)
|
|---|
| 702 | // fX[1] = dXStart + sqrt(pow(dMagnitude, 2) - pow(dYStart - dYEnd, 2)) * dCellSize * dScaleFactor;
|
|---|
| 703 | //else
|
|---|
| 704 | // fX[1] = dXStart - sqrt(pow(dMagnitude, 2) - pow(dYStart - dYEnd, 2)) * dCellSize * dScaleFactor;
|
|---|
| 705 |
|
|---|
| 706 | //if (dYEnd >= dYStart)
|
|---|
| 707 | // fY[1] = dYStart + sqrt(pow(dMagnitude, 2) - pow(dXStart - dXEnd, 2)) * dCellSize * dScaleFactor;
|
|---|
| 708 | //else
|
|---|
| 709 | // fY[1] = dYStart - sqrt(pow(dMagnitude, 2) - pow(dXStart - dXEnd, 2)) * dCellSize * dScaleFactor;
|
|---|
| 710 | }
|
|---|
| 711 |
|
|---|
| 712 | SHPObject *shpObj = SHPCreateObject(SHPT_ARC, -1, 0, NULL, NULL, 2, &fX[0], &fY[0], NULL, NULL);
|
|---|
| 713 |
|
|---|
| 714 | int iShapeID = SHPWriteObject(hOutShapeFile, -1, shpObj);
|
|---|
| 715 | if (iShapeID == -1)
|
|---|
| 716 | {
|
|---|
| 717 | if (errno != 0)
|
|---|
| 718 | printf("ERROR: Failed to write line to output shapefile \"%s\". The shapelib.dll function SHPWriteObject() failed. On exit of that function, the global error number was set to %d: %s\n", pszOutFile, errno, strerror(errno));
|
|---|
| 719 | else
|
|---|
| 720 | printf("ERROR: Failed to write line to output shapefile \"%s\". The shapelib.dll function SHPWriteObject() failed. Unfortunately that function does not return any detailed error information, and the global error number was set to zero (no error).\n", pszOutFile);
|
|---|
| 721 | SHPClose(hOutShapeFile);
|
|---|
| 722 | DBFClose(hOutDBFFile);
|
|---|
| 723 | return 1;
|
|---|
| 724 | }
|
|---|
| 725 |
|
|---|
| 726 | SHPDestroyObject(shpObj);
|
|---|
| 727 |
|
|---|
| 728 | // Write attributes to the DBF file.
|
|---|
| 729 |
|
|---|
| 730 |
|
|---|
| 731 | if (!DBFWriteDoubleAttribute(hOutDBFFile, iShapeID, 0, dMagnitude) ||
|
|---|
| 732 | !DBFWriteDoubleAttribute(hOutDBFFile, iShapeID, 1, dDirection))
|
|---|
| 733 | {
|
|---|
| 734 | if (errno != 0)
|
|---|
| 735 | printf("ERROR: Failed to write an attribute to the output DBF file \"%s.dbf\". The shapelib.dll function DBFWriteDoubleAttribute() failed. On exit of that function, the global error number was set to %d: %s\n", pszOutFile, errno, strerror(errno));
|
|---|
| 736 | else
|
|---|
| 737 | printf("ERROR: Failed to write an attribute to the output DBF file \"%s.dbf\". The shapelib.dll function DBFWriteDoubleAttribute() failed. Unfortunately that function does not return any detailed error information, and the global error number was set to zero (no error).\n", pszOutFile);
|
|---|
| 738 | SHPClose(hOutShapeFile);
|
|---|
| 739 | DBFClose(hOutDBFFile);
|
|---|
| 740 | return 1;
|
|---|
| 741 | }
|
|---|
| 742 | }
|
|---|
| 743 |
|
|---|
| 744 | // Go on to the next cell.
|
|---|
| 745 |
|
|---|
| 746 | switch (iDataType)
|
|---|
| 747 | {
|
|---|
| 748 | case Int8_DataType:
|
|---|
| 749 | case Uint8_DataType:
|
|---|
| 750 | dwReadIndex++;
|
|---|
| 751 | break;
|
|---|
| 752 |
|
|---|
| 753 | case Int16_DataType:
|
|---|
| 754 | case Uint16_DataType:
|
|---|
| 755 | dwReadIndex += 2;
|
|---|
| 756 | break;
|
|---|
| 757 |
|
|---|
| 758 | case Int32_DataType:
|
|---|
| 759 | case Float_DataType:
|
|---|
| 760 | dwReadIndex += 4;
|
|---|
| 761 | break;
|
|---|
| 762 |
|
|---|
| 763 | case Double_DataType:
|
|---|
| 764 | dwReadIndex += 8;
|
|---|
| 765 | break;
|
|---|
| 766 |
|
|---|
| 767 | default:
|
|---|
| 768 | printf("ERROR: Programming error in this tool. Invalid DataType. Please contact the author of this tool for assistance.\n");
|
|---|
| 769 | SHPClose(hOutShapeFile);
|
|---|
| 770 | DBFClose(hOutDBFFile);
|
|---|
| 771 | return 1;
|
|---|
| 772 | }
|
|---|
| 773 | }
|
|---|
| 774 | }
|
|---|
| 775 |
|
|---|
| 776 | // Close the files.
|
|---|
| 777 |
|
|---|
| 778 | printf("Done.\n");
|
|---|
| 779 |
|
|---|
| 780 | CloseHandle(hXFile);
|
|---|
| 781 | CloseHandle(hYFile);
|
|---|
| 782 | SHPClose(hOutShapeFile);
|
|---|
| 783 | DBFClose(hOutDBFFile);
|
|---|
| 784 |
|
|---|
| 785 | // Return successfully.
|
|---|
| 786 |
|
|---|
| 787 | return 0;
|
|---|
| 788 | }
|
|---|