diff --git a/404.html b/404.html new file mode 100644 index 0000000..0698648 --- /dev/null +++ b/404.html @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + geo 0.7.5 + + + + + + + + + + +
+

+ 404 Not Found +

+ +

+ This page is unavailable in this version of the API docs. +

+ +

+ You can use the sidebar to search for your page, or try a different + Crystal version. +

+ +
+ + diff --git a/Geo.html b/Geo.html new file mode 100644 index 0000000..82a0961 --- /dev/null +++ b/Geo.html @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + Geo - geo 0.7.5 + + + + + + + + + + +
+

+ + module Geo + +

+ + + + + + + + + + + + + + + + + + +

+ + + + Defined in: +

+ + + lib/geo_bearing/src/geo_bearing.cr + +
+ + + geo.cr + +
+ + + geo/bearing.cr + +
+ + + geo/coord.cr + +
+ + + geo/distance.cr + +
+ + + geo/polygon.cr + +
+ + + geo/utils.cr + +
+ + + + + +

+ + + + Constant Summary +

+ +
+ +
+ DISTANCE_UNITS = Haversine::FACTORS.keys +
+ + +
+ VERSION = {{ (`shards version /__w/geo/geo/src`).chomp.stringify }} +
+ + +
+ + + + + + + + + + + +
+ +
+ + + + + + + + + +
+ + + diff --git a/Geo/Coord.html b/Geo/Coord.html new file mode 100644 index 0000000..ebd5ce3 --- /dev/null +++ b/Geo/Coord.html @@ -0,0 +1,937 @@ + + + + + + + + + + + + + + + + + Geo::Coord - geo 0.7.5 + + + + + + + + + + +
+

+ + struct Geo::Coord + +

+ + + + + + + +

+ + + + Overview +

+ +

A Coord is a point in geographical coordinates: latitude and longitude.

+ + + + + +

+ + + + Included Modules +

+ + + + + + + + + + + +

+ + + + Defined in: +

+ + + geo/bearing.cr + +
+ + + geo/coord.cr + +
+ + + geo/distance.cr + +
+ + + + + +

+ + + + Constant Summary +

