foliage 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +9 -0
- data/app/assets/images/.keep +0 -0
- data/app/assets/images/map/marker/icon-2x.png +0 -0
- data/app/assets/images/map/marker/icon.png +0 -0
- data/app/assets/images/map/marker/icon.svg +67 -0
- data/app/assets/images/map/marker/shadow.png +0 -0
- data/app/assets/javascripts/core_ext.js.coffee +61 -0
- data/app/assets/javascripts/foliage.js.coffee +23 -0
- data/app/assets/javascripts/foliage/band.js.coffee +99 -0
- data/app/assets/javascripts/foliage/bubbles.js.coffee +77 -0
- data/app/assets/javascripts/foliage/categories.js.coffee +70 -0
- data/app/assets/javascripts/foliage/choropleth.js.coffee +51 -0
- data/app/assets/javascripts/foliage/color.js.coffee +39 -0
- data/app/assets/javascripts/foliage/gradient.js.coffee +72 -0
- data/app/assets/javascripts/foliage/heatmap.js.coffee +49 -0
- data/app/assets/javascripts/foliage/leaf.js.coffee +422 -0
- data/app/assets/javascripts/foliage/path.js.coffee +76 -0
- data/app/assets/javascripts/foliage/paths.js.coffee +131 -0
- data/app/assets/javascripts/foliage/point_group.js.coffee +83 -0
- data/app/assets/javascripts/foliage/points.js.coffee +79 -0
- data/app/assets/javascripts/foliage/simple.js.coffee +35 -0
- data/app/assets/javascripts/leaflet/geographic_util.js.coffee +23 -0
- data/app/assets/javascripts/leaflet/ghost_label.js.coffee +100 -0
- data/app/assets/javascripts/leaflet/ghost_label_cluster.js.coffee +192 -0
- data/app/assets/javascripts/leaflet/layers_scheduler.js.coffee +57 -0
- data/app/assets/javascripts/leaflet/reactive_measure.js.coffee +414 -0
- data/app/assets/stylesheets/all.scss +16 -0
- data/app/assets/stylesheets/application.css +15 -0
- data/app/assets/stylesheets/compass/reset.scss +3 -0
- data/app/assets/stylesheets/compass/reset/utilities.scss +142 -0
- data/app/assets/stylesheets/leaflet.scss +1093 -0
- data/app/assets/stylesheets/leaflet/label.scss +40 -0
- data/app/assets/stylesheets/leaflet/tooltip.scss +42 -0
- data/app/assets/stylesheets/mixins.scss +131 -0
- data/app/assets/stylesheets/reset.scss +89 -0
- data/app/assets/stylesheets/variables.scss +47 -0
- data/app/helpers/foliage_helper.rb +23 -0
- data/lib/foliage.rb +9 -0
- data/lib/foliage/leaf.rb +235 -0
- data/lib/foliage/rails.rb +2 -0
- data/lib/foliage/rails/engine.rb +7 -0
- data/lib/foliage/rails/integration.rb +8 -0
- data/lib/foliage/version.rb +3 -0
- data/vendor/assets/javascripts/.keep +0 -0
- data/vendor/assets/javascripts/autosize.js +211 -0
- data/vendor/assets/javascripts/geographiclib.js +3074 -0
- data/vendor/assets/javascripts/leaflet.js.erb +9175 -0
- data/vendor/assets/javascripts/leaflet/draw.js +3573 -0
- data/vendor/assets/javascripts/leaflet/easy-button.js +366 -0
- data/vendor/assets/javascripts/leaflet/fullscreen.js +162 -0
- data/vendor/assets/javascripts/leaflet/heatmap.js +142 -0
- data/vendor/assets/javascripts/leaflet/label.js +545 -0
- data/vendor/assets/javascripts/leaflet/measure.js +6966 -0
- data/vendor/assets/javascripts/leaflet/modal.js +364 -0
- data/vendor/assets/javascripts/leaflet/providers.js +479 -0
- data/vendor/assets/javascripts/rbush.js +621 -0
- data/vendor/assets/stylesheets/.keep +0 -0
- data/vendor/assets/stylesheets/bootstrap/mixins.scss +55 -0
- data/vendor/assets/stylesheets/bootstrap/variables.scss +10 -0
- data/vendor/assets/stylesheets/leaflet.scss +479 -0
- data/vendor/assets/stylesheets/leaflet/draw.scss +282 -0
- data/vendor/assets/stylesheets/leaflet/easy-button.scss +56 -0
- data/vendor/assets/stylesheets/leaflet/fullscreen.scss +2 -0
- data/vendor/assets/stylesheets/leaflet/measure.scss +168 -0
- data/vendor/assets/stylesheets/leaflet/modal.scss +85 -0
- metadata +171 -0
@@ -0,0 +1,76 @@
|
|
1
|
+
# Foliage.Paths class
|
2
|
+
# displays crumbs by intervention as a path
|
3
|
+
#
|
4
|
+
# @data is an array of hashes containing info to display
|
5
|
+
# @layer is the layer name
|
6
|
+
#
|
7
|
+
# ==== examples
|
8
|
+
#
|
9
|
+
# @data is an array of hashes built according to the following model:
|
10
|
+
# * minimal example of a hash representing a crumb:
|
11
|
+
# item {
|
12
|
+
# name: <intervention name>, # may be the date, the doer's name,
|
13
|
+
# # whatever you want as long as all the crumbs
|
14
|
+
# # for a given intervention have the same one.
|
15
|
+
# # This is what is called in the
|
16
|
+
# # FoliageHelper to build the legend if
|
17
|
+
# # you wrote something like:
|
18
|
+
# # = foliage do |leaf|
|
19
|
+
# # - leaf.serie :crumbs, my_array_of_crumbs_hashes
|
20
|
+
# # - leaf.paths :name, :crumbs
|
21
|
+
# # :name being the @layer parameter the constructor requires.
|
22
|
+
# nature: crumb.nature, # proper to the crumb. May be one of the natures
|
23
|
+
# # enumerated in Crumb model.
|
24
|
+
# # this option is used to display particular points
|
25
|
+
# # bigger and to change the path opacity for parts
|
26
|
+
# # that correspond to actual works (points between a
|
27
|
+
# # hard_start) and a hard_stop crumb
|
28
|
+
# shape: crumb.geolocation, # proper to the crumb. contains the actual crumb
|
29
|
+
# # location as a Charta::Geometry object.
|
30
|
+
# # This is what is used to draw the crumb on the map
|
31
|
+
# }
|
32
|
+
class Foliage.Path
|
33
|
+
|
34
|
+
constructor: (@layer, @data, @options = {}) ->
|
35
|
+
if this.valid()
|
36
|
+
@options.color ?= Foliage.colors[0]
|
37
|
+
@options.fillColor ?= @options.color
|
38
|
+
console.log "Paths computed", @options
|
39
|
+
else
|
40
|
+
console.warn "Invalid paths"
|
41
|
+
|
42
|
+
# Build layer as wanted
|
43
|
+
buildLayerGroup: (widget, globalStyle = {}) ->
|
44
|
+
group = []
|
45
|
+
for crumb in @data
|
46
|
+
crumbLayer = new L.circleMarker(new L.geoJson(crumb.shape).getBounds().getCenter(), $.extend(true, {}, globalStyle, @options, {className: "crumb crumb-#{crumb.name}"}))
|
47
|
+
widget._bindPopup(crumbLayer, crumb)
|
48
|
+
group.push(crumbLayer)
|
49
|
+
previous_crumb = @data[@data.indexOf(crumb) - 1]
|
50
|
+
if previous_crumb
|
51
|
+
points = []
|
52
|
+
points.push(new L.geoJson(previous_crumb.shape).getBounds().getCenter())
|
53
|
+
points.push(new L.geoJson(crumb.shape).getBounds().getCenter())
|
54
|
+
crumbLayer = new L.polyline(points, $.extend(true, {}, globalStyle, @options))
|
55
|
+
group.push(crumbLayer)
|
56
|
+
return group
|
57
|
+
|
58
|
+
# Build HTML legend for given paths computed layer
|
59
|
+
buildLegend: () ->
|
60
|
+
html = "<div class='leaflet-legend-item' id='legend-#{@layer.name}'>"
|
61
|
+
html += "<div class='leaflet-legend-body leaflet-categories-scale'>"
|
62
|
+
html += "<span class='leaflet-categories-items'>"
|
63
|
+
html += "<span class='leaflet-categories-item'>"
|
64
|
+
html += "<i class='leaflet-categories-sample' style='background-color: #{@options.color};'></i>"
|
65
|
+
html += " #{@layer.label}"
|
66
|
+
html += "</span>"
|
67
|
+
html += "</span>"
|
68
|
+
html += "</div>"
|
69
|
+
html += "</div>"
|
70
|
+
return html
|
71
|
+
|
72
|
+
# Check if paths are valid
|
73
|
+
valid: () ->
|
74
|
+
true
|
75
|
+
|
76
|
+
Foliage.registerLayerType "path", Foliage.Path
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# Foliage.Paths class
|
2
|
+
# displays crumbs by intervention as a path
|
3
|
+
#
|
4
|
+
# @data is an array of hashes containing info to display
|
5
|
+
# @layer is the layer name
|
6
|
+
#
|
7
|
+
# ==== examples
|
8
|
+
#
|
9
|
+
# @data is an array of hashes built according to the following model:
|
10
|
+
# * minimal example of a hash representing a crumb:
|
11
|
+
# item {
|
12
|
+
# name: <intervention name>, # may be the date, the doer's name,
|
13
|
+
# # whatever you want as long as all the crumbs
|
14
|
+
# # for a given intervention have the same one.
|
15
|
+
# # This is what is called in the
|
16
|
+
# # FoliageHelper to build the legend if
|
17
|
+
# # you wrote something like:
|
18
|
+
# # = foliage do |leaf|
|
19
|
+
# # - leaf.serie :crumbs, my_array_of_crumbs_hashes
|
20
|
+
# # - leaf.paths :name, :crumbs
|
21
|
+
# # :name being the @layer parameter the constructor requires.
|
22
|
+
# nature: crumb.nature, # proper to the crumb. May be one of the natures
|
23
|
+
# # enumerated in Crumb model.
|
24
|
+
# # this option is used to display particular points
|
25
|
+
# # bigger and to change the path opacity for parts
|
26
|
+
# # that correspond to actual works (points between a
|
27
|
+
# # hard_start) and a hard_stop crumb
|
28
|
+
# shape: crumb.geolocation, # proper to the crumb. contains the actual crumb
|
29
|
+
# # location as a Charta::Geometry object.
|
30
|
+
# # This is what is used to draw the crumb on the map
|
31
|
+
# }
|
32
|
+
class Foliage.Paths
|
33
|
+
|
34
|
+
constructor: (@layer, @data, options = {}) ->
|
35
|
+
@items = []
|
36
|
+
property = @layer.reference
|
37
|
+
for crumb in @data
|
38
|
+
unless this.itemFor(crumb[property])
|
39
|
+
@items.push
|
40
|
+
name: crumb[property]
|
41
|
+
|
42
|
+
if this.valid()
|
43
|
+
@items = @items.sort (a, b) ->
|
44
|
+
a.name > b.name
|
45
|
+
@colors = options.colors ? []
|
46
|
+
if @items.length > @colors.length
|
47
|
+
for x in [@colors.length..@items.length]
|
48
|
+
@colors.push(Foliage.colors[x] ? "#000000")
|
49
|
+
for item, index in @items
|
50
|
+
item.fillColor = @colors[index]
|
51
|
+
|
52
|
+
console.log "Paths computed"
|
53
|
+
else
|
54
|
+
console.warn "Invalid paths"
|
55
|
+
|
56
|
+
# Build layer as wanted
|
57
|
+
buildLayerGroup: (widget, globalStyle = {}) ->
|
58
|
+
group = []
|
59
|
+
# defining styles
|
60
|
+
strokeWidth = 4
|
61
|
+
crumbStyle =
|
62
|
+
radius: strokeWidth
|
63
|
+
stroke: true
|
64
|
+
weight: strokeWidth/2
|
65
|
+
color: "#000000"
|
66
|
+
fillColor: "#FFFFFF"
|
67
|
+
opacity: 1
|
68
|
+
lineStyle =
|
69
|
+
weight: strokeWidth
|
70
|
+
stroke: true
|
71
|
+
color: this.itemFor(@data[0][@layer.reference]).fillColor
|
72
|
+
fillColor: "rgba(0,0,0,0)"
|
73
|
+
opacity: 1
|
74
|
+
|
75
|
+
# drawing line
|
76
|
+
points = []
|
77
|
+
current_name = @data[0].name
|
78
|
+
current_color = this.itemFor(@data[0][@layer.reference]).fillColor
|
79
|
+
for crumb in @data
|
80
|
+
if crumb.name != current_name
|
81
|
+
lineStyle.color = current_color
|
82
|
+
lineLayer = new L.polyline(points, $.extend(true, {}, globalStyle, lineStyle))
|
83
|
+
group.push(lineLayer)
|
84
|
+
points = []
|
85
|
+
current_name = crumb.name
|
86
|
+
current_color = this.itemFor(crumb[@layer.reference]).fillColor
|
87
|
+
points.push(new L.geoJson(crumb.shape).getBounds().getCenter())
|
88
|
+
if points.length > 0
|
89
|
+
lineStyle.color = current_color
|
90
|
+
lineLayer = new L.polyline(points, $.extend(true, {}, globalStyle, lineStyle))
|
91
|
+
group.push(lineLayer)
|
92
|
+
# drawing circles
|
93
|
+
for crumb in @data
|
94
|
+
crumbStyle.color= this.itemFor(crumb[@layer.reference]).fillColor
|
95
|
+
if crumb.nature == 'hard_start'
|
96
|
+
crumbStyle.fillColor = "#000000"
|
97
|
+
if crumb.nature == 'hard_stop'
|
98
|
+
crumbStyle.fillColor = "#FFFFFF"
|
99
|
+
crumbLayer = new L.circleMarker(new L.geoJson(crumb.shape).getBounds().getCenter(), $.extend(true, {}, globalStyle, crumbStyle))
|
100
|
+
widget._bindPopup(crumbLayer, crumb)
|
101
|
+
group.push(crumbLayer)
|
102
|
+
group
|
103
|
+
|
104
|
+
# Build HTML legend for given paths computed layer
|
105
|
+
buildLegend: () ->
|
106
|
+
html = "<div class='leaflet-legend-item' id='legend-#{@layer.name}'>"
|
107
|
+
html += "<h3>#{@layer.label}</h3>"
|
108
|
+
html += "<div class='leaflet-legend-body leaflet-categories-scale'>"
|
109
|
+
html += "<span class='leaflet-categories-items'>"
|
110
|
+
for name, item of @items
|
111
|
+
html += "<span class='leaflet-categories-item'>"
|
112
|
+
html += "<i class='leaflet-categories-sample' style='background-color: #{item.fillColor};'></i>"
|
113
|
+
html += " #{item.name}"
|
114
|
+
html += "</span>"
|
115
|
+
html += "</span>"
|
116
|
+
html += "</div>"
|
117
|
+
html += "</div>"
|
118
|
+
return html
|
119
|
+
|
120
|
+
# Returns the item matching the given name
|
121
|
+
itemFor: (name) ->
|
122
|
+
back = null
|
123
|
+
@items.forEach (item, index, array) ->
|
124
|
+
back = item if item.name == name
|
125
|
+
return back
|
126
|
+
|
127
|
+
# Check if paths are valid
|
128
|
+
valid: () ->
|
129
|
+
@items.length > 0
|
130
|
+
|
131
|
+
Foliage.registerLayerType "paths", Foliage.Paths
|
@@ -0,0 +1,83 @@
|
|
1
|
+
class Foliage.PointGroup
|
2
|
+
|
3
|
+
constructor: (@layer, @data, @options = {}) ->
|
4
|
+
@items = []
|
5
|
+
console.log "Layer: ", @layer
|
6
|
+
for zone in @data
|
7
|
+
lnglat = zone.shape.coordinates
|
8
|
+
@items.push
|
9
|
+
name: zone.name
|
10
|
+
point: [lnglat[1], lnglat[0]]
|
11
|
+
radius: zone.radius ? @options.radius
|
12
|
+
group: zone.group
|
13
|
+
fillColor: zone.shapeColor
|
14
|
+
popup: zone.popup
|
15
|
+
sensorId: zone.sensorId
|
16
|
+
if this.valid()
|
17
|
+
@items = @items.sort (a, b) ->
|
18
|
+
a.name > b.name
|
19
|
+
@groups = {}
|
20
|
+
for {group, name, fillColor} in @items
|
21
|
+
@groups[group] or= fillColor
|
22
|
+
console.log "Point group computed"
|
23
|
+
else
|
24
|
+
console.warn "Invalid categories"
|
25
|
+
|
26
|
+
# Build layer as wanted
|
27
|
+
buildLayerGroup: (widget, globalStyle = {}) ->
|
28
|
+
group = []
|
29
|
+
# Shadow
|
30
|
+
if @options.stroke
|
31
|
+
for zone in @items
|
32
|
+
zoneStyle =
|
33
|
+
fillColor: zone.color ? @options.color
|
34
|
+
radius: (zone.radius ? @options.radius) + @options.weight
|
35
|
+
stroke: false
|
36
|
+
fillOpacity: 0.8
|
37
|
+
console.log zone.point
|
38
|
+
shadow = new L.circleMarker(zone.point, zoneStyle)
|
39
|
+
shadow.markerSensorId = zone.sensorId
|
40
|
+
group.push shadow
|
41
|
+
# Core
|
42
|
+
for zone in @items
|
43
|
+
console.log zone
|
44
|
+
zoneStyle =
|
45
|
+
fillColor: zone.fillColor ? @options.fillColor
|
46
|
+
radius: zone.radius ? @options.radius
|
47
|
+
stroke: false
|
48
|
+
fillOpacity: 1
|
49
|
+
console.log zoneStyle
|
50
|
+
zoneLayer = new L.circleMarker(zone.point, zoneStyle)
|
51
|
+
zoneLayer.sensorId = zone.sensorId
|
52
|
+
widget._bindPopup(zoneLayer, zone)
|
53
|
+
group.push(zoneLayer)
|
54
|
+
group
|
55
|
+
|
56
|
+
# Build HTML legend for given points computed layer
|
57
|
+
buildLegend: () ->
|
58
|
+
html = "<div class='leaflet-legend-item' id='legend-#{@layer.name}'>"
|
59
|
+
html += "<h3>#{@layer.label}</h3>"
|
60
|
+
html += "<div class='leaflet-legend-body leaflet-categories-scale'>"
|
61
|
+
html += "<span class='leaflet-categories-items'>"
|
62
|
+
for group in Object.keys(@groups)
|
63
|
+
html += "<span class='leaflet-categories-item'>"
|
64
|
+
html += "<i class='leaflet-categories-sample' style='background-color: #{@groups[group]};'></i>"
|
65
|
+
html += " <span class='leaflet-categories-item_label'>#{group}</span>"
|
66
|
+
html += "</span>"
|
67
|
+
html += "</span>"
|
68
|
+
html += "</div>"
|
69
|
+
html += "</div>"
|
70
|
+
return html
|
71
|
+
|
72
|
+
# Returns the item matching the given name
|
73
|
+
itemFor: (name) ->
|
74
|
+
back = null
|
75
|
+
@items.forEach (item, index, array) ->
|
76
|
+
back = item if item.name == name
|
77
|
+
return back
|
78
|
+
|
79
|
+
# Check if categories are valid
|
80
|
+
valid: () ->
|
81
|
+
@items.length > 0
|
82
|
+
|
83
|
+
Foliage.registerLayerType "point_group", Foliage.PointGroup
|
@@ -0,0 +1,79 @@
|
|
1
|
+
class Foliage.Points
|
2
|
+
|
3
|
+
constructor: (@layer, @data, @options = {}) ->
|
4
|
+
@items = []
|
5
|
+
console.log "Layer: ", @layer
|
6
|
+
for zone in @data
|
7
|
+
lnglat = zone.shape.coordinates
|
8
|
+
@items.push
|
9
|
+
name: zone.name
|
10
|
+
point: [lnglat[1], lnglat[0]]
|
11
|
+
radius: zone.radius ? @options.radius
|
12
|
+
if this.valid()
|
13
|
+
@items = @items.sort (a, b) ->
|
14
|
+
a.name > b.name
|
15
|
+
@colors = @options.colors ? []
|
16
|
+
if @items.length > @colors.length
|
17
|
+
for x in [@colors.length..@items.length]
|
18
|
+
@colors.push(Foliage.colors[x] ? "#000000")
|
19
|
+
for item, index in @items
|
20
|
+
item.fillColor = @colors[index]
|
21
|
+
console.log "Points computed"
|
22
|
+
else
|
23
|
+
console.warn "Invalid categories"
|
24
|
+
|
25
|
+
# Build layer as wanted
|
26
|
+
buildLayerGroup: (widget, globalStyle = {}) ->
|
27
|
+
group = []
|
28
|
+
# Shadow
|
29
|
+
if @options.stroke
|
30
|
+
for zone in @items
|
31
|
+
zoneStyle =
|
32
|
+
fillColor: zone.color ? @options.color
|
33
|
+
radius: (zone.radius ? @options.radius) + @options.weight
|
34
|
+
stroke: false
|
35
|
+
fillOpacity: 0.8
|
36
|
+
console.log zone.point
|
37
|
+
group.push new L.circleMarker(zone.point, zoneStyle)
|
38
|
+
# Core
|
39
|
+
for zone in @items
|
40
|
+
console.log zone
|
41
|
+
zoneStyle =
|
42
|
+
fillColor: zone.fillColor ? @options.fillColor
|
43
|
+
radius: zone.radius ? @options.radius
|
44
|
+
stroke: false
|
45
|
+
fillOpacity: 1
|
46
|
+
console.log zoneStyle
|
47
|
+
zoneLayer = new L.circleMarker(zone.point, zoneStyle)
|
48
|
+
widget._bindPopup(zoneLayer, zone)
|
49
|
+
group.push(zoneLayer)
|
50
|
+
group
|
51
|
+
|
52
|
+
# Build HTML legend for given points computed layer
|
53
|
+
buildLegend: () ->
|
54
|
+
html = "<div class='leaflet-legend-item' id='legend-#{@layer.name}'>"
|
55
|
+
html += "<h3>#{@layer.label}</h3>"
|
56
|
+
html += "<div class='leaflet-legend-body leaflet-categories-scale'>"
|
57
|
+
html += "<span class='leaflet-categories-items'>"
|
58
|
+
for name, item of @items
|
59
|
+
html += "<span class='leaflet-categories-item'>"
|
60
|
+
html += "<i class='leaflet-categories-sample' style='background-color: #{item.fillColor};'></i>"
|
61
|
+
html += " #{item.name}"
|
62
|
+
html += "</span>"
|
63
|
+
html += "</span>"
|
64
|
+
html += "</div>"
|
65
|
+
html += "</div>"
|
66
|
+
return html
|
67
|
+
|
68
|
+
# Returns the item matching the given name
|
69
|
+
itemFor: (name) ->
|
70
|
+
back = null
|
71
|
+
@items.forEach (item, index, array) ->
|
72
|
+
back = item if item.name == name
|
73
|
+
return back
|
74
|
+
|
75
|
+
# Check if categories are valid
|
76
|
+
valid: () ->
|
77
|
+
@items.length > 0
|
78
|
+
|
79
|
+
Foliage.registerLayerType "points", Foliage.Points
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class Foliage.Simple
|
2
|
+
|
3
|
+
constructor: (@layer, @data, @options = {}) ->
|
4
|
+
|
5
|
+
# Build layer as wanted
|
6
|
+
buildLayerGroup: (widget, globalStyle = {}) ->
|
7
|
+
group = []
|
8
|
+
for zone in @data
|
9
|
+
zoneLayer = new L.GeoJSON(zone.shape, globalStyle)
|
10
|
+
label = new L.GhostLabel(className: 'leaflet-ghost-label', toBack: false).setContent(zone.name).toCentroidOfBounds(zoneLayer.getLayers()[0].getLatLngs())
|
11
|
+
widget.ghostLabelCluster.bind label, zoneLayer.getLayers()[0]
|
12
|
+
widget._bindPopup(zoneLayer, zone)
|
13
|
+
group.push(zoneLayer)
|
14
|
+
group
|
15
|
+
|
16
|
+
# Build HTML legend for given categories computed layer
|
17
|
+
buildLegend: () ->
|
18
|
+
html = "<div class='leaflet-legend-item' id='legend-#{@layer.name}'>"
|
19
|
+
# html += "<h3>#{@layer.label}</h3>"
|
20
|
+
html += "<div class='leaflet-legend-body leaflet-categories-scale'>"
|
21
|
+
html += "<span class='leaflet-categories-items'>"
|
22
|
+
html += "<span class='leaflet-categories-item'>"
|
23
|
+
html += "<i class='leaflet-categories-sample' style='background-color: #{@layer.fillColor || @options.parent.options.layerDefaults[@layer.type].fillColor };'></i>"
|
24
|
+
html += " <span class='leaflet-categories-item_label'>#{@layer.label}</span>"
|
25
|
+
html += "</span>"
|
26
|
+
html += "</span>"
|
27
|
+
html += "</div>"
|
28
|
+
html += "</div>"
|
29
|
+
return html
|
30
|
+
|
31
|
+
# Check if categories are valid
|
32
|
+
valid: () ->
|
33
|
+
true
|
34
|
+
|
35
|
+
Foliage.registerLayerType "simple", Foliage.Simple
|
@@ -0,0 +1,23 @@
|
|
1
|
+
L.GeographicUtil = L.extend L.GeographicUtil || {},
|
2
|
+
geod: GeographicLib.Geodesic.WGS84
|
3
|
+
|
4
|
+
# Use Karney distance formula
|
5
|
+
# ([lat, lng], [lat, lng]) -> Number (in meters)
|
6
|
+
distance: (a, b) ->
|
7
|
+
r = @geod.Inverse(a[0], a[1], b[0], b[1])
|
8
|
+
r.s12.toFixed(3)
|
9
|
+
|
10
|
+
Polygon: (points) -> # (Array of [lat,lng] pair)
|
11
|
+
@geod = GeographicLib.Geodesic.WGS84
|
12
|
+
@poly = @geod.Polygon(false)
|
13
|
+
for point in points
|
14
|
+
@poly.AddPoint point[0], point[1]
|
15
|
+
|
16
|
+
@poly = @poly.Compute(false, true)
|
17
|
+
return
|
18
|
+
|
19
|
+
L.GeographicUtil.Polygon.prototype =
|
20
|
+
perimeter: ->
|
21
|
+
@poly.perimeter
|
22
|
+
area: ->
|
23
|
+
Math.abs @poly.area
|
@@ -0,0 +1,100 @@
|
|
1
|
+
###
|
2
|
+
# Extend L.Label to provide a label on centroid, calculated from a L.Latlng[]
|
3
|
+
# options:
|
4
|
+
# toBack {boolean} if true, label is set to objectsPane, allowing to be covered by higher level pane
|
5
|
+
# opacity: {string} ([0..1] | 'inherit') inherit allows to use opacity in your class. Default: 'inherit'
|
6
|
+
###
|
7
|
+
L.GhostLabel = L.Label.extend
|
8
|
+
__initialize: L.Label::initialize
|
9
|
+
_onAdd: L.Label.prototype.onAdd
|
10
|
+
__updateContent: L.Label.prototype._updateContent
|
11
|
+
__setOpacity: L.Label::setOpacity
|
12
|
+
|
13
|
+
initialize: (options, source) ->
|
14
|
+
options.opacity ||= 'inherit'
|
15
|
+
|
16
|
+
@__initialize.apply @, arguments
|
17
|
+
|
18
|
+
###
|
19
|
+
# Set the latLng[] to calculate the centroid
|
20
|
+
###
|
21
|
+
toCentroidOfBounds: (latLngs) ->
|
22
|
+
# To center of bounds if centroid can't be calculated during onAdd
|
23
|
+
@_latlng = L.latLngBounds(latLngs).getCenter()
|
24
|
+
@_latLngs = latLngs
|
25
|
+
return this
|
26
|
+
|
27
|
+
onAdd: (map) ->
|
28
|
+
# Don't hide labels on click
|
29
|
+
@options.noHide = true
|
30
|
+
|
31
|
+
if @options.toBack
|
32
|
+
@options.pane = 'objectsPane'
|
33
|
+
|
34
|
+
@_onAdd.apply this, arguments
|
35
|
+
|
36
|
+
map.on 'zoomend', @_onZoomEnd, @
|
37
|
+
|
38
|
+
if @options.toBack
|
39
|
+
# ZIndex 3 is default index of objectsPane
|
40
|
+
@updateZIndex '3'
|
41
|
+
|
42
|
+
@_updatePosition()
|
43
|
+
return
|
44
|
+
|
45
|
+
setOpacity: (opacity) ->
|
46
|
+
unless opacity is 'inherit'
|
47
|
+
@__setOpacity.call @, opacity
|
48
|
+
|
49
|
+
getLatLng: ->
|
50
|
+
@_latlng
|
51
|
+
|
52
|
+
_onZoomEnd: (e) ->
|
53
|
+
@getCenter(e.target)
|
54
|
+
|
55
|
+
getCenter: (map)->
|
56
|
+
if @_latLngs
|
57
|
+
poly = L.polygon(@_latLngs)
|
58
|
+
poly._map = @_map || map
|
59
|
+
@_latlng = poly.__getCenter()
|
60
|
+
|
61
|
+
@_latlng
|
62
|
+
|
63
|
+
|
64
|
+
###
|
65
|
+
# Override to set position on pos, considering label center
|
66
|
+
###
|
67
|
+
_setPosition: (pos) ->
|
68
|
+
map = @_map
|
69
|
+
container = @_container
|
70
|
+
labelWidth = @_labelWidth
|
71
|
+
labelHeight = @_labelHeight || 0
|
72
|
+
|
73
|
+
pos = pos.add(L.point(-labelWidth/2, -labelHeight/2))
|
74
|
+
L.DomUtil.setPosition container, pos
|
75
|
+
return
|
76
|
+
|
77
|
+
###
|
78
|
+
# Override to set position on pos, considering label center
|
79
|
+
###
|
80
|
+
_updateContent: ->
|
81
|
+
@__updateContent.call this
|
82
|
+
@_labelHeight = @_container.offsetHeight if @_container
|
83
|
+
|
84
|
+
|
85
|
+
L.extendedMethods =
|
86
|
+
# Allow to be updated
|
87
|
+
bindGhostLabel: (object, options) ->
|
88
|
+
|
89
|
+
if !@label
|
90
|
+
@label = object
|
91
|
+
|
92
|
+
if !@_showLabelAdded
|
93
|
+
@on 'remove', @_hideLabel, @
|
94
|
+
|
95
|
+
@_showLabelAdded = true
|
96
|
+
return
|
97
|
+
|
98
|
+
L.Polygon.include L.extendedMethods
|
99
|
+
L.FeatureGroup.include L.extendedMethods
|
100
|
+
|