mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
'Join by location' can now use the geometry from the joined layer as output.
This commit is contained in:
parent
8daf8c371a
commit
4e57af6931
@ -53,6 +53,16 @@ def myself(L):
|
|||||||
medianVal = L[ (nVal + 1) / 2 - 1]
|
medianVal = L[ (nVal + 1) / 2 - 1]
|
||||||
return medianVal
|
return medianVal
|
||||||
|
|
||||||
|
# translate single part to multi part geometry type
|
||||||
|
multipart = {
|
||||||
|
QGis.WKBPoint: QGis.WKBMultiPoint,
|
||||||
|
QGis.WKBLineString: QGis.WKBMultiLineString,
|
||||||
|
QGis.WKBPolygon: QGis.WKBMultiPolygon,
|
||||||
|
QGis.WKBPoint25D: QGis.WKBMultiPoint25D,
|
||||||
|
QGis.WKBLineString25D: QGis.WKBMultiLineString25D,
|
||||||
|
QGis.WKBPolygon25D: QGis.WKBMultiPolygon25D,
|
||||||
|
}
|
||||||
|
|
||||||
class SpatialJoin(GeoAlgorithm):
|
class SpatialJoin(GeoAlgorithm):
|
||||||
'''
|
'''
|
||||||
Join attributes by location
|
Join attributes by location
|
||||||
@ -64,6 +74,7 @@ class SpatialJoin(GeoAlgorithm):
|
|||||||
INPUT2 = "INPUT2"
|
INPUT2 = "INPUT2"
|
||||||
SUMMARY = "SUMMARY"
|
SUMMARY = "SUMMARY"
|
||||||
STATS = "STATS"
|
STATS = "STATS"
|
||||||
|
GEOMETRY = "GEOMETRY"
|
||||||
KEEP = "KEEP"
|
KEEP = "KEEP"
|
||||||
OUTPUT = "OUTPUT"
|
OUTPUT = "OUTPUT"
|
||||||
|
|
||||||
@ -71,6 +82,11 @@ class SpatialJoin(GeoAlgorithm):
|
|||||||
'Take attributes of the first located feature',
|
'Take attributes of the first located feature',
|
||||||
'Take summary of intersecting features'
|
'Take summary of intersecting features'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
GEOMETRYS = [
|
||||||
|
'Use geometry from target layer',
|
||||||
|
'Use geometry from joined layer (multipart if summary)'
|
||||||
|
]
|
||||||
|
|
||||||
KEEPS = [
|
KEEPS = [
|
||||||
'Only keep matching records',
|
'Only keep matching records',
|
||||||
@ -88,7 +104,8 @@ class SpatialJoin(GeoAlgorithm):
|
|||||||
self.addParameter(ParameterVector(SpatialJoin.INPUT1, "Target vector layer", [ParameterVector.VECTOR_TYPE_ANY]))
|
self.addParameter(ParameterVector(SpatialJoin.INPUT1, "Target vector layer", [ParameterVector.VECTOR_TYPE_ANY]))
|
||||||
self.addParameter(ParameterVector(SpatialJoin.INPUT2, "Join vector layer", [ParameterVector.VECTOR_TYPE_ANY]))
|
self.addParameter(ParameterVector(SpatialJoin.INPUT2, "Join vector layer", [ParameterVector.VECTOR_TYPE_ANY]))
|
||||||
self.addParameter(ParameterSelection(self.SUMMARY, "Attribute summary", self.SUMMARYS, 0))
|
self.addParameter(ParameterSelection(self.SUMMARY, "Attribute summary", self.SUMMARYS, 0))
|
||||||
self.addParameter(ParameterString(self.STATS, "Statistics for summary (comma separated)", "sum,mean,min,max,med"))
|
self.addParameter(ParameterString(self.STATS, "Statistics for summary (comma separated)", "sum,mean,min,max,median"))
|
||||||
|
self.addParameter(ParameterSelection(self.GEOMETRY, "Output geometry", self.GEOMETRYS, 0))
|
||||||
self.addParameter(ParameterSelection(self.KEEP, "Output table", self.KEEPS, 0))
|
self.addParameter(ParameterSelection(self.KEEP, "Output table", self.KEEPS, 0))
|
||||||
self.addOutput(OutputVector(SpatialJoin.OUTPUT, "Output layer"))
|
self.addOutput(OutputVector(SpatialJoin.OUTPUT, "Output layer"))
|
||||||
|
|
||||||
@ -97,6 +114,7 @@ class SpatialJoin(GeoAlgorithm):
|
|||||||
|
|
||||||
summary = self.getParameterValue(self.SUMMARY) == 1
|
summary = self.getParameterValue(self.SUMMARY) == 1
|
||||||
sumList = self.getParameterValue(self.STATS).upper().replace(' ','').split(',')
|
sumList = self.getParameterValue(self.STATS).upper().replace(' ','').split(',')
|
||||||
|
use_geom = self.getParameterValue(self.GEOMETRY)
|
||||||
keep = self.getParameterValue(self.KEEP) == 1
|
keep = self.getParameterValue(self.KEEP) == 1
|
||||||
|
|
||||||
input1 = self.getParameterValue(self.INPUT1)
|
input1 = self.getParameterValue(self.INPUT1)
|
||||||
@ -130,13 +148,25 @@ class SpatialJoin(GeoAlgorithm):
|
|||||||
seq = range(0, len(fieldList1))
|
seq = range(0, len(fieldList1))
|
||||||
fieldList1 = dict(zip(seq, fieldList1))
|
fieldList1 = dict(zip(seq, fieldList1))
|
||||||
|
|
||||||
sRs = provider1.crs()
|
|
||||||
progress.setPercentage(13)
|
progress.setPercentage(13)
|
||||||
fields = QgsFields()
|
fields = QgsFields()
|
||||||
for f in fieldList1.values():
|
for f in fieldList1.values():
|
||||||
fields.append(f)
|
fields.append(f)
|
||||||
output = self.getOutputFromName(self.OUTPUT)
|
output = self.getOutputFromName(self.OUTPUT)
|
||||||
writer = output.getVectorWriter(fields, provider1.geometryType(), sRs)
|
|
||||||
|
if use_geom == 0:
|
||||||
|
# from target layer
|
||||||
|
crs = provider1.crs()
|
||||||
|
geometry_type = provider1.geometryType()
|
||||||
|
else:
|
||||||
|
# from joined layer
|
||||||
|
crs = provider2.crs()
|
||||||
|
if summary:
|
||||||
|
geometry_type = multipart[provider2.geometryType()]
|
||||||
|
else:
|
||||||
|
geometry_type = provider2.geometryType()
|
||||||
|
|
||||||
|
writer = output.getVectorWriter(fields, geometry_type, crs)
|
||||||
|
|
||||||
inFeat = QgsFeature()
|
inFeat = QgsFeature()
|
||||||
outFeat = QgsFeature()
|
outFeat = QgsFeature()
|
||||||
@ -154,7 +184,8 @@ class SpatialJoin(GeoAlgorithm):
|
|||||||
while fit1.nextFeature(inFeat):
|
while fit1.nextFeature(inFeat):
|
||||||
inGeom = inFeat.geometry()
|
inGeom = inFeat.geometry()
|
||||||
atMap1 = inFeat.attributes()
|
atMap1 = inFeat.attributes()
|
||||||
outFeat.setGeometry(inGeom)
|
if use_geom == 0:
|
||||||
|
outFeat.setGeometry(inGeom)
|
||||||
none = True
|
none = True
|
||||||
joinList = []
|
joinList = []
|
||||||
if inGeom.type() == QGis.Point:
|
if inGeom.type() == QGis.Point:
|
||||||
@ -171,17 +202,30 @@ class SpatialJoin(GeoAlgorithm):
|
|||||||
provider2.getFeatures( QgsFeatureRequest().setFilterFid( int(i) ) ).nextFeature( inFeatB )
|
provider2.getFeatures( QgsFeatureRequest().setFilterFid( int(i) ) ).nextFeature( inFeatB )
|
||||||
if inGeom.intersects(inFeatB.geometry()):
|
if inGeom.intersects(inFeatB.geometry()):
|
||||||
count = count + 1
|
count = count + 1
|
||||||
none = False
|
|
||||||
atMap2 = inFeatB.attributes()
|
atMap2 = inFeatB.attributes()
|
||||||
if not summary:
|
if not summary:
|
||||||
|
# first located feature
|
||||||
atMap = atMap1
|
atMap = atMap1
|
||||||
atMap2 = atMap2
|
atMap2 = atMap2
|
||||||
atMap.extend(atMap2)
|
atMap.extend(atMap2)
|
||||||
atMap = dict(zip(seq, atMap))
|
atMap = dict(zip(seq, atMap))
|
||||||
|
if use_geom == 1:
|
||||||
|
outFeat.setGeometry(inFeatB.geometry())
|
||||||
|
none = False
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
for j in numFields.keys():
|
for j in numFields.keys():
|
||||||
numFields[j].append(atMap2[j])
|
numFields[j].append(atMap2[j])
|
||||||
|
if none:
|
||||||
|
# first located feature in summary
|
||||||
|
outFeat.setGeometry(inFeatB.geometry())
|
||||||
|
else:
|
||||||
|
# combine (union) with existing geometry
|
||||||
|
existing = outFeat.geometry()
|
||||||
|
additional = inFeatB.geometry()
|
||||||
|
union = existing.combine(additional)
|
||||||
|
outFeat.setGeometry(union)
|
||||||
|
none = False
|
||||||
if summary and not none:
|
if summary and not none:
|
||||||
atMap = atMap1
|
atMap = atMap1
|
||||||
for j in numFields.keys():
|
for j in numFields.keys():
|
||||||
@ -189,7 +233,7 @@ class SpatialJoin(GeoAlgorithm):
|
|||||||
if k == "SUM": atMap.append(sum(numFields[j]))
|
if k == "SUM": atMap.append(sum(numFields[j]))
|
||||||
elif k == "MEAN": atMap.append(sum(numFields[j]) / count)
|
elif k == "MEAN": atMap.append(sum(numFields[j]) / count)
|
||||||
elif k == "MIN": atMap.append(min(numFields[j]))
|
elif k == "MIN": atMap.append(min(numFields[j]))
|
||||||
elif k == "MED": atMap.append(myself(numFields[j]))
|
elif k == "MEDIAN": atMap.append(myself(numFields[j]))
|
||||||
else: atMap.append(max(numFields[j]))
|
else: atMap.append(max(numFields[j]))
|
||||||
numFields[j] = []
|
numFields[j] = []
|
||||||
atMap.append(count)
|
atMap.append(count)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user