Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix crashes due to geometry pointers in QgsGeometryAnalyzer; Add QgsO…
…verlayAnalyzer to analysis library (currently only supports intersections)

git-svn-id: http://svn.osgeo.org/qgis/trunk@12040 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
cfarmer committed Nov 8, 2009
1 parent 3c81073 commit c1b360b
Show file tree
Hide file tree
Showing 5 changed files with 441 additions and 48 deletions.
1 change: 1 addition & 0 deletions python/analysis/analysis.sip
Expand Up @@ -8,4 +8,5 @@
%Import core/core.sip

%Include qgsgeometryanalyzer.sip
%Include qgsoverlayanalyzer.sip

4 changes: 3 additions & 1 deletion src/analysis/CMakeLists.txt
Expand Up @@ -31,6 +31,7 @@ SET(QGIS_ANALYSIS_SRCS
raster/qgstotalcurvaturefilter.cpp
vector/qgsgeometryanalyzer.cpp
vector/qgszonalstatistics.cpp
vector/qgsoverlayanalyzer.cpp
)

SET(QGIS_ANALYSIS_MOC_HDRS
Expand All @@ -43,6 +44,7 @@ INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/../core/
${CMAKE_CURRENT_SOURCE_DIR}/../core/renderer
${CMAKE_CURRENT_SOURCE_DIR}/../core/spatialindex
interpolation
${PROJ_INCLUDE_DIR}
${GEOS_INCLUDE_DIR}
Expand Down Expand Up @@ -99,7 +101,7 @@ INSTALL(TARGETS qgis_analysis

# Added by Tim to install headers

SET(QGIS_ANALYSIS_HDRS vector/qgsgeometryanalyzer.h vector/qgszonalstatistics.h
SET(QGIS_ANALYSIS_HDRS vector/qgsgeometryanalyzer.h vector/qgszonalstatistics.h vector/qgsgeometryanalyzer.h
)

INSTALL(CODE "MESSAGE(\"Installing ANALYSIS headers...\")")
Expand Down
175 changes: 128 additions & 47 deletions src/analysis/vector/qgsgeometryanalyzer.cpp
Expand Up @@ -329,6 +329,7 @@ bool QgsGeometryAnalyzer::extent( QgsVectorLayer* layer, const QString& shapefil
QList<double> QgsGeometryAnalyzer::simpleMeasure( QgsGeometry* mpGeometry )
{
QList<double> list;
double perim;
if ( mpGeometry->wkbType() == QGis::WKBPoint )
{
QgsPoint pt = mpGeometry->asPoint();
Expand All @@ -341,11 +342,11 @@ QList<double> QgsGeometryAnalyzer::simpleMeasure( QgsGeometry* mpGeometry )
list.append( measure.measure( mpGeometry ) );
if ( mpGeometry->type() == QGis::Polygon )
{
list.append( perimeterMeasure( mpGeometry, measure ) );
perim = perimeterMeasure( mpGeometry, measure );
list.append( perim );
}
}
return list;

}

double QgsGeometryAnalyzer::perimeterMeasure( QgsGeometry* geometry, QgsDistanceArea& measure )
Expand Down Expand Up @@ -383,51 +384,90 @@ bool QgsGeometryAnalyzer::convexHull( QgsVectorLayer* layer, const QString& shap
{
return false;
}

QgsVectorDataProvider* dp = layer->dataProvider();
if ( !dp )
{
return false;
}
bool useField = false;
if ( uniqueIdField == -1 )
{
uniqueIdField = 0;
}
else
{
useField = true;
}
QgsFieldMap fields;
fields.insert( 0 , QgsField( QString( "UID" ), QVariant::String ) );
fields.insert( 1 , QgsField( QString( "AREA" ), QVariant::Double ) );
fields.insert( 2 , QgsField( QString( "PERIM" ), QVariant::Double ) );

QGis::WkbType outputType = QGis::WKBPolygon;
const QgsCoordinateReferenceSystem crs = layer->srs();

QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs );
QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), fields, outputType, &crs );
QgsFeature currentFeature;
QgsGeometry* dissolveGeometry; //dissolve geometry
QMultiMap<QString, int> map;
bool useField = false;

if ( uniqueIdField == -1 )
if ( onlySelectedFeatures )
{
uniqueIdField = 0;
//use QgsVectorLayer::featureAtId
const QgsFeatureIds selection = layer->selectedFeaturesIds();
QgsFeatureIds::const_iterator it = selection.constBegin();
for ( ; it != selection.constEnd(); ++it )
{
// if ( p )
// {
// p->setValue( processedFeatures );
// }
// if ( p && p->wasCanceled() )
// {
// // break; // it may be better to do something else here?
// return false;
// }
if ( !layer->featureAtId( *it, currentFeature, true, true ) )
{
continue;
}
map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() );
}
}
else
{
useField = true;
layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
while ( layer->nextFeature( currentFeature ) )
{
map.insert( currentFeature.attributeMap()[uniqueIdField].toString(), currentFeature.id() );
// if ( p )
// {
// p->setValue( processedFeatures );
// }
// if ( p && p->wasCanceled() )
// {
// // break; // it may be better to do something else here?
// return false;
// }
map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() );
}
}
QMultiMap<QString, int>::const_iterator jt;
for (jt = map.constBegin(); jt != map.constEnd(); ++jt)

