shp 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +34 -0
  3. data/.travis.yml +4 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +28 -0
  6. data/README.md +30 -0
  7. data/Rakefile +23 -0
  8. data/ext/shp/base.hpp +113 -0
  9. data/ext/shp/dbf.cpp +381 -0
  10. data/ext/shp/dbf.hpp +44 -0
  11. data/ext/shp/extconf.rb +13 -0
  12. data/ext/shp/shape_object.cpp +58 -0
  13. data/ext/shp/shape_object.hpp +27 -0
  14. data/ext/shp/shapefile.cpp +299 -0
  15. data/ext/shp/shapefile.hpp +35 -0
  16. data/ext/shp/shapelib/.cvsignore +15 -0
  17. data/ext/shp/shapelib/ChangeLog +450 -0
  18. data/ext/shp/shapelib/HOWTO-RELEASE +16 -0
  19. data/ext/shp/shapelib/LICENSE.LGPL +483 -0
  20. data/ext/shp/shapelib/Makefile +113 -0
  21. data/ext/shp/shapelib/README +41 -0
  22. data/ext/shp/shapelib/README.tree +172 -0
  23. data/ext/shp/shapelib/contrib/.cvsignore +12 -0
  24. data/ext/shp/shapelib/contrib/Makefile +66 -0
  25. data/ext/shp/shapelib/contrib/ShapeFileII.pas +234 -0
  26. data/ext/shp/shapelib/contrib/Shape_PointInPoly.cpp +238 -0
  27. data/ext/shp/shapelib/contrib/Shape_PointInPoly_README.txt +59 -0
  28. data/ext/shp/shapelib/contrib/csv2shp.c +558 -0
  29. data/ext/shp/shapelib/contrib/dbfcat.c +166 -0
  30. data/ext/shp/shapelib/contrib/dbfinfo.c +106 -0
  31. data/ext/shp/shapelib/contrib/makefile.vc +34 -0
  32. data/ext/shp/shapelib/contrib/my_nan.h +46 -0
  33. data/ext/shp/shapelib/contrib/shpcat.c +100 -0
  34. data/ext/shp/shapelib/contrib/shpcentrd.c +159 -0
  35. data/ext/shp/shapelib/contrib/shpdata.c +129 -0
  36. data/ext/shp/shapelib/contrib/shpdxf.c +340 -0
  37. data/ext/shp/shapelib/contrib/shpfix.c +110 -0
  38. data/ext/shp/shapelib/contrib/shpgeo.c +1595 -0
  39. data/ext/shp/shapelib/contrib/shpgeo.h +154 -0
  40. data/ext/shp/shapelib/contrib/shpinfo.c +113 -0
  41. data/ext/shp/shapelib/contrib/shpproj.c +260 -0
  42. data/ext/shp/shapelib/contrib/shpsort.c +605 -0
  43. data/ext/shp/shapelib/contrib/shpsort.txt +44 -0
  44. data/ext/shp/shapelib/contrib/shpwkb.c +123 -0
  45. data/ext/shp/shapelib/contrib/tests/shpproj.sh +38 -0
  46. data/ext/shp/shapelib/dbfopen.c +2221 -0
  47. data/ext/shp/shapelib/makefile.vc +86 -0
  48. data/ext/shp/shapelib/makeshape.sh +21 -0
  49. data/ext/shp/shapelib/mkdist.sh +37 -0
  50. data/ext/shp/shapelib/mkinstalldirs +38 -0
  51. data/ext/shp/shapelib/mkrelease.sh +55 -0
  52. data/ext/shp/shapelib/safileio.c +286 -0
  53. data/ext/shp/shapelib/shapefil.h +647 -0
  54. data/ext/shp/shapelib/shapelib.def +46 -0
  55. data/ext/shp/shapelib/shpopen.c +2388 -0
  56. data/ext/shp/shapelib/shptree.c +1187 -0
  57. data/ext/shp/shapelib/shputils.c +1072 -0
  58. data/ext/shp/shapelib/stream1.out +1465 -0
  59. data/ext/shp/shapelib/stream1.sh +28 -0
  60. data/ext/shp/shapelib/stream2.out +530 -0
  61. data/ext/shp/shapelib/stream2.sh +11 -0
  62. data/ext/shp/shapelib/stream3.out +37 -0
  63. data/ext/shp/shapelib/web/.cvsignore +2 -0
  64. data/ext/shp/shapelib/web/codepage.html +403 -0
  65. data/ext/shp/shapelib/web/dbf_api.html +436 -0
  66. data/ext/shp/shapelib/web/index.html +235 -0
  67. data/ext/shp/shapelib/web/license.html +78 -0
  68. data/ext/shp/shapelib/web/manifest.html +87 -0
  69. data/ext/shp/shapelib/web/release.html +80 -0
  70. data/ext/shp/shapelib/web/shapelib-tools.html +352 -0
  71. data/ext/shp/shapelib/web/shp_api.html +376 -0
  72. data/ext/shp/shp.cpp +19 -0
  73. data/ext/shp/shp.hpp +47 -0
  74. data/lib/shp.rb +35 -0
  75. data/lib/shp/version.rb +3 -0
  76. data/shp.gemspec +23 -0
  77. data/spec/shp_spec.rb +127 -0
  78. metadata +176 -0
