comparison pkg/imports/wkb.go @ 1786:09349ca27dd7

Imports: Removed duplicated code path to store WKB polygons into database.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Sun, 13 Jan 2019 13:02:39 +0100
parents 614c6c766691
children f54ac71db1ac
comparison
equal deleted inserted replaced
1785:614c6c766691 1786:09349ca27dd7
23 ) 23 )
24 24
25 type ( 25 type (
26 lineSlice [][]float64 26 lineSlice [][]float64
27 polygonSlice [][][]float64 27 polygonSlice [][][]float64
28
29 point struct {
30 X float64
31 Y float64
32 }
33 lineString []point
34 polygon []lineString
35 ) 28 )
36 29
37 const ( 30 const (
38 wkbNDR byte = 1 31 wkbNDR byte = 1
39 32
98 } 91 }
99 92
100 return buf.Bytes() 93 return buf.Bytes()
101 } 94 }
102 95
103 func shapeToPolygon(s shp.Shape) (polygon, error) { 96 func shapeToPolygon(s shp.Shape) (polygonSlice, error) {
104 switch p := s.(type) { 97 switch p := s.(type) {
105 case *shp.Polygon: 98 case *shp.Polygon:
106 return toPolygon(p.NumParts, p.Parts, p.Points), nil 99 return toPolygon(p.NumParts, p.Parts, p.Points), nil
107 case *shp.PolygonZ: 100 case *shp.PolygonZ:
108 return toPolygon(p.NumParts, p.Parts, p.Points), nil 101 return toPolygon(p.NumParts, p.Parts, p.Points), nil
110 return toPolygon(p.NumParts, p.Parts, p.Points), nil 103 return toPolygon(p.NumParts, p.Parts, p.Points), nil
111 } 104 }
112 return nil, fmt.Errorf("Unsupported shape type %T", s) 105 return nil, fmt.Errorf("Unsupported shape type %T", s)
113 } 106 }
114 107
115 func toPolygon(numParts int32, parts []int32, points []shp.Point) polygon { 108 func toPolygon(numParts int32, parts []int32, points []shp.Point) polygonSlice {
116 out := make(polygon, numParts) 109 out := make(polygonSlice, numParts)
117 var pos int32 110 var pos int32
118 111
119 for i := range out { 112 for i := range out {
120 var howMany int32 113 var howMany int32
121 if i+1 >= len(parts) { 114 if i+1 >= len(parts) {
122 howMany = int32(len(points)) - pos 115 howMany = int32(len(points)) - pos
123 } else { 116 } else {
124 howMany = parts[i+1] - parts[i] 117 howMany = parts[i+1] - parts[i]
125 } 118 }
126 119
127 line := make(lineString, howMany) 120 line := make([][]float64, howMany)
121 vertices := make([]float64, 2*howMany)
128 for j := int32(0); j < howMany; j, pos = j+1, pos+1 { 122 for j := int32(0); j < howMany; j, pos = j+1, pos+1 {
129 p := &points[pos] 123 p := &points[pos]
130 line[j] = point{p.X, p.Y} 124 vertex := vertices[j*2 : j*2+2]
125 vertex[0], vertex[1] = p.X, p.Y
126 line[j] = vertex
131 } 127 }
132 out[i] = line 128 out[i] = line
133 } 129 }
134 return out 130 return out
135 } 131 }
136
137 func (p polygon) asWKB() []byte {
138 if p == nil {
139 return nil
140 }
141 // pre-calculate size to avoid reallocations.
142 size := 1 + 4 + 4
143 for _, ring := range p {
144 size += 4 + len(ring)*2*8
145 }
146
147 buf := bytes.NewBuffer(make([]byte, 0, size))
148
149 binary.Write(buf, binary.LittleEndian, wkbNDR)
150 binary.Write(buf, binary.LittleEndian, wkbPolygon)
151 binary.Write(buf, binary.LittleEndian, uint32(len(p)))
152
153 for _, ring := range p {
154 binary.Write(buf, binary.LittleEndian, uint32(len(ring)))
155 for _, v := range ring {
156 binary.Write(buf, binary.LittleEndian, math.Float64bits(v.X))
157 binary.Write(buf, binary.LittleEndian, math.Float64bits(v.Y))
158 }
159 }
160
161 return buf.Bytes()
162 }