comparison cmd/isoareas/main.go @ 4542:56f4e8cbfab7 iso-areas

Sew together triangles that totally inside a single class.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 26 Sep 2019 18:11:38 +0200
parents 53b55f811666
children 2a707732331f
comparison
equal deleted inserted replaced
4541:53b55f811666 4542:56f4e8cbfab7
13 13
14 package main 14 package main
15 15
16 import ( 16 import (
17 "bufio" 17 "bufio"
18 "container/list"
18 "fmt" 19 "fmt"
19 "io" 20 "io"
20 "log" 21 "log"
21 "math" 22 "math"
22 "math/bits" 23 "math/bits"
140 result := make([][]octree.LineStringZ, len(classes)) 141 result := make([][]octree.LineStringZ, len(classes))
141 142
142 log.Println("inside classes:") 143 log.Println("inside classes:")
143 for i, c := range classes { 144 for i, c := range classes {
144 145
145 var pb polygonBuilder 146 pb := polygonBuilder{open: list.New()}
146 147
147 var isolated, inside int 148 var isolated, inside int
148 allInClass: 149 allInClass:
149 for _, idx := range c { 150 for _, idx := range c {
150 ns := neighbors(tri, idx) 151 ns := neighbors(tri, idx)
151 w := where(ns, c) 152 mask := where(ns, c)
152 switch bits.OnesCount8(w) { 153 switch bits.OnesCount8(mask) {
153 case 0: 154 case 0:
154 // Totally insides do not contribute to the geometries. 155 // Totally insides do not contribute to the geometries.
155 inside++ 156 inside++
156 continue allInClass 157 continue allInClass
157 case 3: 158 case 3:
161 pb.addTriangle( 162 pb.addTriangle(
162 tri.Points[ti[0]], 163 tri.Points[ti[0]],
163 tri.Points[ti[1]], 164 tri.Points[ti[1]],
164 tri.Points[ti[2]]) 165 tri.Points[ti[2]])
165 continue allInClass 166 continue allInClass
166 } 167 default:
167 } 168 ti := tri.Triangles[idx*3 : idx*3+3]
168 169 for j := 0; j < 3; j++ {
169 log.Printf("\t%d: inside: %d / isolated: %d\n", 170 if mask&(1<<j) == 0 {
170 i, inside, isolated) 171
172 // TODO: Look into cuts to see
173 // if there are real intersections
174 k := (j + 1) % 3
175 front := tri.Points[ti[j]]
176 back := tri.Points[ti[k]]
177
178 curr := octree.LineStringZ{front, back}
179
180 segment:
181 for e := pb.open.Front(); e != nil; e = e.Next() {
182 line := e.Value.(octree.LineStringZ)
183 first, last := line[0], line[len(line)-1]
184
185 if back.EpsEquals(first) {
186 curr = append(curr, line[1:]...)
187 pb.open.Remove(e)
188 goto segment
189 }
190
191 if back.EpsEquals(last) {
192 line.Reverse()
193 curr = append(curr, line[1:]...)
194 pb.open.Remove(e)
195 goto segment
196 }
197
198 if front.EpsEquals(last) {
199 curr = append(line, curr[1:]...)
200 pb.open.Remove(e)
201 goto segment
202 }
203
204 if front.EpsEquals(first) {
205 line.Reverse()
206 curr = append(line, curr[1:]...)
207 pb.open.Remove(e)
208 goto segment
209 }
210 } // all open
211
212 // check if closed
213 if curr[0].EpsEquals(curr[len(curr)-1]) {
214 if !curr.CCW() {
215 curr.Reverse()
216 }
217 pb.polygons = append(pb.polygons, curr)
218 } else {
219 pb.open.PushFront(curr)
220 }
221 } // for all border parts
222 }
223 }
224 }
225
226 log.Printf("\t%d: inside: %d / isolated: %d open: %d closed: %d\n",
227 i, inside, isolated, pb.open.Len(), len(pb.polygons))
171 228
172 result[i] = pb.polygons 229 result[i] = pb.polygons
173 } 230 }
174 231
175 log.Println("cuts:") 232 log.Println("cuts:")
183 240
184 } 241 }
185 242
186 type polygonBuilder struct { 243 type polygonBuilder struct {
187 polygons []octree.LineStringZ 244 polygons []octree.LineStringZ
245
246 open *list.List
188 } 247 }
189 248
190 func (pb *polygonBuilder) addTriangle(v0, v1, v2 octree.Vertex) { 249 func (pb *polygonBuilder) addTriangle(v0, v1, v2 octree.Vertex) {
191 polygon := octree.LineStringZ{v0, v1, v2, v0} 250 polygon := octree.LineStringZ{v0, v1, v2, v0}
192 pb.polygons = append(pb.polygons, polygon) 251 pb.polygons = append(pb.polygons, polygon)