Skip to content

Commit 1f0d1af

Browse files
author
cfarmer
committed
Simplify geometry tool now works properly for multipart features. Note: tool now uses builtin simplify function from QgsGeometry (i.e. should be noticeably faster). Fixes #2493 and #2499.
git-svn-id: http://svn.osgeo.org/qgis/trunk@13033 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 1f1d648 commit 1f0d1af

File tree

1 file changed

+2
-138
lines changed

1 file changed

+2
-138
lines changed

python/plugins/fTools/tools/doGeometry.py

+2-138
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# -*- coding: utf-8 -*-
12
from PyQt4.QtCore import *
23
from PyQt4.QtGui import *
34
from qgis.core import *
@@ -402,7 +403,7 @@ def simplify_geometry( self ):
402403
self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), nElement )
403404
inGeom = inFeat.geometry()
404405
atMap = inFeat.attributeMap()
405-
outGeom = self.extractAsSimple( inGeom, tolerance )
406+
outGeom = QgsGeometry(inGeom.simplify(tolerance))
406407
if outGeom is None:
407408
return "math_error"
408409
outFeat.setAttributeMap( atMap )
@@ -568,143 +569,6 @@ def layer_extent( self ):
568569

569570
return True
570571

571-
def extractAsSimple( self, geom, tolerance ):
572-
temp_geom1 = []
573-
temp_geom2 = []
574-
if geom.type() == 1:
575-
if geom.isMultipart():
576-
multi_geom = geom.asMultiPolyline()
577-
for i in multi_geom:
578-
simple = self.simplifyLine( i, 1, tolerance )
579-
if simple is None:
580-
return None
581-
else:
582-
temp_geom1.append( simple )
583-
return QgsGeometry().fromMultiPolyline(temp_geom1)
584-
else:
585-
multi_geom = self.simplifyLine( geom.asPolyline(), 1, tolerance )
586-
if multi_geom is None:
587-
return None
588-
else:
589-
return QgsGeometry().fromPolyline(multi_geom)
590-
elif geom.type() == 2:
591-
if geom.isMultipart():
592-
multi_geom = geom.asMultiPolygon()
593-
for i in multi_geom:
594-
temp_geom2 = []
595-
for j in i:
596-
simple = self.simplifyLine( j, 2, tolerance )
597-
if simple is None:
598-
return None
599-
else:
600-
temp_geom2.append( simple )
601-
temp_geom1.append( temp_geom2 )
602-
return QgsGeometry().fromMultiPolygon( temp_geom1 )
603-
else:
604-
multi_geom = geom.asPolygon()
605-
for i in multi_geom:
606-
simple = self.simplifyLine( i, 2, tolerance )
607-
if simple is None:
608-
return None
609-
else:
610-
temp_geom1.append( simple )
611-
return QgsGeometry().fromPolygon(temp_geom1)
612-
613-
def simplifyLine( self, ln, typ, tol ):
614-
newline = []
615-
last = len(ln) - 1
616-
if typ == 2:
617-
tml = 0.00
618-
mid = 1
619-
for m in range(1 , last):
620-
ml = self.measure.measureLine(ln[0], ln[m])
621-
if ml > tml:
622-
tml = ml
623-
mid = m
624-
keep = [0, mid, last]
625-
try:
626-
keep.extend( self.recursiveDouglasPeucker( ln, tol, 0, mid) )
627-
keep.extend( self.recursiveDouglasPeucker( ln, tol, mid, last) )
628-
except:
629-
return None
630-
if len(keep) <= 3:
631-
return ln
632-
else:
633-
keep = [0, last]
634-
keep.extend( self.recursiveDouglasPeucker( ln, tol, 0, last) )
635-
keep.sort()
636-
for i in keep:
637-
newline.append(ln[i])
638-
return newline
639-
640-
def recursiveDouglasPeucker( self, line, tol, j, k ):
641-
# recursiveDouglasPeucker based on function
642-
# by Schuyler Erle <schuyler@nocat.net>
643-
# Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
644-
keep = []
645-
if k <= j+1: # there is nothing to simplify
646-
return keep
647-
# degenerate case
648-
if self.measure.measureLine( line[ j ], line[ k ]) < tol:
649-
return keep
650-
# check for adequate approximation by segment S from v[j] to v[k]
651-
maxi = j # index of vertex farthest from S
652-
maxd = 0 # distance squared of farthest vertex
653-
tline = [ line[ j ], line[ k ] ]
654-
# test each vertex v[i] for max distance from S
655-
for i in range( j + 1, k ):
656-
# compute distance
657-
#dv = seg.Distance( pts[i] )
658-
dv = self.shortestDistance( tline, line[ i ] )
659-
if dv is None:
660-
return None
661-
# test with current max distance
662-
if dv > maxd:
663-
# v[i] is a new max vertex
664-
maxi = i
665-
maxd = dv
666-
if maxd > tol: # error is worse than the tolerance
667-
# split the polyline at the farthest vertex from S
668-
keep.append( maxi ) # mark v[maxi] for the simplified polyline
669-
# recursively simplify the two subpolylines at v[maxi]
670-
keep.extend( self.recursiveDouglasPeucker( line, tol, j, maxi ) ) # v[j] to v[maxi]
671-
keep.extend( self.recursiveDouglasPeucker( line, tol, maxi, k ) ) # v[maxi] to v[k]
672-
673-
# else the approximation is OK, so ignore intermediate vertices
674-
return keep
675-
676-
def shortestDistance( self, tline, point):
677-
try:
678-
a = self.measure.measureLine( tline[ 1 ], point )
679-
b = self.measure.measureLine( tline[ 0 ], point)
680-
c = self.measure.measureLine( tline[ 0 ], tline[ 1 ] )
681-
if a * b * c == 0.00:
682-
return 0.00
683-
x = ( ( a * a + b * b - c * c ) / ( 2.00 * b ) )
684-
h = math.sqrt( ( a * a ) - ( x * x ) )
685-
y = ( b - x )
686-
a3 = ( math.atan( h / x ) )
687-
if a3 < 0:
688-
a3 = a3 + math.pi
689-
elif a3 > math.pi:
690-
a3 = a3 - math.pi
691-
a1 = ( math.atan( h / y ) )
692-
if a1 < 0:
693-
a1 = a1 + math.pi
694-
elif a1 > math.pi:
695-
a1 = a1 - math.pi
696-
a3 = a3 * ( 180 / math.pi )
697-
a1 = a1 * (180 / math.pi)
698-
a2 = ( ( math.pi ) * ( 180 / math.pi ) ) - a1 - a3
699-
if a3 >= 90.00:
700-
length = c
701-
elif a2 >= 90.00:
702-
length = b
703-
length = math.sin( a1 ) * b
704-
return math.fabs( length )
705-
except:
706-
return None
707-
708572
def simpleMeasure( self, inGeom ):
709573
if inGeom.wkbType() == QGis.WKBPoint:
710574
pt = QgsPoint()

0 commit comments

Comments
 (0)