//特定位置の道路取得、なしなら NULL Road* MapFrame::getRoadAt(int viewX, int viewY) { Map* pMap = app.getMap(); Road* pRoad; Road* pRoadSelect; MAP_ROADMAP_IT rmi; double distance, distancePrev; pRoad = pMap->nextRoad(&rmi, true); pRoadSelect = NULL; distancePrev = (double)ROADSELECT_MIN; while (pRoad != NULL) { if (app.measureLinePoint(getViewX(pRoad->getIntsec(ROAD_IT_SMALL)->getMapPosX()), getViewY(pRoad->getIntsec(ROAD_IT_SMALL)->getMapPosY()), getViewX(pRoad->getIntsec(ROAD_IT_LARGE)->getMapPosX()), getViewY(pRoad->getIntsec(ROAD_IT_LARGE)->getMapPosY()), viewX, viewY, ROADSELECT_MIN, &distance)) { if (distance < distancePrev) { // qDebug("MapFrame::mouseReleaseEvent road %f-%f", distance, distancePrev); pRoadSelect = pRoad; distancePrev = distance; } } pRoad = pMap->nextRoad(&rmi); } return pRoadSelect; }
//単路削除、なしなら無視 void Map::deleteRoad(int roadId) { MAP_ROADMAP_IT rmi; Road* pRoad; Intsec* pIntsec1; Intsec* pIntsec2; rmi = _roadMap.find(roadId); if (rmi != _roadMap.end()) { pRoad = rmi->second; pIntsec1 = pRoad->getIntsec(ROAD_IT_SMALL); pIntsec2 = pRoad->getIntsec(ROAD_IT_LARGE); // qDebug("Map::deleteRoad %d %d-%d 0x%x", // roadId, pIntsec1->getIntsecId(), pIntsec2->getIntsecId(), pRoad); pIntsec1->deleteRoad(pIntsec2->getIntsecId()); pIntsec2->deleteRoad(pIntsec1->getIntsecId()); delete pRoad; _roadMap.erase(rmi); } // qDebug("Map::deleteRoad end %d", roadId); }
//描画 void MapFrame::paint(QPainter* pp) { Map* pMap = app.getMap(); QRect rectSource, rectDest; double viewBackMagni; MAP_INTSECMAP_IT imi; Intsec* pIntsec; stringstream ss; int viewX, viewY; MAP_ROADMAP_IT rmi; Road* pRoad; DrawLineType drawLineType; //塗りつぶし、ドラッグ画面用 pp->fillRect(0, 0, width(), height(), Qt::gray); //背景描画 if (app.getBackImage() && !_backPixmap.isNull()) { viewBackMagni = app.getBackMagni() * app.getViewMagni(); // view / back rectDest.setCoords(0, 0, width(), height()); rectSource.setLeft( (int)((double)(app.getViewMapX() - app.getBackMapX()) / app.getBackMagni())); rectSource.setBottom(_backPixmap.size().height() - (int)((double)(app.getViewMapY() - app.getBackMapY()) / app.getBackMagni())); rectSource.setRight( rectSource.left() + (int)((double)width() / viewBackMagni)); rectSource.setTop( rectSource.bottom() - (int)((double)height() / viewBackMagni)); pp->drawPixmap(rectDest, _backPixmap, rectSource); } //全単路描画 pMap = app.getMap(); pRoad = pMap->nextRoad(&rmi, true); while (pRoad != NULL) { if (pRoad->getRoadId() == _roadIdSelect) { if (_dragType == roadRepl) { // qDebug("MapFrame::paint drag road replace selected"); drawLineType = selectedDark; } else drawLineType = selected; } else drawLineType = normal; if (_dragType == intsec) { // qDebug("MapFrame::paint drag intsec road"); if (pRoad->getIntsec(ROAD_IT_SMALL)->getIntsecId() == _intsecIdDrag || pRoad->getIntsec(ROAD_IT_LARGE)->getIntsecId() == _intsecIdDrag ) { // qDebug("MapFrame::paint drag intsec road selected"); drawLineType = selectedDark; } } // qDebug("MapFrame::paint road (%d,%d) drag %d lineType:%d", // pRoad->getIntsec(ROAD_IT_SMALL)->getIntsecId(), // pRoad->getIntsec(ROAD_IT_LARGE)->getIntsecId(), _intsecIdDrag, drawLineType); if (isViewArea(pRoad->getIntsec(ROAD_IT_SMALL)) || isViewArea(pRoad->getIntsec(ROAD_IT_LARGE))) drawLine(pp, getViewX(pRoad->getIntsec(ROAD_IT_SMALL)->getMapPosX()), getViewY(pRoad->getIntsec(ROAD_IT_SMALL)->getMapPosY()), getViewX(pRoad->getIntsec(ROAD_IT_LARGE)->getMapPosX()), getViewY(pRoad->getIntsec(ROAD_IT_LARGE)->getMapPosY()), drawLineType, pRoad->isLaneOver4(), pRoad->isError()); pRoad = pMap->nextRoad(&rmi); } //交差点ID描画、広域表示では点描画 if (app.getShowId()) { pIntsec = pMap->nextIntsec(&imi, true); while (pIntsec != NULL) { if (isViewArea(pIntsec)) { if (app.getMainWindow()->getEditMode() != MainWindow::large) { ss.str(""); ss << pIntsec->getIntsecId(); viewX = getViewX(pIntsec->getMapPosX()) + INTSEC_LABELSIZE_H + 2; viewY = getViewY(pIntsec->getMapPosY()) + INTSEC_LABELSIZE_H + 2; pp->setPen(QColor("#FFFFFF")); pp->drawText(viewX - 1, viewY + 1, ss.str().c_str()); pp->drawText(viewX - 1, viewY - 1, ss.str().c_str()); pp->drawText(viewX + 1, viewY - 1, ss.str().c_str()); pp->drawText(viewX + 1, viewY + 1, ss.str().c_str()); pp->setPen(QColor("#0000FF")); pp->drawText(viewX, viewY, ss.str().c_str()); } else { viewX = getViewX(pIntsec->getMapPosX()) - 2; viewY = getViewY(pIntsec->getMapPosY()) - 2; QString colorName; if (pIntsec->getIntsecId() == _intsecIdSelect) { if (pIntsec->isError()) colorName = "#FF00FF"; else colorName = "#0000FF"; } else { if (pIntsec->isError()) colorName = "#FF0000"; else colorName = "#000000"; } //何故かこうしないと描けない QBrush brush(QColor(colorName.toStdString().c_str())); pp->setPen(QColor(colorName)); pp->fillRect(viewX, viewY, 4, 4, brush); pp->drawRect(viewX, viewY, 4, 4); } } pIntsec = pMap->nextIntsec(&imi); } } }
//マウス開放イベント void MapFrame::mouseReleaseEvent(QMouseEvent *event) { Map* pMap = app.getMap(); Intsec* pIntsec; Road* pRoad; bool roadSelected; int intsecIdSmall, intsecIdLarge, intsecIdNew; double x, y; //右ボタンクリック/ドラッグならクリック、このチェックはいらないようだが念のため // qDebug("MapFrame::mouseReleaseEvent"); if (event->button()!=Qt::LeftButton || !_clickDrag) return; // qDebug("MapFrame::mouseReleaseEvent click"); _clickDrag = false; //交差点選択あり、交差点以外は NULL pIntsec = getIntsecAt(_clickDragX, _clickDragY); if (pIntsec != NULL) { changeShowSelect(pIntsec->getIntsecId(), MAP_NOID, MAP_NOID); showStatus(event->pos().x(), event->pos().y(), pIntsec->getIntsecId()); //交差点モードなら編集画面 if (app.getMainWindow()->getEditMode() == MainWindow::intsec) { IntsecDialog id(this); // qDebug("MapFrame::mouseReleaseEvent intsec dialog (%d, %d)", _intsecDialogX, _intsecDialogY); id.init(pIntsec); if (_intsecDialogX != DIALOG_NOPOS) id.move(_intsecDialogX, _intsecDialogY); if (id.exec() == QDialog::Accepted) { if (id.isDelete()) { pMap->deleteIntsec(pIntsec->getIntsecId()); changeShowSelect(MAP_NOID, MAP_NOID, MAP_NOID, true); } else { if (id.isCenter()) { app.setViewMap(app.getViewMapX() - pIntsec->getMapPosX(), app.getViewMapY() - pIntsec->getMapPosY()); if (app.getBackImage()) app.setBackMap(app.getBackMapX() - pIntsec->getMapPosX(), app.getBackMapY() - pIntsec->getMapPosY()); pMap->setCenter(pIntsec->getMapPosX(), pIntsec->getMapPosY(), 0); } //ID が変わったらマップで入れ替え、再選択 intsecIdNew = id.getIntsecId(); if (intsecIdNew != pIntsec->getIntsecId()) { pIntsec = pMap->changeIntsecId(pIntsec, intsecIdNew); changeShowSelect(intsecIdNew, MAP_NOID, MAP_NOID, true); } showIntsec(pIntsec); //全体再描画は遅いので先に書いとく } repaintAll(true); } // qDebug("MapFrame::mouseReleaseEvent intsec dialog (%d, %d)", id.x(), id.y()); _intsecDialogX = id.x(); _intsecDialogY = id.y(); } //単路/単路付け替えモードならモード切り替え(メインウィンドウから) else if (app.getMainWindow()->getEditMode() == MainWindow::road || app.getMainWindow()->getEditMode() == MainWindow::roadRepl) app.getMainWindow()->setEditMode(MainWindow::intsec); } //交差点選択なし else { //単路選択あり pRoad = getRoadAt(_clickDragX, _clickDragY); if (pRoad != NULL) { roadSelected = false; if (pRoad->getRoadId() == _roadIdSelect) roadSelected = true; intsecIdSmall = pRoad->getIntsec(ROAD_IT_SMALL)->getIntsecId(); intsecIdLarge = pRoad->getIntsec(ROAD_IT_LARGE)->getIntsecId(); if (intsecIdLarge == _intsecIdSelect) changeShowSelect(intsecIdLarge, intsecIdSmall, pRoad->getRoadId()); else changeShowSelect(intsecIdSmall, intsecIdLarge, pRoad->getRoadId()); showStatus(event->pos().x(), event->pos().y(), MAP_NOID); //交差点モードならモード切り替え(メインウィンドウから) if (app.getMainWindow()->getEditMode() == MainWindow::intsec) app.getMainWindow()->setEditMode(MainWindow::road); //単路モードなら編集画面、単路付け替えモードでも選択済みなら編集画面 else if (app.getMainWindow()->getEditMode() == MainWindow::road || (app.getMainWindow()->getEditMode() == MainWindow::roadRepl && roadSelected)) { RoadDialog rd(this); rd.init(pRoad); if (_roadDialogX != DIALOG_NOPOS) rd.move(_roadDialogX, _roadDialogY); if (rd.exec() == QDialog::Accepted) { if (rd.isDelete()) { pMap->deleteRoad(pRoad->getRoadId()); changeShowSelect(MAP_NOID, MAP_NOID, MAP_NOID, true); } else if (rd.isDelIntsec()) { Intsec* intsec1 = pRoad->getIntsec(ROAD_IT_SMALL); Intsec* intsec2 = pRoad->getIntsec(ROAD_IT_LARGE); pMap->deleteRoad(pRoad->getRoadId()); pMap->deleteIntsec(intsec1->getIntsecId()); pMap->deleteIntsec(intsec2->getIntsecId()); changeShowSelect(MAP_NOID, MAP_NOID, MAP_NOID, true); } repaintAll(true); } _roadDialogX = rd.x(); _roadDialogY = rd.y(); } } //単路選択なし else { //交差点モードなら交差点新規作成、選択変更とエラーチェックと表示、ここは全体再描画なし if (app.getMainWindow()->getEditMode() == MainWindow::intsec) { pIntsec = pMap->createIntsec(); x = getMapX(_clickDragX); y = getMapY(_clickDragY); if (pIntsec == NULL) QMessageBox::critical(this, tr(TITLE), tr("最大交差点IDが大きすぎます。")); if (x < APP_POS_MIN || y < APP_POS_MIN ) QMessageBox::critical(this, tr(TITLE), tr("最大位置が小さすぎます。")); else if (x > APP_POS_MAX || y > APP_POS_MAX ) QMessageBox::critical(this, tr(TITLE), tr("最大位置が大きすぎます。")); else { pIntsec->setMapPos(x, y, 0); changeShowSelect(pIntsec->getIntsecId(), _intsecIdDest, _roadIdSelect); // showStatus なしでも変わるが念のため showStatus(event->pos().x(), event->pos().y(), pIntsec->getIntsecId()); pIntsec->checkError(); showIntsec(pIntsec); // app.getMap()->debugTrace(); } } } } }