Module: KmlPolygon
- Extended by:
- KmlPolygon
- Includes:
- Math
- Included in:
- KmlPolygon
- Defined in:
- lib/kml_polygon.rb,
lib/kml_polygon/version.rb
Overview
require ‘kml_polygon/version’
Constant Summary collapse
- DEGREES =
constant to convert to degrees
180.0 / PI
- RADIANS =
constant to convert to radians
PI / 180.0
- EARTH_MEAN_RADIUS =
Mean Radius of Earth, radius
6378.1 * 1000.0
- VERSION =
"2.0.2"
Instance Method Summary collapse
-
#kml_regular_polygon(longitude, latitude, radius, segments = 20, rotate = 0) ⇒ Object
kml_regular_polygon - Regular polygon.
-
#kml_star(longitude, latitude, radius, inner_radius, segments = 10, rotate = 0) ⇒ Object
kml_star - Make a “star” or “burst” pattern.
-
#points_to_kml(points) ⇒ Object
Output points formatted as a KML string.
-
#rotate_point(vector, point, phi) ⇒ Object
rotate point around unit vector by phi radians blog.modp.com/2007/09/rotating-point-around-vector.html.
-
#spoints(longitude, latitude, radius, sides, rotate = 0) ⇒ Object
spoints – get raw list of points in longitude,latitude format.
-
#to_cart(longitude, latitude) ⇒ Object
convert longitude, latitude IN RADIANS to (x,y,z).
-
#to_earth(p) ⇒ Object
Convert (x,y,z) on unit sphere back to (longitude, latitude).
Instance Method Details
#kml_regular_polygon(longitude, latitude, radius, segments = 20, rotate = 0) ⇒ Object
kml_regular_polygon - Regular polygon
(longitude, latitude) - center point in decimal degrees
radius - radius in meters
segments - number of sides, > 20 looks like a circle (optional, default: 20)
rotate - rotate polygon by number of degrees (optional, default: 0)
Returns a string suitable for adding into a KML file.
153 154 155 |
# File 'lib/kml_polygon.rb', line 153 def kml_regular_polygon(longitude, latitude, radius, segments=20, rotate=0) points_to_kml(spoints(longitude, latitude, radius, segments, rotate)) end |
#kml_star(longitude, latitude, radius, inner_radius, segments = 10, rotate = 0) ⇒ Object
kml_star - Make a “star” or “burst” pattern
(longitude, latitude) - center point in decimal degrees
radius - radius in meters
innner_radius - radius in meters, typically < outer_radius
segments - number of "points" on the star (optional, default: 10)
rotate - rotate polygon by number of degrees (optional, default: 0)
Returns a string suitable for adding into a KML file.
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/kml_polygon.rb', line 168 def kml_star(longitude, latitude, radius, inner_radius, segments=10, rotate=0) outer_points = spoints(longitude, latitude, radius, segments, rotate) inner_points = spoints(longitude, latitude, inner_radius, segments, rotate + 180.0 / segments) # interweave the radius and inner_radius points # I'm sure there is a better way points = [] for point in 0...outer_points.length points << outer_points[point] points << inner_points[point] end # MTB - Drop the last overlapping point leaving start and end points connecting # (resulting output differs from orig, but is more correct) points.pop points_to_kml(points) end |
#points_to_kml(points) ⇒ Object
Output points formatted as a KML string
You may want to edit this function to change “extrude” and other XML nodes.
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/kml_polygon.rb', line 127 def points_to_kml(points) kml_string = "<Polygon>\n" kml_string << " <outerBoundaryIs><LinearRing><coordinates>\n" points.each do |point| kml_string << " " << point[0].to_s << "," << point[1].to_s << "\n" end kml_string << " </coordinates></LinearRing></outerBoundaryIs>\n" kml_string << "</Polygon>\n" # kml_string << " <extrude>1</extrude>\sides" # kml_string << " <altitudeMode>clampToGround</altitudeMode>\sides" end |
#rotate_point(vector, point, phi) ⇒ Object
rotate point around unit vector by phi radians blog.modp.com/2007/09/rotating-point-around-vector.html
109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/kml_polygon.rb', line 109 def rotate_point(vector, point, phi) # remap vector for sanity u, v, w, x, y, z = vector[0], vector[1], vector[2], point[0], point[1], point[2] a = u*x + v*y + w*z d = Math.cos(phi) e = Math.sin(phi) [(a*u + (x - a*u)*d + (v*z - w*y) * e), (a*v + (y - a*v)*d + (w*x - u*z) * e), (a*w + (z - a*w)*d + (u*y - v*x) * e)] end |
#spoints(longitude, latitude, radius, sides, rotate = 0) ⇒ Object
spoints – get raw list of points in longitude,latitude format
radius: radius of polygon in meters sides: number of sides rotate: rotate polygon by number of degrees
Returns a list of points comprising the object
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/kml_polygon.rb', line 85 def spoints(longitude, latitude, radius, sides, rotate=0) rotate_radians = rotate * RADIANS # compute longitude degrees (in radians) at given latitude r = radius / (EARTH_MEAN_RADIUS * Math.cos(latitude * RADIANS)) vector = to_cart(longitude * RADIANS, latitude * RADIANS) point = to_cart(longitude * RADIANS + r, latitude * RADIANS) points = [] for side in 0...sides points << to_earth(rotate_point(vector, point, rotate_radians + (2.0 * PI/sides)*side)) end # Connect to starting point exactly # Not sure if required, but seems to help when the polygon is not filled points << points[0] end |
#to_cart(longitude, latitude) ⇒ Object
convert longitude, latitude IN RADIANS to (x,y,z)
68 69 70 71 72 73 74 75 |
# File 'lib/kml_polygon.rb', line 68 def to_cart(longitude, latitude) theta = longitude # spherical coordinate use "co-latitude", not "latitude" # lattiude = [-90, 90] with 0 at equator # co-latitude = [0, 180] with 0 at north pole phi = PI / 2.0 - latitude [Math.cos(theta) * Math.sin(phi), Math.sin(theta) * Math.sin(phi), Math.cos(phi)] end |
#to_earth(p) ⇒ Object
Convert (x,y,z) on unit sphere back to (longitude, latitude)
p is vector of three elements
56 57 58 59 60 61 62 63 |
# File 'lib/kml_polygon.rb', line 56 def to_earth(p) p[0] == 0.0 ? longitude = PI / 2.0 :longitude = Math.atan(p[1]/p[0]) latitude = PI / 2.0 - Math.acos(p[2]) # select correct branch of arctan (p[1] <= 0.0 ? longitude = -(PI - longitude) : longitude = PI + longitude) if p[0] < 0.0 [longitude * DEGREES, latitude * DEGREES] end |