comparison pkg/imports/wx.go @ 2726:dff749c07ae0

Warn if imported axis linestrings cross each other
author Tom Gottfried <tom@intevation.de>
date Tue, 19 Mar 2019 12:57:11 +0100
parents a10022399e24
children 7cb027be277d
comparison
equal deleted inserted replaced
2725:9465749410ba 2726:dff749c07ae0
87 ) 87 )
88 DELETE FROM waterway.waterway_axis 88 DELETE FROM waterway.waterway_axis
89 WHERE pg_has_role('sys_admin', 'MEMBER') 89 WHERE pg_has_role('sys_admin', 'MEMBER')
90 OR ST_Covers((SELECT a FROM resp), 90 OR ST_Covers((SELECT a FROM resp),
91 ST_Transform(wtwaxs::geometry, (SELECT t FROM resp))) 91 ST_Transform(wtwaxs::geometry, (SELECT t FROM resp)))
92 `
93
94 checkCrossingAxisSQL = `
95 SELECT ST_AsText(ST_Intersection(new_line.wtwaxs, axis.wtwaxs))
96 FROM waterway.waterway_axis AS axis, waterway.waterway_axis AS new_line
97 WHERE new_line.id = $1 AND axis.id <> $1
98 AND ST_Crosses(new_line.wtwaxs::geometry, axis.wtwaxs::geometry)
92 ` 99 `
93 100
94 insertWaterwayAxisSQL = ` 101 insertWaterwayAxisSQL = `
95 WITH resp AS ( 102 WITH resp AS (
96 SELECT best_utm(area::geometry) AS t, 103 SELECT best_utm(area::geometry) AS t,
108 THEN new_line 115 THEN new_line
109 ELSE ST_Intersection(a, new_line) 116 ELSE ST_Intersection(a, new_line)
110 END 117 END
111 )).geom AS geom 118 )).geom AS geom
112 ) AS clipped 119 ) AS clipped
120 RETURNING id
113 ` 121 `
114 ) 122 )
115 123
116 // Do executes the actual waterway axis import. 124 // Do executes the actual waterway axis import.
117 func (wx *WaterwayAxis) Do( 125 func (wx *WaterwayAxis) Do(
164 insertStmt, err := tx.PrepareContext(ctx, insertWaterwayAxisSQL) 172 insertStmt, err := tx.PrepareContext(ctx, insertWaterwayAxisSQL)
165 if err != nil { 173 if err != nil {
166 return nil, err 174 return nil, err
167 } 175 }
168 defer insertStmt.Close() 176 defer insertStmt.Close()
177
178 checkCrossingStmt, err := tx.PrepareContext(ctx, checkCrossingAxisSQL)
179 if err != nil {
180 return nil, err
181 }
182 defer checkCrossingStmt.Close()
169 183
170 // Delete the old features. 184 // Delete the old features.
171 if _, err := tx.ExecContext(ctx, deleteWaterwayAxisSQL); err != nil { 185 if _, err := tx.ExecContext(ctx, deleteWaterwayAxisSQL); err != nil {
172 return nil, err 186 return nil, err
173 } 187 }
225 case "LineString": 239 case "LineString":
226 var l lineSlice 240 var l lineSlice
227 if err := json.Unmarshal(*feature.Geometry.Coordinates, &l); err != nil { 241 if err := json.Unmarshal(*feature.Geometry.Coordinates, &l); err != nil {
228 return err 242 return err
229 } 243 }
230 if _, err := insertStmt.ExecContext( 244 if err := storeLinestring(
231 ctx, 245 ctx,
232 l.asWKB(), 246 tx,
247 feedback,
248 l,
233 epsg, 249 epsg,
234 props.ObjNam, 250 props,
235 nobjnam, 251 nobjnam,
236 ); err != nil { 252 checkCrossingStmt,
253 insertStmt); err != nil {
237 return err 254 return err
238 } 255 }
239 features++ 256 features++
240 case "MultiLineString": 257 case "MultiLineString":
241 var ls []lineSlice 258 var ls []lineSlice
242 if err := json.Unmarshal(*feature.Geometry.Coordinates, &ls); err != nil { 259 if err := json.Unmarshal(*feature.Geometry.Coordinates, &ls); err != nil {
243 return err 260 return err
244 } 261 }
245 for _, l := range ls { 262 for _, l := range ls {
246 if _, err := insertStmt.ExecContext( 263 if err := storeLinestring(
247 ctx, 264 ctx,
248 l.asWKB(), 265 tx,
266 feedback,
267 l,
249 epsg, 268 epsg,
250 props.ObjNam, 269 props,
251 nobjnam, 270 nobjnam,
252 ); err != nil { 271 checkCrossingStmt,
272 insertStmt); err != nil {
253 return err 273 return err
254 } 274 }
255 features++ 275 features++
256 } 276 }
257 default: 277 default:
286 features, time.Since(start)) 306 features, time.Since(start))
287 } 307 }
288 308
289 return nil, err 309 return nil, err
290 } 310 }
311
312 func storeLinestring(
313 ctx context.Context,
314 tx *sql.Tx,
315 feedback Feedback,
316 l lineSlice,
317 epsg int,
318 props waterwayAxisProperties,
319 nobjnam sql.NullString,
320 checkCrossingStmt, insertStmt *sql.Stmt,
321 ) error {
322 var id int
323 if err := insertStmt.QueryRowContext(
324 ctx,
325 l.asWKB(),
326 epsg,
327 props.ObjNam,
328 nobjnam,
329 ).Scan(&id); err != nil {
330 return err
331 }
332
333 var crossing string
334 switch err := checkCrossingStmt.QueryRowContext(
335 ctx,
336 id,
337 ).Scan(&crossing); {
338 case err != nil && err != sql.ErrNoRows:
339 return err
340 case err == nil:
341 feedback.Warn(
342 "Linestring %d crosses previously imported linestring near %s. Finding a contiguous axis may not work here",
343 id, crossing)
344 }
345 return nil
346 }