From d028a06802ada91492a88e0f86b3222b338a4aaf Mon Sep 17 00:00:00 2001 From: gsherman Date: Fri, 19 Jul 2002 07:57:30 +0000 Subject: [PATCH] initial point and line drawing git-svn-id: http://svn.osgeo.org/qgis/trunk@32 c8812cc2-4d05-0410-92ff-de0c093fc19c --- src/qgisapp.cpp | 8 +++++ src/qgisapp.h | 2 ++ src/qgisappbase.ui | 26 ++++++++++++-- src/qgisappbase.ui.h | 6 ++++ src/qgsdatabaselayer.cpp | 77 +++++++++++++++++++++++++++++++++++++--- src/qgsdatabaselayer.h | 2 +- src/qgsmapcanvas.cpp | 46 ++++++++++++++++++++++-- src/qgsmapcanvas.h | 40 ++++++++++++--------- src/qgsmaplayer.cpp | 10 +++++- src/qgsmaplayer.h | 2 +- src/qgsrect.cpp | 19 +++++++++- src/qgsrect.h | 9 +++++ 12 files changed, 217 insertions(+), 30 deletions(-) diff --git a/src/qgisapp.cpp b/src/qgisapp.cpp index fe9a1d6bb62..ecd7ae6de79 100644 --- a/src/qgisapp.cpp +++ b/src/qgisapp.cpp @@ -31,9 +31,11 @@ #include #include #include +#include "qgsrect.h" #include "qgsmapcanvas.h" #include "qgsdbsourceselect.h" #include "qgsdatabaselayer.h" + #include "qgisapp.h" #include "xpm/qgis.xpm" @@ -95,6 +97,7 @@ QgisApp::addLayer () mapCanvas->addLayer (lyr); // no drawing done -- need to pass the layer collection // to the rendering engine (yet to be written) + ++it; } @@ -247,3 +250,8 @@ QgisApp::drawPoint (double x, double y) paint.drawPoint (x, y); paint.end (); } + +void QgisApp::drawLayers(){ + cout << "In QgisApp::drawLayers()" << endl; + mapCanvas->render(); +} diff --git a/src/qgisapp.h b/src/qgisapp.h index 5812fc5fd1f..6422b3b5f54 100644 --- a/src/qgisapp.h +++ b/src/qgisapp.h @@ -45,6 +45,8 @@ public: void readWKB(const char *, QStringList tables); //! Draw a point on the map canvas void drawPoint(double x, double y); + //! draw layers + void drawLayers(); private: //! Map canvase QgsMapCanvas *mapCanvas; diff --git a/src/qgisappbase.ui b/src/qgisappbase.ui index 1c20d47daa5..f8378f2b70f 100644 --- a/src/qgisappbase.ui +++ b/src/qgisappbase.ui @@ -95,6 +95,7 @@ Toolbar_2 + @@ -173,6 +174,17 @@ Add Layer + + + drawAction + + + image5 + + + Draw + + @@ -190,6 +202,9 @@ 789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade6523232520022630543251d2e253d856405bffcbc54105b19c8563600020b03103711c44d0303b04aac005546593911b74ce2d09151c60089046512a100641a14109419789f522203f6082e19385ba9d69a0b008e2682ef + + 789cc5d3c10ac2300c00d07bbf222cb722dd9c1741fc04c5a3201e4615f430059d0711ffdd2ada364d8a3010c30e813cb2a4b4a586e56206ba54e7aee9f616ecae3981de5cdaf6ba5a4f6faa18d5e0be1a86c54015062ccc8f87ed33479763e5625cbd4a5fa287411f598328a1d8c485388f0ce96f244347202818b60e336917d130c24d98826f9f3f9f8c61bb894622c9398be48f465e8c190191bb81463c23660ced85c4840ac629355177afd064cda7292686c67bfe74e614f91fe6df6998fc47efbdbfb94fd403df21d37e + @@ -222,17 +237,24 @@ QgisAppBase zoomIn() + + drawAction + activated() + QgisAppBase + drawLayers() + qgisappbase.ui.h + addLayer() fileExit() fileOpen() - addLayer() + init() + drawLayers() zoomIn() zoomOut() - init() diff --git a/src/qgisappbase.ui.h b/src/qgisappbase.ui.h index c92f4feb986..f3f576fa544 100644 --- a/src/qgisappbase.ui.h +++ b/src/qgisappbase.ui.h @@ -47,3 +47,9 @@ void QgisAppBase::init() PopupMenu_2->setFont( menubar_font ); */ } + + +void QgisAppBase::drawLayers() +{ + +} \ No newline at end of file diff --git a/src/qgsdatabaselayer.cpp b/src/qgsdatabaselayer.cpp index cf682744728..ec652ceb938 100644 --- a/src/qgsdatabaselayer.cpp +++ b/src/qgsdatabaselayer.cpp @@ -1,4 +1,5 @@ #include +#include #include "qgsrect.h" #include #include @@ -59,7 +60,7 @@ QgsDatabaseLayer::~QgsDatabaseLayer(){ QgsRect QgsDatabaseLayer::calculateExtent(){ return layerExtent; } -void QgsDatabaseLayer::draw(QPainter *p, QgsRect *viewExtent){ +void QgsDatabaseLayer::draw(QPainter *p, QgsRect *viewExtent, int yTransform){ // painter is active (begin has been called /* Steps to draw the layer 1. get the features in the view extent by SQL query @@ -68,16 +69,82 @@ void QgsDatabaseLayer::draw(QPainter *p, QgsRect *viewExtent){ 4. draw */ PgCursor pgs(dataSource, "drawCursor"); - QString sql = "select asbinary(" + geometryColumn + ",'" + endianString() + - "') as features from " + tableName + " where " + geometryColumn + - " && GeometryFromText('BOX3D(" + viewExtent->xMin() + " " + viewExtent->yMin() - + "," + viewExtent->xMax() + " " + viewExtent->yMax() + ")'::box3d,-1)"; + QString sql = "select asbinary(" + geometryColumn + ",'" + endianString(); + sql += "') as features from " + tableName; + sql += " where " + geometryColumn; + sql += " && GeometryFromText('BOX3D(" + viewExtent->stringRep(); + sql += ")'::box3d,-1)"; + qWarning(sql); pgs.Declare((const char *)sql, true); int res = pgs.Fetch(); cout << "Number of matching records: " << pgs.Tuples() << endl; for (int idx = 0; idx < pgs.Tuples (); idx++) { + // allocate memory for the item + char *feature = new char[pgs.GetLength (idx, 0) + 1]; + memset (feature, '\0', pgs.GetLength (idx, 0) + 1); + memcpy (feature, pgs.GetValue (idx, 0), pgs.GetLength (idx, 0)); + wkbType = (int)feature[1]; + cout << "Feature type: " << wkbType << endl; // read each feature based on its type + double *x; + double *y; + int *nPoints; + int numPoints; + int numLineStrings; + int idx,jdx; + char *ptr; + char lsb; + int ttype; + switch(wkbType){ + case WKBPoint: + x = (double *) (feature + 5); + y = (double *) (feature + 5 + sizeof (double)); + p->drawRect ((int) *x, yTransform - (int) *y, 15000, + 15000); + break; + case WKBLineString: + // get number of points in the line + numPoints = (int)(feature + 1 + sizeof(int)); + ptr = feature + 1 + 2 * sizeof(int); + for(idx = 0; idx < numPoints; idx++){ + x = (double *) ptr; + ptr += sizeof(double); + y = (double *) ptr; + ptr += sizeof(double); + if(idx == 0) + p->moveTo((int) *x, yTransform - (int) *y); + else + p->lineTo((int) *x, yTransform - (int) *y); + + } + break; + case WKBMultiLineString: + numLineStrings = (int)(feature[5]); + ptr = feature+9; + for(jdx = 0; jdx < numLineStrings; jdx++){ + // each of these is a wbklinestring so must handle as such + lsb = *ptr; + ptr += 5; // skip type since we know its 2 + nPoints = (int *)ptr; + ptr += sizeof(int); + for(idx = 0; idx < *nPoints; idx++){ + x = (double *) ptr; + ptr += sizeof(double); + y = (double *) ptr; + ptr += sizeof(double); + if(idx == 0) + p->moveTo((int) *x, yTransform - (int) *y); + else + p->lineTo((int) *x, yTransform - (int) *y); + + } + } + break; + case WKBPolygon: + break; + } + } diff --git a/src/qgsdatabaselayer.h b/src/qgsdatabaselayer.h index 6b6bbb7ee8f..377ffd19531 100644 --- a/src/qgsdatabaselayer.h +++ b/src/qgsdatabaselayer.h @@ -38,7 +38,7 @@ class QgsDatabaseLayer : public QgsMapLayer { QgsDatabaseLayer(const char *conninfo=0, QString table=QString::null); //! Destructor ~QgsDatabaseLayer(); - void draw(QPainter *p, QgsRect *viewExtent=0); + virtual void draw(QPainter *, QgsRect *, int ); private: //! Calculates extent of the layer using SQL and PostGIS functions QgsRect calculateExtent(); diff --git a/src/qgsmapcanvas.cpp b/src/qgsmapcanvas.cpp index e73bad70da5..e3d3b1c1430 100644 --- a/src/qgsmapcanvas.cpp +++ b/src/qgsmapcanvas.cpp @@ -15,19 +15,61 @@ * * ***************************************************************************/ #include +#include +#include +#include "qgsrect.h" #include "qgsmaplayer.h" +#include "qgsdatabaselayer.h" #include "qgsmapcanvas.h" QgsMapCanvas::QgsMapCanvas(QWidget *parent, const char *name ) : QWidget(parent,name) { + mapWindow = new QRect(); } QgsMapCanvas::~QgsMapCanvas(){ + delete mapWindow; } void QgsMapCanvas::addLayer(QgsMapLayer *lyr){ - layers[lyr->name()] = *lyr; + layers[lyr->name()] = lyr; + // update extent if warranted + if(layers.size() == 1){ + fullExtent = lyr->extent(); + } // set zpos to something... //lyr->zpos = 0; } void QgsMapCanvas::render(){ + QPainter *paint = new QPainter(); + paint->begin(this); + currentExtent = fullExtent; + mapWindow->setLeft(currentExtent.xMin()); + mapWindow->setBottom(currentExtent.yMin()); + // determine the dominate direction for the mapcanvas + if (width () > height ()) + { + mapWindow->setWidth(currentExtent.width()); + mapWindow->setHeight(currentExtent.width()); + } + else + { + mapWindow->setWidth(currentExtent.height()); + mapWindow->setHeight(currentExtent.height()); + } + paint->setWindow(*mapWindow); + QRect v = paint->viewport (); + int d = QMIN (v.width (), v.height ()); + int dm = QMAX(v.width(), v.height()); + paint->setViewport (v.left () + (v.width () - d) / 2, + v.top () + (v.height () - d) / 2, d, d); + // render all layers in the stack, starting at the base - + map::iterator mi = layers.begin(); + int yTransform = mapWindow->bottom() - abs(mapWindow->height() - currentExtent.height())/2; + while(mi != layers.end()){ + QgsMapLayer *ml = (*mi).second; + // QgsDatabaseLayer *dbl = (QgsDatabaseLayer *)&ml; + ml->draw(paint, ¤tExtent, yTransform); + mi++; + // mi.draw(p, &fullExtent); + } + paint->end(); } diff --git a/src/qgsmapcanvas.h b/src/qgsmapcanvas.h index 9e6d093ce8d..59106d0f45b 100644 --- a/src/qgsmapcanvas.h +++ b/src/qgsmapcanvas.h @@ -4,7 +4,7 @@ begin : Sun Jun 30 2002 copyright : (C) 2002 by Gary E.Sherman email : sherman@mrcc.com - ***************************************************************************/ +***************************************************************************/ /*************************************************************************** * * @@ -19,7 +19,8 @@ #define QGSMAPCANVAS_H #include #include - +#include "qgsrect.h" +class QRect; class QgsMapLayer; /*! \class QgsMapCanvas @@ -27,23 +28,28 @@ class QgsMapLayer; */ class QgsMapCanvas : public QWidget { - Q_OBJECT + Q_OBJECT public: - //! Constructor - QgsMapCanvas(QWidget *parent=0, const char *name=0); - //! Destructor - ~QgsMapCanvas(); - /*! Adds a layer to the map canvas. - * @param lyr Pointer to a layer derived from QgsMapLayer - */ - void addLayer(QgsMapLayer *lyr); - /*! Draw the map using the symbology set for each layer - */ - void render(); -private: + //! Constructor + QgsMapCanvas(QWidget *parent=0, const char *name=0); + //! Destructor + ~QgsMapCanvas(); + /*! Adds a layer to the map canvas. + * @param lyr Pointer to a layer derived from QgsMapLayer + */ + void addLayer(QgsMapLayer *lyr); + /*! Draw the map using the symbology set for each layer + */ + void render(); + private: -//! map containing the layers by name - map layers; + //! map containing the layers by name + maplayers; + //! Full extent of the map canvas + QgsRect fullExtent; + //! Current extent + QgsRect currentExtent; + QRect *mapWindow; }; #endif diff --git a/src/qgsmaplayer.cpp b/src/qgsmaplayer.cpp index 5b93d0fc729..e5d9b4e79c2 100644 --- a/src/qgsmaplayer.cpp +++ b/src/qgsmaplayer.cpp @@ -14,6 +14,7 @@ * (at your option) any later version. * * * ***************************************************************************/ +#include #include "qgsrect.h" #include "qgsmaplayer.h" @@ -37,7 +38,14 @@ void QgsMapLayer::setlayerName( const QString& _newVal){ const QString QgsMapLayer::name(){ return layerName; } +const QgsRect QgsMapLayer::extent(){ + return layerExtent; +} QgsRect QgsMapLayer::calculateExtent(){ + } -void QgsMapLayer::draw(QPainter *, QgsRect *){ +void QgsMapLayer::draw(QPainter *p, QgsRect *viewExtent, int yTransform){ + cout << "In QgsMapLayer::draw" << endl; } + + diff --git a/src/qgsmaplayer.h b/src/qgsmaplayer.h index 1f439b89d01..9ff81618fee 100644 --- a/src/qgsmaplayer.h +++ b/src/qgsmaplayer.h @@ -55,7 +55,7 @@ class QgsMapLayer : public QgsDataSource { * based on the layer type */ virtual QgsRect calculateExtent(); - virtual void draw(QPainter *, QgsRect * = 0); + virtual void draw(QPainter *, QgsRect *, int); /*! Return the extent of the layer as a QRect */ const QgsRect extent(); diff --git a/src/qgsrect.cpp b/src/qgsrect.cpp index d592741a0ff..a8023c315ff 100644 --- a/src/qgsrect.cpp +++ b/src/qgsrect.cpp @@ -1,3 +1,4 @@ +#include #include "qgsrect.h" QgsRect::QgsRect(double minX, double minY, double maxX, double maxY) : xmin(minX), ymin(minY), xmax(maxX), ymax(maxY){ @@ -28,6 +29,12 @@ double QgsRect::yMax() const { double QgsRect::yMin() const { return ymin; } +double QgsRect::width() const{ + return xmax - xmin; +} +double QgsRect::height() const { + return ymax - ymin; +} void QgsRect::normalize(){ double temp; if( xmin > xmax){ @@ -41,7 +48,17 @@ void QgsRect::normalize(){ ymax = temp; } } - +QString QgsRect::stringRep() const{ + QString tmp; + QString rep = tmp.setNum(xmin);; + rep += " "; + rep += tmp.setNum(ymin); + rep += ","; + rep += tmp.setNum(xmax); + rep += " "; + rep += tmp.setNum(ymax); + return rep; +} bool QgsRect::operator==(const QgsRect &r1){ return (r1.xMax() == this->xMax() && r1.xMin() == this->xMin() && r1.yMax() == this->yMax() && r1.yMin() == this->yMin()); diff --git a/src/qgsrect.h b/src/qgsrect.h index f69f4aae946..8440279751e 100644 --- a/src/qgsrect.h +++ b/src/qgsrect.h @@ -1,5 +1,8 @@ #ifndef QGSRECT_H #define QGSRECT_H + +class QString; + /*! \class QgsRect * \brief A rectangle specified with double values. * @@ -30,6 +33,12 @@ class QgsRect{ double yMin() const; //! Normalize the rectangle so it has non-negative width/height void normalize(); + //! Width of the rectangle + double width() const; + //! Height of the rectangle + double height() const; + //! returns string representation of form xmin,ymin xmax,ymax + QString stringRep() const; /*! Comparison operator @return True if rectangles are equal */