foliage 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|