QGraphicsView coordinate system
I´ve been reading about QGraphicsView/Scene/Item all day and still I fail to understand how it works. I started with QT Creator and added a QGraphicsView to the mainWindow. Then I subclassed QGraphicsScene and QGraphicsItem(I probably need to subclass the QGraphicsView later on). I use shapelib to open a shape-file and If I´ve done it right it will be implemented as a QGraphicsItem. I add the item to the scene and the scene to the view. I can see the map(shapefile) but it´s centered and very small. So I thought let´s change the coordinatesystem of the scene... And this is where I got stuck.
I know the boundaries of the GraphicsView and the Scene. I also know the boundaries of the shapefile. Why can´t I tell the scene to have the same boundaries as the shapefile but extend it to the size of the view!?
Maybe it isn´t hard but obviously I don´t have the brains for it so any help at all will be very appreciated.
Code for subclassed QGraphicsItem
Code:
{
}
QRectF item
::boundingRect() const {
recWindow.
setBottomLeft(QPointF(sBoundingBox.
minX,sBoundingBox.
minY));
recWindow.
setBottomRight(QPointF(sBoundingBox.
maxX, sBoundingBox.
minY));
recWindow.
setTopLeft(QPointF(sBoundingBox.
minX,sBoundingBox.
maxY));
recWindow.
setTopRight(QPointF(sBoundingBox.
maxX,sBoundingBox.
maxY));
return recWindow;
}
{
OpenShapeFile("./Maps/Norden_wgs84.shp");
painter
->setRenderHint
(QPainter::Antialiasing);
painter->setBrush(Qt::blue);
for(int i = 0;i< vMap.size(); i++)
{
painter->drawPolyline(vMap.at(i)->p.data() ,vMap.at(i)->p.size());
}
}
I´m not really doing anything in the subclassed QGraphicsScene yet so I don´t think there is any reason to show the code.
And here is the mainWindow
Code:
IceChart3
::IceChart3(QWidget *parent
){
ui.setupUi(this);
sceneRect.
setBottomLeft(QPoint(4,
52));
sceneRect.
setBottomRight(QPoint(42,
52));
sceneRect.
setTopLeft(QPoint(4,
72));
sceneRect.
setTopRight(QPoint(42,
72));
scene = new MyScene(this);
scene->setSceneRect(sceneRect);
itemMap = new item();
scene->addItem(itemMap);
//Flip upside down.
ui.graphicsView->scale(1,-1);
//Set scene to view
ui.graphicsView->setScene(scene);
Re: QGraphicsView coordinate system
Re: QGraphicsView coordinate system
Hmm I tried it like this and it does nothing I'm afraid. Probably I'm not doing it right?
Code:
MainWindow
::MainWindow(QWidget *parent
) : ui(new Ui::MainWindow)
{
ui->setupUi(this);
recWindow.
setBottomLeft(QPointF(4.,52.
));
recWindow.
setBottomRight(QPointF(42., 52.
));
recWindow.
setTopLeft(QPointF(4.,72.
));
recWindow.
setTopRight(QPointF(42.,72.
));
scene = new MyScene(this);
test = new item();
scene->setSceneRect(recWindow);
ui->graphicsView->fitInView(recWindow,Qt::IgnoreAspectRatio);
scene->addItem(test);
ui->graphicsView->setScene(scene);
Re: QGraphicsView coordinate system
I did not try really but this should do the trick.
by the way the rect you define does not seem valid, unless you invert top and bottom (like you scaled view's Y in first post)
Code:
MainWindow
::MainWindow(QWidget *parent
) : ui(new Ui::MainWindow)
{
ui->setupUi(this);
scene = new MyScene(this);
ui->graphicsView->setScene(scene);
test = new item();
scene->addItem(test);
ui->graphicsView->fitInView(scene->itemsBoundingRect());
}
Re: QGraphicsView coordinate system
That didn´t work either I´m afraid. I´ve managed to implement a zoom-function. And for a moment I saw a light in the tunnel actually...But this function only works halfway so to speak. After just a few rolls with the scrollwheel on the mouse everything turns white.
Code:
{
//Get the position of the mouse before scaling, in scene coords
QPointF pointBeforeScale
(ui.
graphicsView->mapToScene
(event
->pos
()));
//Get the original screen centerpoint
QPointF screenCenter
= GetCenter
();
//CurrentCenterPoint; //(visRect.center());
double scaleFactor = 2.15; //How fast we zoom
if(event->delta() > 0)
{
//Zoom in
ui.graphicsView->scale(scaleFactor, scaleFactor);
}
else
{
//Zooming out
ui.graphicsView->scale(1.0 / scaleFactor, 1.0 / scaleFactor);
}
//Get the position after scaling, in scene coords
QPointF pointAfterScale
(ui.
graphicsView->mapToScene
(event
->pos
()));
//Get the offset of how the screen moved
QPointF offset
= pointBeforeScale
- pointAfterScale;
//Adjust to the new center for correct zooming
QPointF newCenter
= screenCenter
+ offset;
SetCenter(newCenter);
}
Thank you totem by the way for taking the time to help me. If I could I´d by you a beer :)
Re: QGraphicsView coordinate system
Quote:
Originally Posted by
roband915
That didn´t work either I´m afraid
What happened then ?
Speaking of zoom method, here is how I usually do :
Code:
{
const qreal zoomStep = 0.25 ;
double zoomFactor = pow( 2.0, e->delta() / 8.0 / 15.0 * zoomStep ) ;
scale(zoomFactor, zoomFactor);
e->setModifiers(Qt::NoModifier) ; // to avoid [CTRL+wheel] behave like QAbstractScrollArea, maybe not useful for everyone
}
Plus, you can choose to zoom on view's center or under cursor using QGraphiscView::transformationAnchor
Re: QGraphicsView coordinate system
Nothing really. The map(QGraphicsItem) is still centered and small.
I tried your zoom method and I still get the same result. After just a few movements with the wheel then the map disappears.
Re: QGraphicsView coordinate system
After adding an item to the scene, the following code should have worked
Code:
ui->graphicsView->fitInView(scene->itemsBoundingRect());
Can you post your graphicsitem's code ? because I don't see were the problem comes from. Something must be wrong, like item's bounding rect or something
Re: QGraphicsView coordinate system
Hmm ok maybe like you said I´m doing something wrong in with the QGraphicsItem.
Here is the .h file
Code:
#ifndef ITEM_H
#define ITEM_H
#include <QGraphicsItem>
#include <QPointF>
#include <QRectF>
#include <QPolygonF>
#include <QPainter>
#include <QPainterPath>
#include <QWidget>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsSceneHoverEvent>
#include <QMessageBox>
#include <shapelib/shapefil.h>
#include <object.h>
{
Q_OBJECT
public:
void OpenShapeFile(char *fileName);
QVector<object*> vMap;
object *map;
private:
typedef struct MyPoint2D
{
double x;
double y;
}MyPoint2D;
std::vector<MyPoint2D> vPoints;
typedef struct MyLineString2D
{
std::vector<MyPoint2D> vPointList;
}MyLineString2D;
//Holds coordinates of Line Shapefile
std::vector<MyLineString2D> vLines;
typedef struct MyPolygon2D
{
std::vector<MyPoint2D> vPointList;
}MyPolygon2D;
//Holds coordinates of Polygon Shapefile
std::vector<MyPolygon2D> vPolygons;
typedef struct SBoundingBox
{
qreal maxX;
qreal maxY;
qreal minX;
qreal minY;
}SBoundingBox;
qreal xMax,yMax,x2Min,y2Min;
//BoundingBox of Shapefile
SBoundingBox sBoundingBox;
};
#endif // ITEM_H
And the .cpp file
Code:
#include "item.h"
{
setAcceptHoverEvents(true);
setFlags
(ItemIsMovable | ItemIsFocusable |
QGraphicsItem::ItemIsSelectable);
}
QRectF item
::boundingRect() const {
recWindow.
setBottomLeft(QPointF(sBoundingBox.
minX,sBoundingBox.
minY));
recWindow.
setBottomRight(QPointF(sBoundingBox.
maxX, sBoundingBox.
minY));
recWindow.
setTopLeft(QPointF(sBoundingBox.
minX,sBoundingBox.
maxY));
recWindow.
setTopRight(QPointF(sBoundingBox.
maxX,sBoundingBox.
maxY));
return recWindow;
}
{
OpenShapeFile("./Maps/Norden_wgs84.shp");
painter
->setRenderHint
(QPainter::Antialiasing);
painter->setBrush(Qt::red);
for(int i = 0;i< vMap.size(); i++)
{
painter->drawPolyline(vMap.at(i)->p.data() ,vMap.at(i)->p.size());
}
}
{
}
{
}
{
}
void item::OpenShapeFile(char *fileName)
{
SHPHandle hSHP = SHPOpen(fileName, "rb");
if(hSHP == NULL)
{
m.setText("Could not open shape.");
m.exec();
}
else
{
//Read boundingbox of shapefile.
sBoundingBox.maxX = hSHP->adBoundsMax[0];
sBoundingBox.maxY = hSHP->adBoundsMax[1];
sBoundingBox.minX = hSHP->adBoundsMin[0];
sBoundingBox.minY = hSHP->adBoundsMin[1];
//Point shape-file
if(hSHP->nShapeType == SHPT_POINT)
{
SHPObject *psShape;
for(int i=0;i<hSHP->nRecords;i++)
{
psShape = SHPReadObject(hSHP, i);
double fX = psShape->padfX[0];
double fY = -psShape->padfY[0];
//Plot these points
MyPoint2D pt;
pt.x = fX;
pt.y = fY;
vPoints.push_back(pt);
}
}
//Line Shapefile
else if(hSHP->nShapeType == SHPT_ARC)
{
SHPObject *psShape;
for(int i=0;i<hSHP->nRecords;i++)
{
psShape = SHPReadObject(hSHP, i);
std::vector<MyPoint2D> tempPointArray;
QVector<QPointF> tempQPointArray;
map = new object();
for(int j=0;j<psShape->nVertices;j++)
{
double fX = psShape->padfX[j];
double fY = psShape->padfY[j];
MyPoint2D pt;
pt.x = fX;
pt.y= fY;
//QT Point
map->addVertices(test);
tempPointArray.push_back(pt);
}
vMap.push_back(map);
MyLineString2D linestring;
linestring.vPointList=tempPointArray;
vLines.push_back(linestring);
}
}
//Polygon Shapefile
if(hSHP->nShapeType == SHPT_POLYGON)
{
SHPObject *psShape;
for(int i=0;i<hSHP->nRecords;i++)
{
psShape = SHPReadObject(hSHP, i);
std::vector<MyPoint2D> tempPointArray;
for(int j=0;j<psShape->nVertices;j++)
{
double fX = psShape->padfX[j];
double fY = psShape->padfY[j];
MyPoint2D pt;
pt.x = fX;
pt.y= fY;
tempPointArray.push_back(pt);
}
MyPolygon2D polygon;
polygon.vPointList = tempPointArray;
vPolygons.push_back(polygon);
}
}
}
}
Re: QGraphicsView coordinate system
Looking your ::boundingRect() method, did you scale view's Y to -1 or not ?
In QGraphicsScene nominal coordinate system, the bottom of a valid QRectF has a greater value than its top, which is not the case in your code (bottom<top).
Try to define your boundingrect as follow : a point in space (x,y) and 2D dimensions (width,height)
Otherwise I don't see what can be wrong for now..
Beside, you define custom structs where using Qt would just be fine : I'm thinking of
MyPolygon2D => QPolygonF
MyPoint2D => QPointF
MyLineString2D => QPainterPath
SBoundingBox => QRectF
Another thing : you read your file and initialize your structs each time you paint your item, which is not good. You could read your file once in constructor, initialize some member and use these members in your paint method. Plus, it seems your OpenShapeFile() contains memory leaks (1 new == 1 delete somewhere in your code)
Re: QGraphicsView coordinate system
Sorry to butt in like this but if your whole shapefile is represented by a single item then that's probably not a very good approach. As for zooming, what you want is to zoom in the view on the item and not zoom in the view on the scene.
Something like:
Code:
ui->graphicsView->setScene(scene);
scene->addItem(test);
ui->graphicsView->fitInView(test->sceneRect(), Qt::KeepAspectRatio);
Re: QGraphicsView coordinate system
I have had a similar thing happen (screen going white / disapearing) when my custom items bounding rect has been wrong. Try just adding a normal QGraphicsLineIteminstead to see if your zooming is ok.
I had good results displaying dwg files by just with a QGraphicsItemGroup and just adding the individual lines, text, path items.
Re: QGraphicsView coordinate system
can you please send me the source folder
Re: QGraphicsView coordinate system
hi all,
I would try if you share me the total source code folder. other way share object.h file and mainwindow.cpp, mainwindow.h,main.cpp.
Thanks & regards,
Swapan
Re: QGraphicsView coordinate system
if possible then share the source for object.h file
Re: QGraphicsView coordinate system
Atlast I solve the problem.........
swapan