深圳做網(wǎng)站600新聞源發(fā)稿平臺(tái)
前文鏈接:QGraphicsView實(shí)現(xiàn)簡易地圖4『局部加載-地圖漫游』
由于GCJ02 Web 墨卡托投影 緯度并不隨像素等分,且兩極跨度較大,因此本次演示采用的經(jīng)緯網(wǎng)等分邏輯為等分像素。同等像素跨度之間,兩級(jí)緯度變化較小,越靠近赤道附近緯度變化越大。以下將提供實(shí)現(xiàn)此需求的核心代碼。
1、動(dòng)態(tài)演示效果
2、靜態(tài)展示圖片
核心代碼
void MapView::showGraticules()
{// 計(jì)算等分像素后的經(jīng)緯度步長int gridCount = MapUtility::graticulesGridCount(m_curLevel);int mapSideCount = apUtility::mapSideCount(m_curLevel);double perLon = PIXMAP_SIZE * mapSideCount * 1.0 / gridCount;double perLat = perLon;// 計(jì)算呈現(xiàn)的瓦片地圖左上角和右下角的場景坐標(biāo)QPoint topLeftScenePos(m_topLeftTileCoord.x * PIXMAP_SIZE, m_topLeftTileCoord.y * PIXMAP_SIZE);QPoint bottomRightScenePos((m_bottomRightTileCoord.x + 1) * PIXMAP_SIZE, (m_bottomRightTileCoord.y + 1) * PIXMAP_SIZE);// 計(jì)算經(jīng)緯線覆蓋范圍,此處采用的邏輯是經(jīng)緯網(wǎng)覆蓋區(qū)域>=呈現(xiàn)的瓦片地圖區(qū)域int leftGridIndex = qFloor(topLeftScenePos.x() / perLon);int rightGridIndex = qCeil(bottomRightScenePos.x() / perLon);int topGridIndex = qFloor(topLeftScenePos.y() / perLat);int bottomGridIndex = qCeil(bottomRightScenePos.y() / perLat);if (leftGridIndex < 0)leftGridIndex = 0;if (rightGridIndex > gridCount)rightGridIndex = gridCount;if (topGridIndex < 0)topGridIndex = 0;if (bottomGridIndex > gridCount)bottomGridIndex = gridCount;// 視口寬度和高度int vw = viewport()->width();int vh = viewport()->height();// 場景寬度和高度int sw = MapUtility::sceneSize(m_curLevel);int sh = sw;// 視口右下角對應(yīng)場景坐標(biāo)QPointF bottomRightViewToScenePos = mapToScene(viewport()->rect().bottomRight());// 經(jīng)緯網(wǎng)線條顏色、文本顏色QColor gridLineColor(255, 163, 70);QColor textColor(Qt::white);// 繪制經(jīng)緯網(wǎng):緯度線for (int row = topGridIndex; row <= bottomGridIndex; ++row){ // 緯度線double sceneY = row * perLat;QGraphicsLineItem *item = m_scene->addLine(topLeftScenePos.x(), sceneY, bottomRightScenePos.x(), sceneY);item->setPen(QPen(gridLineColor, 1, Qt::DotLine));item->setZValue(50);m_vecGraticulesItems.append(item);// 緯度文本double lat = MapUtility::latFromSceneY(sceneY, m_curLevel);QGraphicsTextItem *textItem = m_scene->addText(CommonUtility::convertToDMSLatSymbol(lat));textItem->setDefaultTextColor(Qt::white);QFont font = textItem->font();font.setFamily("微軟雅黑");textItem->setFont(font);// 調(diào)整文本位置QRectF textBoundingRect = textItem->boundingRect();int sceneX = sw <= vw ? bottomRightScenePos.x() : bottomRightViewToScenePos.x();textItem->setPos(sceneX - textItem->boundingRect().width(), sceneY - textBoundingRect.height() / 2);m_vecGraticulesTextItems.append(textItem);}// 繪制經(jīng)緯網(wǎng):經(jīng)度線for (int col = leftGridIndex; col <= rightGridIndex; ++col){// 經(jīng)度線double sceneX = col * perLon;QGraphicsLineItem *item = m_scene->addLine(sceneX, topLeftScenePos.y(), sceneX, bottomRightScenePos.y());item->setPen(QPen(gridLineColor, 1, Qt::DotLine));item->setZValue(50);m_vecGraticulesItems.append(item);// 經(jīng)度文本double lon = MapUtility::lonFromSceneX(sceneX, m_curLevel);QGraphicsTextItem *textItem = m_scene->addText(CommonUtility::convertToDMSLonSymbol(lon));textItem->setDefaultTextColor(Qt::white);QFont font = textItem->font();font.setFamily("微軟雅黑");textItem->setFont(font);// 調(diào)整文本位置QRectF textBoundingRect = textItem->boundingRect();int sceneY = sh <= vh ? bottomRightScenePos.y() : bottomRightViewToScenePos.y();textItem->setPos(sceneX - textBoundingRect.width() / 2, sceneY - textItem->boundingRect().height());m_vecGraticulesTextItems.append(textItem);}
}
輔助代碼
void CommonUtility::convertToDMS(double value, int &d, int &m, int &s)
{d = (int)(value); m = (int)((value - d) * 60);s = (int)(((value - d) * 60 - m) * 60);// 四舍五入float e = ((value - d) * 60 - m) * 60 - s;if (5 <= (int)(e * 10))s += 1;// 秒進(jìn)位if (60 == s){s = 0;m += 1;}// 分進(jìn)位if (60 == m){m = 0;d += 1;}
}QString CommonUtility::convertToDMS(double value)
{int d, m, s;convertToDMS(value, d, m, s);QString strM = QString::number(m).rightJustified(2, '0');QString strS = QString::number(s).rightJustified(2, '0');return QString("%1°%2′%3″").arg(d).arg(strM).arg(strS);
}QString CommonUtility::convertToDMSLonSymbol(double value)
{return QString("%1%2").arg(convertToDMS(fabs(value))).arg(value > 0 ? "E" : (value != 0 ? "W" : ""));
}QString CommonUtility::convertToDMSLatSymbol(double value)
{return QString("%1%2").arg(convertToDMS(fabs(value))).arg(value > 0 ? "N" : (value != 0 ? "S" : ""));
}