| 0,0 → 1,307 |
| /* |
| * |
| * This file is part of QMapControl, |
| * an open-source cross-platform map widget |
| * |
| * Copyright (C) 2007 - 2008 Kai Winter |
| * |
| * This program is free software: you can redistribute it and/or modify |
| * it under the terms of the GNU Lesser General Public License as published by |
| * the Free Software Foundation, either version 3 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public License |
| * along with QMapControl. If not, see <http://www.gnu.org/licenses/>. |
| * |
| * Contact e-mail: kaiwinter@gmx.de |
| * Program URL : http://qmapcontrol.sourceforge.net/ |
| * |
| */ |
| |
| #include "layer.h" |
| namespace qmapcontrol |
| { |
| Layer::Layer(QString layername, MapAdapter* mapadapter, enum LayerType layertype, bool takeevents) |
| :visible(true), mylayername(layername), mylayertype(layertype), mapAdapter(mapadapter), takeevents(takeevents), myoffscreenViewport(QRect(0,0,0,0)) |
| { |
| //qDebug() << "creating new Layer: " << layername << ", type: " << contents; |
| //qDebug() << this->layertype; |
| } |
| |
| Layer::~Layer() |
| { |
| delete mapAdapter; |
| } |
| |
| void Layer::setSize(QSize size) |
| { |
| this->size = size; |
| screenmiddle = QPoint(size.width()/2, size.height()/2); |
| //QMatrix mat; |
| //mat.translate(480/2, 640/2); |
| //mat.rotate(45); |
| //mat.translate(-480/2,-640/2); |
| //screenmiddle = mat.map(screenmiddle); |
| } |
| |
| QString Layer::layername() const |
| { |
| return mylayername; |
| } |
| |
| const MapAdapter* Layer::mapadapter() const |
| { |
| return mapAdapter; |
| } |
| |
| void Layer::setVisible(bool visible) |
| { |
| this->visible = visible; |
| emit(updateRequest()); |
| } |
| |
| void Layer::addGeometry(Geometry* geom) |
| { |
| //qDebug() << geom->getName() << ", " << geom->getPoints().at(0)->getWidget(); |
| |
| geometries.append(geom); |
| emit(updateRequest(geom->boundingBox())); |
| //a geometry can request a redraw, e.g. when its position has been changed |
| connect(geom, SIGNAL(updateRequest(QRectF)), |
| this, SIGNAL(updateRequest(QRectF))); |
| } |
| void Layer::removeGeometry(Geometry* geometry) |
| { |
| for (int i=0; i<geometries.count(); i++) |
| { |
| if (geometry == geometries.at(i)) |
| { |
| disconnect(geometry); |
| geometries.removeAt(i); |
| //delete geometry; |
| } |
| } |
| } |
| |
| void Layer::clearGeometries() |
| { |
| foreach(Geometry *geometry, geometries){ |
| disconnect(geometry); |
| } |
| geometries.clear(); |
| } |
| |
| bool Layer::isVisible() const |
| { |
| return visible; |
| } |
| void Layer::zoomIn() const |
| { |
| mapAdapter->zoom_in(); |
| } |
| void Layer::zoomOut() const |
| { |
| mapAdapter->zoom_out(); |
| } |
| |
| void Layer::mouseEvent(const QMouseEvent* evnt, const QPoint mapmiddle_px) |
| { |
| if (takesMouseEvents()) |
| { |
| if (evnt->button() == Qt::LeftButton && evnt->type() == QEvent::MouseButtonPress) |
| { |
| // check for collision |
| QPointF c = mapAdapter->displayToCoordinate(QPoint(evnt->x()-screenmiddle.x()+mapmiddle_px.x(), |
| evnt->y()-screenmiddle.y()+mapmiddle_px.y())); |
| Point* tmppoint = new Point(c.x(), c.y()); |
| for (int i=0; i<geometries.count(); i++) |
| { |
| if (geometries.at(i)->isVisible() && geometries.at(i)->Touches(tmppoint, mapAdapter)) |
| |
| //if (geometries.at(i)->Touches(c, mapAdapter)) |
| { |
| emit(geometryClicked(geometries.at(i), QPoint(evnt->x(), evnt->y()))); |
| } |
| } |
| delete tmppoint; |
| } |
| } |
| } |
| |
| bool Layer::takesMouseEvents() const |
| { |
| return takeevents; |
| } |
| |
| void Layer::drawYourImage(QPainter* painter, const QPoint mapmiddle_px) const |
| { |
| if (mylayertype == MapLayer) |
| { |
| //qDebug() << ":: " << mapmiddle_px; |
| //QMatrix mat; |
| //mat.translate(480/2, 640/2); |
| //mat.rotate(45); |
| //mat.translate(-480/2,-640/2); |
| |
| //mapmiddle_px = mat.map(mapmiddle_px); |
| //qDebug() << ":: " << mapmiddle_px; |
| _draw(painter, mapmiddle_px); |
| } |
| |
| drawYourGeometries(painter, QPoint(mapmiddle_px.x()-screenmiddle.x(), mapmiddle_px.y()-screenmiddle.y()), myoffscreenViewport); |
| } |
| void Layer::drawYourGeometries(QPainter* painter, const QPoint mapmiddle_px, QRect viewport) const |
| { |
| QPoint offset; |
| if (mylayertype == MapLayer) |
| offset = mapmiddle_px; |
| else |
| offset = mapmiddle_px-screenmiddle; |
| |
| painter->translate(-mapmiddle_px+screenmiddle); |
| for (int i=0; i<geometries.count(); i++) |
| { |
| geometries.at(i)->draw(painter, mapAdapter, viewport, offset); |
| } |
| painter->translate(mapmiddle_px-screenmiddle); |
| |
| } |
| void Layer::_draw(QPainter* painter, const QPoint mapmiddle_px) const |
| { |
| // screen middle rotieren... |
| |
| int tilesize = mapAdapter->tilesize(); |
| int cross_x = int(mapmiddle_px.x())%tilesize; // position on middle tile |
| int cross_y = int(mapmiddle_px.y())%tilesize; |
| //qDebug() << screenmiddle << " - " << cross_x << ", " << cross_y; |
| |
| // calculate how many surrounding tiles have to be drawn to fill the display |
| int space_left = screenmiddle.x() - cross_x; |
| int tiles_left = space_left/tilesize; |
| if (space_left>0) |
| tiles_left+=1; |
| |
| int space_above = screenmiddle.y() - cross_y; |
| int tiles_above = space_above/tilesize; |
| if (space_above>0) |
| tiles_above+=1; |
| |
| int space_right = screenmiddle.x() - (tilesize-cross_x); |
| int tiles_right = space_right/tilesize; |
| if (space_right>0) |
| tiles_right+=1; |
| |
| int space_bottom = screenmiddle.y() - (tilesize-cross_y); |
| int tiles_bottom = space_bottom/tilesize; |
| if (space_bottom>0) |
| tiles_bottom+=1; |
| |
| //int tiles_displayed = 0; |
| int mapmiddle_tile_x = mapmiddle_px.x()/tilesize; |
| int mapmiddle_tile_y = mapmiddle_px.y()/tilesize; |
| |
| const QPoint from = QPoint((-tiles_left+mapmiddle_tile_x)*tilesize, (-tiles_above+mapmiddle_tile_y)*tilesize); |
| const QPoint to = QPoint((tiles_right+mapmiddle_tile_x+1)*tilesize, (tiles_bottom+mapmiddle_tile_y+1)*tilesize); |
| |
| myoffscreenViewport = QRect(from, to); |
| |
| // for the EmptyMapAdapter no tiles should be loaded and painted. |
| if (mapAdapter->host() == "") |
| { |
| return; |
| } |
| |
| if (mapAdapter->isValid(mapmiddle_tile_x, mapmiddle_tile_y, mapAdapter->currentZoom())) |
| { |
| painter->drawPixmap(-cross_x+size.width(), |
| -cross_y+size.height(), |
| ImageManager::instance()->getImage(mapAdapter->host(), mapAdapter->query(mapmiddle_tile_x, mapmiddle_tile_y, mapAdapter->currentZoom()))); |
| } |
| |
| for (int i=-tiles_left+mapmiddle_tile_x; i<=tiles_right+mapmiddle_tile_x; i++) |
| { |
| for (int j=-tiles_above+mapmiddle_tile_y; j<=tiles_bottom+mapmiddle_tile_y; j++) |
| { |
| // check if image is valid |
| if (!(i==mapmiddle_tile_x && j==mapmiddle_tile_y)) |
| if (mapAdapter->isValid(i, j, mapAdapter->currentZoom())) |
| { |
| |
| painter->drawPixmap(((i-mapmiddle_tile_x)*tilesize)-cross_x+size.width(), |
| ((j-mapmiddle_tile_y)*tilesize)-cross_y+size.height(), |
| ImageManager::instance()->getImage(mapAdapter->host(), mapAdapter->query(i, j, mapAdapter->currentZoom()))); |
| //if (QCoreApplication::hasPendingEvents()) |
| // QCoreApplication::processEvents(); |
| } |
| } |
| } |
| |
| |
| // PREFETCHING |
| int upper = mapmiddle_tile_y-tiles_above-1; |
| int right = mapmiddle_tile_x+tiles_right+1; |
| int left = mapmiddle_tile_x-tiles_right-1; |
| int lower = mapmiddle_tile_y+tiles_bottom+1; |
| |
| int j = upper; |
| for (int i=left; i<=right; i++) |
| { |
| if (mapAdapter->isValid(i, j, mapAdapter->currentZoom())) |
| ImageManager::instance()->prefetchImage(mapAdapter->host(), mapAdapter->query(i, j, mapAdapter->currentZoom())); |
| } |
| j = lower; |
| for (int i=left; i<=right; i++) |
| { |
| if (mapAdapter->isValid(i, j, mapAdapter->currentZoom())) |
| ImageManager::instance()->prefetchImage(mapAdapter->host(), mapAdapter->query(i, j, mapAdapter->currentZoom())); |
| } |
| int i = left; |
| for (int j=upper+1; j<=lower-1; j++) |
| { |
| if (mapAdapter->isValid(i, j, mapAdapter->currentZoom())) |
| ImageManager::instance()->prefetchImage(mapAdapter->host(), mapAdapter->query(i, j, mapAdapter->currentZoom())); |
| } |
| i = right; |
| for (int j=upper+1; j<=lower-1; j++) |
| { |
| if (mapAdapter->isValid(i, j, mapAdapter->currentZoom())) |
| ImageManager::instance()->prefetchImage(mapAdapter->host(), mapAdapter->query(i, j, mapAdapter->currentZoom())); |
| } |
| } |
| |
| QRect Layer::offscreenViewport() const |
| { |
| return myoffscreenViewport; |
| } |
| |
| void Layer::moveWidgets(const QPoint mapmiddle_px) const |
| { |
| for (int i=0; i<geometries.count(); i++) |
| { |
| const Geometry* geom = geometries.at(i); |
| if (geom->GeometryType == "Point") |
| { |
| if (((Point*)geom)->widget()!=0) |
| { |
| QPoint topleft_relative = QPoint(mapmiddle_px-screenmiddle); |
| ((Point*)geom)->drawWidget(mapAdapter, topleft_relative); |
| } |
| } |
| } |
| } |
| Layer::LayerType Layer::layertype() const |
| { |
| return mylayertype; |
| } |
| |
| void Layer::setMapAdapter(MapAdapter* mapadapter) |
| { |
| |
| mapAdapter = mapadapter; |
| } |
| } |