├── icon.png ├── resources.qrc ├── CHANGELOG ├── metadata.txt ├── dialogs.py ├── __init__.py ├── matrix.py ├── generalizer.py ├── points.py ├── simplify.py ├── smooth.py ├── resources.py ├── ui_generalizer.ui ├── ui_generalizer.py └── generalizerdialog.py /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p0cisk/Generalizer/HEAD/icon.png -------------------------------------------------------------------------------- /resources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | icon.png 4 | 5 | 6 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | 0.5 (24.11.2013) 2 | -updated to QGIS 2.0 API (thanks to Matthew Petroff) 3 | -fix unicode error 4 | 5 | 0.4 (27.10.2013) 6 | -add setDecimal() method in batch mode. Added by Bakhtiar Hasmanan 7 | 8 | 0.3 (15.09.2011) 9 | -new algorithms: 10 | smoothing: Snakes Algorithm 11 | simplifying: Jenk's Algorithm, Reumann-Witkam Algorithm 12 | 13 | 0.2 (11.09.2011) 14 | -added batch mode 15 | -choose to save layer(s) on disk or to store in memory 16 | -new algorithms: 17 | smoothing: Hermite Spline Interpolation 18 | 19 | 0.1 (28.08.2011) 20 | -first release 21 | -supported algorithms: 22 | generalization: Remove small objects 23 | simplifying: Douglas-Peucker, Lang, Vertex Reduction 24 | smoothing: Boyle's Forward-Looking, Chaiken's, McMaster's Distance-Weighting, McMaster's Sliding Averaging -------------------------------------------------------------------------------- /metadata.txt: -------------------------------------------------------------------------------- 1 | # This file contains metadata for your plugin. Beginning 2 | # with version 1.8 this is the preferred way to supply information about a 3 | # plugin. The current method of embedding metadata in __init__.py will 4 | # be supported until version 2.0 5 | 6 | # This file should be included when you package your plugin. 7 | 8 | # Mandatory items: 9 | 10 | 11 | [general] 12 | name=Generalizer 13 | qgisMinimumVersion=2.0 14 | description=Lines generalization and smoothing (partially based on v.generalize GRASS module) 15 | version=0.5 16 | author=Piotr Pociask 17 | email= 18 | 19 | # end of mandatory metadata 20 | 21 | # Optional items: 22 | 23 | homepage=https://github.com/p0cisk/Generalizer 24 | tracker=https://github.com/p0cisk/Generalizer/issues 25 | repository=https://github.com/p0cisk/Generalizer 26 | icon=icon.png 27 | 28 | # experimental flag 29 | experimental=True 30 | 31 | # deprecated flag (applies to the whole plugin, not just a single version 32 | deprecated=False 33 | -------------------------------------------------------------------------------- /dialogs.py: -------------------------------------------------------------------------------- 1 | from PyQt4.QtGui import * 2 | from PyQt4.QtCore import * 3 | 4 | from os.path import splitext, dirname 5 | 6 | def saveDialog(parent): 7 | """Shows a save file dialog and return the selected file path.""" 8 | settings = QSettings() 9 | key = '/UI/lastShapefileDir' 10 | outDir = settings.value(key) 11 | 12 | filter = 'Shapefiles (*.shp)' 13 | outFilePath = QFileDialog.getSaveFileName(parent, parent.tr('Save output shapefile'), outDir, filter) 14 | outFilePath = unicode(outFilePath) 15 | 16 | if outFilePath: 17 | root, ext = splitext(outFilePath) 18 | if ext.upper() != '.SHP': 19 | outFilePath = '%s.shp' % outFilePath 20 | outDir = dirname(outFilePath) 21 | settings.setValue(key, outDir) 22 | 23 | return outFilePath 24 | 25 | def openDir(parent): 26 | settings = QSettings() 27 | key = '/UI/lastShapefileDir' 28 | outDir = settings.value(key) 29 | 30 | outPath = QFileDialog.getExistingDirectory(parent, 'Generalizer', outDir)#, QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks) 31 | return outPath 32 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | /*************************************************************************** 3 | generalizer 4 | A QGIS plugin 5 | "Lines generalization and smoothing (partially based on v.generalize GRASS module)" 6 | ------------------- 7 | begin : 2011-08-17 8 | copyright : (C) 2011 by Piotr Pociask 9 | email : ppociask (at) o2 pl 10 | ***************************************************************************/ 11 | 12 | /*************************************************************************** 13 | * * 14 | * This program is free software; you can redistribute it and/or modify * 15 | * it under the terms of the GNU General Public License as published by * 16 | * the Free Software Foundation; either version 2 of the License, or * 17 | * (at your option) any later version. * 18 | * * 19 | ***************************************************************************/ 20 | This script initializes the plugin, making it known to QGIS. 21 | """ 22 | def classFactory(iface): 23 | # load generalizer class from file generalizer 24 | from generalizer import generalizer 25 | return generalizer(iface) 26 | -------------------------------------------------------------------------------- /matrix.py: -------------------------------------------------------------------------------- 1 | class MATRIX(object): 2 | def __init__(self, rows, cols): 3 | self.rows = rows 4 | self.cols = cols 5 | self.a = [] 6 | 7 | 8 | i = 0 9 | while i n-1: break 36 | point_assign(points, j, p2) 37 | dst = point_dist(p1, p2) 38 | res.add_point(p2) 39 | 40 | i = j 41 | 42 | 43 | points.repleace_all_pts(res) 44 | 45 | return points.n_points 46 | 47 | 48 | 49 | def douglas_peucker(pts, tolerance): 50 | anchor = 0 51 | floater = len(pts) - 1 52 | stack = [] 53 | keep = set() 54 | 55 | if len(pts) < 3: return pts 56 | 57 | stack.append((anchor, floater)) 58 | while stack: 59 | anchor, floater = stack.pop() 60 | 61 | # initialize line segment 62 | if pts[floater] != pts[anchor]: 63 | anchorX = float(pts[floater][0] - pts[anchor][0]) 64 | anchorY = float(pts[floater][1] - pts[anchor][1]) 65 | seg_len = math.sqrt(anchorX ** 2 + anchorY ** 2) 66 | # get the unit vector 67 | anchorX /= seg_len 68 | anchorY /= seg_len 69 | else: 70 | anchorX = anchorY = seg_len = 0.0 71 | 72 | # inner loop: 73 | max_dist = 0.0 74 | farthest = anchor + 1 75 | for i in range(anchor + 1, floater): 76 | dist_to_seg = 0.0 77 | # compare to anchor 78 | vecX = float(pts[i][0] - pts[anchor][0]) 79 | vecY = float(pts[i][1] - pts[anchor][1]) 80 | seg_len = math.sqrt( vecX ** 2 + vecY ** 2 ) 81 | # dot product: 82 | proj = vecX * anchorX + vecY * anchorY 83 | if proj < 0.0: 84 | dist_to_seg = seg_len 85 | else: 86 | # compare to floater 87 | vecX = float(pts[i][0] - pts[floater][0]) 88 | vecY = float(pts[i][1] - pts[floater][1]) 89 | seg_len = math.sqrt( vecX ** 2 + vecY ** 2 ) 90 | # dot product: 91 | proj = vecX * (-anchorX) + vecY * (-anchorY) 92 | if proj < 0.0: 93 | dist_to_seg = seg_len 94 | else: # calculate perpendicular distance to line (pythagorean theorem): 95 | dist_to_seg = math.sqrt(abs(seg_len ** 2 - proj ** 2)) 96 | if max_dist < dist_to_seg: 97 | max_dist = dist_to_seg 98 | farthest = i 99 | 100 | if max_dist <= tolerance: # use line segment 101 | keep.add(anchor) 102 | keep.add(floater) 103 | else: 104 | stack.append((anchor, farthest)) 105 | stack.append((farthest, floater)) 106 | 107 | keep = list(keep) 108 | keep.sort() 109 | return [pts[i] for i in keep] 110 | 111 | 112 | def lang(points, eps, look_ahead): 113 | i = 0 114 | j = look_ahead 115 | n = points.n_points 116 | if j > n-1: j = n-1 117 | p1 = point() 118 | p2 = point() 119 | p = point() 120 | res = line_pnts() 121 | 122 | point_assign(points, i, p1) 123 | point_assign(points, j, p2) 124 | res.add_point_xy(points.x[0], points.y[0]) 125 | #point_add_new(points, 0, res) #use point_add insted of this function 126 | 127 | end = False 128 | while not end: 129 | dists = [] 130 | between = True 131 | 132 | for m in range(i+1, j): 133 | point_assign(points, m, p) 134 | dists.append(point_distance(p1, p2, p)) 135 | 136 | for dist in dists: 137 | if dist > eps: 138 | between = False 139 | break 140 | 141 | if not between: 142 | j = j - 1 143 | point_assign(points, j, p2) 144 | else: 145 | res.add_point_xy(points.x[j], points.y[j]) 146 | #point_add_new(points, j, res) #use point_add insted of this function 147 | i = j 148 | if i == n-1: 149 | end = True 150 | j = j + look_ahead 151 | if j > n-1: j = n-1 152 | point_assign(points, i, p1) 153 | point_assign(points, j, p2) 154 | 155 | points.repleace_all_pts(res) 156 | 157 | return points.n_points 158 | 159 | 160 | def jenks(points, threshold, angle_thresh): 161 | n = points.n_points 162 | i = 1 163 | p = point() 164 | p1 = point() 165 | p2 = point() 166 | res = line_pnts() 167 | 168 | res.add_point_xy(points.x[0], points.y[0]) 169 | #point_add_new(points, 0, res) #use point_add insted of this function 170 | 171 | point_assign(points, 0, p1) 172 | while i < n-1: 173 | point_assign(points, i, p) 174 | point_assign(points, i+1, p2) 175 | 176 | dist = point_distance(p1, p2, p) 177 | #angle = point_angle(p1, p, p2) 178 | #print i, angle 179 | if dist >= threshold:# and angle >= angle_thresh: 180 | i = i + 1 181 | res.add_point_xy(points.x[i-1], points.y[i-1]) 182 | point_assign(points, i-1, p1) 183 | else: 184 | while dist < threshold:# or angle < angle_thresh: 185 | i = i+1 186 | if i == n-1: break 187 | point_assign(points, i, p) 188 | point_assign(points, i+1, p2) 189 | dist = point_distance(p1, p2, p) 190 | #angle = point_angle(p1, p, p2) 191 | 192 | res.add_point_xy(points.x[n-1], points.y[n-1]) 193 | 194 | points.repleace_all_pts(res) 195 | 196 | return points.n_points 197 | 198 | 199 | def reumann_witkam(points, thresh): 200 | x0 = point() 201 | x1 = point() 202 | x2 = point() 203 | sub = point() 204 | diff = point() 205 | res = line_pnts() 206 | same = True 207 | 208 | n = points.n_points 209 | 210 | if n<3: return n 211 | 212 | thresh = thresh**2 213 | 214 | seg1 = 0 215 | seg2 = 1 216 | count = 1 217 | 218 | point_assign(points, 0, x1) 219 | res.add_point(x1) 220 | i = 1 221 | while same: 222 | point_assign(points, i, x2) 223 | same = compare_points(x1, x2) 224 | i = i+1 225 | if i == n: return n 226 | point_substract(x2, x1, sub) 227 | subd = point_dist2(sub) 228 | 229 | i = 2 230 | while i < n: 231 | point_assign(points, i, x0) 232 | point_substract(x1, x0, diff) 233 | diffd = point_dist2(diff) 234 | sp = point_dot(diff, sub) 235 | if subd == 0: dist = 0 236 | else: dist = (diffd * subd - sp*sp) / subd 237 | 238 | if dist > thresh: 239 | point_assign(points, i-1, x1) 240 | same = True 241 | j = i 242 | while same: 243 | point_assign(points, j, x2) 244 | same = compare_points(x2, x1) 245 | j = j+1 246 | point_substract(x2, x1, sub) 247 | subd = point_dist2(sub) 248 | 249 | res.add_point(x0) 250 | 251 | count = count + 1 252 | 253 | i = i+1 254 | 255 | res.add_point_xy(points.x[n-1], points.y[n-1]) 256 | 257 | 258 | points.repleace_all_pts(res) 259 | 260 | return points.n_points 261 | 262 | 263 | 264 | """ 265 | l = [[0,0], [1,1], [1,2], [2,3], [3,3], [4,2], [5,3], [4,5], [4,7], [6,9], [9,10]] 266 | #l = [[9,10], [6,9], [4,7], [4,5], [5,3], [4,2], [3,3], [2,3], [1,2], [1,1], [0,0]] 267 | #l = [(487532,653736), (487532,653736), (487608,653726), (487646,653736)] 268 | p = Vect_new_line_struct(l) 269 | reumann_witkam(p, 1) 270 | print l 271 | print 'X,Y' 272 | for i in range(len(p.x)): 273 | print p.x[i], ',', p.y[i]""" -------------------------------------------------------------------------------- /smooth.py: -------------------------------------------------------------------------------- 1 | from PyQt4.QtGui import * 2 | from points import * 3 | from matrix import * 4 | 5 | GRASS_EPSILON = 1.0e-15 6 | 7 | 8 | def boyle(points, look_ahead): 9 | ppoint = point() 10 | npoint = point() 11 | last = point() 12 | next = 1 13 | i = 0 14 | p = 0 15 | c1 = 0. 16 | c2 = 0. 17 | 18 | n = points.n_points 19 | 20 | if look_ahead < 2 or look_ahead > n: return n 21 | 22 | point_assign(points, 0, last) 23 | 24 | c1 = 1. / float(look_ahead-1) 25 | c2 = 1. - c1 26 | 27 | while i < n-2: 28 | p = i + look_ahead 29 | if p >= n: p = n - 1 30 | point_assign(points, p, ppoint) 31 | point_scalar(ppoint, c1, ppoint) 32 | point_scalar(last, c2, last) 33 | points_add(last, ppoint, npoint) 34 | points.repleace_point(next, npoint) 35 | 36 | next = next + 1 37 | i = i + 1 38 | 39 | last = npoint 40 | 41 | points_copy_last(points, next) 42 | 43 | return points.n_points 44 | 45 | def sliding_averaging(points, slide, look_ahead): 46 | n = 0 47 | half = 0 48 | i = 1 49 | sc = 0. 50 | p = point() 51 | tmp = point() 52 | s = point() 53 | 54 | n = points.n_points 55 | res = [] 56 | for w in range(n): 57 | res.append(point()) 58 | 59 | half = look_ahead / 2 60 | 61 | if look_ahead % 2 == 0: 62 | return n 63 | 64 | if look_ahead >= n or look_ahead == 1: 65 | return 0 66 | 67 | sc = 1. / float(look_ahead) 68 | 69 | point_assign(points, 0, p) 70 | while i < look_ahead: 71 | point_assign(points, i, tmp) 72 | points_add(p, tmp, p) 73 | i = i + 1 74 | 75 | i = half 76 | while i+half < n: 77 | point_assign(points, i, s) 78 | point_scalar(s, 1. - slide, s) 79 | point_scalar(p, sc*slide, tmp) 80 | points_add(tmp, s, res[i]) 81 | if i+half+1 < n: 82 | point_assign(points, i-half, tmp) 83 | point_substract(p, tmp, p) 84 | point_assign(points, i+half+1, tmp) 85 | points_add(p, tmp, p) 86 | i = i + 1 87 | 88 | i = half 89 | while i+half < n: 90 | points.repleace_point(i, res[i]) 91 | 92 | i = i + 1 93 | 94 | return points.n_points 95 | 96 | def distance_weighting(points, slide, look_ahead): 97 | p = point() 98 | c = point() 99 | s = point() 100 | tmp = point() 101 | 102 | n = 0 103 | i = 0 104 | half = 0 105 | j = 0 106 | 107 | dists = 0. 108 | d = 0. 109 | 110 | n = points.n_points 111 | 112 | res = [] 113 | for w in range(n): 114 | res.append(point()) 115 | 116 | if look_ahead % 2 == 0: 117 | return n 118 | 119 | point_assign(points, 0, res[0]) 120 | 121 | half = look_ahead / 2 122 | 123 | i = half 124 | while i+half < n: 125 | point_assign(points, i, c) 126 | s.x = 0. 127 | s.y = 0. 128 | dists = 0. 129 | 130 | j = i-half 131 | while j <= i+half: 132 | if j == i: 133 | j = j + 1 134 | continue 135 | 136 | point_assign(points, j, p) 137 | d = point_dist(p, c) 138 | 139 | if d < GRASS_EPSILON: 140 | 141 | j = j + 1 142 | continue 143 | 144 | d = 1. / d 145 | dists = dists + d 146 | point_scalar(p, d, tmp) 147 | s.x = s.x + tmp.x 148 | s.y = s.y + tmp.y 149 | j = j + 1 150 | 151 | if dists == 0: 152 | point_scalar(s, slide, tmp) 153 | else: 154 | point_scalar(s, slide/dists, tmp) 155 | point_scalar(c, 1.-slide, s) 156 | points_add(s, tmp, res[i]) 157 | i = i + 1 158 | 159 | i = half 160 | while i+half < n: 161 | points.repleace_point(i, res[i]) 162 | 163 | i = i + 1 164 | 165 | return points.n_points 166 | 167 | 168 | def chaiken(points, level, weight): 169 | n = 0 170 | i = 0 171 | j = 0 172 | p0 = point() 173 | pn = point() 174 | p1 = point() 175 | p2 = point() 176 | m1 = point() 177 | m2 = point() 178 | res = line_pnts() 179 | 180 | n = points.n_points 181 | 182 | if n < 3: return n 183 | 184 | d1 = 1./(1+weight) 185 | d2 = float(weight)/(1+weight) 186 | 187 | point_assign(points, 0, p0) 188 | point_assign(points, n-1, pn) 189 | 190 | tmp = line_pnts(points) 191 | 192 | for i in range(level): 193 | cut_edges(tmp, res, d1, d2) 194 | 195 | res.n_points = len(res.x) 196 | tmp = line_pnts(res) 197 | 198 | res = line_pnts() 199 | 200 | 201 | tmp.insert_point(0, p0) 202 | tmp.add_point(pn) 203 | 204 | points.repleace_all_pts(tmp) 205 | 206 | return points.n_points 207 | 208 | 209 | def point_calc_new(p1, p2, d, m): 210 | m.x = (p1.x+d*(p2.x-p1.x)) 211 | m.y = (p1.y+d*(p2.y-p1.y)) 212 | 213 | 214 | def cut_edges(points, res, d1, d2): 215 | p1 = point() 216 | p2 = point() 217 | m1 = point() 218 | m2 = point() 219 | 220 | for i in range(points.n_points): 221 | if i == points.n_points-1: break 222 | point_assign(points, i, p1) 223 | point_assign(points, i+1, p2) 224 | 225 | point_calc_new(p1, p2, d1, m1) 226 | point_calc_new(p1, p2, d2, m2) 227 | 228 | res.add_point(m1) 229 | res.add_point(m2) 230 | 231 | 232 | def hermite(points, threshold, a): 233 | i = 1 234 | p1 = point() 235 | p2 = point() 236 | t1 = point() 237 | t2 = point() 238 | h1p1 = point() 239 | h2p2 = point() 240 | h3t1 = point() 241 | h4t2 = point() 242 | tmp1 = point() 243 | tmp2 = point() 244 | tmp = point() 245 | 246 | res = line_pnts() 247 | 248 | 249 | point_assign(points, 1, p1) 250 | point_assign(points, 0, p2) 251 | t1 = getEdgeTangent(p1, p2) 252 | points.insert_point(0, t1) 253 | 254 | point_assign(points, -2, p1) 255 | point_assign(points, -1, p2) 256 | t2 = getEdgeTangent(p1, p2) 257 | points.insert_point(points.n_points, t1) 258 | 259 | n = points.n_points 260 | 261 | if n < 3: 262 | return n 263 | 264 | h1 = lambda s: (2*(s**3))-(3*(s**2))+1 265 | h2 = lambda s: 3*(s**2)-2*(s**3) 266 | h3 = lambda s: (s**3)-(2*(s**2))+s 267 | h4 = lambda s: (s**3)-(s**2) 268 | ht = lambda s: (1+2*s)*(1-s)**2 269 | 270 | while i < n-2: 271 | point_assign(points, i, p1) 272 | point_assign(points, i+1, p2) 273 | 274 | dist = point_dist(p1, p2) 275 | #t = 0. 276 | if dist == 0 or dist= 0 and index <=4: 377 | g.a[i][j] = val[index] 378 | else: 379 | g.a[i][j] = 0 380 | j = j +1 381 | 382 | i = i+1 383 | 384 | i = 0 385 | while i < g.rows: 386 | g.a[i][i]= g.a[i][i] + 1. 387 | i = i+1 388 | 389 | print 2 390 | ginv = matrix_inverse(g) 391 | print 3 392 | 393 | xout = matrix_mult(ginv, xcoord) 394 | yout = matrix_mult(ginv, ycoord) 395 | 396 | print 4 397 | 398 | i = 1 399 | while i < n-1: 400 | points.x[i] = xout.a[i+plus][0] + x0 401 | points.y[i] = yout.a[i+plus][0] + y0 402 | 403 | i = i+1 404 | 405 | points.n_points = len(points.x) 406 | return points.n_points 407 | 408 | """ 409 | l = [[0,0], [1,1], [1,2], [2,3], [3,3], [4,2], [5,3], [4,5], [4,7], [6,9], [9,10]] 410 | p = Vect_new_line_struct(l) 411 | pi = hermite(p, 1, 0.3) 412 | print l 413 | print 'X;Y' 414 | for i in range(len(p.x)): 415 | print p.x[i], ';', p.y[i]""" -------------------------------------------------------------------------------- /resources.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Resource object code 4 | # 5 | # Created: N 28. sie 10:51:26 2011 6 | # by: The Resource Compiler for PyQt (Qt v4.7.1) 7 | # 8 | # WARNING! All changes made in this file will be lost! 9 | 10 | from PyQt4 import QtCore 11 | 12 | qt_resource_data = "\ 13 | \x00\x00\x17\xc5\ 14 | \x89\ 15 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ 16 | \x00\x00\x40\x00\x00\x00\x40\x08\x06\x00\x00\x00\xaa\x69\x71\xde\ 17 | \x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\ 18 | \x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0d\xd7\x00\x00\x0d\xd7\ 19 | \x01\x42\x28\x9b\x78\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\ 20 | \x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\ 21 | \x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x17\x42\x49\x44\ 22 | \x41\x54\x78\x9c\xed\x9b\x5b\x6c\x5d\xd7\x9d\xde\x7f\xdf\xda\xfb\ 23 | \x5c\x78\x48\xf1\x4e\x91\x12\x69\x49\xb6\x25\xcb\x36\x6d\xc7\x36\ 24 | \xed\xf8\x96\xd8\x72\x9a\x66\xea\x41\x9b\x5e\x50\x69\x8a\x4e\xd1\ 25 | \x87\x00\x35\x50\x14\x19\xa0\x83\xe9\xbc\x8a\x7c\x9d\x87\x0e\xd0\ 26 | \x3c\x65\x80\x62\xda\x87\xbe\x48\x40\x81\xa6\xd3\x64\x92\x60\x12\ 27 | \x66\x9a\x9b\xe3\xc8\x76\xe2\x50\x96\x2d\x59\x17\x8b\xa4\x28\x91\ 28 | \xa2\xc4\x8b\x78\x6e\x7b\xaf\xaf\x0f\xe7\x50\x17\x5b\x96\x25\xc5\ 29 | \x99\x04\x98\xfe\x81\x03\xf0\x90\xe7\xec\xf5\x5f\xdf\xfa\xfe\xf7\ 30 | \x45\xd9\xe6\xef\xb3\x84\xdf\xb6\x02\xbf\x6d\xf9\xff\x00\xfc\xb6\ 31 | \x15\xf8\x6d\xcb\xdf\x7b\x00\xd2\xdb\xf9\x90\x84\x00\x6c\x7e\x27\ 32 | \x3c\x66\x5b\x9f\xcd\x97\x41\xf6\x5d\x7a\x73\xdd\xea\x7b\x12\x7a\ 33 | \xf5\xd5\x23\x29\x9c\x2b\x74\x76\x0e\xf8\xca\x95\x62\xb6\x7d\xfb\ 34 | \x5f\xe5\x93\x93\x93\x77\xbd\xe0\xaf\x2b\x12\x9a\x98\x20\x5d\x5c\ 35 | \xfc\xa0\x4b\xaa\x94\xed\x8d\xda\xd0\xd0\x8e\xf5\x23\x47\xc8\xee\ 36 | \xe6\x80\x6e\x09\xc0\xd4\xd4\x74\x3a\x3b\xdb\x31\x10\x42\x63\x34\ 37 | \x0f\xa4\x49\x4c\x2e\xe6\xf9\xda\xa5\x4a\xe5\xfe\x2b\x0b\x0b\x6f\ 38 | \x66\x87\x0f\xef\x8f\x7f\x97\xac\x90\xd0\xee\xdd\x14\xab\xd5\xe5\ 39 | \x21\xf0\x03\x0e\x61\x6b\xb0\x16\x6a\xca\xde\x5b\x3a\x7b\x61\x09\ 40 | \x1e\x6e\xde\xa9\x3e\x1f\x0b\x80\x84\xbe\xf2\x95\x6f\x74\x25\x49\ 41 | \xef\xa3\x04\xbe\x60\x6b\x20\x5a\x67\x9d\xf1\x9e\x1d\xcf\xd4\xeb\ 42 | \xa5\x0b\x5b\xb6\xa4\x6b\xef\x6d\x5f\x6b\x4c\x4f\xee\xcb\x7f\xd3\ 43 | \x40\x48\x68\xd7\xae\xd3\x25\x28\x8f\xd8\x85\x27\x73\xf3\x12\xd6\ 44 | \x3d\x79\xe4\x94\x89\xdf\xcb\xea\xbc\xb1\xb4\x34\xb8\x04\x77\xc6\ 45 | \x84\x8f\x05\xe0\xc0\x81\xc3\xc9\xf0\x70\xef\x70\xb3\x59\xfa\x62\ 46 | \x84\x3f\x88\xd6\xfd\x8e\x61\xd5\x91\x53\x46\xef\xc4\x2c\xbc\x93\ 47 | \xe1\x53\xb1\x91\x9e\xdb\xa8\x34\x2e\x8f\xa4\xe5\xda\x6f\xca\x3c\ 48 | \x5a\x9b\xa7\x14\x8b\x17\xb6\x87\x3c\x7c\xd6\xb9\xbf\x14\xa3\x9e\ 49 | \xc9\xad\x7e\xa2\x16\x72\xf8\x81\x23\xdf\x22\x2f\xbd\x75\xe1\xc2\ 50 | \xb1\x65\x78\x2a\xbb\x5d\x1d\x3e\xd6\x09\x8e\x8c\x74\xa5\xb5\x98\ 51 | \xf6\x49\xdc\x2b\x73\x8f\x60\xcc\x20\xa3\x9d\xd1\x7a\xd8\xf0\x01\ 52 | \xd6\xbb\x4a\x7d\xb4\x54\x2d\x1e\x5f\x89\xcc\xce\xad\xff\x83\xe5\ 53 | \x57\x5e\xf9\xc3\x8d\xa9\x29\x9a\x93\x93\xf8\xd3\x62\xc5\xbe\x7d\ 54 | \x24\xf3\xf3\xb3\x03\xcd\x58\x7a\xd2\xf6\xef\x21\x9e\x47\x8c\x2a\ 55 | \x52\x8a\xa2\xa2\xa8\x68\x87\x46\xae\x2c\x1b\x19\xd9\xfb\xcb\x85\ 56 | \x05\x5f\x02\xb2\xdb\x79\xf6\x4d\xc3\xa0\x24\xe5\x79\x47\x21\x8d\ 57 | \x0c\x02\x3b\xc0\xfd\x12\x25\x70\x07\x30\x80\xbd\xc7\xf0\x9c\xac\ 58 | \x7f\x62\xeb\x0f\x05\xff\x26\xb3\xbf\xdc\xd1\xe8\x7c\xb6\x52\xb9\ 59 | \xb2\xfb\xc8\xbb\xef\xf5\xef\xdb\x37\x5d\x9a\x9a\xfa\x74\xc2\xec\ 60 | \xec\xec\x89\x24\xc6\xb4\x47\xb0\x1b\xf1\x20\x30\x02\x74\x20\x52\ 61 | \x4c\xa7\xe1\x3e\xf0\x4b\xc0\x17\xb2\x2c\x7b\x78\x74\x74\xad\x47\ 62 | \x9a\xbe\xad\x08\x77\xd3\x0f\xed\xdf\x7f\x28\xc4\x58\xac\x84\x90\ 63 | \x8d\x08\x46\x8d\xba\x1c\x49\x68\x85\x9d\x04\x42\x00\x15\x0c\x5d\ 64 | \xc2\xc3\xb2\xee\x17\x3c\x16\xf1\x49\x94\x1d\x4d\xaa\x1b\x6f\x77\ 65 | \x76\x76\xbf\xfb\xd6\x5b\x6f\x9d\x7b\xf9\xe5\xc7\xd7\xa7\xa7\xf9\ 66 | \xb5\x7c\x44\x4f\xcf\x4a\xbc\x78\xb1\x6b\x23\x84\x78\x41\x84\x45\ 67 | \xc3\x06\xd0\x01\x6a\xe9\x63\xb6\x18\xf6\x60\x65\x11\x35\xab\x55\ 68 | \x9a\x3d\x3b\x9e\x78\x47\x62\xd5\x26\xbf\x63\x00\xfa\xfa\xee\x0b\ 69 | \x79\x72\xb9\x57\xa4\x3b\x40\x43\x98\x52\x7b\xf3\x6d\x71\x3b\x06\ 70 | \x2b\xd8\xa4\x86\x16\x33\xe4\x9d\x31\x0f\x0f\x45\x78\x24\x84\xf0\ 71 | \x7a\x9e\xfb\xf5\xee\xee\x77\x8f\xef\xdb\x57\x5a\x96\x76\x35\x6c\ 72 | \xe2\xdd\x00\x70\xe4\xc8\x44\x36\x3e\xbe\xb8\x74\xe5\x0a\x6f\x48\ 73 | \xea\x03\x2a\xc6\x8f\x81\xfb\x40\x69\x0b\x04\x6d\x01\xf6\x1a\x65\ 74 | \x88\x86\xaf\x14\xb3\xde\xde\xcb\xef\x49\xbd\x6b\xb7\x02\xe1\x23\ 75 | \x14\x95\x24\xa0\x10\x48\x07\xc0\x3b\xb1\xfb\x3f\x04\x94\x41\xb1\ 76 | \xf5\xc2\x6d\x60\x52\xa0\x03\x33\x08\x3c\x80\xfd\xa2\xc5\x3f\x37\ 77 | \xe1\x5f\x34\x63\xed\xf3\x1d\x1d\x97\xee\xfb\xe2\x17\x8f\x6c\x79\ 78 | \xf9\xe5\xe9\x74\x33\xa9\xba\x13\xb1\xf1\xcc\xcc\x74\x35\x84\xf4\ 79 | \x94\xa4\xbf\x8d\xd1\xdf\x13\x3a\x0a\xac\x80\xda\xb6\xee\x14\xd3\ 80 | \x03\x3c\x64\x87\x2f\x28\x66\x2f\xd9\xc5\xfb\xfa\xfb\xe9\x94\x3e\ 81 | \xde\x14\x3f\xc2\x80\xc9\xc9\x49\xad\xac\x34\xca\xb5\x9a\x87\x15\ 82 | \x18\x03\xba\x41\x9b\x0f\x30\xb8\x01\xae\xba\xc5\x80\x22\x50\x80\ 83 | \xeb\xcd\x83\x32\x52\x01\xab\x12\xcd\x00\x0e\xdb\xad\x30\x9a\x24\ 84 | \x7e\xbd\x9e\x0c\x9f\xd8\xb7\xef\xf4\xa5\xbb\x61\x83\xbd\x3f\x97\ 85 | \x58\xdf\xb1\x63\xe5\x44\x50\xbd\x90\x5b\x05\xa3\x14\xfc\x30\xa8\ 86 | \xbb\xbd\x76\x82\xd5\x6b\xfc\x88\x63\xc8\xb0\x1a\xf5\xfa\x95\x1c\ 87 | \xaa\x27\xa5\xc1\x2b\x37\x5b\xf3\x26\x26\xf0\x52\xb0\xeb\xdd\x4a\ 88 | \x19\xb3\x19\x96\x28\xdb\x0e\x6d\x0b\xc8\x8c\x17\x11\xef\x83\x6a\ 89 | \x88\x41\x60\x18\xdc\x0b\x2a\xb5\x9f\x27\x20\x95\xd4\x05\xda\x69\ 90 | \xd3\xed\xa8\x91\xdc\x8c\x15\xf1\x8f\x63\xb9\xfe\xf6\x2b\xaf\x9c\ 91 | \x38\xf7\xf2\xcb\xb3\x1b\xd3\xd3\x77\x96\x3f\xd8\xe4\x52\xcf\xea\ 92 | \xe8\xe8\xdc\xbb\x21\x14\x53\x47\x15\x8c\x53\xc3\x5e\xd0\x16\x70\ 93 | \xd2\x62\x82\xfa\x11\x8f\xd9\x31\x93\xd4\xec\xea\xea\xce\xd6\xd7\ 94 | \x39\x2d\x51\xfd\x30\x08\x1f\x01\x60\x66\x66\xb1\x30\x38\xd8\x33\ 95 | \xa0\xa4\xb8\x13\x34\x40\xeb\x84\xa1\x45\xf7\x9a\xa4\x93\x96\xbf\ 96 | \x45\xce\x9c\x1d\xb7\xe1\xe4\x41\xa3\x3d\x46\xf7\x00\x03\xb4\xfc\ 97 | \x41\xd2\x02\x8d\x12\x68\xc8\x50\x81\x30\x00\xda\xee\x66\x1c\xad\ 98 | \xdb\xaf\xc3\xd6\x93\xaf\xbc\x72\xe2\x92\xf4\x3f\x9a\xf6\xc1\xdb\ 99 | \x66\x43\x0b\x84\xd1\x95\x91\x91\x85\x77\x9c\x84\x54\x56\x51\x28\ 100 | \xb5\xbd\x07\xd4\x45\xcb\xac\x53\xcc\x80\x1d\x3e\x03\x34\x63\x8c\ 101 | \xcd\x62\xb1\x91\x37\x1a\xc5\x0f\xa4\xa9\xda\xf5\xeb\xdd\x00\x40\ 102 | \x2b\xf7\xef\x2b\xaa\xa0\x21\xcc\x3d\x32\x3d\x6e\xfb\x09\x89\x1c\ 103 | \xb1\x2a\xf4\x7e\xc0\x6f\x34\x92\x70\xcc\xf5\x66\x87\x93\xf0\x73\ 104 | \xe5\xc9\x5e\xe1\xc7\x23\xe1\x31\xc1\xbd\x40\x9f\xa4\xc2\xa6\x32\ 105 | \x12\x5b\x80\x7b\xb1\x7b\xa4\x30\x92\xa3\x51\x2b\xfc\x74\x6d\x2d\ 106 | \xfb\xd5\x0b\x2f\xfc\x87\x73\x2f\xbf\x3c\x5d\xbd\x13\x36\xd8\x64\ 107 | \xd2\xdc\xe5\xe1\xe1\xbd\xbf\x8a\x49\x23\x15\xb1\x00\x21\x05\xdd\ 108 | \x07\x74\xb6\xd7\x2d\x00\x43\xd1\x3c\x69\x9c\x85\x10\x9b\xa5\x52\ 109 | \x3d\xaf\xd7\x0f\xce\x4a\xd4\x36\xd7\xba\x01\x80\x7d\xfb\xa6\x93\ 110 | \x52\x29\xdd\x62\x31\x1a\xa3\xb7\xd1\x3a\xb9\xd0\x3e\xff\x5c\xe6\ 111 | \x92\xed\xd3\x39\xcd\x73\x65\x8f\x2e\x5e\x89\xaf\xc7\x62\xba\x63\ 112 | \x21\x0f\xcd\x53\xce\x8b\xef\x39\xc6\x93\x26\x7d\x16\x34\x6e\x7b\ 113 | \x1b\xa8\xcd\x06\x02\x50\x32\xde\x6a\xbb\x42\x64\xd0\x84\x31\x8b\ 114 | \xed\x8e\x97\x8f\x54\xab\x83\x27\x77\xef\x3e\x71\xf9\xce\xd8\x30\ 115 | \x91\x9d\x3f\xcf\xa5\xc1\xc1\xa5\xb7\x49\x93\x82\x50\xd1\xa6\x00\ 116 | \xda\x45\x8b\x85\x02\x17\x21\x6c\xb5\x99\x00\x9a\xb6\x9a\x94\xeb\ 117 | \x39\xb5\xd2\xbc\x44\xdd\xc6\x37\x00\xf0\xe8\xa3\xd5\xc4\x69\xa1\ 118 | \x8f\x3c\xd9\x29\x31\xd8\x7a\xa0\x05\xb2\xa1\x81\x58\x94\xf4\x41\ 119 | \x21\x2f\x2c\x9f\x3c\xfd\xdf\xb3\xef\x7f\xff\x60\x26\xd1\x7c\xf5\ 120 | \xd5\x23\xd5\xb9\xf5\x8d\x95\x72\xdc\x72\x3e\x27\x9e\x35\x9a\xc3\ 121 | \x9a\x68\x9f\x48\xef\x35\x36\x28\x95\xd4\x1d\x51\x49\x76\x2f\xd2\ 122 | \x48\x0c\x8c\x41\xf9\x27\x43\x43\x9a\x49\x86\xff\xd5\xf9\x03\x07\ 123 | \xd8\x38\x7c\x58\xf1\x93\x52\x59\x1b\x4b\x64\x5d\x5d\xeb\x97\xaa\ 124 | \xd5\x8e\xa3\x79\x2c\xf6\xa2\x74\x08\xd3\xdb\x76\xce\x6d\x7f\xe4\ 125 | \x12\x68\x9b\xad\xa7\x0d\xcd\x24\xaa\x99\x53\x7b\x0d\xca\x0b\x12\ 126 | \x8d\xab\x00\x48\xe8\x2b\x7f\xda\x5d\xec\xca\xb2\xc1\x18\xe2\x0e\ 127 | \x22\xbd\xf6\x55\x86\x44\xf0\x86\x61\x81\x3c\x9b\xaf\xd7\x4b\xeb\ 128 | \xd3\xd3\x07\xf3\x4d\x45\x60\xa2\x39\x35\xc5\xca\xcc\xcc\x4f\x6a\ 129 | \x81\xca\xe5\x7a\x93\x05\xe3\x59\xcc\x73\x58\xe3\xb6\x87\x37\xd9\ 130 | \xd4\x66\x43\xd9\x66\x18\x87\x8a\xd0\x20\x78\x34\xb3\xb6\x6f\x89\ 131 | \xc5\x23\x27\x16\x16\x4e\x8d\x8f\xcf\xac\x48\x7c\x6c\x65\xd7\x0a\ 132 | \xd5\xd6\xee\xdd\x14\xaa\xd5\x42\x27\x14\x3b\x5b\x24\xa5\x8a\xdd\ 133 | \x68\xfd\x78\x35\xda\xaa\xc5\x3e\xb6\x83\x9e\xc1\xb1\x99\x24\x85\ 134 | \x66\x9e\xf3\x3a\x70\xe1\x2a\x00\xfb\xf7\x1f\x0e\x5b\xea\xfd\x95\ 135 | \x28\xb6\x63\x6d\xbf\xce\xa1\x00\xca\x11\x97\x65\x7d\x80\xbc\x58\ 136 | \x28\x54\x1b\x1f\x56\xee\xe0\x41\xa2\xf4\x5c\x6d\xdf\x24\xe7\x3b\ 137 | \x5f\x7f\x7b\xc3\x66\x29\x2a\xce\xa1\x30\xe7\xa8\x09\xe0\x5e\x70\ 138 | \xaf\x14\xd2\x4d\x36\x80\x7b\x30\x65\xa3\x5e\xf0\x36\x72\x8d\x29\ 139 | \x6f\xfc\xa4\x52\xe9\x3a\x3a\x3e\xbe\x78\xe1\xc0\x81\xa1\xea\x87\ 140 | \xd9\x20\x11\x76\xef\x3e\x5e\xa8\xd5\x56\x3b\xd7\x1b\xd9\x88\x29\ 141 | \xdd\x67\xf1\x10\x41\x8f\x06\xfb\x91\x28\xf5\x62\x7d\x38\xee\xab\ 142 | \x05\xba\xc7\x44\x78\xc6\xc4\x8d\x34\xf5\x95\x2c\x4b\x6b\xd7\x4c\ 143 | \x60\x9c\x24\x5f\xcb\xfb\x92\x98\xde\x93\xb7\xb2\xbf\xa2\x5a\xc5\ 144 | \x8f\xc1\x19\xe6\xa2\xc4\x19\x93\x2d\xef\xda\x15\x6e\x5a\x68\xb4\ 145 | \x41\xc9\xa6\xa6\x1e\x5d\x99\x99\x99\xad\xad\xac\x5c\xbe\xec\x10\ 146 | \xcf\x41\x98\x33\x7a\x16\xf3\x70\x8b\x0d\xea\x68\xe7\x16\x01\x28\ 147 | \x63\x46\x84\xba\xa2\x19\x74\x8c\xa3\x4d\x87\x1f\xab\x58\x7b\xe3\ 148 | \xe4\xc9\x73\xa7\xc7\xc7\x67\x56\xa5\x56\x61\x33\x3e\x7e\x34\xdd\ 149 | \xb5\x6b\x7b\x25\xcf\x7b\x87\x49\xf2\xfb\x13\xfb\x33\x39\xc9\x63\ 150 | \x48\xbb\x05\xdb\xdc\x0a\xc7\xe5\x56\x38\xbc\x21\xdf\x72\xfb\x15\ 151 | \x0c\xdd\x48\x3b\xec\x6c\x07\x64\xc7\xd3\x4d\x4a\xfd\xc9\x9f\x7c\ 152 | \xbb\x90\xe5\x85\x81\x9c\xb8\x4b\xa6\x1f\x94\xfa\xea\x97\x5d\x95\ 153 | \x74\x3e\xa2\xd9\x6a\xb1\xb8\x0a\x7f\x13\x61\xdf\xcd\x30\xb8\x8e\ 154 | \x0d\x63\xb5\x89\x89\xf3\x0b\x23\x23\xc5\xf5\x5a\x5e\x58\x14\x71\ 155 | \x36\xca\xcf\x63\x9e\xc4\xec\x32\xee\x01\x15\xda\xa7\x53\x70\x2b\ 156 | \x8b\xdb\x23\xe8\x8b\xb0\x4d\x91\xb1\x46\xd6\xf8\x69\x96\x74\xbe\ 157 | \x73\xdf\x7d\x27\x97\x63\x77\xbf\xea\xeb\x83\x03\x52\xe3\xbe\x48\ 158 | \x78\x0c\xe2\x13\x36\x0f\x4a\x1e\x35\xee\x41\x49\x01\x6b\x33\x21\ 159 | \xdb\x94\x08\xe4\x40\x43\x62\x15\x58\xc4\x3a\x25\xe2\xdb\x46\x73\ 160 | \x90\x55\x53\x68\x65\x7f\x6b\x6b\x8d\x0e\x92\xc2\x70\x30\xa3\x31\ 161 | \x67\xcb\x35\xfa\x6f\x86\x3f\xce\xc6\xc8\x85\xae\xfc\x72\xfd\xe0\ 162 | \xc1\x4f\xf6\xd4\xd7\xfb\x86\x23\x47\x8e\xd4\xab\xd5\x8e\xcb\xd1\ 163 | \x3a\x27\x6b\x16\xf1\x1c\xd6\x83\xc0\x56\x5a\x45\xcd\x26\x1b\x3a\ 164 | \x0c\xdb\x84\x3a\xc1\x43\x26\x19\x4d\xad\xd7\x5c\x2a\x9c\xcc\x37\ 165 | \x6a\x05\x4b\x7b\x2c\x1e\xc7\x3c\x2c\x7c\x8f\x50\xaf\x4d\xa9\xf5\ 166 | \x7d\xab\xbd\x77\xb7\x37\x9e\x81\xab\x48\xcb\xe0\x73\x26\x9c\x44\ 167 | \xbc\x8b\xe2\xbb\xb2\x4e\x65\x59\x71\x1e\x4a\x97\x53\x80\xf9\xf9\ 168 | \x6d\x49\x67\x7f\x47\xb7\x9a\xf1\x9e\x68\x6d\x45\x94\xdb\xce\x0a\ 169 | \x20\x93\x75\x31\x3a\x9c\x09\x79\x76\x91\x64\x5b\xf3\x93\x36\xff\ 170 | \x51\x36\x4c\x54\x27\x26\x8e\x9c\x1b\x1c\xec\x58\xaf\xd7\xf3\x45\ 171 | \x53\x98\x05\x3d\x0f\x7e\xd2\xb0\x13\xdc\x7d\x8d\x0d\x2a\x00\xbd\ 172 | \x10\xca\x96\xfa\x9c\x7b\x57\x20\xcc\x3a\x50\x8c\x19\x3b\xa4\x70\ 173 | \x4f\x8c\xee\x87\x50\xe2\x5a\x0a\xbe\xb9\xf1\x1c\xdc\x40\x5a\x97\ 174 | \xb8\x20\xe9\xac\x22\xc7\x83\x7c\x0c\x87\xe3\x10\xe7\x1a\x8d\xc6\ 175 | \x52\x4e\xd7\x3a\xd0\x04\xf2\x14\xa0\xb3\xb3\x2f\x0d\xcd\xe6\x40\ 176 | \x24\xdd\x29\x31\x60\x2b\x6d\x3f\xd1\x92\xeb\x51\x2c\x2a\xe6\x67\ 177 | \x63\x4c\x56\x56\x57\x4f\x46\x98\xb8\x13\x0c\xae\xb2\xe1\xc0\x81\ 178 | \xc3\x2b\x2b\x2b\x7b\x8f\x67\x99\x2e\x35\x9b\x3a\x17\x1d\xe6\x20\ 179 | \x3c\x03\x3c\x04\x1a\x6a\xd9\x2f\x89\xed\x04\xa8\x60\x8f\x5a\xea\ 180 | \x33\xf1\x21\x48\x02\xa2\x53\x76\x59\x52\x62\xdf\x70\xe2\x39\x50\ 181 | \x45\xbe\x04\x3a\x87\x39\x65\x74\xcc\xc4\x77\x93\x24\x39\xd5\x68\ 182 | \x84\x85\x5a\x2d\xbd\x04\xd4\xa0\x98\xc1\xb5\x66\x4d\x3a\x35\x35\ 183 | \x15\xdc\xf3\x52\xc9\x57\x9a\x43\x8e\xbe\x07\xab\x67\xd3\x89\x48\ 184 | \xe4\x31\x6a\x0d\x7b\x2e\x49\x58\x48\xd3\xbc\xfa\x97\x7f\x79\x20\ 185 | \x72\x97\xa5\xfd\xa1\x43\xfb\x73\x89\x8d\x89\x09\xe6\x7b\x7b\x8f\ 186 | \xad\x5f\x69\x84\x45\xe5\x9e\x8d\x84\xe7\x8c\x9f\x00\x6d\xb2\x21\ 187 | \xbd\xca\x06\x6b\x0b\xa8\xab\xbd\x64\xf0\x47\x4e\x9c\x1a\xb0\x8c\ 188 | \x38\x63\x73\x2c\x84\xf0\xab\xdc\x7a\x2f\x2a\x3d\x4b\x56\x5c\xec\ 189 | \xea\x66\x7d\x7e\x9e\x06\xdc\xbc\x27\x91\xc2\x4b\x41\x2b\xeb\x9d\ 190 | \xa4\xa5\xad\x40\x7f\xab\xcb\xa2\x96\xd7\x34\x19\xf8\x92\xe4\x33\ 191 | \x4d\x85\xa5\xb9\x53\x1b\xcd\x5f\xb7\xdf\xd7\x56\xa2\x79\xe0\xc0\ 192 | \xdb\x97\x17\x57\x5e\xac\x55\x56\xab\xcb\x91\x7c\x1e\x27\xb3\x86\ 193 | \x67\x5b\xbe\x41\x83\x52\x8b\x0d\x5c\xf5\x45\x9b\x95\xf7\xa6\x8d\ 194 | \xbb\x0e\xba\x24\xf8\x00\xf9\x28\xe6\xcd\x10\x99\x69\x26\x85\x0f\ 195 | \x42\xb3\xba\xbc\x7a\xb9\xb3\x0a\x64\xeb\xeb\xdc\xb2\x73\xdd\x8e\ 196 | \x02\xc5\x80\xc9\xa4\x70\x21\x9a\xf9\x76\x95\x57\x01\xea\x88\xf3\ 197 | \x92\xce\x84\xa6\x2e\x77\x75\xad\xdf\x56\x9f\xed\x76\x64\x93\x0d\ 198 | \xe3\xe3\x47\xe7\xcb\x43\xe9\xba\xab\x85\x0b\x64\xf9\x9c\xe1\x79\ 199 | \xf0\xe3\x36\x3b\x80\x2d\xd7\xd8\x70\xd5\xb9\x35\x68\xf5\x01\x66\ 200 | \x11\xef\x08\xde\x44\xc9\x2f\x83\x39\xd5\x8c\xf9\xd2\xca\x52\xa9\ 201 | \x0a\xa5\xfc\x76\xcb\xed\x14\x7e\x10\x0b\x85\x17\x56\x9b\x4d\x66\ 202 | \x10\x89\xcc\x99\x08\x3b\x41\xc3\x88\x20\xc7\x63\x44\x3e\xc8\xb2\ 203 | \x74\xfd\xf0\xe1\xfd\x77\xd5\xd1\xf9\x38\x69\xa5\xb3\xe3\xcd\xfd\ 204 | \xfb\x7d\xe9\xe8\xd1\xa3\xb5\x4a\xa5\xeb\x52\x74\x98\x23\xf7\xac\ 205 | \xe1\x19\xd0\x5e\x60\xb0\xed\x18\x73\x60\x15\x31\x2f\x78\x57\xd2\ 206 | \x9b\x92\x7e\x41\x4c\xdf\x6f\x14\xf3\x0b\x97\xe6\xfa\x36\xb8\xc3\ 207 | \x96\x38\xb4\xc7\x4b\x87\x0e\x1d\x0a\x3f\xff\x79\xa9\xb2\x9e\x95\ 208 | \x7b\x89\x1a\x28\x38\x0c\x65\xd6\x08\x4e\xba\x4c\x3c\x1f\x9c\xbc\ 209 | \x79\xfe\xfc\xf9\xb9\x43\x87\xf6\x37\x3e\x4d\x00\x6e\x50\x44\x68\ 210 | \x7c\xfc\x68\xa1\x58\x2c\xf6\x34\x5c\xda\x15\x1c\x9e\x8c\x79\x7c\ 211 | \x3e\x3a\x3c\x1a\xa3\xfa\x1c\xb5\x96\x47\x1d\xb7\xc3\x2f\x9c\xfb\ 212 | \xad\x18\xd3\xe3\x79\x5e\x3d\xdf\xd3\x33\xb6\x3e\x33\x43\x76\xb7\ 213 | \xed\xb6\xb4\x6d\xd3\xf9\xfe\xfd\xac\x4f\x4d\x4d\x57\x2f\x5e\xac\ 214 | \x5e\x28\x75\x74\xbf\xdf\x5c\x6f\x76\xc6\xe8\x72\x9a\x66\x8d\x95\ 215 | \x95\xe6\xca\xf8\xf8\xd1\x4f\x8d\xfe\x37\x93\xeb\xd8\xb0\x7c\xf4\ 216 | \xe8\x62\xd5\xaa\x2d\xe7\x84\x39\x11\x4f\x88\x64\x38\xb7\x2e\x04\ 217 | \x3c\x93\xa7\x7e\xaf\x1e\xe2\xb9\x4a\x1c\x58\x3b\x73\x86\xe6\xd9\ 218 | \xb3\x77\xb7\xf1\x4d\xf9\xb8\xc1\x88\x0e\x1c\x38\x1c\xc6\xc7\x87\ 219 | \x34\x3d\x0d\xdf\xff\xfe\xbe\x9c\xbb\x75\xfd\x77\xa3\x94\xa6\xc2\ 220 | \xf8\xf8\xc1\xb4\x59\x3e\xd7\x5d\xa8\x69\x2b\xd0\x55\xaf\xb3\x6e\ 221 | \x6b\x29\xcf\xab\xab\xa7\x4f\xbf\xde\x84\x4f\x67\x2c\x77\xcb\xd9\ 222 | \xe0\x47\x15\x93\x30\x30\x85\x98\x41\x8c\x23\x66\x30\xe3\x98\x83\ 223 | \xd8\x7c\x7a\x13\xa1\xcd\x09\xf0\xf8\x38\xe9\xca\xca\x6c\xd2\xd3\ 224 | \x33\x96\xcf\xcc\x1c\xce\x3f\xad\x8d\x5f\x5d\xe7\x76\x00\x10\x12\ 225 | \x53\x24\x63\x2b\x63\x85\x62\xf1\x4a\xd1\xb5\x42\x59\xa4\xa5\x2c\ 226 | \xe4\x69\x12\x42\x4e\x96\xd7\x54\x6e\xd6\x62\x47\x4f\xfd\x34\xa7\ 227 | \x33\x0e\x92\x7f\xba\x60\x48\xb7\x0a\xbf\x9a\x52\xd8\xc7\xbe\x00\ 228 | \xb0\x8f\xe9\x38\x79\x07\x87\x71\xeb\xf1\xf8\x94\xc2\xf8\x0c\xe9\ 229 | \x95\xd1\xde\x4a\xa6\x38\x18\x63\x32\x82\xc2\x60\x82\xfb\x45\xe8\ 230 | \x26\xa8\x64\xb9\x11\xac\x15\x85\x70\x31\x49\xbc\x98\x34\xb4\x10\ 231 | \x7b\x9a\x4b\x3d\xf3\xcb\xd5\x23\x5f\x27\xfb\x34\x81\xb8\x99\x1c\ 232 | \x38\x7c\x20\x39\xb7\x74\xac\x3b\x75\x61\xa0\x90\x44\xd5\xaa\xc9\ 233 | \x7a\x52\xac\xad\xb1\x38\x54\x9b\x3e\x38\xfd\x89\x07\xf1\xf1\xd3\ 234 | \xe1\x03\x4a\xfa\xfa\xfa\xba\x3a\x8a\x61\x5b\x54\xbc\x5f\xe2\x31\ 235 | \xc4\xc3\x01\x6d\x97\xd4\x25\x42\x59\xc1\x89\xa4\x5c\xa8\x26\xb4\ 236 | \x46\xd0\x5c\x80\xb7\x83\xc2\x2f\x14\xf2\xf7\x15\xf3\xc5\x77\x2b\ 237 | \x4b\x55\x26\xc9\x7f\x13\xf7\x09\x84\xf4\xc2\x9f\xed\xed\x2a\x76\ 238 | \x76\x3d\x8c\xb3\xe7\xa5\xd0\x19\x60\x5e\x81\xf7\x93\xba\xcf\xc4\ 239 | \x81\xb8\xd8\x53\xde\x5b\x3b\xb4\xff\xd0\xc7\x0e\x46\x3e\x02\x80\ 240 | \x24\x31\x49\x32\x72\xb1\xab\x2f\xcb\x78\x38\x09\xc9\xf3\x0a\x7a\ 241 | \x2a\xa0\x3d\x04\x0d\x0b\xba\x24\xa5\x52\xab\x2f\x23\x09\x21\x4b\ 242 | \xca\xd4\x2a\x42\xe6\x24\xbd\x83\xf8\x39\xf8\xcd\x90\xa4\xc7\xe3\ 243 | \x70\x79\xe9\xc4\x57\x4f\x34\x3e\x6d\x36\x1c\x38\x7c\x20\xb9\x38\ 244 | \xfb\xde\x08\x05\xbe\x04\xda\x0f\xdc\x13\xa4\x15\x05\x4e\x58\xc9\ 245 | \xcf\x43\xa2\x37\xc8\x0b\x27\x2e\x86\xfa\xa5\x23\xaf\x1e\xb9\x29\ 246 | \x1b\x3f\xd4\x15\x96\x78\x95\x74\x70\xa9\x32\x94\xe5\xe1\x89\x44\ 247 | \x7c\x49\xf0\x3c\xb0\xcb\x78\x8b\x4c\x81\xd6\xe4\xe8\x66\xd3\x9d\ 248 | \x02\x50\x06\xba\x81\xed\x88\x07\x82\xc3\xc3\xca\xf3\xe9\xd2\x72\ 249 | \xed\xb5\xb1\x3f\x1f\x9b\xd3\x7f\x54\xed\xd3\x04\xe1\xe4\xa5\x93\ 250 | \xa1\xb3\x94\x74\x27\x31\xbf\x17\x74\xaf\xc4\x4e\x84\xdd\xea\x45\ 251 | \x3e\xe0\x3c\xee\x49\x92\xc6\xdf\xf4\xe4\xd9\x91\xfd\x87\xc7\x17\ 252 | \x75\x40\x1f\x49\xe5\x6f\x9c\x0b\xec\x23\x19\x4a\x3b\x07\x82\xc3\ 253 | \xd3\x11\xff\x63\xd0\xe7\x8c\xc6\x64\x2a\xdc\x62\xbc\xd4\x96\x4d\ 254 | \x60\x4a\xc0\xa0\xd0\x16\xc4\x90\xa5\x81\x3c\xa3\xd2\xb1\x9c\xff\ 255 | \x70\xf8\x3f\x0d\x7f\xa0\x2e\x55\x7d\xd0\x9f\x4a\x46\xb9\xe5\xdc\ 256 | \xc5\x84\xfe\xee\x1e\xd0\x28\xa2\x07\x51\xb4\x08\x42\x25\xf0\x16\ 257 | \x49\xfd\xb6\xb6\x14\x55\x4c\xab\x17\x2b\xaf\x4d\x7c\x7d\xe2\x02\ 258 | \xad\x32\xf8\xaa\x5c\xdd\x94\x90\xfa\x1e\xe8\xeb\x74\xa6\x87\xf2\ 259 | \xdc\xbf\x07\xbc\x68\xb4\x13\xbb\xf3\xba\xcf\x6d\x56\x60\x4d\x5a\ 260 | \x75\x42\x0d\xa8\xb7\xdf\x6f\xe6\x0a\x9b\x13\xdb\x0e\xa4\x6d\x42\ 261 | \xcf\x62\xff\x53\x91\x7e\xa1\xbf\x58\xbc\x77\xfc\xc2\x50\x45\x53\ 262 | \x1f\xe9\xd9\xdd\xb1\x48\x52\xb3\xa3\x54\xc0\xf4\x1a\x86\x90\x2b\ 263 | \x32\xc2\x08\x9c\x08\x3a\xdd\x1a\xed\x7f\xde\x09\xaf\xe4\xc5\xe6\ 264 | \x63\xbd\xe5\xa4\x7b\x8a\x1b\xd7\xbe\xc6\x80\x3f\xa2\x28\x35\x47\ 265 | \x8d\x9e\x15\x7c\x16\x34\x86\x5d\x26\x68\x93\xee\x91\x56\xe9\x79\ 266 | \x09\x74\x11\x58\x73\xa4\x29\x51\x90\xe8\x06\x06\x81\x5e\xa0\xd8\ 267 | \x06\x4c\x98\x02\x62\x08\x78\x2a\x98\x02\x41\x69\x3e\x50\xfa\xde\ 268 | \x63\x9d\xc3\x27\x35\xf5\x6b\x32\x61\x12\xf5\x6e\x29\xa6\x1b\xcd\ 269 | \x50\x32\xe4\x58\x55\x07\x95\x02\xbe\xba\xbe\xa0\x6c\x34\x2a\x78\ 270 | \x96\x18\x2e\x14\x9b\xc9\xc2\xcc\x9f\x3f\xb7\xa1\x3f\x56\x6d\xd3\ 271 | \x14\x5a\xd5\xe0\x94\x42\xd7\x7a\x57\x37\x45\x1e\x06\x3f\xa3\x56\ 272 | \x5d\x5e\x6e\xdb\x3b\xb4\x9a\x92\x2b\xc2\x27\x8d\x7e\x89\xe3\x4c\ 273 | \x50\x32\x07\xae\x86\x40\x07\xe6\x1e\xc9\x8f\x80\xc6\x69\x15\x52\ 274 | \xbd\xed\xcd\xb7\x27\xc7\x1a\x90\x78\x02\xa1\xa0\x10\xb3\xd5\x52\ 275 | \x9c\x48\xb6\x9f\x12\xaa\xde\xb5\x4f\x38\x88\x2f\xff\x59\x23\x2b\ 276 | \x96\x4a\x0b\x84\xe4\x35\x20\x6f\x5f\xdc\x18\x93\xe8\x46\xad\x6e\ 277 | \x51\x68\xb5\xc4\xc7\x10\x4f\x05\xc7\x77\xae\xf4\xc5\x73\xfb\x0f\ 278 | \xb5\xfa\x03\x57\x01\x60\x9e\xa4\x58\x64\x08\xf3\x18\xf0\x80\xa1\ 279 | \xfb\xba\x91\x72\x8e\xbd\x22\xe9\x2d\x5b\xdf\x8d\x8e\x3f\x25\xe1\ 280 | \x4c\x52\xca\x57\x36\x62\x21\xab\x84\x46\xaa\xac\xdc\x5b\x48\x74\ 281 | \x84\x4c\x4f\x5a\x7e\x01\xfc\x04\xd2\x36\x4c\xe9\x1a\x08\xf4\x05\ 282 | \xe9\x33\x98\x5c\x52\xd6\x4c\x4a\xd9\xd8\x1f\x8f\x7d\xa0\xff\x7c\ 283 | \x97\x8e\x51\x50\xf8\xfe\xb6\x6a\xf1\xcd\xc5\xe3\x59\x48\xd6\x2c\ 284 | \x7e\x81\xfc\xa4\x08\x2f\x82\x1f\x6f\x0f\x48\x53\x43\xc0\x74\x02\ 285 | \xf7\x5b\x7e\xc2\x79\x3a\xb3\xbe\xb0\xfb\xd2\x0d\x00\x6c\x87\x42\ 286 | \x23\x32\x64\xf9\x7e\x05\x0d\x72\xcd\x34\x0c\x54\x0d\xc7\x63\xd4\ 287 | \xb7\x93\xe0\xef\x34\x08\xa7\x96\x7b\x97\x37\x38\x48\x7e\xb5\x4a\ 288 | \x9f\x5a\x59\xdb\xbb\x31\xb8\xd4\x8c\xa5\xf9\x34\xc9\xe6\x73\xc2\ 289 | \x6a\x68\x45\x8f\x7b\x30\xe5\x36\x08\x89\xed\x7e\x49\x8f\xd3\x1a\ 290 | \x58\x36\x7a\x7a\xf8\x41\x3a\xb5\x6b\x56\x07\x55\xbf\x53\x10\x6c\ 291 | \x5b\x52\x3e\x39\xc9\xe5\xc3\x8c\xaf\x6f\xdb\x56\x9e\x73\xee\x39\ 292 | \x47\xaf\xb5\x27\x51\x4f\x8a\x56\x73\x57\xad\xfd\x0c\xda\xec\x21\ 293 | \x78\x04\x06\xde\x97\xd4\xb0\xed\x54\x53\x0a\xdd\x9d\xdd\xe5\xf4\ 294 | \x4a\xdc\x2a\x31\x62\xab\x72\xdd\x25\x86\x08\x2c\x0b\xde\x52\xe0\ 295 | \xa7\x5d\x1d\xe9\xc9\xb9\xca\xd2\x95\xab\xb6\xbb\xa9\xf2\x41\x32\ 296 | \xa1\xf5\xdd\x7f\xb4\xfb\x4c\x4c\xab\x1b\x92\xab\xa0\x06\xe2\x45\ 297 | \xc4\xce\xeb\x41\xc0\x0c\x28\x78\xc2\xa6\x99\x50\x68\x76\x27\xf1\ 298 | \xff\xee\xfe\xda\xee\x79\x7d\x55\x77\x9c\x27\xb4\xed\xd8\x07\xa1\ 299 | \x31\x35\xa5\x6c\x7a\x68\xfc\x64\x21\x2d\x16\x31\xa3\x88\x31\x43\ 300 | \x45\x9b\xfe\x08\x4a\x82\x01\xc8\x87\xd3\x8e\xd0\x31\x39\xc9\x3a\ 301 | \xe0\xc0\x0c\x4a\xb3\x66\x45\xad\x16\x75\x8f\xe4\xcd\x0e\x0c\x98\ 302 | \xdc\xb0\x64\x74\x54\x81\x33\xef\x56\x96\x3e\xd6\x71\x19\xfb\xc4\ 303 | \xd7\x4e\x34\x7a\x2e\xcf\x9d\x6f\x26\x85\x9f\x59\xfc\x6f\xc4\xdf\ 304 | \x0a\xce\x22\xea\xb8\x1d\x21\x5a\xb4\x1c\x14\x7a\x1a\xf9\xf7\xed\ 305 | \xe4\xb9\xca\x4a\x73\xfb\xae\xff\xb6\xab\xf4\xeb\x44\x87\x83\x07\ 306 | \x1d\xa7\x87\x66\xaa\xcd\x3c\x9d\x05\xde\x91\xb5\x04\xd7\x5d\x8d\ 307 | \x11\xa1\x75\xd7\x29\x0c\x18\x57\xa6\xdb\xb5\x43\x60\x1c\xe5\x99\ 308 | \x8b\x11\x57\x6c\x8a\xf6\x0d\x77\x81\x22\xb0\x2e\xbc\x90\x36\xe2\ 309 | \x1a\x93\xb7\xae\xbd\x6d\xfb\xc8\x5f\x90\x0d\x2e\x9d\x59\x4a\x55\ 310 | \x3f\xa2\xe0\xff\x63\xf4\x43\xc1\xdc\x87\x40\x28\x00\x5b\x41\xcf\ 311 | \x06\xfb\xcb\x22\xd9\xd7\x3d\x9f\xec\x9e\x28\xdf\xb7\xe5\xe5\xa9\ 312 | \x97\x53\x49\x37\x4b\xb4\x3e\x59\x0e\x10\x9b\xe5\xe2\x15\x89\x8b\ 313 | \x86\x0d\xae\xab\x1a\x6d\x24\x28\x48\xea\xc8\x4d\x81\x97\x5a\xbf\ 314 | \x6f\x21\x5e\x07\xf9\xea\xf8\xe8\x9a\x08\x0b\x62\xb4\xb2\xb5\x3c\ 315 | \xc4\x8f\xfc\xfd\x16\x20\x54\x96\x96\x96\xec\x70\x44\xe2\x9b\x11\ 316 | \x7e\x0c\x9c\xa3\xd5\xcf\x73\x2b\x56\x53\x04\xb6\x21\x7d\x0e\xe9\ 317 | \x0f\x12\xf3\xcf\x6c\x4d\x5c\x4a\xe7\x87\xf7\x4d\xde\x25\x1b\x0c\ 318 | \x1d\x59\x2d\xd8\xa4\x12\xe1\x23\xf9\xaa\x94\x63\x67\x69\x48\xae\ 319 | \xbb\x20\x31\x83\x93\x21\x35\x95\xa9\x06\xce\x3e\xfc\x0d\xec\x72\ 320 | \x40\x3d\x85\x8e\x46\x99\xfd\xac\xc3\xad\xaf\x9d\x6d\x82\x20\x29\ 321 | \x1b\x9f\x9c\x5d\xac\x35\xb7\xff\xac\x08\x29\x24\x29\xd2\x0b\xc0\ 322 | \x48\x9b\x01\x9b\x4c\x18\x96\x5d\x91\xb4\xd5\x51\x3b\xd3\xc0\x0f\ 323 | \x57\xca\xc5\xb7\x3e\x1b\x1f\x9c\xdd\xf3\xb5\x3d\xeb\x27\x96\x4f\ 324 | \x34\x99\xe4\xb6\x6e\x9f\x4e\xfc\xc5\x44\x1a\x9b\xb1\x37\x24\x1a\ 325 | \xb5\xdd\x13\xa4\xe4\xea\x4e\x5a\x6a\x35\x50\x58\x57\x28\xd4\x87\ 326 | \x16\x87\x0c\x2d\x13\x70\xda\x08\x0d\x72\xaf\x59\xda\xd0\xb5\x8c\ 327 | \x2e\x82\x6c\xa9\x03\x79\xb8\xd8\x4c\xb6\x30\x7e\xfb\x37\xbc\x6c\ 328 | \x7b\x66\x92\xa6\x56\x2b\x17\x9c\xc7\xd7\x24\x7f\x13\xfc\x33\x99\ 329 | \x45\x4c\x13\x5d\x65\x42\x0a\xea\x31\x3c\x28\xf1\x25\xf0\xbf\x0e\ 330 | \xd1\xff\x12\xc5\x17\x7b\xeb\xde\x33\xd1\xf5\x40\xff\xbe\xc9\x5d\ 331 | \xa5\x03\x87\x0f\x24\xe2\xe6\xa6\x21\x49\x2f\x4f\xbd\x9c\xf6\x36\ 332 | \x93\xee\x10\xd8\x23\xeb\xf1\xb6\x4f\x4b\xda\xbb\x37\xad\x51\xd9\ 333 | \x9a\x60\xb9\x81\x6b\xe3\x47\xc7\xdd\x06\x06\x0d\x7e\x85\xae\x58\ 334 | \xe8\x7c\x41\xe8\xdf\x09\x5e\x24\xd0\x09\xaa\x05\x69\x11\x71\x0c\ 335 | \xf1\x6d\x15\xf4\xd7\xe7\x7b\x56\x3e\xf0\xc1\x0f\xb3\xe4\xd6\x22\ 336 | \x49\xbb\xff\xcb\xee\x22\x17\xea\x63\xa5\x94\xcf\x2b\x86\x2f\x13\ 337 | \xf4\x94\xc4\x56\xa1\xa2\xda\x65\xa5\x02\x16\xca\x5b\x15\xa5\x16\ 338 | \x04\x27\x14\xf4\x8b\x60\x7e\x99\x88\x93\x4e\xc2\x62\x68\xa6\xab\ 339 | \x79\xa9\xab\xb6\xba\xba\x9a\x97\xb7\x95\x5d\x3b\x57\xd3\x8e\xfe\ 340 | \xba\xf2\x7a\x25\xcd\xba\xd4\x9b\x66\xc9\xde\x18\xfc\x0f\x51\xf8\ 341 | \x47\x12\x0f\x48\xea\x90\xa4\x20\x22\xd2\x12\xf0\xdd\x10\xf4\x5f\ 342 | \x9b\x85\x9e\x9f\x7d\xe7\xdf\x7e\x67\xc3\xb6\x53\xdb\xd6\xef\xab\ 343 | \xd1\xb7\x8b\x79\x22\x47\x05\xc3\x58\x05\xc1\x9c\xf1\xb1\x80\xde\ 344 | \x76\x9a\xcc\x34\x33\x2d\xb5\x58\x71\x67\x62\xdb\x42\x8d\x5d\x53\ 345 | \xbb\xe6\x4a\x64\x3f\x74\x22\x07\x7b\x03\x6b\x02\x31\x0a\xed\x42\ 346 | \xcb\xad\x08\x41\xab\x9a\xac\x20\x46\x30\x0f\x38\xe8\xe9\x0c\x1d\ 347 | \x0f\xe2\x44\x2c\xc6\xb3\x8a\xeb\x8b\xfd\x3d\x71\xdd\xeb\xb5\xbc\ 348 | \xb3\x3f\x0d\x6b\x31\x29\x16\x3a\xe8\x72\x43\xf7\xe6\x89\x9f\x02\ 349 | \x9e\x11\xbe\x4f\xad\x31\xdb\xe6\x24\xa5\x29\x7c\x41\x4a\x8e\xe5\ 350 | \x64\xf3\x17\xab\x17\x1b\x37\xa4\xc2\x74\x91\x35\xad\x85\x22\xfe\ 351 | \x11\x70\xc9\x50\x95\x7d\x2a\xa0\x59\xec\x0b\x95\xbe\xfe\xd5\xd3\ 352 | \x9c\x6e\xdc\x6d\xee\x6e\x6c\x1d\x54\x7d\xd7\xd4\xae\xd9\x8e\x44\ 353 | \xd3\x49\x43\xcb\x04\xe6\x81\x67\x0d\x7b\x64\xfa\x10\xc5\xb6\xc2\ 354 | \x81\x96\x83\x2c\x20\x3a\x11\x23\x82\x87\x64\x2d\x23\x2f\x4b\xf1\ 355 | \x82\x63\xb2\x4c\x12\x9a\xb6\x0b\x89\x54\x8e\xa6\x57\x81\x11\x60\ 356 | \x94\x56\x4d\x52\x76\x2b\x01\x82\xf6\x3c\xc1\xf0\x9e\xec\xb7\x9b\ 357 | \x85\xb0\x74\xe4\xec\xcf\xae\xfa\x31\xd9\x6e\xf5\x01\xf6\x53\xe8\ 358 | \x1a\xe9\xea\xa9\xd4\x93\xee\x2c\x36\xea\x74\x74\xac\x2e\x2f\x2c\ 359 | \xd7\x18\x27\xbb\x5d\x27\xf4\x49\x22\x49\x13\x5f\x9f\x48\xd7\xce\ 360 | \x9d\xeb\x29\xe4\xe5\x7b\x93\x02\x4f\x07\xf1\x39\xa4\xcf\x08\x46\ 361 | \x25\x75\x4a\x4a\x6e\x68\xb6\x48\x96\x88\x52\xc8\x25\x32\x05\x55\ 362 | \x65\xd5\x24\x45\x49\x41\x22\x95\x54\x6a\xbf\x0a\x12\xc9\x55\xb3\ 363 | \x6a\x7d\x66\x4d\xe2\x57\xa0\xff\x19\xe0\xaf\x5c\x5b\x3e\xf3\xcd\ 364 | \xaf\x1e\xaf\xdf\x00\xc0\xa6\x72\x4c\xb6\x4f\x60\x06\x73\x98\x4f\ 365 | \xbc\xa8\x74\xd7\x40\x1c\x50\xf2\xd8\xce\xe1\x32\x3d\xe5\xad\x22\ 366 | \x19\x17\x3c\x2f\xe9\x69\x89\xdd\x41\x61\x00\xa9\xe3\x43\x1b\xe1\ 367 | \x3a\x3f\x61\x11\xbc\x09\x50\xab\xc0\x6a\x19\xba\xb8\x01\xb8\x5c\ 368 | \xd2\x15\x49\xc7\xc1\x7f\x5d\x48\x0a\xdf\x08\x17\xc3\x3b\xdf\xf8\ 369 | \xd3\x1f\xad\x5f\x9f\x71\x5e\x2d\x87\x37\xd3\x4a\xee\xc2\xce\xef\ 370 | \x54\x7c\xc8\xb9\xa4\x8d\x89\xaf\x4f\xcc\x5e\xb9\xb8\xb0\x5a\xca\ 371 | \x3a\xe6\x14\x7c\x4c\x0a\x13\x46\x8f\xa8\x95\x3e\x0f\x21\xca\x40\ 372 | \xca\xe6\x3f\x49\xb5\xfc\x84\xae\x1b\x94\x5e\x0b\x4b\xed\x5f\xe9\ 373 | \xea\xe5\x08\x56\x80\x13\x86\x1f\x24\xd2\x77\xdd\x48\x8e\x3f\x59\ 374 | \xfd\xe1\x95\xff\xc5\xad\x3a\x42\x7f\x87\xd2\x06\xbc\xa9\x29\x5d\ 375 | \x7a\x6e\x65\x6c\xa3\x31\x98\x2c\xc4\x98\x1c\x4d\x55\x78\x10\xf8\ 376 | \x0c\xc1\x8f\x60\xed\x40\xf4\x63\xba\x0c\x45\x89\x70\x9d\x6d\xb7\ 377 | \xf6\x2c\xf9\xea\x5b\x91\x59\x6c\xc8\x5c\x40\xbc\x63\xfb\x47\x69\ 378 | \x8c\x3f\x8a\xc5\xd2\x7b\x5d\x83\xdb\x56\x0f\xfe\xfb\x8f\xfa\xb0\ 379 | \x3b\x1a\x8c\xfc\xa6\x44\x92\x38\x44\x78\x6e\x76\xac\x18\xab\x85\ 380 | \xee\x3c\x24\xdb\x93\x90\xdc\x6f\xd8\x2b\x85\xfb\x24\x6d\x57\xf0\ 381 | \xa0\x50\xaf\xa4\xae\xd0\xaa\xf6\x80\x90\x87\x40\x16\x14\x32\x89\ 382 | \x3a\xd2\x65\x82\xce\x82\x8e\x26\xf2\x1b\x99\xc3\x51\x0f\x56\xe7\ 383 | \x86\x0e\x3f\x5c\x3d\x74\xe8\xe6\x9d\xe1\xdf\x09\x00\x36\x65\xd3\ 384 | \x0f\xed\x62\x57\x71\x6b\xb1\xdc\x99\x94\x93\x3e\xe7\x1e\x90\xc3\ 385 | \x90\x0a\xde\xde\xbe\xbe\xbb\x4d\x84\x8a\x02\x91\x10\x1a\xc2\xf5\ 386 | \x40\xa8\x2b\x78\x55\x0e\xe7\x94\xe8\x54\x74\x7e\xd6\x85\xf4\x7c\ 387 | \x47\x7d\x65\xed\x5b\x9f\xd0\x8d\xfe\x9d\x02\x60\x53\x36\x81\xd8\ 388 | \xc7\xbe\xd0\xd1\x3f\x9b\x2c\x43\x29\xad\x26\x5d\x31\x29\x76\x87\ 389 | \xe0\xae\x68\x8a\x0a\x72\xe2\x90\x53\x74\x96\xc6\x24\xb7\xb2\x7a\ 390 | \x48\xc3\x5a\xa9\x59\x5e\xfb\x60\x79\xbd\xb6\x9f\x99\x6c\xf2\x36\ 391 | \xa2\xd7\xef\x24\x00\x1f\x16\x21\xed\x3f\x40\x58\x1c\xdf\xa7\x45\ 392 | \x16\xc3\x8e\xfe\xba\x00\xba\x46\x4a\x3e\x7a\x14\xca\xdb\xca\xde\ 393 | \xf2\xc0\x16\x0f\x2d\x0e\xf9\xf0\xfe\xc3\xf1\x4e\xfa\x0a\xff\x0f\ 394 | \xc1\xea\x47\x68\xcb\x86\x1c\x37\x00\x00\x00\x00\x49\x45\x4e\x44\ 395 | \xae\x42\x60\x82\ 396 | " 397 | 398 | qt_resource_name = "\ 399 | \x00\x07\ 400 | \x07\x3b\xe0\xb3\ 401 | \x00\x70\ 402 | \x00\x6c\x00\x75\x00\x67\x00\x69\x00\x6e\x00\x73\ 403 | \x00\x0b\ 404 | \x08\xd8\x99\x42\ 405 | \x00\x67\ 406 | \x00\x65\x00\x6e\x00\x65\x00\x72\x00\x61\x00\x6c\x00\x69\x00\x7a\x00\x65\x00\x72\ 407 | \x00\x08\ 408 | \x0a\x61\x5a\xa7\ 409 | \x00\x69\ 410 | \x00\x63\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\ 411 | " 412 | 413 | qt_resource_struct = "\ 414 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ 415 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ 416 | \x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\ 417 | \x00\x00\x00\x30\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ 418 | " 419 | 420 | def qInitResources(): 421 | QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) 422 | 423 | def qCleanupResources(): 424 | QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) 425 | 426 | qInitResources() 427 | -------------------------------------------------------------------------------- /ui_generalizer.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | generalizer 4 | 5 | 6 | 7 | 0 8 | 0 9 | 493 10 | 348 11 | 12 | 13 | 14 | Generalizer 15 | 16 | 17 | 18 | 19 | 20 | Batch mode 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 0 29 | 0 30 | 31 | 32 | 33 | ? 34 | 35 | 36 | true 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 0 45 | 0 46 | 47 | 48 | 49 | OK 50 | 51 | 52 | 53 | 54 | 55 | 56 | Close 57 | 58 | 59 | 60 | 61 | 62 | 63 | 0 64 | 65 | 66 | 67 | 68 | 69 | 70 | Input line layer: 71 | 72 | 73 | cbInput 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | Options 84 | 85 | 86 | 87 | 88 | 89 | Alghoritm: 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 0 98 | 0 99 | 100 | 101 | 102 | 1 103 | 104 | 105 | 106 | -----Generalizing----- 107 | 108 | 109 | 110 | 111 | Remove small objects 112 | 113 | 114 | 115 | 116 | -----Simplifying----- 117 | 118 | 119 | 120 | 121 | Douglas-Peucker Algorithm 122 | 123 | 124 | 125 | 126 | Jenk's Algorithm 127 | 128 | 129 | 130 | 131 | Lang Algorithm 132 | 133 | 134 | 135 | 136 | Reumann-Witkam Algorithm 137 | 138 | 139 | 140 | 141 | Vertex Reduction 142 | 143 | 144 | 145 | 146 | -----Smoothing----- 147 | 148 | 149 | 150 | 151 | Boyle's Forward-Looking Algorithm 152 | 153 | 154 | 155 | 156 | Chaiken's Algorithm 157 | 158 | 159 | 160 | 161 | Hermite Spline Interpolation 162 | 163 | 164 | 165 | 166 | McMaster's Distance-Weighting Algorithm 167 | 168 | 169 | 170 | 171 | McMaster's Sliding Averaging Algorithm 172 | 173 | 174 | 175 | 176 | Snakes Algorithm 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 0 185 | 186 | 187 | 188 | 189 | 190 | 191 | Threshold: 192 | 193 | 194 | sbRemove_thresh 195 | 196 | 197 | 198 | 199 | 200 | 201 | 4 202 | 203 | 204 | 0.000100000000000 205 | 206 | 207 | 9999999.999900000169873 208 | 209 | 210 | 0.000100000000000 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | Threshold: 222 | 223 | 224 | 225 | 226 | 227 | 228 | 4 229 | 230 | 231 | 0.000100000000000 232 | 233 | 234 | 9999999.999900000169873 235 | 236 | 237 | 0.000100000000000 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | Threshold: 249 | 250 | 251 | 252 | 253 | 254 | 255 | 4 256 | 257 | 258 | 9999999.999900000169873 259 | 260 | 261 | 0.000100000000000 262 | 263 | 264 | 265 | 266 | 267 | 268 | Angle threshold: 269 | 270 | 271 | 272 | 273 | 274 | 275 | 180.000000000000000 276 | 277 | 278 | 3.000000000000000 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | Threshold: 290 | 291 | 292 | 293 | 294 | 295 | 296 | 4 297 | 298 | 299 | 0.000100000000000 300 | 301 | 302 | 9999999.999900000169873 303 | 304 | 305 | 0.000100000000000 306 | 307 | 308 | 309 | 310 | 311 | 312 | Looka ahead: 313 | 314 | 315 | 316 | 317 | 318 | 319 | 1 320 | 321 | 322 | 9999 323 | 324 | 325 | 8 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | Threshold: 337 | 338 | 339 | 340 | 341 | 342 | 343 | 4 344 | 345 | 346 | 9999999.999900000169873 347 | 348 | 349 | 0.000100000000000 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | Threshold: 361 | 362 | 363 | 364 | 365 | 366 | 367 | 4 368 | 369 | 370 | 0.000100000000000 371 | 372 | 373 | 9999999.999900000169873 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | Look ahead: 385 | 386 | 387 | 388 | 389 | 390 | 391 | 2 392 | 393 | 394 | 999 395 | 396 | 397 | 7 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | Level: 409 | 410 | 411 | 412 | 413 | 414 | 415 | 1 416 | 417 | 418 | 99 419 | 420 | 421 | 422 | 423 | 424 | 425 | Weight: 426 | 427 | 428 | 429 | 430 | 431 | 432 | 1.000000000000000 433 | 434 | 435 | 3.000000000000000 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | Threshold: 447 | 448 | 449 | 450 | 451 | 452 | 453 | Thightness: 454 | 455 | 456 | 457 | 458 | 459 | 460 | 0.500000000000000 461 | 462 | 463 | 464 | 465 | 466 | 467 | 4 468 | 469 | 470 | 9999999.999900000169873 471 | 472 | 473 | 0.000100000000000 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | Slide: 485 | 486 | 487 | 488 | 489 | 490 | 491 | 0.100000000000000 492 | 493 | 494 | 0.500000000000000 495 | 496 | 497 | 498 | 499 | 500 | 501 | Look ahead: 502 | 503 | 504 | 505 | 506 | 507 | 508 | 3 509 | 510 | 511 | 999 512 | 513 | 514 | 2 515 | 516 | 517 | 7 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | Slide: 529 | 530 | 531 | 532 | 533 | 534 | 535 | 0.100000000000000 536 | 537 | 538 | 0.500000000000000 539 | 540 | 541 | 542 | 543 | 544 | 545 | Look ahead: 546 | 547 | 548 | 549 | 550 | 551 | 552 | 3 553 | 554 | 555 | 999 556 | 557 | 558 | 2 559 | 560 | 561 | 7 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | Alpha: 573 | 574 | 575 | 576 | 577 | 578 | 579 | 9999.989999999999782 580 | 581 | 582 | 1.000000000000000 583 | 584 | 585 | 586 | 587 | 588 | 589 | Beta: 590 | 591 | 592 | 593 | 594 | 595 | 596 | 9999.989999999999782 597 | 598 | 599 | 0.500000000000000 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | false 614 | 615 | 616 | 617 | 618 | 619 | 620 | false 621 | 622 | 623 | Browse 624 | 625 | 626 | 627 | 628 | 629 | 630 | Save output layer 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 0 643 | 0 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 0 653 | 0 654 | 655 | 656 | 657 | 658 | Algorithm 659 | 660 | 661 | 662 | 663 | Parameter 1 664 | 665 | 666 | 667 | 668 | Parameter 2 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | Add 677 | 678 | 679 | 680 | 681 | 682 | 683 | Delete 684 | 685 | 686 | 687 | 688 | 689 | 690 | Edit 691 | 692 | 693 | 694 | 695 | 696 | 697 | false 698 | 699 | 700 | 701 | 702 | 703 | 704 | false 705 | 706 | 707 | Browse 708 | 709 | 710 | 711 | 712 | 713 | 714 | Save output layer(s) to folder 715 | 716 | 717 | 718 | 719 | 720 | 721 | Algorithm(s) 722 | 723 | 724 | 725 | 726 | 727 | 728 | Choose layer(s) 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | cbBatch 740 | cbInput 741 | cbAlgorithm 742 | sbRemove_thresh 743 | cbOutFile 744 | eOutput 745 | bBrowse 746 | bOk 747 | bCancel 748 | sbLang_LA 749 | sbReduction_thresh 750 | sbBoyle_LA 751 | sbChaiken_level 752 | sbChaiken_weight 753 | sbHermite_steps 754 | sbHermite_tightness 755 | sbDist_slide 756 | sbDist_LA 757 | sbSlide_slide 758 | sbSlide_LA 759 | bHelp 760 | sbLang_thresh 761 | sbDP_thresh 762 | lstLayers 763 | tblBatchAlg 764 | bAddAlg 765 | bDelAlg 766 | bEditAlg 767 | eDir 768 | bBrowseDir 769 | cbOutDir 770 | 771 | 772 | 773 | 774 | bCancel 775 | clicked() 776 | generalizer 777 | close() 778 | 779 | 780 | 328 781 | 234 782 | 783 | 784 | 202 785 | 210 786 | 787 | 788 | 789 | 790 | 791 | -------------------------------------------------------------------------------- /ui_generalizer.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'C:\Documents and Settings\Pocisk\.qgis\python\plugins\generalizer\ui_generalizer.ui' 4 | # 5 | # Created: Tue Sep 13 17:03:23 2011 6 | # by: PyQt4 UI code generator 4.8.3 7 | # 8 | # WARNING! All changes made in this file will be lost! 9 | 10 | from PyQt4 import QtCore, QtGui 11 | 12 | class Ui_generalizer(object): 13 | def setupUi(self, generalizer): 14 | generalizer.setObjectName("generalizer") 15 | generalizer.resize(493, 348) 16 | self.gridLayout_20 = QtGui.QGridLayout(generalizer) 17 | self.gridLayout_20.setObjectName("gridLayout_20") 18 | self.cbBatch = QtGui.QCheckBox(generalizer) 19 | self.cbBatch.setObjectName("cbBatch") 20 | self.gridLayout_20.addWidget(self.cbBatch, 0, 0, 1, 1) 21 | self.bHelp = QtGui.QPushButton(generalizer) 22 | sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Fixed) 23 | sizePolicy.setHorizontalStretch(0) 24 | sizePolicy.setVerticalStretch(0) 25 | sizePolicy.setHeightForWidth(self.bHelp.sizePolicy().hasHeightForWidth()) 26 | self.bHelp.setSizePolicy(sizePolicy) 27 | self.bHelp.setFlat(True) 28 | self.bHelp.setObjectName("bHelp") 29 | self.gridLayout_20.addWidget(self.bHelp, 0, 2, 1, 1) 30 | self.bOk = QtGui.QPushButton(generalizer) 31 | sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Fixed) 32 | sizePolicy.setHorizontalStretch(0) 33 | sizePolicy.setVerticalStretch(0) 34 | sizePolicy.setHeightForWidth(self.bOk.sizePolicy().hasHeightForWidth()) 35 | self.bOk.setSizePolicy(sizePolicy) 36 | self.bOk.setObjectName("bOk") 37 | self.gridLayout_20.addWidget(self.bOk, 2, 1, 1, 1) 38 | self.bCancel = QtGui.QPushButton(generalizer) 39 | self.bCancel.setObjectName("bCancel") 40 | self.gridLayout_20.addWidget(self.bCancel, 2, 2, 1, 1) 41 | self.stackBatch = QtGui.QStackedWidget(generalizer) 42 | self.stackBatch.setObjectName("stackBatch") 43 | self.page_6 = QtGui.QWidget() 44 | self.page_6.setObjectName("page_6") 45 | self.gridLayout_19 = QtGui.QGridLayout(self.page_6) 46 | self.gridLayout_19.setObjectName("gridLayout_19") 47 | self.label = QtGui.QLabel(self.page_6) 48 | self.label.setObjectName("label") 49 | self.gridLayout_19.addWidget(self.label, 0, 0, 1, 1) 50 | self.cbInput = QtGui.QComboBox(self.page_6) 51 | self.cbInput.setObjectName("cbInput") 52 | self.gridLayout_19.addWidget(self.cbInput, 1, 0, 1, 2) 53 | self.groupBox = QtGui.QGroupBox(self.page_6) 54 | self.groupBox.setObjectName("groupBox") 55 | self.gridLayout_2 = QtGui.QGridLayout(self.groupBox) 56 | self.gridLayout_2.setObjectName("gridLayout_2") 57 | self.label_3 = QtGui.QLabel(self.groupBox) 58 | self.label_3.setObjectName("label_3") 59 | self.gridLayout_2.addWidget(self.label_3, 0, 0, 1, 1) 60 | self.cbAlgorithm = QtGui.QComboBox(self.groupBox) 61 | sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed) 62 | sizePolicy.setHorizontalStretch(0) 63 | sizePolicy.setVerticalStretch(0) 64 | sizePolicy.setHeightForWidth(self.cbAlgorithm.sizePolicy().hasHeightForWidth()) 65 | self.cbAlgorithm.setSizePolicy(sizePolicy) 66 | self.cbAlgorithm.setObjectName("cbAlgorithm") 67 | self.cbAlgorithm.addItem("") 68 | self.cbAlgorithm.addItem("") 69 | self.cbAlgorithm.addItem("") 70 | self.cbAlgorithm.addItem("") 71 | self.cbAlgorithm.addItem("") 72 | self.cbAlgorithm.addItem("") 73 | self.cbAlgorithm.addItem("") 74 | self.cbAlgorithm.addItem("") 75 | self.cbAlgorithm.addItem("") 76 | self.cbAlgorithm.addItem("") 77 | self.cbAlgorithm.addItem("") 78 | self.cbAlgorithm.addItem("") 79 | self.cbAlgorithm.addItem("") 80 | self.cbAlgorithm.addItem("") 81 | self.cbAlgorithm.addItem("") 82 | self.gridLayout_2.addWidget(self.cbAlgorithm, 0, 1, 1, 1) 83 | self.stackOptions = QtGui.QStackedWidget(self.groupBox) 84 | self.stackOptions.setObjectName("stackOptions") 85 | self.page_11 = QtGui.QWidget() 86 | self.page_11.setObjectName("page_11") 87 | self.gridLayout_11 = QtGui.QGridLayout(self.page_11) 88 | self.gridLayout_11.setObjectName("gridLayout_11") 89 | self.label_12 = QtGui.QLabel(self.page_11) 90 | self.label_12.setObjectName("label_12") 91 | self.gridLayout_11.addWidget(self.label_12, 0, 0, 1, 1) 92 | self.sbRemove_thresh = QtGui.QDoubleSpinBox(self.page_11) 93 | self.sbRemove_thresh.setDecimals(4) 94 | self.sbRemove_thresh.setMinimum(0.0001) 95 | self.sbRemove_thresh.setMaximum(9999999.9999) 96 | self.sbRemove_thresh.setProperty("value", 0.0001) 97 | self.sbRemove_thresh.setObjectName("sbRemove_thresh") 98 | self.gridLayout_11.addWidget(self.sbRemove_thresh, 0, 1, 1, 1) 99 | self.stackOptions.addWidget(self.page_11) 100 | self.page_12 = QtGui.QWidget() 101 | self.page_12.setObjectName("page_12") 102 | self.gridLayout_12 = QtGui.QGridLayout(self.page_12) 103 | self.gridLayout_12.setObjectName("gridLayout_12") 104 | self.label_18 = QtGui.QLabel(self.page_12) 105 | self.label_18.setObjectName("label_18") 106 | self.gridLayout_12.addWidget(self.label_18, 0, 0, 1, 1) 107 | self.sbDP_thresh = QtGui.QDoubleSpinBox(self.page_12) 108 | self.sbDP_thresh.setDecimals(4) 109 | self.sbDP_thresh.setMinimum(0.0001) 110 | self.sbDP_thresh.setMaximum(9999999.9999) 111 | self.sbDP_thresh.setProperty("value", 0.0001) 112 | self.sbDP_thresh.setObjectName("sbDP_thresh") 113 | self.gridLayout_12.addWidget(self.sbDP_thresh, 0, 1, 1, 1) 114 | self.stackOptions.addWidget(self.page_12) 115 | self.page_2 = QtGui.QWidget() 116 | self.page_2.setObjectName("page_2") 117 | self.gridLayout_4 = QtGui.QGridLayout(self.page_2) 118 | self.gridLayout_4.setObjectName("gridLayout_4") 119 | self.label_7 = QtGui.QLabel(self.page_2) 120 | self.label_7.setObjectName("label_7") 121 | self.gridLayout_4.addWidget(self.label_7, 0, 0, 1, 1) 122 | self.sbJenks_thresh = QtGui.QDoubleSpinBox(self.page_2) 123 | self.sbJenks_thresh.setDecimals(4) 124 | self.sbJenks_thresh.setMaximum(9999999.9999) 125 | self.sbJenks_thresh.setProperty("value", 0.0001) 126 | self.sbJenks_thresh.setObjectName("sbJenks_thresh") 127 | self.gridLayout_4.addWidget(self.sbJenks_thresh, 0, 1, 1, 1) 128 | self.label_8 = QtGui.QLabel(self.page_2) 129 | self.label_8.setObjectName("label_8") 130 | self.gridLayout_4.addWidget(self.label_8, 1, 0, 1, 1) 131 | self.sbJenks_angle = QtGui.QDoubleSpinBox(self.page_2) 132 | self.sbJenks_angle.setMaximum(180.0) 133 | self.sbJenks_angle.setProperty("value", 3.0) 134 | self.sbJenks_angle.setObjectName("sbJenks_angle") 135 | self.gridLayout_4.addWidget(self.sbJenks_angle, 1, 1, 1, 1) 136 | self.stackOptions.addWidget(self.page_2) 137 | self.page_13 = QtGui.QWidget() 138 | self.page_13.setObjectName("page_13") 139 | self.gridLayout_3 = QtGui.QGridLayout(self.page_13) 140 | self.gridLayout_3.setObjectName("gridLayout_3") 141 | self.label_13 = QtGui.QLabel(self.page_13) 142 | self.label_13.setObjectName("label_13") 143 | self.gridLayout_3.addWidget(self.label_13, 0, 0, 1, 1) 144 | self.sbLang_thresh = QtGui.QDoubleSpinBox(self.page_13) 145 | self.sbLang_thresh.setDecimals(4) 146 | self.sbLang_thresh.setMinimum(0.0001) 147 | self.sbLang_thresh.setMaximum(9999999.9999) 148 | self.sbLang_thresh.setProperty("value", 0.0001) 149 | self.sbLang_thresh.setObjectName("sbLang_thresh") 150 | self.gridLayout_3.addWidget(self.sbLang_thresh, 0, 1, 1, 1) 151 | self.label_19 = QtGui.QLabel(self.page_13) 152 | self.label_19.setObjectName("label_19") 153 | self.gridLayout_3.addWidget(self.label_19, 1, 0, 1, 1) 154 | self.sbLang_LA = QtGui.QSpinBox(self.page_13) 155 | self.sbLang_LA.setMinimum(1) 156 | self.sbLang_LA.setMaximum(9999) 157 | self.sbLang_LA.setProperty("value", 8) 158 | self.sbLang_LA.setObjectName("sbLang_LA") 159 | self.gridLayout_3.addWidget(self.sbLang_LA, 1, 1, 1, 1) 160 | self.stackOptions.addWidget(self.page_13) 161 | self.page_4 = QtGui.QWidget() 162 | self.page_4.setObjectName("page_4") 163 | self.gridLayout_6 = QtGui.QGridLayout(self.page_4) 164 | self.gridLayout_6.setObjectName("gridLayout_6") 165 | self.label_11 = QtGui.QLabel(self.page_4) 166 | self.label_11.setObjectName("label_11") 167 | self.gridLayout_6.addWidget(self.label_11, 0, 0, 1, 1) 168 | self.sbRW_thresh = QtGui.QDoubleSpinBox(self.page_4) 169 | self.sbRW_thresh.setDecimals(4) 170 | self.sbRW_thresh.setMaximum(9999999.9999) 171 | self.sbRW_thresh.setProperty("value", 0.0001) 172 | self.sbRW_thresh.setObjectName("sbRW_thresh") 173 | self.gridLayout_6.addWidget(self.sbRW_thresh, 0, 1, 1, 1) 174 | self.stackOptions.addWidget(self.page_4) 175 | self.page_14 = QtGui.QWidget() 176 | self.page_14.setObjectName("page_14") 177 | self.gridLayout_14 = QtGui.QGridLayout(self.page_14) 178 | self.gridLayout_14.setObjectName("gridLayout_14") 179 | self.label_20 = QtGui.QLabel(self.page_14) 180 | self.label_20.setObjectName("label_20") 181 | self.gridLayout_14.addWidget(self.label_20, 0, 0, 1, 1) 182 | self.sbReduction_thresh = QtGui.QDoubleSpinBox(self.page_14) 183 | self.sbReduction_thresh.setDecimals(4) 184 | self.sbReduction_thresh.setMinimum(0.0001) 185 | self.sbReduction_thresh.setMaximum(9999999.9999) 186 | self.sbReduction_thresh.setObjectName("sbReduction_thresh") 187 | self.gridLayout_14.addWidget(self.sbReduction_thresh, 0, 1, 1, 1) 188 | self.stackOptions.addWidget(self.page_14) 189 | self.page_15 = QtGui.QWidget() 190 | self.page_15.setObjectName("page_15") 191 | self.gridLayout_15 = QtGui.QGridLayout(self.page_15) 192 | self.gridLayout_15.setObjectName("gridLayout_15") 193 | self.label_21 = QtGui.QLabel(self.page_15) 194 | self.label_21.setObjectName("label_21") 195 | self.gridLayout_15.addWidget(self.label_21, 0, 0, 1, 1) 196 | self.sbBoyle_LA = QtGui.QSpinBox(self.page_15) 197 | self.sbBoyle_LA.setMinimum(2) 198 | self.sbBoyle_LA.setMaximum(999) 199 | self.sbBoyle_LA.setProperty("value", 7) 200 | self.sbBoyle_LA.setObjectName("sbBoyle_LA") 201 | self.gridLayout_15.addWidget(self.sbBoyle_LA, 0, 1, 1, 1) 202 | self.stackOptions.addWidget(self.page_15) 203 | self.page_16 = QtGui.QWidget() 204 | self.page_16.setObjectName("page_16") 205 | self.gridLayout_16 = QtGui.QGridLayout(self.page_16) 206 | self.gridLayout_16.setObjectName("gridLayout_16") 207 | self.label_22 = QtGui.QLabel(self.page_16) 208 | self.label_22.setObjectName("label_22") 209 | self.gridLayout_16.addWidget(self.label_22, 0, 0, 1, 1) 210 | self.sbChaiken_level = QtGui.QSpinBox(self.page_16) 211 | self.sbChaiken_level.setMinimum(1) 212 | self.sbChaiken_level.setMaximum(99) 213 | self.sbChaiken_level.setObjectName("sbChaiken_level") 214 | self.gridLayout_16.addWidget(self.sbChaiken_level, 0, 1, 1, 1) 215 | self.label_23 = QtGui.QLabel(self.page_16) 216 | self.label_23.setObjectName("label_23") 217 | self.gridLayout_16.addWidget(self.label_23, 1, 0, 1, 1) 218 | self.sbChaiken_weight = QtGui.QDoubleSpinBox(self.page_16) 219 | self.sbChaiken_weight.setMinimum(1.0) 220 | self.sbChaiken_weight.setProperty("value", 3.0) 221 | self.sbChaiken_weight.setObjectName("sbChaiken_weight") 222 | self.gridLayout_16.addWidget(self.sbChaiken_weight, 1, 1, 1, 1) 223 | self.stackOptions.addWidget(self.page_16) 224 | self.page = QtGui.QWidget() 225 | self.page.setObjectName("page") 226 | self.gridLayout = QtGui.QGridLayout(self.page) 227 | self.gridLayout.setObjectName("gridLayout") 228 | self.label_2 = QtGui.QLabel(self.page) 229 | self.label_2.setObjectName("label_2") 230 | self.gridLayout.addWidget(self.label_2, 0, 0, 1, 1) 231 | self.label_4 = QtGui.QLabel(self.page) 232 | self.label_4.setObjectName("label_4") 233 | self.gridLayout.addWidget(self.label_4, 1, 0, 1, 1) 234 | self.sbHermite_tightness = QtGui.QDoubleSpinBox(self.page) 235 | self.sbHermite_tightness.setProperty("value", 0.5) 236 | self.sbHermite_tightness.setObjectName("sbHermite_tightness") 237 | self.gridLayout.addWidget(self.sbHermite_tightness, 1, 1, 1, 1) 238 | self.sbHermite_steps = QtGui.QDoubleSpinBox(self.page) 239 | self.sbHermite_steps.setDecimals(4) 240 | self.sbHermite_steps.setMaximum(9999999.9999) 241 | self.sbHermite_steps.setProperty("value", 0.0001) 242 | self.sbHermite_steps.setObjectName("sbHermite_steps") 243 | self.gridLayout.addWidget(self.sbHermite_steps, 0, 1, 1, 1) 244 | self.stackOptions.addWidget(self.page) 245 | self.page_17 = QtGui.QWidget() 246 | self.page_17.setObjectName("page_17") 247 | self.gridLayout_17 = QtGui.QGridLayout(self.page_17) 248 | self.gridLayout_17.setObjectName("gridLayout_17") 249 | self.label_24 = QtGui.QLabel(self.page_17) 250 | self.label_24.setObjectName("label_24") 251 | self.gridLayout_17.addWidget(self.label_24, 0, 0, 1, 1) 252 | self.sbDist_slide = QtGui.QDoubleSpinBox(self.page_17) 253 | self.sbDist_slide.setSingleStep(0.1) 254 | self.sbDist_slide.setProperty("value", 0.5) 255 | self.sbDist_slide.setObjectName("sbDist_slide") 256 | self.gridLayout_17.addWidget(self.sbDist_slide, 0, 1, 1, 1) 257 | self.label_25 = QtGui.QLabel(self.page_17) 258 | self.label_25.setObjectName("label_25") 259 | self.gridLayout_17.addWidget(self.label_25, 1, 0, 1, 1) 260 | self.sbDist_LA = QtGui.QSpinBox(self.page_17) 261 | self.sbDist_LA.setMinimum(3) 262 | self.sbDist_LA.setMaximum(999) 263 | self.sbDist_LA.setSingleStep(2) 264 | self.sbDist_LA.setProperty("value", 7) 265 | self.sbDist_LA.setObjectName("sbDist_LA") 266 | self.gridLayout_17.addWidget(self.sbDist_LA, 1, 1, 1, 1) 267 | self.stackOptions.addWidget(self.page_17) 268 | self.page_18 = QtGui.QWidget() 269 | self.page_18.setObjectName("page_18") 270 | self.gridLayout_18 = QtGui.QGridLayout(self.page_18) 271 | self.gridLayout_18.setObjectName("gridLayout_18") 272 | self.label_26 = QtGui.QLabel(self.page_18) 273 | self.label_26.setObjectName("label_26") 274 | self.gridLayout_18.addWidget(self.label_26, 0, 0, 1, 1) 275 | self.sbSlide_slide = QtGui.QDoubleSpinBox(self.page_18) 276 | self.sbSlide_slide.setSingleStep(0.1) 277 | self.sbSlide_slide.setProperty("value", 0.5) 278 | self.sbSlide_slide.setObjectName("sbSlide_slide") 279 | self.gridLayout_18.addWidget(self.sbSlide_slide, 0, 1, 1, 1) 280 | self.label_27 = QtGui.QLabel(self.page_18) 281 | self.label_27.setObjectName("label_27") 282 | self.gridLayout_18.addWidget(self.label_27, 1, 0, 1, 1) 283 | self.sbSlide_LA = QtGui.QSpinBox(self.page_18) 284 | self.sbSlide_LA.setMinimum(3) 285 | self.sbSlide_LA.setMaximum(999) 286 | self.sbSlide_LA.setSingleStep(2) 287 | self.sbSlide_LA.setProperty("value", 7) 288 | self.sbSlide_LA.setObjectName("sbSlide_LA") 289 | self.gridLayout_18.addWidget(self.sbSlide_LA, 1, 1, 1, 1) 290 | self.stackOptions.addWidget(self.page_18) 291 | self.page_3 = QtGui.QWidget() 292 | self.page_3.setObjectName("page_3") 293 | self.gridLayout_5 = QtGui.QGridLayout(self.page_3) 294 | self.gridLayout_5.setObjectName("gridLayout_5") 295 | self.label_9 = QtGui.QLabel(self.page_3) 296 | self.label_9.setObjectName("label_9") 297 | self.gridLayout_5.addWidget(self.label_9, 0, 0, 1, 1) 298 | self.sbSnakes_alpha = QtGui.QDoubleSpinBox(self.page_3) 299 | self.sbSnakes_alpha.setMaximum(9999.99) 300 | self.sbSnakes_alpha.setProperty("value", 1.0) 301 | self.sbSnakes_alpha.setObjectName("sbSnakes_alpha") 302 | self.gridLayout_5.addWidget(self.sbSnakes_alpha, 0, 1, 1, 1) 303 | self.label_10 = QtGui.QLabel(self.page_3) 304 | self.label_10.setObjectName("label_10") 305 | self.gridLayout_5.addWidget(self.label_10, 1, 0, 1, 1) 306 | self.sbSnakes_beta = QtGui.QDoubleSpinBox(self.page_3) 307 | self.sbSnakes_beta.setMaximum(9999.99) 308 | self.sbSnakes_beta.setProperty("value", 0.5) 309 | self.sbSnakes_beta.setObjectName("sbSnakes_beta") 310 | self.gridLayout_5.addWidget(self.sbSnakes_beta, 1, 1, 1, 1) 311 | self.stackOptions.addWidget(self.page_3) 312 | self.gridLayout_2.addWidget(self.stackOptions, 1, 0, 1, 2) 313 | self.gridLayout_19.addWidget(self.groupBox, 2, 0, 1, 2) 314 | self.eOutput = QtGui.QLineEdit(self.page_6) 315 | self.eOutput.setEnabled(False) 316 | self.eOutput.setObjectName("eOutput") 317 | self.gridLayout_19.addWidget(self.eOutput, 4, 0, 1, 1) 318 | self.bBrowse = QtGui.QPushButton(self.page_6) 319 | self.bBrowse.setEnabled(False) 320 | self.bBrowse.setObjectName("bBrowse") 321 | self.gridLayout_19.addWidget(self.bBrowse, 4, 1, 1, 1) 322 | self.cbOutFile = QtGui.QCheckBox(self.page_6) 323 | self.cbOutFile.setObjectName("cbOutFile") 324 | self.gridLayout_19.addWidget(self.cbOutFile, 3, 0, 1, 1) 325 | self.stackBatch.addWidget(self.page_6) 326 | self.page_10 = QtGui.QWidget() 327 | self.page_10.setObjectName("page_10") 328 | self.gridLayout_21 = QtGui.QGridLayout(self.page_10) 329 | self.gridLayout_21.setObjectName("gridLayout_21") 330 | self.lstLayers = QtGui.QListWidget(self.page_10) 331 | sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) 332 | sizePolicy.setHorizontalStretch(0) 333 | sizePolicy.setVerticalStretch(0) 334 | sizePolicy.setHeightForWidth(self.lstLayers.sizePolicy().hasHeightForWidth()) 335 | self.lstLayers.setSizePolicy(sizePolicy) 336 | self.lstLayers.setObjectName("lstLayers") 337 | self.gridLayout_21.addWidget(self.lstLayers, 1, 0, 1, 1) 338 | self.tblBatchAlg = QtGui.QTableWidget(self.page_10) 339 | sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) 340 | sizePolicy.setHorizontalStretch(0) 341 | sizePolicy.setVerticalStretch(0) 342 | sizePolicy.setHeightForWidth(self.tblBatchAlg.sizePolicy().hasHeightForWidth()) 343 | self.tblBatchAlg.setSizePolicy(sizePolicy) 344 | self.tblBatchAlg.setObjectName("tblBatchAlg") 345 | self.tblBatchAlg.setColumnCount(3) 346 | self.tblBatchAlg.setRowCount(0) 347 | item = QtGui.QTableWidgetItem() 348 | self.tblBatchAlg.setHorizontalHeaderItem(0, item) 349 | item = QtGui.QTableWidgetItem() 350 | self.tblBatchAlg.setHorizontalHeaderItem(1, item) 351 | item = QtGui.QTableWidgetItem() 352 | self.tblBatchAlg.setHorizontalHeaderItem(2, item) 353 | self.gridLayout_21.addWidget(self.tblBatchAlg, 3, 0, 3, 1) 354 | self.bAddAlg = QtGui.QPushButton(self.page_10) 355 | self.bAddAlg.setObjectName("bAddAlg") 356 | self.gridLayout_21.addWidget(self.bAddAlg, 3, 1, 1, 1) 357 | self.bDelAlg = QtGui.QPushButton(self.page_10) 358 | self.bDelAlg.setObjectName("bDelAlg") 359 | self.gridLayout_21.addWidget(self.bDelAlg, 4, 1, 1, 1) 360 | self.bEditAlg = QtGui.QPushButton(self.page_10) 361 | self.bEditAlg.setObjectName("bEditAlg") 362 | self.gridLayout_21.addWidget(self.bEditAlg, 5, 1, 1, 1) 363 | self.eDir = QtGui.QLineEdit(self.page_10) 364 | self.eDir.setEnabled(False) 365 | self.eDir.setObjectName("eDir") 366 | self.gridLayout_21.addWidget(self.eDir, 7, 0, 1, 1) 367 | self.bBrowseDir = QtGui.QPushButton(self.page_10) 368 | self.bBrowseDir.setEnabled(False) 369 | self.bBrowseDir.setObjectName("bBrowseDir") 370 | self.gridLayout_21.addWidget(self.bBrowseDir, 7, 1, 1, 1) 371 | self.cbOutDir = QtGui.QCheckBox(self.page_10) 372 | self.cbOutDir.setObjectName("cbOutDir") 373 | self.gridLayout_21.addWidget(self.cbOutDir, 6, 0, 1, 1) 374 | self.label_5 = QtGui.QLabel(self.page_10) 375 | self.label_5.setObjectName("label_5") 376 | self.gridLayout_21.addWidget(self.label_5, 2, 0, 1, 1) 377 | self.label_6 = QtGui.QLabel(self.page_10) 378 | self.label_6.setObjectName("label_6") 379 | self.gridLayout_21.addWidget(self.label_6, 0, 0, 1, 1) 380 | self.stackBatch.addWidget(self.page_10) 381 | self.gridLayout_20.addWidget(self.stackBatch, 1, 0, 1, 3) 382 | self.label.setBuddy(self.cbInput) 383 | self.label_12.setBuddy(self.sbRemove_thresh) 384 | 385 | self.retranslateUi(generalizer) 386 | self.stackBatch.setCurrentIndex(0) 387 | self.cbAlgorithm.setCurrentIndex(1) 388 | self.stackOptions.setCurrentIndex(0) 389 | self.bCancel.clicked.connect( generalizer.close ) 390 | QtCore.QMetaObject.connectSlotsByName(generalizer) 391 | generalizer.setTabOrder(self.cbBatch, self.cbInput) 392 | generalizer.setTabOrder(self.cbInput, self.cbAlgorithm) 393 | generalizer.setTabOrder(self.cbAlgorithm, self.sbRemove_thresh) 394 | generalizer.setTabOrder(self.sbRemove_thresh, self.cbOutFile) 395 | generalizer.setTabOrder(self.cbOutFile, self.eOutput) 396 | generalizer.setTabOrder(self.eOutput, self.bBrowse) 397 | generalizer.setTabOrder(self.bBrowse, self.bOk) 398 | generalizer.setTabOrder(self.bOk, self.bCancel) 399 | generalizer.setTabOrder(self.bCancel, self.sbLang_LA) 400 | generalizer.setTabOrder(self.sbLang_LA, self.sbReduction_thresh) 401 | generalizer.setTabOrder(self.sbReduction_thresh, self.sbBoyle_LA) 402 | generalizer.setTabOrder(self.sbBoyle_LA, self.sbChaiken_level) 403 | generalizer.setTabOrder(self.sbChaiken_level, self.sbChaiken_weight) 404 | generalizer.setTabOrder(self.sbChaiken_weight, self.sbHermite_steps) 405 | generalizer.setTabOrder(self.sbHermite_steps, self.sbHermite_tightness) 406 | generalizer.setTabOrder(self.sbHermite_tightness, self.sbDist_slide) 407 | generalizer.setTabOrder(self.sbDist_slide, self.sbDist_LA) 408 | generalizer.setTabOrder(self.sbDist_LA, self.sbSlide_slide) 409 | generalizer.setTabOrder(self.sbSlide_slide, self.sbSlide_LA) 410 | generalizer.setTabOrder(self.sbSlide_LA, self.bHelp) 411 | generalizer.setTabOrder(self.bHelp, self.sbLang_thresh) 412 | generalizer.setTabOrder(self.sbLang_thresh, self.sbDP_thresh) 413 | generalizer.setTabOrder(self.sbDP_thresh, self.lstLayers) 414 | generalizer.setTabOrder(self.lstLayers, self.tblBatchAlg) 415 | generalizer.setTabOrder(self.tblBatchAlg, self.bAddAlg) 416 | generalizer.setTabOrder(self.bAddAlg, self.bDelAlg) 417 | generalizer.setTabOrder(self.bDelAlg, self.bEditAlg) 418 | generalizer.setTabOrder(self.bEditAlg, self.eDir) 419 | generalizer.setTabOrder(self.eDir, self.bBrowseDir) 420 | generalizer.setTabOrder(self.bBrowseDir, self.cbOutDir) 421 | 422 | def retranslateUi(self, generalizer): 423 | generalizer.setWindowTitle(QtGui.QApplication.translate("generalizer", "Generalizer", None, QtGui.QApplication.UnicodeUTF8)) 424 | self.cbBatch.setText(QtGui.QApplication.translate("generalizer", "Batch mode", None, QtGui.QApplication.UnicodeUTF8)) 425 | self.bHelp.setText(QtGui.QApplication.translate("generalizer", "?", None, QtGui.QApplication.UnicodeUTF8)) 426 | self.bOk.setText(QtGui.QApplication.translate("generalizer", "OK", None, QtGui.QApplication.UnicodeUTF8)) 427 | self.bCancel.setText(QtGui.QApplication.translate("generalizer", "Close", None, QtGui.QApplication.UnicodeUTF8)) 428 | self.label.setText(QtGui.QApplication.translate("generalizer", "Input line layer:", None, QtGui.QApplication.UnicodeUTF8)) 429 | self.groupBox.setTitle(QtGui.QApplication.translate("generalizer", "Options", None, QtGui.QApplication.UnicodeUTF8)) 430 | self.label_3.setText(QtGui.QApplication.translate("generalizer", "Alghoritm:", None, QtGui.QApplication.UnicodeUTF8)) 431 | self.cbAlgorithm.setItemText(0, QtGui.QApplication.translate("generalizer", "-----Generalizing-----", None, QtGui.QApplication.UnicodeUTF8)) 432 | self.cbAlgorithm.setItemText(1, QtGui.QApplication.translate("generalizer", "Remove small objects", None, QtGui.QApplication.UnicodeUTF8)) 433 | self.cbAlgorithm.setItemText(2, QtGui.QApplication.translate("generalizer", "-----Simplifying-----", None, QtGui.QApplication.UnicodeUTF8)) 434 | self.cbAlgorithm.setItemText(3, QtGui.QApplication.translate("generalizer", "Douglas-Peucker Algorithm", None, QtGui.QApplication.UnicodeUTF8)) 435 | self.cbAlgorithm.setItemText(4, QtGui.QApplication.translate("generalizer", "Jenk\'s Algorithm", None, QtGui.QApplication.UnicodeUTF8)) 436 | self.cbAlgorithm.setItemText(5, QtGui.QApplication.translate("generalizer", "Lang Algorithm", None, QtGui.QApplication.UnicodeUTF8)) 437 | self.cbAlgorithm.setItemText(6, QtGui.QApplication.translate("generalizer", "Reumann-Witkam Algorithm", None, QtGui.QApplication.UnicodeUTF8)) 438 | self.cbAlgorithm.setItemText(7, QtGui.QApplication.translate("generalizer", "Vertex Reduction", None, QtGui.QApplication.UnicodeUTF8)) 439 | self.cbAlgorithm.setItemText(8, QtGui.QApplication.translate("generalizer", "-----Smoothing-----", None, QtGui.QApplication.UnicodeUTF8)) 440 | self.cbAlgorithm.setItemText(9, QtGui.QApplication.translate("generalizer", "Boyle\'s Forward-Looking Algorithm", None, QtGui.QApplication.UnicodeUTF8)) 441 | self.cbAlgorithm.setItemText(10, QtGui.QApplication.translate("generalizer", "Chaiken\'s Algorithm", None, QtGui.QApplication.UnicodeUTF8)) 442 | self.cbAlgorithm.setItemText(11, QtGui.QApplication.translate("generalizer", "Hermite Spline Interpolation", None, QtGui.QApplication.UnicodeUTF8)) 443 | self.cbAlgorithm.setItemText(12, QtGui.QApplication.translate("generalizer", "McMaster\'s Distance-Weighting Algorithm", None, QtGui.QApplication.UnicodeUTF8)) 444 | self.cbAlgorithm.setItemText(13, QtGui.QApplication.translate("generalizer", "McMaster\'s Sliding Averaging Algorithm", None, QtGui.QApplication.UnicodeUTF8)) 445 | self.cbAlgorithm.setItemText(14, QtGui.QApplication.translate("generalizer", "Snakes Algorithm", None, QtGui.QApplication.UnicodeUTF8)) 446 | self.label_12.setText(QtGui.QApplication.translate("generalizer", "Threshold:", None, QtGui.QApplication.UnicodeUTF8)) 447 | self.label_18.setText(QtGui.QApplication.translate("generalizer", "Threshold:", None, QtGui.QApplication.UnicodeUTF8)) 448 | self.label_7.setText(QtGui.QApplication.translate("generalizer", "Threshold:", None, QtGui.QApplication.UnicodeUTF8)) 449 | self.label_8.setText(QtGui.QApplication.translate("generalizer", "Angle threshold:", None, QtGui.QApplication.UnicodeUTF8)) 450 | self.label_13.setText(QtGui.QApplication.translate("generalizer", "Threshold:", None, QtGui.QApplication.UnicodeUTF8)) 451 | self.label_19.setText(QtGui.QApplication.translate("generalizer", "Looka ahead:", None, QtGui.QApplication.UnicodeUTF8)) 452 | self.label_11.setText(QtGui.QApplication.translate("generalizer", "Threshold:", None, QtGui.QApplication.UnicodeUTF8)) 453 | self.label_20.setText(QtGui.QApplication.translate("generalizer", "Threshold:", None, QtGui.QApplication.UnicodeUTF8)) 454 | self.label_21.setText(QtGui.QApplication.translate("generalizer", "Look ahead:", None, QtGui.QApplication.UnicodeUTF8)) 455 | self.label_22.setText(QtGui.QApplication.translate("generalizer", "Level:", None, QtGui.QApplication.UnicodeUTF8)) 456 | self.label_23.setText(QtGui.QApplication.translate("generalizer", "Weight:", None, QtGui.QApplication.UnicodeUTF8)) 457 | self.label_2.setText(QtGui.QApplication.translate("generalizer", "Threshold:", None, QtGui.QApplication.UnicodeUTF8)) 458 | self.label_4.setText(QtGui.QApplication.translate("generalizer", "Thightness:", None, QtGui.QApplication.UnicodeUTF8)) 459 | self.label_24.setText(QtGui.QApplication.translate("generalizer", "Slide:", None, QtGui.QApplication.UnicodeUTF8)) 460 | self.label_25.setText(QtGui.QApplication.translate("generalizer", "Look ahead:", None, QtGui.QApplication.UnicodeUTF8)) 461 | self.label_26.setText(QtGui.QApplication.translate("generalizer", "Slide:", None, QtGui.QApplication.UnicodeUTF8)) 462 | self.label_27.setText(QtGui.QApplication.translate("generalizer", "Look ahead:", None, QtGui.QApplication.UnicodeUTF8)) 463 | self.label_9.setText(QtGui.QApplication.translate("generalizer", "Alpha:", None, QtGui.QApplication.UnicodeUTF8)) 464 | self.label_10.setText(QtGui.QApplication.translate("generalizer", "Beta:", None, QtGui.QApplication.UnicodeUTF8)) 465 | self.bBrowse.setText(QtGui.QApplication.translate("generalizer", "Browse", None, QtGui.QApplication.UnicodeUTF8)) 466 | self.cbOutFile.setText(QtGui.QApplication.translate("generalizer", "Save output layer", None, QtGui.QApplication.UnicodeUTF8)) 467 | self.tblBatchAlg.horizontalHeaderItem(0).setText(QtGui.QApplication.translate("generalizer", "Algorithm", None, QtGui.QApplication.UnicodeUTF8)) 468 | self.tblBatchAlg.horizontalHeaderItem(1).setText(QtGui.QApplication.translate("generalizer", "Parameter 1", None, QtGui.QApplication.UnicodeUTF8)) 469 | self.tblBatchAlg.horizontalHeaderItem(2).setText(QtGui.QApplication.translate("generalizer", "Parameter 2", None, QtGui.QApplication.UnicodeUTF8)) 470 | self.bAddAlg.setText(QtGui.QApplication.translate("generalizer", "Add", None, QtGui.QApplication.UnicodeUTF8)) 471 | self.bDelAlg.setText(QtGui.QApplication.translate("generalizer", "Delete", None, QtGui.QApplication.UnicodeUTF8)) 472 | self.bEditAlg.setText(QtGui.QApplication.translate("generalizer", "Edit", None, QtGui.QApplication.UnicodeUTF8)) 473 | self.bBrowseDir.setText(QtGui.QApplication.translate("generalizer", "Browse", None, QtGui.QApplication.UnicodeUTF8)) 474 | self.cbOutDir.setText(QtGui.QApplication.translate("generalizer", "Save output layer(s) to folder", None, QtGui.QApplication.UnicodeUTF8)) 475 | self.label_5.setText(QtGui.QApplication.translate("generalizer", "Algorithm(s)", None, QtGui.QApplication.UnicodeUTF8)) 476 | self.label_6.setText(QtGui.QApplication.translate("generalizer", "Choose layer(s)", None, QtGui.QApplication.UnicodeUTF8)) 477 | 478 | -------------------------------------------------------------------------------- /generalizerdialog.py: -------------------------------------------------------------------------------- 1 | """ 2 | /*************************************************************************** 3 | generalizerDialog 4 | A QGIS plugin 5 | Lines generalization (smooth and simplify) based on v.generalize GRASS module 6 | ------------------- 7 | begin : 2011-08-17 8 | copyright : (C) 2011 by Piotr Pociask 9 | email : ppociask (at) o2 pl 10 | ***************************************************************************/ 11 | 12 | /*************************************************************************** 13 | * * 14 | * This program is free software; you can redistribute it and/or modify * 15 | * it under the terms of the GNU General Public License as published by * 16 | * the Free Software Foundation; either version 2 of the License, or * 17 | * (at your option) any later version. * 18 | * * 19 | ***************************************************************************/ 20 | """ 21 | 22 | from PyQt4.QtCore import * 23 | from PyQt4.QtGui import * 24 | 25 | from qgis.core import * 26 | from qgis.gui import * 27 | 28 | import smooth, simplify, points 29 | from dialogs import * 30 | 31 | from ui_generalizer import Ui_generalizer 32 | 33 | #global variable with short to full algorithm names 34 | algorithm = {'remove':'Remove small objects', 35 | 'DP':'Douglas-Peucker Algorithm', 36 | 'lang':'Lang Algorithm', 37 | 'reduction':'Vertex Reduction', 38 | 'boyle':'Boyle\'s Forward-Looking Algorithm', 39 | 'chaiken':'Chaiken\'s Algorithm', 40 | 'hermite':'Hermite Spline Interpolation', 41 | 'distance':'McMaster\'s Distance-Weighting Algorithm', 42 | 'sliding':'McMaster\'s Sliding Averaging Algorithm', 43 | 'snakes':'Snakes Algorithm', 44 | 'jenks':'Jenk\'s Algorithm', 45 | 'RW':'Reumann-Witkam Algorithm' 46 | } 47 | 48 | 49 | class generalizerDialog(QDialog): 50 | def __init__(self, iface): 51 | QDialog.__init__(self) 52 | # Set up the user interface from Designer. 53 | self.ui = Ui_generalizer() 54 | self.ui.setupUi(self) 55 | self.iface = iface 56 | 57 | self.ui.sbJenks_angle.setVisible(False) 58 | self.ui.label_8.setVisible(False) 59 | 60 | #set signals 61 | self.ui.bBrowse.clicked.connect( self.outFile ) 62 | self.ui.bBrowseDir.clicked.connect( self.outDir ) 63 | self.ui.bOk.clicked.connect( self.generalize ) 64 | self.ui.cbAlgorithm.currentIndexChanged.connect( self.cbChange ) 65 | self.ui.bHelp.clicked.connect( self.showHelp ) 66 | self.ui.cbBatch.stateChanged.connect( self.BatchOn ) 67 | self.ui.bAddAlg.clicked.connect( self.AddAlgorithm ) 68 | self.ui.bDelAlg.clicked.connect( self.DelAlgorithm ) 69 | self.ui.bEditAlg.clicked.connect( self.EditAlgorithm ) 70 | self.ui.cbOutFile.stateChanged.connect( self.FileEnabled ) 71 | self.ui.cbOutDir.stateChanged.connect( self.DirEnabled ) 72 | 73 | #load line layers to lists 74 | self.layerList = getLayersNames() 75 | self.ui.cbInput.addItems(self.layerList) 76 | self.ui.lstLayers.addItems(self.layerList) 77 | [self.ui.lstLayers.item(i).setCheckState(Qt.Unchecked) for i in range(self.ui.lstLayers.count()) ] 78 | 79 | def FileEnabled(self, state): 80 | #enable or disable path to file 81 | enabled = self.ui.eOutput.isEnabled() 82 | self.ui.eOutput.setEnabled(not enabled) 83 | self.ui.bBrowse.setEnabled(not enabled) 84 | 85 | def DirEnabled(self, state): 86 | #enable/disable directory 87 | enabled = self.ui.eDir.isEnabled() 88 | self.ui.eDir.setEnabled(not enabled) 89 | self.ui.bBrowseDir.setEnabled(not enabled) 90 | 91 | def AddAlgorithm(self): 92 | #add new algorithm in batch mode 93 | self.doAddAlgorithm(self.ui.tblBatchAlg.rowCount()) 94 | 95 | def EditAlgorithm(self): 96 | #edit algorithm in batch mode 97 | if self.ui.tblBatchAlg.currentRow() == -1: 98 | QMessageBox.warning(self, 'Generalizer', 'Select algorithm to edit!') 99 | return 100 | 101 | self.doAddAlgorithm(self.ui.tblBatchAlg.currentRow()) 102 | 103 | def doAddAlgorithm(self, index): 104 | #add new algorithm in batch mode 105 | global algorithm 106 | 107 | new = index > self.ui.tblBatchAlg.rowCount()-1 108 | 109 | items = [self.ui.cbAlgorithm.itemText(i) for i in range(self.ui.cbAlgorithm.count())] 110 | algName = QInputDialog.getItem(None, 'Generalizer', 'Choose algorithm:', items, 1, False) 111 | if not algName[1] or algName[0].startswith('-'): return 112 | #QMessageBox.question(self, 'Generalizer', str(alg)) 113 | par1 = None 114 | par2 = None 115 | 116 | if algName[0] == algorithm['boyle']:#Boyle\'s Forward-Looking Algorithm': 117 | par1 = QSpinBox() 118 | par1.setRange(2, 999) 119 | msg = QInputDialog.getInt(None, 'Generalizer', 'Look ahead:', 7, 2) 120 | if not msg[1]: return 121 | par1.setValue(msg[0]) 122 | par1.setToolTip('Look ahead') 123 | 124 | elif algName[0] == algorithm['sliding']:#'McMaster\'s Sliding Averaging Algorithm': 125 | par1 = QDoubleSpinBox() 126 | par1.setDecimals(2) 127 | par1.setRange(0, 99.99) 128 | msg = QInputDialog.getDouble(None, 'Generalizer', 'Slide:', 0.5, 0, 99.99) 129 | if not msg[1]: return 130 | par1.setValue(msg[0]) 131 | par1.setToolTip('Slide') 132 | 133 | par2 = QSpinBox() 134 | par2.setRange(3, 999) 135 | par2.setSingleStep(2) 136 | par2.setValue(6) 137 | while par2.value()%2 == 0: 138 | msg = QInputDialog.getInt(None, 'Generalizer', 'Look ahead (must be odd number):', par2.value()+1, 3, 999) 139 | if not msg[1]: return 140 | par2.setValue(msg[0]) 141 | par2.setToolTip('Look ahead') 142 | 143 | 144 | elif algName[0] == algorithm['distance']:#'McMaster\'s Distance-Weighting Algorithm': 145 | par1 = QDoubleSpinBox() 146 | par1.setDecimals(2) 147 | par1.setRange(0, 99.99) 148 | msg = QInputDialog.getDouble(None, 'Generalizer', 'Slide:', 0.5, 0, 99.99) 149 | if not msg[1]: return 150 | par1.setValue(msg[0]) 151 | par1.setToolTip('Slide') 152 | 153 | par2 = QSpinBox() 154 | par2.setRange(3, 999) 155 | par2.setSingleStep(2) 156 | par2.setValue(6) 157 | while par2.value()%2 == 0: 158 | msg = QInputDialog.getInt(None, 'Generalizer', 'Look ahead (must be odd number):', par2.value()+1, 3, 999) 159 | if not msg[1]: return 160 | par2.setValue(msg[0]) 161 | par2.setToolTip('Look ahead') 162 | 163 | elif algName[0] == algorithm['chaiken']: #'Chaiken\'s Algorithm': 164 | par1 = QSpinBox() 165 | par1.setRange(0, 99) 166 | msg = QInputDialog.getInt(None, 'Generalizer', 'Level:', 1, 0, 99) 167 | if not msg[1]: return 168 | par1.setValue(msg[0]) 169 | par1.setToolTip('Level') 170 | 171 | par2 = QDoubleSpinBox() 172 | par2.setDecimals(2) 173 | par2.setRange(1, 99.99) 174 | msg = QInputDialog.getDouble(None, 'Generalizer', 'Weight:', 3., 1, 99.99) 175 | if not msg[1]: return 176 | par2.setValue(msg[0]) 177 | par2.setToolTip('Weight') 178 | 179 | elif algName[0] == algorithm['reduction']:#'Vertex Reduction': 180 | par1 = QDoubleSpinBox() 181 | par1.setDecimals(4) 182 | par1.setRange(0.0001, 9999999.9999) 183 | msg = QInputDialog.getDouble(None, 'Generalizer', 'Threshold:', 0.0001, 0.0001, 9999999.9999, 4) 184 | if not msg[1]: return 185 | par1.setValue(msg[0]) 186 | par1.setToolTip('Threshold') 187 | 188 | elif algName[0] == algorithm['DP']:#'Douglas-Peucker Algorithm': 189 | par1 = QDoubleSpinBox() 190 | par1.setDecimals(4) 191 | par1.setRange(0.0001, 9999999.9999) 192 | msg = QInputDialog.getDouble(None, 'Generalizer', 'Threshold:', 0.0001, 0.0001, 9999999.9999, 4) 193 | if not msg[1]: return 194 | par1.setValue(msg[0]) 195 | par1.setToolTip('Threshold') 196 | 197 | elif algName[0] == algorithm['remove']:#'Remove small objects': 198 | par1 = QDoubleSpinBox() 199 | par1.setDecimals(4) 200 | par1.setRange(0.0001, 9999999.9999) 201 | msg = QInputDialog.getDouble(None, 'Generalizer', 'Threshold:', 0.0001, 0.0001, 9999999.9999, 4) 202 | if not msg[1]: return 203 | par1.setValue(msg[0]) 204 | par1.setToolTip('Threshold') 205 | 206 | elif algName[0] == algorithm['lang']:#'Lang Algorithm': 207 | par1 = QDoubleSpinBox() 208 | par1.setDecimals(2) 209 | par1.setRange(0.0001, 9999999.9999) 210 | msg = QInputDialog.getDouble(None, 'Generalizer', 'Threshold:', 0.0001, 0.0001, 9999999.9999, 4) 211 | if not msg[1]: return 212 | par1.setValue(msg[0]) 213 | par1.setToolTip('Threshold') 214 | 215 | par2 = QSpinBox() 216 | par2.setRange(1, 9999) 217 | msg = QInputDialog.getInt(None, 'Generalizer', 'Look ahead:', 8, 1, 999) 218 | if not msg[1]: return 219 | par2.setValue(msg[0]) 220 | par2.setToolTip('Look ahead') 221 | 222 | 223 | elif algName[0] == algorithm['hermite']:#'Hermite Spline Interpolation': 224 | par1 = QDoubleSpinBox() 225 | par1.setDecimals(4) 226 | par1.setRange(0.0001, 9999999.9999) 227 | msg = QInputDialog.getDouble(None, 'Generalizer', 'Threshold:', 2., 0.0001, 9999999.9999, 4) 228 | if not msg[1]: return 229 | par1.setValue(msg[0]) 230 | par1.setToolTip('Threshold') 231 | 232 | par2 = QDoubleSpinBox() 233 | par2.setDecimals(2) 234 | par2.setRange(0, 1) 235 | msg = QInputDialog.getDouble(None, 'Generalizer', 'Thightness:', 0.5, 0, 1, 2) 236 | if not msg[1]: return 237 | par2.setValue(msg[0]) 238 | par2.setToolTip('Thightness') 239 | 240 | elif algName[0] == algorithm['snakes']:#'Snakes algorithm': 241 | par1 = QDoubleSpinBox() 242 | par1.setDecimals(2) 243 | par1.setRange(0, 9999.99) 244 | msg = QInputDialog.getDouble(None, 'Generalizer', 'Alpha:', 1., 0.00, 9999.99, 2) 245 | if not msg[1]: return 246 | par1.setValue(msg[0]) 247 | par1.setToolTip('Alpha') 248 | 249 | par2 = QDoubleSpinBox() 250 | par2.setDecimals(2) 251 | par2.setRange(0, 9999.99) 252 | msg = QInputDialog.getDouble(None, 'Generalizer', 'Beta:', 0.5, 0., 9999.99, 2) 253 | if not msg[1]: return 254 | par2.setValue(msg[0]) 255 | par2.setToolTip('Beta') 256 | 257 | elif algName[0] == algorithm['jenks']:#'Snakes algorithm': 258 | par1 = QDoubleSpinBox() 259 | par1.setDecimals(4) 260 | par1.setRange(0, 9999999.9999) 261 | msg = QInputDialog.getDouble(None, 'Generalizer', 'Threshold:', 0.0001, 0.00, 9999999.9999, 4) 262 | if not msg[1]: return 263 | par1.setValue(msg[0]) 264 | par1.setToolTip('Threshold') 265 | 266 | """par2 = QDoubleSpinBox() 267 | par2.setRange(0, 180) 268 | msg = QInputDialog.getDouble(None, 'Generalizer', 'Angle threshold:', 3, 0., 180, 2) 269 | if not msg[1]: return 270 | par2.setValue(msg[0]) 271 | par2.setToolTip('Angle threshold') """ 272 | 273 | elif algName[0] == algorithm['RW']:#Reumann-Witkam Algorithm 274 | par1 = QDoubleSpinBox() 275 | par1.setDecimals(4) 276 | par1.setRange(0, 9999999.9999) 277 | msg = QInputDialog.getDouble(None, 'Generalizer', 'Threshold:', 0.0001, 0.00, 9999999.9999, 4) 278 | if not msg[1]: return 279 | par1.setValue(msg[0]) 280 | par1.setToolTip('Threshold') 281 | 282 | #QMessageBox.question(self, 'Generalizer', str(type(par1))) 283 | itemAlg = QTableWidgetItem(algName[0]) 284 | itemAlg.setFlags(Qt.ItemIsEnabled) 285 | 286 | if new: 287 | self.ui.tblBatchAlg.setRowCount(self.ui.tblBatchAlg.rowCount()+1) 288 | 289 | self.ui.tblBatchAlg.setItem(index, 0, itemAlg) 290 | self.ui.tblBatchAlg.setCellWidget(index, 1, par1) 291 | if par2 == None: 292 | self.ui.tblBatchAlg.setCellWidget(index, 2, None) 293 | par2 = QTableWidgetItem(0) 294 | par2.setFlags(Qt.ItemIsSelectable) 295 | self.ui.tblBatchAlg.setItem(index, 2, par2) 296 | else: 297 | self.ui.tblBatchAlg.setCellWidget(index, 2, par2) 298 | 299 | def DelAlgorithm(self): 300 | #del algorithm in batch mode 301 | if self.ui.tblBatchAlg.currentRow() == -1: 302 | QMessageBox.warning(self, 'Generalizer', 'Select algorithm to delete!') 303 | return 304 | 305 | alg = self.ui.tblBatchAlg.item(self.ui.tblBatchAlg.currentRow(), 0).text() 306 | msg = QMessageBox.question(self, 'Generalizer', 'Do you want to delete %s' % (alg), QMessageBox.Yes | QMessageBox.No) 307 | 308 | if msg == QMessageBox.Yes: 309 | self.ui.tblBatchAlg.removeRow(self.ui.tblBatchAlg.currentRow()) 310 | 311 | def BatchOn(self, state): 312 | #set batch mode on/off 313 | if state == 0: 314 | self.ui.stackBatch.setCurrentIndex(0) 315 | else: 316 | self.ui.stackBatch.setCurrentIndex(1) 317 | 318 | def showHelp(self): 319 | #show information about plugin 320 | QMessageBox.information(self, 'Generalizer', """Generalizer 321 | Version 0.5 322 | 323 | Created by 324 | Piotr Pociask 325 | 326 | This plugin is marked as experimental. 327 | If you find any bugs or have suggestions, 328 | please contact with me: 329 | opengis84 (at) gmail (dot) com 330 | 331 | """) 332 | 333 | def outFile(self): 334 | """Open a file save dialog and set the output file path.""" 335 | outFilePath = saveDialog(self) 336 | if not outFilePath: 337 | return 338 | self.ui.eOutput.setText(outFilePath) 339 | 340 | def outDir(self): 341 | #select directory to save layer(s) in created batch mode 342 | outPath = openDir(self) 343 | if outPath: 344 | self.ui.eDir.setText(outPath) 345 | 346 | def cbChange(self, index): 347 | #set parameters after algorithm change 348 | if index == 0: self.ui.cbAlgorithm.setCurrentIndex(1) 349 | elif index == 1: self.ui.stackOptions.setCurrentIndex(index-1) #generalization 350 | elif index == 2: self.ui.cbAlgorithm.setCurrentIndex(3) 351 | elif index < 8: self.ui.stackOptions.setCurrentIndex(index-2) #simplify 352 | elif index == 8: self.ui.cbAlgorithm.setCurrentIndex(9) 353 | else: self.ui.stackOptions.setCurrentIndex(index-3) #smooth 354 | 355 | 356 | def GetArguments(self, par1=-1, par2=-1): 357 | #set parameters to algorithm 358 | if not self.ui.cbBatch.checkState(): 359 | arguments = {} 360 | arguments['remove_thresh'] = self.ui.sbRemove_thresh.value() 361 | arguments['dp_thresh'] = self.ui.sbDP_thresh.value() 362 | arguments['lang_thresh'] = self.ui.sbLang_thresh.value() 363 | arguments['lang_LA'] = self.ui.sbLang_LA.value() 364 | arguments['reduction_thresh'] = self.ui.sbReduction_thresh.value() 365 | arguments['boyle_LA'] = self.ui.sbBoyle_LA.value() 366 | arguments['slide_slide'] = self.ui.sbSlide_slide.value() 367 | arguments['slide_LA'] = self.ui.sbSlide_LA.value() 368 | arguments['dist_slide'] = self.ui.sbDist_slide.value() 369 | arguments['dist_LA'] = self.ui.sbDist_LA.value() 370 | arguments['chaiken_level'] = self.ui.sbChaiken_level.value() 371 | arguments['chaiken_weight'] = self.ui.sbChaiken_weight.value() 372 | arguments['hermite_thresh'] = self.ui.sbHermite_steps.value() 373 | arguments['hermite_tightness'] = self.ui.sbHermite_tightness.value() 374 | arguments['jenks_thresh'] = self.ui.sbJenks_thresh.value() 375 | arguments['jenks_angle'] = self.ui.sbJenks_angle.value() 376 | arguments['snakes_alpha'] = self.ui.sbSnakes_alpha.value() 377 | arguments['snakes_beta'] = self.ui.sbSnakes_beta.value() 378 | arguments['rw_thresh'] = self.ui.sbRW_thresh.value() 379 | else: 380 | arguments = {} 381 | arguments['remove_thresh'] = par1 382 | arguments['dp_thresh'] = par1 383 | arguments['lang_thresh'] = par1 384 | arguments['lang_LA'] = par2 385 | arguments['reduction_thresh'] = par1 386 | arguments['boyle_LA'] = par1 387 | arguments['slide_slide'] = par1 388 | arguments['slide_LA'] = par2 389 | arguments['dist_slide'] = par1 390 | arguments['dist_LA'] = par2 391 | arguments['chaiken_level'] = par1 392 | arguments['chaiken_weight'] = par2 393 | arguments['hermite_thresh'] = par1 394 | arguments['hermite_tightness'] = par2 395 | arguments['jenks_thresh'] = par1 396 | arguments['jenks_angle'] = par2 397 | arguments['snakes_alpha'] = par1 398 | arguments['snakes_beta'] = par2 399 | arguments['rw_thresh'] = par1 400 | 401 | if (arguments['slide_LA']%2 == 0) or (arguments['dist_LA']%2 == 0): 402 | QMessageBox.critical(None, 'Generalizer', 'Look ehead parameter must be odd number!') 403 | return None 404 | else: 405 | return arguments 406 | 407 | def GetFunction(self, funcName): 408 | #set function from name 409 | global algorithm 410 | 411 | if funcName == algorithm['boyle']:#'Boyle\'s Forward-Looking Algorithm': 412 | return self.boyle 413 | elif funcName == algorithm['sliding']:#'McMaster\'s Sliding Averaging Algorithm': 414 | return self.sliding_averaging 415 | elif funcName == algorithm['distance']:#'McMaster\'s Distance-Weighting Algorithm': 416 | return self.distance_weighting 417 | elif funcName == algorithm['chaiken']:#'Chaiken\'s Algorithm': 418 | return self.chaiken 419 | elif funcName == algorithm['reduction']:#'Vertex Reduction': 420 | return self.vertex_reduction 421 | elif funcName == algorithm['DP']:#'Douglas-Peucker Algorithm': 422 | return self.douglas_peucker 423 | elif funcName == algorithm['remove']:#'Remove small objects': 424 | return self.remove 425 | elif funcName == algorithm['lang']:#'Lang Algorithm': 426 | return self.lang 427 | elif funcName == algorithm['hermite']:#'Hermite Spline Interpolation': 428 | return self.hermite 429 | elif funcName == algorithm['jenks']:#'Jenk's Algorithm': 430 | return self.jenks 431 | elif funcName == algorithm['snakes']:#'Snakes': 432 | return self.snakes 433 | elif funcName == algorithm['RW']:#'Reumann-Witkam Algorithm': 434 | return self.reumann_witkam 435 | 436 | def NameFromFunc(self, func, arguments): 437 | if func == self.boyle: 438 | return '-boyle_LA-' + str(arguments['boyle_LA']) 439 | elif func == self.sliding_averaging: 440 | return '-slide_slide-' + str(arguments['slide_slide']) + '_LA-' + str(arguments['slide_LA']) 441 | elif func == self.distance_weighting: 442 | return '-dist_slide-' + str(arguments['dist_slide']) + '_LA-' + str(arguments['dist_LA']) 443 | elif func == self.chaiken: 444 | return '-chaiken_level-' + str(arguments['chaiken_level']) + '_weight-' + str(arguments['chaiken_weight']) 445 | elif func == self.vertex_reduction: 446 | return '-reduction_thresh-' + str(arguments['reduction_thresh']) 447 | elif func == self.douglas_peucker: 448 | return '-DP_thresh-' + str(arguments['dp_thresh']) 449 | elif func == self.remove: 450 | return '-remove_thresh-' + str(arguments['remove_thresh']) 451 | elif func == self.lang: 452 | return '-lang_thresh-' + str(arguments['lang_thresh']) + '_LA-' + str(arguments['lang_LA']) 453 | elif func == self.hermite: 454 | return '-hermite_thresh-' + str(arguments['hermite_thresh']) + '_tight-' + str(arguments['hermite_tightness']) 455 | elif func == self.jenks: 456 | return '-jenks_thresh-' + str(arguments['jenks_thresh']) + '_angle-' + str(arguments['jenks_angle']) 457 | elif func == self.snakes: 458 | return '-snakes_alpha-' + str(arguments['snakes_alpha']) + '_beta-' + str(arguments['snakes_beta']) 459 | elif func == self.reumann_witkam: 460 | return '-RW_thresh-' + str(arguments['rw_thresh']) 461 | 462 | 463 | def LoadLayers(self, fileList): 464 | #load created layer 465 | msg = QMessageBox.question(self, 'Generalizer', 'New layer(s) created. \n Add to TOC?', QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) 466 | if msg == QMessageBox.Yes: 467 | for filePath in fileList: 468 | if "\\" in filePath: 469 | out_name = filePath[(len(filePath) - filePath.rfind("\\")) - 1:] 470 | else: 471 | out_name = filePath[(len(filePath) - filePath.rfind("/")) - 1:] 472 | 473 | if out_name.endswith(".shp"): 474 | out_name = out_name[:len(out_name) - 4] 475 | 476 | self.iface.addVectorLayer(filePath, out_name, "ogr") 477 | 478 | 479 | def doGeneralize(self, iLayerName, iLayer, oPath, func, arguments): 480 | #do calculations 481 | fet = QgsFeature() 482 | 483 | iProvider = iLayer.dataProvider() 484 | fields = iProvider.fields() 485 | 486 | if oPath == 'memory': #create memory layer 487 | if iLayer.wkbType() == QGis.WKBLineString: 488 | mLayer = QgsVectorLayer('LineString', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') 489 | else: 490 | mLayer = QgsVectorLayer('MultiLineString', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') 491 | 492 | mProvider = mLayer.dataProvider() 493 | mProvider.addAttributes( [key for key in fields] ) 494 | 495 | for feat in iProvider.getFeatures(): 496 | geom = feat.geometry() 497 | if geom.isMultipart(): 498 | lm = geom.asMultiPolyline() 499 | l = [] 500 | for ls in lm: 501 | p = func(ls, **arguments) 502 | l2 = [] 503 | for n in range(p.n_points): 504 | l2.append(QgsPoint(p.x[n], p.y[n])) 505 | if len(l2) > 1: 506 | l.append(l2) 507 | if len(l) > 1: 508 | fet.setGeometry(QgsGeometry.fromMultiPolyline(l)) 509 | elif len(l) == 1: #jesli z obiektu wieloczesciowego zostaje tylko jedna linia (np. przy usuwaniu malych obiektow) 510 | fet.setGeometry(QgsGeometry.fromPolyline(l[0])) 511 | else: 512 | ls = geom.asPolyline() 513 | p = func(ls, **arguments) 514 | l = [] 515 | for n in range(p.n_points): 516 | l.append(QgsPoint(p.x[n], p.y[n])) 517 | if len(l) > 1: 518 | fet.setGeometry(QgsGeometry.fromPolyline(l)) 519 | else: 520 | continue #jak linia jest pusta to przejdz do nastepnej 521 | fet.setAttributes(feat.attributes()) 522 | mProvider.addFeatures([fet]) 523 | mLayer.updateFields() 524 | mLayer.updateExtents() 525 | return mLayer 526 | 527 | else: #write shapefile on disk 528 | writer = QgsVectorFileWriter(oPath, iProvider.encoding(), fields, QGis.WKBLineString, iLayer.crs()) 529 | if writer.hasError() != QgsVectorFileWriter.NoError: 530 | QMessageBox.critical(None, 'Generalizer', 'Error when creating shapefile: %s' % (writer.hasError())) 531 | 532 | for feat in iProvider.getFeatures(): 533 | geom = feat.geometry() 534 | if geom.isMultipart(): 535 | lm = geom.asMultiPolyline() 536 | #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(lm) ) 537 | l = [] 538 | for ls in lm: 539 | p = func(ls, **arguments) 540 | l2 = [] 541 | #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(p.n_points) ) 542 | for n in range(p.n_points): 543 | l2.append(QgsPoint(p.x[n], p.y[n])) 544 | if len(l2) > 1: 545 | l.append(l2) 546 | if len(l) > 1: 547 | #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(l) ) 548 | fet.setGeometry(QgsGeometry.fromMultiPolyline(l)) 549 | else: 550 | ls = geom.asPolyline() 551 | #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(ls) ) 552 | p = func(ls, **arguments) 553 | l = [] 554 | for n in range(p.n_points): 555 | l.append(QgsPoint(p.x[n], p.y[n])) 556 | 557 | if len(l) > 1: 558 | #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(l) ) 559 | fet.setGeometry(QgsGeometry.fromPolyline(l)) 560 | fet.setAttributes(feat.attributes()) 561 | writer.addFeature(fet) 562 | 563 | del writer 564 | return self.ui.eOutput.text() 565 | 566 | 567 | def batchGeneralize(self, layers): 568 | outNames = [] 569 | for layer in layers: 570 | vLayer = getMapLayerByName(layer) 571 | for i in range(self.ui.tblBatchAlg.rowCount()): 572 | #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(i) ) 573 | alg = self.ui.tblBatchAlg.item(i, 0).text() 574 | func = self.GetFunction(alg) 575 | 576 | par1 = self.ui.tblBatchAlg.cellWidget(i,1).value() 577 | if not func in [self.remove, self.douglas_peucker, self.vertex_reduction, self.boyle, self.jenks, self.reumann_witkam]: 578 | par2 = self.ui.tblBatchAlg.cellWidget(i,2).value() 579 | else: 580 | par2 = -1 581 | #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(par2) ) 582 | 583 | arguments = self.GetArguments(par1, par2) 584 | if self.ui.cbOutDir.isChecked() and i == self.ui.tblBatchAlg.rowCount()-1: 585 | #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(i) ) 586 | path = self.ui.eDir.text() 587 | if path.contains("\\"): 588 | out_name = path + '\\' + layer + '_new.shp' 589 | else: 590 | out_name = path + '/' + layer + '_new.shp' 591 | outNames.append(out_name) 592 | vLayer = self.doGeneralize(layer, vLayer, out_name, func, arguments) 593 | else: 594 | vLayer = self.doGeneralize(layer, vLayer, 'memory', func, arguments) 595 | 596 | if not self.ui.cbOutDir.isChecked(): 597 | QgsMapLayerRegistry.instance().addMapLayer(vLayer) 598 | 599 | if self.ui.cbOutDir.isChecked(): 600 | self.LoadLayers(outNames) 601 | 602 | 603 | 604 | def generalize(self): 605 | if self.ui.cbBatch.isChecked(): 606 | if self.ui.cbOutDir.isChecked(): 607 | if self.ui.eDir.text() == '': 608 | QMessageBox.critical(None, 'Generalizer', 'Enter output directory!') 609 | return 610 | 611 | 612 | layers = [self.ui.lstLayers.item(i).text() for i in range(self.ui.lstLayers.count()) if self.ui.lstLayers.item(i).checkState() ] 613 | self.batchGeneralize(layers) 614 | #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(layers) ) 615 | else: 616 | if self.ui.cbInput.currentText() == '': 617 | QMessageBox.critical(None, 'Generalizer', 'No line layers!') 618 | return 619 | 620 | arguments = self.GetArguments() 621 | #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(arguments) ) 622 | if arguments == None: 623 | return 624 | 625 | func = self.GetFunction(self.ui.cbAlgorithm.currentText()) 626 | if self.ui.cbOutFile.isChecked(): 627 | if self.ui.eOutput.text() == '': 628 | QMessageBox.critical(None, 'Generalizer', 'Enter output file name!') 629 | return 630 | filePath = self.doGeneralize(self.ui.cbInput.currentText(), getMapLayerByName(self.ui.cbInput.currentText()), self.ui.eOutput.text(), func, arguments) 631 | self.LoadLayers([filePath]) 632 | else: 633 | mLayer = self.doGeneralize(self.ui.cbInput.currentText(), getMapLayerByName(self.ui.cbInput.currentText()), 'memory', func, arguments) 634 | QgsMapLayerRegistry.instance().addMapLayer(mLayer) 635 | 636 | #self.close() 637 | #refresh layer list 638 | self.layerList = getLayersNames() 639 | self.ui.cbInput.clear() 640 | self.ui.lstLayers.clear() 641 | self.ui.cbInput.addItems(self.layerList) 642 | self.ui.lstLayers.addItems(self.layerList) 643 | [self.ui.lstLayers.item(i).setCheckState(Qt.Unchecked) for i in range(self.ui.lstLayers.count()) ] 644 | 645 | def remove(self, l, **kwargs): 646 | #Remove Small Objects 647 | thresh = kwargs['remove_thresh'] 648 | length = 0. 649 | p = points.Vect_new_line_struct(l) 650 | p1 = points.point() 651 | p2 = points.point() 652 | 653 | for i in range(p.n_points-1): 654 | points.point_assign(p, i, p1) 655 | points.point_assign(p, i+1, p2) 656 | length = length + points.point_dist(p1, p2) 657 | 658 | #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str( length ) ) 659 | if length < thresh: 660 | p.x = [] 661 | p.y = [] 662 | p.n_points = 0 663 | #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str( p.x ) ) 664 | 665 | return p 666 | 667 | def boyle(self,l, **kwargs): 668 | #Boyle's Forward-Looking Algorithm 669 | p = points.Vect_new_line_struct(l) 670 | n = smooth.boyle(p, kwargs['boyle_LA']) 671 | 672 | return p 673 | 674 | def sliding_averaging(self,l, **kwargs): 675 | #McMaster's Sliding Averaging Algorithm 676 | p = points.Vect_new_line_struct(l) 677 | n = smooth.sliding_averaging(p, kwargs['slide_slide'], kwargs['slide_LA']) 678 | 679 | return p 680 | 681 | def distance_weighting(self,l, **kwargs): 682 | #McMaster's Distance Weighting Algorithm 683 | p = points.Vect_new_line_struct(l) 684 | n = smooth.distance_weighting(p, kwargs['dist_slide'], kwargs['dist_LA']) 685 | 686 | return p 687 | 688 | def chaiken(self,l, **kwargs): 689 | #Chaiken's Algorithm 690 | p = points.Vect_new_line_struct(l) 691 | #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(p.n_points) ) 692 | n = smooth.chaiken(p, kwargs['chaiken_level'], kwargs['chaiken_weight']) 693 | 694 | return p 695 | 696 | def vertex_reduction(self,l, **kwargs): 697 | #Vertex Reduction 698 | #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(l) ) 699 | p = points.Vect_new_line_struct(l) 700 | n = simplify.vertex_reduction(p, kwargs['reduction_thresh']) 701 | 702 | return p 703 | 704 | def douglas_peucker(self,l, **kwargs): 705 | #Douglas-peucker Algorithm 706 | tmp = simplify.douglas_peucker(l, kwargs['dp_thresh']) 707 | p = points.Vect_new_line_struct(tmp) 708 | 709 | return p 710 | 711 | def lang(self,l, **kwargs): 712 | #Vertex Reduction 713 | p = points.Vect_new_line_struct(l) 714 | n = simplify.lang(p, kwargs['lang_thresh'], kwargs['lang_LA']) 715 | 716 | return p 717 | 718 | def hermite(self,l, **kwargs): 719 | #Vertex Reduction 720 | p = points.Vect_new_line_struct(l) 721 | n = smooth.hermite(p, kwargs['hermite_thresh'], kwargs['hermite_tightness']) 722 | 723 | return p 724 | 725 | def jenks(self,l, **kwargs): 726 | #Jenk's Algorithm 727 | #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(kwargs['jenks_angle']) ) 728 | p = points.Vect_new_line_struct(l) 729 | n = simplify.jenks(p, kwargs['jenks_thresh'], kwargs['jenks_angle']) 730 | 731 | return p 732 | 733 | def snakes(self,l, **kwargs): 734 | #Snakes 735 | p = points.Vect_new_line_struct(l) 736 | n = smooth.snakes(p, kwargs['snakes_alpha'], kwargs['snakes_beta']) 737 | 738 | return p 739 | 740 | def reumann_witkam(self,l, **kwargs): 741 | #Snakes 742 | p = points.Vect_new_line_struct(l) 743 | n = simplify.reumann_witkam(p, kwargs['rw_thresh']) 744 | 745 | return p 746 | 747 | 748 | def getLayersNames(): 749 | layermap = QgsMapLayerRegistry.instance().mapLayers() 750 | layerlist = [] 751 | for name, layer in layermap.iteritems(): 752 | if layer.type() == QgsMapLayer.VectorLayer: 753 | if layer.geometryType() == QGis.Line: 754 | layerlist.append( unicode( layer.name() ) ) 755 | 756 | return layerlist 757 | 758 | def getMapLayerByName(myName): 759 | layermap = QgsMapLayerRegistry.instance().mapLayers() 760 | for name, layer in layermap.iteritems(): 761 | if layer.name() == myName: 762 | if layer.isValid(): 763 | return layer 764 | else: 765 | return None 766 | --------------------------------------------------------------------------------