gotime-postgis_adapter 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,921 @@
1
+ # -*- coding: utf-8 -*-
2
+ # #
3
+ #
4
+ # COMMON GEOMETRICAL FUNCTIONS
5
+ #
6
+ # The methods here can be used by all geoms.
7
+ #
8
+
9
+ module PostgisAdapter
10
+ module Functions
11
+
12
+ #
13
+ # Test if a geometry is well formed.
14
+ #
15
+ def valid_geom?
16
+ postgis_calculate(:isvalid, self)
17
+ end
18
+
19
+ #
20
+ # True if the given geometries represent the same geometry.
21
+ # Directionality is ignored.
22
+ #
23
+ # Returns TRUE if the given Geometries are "spatially equal".
24
+ # Use this for a 'better' answer than '='. Note by spatially equal we
25
+ # mean ST_Within(A,B) = true and ST_Within(B,A) = true and also mean ordering
26
+ # of points can be different but represent the same geometry structure.
27
+ # To verify the order of points is consistent, use ST_OrderingEquals
28
+ # (it must be noted ST_OrderingEquals is a little more stringent than
29
+ # simply verifying order of points are the same).
30
+ #
31
+ # This function will return false if either geometry is invalid even
32
+ # if they are binary equal.
33
+ #
34
+ # Returns Boolean ST_Equals(geometry A, geometry B);
35
+ #
36
+ def spatially_equal?(other)
37
+ postgis_calculate(:equals, [self, other])
38
+ end
39
+
40
+ #
41
+ # Returns the minimum bounding box for the supplied geometry, as a geometry.
42
+ # The polygon is defined by the corner points of the bounding box
43
+ # ((MINX, MINY), (MINX, MAXY), (MAXX, MAXY), (MAXX, MINY), (MINX, MINY)).
44
+ # PostGIS will add a ZMIN/ZMAX coordinate as well/
45
+ #
46
+ # Degenerate cases (vertical lines, points) will return a geometry of
47
+ # lower dimension than POLYGON, ie. POINT or LINESTRING.
48
+ #
49
+ # In PostGIS, the bounding box of a geometry is represented internally using
50
+ # float4s instead of float8s that are used to store geometries. The bounding
51
+ # box coordinates are floored, guarenteeing that the geometry is contained
52
+ # entirely within its bounds. This has the advantage that a geometry's
53
+ # bounding box is half the size as the minimum bounding rectangle,
54
+ # which means significantly faster indexes and general performance.
55
+ # But it also means that the bounding box is NOT the same as the minimum
56
+ # bounding rectangle that bounds the geome.
57
+ #
58
+ # Returns GeometryCollection ST_Envelope(geometry g1);
59
+ #
60
+ def envelope
61
+ postgis_calculate(:envelope, self)
62
+ end
63
+
64
+ #
65
+ # Computes the geometric center of a geometry, or equivalently,
66
+ # the center of mass of the geometry as a POINT. For [MULTI]POINTs, this is
67
+ # computed as the arithmetric mean of the input coordinates.
68
+ # For [MULTI]LINESTRINGs, this is computed as the weighted length of each
69
+ # line segment. For [MULTI]POLYGONs, "weight" is thought in terms of area.
70
+ # If an empty geometry is supplied, an empty GEOMETRYCOLLECTION is returned.
71
+ # If NULL is supplied, NULL is returned.
72
+ #
73
+ # The centroid is equal to the centroid of the set of component Geometries of
74
+ # highest dimension (since the lower-dimension geometries contribute zero
75
+ # "weight" to the centroid).
76
+ #
77
+ # Computation will be more accurate if performed by the GEOS module (enabled at compile time).
78
+ #
79
+ # http://postgis.refractions.net/documentation/manual-svn/ST_Centroid.html
80
+ #
81
+ # Returns Geometry ST_Centroid(geometry g1);
82
+ #
83
+ def centroid
84
+ postgis_calculate(:centroid, self)
85
+ end
86
+
87
+ #
88
+ # Returns the closure of the combinatorial boundary of this Geometry.
89
+ # The combinatorial boundary is defined as described in section 3.12.3.2 of the
90
+ # OGC SPEC. Because the result of this function is a closure, and hence topologically
91
+ # closed, the resulting boundary can be represented using representational
92
+ # geometry primitives as discussed in the OGC SPEC, section 3.12.2.
93
+ #
94
+ # Do not call with a GEOMETRYCOLLECTION as an argument.
95
+ #
96
+ # Performed by the GEOS module.
97
+ #
98
+ # Returns Geometry ST_Boundary(geometry geomA);
99
+ #
100
+ def boundary
101
+ postgis_calculate(:boundary, self)
102
+ end
103
+
104
+ #
105
+ # 2D minimum cartesian distance between two geometries in projected units.
106
+ #
107
+ # Returns Float ST_Distance(geometry g1, geometry g2);
108
+ #
109
+ def distance_to(other)
110
+ postgis_calculate(:distance, [self, other]).to_f
111
+ end
112
+
113
+ #
114
+ # True if geometry A is completely inside geometry B.
115
+ #
116
+ # For this function to make sense, the source geometries must both be of the same
117
+ # coordinate projection, having the same SRID. It is a given that
118
+ # if ST_Within(A,B) is true and ST_Within(B,A) is true, then the
119
+ # two geometries are considered spatially equal.
120
+ #
121
+ # This function call will automatically include a bounding box comparison that will
122
+ # make use of any indexes that are available on the geometries. To avoid index use,
123
+ # use the function _ST_Within.
124
+ #
125
+ # Do not call with a GEOMETRYCOLLECTION as an argument
126
+ # Do not use this function with invalid geometries. You will get unexpected results.
127
+ #
128
+ # Performed by the GEOS module.
129
+ #
130
+ # Returns Boolean ST_Within(geometry A, geometry B);
131
+ #
132
+ def within? other
133
+ postgis_calculate(:within, [self, other])
134
+ end
135
+
136
+ #
137
+ # True if the geometries are within the specified distance of one another.
138
+ # The distance is specified in units defined by the spatial reference system
139
+ # of the geometries. For this function to make sense, the source geometries
140
+ # must both be of the same coorindate projection, having the same SRID.
141
+ #
142
+ # Returns boolean ST_DWithin(geometry g1, geometry g2, double precision distance);
143
+ #
144
+ def d_within?(other, margin=0.1)
145
+ postgis_calculate(:dwithin, [self, other], margin)
146
+ end
147
+ alias_method "in_bounds?", "d_within?"
148
+
149
+ #
150
+ # True if geometry B is completely inside geometry A.
151
+ #
152
+ # For this function to make sense, the source geometries must both be of the same
153
+ # coordinate projection, having the same SRID. 'contains?' is the inverse of 'within?'.
154
+ #
155
+ # So a.contains?(b) is like b.within?(a) except in the case of invalid
156
+ # geometries where the result is always false regardless or not defined.
157
+ #
158
+ # Do not call with a GEOMETRYCOLLECTION as an argument
159
+ # Do not use this function with invalid geometries. You will get unexpected results.
160
+ #
161
+ # Performed by the GEOS module
162
+ #
163
+ # Returns Boolean ST_Contains(geometry geomA, geometry geomB);
164
+ #
165
+ def contains? other
166
+ postgis_calculate(:contains, [self, other])
167
+ end
168
+
169
+ #
170
+ # True if no point in Geometry A is outside Geometry B
171
+ #
172
+ # This function call will automatically include a bounding box comparison that
173
+ # will make use of any indexes that are available on the geometries. To avoid
174
+ # index use, use the function _ST_CoveredBy.
175
+ #
176
+ # Do not call with a GEOMETRYCOLLECTION as an argument.
177
+ # Do not use this function with invalid geometries. You will get unexpected results.
178
+ #
179
+ # Performed by the GEOS module.
180
+ #
181
+ # Aliased as 'inside?'
182
+ #
183
+ # Returns Boolean ST_CoveredBy(geometry geomA, geometry geomB);
184
+ #
185
+ def covered_by? other
186
+ postgis_calculate(:coveredby, [self, other])
187
+ end
188
+ alias_method "inside?", "covered_by?"
189
+
190
+ #
191
+ # Eye-candy. See 'covered_by?'.
192
+ #
193
+ # Returns !(Boolean ST_CoveredBy(geometry geomA, geometry geomB);)
194
+ #
195
+ def outside? other
196
+ !covered_by? other
197
+ end
198
+
199
+ #
200
+ # True if the Geometries do not "spatially intersect" - if they
201
+ # do not share any space together.
202
+ #
203
+ # Overlaps, Touches, Within all imply geometries are not spatially disjoint.
204
+ # If any of the aforementioned returns true, then the geometries are not
205
+ # spatially disjoint. Disjoint implies false for spatial intersection.
206
+ #
207
+ # Do not call with a GEOMETRYCOLLECTION as an argument.
208
+ #
209
+ # Returns boolean ST_Disjoint( geometry A , geometry B );
210
+ #
211
+ def disjoint? other
212
+ postgis_calculate(:disjoint, [self, other])
213
+ end
214
+
215
+ #
216
+ # How many dimensions the geom is made of (2, 3 or 4)
217
+ #
218
+ # Returns Integer ST_Dimension(geom g1)
219
+ #
220
+ def dimension
221
+ postgis_calculate(:dimension, self).to_i
222
+ end
223
+
224
+ #
225
+ # Returns a "simplified" version of the given geometry using the Douglas-Peuker
226
+ # algorithm. Will actually do something only with (multi)lines and (multi)polygons
227
+ # but you can safely call it with any kind of geometry. Since simplification
228
+ # occurs on a object-by-object basis you can also feed a GeometryCollection to this
229
+ # function.
230
+ #
231
+ # Note that returned geometry might loose its simplicity (see 'is_simple?').
232
+ # Topology may not be preserved and may result in invalid geometries.
233
+ # Use 'simplify_preserve_topology' to preserve topology.
234
+ #
235
+ # Performed by the GEOS Module.
236
+ #
237
+ # Returns Geometry ST_Simplify(geometry geomA, float tolerance);
238
+ #
239
+ def simplify(tolerance=0.1)
240
+ postgis_calculate(:simplify, self, tolerance)
241
+ end
242
+
243
+ def simplify!(tolerance=0.1)
244
+ #FIXME: not good..
245
+ self.update_attribute(geo_columns.first, simplify)
246
+ end
247
+
248
+ #
249
+ #
250
+ def buffer(width=0.1)
251
+ postgis_calculate(:buffer, self, width)
252
+ end
253
+
254
+ #
255
+ # Returns a "simplified" version of the given geometry using the Douglas-Peuker
256
+ # algorithm. Will avoid creating derived geometries (polygons in particular) that
257
+ # are invalid. Will actually do something only with (multi)lines and (multi)polygons
258
+ # but you can safely call it with any kind of geometry. Since simplification occurs
259
+ # on a object-by-object basis you can also feed a GeometryCollection to this function.
260
+ #
261
+ # Performed by the GEOS module. Requires GEOS 3.0.0+
262
+ #
263
+ # Returns Geometry ST_SimplifyPreserveTopology(geometry geomA, float tolerance);
264
+ #
265
+ def simplify_preserve_topology(tolerance=0.1)
266
+ postgis_calculate(:simplifypreservetopology, self, tolerance)
267
+ end
268
+
269
+ #
270
+ # True if Geometries "spatially intersect", share any portion of space.
271
+ # False if they don't (they are Disjoint).
272
+ #
273
+ # 'overlaps?', 'touches?', 'within?' all imply spatial intersection.
274
+ # If any of the aforementioned returns true, then the geometries also
275
+ # spatially intersect. 'disjoint?' implies false for spatial intersection.
276
+ #
277
+ # Returns Boolean ST_Intersects(geometry geomA, geometry geomB);
278
+ #
279
+ def intersects? other
280
+ postgis_calculate(:intersects, [self, other])
281
+ end
282
+
283
+ #
284
+ # True if a Geometry`s Envelope "spatially intersect", share any portion of space.
285
+ #
286
+ # It`s 'intersects?', for envelopes.
287
+ #
288
+ # Returns Boolean SE_EnvelopesIntersect(geometry geomA, geometry geomB);
289
+ #
290
+ def envelopes_intersect? other
291
+ postgis_calculate(:se_envelopesintersect, [self, other])
292
+ end
293
+
294
+ #
295
+ # Geometry that represents the point set intersection of the Geometries.
296
+ # In other words - that portion of geometry A and geometry B that is shared between
297
+ # the two geometries. If the geometries do not share any space (are disjoint),
298
+ # then an empty geometry collection is returned.
299
+ #
300
+ # 'intersection' in conjunction with intersects? is very useful for clipping
301
+ # geometries such as in bounding box, buffer, region queries where you only want
302
+ # to return that portion of a geometry that sits in a country or region of interest.
303
+ #
304
+ # Do not call with a GEOMETRYCOLLECTION as an argument.
305
+ # Performed by the GEOS module.
306
+ #
307
+ # Returns Geometry ST_Intersection(geometry geomA, geometry geomB);
308
+ #
309
+ def intersection other
310
+ postgis_calculate(:intersection, [self, other])
311
+ end
312
+
313
+ #
314
+ # True if the Geometries share space, are of the same dimension, but are
315
+ # not completely contained by each other. They intersect, but one does not
316
+ # completely contain another.
317
+ #
318
+ # Do not call with a GeometryCollection as an argument
319
+ # This function call will automatically include a bounding box comparison that
320
+ # will make use of any indexes that are available on the geometries. To avoid
321
+ # index use, use the function _ST_Overlaps.
322
+ #
323
+ # Performed by the GEOS module.
324
+ #
325
+ # Returns Boolean ST_Overlaps(geometry A, geometry B);
326
+ #
327
+ def overlaps? other
328
+ postgis_calculate(:overlaps, [self, other])
329
+ end
330
+
331
+ # True if the geometries have at least one point in common,
332
+ # but their interiors do not intersect.
333
+ #
334
+ # If the only points in common between g1 and g2 lie in the union of the
335
+ # boundaries of g1 and g2. The 'touches?' relation applies to all Area/Area,
336
+ # Line/Line, Line/Area, Point/Area and Point/Line pairs of relationships,
337
+ # but not to the Point/Point pair.
338
+ #
339
+ # Returns Boolean ST_Touches(geometry g1, geometry g2);
340
+ #
341
+ def touches? other
342
+ postgis_calculate(:touches, [self, other])
343
+ end
344
+
345
+ def st_collect(other=nil)
346
+ postgis_calculate(:collect, [self, other])
347
+ end
348
+ #
349
+ # The convex hull of a geometry represents the minimum closed geometry that
350
+ # encloses all geometries within the set.
351
+ #
352
+ # It is usually used with MULTI and Geometry Collections. Although it is not
353
+ # an aggregate - you can use it in conjunction with ST_Collect to get the convex
354
+ # hull of a set of points. ST_ConvexHull(ST_Collect(somepointfield)).
355
+ # It is often used to determine an affected area based on a set of point observations.
356
+ #
357
+ # Performed by the GEOS module.
358
+ #
359
+ # Returns Geometry ST_ConvexHull(geometry geomA);
360
+ #
361
+ def convex_hull
362
+ postgis_calculate(:convexhull, self)
363
+ end
364
+
365
+ #
366
+ # Creates an areal geometry formed by the constituent linework of given geometry.
367
+ # The return type can be a Polygon or MultiPolygon, depending on input.
368
+ # If the input lineworks do not form polygons NULL is returned. The inputs can
369
+ # be LINESTRINGS, MULTILINESTRINGS, POLYGONS, MULTIPOLYGONS, and GeometryCollections.
370
+ #
371
+ # Returns Boolean ST_BuildArea(geometry A);
372
+ #
373
+ def build_area
374
+ postgis_calculate(:buildarea, self)
375
+ end
376
+
377
+ #
378
+ # Returns true if this Geometry has no anomalous geometric points, such as
379
+ # self intersection or self tangency.
380
+ #
381
+ # Returns boolean ST_IsSimple(geometry geomA);
382
+ #
383
+ def is_simple?
384
+ postgis_calculate(:issimple, self)
385
+ end
386
+ alias_method "simple?", "is_simple?"
387
+
388
+ #
389
+ # Aggregate. Creates a GeometryCollection containing possible polygons formed
390
+ # from the constituent linework of a set of geometries.
391
+ #
392
+ # Geometry Collections are often difficult to deal with with third party tools,
393
+ # so use ST_Polygonize in conjunction with ST_Dump to dump the polygons out into
394
+ # individual polygons.
395
+ #
396
+ # Returns Geometry ST_Polygonize(geometry set geomfield);
397
+ #
398
+ def polygonize
399
+ postgis_calculate(:polygonize, self)
400
+ end
401
+
402
+ #
403
+ # Returns true if this Geometry is spatially related to anotherGeometry,
404
+ # by testing for intersections between the Interior, Boundary and Exterior
405
+ # of the two geometries as specified by the values in the
406
+ # intersectionPatternMatrix. If no intersectionPatternMatrix is passed in,
407
+ # then returns the maximum intersectionPatternMatrix that relates the 2 geometries.
408
+ #
409
+ #
410
+ # Version 1: Takes geomA, geomB, intersectionMatrix and Returns 1 (TRUE) if
411
+ # this Geometry is spatially related to anotherGeometry, by testing for
412
+ # intersections between the Interior, Boundary and Exterior of the two
413
+ # geometries as specified by the values in the intersectionPatternMatrix.
414
+ #
415
+ # This is especially useful for testing compound checks of intersection,
416
+ # crosses, etc in one step.
417
+ #
418
+ # Do not call with a GeometryCollection as an argument
419
+ #
420
+ # This is the "allowable" version that returns a boolean, not an integer.
421
+ # This is defined in OGC spec.
422
+ # This DOES NOT automagically include an index call. The reason for that
423
+ # is some relationships are anti e.g. Disjoint. If you are using a relationship
424
+ # pattern that requires intersection, then include the && index call.
425
+ #
426
+ # Version 2: Takes geomA and geomB and returns the DE-9IM
427
+ # (dimensionally extended nine-intersection matrix)
428
+ #
429
+ # Do not call with a GeometryCollection as an argument
430
+ # Not in OGC spec, but implied. see s2.1.13.2
431
+ #
432
+ # Both Performed by the GEOS module
433
+ #
434
+ # Returns:
435
+ #
436
+ # String ST_Relate(geometry geomA, geometry geomB);
437
+ # Boolean ST_Relate(geometry geomA, geometry geomB, text intersectionPatternMatrix);
438
+ #
439
+ def relate?(other, m = nil)
440
+ # Relate is case sentitive.......
441
+ m = "'#{m}'" if m
442
+ postgis_calculate("Relate", [self, other], m)
443
+ end
444
+
445
+ #
446
+ # Transform the geometry into a different spatial reference system.
447
+ # The destination SRID must exist in the SPATIAL_REF_SYS table.
448
+ #
449
+ # This method implements the OpenGIS Simple Features Implementation Specification for SQL.
450
+ # This method supports Circular Strings and Curves (PostGIS 1.3.4+)
451
+ #
452
+ # Requires PostGIS be compiled with Proj support.
453
+ #
454
+ # Return Geometry ST_Transform(geometry g1, integer srid);
455
+ #
456
+ def transform!(new_srid)
457
+ self[postgis_geoms.keys[0]] = postgis_calculate("Transform", self.new_record? ? self.geom : self, new_srid)
458
+ end
459
+
460
+ def transform(new_srid)
461
+ dup.transform!(new_srid)
462
+ end
463
+
464
+ #
465
+ # Returns a modified geometry having no segment longer than the given distance.
466
+ # Distance computation is performed in 2d only.
467
+ #
468
+ # This will only increase segments. It will not lengthen segments shorter than max length
469
+ #
470
+ # Return Geometry ST_Segmentize(geometry geomA, float max_length);
471
+ #
472
+ def segmentize(max_length=1.0)
473
+ postgis_calculate("segmentize", self, max_length)
474
+ end
475
+
476
+ #
477
+ # Returns the instance`s geom srid
478
+ #
479
+ def srid
480
+ self[postgis_geoms.keys.first].srid
481
+ end
482
+
483
+ #
484
+ # Return UTM Zone for a geom
485
+ #
486
+ # Return Integer
487
+ def utm_zone
488
+ if srid == 4326
489
+ geom = centroid
490
+ else
491
+ geomdup = transform(4326)
492
+ mezzo = geomdup.length / 2
493
+ geom = case geomdup
494
+ when Point then geomdup
495
+ when LineString then geomdup[mezzo]
496
+ else
497
+ geomgeog[mezzo][geomgeo[mezzo]/2]
498
+ end
499
+
500
+ end
501
+
502
+ pref = geom.y > 0 ? 32700 : 32600
503
+ zone = ((geom.x + 180) / 6 + 1).to_i
504
+ zone + pref
505
+ end
506
+
507
+ #
508
+ # Returns the Geometry in its UTM Zone
509
+ #
510
+ # Return Geometry
511
+ def to_utm!(utm=nil)
512
+ utm ||= utm_zone
513
+ self[postgis_geoms.keys.first] = transform(utm)
514
+ end
515
+
516
+ def to_utm
517
+ dup.to_utm!
518
+ end
519
+
520
+ #
521
+ # Returns Geometry as GeoJSON
522
+ #
523
+ # http://geojson.org/
524
+ #
525
+ def as_geo_json(precision=15, bbox = 0)
526
+ postgis_calculate(:AsGeoJSON, self, [precision, bbox])
527
+ end
528
+
529
+ #
530
+ # ST_PointOnSurface — Returns a POINT guaranteed to lie on the surface.
531
+ #
532
+ # geometry ST_PointOnSurface(geometry g1);eometry A, geometry B);
533
+ #
534
+ def point_on_surface
535
+ postgis_calculate(:pointonsurface, self)
536
+ end
537
+
538
+ #
539
+ #
540
+ # LINESTRING
541
+ #
542
+ #
543
+ #
544
+ module LineStringFunctions
545
+
546
+ #
547
+ # Returns the 2D length of the geometry if it is a linestring, multilinestring,
548
+ # ST_Curve, ST_MultiCurve. 0 is returned for areal geometries. For areal geometries
549
+ # use 'perimeter'. Measurements are in the units of the spatial reference system
550
+ # of the geometry.
551
+ #
552
+ # Returns Float
553
+ #
554
+ def length
555
+ postgis_calculate(:length, self).to_f
556
+ end
557
+
558
+ #
559
+ # Returns the 3-dimensional or 2-dimensional length of the geometry if it is
560
+ # a linestring or multi-linestring. For 2-d lines it will just return the 2-d
561
+ # length (same as 'length')
562
+ #
563
+ # Returns Float
564
+ #
565
+ def length_3d
566
+ postgis_calculate(:length3d, self).to_f
567
+ end
568
+
569
+ #
570
+ # Calculates the length of a geometry on an ellipsoid. This is useful if the
571
+ # coordinates of the geometry are in longitude/latitude and a length is
572
+ # desired without reprojection. The ellipsoid is a separate database type and
573
+ # can be constructed as follows:
574
+ #
575
+ # SPHEROID[<NAME>,<SEMI-MAJOR AXIS>,<INVERSE FLATTENING>]
576
+ #
577
+ # Example:
578
+ # SPHEROID["GRS_1980",6378137,298.257222101]
579
+ #
580
+ # Defaults to:
581
+ #
582
+ # SPHEROID["IERS_2003",6378136.6,298.25642]
583
+ #
584
+ # Returns Float length_spheroid(geometry linestring, spheroid);
585
+ #
586
+ def length_spheroid(spheroid = EARTH_SPHEROID)
587
+ postgis_calculate(:length_spheroid, self, spheroid).to_f
588
+ end
589
+
590
+ #
591
+ # Return the number of points of the geometry.
592
+ # PostGis ST_NumPoints does not work as nov/08
593
+ #
594
+ # Returns Integer ST_NPoints(geometry g1);
595
+ #
596
+ def num_points
597
+ postgis_calculate(:npoints, self).to_i
598
+ end
599
+
600
+ #
601
+ # Returns geometry start point.
602
+ #
603
+ def start_point
604
+ postgis_calculate(:startpoint, self)
605
+ end
606
+
607
+ #
608
+ # Returns geometry end point.
609
+ #
610
+ def end_point
611
+ postgis_calculate(:endpoint, self)
612
+ end
613
+
614
+ #
615
+ # Takes two geometry objects and returns TRUE if their intersection
616
+ # "spatially cross", that is, the geometries have some, but not all interior
617
+ # points in common. The intersection of the interiors of the geometries must
618
+ # not be the empty set and must have a dimensionality less than the the
619
+ # maximum dimension of the two input geometries. Additionally, the
620
+ # intersection of the two geometries must not equal either of the source
621
+ # geometries. Otherwise, it returns FALSE.
622
+ #
623
+ #
624
+ # Returns Boolean ST_Crosses(geometry g1, geometry g2);
625
+ #
626
+ def crosses? other
627
+ postgis_calculate(:crosses, [self, other])
628
+ end
629
+
630
+ #
631
+ # Warning: PostGIS 1.4+
632
+ #
633
+ # Return crossing direction
634
+ def line_crossing_direction(other)
635
+ postgis_calculate(:lineCrossingDirection, [self, other])
636
+ end
637
+
638
+ #
639
+ # Returns a float between 0 and 1 representing the location of the closest point
640
+ # on LineString to the given Point, as a fraction of total 2d line length.
641
+ #
642
+ # You can use the returned location to extract a Point (ST_Line_Interpolate_Point)
643
+ # or a substring (ST_Line_Substring).
644
+ #
645
+ # This is useful for approximating numbers of addresses.
646
+ #
647
+ # Returns float (0 to 1) ST_Line_Locate_Point(geometry a_linestring, geometry a_point);
648
+ #
649
+ def locate_point point
650
+ postgis_calculate(:line_locate_point, [self, point]).to_f
651
+ end
652
+
653
+ #
654
+ # Return a derived geometry collection value with elements that match the
655
+ # specified measure. Polygonal elements are not supported.
656
+ #
657
+ # Semantic is specified by: ISO/IEC CD 13249-3:200x(E) - Text for
658
+ # Continuation CD Editing Meeting
659
+ #
660
+ # Returns geometry ST_Locate_Along_Measure(geometry ageom_with_measure, float a_measure);
661
+ #
662
+ def locate_along_measure(measure)
663
+ postgis_calculate(:locate_along_measure, self, measure)
664
+ end
665
+
666
+ #
667
+ # Return a derived geometry collection value with elements that match the
668
+ # specified range of measures inclusively. Polygonal elements are not supported.
669
+ #
670
+ # Semantic is specified by: ISO/IEC CD 13249-3:200x(E) - Text for Continuation CD Editing Meeting
671
+ #
672
+ # Returns geometry ST_Locate_Between_Measures(geometry geomA, float measure_start, float measure_end);
673
+ #
674
+ def locate_between_measures(a, b)
675
+ postgis_calculate(:locate_between_measures, self, [a,b])
676
+ end
677
+
678
+ #
679
+ # Returns a point interpolated along a line. First argument must be a LINESTRING.
680
+ # Second argument is a float8 between 0 and 1 representing fraction of total
681
+ # linestring length the point has to be located.
682
+ #
683
+ # See ST_Line_Locate_Point for computing the line location nearest to a Point.
684
+ #
685
+ # Returns geometry ST_Line_Interpolate_Point(geometry a_linestring, float a_fraction);
686
+ #
687
+ def interpolate_point(fraction)
688
+ postgis_calculate(:line_interpolate_point, self, fraction)
689
+ end
690
+
691
+ #
692
+ # Return a linestring being a substring of the input one starting and ending
693
+ # at the given fractions of total 2d length. Second and third arguments are
694
+ # float8 values between 0 and 1. This only works with LINESTRINGs. To use
695
+ # with contiguous MULTILINESTRINGs use in conjunction with ST_LineMerge.
696
+ #
697
+ # If 'start' and 'end' have the same value this is equivalent to 'interpolate_point'.
698
+ #
699
+ # See 'locate_point' for computing the line location nearest to a Point.
700
+ #
701
+ # Returns geometry ST_Line_Substring(geometry a_linestring, float startfraction, float endfraction);
702
+ #
703
+ def line_substring(s,e)
704
+ postgis_calculate(:line_substring, self, [s, e])
705
+ end
706
+
707
+ ###
708
+ #Not implemented in postgis yet
709
+ # ST_max_distance Returns the largest distance between two line strings.
710
+ #def max_distance other
711
+ # #float ST_Max_Distance(geometry g1, geometry g2);
712
+ # postgis_calculate(:max_distance, [self, other])
713
+ #end
714
+
715
+ #
716
+ # Returns a (set of) LineString(s) formed by sewing together a MULTILINESTRING.
717
+ #
718
+ # Only use with MULTILINESTRING/LINESTRINGs. If you feed a polygon or geometry collection into this function, it will return an empty GEOMETRYCOLLECTION
719
+ #
720
+ # Returns geometry ST_LineMerge(geometry amultilinestring);
721
+ #
722
+ def line_merge
723
+ postgis_calculate(:LineMerge, self, { :stcollect => self})
724
+ end
725
+
726
+ end
727
+ #
728
+ #
729
+ #
730
+ #
731
+ # POINT
732
+ #
733
+ #
734
+ #
735
+ #
736
+ module PointFunctions
737
+
738
+ #
739
+ # Returns a float between 0 and 1 representing the location of the closest point
740
+ # on LineString to the given Point, as a fraction of total 2d line length.
741
+ #
742
+ # You can use the returned location to extract a Point (ST_Line_Interpolate_Point)
743
+ # or a substring (ST_Line_Substring).
744
+ #
745
+ # This is useful for approximating numbers of addresses.
746
+ #
747
+ # Returns float (0 to 1) ST_Line_Locate_Point(geometry a_linestring, geometry a_point);
748
+ #
749
+ def where_on_line line
750
+ postgis_calculate(:line_locate_point, [line, self]).to_f
751
+ end
752
+
753
+ #
754
+ # Linear distance in meters between two lon/lat points.
755
+ # Uses a spherical earth and radius of 6370986 meters.
756
+ # Faster than 'distance_spheroid', but less accurate.
757
+ #
758
+ # Only implemented for points.
759
+ #
760
+ # Returns Float ST_Distance_Sphere(geometry pointlonlatA, geometry pointlonlatB);
761
+ #
762
+ def distance_sphere_to(other)
763
+ postgis_calculate(:distance_sphere, [self, other]).to_f
764
+ end
765
+
766
+ #
767
+ # Calculates the distance on an ellipsoid. This is useful if the
768
+ # coordinates of the geometry are in longitude/latitude and a length is
769
+ # desired without reprojection. The ellipsoid is a separate database type and
770
+ # can be constructed as follows:
771
+ #
772
+ # This is slower then 'distance_sphere_to', but more precise.
773
+ #
774
+ # SPHEROID[<NAME>,<SEMI-MAJOR AXIS>,<INVERSE FLATTENING>]
775
+ #
776
+ # Example:
777
+ # SPHEROID["GRS_1980",6378137,298.257222101]
778
+ #
779
+ # Defaults to:
780
+ #
781
+ # SPHEROID["IERS_2003",6378136.6,298.25642]
782
+ #
783
+ # Returns ST_Distance_Spheroid(geometry geomA, geometry geomB, spheroid);
784
+ #
785
+ def distance_spheroid_to(other, spheroid = EARTH_SPHEROID)
786
+ postgis_calculate(:distance_spheroid, [self, other], spheroid).to_f
787
+ end
788
+
789
+ #
790
+ # The azimuth of the segment defined by the given Point geometries,
791
+ # or NULL if the two points are coincident. Return value is in radians.
792
+ #
793
+ # The Azimuth is mathematical concept defined as the angle, in this case
794
+ # measured in radian, between a reference plane and a point.
795
+ #
796
+ # Returns Float ST_Azimuth(geometry pointA, geometry pointB);
797
+ #
798
+ def azimuth other
799
+ #TODO: return if not point/point
800
+ postgis_calculate(:azimuth, [self, other]).to_f
801
+ rescue
802
+ ActiveRecord::StatementInvalid
803
+ end
804
+
805
+ #
806
+ # True if the geometry is a point and is inside the circle.
807
+ #
808
+ # Returns Boolean ST_point_inside_circle(geometry, float, float, float)
809
+ #
810
+ def inside_circle?(x,y,r)
811
+ postgis_calculate(:point_inside_circle, self, [x,y,r])
812
+ end
813
+
814
+ end
815
+
816
+ #
817
+ #
818
+ #
819
+ #
820
+ # Polygon
821
+ #
822
+ #
823
+ #
824
+ #
825
+ module PolygonFunctions
826
+
827
+ #
828
+ # The area of the geometry if it is a polygon or multi-polygon.
829
+ # Return the area measurement of an ST_Surface or ST_MultiSurface value.
830
+ # Area is in the units of the spatial reference system.
831
+ #
832
+ # Accepts optional parameter, the srid to transform to.
833
+ #
834
+ # Returns Float ST_Area(geometry g1);
835
+ #
836
+ def area transform=nil
837
+ postgis_calculate(:area, self, { :transform => transform }).to_f
838
+ end
839
+
840
+ #
841
+ # Returns the 2D perimeter of the geometry if it is a ST_Surface, ST_MultiSurface
842
+ # (Polygon, Multipolygon). 0 is returned for non-areal geometries. For linestrings
843
+ # use 'length'. Measurements are in the units of the spatial reference system of
844
+ # the geometry.
845
+ #
846
+ # Accepts optional parameter, the sridto transform to.
847
+ #
848
+ # Returns Float ST_Perimeter(geometry g1);
849
+ #
850
+ def perimeter transform=nil
851
+ postgis_calculate(:perimeter, self, { :transform => transform }).to_f
852
+ end
853
+
854
+ #
855
+ # Returns the 3-dimensional perimeter of the geometry, if it is a polygon or multi-polygon.
856
+ # If the geometry is 2-dimensional, then the 2-dimensional perimeter is returned.
857
+ #
858
+ # Returns Float ST_Perimeter3D(geometry geomA);
859
+ #
860
+ def perimeter3d
861
+ postgis_calculate(:perimeter3d, self).to_f
862
+ end
863
+
864
+ #
865
+ # True if the LineString's start and end points are coincident.
866
+ #
867
+ # This method implements the OpenGIS Simple Features Implementation
868
+ # Specification for SQL.
869
+ #
870
+ # SQL-MM defines the result of ST_IsClosed(NULL) to be 0, while PostGIS returns NULL.
871
+ #
872
+ # Returns boolean ST_IsClosed(geometry g);
873
+ #
874
+ def closed?
875
+ postgis_calculate(:isclosed, self)
876
+ end
877
+ alias_method "is_closed?", "closed?"
878
+
879
+ #
880
+ # True if no point in Geometry B is outside Geometry A
881
+ #
882
+ # This function call will automatically include a bounding box comparison
883
+ # that will make use of any indexes that are available on the geometries.
884
+ # To avoid index use, use the function _ST_Covers.
885
+ #
886
+ # Do not call with a GEOMETRYCOLLECTION as an argument
887
+ # Do not use this function with invalid geometries. You will get unexpected results.
888
+ #
889
+ # Performed by the GEOS module.
890
+ #
891
+ # Returns Boolean ST_Covers(geometry geomA, geometry geomB);
892
+ #
893
+ def covers? other
894
+ postgis_calculate(:covers, [self, other])
895
+ end
896
+
897
+ end
898
+
899
+ #
900
+ #
901
+ #
902
+ #
903
+ # MultiPolygon
904
+ #
905
+ #
906
+ #
907
+ #
908
+ module MultiPolygonFunctions
909
+ end
910
+
911
+ end
912
+ end
913
+ # NEW
914
+ #ST_OrderingEquals — Returns true if the given geometries represent the same geometry and points are in the same directional order.
915
+ #boolean ST_OrderingEquals(g
916
+ # ST_PointOnSurface — Returns a POINT guaranteed to lie on the surface.
917
+ #geometry ST_PointOnSurface(geometry g1);eometry A, geometry B);
918
+
919
+
920
+ #x ST_SnapToGrid(geometry, geometry, sizeX, sizeY, sizeZ, sizeM)
921
+ # ST_X , ST_Y, SE_M, SE_Z, SE_IsMeasured has_m?