Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
305 KeyOz 1
/*
2
*
3
* This file is part of QMapControl,
4
* an open-source cross-platform map widget
5
*
6
* Copyright (C) 2007 - 2008 Kai Winter
7
*
8
* This program is free software: you can redistribute it and/or modify
9
* it under the terms of the GNU Lesser General Public License as published by
10
* the Free Software Foundation, either version 3 of the License, or
11
* (at your option) any later version.
12
*
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
* GNU Lesser General Public License for more details.
17
*
18
* You should have received a copy of the GNU Lesser General Public License
19
* along with QMapControl. If not, see <http://www.gnu.org/licenses/>.
20
*
21
* Contact e-mail: kaiwinter@gmx.de
22
* Program URL   : http://qmapcontrol.sourceforge.net/
23
*
24
*/
25
 
26
#include "layer.h"
27
namespace qmapcontrol
28
{
29
    Layer::Layer(QString layername, MapAdapter* mapadapter, enum LayerType layertype, bool takeevents)
30
        :visible(true), mylayername(layername), mylayertype(layertype), mapAdapter(mapadapter), takeevents(takeevents), myoffscreenViewport(QRect(0,0,0,0))
31
    {
32
        //qDebug() << "creating new Layer: " << layername << ", type: " << contents;
33
        //qDebug() << this->layertype;
34
    }
35
 
36
    Layer::~Layer()
37
    {
38
        delete mapAdapter;
39
    }
40
 
41
    void Layer::setSize(QSize size)
42
    {
43
        this->size = size;
44
        screenmiddle = QPoint(size.width()/2, size.height()/2);
45
        //QMatrix mat;
46
        //mat.translate(480/2, 640/2);
47
        //mat.rotate(45);
48
        //mat.translate(-480/2,-640/2);
49
        //screenmiddle = mat.map(screenmiddle);
50
    }
51
 
52
    QString Layer::layername() const
53
    {
54
        return mylayername;
55
    }
56
 
57
    const MapAdapter* Layer::mapadapter() const
58
    {
59
        return mapAdapter;
60
    }
61
 
62
    void Layer::setVisible(bool visible)
63
    {
64
        this->visible = visible;
65
        emit(updateRequest());
66
    }
67
 
68
    void Layer::addGeometry(Geometry* geom)
69
    {
70
        //qDebug() << geom->getName() << ", " << geom->getPoints().at(0)->getWidget();
71
 
72
        geometries.append(geom);
73
        emit(updateRequest(geom->boundingBox()));
74
        //a geometry can request a redraw, e.g. when its position has been changed
75
        connect(geom, SIGNAL(updateRequest(QRectF)),
76
                this, SIGNAL(updateRequest(QRectF)));
77
    }
78
    void Layer::removeGeometry(Geometry* geometry)
79
    {
80
        for (int i=0; i<geometries.count(); i++)
81
        {
82
            if (geometry == geometries.at(i))
83
            {
84
                disconnect(geometry);
85
                geometries.removeAt(i);
86
                //delete geometry;
87
            }
88
        }
89
    }
90
 
91
    void Layer::clearGeometries()
92
    {
93
        foreach(Geometry *geometry, geometries){
94
            disconnect(geometry);
95
        }
96
        geometries.clear();
97
    }
98
 
99
    bool Layer::isVisible() const
100
    {
101
        return visible;
102
    }
103
    void Layer::zoomIn() const
104
    {
105
        mapAdapter->zoom_in();
106
    }
107
    void Layer::zoomOut() const
108
    {
109
        mapAdapter->zoom_out();
110
    }
111
 
112
    void Layer::mouseEvent(const QMouseEvent* evnt, const QPoint mapmiddle_px)
113
    {
114
        if (takesMouseEvents())
115
        {
116
            if (evnt->button() == Qt::LeftButton && evnt->type() == QEvent::MouseButtonPress)
117
            {
118
                // check for collision
119
                QPointF c = mapAdapter->displayToCoordinate(QPoint(evnt->x()-screenmiddle.x()+mapmiddle_px.x(),
120
                                                                   evnt->y()-screenmiddle.y()+mapmiddle_px.y()));
121
                Point* tmppoint = new Point(c.x(), c.y());
122
                for (int i=0; i<geometries.count(); i++)
123
                {
124
                    if (geometries.at(i)->isVisible() && geometries.at(i)->Touches(tmppoint, mapAdapter))
125
 
126
                        //if (geometries.at(i)->Touches(c, mapAdapter))
127
                    {
128
                        emit(geometryClicked(geometries.at(i), QPoint(evnt->x(), evnt->y())));
129
                    }
130
                }
131
                delete tmppoint;
132
            }
133
        }
134
    }
135
 
136
    bool Layer::takesMouseEvents() const
137
    {
138
        return takeevents;
139
    }
140
 
141
    void Layer::drawYourImage(QPainter* painter, const QPoint mapmiddle_px) const
142
    {
143
        if (mylayertype == MapLayer)
144
        {
145
            //qDebug() << ":: " << mapmiddle_px;
146
            //QMatrix mat;
147
            //mat.translate(480/2, 640/2);
148
            //mat.rotate(45);
149
            //mat.translate(-480/2,-640/2);
150
 
151
            //mapmiddle_px = mat.map(mapmiddle_px);
152
            //qDebug() << ":: " << mapmiddle_px;
153
            _draw(painter, mapmiddle_px);
154
        }
155
 
156
        drawYourGeometries(painter, QPoint(mapmiddle_px.x()-screenmiddle.x(), mapmiddle_px.y()-screenmiddle.y()), myoffscreenViewport);
157
    }
158
    void Layer::drawYourGeometries(QPainter* painter, const QPoint mapmiddle_px, QRect viewport) const
159
    {
160
        QPoint offset;
161
        if (mylayertype == MapLayer)
162
            offset = mapmiddle_px;
163
        else
164
            offset = mapmiddle_px-screenmiddle;
165
 
166
        painter->translate(-mapmiddle_px+screenmiddle);
167
        for (int i=0; i<geometries.count(); i++)
168
        {
169
            geometries.at(i)->draw(painter, mapAdapter, viewport, offset);
170
        }
171
        painter->translate(mapmiddle_px-screenmiddle);
172
 
173
    }
174
    void Layer::_draw(QPainter* painter, const QPoint mapmiddle_px) const
175
    {
176
        // screen middle rotieren...
177
 
178
        int tilesize = mapAdapter->tilesize();
179
        int cross_x = int(mapmiddle_px.x())%tilesize; // position on middle tile
180
        int cross_y = int(mapmiddle_px.y())%tilesize;
181
        //qDebug() << screenmiddle << " - " << cross_x << ", " << cross_y;
182
 
183
        // calculate how many surrounding tiles have to be drawn to fill the display
184
        int space_left = screenmiddle.x() - cross_x;
185
        int tiles_left = space_left/tilesize;
186
        if (space_left>0)
187
            tiles_left+=1;
188
 
189
        int space_above = screenmiddle.y() - cross_y;
190
        int tiles_above = space_above/tilesize;
191
        if (space_above>0)
192
            tiles_above+=1;
193
 
194
        int space_right = screenmiddle.x() - (tilesize-cross_x);
195
        int tiles_right = space_right/tilesize;
196
        if (space_right>0)
197
            tiles_right+=1;
198
 
199
        int space_bottom = screenmiddle.y() - (tilesize-cross_y);
200
        int tiles_bottom = space_bottom/tilesize;
201
        if (space_bottom>0)
202
            tiles_bottom+=1;
203
 
204
        //int tiles_displayed = 0;
205
        int mapmiddle_tile_x = mapmiddle_px.x()/tilesize;
206
        int mapmiddle_tile_y = mapmiddle_px.y()/tilesize;
207
 
208
        const QPoint from =     QPoint((-tiles_left+mapmiddle_tile_x)*tilesize, (-tiles_above+mapmiddle_tile_y)*tilesize);
209
        const QPoint to =               QPoint((tiles_right+mapmiddle_tile_x+1)*tilesize, (tiles_bottom+mapmiddle_tile_y+1)*tilesize);
210
 
211
        myoffscreenViewport = QRect(from, to);
212
 
213
        if (mapAdapter->isValid(mapmiddle_tile_x, mapmiddle_tile_y, mapAdapter->currentZoom()))
214
        {
215
            painter->drawPixmap(-cross_x+size.width(),
216
                                -cross_y+size.height(),
217
                                ImageManager::instance()->getImage(mapAdapter->host(), mapAdapter->query(mapmiddle_tile_x, mapmiddle_tile_y, mapAdapter->currentZoom())));
218
        }
219
 
220
        for (int i=-tiles_left+mapmiddle_tile_x; i<=tiles_right+mapmiddle_tile_x; i++)
221
        {
222
            for (int j=-tiles_above+mapmiddle_tile_y; j<=tiles_bottom+mapmiddle_tile_y; j++)
223
            {
224
                // check if image is valid
225
                if (!(i==mapmiddle_tile_x && j==mapmiddle_tile_y))
226
                    if (mapAdapter->isValid(i, j, mapAdapter->currentZoom()))
227
                    {
228
 
229
                    painter->drawPixmap(((i-mapmiddle_tile_x)*tilesize)-cross_x+size.width(),
230
                                        ((j-mapmiddle_tile_y)*tilesize)-cross_y+size.height(),
231
                                        ImageManager::instance()->getImage(mapAdapter->host(), mapAdapter->query(i, j, mapAdapter->currentZoom())));
232
                    //if (QCoreApplication::hasPendingEvents())
233
                    //  QCoreApplication::processEvents();
234
                }
235
            }
236
        }
237
 
238
 
239
        // PREFETCHING
240
        int upper = mapmiddle_tile_y-tiles_above-1;
241
        int right = mapmiddle_tile_x+tiles_right+1;
242
        int left = mapmiddle_tile_x-tiles_right-1;
243
        int lower = mapmiddle_tile_y+tiles_bottom+1;
244
 
245
        int j = upper;
246
        for (int i=left; i<=right; i++)
247
        {
248
            if (mapAdapter->isValid(i, j, mapAdapter->currentZoom()))
249
                ImageManager::instance()->prefetchImage(mapAdapter->host(), mapAdapter->query(i, j, mapAdapter->currentZoom()));
250
        }
251
        j = lower;
252
        for (int i=left; i<=right; i++)
253
        {
254
            if (mapAdapter->isValid(i, j, mapAdapter->currentZoom()))
255
                ImageManager::instance()->prefetchImage(mapAdapter->host(), mapAdapter->query(i, j, mapAdapter->currentZoom()));
256
        }
257
        int i = left;
258
        for (int j=upper+1; j<=lower-1; j++)
259
        {
260
            if (mapAdapter->isValid(i, j, mapAdapter->currentZoom()))
261
                ImageManager::instance()->prefetchImage(mapAdapter->host(), mapAdapter->query(i, j, mapAdapter->currentZoom()));
262
        }
263
        i = right;
264
        for (int j=upper+1; j<=lower-1; j++)
265
        {
266
            if (mapAdapter->isValid(i, j, mapAdapter->currentZoom()))
267
                ImageManager::instance()->prefetchImage(mapAdapter->host(), mapAdapter->query(i, j, mapAdapter->currentZoom()));
268
        }
269
    }
270
 
271
    QRect Layer::offscreenViewport() const
272
    {
273
        return myoffscreenViewport;
274
    }
275
 
276
    void Layer::moveWidgets(const QPoint mapmiddle_px) const
277
    {
278
        for (int i=0; i<geometries.count(); i++)
279
        {
280
            const Geometry* geom = geometries.at(i);
281
            if (geom->GeometryType == "Point")
282
            {
283
                if (((Point*)geom)->widget()!=0)
284
                {
285
                    QPoint topleft_relative = QPoint(mapmiddle_px-screenmiddle);
286
                    ((Point*)geom)->drawWidget(mapAdapter, topleft_relative);
287
                }
288
            }
289
        }
290
    }
291
    Layer::LayerType Layer::layertype() const
292
    {
293
        return mylayertype;
294
    }
295
 
296
    void Layer::setMapAdapter(MapAdapter* mapadapter)
297
    {
298
 
299
        mapAdapter = mapadapter;
300
    }
301
}