rgeo 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,46 @@
1
+ /*
2
+ Geometry collection methods for GEOS wrapper
3
+ */
4
+
5
+
6
+ #ifndef RGEO_GEOS_GEOMETRY_COLLECTION_INCLUDED
7
+ #define RGEO_GEOS_GEOMETRY_COLLECTION_INCLUDED
8
+
9
+ #include <ruby.h>
10
+ #include <geos_c.h>
11
+
12
+ #include "factory.h"
13
+
14
+ RGEO_BEGIN_C
15
+
16
+
17
+ /*
18
+ Initializes the geometry collection module. This should be called after
19
+ the geometry module is initialized.
20
+ */
21
+ void rgeo_init_geos_geometry_collection(RGeo_Globals* globals);
22
+
23
+ /*
24
+ Comopares the contents of two geometry collections. Does not test the
25
+ types of the collections themselves, but tests the types, values, and
26
+ contents of all the contents. The two given geometries MUST be
27
+ collection types-- i.e. GeometryCollection, MultiPoint, MultiLineString,
28
+ or MultiPolygon.
29
+ Returns Qtrue if the contents of the two geometry collections are equal,
30
+ Qfalse if they are inequal, or Qnil if an error occurs.
31
+ */
32
+ VALUE rgeo_geos_geometry_collections_eql(GEOSContextHandle_t context, const GEOSGeometry* geom1, const GEOSGeometry* geom2, char check_z);
33
+
34
+ /*
35
+ A tool for building up hash values.
36
+ You must pass in the context, a geos geometry, and a seed hash.
37
+ Returns an updated hash.
38
+ This call is useful in sequence, and should be bracketed by calls to
39
+ rb_hash_start and rb_hash_end.
40
+ */
41
+ st_index_t rgeo_geos_geometry_collection_hash(GEOSContextHandle_t context, const GEOSGeometry* geom, st_index_t hash);
42
+
43
+
44
+ RGEO_END_C
45
+
46
+ #endif
@@ -0,0 +1,675 @@
1
+ /*
2
+ Line string methods for GEOS wrapper
3
+ */
4
+
5
+
6
+ #include "preface.h"
7
+
8
+ #ifdef RGEO_GEOS_SUPPORTED
9
+
10
+ #include <string.h>
11
+ #include <ruby.h>
12
+ #include <geos_c.h>
13
+
14
+ #include "factory.h"
15
+ #include "geometry.h"
16
+ #include "point.h"
17
+ #include "line_string.h"
18
+
19
+ #include "coordinates.h"
20
+
21
+ RGEO_BEGIN_C
22
+
23
+
24
+ static VALUE method_line_string_geometry_type(VALUE self)
25
+ {
26
+ VALUE result;
27
+ RGeo_GeometryData* self_data;
28
+
29
+ result = Qnil;
30
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
31
+ if (self_data->geom) {
32
+ result = RGEO_FACTORY_DATA_PTR(self_data->factory)->globals->feature_line_string;
33
+ }
34
+ return result;
35
+ }
36
+
37
+
38
+ static VALUE method_linear_ring_geometry_type(VALUE self)
39
+ {
40
+ VALUE result;
41
+ RGeo_GeometryData* self_data;
42
+
43
+ result = Qnil;
44
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
45
+ if (self_data->geom) {
46
+ result = RGEO_FACTORY_DATA_PTR(self_data->factory)->globals->feature_linear_ring;
47
+ }
48
+ return result;
49
+ }
50
+
51
+
52
+ static VALUE method_line_geometry_type(VALUE self)
53
+ {
54
+ VALUE result;
55
+ RGeo_GeometryData* self_data;
56
+
57
+ result = Qnil;
58
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
59
+ if (self_data->geom) {
60
+ result = RGEO_FACTORY_DATA_PTR(self_data->factory)->globals->feature_line;
61
+ }
62
+ return result;
63
+ }
64
+
65
+
66
+ static VALUE method_line_string_length(VALUE self)
67
+ {
68
+ VALUE result;
69
+ RGeo_GeometryData* self_data;
70
+ const GEOSGeometry* self_geom;
71
+ double len;
72
+
73
+ result = Qnil;
74
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
75
+ self_geom = self_data->geom;
76
+ if (self_geom) {
77
+ if (GEOSLength_r(self_data->geos_context, self_geom, &len)) {
78
+ result = rb_float_new(len);
79
+ }
80
+ }
81
+ return result;
82
+ }
83
+
84
+
85
+ static VALUE method_line_string_num_points(VALUE self)
86
+ {
87
+ VALUE result;
88
+ RGeo_GeometryData* self_data;
89
+ const GEOSGeometry* self_geom;
90
+
91
+ result = Qnil;
92
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
93
+ self_geom = self_data->geom;
94
+ if (self_geom) {
95
+ result = INT2NUM(GEOSGetNumCoordinates_r(self_data->geos_context, self_geom));
96
+ }
97
+ return result;
98
+ }
99
+
100
+
101
+ static void d(VALUE v) {
102
+ ID sym_puts = rb_intern("puts");
103
+ ID sym_inspect = rb_intern("inspect");
104
+ rb_funcall(rb_mKernel, sym_puts, 1,
105
+ rb_funcall(v, sym_inspect, 0));
106
+ }
107
+
108
+ static VALUE method_line_string_coordinates(VALUE self)
109
+ {
110
+ VALUE result;
111
+ VALUE point_tuple;
112
+ RGeo_GeometryData* self_data;
113
+ const GEOSGeometry* self_geom;
114
+ const GEOSCoordSequence* coord_sequence;
115
+ int zCoordinate;
116
+
117
+ GEOSContextHandle_t context;
118
+
119
+ result = Qnil;
120
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
121
+ self_geom = self_data->geom;
122
+
123
+ if (self_geom) {
124
+ zCoordinate = RGEO_FACTORY_DATA_PTR(self_data->factory)->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M;
125
+ context = self_data->geos_context;
126
+ coord_sequence = GEOSGeom_getCoordSeq_r(context, self_geom);
127
+ if(coord_sequence) {
128
+ result = extract_points_from_coordinate_sequence(context, coord_sequence, zCoordinate);
129
+ }
130
+ }
131
+ return result;
132
+ }
133
+
134
+
135
+
136
+ static VALUE get_point_from_coordseq(VALUE self, const GEOSCoordSequence* coord_seq, unsigned int i, char has_z)
137
+ {
138
+ VALUE result;
139
+ RGeo_GeometryData* self_data;
140
+ GEOSContextHandle_t self_context;
141
+ double x, y, z;
142
+
143
+ result = Qnil;
144
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
145
+ self_context = self_data->geos_context;
146
+ if (GEOSCoordSeq_getX_r(self_context, coord_seq, i, &x)) {
147
+ if (GEOSCoordSeq_getY_r(self_context, coord_seq, i, &y)) {
148
+ if (has_z) {
149
+ if (!GEOSCoordSeq_getZ_r(self_context, coord_seq, i, &z)) {
150
+ z = 0.0;
151
+ }
152
+ }
153
+ else {
154
+ z = 0.0;
155
+ }
156
+ result = rgeo_create_geos_point(self_data->factory, x, y, z);
157
+ }
158
+ }
159
+ return result;
160
+ }
161
+
162
+
163
+ static VALUE method_line_string_point_n(VALUE self, VALUE n)
164
+ {
165
+ VALUE result;
166
+ RGeo_GeometryData* self_data;
167
+ const GEOSGeometry* self_geom;
168
+ GEOSContextHandle_t self_context;
169
+ const GEOSCoordSequence* coord_seq;
170
+ char has_z;
171
+ int si;
172
+ unsigned int i;
173
+ unsigned int size;
174
+
175
+ result = Qnil;
176
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
177
+ self_geom = self_data->geom;
178
+ if (self_geom) {
179
+ self_context = self_data->geos_context;
180
+ coord_seq = GEOSGeom_getCoordSeq_r(self_context, self_geom);
181
+ if (coord_seq) {
182
+ has_z = (char)(RGEO_FACTORY_DATA_PTR(self_data->factory)->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M);
183
+ si = NUM2INT(n);
184
+ if (si >= 0) {
185
+ i = si;
186
+ if (GEOSCoordSeq_getSize_r(self_context, coord_seq, &size)) {
187
+ if (i < size) {
188
+ result = get_point_from_coordseq(self, coord_seq, i, has_z);
189
+ }
190
+ }
191
+ }
192
+ }
193
+ }
194
+ return result;
195
+ }
196
+
197
+
198
+ static VALUE method_line_string_points(VALUE self)
199
+ {
200
+ VALUE result;
201
+ RGeo_GeometryData* self_data;
202
+ const GEOSGeometry* self_geom;
203
+ GEOSContextHandle_t self_context;
204
+ const GEOSCoordSequence* coord_seq;
205
+ char has_z;
206
+ unsigned int size;
207
+ double x;
208
+ double y;
209
+ double z;
210
+ unsigned int i;
211
+ VALUE point;
212
+
213
+ result = Qnil;
214
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
215
+ self_geom = self_data->geom;
216
+ if (self_geom) {
217
+ self_context = self_data->geos_context;
218
+ coord_seq = GEOSGeom_getCoordSeq_r(self_context, self_geom);
219
+ if (coord_seq) {
220
+ has_z = (char)(RGEO_FACTORY_DATA_PTR(self_data->factory)->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M);
221
+ if (GEOSCoordSeq_getSize_r(self_context, coord_seq, &size)) {
222
+ result = rb_ary_new2(size);
223
+ for (i=0; i<size; ++i) {
224
+ point = get_point_from_coordseq(self, coord_seq, i, has_z);
225
+ if (!NIL_P(point)) {
226
+ rb_ary_store(result, i, point);
227
+ }
228
+ }
229
+ }
230
+ }
231
+ }
232
+ return result;
233
+ }
234
+
235
+
236
+ static VALUE method_line_string_start_point(VALUE self)
237
+ {
238
+ return method_line_string_point_n(self, INT2NUM(0));
239
+ }
240
+
241
+
242
+ static VALUE method_line_string_end_point(VALUE self)
243
+ {
244
+ VALUE result;
245
+ RGeo_GeometryData* self_data;
246
+ const GEOSGeometry* self_geom;
247
+ unsigned int n;
248
+
249
+ result = Qnil;
250
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
251
+ self_geom = self_data->geom;
252
+ if (self_geom) {
253
+ n = GEOSGetNumCoordinates_r(self_data->geos_context, self_geom);
254
+ if (n > 0) {
255
+ result = method_line_string_point_n(self, INT2NUM(n-1));
256
+ }
257
+ }
258
+ return result;
259
+ }
260
+
261
+
262
+ static VALUE method_line_string_is_closed(VALUE self)
263
+ {
264
+ VALUE result;
265
+ RGeo_GeometryData* self_data;
266
+ const GEOSGeometry* self_geom;
267
+
268
+ result = Qnil;
269
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
270
+ self_geom = self_data->geom;
271
+ if (self_geom) {
272
+ result = rgeo_is_geos_line_string_closed(self_data->geos_context, self_geom);
273
+ }
274
+ return result;
275
+ }
276
+
277
+
278
+ static VALUE method_line_string_is_ring(VALUE self)
279
+ {
280
+ VALUE result;
281
+ RGeo_GeometryData* self_data;
282
+ const GEOSGeometry* self_geom;
283
+ char val;
284
+
285
+ result = Qnil;
286
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
287
+ self_geom = self_data->geom;
288
+ if (self_geom) {
289
+ val = GEOSisRing_r(self_data->geos_context, self_geom);
290
+ if (val == 0) {
291
+ result = Qfalse;
292
+ }
293
+ else if (val == 1) {
294
+ result = Qtrue;
295
+ }
296
+ }
297
+ return result;
298
+ }
299
+
300
+
301
+ static VALUE method_line_string_eql(VALUE self, VALUE rhs)
302
+ {
303
+ VALUE result;
304
+ RGeo_GeometryData* self_data;
305
+
306
+ result = rgeo_geos_klasses_and_factories_eql(self, rhs);
307
+ if (RTEST(result)) {
308
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
309
+ result = rgeo_geos_coordseqs_eql(self_data->geos_context, self_data->geom, RGEO_GEOMETRY_DATA_PTR(rhs)->geom, RGEO_FACTORY_DATA_PTR(self_data->factory)->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M);
310
+ }
311
+ return result;
312
+ }
313
+
314
+
315
+ static VALUE method_line_string_hash(VALUE self)
316
+ {
317
+ st_index_t hash;
318
+ RGeo_GeometryData* self_data;
319
+ VALUE factory;
320
+
321
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
322
+ factory = self_data->factory;
323
+ hash = rb_hash_start(0);
324
+ hash = rgeo_geos_objbase_hash(factory,
325
+ RGEO_FACTORY_DATA_PTR(factory)->globals->feature_line_string, hash);
326
+ hash = rgeo_geos_coordseq_hash(self_data->geos_context, self_data->geom, hash);
327
+ return LONG2FIX(rb_hash_end(hash));
328
+ }
329
+
330
+
331
+ static VALUE method_linear_ring_hash(VALUE self)
332
+ {
333
+ st_index_t hash;
334
+ RGeo_GeometryData* self_data;
335
+ VALUE factory;
336
+
337
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
338
+ factory = self_data->factory;
339
+ hash = rb_hash_start(0);
340
+ hash = rgeo_geos_objbase_hash(factory,
341
+ RGEO_FACTORY_DATA_PTR(factory)->globals->feature_linear_ring, hash);
342
+ hash = rgeo_geos_coordseq_hash(self_data->geos_context, self_data->geom, hash);
343
+ return LONG2FIX(rb_hash_end(hash));
344
+ }
345
+
346
+
347
+ static VALUE method_line_hash(VALUE self)
348
+ {
349
+ st_index_t hash;
350
+ RGeo_GeometryData* self_data;
351
+ VALUE factory;
352
+
353
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
354
+ factory = self_data->factory;
355
+ hash = rb_hash_start(0);
356
+ hash = rgeo_geos_objbase_hash(factory,
357
+ RGEO_FACTORY_DATA_PTR(factory)->globals->feature_line, hash);
358
+ hash = rgeo_geos_coordseq_hash(self_data->geos_context, self_data->geom, hash);
359
+ return LONG2FIX(rb_hash_end(hash));
360
+ }
361
+
362
+
363
+ static GEOSCoordSequence* coord_seq_from_array(VALUE factory, VALUE array, char close)
364
+ {
365
+ RGeo_FactoryData* factory_data;
366
+ VALUE point_type;
367
+ unsigned int len;
368
+ char has_z;
369
+ unsigned int dims;
370
+ double* coords;
371
+ GEOSContextHandle_t context;
372
+ unsigned int i;
373
+ char good;
374
+ const GEOSGeometry* entry_geom;
375
+ const GEOSCoordSequence* entry_cs;
376
+ double x;
377
+ GEOSCoordSequence* coord_seq;
378
+
379
+ Check_Type(array, T_ARRAY);
380
+ factory_data = RGEO_FACTORY_DATA_PTR(factory);
381
+ point_type = factory_data->globals->feature_point;
382
+ len = (unsigned int)RARRAY_LEN(array);
383
+ has_z = (char)(RGEO_FACTORY_DATA_PTR(factory)->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M);
384
+ dims = has_z ? 3 : 2;
385
+ coords = ALLOC_N(double, len == 0 ? 1 : len * dims);
386
+ if (!coords) {
387
+ return NULL;
388
+ }
389
+ context = factory_data->geos_context;
390
+ for (i=0; i<len; ++i) {
391
+ good = 0;
392
+ entry_geom = rgeo_convert_to_geos_geometry(factory, rb_ary_entry(array, i), point_type);
393
+ if (entry_geom) {
394
+ entry_cs = GEOSGeom_getCoordSeq_r(context, entry_geom);
395
+ if (entry_cs) {
396
+ if (GEOSCoordSeq_getX_r(context, entry_cs, 0, &x)) {
397
+ coords[i*dims] = x;
398
+ if (GEOSCoordSeq_getY_r(context, entry_cs, 0, &x)) {
399
+ coords[i*dims+1] = x;
400
+ good = 1;
401
+ if (has_z) {
402
+ if (GEOSCoordSeq_getZ_r(context, entry_cs, 0, &x)) {
403
+ coords[i*dims+2] = x;
404
+ }
405
+ else {
406
+ good = 0;
407
+ }
408
+ }
409
+ }
410
+ }
411
+ }
412
+ }
413
+ if (!good) {
414
+ free(coords);
415
+ return NULL;
416
+ }
417
+ }
418
+ if (len > 0 && close) {
419
+ if (coords[0] == coords[(len-1)*dims] && coords[1] == coords[(len-1)*dims+1]) {
420
+ close = 0;
421
+ }
422
+ }
423
+ else {
424
+ close = 0;
425
+ }
426
+ coord_seq = GEOSCoordSeq_create_r(context, len + close, 3);
427
+ if (coord_seq) {
428
+ for (i=0; i<len; ++i) {
429
+ GEOSCoordSeq_setX_r(context, coord_seq, i, coords[i*dims]);
430
+ GEOSCoordSeq_setY_r(context, coord_seq, i, coords[i*dims+1]);
431
+ GEOSCoordSeq_setZ_r(context, coord_seq, i, has_z ? coords[i*dims+2] : 0);
432
+ }
433
+ if (close) {
434
+ GEOSCoordSeq_setX_r(context, coord_seq, len, coords[0]);
435
+ GEOSCoordSeq_setY_r(context, coord_seq, len, coords[1]);
436
+ GEOSCoordSeq_setZ_r(context, coord_seq, len, has_z ? coords[2] : 0);
437
+ }
438
+ }
439
+ free(coords);
440
+ return coord_seq;
441
+ }
442
+
443
+
444
+ static VALUE cmethod_create_line_string(VALUE module, VALUE factory, VALUE array)
445
+ {
446
+ VALUE result;
447
+ GEOSCoordSequence* coord_seq;
448
+ RGeo_FactoryData* factory_data;
449
+ GEOSGeometry* geom;
450
+
451
+ result = Qnil;
452
+ coord_seq = coord_seq_from_array(factory, array, 0);
453
+ if (coord_seq) {
454
+ factory_data = RGEO_FACTORY_DATA_PTR(factory);
455
+ geom = GEOSGeom_createLineString_r(factory_data->geos_context, coord_seq);
456
+ if (geom) {
457
+ result = rgeo_wrap_geos_geometry(factory, geom, factory_data->globals->geos_line_string);
458
+ }
459
+ }
460
+ return result;
461
+ }
462
+
463
+
464
+ static VALUE cmethod_create_linear_ring(VALUE module, VALUE factory, VALUE array)
465
+ {
466
+ VALUE result;
467
+ GEOSCoordSequence* coord_seq;
468
+ RGeo_FactoryData* factory_data;
469
+ GEOSGeometry* geom;
470
+
471
+ result = Qnil;
472
+ coord_seq = coord_seq_from_array(factory, array, 1);
473
+ if (coord_seq) {
474
+ factory_data = RGEO_FACTORY_DATA_PTR(factory);
475
+ geom = GEOSGeom_createLinearRing_r(factory_data->geos_context, coord_seq);
476
+ if (geom) {
477
+ result = rgeo_wrap_geos_geometry(factory, geom, factory_data->globals->geos_linear_ring);
478
+ }
479
+ }
480
+ return result;
481
+ }
482
+
483
+
484
+ static void populate_geom_into_coord_seq(GEOSContextHandle_t context, const GEOSGeometry* geom, GEOSCoordSequence* coord_seq, unsigned int i, char has_z)
485
+ {
486
+ const GEOSCoordSequence* cs;
487
+ double x;
488
+
489
+ cs = GEOSGeom_getCoordSeq_r(context, geom);
490
+ x = 0;
491
+ if (cs) {
492
+ GEOSCoordSeq_getX_r(context, cs, 0, &x);
493
+ }
494
+ GEOSCoordSeq_setX_r(context, coord_seq, i, x);
495
+ x = 0;
496
+ if (cs) {
497
+ GEOSCoordSeq_getY_r(context, cs, 0, &x);
498
+ }
499
+ GEOSCoordSeq_setY_r(context, coord_seq, i, x);
500
+ x = 0;
501
+ if (has_z && cs) {
502
+ GEOSCoordSeq_getZ_r(context, cs, 0, &x);
503
+ }
504
+ GEOSCoordSeq_setZ_r(context, coord_seq, i, x);
505
+ }
506
+
507
+
508
+ static VALUE cmethod_create_line(VALUE module, VALUE factory, VALUE start, VALUE end)
509
+ {
510
+ VALUE result;
511
+ RGeo_FactoryData* factory_data;
512
+ char has_z;
513
+ VALUE point_type;
514
+ GEOSContextHandle_t context;
515
+ const GEOSGeometry* start_geom;
516
+ const GEOSGeometry* end_geom;
517
+ GEOSCoordSequence* coord_seq;
518
+ GEOSGeometry* geom;
519
+
520
+ result = Qnil;
521
+ factory_data = RGEO_FACTORY_DATA_PTR(factory);
522
+ has_z = (char)(factory_data->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M);
523
+ point_type = factory_data->globals->feature_point;
524
+ context = factory_data->geos_context;
525
+
526
+ start_geom = rgeo_convert_to_geos_geometry(factory, start, point_type);
527
+ if (start_geom) {
528
+ end_geom = rgeo_convert_to_geos_geometry(factory, end, point_type);
529
+ if (end_geom) {
530
+ coord_seq = GEOSCoordSeq_create_r(context, 2, 3);
531
+ if (coord_seq) {
532
+ populate_geom_into_coord_seq(context, start_geom, coord_seq, 0, has_z);
533
+ populate_geom_into_coord_seq(context, end_geom, coord_seq, 1, has_z);
534
+ geom = GEOSGeom_createLineString_r(context, coord_seq);
535
+ if (geom) {
536
+ result = rgeo_wrap_geos_geometry(factory, geom, factory_data->globals->geos_line);
537
+ }
538
+ }
539
+ }
540
+ }
541
+
542
+ return result;
543
+ }
544
+
545
+
546
+ static VALUE impl_copy_from(VALUE klass, VALUE factory, VALUE original, char subtype)
547
+ {
548
+ VALUE result;
549
+ const GEOSGeometry* original_geom;
550
+ GEOSContextHandle_t context;
551
+ const GEOSCoordSequence* original_coord_seq;
552
+ GEOSCoordSequence* coord_seq;
553
+ GEOSGeometry* geom;
554
+
555
+ result = Qnil;
556
+ original_geom = RGEO_GEOMETRY_DATA_PTR(original)->geom;
557
+ if (original_geom) {
558
+ context = RGEO_FACTORY_DATA_PTR(factory)->geos_context;
559
+ if (subtype == 1 && GEOSGetNumCoordinates_r(context, original_geom) != 2) {
560
+ original_geom = NULL;
561
+ }
562
+ if (original_geom) {
563
+ original_coord_seq = GEOSGeom_getCoordSeq_r(context, original_geom);
564
+ if (original_coord_seq) {
565
+ coord_seq = GEOSCoordSeq_clone_r(context, original_coord_seq);
566
+ if (coord_seq) {
567
+ geom = subtype == 2 ? GEOSGeom_createLinearRing_r(context, coord_seq) : GEOSGeom_createLineString_r(context, coord_seq);
568
+ if (geom) {
569
+ result = rgeo_wrap_geos_geometry(factory, geom, klass);
570
+ }
571
+ }
572
+ }
573
+ }
574
+ }
575
+ return result;
576
+ }
577
+
578
+
579
+ static VALUE cmethod_line_string_copy_from(VALUE klass, VALUE factory, VALUE original)
580
+ {
581
+ return impl_copy_from(klass, factory, original, 0);
582
+ }
583
+
584
+
585
+ static VALUE cmethod_line_copy_from(VALUE klass, VALUE factory, VALUE original)
586
+ {
587
+ return impl_copy_from(klass, factory, original, 1);
588
+ }
589
+
590
+
591
+ static VALUE cmethod_linear_ring_copy_from(VALUE klass, VALUE factory, VALUE original)
592
+ {
593
+ return impl_copy_from(klass, factory, original, 2);
594
+ }
595
+
596
+
597
+ void rgeo_init_geos_line_string(RGeo_Globals* globals)
598
+ {
599
+ VALUE geos_line_string_methods;
600
+ VALUE geos_linear_ring_methods;
601
+ VALUE geos_line_methods;
602
+
603
+ // Class methods for CAPILineStringImpl
604
+ rb_define_module_function(globals->geos_line_string, "create", cmethod_create_line_string, 2);
605
+ rb_define_module_function(globals->geos_line_string, "_copy_from", cmethod_line_string_copy_from, 2);
606
+
607
+ // Class methods for CAPILinearRingImpl
608
+ rb_define_module_function(globals->geos_linear_ring, "create", cmethod_create_linear_ring, 2);
609
+ rb_define_module_function(globals->geos_linear_ring, "_copy_from", cmethod_linear_ring_copy_from, 2);
610
+
611
+ // Class methods for CAPILineImpl
612
+ rb_define_module_function(globals->geos_line, "create", cmethod_create_line, 3);
613
+ rb_define_module_function(globals->geos_line, "_copy_from", cmethod_line_copy_from, 2);
614
+
615
+ // CAPILineStringMethods module
616
+ geos_line_string_methods = rb_define_module_under(globals->geos_module, "CAPILineStringMethods");
617
+ rb_define_method(geos_line_string_methods, "rep_equals?", method_line_string_eql, 1);
618
+ rb_define_method(geos_line_string_methods, "eql?", method_line_string_eql, 1);
619
+ rb_define_method(geos_line_string_methods, "hash", method_line_string_hash, 0);
620
+ rb_define_method(geos_line_string_methods, "geometry_type", method_line_string_geometry_type, 0);
621
+ rb_define_method(geos_line_string_methods, "length", method_line_string_length, 0);
622
+ rb_define_method(geos_line_string_methods, "num_points", method_line_string_num_points, 0);
623
+ rb_define_method(geos_line_string_methods, "point_n", method_line_string_point_n, 1);
624
+ rb_define_method(geos_line_string_methods, "points", method_line_string_points, 0);
625
+ rb_define_method(geos_line_string_methods, "start_point", method_line_string_start_point, 0);
626
+ rb_define_method(geos_line_string_methods, "end_point", method_line_string_end_point, 0);
627
+ rb_define_method(geos_line_string_methods, "is_closed?", method_line_string_is_closed, 0);
628
+ rb_define_method(geos_line_string_methods, "is_ring?", method_line_string_is_ring, 0);
629
+ rb_define_method(geos_line_string_methods, "coordinates", method_line_string_coordinates, 0);
630
+
631
+ // CAPILinearRingMethods module
632
+ geos_linear_ring_methods = rb_define_module_under(globals->geos_module, "CAPILinearRingMethods");
633
+ rb_define_method(geos_linear_ring_methods, "geometry_type", method_linear_ring_geometry_type, 0);
634
+ rb_define_method(geos_linear_ring_methods, "hash", method_linear_ring_hash, 0);
635
+
636
+ // CAPILineMethods module
637
+ geos_line_methods = rb_define_module_under(globals->geos_module, "CAPILineMethods");
638
+ rb_define_method(geos_line_methods, "geometry_type", method_line_geometry_type, 0);
639
+ rb_define_method(geos_line_methods, "hash", method_line_hash, 0);
640
+ }
641
+
642
+
643
+ VALUE rgeo_is_geos_line_string_closed(GEOSContextHandle_t context, const GEOSGeometry* geom)
644
+ {
645
+ VALUE result;
646
+ unsigned int n;
647
+ double x1, x2, y1, y2, z1, z2;
648
+ const GEOSCoordSequence* coord_seq;
649
+
650
+ result = Qnil;
651
+ n = GEOSGetNumCoordinates_r(context, geom);
652
+ if (n > 0) {
653
+ coord_seq = GEOSGeom_getCoordSeq_r(context, geom);
654
+ if (GEOSCoordSeq_getX_r(context, coord_seq, 0, &x1)) {
655
+ if (GEOSCoordSeq_getX_r(context, coord_seq, n-1, &x2)) {
656
+ if (x1 == x2) {
657
+ if (GEOSCoordSeq_getY_r(context, coord_seq, 0, &y1)) {
658
+ if (GEOSCoordSeq_getY_r(context, coord_seq, n-1, &y2)) {
659
+ result = y1 == y2 ? Qtrue : Qfalse;
660
+ }
661
+ }
662
+ }
663
+ else {
664
+ result = Qfalse;
665
+ }
666
+ }
667
+ }
668
+ }
669
+ return result;
670
+ }
671
+
672
+
673
+ RGEO_END_C
674
+
675
+ #endif