qt 二维地图库_Qt轻量级地图解决方案:基于QtLocation的二次开发(四)
寫在前面
在本系列的上一篇中,我將從《Qt之美1:數(shù)據(jù)指針和私有實現(xiàn)》中的例子抄過來,說明了Qt中源碼中(同時也是QtLcation模塊中)大量存在的D-P機制。這種設(shè)計模式實現(xiàn)了動態(tài)庫的二進制兼容,同時也隱藏了私有成員和潛在的實現(xiàn)細節(jié);除此之外,還能基于它實現(xiàn)另一種Qt中大量采用的技術(shù),即“隱式共享技術(shù)”。
以下關(guān)于“隱式共享技術(shù)”的說明內(nèi)容,大多出自《Qt中的C++技術(shù)》這本書的第8章《隱式共享與d-pointer技術(shù)》。
一般地,一個類型的多個實例所占內(nèi)存是相互獨立的,如果其中某些數(shù)據(jù)成員的取值完全相同,那么這些實例可共享這些數(shù)據(jù)成員,當(dāng)某實例需要修改其中的數(shù)據(jù)成員時才為該對象重新分配內(nèi)存;這種技術(shù)被稱為“隱式共享技術(shù)”,又被形象地描述為“寫時復(fù)制(copy on write)”。如下圖所示,假如對象O1、O2、O3和O4都有部分數(shù)據(jù)成員取值相同,都共享這部分數(shù)據(jù)成員所占用的內(nèi)存A;此后需要修改O4位于共享內(nèi)存A中的某個數(shù)據(jù)成員,此時不能直接修改內(nèi)存A,否則會影響O1、O2和O3的數(shù)據(jù)成員;只好先復(fù)制將內(nèi)存A復(fù)制成B,然后重新分配給O4,在B中修改O4需要修改的數(shù)據(jù)成員。
由于共享內(nèi)存A的存在,假如要析構(gòu)O3時,O1和O2還未析構(gòu),則不能簡單地釋放共享內(nèi)存A,因為這樣做會使O1和O2受到牽連。只有當(dāng)僅存在一個對象引用共享內(nèi)存時,析構(gòu)這個僅存的實例才完全釋放共享內(nèi)存,其他時候僅需要“斷開”析構(gòu)實例與共享內(nèi)存的引用關(guān)系即可。這就需要維護一個共享內(nèi)存的引用計數(shù)器(reference counter),每當(dāng)析構(gòu)了一個引用該塊共享內(nèi)存的對象時,就減少一個引用計數(shù),直到引用計數(shù)為1(即僅存一個引用該內(nèi)存塊的對象)時,下一次再進行減少引用計數(shù)的操作(即析構(gòu)引用該內(nèi)存的對象)才會完全釋放這塊內(nèi)存。
剛才我們講了同一類型不同實例之間實現(xiàn)隱式共享的基本原理,但這并不適用于所有應(yīng)用場景。其實,Qt已經(jīng)在“隱式共享技術(shù)”上為我們做了很多基礎(chǔ)性和示范性工作,其提供了一個名為QSharedData的共享數(shù)據(jù)類型,還提供了QSharedDataPointer等共享數(shù)據(jù)類的指針,利用QSharedData和QSharedDataPointer等類型就可以實現(xiàn)隱式共享的進階操作,比如同一基類不同子類之間的隱式共享。
了解QGeoShape為基類的地理數(shù)據(jù)類型
這里以QtPositioning中QGeoShape類型體系的源碼作為示例,QGeoShape是所有地理形狀類型的基類,其繼承者們包括:QGeoRectangle、QGeoCircle、QGeoPath和QGeoPolygon。QGeoShape類似于 Simple Feature標準 中的Geometry類型,但QGeoShape坐標點都是QGeoCoordinate類型,只能表示經(jīng)緯高坐標。
QGeoShape的源碼如下:
class QGeoRectangle;
class QGeoShapePrivate;
class Q_POSITIONING_EXPORT QGeoShape
{
Q_GADGET
Q_PROPERTY(ShapeType type READ type)
Q_PROPERTY(bool isValid READ isValid)
Q_PROPERTY(bool isEmpty READ isEmpty)
Q_ENUMS(ShapeType)
public:
QGeoShape();
QGeoShape(const QGeoShape &other);
~QGeoShape();
enum ShapeType {
UnknownType,
RectangleType,
CircleType,
PathType,
PolygonType
};
ShapeType type() const;
bool isValid() const;
bool isEmpty() const;
Q_INVOKABLE bool contains(const QGeoCoordinate &coordinate) const;
Q_INVOKABLE QGeoRectangle boundingGeoRectangle() const;
Q_INVOKABLE QGeoCoordinate center() const;
Q_INVOKABLE void extendShape(const QGeoCoordinate &coordinate);
bool operator==(const QGeoShape &other) const;
bool operator!=(const QGeoShape &other) const;
QGeoShape &operator=(const QGeoShape &other);
Q_INVOKABLE QString toString() const;
protected:
QGeoShape(QGeoShapePrivate *d);
QSharedDataPointer d_ptr;
private:
inline QGeoShapePrivate *d_func();
inline const QGeoShapePrivate *d_func() const;
};
其給出了私有共享數(shù)據(jù)類型QGeoShapePrivate的前向聲明:
class QGeoShapePrivate : public QSharedData
{
public:
explicit QGeoShapePrivate(QGeoShape::ShapeType type);
virtual ~QGeoShapePrivate();
virtual bool isValid() const = 0;
virtual bool isEmpty() const = 0;
virtual bool contains(const QGeoCoordinate &coordinate) const = 0;
virtual QGeoCoordinate center() const = 0;
virtual QGeoRectangle boundingGeoRectangle() const = 0;
virtual void extendShape(const QGeoCoordinate &coordinate) = 0;
virtual QGeoShapePrivate *clone() const = 0;
virtual bool operator==(const QGeoShapePrivate &other) const;
QGeoShape::ShapeType type;
};
本來QGeoShapePrivate應(yīng)該是QGeoShape的具體實現(xiàn),但是由于QGeoShape被定義為抽象基類,QGeoShapePrivate中的接口都被定義為純虛函數(shù),實際上QGeoShape接口都是在其子類對應(yīng)的私有數(shù)據(jù)類型中具體實現(xiàn)的,比如QGeoRectanglePrivate(繼承自QGeoShapePrivate):
class QGeoRectanglePrivate : public QGeoShapePrivate
{
public:
QGeoRectanglePrivate();
QGeoRectanglePrivate(const QGeoCoordinate &topLeft, const QGeoCoordinate &bottomRight);
QGeoRectanglePrivate(const QGeoRectanglePrivate &other);
~QGeoRectanglePrivate();
bool isValid() const override;
bool isEmpty() const override;
bool contains(const QGeoCoordinate &coordinate) const override;
QGeoCoordinate center() const override;
QGeoRectangle boundingGeoRectangle() const override;
void extendShape(const QGeoCoordinate &coordinate) override;
QGeoShapePrivate *clone() const override;
bool operator==(const QGeoShapePrivate &other) const override;
QGeoCoordinate topLeft;
QGeoCoordinate bottomRight;
};
QGeoShape及其子類是地圖要素的幾何數(shù)據(jù)的主要表達形式。前端的MapPolyline、MapRectangle、MapCircle和MapPolygon等地圖元素(MapItem),其宿主對象是由后端Qt提供的QDeclarativePolylineMapItem、QDeclarativeRectangleMapItem、QDeclarativeCircleMapItem和QDeclarativePolygonMapItem等類型,它們的地理幾何數(shù)據(jù)(geoShape方法)就分別由QGeoPath、QGeoRectangle、QGeoCircle和QGeoPolygon的實例表示。
下面以QDeclarativeRectangleMapItem源碼為例:
class Q_LOCATION_PRIVATE_EXPORT QDeclarativeRectangleMapItem: public QDeclarativeGeoMapItemBase
{
Q_OBJECT
Q_PROPERTY(QGeoCoordinate topLeft READ topLeft WRITE setTopLeft NOTIFY topLeftChanged)
Q_PROPERTY(QGeoCoordinate bottomRight READ bottomRight WRITE setBottomRight NOTIFY bottomRightChanged)
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
Q_PROPERTY(QDeclarativeMapLineProperties *border READ border CONSTANT)
public:
explicit QDeclarativeRectangleMapItem(QQuickItem *parent = 0);
~QDeclarativeRectangleMapItem();
virtual void setMap(QDeclarativeGeoMap *quickMap, QGeoMap *map) override;
//from QuickItem
virtual QSGNode *updateMapItemPaintNode(QSGNode *, UpdatePaintNodeData *) override;
QGeoCoordinate topLeft();
void setTopLeft(const QGeoCoordinate ¢er);
QGeoCoordinate bottomRight();
void setBottomRight(const QGeoCoordinate ¢er);
QColor color() const;
void setColor(const QColor &color);
QDeclarativeMapLineProperties *border();
bool contains(const QPointF &point) const override;
const QGeoShape &geoShape() const override;
QGeoMap::ItemType itemType() const override;
Q_SIGNALS:
void topLeftChanged(const QGeoCoordinate &topLeft);
void bottomRightChanged(const QGeoCoordinate &bottomRight);
void colorChanged(const QColor &color);
protected:
void updatePath();
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
void updatePolish() override;
protected Q_SLOTS:
void markSourceDirtyAndUpdate();
virtual void afterViewportChanged(const QGeoMapViewportChangeEvent &event) override;
private:
QGeoRectangle rectangle_;
QDeclarativeMapLineProperties border_;
QColor color_;
bool dirtyMaterial_;
QGeoMapPolygonGeometry geometry_;
QGeoMapPolylineGeometry borderGeometry_;
bool updatingGeometry_;
QList pathMercator_;
};
總結(jié)
以上是生活随笔為你收集整理的qt 二维地图库_Qt轻量级地图解决方案:基于QtLocation的二次开发(四)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [项目管理-22]:项目中开环、闭环、安
- 下一篇: OkHttp用法详解