+ +
+ +
+ DIRECTIVES = {/%(#{FLOATUFLAGS})?lats/ => ->(m : Regex::MatchData) do + "%<lats>#{m[1]? || "0."}f" +end, "%latm" => "%<latm>i", /%(#{INTFLAGS})?latds/ => ->(m : Regex::MatchData) do + "%<latds>#{m[1]}i" +end, "%latd" => "%<latd>i", "%lath" => "%<lath>s", /%(#{FLOATFLAGS})?lat/ => ->(m : Regex::MatchData) do + "%<lat>#{m[1]}f" +end, /%(#{FLOATUFLAGS})?lngs/ => ->(m : Regex::MatchData) do + "%<lngs>#{m[1]? || "0."}f" +end, "%lngm" => "%<lngm>i", /%(#{INTFLAGS})?lngds/ => ->(m : Regex::MatchData) do + "%<lngds>#{m[1]}i" +end, "%lngd" => "%<lngd>i", "%lngh" => "%<lngh>s", /%(#{FLOATFLAGS})?lng/ => ->(m : Regex::MatchData) do + "%<lng>#{m[1]}f" +end} +
+ + +
+ FLOATFLAGS = /\+?#{FLOATUFLAGS}?/ +
+ + +
+ FLOATUFLAGS = /0\.\d+/ +
+ + +
+ INTFLAGS = /\+?/ +
+ + +
+ + + +

+ + + + Constructors +

+ + + + + + + + +

+ + + + Instance Method Summary +

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +

+ + + + Constructor Detail +

+ +
+
+ + def self.new(lat : Number, lng : Number) + + # +
+ +
+
+ +
+
+ + + + + + + + +

+ + + + Instance Method Detail +

+ +
+
+ + def <=>(other : Geo::Coord) + + # +
+ +
+ +
+ Description copied from module Comparable(Geo::Coord) +
+ +

The comparison operator. Returns 0 if the two objects are equal, +a negative number if this object is considered less than other, +a positive number if this object is considered greater than other, +or nil if the two objects are not comparable.

+

Subclasses define this method to provide class-specific ordering.

+

The comparison operator is usually used to sort values:

+
# Sort in a descending way:
+[3, 1, 2].sort { |x, y| y <=> x } # => [3, 2, 1]
+
+# Sort in an ascending way:
+[3, 1, 2].sort { |x, y| x <=> y } # => [1, 2, 3]
+
+ +
+
+ +
+
+ +
+
+ + def bearing(to : Geo::Coord, final = false) : Float64 + + # +
+ +
+ +

Calculates initial and final bearings between two points using great-circle distance formulas

+
+ +
+
+ +
+
+ +
+
+ + def between?(p1 : Geo::Coord, p2 : Geo::Coord) + + # +
+ +
+
+ +
+
+ +
+
+ + def destination(distance : Number, bearing : Number, unit : Symbol = :kilometers) : Geo::Coord + + # +
+ +
+ +

Calculates the location of a destination point

+
+ +
+
+ +
+
+ +
+
+ + def distance(other : Geo::Coord) : Haversine::Distance + + # +
+ +
+ +

Calculates distance to other. +Haversine formula is used.

+
+ +
+
+ +
+
+ +
+
+ + def geohash(precision = 12) + + # +
+ +
+ +

Returns a geohash representing coordinates.

+
+ +
+
+ +
+
+ +
+
+ + def lat : Float32 | Float64 | Int32 + + # +
+ +
+
+ +
+
+ +
+
+ + def latd : Int32 + + # +
+ +
+ +

Returns latitude degrees

+
+ +
+
+ +
+
+ +
+
+ + def latds + + # +
+ +
+
+ +
+
+ +
+
+ + def lath : String + + # +
+ +
+ +

Returns latitude hemisphere

+
+ +
+
+ +
+
+ +
+
+ + def latm : Int32 + + # +
+ +
+ +

Returns latitude minutes

+
+ +
+
+ +
+
+ +
+
+ + def lats : Number + + # +
+ +
+ +

Returns latitude seconds

+
+ +
+
+ +
+
+ +
+
+ + def ll + + # +
+ +
+
+ +
+
+ +
+
+ + def lng : Float32 | Float64 | Int32 + + # +
+ +
+
+ +
+
+ +
+
+ + def lngd : Int32 + + # +
+ +
+ +

Returns longitude degrees

+
+ +
+
+ +
+
+ +
+
+ + def lngds + + # +
+ +
+
+ +
+
+ +
+
+ + def lngh : String + + # +
+ +
+ +

Returns longitude hemisphere

+
+ +
+
+ +
+
+ +
+
+ + def lngm : Int32 + + # +
+ +
+ +

Returns longitude minutes

+
+ +
+
+ +
+
+ +
+
+ + def lngs : Number + + # +
+ +
+ +

Returns longitude seconds

+
+ +
+
+ +
+
+ +
+
+ + def strfcoord(formatstr) : String + + # +
+ +
+ +

Formats coordinates according to directives in formatstr.

+

Each directive starts with % and can contain some modifiers before its name.

+

Acceptable modifiers:

+
    +
  • unsigned integers: none;
  • +
  • signed integers: + for mandatory sign printing;
  • +
  • floats: same as integers and number of digits modifier, like 0.3.
  • +
+

List of directives:

+
    +
  • %lat - Full latitude, floating point, signed
  • +
  • %latds - Latitude degrees, integer, signed
  • +
  • %latd - Latitude degrees, integer, unsigned
  • +
  • %latm - Latitude minutes, integer, unsigned
  • +
  • %lats - Latitude seconds, floating point, unsigned
  • +
  • %lath - Latitude hemisphere, "N" or "S"
  • +
  • %lng - Full longitude, floating point, signed
  • +
  • %lngds - Longitude degrees, integer, signed
  • +
  • %lngd - Longitude degrees, integer, unsigned
  • +
  • %lngm - Longitude minutes, integer, unsigned
  • +
  • #lngs - Longitude seconds, floating point, unsigned
  • +
  • `%lngh`` - Longitude hemisphere, "E" or "W"
  • +
+

Examples:

+
g = Geo::Coord.new(50.004444, 36.231389)
+g.strfcoord('%+lat, %+lng')
+# => "+50.004444, +36.231389"
+g.strfcoord("%latd°%latm'%lath -- %lngd°%lngm'%lngh")
+# => "50°0'N -- 36°13'E"
+

#strfcoord handles seconds rounding implicitly:

+
pos = Geo::Coord.new(0.033333, 91.333333)
+pos.strfcoord('%latd %latm %0.5lats') # => "0 1 59.99880"
+pos.strfcoord('%latd %latm %lats')  # => "0 2 0"
+
+ +
+
+ +
+
+ +
+
+ + def to_geojson : GeoJSON::Coordinates + + # +
+ +
+
+ +
+
+ +
+
+ + def to_s(io) + + # +
+ +
+ +

Returns a string representing coordinates.

+
g.to_s             # => "50°0'16\"N 36°13'53\"E"
+g.to_s(dms: false) # => "50.004444,36.231389"
+
+ +
+
+ +
+
+ + + +
+ + + diff --git a/Geo/Coord/Number.html b/Geo/Coord/Number.html new file mode 100644 index 0000000..b8d3893 --- /dev/null +++ b/Geo/Coord/Number.html @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + Geo::Coord::Number - geo 0.7.5 + + + + + + + + + + +
+

+ + alias Geo::Coord::Number + +

+ + + + + + + +

+ + + + Alias Definition +

+ Float32 | Float64 | Int32 + + + + + + + + + + + + +

+ + + + Defined in: +

+ + + geo/coord.cr + +
+ + + + + + + + + + + + + + +
+ +
+ + + + + + + + + +
+ + + diff --git a/Geo/Polygon.html b/Geo/Polygon.html new file mode 100644 index 0000000..afcd8c5 --- /dev/null +++ b/Geo/Polygon.html @@ -0,0 +1,525 @@ + + + + + + + + + + + + + + + + + Geo::Polygon - geo 0.7.5 + + + + + + + + + + +
+

+ + struct Geo::Polygon + +

+ + + + + + + +

+ + + + Overview +

+ +

A Polygon is a fixed-size, immutable, stack-allocated sequence of Geo::Coord. +Coordinates are in lexicographical order. +Additionally, polygons form a closed loop and define a filled region.

+ + + + + +

+ + + + Included Modules +

+ + + + + + + + + + + +

+ + + + Defined in: +

+ + + geo/polygon.cr + +
+ + + + + + +

+ + + + Constructors +

+ + + + + + + + +

+ + + + Instance Method Summary +

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +

+ + + + Constructor Detail +

+ +
+
+ + def self.new(coords : Array(Geo::Coord), convex_hull = false) + + # +
+ +
+
+ +
+
+ + + + + + + + +

+ + + + Instance Method Detail +

+ +
+
+ + def ==(other : Geo::Polygon) : Bool + + # +
+ +
+
+ +
+
+ +
+
+ + def area + + # +
+ +
+ +

Return the approximate signed geodesic area of the polygon in square meters.

+
+ +
+
+ +
+
+ +
+
+ + def centroid : Geo::Coord + + # +
+ +
+
+ +
+
+ +
+
+ + def contains?(coord : Geo::Coord) : Bool + + # +
+ +
+
+ +
+
+ +
+
+ + def coords : Array(Geo::Coord) + + # +
+ +
+
+ +
+
+ +
+
+ + def size : Int32 + + # +
+ +
+ +
+ Description copied from module Indexable(Geo::Coord) +
+ +

Returns the number of elements in this container.

+
+ +
+
+ +
+
+ +
+
+ + def to_geojson : GeoJSON::Polygon + + # +
+ +
+
+ +
+
+ +
+
+ + def unsafe_fetch(index : Int) + + # +
+ +
+ +
+ Description copied from module Indexable(Geo::Coord) +
+ +

Returns the element at the given index, without doing any bounds check.

+

Indexable makes sure to invoke this method with index in 0...size, +so converting negative indices to positive ones is not needed here.

+

Clients never invoke this method directly. Instead, they access +elements with #[](index) and #[]?(index).

+

This method should only be directly invoked if you are absolutely +sure the index is in bounds, to avoid a bounds check for a small boost +of performance.

+
+ +
+
+ +
+
+ + + +
+ + + diff --git a/Geo/Utils.html b/Geo/Utils.html new file mode 100644 index 0000000..e7b7891 --- /dev/null +++ b/Geo/Utils.html @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + Geo::Utils - geo 0.7.5 + + + + + + + + + + +
+

+ + module Geo::Utils + +

+ + + + + + + + + + + +

+ + + + Extended Modules +

+ + + + + + + + + +

+ + + + Defined in: +

+ + + geo/utils.cr + +
+ + + + + + + + + + + + +

+ + + + Instance Method Summary +

+ + + + +
+ +
+ + + + + + + + +

+ + + + Instance Method Detail +

+ +
+
+ + def orientation(p : Geo::Coord, q : Geo::Coord, r : Geo::Coord) + + # +
+ +
+ +

Orientation of ordered triplet (p, q, r)

+

Orientation of an ordered triplet of points in the plane can be

+
    +
  • counterclockwise
  • +
  • clockwise
  • +
  • colinear
  • +
+

The function returns following values +0 --> p, q and r are colinear +1 --> Clockwise +2 --> Counterclockwise

+
+ +
+
+ +
+
+ + + +
+ + + diff --git a/css/style.css b/css/style.css new file mode 100644 index 0000000..3d0a8a5 --- /dev/null +++ b/css/style.css @@ -0,0 +1,980 @@ +:root { + color-scheme: light dark; +} + +html, body { + background: #FFFFFF; + position: relative; + margin: 0; + padding: 0; + width: 100%; + height: 100%; + overflow: hidden; +} + +body { + font-family: "Avenir", "Tahoma", "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; + color: #333; + line-height: 1.5; +} + +a { + color: #263F6C; +} + +a:visited { + color: #112750; +} + +h1, h2, h3, h4, h5, h6 { + margin: 35px 0 25px; + color: #444444; +} + +h1.type-name { + color: #47266E; + margin: 20px 0 30px; + background-color: #F8F8F8; + padding: 10px 12px; + border: 1px solid #EBEBEB; + border-radius: 2px; +} + +h2 { + border-bottom: 1px solid #E6E6E6; + padding-bottom: 5px; +} + +body { + display: flex; +} + +.sidebar, .main-content { + overflow: auto; +} + +.sidebar { + width: 30em; + color: #F8F4FD; + background-color: #2E1052; + padding: 0 0 30px; + box-shadow: inset -3px 0 4px rgba(0,0,0,.35); + line-height: 1.2; + z-index: 0; +} + +.sidebar .search-box { + padding: 13px 9px; +} + +.sidebar input { + display: block; + box-sizing: border-box; + margin: 0; + padding: 5px; + font: inherit; + font-family: inherit; + line-height: 1.2; + width: 100%; + border: 0; + outline: 0; + border-radius: 2px; + box-shadow: 0px 3px 5px rgba(0,0,0,.25); + transition: box-shadow .12s; +} + +.sidebar input:focus { + box-shadow: 0px 5px 6px rgba(0,0,0,.5); +} + +.sidebar input::-webkit-input-placeholder { /* Chrome/Opera/Safari */ + color: #757575; + font-size: 14px; + text-indent: 2px; +} + +.sidebar input::-moz-placeholder { /* Firefox 19+ */ + color: #757575; + font-size: 14px; + text-indent: 2px; +} + +.sidebar input:-ms-input-placeholder { /* IE 10+ */ + color: #757575; + font-size: 14px; + text-indent: 2px; +} + +.sidebar input:-moz-placeholder { /* Firefox 18- */ + color: #757575; + font-size: 14px; + text-indent: 2px; +} + +.project-summary { + padding: 9px 15px 30px 30px; +} + +.project-name { + font-size: 1.4rem; + margin: 0; + color: #f4f4f4; + font-weight: 600; +} + +.project-version { + margin-top: 5px; + display: inline-block; + position: relative; +} + +.project-version > form::after { + position: absolute; + right: 0; + top: 0; + content: "\25BC"; + font-size: .6em; + line-height: 1.2rem; + z-index: -1; +} + +.project-versions-nav { + cursor: pointer; + margin: 0; + padding: 0 .9em 0 0; + border: none; + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + background-color: transparent; + color: inherit; + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +.project-versions-nav:focus { + outline: none; +} + +.project-versions-nav > option { + color: initial; +} + +.sidebar ul { + margin: 0; + padding: 0; + list-style: none outside; +} + +.sidebar li { + display: block; + position: relative; +} + +.types-list li.hide { + display: none; +} + +.sidebar a { + text-decoration: none; + color: inherit; + transition: color .14s; +} +.types-list a { + display: block; + padding: 5px 15px 5px 30px; +} + +.types-list { + display: block; +} + +.sidebar a:focus { + outline: 1px solid #D1B7F1; +} + +.types-list a { + padding: 5px 15px 5px 30px; +} + +.sidebar .current > a, +.sidebar a:hover { + color: #866BA6; +} + +.types-list li ul { + overflow: hidden; + height: 0; + max-height: 0; + transition: 1s ease-in-out; +} + +.types-list li.parent { + padding-left: 30px; +} + +.types-list li.parent::before { + box-sizing: border-box; + content: "▼"; + display: block; + width: 30px; + height: 30px; + position: absolute; + top: 0; + left: 0; + text-align: center; + color: white; + font-size: 8px; + line-height: 30px; + transform: rotateZ(-90deg); + cursor: pointer; + transition: .2s linear; +} + + +.types-list li.parent > a { + padding-left: 0; +} + +.types-list li.parent.open::before { + transform: rotateZ(0); +} + +.types-list li.open > ul { + height: auto; + max-height: 1000em; +} + +.main-content { + padding: 0 30px 30px 30px; + width: 100%; +} + +.kind { + font-size: 60%; + color: #866BA6; +} + +.superclass-hierarchy { + margin: -15px 0 30px 0; + padding: 0; + list-style: none outside; + font-size: 80%; +} + +.superclass-hierarchy .superclass { + display: inline-block; + margin: 0 7px 0 0; + padding: 0; +} + +.superclass-hierarchy .superclass + .superclass::before { + content: "<"; + margin-right: 7px; +} + +.other-types-list li { + display: inline-block; +} + +.other-types-list, +.list-summary { + margin: 0 0 30px 0; + padding: 0; + list-style: none outside; +} + +.entry-const { + font-family: Menlo, Monaco, Consolas, 'Courier New', Courier, monospace; +} + +.entry-const code { + white-space: pre-wrap; +} + +.entry-summary { + padding-bottom: 4px; +} + +.superclass-hierarchy .superclass a, +.other-type a, +.entry-summary .signature { + padding: 4px 8px; + margin-bottom: 4px; + display: inline-block; + background-color: #f8f8f8; + color: #47266E; + border: 1px solid #f0f0f0; + text-decoration: none; + border-radius: 3px; + font-family: Menlo, Monaco, Consolas, 'Courier New', Courier, monospace; + transition: background .15s, border-color .15s; +} + +.superclass-hierarchy .superclass a:hover, +.other-type a:hover, +.entry-summary .signature:hover { + background: #D5CAE3; + border-color: #624288; +} + +.entry-summary .summary { + padding-left: 32px; +} + +.entry-summary .summary p { + margin: 12px 0 16px; +} + +.entry-summary a { + text-decoration: none; +} + +.entry-detail { + padding: 30px 0; +} + +.entry-detail .signature { + position: relative; + padding: 5px 15px; + margin-bottom: 10px; + display: block; + border-radius: 5px; + background-color: #f8f8f8; + color: #47266E; + border: 1px solid #f0f0f0; + font-family: Menlo, Monaco, Consolas, 'Courier New', Courier, monospace; + transition: .2s ease-in-out; +} + +.entry-detail:target .signature { + background-color: #D5CAE3; + border: 1px solid #624288; +} + +.entry-detail .signature .method-permalink { + position: absolute; + top: 0; + left: -35px; + padding: 5px 15px; + text-decoration: none; + font-weight: bold; + color: #624288; + opacity: .4; + transition: opacity .2s; +} + +.entry-detail .signature .method-permalink:hover { + opacity: 1; +} + +.entry-detail:target .signature .method-permalink { + opacity: 1; +} + +.methods-inherited { + padding-right: 10%; + line-height: 1.5em; +} + +.methods-inherited h3 { + margin-bottom: 4px; +} + +.methods-inherited a { + display: inline-block; + text-decoration: none; + color: #47266E; +} + +.methods-inherited a:hover { + text-decoration: underline; + color: #6C518B; +} + +.methods-inherited .tooltip>span { + background: #D5CAE3; + padding: 4px 8px; + border-radius: 3px; + margin: -4px -8px; +} + +.methods-inherited .tooltip * { + color: #47266E; +} + +pre { + padding: 10px 20px; + margin-top: 4px; + border-radius: 3px; + line-height: 1.45; + overflow: auto; + color: #333; + background: #fdfdfd; + font-size: 14px; + border: 1px solid #eee; +} + +code { + font-family: Menlo, Monaco, Consolas, 'Courier New', Courier, monospace; +} + +:not(pre) > code { + background-color: rgba(40,35,30,0.05); + padding: 0.2em 0.4em; + font-size: 85%; + border-radius: 3px; +} + +span.flag { + padding: 2px 4px 1px; + border-radius: 3px; + margin-right: 3px; + font-size: 11px; + border: 1px solid transparent; +} + +span.flag.orange { + background-color: #EE8737; + color: #FCEBDD; + border-color: #EB7317; +} + +span.flag.yellow { + background-color: #E4B91C; + color: #FCF8E8; + border-color: #B69115; +} + +span.flag.green { + background-color: #469C14; + color: #E2F9D3; + border-color: #34700E; +} + +span.flag.red { + background-color: #BF1919; + color: #F9ECEC; + border-color: #822C2C; +} + +span.flag.purple { + background-color: #2E1052; + color: #ECE1F9; + border-color: #1F0B37; +} + +span.flag.lime { + background-color: #a3ff00; + color: #222222; + border-color: #00ff1e; +} + +.tooltip>span { + position: absolute; + opacity: 0; + display: none; + pointer-events: none; +} + +.tooltip:hover>span { + display: inline-block; + opacity: 1; +} + +.c { + color: #969896; +} + +.n { + color: #0086b3; +} + +.t { + color: #0086b3; +} + +.s { + color: #183691; +} + +.i { + color: #7f5030; +} + +.k { + color: #a71d5d; +} + +.o { + color: #a71d5d; +} + +.m { + color: #795da3; +} + +.hidden { + display: none; +} +.search-results { + font-size: 90%; + line-height: 1.3; +} + +.search-results mark { + color: inherit; + background: transparent; + font-weight: bold; +} +.search-result { + padding: 5px 8px 5px 5px; + cursor: pointer; + border-left: 5px solid transparent; + transform: translateX(-3px); + transition: all .2s, background-color 0s, border .02s; + min-height: 3.2em; +} +.search-result.current { + border-left-color: #ddd; + background-color: rgba(200,200,200,0.4); + transform: translateX(0); + transition: all .2s, background-color .5s, border 0s; +} +.search-result.current:hover, +.search-result.current:focus { + border-left-color: #866BA6; +} +.search-result:not(.current):nth-child(2n) { + background-color: rgba(255,255,255,.06); +} +.search-result__title { + font-size: 105%; + word-break: break-all; + line-height: 1.1; + padding: 3px 0; +} +.search-result__title strong { + font-weight: normal; +} +.search-results .search-result__title > a { + padding: 0; + display: block; +} +.search-result__title > a > .args { + color: #dddddd; + font-weight: 300; + transition: inherit; + font-size: 88%; + line-height: 1.2; + letter-spacing: -.02em; +} +.search-result__title > a > .args * { + color: inherit; +} + +.search-result a, +.search-result a:hover { + color: inherit; +} +.search-result:not(.current):hover .search-result__title > a, +.search-result:not(.current):focus .search-result__title > a, +.search-result__title > a:focus { + color: #866BA6; +} +.search-result:not(.current):hover .args, +.search-result:not(.current):focus .args { + color: #6a5a7d; +} + +.search-result__type { + color: #e8e8e8; + font-weight: 300; +} +.search-result__doc { + color: #bbbbbb; + font-size: 90%; +} +.search-result__doc p { + margin: 0; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + line-height: 1.2em; + max-height: 2.4em; +} + +.js-modal-visible .modal-background { + display: flex; +} +.main-content { + position: relative; +} +.modal-background { + position: absolute; + display: none; + height: 100%; + width: 100%; + background: rgba(120,120,120,.4); + z-index: 100; + align-items: center; + justify-content: center; +} +.usage-modal { + max-width: 90%; + background: #fff; + border: 2px solid #ccc; + border-radius: 9px; + padding: 5px 15px 20px; + min-width: 50%; + color: #555; + position: relative; + transform: scale(.5); + transition: transform 200ms; +} +.js-modal-visible .usage-modal { + transform: scale(1); +} +.usage-modal > .close-button { + position: absolute; + right: 15px; + top: 8px; + color: #aaa; + font-size: 27px; + cursor: pointer; +} +.usage-modal > .close-button:hover { + text-shadow: 2px 2px 2px #ccc; + color: #999; +} +.modal-title { + margin: 0; + text-align: center; + font-weight: normal; + color: #666; + border-bottom: 2px solid #ddd; + padding: 10px; +} +.usage-list { + padding: 0; + margin: 13px; +} +.usage-list > li { + padding: 5px 2px; + overflow: auto; + padding-left: 100px; + min-width: 12em; +} +.usage-modal kbd { + background: #eee; + border: 1px solid #ccc; + border-bottom-width: 2px; + border-radius: 3px; + padding: 3px 8px; + font-family: monospace; + margin-right: 2px; + display: inline-block; +} +.usage-key { + float: left; + clear: left; + margin-left: -100px; + margin-right: 12px; +} +.doc-inherited { + font-weight: bold; +} + +.anchor { + float: left; + padding-right: 4px; + margin-left: -20px; +} + +.main-content .anchor .octicon-link { + width: 16px; + height: 16px; +} + +.main-content .anchor:focus { + outline: none +} + +.main-content h1:hover .anchor, +.main-content h2:hover .anchor, +.main-content h3:hover .anchor, +.main-content h4:hover .anchor, +.main-content h5:hover .anchor, +.main-content h6:hover .anchor { + text-decoration: none +} + +.main-content h1 .octicon-link, +.main-content h2 .octicon-link, +.main-content h3 .octicon-link, +.main-content h4 .octicon-link, +.main-content h5 .octicon-link, +.main-content h6 .octicon-link { + visibility: hidden +} + +.main-content h1:hover .anchor .octicon-link, +.main-content h2:hover .anchor .octicon-link, +.main-content h3:hover .anchor .octicon-link, +.main-content h4:hover .anchor .octicon-link, +.main-content h5:hover .anchor .octicon-link, +.main-content h6:hover .anchor .octicon-link { + visibility: visible +} + +img { + max-width: 100%; +} + +table { + font-size: 14px; + display: block; + max-width: -moz-fit-content; + max-width: fit-content; + overflow-x: auto; + white-space: nowrap; + background: #fdfdfd; + text-align: center; + border: 1px solid #eee; + border-collapse: collapse; + padding: 0px 5px 0px 5px; +} + +table th { + padding: 10px; + letter-spacing: 1px; + border-bottom: 1px solid #eee; +} + +table td { + padding: 10px; +} + +#sidebar-btn { + height: 32px; + width: 32px; +} + +#sidebar-btn-label { + height: 2em; + width: 2em; +} + +#sidebar-btn, #sidebar-btn-label { + display: none; + margin: .7rem; + appearance: none; + color: black; + cursor: pointer; +} + +@media only screen and (max-width: 635px) { + .sidebar, .main-content { + /* svg size + vertical margin - .search-box padding-top */ + padding-top: calc(2em + 2 * 0.7rem - 13px); + } + + #sidebar-btn, #sidebar-btn-label { + display: block; + position: absolute; + z-index: 50; + transition-duration: 200ms; + left: 0; + } + + #sidebar-btn:not(:checked) ~ #sidebar-btn-label > .close, + #sidebar-btn:checked ~ #sidebar-btn-label > .open, + #sidebar-btn:checked ~ .main-content { + display: none; + } + + #sidebar-btn:checked { + left: calc(100% - 32px - (2 * 0.7rem)); + } + + #sidebar-btn:checked ~ #sidebar-btn-label { + color: white; + /* 100% - svg size - horizontal margin */ + left: calc(100% - 2em - (2 * 0.7rem)); + } + + #sidebar-btn~.sidebar { + width: 0%; + } + + #sidebar-btn:checked~.sidebar { + visibility: visible; + width: 100%; + } + + .sidebar { + transition-duration: 200ms; + max-width: 100vw; + visibility: hidden; + } +} + +@media (prefers-color-scheme: dark) { + html, body { + background: #1b1b1b; + } + + body { + color: white; + } + + a { + color: #8cb4ff; + } + + .main-content a:visited { + color: #5f8de3; + } + + h1, h2, h3, h4, h5, h6 { + color: white; + } + + h1.type-name { + color: white; + background-color: #202020; + border: 1px solid #353535; + } + + .project-versions-nav > option { + background-color: #222; + } + + .superclass-hierarchy .superclass a, + .superclass-hierarchy .superclass a:visited, + .other-type a, + .other-type a:visited, + .entry-summary .signature, + .entry-summary a:visited { + background-color: #202020; + color: white; + border: 1px solid #353535; + } + + .superclass-hierarchy .superclass a:hover, + .other-type a:hover, + .entry-summary .signature:hover { + background: #443d4d; + border-color: #b092d4; + } + + .kind { + color: #b092d4; + } + + .n { + color: #00ade6; + } + + .t { + color: #00ade6; + } + + .k { + color: #ff66ae; + } + + .o { + color: #ff66ae; + } + + .s { + color: #7799ff; + } + + .i { + color: #b38668; + } + + .m { + color: #b9a5d6; + } + + .c { + color: #a1a1a1; + } + + .methods-inherited a, .methods-inherited a:visited { + color: #B290D9; + } + + .methods-inherited a:hover { + color: #D4B7F4; + } + + .methods-inherited .tooltip>span { + background: #443d4d; + } + + .methods-inherited .tooltip * { + color: white; + } + + .entry-detail:target .signature { + background-color: #443d4d; + border: 1px solid #b092d4; + } + + .entry-detail .signature { + background-color: #202020; + color: white; + border: 1px solid #353535; + } + + .entry-detail .signature .method-permalink { + color: #b092d4; + } + + :not(pre)>code { + background-color: #202020; + } + + span.flag.purple { + background-color: #443d4d; + color: #ECE1F9; + border-color: #b092d4; + } + + .sidebar input::-webkit-input-placeholder { /* Chrome/Opera/Safari */ + color: white; + } + + .sidebar input::-moz-placeholder { /* Firefox 19+ */ + color: white; + } + + .sidebar input:-ms-input-placeholder { /* IE 10+ */ + color: white; + } + + .sidebar input:-moz-placeholder { /* Firefox 18- */ + color: white; + } + + pre, + table { + color: white; + background: #202020; + border: 1px solid #353535; + } + + table th { + border-bottom: 1px solid #353535; + } + + #sidebar-btn, #sidebar-btn-label { + color: white; + } +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..c360c86 --- /dev/null +++ b/index.html @@ -0,0 +1,281 @@ + + + + + + + + + + + + + + + + + geo 0.7.5 + + + + + + + + + + +
+

+Geo

+

Crystal CI +GitHub release +Docs +License

+

Geospatial primitives, algorithms, and utilities for Crystal.

+

+ +Installation

+

Add this to your application's shard.yml:

+
dependencies:
+  geo:
+    github: geocrystal/geo
+

Run shards install

+

+ +Usage

+

A Geo::Coord is a point in geographical coordinates: latitude and longitude.

+
require "geo"
+
+c = Geo::Coord.new(50.004444, 36.231389)
+
+c.strfcoord(%{%latd %latm' %0.1lats" %lath, %lngd %lngm' %0.1lngs" %lngh})
+# => "50 0' 16.0" N, 36 13' 53.0" E"
+
+c.strfcoord("%lat,%lng")
+# => "-50.004444,-36.231389"
+
+c.to_s
+# => "50°0'16"N 36°13'53"E"
+
+pos = Geo::Coord.new(50.004444, 36.231389)
+
+pos.geohash
+# => "ubcu2rnbuxcx"
+
+pos.geohash(5)
+# => "ubcu2"
+

+ +Polygon

+

A polygon represents an area enclosed by a closed path (or loop), which is defined by a series of coordinates.

+
require "geo"
+
+pos1 = Geo::Coord.new(45.3142533036254, -93.47527313511819)
+pos2 = Geo::Coord.new(45.31232182518015, -93.34893036168069)
+pos3 = Geo::Coord.new(45.23694281999268, -93.35167694371194)
+pos4 = Geo::Coord.new(45.23500870841669, -93.47801971714944)
+
+polygon = Geo::Polygon.new([pos1, pos2, pos3, pos4])
+

The Polygon in the example above consists of four sets of Geo::Coord coordinates, but notice that the first and last sets define the same location, which completes the loop. In practice, however, since polygons define closed areas, you don't need to specify the last set of coordinates. Ot will automatically complete the polygon by connecting the last location back to the first location.

+

The following example is identical to the previous one, except that the last Geo::Coord is omitted:

+
require "geo"
+
+pos1 = Geo::Coord.new(45.3142533036254, -93.47527313511819)
+pos2 = Geo::Coord.new(45.31232182518015, -93.34893036168069)
+pos3 = Geo::Coord.new(45.23694281999268, -93.35167694371194)
+
+polygon = Geo::Polygon.new([pos1, pos2, pos3])
+

Additional actions:

+
coord_inside = Geo::Coord.new(45.27428243796789, -93.41648483416066)
+coord_outside = Geo::Coord.new(45.45411010558687, -93.78151703160256)
+
+polygon.contains?(coord_inside)  # => true
+polygon.contains?(coord_outside) # => false
+
+polygon.centroid # => Geo::Coord(@lat=45.27463866133501, @lng=-93.41400121829719)
+

Additionally you can initialize polygon as convex hull from coordinates of points.

+
points = [
+  {1.0, 1.0},
+  {1.0, 0.0},
+  {1.0, -1.0},
+  {0.0, -1.0},
+  {-1.0, -1.0},
+  {-1.0, 0.0},
+  {-1.0, 1.0},
+  {0.0, 1.0},
+  {0.0, 0.0},
+].map { |point| Geo::Coord.new(point[0], point[1]) }
+
+polygon = Geo::Polygon.new(points, convex_hull: true)
+polygon.coords
+# => {-1.0, -1.0}, {1.0, -1.0}, {1.0, 1.0}, {-1.0, 1.0}, {-1.0, -1.0}
+

The convex hull is computed using the convex_hull library.

+

+ +Formatting

+

Geo::Coord#strfcoord formats coordinates according to directives.

+

Each directive starts with % and can contain some modifiers before its name.

+

Acceptable modifiers:

+ +

List of directives:

+

| Directive | Description | +| --------- | ------------------------------------------- | +| %lat | Full latitude, floating point, signed | +| %latds | Latitude degrees, integer, signed | +| %latd | Latitude degrees, integer, unsigned | +| %latm | Latitude minutes, integer, unsigned | +| %lats | Latitude seconds, floating point, unsigned | +| %lath | Latitude hemisphere, "N" or "S" | +| %lng | Full longitude, floating point, signed | +| %lngds | Longitude degrees, integer, signed | +| %lngd | Longitude degrees, integer, unsigned | +| %lngm | Longitude minutes, integer, unsigned | +| lngs | Longitude seconds, floating point, unsigned | +| %lngh | Longitude hemisphere, "E" or "W" |

+

Examples:

+
g = Geo::Coord.new(50.004444, 36.231389)
+g.strfcoord('%+lat, %+lng')
+# => "+50.004444, +36.231389"
+g.strfcoord("%latd°%latm'%lath -- %lngd°%lngm'%lngh")
+# => "50°0'N -- 36°13'E"
+

strfcoord handles seconds rounding implicitly:

+
pos = Geo::Coord.new(0.033333, 91.333333)
+pos.strfcoord('%latd %latm %0.5lats') # => "0 1 59.99880"
+pos.strfcoord('%latd %latm %lats')  # => "0 2 0"
+

+ +Calculate distances between two coords

+

Haversine formula from haversine shard is used.

+
require "geo"
+require "geo/distance"
+
+london = Geo::Coord.new(51.500153, -0.126236)
+new_york = Geo::Coord.new(40.714268, -74.005974)
+
+new_york.distance(london).to_kilometers
+# => 5570.4744596620685
+

+ +Calculates the location of a destination coord

+
require "geo"
+require "geo/distance"
+
+point = Geo::Coord.new(39, -75)
+
+point.destination(5000, 90, :kilometers)
+# Geo::Coord(@lat=26.440010707631124, @lng=-22.885355549364313)
+

+ +Contributing

+
    +
  1. Fork it (https://github.com/geocrystal/geo/fork)
  2. +
  3. Create your feature branch (git checkout -b my-new-feature)
  4. +
  5. Commit your changes (git commit -am 'Add some feature')
  6. +
  7. Push to the branch (git push origin my-new-feature)
  8. +
  9. Create a new Pull Request
  10. +
+

+ +Contributors

+ +
+ + diff --git a/index.json b/index.json new file mode 100644 index 0000000..aabc6b0 --- /dev/null +++ b/index.json @@ -0,0 +1 @@ +{"repository_name":"geo","body":"# Geo\n\n![Crystal CI](https://github.com/geocrystal/geo/workflows/Crystal%20CI/badge.svg)\n[![GitHub release](https://img.shields.io/github/release/geocrystal/geo.svg)](https://github.com/geocrystal/geo/releases)\n[![Docs](https://img.shields.io/badge/docs-available-brightgreen.svg)](https://geocrystal.github.io/geo/)\n[![License](https://img.shields.io/github/license/geocrystal/geo.svg)](https://github.com/geocrystal/geo/blob/master/LICENSE)\n\nGeospatial primitives, algorithms, and utilities for Crystal.\n\n## Installation\n\nAdd this to your application's `shard.yml`:\n\n```yaml\ndependencies:\n geo:\n github: geocrystal/geo\n```\n\nRun `shards install`\n\n## Usage\n\nA `Geo::Coord` is a point in geographical coordinates: latitude and longitude.\n\n```crystal\nrequire \"geo\"\n\nc = Geo::Coord.new(50.004444, 36.231389)\n\nc.strfcoord(%{%latd %latm' %0.1lats\" %lath, %lngd %lngm' %0.1lngs\" %lngh})\n# => \"50 0' 16.0\" N, 36 13' 53.0\" E\"\n\nc.strfcoord(\"%lat,%lng\")\n# => \"-50.004444,-36.231389\"\n\nc.to_s\n# => \"50°0'16\"N 36°13'53\"E\"\n\npos = Geo::Coord.new(50.004444, 36.231389)\n\npos.geohash\n# => \"ubcu2rnbuxcx\"\n\npos.geohash(5)\n# => \"ubcu2\"\n```\n\n### Polygon\n\nA polygon represents an area enclosed by a closed path (or loop), which is defined by a series of coordinates.\n\n```crystal\nrequire \"geo\"\n\npos1 = Geo::Coord.new(45.3142533036254, -93.47527313511819)\npos2 = Geo::Coord.new(45.31232182518015, -93.34893036168069)\npos3 = Geo::Coord.new(45.23694281999268, -93.35167694371194)\npos4 = Geo::Coord.new(45.23500870841669, -93.47801971714944)\n\npolygon = Geo::Polygon.new([pos1, pos2, pos3, pos4])\n```\n\nThe Polygon in the example above consists of four sets of `Geo::Coord` coordinates, but notice that the first and last sets define the same location, which completes the loop. In practice, however, since polygons define closed areas, you don't need to specify the last set of coordinates. Ot will automatically complete the polygon by connecting the last location back to the first location.\n\nThe following example is identical to the previous one, except that the last `Geo::Coord` is omitted:\n\n```crystal\nrequire \"geo\"\n\npos1 = Geo::Coord.new(45.3142533036254, -93.47527313511819)\npos2 = Geo::Coord.new(45.31232182518015, -93.34893036168069)\npos3 = Geo::Coord.new(45.23694281999268, -93.35167694371194)\n\npolygon = Geo::Polygon.new([pos1, pos2, pos3])\n```\n\nAdditional actions:\n\n```crystal\ncoord_inside = Geo::Coord.new(45.27428243796789, -93.41648483416066)\ncoord_outside = Geo::Coord.new(45.45411010558687, -93.78151703160256)\n\npolygon.contains?(coord_inside) # => true\npolygon.contains?(coord_outside) # => false\n\npolygon.centroid # => Geo::Coord(@lat=45.27463866133501, @lng=-93.41400121829719)\n```\n\nAdditionally you can initialize polygon as [convex hull](https://en.wikipedia.org/wiki/Convex_hull) from coordinates of points.\n\n```crystal\npoints = [\n {1.0, 1.0},\n {1.0, 0.0},\n {1.0, -1.0},\n {0.0, -1.0},\n {-1.0, -1.0},\n {-1.0, 0.0},\n {-1.0, 1.0},\n {0.0, 1.0},\n {0.0, 0.0},\n].map { |point| Geo::Coord.new(point[0], point[1]) }\n\npolygon = Geo::Polygon.new(points, convex_hull: true)\npolygon.coords\n# => {-1.0, -1.0}, {1.0, -1.0}, {1.0, 1.0}, {-1.0, 1.0}, {-1.0, -1.0}\n```\n\nThe convex hull is computed using the [convex_hull](https://github.com/geocrystal/convex_hull) library.\n\n### Formatting\n\n`Geo::Coord#strfcoord` formats coordinates according to directives.\n\nEach directive starts with `%` and can contain some modifiers before its name.\n\nAcceptable modifiers:\n\n- unsigned integers: none;\n- signed integers: `+` for mandatory sign printing;\n- floats: same as integers and number of digits modifier, like `0.3`.\n\nList of directives:\n\n| Directive | Description |\n| --------- | ------------------------------------------- |\n| `%lat` | Full latitude, floating point, signed |\n| `%latds` | Latitude degrees, integer, signed |\n| `%latd` | Latitude degrees, integer, unsigned |\n| `%latm` | Latitude minutes, integer, unsigned |\n| `%lats` | Latitude seconds, floating point, unsigned |\n| `%lath` | Latitude hemisphere, \"N\" or \"S\" |\n| `%lng` | Full longitude, floating point, signed |\n| `%lngds` | Longitude degrees, integer, signed |\n| `%lngd` | Longitude degrees, integer, unsigned |\n| `%lngm` | Longitude minutes, integer, unsigned |\n| `lngs` | Longitude seconds, floating point, unsigned |\n| `%lngh` | Longitude hemisphere, \"E\" or \"W\" |\n\nExamples:\n\n```crystal\ng = Geo::Coord.new(50.004444, 36.231389)\ng.strfcoord('%+lat, %+lng')\n# => \"+50.004444, +36.231389\"\ng.strfcoord(\"%latd°%latm'%lath -- %lngd°%lngm'%lngh\")\n# => \"50°0'N -- 36°13'E\"\n```\n\n`strfcoord` handles seconds rounding implicitly:\n\n```crystal\npos = Geo::Coord.new(0.033333, 91.333333)\npos.strfcoord('%latd %latm %0.5lats') # => \"0 1 59.99880\"\npos.strfcoord('%latd %latm %lats') # => \"0 2 0\"\n```\n\n### Calculate distances between two coords\n\nHaversine formula from [haversine](https://github.com/geocrystal/haversine) shard is used.\n\n```crystal\nrequire \"geo\"\nrequire \"geo/distance\"\n\nlondon = Geo::Coord.new(51.500153, -0.126236)\nnew_york = Geo::Coord.new(40.714268, -74.005974)\n\nnew_york.distance(london).to_kilometers\n# => 5570.4744596620685\n```\n\n### Calculates the location of a destination coord\n\n```crystal\nrequire \"geo\"\nrequire \"geo/distance\"\n\npoint = Geo::Coord.new(39, -75)\n\npoint.destination(5000, 90, :kilometers)\n# Geo::Coord(@lat=26.440010707631124, @lng=-22.885355549364313)\n```\n\n\n## Contributing\n\n1. Fork it ()\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create a new Pull Request\n\n## Contributors\n\n- [Anton Maminov](https://github.com/mamantoha) - creator and maintainer\n","program":{"html_id":"geo/toplevel","path":"toplevel.html","kind":"module","full_name":"Top Level Namespace","name":"Top Level Namespace","abstract":false,"locations":[],"repository_name":"geo","program":true,"enum":false,"alias":false,"const":false,"types":[{"html_id":"geo/Geo","path":"Geo.html","kind":"module","full_name":"Geo","name":"Geo","abstract":false,"locations":[{"filename":"lib/geo_bearing/src/geo_bearing.cr","line_number":1,"url":null},{"filename":"src/geo.cr","line_number":12,"url":null},{"filename":"src/geo/bearing.cr","line_number":1,"url":null},{"filename":"src/geo/coord.cr","line_number":1,"url":null},{"filename":"src/geo/distance.cr","line_number":1,"url":null},{"filename":"src/geo/polygon.cr","line_number":1,"url":null},{"filename":"src/geo/utils.cr","line_number":1,"url":null}],"repository_name":"geo","program":false,"enum":false,"alias":false,"const":false,"constants":[{"id":"DISTANCE_UNITS","name":"DISTANCE_UNITS","value":"Haversine::FACTORS.keys"},{"id":"VERSION","name":"VERSION","value":"{{ (`shards version /__w/geo/geo/src`).chomp.stringify }}"}],"types":[{"html_id":"geo/Geo/Coord","path":"Geo/Coord.html","kind":"struct","full_name":"Geo::Coord","name":"Coord","abstract":false,"superclass":{"html_id":"geo/Struct","kind":"struct","full_name":"Struct","name":"Struct"},"ancestors":[{"html_id":"geo/Comparable","kind":"module","full_name":"Comparable","name":"Comparable"},{"html_id":"geo/Struct","kind":"struct","full_name":"Struct","name":"Struct"},{"html_id":"geo/Value","kind":"struct","full_name":"Value","name":"Value"},{"html_id":"geo/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/geo/bearing.cr","line_number":2,"url":null},{"filename":"src/geo/coord.cr","line_number":3,"url":null},{"filename":"src/geo/distance.cr","line_number":2,"url":null}],"repository_name":"geo","program":false,"enum":false,"alias":false,"const":false,"constants":[{"id":"DIRECTIVES","name":"DIRECTIVES","value":"{/%(#{FLOATUFLAGS})?lats/ => ->(m : Regex::MatchData) do\n \"%#{m[1]? || \"0.\"}f\"\nend, \"%latm\" => \"%i\", /%(#{INTFLAGS})?latds/ => ->(m : Regex::MatchData) do\n \"%#{m[1]}i\"\nend, \"%latd\" => \"%i\", \"%lath\" => \"%s\", /%(#{FLOATFLAGS})?lat/ => ->(m : Regex::MatchData) do\n \"%#{m[1]}f\"\nend, /%(#{FLOATUFLAGS})?lngs/ => ->(m : Regex::MatchData) do\n \"%#{m[1]? || \"0.\"}f\"\nend, \"%lngm\" => \"%i\", /%(#{INTFLAGS})?lngds/ => ->(m : Regex::MatchData) do\n \"%#{m[1]}i\"\nend, \"%lngd\" => \"%i\", \"%lngh\" => \"%s\", /%(#{FLOATFLAGS})?lng/ => ->(m : Regex::MatchData) do\n \"%#{m[1]}f\"\nend}"},{"id":"FLOATFLAGS","name":"FLOATFLAGS","value":"/\\+?#{FLOATUFLAGS}?/"},{"id":"FLOATUFLAGS","name":"FLOATUFLAGS","value":"/0\\.\\d+/"},{"id":"INTFLAGS","name":"INTFLAGS","value":"/\\+?/"}],"included_modules":[{"html_id":"geo/Comparable","kind":"module","full_name":"Comparable","name":"Comparable"}],"namespace":{"html_id":"geo/Geo","kind":"module","full_name":"Geo","name":"Geo"},"doc":"A `Coord` is a point in geographical coordinates: latitude and longitude.","summary":"

A Coord is a point in geographical coordinates: latitude and longitude.

","constructors":[{"html_id":"new(lat:Number,lng:Number)-class-method","name":"new","abstract":false,"args":[{"name":"lat","external_name":"lat","restriction":"Number"},{"name":"lng","external_name":"lng","restriction":"Number"}],"args_string":"(lat : Number, lng : Number)","args_html":"(lat : Number, lng : Number)","location":{"filename":"src/geo/coord.cr","line_number":32,"url":null},"def":{"name":"new","args":[{"name":"lat","external_name":"lat","restriction":"Number"},{"name":"lng","external_name":"lng","restriction":"Number"}],"visibility":"Public","body":"_ = allocate\n_.initialize(lat, lng)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"<=>(other:Geo::Coord)-instance-method","name":"<=>","doc":"The comparison operator. Returns `0` if the two objects are equal,\na negative number if this object is considered less than *other*,\na positive number if this object is considered greater than *other*,\nor `nil` if the two objects are not comparable.\n\nSubclasses define this method to provide class-specific ordering.\n\nThe comparison operator is usually used to sort values:\n\n```\n# Sort in a descending way:\n[3, 1, 2].sort { |x, y| y <=> x } # => [3, 2, 1]\n\n# Sort in an ascending way:\n[3, 1, 2].sort { |x, y| x <=> y } # => [1, 2, 3]\n```","summary":"

The comparison operator.

","abstract":false,"args":[{"name":"other","external_name":"other","restriction":"Geo::Coord"}],"args_string":"(other : Geo::Coord)","args_html":"(other : Geo::Coord)","location":{"filename":"src/geo/coord.cr","line_number":177,"url":null},"def":{"name":"<=>","args":[{"name":"other","external_name":"other","restriction":"Geo::Coord"}],"visibility":"Public","body":"ll <=> other.ll"}},{"html_id":"bearing(to:Geo::Coord,final=false):Float64-instance-method","name":"bearing","doc":"Calculates initial and final bearings between two points using great-circle distance formulas","summary":"

Calculates initial and final bearings between two points using great-circle distance formulas

","abstract":false,"args":[{"name":"to","external_name":"to","restriction":"Geo::Coord"},{"name":"final","default_value":"false","external_name":"final","restriction":""}],"args_string":"(to : Geo::Coord, final = false) : Float64","args_html":"(to : Geo::Coord, final = false) : Float64","location":{"filename":"src/geo/bearing.cr","line_number":4,"url":null},"def":{"name":"bearing","args":[{"name":"to","external_name":"to","restriction":"Geo::Coord"},{"name":"final","default_value":"false","external_name":"final","restriction":""}],"return_type":"Float64","visibility":"Public","body":"Geo::Bearing.bearing(lat, lng, to.lat, to.lng, final)"}},{"html_id":"between?(p1:Geo::Coord,p2:Geo::Coord)-instance-method","name":"between?","abstract":false,"args":[{"name":"p1","external_name":"p1","restriction":"Geo::Coord"},{"name":"p2","external_name":"p2","restriction":"Geo::Coord"}],"args_string":"(p1 : Geo::Coord, p2 : Geo::Coord)","args_html":"(p1 : Geo::Coord, p2 : Geo::Coord)","location":{"filename":"src/geo/coord.cr","line_number":181,"url":null},"def":{"name":"between?","args":[{"name":"p1","external_name":"p1","restriction":"Geo::Coord"},{"name":"p2","external_name":"p2","restriction":"Geo::Coord"}],"visibility":"Public","body":"min, max = [p1, p2].minmax\nif cmp = self <=> min\n if cmp < 0\n return false\n end\nend\nif cmp = self <=> max\n if cmp > 0\n return false\n end\nend\ntrue\n"}},{"html_id":"destination(distance:Number,bearing:Number,unit:Symbol=:kilometers):Geo::Coord-instance-method","name":"destination","doc":"Calculates the location of a destination point","summary":"

Calculates the location of a destination point

","abstract":false,"args":[{"name":"distance","external_name":"distance","restriction":"Number"},{"name":"bearing","external_name":"bearing","restriction":"Number"},{"name":"unit","default_value":":kilometers","external_name":"unit","restriction":"Symbol"}],"args_string":"(distance : Number, bearing : Number, unit : Symbol = :kilometers) : Geo::Coord","args_html":"(distance : Number, bearing : Number, unit : Symbol = :kilometers) : Geo::Coord","location":{"filename":"src/geo/distance.cr","line_number":10,"url":null},"def":{"name":"destination","args":[{"name":"distance","external_name":"distance","restriction":"Number"},{"name":"bearing","external_name":"bearing","restriction":"Number"},{"name":"unit","default_value":":kilometers","external_name":"unit","restriction":"Symbol"}],"return_type":"Geo::Coord","visibility":"Public","body":"point = Haversine.destination(self.ll, distance, bearing, unit)\nGeo::Coord.new(point[0], point[1])\n"}},{"html_id":"distance(other:Geo::Coord):Haversine::Distance-instance-method","name":"distance","doc":"Calculates distance to `other`.\nHaversine formula is used.","summary":"

Calculates distance to other.

","abstract":false,"args":[{"name":"other","external_name":"other","restriction":"Geo::Coord"}],"args_string":"(other : Geo::Coord) : Haversine::Distance","args_html":"(other : Geo::Coord) : Haversine::Distance","location":{"filename":"src/geo/distance.cr","line_number":5,"url":null},"def":{"name":"distance","args":[{"name":"other","external_name":"other","restriction":"Geo::Coord"}],"return_type":"Haversine::Distance","visibility":"Public","body":"Haversine.distance(self.ll, other.ll)"}},{"html_id":"geohash(precision=12)-instance-method","name":"geohash","doc":"Returns a geohash representing coordinates.","summary":"

Returns a geohash representing coordinates.

","abstract":false,"args":[{"name":"precision","default_value":"12","external_name":"precision","restriction":""}],"args_string":"(precision = 12)","args_html":"(precision = 12)","location":{"filename":"src/geo/coord.cr","line_number":155,"url":null},"def":{"name":"geohash","args":[{"name":"precision","default_value":"12","external_name":"precision","restriction":""}],"visibility":"Public","body":"Geohash.encode(lat.to_f, lng.to_f, precision)"}},{"html_id":"lat:Float32|Float64|Int32-instance-method","name":"lat","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":8,"url":null},"def":{"name":"lat","visibility":"Public","body":"@lat"}},{"html_id":"latd:Int32-instance-method","name":"latd","doc":"Returns latitude degrees","summary":"

Returns latitude degrees

","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":36,"url":null},"def":{"name":"latd","return_type":"Int32","visibility":"Public","body":"lat.abs.to_i"}},{"html_id":"latds-instance-method","name":"latds","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":75,"url":null},"def":{"name":"latds","visibility":"Public","body":"lat.to_i"}},{"html_id":"lath:String-instance-method","name":"lath","doc":"Returns latitude hemisphere","summary":"

Returns latitude hemisphere

","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":51,"url":null},"def":{"name":"lath","return_type":"String","visibility":"Public","body":"lat > 0 ? \"N\" : \"S\""}},{"html_id":"latm:Int32-instance-method","name":"latm","doc":"Returns latitude minutes","summary":"

Returns latitude minutes

","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":41,"url":null},"def":{"name":"latm","return_type":"Int32","visibility":"Public","body":"(lat.abs * 60).to_i % 60"}},{"html_id":"lats:Number-instance-method","name":"lats","doc":"Returns latitude seconds","summary":"

Returns latitude seconds

","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":46,"url":null},"def":{"name":"lats","return_type":"Number","visibility":"Public","body":"(lat.abs * 3600) % 60"}},{"html_id":"ll-instance-method","name":"ll","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":173,"url":null},"def":{"name":"ll","visibility":"Public","body":"{lat, lng}"}},{"html_id":"lng:Float32|Float64|Int32-instance-method","name":"lng","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":9,"url":null},"def":{"name":"lng","visibility":"Public","body":"@lng"}},{"html_id":"lngd:Int32-instance-method","name":"lngd","doc":"Returns longitude degrees","summary":"

Returns longitude degrees

","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":56,"url":null},"def":{"name":"lngd","return_type":"Int32","visibility":"Public","body":"lng.abs.to_i"}},{"html_id":"lngds-instance-method","name":"lngds","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":79,"url":null},"def":{"name":"lngds","visibility":"Public","body":"lng.to_i"}},{"html_id":"lngh:String-instance-method","name":"lngh","doc":"Returns longitude hemisphere","summary":"

Returns longitude hemisphere

","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":71,"url":null},"def":{"name":"lngh","return_type":"String","visibility":"Public","body":"lng > 0 ? \"E\" : \"W\""}},{"html_id":"lngm:Int32-instance-method","name":"lngm","doc":"Returns longitude minutes","summary":"

Returns longitude minutes

","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":61,"url":null},"def":{"name":"lngm","return_type":"Int32","visibility":"Public","body":"(lng.abs * 60).to_i % 60"}},{"html_id":"lngs:Number-instance-method","name":"lngs","doc":"Returns longitude seconds","summary":"

Returns longitude seconds

","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":66,"url":null},"def":{"name":"lngs","return_type":"Number","visibility":"Public","body":"(lng.abs * 3600) % 60"}},{"html_id":"strfcoord(formatstr):String-instance-method","name":"strfcoord","doc":"Formats coordinates according to directives in `formatstr`.\n\nEach directive starts with `%` and can contain some modifiers before its name.\n\nAcceptable modifiers:\n- unsigned integers: none;\n- signed integers: `+` for mandatory sign printing;\n- floats: same as integers and number of digits modifier, like `0.3`.\n\nList of directives:\n\n- `%lat` - Full latitude, floating point, signed\n- `%latds` - Latitude degrees, integer, signed\n- `%latd` - Latitude degrees, integer, unsigned\n- `%latm` - Latitude minutes, integer, unsigned\n- `%lats` - Latitude seconds, floating point, unsigned\n- `%lath` - Latitude hemisphere, \"N\" or \"S\"\n- `%lng` - Full longitude, floating point, signed\n- `%lngds` - Longitude degrees, integer, signed\n- `%lngd` - Longitude degrees, integer, unsigned\n- `%lngm` - Longitude minutes, integer, unsigned\n- `lngs` - Longitude seconds, floating point, unsigned\n- `%lngh`` - Longitude hemisphere, \"E\" or \"W\"\n\nExamples:\n\n```\ng = Geo::Coord.new(50.004444, 36.231389)\ng.strfcoord('%+lat, %+lng')\n# => \"+50.004444, +36.231389\"\ng.strfcoord(\"%latd°%latm'%lath -- %lngd°%lngm'%lngh\")\n# => \"50°0'N -- 36°13'E\"\n```\n\n`strfcoord` handles seconds rounding implicitly:\n\n```\npos = Geo::Coord.new(0.033333, 91.333333)\npos.strfcoord('%latd %latm %0.5lats') # => \"0 1 59.99880\"\npos.strfcoord('%latd %latm %lats') # => \"0 2 0\"\n```","summary":"

Formats coordinates according to directives in formatstr.

","abstract":false,"args":[{"name":"formatstr","external_name":"formatstr","restriction":""}],"args_string":"(formatstr) : String","args_html":"(formatstr) : String","location":{"filename":"src/geo/coord.cr","line_number":124,"url":null},"def":{"name":"strfcoord","args":[{"name":"formatstr","external_name":"formatstr","restriction":""}],"return_type":"String","visibility":"Public","body":"h = full_hash\nDIRECTIVES.reduce(formatstr) do |memo, __temp_52|\n from, to = __temp_52\n memo.gsub(from) do\n to = if (to.is_a?(Proc) && from.is_a?(Regex)) && (match_data = memo.match(from))\n to.call(match_data)\n else\n to.as(String)\n end\n res = to % h\n if tmp = guard_seconds(to, res)\n res, carrymin = tmp\n if carrymin.empty?\n else\n if h[carrymin].is_a?(Int32)\n tmp = h[carrymin].as(Int32)\n h[carrymin] = tmp + 1\n end\n end\n end\n res\n end\nend\n"}},{"html_id":"to_geojson:GeoJSON::Coordinates-instance-method","name":"to_geojson","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":159,"url":null},"def":{"name":"to_geojson","return_type":"GeoJSON::Coordinates","visibility":"Public","body":"GeoJSON::Coordinates.new(lng.to_f64, lat.to_f64)"}},{"html_id":"to_s(io)-instance-method","name":"to_s","doc":"Returns a string representing coordinates.\n\n```\ng.to_s # => \"50°0'16\\\"N 36°13'53\\\"E\"\ng.to_s(dms: false) # => \"50.004444,36.231389\"\n```","summary":"

Returns a string representing coordinates.

","abstract":false,"args":[{"name":"io","external_name":"io","restriction":""}],"args_string":"(io)","args_html":"(io)","location":{"filename":"src/geo/coord.cr","line_number":169,"url":null},"def":{"name":"to_s","args":[{"name":"io","external_name":"io","restriction":""}],"visibility":"Public","body":"io << (strfcoord(\"%latd°%latm'%lats\\\"%lath %lngd°%lngm'%lngs\\\"%lngh\"))"}}],"types":[{"html_id":"geo/Geo/Coord/Number","path":"Geo/Coord/Number.html","kind":"alias","full_name":"Geo::Coord::Number","name":"Number","abstract":false,"locations":[{"filename":"src/geo/coord.cr","line_number":6,"url":null}],"repository_name":"geo","program":false,"enum":false,"alias":true,"aliased":"(Float32 | Float64 | Int32)","aliased_html":"Float32 | Float64 | Int32","const":false,"namespace":{"html_id":"geo/Geo/Coord","kind":"struct","full_name":"Geo::Coord","name":"Coord"}}]},{"html_id":"geo/Geo/Polygon","path":"Geo/Polygon.html","kind":"struct","full_name":"Geo::Polygon","name":"Polygon","abstract":false,"superclass":{"html_id":"geo/Struct","kind":"struct","full_name":"Struct","name":"Struct"},"ancestors":[{"html_id":"geo/Indexable","kind":"module","full_name":"Indexable","name":"Indexable"},{"html_id":"geo/Enumerable","kind":"module","full_name":"Enumerable","name":"Enumerable"},{"html_id":"geo/Iterable","kind":"module","full_name":"Iterable","name":"Iterable"},{"html_id":"geo/Struct","kind":"struct","full_name":"Struct","name":"Struct"},{"html_id":"geo/Value","kind":"struct","full_name":"Value","name":"Value"},{"html_id":"geo/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/geo/polygon.cr","line_number":5,"url":null}],"repository_name":"geo","program":false,"enum":false,"alias":false,"const":false,"included_modules":[{"html_id":"geo/Indexable","kind":"module","full_name":"Indexable","name":"Indexable"}],"namespace":{"html_id":"geo/Geo","kind":"module","full_name":"Geo","name":"Geo"},"doc":"A `Polygon` is a fixed-size, immutable, stack-allocated sequence of `Geo::Coord`.\nCoordinates are in lexicographical order.\nAdditionally, polygons form a closed loop and define a filled region.","summary":"

A Polygon is a fixed-size, immutable, stack-allocated sequence of Geo::Coord.

","constructors":[{"html_id":"new(coords:Array(Geo::Coord),convex_hull=false)-class-method","name":"new","abstract":false,"args":[{"name":"coords","external_name":"coords","restriction":"Array(Geo::Coord)"},{"name":"convex_hull","default_value":"false","external_name":"convex_hull","restriction":""}],"args_string":"(coords : Array(Geo::Coord), convex_hull = false)","args_html":"(coords : Array(Geo::Coord), convex_hull = false)","location":{"filename":"src/geo/polygon.cr","line_number":11,"url":null},"def":{"name":"new","args":[{"name":"coords","external_name":"coords","restriction":"Array(Geo::Coord)"},{"name":"convex_hull","default_value":"false","external_name":"convex_hull","restriction":""}],"visibility":"Public","body":"_ = allocate\n_.initialize(coords, convex_hull)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"==(other:Geo::Polygon):Bool-instance-method","name":"==","abstract":false,"args":[{"name":"other","external_name":"other","restriction":"Geo::Polygon"}],"args_string":"(other : Geo::Polygon) : Bool","args_html":"(other : Geo::Polygon) : Bool","location":{"filename":"src/geo/polygon.cr","line_number":93,"url":null},"def":{"name":"==","args":[{"name":"other","external_name":"other","restriction":"Geo::Polygon"}],"return_type":"Bool","visibility":"Public","body":"min_size = Math.min(size, other.size)\n0.upto(min_size - 1) do |i|\n if self[i] == other[i]\n else\n return false\n end\nend\nsize == other.size\n"}},{"html_id":"area-instance-method","name":"area","doc":"Return the approximate signed geodesic area of the polygon in square meters.","summary":"

Return the approximate signed geodesic area of the polygon in square meters.

","abstract":false,"location":{"filename":"src/geo/polygon.cr","line_number":29,"url":null},"def":{"name":"area","visibility":"Public","body":"coordinates = @coords.map do |coord|\n [coord.lng, coord.lat]\nend\nRingArea.ring_area(coordinates)\n"}},{"html_id":"centroid:Geo::Coord-instance-method","name":"centroid","abstract":false,"location":{"filename":"src/geo/polygon.cr","line_number":83,"url":null},"def":{"name":"centroid","return_type":"Geo::Coord","visibility":"Public","body":"@centroid || (@centroid = calculate_centroid)"}},{"html_id":"contains?(coord:Geo::Coord):Bool-instance-method","name":"contains?","abstract":false,"args":[{"name":"coord","external_name":"coord","restriction":"Geo::Coord"}],"args_string":"(coord : Geo::Coord) : Bool","args_html":"(coord : Geo::Coord) : Bool","location":{"filename":"src/geo/polygon.cr","line_number":63,"url":null},"def":{"name":"contains?","args":[{"name":"coord","external_name":"coord","restriction":"Geo::Coord"}],"return_type":"Bool","visibility":"Public","body":"last_coord = @coords.last\nodd_nodes = false\ny, x = coord.ll\n@coords.each do |iter_coord|\n yi, xi = iter_coord.ll\n yj, xj = last_coord.ll\n if (yi < y && yj >= y) || (yj < y && yi >= y)\n if (xi + (((y - yi) / (yj - yi)) * (xj - xi))) < x\n odd_nodes = !odd_nodes\n end\n end\n last_coord = iter_coord\nend\nodd_nodes\n"}},{"html_id":"coords:Array(Geo::Coord)-instance-method","name":"coords","abstract":false,"location":{"filename":"src/geo/polygon.cr","line_number":24,"url":null},"def":{"name":"coords","visibility":"Public","body":"@coords"}},{"html_id":"size:Int32-instance-method","name":"size","doc":"Returns the number of elements in this container.","summary":"

Returns the number of elements in this container.

","abstract":false,"location":{"filename":"src/geo/polygon.cr","line_number":9,"url":null},"def":{"name":"size","return_type":"Int32","visibility":"Public","body":"@size"}},{"html_id":"to_geojson:GeoJSON::Polygon-instance-method","name":"to_geojson","abstract":false,"location":{"filename":"src/geo/polygon.cr","line_number":103,"url":null},"def":{"name":"to_geojson","return_type":"GeoJSON::Polygon","visibility":"Public","body":"coordinates = @coords.map do |coord|\n GeoJSON::Coordinates.new(coord.lng.to_f64, coord.lat.to_f64)\nend\nGeoJSON::Polygon.new([coordinates])\n"}},{"html_id":"unsafe_fetch(index:Int)-instance-method","name":"unsafe_fetch","doc":"Returns the element at the given *index*, without doing any bounds check.\n\n`Indexable` makes sure to invoke this method with *index* in `0...size`,\nso converting negative indices to positive ones is not needed here.\n\nClients never invoke this method directly. Instead, they access\nelements with `#[](index)` and `#[]?(index)`.\n\nThis method should only be directly invoked if you are absolutely\nsure the index is in bounds, to avoid a bounds check for a small boost\nof performance.","summary":"

Returns the element at the given index, without doing any bounds check.

","abstract":false,"args":[{"name":"index","external_name":"index","restriction":"Int"}],"args_string":"(index : Int)","args_html":"(index : Int)","location":{"filename":"src/geo/polygon.cr","line_number":89,"url":null},"def":{"name":"unsafe_fetch","args":[{"name":"index","external_name":"index","restriction":"Int"}],"visibility":"Public","body":"@coords[index]"}}]},{"html_id":"geo/Geo/Utils","path":"Geo/Utils.html","kind":"module","full_name":"Geo::Utils","name":"Utils","abstract":false,"locations":[{"filename":"src/geo/utils.cr","line_number":2,"url":null}],"repository_name":"geo","program":false,"enum":false,"alias":false,"const":false,"extended_modules":[{"html_id":"geo/Geo/Utils","kind":"module","full_name":"Geo::Utils","name":"Utils"}],"namespace":{"html_id":"geo/Geo","kind":"module","full_name":"Geo","name":"Geo"},"instance_methods":[{"html_id":"orientation(p:Geo::Coord,q:Geo::Coord,r:Geo::Coord)-instance-method","name":"orientation","doc":"Orientation of ordered triplet (p, q, r)\n\nOrientation of an ordered triplet of points in the plane can be\n\n* counterclockwise\n* clockwise\n* colinear\n\nThe function returns following values\n0 --> p, q and r are colinear\n1 --> Clockwise\n2 --> Counterclockwise","summary":"

Orientation of ordered triplet (p, q, r)

","abstract":false,"args":[{"name":"p","external_name":"p","restriction":"Geo::Coord"},{"name":"q","external_name":"q","restriction":"Geo::Coord"},{"name":"r","external_name":"r","restriction":"Geo::Coord"}],"args_string":"(p : Geo::Coord, q : Geo::Coord, r : Geo::Coord)","args_html":"(p : Geo::Coord, q : Geo::Coord, r : Geo::Coord)","location":{"filename":"src/geo/utils.cr","line_number":17,"url":null},"def":{"name":"orientation","args":[{"name":"p","external_name":"p","restriction":"Geo::Coord"},{"name":"q","external_name":"q","restriction":"Geo::Coord"},{"name":"r","external_name":"r","restriction":"Geo::Coord"}],"visibility":"Public","body":"val = ((q.lng - p.lng) * (r.lat - q.lat)) - ((q.lat - p.lat) * (r.lng - q.lng))\nif val == 0\n return 0\nend\nval > 0 ? 1 : 2\n"}}]}]}]}} \ No newline at end of file diff --git a/js/doc.js b/js/doc.js new file mode 100644 index 0000000..45d38b9 --- /dev/null +++ b/js/doc.js @@ -0,0 +1,1099 @@ +window.CrystalDocs = (window.CrystalDocs || {}); + +CrystalDocs.base_path = (CrystalDocs.base_path || ""); + +CrystalDocs.searchIndex = (CrystalDocs.searchIndex || false); +CrystalDocs.MAX_RESULTS_DISPLAY = 140; + +CrystalDocs.runQuery = function(query) { + function searchType(type, query, results) { + var matches = []; + var matchedFields = []; + var name = type.full_name; + var i = name.lastIndexOf("::"); + if (i > 0) { + name = name.substring(i + 2); + } + var nameMatches = query.matches(name); + if (nameMatches){ + matches = matches.concat(nameMatches); + matchedFields.push("name"); + } + + var namespaceMatches = query.matchesNamespace(type.full_name); + if(namespaceMatches){ + matches = matches.concat(namespaceMatches); + matchedFields.push("name"); + } + + var docMatches = query.matches(type.doc); + if(docMatches){ + matches = matches.concat(docMatches); + matchedFields.push("doc"); + } + if (matches.length > 0) { + results.push({ + id: type.html_id, + result_type: "type", + kind: type.kind, + name: name, + full_name: type.full_name, + href: type.path, + summary: type.summary, + matched_fields: matchedFields, + matched_terms: matches + }); + } + + if (type.instance_methods) { + type.instance_methods.forEach(function(method) { + searchMethod(method, type, "instance_method", query, results); + }) + } + if (type.class_methods) { + type.class_methods.forEach(function(method) { + searchMethod(method, type, "class_method", query, results); + }) + } + if (type.constructors) { + type.constructors.forEach(function(constructor) { + searchMethod(constructor, type, "constructor", query, results); + }) + } + if (type.macros) { + type.macros.forEach(function(macro) { + searchMethod(macro, type, "macro", query, results); + }) + } + if (type.constants) { + type.constants.forEach(function(constant){ + searchConstant(constant, type, query, results); + }); + } + if (type.types) { + type.types.forEach(function(subtype){ + searchType(subtype, query, results); + }); + } + }; + + function searchMethod(method, type, kind, query, results) { + var matches = []; + var matchedFields = []; + var nameMatches = query.matchesMethod(method.name, kind, type); + if (nameMatches){ + matches = matches.concat(nameMatches); + matchedFields.push("name"); + } + + if (method.args) { + method.args.forEach(function(arg){ + var argMatches = query.matches(arg.external_name); + if (argMatches) { + matches = matches.concat(argMatches); + matchedFields.push("args"); + } + }); + } + + var docMatches = query.matches(type.doc); + if(docMatches){ + matches = matches.concat(docMatches); + matchedFields.push("doc"); + } + + if (matches.length > 0) { + var typeMatches = query.matches(type.full_name); + if (typeMatches) { + matchedFields.push("type"); + matches = matches.concat(typeMatches); + } + results.push({ + id: method.html_id, + type: type.full_name, + result_type: kind, + name: method.name, + full_name: type.full_name + "#" + method.name, + args_string: method.args_string, + summary: method.summary, + href: type.path + "#" + method.html_id, + matched_fields: matchedFields, + matched_terms: matches + }); + } + } + + function searchConstant(constant, type, query, results) { + var matches = []; + var matchedFields = []; + var nameMatches = query.matches(constant.name); + if (nameMatches){ + matches = matches.concat(nameMatches); + matchedFields.push("name"); + } + var docMatches = query.matches(constant.doc); + if(docMatches){ + matches = matches.concat(docMatches); + matchedFields.push("doc"); + } + if (matches.length > 0) { + var typeMatches = query.matches(type.full_name); + if (typeMatches) { + matchedFields.push("type"); + matches = matches.concat(typeMatches); + } + results.push({ + id: constant.id, + type: type.full_name, + result_type: "constant", + name: constant.name, + full_name: type.full_name + "#" + constant.name, + value: constant.value, + summary: constant.summary, + href: type.path + "#" + constant.id, + matched_fields: matchedFields, + matched_terms: matches + }); + } + } + + var results = []; + searchType(CrystalDocs.searchIndex.program, query, results); + return results; +}; + +CrystalDocs.rankResults = function(results, query) { + function uniqueArray(ar) { + var j = {}; + + ar.forEach(function(v) { + j[v + "::" + typeof v] = v; + }); + + return Object.keys(j).map(function(v) { + return j[v]; + }); + } + + results = results.sort(function(a, b) { + var matchedTermsDiff = uniqueArray(b.matched_terms).length - uniqueArray(a.matched_terms).length; + var aHasDocs = b.matched_fields.includes("doc"); + var bHasDocs = b.matched_fields.includes("doc"); + + var aOnlyDocs = aHasDocs && a.matched_fields.length == 1; + var bOnlyDocs = bHasDocs && b.matched_fields.length == 1; + + if (a.result_type == "type" && b.result_type != "type" && !aOnlyDocs) { + if(CrystalDocs.DEBUG) { console.log("a is type b not"); } + return -1; + } else if (b.result_type == "type" && a.result_type != "type" && !bOnlyDocs) { + if(CrystalDocs.DEBUG) { console.log("b is type, a not"); } + return 1; + } + if (a.matched_fields.includes("name")) { + if (b.matched_fields.includes("name")) { + var a_name = (CrystalDocs.prefixForType(a.result_type) || "") + ((a.result_type == "type") ? a.full_name : a.name); + var b_name = (CrystalDocs.prefixForType(b.result_type) || "") + ((b.result_type == "type") ? b.full_name : b.name); + a_name = a_name.toLowerCase(); + b_name = b_name.toLowerCase(); + for(var i = 0; i < query.normalizedTerms.length; i++) { + var term = query.terms[i].replace(/^::?|::?$/, ""); + var a_orig_index = a_name.indexOf(term); + var b_orig_index = b_name.indexOf(term); + if(CrystalDocs.DEBUG) { console.log("term: " + term + " a: " + a_name + " b: " + b_name); } + if(CrystalDocs.DEBUG) { console.log(a_orig_index, b_orig_index, a_orig_index - b_orig_index); } + if (a_orig_index >= 0) { + if (b_orig_index >= 0) { + if(CrystalDocs.DEBUG) { console.log("both have exact match", a_orig_index > b_orig_index ? -1 : 1); } + if(a_orig_index != b_orig_index) { + if(CrystalDocs.DEBUG) { console.log("both have exact match at different positions", a_orig_index > b_orig_index ? 1 : -1); } + return a_orig_index > b_orig_index ? 1 : -1; + } + } else { + if(CrystalDocs.DEBUG) { console.log("a has exact match, b not"); } + return -1; + } + } else if (b_orig_index >= 0) { + if(CrystalDocs.DEBUG) { console.log("b has exact match, a not"); } + return 1; + } + } + } else { + if(CrystalDocs.DEBUG) { console.log("a has match in name, b not"); } + return -1; + } + } else if ( + !a.matched_fields.includes("name") && + b.matched_fields.includes("name") + ) { + return 1; + } + + if (matchedTermsDiff != 0 || (aHasDocs != bHasDocs)) { + if(CrystalDocs.DEBUG) { console.log("matchedTermsDiff: " + matchedTermsDiff, aHasDocs, bHasDocs); } + return matchedTermsDiff; + } + + var matchedFieldsDiff = b.matched_fields.length - a.matched_fields.length; + if (matchedFieldsDiff != 0) { + if(CrystalDocs.DEBUG) { console.log("matched to different number of fields: " + matchedFieldsDiff); } + return matchedFieldsDiff > 0 ? 1 : -1; + } + + var nameCompare = a.name.localeCompare(b.name); + if(nameCompare != 0){ + if(CrystalDocs.DEBUG) { console.log("nameCompare resulted in: " + a.name + "<=>" + b.name + ": " + nameCompare); } + return nameCompare > 0 ? 1 : -1; + } + + if(a.matched_fields.includes("args") && b.matched_fields.includes("args")) { + for(var i = 0; i < query.terms.length; i++) { + var term = query.terms[i]; + var aIndex = a.args_string.indexOf(term); + var bIndex = b.args_string.indexOf(term); + if(CrystalDocs.DEBUG) { console.log("index of " + term + " in args_string: " + aIndex + " - " + bIndex); } + if(aIndex >= 0){ + if(bIndex >= 0){ + if(aIndex != bIndex){ + return aIndex > bIndex ? 1 : -1; + } + }else{ + return -1; + } + }else if(bIndex >= 0) { + return 1; + } + } + } + + return 0; + }); + + if (results.length > 1) { + // if we have more than two search terms, only include results with the most matches + var bestMatchedTerms = uniqueArray(results[0].matched_terms).length; + + results = results.filter(function(result) { + return uniqueArray(result.matched_terms).length + 1 >= bestMatchedTerms; + }); + } + return results; +}; + +CrystalDocs.prefixForType = function(type) { + switch (type) { + case "instance_method": + return "#"; + + case "class_method": + case "macro": + case "constructor": + return "."; + + default: + return false; + } +}; + +CrystalDocs.displaySearchResults = function(results, query) { + function sanitize(html){ + return html.replace(/<(?!\/?code)[^>]+>/g, ""); + } + + // limit results + if (results.length > CrystalDocs.MAX_RESULTS_DISPLAY) { + results = results.slice(0, CrystalDocs.MAX_RESULTS_DISPLAY); + } + + var $frag = document.createDocumentFragment(); + var $resultsElem = document.querySelector(".search-list"); + $resultsElem.innerHTML = ""; + + results.forEach(function(result, i) { + var url = CrystalDocs.base_path + result.href; + var type = false; + + var title = query.highlight(result.result_type == "type" ? result.full_name : result.name); + + var prefix = CrystalDocs.prefixForType(result.result_type); + if (prefix) { + title = "" + prefix + "" + title; + } + + title = "" + title + ""; + + if (result.args_string) { + title += + "" + query.highlight(result.args_string) + ""; + } + + $elem = document.createElement("li"); + $elem.className = "search-result search-result--" + result.result_type; + $elem.dataset.href = url; + $elem.setAttribute("title", result.full_name + " docs page"); + + var $title = document.createElement("div"); + $title.setAttribute("class", "search-result__title"); + var $titleLink = document.createElement("a"); + $titleLink.setAttribute("href", url); + + $titleLink.innerHTML = title; + $title.appendChild($titleLink); + $elem.appendChild($title); + $elem.addEventListener("click", function() { + $titleLink.click(); + }); + + if (result.result_type !== "type") { + var $type = document.createElement("div"); + $type.setAttribute("class", "search-result__type"); + $type.innerHTML = query.highlight(result.type); + $elem.appendChild($type); + } + + if(result.summary){ + var $doc = document.createElement("div"); + $doc.setAttribute("class", "search-result__doc"); + $doc.innerHTML = query.highlight(sanitize(result.summary)); + $elem.appendChild($doc); + } + + $elem.appendChild(document.createComment(JSON.stringify(result))); + $frag.appendChild($elem); + }); + + $resultsElem.appendChild($frag); + + CrystalDocs.toggleResultsList(true); +}; + +CrystalDocs.toggleResultsList = function(visible) { + if (visible) { + document.querySelector(".types-list").classList.add("hidden"); + document.querySelector(".search-results").classList.remove("hidden"); + } else { + document.querySelector(".types-list").classList.remove("hidden"); + document.querySelector(".search-results").classList.add("hidden"); + } +}; + +CrystalDocs.Query = function(string) { + this.original = string; + this.terms = string.split(/\s+/).filter(function(word) { + return CrystalDocs.Query.stripModifiers(word).length > 0; + }); + + var normalized = this.terms.map(CrystalDocs.Query.normalizeTerm); + this.normalizedTerms = normalized; + + function runMatcher(field, matcher) { + if (!field) { + return false; + } + var normalizedValue = CrystalDocs.Query.normalizeTerm(field); + + var matches = []; + normalized.forEach(function(term) { + if (matcher(normalizedValue, term)) { + matches.push(term); + } + }); + return matches.length > 0 ? matches : false; + } + + this.matches = function(field) { + return runMatcher(field, function(normalized, term) { + if (term[0] == "#" || term[0] == ".") { + return false; + } + return normalized.indexOf(term) >= 0; + }); + }; + + function namespaceMatcher(normalized, term){ + var i = term.indexOf(":"); + if(i >= 0){ + term = term.replace(/^::?|::?$/, ""); + var index = normalized.indexOf(term); + if((index == 0) || (index > 0 && normalized[index-1] == ":")){ + return true; + } + } + return false; + } + this.matchesMethod = function(name, kind, type) { + return runMatcher(name, function(normalized, term) { + var i = term.indexOf("#"); + if(i >= 0){ + if (kind != "instance_method") { + return false; + } + }else{ + i = term.indexOf("."); + if(i >= 0){ + if (kind != "class_method" && kind != "macro" && kind != "constructor") { + return false; + } + }else{ + //neither # nor . + if(term.indexOf(":") && namespaceMatcher(normalized, term)){ + return true; + } + } + } + + var methodName = term; + if(i >= 0){ + var termType = term.substring(0, i); + methodName = term.substring(i+1); + + if(termType != "") { + if(CrystalDocs.Query.normalizeTerm(type.full_name).indexOf(termType) < 0){ + return false; + } + } + } + return normalized.indexOf(methodName) >= 0; + }); + }; + + this.matchesNamespace = function(namespace){ + return runMatcher(namespace, namespaceMatcher); + }; + + this.highlight = function(string) { + if (typeof string == "undefined") { + return ""; + } + function escapeRegExp(s) { + return s.replace(/[.*+?\^${}()|\[\]\\]/g, "\\$&").replace(/^[#\.:]+/, ""); + } + return string.replace( + new RegExp("(" + this.normalizedTerms.map(escapeRegExp).join("|") + ")", "gi"), + "$1" + ); + }; +}; +CrystalDocs.Query.normalizeTerm = function(term) { + return term.toLowerCase(); +}; +CrystalDocs.Query.stripModifiers = function(term) { + switch (term[0]) { + case "#": + case ".": + case ":": + return term.substr(1); + + default: + return term; + } +} + +CrystalDocs.search = function(string) { + if(!CrystalDocs.searchIndex) { + console.log("CrystalDocs search index not initialized, delaying search"); + + document.addEventListener("CrystalDocs:loaded", function listener(){ + document.removeEventListener("CrystalDocs:loaded", listener); + CrystalDocs.search(string); + }); + return; + } + + document.dispatchEvent(new Event("CrystalDocs:searchStarted")); + + var query = new CrystalDocs.Query(string); + var results = CrystalDocs.runQuery(query); + results = CrystalDocs.rankResults(results, query); + CrystalDocs.displaySearchResults(results, query); + + document.dispatchEvent(new Event("CrystalDocs:searchPerformed")); +}; + +CrystalDocs.initializeIndex = function(data) { + CrystalDocs.searchIndex = data; + + document.dispatchEvent(new Event("CrystalDocs:loaded")); +}; + +CrystalDocs.loadIndex = function() { + function loadJSON(file, callback) { + var xobj = new XMLHttpRequest(); + xobj.overrideMimeType("application/json"); + xobj.open("GET", file, true); + xobj.onreadystatechange = function() { + if (xobj.readyState == 4 && xobj.status == "200") { + callback(xobj.responseText); + } + }; + xobj.send(null); + } + + function loadScript(file) { + script = document.createElement("script"); + script.src = file; + document.body.appendChild(script); + } + + function parseJSON(json) { + CrystalDocs.initializeIndex(JSON.parse(json)); + } + + for(var i = 0; i < document.scripts.length; i++){ + var script = document.scripts[i]; + if (script.src && script.src.indexOf("js/doc.js") >= 0) { + if (script.src.indexOf("file://") == 0) { + // We need to support JSONP files for the search to work on local file system. + var jsonPath = script.src.replace("js/doc.js", "search-index.js"); + loadScript(jsonPath); + return; + } else { + var jsonPath = script.src.replace("js/doc.js", "index.json"); + loadJSON(jsonPath, parseJSON); + return; + } + } + } + console.error("Could not find location of js/doc.js"); +}; + +// Callback for jsonp +function crystal_doc_search_index_callback(data) { + CrystalDocs.initializeIndex(data); +} + +Navigator = function(sidebar, searchInput, list, leaveSearchScope){ + this.list = list; + var self = this; + + var performingSearch = false; + + document.addEventListener('CrystalDocs:searchStarted', function(){ + performingSearch = true; + }); + document.addEventListener('CrystalDocs:searchDebounceStarted', function(){ + performingSearch = true; + }); + document.addEventListener('CrystalDocs:searchPerformed', function(){ + performingSearch = false; + }); + document.addEventListener('CrystalDocs:searchDebounceStopped', function(event){ + performingSearch = false; + }); + + function delayWhileSearching(callback) { + if(performingSearch){ + document.addEventListener('CrystalDocs:searchPerformed', function listener(){ + document.removeEventListener('CrystalDocs:searchPerformed', listener); + + // add some delay to let search results display kick in + setTimeout(callback, 100); + }); + }else{ + callback(); + } + } + + function clearMoveTimeout() { + clearTimeout(self.moveTimeout); + self.moveTimeout = null; + } + + function startMoveTimeout(upwards){ + /*if(self.moveTimeout) { + clearMoveTimeout(); + } + + var go = function() { + if (!self.moveTimeout) return; + self.move(upwards); + self.moveTimeout = setTimeout(go, 600); + }; + self.moveTimeout = setTimeout(go, 800);*/ + } + + function scrollCenter(element) { + var rect = element.getBoundingClientRect(); + var middle = sidebar.clientHeight / 2; + sidebar.scrollTop += rect.top + rect.height / 2 - middle; + } + + var move = this.move = function(upwards){ + if(!this.current){ + this.highlightFirst(); + return true; + } + var next = upwards ? this.current.previousElementSibling : this.current.nextElementSibling; + if(next && next.classList) { + this.highlight(next); + scrollCenter(next); + return true; + } + return false; + }; + + this.moveRight = function(){ + }; + this.moveLeft = function(){ + }; + + this.highlight = function(elem) { + if(!elem){ + return; + } + this.removeHighlight(); + + this.current = elem; + this.current.classList.add("current"); + }; + + this.highlightFirst = function(){ + this.highlight(this.list.querySelector('li:first-child')); + }; + + this.removeHighlight = function() { + if(this.current){ + this.current.classList.remove("current"); + } + this.current = null; + } + + this.openSelectedResult = function() { + if(this.current) { + this.current.click(); + } + } + + this.focus = function() { + searchInput.focus(); + searchInput.select(); + this.highlightFirst(); + } + + function handleKeyUp(event) { + switch(event.key) { + case "ArrowUp": + case "ArrowDown": + case "i": + case "j": + case "k": + case "l": + case "c": + case "h": + case "t": + case "n": + event.stopPropagation(); + clearMoveTimeout(); + } + } + + function handleKeyDown(event) { + switch(event.key) { + case "Enter": + event.stopPropagation(); + event.preventDefault(); + leaveSearchScope(); + self.openSelectedResult(); + break; + case "Escape": + event.stopPropagation(); + event.preventDefault(); + leaveSearchScope(); + break; + case "j": + case "c": + case "ArrowUp": + if(event.ctrlKey || event.key == "ArrowUp") { + event.stopPropagation(); + self.move(true); + startMoveTimeout(true); + } + break; + case "k": + case "h": + case "ArrowDown": + if(event.ctrlKey || event.key == "ArrowDown") { + event.stopPropagation(); + self.move(false); + startMoveTimeout(false); + } + break; + case "k": + case "t": + case "ArrowLeft": + if(event.ctrlKey || event.key == "ArrowLeft") { + event.stopPropagation(); + self.moveLeft(); + } + break; + case "l": + case "n": + case "ArrowRight": + if(event.ctrlKey || event.key == "ArrowRight") { + event.stopPropagation(); + self.moveRight(); + } + break; + } + } + + function handleInputKeyUp(event) { + switch(event.key) { + case "ArrowUp": + case "ArrowDown": + event.stopPropagation(); + event.preventDefault(); + clearMoveTimeout(); + } + } + + function handleInputKeyDown(event) { + switch(event.key) { + case "Enter": + event.stopPropagation(); + event.preventDefault(); + delayWhileSearching(function(){ + self.openSelectedResult(); + leaveSearchScope(); + }); + break; + case "Escape": + event.stopPropagation(); + event.preventDefault(); + // remove focus from search input + leaveSearchScope(); + sidebar.focus(); + break; + case "ArrowUp": + event.stopPropagation(); + event.preventDefault(); + self.move(true); + startMoveTimeout(true); + break; + + case "ArrowDown": + event.stopPropagation(); + event.preventDefault(); + self.move(false); + startMoveTimeout(false); + break; + } + } + + sidebar.tabIndex = 100; // set tabIndex to enable keylistener + sidebar.addEventListener('keyup', function(event) { + handleKeyUp(event); + }); + sidebar.addEventListener('keydown', function(event) { + handleKeyDown(event); + }); + searchInput.addEventListener('keydown', function(event) { + handleInputKeyDown(event); + }); + searchInput.addEventListener('keyup', function(event) { + handleInputKeyUp(event); + }); + this.move(); +}; + +CrystalDocs.initializeVersions = function () { + function loadJSON(file, callback) { + var xobj = new XMLHttpRequest(); + xobj.overrideMimeType("application/json"); + xobj.open("GET", file, true); + xobj.onreadystatechange = function() { + if (xobj.readyState == 4 && xobj.status == "200") { + callback(xobj.responseText); + } + }; + xobj.send(null); + } + + function parseJSON(json) { + CrystalDocs.loadConfig(JSON.parse(json)); + } + + $elem = document.querySelector("html > head > meta[name=\"crystal_docs.json_config_url\"]") + if ($elem == undefined) { + return + } + jsonURL = $elem.getAttribute("content") + if (jsonURL && jsonURL != "") { + loadJSON(jsonURL, parseJSON); + } +} + +CrystalDocs.loadConfig = function (config) { + var projectVersions = config["versions"] + var currentVersion = document.querySelector("html > head > meta[name=\"crystal_docs.project_version\"]").getAttribute("content") + + var currentVersionInList = projectVersions.find(function (element) { + return element.name == currentVersion + }) + + if (!currentVersionInList) { + projectVersions.unshift({ name: currentVersion, url: '#' }) + } + + $version = document.querySelector(".project-summary > .project-version") + $version.innerHTML = "" + + $select = document.createElement("select") + $select.classList.add("project-versions-nav") + $select.addEventListener("change", function () { + window.location.href = this.value + }) + projectVersions.forEach(function (version) { + $item = document.createElement("option") + $item.setAttribute("value", version.url) + $item.append(document.createTextNode(version.name)) + + if (version.name == currentVersion) { + $item.setAttribute("selected", true) + $item.setAttribute("disabled", true) + } + $select.append($item) + }); + $form = document.createElement("form") + $form.setAttribute("autocomplete", "off") + $form.append($select) + $version.append($form) +} + +document.addEventListener("DOMContentLoaded", function () { + CrystalDocs.initializeVersions() +}) + +var UsageModal = function(title, content) { + var $body = document.body; + var self = this; + var $modalBackground = document.createElement("div"); + $modalBackground.classList.add("modal-background"); + var $usageModal = document.createElement("div"); + $usageModal.classList.add("usage-modal"); + $modalBackground.appendChild($usageModal); + var $title = document.createElement("h3"); + $title.classList.add("modal-title"); + $title.innerHTML = title + $usageModal.appendChild($title); + var $closeButton = document.createElement("span"); + $closeButton.classList.add("close-button"); + $closeButton.setAttribute("title", "Close modal"); + $closeButton.innerText = '×'; + $usageModal.appendChild($closeButton); + $usageModal.insertAdjacentHTML("beforeend", content); + + $modalBackground.addEventListener('click', function(event) { + var element = event.target || event.srcElement; + + if(element == $modalBackground) { + self.hide(); + } + }); + $closeButton.addEventListener('click', function(event) { + self.hide(); + }); + + $body.insertAdjacentElement('beforeend', $modalBackground); + + this.show = function(){ + $body.classList.add("js-modal-visible"); + }; + this.hide = function(){ + $body.classList.remove("js-modal-visible"); + }; + this.isVisible = function(){ + return $body.classList.contains("js-modal-visible"); + } +} + + +document.addEventListener('DOMContentLoaded', function() { + var sessionStorage; + try { + sessionStorage = window.sessionStorage; + } catch (e) { } + if(!sessionStorage) { + sessionStorage = { + setItem: function() {}, + getItem: function() {}, + removeItem: function() {} + }; + } + + var repositoryName = document.querySelector('[name=repository-name]').getAttribute('content'); + var typesList = document.querySelector('.types-list'); + var searchInput = document.querySelector('.search-input'); + var parents = document.querySelectorAll('.types-list li.parent'); + + var scrollSidebarToOpenType = function(){ + var openTypes = typesList.querySelectorAll('.current'); + if (openTypes.length > 0) { + var lastOpenType = openTypes[openTypes.length - 1]; + lastOpenType.scrollIntoView(!(window.matchMedia('only screen and (max-width: 635px)')).matches); + } + } + + scrollSidebarToOpenType(); + + var setPersistentSearchQuery = function(value){ + sessionStorage.setItem(repositoryName + '::search-input:value', value); + } + + for(var i = 0; i < parents.length; i++) { + var _parent = parents[i]; + _parent.addEventListener('click', function(e) { + e.stopPropagation(); + + if(e.target.tagName.toLowerCase() == 'li') { + if(e.target.className.match(/open/)) { + sessionStorage.removeItem(e.target.getAttribute('data-id')); + e.target.className = e.target.className.replace(/ +open/g, ''); + } else { + sessionStorage.setItem(e.target.getAttribute('data-id'), '1'); + if(e.target.className.indexOf('open') == -1) { + e.target.className += ' open'; + } + } + } + }); + + if(sessionStorage.getItem(_parent.getAttribute('data-id')) == '1') { + _parent.className += ' open'; + } + } + + var leaveSearchScope = function(){ + CrystalDocs.toggleResultsList(false); + window.focus(); + } + + var navigator = new Navigator(document.querySelector('.types-list'), searchInput, document.querySelector(".search-results"), leaveSearchScope); + + CrystalDocs.loadIndex(); + var searchTimeout; + var lastSearchText = false; + var performSearch = function() { + document.dispatchEvent(new Event("CrystalDocs:searchDebounceStarted")); + + clearTimeout(searchTimeout); + searchTimeout = setTimeout(function() { + var text = searchInput.value; + + if(text == "") { + CrystalDocs.toggleResultsList(false); + }else if(text == lastSearchText){ + document.dispatchEvent(new Event("CrystalDocs:searchDebounceStopped")); + }else{ + CrystalDocs.search(text); + navigator.highlightFirst(); + searchInput.focus(); + } + lastSearchText = text; + setPersistentSearchQuery(text); + }, 200); + }; + + if(location.hash.length > 3 && location.hash.substring(0,3) == "#q="){ + // allows directly linking a search query which is then executed on the client + // this comes handy for establishing a custom browser search engine with https://crystal-lang.org/api/#q=%s as a search URL + // TODO: Add OpenSearch description + var searchQuery = location.hash.substring(3); + history.pushState({searchQuery: searchQuery}, "Search for " + searchQuery, location.href.replace(/#q=.*/, "")); + searchInput.value = searchQuery; + document.addEventListener('CrystalDocs:loaded', performSearch); + } + + if (searchInput.value.length == 0) { + var searchText = sessionStorage.getItem(repositoryName + '::search-input:value'); + if(searchText){ + searchInput.value = searchText; + } + } + searchInput.addEventListener('keyup', performSearch); + searchInput.addEventListener('input', performSearch); + + var usageModal = new UsageModal('Keyboard Shortcuts', '' + + '
    ' + + '
  • ' + + ' ' + + ' s,' + + ' /' + + ' ' + + ' Search' + + '
  • ' + + '
  • ' + + ' Esc' + + ' Abort search / Close modal' + + '
  • ' + + '
  • ' + + ' ' + + ' ,' + + ' Enter' + + ' ' + + ' Open highlighted result' + + '
  • ' + + '
  • ' + + ' ' + + ' ,' + + ' Ctrl+j' + + ' ' + + ' Select previous result' + + '
  • ' + + '
  • ' + + ' ' + + ' ,' + + ' Ctrl+k' + + ' ' + + ' Select next result' + + '
  • ' + + '
  • ' + + ' ?' + + ' Show usage info' + + '
  • ' + + '
' + ); + + function handleShortkeys(event) { + var element = event.target || event.srcElement; + + if(element.tagName == "INPUT" || element.tagName == "TEXTAREA" || element.parentElement.tagName == "TEXTAREA"){ + return; + } + + switch(event.key) { + case "?": + usageModal.show(); + break; + + case "Escape": + usageModal.hide(); + break; + + case "s": + case "/": + if(usageModal.isVisible()) { + return; + } + event.stopPropagation(); + navigator.focus(); + performSearch(); + break; + } + } + + document.addEventListener('keyup', handleShortkeys); + + var scrollToEntryFromLocationHash = function() { + var hash = window.location.hash; + if (hash) { + var targetAnchor = decodeURI(hash.substr(1)); + var targetEl = document.getElementById(targetAnchor) + if (targetEl) { + targetEl.offsetParent.scrollTop = targetEl.offsetTop; + } + } + }; + window.addEventListener("hashchange", scrollToEntryFromLocationHash, false); + scrollToEntryFromLocationHash(); +}); diff --git a/search-index.js b/search-index.js new file mode 100644 index 0000000..f9400a0 --- /dev/null +++ b/search-index.js @@ -0,0 +1 @@ +crystal_doc_search_index_callback({"repository_name":"geo","body":"# Geo\n\n![Crystal CI](https://github.com/geocrystal/geo/workflows/Crystal%20CI/badge.svg)\n[![GitHub release](https://img.shields.io/github/release/geocrystal/geo.svg)](https://github.com/geocrystal/geo/releases)\n[![Docs](https://img.shields.io/badge/docs-available-brightgreen.svg)](https://geocrystal.github.io/geo/)\n[![License](https://img.shields.io/github/license/geocrystal/geo.svg)](https://github.com/geocrystal/geo/blob/master/LICENSE)\n\nGeospatial primitives, algorithms, and utilities for Crystal.\n\n## Installation\n\nAdd this to your application's `shard.yml`:\n\n```yaml\ndependencies:\n geo:\n github: geocrystal/geo\n```\n\nRun `shards install`\n\n## Usage\n\nA `Geo::Coord` is a point in geographical coordinates: latitude and longitude.\n\n```crystal\nrequire \"geo\"\n\nc = Geo::Coord.new(50.004444, 36.231389)\n\nc.strfcoord(%{%latd %latm' %0.1lats\" %lath, %lngd %lngm' %0.1lngs\" %lngh})\n# => \"50 0' 16.0\" N, 36 13' 53.0\" E\"\n\nc.strfcoord(\"%lat,%lng\")\n# => \"-50.004444,-36.231389\"\n\nc.to_s\n# => \"50°0'16\"N 36°13'53\"E\"\n\npos = Geo::Coord.new(50.004444, 36.231389)\n\npos.geohash\n# => \"ubcu2rnbuxcx\"\n\npos.geohash(5)\n# => \"ubcu2\"\n```\n\n### Polygon\n\nA polygon represents an area enclosed by a closed path (or loop), which is defined by a series of coordinates.\n\n```crystal\nrequire \"geo\"\n\npos1 = Geo::Coord.new(45.3142533036254, -93.47527313511819)\npos2 = Geo::Coord.new(45.31232182518015, -93.34893036168069)\npos3 = Geo::Coord.new(45.23694281999268, -93.35167694371194)\npos4 = Geo::Coord.new(45.23500870841669, -93.47801971714944)\n\npolygon = Geo::Polygon.new([pos1, pos2, pos3, pos4])\n```\n\nThe Polygon in the example above consists of four sets of `Geo::Coord` coordinates, but notice that the first and last sets define the same location, which completes the loop. In practice, however, since polygons define closed areas, you don't need to specify the last set of coordinates. Ot will automatically complete the polygon by connecting the last location back to the first location.\n\nThe following example is identical to the previous one, except that the last `Geo::Coord` is omitted:\n\n```crystal\nrequire \"geo\"\n\npos1 = Geo::Coord.new(45.3142533036254, -93.47527313511819)\npos2 = Geo::Coord.new(45.31232182518015, -93.34893036168069)\npos3 = Geo::Coord.new(45.23694281999268, -93.35167694371194)\n\npolygon = Geo::Polygon.new([pos1, pos2, pos3])\n```\n\nAdditional actions:\n\n```crystal\ncoord_inside = Geo::Coord.new(45.27428243796789, -93.41648483416066)\ncoord_outside = Geo::Coord.new(45.45411010558687, -93.78151703160256)\n\npolygon.contains?(coord_inside) # => true\npolygon.contains?(coord_outside) # => false\n\npolygon.centroid # => Geo::Coord(@lat=45.27463866133501, @lng=-93.41400121829719)\n```\n\nAdditionally you can initialize polygon as [convex hull](https://en.wikipedia.org/wiki/Convex_hull) from coordinates of points.\n\n```crystal\npoints = [\n {1.0, 1.0},\n {1.0, 0.0},\n {1.0, -1.0},\n {0.0, -1.0},\n {-1.0, -1.0},\n {-1.0, 0.0},\n {-1.0, 1.0},\n {0.0, 1.0},\n {0.0, 0.0},\n].map { |point| Geo::Coord.new(point[0], point[1]) }\n\npolygon = Geo::Polygon.new(points, convex_hull: true)\npolygon.coords\n# => {-1.0, -1.0}, {1.0, -1.0}, {1.0, 1.0}, {-1.0, 1.0}, {-1.0, -1.0}\n```\n\nThe convex hull is computed using the [convex_hull](https://github.com/geocrystal/convex_hull) library.\n\n### Formatting\n\n`Geo::Coord#strfcoord` formats coordinates according to directives.\n\nEach directive starts with `%` and can contain some modifiers before its name.\n\nAcceptable modifiers:\n\n- unsigned integers: none;\n- signed integers: `+` for mandatory sign printing;\n- floats: same as integers and number of digits modifier, like `0.3`.\n\nList of directives:\n\n| Directive | Description |\n| --------- | ------------------------------------------- |\n| `%lat` | Full latitude, floating point, signed |\n| `%latds` | Latitude degrees, integer, signed |\n| `%latd` | Latitude degrees, integer, unsigned |\n| `%latm` | Latitude minutes, integer, unsigned |\n| `%lats` | Latitude seconds, floating point, unsigned |\n| `%lath` | Latitude hemisphere, \"N\" or \"S\" |\n| `%lng` | Full longitude, floating point, signed |\n| `%lngds` | Longitude degrees, integer, signed |\n| `%lngd` | Longitude degrees, integer, unsigned |\n| `%lngm` | Longitude minutes, integer, unsigned |\n| `lngs` | Longitude seconds, floating point, unsigned |\n| `%lngh` | Longitude hemisphere, \"E\" or \"W\" |\n\nExamples:\n\n```crystal\ng = Geo::Coord.new(50.004444, 36.231389)\ng.strfcoord('%+lat, %+lng')\n# => \"+50.004444, +36.231389\"\ng.strfcoord(\"%latd°%latm'%lath -- %lngd°%lngm'%lngh\")\n# => \"50°0'N -- 36°13'E\"\n```\n\n`strfcoord` handles seconds rounding implicitly:\n\n```crystal\npos = Geo::Coord.new(0.033333, 91.333333)\npos.strfcoord('%latd %latm %0.5lats') # => \"0 1 59.99880\"\npos.strfcoord('%latd %latm %lats') # => \"0 2 0\"\n```\n\n### Calculate distances between two coords\n\nHaversine formula from [haversine](https://github.com/geocrystal/haversine) shard is used.\n\n```crystal\nrequire \"geo\"\nrequire \"geo/distance\"\n\nlondon = Geo::Coord.new(51.500153, -0.126236)\nnew_york = Geo::Coord.new(40.714268, -74.005974)\n\nnew_york.distance(london).to_kilometers\n# => 5570.4744596620685\n```\n\n### Calculates the location of a destination coord\n\n```crystal\nrequire \"geo\"\nrequire \"geo/distance\"\n\npoint = Geo::Coord.new(39, -75)\n\npoint.destination(5000, 90, :kilometers)\n# Geo::Coord(@lat=26.440010707631124, @lng=-22.885355549364313)\n```\n\n\n## Contributing\n\n1. Fork it ()\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create a new Pull Request\n\n## Contributors\n\n- [Anton Maminov](https://github.com/mamantoha) - creator and maintainer\n","program":{"html_id":"geo/toplevel","path":"toplevel.html","kind":"module","full_name":"Top Level Namespace","name":"Top Level Namespace","abstract":false,"locations":[],"repository_name":"geo","program":true,"enum":false,"alias":false,"const":false,"types":[{"html_id":"geo/Geo","path":"Geo.html","kind":"module","full_name":"Geo","name":"Geo","abstract":false,"locations":[{"filename":"lib/geo_bearing/src/geo_bearing.cr","line_number":1,"url":null},{"filename":"src/geo.cr","line_number":12,"url":null},{"filename":"src/geo/bearing.cr","line_number":1,"url":null},{"filename":"src/geo/coord.cr","line_number":1,"url":null},{"filename":"src/geo/distance.cr","line_number":1,"url":null},{"filename":"src/geo/polygon.cr","line_number":1,"url":null},{"filename":"src/geo/utils.cr","line_number":1,"url":null}],"repository_name":"geo","program":false,"enum":false,"alias":false,"const":false,"constants":[{"id":"DISTANCE_UNITS","name":"DISTANCE_UNITS","value":"Haversine::FACTORS.keys"},{"id":"VERSION","name":"VERSION","value":"{{ (`shards version /__w/geo/geo/src`).chomp.stringify }}"}],"types":[{"html_id":"geo/Geo/Coord","path":"Geo/Coord.html","kind":"struct","full_name":"Geo::Coord","name":"Coord","abstract":false,"superclass":{"html_id":"geo/Struct","kind":"struct","full_name":"Struct","name":"Struct"},"ancestors":[{"html_id":"geo/Comparable","kind":"module","full_name":"Comparable","name":"Comparable"},{"html_id":"geo/Struct","kind":"struct","full_name":"Struct","name":"Struct"},{"html_id":"geo/Value","kind":"struct","full_name":"Value","name":"Value"},{"html_id":"geo/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/geo/bearing.cr","line_number":2,"url":null},{"filename":"src/geo/coord.cr","line_number":3,"url":null},{"filename":"src/geo/distance.cr","line_number":2,"url":null}],"repository_name":"geo","program":false,"enum":false,"alias":false,"const":false,"constants":[{"id":"DIRECTIVES","name":"DIRECTIVES","value":"{/%(#{FLOATUFLAGS})?lats/ => ->(m : Regex::MatchData) do\n \"%#{m[1]? || \"0.\"}f\"\nend, \"%latm\" => \"%i\", /%(#{INTFLAGS})?latds/ => ->(m : Regex::MatchData) do\n \"%#{m[1]}i\"\nend, \"%latd\" => \"%i\", \"%lath\" => \"%s\", /%(#{FLOATFLAGS})?lat/ => ->(m : Regex::MatchData) do\n \"%#{m[1]}f\"\nend, /%(#{FLOATUFLAGS})?lngs/ => ->(m : Regex::MatchData) do\n \"%#{m[1]? || \"0.\"}f\"\nend, \"%lngm\" => \"%i\", /%(#{INTFLAGS})?lngds/ => ->(m : Regex::MatchData) do\n \"%#{m[1]}i\"\nend, \"%lngd\" => \"%i\", \"%lngh\" => \"%s\", /%(#{FLOATFLAGS})?lng/ => ->(m : Regex::MatchData) do\n \"%#{m[1]}f\"\nend}"},{"id":"FLOATFLAGS","name":"FLOATFLAGS","value":"/\\+?#{FLOATUFLAGS}?/"},{"id":"FLOATUFLAGS","name":"FLOATUFLAGS","value":"/0\\.\\d+/"},{"id":"INTFLAGS","name":"INTFLAGS","value":"/\\+?/"}],"included_modules":[{"html_id":"geo/Comparable","kind":"module","full_name":"Comparable","name":"Comparable"}],"namespace":{"html_id":"geo/Geo","kind":"module","full_name":"Geo","name":"Geo"},"doc":"A `Coord` is a point in geographical coordinates: latitude and longitude.","summary":"

A Coord is a point in geographical coordinates: latitude and longitude.

","constructors":[{"html_id":"new(lat:Number,lng:Number)-class-method","name":"new","abstract":false,"args":[{"name":"lat","external_name":"lat","restriction":"Number"},{"name":"lng","external_name":"lng","restriction":"Number"}],"args_string":"(lat : Number, lng : Number)","args_html":"(lat : Number, lng : Number)","location":{"filename":"src/geo/coord.cr","line_number":32,"url":null},"def":{"name":"new","args":[{"name":"lat","external_name":"lat","restriction":"Number"},{"name":"lng","external_name":"lng","restriction":"Number"}],"visibility":"Public","body":"_ = allocate\n_.initialize(lat, lng)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"<=>(other:Geo::Coord)-instance-method","name":"<=>","doc":"The comparison operator. Returns `0` if the two objects are equal,\na negative number if this object is considered less than *other*,\na positive number if this object is considered greater than *other*,\nor `nil` if the two objects are not comparable.\n\nSubclasses define this method to provide class-specific ordering.\n\nThe comparison operator is usually used to sort values:\n\n```\n# Sort in a descending way:\n[3, 1, 2].sort { |x, y| y <=> x } # => [3, 2, 1]\n\n# Sort in an ascending way:\n[3, 1, 2].sort { |x, y| x <=> y } # => [1, 2, 3]\n```","summary":"

The comparison operator.

","abstract":false,"args":[{"name":"other","external_name":"other","restriction":"Geo::Coord"}],"args_string":"(other : Geo::Coord)","args_html":"(other : Geo::Coord)","location":{"filename":"src/geo/coord.cr","line_number":177,"url":null},"def":{"name":"<=>","args":[{"name":"other","external_name":"other","restriction":"Geo::Coord"}],"visibility":"Public","body":"ll <=> other.ll"}},{"html_id":"bearing(to:Geo::Coord,final=false):Float64-instance-method","name":"bearing","doc":"Calculates initial and final bearings between two points using great-circle distance formulas","summary":"

Calculates initial and final bearings between two points using great-circle distance formulas

","abstract":false,"args":[{"name":"to","external_name":"to","restriction":"Geo::Coord"},{"name":"final","default_value":"false","external_name":"final","restriction":""}],"args_string":"(to : Geo::Coord, final = false) : Float64","args_html":"(to : Geo::Coord, final = false) : Float64","location":{"filename":"src/geo/bearing.cr","line_number":4,"url":null},"def":{"name":"bearing","args":[{"name":"to","external_name":"to","restriction":"Geo::Coord"},{"name":"final","default_value":"false","external_name":"final","restriction":""}],"return_type":"Float64","visibility":"Public","body":"Geo::Bearing.bearing(lat, lng, to.lat, to.lng, final)"}},{"html_id":"between?(p1:Geo::Coord,p2:Geo::Coord)-instance-method","name":"between?","abstract":false,"args":[{"name":"p1","external_name":"p1","restriction":"Geo::Coord"},{"name":"p2","external_name":"p2","restriction":"Geo::Coord"}],"args_string":"(p1 : Geo::Coord, p2 : Geo::Coord)","args_html":"(p1 : Geo::Coord, p2 : Geo::Coord)","location":{"filename":"src/geo/coord.cr","line_number":181,"url":null},"def":{"name":"between?","args":[{"name":"p1","external_name":"p1","restriction":"Geo::Coord"},{"name":"p2","external_name":"p2","restriction":"Geo::Coord"}],"visibility":"Public","body":"min, max = [p1, p2].minmax\nif cmp = self <=> min\n if cmp < 0\n return false\n end\nend\nif cmp = self <=> max\n if cmp > 0\n return false\n end\nend\ntrue\n"}},{"html_id":"destination(distance:Number,bearing:Number,unit:Symbol=:kilometers):Geo::Coord-instance-method","name":"destination","doc":"Calculates the location of a destination point","summary":"

Calculates the location of a destination point

","abstract":false,"args":[{"name":"distance","external_name":"distance","restriction":"Number"},{"name":"bearing","external_name":"bearing","restriction":"Number"},{"name":"unit","default_value":":kilometers","external_name":"unit","restriction":"Symbol"}],"args_string":"(distance : Number, bearing : Number, unit : Symbol = :kilometers) : Geo::Coord","args_html":"(distance : Number, bearing : Number, unit : Symbol = :kilometers) : Geo::Coord","location":{"filename":"src/geo/distance.cr","line_number":10,"url":null},"def":{"name":"destination","args":[{"name":"distance","external_name":"distance","restriction":"Number"},{"name":"bearing","external_name":"bearing","restriction":"Number"},{"name":"unit","default_value":":kilometers","external_name":"unit","restriction":"Symbol"}],"return_type":"Geo::Coord","visibility":"Public","body":"point = Haversine.destination(self.ll, distance, bearing, unit)\nGeo::Coord.new(point[0], point[1])\n"}},{"html_id":"distance(other:Geo::Coord):Haversine::Distance-instance-method","name":"distance","doc":"Calculates distance to `other`.\nHaversine formula is used.","summary":"

Calculates distance to other.

","abstract":false,"args":[{"name":"other","external_name":"other","restriction":"Geo::Coord"}],"args_string":"(other : Geo::Coord) : Haversine::Distance","args_html":"(other : Geo::Coord) : Haversine::Distance","location":{"filename":"src/geo/distance.cr","line_number":5,"url":null},"def":{"name":"distance","args":[{"name":"other","external_name":"other","restriction":"Geo::Coord"}],"return_type":"Haversine::Distance","visibility":"Public","body":"Haversine.distance(self.ll, other.ll)"}},{"html_id":"geohash(precision=12)-instance-method","name":"geohash","doc":"Returns a geohash representing coordinates.","summary":"

Returns a geohash representing coordinates.

","abstract":false,"args":[{"name":"precision","default_value":"12","external_name":"precision","restriction":""}],"args_string":"(precision = 12)","args_html":"(precision = 12)","location":{"filename":"src/geo/coord.cr","line_number":155,"url":null},"def":{"name":"geohash","args":[{"name":"precision","default_value":"12","external_name":"precision","restriction":""}],"visibility":"Public","body":"Geohash.encode(lat.to_f, lng.to_f, precision)"}},{"html_id":"lat:Float32|Float64|Int32-instance-method","name":"lat","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":8,"url":null},"def":{"name":"lat","visibility":"Public","body":"@lat"}},{"html_id":"latd:Int32-instance-method","name":"latd","doc":"Returns latitude degrees","summary":"

Returns latitude degrees

","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":36,"url":null},"def":{"name":"latd","return_type":"Int32","visibility":"Public","body":"lat.abs.to_i"}},{"html_id":"latds-instance-method","name":"latds","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":75,"url":null},"def":{"name":"latds","visibility":"Public","body":"lat.to_i"}},{"html_id":"lath:String-instance-method","name":"lath","doc":"Returns latitude hemisphere","summary":"

Returns latitude hemisphere

","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":51,"url":null},"def":{"name":"lath","return_type":"String","visibility":"Public","body":"lat > 0 ? \"N\" : \"S\""}},{"html_id":"latm:Int32-instance-method","name":"latm","doc":"Returns latitude minutes","summary":"

Returns latitude minutes

","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":41,"url":null},"def":{"name":"latm","return_type":"Int32","visibility":"Public","body":"(lat.abs * 60).to_i % 60"}},{"html_id":"lats:Number-instance-method","name":"lats","doc":"Returns latitude seconds","summary":"

Returns latitude seconds

","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":46,"url":null},"def":{"name":"lats","return_type":"Number","visibility":"Public","body":"(lat.abs * 3600) % 60"}},{"html_id":"ll-instance-method","name":"ll","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":173,"url":null},"def":{"name":"ll","visibility":"Public","body":"{lat, lng}"}},{"html_id":"lng:Float32|Float64|Int32-instance-method","name":"lng","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":9,"url":null},"def":{"name":"lng","visibility":"Public","body":"@lng"}},{"html_id":"lngd:Int32-instance-method","name":"lngd","doc":"Returns longitude degrees","summary":"

Returns longitude degrees

","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":56,"url":null},"def":{"name":"lngd","return_type":"Int32","visibility":"Public","body":"lng.abs.to_i"}},{"html_id":"lngds-instance-method","name":"lngds","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":79,"url":null},"def":{"name":"lngds","visibility":"Public","body":"lng.to_i"}},{"html_id":"lngh:String-instance-method","name":"lngh","doc":"Returns longitude hemisphere","summary":"

Returns longitude hemisphere

","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":71,"url":null},"def":{"name":"lngh","return_type":"String","visibility":"Public","body":"lng > 0 ? \"E\" : \"W\""}},{"html_id":"lngm:Int32-instance-method","name":"lngm","doc":"Returns longitude minutes","summary":"

Returns longitude minutes

","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":61,"url":null},"def":{"name":"lngm","return_type":"Int32","visibility":"Public","body":"(lng.abs * 60).to_i % 60"}},{"html_id":"lngs:Number-instance-method","name":"lngs","doc":"Returns longitude seconds","summary":"

Returns longitude seconds

","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":66,"url":null},"def":{"name":"lngs","return_type":"Number","visibility":"Public","body":"(lng.abs * 3600) % 60"}},{"html_id":"strfcoord(formatstr):String-instance-method","name":"strfcoord","doc":"Formats coordinates according to directives in `formatstr`.\n\nEach directive starts with `%` and can contain some modifiers before its name.\n\nAcceptable modifiers:\n- unsigned integers: none;\n- signed integers: `+` for mandatory sign printing;\n- floats: same as integers and number of digits modifier, like `0.3`.\n\nList of directives:\n\n- `%lat` - Full latitude, floating point, signed\n- `%latds` - Latitude degrees, integer, signed\n- `%latd` - Latitude degrees, integer, unsigned\n- `%latm` - Latitude minutes, integer, unsigned\n- `%lats` - Latitude seconds, floating point, unsigned\n- `%lath` - Latitude hemisphere, \"N\" or \"S\"\n- `%lng` - Full longitude, floating point, signed\n- `%lngds` - Longitude degrees, integer, signed\n- `%lngd` - Longitude degrees, integer, unsigned\n- `%lngm` - Longitude minutes, integer, unsigned\n- `lngs` - Longitude seconds, floating point, unsigned\n- `%lngh`` - Longitude hemisphere, \"E\" or \"W\"\n\nExamples:\n\n```\ng = Geo::Coord.new(50.004444, 36.231389)\ng.strfcoord('%+lat, %+lng')\n# => \"+50.004444, +36.231389\"\ng.strfcoord(\"%latd°%latm'%lath -- %lngd°%lngm'%lngh\")\n# => \"50°0'N -- 36°13'E\"\n```\n\n`strfcoord` handles seconds rounding implicitly:\n\n```\npos = Geo::Coord.new(0.033333, 91.333333)\npos.strfcoord('%latd %latm %0.5lats') # => \"0 1 59.99880\"\npos.strfcoord('%latd %latm %lats') # => \"0 2 0\"\n```","summary":"

Formats coordinates according to directives in formatstr.

","abstract":false,"args":[{"name":"formatstr","external_name":"formatstr","restriction":""}],"args_string":"(formatstr) : String","args_html":"(formatstr) : String","location":{"filename":"src/geo/coord.cr","line_number":124,"url":null},"def":{"name":"strfcoord","args":[{"name":"formatstr","external_name":"formatstr","restriction":""}],"return_type":"String","visibility":"Public","body":"h = full_hash\nDIRECTIVES.reduce(formatstr) do |memo, __temp_52|\n from, to = __temp_52\n memo.gsub(from) do\n to = if (to.is_a?(Proc) && from.is_a?(Regex)) && (match_data = memo.match(from))\n to.call(match_data)\n else\n to.as(String)\n end\n res = to % h\n if tmp = guard_seconds(to, res)\n res, carrymin = tmp\n if carrymin.empty?\n else\n if h[carrymin].is_a?(Int32)\n tmp = h[carrymin].as(Int32)\n h[carrymin] = tmp + 1\n end\n end\n end\n res\n end\nend\n"}},{"html_id":"to_geojson:GeoJSON::Coordinates-instance-method","name":"to_geojson","abstract":false,"location":{"filename":"src/geo/coord.cr","line_number":159,"url":null},"def":{"name":"to_geojson","return_type":"GeoJSON::Coordinates","visibility":"Public","body":"GeoJSON::Coordinates.new(lng.to_f64, lat.to_f64)"}},{"html_id":"to_s(io)-instance-method","name":"to_s","doc":"Returns a string representing coordinates.\n\n```\ng.to_s # => \"50°0'16\\\"N 36°13'53\\\"E\"\ng.to_s(dms: false) # => \"50.004444,36.231389\"\n```","summary":"

Returns a string representing coordinates.

","abstract":false,"args":[{"name":"io","external_name":"io","restriction":""}],"args_string":"(io)","args_html":"(io)","location":{"filename":"src/geo/coord.cr","line_number":169,"url":null},"def":{"name":"to_s","args":[{"name":"io","external_name":"io","restriction":""}],"visibility":"Public","body":"io << (strfcoord(\"%latd°%latm'%lats\\\"%lath %lngd°%lngm'%lngs\\\"%lngh\"))"}}],"types":[{"html_id":"geo/Geo/Coord/Number","path":"Geo/Coord/Number.html","kind":"alias","full_name":"Geo::Coord::Number","name":"Number","abstract":false,"locations":[{"filename":"src/geo/coord.cr","line_number":6,"url":null}],"repository_name":"geo","program":false,"enum":false,"alias":true,"aliased":"(Float32 | Float64 | Int32)","aliased_html":"Float32 | Float64 | Int32","const":false,"namespace":{"html_id":"geo/Geo/Coord","kind":"struct","full_name":"Geo::Coord","name":"Coord"}}]},{"html_id":"geo/Geo/Polygon","path":"Geo/Polygon.html","kind":"struct","full_name":"Geo::Polygon","name":"Polygon","abstract":false,"superclass":{"html_id":"geo/Struct","kind":"struct","full_name":"Struct","name":"Struct"},"ancestors":[{"html_id":"geo/Indexable","kind":"module","full_name":"Indexable","name":"Indexable"},{"html_id":"geo/Enumerable","kind":"module","full_name":"Enumerable","name":"Enumerable"},{"html_id":"geo/Iterable","kind":"module","full_name":"Iterable","name":"Iterable"},{"html_id":"geo/Struct","kind":"struct","full_name":"Struct","name":"Struct"},{"html_id":"geo/Value","kind":"struct","full_name":"Value","name":"Value"},{"html_id":"geo/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/geo/polygon.cr","line_number":5,"url":null}],"repository_name":"geo","program":false,"enum":false,"alias":false,"const":false,"included_modules":[{"html_id":"geo/Indexable","kind":"module","full_name":"Indexable","name":"Indexable"}],"namespace":{"html_id":"geo/Geo","kind":"module","full_name":"Geo","name":"Geo"},"doc":"A `Polygon` is a fixed-size, immutable, stack-allocated sequence of `Geo::Coord`.\nCoordinates are in lexicographical order.\nAdditionally, polygons form a closed loop and define a filled region.","summary":"

A Polygon is a fixed-size, immutable, stack-allocated sequence of Geo::Coord.

","constructors":[{"html_id":"new(coords:Array(Geo::Coord),convex_hull=false)-class-method","name":"new","abstract":false,"args":[{"name":"coords","external_name":"coords","restriction":"Array(Geo::Coord)"},{"name":"convex_hull","default_value":"false","external_name":"convex_hull","restriction":""}],"args_string":"(coords : Array(Geo::Coord), convex_hull = false)","args_html":"(coords : Array(Geo::Coord), convex_hull = false)","location":{"filename":"src/geo/polygon.cr","line_number":11,"url":null},"def":{"name":"new","args":[{"name":"coords","external_name":"coords","restriction":"Array(Geo::Coord)"},{"name":"convex_hull","default_value":"false","external_name":"convex_hull","restriction":""}],"visibility":"Public","body":"_ = allocate\n_.initialize(coords, convex_hull)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"==(other:Geo::Polygon):Bool-instance-method","name":"==","abstract":false,"args":[{"name":"other","external_name":"other","restriction":"Geo::Polygon"}],"args_string":"(other : Geo::Polygon) : Bool","args_html":"(other : Geo::Polygon) : Bool","location":{"filename":"src/geo/polygon.cr","line_number":93,"url":null},"def":{"name":"==","args":[{"name":"other","external_name":"other","restriction":"Geo::Polygon"}],"return_type":"Bool","visibility":"Public","body":"min_size = Math.min(size, other.size)\n0.upto(min_size - 1) do |i|\n if self[i] == other[i]\n else\n return false\n end\nend\nsize == other.size\n"}},{"html_id":"area-instance-method","name":"area","doc":"Return the approximate signed geodesic area of the polygon in square meters.","summary":"

Return the approximate signed geodesic area of the polygon in square meters.

","abstract":false,"location":{"filename":"src/geo/polygon.cr","line_number":29,"url":null},"def":{"name":"area","visibility":"Public","body":"coordinates = @coords.map do |coord|\n [coord.lng, coord.lat]\nend\nRingArea.ring_area(coordinates)\n"}},{"html_id":"centroid:Geo::Coord-instance-method","name":"centroid","abstract":false,"location":{"filename":"src/geo/polygon.cr","line_number":83,"url":null},"def":{"name":"centroid","return_type":"Geo::Coord","visibility":"Public","body":"@centroid || (@centroid = calculate_centroid)"}},{"html_id":"contains?(coord:Geo::Coord):Bool-instance-method","name":"contains?","abstract":false,"args":[{"name":"coord","external_name":"coord","restriction":"Geo::Coord"}],"args_string":"(coord : Geo::Coord) : Bool","args_html":"(coord : Geo::Coord) : Bool","location":{"filename":"src/geo/polygon.cr","line_number":63,"url":null},"def":{"name":"contains?","args":[{"name":"coord","external_name":"coord","restriction":"Geo::Coord"}],"return_type":"Bool","visibility":"Public","body":"last_coord = @coords.last\nodd_nodes = false\ny, x = coord.ll\n@coords.each do |iter_coord|\n yi, xi = iter_coord.ll\n yj, xj = last_coord.ll\n if (yi < y && yj >= y) || (yj < y && yi >= y)\n if (xi + (((y - yi) / (yj - yi)) * (xj - xi))) < x\n odd_nodes = !odd_nodes\n end\n end\n last_coord = iter_coord\nend\nodd_nodes\n"}},{"html_id":"coords:Array(Geo::Coord)-instance-method","name":"coords","abstract":false,"location":{"filename":"src/geo/polygon.cr","line_number":24,"url":null},"def":{"name":"coords","visibility":"Public","body":"@coords"}},{"html_id":"size:Int32-instance-method","name":"size","doc":"Returns the number of elements in this container.","summary":"

Returns the number of elements in this container.

","abstract":false,"location":{"filename":"src/geo/polygon.cr","line_number":9,"url":null},"def":{"name":"size","return_type":"Int32","visibility":"Public","body":"@size"}},{"html_id":"to_geojson:GeoJSON::Polygon-instance-method","name":"to_geojson","abstract":false,"location":{"filename":"src/geo/polygon.cr","line_number":103,"url":null},"def":{"name":"to_geojson","return_type":"GeoJSON::Polygon","visibility":"Public","body":"coordinates = @coords.map do |coord|\n GeoJSON::Coordinates.new(coord.lng.to_f64, coord.lat.to_f64)\nend\nGeoJSON::Polygon.new([coordinates])\n"}},{"html_id":"unsafe_fetch(index:Int)-instance-method","name":"unsafe_fetch","doc":"Returns the element at the given *index*, without doing any bounds check.\n\n`Indexable` makes sure to invoke this method with *index* in `0...size`,\nso converting negative indices to positive ones is not needed here.\n\nClients never invoke this method directly. Instead, they access\nelements with `#[](index)` and `#[]?(index)`.\n\nThis method should only be directly invoked if you are absolutely\nsure the index is in bounds, to avoid a bounds check for a small boost\nof performance.","summary":"

Returns the element at the given index, without doing any bounds check.

","abstract":false,"args":[{"name":"index","external_name":"index","restriction":"Int"}],"args_string":"(index : Int)","args_html":"(index : Int)","location":{"filename":"src/geo/polygon.cr","line_number":89,"url":null},"def":{"name":"unsafe_fetch","args":[{"name":"index","external_name":"index","restriction":"Int"}],"visibility":"Public","body":"@coords[index]"}}]},{"html_id":"geo/Geo/Utils","path":"Geo/Utils.html","kind":"module","full_name":"Geo::Utils","name":"Utils","abstract":false,"locations":[{"filename":"src/geo/utils.cr","line_number":2,"url":null}],"repository_name":"geo","program":false,"enum":false,"alias":false,"const":false,"extended_modules":[{"html_id":"geo/Geo/Utils","kind":"module","full_name":"Geo::Utils","name":"Utils"}],"namespace":{"html_id":"geo/Geo","kind":"module","full_name":"Geo","name":"Geo"},"instance_methods":[{"html_id":"orientation(p:Geo::Coord,q:Geo::Coord,r:Geo::Coord)-instance-method","name":"orientation","doc":"Orientation of ordered triplet (p, q, r)\n\nOrientation of an ordered triplet of points in the plane can be\n\n* counterclockwise\n* clockwise\n* colinear\n\nThe function returns following values\n0 --> p, q and r are colinear\n1 --> Clockwise\n2 --> Counterclockwise","summary":"

Orientation of ordered triplet (p, q, r)

","abstract":false,"args":[{"name":"p","external_name":"p","restriction":"Geo::Coord"},{"name":"q","external_name":"q","restriction":"Geo::Coord"},{"name":"r","external_name":"r","restriction":"Geo::Coord"}],"args_string":"(p : Geo::Coord, q : Geo::Coord, r : Geo::Coord)","args_html":"(p : Geo::Coord, q : Geo::Coord, r : Geo::Coord)","location":{"filename":"src/geo/utils.cr","line_number":17,"url":null},"def":{"name":"orientation","args":[{"name":"p","external_name":"p","restriction":"Geo::Coord"},{"name":"q","external_name":"q","restriction":"Geo::Coord"},{"name":"r","external_name":"r","restriction":"Geo::Coord"}],"visibility":"Public","body":"val = ((q.lng - p.lng) * (r.lat - q.lat)) - ((q.lat - p.lat) * (r.lng - q.lng))\nif val == 0\n return 0\nend\nval > 0 ? 1 : 2\n"}}]}]}]}}) \ No newline at end of file