schleyfox-rgeo 0.2.5

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.
Files changed (150) hide show
  1. data/History.rdoc +199 -0
  2. data/README.rdoc +172 -0
  3. data/Spatial_Programming_With_RGeo.rdoc +440 -0
  4. data/Version +1 -0
  5. data/ext/geos_c_impl/extconf.rb +84 -0
  6. data/ext/geos_c_impl/factory.c +468 -0
  7. data/ext/geos_c_impl/factory.h +224 -0
  8. data/ext/geos_c_impl/geometry.c +705 -0
  9. data/ext/geos_c_impl/geometry.h +55 -0
  10. data/ext/geos_c_impl/geometry_collection.c +482 -0
  11. data/ext/geos_c_impl/geometry_collection.h +69 -0
  12. data/ext/geos_c_impl/line_string.c +509 -0
  13. data/ext/geos_c_impl/line_string.h +64 -0
  14. data/ext/geos_c_impl/main.c +70 -0
  15. data/ext/geos_c_impl/point.c +193 -0
  16. data/ext/geos_c_impl/point.h +62 -0
  17. data/ext/geos_c_impl/polygon.c +265 -0
  18. data/ext/geos_c_impl/polygon.h +66 -0
  19. data/ext/geos_c_impl/preface.h +50 -0
  20. data/ext/proj4_c_impl/extconf.rb +88 -0
  21. data/ext/proj4_c_impl/main.c +271 -0
  22. data/lib/rgeo.rb +124 -0
  23. data/lib/rgeo/cartesian.rb +60 -0
  24. data/lib/rgeo/cartesian/analysis.rb +118 -0
  25. data/lib/rgeo/cartesian/bounding_box.rb +337 -0
  26. data/lib/rgeo/cartesian/calculations.rb +161 -0
  27. data/lib/rgeo/cartesian/factory.rb +209 -0
  28. data/lib/rgeo/cartesian/feature_classes.rb +173 -0
  29. data/lib/rgeo/cartesian/feature_methods.rb +106 -0
  30. data/lib/rgeo/cartesian/interface.rb +150 -0
  31. data/lib/rgeo/coord_sys.rb +79 -0
  32. data/lib/rgeo/coord_sys/cs/entities.rb +1524 -0
  33. data/lib/rgeo/coord_sys/cs/factories.rb +208 -0
  34. data/lib/rgeo/coord_sys/cs/wkt_parser.rb +308 -0
  35. data/lib/rgeo/coord_sys/proj4.rb +312 -0
  36. data/lib/rgeo/coord_sys/srs_database/active_record_table.rb +194 -0
  37. data/lib/rgeo/coord_sys/srs_database/interface.rb +165 -0
  38. data/lib/rgeo/coord_sys/srs_database/proj4_data.rb +188 -0
  39. data/lib/rgeo/coord_sys/srs_database/sr_org.rb +108 -0
  40. data/lib/rgeo/coord_sys/srs_database/url_reader.rb +108 -0
  41. data/lib/rgeo/error.rb +63 -0
  42. data/lib/rgeo/feature.rb +88 -0
  43. data/lib/rgeo/feature/curve.rb +156 -0
  44. data/lib/rgeo/feature/factory.rb +332 -0
  45. data/lib/rgeo/feature/factory_generator.rb +138 -0
  46. data/lib/rgeo/feature/geometry.rb +614 -0
  47. data/lib/rgeo/feature/geometry_collection.rb +129 -0
  48. data/lib/rgeo/feature/line.rb +66 -0
  49. data/lib/rgeo/feature/line_string.rb +102 -0
  50. data/lib/rgeo/feature/linear_ring.rb +66 -0
  51. data/lib/rgeo/feature/multi_curve.rb +113 -0
  52. data/lib/rgeo/feature/multi_line_string.rb +66 -0
  53. data/lib/rgeo/feature/multi_point.rb +73 -0
  54. data/lib/rgeo/feature/multi_polygon.rb +97 -0
  55. data/lib/rgeo/feature/multi_surface.rb +116 -0
  56. data/lib/rgeo/feature/point.rb +120 -0
  57. data/lib/rgeo/feature/polygon.rb +141 -0
  58. data/lib/rgeo/feature/surface.rb +122 -0
  59. data/lib/rgeo/feature/types.rb +305 -0
  60. data/lib/rgeo/geographic.rb +75 -0
  61. data/lib/rgeo/geographic/factory.rb +287 -0
  62. data/lib/rgeo/geographic/interface.rb +410 -0
  63. data/lib/rgeo/geographic/proj4_projector.rb +98 -0
  64. data/lib/rgeo/geographic/projected_feature_classes.rb +213 -0
  65. data/lib/rgeo/geographic/projected_feature_methods.rb +228 -0
  66. data/lib/rgeo/geographic/projected_window.rb +467 -0
  67. data/lib/rgeo/geographic/simple_mercator_projector.rb +157 -0
  68. data/lib/rgeo/geographic/spherical_feature_classes.rb +212 -0
  69. data/lib/rgeo/geographic/spherical_feature_methods.rb +97 -0
  70. data/lib/rgeo/geographic/spherical_math.rb +206 -0
  71. data/lib/rgeo/geos.rb +72 -0
  72. data/lib/rgeo/geos/factory.rb +301 -0
  73. data/lib/rgeo/geos/impl_additions.rb +76 -0
  74. data/lib/rgeo/geos/interface.rb +139 -0
  75. data/lib/rgeo/geos/zm_factory.rb +275 -0
  76. data/lib/rgeo/geos/zm_impl.rb +432 -0
  77. data/lib/rgeo/impl_helper.rb +53 -0
  78. data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +235 -0
  79. data/lib/rgeo/impl_helper/basic_geometry_methods.rb +85 -0
  80. data/lib/rgeo/impl_helper/basic_line_string_methods.rb +197 -0
  81. data/lib/rgeo/impl_helper/basic_point_methods.rb +138 -0
  82. data/lib/rgeo/impl_helper/basic_polygon_methods.rb +121 -0
  83. data/lib/rgeo/impl_helper/math.rb +50 -0
  84. data/lib/rgeo/version.rb +52 -0
  85. data/lib/rgeo/wkrep.rb +72 -0
  86. data/lib/rgeo/wkrep/wkb_generator.rb +267 -0
  87. data/lib/rgeo/wkrep/wkb_parser.rb +315 -0
  88. data/lib/rgeo/wkrep/wkt_generator.rb +275 -0
  89. data/lib/rgeo/wkrep/wkt_parser.rb +496 -0
  90. data/test/common/geometry_collection_tests.rb +238 -0
  91. data/test/common/line_string_tests.rb +324 -0
  92. data/test/common/multi_line_string_tests.rb +209 -0
  93. data/test/common/multi_point_tests.rb +201 -0
  94. data/test/common/multi_polygon_tests.rb +208 -0
  95. data/test/common/point_tests.rb +331 -0
  96. data/test/common/polygon_tests.rb +232 -0
  97. data/test/coord_sys/tc_active_record_table.rb +102 -0
  98. data/test/coord_sys/tc_ogc_cs.rb +356 -0
  99. data/test/coord_sys/tc_proj4.rb +138 -0
  100. data/test/coord_sys/tc_proj4_srs_data.rb +76 -0
  101. data/test/coord_sys/tc_sr_org.rb +70 -0
  102. data/test/coord_sys/tc_url_reader.rb +82 -0
  103. data/test/geos/tc_factory.rb +91 -0
  104. data/test/geos/tc_geometry_collection.rb +62 -0
  105. data/test/geos/tc_line_string.rb +62 -0
  106. data/test/geos/tc_misc.rb +72 -0
  107. data/test/geos/tc_multi_line_string.rb +62 -0
  108. data/test/geos/tc_multi_point.rb +62 -0
  109. data/test/geos/tc_multi_polygon.rb +63 -0
  110. data/test/geos/tc_point.rb +86 -0
  111. data/test/geos/tc_polygon.rb +86 -0
  112. data/test/geos/tc_zmfactory.rb +85 -0
  113. data/test/projected_geographic/tc_geometry_collection.rb +62 -0
  114. data/test/projected_geographic/tc_line_string.rb +62 -0
  115. data/test/projected_geographic/tc_multi_line_string.rb +62 -0
  116. data/test/projected_geographic/tc_multi_point.rb +62 -0
  117. data/test/projected_geographic/tc_multi_polygon.rb +63 -0
  118. data/test/projected_geographic/tc_point.rb +93 -0
  119. data/test/projected_geographic/tc_polygon.rb +62 -0
  120. data/test/simple_cartesian/tc_calculations.rb +145 -0
  121. data/test/simple_cartesian/tc_geometry_collection.rb +69 -0
  122. data/test/simple_cartesian/tc_line_string.rb +70 -0
  123. data/test/simple_cartesian/tc_multi_line_string.rb +67 -0
  124. data/test/simple_cartesian/tc_multi_point.rb +67 -0
  125. data/test/simple_cartesian/tc_multi_polygon.rb +70 -0
  126. data/test/simple_cartesian/tc_point.rb +91 -0
  127. data/test/simple_cartesian/tc_polygon.rb +67 -0
  128. data/test/simple_mercator/tc_geometry_collection.rb +62 -0
  129. data/test/simple_mercator/tc_line_string.rb +62 -0
  130. data/test/simple_mercator/tc_multi_line_string.rb +62 -0
  131. data/test/simple_mercator/tc_multi_point.rb +62 -0
  132. data/test/simple_mercator/tc_multi_polygon.rb +63 -0
  133. data/test/simple_mercator/tc_point.rb +93 -0
  134. data/test/simple_mercator/tc_polygon.rb +62 -0
  135. data/test/simple_mercator/tc_window.rb +219 -0
  136. data/test/spherical_geographic/tc_calculations.rb +203 -0
  137. data/test/spherical_geographic/tc_geometry_collection.rb +70 -0
  138. data/test/spherical_geographic/tc_line_string.rb +70 -0
  139. data/test/spherical_geographic/tc_multi_line_string.rb +67 -0
  140. data/test/spherical_geographic/tc_multi_point.rb +67 -0
  141. data/test/spherical_geographic/tc_multi_polygon.rb +70 -0
  142. data/test/spherical_geographic/tc_point.rb +100 -0
  143. data/test/spherical_geographic/tc_polygon.rb +67 -0
  144. data/test/tc_cartesian_analysis.rb +107 -0
  145. data/test/tc_oneoff.rb +63 -0
  146. data/test/wkrep/tc_wkb_generator.rb +249 -0
  147. data/test/wkrep/tc_wkb_parser.rb +353 -0
  148. data/test/wkrep/tc_wkt_generator.rb +362 -0
  149. data/test/wkrep/tc_wkt_parser.rb +480 -0
  150. metadata +267 -0
