From 749390f2e429f1f19b2da761cb14db0b110f5b3f Mon Sep 17 00:00:00 2001 From: mhugent Date: Thu, 14 May 2009 15:58:24 +0000 Subject: [PATCH] Change in overlay classes such that pal object and geos geometry don't appear in the public interfaces (important for python bindings) git-svn-id: http://svn.osgeo.org/qgis/trunk@10791 c8812cc2-4d05-0410-92ff-de0c093fc19c --- python/core/conversions.sip | 79 +++++++++++++++++++ python/core/core.sip | 2 + python/core/qgsoverlayobject.sip | 51 ++++-------- python/core/qgsvectoroverlay.sip | 29 ++----- src/core/CMakeLists.txt | 1 + src/core/qgsoverlayobject.h | 12 +-- src/core/qgsoverlayobjectpositionmanager.h | 3 +- src/core/qgspalgeometry.cpp | 46 +++++++++++ src/core/qgspalgeometry.h | 49 ++++++++++++ src/core/qgspalobjectpositionmanager.cpp | 37 +++++++-- src/core/qgspalobjectpositionmanager.h | 6 ++ src/core/qgsvectorlayer.cpp | 8 ++ .../diagram_overlay/qgsdiagramoverlay.cpp | 5 ++ 13 files changed, 259 insertions(+), 69 deletions(-) create mode 100644 src/core/qgspalgeometry.cpp create mode 100644 src/core/qgspalgeometry.h diff --git a/python/core/conversions.sip b/python/core/conversions.sip index 4adf07f68a9..cfbfe801ae0 100644 --- a/python/core/conversions.sip +++ b/python/core/conversions.sip @@ -9,6 +9,7 @@ which are not wrapped by PyQt: - QMap - QMap - QMultiMap +- QMap* */ %ModuleHeaderCode @@ -21,6 +22,7 @@ typedef int Py_ssize_t; %End + template %MappedType QVector< QVector > { @@ -737,3 +739,80 @@ template return sipGetState(sipTransferObj); %End }; + +%MappedType QMap +{ +%TypeHeaderCode +#include +%End + +%ConvertFromTypeCode + +//convert map to a python dictionary + PyObject *d; + + if ((d = PyDict_New()) == NULL) + return NULL; + + for (QMap::iterator it = sipCpp->begin(); it != sipCpp->end(); ++it) + { + QgsOverlayObject* oobj = new QgsOverlayObject(*it.value()); + + PyObject* keyobj = PyInt_FromLong(it.key()); + PyObject* pyOobj = sipConvertFromInstance(oobj, sipClass_QgsOverlayObject, sipTransferObj); + PyDict_SetItem(d, keyobj, pyOobj); + + if(pyOobj == NULL || keyobj == NULL || PyDict_SetItem(d, keyobj, pyOobj) < 0) + { + Py_DECREF(d); + + if (pyOobj) + { + Py_DECREF(pyOobj); + } + + if (keyobj) + { + Py_DECREF(keyobj); + } + return NULL; + } + Py_DECREF(pyOobj); + Py_DECREF(keyobj); + } + return d; + +%End +%ConvertToTypeCode + PyObject *t1obj, *t2obj; +#if PY_VERSION_HEX >= 0x02050000 + Py_ssize_t i = 0; +#else + int i = 0; +#endif + + QMap *qm = new QMap; + + while (PyDict_Next(sipPy, &i, &t1obj, &t2obj)) + { + int state; + int t1 = (int)(PyFloat_AsDouble(t1obj)); + QgsOverlayObject* t2 = reinterpret_cast(sipConvertToInstance(t2obj, sipClass_QgsOverlayObject, sipTransferObj, SIP_NOT_NONE, &state, sipIsErr)); + + if (*sipIsErr) + { + sipReleaseInstance(t2, sipClass_QgsOverlayObject, state); + delete qm; + return 0; + } + + qm->insert(t1, t2); + + sipReleaseInstance(t2, sipClass_QgsOverlayObject, state); + } + + *sipCppPtr = qm; + + return sipGetState(sipTransferObj); +%End +}; diff --git a/python/core/core.sip b/python/core/core.sip index bb605724231..2e798ca8435 100644 --- a/python/core/core.sip +++ b/python/core/core.sip @@ -42,6 +42,7 @@ %Include qgsmaptopixel.sip %Include qgsmarkercatalogue.sip %Include qgsmessageoutput.sip +%Include qgsoverlayobject.sip %Include qgspoint.sip %Include qgsproject.sip %Include qgsprovidermetadata.sip @@ -70,4 +71,5 @@ %Include qgsvectordataprovider.sip %Include qgsvectorfilewriter.sip %Include qgsvectorlayer.sip +%Include qgsvectoroverlay.sip diff --git a/python/core/qgsoverlayobject.sip b/python/core/qgsoverlayobject.sip index 298b6b7a4a6..55e75d52b03 100644 --- a/python/core/qgsoverlayobject.sip +++ b/python/core/qgsoverlayobject.sip @@ -1,56 +1,39 @@ -class CORE_EXPORT QgsOverlayObject: public pal::PalGeometry +class QgsOverlayObject { %TypeHeaderCode #include "qgsoverlayobject.h" %End - public: + public: QgsOverlayObject( int width = 0, int height = 0, double rotation = 0, QgsGeometry* geometry = 0 ); virtual ~QgsOverlayObject(); //copy constructor and assignment operator necessary because of mGeometry QgsOverlayObject( const QgsOverlayObject& other ); - QgsOverlayObject& operator=( const QgsOverlayObject& other ); + //this function fill not be wrapped to not depend on geos python bindings /**Returns the feature geometry in geos format. The calling function does _not_ take - ownership of the generated object*/ - GEOSGeometry* getGeosGeometry(); - /**Feature geometry is released when object is destructed so this function is empty*/ - void releaseGeosGeometry( GEOSGeometry *the_geom ) {} + ownership of the generated object. The geometry is in map coordinates + @note: this function is deprecated. Please use geometry() and QgsGeometry::asGeos instead*/ + //GEOSGeometry* getGeosGeometry(); + /**Feature geometry is released when object is destructed so this function is empty. This function is deprecated and does nothing*/ + //void releaseGeosGeometry( GEOSGeometry *the_geom ) //getters - int width() const {return mWidth;} - int height() const {return mHeight;} - double rotation() const {return mRotation;} - QgsGeometry* geometry() {return mGeometry;} - const QgsGeometry* geometry() const {return mGeometry;} + int width() const; + int height() const; + double rotation() const; + QgsGeometry* geometry(); + //const QgsGeometry* geometry() const; QgsPoint position() const; - QList positions() const {return mPositions;} + QList positions() const; //setters - void setHeight( int height ) {mHeight = height;} - void setWidth( int width ) {mWidth = width;} - void setRotation( double rotation ) {mRotation = rotation;} + void setHeight( int height ); + void setWidth( int width ); + void setRotation( double rotation ); /**Set geometry. This class takes ownership of the object*/ void setGeometry( QgsGeometry* g ); /**Adds a position in map coordinates*/ void addPosition( const QgsPoint& position ); - - - private: - - /**Width of the bounding box in pixels*/ - int mWidth; - /**Height of the bounding box in pixels*/ - int mHeight; - /**Position of the object in map coordinates. Note that it is possible that an object - has several positions, e.g. a multiobject or an object that is split into multiple parts - by the edge of the view extent*/ - QList mPositions; - /**Rotation of the object*/ - double mRotation; - /**Copy of the feature geometry. A copy is necessary because in QGIS geometries are deleted - after drawing*/ - QgsGeometry* mGeometry; - }; diff --git a/python/core/qgsvectoroverlay.sip b/python/core/qgsvectoroverlay.sip index 87176cd9ee1..409c15671a8 100644 --- a/python/core/qgsvectoroverlay.sip +++ b/python/core/qgsvectoroverlay.sip @@ -1,4 +1,4 @@ -class CORE_EXPORT QgsVectorOverlay +class QgsVectorOverlay { %TypeHeaderCode #include "qgsvectoroverlay.h" @@ -7,7 +7,7 @@ class CORE_EXPORT QgsVectorOverlay QgsVectorOverlay( QgsVectorLayer* vl ); virtual ~QgsVectorOverlay(); - /**Create the overlay objects contained in a view extent. Subclasses need to implement this method and assign width/height information to the overlay ovbjects*/ + /**Create the overlay objects contained in a view extent. Subclasses need to implement this method and assign width/height information to the overlay objects*/ virtual void createOverlayObjects( const QgsRenderContext& renderContext ) = 0; @@ -18,39 +18,22 @@ class CORE_EXPORT QgsVectorOverlay virtual void drawOverlayObjects( QgsRenderContext& context ) const = 0; /**Gives direct access to oberlay objects*/ - QMap* overlayObjects() {return &mOverlayObjects;} + QMap* overlayObjects(); /**Describes the overlay type (e.g. "diagram" or "label")*/ virtual QString typeName() const = 0; /**Set attribute indices necessary to fetch*/ - void setAttributes( const QgsAttributeList& list ) {mAttributes = list;} + void setAttributes( const QList& list ); - bool displayFlag() const {return mDisplayFlag;} + bool displayFlag() const; /**Display yes/no*/ - void setDisplayFlag( bool flag ) {mDisplayFlag = flag;} + void setDisplayFlag( bool flag ); /**Restore from project file*/ virtual bool readXML( const QDomNode& overlayNode ) = 0; /**Save to project file*/ virtual bool writeXML( QDomNode& layer_node, QDomDocument& doc ) const = 0; - - protected: - /**Pointer to the vector layer for this overlay*/ - QgsVectorLayer* mVectorLayer; - - /**True if overlay should be displayed*/ - bool mDisplayFlag; - - /**A list with attribute indexes that are needed for overlay rendering*/ - QgsAttributeList mAttributes; - - /**Key: feature ids, value: the corresponding overlay objects. Normally, they are created for each redraw and deleted before the next redraw*/ - QMap mOverlayObjects; - - /**Position constraints that may be set to be persistent after redraws. Key is the feature id, value the map point - where the feature should be placed*/ - QMap mPositionConstraints; }; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index db77395a14e..96646a53722 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -27,6 +27,7 @@ SET(QGIS_CORE_SRCS qgsmaptopixel.cpp qgsmessageoutput.cpp qgsoverlayobject.cpp + qgspalgeometry.cpp qgspalobjectpositionmanager.cpp qgspoint.cpp qgsproject.cpp diff --git a/src/core/qgsoverlayobject.h b/src/core/qgsoverlayobject.h index de41f10db76..767756e29c8 100644 --- a/src/core/qgsoverlayobject.h +++ b/src/core/qgsoverlayobject.h @@ -18,8 +18,8 @@ #ifndef QGSOVERLAYOBJECT_H #define QGSOVERLAYOBJECT_H +#include "qgsgeometry.h" #include "qgspoint.h" -#include "palgeometry.h" #include class QgsGeometry; @@ -29,7 +29,7 @@ class QgsGeometry; * to calculate object placement * \note This class has been added in version 1.1 */ -class CORE_EXPORT QgsOverlayObject: public pal::PalGeometry +class CORE_EXPORT QgsOverlayObject { public: QgsOverlayObject( int width = 0, int height = 0, double rotation = 0, QgsGeometry* geometry = 0 ); @@ -41,9 +41,10 @@ class CORE_EXPORT QgsOverlayObject: public pal::PalGeometry /**Returns the feature geometry in geos format. The calling function does _not_ take - ownership of the generated object. The geometry is in map coordinates*/ + ownership of the generated object. The geometry is in map coordinates + @note: this function is deprecated. Please use geometry() and QgsGeometry::asGeos instead*/ GEOSGeometry* getGeosGeometry(); - /**Feature geometry is released when object is destructed so this function is empty*/ + /**Feature geometry is released when object is destructed so this function is empty. This function is deprecated and does nothing*/ void releaseGeosGeometry( GEOSGeometry *the_geom ) {} //getters @@ -73,7 +74,8 @@ class CORE_EXPORT QgsOverlayObject: public pal::PalGeometry int mHeight; /**Position of the object in map coordinates. Note that it is possible that an object has several positions, e.g. a multiobject or an object that is split into multiple parts - by the edge of the view extent*/ + by the edge of the view extent. It is also possible that there is no position (e.g. geometry too small). In + that case*/ QList mPositions; /**Rotation of the object*/ double mRotation; diff --git a/src/core/qgsoverlayobjectpositionmanager.h b/src/core/qgsoverlayobjectpositionmanager.h index ba18445d388..ca9e6291f80 100644 --- a/src/core/qgsoverlayobjectpositionmanager.h +++ b/src/core/qgsoverlayobjectpositionmanager.h @@ -31,7 +31,8 @@ class QgsVectorOverlay; class QgsOverlayObjectPositionManager { public: - + //virtual destructor needed for proper memory management + virtual ~QgsOverlayObjectPositionManager(){} /**Adds a layer that may contain * overlays to the position manager. The overlay objects contained in the overlays will then be considered in label placement*/ virtual void addLayer( QgsVectorLayer* vl, QList& overlays ) = 0; diff --git a/src/core/qgspalgeometry.cpp b/src/core/qgspalgeometry.cpp new file mode 100644 index 00000000000..f1cd6fe2173 --- /dev/null +++ b/src/core/qgspalgeometry.cpp @@ -0,0 +1,46 @@ +/*************************************************************************** + qgspalgeometry.cpp - description + --------------------------------- + begin : May 2009 + copyright : (C) 2009 by Marco Hugentobler + email : marco dot hugentobler at karto dot baug dot ethz dot ch +***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgspalgeometry.h" +#include "qgsgeometry.h" +#include "qgsoverlayobject.h" +#include + +QgsPALGeometry::QgsPALGeometry(QgsOverlayObject* op): mOverlayObjectPtr(op) +{ +} + +QgsPALGeometry::QgsPALGeometry(): mOverlayObjectPtr(0) +{ +} + +QgsPALGeometry::~QgsPALGeometry() +{ +} + +GEOSGeometry* QgsPALGeometry::getGeosGeometry() +{ + if(mOverlayObjectPtr) + { + if(mOverlayObjectPtr->geometry()) + { + return mOverlayObjectPtr->geometry()->asGeos(); + } + } + return 0; +} + diff --git a/src/core/qgspalgeometry.h b/src/core/qgspalgeometry.h new file mode 100644 index 00000000000..57706291164 --- /dev/null +++ b/src/core/qgspalgeometry.h @@ -0,0 +1,49 @@ +/*************************************************************************** + qgspalgeometry.h + ---------------- + begin : May 2009 + copyright : (C) 2009 by Marco Hugentobler + email : marco dot hugentobler at karto dot baug dot ethz dot ch +***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSPALGEOMETRY_H +#define QGSPALGEOMETRY_H + +#include "palgeometry.h" + +class QgsOverlayObject; + + +/**A class to make the QGIS geometries known to the PAL library (PAL works on geos geometry). The main purpose of this class is to remove the visibility of PAL and geos classes in the python interface*/ +class CORE_EXPORT QgsPALGeometry: public pal::PalGeometry +{ + public: + /**Constructor that takes the geometry representation as geos object. \ + Note that the class does not take ownership*/ + QgsPALGeometry(QgsOverlayObject* op); + ~QgsPALGeometry(); + + //methods inherited from PalGeometry + GEOSGeometry* getGeosGeometry(); + void releaseGeosGeometry( GEOSGeometry *the_geom ){} + + /**Returns pointer to the overlay object this geometry referrs to. Don't delete the returned object!*/ + QgsOverlayObject* overlayObjectPtr() const {return mOverlayObjectPtr;} + + private: + /**Default constructor forbidden*/ + QgsPALGeometry(); + /**Pointer to the related overlay object*/ + QgsOverlayObject* mOverlayObjectPtr; +}; + +#endif // QGSPALGEOMETRY_H diff --git a/src/core/qgspalobjectpositionmanager.cpp b/src/core/qgspalobjectpositionmanager.cpp index 65d07676b57..2a151a2fa5a 100644 --- a/src/core/qgspalobjectpositionmanager.cpp +++ b/src/core/qgspalobjectpositionmanager.cpp @@ -16,6 +16,8 @@ ***************************************************************************/ #include "qgspalobjectpositionmanager.h" +#include "qgsgeometry.h" +#include "qgspalgeometry.h" #include "qgsoverlayobject.h" #include "qgsrendercontext.h" #include "qgsvectorlayer.h" @@ -31,7 +33,7 @@ QgsPALObjectPositionManager::QgsPALObjectPositionManager(): mNumberOfLayers( 0 ) QgsPALObjectPositionManager::~QgsPALObjectPositionManager() { - + deletePALGeometries(); } void QgsPALObjectPositionManager::addLayer( QgsVectorLayer* vl, QList& overlays ) @@ -85,7 +87,10 @@ void QgsPALObjectPositionManager::addLayer( QgsVectorLayer* vl, QList::const_iterator objectIt = positionObjects->begin(); for ( ; objectIt != positionObjects->end(); ++objectIt ) { - positionLayer->registerFeature( strdup( QString::number( objectNr ).toAscii().data() ), objectIt.value(), objectIt.value()->width(), objectIt.value()->height() ); + QgsPALGeometry* palGeom = new QgsPALGeometry(objectIt.value()); + mPALGeometries.push_back(palGeom); //insert object into list to delete memory later + char* featureLabel = QString::number( objectNr ).toAscii().data(); + positionLayer->registerFeature(featureLabel, palGeom, objectIt.value()->width(), objectIt.value()->height() ); ++objectNr; } } @@ -135,13 +140,20 @@ void QgsPALObjectPositionManager::findObjectPositions( const QgsRenderContext& r return; } - QgsOverlayObject* currentOverlayObject = 0; + //pal geometry that the current label object refers to + QgsPALGeometry* referredGeometry = 0; + QgsOverlayObject* referredOverlayObject = 0; std::list::iterator labelIt = resultLabelList->begin(); for ( ; labelIt != resultLabelList->end(); ++labelIt ) { - currentOverlayObject = dynamic_cast(( *labelIt )->getGeometry() ); - if ( !currentOverlayObject ) + referredGeometry = dynamic_cast(( *labelIt )->getGeometry() ); + if ( !referredGeometry) + { + continue; + } + referredOverlayObject = referredGeometry->overlayObjectPtr(); + if(!referredOverlayObject) { continue; } @@ -149,8 +161,11 @@ void QgsPALObjectPositionManager::findObjectPositions( const QgsRenderContext& r //QGIS takes the coordinates of the middle points double x = (( *labelIt )->getX( 0 ) + ( *labelIt )->getX( 1 ) + ( *labelIt )->getX( 2 ) + ( *labelIt )->getX( 3 ) ) / 4; double y = (( *labelIt )->getY( 0 ) + ( *labelIt )->getY( 1 ) + ( *labelIt )->getY( 2 ) + ( *labelIt )->getY( 3 ) ) / 4; - currentOverlayObject->addPosition( QgsPoint( x, y ) ); + referredOverlayObject->addPosition( QgsPoint( x, y ) ); } + + //release memory for QgsPALGeometries + deletePALGeometries(); } void QgsPALObjectPositionManager::removeLayers() @@ -196,3 +211,13 @@ void QgsPALObjectPositionManager::setPlacementAlgorithm( const QString& algorith mPositionEngine.setSearch( pal::CHAIN ); } } + +void QgsPALObjectPositionManager::deletePALGeometries() +{ + QList::iterator geomIt = mPALGeometries.begin(); + for(; geomIt != mPALGeometries.end(); ++geomIt) + { + delete (*geomIt); + } + mPALGeometries.clear(); +} diff --git a/src/core/qgspalobjectpositionmanager.h b/src/core/qgspalobjectpositionmanager.h index 4ccbb4778a8..fc6c35d16c6 100644 --- a/src/core/qgspalobjectpositionmanager.h +++ b/src/core/qgspalobjectpositionmanager.h @@ -21,6 +21,8 @@ #include "qgsoverlayobjectpositionmanager.h" #include "pal.h" +class QgsPALGeometry; + /**A class that uses the PAL library for overlay object placement * \note This class has been added in version 1.1 */ @@ -40,5 +42,9 @@ class QgsPALObjectPositionManager: public QgsOverlayObjectPositionManager private: pal::Pal mPositionEngine; int mNumberOfLayers; + /**Internal storage of the pal geometries between addLayer and findObjectPositions operations*/ + QList mPALGeometries; + + void deletePALGeometries(); }; #endif diff --git a/src/core/qgsvectorlayer.cpp b/src/core/qgsvectorlayer.cpp index 062ee16ac92..596394093bf 100644 --- a/src/core/qgsvectorlayer.cpp +++ b/src/core/qgsvectorlayer.cpp @@ -168,6 +168,14 @@ QgsVectorLayer::~QgsVectorLayer() deleteCachedGeometries(); delete mActions; + + //delete remaining overlays + + QList::iterator overlayIt = mOverlays.begin(); + for(; overlayIt != mOverlays.end(); ++overlayIt) + { + delete (*overlayIt); + } } QString QgsVectorLayer::storageType() const diff --git a/src/plugins/diagram_overlay/qgsdiagramoverlay.cpp b/src/plugins/diagram_overlay/qgsdiagramoverlay.cpp index d9300014a0d..1f76bb7d352 100644 --- a/src/plugins/diagram_overlay/qgsdiagramoverlay.cpp +++ b/src/plugins/diagram_overlay/qgsdiagramoverlay.cpp @@ -41,6 +41,11 @@ QgsDiagramOverlay::QgsDiagramOverlay( QgsVectorLayer* vl ): QgsVectorOverlay( vl QgsDiagramOverlay::~QgsDiagramOverlay() { + //memory cleanup + for ( QMap::iterator it = mOverlayObjects.begin(); it != mOverlayObjects.end(); ++it ) + { + delete it.value(); + } delete mDiagramRenderer; }