//--------------------------------------------------------- void CD8_Flow_Analysis::Get_Basins(void) { Process_Set_Text(_TL("Drainage Basins")); for(int y=0; y<Get_NY() && Set_Progress(y); y++) { for(int x=0; x<Get_NX(); x++) { Get_Basin(x, y); } } //----------------------------------------------------- CSG_Shapes *pBasins = Parameters("BASINS")->asShapes(); if( pBasins ) { bool bResult; SG_RUN_MODULE(bResult, "shapes_grid", 6, pModule->Get_Parameters()->Set_Parameter(SG_T("GRID") , m_pBasins) && pModule->Get_Parameters()->Set_Parameter(SG_T("POLYGONS"), pBasins) ) pBasins->Set_Name(_TL("Drainage Basins")); } }
//--------------------------------------------------------- int CD8_Flow_Analysis::Get_Basin(int x, int y) { int i, Basin = m_pBasins->asInt(x, y); if( Basin <= 0 && (i = m_pDir->asInt(x, y)) >= 0 && (Basin = Get_Basin(Get_xTo(i, x), Get_yTo(i, y))) > 0 ) { m_pBasins->Set_Value(x, y, Basin); } return( Basin ); }
//--------------------------------------------------------- int CWatersheds::Get_Basin(int x, int y) { int i, ix, iy, nCells; if( m_pBasins->is_NoData(x, y) && !m_Direction.is_NoData(x, y) ) { m_pBasins->Set_Value(x, y, m_nBasins); for(i=0, nCells=1; i<8; i++) { ix = Get_xTo(i, x); iy = Get_yTo(i, y); if( is_InGrid(ix,iy) && m_Direction.asInt(ix, iy) == i ) { nCells += Get_Basin(ix, iy); } } return( nCells ); } return( -1 ); }
//--------------------------------------------------------- bool CWatersheds_ext::Get_Basin(CSG_Grid *pBasins, CSG_Shapes *pPolygons, int xMouth, int yMouth, int Main_ID) { int x, y, Basin_ID = 1 + pPolygons->Get_Count(); CSG_Shape *pPolygon; CSG_Grid_Stack Stack; CSG_Simple_Statistics s_Height, s_Distance; //----------------------------------------------------- Stack.Push(x = xMouth, y = yMouth); pBasins ->Set_Value(x, y, Basin_ID); m_Distance .Set_Value(x, y, 0.0); s_Height += m_pDEM->asDouble(x, y); s_Distance += 0.0; //----------------------------------------------------- while( Stack.Get_Size() > 0 && Process_Get_Okay() ) { Stack.Pop(x, y); double d = m_Distance.asDouble(x, y); //------------------------------------------------- for(int i=0; i<8; i++) { int ix = Get_xFrom(i, x); int iy = Get_yFrom(i, y); if( is_InGrid(ix, iy) && pBasins->is_NoData(ix, iy) && i == m_Direction.asInt(ix, iy) ) { Stack.Push(ix, iy); pBasins ->Set_Value(ix, iy, Basin_ID); m_Distance .Set_Value(ix, iy, d + Get_Length(i)); s_Height += m_pDEM->asDouble(ix, iy); s_Distance += d + Get_Length(i); } } } //----------------------------------------------------- if( s_Height.Get_Count() > 1 && (pPolygon = Get_Basin(pBasins, pPolygons)) != NULL ) { double d, Area, Perimeter, Side_A, Side_B; CSG_String Gravelius; // Area = s_Height.Get_Count() * Get_System()->Get_Cellarea(); Area = ((CSG_Shape_Polygon*)pPolygon)->Get_Area(); Perimeter = ((CSG_Shape_Polygon*)pPolygon)->Get_Perimeter(); d = 0.28 * Perimeter / sqrt(Area); Gravelius = d > 1.75 ? _TL("rectangular") : d > 1.5 ? _TL("ovalooblonga-rectangularoblonga") : d > 1.25 ? _TL("ovaloredonda-ovalooblonga") : _TL("redonda-ovaloredonda"); d = pow(Perimeter, 2.0) - 8.0 * Area; Side_A = d > 0.0 ? (Perimeter + sqrt(d)) / 4.0 : -1.0; Side_B = d > 0.0 ? (Perimeter - 2.0 * Side_A) / 2.0 : -1.0; pPolygon->Set_Value(FIELD_ID , Basin_ID); pPolygon->Set_Value(FIELD_ID_MAIN , Main_ID); pPolygon->Set_Value(FIELD_MOUTH_X , Get_System()->Get_xGrid_to_World(xMouth)); pPolygon->Set_Value(FIELD_MOUTH_Y , Get_System()->Get_yGrid_to_World(yMouth)); pPolygon->Set_Value(FIELD_PERIMETER , Perimeter); pPolygon->Set_Value(FIELD_AREA , Area); pPolygon->Set_Value(FIELD_CENTROID_X , ((CSG_Shape_Polygon*)pPolygon)->Get_Centroid().x); pPolygon->Set_Value(FIELD_CENTROID_Y , ((CSG_Shape_Polygon*)pPolygon)->Get_Centroid().y); pPolygon->Set_Value(FIELD_Z_MEAN , s_Height .Get_Mean()); pPolygon->Set_Value(FIELD_Z_RANGE , s_Height .Get_Range()); pPolygon->Set_Value(FIELD_DIST_MEAN , s_Distance.Get_Mean()); pPolygon->Set_Value(FIELD_DIST_MAX , s_Distance.Get_Maximum()); pPolygon->Set_Value(FIELD_CONCTIME , s_Height.Get_Range() <= 0.0 ? -1.0 : pow(0.87 * pow(s_Distance.Get_Maximum() / 1000.0, 3.0) / s_Height.Get_Range(), 0.385) ); pPolygon->Set_Value(FIELD_BASIN_TYPE , Gravelius); pPolygon->Set_Value(FIELD_EQVRECT_A , Side_A); pPolygon->Set_Value(FIELD_EQVRECT_B , Side_B); pPolygon->Set_Value(FIELD_OROG_IDX , SG_Get_Square(s_Height.Get_Mean()) / (0.0001 * Area)); // Orographic index, defined as the mean catchment altitude times the ratio of the mean catchment altitude to the orthogonal projection of drainage area (Alcázar, Palau (2010): Establishing environmental flow regimes in a Mediterranean watershed based on a regional classification. Journal of Hydrology, V. 388 pPolygon->Set_Value(FIELD_MASS_IDX , Perimeter / (0.0001 * Area)); // Perimeter / (0.0001 * Area) ??!! pPolygon->Set_Value(FIELD_BASINS_UP , 0.0); // Upslope Basins pPolygon->Set_Value(FIELD_BASINS_DOWN , 0.0); // Downslope Basins return( true ); } return( false ); }
//--------------------------------------------------------- bool CWatersheds_ext::On_Execute(void) { int x, y; CSG_Grid *pBasins, *pSubBasins, Inflows; CSG_Shapes *pHeads, *pMouths, *pVBasins, *pVSubBasins; m_pDEM = Parameters("DEM") ->asGrid(); m_pChannels = Parameters("CHANNELS") ->asGrid(); pBasins = Parameters("BASINS") ->asGrid(); pSubBasins = Parameters("SUBBASINS") ->asGrid(); pVBasins = Parameters("V_BASINS") ->asShapes(); pVSubBasins = Parameters("V_SUBBASINS") ->asShapes(); pHeads = Parameters("HEADS") ->asShapes(); pMouths = Parameters("MOUTHS") ->asShapes(); //----------------------------------------------------- Inflows .Create(*Get_System(), SG_DATATYPE_Char); m_Direction .Create(*Get_System(), SG_DATATYPE_Char); m_Direction .Set_NoData_Value(-1); m_Distance .Create(*Get_System(), SG_DATATYPE_Float); m_Distance .Set_NoData_Value(-1); m_Distance .Assign_NoData(); pBasins ->Assign(0.0); pBasins ->Set_NoData_Value(0.0); pSubBasins ->Assign(0.0); pSubBasins ->Set_NoData_Value(0.0); pHeads ->Create(SHAPE_TYPE_Point , _TL("Heads")); pHeads ->Add_Field("ID" , SG_DATATYPE_Int); pHeads ->Add_Field("MAIN_ID" , SG_DATATYPE_Int); pHeads ->Add_Field("ELEVATION" , SG_DATATYPE_Double); pHeads ->Add_Field("DISTANCE" , SG_DATATYPE_Double); pMouths ->Create(SHAPE_TYPE_Point , _TL("Mouths")); pMouths ->Add_Field("ID" , SG_DATATYPE_Int); pMouths ->Add_Field("MAIN_ID" , SG_DATATYPE_Int); pMouths ->Add_Field("ELEVATION" , SG_DATATYPE_Double); pVBasins ->Create(SHAPE_TYPE_Polygon , _TL("Basins")); BASIN_ADD_FIELDS(pVBasins); pVSubBasins ->Create(SHAPE_TYPE_Polygon , _TL("Subbasins")); BASIN_ADD_FIELDS(pVSubBasins); //----------------------------------------------------- Process_Set_Text(_TL("flow directions...")); for(y=0; y<Get_NY() && Set_Progress(y); y++) { for(x=0; x<Get_NX(); x++) { int Direction = -1; if( m_pDEM->is_InGrid(x, y) ) { double dMax = 0.0; for(int i=0; i<8; i++) { int ix = Get_xTo(i, x); int iy = Get_yTo(i, y); if( m_pDEM->is_InGrid(ix, iy) && !m_pChannels->is_NoData(ix, iy) ) { double dz = (m_pDEM->asDouble(x, y) - m_pDEM->asDouble(ix, iy)) / Get_Length(i); if( dMax < dz ) { dMax = dz; Direction = i; } } } if( !m_pChannels->is_NoData(x, y) ) { if( Direction >= 0 ) { int ix = Get_xTo(Direction, x); int iy = Get_yTo(Direction, y); if( m_pDEM->is_InGrid(ix, iy) ) { Inflows.Add_Value(ix, iy, 1); } } } else if( Direction < 0 ) { Direction = m_pDEM->Get_Gradient_NeighborDir(x, y); } } m_Direction.Set_Value(x, y, Direction); } } //----------------------------------------------------- Process_Set_Text(_TL("main basins...")); for(y=0; y<Get_NY() && Set_Progress(y); y++) { for(x=0; x<Get_NX(); x++) { if( m_pChannels->is_InGrid(x, y) && is_Outlet(x, y) ) { Get_Basin(pBasins, pVBasins, x, y, -1); CSG_Shape *pMouth = pMouths->Add_Shape(); pMouth->Add_Point(Get_System()->Get_Grid_to_World(x, y)); pMouth->Set_Value(0, pVBasins->Get_Count()); // ID pMouth->Set_Value(1, pVBasins->Get_Count()); // MAIN_ID pMouth->Set_Value(2, m_pDEM->asDouble(x, y)); // ELEVATION } } } if( Parameters("DISTANCE")->asBool() ) { m_Distance.Set_Name(_TL("Flow Distance")); DataObject_Add(SG_Create_Grid(m_Distance)); } //----------------------------------------------------- Process_Set_Text(_TL("heads and mouths...")); for(y=0; y<Get_NY() && Set_Progress(y); y++) { for(x=0; x<Get_NX(); x++) { if( m_pChannels->is_InGrid(x, y) ) { //----------------------------------------- if( Inflows.asInt(x, y) > 1 ) // mouth, linking channels of subcatchments { CSG_Shape *pMouth = pMouths->Add_Shape(); pMouth->Add_Point(Get_System()->Get_Grid_to_World(x, y)); pMouth->Set_Value(0, pMouths->Get_Count()); // ID pMouth->Set_Value(1, pBasins->asDouble(x, y)); // MAIN_ID pMouth->Set_Value(2, m_pDEM->asDouble(x, y)); // ELEVATION } //----------------------------------------- else if( Inflows.asInt(x, y) == 0 ) // head { CSG_Shape *pHead = pHeads->Add_Shape(); pHead->Add_Point(Get_System()->Get_Grid_to_World(x, y)); pHead->Set_Value(0, pHeads->Get_Count() + 1); pHead->Set_Value(1, m_Distance.asDouble(x, y)); } } } } //----------------------------------------------------- Process_Set_Text(_TL("subbasins...")); pMouths->Set_Index(1, TABLE_INDEX_Ascending, 2, TABLE_INDEX_Descending); for(int iMouth=0; iMouth<pMouths->Get_Count() && Set_Progress(iMouth, pMouths->Get_Count()); iMouth++) { CSG_Shape *pMouth = pMouths->Get_Shape_byIndex(iMouth); if( Get_System()->Get_World_to_Grid(x, y, pMouth->Get_Point(0)) ) { if( pMouth->asInt(0) == pMouth->asInt(1) ) { Get_Basin(pSubBasins, pVSubBasins, x, y, pMouth->asInt(1)); } else { for(int i=0; i<8; i++) { int ix = Get_xFrom(i, x); int iy = Get_yFrom(i, y); if( m_pChannels->is_InGrid(ix, iy) && m_Direction.asInt(ix, iy) == i ) { Get_Basin(pSubBasins, pVSubBasins, ix, iy, pMouth->asInt(1)); } } } } } if( Parameters("DISTANCE")->asBool() ) { m_Distance.Set_Name(_TL("Subbasin Flow Distance")); DataObject_Add(SG_Create_Grid(m_Distance)); } //----------------------------------------------------- m_Distance .Destroy(); m_Direction .Destroy(); return( true ); }
//--------------------------------------------------------- bool CWatersheds::On_Execute(void) { int x, y, nCells, nCells_Min, nBasins; sLong n; CSG_Grid *pDTM, *pSeed, *pRoute; //----------------------------------------------------- pDTM = Parameters("ELEVATION")->asGrid(); pSeed = Parameters("CHANNELS" )->asGrid(); pRoute = Parameters("SINKROUTE")->asGrid(); nCells_Min = Parameters("MINSIZE" )->asInt(); m_pBasins = Parameters("BASINS" )->asGrid(); m_pBasins->Set_NoData_Value(NO_BASIN); m_pBasins->Assign_NoData(); if( !pDTM->Set_Index() ) { Error_Set(_TL("index creation failed")); return( false ); } m_Direction.Create(m_pBasins, SG_DATATYPE_Char); for(y=0; y<Get_NY() && Set_Progress(y); y++) { for(x=0; x<Get_NX(); x++) { if( pDTM->is_NoData(x, y) ) { m_Direction.Set_NoData(x, y); } else { if( !pRoute || (n = pRoute->asChar(x, y)) <= 0 ) { n = pDTM->Get_Gradient_NeighborDir(x, y); } m_Direction.Set_Value(x, y, (int)(n < 0 ? -1 : (n + 4) % 8)); } } } //----------------------------------------------------- for(n=0, m_nBasins=0; n<Get_NCells() && Set_Progress_NCells(n); n++) { pDTM->Get_Sorted(n, x, y, true, false); if( !pSeed->is_NoData(x, y) && pSeed->asInt(x, y) < 0 ) { m_nBasins++; if( (nCells = Get_Basin(x, y)) < nCells_Min ) { nBasins = m_nBasins - 1; m_nBasins = NO_BASIN; Get_Basin(x, y); m_nBasins = nBasins; } } } //----------------------------------------------------- m_Direction.Destroy(); return( true ); }