-
Notifications
You must be signed in to change notification settings - Fork 0
/
trans.go
170 lines (151 loc) · 3.9 KB
/
trans.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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package esri
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
type transfieldAliases struct {
}
type transspatialReference struct {
Wkid int `json:"wkid"`
Latestwkid int `json:"latestWkid"`
}
type transfields struct {
Name string `json:"name"`
Type string `json:"type"`
Alias string `json:"alias"`
}
type transattributes struct {
Objectid int `json:"OBJECTID"`
Mapname string `json:"MapName"`
Altdes string `json:"AltDes"`
ScaddType string `json:"SCADD_Type"`
Editdate int `json:"EditDate"`
Editorname int `json:"EditorName"`
ShapeLen float64 `json:"Shape.len"`
}
type transgeometry struct {
Paths [][][]float64 `json:"paths"`
}
type transfeatures struct {
Attributes transattributes `json:"attributes"`
Geometry transgeometry `json:"geometry"`
}
type trans struct {
Displayfieldname string `json:"displayFieldName"`
Fieldaliases transfieldAliases `json:"fieldAliases"`
Geometrytype string `json:"geometryType"`
Spatialreference transspatialReference `json:"spatialReference"`
Fields []transfields `json:"fields"`
Features []transfeatures `json:"features"`
}
type StreetClass int
// Street classifications. Residential and minor residential aren't queryable
// so there may be no way to get this to work.
const (
Residential StreetClass = iota
MinorResidential
Collector
Commercial
MinorArterial
Arterial
)
//go:generate stringer -type=StreetClass
// Street refers to a specific road
type Street struct {
Name string
Class StreetClass
Row int
Alt bool
ARDOT bool
}
// FetchRoads takes an envelope as an argument and returns a list of street
// names and their classifications.
// TODO: this is HIGHLY sensitive to the envelope buffer. Absolute widths are probably necessary.
func FetchRoads(e Envelope) ([]Street, error) {
var sts []Street
tURL, err := url.Parse("https://maps.littlerock.state.ar.us/arcgis/rest/services/Master_Street_Plan/MapServer/0/query")
if err != nil {
return sts, err
}
params := url.Values{}
params.Add("f", "json")
params.Add("spatialRel", "esriSpatialRelIntersects")
geomString := 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) // spatialReference will not change
params.Add("geometry", geomString)
params.Add("geometryType", "esriGeometryEnvelope")
params.Add("inSR", "102651")
params.Add("outFields", "OBJECTID,MapName,AltDes,SCADD_Type,EditDate,EditorName,Shape.len")
params.Add("outSR", "102651")
tURL.RawQuery = params.Encode()
res, err := http.Get(tURL.String())
if err != nil {
return sts, err
}
tData, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
return sts, err
}
var tJSON trans
err = json.Unmarshal(tData, &tJSON)
if err != nil {
return sts, err
}
for _, f := range tJSON.Features {
class := deString(f.Attributes.ScaddType)
st := Street{
Name: f.Attributes.Mapname,
Class: class,
Row: calcRow(class),
Alt: isAlt(f.Attributes.Altdes),
ARDOT: isAlt(f.Attributes.Altdes), // this is a VERY weak inference
}
sts = append(sts, st)
}
return sts, nil
}
func deString(s string) StreetClass {
switch s {
case "MINOR RESIDENTIAL":
return MinorResidential
case "RESIDENTIAL":
return Residential
case "COLLECTOR":
return Collector
case "COMMERCIAL":
return Commercial // not sure this exists
case "MINOR ARTERIAL":
return MinorArterial
case "PRINCIPAL ARTERIAL":
return Arterial
default:
return MinorResidential
}
}
func calcRow(sc StreetClass) int {
switch sc {
case Residential:
return 50
case MinorResidential:
return 45
case Collector:
return 60
case Commercial:
return 60
case MinorArterial:
return 90
case Arterial:
return 110
default:
return 50
}
}
func isAlt(s string) bool {
if s == "YES" {
return true
}
return false
}