QMultiMap<QString, int>::const_iterator jt = map.constBegin();
while ( jt != map.constEnd() )
{
QString currentKey = jt.key();
int processedFeatures = 0;
//take only selection
if ( onlySelectedFeatures )
{
//use QgsVectorLayer::featureAtId
const QgsFeatureIds selection = layer->selectedFeaturesIds();
const QgsFeatureIds selection = layer->selectedFeaturesIds();
if ( p )
{
p->setMaximum( selection.size() );
p->setMaximum( selection.size() );
}
processedFeatures = 0;
while ( jt != map.end() && ( jt.key() == currentKey || !useField ) )
while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
{
if ( p && p->wasCanceled() )
{
Expand All @@ -437,18 +477,26 @@ bool QgsGeometryAnalyzer::convexHull( QgsVectorLayer* layer, const QString& shap
{
if ( p )
{
p->setValue( processedFeatures );
p->setValue( processedFeatures );
}
if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) )
{
continue;
continue;
}
convexFeature( currentFeature, processedFeatures, &dissolveGeometry );
++processedFeatures;
}
++jt;
}
QList<double> values;
dissolveGeometry = dissolveGeometry->convexHull();
values = simpleMeasure( dissolveGeometry );
QgsAttributeMap attributeMap;
attributeMap.insert( 0 , QVariant( currentKey ) );
attributeMap.insert( 1 , values[ 0 ] );
attributeMap.insert( 2 , values[ 1 ] );
QgsFeature dissolveFeature;
dissolveFeature.setAttributeMap( attributeMap );
dissolveFeature.setGeometry( dissolveGeometry );
vWriter.addFeature( dissolveFeature );
}
Expand All @@ -461,7 +509,7 @@ bool QgsGeometryAnalyzer::convexHull( QgsVectorLayer* layer, const QString& shap
p->setMaximum( featureCount );
}
processedFeatures = 0;
while ( jt != map.end() && ( jt.key() == currentKey || !useField ) )
while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
{
if ( p )
{
Expand All @@ -480,9 +528,19 @@ bool QgsGeometryAnalyzer::convexHull( QgsVectorLayer* layer, const QString& shap
++processedFeatures;
++jt;
}
QgsFeature dissolveFeature;
dissolveFeature.setGeometry( dissolveGeometry );
vWriter.addFeature( dissolveFeature );
QList<double> values;
// QgsGeometry* tmpGeometry = 0;
dissolveGeometry = dissolveGeometry->convexHull();
// values = simpleMeasure( tmpGeometry );
values = simpleMeasure( dissolveGeometry );
QgsAttributeMap attributeMap;
attributeMap.insert( 0 , QVariant( currentKey ) );
attributeMap.insert( 1 , QVariant( values[ 0 ] ) );
attributeMap.insert( 2 , QVariant( values[ 1 ] ) );
QgsFeature dissolveFeature;
dissolveFeature.setAttributeMap( attributeMap );
dissolveFeature.setGeometry( dissolveGeometry );
vWriter.addFeature( dissolveFeature );
}
}
return true;
Expand Down Expand Up @@ -522,51 +580,69 @@ bool QgsGeometryAnalyzer::dissolve( QgsVectorLayer* layer, const QString& shapef
{
return false;
}

QgsVectorDataProvider* dp = layer->dataProvider();
if ( !dp )
{
return false;
}
bool useField = false;
if ( uniqueIdField == -1 )
{
uniqueIdField = 0;
}
else
{
useField = true;
}

QGis::WkbType outputType = dp->geometryType();
const QgsCoordinateReferenceSystem crs = layer->srs();

QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs );
QgsFeature currentFeature;
QgsGeometry* dissolveGeometry; //dissolve geometry
QMultiMap<QString, int> map;
bool useField = false;

if ( uniqueIdField == -1 )
if ( onlySelectedFeatures )
{
uniqueIdField = 0;
//use QgsVectorLayer::featureAtId
const QgsFeatureIds selection = layer->selectedFeaturesIds();
QgsFeatureIds::const_iterator it = selection.constBegin();
for ( ; it != selection.constEnd(); ++it )
{
if ( !layer->featureAtId( *it, currentFeature, true, true ) )
{
continue;
}
map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() );
}
}
else
{
useField = true;
layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
while ( layer->nextFeature( currentFeature ) )
{
map.insert( currentFeature.attributeMap()[uniqueIdField].toString(), currentFeature.id() );
map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() );
}
}
QMultiMap<QString, int>::const_iterator jt;
for (jt = map.constBegin(); jt != map.constEnd(); ++jt)

