28 #include <QProgressDialog>
31 const QString& shapefileName,
33 bool onlySelectedFeatures,
54 if ( onlySelectedFeatures )
60 p->setMaximum( selection.size() );
63 int processedFeatures = 0;
64 QgsFeatureIds::const_iterator it = selection.constBegin();
65 for ( ; it != selection.constEnd(); ++it )
69 p->setValue( processedFeatures );
72 if ( p && p->wasCanceled() )
80 simplifyFeature( currentFeature, &vWriter, tolerance );
86 p->setValue( selection.size() );
97 p->setMaximum( featureCount );
99 int processedFeatures = 0;
105 p->setValue( processedFeatures );
107 if ( p && p->wasCanceled() )
111 simplifyFeature( currentFeature, &vWriter, tolerance );
116 p->setValue( featureCount );
128 if ( !featureGeometry )
133 tmpGeometry = featureGeometry->
simplify( tolerance );
147 bool onlySelectedFeatures, QProgressDialog* p )
158 QgsDebugMsg(
"No data provider for layer passed to centroids" );
169 if ( onlySelectedFeatures )
175 p->setMaximum( selection.size() );
178 int processedFeatures = 0;
179 QgsFeatureIds::const_iterator it = selection.constBegin();
180 for ( ; it != selection.constEnd(); ++it )
184 p->setValue( processedFeatures );
187 if ( p && p->wasCanceled() )
195 centroidFeature( currentFeature, &vWriter );
201 p->setValue( selection.size() );
212 p->setMaximum( featureCount );
214 int processedFeatures = 0;
220 p->setValue( processedFeatures );
222 if ( p && p->wasCanceled() )
226 centroidFeature( currentFeature, &vWriter );
231 p->setValue( featureCount );
244 if ( !featureGeometry )
249 tmpGeometry = featureGeometry->
centroid();
263 const QString& shapefileName,
264 bool onlySelectedFeatures,
289 fields.
append(
QgsField( QString(
"PERIM" ), QVariant::Double ) );
290 fields.
append(
QgsField( QString(
"HEIGHT" ), QVariant::Double ) );
291 fields.
append(
QgsField( QString(
"WIDTH" ), QVariant::Double ) );
296 if ( onlySelectedFeatures )
306 double miny = rect.yMinimum();
307 double maxx = rect.xMaximum();
308 double maxy = rect.yMaximum();
309 double height = rect.height();
310 double width = rect.width();
311 double cntx = minx + ( width / 2.0 );
312 double cnty = miny + ( height / 2.0 );
313 double area = width * height;
314 double perim = ( 2 * width ) + ( 2 * height );
318 attrs[0] = QVariant( minx );
319 attrs[1] = QVariant( miny );
320 attrs[2] = QVariant( maxx );
321 attrs[3] = QVariant( maxy );
322 attrs[4] = QVariant( cntx );
323 attrs[5] = QVariant( cnty );
324 attrs[6] = QVariant( area );
325 attrs[7] = QVariant( perim );
326 attrs[8] = QVariant( height );
327 attrs[9] = QVariant( width );
330 vWriter.addFeature( feat );
334 QList<double> QgsGeometryAnalyzer::simpleMeasure(
QgsGeometry* mpGeometry )
341 list.append( pt.
x() );
342 list.append( pt.
y() );
347 list.append( measure.
measure( mpGeometry ) );
350 perim = perimeterMeasure( mpGeometry, measure );
351 list.append( perim );
363 QgsMultiPolygon::iterator it;
364 QgsPolygon::iterator jt;
365 for ( it = poly.begin(); it != poly.end(); ++it )
367 for ( jt = it->begin(); jt != it->end(); ++jt )
370 value = value + measure.
measure( geom );
377 QgsPolygon::iterator jt;
379 for ( jt = poly.begin(); jt != poly.end(); ++jt )
382 value = value + measure.
measure( geom );
390 bool onlySelectedFeatures,
int uniqueIdField, QProgressDialog* p )
401 bool useField =
false;
402 if ( uniqueIdField == -1 )
413 fields.
append(
QgsField( QString(
"PERIM" ), QVariant::Double ) );
421 QMultiMap<QString, QgsFeatureId> map;
423 if ( onlySelectedFeatures )
427 QgsFeatureIds::const_iterator it = selection.constBegin();
428 for ( ; it != selection.constEnd(); ++it )
433 p->setValue( processedFeatures );
435 if ( p && p->wasCanceled() )
445 map.insert( currentFeature.attribute( uniqueIdField ).toString(), currentFeature.id() );
456 p->setValue( processedFeatures );
458 if ( p && p->wasCanceled() )
464 map.insert( currentFeature.attribute( uniqueIdField ).toString(), currentFeature.id() );
468 QMultiMap<QString, QgsFeatureId>::const_iterator jt = map.constBegin();
469 while ( jt != map.constEnd() )
471 QString currentKey = jt.key();
472 int processedFeatures = 0;
474 if ( onlySelectedFeatures )
480 p->setMaximum( selection.size() );
482 processedFeatures = 0;
483 while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
485 if ( p && p->wasCanceled() )
489 if ( selection.contains( jt.value() ) )
493 p->setValue( processedFeatures );
499 convexFeature( currentFeature, processedFeatures, &dissolveGeometry );
504 QList<double> values;
505 if ( !dissolveGeometry )
507 QgsDebugMsg(
"no dissolved geometry - should not happen" );
510 dissolveGeometry = dissolveGeometry->
convexHull();
511 values = simpleMeasure( dissolveGeometry );
513 attributes[0] = QVariant( currentKey );
514 attributes[1] = values[ 0 ];
515 attributes[2] = values[ 1 ];
519 vWriter.addFeature( dissolveFeature );
527 p->setMaximum( featureCount );
529 processedFeatures = 0;
530 while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
534 p->setValue( processedFeatures );
537 if ( p && p->wasCanceled() )
545 convexFeature( currentFeature, processedFeatures, &dissolveGeometry );
549 QList<double> values;
551 if ( !dissolveGeometry )
553 QgsDebugMsg(
"no dissolved geometry - should not happen" );
556 dissolveGeometry = dissolveGeometry->
convexHull();
558 values = simpleMeasure( dissolveGeometry );
560 attributes[0] = QVariant( currentKey );
561 attributes[1] = QVariant( values[ 0 ] );
562 attributes[2] = QVariant( values[ 1 ] );
566 vWriter.addFeature( dissolveFeature );
573 void QgsGeometryAnalyzer::convexFeature(
QgsFeature& f,
int nProcessedFeatures,
QgsGeometry** dissolveGeometry )
579 if ( !featureGeometry )
584 convexGeometry = featureGeometry->
convexHull();
586 if ( nProcessedFeatures == 0 )
588 *dissolveGeometry = convexGeometry;
592 tmpGeometry = *dissolveGeometry;
593 *dissolveGeometry = ( *dissolveGeometry )->
combine( convexGeometry );
595 delete convexGeometry;
600 bool onlySelectedFeatures,
int uniqueIdField, QProgressDialog* p )
611 bool useField =
false;
612 if ( uniqueIdField == -1 )
626 QMultiMap<QString, QgsFeatureId> map;
628 if ( onlySelectedFeatures )
632 QgsFeatureIds::const_iterator it = selection.constBegin();
633 for ( ; it != selection.constEnd(); ++it )
639 map.insert( currentFeature.attribute( uniqueIdField ).toString(), currentFeature.id() );
647 map.insert( currentFeature.attribute( uniqueIdField ).toString(), currentFeature.id() );
652 QMultiMap<QString, QgsFeatureId>::const_iterator jt = map.constBegin();
654 while ( jt != map.constEnd() )
656 QString currentKey = jt.key();
657 int processedFeatures = 0;
660 if ( onlySelectedFeatures )
666 p->setMaximum( selection.size() );
668 while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
670 if ( p && p->wasCanceled() )
674 if ( selection.contains( jt.value() ) )
678 p->setValue( processedFeatures );
689 dissolveFeature( currentFeature, processedFeatures, &dissolveGeometry );
701 p->setMaximum( featureCount );
703 while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
707 p->setValue( processedFeatures );
710 if ( p && p->wasCanceled() )
722 dissolveFeature( currentFeature, processedFeatures, &dissolveGeometry );
728 vWriter.addFeature( outputFeature );
733 void QgsGeometryAnalyzer::dissolveFeature(
QgsFeature& f,
int nProcessedFeatures,
QgsGeometry** dissolveGeometry )
737 if ( !featureGeometry )
742 if ( nProcessedFeatures == 0 )
744 size_t geomSize = featureGeometry->
wkbSize();
746 unsigned char* wkb =
new unsigned char[geomSize];
747 memcpy( wkb, featureGeometry->
asWkb(), geomSize );
748 ( *dissolveGeometry )->fromWkb( wkb, geomSize );
752 *dissolveGeometry = ( *dissolveGeometry )->
combine( featureGeometry );
757 bool onlySelectedFeatures,
bool dissolve,
int bufferDistanceField, QProgressDialog* p )
782 if ( onlySelectedFeatures )
788 p->setMaximum( selection.size() );
791 int processedFeatures = 0;
792 QgsFeatureIds::const_iterator it = selection.constBegin();
793 for ( ; it != selection.constEnd(); ++it )
797 p->setValue( processedFeatures );
800 if ( p && p->wasCanceled() )
808 bufferFeature( currentFeature, processedFeatures, &vWriter, dissolve, &dissolveGeometry, bufferDistance, bufferDistanceField );
814 p->setValue( selection.size() );
825 p->setMaximum( featureCount );
827 int processedFeatures = 0;
833 p->setValue( processedFeatures );
835 if ( p && p->wasCanceled() )
839 bufferFeature( currentFeature, processedFeatures, &vWriter, dissolve, &dissolveGeometry, bufferDistance, bufferDistanceField );
844 p->setValue( featureCount );
851 if ( !dissolveGeometry )
853 QgsDebugMsg(
"no dissolved geometry - should not happen" );
857 vWriter.addFeature( dissolveFeature );
863 QgsGeometry** dissolveGeometry,
double bufferDistance,
int bufferDistanceField )
865 double currentBufferDistance;
870 if ( !featureGeometry )
876 if ( bufferDistanceField == -1 )
878 currentBufferDistance = bufferDistance;
882 currentBufferDistance = f.
attribute( bufferDistanceField ).toDouble();
884 bufferGeometry = featureGeometry->
buffer( currentBufferDistance, 5 );
888 if ( nProcessedFeatures == 0 )
890 *dissolveGeometry = bufferGeometry;
894 tmpGeometry = *dissolveGeometry;
895 *dissolveGeometry = ( *dissolveGeometry )->
combine( bufferGeometry );
897 delete bufferGeometry;
915 const QString& outputFormat,
int locationField1,
int locationField2,
int offsetField,
double offsetScale,
918 if ( !lineLayer || !eventLayer || !lineLayer->
isValid() || !eventLayer->
isValid() )
924 QMultiHash< QString, QgsFeature > lineLayerIdMap;
929 lineLayerIdMap.insert( fet.
attribute( lineField ).toString(), fet );
935 if ( !memoryProvider )
938 if ( locationField2 == -1 )
950 &( lineLayer->
crs() ),
961 double measure1, measure2 = 0.0;
964 int featureCounter = 0;
965 int nOutputFeatures = 0;
968 p->setWindowModality( Qt::WindowModal );
970 p->setMaximum( nEventFeatures );
981 if ( p->wasCanceled() )
985 p->setValue( featureCounter );
989 measure1 = fet.
attribute( locationField1 ).toDouble();
990 if ( locationField2 != -1 )
992 measure2 = fet.
attribute( locationField2 ).toDouble();
999 QList<QgsFeature> featureIdList = lineLayerIdMap.values( fet.
attribute( eventField ).toString() );
1000 QList<QgsFeature>::const_iterator featureIdIt = featureIdList.constBegin();
1001 for ( ; featureIdIt != featureIdList.constEnd(); ++featureIdIt )
1003 if ( locationField2 == -1 )
1015 addEventLayerFeature( fet, lrsGeom, featureIdIt->geometry(), fileWriter, memoryProviderFeatures, offsetField, offsetScale, forceSingleGeometry );
1018 if ( nOutputFeatures < 1 )
1020 unlocatedFeatureIds.insert( fet.
id() );
1026 p->setValue( nEventFeatures );
1029 if ( memoryProvider )
1031 memoryProvider->
addFeatures( memoryProviderFeatures );
1038 int offsetField,
double offsetScale,
bool forceSingleType )
1045 QList<QgsGeometry*> geomList;
1046 if ( forceSingleType )
1052 geomList.push_back( geom );
1055 QList<QgsGeometry*>::iterator geomIt = geomList.begin();
1056 for ( ; geomIt != geomList.end(); ++geomIt )
1059 if ( offsetField >= 0 )
1061 double offsetVal = feature.
attribute( offsetField ).toDouble();
1062 offsetVal *= offsetScale;
1063 if ( !createOffsetGeometry( *geomIt, lineGeom, offsetVal ) )
1077 memoryFeatures << feature;
1081 if ( forceSingleType )
1087 bool QgsGeometryAnalyzer::createOffsetGeometry(
QgsGeometry* geom,
QgsGeometry* lineGeom,
double offset )
1089 if ( !geom || !lineGeom )
1094 QList<QgsGeometry*> inputGeomList;
1102 inputGeomList.push_back( geom );
1105 QList<GEOSGeometry*> outputGeomList;
1106 QList<QgsGeometry*>::const_iterator inputGeomIt = inputGeomList.constBegin();
1108 for ( ; inputGeomIt != inputGeomList.constEnd(); ++inputGeomIt )
1113 #if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
1114 ((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3)))
1115 GEOSGeometry* offsetGeom = GEOSOffsetCurve_r( geosctxt, ( *inputGeomIt )->asGeos(), -offset, 8 , 0 , 5.0 );
1116 if ( !offsetGeom || !GEOSisValid_r( geosctxt, offsetGeom ) )
1120 if ( !GEOSisValid_r( geosctxt, offsetGeom ) || GEOSGeomTypeId_r( geosctxt, offsetGeom ) != GEOS_LINESTRING || GEOSGeomGetNumPoints_r( geosctxt, offsetGeom ) < 1 )
1122 GEOSGeom_destroy_r( geosctxt, offsetGeom );
1125 outputGeomList.push_back( offsetGeom );
1127 outputGeomList.push_back( GEOSGeom_clone_r( geosctxt, ( *inputGeomIt )->asGeos() ) );
1132 QgsPoint p = ( *inputGeomIt )->asPoint();
1133 p = createPointOffset( p.
x(), p.
y(), offset, lineGeom );
1134 GEOSCoordSequence* ptSeq = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
1135 GEOSCoordSeq_setX_r( geosctxt, ptSeq, 0, p.
x() );
1136 GEOSCoordSeq_setY_r( geosctxt, ptSeq, 0, p.
y() );
1137 GEOSGeometry* geosPt = GEOSGeom_createPoint_r( geosctxt, ptSeq );
1138 outputGeomList.push_back( geosPt );
1144 GEOSGeometry* outputGeom = outputGeomList.at( 0 );
1152 GEOSGeometry** geomArray =
new GEOSGeometry*[outputGeomList.size()];
1153 for (
int i = 0; i < outputGeomList.size(); ++i )
1155 geomArray[i] = outputGeomList.at( i );
1157 GEOSGeometry* collection = 0;
1160 collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTIPOINT, geomArray, outputGeomList.size() );
1164 collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTILINESTRING, geomArray, outputGeomList.size() );
1172 QgsPoint QgsGeometryAnalyzer::createPointOffset(
double x,
double y,
double dist,
QgsGeometry* lineGeom )
const
1179 int beforeVertexNr = afterVertexNr - 1;
1184 double dx = afterVertex.
x() - beforeVertex.
x();
1185 double dy = afterVertex.
y() - beforeVertex.
y();
1186 double normalX = -dy;
1187 double normalY = dx;
1188 double normalLength = sqrt( normalX * normalX + normalY * normalY );
1189 normalX *= ( dist / normalLength );
1190 normalY *= ( dist / normalLength );
1192 double debugLength = sqrt( normalX * normalX + normalY * normalY );
1193 Q_UNUSED( debugLength );
1194 return QgsPoint( x - normalX, y - normalY );
1207 const unsigned char* lineWkb = lineGeom->
asWkb();
1209 const unsigned char* ptr = lineWkb + 1;
1211 memcpy( &wkbType, ptr,
sizeof( wkbType ) );
1212 ptr +=
sizeof( wkbType );
1221 locateBetweenWkbString( ptr, resultGeom, fromMeasure, toMeasure );
1225 int* nLines = (
int* )ptr;
1226 ptr +=
sizeof( int );
1227 for (
int i = 0; i < *nLines; ++i )
1229 ptr += ( 1 +
sizeof( wkbType ) );
1230 ptr = locateBetweenWkbString( ptr, resultGeom, fromMeasure, toMeasure );
1234 if ( resultGeom.size() < 1 )
1251 const unsigned char* lineWkb = lineGeom->
asWkb();
1253 const unsigned char* ptr = lineWkb + 1;
1255 memcpy( &wkbType, ptr,
sizeof( wkbType ) );
1256 ptr +=
sizeof( wkbType );
1265 locateAlongWkbString( ptr, resultGeom, measure );
1269 int* nLines = (
int* )ptr;
1270 ptr +=
sizeof( int );
1271 for (
int i = 0; i < *nLines; ++i )
1273 ptr += ( 1 +
sizeof( wkbType ) );
1274 ptr = locateAlongWkbString( ptr, resultGeom, measure );
1278 if ( resultGeom.size() < 1 )
1285 const unsigned char* QgsGeometryAnalyzer::locateBetweenWkbString(
const unsigned char* ptr,
QgsMultiPolyline& result,
double fromMeasure,
double toMeasure )
1287 int* nPoints = (
int* ) ptr;
1288 ptr +=
sizeof( int );
1289 double prevx = 0.0, prevy = 0.0, prevz = 0.0;
1294 bool measureInSegment;
1295 bool secondPointClipped;
1298 for (
int i = 0; i < *nPoints; ++i )
1301 ptr +=
sizeof( double );
1303 ptr +=
sizeof( double );
1304 z = (
double* ) ptr;
1305 ptr +=
sizeof( double );
1309 measureInSegment = clipSegmentByRange( prevx, prevy, prevz, *x, *y, *z, fromMeasure, toMeasure, pt1, pt2, secondPointClipped );
1310 if ( measureInSegment )
1312 if ( currentLine.size() < 1 )
1314 currentLine.append( pt1 );
1319 currentLine.append( pt2 );
1322 if ( secondPointClipped || i == *nPoints - 1 )
1324 if ( currentLine.size() > 1 )
1326 result.append( currentLine );
1328 currentLine.clear();
1332 prevx = *x; prevy = *y; prevz = *z;
1337 const unsigned char* QgsGeometryAnalyzer::locateAlongWkbString(
const unsigned char* ptr,
QgsMultiPoint& result,
double measure )
1339 int* nPoints = (
int* ) ptr;
1340 ptr +=
sizeof( int );
1341 double prevx = 0.0, prevy = 0.0, prevz = 0.0;
1347 for (
int i = 0; i < *nPoints; ++i )
1350 ptr +=
sizeof( double );
1352 ptr +=
sizeof( double );
1353 z = (
double* ) ptr;
1354 ptr +=
sizeof( double );
1358 locateAlongSegment( prevx, prevy, prevz, *x, *y, *z, measure, pt1Ok, pt1, pt2Ok, pt2 );
1361 result.append( pt1 );
1363 if ( pt2Ok && ( i == ( *nPoints - 1 ) ) )
1365 result.append( pt2 );
1368 prevx = *x; prevy = *y; prevz = *z;
1373 bool QgsGeometryAnalyzer::clipSegmentByRange(
double x1,
double y1,
double m1,
double x2,
double y2,
double m2,
double range1,
double range2,
QgsPoint& pt1,
1374 QgsPoint& pt2,
bool& secondPointClipped )
1376 bool reversed = m1 > m2;
1396 if ( range1 > range2 )
1404 if ( m2 < range1 || m1 > range2 )
1410 if ( m2 <= range2 && m1 >= range1 )
1422 secondPointClipped =
false;
1427 if ( m1 >= range1 && m1 <= range2 )
1430 double dist = ( range2 - m1 ) / ( m2 - m1 );
1431 pt2.
setX( x1 + ( x2 - x1 ) * dist );
1432 pt2.
setY( y1 + ( y2 - y1 ) * dist );
1433 secondPointClipped = !reversed;
1437 if ( m2 >= range1 && m2 <= range2 )
1440 double dist = ( m2 - range1 ) / ( m2 - m1 );
1441 pt1.
setX( x2 - ( x2 - x1 ) * dist );
1442 pt1.
setY( y2 - ( y2 - y1 ) * dist );
1443 secondPointClipped = reversed;
1447 if ( range1 >= m1 && range2 <= m2 )
1449 double dist1 = ( range1 - m1 ) / ( m2 - m1 );
1450 double dist2 = ( range2 - m1 ) / ( m2 - m1 );
1451 pt1.
setX( x1 + ( x2 - x1 ) * dist1 );
1452 pt1.
setY( y1 + ( y2 - y1 ) * dist1 );
1453 pt2.
setX( x1 + ( x2 - x1 ) * dist2 );
1454 pt2.
setY( y1 + ( y2 - y1 ) * dist2 );
1455 secondPointClipped =
true;
1468 void QgsGeometryAnalyzer::locateAlongSegment(
double x1,
double y1,
double m1,
double x2,
double y2,
double m2,
double measure,
bool& pt1Ok,
QgsPoint& pt1,
bool& pt2Ok,
QgsPoint& pt2 )
1470 bool reversed =
false;
1473 double tolerance = 0.000001;
1484 if (( m1 - measure ) > tolerance || ( measure - m2 ) > tolerance )
1522 if ( pt1Ok || pt2Ok )
1535 double dist = ( measure - m1 ) / ( m2 - m1 );
1541 pt1.
setX( x1 + dist * ( x2 - x1 ) );
1542 pt1.
setY( y1 + dist * ( y2 - y1 ) );