void EnviroFrame::CarveTerrainToFitNode(osg::Node *node) { vtTerrain *terr = g_App.GetCurrentTerrain(); if (!terr) return; vtDynTerrainGeom *dyn = terr->GetDynTerrain(); if (!dyn) return; FSphere sph; GetBoundSphere(node, sph, true); int changed = 0; int cols, rows; dyn->GetDimensions(cols, rows); const FPoint3 yvec(0,100,0); for (int c = 0; c < cols; c++) { for (int r = 0; r < rows; r++) { FPoint3 wpos; dyn->GetWorldLocation(c, r, wpos); if (wpos.x < (sph.center.x - sph.radius)) continue; if (wpos.x > (sph.center.x + sph.radius)) continue; if (wpos.z < (sph.center.z - sph.radius)) continue; if (wpos.z > (sph.center.z + sph.radius)) continue; // Shoot a ray upwards through the terrain surface point vtHitList HitList; int iNumHits = vtIntersect(node, wpos - yvec, wpos + yvec, HitList); if (iNumHits) { FPoint3 pos = HitList.front().point; dyn->SetElevation(c, r, pos.y); changed++; } } } if (changed != 0) { wxString msg; msg.Printf(_T("Adjusted %d heixels. Re-shade the terrain?"), changed); int res = wxMessageBox(msg, _T(""), wxYES_NO, this); if (res == wxYES) { // Update the (entire) shading and culture EnableContinuousRendering(false); OpenProgressDialog(_("Recalculating Shading"), _T(""), false, this); terr->ReshadeTexture(vtGetTS()->GetSunLightTransform(), progress_callback); DRECT area; area.SetToZero(); terr->RedrapeCulture(area); CloseProgressDialog(); EnableContinuousRendering(true); } } }
void EnviroFrame::OnChar(wxKeyEvent& event) { static NavType prev = NT_Normal; vtTerrain *pTerr = g_App.GetCurrentTerrain(); long key = event.GetKeyCode(); // Keyboard shortcuts ("accelerators") switch (key) { case 27: // Esc: cancel a building or linear we're making if (g_App.m_mode == MM_BUILDINGS && g_App.IsMakingElastic()) g_App.CancelElastic(); else if (g_App.m_mode == MM_LINEARS && g_App.IsMakingElastic()) g_App.CancelElastic(); else // or exit the application { // It's not safe to close immediately, as that will kill the canvas, // and it might some Canvas event that caused us to close. So, // simply stop rendering, and delay closing until the next Idle event. m_canvas->m_bRunning = false; m_bCloseOnIdle = true; } break; case ' ': if (g_App.m_state == AS_Terrain) ToggleNavigate(); break; case 'f': ChangeFlightSpeed(1.8f); break; case 's': ChangeFlightSpeed(1.0f / 1.8f); break; case 'a': g_App.SetMaintain(!g_App.GetMaintain()); break; case '+': SetTerrainDetail(GetTerrainDetail()+1000); break; case '-': SetTerrainDetail(GetTerrainDetail()-1000); break; case 'd': // Toggle grab-pivot if (g_App.m_nav == NT_Grab) g_App.SetNavType(prev); else { prev = g_App.m_nav; g_App.SetNavType(NT_Grab); } break; case 'w': m_bAlwaysMove = !m_bAlwaysMove; if (g_App.m_pTFlyer != NULL) g_App.m_pTFlyer->SetAlwaysMove(m_bAlwaysMove); break; case '[': { float exag = pTerr->GetVerticalExag(); exag /= 1.01; pTerr->SetVerticalExag(exag); } break; case ']': { float exag = pTerr->GetVerticalExag(); exag *= 1.01; pTerr->SetVerticalExag(exag); } break; case 'e': m_bEarthLines = !m_bEarthLines; g_App.ShowEarthLines(m_bEarthLines); break; case 'y': // Example code: modify the terrain by using the (slow) approach of using // vtTerrain methods GetInitialGrid and UpdateElevation. { vtTerrain *pTerr = g_App.GetCurrentTerrain(); if (pTerr && pTerr->GetParams().GetValueBool(STR_ALLOW_GRID_SCULPTING)) { vtElevationGrid *grid = pTerr->GetInitialGrid(); if (grid) { clock_t t1 = clock(); // Raise an area of the terrain int cols, rows; grid->GetDimensions(cols, rows); for (int i = cols / 4; i < cols / 2; i++) for (int j = rows / 4; j < rows / 2; j++) { grid->SetFValue(i, j, grid->GetFValue(i, j) + 40); } pTerr->UpdateElevation(); clock_t t2 = clock(); VTLOG(" Modify1: %.3f sec\n", (float)(t2-t1)/CLOCKS_PER_SEC); // Update the shading and culture pTerr->ReshadeTexture(vtGetTS()->GetSunLightTransform()); DRECT area; area.SetToZero(); pTerr->RedrapeCulture(area); } } } break; case 'Y': // Example code: modify the terrain by using the (fast) approach of using // vtDynTerrainGeom::SetElevation. { vtTerrain *pTerr = g_App.GetCurrentTerrain(); if (pTerr) { vtDynTerrainGeom *dyn = pTerr->GetDynTerrain(); if (dyn) { clock_t t1 = clock(); // Raise an area of the terrain int cols, rows; dyn->GetDimensions(cols, rows); for (int i = cols / 4; i < cols / 2; i++) for (int j = rows / 4; j < rows / 2; j++) { dyn->SetElevation(i, j, dyn->GetElevation(i, j) + 40); } clock_t t2 = clock(); VTLOG(" Modify2: %.3f sec\n", (float)(t2-t1)/CLOCKS_PER_SEC); // Update the shading and culture pTerr->ReshadeTexture(vtGetTS()->GetSunLightTransform()); DRECT area; area.SetToZero(); pTerr->RedrapeCulture(area); } } } break; case 'u': // Example code: modify a small area of terrain around the mouse pointer. { vtTerrain *pTerr = g_App.GetCurrentTerrain(); if (pTerr) { vtDynTerrainGeom *dyn = pTerr->GetDynTerrain(); if (dyn) { // Get 3D cursor location in grid coordinates FPoint3 fpos; g_App.m_pTerrainPicker->GetCurrentPoint(fpos); IPoint2 ipos; dyn->WorldToGrid(fpos, ipos); for (int x = -4; x < 4; x++) for (int y = -4; y < 4; y++) { float val = dyn->GetElevation(ipos.x + x, ipos.y + y); dyn->SetElevation(ipos.x + x, ipos.y + y, val + 40); } // Update the (entire) shading and culture pTerr->ReshadeTexture(vtGetTS()->GetSunLightTransform()); DRECT area; area.SetToZero(); pTerr->RedrapeCulture(area); } } } break; case 'D': // Shift-D // dump camera info g_App.DumpCameraInfo(); break; case 2: // Ctrl-B // toggle demo g_App.ToggleDemo(); break; case WXK_F11: DoTestCode(); break; case WXK_F12: m_pSceneGraphDlg->Show(true); break; case WXK_DELETE: DeleteAllSelected(); break; default: event.Skip(); break; } }
bool vtElevLayer::ImportFromFile(const wxString &strFileName, bool progress_callback(int), vtElevError *err) { // Avoid trouble with '.' and ',' in Europe - all the file readers assume // the default "C" locale. ScopedLocale normal_numbers(LC_NUMERIC, "C"); wxString strExt = strFileName.AfterLast('.'); vtString fname = (const char *) strFileName.mb_str(wxConvUTF8); VTLOG("ImportFromFile '%s'\n", (const char *) fname); if (!strExt.CmpNoCase(_T("gz"))) { // ignore .gz, look at extension under it wxString dropped = strFileName.Left(strFileName.Len()-3); strExt = dropped.AfterLast('.'); } if (!strExt.CmpNoCase(_T("bz2"))) { // ignore .bz2, look at extension under it wxString dropped = strFileName.Left(strFileName.Len()-4); strExt = dropped.AfterLast('.'); } // The first character in the file is useful for telling which format // the file really is. FILE *fp = vtFileOpen(fname, "rb"); char first = fgetc(fp); fclose(fp); bool success = false; if (!strExt.CmpNoCase(_T("dxf"))) { m_pTin = new vtTin2d; success = m_pTin->ReadDXF(fname, progress_callback); } else if (!strFileName.Right(6).CmpNoCase(_T("xy.adf"))) { m_pTin = new vtTin2d; success = m_pTin->ReadADF(fname, progress_callback); } else if (!strFileName.Right(4).CmpNoCase(_T(".tin"))) { m_pTin = new vtTin2d; success = m_pTin->ReadGMS(fname, progress_callback); } else if (!strFileName.Right(4).CmpNoCase(_T(".ply"))) { m_pTin = new vtTin2d; success = m_pTin->ReadPLY(fname, progress_callback); } else { if (m_pGrid == NULL) m_pGrid = new vtElevationGrid; } if (!strExt.CmpNoCase(_T("3tx"))) { success = m_pGrid->LoadFrom3TX(fname, progress_callback); } else if (!strExt.CmpNoCase(_T("dem"))) { // If there is a .hdr file in the same place, it is most likely // a GTOPO30/SRTM30 file vtString hdr_fname = ChangeFileExtension(fname, ".hdr"); if (vtFileExists(hdr_fname)) success = m_pGrid->LoadFromGTOPO30(hdr_fname, progress_callback); else { if (first == '*') success = m_pGrid->LoadFromMicroDEM(fname, progress_callback); else success = m_pGrid->LoadFromDEM(fname, progress_callback, err); } } else if (!strExt.CmpNoCase(_T("asc"))) { success = m_pGrid->LoadFromASC(fname, progress_callback); // vtElevationGrid does have its own ASC reader, but use GDAL instead // success = m_pGrid->LoadWithGDAL(strFileName.mb_str(wxConvUTF8), progress_callback, err); } else if (!strExt.CmpNoCase(_T("bil"))) { success = m_pGrid->LoadWithGDAL(fname, progress_callback, err); } else if (!strExt.CmpNoCase(_T("mem"))) { success = m_pGrid->LoadWithGDAL(fname, progress_callback, err); } else if (!strExt.CmpNoCase(_T("ter"))) { success = m_pGrid->LoadFromTerragen(fname, progress_callback); } else if (!strExt.CmpNoCase(_T("cdf"))) { success = m_pGrid->LoadWithGDAL(fname, progress_callback, err); } else if (!strExt.CmpNoCase(_T("hdr"))) { success = m_pGrid->LoadFromGTOPO30(fname, progress_callback); if (!success) success = m_pGrid->LoadFromGLOBE(fname, progress_callback); } else if (!strExt.CmpNoCase(_T("dte")) || !strExt.CmpNoCase(_T("dt0")) || !strExt.CmpNoCase(_T("dt1")) || !strExt.CmpNoCase(_T("dt2"))) { success = m_pGrid->LoadFromDTED(fname, progress_callback); } else if (!strExt.Left(3).CmpNoCase(_T("pgm"))) { success = m_pGrid->LoadFromPGM(fname, progress_callback); } else if (!strExt.CmpNoCase(_T("grd"))) { // might by CDF, might be Surfer GRD if (first == 'D') { VTLOG("First character is 'D', attempting load as a Surfer Grid file.\n"); success = m_pGrid->LoadFromGRD(fname, progress_callback); } else { VTLOG("First character is not 'D', attempting load as a netCDF file.\n"); success = m_pGrid->LoadWithGDAL(fname, progress_callback, err); } if (!success) { VTLOG("Didn't load successfully, attempting load with GDAL.\n"); // Might be 'Arc Binary Grid', try GDAL success = m_pGrid->LoadWithGDAL(fname, progress_callback, err); } } else if (!strFileName.Right(8).CmpNoCase(_T("catd.ddf")) || !strExt.Left(3).CmpNoCase(_T("tif")) || !strExt.Left(3).CmpNoCase(_T("png")) || !strExt.Left(3).CmpNoCase(_T("img")) || !strExt.CmpNoCase(_T("adf"))) { if (m_pGrid) success = m_pGrid->LoadWithGDAL(fname, progress_callback, err); } else if (!strExt.CmpNoCase(_T("raw"))) { RawDlg dlg(NULL, -1, _("Raw Elevation File")); dlg.m_iBytes = 2; dlg.m_iWidth = 100; dlg.m_iHeight = 100; dlg.m_fVUnits = 1.0f; dlg.m_fSpacing = 30.0f; dlg.m_bBigEndian = false; dlg.m_extents.SetToZero(); g_bld->GetProjection(dlg.m_original); if (dlg.ShowModal() == wxID_OK) { success = m_pGrid->LoadFromRAW(fname, dlg.m_iWidth, dlg.m_iHeight, dlg.m_iBytes, dlg.m_fVUnits, dlg.m_bBigEndian, progress_callback); } if (success) { m_pGrid->SetEarthExtents(dlg.m_extents); m_pGrid->SetProjection(dlg.m_proj); } } else if (!strExt.CmpNoCase(_T("ntf"))) { success = m_pGrid->LoadFromNTF5(fname, progress_callback); } else if (!strExt.CmpNoCase(_T("txt")) || !strExt.CmpNoCase(_T("xyz"))) { success = m_pGrid->LoadFromXYZ(fname, progress_callback); } else if (!strExt.CmpNoCase(_T("hgt"))) { success = m_pGrid->LoadFromHGT(fname, progress_callback); } else if (!strExt.Left(2).CmpNoCase(_T("db"))) { success = ImportFromDB(fname, progress_callback); } if (!success) return false; vtProjection *pProj; if (m_pGrid) pProj = &m_pGrid->GetProjection(); else pProj = &m_pTin->m_proj; // We should ask for a CRS before asking for extents if (!g_bld->ConfirmValidCRS(pProj)) { if (err) { err->type = vtElevError::CANCELLED; err->message = "Cancelled"; } return false; } if (m_pGrid != NULL) { if (m_pGrid->GetEarthExtents().IsEmpty()) { // No extents. wxString msg = _("File lacks geographic location (extents). Would you like to specify extents?\n Yes - specify extents\n No - use some default values\n"); int res = wxMessageBox(msg, _("Elevation Import"), wxYES_NO | wxCANCEL); if (res == wxYES) { DRECT ext; ext.SetToZero(); ExtentDlg dlg(NULL, -1, _("Elevation Grid Extents")); dlg.SetArea(ext, (pProj->IsGeographic() != 0)); if (dlg.ShowModal() == wxID_OK) m_pGrid->SetEarthExtents(dlg.m_area); else return false; } if (res == wxNO) { // Just make up some fake extents, assuming a regular even grid int xsize, ysize; m_pGrid->GetDimensions(xsize, ysize); DRECT ext; ext.left = ext.bottom = 0; if (pProj->IsGeographic()) { ext.right = xsize * (1.0/3600); // arc second ext.top = ysize * (1.0/3600); } else { ext.right = xsize * 10; // 10 linear units (meters, feet..) ext.top = ysize * 10; } m_pGrid->SetEarthExtents(ext); } if (res == wxCANCEL) { if (err) { err->type = vtElevError::CANCELLED; err->message = "Cancelled"; } return false; } } m_pGrid->SetupLocalCS(1.0f); } return true; }