QgsGeometry* dissolveGeometry; //dissolve geometry
QMultiMap<QString, int>::const_iterator jt = map.constBegin();
QgsFeature outputFeature;
while ( jt != map.constEnd() )
{
QString currentKey = jt.key();
int processedFeatures = 0;
bool first = true;
//take only selection
if ( onlySelectedFeatures )
{
//use QgsVectorLayer::featureAtId
const QgsFeatureIds selection = layer->selectedFeaturesIds();
const QgsFeatureIds selection = layer->selectedFeaturesIds();
if ( p )
{
p->setMaximum( selection.size() );
p->setMaximum( selection.size() );
}
processedFeatures = 0;
while ( jt != map.end() && ( jt.key() == currentKey || !useField ) )
while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
{
if ( p && p->wasCanceled() )
{
Expand All @@ -576,20 +652,22 @@ bool QgsGeometryAnalyzer::dissolve( QgsVectorLayer* layer, const QString& shapef
{
if ( p )
{
p->setValue( processedFeatures );
p->setValue( processedFeatures );
}
if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) )
{
continue;
continue;
}
if ( first )
{
outputFeature.setAttributeMap( currentFeature.attributeMap() );
first = false;
}
dissolveFeature( currentFeature, processedFeatures, &dissolveGeometry );
++processedFeatures;
}
++jt;
}
QgsFeature dissolveFeature;
dissolveFeature.setGeometry( dissolveGeometry );
vWriter.addFeature( dissolveFeature );
}
//take all features
else
Expand All @@ -599,8 +677,7 @@ bool QgsGeometryAnalyzer::dissolve( QgsVectorLayer* layer, const QString& shapef
{
p->setMaximum( featureCount );
}
processedFeatures = 0;
while ( jt != map.end() && ( jt.key() == currentKey || !useField ) )
while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
{
if ( p )
{
Expand All @@ -615,22 +692,24 @@ bool QgsGeometryAnalyzer::dissolve( QgsVectorLayer* layer, const QString& shapef
{
continue;
}
{
outputFeature.setAttributeMap( currentFeature.attributeMap() );
first = false;
}
dissolveFeature( currentFeature, processedFeatures, &dissolveGeometry );
++processedFeatures;
++jt;
}
QgsFeature dissolveFeature;
dissolveFeature.setGeometry( dissolveGeometry );
vWriter.addFeature( dissolveFeature );
}
outputFeature.setGeometry( dissolveGeometry );
vWriter.addFeature( outputFeature );
}
return true;
}

void QgsGeometryAnalyzer::dissolveFeature( QgsFeature& f, int nProcessedFeatures, QgsGeometry** dissolveGeometry )
{
QgsGeometry* featureGeometry = f.geometry();
QgsGeometry* tmpGeometry = 0;

if ( !featureGeometry )
{
Expand All @@ -639,13 +718,15 @@ void QgsGeometryAnalyzer::dissolveFeature( QgsFeature& f, int nProcessedFeatures

if ( nProcessedFeatures == 0 )
{
*dissolveGeometry = featureGeometry;
int geomSize = featureGeometry->wkbSize();
*dissolveGeometry = new QgsGeometry();
unsigned char* wkb = new unsigned char[geomSize];
memcpy(wkb, featureGeometry->asWkb(), geomSize);
(*dissolveGeometry)->fromWkb(wkb, geomSize);
}
else
{
tmpGeometry = *dissolveGeometry;
*dissolveGeometry = ( *dissolveGeometry )->combine( featureGeometry );
delete tmpGeometry;
}
}

Expand Down

0 comments on commit c1b360b

Please sign in to comment.