@@ -0,0 +1,124 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # RGeo main file
4
+ #
5
+ # -----------------------------------------------------------------------------
6
+ # Copyright 2010 Daniel Azuma
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are met:
12
+ #
13
+ # * Redistributions of source code must retain the above copyright notice,
14
+ # this list of conditions and the following disclaimer.
15
+ # * Redistributions in binary form must reproduce the above copyright notice,
16
+ # this list of conditions and the following disclaimer in the documentation
17
+ # and/or other materials provided with the distribution.
18
+ # * Neither the name of the copyright holder, nor the names of any other
19
+ # contributors to this software, may be used to endorse or promote products
20
+ # derived from this software without specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
+ # POSSIBILITY OF SUCH DAMAGE.
33
+ # -----------------------------------------------------------------------------
34
+ ;
35
+
36
+
37
+ # RGeo is a spatial data library for Ruby. It focuses on the storage and
38
+ # manipulation of spatial data types such as points, lines, and polygons.
39
+ #
40
+ # RGeo comprises a number of modules. The "rgeo" gem provides a suite of
41
+ # standard modules. Additional optional modules are provided by separate
42
+ # gems with names of the form "<tt>rgeo-*</tt>".
43
+ #
44
+ # === Standard modules
45
+ #
46
+ # These are the standard modules provided by the "rgeo" gem.
47
+ #
48
+ # * RGeo::Feature contains interface specifications for spatial
49
+ # objects implemented by RGeo. These interfaces closely follow the OGC
50
+ # Simple Features Specifiation (SFS). This module forms the core of RGeo.
51
+ #
52
+ # * RGeo::CoordSys contains classes for representing spatial
53
+ # reference systems and coordinate transformations. For example, it
54
+ # includes a wrapper for the Proj4 library, supporting many geographic
55
+ # projections.
56
+ #
57
+ # * RGeo::Cartesian is a gateway for geometric data implementations
58
+ # that operate in Caresian (flat) coordinate systems. It also provides a
59
+ # basic pure ruby Cartesian implementation. This implementation does not
60
+ # cover all the geometric analysis operations defined by the SFS, but it
61
+ # does not require an external C library and is often sufficient for
62
+ # basic applications.
63
+ #
64
+ # * RGeo::Geos is another Cartesian implementation that wraps the
65
+ # GEOS library to provide a full, high-performance implementation of
66
+ # Cartesian geometry that includes every operation defined in the SFS.
67
+ # It requires GEOS 3.2 or later.
68
+ #
69
+ # * RGeo::Geographic contains spatial implementations that operate
70
+ # in latitude-longitude coordinates and are well-suited for geographic
71
+ # location based applications. Geographic spatial objects may also be
72
+ # linked to projections.
73
+ #
74
+ # * RGeo::WKRep contains tools for reading and writing spatial
75
+ # data in the OGC Well-Known Text (WKT) and Well-Known Binary (WKB)
76
+ # representations. It also supports common variants such as the PostGIS
77
+ # EWKT and EWKB representations.
78
+ #
79
+ # === Optional Modules
80
+ #
81
+ # Here is a partial list of optional modules available as separate gems.
82
+ #
83
+ # * <b>rgeo-geojson</b> provides the RGeo::GeoJSON module, containing
84
+ # tools for GeoJSON encoding and decoding of spatial objects.
85
+ #
86
+ # * <b>rgeo-shapefile</b> provides the RGeo::Shapefile module, containing
87
+ # tools for reading ESRI shapefiles.
88
+ #
89
+ # * <b>rgeo-activerecord</b> provides the RGeo::ActiveRecord module,
90
+ # containing some ActiveRecord extensions for spatial databases, and a
91
+ # set of common tools for ActiveRecord spatial database adapters.
92
+ #
93
+ # Several ActiveRecord adapters use RGeo. These include:
94
+ #
95
+ # * <b>mysqlspatial</b>, an adapter for MySQL spatial extensions based on
96
+ # the mysql adapter. Available as the activerecord-mysqlspatial-adapter
97
+ # gem.
98
+ #
99
+ # * <b>mysql2spatial</b>, an adapter for MySQL spatial extensions based on
100
+ # the mysql2 adapter. Available as the activerecord-mysql2spatial-adapter
101
+ # gem.
102
+ #
103
+ # * <b>spatialite</b>, an adapter for the SpatiaLite extension to the
104
+ # Sqlite3 database, and based on the sqlite3 adapter. Available as the
105
+ # activerecord-spatialite-adapter gem.
106
+ #
107
+ # * <b>postgis</b>, an adapter for the PostGIS extension to the PostgreSQL
108
+ # database, and based on the postgresql adapter. Available as the
109
+ # activerecord-postgis-adapter gem.
110
+
111
+ module RGeo
112
+ end
113
+
114
+
115
+ # Core modules
116
+ require 'rgeo/version'
117
+ require 'rgeo/error'
118
+ require 'rgeo/feature'
119
+ require 'rgeo/coord_sys'
120
+ require 'rgeo/impl_helper'
121
+ require 'rgeo/wkrep'
122
+ require 'rgeo/geos'
123
+ require 'rgeo/cartesian'
124
+ require 'rgeo/geographic'
@@ -0,0 +1,60 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Cartesian features for RGeo
4
+ #
5
+ # -----------------------------------------------------------------------------
6
+ # Copyright 2010 Daniel Azuma
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are met:
12
+ #
13
+ # * Redistributions of source code must retain the above copyright notice,
14
+ # this list of conditions and the following disclaimer.
15
+ # * Redistributions in binary form must reproduce the above copyright notice,
16
+ # this list of conditions and the following disclaimer in the documentation
17
+ # and/or other materials provided with the distribution.
18
+ # * Neither the name of the copyright holder, nor the names of any other
19
+ # contributors to this software, may be used to endorse or promote products
20
+ # derived from this software without specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
+ # POSSIBILITY OF SUCH DAMAGE.
33
+ # -----------------------------------------------------------------------------
34
+ ;
35
+
36
+
37
+ module RGeo
38
+
39
+
40
+ # The Cartesian module is a gateway to implementations that use the
41
+ # Cartesian (i.e. flat) coordinate system. It provides convenient
42
+ # access to Cartesian factories such as the Geos implementation and
43
+ # the simple Cartesian implementation. It also provides a namespace
44
+ # for Cartesian-specific analysis tools.
45
+
46
+ module Cartesian
47
+ end
48
+
49
+
50
+ end
51
+
52
+
53
+ # Implementation files.
54
+ require 'rgeo/cartesian/calculations'
55
+ require 'rgeo/cartesian/feature_methods'
56
+ require 'rgeo/cartesian/feature_classes'
57
+ require 'rgeo/cartesian/factory'
58
+ require 'rgeo/cartesian/interface'
59
+ require 'rgeo/cartesian/bounding_box'
60
+ require 'rgeo/cartesian/analysis'
@@ -0,0 +1,118 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Cartesian toplevel interface
4
+ #
5
+ # -----------------------------------------------------------------------------
6
+ # Copyright 2010 Daniel Azuma
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are met:
12
+ #
13
+ # * Redistributions of source code must retain the above copyright notice,
14
+ # this list of conditions and the following disclaimer.
15
+ # * Redistributions in binary form must reproduce the above copyright notice,
16
+ # this list of conditions and the following disclaimer in the documentation
17
+ # and/or other materials provided with the distribution.
18
+ # * Neither the name of the copyright holder, nor the names of any other
19
+ # contributors to this software, may be used to endorse or promote products
20
+ # derived from this software without specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
+ # POSSIBILITY OF SUCH DAMAGE.
33
+ # -----------------------------------------------------------------------------
34
+ ;
35
+
36
+
37
+ module RGeo
38
+
39
+ module Cartesian
40
+
41
+
42
+ # This provides includes some spatial analysis algorithms supporting
43
+ # Cartesian data.
44
+
45
+ module Analysis
46
+
47
+ class << self
48
+
49
+
50
+ # Given a LineString, which must be a ring, determine whether the
51
+ # ring proceeds clockwise or counterclockwise.
52
+ # Returns 1 for counterclockwise, or -1 for clockwise.
53
+ #
54
+ # Returns 0 if the ring is empty.
55
+ # The return value is undefined if the object is not a ring, or
56
+ # is not in a Cartesian coordinate system.
57
+
58
+ def ring_direction(ring_)
59
+ size_ = ring_.num_points - 1
60
+ return 0 if size_ == 0
61
+
62
+ # Extract unit-length segments from the ring.
63
+ segs_ = []
64
+ size_.times do |i_|
65
+ p0_ = ring_.point_n(i_)
66
+ p1_ = ring_.point_n(i_+1)
67
+ x_ = p1_.x - p0_.x
68
+ y_ = p1_.y - p0_.y
69
+ r_ = ::Math.sqrt(x_*x_ + y_*y_)
70
+ if r_ > 0.0
71
+ segs_ << x_/r_ << y_/r_
72
+ end
73
+ end
74
+ segs_ << segs_[0] << segs_[1]
75
+
76
+ # Extract angles from the segments by subtracting the segments.
77
+ # Note angles are represented as cos/sin pairs so we don't
78
+ # have to calculate any trig functions.
79
+ angs_ = []
80
+ size_.times do |i_|
81
+ x0_, y0_, x1_, y1_ = segs_[i_*2,4]
82
+ angs_ << x0_*x1_ + y0_*y1_ << x0_*y1_ - x1_*y0_
83
+ end
84
+
85
+ # Now add the angles and count revolutions.
86
+ # Again, our running sum is represented as a cos/sin pair.
87
+ revolutions_ = 0
88
+ sin_ = 0.0
89
+ cos_ = 1.0
90
+ angs_.each_slice(2) do |(x_, y_)|
91
+ ready_ = y_ > 0.0 && sin_ > 0.0 || y_ < 0.0 && sin_ < 0.0
92
+ if y_ != 0.0
93
+ s_ = sin_*x_ + cos_*y_
94
+ c_ = cos_*x_ - sin_*y_
95
+ r_ = ::Math.sqrt(s_*s_ + c_*c_)
96
+ sin_ = s_ / r_
97
+ cos_ = c_ / r_
98
+ end
99
+ if ready_
100
+ if y_ > 0.0 && sin_ <= 0.0
101
+ revolutions_ += 1
102
+ elsif y_ < 0.0 && sin_ >= 0.0
103
+ revolutions_ -= 1
104
+ end
105
+ end
106
+ end
107
+ revolutions_
108
+ end
109
+
110
+
111
+ end
112
+
113
+ end
114
+
115
+
116
+ end
117
+
118
+ end
@@ -0,0 +1,337 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Cartesian toplevel interface
4
+ #
5
+ # -----------------------------------------------------------------------------
6
+ # Copyright 2010 Daniel Azuma
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are met:
12
+ #
13
+ # * Redistributions of source code must retain the above copyright notice,
14
+ # this list of conditions and the following disclaimer.
15
+ # * Redistributions in binary form must reproduce the above copyright notice,
16
+ # this list of conditions and the following disclaimer in the documentation
17
+ # and/or other materials provided with the distribution.
18
+ # * Neither the name of the copyright holder, nor the names of any other
19
+ # contributors to this software, may be used to endorse or promote products
20
+ # derived from this software without specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
+ # POSSIBILITY OF SUCH DAMAGE.
33
+ # -----------------------------------------------------------------------------
34
+ ;
35
+
36
+
37
+ module RGeo
38
+
39
+ module Cartesian
40
+
41
+
42
+ # This is a bounding box for Cartesian data.
43
+ # The simple cartesian implementation uses this internally to compute
44
+ # envelopes. You may also use it directly to compute and represent
45
+ # bounding boxes.
46
+ #
47
+ # A bounding box is a set of ranges in each dimension: X, Y, as well
48
+ # as Z and M if supported. You can compute a bounding box for one or
49
+ # more geometry objects by creating a new bounding box object, and
50
+ # adding the geometries to it. You may then query it for the bounds,
51
+ # or use it to determine whether it encloses other geometries or
52
+ # bounding boxes.
53
+
54
+ class BoundingBox
55
+
56
+
57
+ # Create a new empty bounding box with the given factory.
58
+ #
59
+ # The factory defines the coordinate system for the bounding box,
60
+ # and also defines whether it should track Z and M coordinates.
61
+ # All geometries will be cast to this factory when added to this
62
+ # bounding box, and any generated envelope geometry will have this
63
+ # as its factory.
64
+ #
65
+ # Options include:
66
+ #
67
+ # [<tt>:ignore_z</tt>]
68
+ # If true, ignore z coordinates even if the factory supports them.
69
+ # Default is false.
70
+ # [<tt>:ignore_m</tt>]
71
+ # If true, ignore m coordinates even if the factory supports them.
72
+ # Default is false.
73
+
74
+ def initialize(factory_, opts_={})
75
+ @factory = factory_
76
+ @has_z = !opts_[:ignore_z] && factory_.property(:has_z_coordinate) ? true : false
77
+ @has_m = !opts_[:ignore_m] && factory_.property(:has_m_coordinate) ? true : false
78
+ @min_x = @max_x = @min_y = @max_y = @min_z = @max_z = @min_m = @max_m = nil
79
+ end
80
+
81
+
82
+ def eql?(rhs_) # :nodoc:
83
+ rhs_.is_a?(BoundingBox) && @factory == rhs_.factory &&
84
+ @min_x == rhs_.min_x && @max_x == rhs_.max_x &&
85
+ @min_y == rhs_.min_y && @max_y == rhs_.max_y &&
86
+ @min_z == rhs_.min_z && @max_z == rhs_.max_z &&
87
+ @min_m == rhs_.min_m && @max_m == rhs_.max_m
88
+ end
89
+ alias_method :==, :eql?
90
+
91
+
92
+ # Returns the bounding box's factory.
93
+
94
+ def factory
95
+ @factory
96
+ end
97
+
98
+
99
+ # Returns true if this bounding box is still empty.
100
+
101
+ def empty?
102
+ @min_x.nil?
103
+ end
104
+
105
+
106
+ # Returns true if this bounding box tracks Z coordinates.
107
+
108
+ def has_z
109
+ @has_z
110
+ end
111
+
112
+
113
+ # Returns true if this bounding box tracks M coordinates.
114
+
115
+ def has_m
116
+ @has_m
117
+ end
118
+
119
+
120
+ # Returns the minimum X, or nil if this bounding box is empty.
121
+
122
+ def min_x
123
+ @min_x
124
+ end
125
+
126
+
127
+ # Returns the maximum X, or nil if this bounding box is empty.
128
+
129
+ def max_x
130
+ @max_x
131
+ end
132
+
133
+
134
+ # Returns the minimum Y, or nil if this bounding box is empty.
135
+
136
+ def min_y
137
+ @min_y
138
+ end
139
+
140
+
141
+ # Returns the maximum Y, or nil if this bounding box is empty.
142
+
143
+ def max_y
144
+ @max_y
145
+ end
146
+
147
+
148
+ # Returns the minimum Z, or nil if this bounding box is empty.
149
+
150
+ def min_z
151
+ @min_z
152
+ end
153
+
154
+
155
+ # Returns the maximum Z, or nil if this bounding box is empty.
156
+
157
+ def max_z
158
+ @max_z
159
+ end
160
+
161
+
162
+ # Returns the minimum M, or nil if this bounding box is empty.
163
+
164
+ def min_m
165
+ @min_m
166
+ end
167
+
168
+
169
+ # Returns the maximum M, or nil if this bounding box is empty.
170
+
171
+ def max_m
172
+ @max_m
173
+ end
174
+
175
+
176
+ # Returns a point representing the minimum extent in all dimensions,
177
+ # or nil if this bounding box is empty.
178
+
179
+ def min_point
180
+ if @min_x
181
+ extras_ = []
182
+ extras_ << @min_z if @has_z
183
+ extras_ << @min_m if @has_m
184
+ @factory.point(@min_x, @min_y, *extras_)
185
+ else
186
+ nil
187
+ end
188
+ end
189
+
190
+
191
+ # Returns a point representing the maximum extent in all dimensions,
192
+ # or nil if this bounding box is empty.
193
+
194
+ def max_point
195
+ if @min_x
196
+ extras_ = []
197
+ extras_ << @max_z if @has_z
198
+ extras_ << @max_m if @has_m
199
+ @factory.point(@max_x, @max_y, *extras_)
200
+ else
201
+ nil
202
+ end
203
+ end
204
+
205
+
206
+ # Adjusts the extents of this bounding box to encomass the given
207
+ # object, which may be a geometry or another bounding box.
208
+ # Returns self.
209
+
210
+ def add(geometry_)
211
+ case geometry_
212
+ when BoundingBox
213
+ add(geometry_.min_point)
214
+ add(geometry_.max_point)
215
+ when Feature::Geometry
216
+ if geometry_.factory == @factory
217
+ _add_geometry(geometry_)
218
+ else
219
+ _add_geometry(Factory.cast(geometry_, @factory))
220
+ end
221
+ end
222
+ self
223
+ end
224
+
225
+
226
+ # Converts this bounding box to an envelope polygon.
227
+ # Returns the empty collection if this bounding box is empty.
228
+
229
+ def to_geometry
230
+ if @min_x
231
+ extras_ = []
232
+ extras_ << @min_z if @has_z
233
+ extras_ << @min_m if @has_m
234
+ point_min_ = @factory.point(@min_x, @min_y, *extras_)
235
+ if @min_x == @max_x && @min_y == @max_y
236
+ point_min_
237
+ else
238
+ extras_ = []
239
+ extras_ << @max_z if @has_z
240
+ extras_ << @max_m if @has_m
241
+ point_max_ = @factory.point(@max_x, @max_y, *extras_)
242
+ if @min_x == @max_x || @min_y == @max_y
243
+ @factory.line(point_min_, point_max_)
244
+ else
245
+ @factory.polygon(@factory.linear_ring(point_min_, @factory.point(@max_x, @min_y, *extras_), point_max_, @factory.point(@min_x, @max_y, *extras_), point_min_))
246
+ end
247
+ end
248
+ else
249
+ @factory.collection([])
250
+ end
251
+ end
252
+
253
+
254
+ # Returns true if this bounding box contains the given object,
255
+ # which may be a geometry or another bounding box.
256
+ #
257
+ # Supports these options:
258
+ #
259
+ # <tt>:ignore_z</tt>
260
+ # Ignore the Z coordinate when testing, even if both objects
261
+ # have Z. Default is false.
262
+ # <tt>:ignore_m</tt>
263
+ # Ignore the M coordinate when testing, even if both objects
264
+ # have M. Default is false.
265
+
266
+ def contains?(rhs_, opts_={})
267
+ if Feature::Geometry === rhs_
268
+ contains?(BoundingBox.new(@factory).add(rhs_))
269
+ elsif rhs_.empty?
270
+ true
271
+ elsif empty?
272
+ false
273
+ elsif @min_x > rhs_.min_x || @max_x < rhs_.max_x || @min_y > rhs_.min_y || @max_y < rhs_.max_y
274
+ false
275
+ elsif @has_m && rhs_.has_m && !opts_[:ignore_m] && (@min_m > rhs_.min_m || @max_m < rhs_.max_m)
276
+ false
277
+ elsif @has_z && rhs_.has_z && !opts_[:ignore_z] && (@min_z > rhs_.min_z || @max_z < rhs_.max_z)
278
+ false
279
+ else
280
+ true
281
+ end
282
+ end
283
+
284
+
285
+ def _add_geometry(geometry_) # :nodoc:
286
+ case geometry_
287
+ when Feature::Point
288
+ _add_point(geometry_)
289
+ when Feature::LineString
290
+ geometry_.points.each{ |p_| _add_point(p_) }
291
+ when Feature::Polygon
292
+ geometry_.exterior_ring.points.each{ |p_| _add_point(p_) }
293
+ when Feature::MultiPoint
294
+ geometry_.each{ |p_| _add_point(p_) }
295
+ when Feature::MultiLineString
296
+ geometry_.each{ |line_| line_.points.each{ |p_| _add_point(p_) } }
297
+ when Feature::MultiPolygon
298
+ geometry_.each{ |poly_| poly_.exterior_ring.points.each{ |p_| _add_point(p_) } }
299
+ when Feature::GeometryCollection
300
+ geometry_.each{ |g_| _add_geometry(g_) }
301
+ end
302
+ end
303
+
304
+
305
+ def _add_point(point_) # :nodoc:
306
+ if @min_x
307
+ x_ = point_.x
308
+ @min_x = x_ if x_ < @min_x
309
+ @max_x = x_ if x_ > @max_x
310
+ y_ = point_.y
311
+ @min_y = y_ if y_ < @min_y
312
+ @max_y = y_ if y_ > @max_y
313
+ if @has_z
314
+ z_ = point_.z
315
+ @min_z = z_ if z_ < @min_z
316
+ @max_z = z_ if z_ > @max_z
317
+ end
318
+ if @has_m
319
+ m_ = point_.m
320
+ @min_m = m_ if m_ < @min_m
321
+ @max_m = m_ if m_ > @max_m
322
+ end
323
+ else
324
+ @min_x = @max_x = point_.x
325
+ @min_y = @max_y = point_.y
326
+ @min_z = @max_z = point_.z if @has_z
327
+ @min_m = @max_m = point_.m if @has_m
328
+ end
329
+ end
330
+
331
+
332
+ end
333
+
334
+
335
+ end
336
+
337
+ end