-
Notifications
You must be signed in to change notification settings - Fork 0
/
floodmap.go
143 lines (124 loc) · 4.74 KB
/
floodmap.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package esri
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
type fmFieldAliases struct {
}
type fmSpatialReference struct {
Wkid int `json:"wkid"`
Latestwkid int `json:"latestWkid"`
}
type fmAttributes struct {
Objectid int `json:"OBJECTID"`
FldZone string `json:"FLD_ZONE"`
Legend string `json:"LEGEND"`
Panel string `json:"PANEL"`
FirmPan string `json:"FIRM_PAN"`
FloodplainadministratorcontactsCityname string `json:"FloodplainAdministratorContacts_CityName"`
FloodplainadministratorcontactsFloodplainadmin string `json:"FloodplainAdministratorContacts_FloodplainAdmin"`
FloodplainadministratorcontactsPhone string `json:"FloodplainAdministratorContacts_Phone"`
FloodplainadministratorcontactsEmail string `json:"FloodplainAdministratorContacts_Email"`
OwName string `json:"OW_NAME"`
Proplookup string `json:"PROPLOOKUP"`
OrigFid int `json:"ORIG_FID"`
FidUnionfloodzonespanelsparcels int `json:"FID_UnionFloodZonesPanelsParcels"`
}
type fmGeometry struct {
Rings [][][]float64 `json:"rings"`
}
type fmFeatures struct {
Attributes fmAttributes `json:"attributes"`
Geometry fmGeometry `json:"geometry"`
}
type fmResponse struct {
Displayfieldname string `json:"displayFieldName"`
Fieldaliases fmFieldAliases `json:"fieldAliases"`
Geometrytype string `json:"geometryType"`
Spatialreference fmSpatialReference `json:"spatialReference"`
Features []fmFeatures `json:"features"`
}
// FloodHaz is an enumeration of valid flood hazard area designations. Its use
// is an alternative to a hashmap
type FloodHaz int
// Flood Hazard Area classifications
const (
X FloodHaz = iota
FIVE // 0.2% annual chance
A
AE
FLOODWAY
LEVEE
)
func (f FloodHaz) String() string {
return [...]string{"X", "FIVE", "A", "AE", "FLOODWAY", "LEVEE"}[f]
}
// FloodData takes an envelope as an argument, queries the PAGIS DFIRM map
// server and returns an array of strings of flood zones
func FloodData(e Envelope) ([]FloodHaz, error) {
var hazards []FloodHaz
floodURL, err := url.Parse("https://www.pagis.org/arcgis/rest/services/APPS/Apps_DFIRM/MapServer//dynamicLayer/query")
if err != nil {
return hazards, err
}
params := url.Values{}
params.Add("f", "json")
params.Add("returnGeometry", "true")
params.Add("spatialRel", "esriSpatialRelIntersects")
params.Add("maxAllowableOffset", "1")
params.Add("geometry", fmt.Sprintf("{\"xmin\":%f,\"ymin\":%f,\"xmax\":%f,\"ymax\":%f,\"spatialReference\":{\"wkid\":102651,\"latestWkid\":3433}}", e.Min.X, e.Min.Y, e.Max.X, e.Max.Y))
params.Add("esriGeometryType", "esriGeometryEnvelope")
params.Add("inSR", "102651")
params.Add("outFields", "OBJECTID,FLD_ZONE,LEGEND,PANEL,FIRM_PAN,FloodplainAdministratorContacts_CityName,FloodplainAdministratorContacts_FloodplainAdmin,FloodplainAdministratorContacts_Phone,FloodplainAdministratorContacts_Email,OW_NAME,PROPLOOKUP,ORIG_FID,FID_UnionFloodZonesPanelsParcels")
params.Add("layer", "{\"source\":{\"type\":\"mapLayer\",\"mapLayerId\":21}}")
floodURL.RawQuery = params.Encode()
res, err := http.Get(floodURL.String())
if err != nil {
return hazards, err
}
floodData, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
return hazards, err
}
var floodJSON fmResponse
err = json.Unmarshal(floodData, &floodJSON)
if err != nil {
return hazards, err
}
zName := make(map[string]FloodHaz)
zName["The Point Clicked has a 1% Annual Chance Flood Hazard, Outside Floodway, Zone AE"] = AE
zName["The Point Clicked has a 1% Annual Chance Flood Hazard, Inside Floodway, Zone AE"] = FLOODWAY
zName["The Point Clicked has a 0.2% Annual Chance Flood Hazard"] = FIVE
zName["The Point Clicked is Outside 1% Annual Floodplain, Zone X"] = X
zName["The Point Clicked is Outside 1% Annual Floodplain, Zone X (Protected by Levee)"] = LEVEE
zName["The Point Clicked has a 1% Annual Chance Flood Hazard, Zone A"] = A
for _, feat := range floodJSON.Features {
hazards = append(hazards, zName[feat.Attributes.Legend])
}
return hazards, nil
}
// InFloodway is a simple function that
func InFloodway(fh []FloodHaz) bool {
for _, f := range fh {
if f == FLOODWAY {
return true
}
}
return false
}
// Unique filters redundant FloodHaz zones
func Unique(fh []FloodHaz) []FloodHaz {
keys := make(map[FloodHaz]bool)
out := []FloodHaz{}
for _, f := range fh {
if _, val := keys[f]; !val {
keys[f] = true
out = append(out, f)
}
}
return out
}