griffordson-georuby-extras 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,7 @@
1
+ === 0.6.0 / 2010-06-30
2
+
3
+ * Added LinearRing#fast_contains?
4
+
5
+ === 0.5.0 / 2008-12-03
6
+
7
+ * Released by David Troy (C) Under the MIT License
data/Manifest.txt ADDED
@@ -0,0 +1,11 @@
1
+ History.txt
2
+ README
3
+ ext/extconf.rb
4
+ ext/vincenty.c
5
+ ext/pnpoly.c
6
+ ext/pnpoly.h
7
+ lib/georuby-extras.rb
8
+ test/test_vincenty.rb
9
+ test/test_pnpoly.rb
10
+ test/extras-benchmark.rb
11
+
data/README ADDED
@@ -0,0 +1,77 @@
1
+ = georuby-extras
2
+
3
+ * http://github.com/davetroy/georuby-extras
4
+
5
+ == DESCRIPTION:
6
+
7
+ GeoRuby-Extras Gem for Ruby (c) 2008 David Troy
8
+ dave@roundhousetech.com
9
+
10
+ GeoRuby-Extras offers some native C enhancements and extras to the popular GeoRuby gem.
11
+
12
+ GeoRuby offers OGC-compliant simple features for Ruby as well as the ability to
13
+ process SHP files and do other cool GIS hacks. GeoRuby is often used in conjunction
14
+ with GIS extensions for popular databases including Postgres and MySQL.
15
+
16
+ == FEATURES/PROBLEMS:
17
+
18
+ * Provides native C implementation of Vincenty distance and direct algorithms.
19
+ * 25 times faster than GeoRuby 'ellipsoidal_distance' function.
20
+ * Adds the Vincenty 'direct' algorithm (point_at_bearing_and_distance).
21
+ * Provides native C implementation of a ray casting algorithm to detect if a point is contained in a polygon.
22
+ * No known problems; won't work with JRuby or non-MRI Ruby implementations.
23
+
24
+ == SYNOPSIS:
25
+
26
+ require 'rubygems'
27
+ require 'georuby-extras'
28
+
29
+ include GeoRuby::SimpleFeatures
30
+
31
+ @home = Point.from_lon_lat(-76.511,39.024)
32
+ @nyc = Point.from_lon_lat(-74,40.6)
33
+
34
+ >> @home.ellipsoidal_distance(@nyc)
35
+ => 277195.510448391
36
+
37
+ >> @home.point_at_bearing_and_distance(91.0, 130000.0).kml_representation
38
+ => "<Point>\n<coordinates>-75.0105920700835,38.9939120193168</coordinates>\n</Point>\n"
39
+
40
+ == REQUIREMENTS:
41
+
42
+ * GCC and a Gnu-ish build environment (for native extensions)
43
+
44
+ == INSTALLATION
45
+
46
+ 1) Update to the latest RubyGems version
47
+ > gem update --system
48
+
49
+ 2) Install gem
50
+ > gem install griffordson-georuby-extras
51
+
52
+ 3) Profit!
53
+
54
+ == LICENSE:
55
+
56
+ (The MIT License)
57
+
58
+ Copyright (c) 2008 David Troy, Roundhouse Technologies LLC
59
+
60
+ Permission is hereby granted, free of charge, to any person obtaining
61
+ a copy of this software and associated documentation files (the
62
+ 'Software'), to deal in the Software without restriction, including
63
+ without limitation the rights to use, copy, modify, merge, publish,
64
+ distribute, sublicense, and/or sell copies of the Software, and to
65
+ permit persons to whom the Software is furnished to do so, subject to
66
+ the following conditions:
67
+
68
+ The above copyright notice and this permission notice shall be
69
+ included in all copies or substantial portions of the Software.
70
+
71
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
72
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
73
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
74
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
75
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
76
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
77
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/ext/extconf.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+ dir_config("grextras")
3
+ create_makefile("grextras")
data/ext/pnpoly.c ADDED
@@ -0,0 +1,105 @@
1
+ // pnpoly.c
2
+ // (c) 2010 Matt Griffith
3
+ //
4
+ // A native Ruby extension for determining if a point is in a polygon.
5
+ //
6
+ // (The MIT License)
7
+ //
8
+ // Copyright (c) 2010 Matt Griffith, AgriSmart Information Systems, LLC
9
+ //
10
+ // Permission is hereby granted, free of charge, to any person obtaining
11
+ // a copy of this software and associated documentation files (the
12
+ // 'Software'), to deal in the Software without restriction, including
13
+ // without limitation the rights to use, copy, modify, merge, publish,
14
+ // distribute, sublicense, and/or sell copies of the Software, and to
15
+ // permit persons to whom the Software is furnished to do so, subject to
16
+ // the following conditions:
17
+ //
18
+ // The above copyright notice and this permission notice shall be
19
+ // included in all copies or substantial portions of the Software.
20
+ //
21
+ // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
22
+ // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24
+ // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25
+ // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26
+ // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
+ //
29
+ // --------------------------------------------------------
30
+ // The pnpoly function is covered by the following license.
31
+ // For more inforation see:
32
+ // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
33
+ //
34
+ // Copyright (c) 1970-2003, Wm. Randolph Franklin
35
+ //
36
+ // Permission is hereby granted, free of charge, to any person obtaining
37
+ // a copy of this software and associated documentation files (the
38
+ // "Software"), to deal in the Software without restriction, including
39
+ // without limitation the rights to use, copy, modify, merge, publish,
40
+ // distribute, sublicense, and/or sell copies of the Software, and to
41
+ // permit persons to whom the Software is furnished to do so, subject to
42
+ // the following conditions:
43
+ //
44
+ // Redistributions of source code must retain the above copyright
45
+ // notice, this list of conditions and the following disclaimers.
46
+ // Redistributions in binary form must reproduce the above copyright
47
+ // notice in the documentation and/or other materials provided with the
48
+ // distribution. The name of W. Randolph Franklin may not be used to
49
+ // endorse or promote products derived from this Software without
50
+ // specific prior written permission. THE SOFTWARE IS PROVIDED "AS IS",
51
+ // WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
52
+ // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
53
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
54
+ // OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
56
+ // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
57
+ // OTHER DEALINGS IN THE SOFTWARE.
58
+
59
+ #include "ruby.h"
60
+ #include "pnpoly.h"
61
+
62
+ static int pnpoly(int nvert, float *vertx, float *verty, float testx, float testy)
63
+ {
64
+ int i, j, c = 0;
65
+ for (i = 0, j = nvert-1; i < nvert; j = i++) {
66
+ if ( ((verty[i]>testy) != (verty[j]>testy)) &&
67
+ (testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
68
+ c = !c;
69
+ }
70
+ return c;
71
+ }
72
+
73
+ VALUE point_in_poly(VALUE self, VALUE rb_x, VALUE rb_y, VALUE rb_points) {
74
+ Check_Type(rb_x, T_FLOAT);
75
+ Check_Type(rb_y, T_FLOAT);
76
+ Check_Type(rb_points, T_ARRAY);
77
+
78
+ int i = 0;
79
+ int s = RARRAY(rb_points)->len;
80
+ float *vertx;
81
+ float *verty;
82
+
83
+ vertx = calloc(s, sizeof(float));
84
+ verty = calloc(s, sizeof(float));
85
+
86
+ float test_x = RFLOAT(rb_x)->value;
87
+ float test_y = RFLOAT(rb_y)->value;
88
+
89
+ ID i_x = rb_intern("x");
90
+ ID i_y = rb_intern("y");
91
+
92
+ for(i = 0; i < s; i++) {
93
+ VALUE point = RARRAY_PTR(rb_points)[i];
94
+ VALUE x = rb_funcall(point, i_x, 0);
95
+ VALUE y = rb_funcall(point, i_y, 0);
96
+ Check_Type(x, T_FLOAT);
97
+ Check_Type(y, T_FLOAT);
98
+ vertx[i] = RFLOAT(x)->value;
99
+ verty[i] = RFLOAT(y)->value;
100
+ }
101
+
102
+ return pnpoly(s, vertx, verty, test_x, test_y);
103
+ }
104
+
105
+ // end
data/ext/pnpoly.h ADDED
@@ -0,0 +1,6 @@
1
+ #if !defined(_pnpoly_h_)
2
+ #define _pnpoly_h_
3
+
4
+ VALUE point_in_poly(VALUE self, VALUE rb_lat, VALUE rb_lon, VALUE rb_points);
5
+
6
+ #endif // _pnpoly_h_
data/ext/vincenty.c ADDED
@@ -0,0 +1,166 @@
1
+ // geohash-native.c
2
+ // (c) 2008 David Troy
3
+ // dave@roundhousetech.com
4
+ //
5
+ // Based on Javascript code (c) by Chris Veness
6
+ // http://www.movable-type.co.uk/scripts/latlong-vincenty.html
7
+ // http://www.movable-type.co.uk/scripts/latlong-vincenty-direct.html
8
+ //
9
+ // Derived from algorithms by T. Vincenty, 1975
10
+ //
11
+ // (The MIT License)
12
+ //
13
+ // Copyright (c) 2008 David Troy, Roundhouse Technologies LLC
14
+ //
15
+ // Permission is hereby granted, free of charge, to any person obtaining
16
+ // a copy of this software and associated documentation files (the
17
+ // 'Software'), to deal in the Software without restriction, including
18
+ // without limitation the rights to use, copy, modify, merge, publish,
19
+ // distribute, sublicense, and/or sell copies of the Software, and to
20
+ // permit persons to whom the Software is furnished to do so, subject to
21
+ // the following conditions:
22
+ //
23
+ // The above copyright notice and this permission notice shall be
24
+ // included in all copies or substantial portions of the Software.
25
+ //
26
+ // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
27
+ // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
29
+ // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
30
+ // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
31
+ // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
32
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33
+
34
+ #include "ruby.h"
35
+ #include <math.h>
36
+ #include <ctype.h>
37
+ #include "pnpoly.h"
38
+
39
+ #define DEG_TO_RAD 0.0174532925199433
40
+ #define PI 3.14159265358979
41
+
42
+ static VALUE rb_mVincenty;
43
+ static VALUE rb_mPointInPoly;
44
+
45
+ static VALUE distance(VALUE self, VALUE rb_lon1, VALUE rb_lat1, VALUE rb_lon2, VALUE rb_lat2, VALUE rb_a, VALUE rb_b) {
46
+
47
+ Check_Type(rb_lon1, T_FLOAT);
48
+ Check_Type(rb_lat1, T_FLOAT);
49
+ Check_Type(rb_lon2, T_FLOAT);
50
+ Check_Type(rb_lat2, T_FLOAT);
51
+ Check_Type(rb_a, T_FLOAT);
52
+ Check_Type(rb_b, T_FLOAT);
53
+
54
+ double lon1 = RFLOAT(rb_lon1)->value;
55
+ double lat1 = RFLOAT(rb_lat1)->value;
56
+ double lon2 = RFLOAT(rb_lon2)->value;
57
+ double lat2 = RFLOAT(rb_lat2)->value;
58
+ double a = RFLOAT(rb_a)->value;
59
+ double b = RFLOAT(rb_b)->value;
60
+
61
+ double sinLambda, cosLambda, sinSigma, cosSigma, sigma, sinAlpha, cosSqAlpha, cos2SigmaM, C;
62
+
63
+ double f = (a-b) / a;
64
+ double L = (lon2-lon1) * DEG_TO_RAD;
65
+ double U1 = atan((1-f) * tan(lat1 * DEG_TO_RAD));
66
+ double U2 = atan((1-f) * tan(lat2 * DEG_TO_RAD));
67
+ double sinU1 = sin(U1), cosU1 = cos(U1);
68
+ double sinU2 = sin(U2), cosU2 = cos(U2);
69
+
70
+ int iterLimit = 20;
71
+ double lambda = L, lambdaP=2*PI;
72
+ while ((fabs(lambda-lambdaP) > 1e-12 && --iterLimit>0)) {
73
+ sinLambda = sin(lambda); cosLambda = cos(lambda);
74
+ sinSigma = sqrt((cosU2*sinLambda) * (cosU2*sinLambda) + (cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda));
75
+ if (sinSigma==0) return rb_float_new(0); // co-incident points
76
+ cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda;
77
+ sigma = atan2(sinSigma, cosSigma);
78
+ sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
79
+ cosSqAlpha = 1 - sinAlpha*sinAlpha;
80
+ cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha;
81
+ if (isnan(cos2SigmaM)) cos2SigmaM = 0; // equatorial line: cosSqAlpha=0 (§6)
82
+ C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
83
+ lambdaP = lambda;
84
+ lambda = L + (1-C) * f * sinAlpha * (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
85
+ }
86
+
87
+ if (iterLimit==0) return Qnil; // formula failed to converge
88
+
89
+ double uSq = cosSqAlpha * (a*a - b*b) / (b*b);
90
+ double A = 1 + uSq/16384.0*(4096+uSq*(-768+uSq*(320-175*uSq)));
91
+ double B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
92
+ double deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM) -
93
+ B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
94
+
95
+ double s = b*A*(sigma-deltaSigma);
96
+
97
+ return rb_float_new(s);
98
+ }
99
+
100
+ static VALUE point_from_lon_lat(VALUE self, VALUE rb_lon1, VALUE rb_lat1, VALUE rb_bearing, VALUE rb_distance, VALUE rb_a, VALUE rb_b) {
101
+ Check_Type(rb_lon1, T_FLOAT);
102
+ Check_Type(rb_lat1, T_FLOAT);
103
+ Check_Type(rb_bearing, T_FLOAT);
104
+ Check_Type(rb_distance, T_FLOAT);
105
+ Check_Type(rb_a, T_FLOAT);
106
+ Check_Type(rb_b, T_FLOAT);
107
+
108
+ VALUE ret;
109
+
110
+ double lon1 = RFLOAT(rb_lon1)->value;
111
+ double lat1 = RFLOAT(rb_lat1)->value;
112
+ double brng = RFLOAT(rb_bearing)->value;
113
+ double s = RFLOAT(rb_distance)->value;
114
+ double a = RFLOAT(rb_a)->value;
115
+ double b = RFLOAT(rb_b)->value;
116
+
117
+ double f = (a-b) / a;
118
+ double alpha1 = brng * DEG_TO_RAD;
119
+ double sinAlpha1 = sin(alpha1), cosAlpha1 = cos(alpha1);
120
+
121
+ double tanU1 = (1-f) * tan(lat1 * DEG_TO_RAD);
122
+ double cosU1 = 1 / sqrt((1 + tanU1*tanU1)), sinU1 = tanU1*cosU1;
123
+ double sigma1 = atan2(tanU1, cosAlpha1);
124
+ double sinAlpha = cosU1 * sinAlpha1;
125
+ double cosSqAlpha = 1 - sinAlpha*sinAlpha;
126
+ double uSq = cosSqAlpha * (a*a - b*b) / (b*b);
127
+ double A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
128
+ double B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
129
+
130
+ double sigma = s / (b*A), sigmaP = 2*PI;
131
+ double cos2SigmaM, sinSigma, deltaSigma, cosSigma;
132
+ while (fabs(sigma-sigmaP) > 1e-12) {
133
+ cos2SigmaM = cos(2*sigma1 + sigma);
134
+ sinSigma = sin(sigma), cosSigma = cos(sigma);
135
+ deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
136
+ B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
137
+ sigmaP = sigma;
138
+ sigma = s / (b*A) + deltaSigma;
139
+ }
140
+
141
+ double tmp = sinU1*sinSigma - cosU1*cosSigma*cosAlpha1;
142
+ double lat2 = atan2(sinU1*cosSigma + cosU1*sinSigma*cosAlpha1, (1-f)*sqrt(sinAlpha*sinAlpha + tmp*tmp));
143
+ double lambda = atan2(sinSigma*sinAlpha1, cosU1*cosSigma - sinU1*sinSigma*cosAlpha1);
144
+ double C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
145
+ double L = lambda - (1-C) * f * sinAlpha * (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
146
+
147
+ double revAz = atan2(sinAlpha, -tmp); // final bearing
148
+
149
+ ret = rb_ary_new2(2); /* [lon, lat] */
150
+ rb_ary_store(ret, 0, rb_float_new(lon1+L/DEG_TO_RAD));
151
+ rb_ary_store(ret, 1, rb_float_new(lat2/DEG_TO_RAD));
152
+
153
+ return ret;
154
+ }
155
+
156
+ void Init_grextras()
157
+ {
158
+ rb_mVincenty = rb_define_module("Vincenty");
159
+ rb_define_module_function(rb_mVincenty, "distance", distance, 6);
160
+ rb_define_module_function(rb_mVincenty, "point_from_lon_lat", point_from_lon_lat, 6);
161
+
162
+ rb_mPointInPoly = rb_define_module("PointInPoly");
163
+ rb_define_module_function(rb_mPointInPoly, "point_in_poly", point_in_poly, 3);
164
+ }
165
+
166
+ // end
@@ -0,0 +1,46 @@
1
+ require 'geo_ruby'
2
+ require "#{File.dirname(__FILE__)}/../ext/grextras"
3
+
4
+ module GeoRuby
5
+ module SimpleFeatures
6
+ class Point < Geometry
7
+
8
+ alias_method :orig_ellipsoidal_distance, :ellipsoidal_distance
9
+
10
+ # Implementation of the Vincenty 'distance' formula to find the ellipsoidal distance between points
11
+ # As per implementation by Chris Veness (http://www.movable-type.co.uk/scripts/latlong-vincenty.html)
12
+ # Default a/b values are for the WGS84 ellipsoid - other values may be specified
13
+ def ellipsoidal_distance(point, a = 6378137.0, b = 6356752.3142)
14
+ Vincenty.distance(x.to_f, y.to_f, point.x.to_f, point.y.to_f, a.to_f, b.to_f)
15
+ end
16
+
17
+ # Implementation of the Vincenty 'direct' formula to find a point based on a bearing and distance
18
+ # As per implementation by Chris Veness (http://www.movable-type.co.uk/scripts/latlong-vincenty-direct.html)
19
+ # Default a/b values are for the WGS84 ellipsoid - other values may be specified
20
+ def point_at_bearing_and_distance(bearing=0.0, distance=0.0, a = 6378137.0, b = 6356752.3142)
21
+ Point.from_coordinates(Vincenty.point_from_lon_lat(lon.to_f,lat.to_f,bearing.to_f,distance.to_f,a.to_f,b.to_f))
22
+ end
23
+
24
+ end
25
+
26
+
27
+ class LinearRing < LineString
28
+ def fast_contains?(point)
29
+ !!PointInPoly.point_in_poly(point.x.to_f, point.y.to_f, points)
30
+ end
31
+
32
+ def slow_contains?(point_to_check)
33
+ c = 0
34
+ last = points[points.length - 1]
35
+
36
+ points.each do |point|
37
+ if (point.y > point_to_check.y) != (last.y > point_to_check.y)
38
+ c += 1 if point_to_check.x < (last.x - point.x) * (point_to_check.y - point.y) / (last.y / point.y) + point.x
39
+ end
40
+ last = point
41
+ end
42
+ ((c % 2) == 1)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'test/unit'
4
+ require 'geo_ruby'
5
+ require "#{File.dirname(__FILE__)}/../lib/georuby-extras"
6
+
7
+ class PointInPolyTest < Test::Unit::TestCase
8
+
9
+ include GeoRuby::SimpleFeatures
10
+
11
+ def setup
12
+ @poly_points = [[-95.81394, 41.008889], [-95.8103490000001, 41.0089209999999], [-95.8109810000001, 41.0072869999999], [-95.8113760000001, 41.00503], [-95.812187, 41.0017499999999], [-95.818804, 41.0017539999999], [-95.8187930000001, 41.0031709999998], [-95.8186090000002, 41.0038159999999], [-95.8186070000002, 41.008026], [-95.8185370000001, 41.008341], [-95.8183790000001, 41.008529], [-95.8181140000002, 41.008707], [-95.8178770000002, 41.0088039999998], [-95.817137, 41.00881], [-95.8158390000001, 41.0088089999999], [-95.815024, 41.0088289999999], [-95.8146770000001, 41.008836], [-95.8141700000001, 41.0089859999998], [-95.81394, 41.008889]]
13
+
14
+ @in_points = [[-95.8169174194336, 41.0077548921441], [-95.8169174194336, 41.0065242578572], [-95.8161449432373, 41.0053259865994], [-95.8147716522217, 41.0043543993136], [-95.8134412765503, 41.0042248532598], [-95.8128833770752, 41.0051316702882], [-95.812668800354, 41.0062327884756], [-95.8130550384521, 41.0073015032386], [-95.8149433135986, 41.0080787394523], [-95.8169174194336, 41.0077548921441], [-95.8176898956299, 41.0056498458448], [-95.8179044723511, 41.0042572397971], [-95.8179044723511, 41.0032856367545], [-95.817174911499, 41.0025731187526], [-95.8152008056641, 41.0024111817688], [-95.8140420913696, 41.0028322170991], [-95.81627368927, 41.0046134906571], [-95.8176898956299, 41.0056498458448], [-95.8176898956299, 41.0056498458448], [-95.8179044723511, 41.0042572397971], [-95.8179044723511, 41.0032856367545], [-95.817174911499, 41.0025731187526], [-95.8152008056641, 41.0024111817688], [-95.8140420913696, 41.0028322170991], [-95.81627368927, 41.0046134906571], [-95.8176898956299, 41.0056498458448], [-95.8176898956299, 41.0056498458448], [-95.8179044723511, 41.0042572397971], [-95.8179044723511, 41.0032856367545], [-95.817174911499, 41.0025731187526], [-95.8152008056641, 41.0024111817688], [-95.8140420913696, 41.0028322170991], [-95.81627368927, 41.0046134906571], [-95.8176898956299, 41.0056498458448]]
15
+
16
+ @out_points = [[-95.8193635940552, 41.0129038758068], [-95.8218097686768, 41.0130657870063], [-95.8228826522827, 41.0119000174887], [-95.8237838745117, 41.0105399269802], [-95.8245992660522, 41.0094388807662], [-95.8248996734619, 41.0079168159972], [-95.8250713348389, 41.0057793890973], [-95.8250713348389, 41.0039009870114], [-95.8233976364136, 41.0047430359468], [-95.8213806152344, 41.0071071927528], [-95.8201789855957, 41.0094388807662], [-95.8179903030396, 41.0117057205636], [-95.8126258850098, 41.0110256768135], [-95.808162689209, 41.0107666106814], [-95.8079051971436, 41.0123209921941], [-95.8193635940552, 41.0129038758068], [-95.8236122131348, 41.003091314427], [-95.8249855041504, 41.0019253684299], [-95.8249855041504, 40.9997877471958], [-95.8235263824463, 40.9977796156103], [-95.8193635940552, 40.9971642082001], [-95.8149433135986, 40.9953179514964], [-95.8091926574707, 40.9967431366616], [-95.8089351654053, 41.0000468564923], [-95.8184623718262, 41.0002087992855], [-95.8212089538574, 41.0019253684299], [-95.8236122131348, 41.003091314427], [-95.8074331283569, 41.0099894061731], [-95.8079051971436, 41.0069776521105], [-95.8079051971436, 41.0044839451126], [-95.8078193664551, 41.0022168568629], [-95.8072185516357, 40.9995286368806], [-95.8069610595703, 40.9978120053149], [-95.8051586151123, 40.9979415639739], [-95.8033990859985, 40.9988808566362], [-95.8033990859985, 41.0025731187526], [-95.8074331283569, 41.0099894061731]]
17
+
18
+ @ring = LinearRing.from_coordinates(@poly_points)
19
+ # @polygon = Polygon.from_linear_rings([@ring])
20
+ end
21
+
22
+ def test_in_points
23
+ @in_points.each_with_index do |coord, i|
24
+ point = Point.from_coordinates(coord)
25
+ assert_equal true, @ring.fast_contains?(point), "point with index #{i} should be in the ring"
26
+ end
27
+ end
28
+
29
+ def test_out_points
30
+ @out_points.each_with_index do |coord, i|
31
+ point = Point.from_coordinates(coord)
32
+ assert_equal false, @ring.fast_contains?(point), "point with index #{i} should not be in the ring"
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'test/unit'
4
+ require 'geo_ruby'
5
+ require "#{File.dirname(__FILE__)}/../lib/georuby-extras"
6
+
7
+ class GeoHashNativeTest < Test::Unit::TestCase
8
+
9
+ include GeoRuby::SimpleFeatures
10
+
11
+ def setup
12
+ @home = Point.from_lon_lat(-76.511,39.024)
13
+ @nyc = Point.from_lon_lat(-74,40.6)
14
+ end
15
+
16
+ def test_distance
17
+ assert_in_delta 277195.5104, @home.ellipsoidal_distance(@nyc), 0.001
18
+ end
19
+
20
+ def test_orig_distance
21
+ assert_in_delta 277195.5104, @home.orig_ellipsoidal_distance(@nyc), 0.001
22
+ end
23
+
24
+ def test_bearing_from_point
25
+ dest = @home.point_at_bearing_and_distance(91.0, 130000.0)
26
+ assert_in_delta -75.0106, dest.x, 0.0001
27
+ assert_in_delta 38.9939, dest.y, 0.0001
28
+ end
29
+
30
+ # This test is basically identical to those in georuby; to confirm compatibility
31
+ def test_point_distance
32
+ point1 = Point.from_x_y(0,0)
33
+ point2 = Point.from_x_y(3,4)
34
+ assert_equal(5,point1.euclidian_distance(point2))
35
+
36
+ assert_in_delta(554058.924,point1.ellipsoidal_distance(point2),0.001)
37
+ assert_in_delta(554058.924,point1.orig_ellipsoidal_distance(point2),0.001)
38
+
39
+ assert_in_delta(555811.68,point1.spherical_distance(point2),0.01)
40
+ end
41
+
42
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: griffordson-georuby-extras
3
+ version: !ruby/object:Gem::Version
4
+ hash: 7
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 6
9
+ - 0
10
+ version: 0.6.0
11
+ platform: ruby
12
+ authors:
13
+ - David Troy
14
+ - Matt Griffith
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-06-30 00:00:00 -05:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: GeoRuby
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 31
31
+ segments:
32
+ - 1
33
+ - 2
34
+ - 0
35
+ version: 1.2.0
36
+ type: :runtime
37
+ version_requirements: *id001
38
+ description: Provides native implementations of Vincenty ellipsoidal functions and a native implementation of a ray casting algorithm to detect if a point is contained in a polygon.
39
+ email: matt@griffith.com
40
+ executables: []
41
+
42
+ extensions:
43
+ - ext/extconf.rb
44
+ extra_rdoc_files:
45
+ - Manifest.txt
46
+ - README
47
+ - History.txt
48
+ files:
49
+ - ext/extconf.rb
50
+ - ext/vincenty.c
51
+ - lib/georuby-extras.rb
52
+ - ext/pnpoly.c
53
+ - ext/pnpoly.h
54
+ - Manifest.txt
55
+ - README
56
+ - History.txt
57
+ - test/test_vincenty.rb
58
+ - test/test_pnpoly.rb
59
+ has_rdoc: true
60
+ homepage: http://github.com/griffordson/georuby-extras
61
+ licenses: []
62
+
63
+ post_install_message:
64
+ rdoc_options:
65
+ - --main
66
+ - README
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ hash: 3
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ requirements: []
88
+
89
+ rubyforge_project:
90
+ rubygems_version: 1.3.7
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: Native extensions and extra functions for the GeoRuby library.
94
+ test_files:
95
+ - test/test_vincenty.rb
96
+ - test/test_pnpoly.rb