@@ -0,0 +1,605 @@
1
+ /******************************************************************************
2
+ * Copyright (c) 2004, Eric G. Miller
3
+ *
4
+ * This code is based in part on the earlier work of Frank Warmerdam
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included
14
+ * in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
+ * DEALINGS IN THE SOFTWARE.
23
+ ******************************************************************************
24
+ * shpsort
25
+ *
26
+ * Rewrite a shapefile sorted by a field or by the geometry. For polygons,
27
+ * sort by area, for lines sort by length and do nothing for all others.
28
+ *
29
+ * $Log: shpsort.c,v $
30
+ * Revision 1.3 2004-07-06 21:23:17 fwarmerdam
31
+ * minor const warning fix
32
+ *
33
+ * Revision 1.2 2004/07/06 21:20:49 fwarmerdam
34
+ * major upgrade .. sort on multiple fields
35
+ *
36
+ * Revision 1.4 2004/06/30 18:19:53 emiller
37
+ * handle POINTZ, POINTM
38
+ *
39
+ * Revision 1.3 2004/06/30 17:40:32 emiller
40
+ * major rewrite allows sorting on multiple fields.
41
+ *
42
+ * Revision 1.2 2004/06/23 23:19:58 emiller
43
+ * use tuple copy, misc changes
44
+ *
45
+ * Revision 1.1 2004/06/23 21:38:17 emiller
46
+ * Initial revision
47
+ *
48
+ *
49
+ */
50
+
51
+ #include <stdio.h>
52
+ #include <stdlib.h>
53
+ #include <ctype.h>
54
+ #include <string.h>
55
+ #include <math.h>
56
+ #include "shapefil.h"
57
+
58
+ enum FieldOrderEnum {DESCENDING, ASCENDING};
59
+ enum FieldTypeEnum {
60
+ FIDType = -2,
61
+ SHPType = -1,
62
+ StringType = FTString,
63
+ LogicalType = FTLogical,
64
+ IntegerType = FTInteger,
65
+ DoubleType = FTDouble
66
+ };
67
+
68
+ struct DataUnion {
69
+ int null;
70
+ union {
71
+ int i;
72
+ double d;
73
+ char *s;
74
+ } u;
75
+ };
76
+
77
+ struct DataStruct {
78
+ int record;
79
+ struct DataUnion *value;
80
+ };
81
+
82
+ /*
83
+ globals used in sorting, each element could have a pointer to
84
+ a single data struct, but that's still nShapes pointers more
85
+ memory. Alternatively, write a custom sort rather than using
86
+ library qsort.
87
+ */
88
+ int nFields;
89
+ int *fldIdx;
90
+ int *fldOrder;
91
+ int *fldType;
92
+ int shpType;
93
+ int nShapes;
94
+
95
+ static struct DataStruct * build_index (SHPHandle shp, DBFHandle dbf);
96
+ static char * dupstr (const char *);
97
+ static void copy_related (const char *inName, const char *outName,
98
+ const char *old_ext, const char *new_ext);
99
+ static char ** split(const char *arg, const char *delim);
100
+ static int compare(const void *, const void *);
101
+ static double area2d_polygon (int n, double *x, double *y);
102
+ static double shp_area (SHPObject *feat);
103
+ static double length2d_polyline (int n, double *x, double *y);
104
+ static double shp_length (SHPObject *feat);
105
+
106
+ int main (int argc, char *argv[]) {
107
+
108
+ SHPHandle inSHP, outSHP;
109
+ DBFHandle inDBF, outDBF;
110
+ int len;
111
+ int i;
112
+ char **fieldNames;
113
+ char **strOrder = 0;
114
+ struct DataStruct *index;
115
+ int width;
116
+ int decimals;
117
+ SHPObject *feat;
118
+ void *tuple;
119
+
120
+ if (argc < 4) {
121
+ printf("USAGE: shpsort <infile> <outfile> <field[;...]> [<(ASCENDING|DESCENDING)[;...]>]\n");
122
+ exit(EXIT_FAILURE);
123
+ }
124
+
125
+ inSHP = SHPOpen (argv[1], "rb");
126
+ if (!inSHP) {
127
+ fputs("Couldn't open shapefile for reading!\n", stderr);
128
+ exit(EXIT_FAILURE);
129
+ }
130
+ SHPGetInfo(inSHP, &nShapes, &shpType, NULL, NULL);
131
+
132
+ /* If we can open the inSHP, open its DBF */
133
+ inDBF = DBFOpen (argv[1], "rb");
134
+ if (!inDBF) {
135
+ fputs("Couldn't open dbf file for reading!\n", stderr);
136
+ exit(EXIT_FAILURE);
137
+ }
138
+
139
+ /* Parse fields and validate existence */
140
+ fieldNames = split(argv[3], ";");
141
+ if (!fieldNames) {
142
+ fputs("ERROR: parsing field names!\n", stderr);
143
+ exit(EXIT_FAILURE);
144
+ }
145
+ for (nFields = 0; fieldNames[nFields] ; nFields++) {
146
+ continue;
147
+ }
148
+
149
+ fldIdx = malloc(sizeof *fldIdx * nFields);
150
+ if (!fldIdx) {
151
+ fputs("malloc failed!\n", stderr);
152
+ exit(EXIT_FAILURE);
153
+ }
154
+ for (i = 0; i < nFields; i++) {
155
+ len = (int)strlen(fieldNames[i]);
156
+ while(len > 0) {
157
+ --len;
158
+ fieldNames[i][len] = (char)toupper((unsigned char)fieldNames[i][len]);
159
+ }
160
+ fldIdx[i] = DBFGetFieldIndex(inDBF, fieldNames[i]);
161
+ if (fldIdx[i] < 0) {
162
+ /* try "SHAPE" */
163
+ if (strcmp(fieldNames[i], "SHAPE") == 0) {
164
+ fldIdx[i] = -1;
165
+ }
166
+ else if (strcmp(fieldNames[i], "FID") == 0) {
167
+ fldIdx[i] = -2;
168
+ }
169
+ else {
170
+ fprintf(stderr, "ERROR: field '%s' not found!\n", fieldNames[i]);
171
+ exit(EXIT_FAILURE);
172
+ }
173
+ }
174
+ }
175
+
176
+
177
+ /* set up field type array */
178
+ fldType = malloc(sizeof *fldType * nFields);
179
+ if (!fldType) {
180
+ fputs("malloc failed!\n", stderr);
181
+ exit(EXIT_FAILURE);
182
+ }
183
+ for (i = 0; i < nFields; i++) {
184
+ if (fldIdx[i] < 0) {
185
+ fldType[i] = fldIdx[i];
186
+ }
187
+ else {
188
+ fldType[i] = DBFGetFieldInfo(inDBF, fldIdx[i], NULL, &width, &decimals);
189
+ if (fldType[i] == FTInvalid) {
190
+ fputs("Unrecognized field type in dBASE file!\n", stderr);
191
+ exit(EXIT_FAILURE);
192
+ }
193
+ }
194
+ }
195
+
196
+
197
+ /* set up field order array */
198
+ fldOrder = malloc(sizeof *fldOrder * nFields);
199
+ if (!fldOrder) {
200
+ fputs("malloc failed!\n", stderr);
201
+ exit(EXIT_FAILURE);
202
+ }
203
+ for (i = 0; i < nFields; i++) {
204
+ /* default to ascending order */
205
+ fldOrder[i] = ASCENDING;
206
+ }
207
+ if (argc > 4) {
208
+ strOrder = split(argv[4], ";");
209
+ if (!strOrder) {
210
+ fputs("ERROR: parsing fields ordering!\n", stderr);
211
+ exit(EXIT_FAILURE);
212
+ }
213
+ for (i = 0; i < nFields && strOrder[i]; i++) {
214
+ if (strcmp(strOrder[i], "DESCENDING") == 0) {
215
+ fldOrder[i] = DESCENDING;
216
+ }
217
+ }
218
+ }
219
+
220
+ /* build the index */
221
+ index = build_index (inSHP, inDBF);
222
+
223
+ /* Create output shapefile */
224
+ outSHP = SHPCreate(argv[2], shpType);
225
+ if (!outSHP) {
226
+ fprintf(stderr, "%s:%d: couldn't create output shapefile!\n",
227
+ __FILE__, __LINE__);
228
+ exit(EXIT_FAILURE);
229
+ }
230
+
231
+ /* Create output dbf */
232
+ outDBF = DBFCloneEmpty(inDBF, argv[2]);
233
+ if (!outDBF) {
234
+ fprintf(stderr, "%s:%d: couldn't create output dBASE file!\n",
235
+ __FILE__, __LINE__);
236
+ exit(EXIT_FAILURE);
237
+ }
238
+
239
+ /* Copy projection file, if any */
240
+ copy_related(argv[1], argv[2], ".shp", ".prj");
241
+
242
+ /* Copy metadata file, if any */
243
+ copy_related(argv[1], argv[2], ".shp", ".shp.xml");
244
+
245
+ /* Write out sorted results */
246
+ for (i = 0; i < nShapes; i++) {
247
+ feat = SHPReadObject(inSHP, index[i].record);
248
+ if (SHPWriteObject(outSHP, -1, feat) < 0) {
249
+ fprintf(stderr, "%s:%d: error writing shapefile!\n", __FILE__, __LINE__);
250
+ exit(EXIT_FAILURE);
251
+ }
252
+ tuple = (void *) DBFReadTuple(inDBF, index[i].record);
253
+ if (DBFWriteTuple(outDBF, i, tuple) < 0) {
254
+ fprintf(stderr, "%s:%d: error writing dBASE file!\n", __FILE__, __LINE__);
255
+ exit(EXIT_FAILURE);
256
+ }
257
+ }
258
+ SHPClose(inSHP);
259
+ SHPClose(outSHP);
260
+ DBFClose(inDBF);
261
+ DBFClose(outDBF);
262
+
263
+ return EXIT_SUCCESS;
264
+
265
+ }
266
+
267
+ static char ** split(const char *arg, const char *delim)
268
+ {
269
+ char *copy = dupstr(arg);
270
+ char *cptr = copy;
271
+ char **result = NULL;
272
+ char **tmp;
273
+ int i = 0;
274
+
275
+ for (cptr = strtok(copy, delim); cptr; cptr = strtok(NULL, delim)) {
276
+ tmp = realloc (result, sizeof *result * (i + 1));
277
+ if (!tmp && result) {
278
+ while (i > 0) {
279
+ free(result[--i]);
280
+ }
281
+ free(result);
282
+ free(copy);
283
+ return NULL;
284
+ }
285
+ result = tmp;
286
+ result[i++] = dupstr(cptr);
287
+ }
288
+
289
+ free(copy);
290
+
291
+ if (i) {
292
+ tmp = realloc(result, sizeof *result * (i + 1));
293
+ if (!tmp) {
294
+ while (i > 0) {
295
+ free(result[--i]);
296
+ }
297
+ free(result);
298
+ free(copy);
299
+ return NULL;
300
+ }
301
+ result = tmp;
302
+ result[i++] = NULL;
303
+ }
304
+
305
+ return result;
306
+ }
307
+
308
+
309
+ static void copy_related (const char *inName, const char *outName,
310
+ const char *old_ext, const char *new_ext)
311
+ {
312
+ char *in;
313
+ char *out;
314
+ FILE *inFile;
315
+ FILE *outFile;
316
+ int c;
317
+ size_t name_len = strlen(inName);
318
+ size_t old_len = strlen(old_ext);
319
+ size_t new_len = strlen(new_ext);
320
+
321
+ in = malloc(name_len - old_len + new_len + 1);
322
+ strncpy(in, inName, (name_len - old_len));
323
+ strcpy(&in[(name_len - old_len)], new_ext);
324
+ inFile = fopen(in, "rb");
325
+ if (!inFile) {
326
+ free(in);
327
+ return;
328
+ }
329
+ name_len = strlen(outName);
330
+ out = malloc(name_len - old_len + new_len + 1);
331
+ strncpy(out, outName, (name_len - old_len));
332
+ strcpy(&out[(name_len - old_len)], new_ext);
333
+ outFile = fopen(out, "wb");
334
+ if (!out) {
335
+ fprintf(stderr, "%s:%d: couldn't copy related file!\n",
336
+ __FILE__, __LINE__);
337
+ free(in);
338
+ free(out);
339
+ return;
340
+ }
341
+ while ((c = fgetc(inFile)) != EOF) {
342
+ fputc(c, outFile);
343
+ }
344
+ fclose(inFile);
345
+ fclose(outFile);
346
+ free(in);
347
+ free(out);
348
+ }
349
+
350
+ static char * dupstr (const char *src)
351
+ {
352
+ char *dst = malloc(strlen(src) + 1);
353
+ char *cptr;
354
+ if (!dst) {
355
+ fprintf(stderr, "%s:%d: malloc failed!\n", __FILE__, __LINE__);
356
+ exit(EXIT_FAILURE);
357
+ }
358
+ cptr = dst;
359
+ while ((*cptr++ = *src++))
360
+ ;
361
+ return dst;
362
+ }
363
+
364
+ #ifdef DEBUG
365
+ static void PrintDataStruct (struct DataStruct *data) {
366
+ int i, j;
367
+ for (i = 0; i < nShapes; i++) {
368
+ printf("data[%d] {\n", i);
369
+ printf("\t.record = %d\n", data[i].record);
370
+ for (j = 0; j < nFields; j++) {
371
+ printf("\t.value[%d].null = %d\n", j, data[i].value[j].null);
372
+ if (!data[i].value[j].null) {
373
+ switch(fldType[j]) {
374
+ case FIDType:
375
+ case IntegerType:
376
+ case LogicalType:
377
+ printf("\t.value[%d].u.i = %d\n", j, data[i].value[j].u.i);
378
+ break;
379
+ case DoubleType:
380
+ case SHPType:
381
+ printf("\t.value[%d].u.d = %f\n", j, data[i].value[j].u.d);
382
+ break;
383
+ case StringType:
384
+ printf("\t.value[%d].u.s = %s\n", j, data[i].value[j].u.s);
385
+ break;
386
+ }
387
+ }
388
+ }
389
+ puts("}");
390
+ }
391
+ }
392
+ #endif
393
+
394
+ static struct DataStruct * build_index (SHPHandle shp, DBFHandle dbf) {
395
+ struct DataStruct *data;
396
+ SHPObject *feat;
397
+ int i;
398
+ int j;
399
+
400
+ /* make array */
401
+ data = malloc (sizeof *data * nShapes);
402
+ if (!data) {
403
+ fputs("malloc failed!\n", stderr);
404
+ exit(EXIT_FAILURE);
405
+ }
406
+
407
+ /* populate array */
408
+ for (i = 0; i < nShapes; i++) {
409
+ data[i].value = malloc(sizeof data[0].value[0] * nFields);
410
+ if (0 == data[i].value) {
411
+ fputs("malloc failed!\n", stderr);
412
+ exit(EXIT_FAILURE);
413
+ }
414
+ data[i].record = i;
415
+ for (j = 0; j < nFields; j++) {
416
+ data[i].value[j].null = 0;
417
+ switch (fldType[j]) {
418
+ case FIDType:
419
+ data[i].value[j].u.i = i;
420
+ break;
421
+ case SHPType:
422
+ feat = SHPReadObject(shp, i);
423
+ switch (feat->nSHPType) {
424
+ case SHPT_NULL:
425
+ fprintf(stderr, "Shape %d is a null feature!\n", i);
426
+ data[i].value[j].null = 1;
427
+ break;
428
+ case SHPT_POINT:
429
+ case SHPT_POINTZ:
430
+ case SHPT_POINTM:
431
+ case SHPT_MULTIPOINT:
432
+ case SHPT_MULTIPOINTZ:
433
+ case SHPT_MULTIPOINTM:
434
+ case SHPT_MULTIPATCH:
435
+ /* Y-sort bounds */
436
+ data[i].value[j].u.d = feat->dfYMax;
437
+ break;
438
+ case SHPT_ARC:
439
+ case SHPT_ARCZ:
440
+ case SHPT_ARCM:
441
+ data[i].value[j].u.d = shp_length(feat);
442
+ break;
443
+ case SHPT_POLYGON:
444
+ case SHPT_POLYGONZ:
445
+ case SHPT_POLYGONM:
446
+ data[i].value[j].u.d = shp_area(feat);
447
+ break;
448
+ default:
449
+ fputs("Can't sort on Shapefile feature type!\n", stderr);
450
+ exit(EXIT_FAILURE);
451
+ }
452
+ SHPDestroyObject(feat);
453
+ break;
454
+ case FTString:
455
+ data[i].value[j].null = DBFIsAttributeNULL(dbf, i, fldIdx[j]);
456
+ if (!data[i].value[j].null) {
457
+ data[i].value[j].u.s = dupstr(DBFReadStringAttribute(dbf, i, fldIdx[j]));
458
+ }
459
+ break;
460
+ case FTInteger:
461
+ case FTLogical:
462
+ data[i].value[j].null = DBFIsAttributeNULL(dbf, i, fldIdx[j]);
463
+ if (!data[i].value[j].null) {
464
+ data[i].value[j].u.i = DBFReadIntegerAttribute(dbf, i, fldIdx[j]);
465
+ }
466
+ break;
467
+ case FTDouble:
468
+ data[i].value[j].null = DBFIsAttributeNULL(dbf, i, fldIdx[j]);
469
+ if (!data[i].value[j].null) {
470
+ data[i].value[j].u.d = DBFReadDoubleAttribute(dbf, i, fldIdx[j]);
471
+ }
472
+ break;
473
+ }
474
+ }
475
+ }
476
+
477
+ #ifdef DEBUG
478
+ PrintDataStruct(data);
479
+ fputs("build_index: sorting array\n", stdout);
480
+ #endif
481
+
482
+ qsort (data, nShapes, sizeof data[0], compare);
483
+
484
+ #ifdef DEBUG
485
+ PrintDataStruct(data);
486
+ fputs("build_index: returning array\n", stdout);
487
+ #endif
488
+
489
+ return data;
490
+ }
491
+
492
+ static int compare(const void *A, const void *B) {
493
+ const struct DataStruct *a = A;
494
+ const struct DataStruct *b = B;
495
+ int i;
496
+ int result = 0;
497
+
498
+ for (i = 0; i < nFields; i++) {
499
+ if (a->value[i].null && b->value[i].null) {
500
+ continue;
501
+ }
502
+ if (a->value[i].null && !b->value[i].null) {
503
+ return (fldOrder[i]) ? 1 : -1;
504
+ }
505
+ if (!a->value[i].null && b->value[i].null) {
506
+ return (fldOrder[i]) ? -1 : 1;
507
+ }
508
+ switch (fldType[i]) {
509
+ case FIDType:
510
+ case IntegerType:
511
+ case LogicalType:
512
+ if (a->value[i].u.i < b->value[i].u.i) {
513
+ return (fldOrder[i]) ? -1 : 1;
514
+ }
515
+ if (a->value[i].u.i > b->value[i].u.i) {
516
+ return (fldOrder[i]) ? 1 : -1;
517
+ }
518
+ break;
519
+ case DoubleType:
520
+ case SHPType:
521
+ if (a->value[i].u.d < b->value[i].u.d) {
522
+ return (fldOrder[i]) ? -1 : 1;
523
+ }
524
+ if (a->value[i].u.d > b->value[i].u.d) {
525
+ return (fldOrder[i]) ? 1 : -1;
526
+ }
527
+ break;
528
+ case StringType:
529
+ result = strcmp(a->value[i].u.s, b->value[i].u.s);
530
+ if (result) {
531
+ return (fldOrder[i]) ? result : -result;
532
+ }
533
+ break;
534
+ default:
535
+ fprintf(stderr, "compare: Program Error! Unhandled field type! fldType[%d] = %d\n", i, fldType[i]);
536
+ break;
537
+ }
538
+ }
539
+ return 0;
540
+ }
541
+
542
+ static double area2d_polygon (int n, double *x, double *y) {
543
+ double area = 0;
544
+ int i;
545
+ for (i = 1; i < n; i++) {
546
+ area += (x[i-1] + x[i]) * (y[i] - y[i-1]);
547
+ }
548
+ return area / 2.0;
549
+ }
550
+
551
+ static double shp_area (SHPObject *feat) {
552
+ double area = 0.0;
553
+ if (feat->nParts == 0) {
554
+ area = area2d_polygon (feat->nVertices, feat->padfX, feat->padfY);
555
+ }
556
+ else {
557
+ int part, n;
558
+ for (part = 0; part < feat->nParts; part++) {
559
+ if (part < feat->nParts - 1) {
560
+ n = feat->panPartStart[part+1] - feat->panPartStart[part];
561
+ }
562
+ else {
563
+ n = feat->nVertices - feat->panPartStart[part];
564
+ }
565
+ area += area2d_polygon (n, &(feat->padfX[feat->panPartStart[part]]),
566
+ &(feat->padfY[feat->panPartStart[part]]));
567
+ }
568
+ }
569
+ /* our area function computes in opposite direction */
570
+ return -area;
571
+ }
572
+
573
+ static double length2d_polyline (int n, double *x, double *y) {
574
+ double length = 0.0;
575
+ int i;
576
+ for (i = 1; i < n; i++) {
577
+ length += sqrt((x[i] - x[i-1])*(x[i] - x[i-1])
578
+ +
579
+ (y[i] - y[i-1])*(y[i] - y[i-1]));
580
+ }
581
+ return length;
582
+ }
583
+
584
+ static double shp_length (SHPObject *feat) {
585
+ double length = 0.0;
586
+ if (feat->nParts == 0) {
587
+ length = length2d_polyline(feat->nVertices, feat->padfX, feat->padfY);
588
+ }
589
+ else {
590
+ int part, n;
591
+ for (part = 0; part < feat->nParts; part++) {
592
+ if (part < feat->nParts - 1) {
593
+ n = feat->panPartStart[part+1] - feat->panPartStart[part];
594
+ }
595
+ else {
596
+ n = feat->nVertices - feat->panPartStart[part];
597
+ }
598
+ length += length2d_polyline (n,
599
+ &(feat->padfX[feat->panPartStart[part]]),
600
+ &(feat->padfY[feat->panPartStart[part]]));
601
+ }
602
+ }
603
+ return length;
604
+ }
605
+