00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <math.h>
00022 #include <glib.h>
00023 #include "utils/utils.h"
00024 #include "avulsion.h"
00025
00026 GQuark
00027 avulsion_data_struct_quark( void )
00028 {
00029 return g_quark_from_static_string( "avulsion-data-struct-quark" );
00030 }
00031
00032 Avulsion_st*
00033 avulsion_new( GRand* rand , double std_dev )
00034 {
00035 Avulsion_st* data = eh_new( Avulsion_st , 1 );
00036
00037 data->rand = rand;
00038 data->std_dev = std_dev;
00039
00040 return data;
00041 }
00042
00043 Avulsion_st*
00044 avulsion_dup( Avulsion_st* s )
00045 {
00046 Avulsion_st* d = NULL;
00047
00048 if ( s )
00049 {
00050 d = avulsion_new( g_rand_copy(s->rand) , s->std_dev );
00051 }
00052
00053 return d;
00054 }
00055
00056 Avulsion_st*
00057 avulsion_destroy( Avulsion_st* data )
00058 {
00059 if ( data )
00060 {
00061 g_rand_free( data->rand );
00062 data->std_dev = 0;
00063 data->rand = NULL;
00064 eh_free( data );
00065 }
00066 return NULL;
00067 }
00068
00069 double
00070 get_std_dev_func( double angle , double std_dev )
00071 {
00072 return std_dev*(1. - .25*exp(-pow(angle-.0*G_PI,2.)) );
00073 }
00074
00075 double
00076 avulsion( GRand* rand , double last_angle , double std_dev )
00077 {
00078 double new_angle;
00079
00080 double d_angle = eh_rand_normal( rand , 0. , get_std_dev_func(last_angle,std_dev) );
00081
00082 new_angle = last_angle+d_angle;
00083
00084 if ( new_angle>G_PI )
00085 new_angle = 2.*G_PI - new_angle;
00086 else if ( new_angle<-G_PI )
00087 new_angle = -2.*G_PI - new_angle;
00088
00089 new_angle = eh_reduce_angle( new_angle );
00090
00091 return new_angle;
00092 }
00093
00094 double
00095 avulsion_scale_angle_down( double angle , double min_angle , double max_angle )
00096 {
00097 return angle*(max_angle-min_angle)/(2.*G_PI) + .5*(min_angle+max_angle);
00098 }
00099
00100 double
00101 avulsion_scale_angle_up( double angle , double min_angle , double max_angle )
00102 {
00103 return (angle - .5*(min_angle+max_angle))*(2.*G_PI)/(max_angle-min_angle);
00104 }
00105
00106 double
00107 avulsion_scale_std_dev_up( double std_dev , double min_angle , double max_angle )
00108 {
00109 return std_dev*2.*G_PI/( max_angle-min_angle );
00110 }
00111
00112 Sed_riv
00113 sed_river_set_avulsion_data( Sed_riv r , Avulsion_st* data )
00114 {
00115 g_dataset_id_set_data_full( r , AVULSION_DATA , data , (GDestroyNotify)avulsion_destroy );
00116 return r;
00117 }
00118
00119 Sed_riv
00120 sed_river_impart_avulsion_data( Sed_riv r )
00121 {
00122 Avulsion_st* parent_data = sed_river_avulsion_data(r);
00123 Avulsion_st* left_data = avulsion_dup( parent_data );
00124 Avulsion_st* right_data = avulsion_dup( parent_data );
00125
00126 left_data->std_dev *=.5;
00127 right_data->std_dev *=2.;
00128
00129 sed_river_set_avulsion_data( sed_river_left (r) , left_data );
00130 sed_river_set_avulsion_data( sed_river_right(r) , right_data );
00131
00132 return r;
00133 }
00134
00135 Sed_riv
00136 sed_river_unset_avulsion_data( Sed_riv r )
00137 {
00138 g_dataset_id_remove_data( r , AVULSION_DATA );
00139 return r;
00140 }
00141
00142 Avulsion_st*
00143 sed_river_avulsion_data( Sed_riv r )
00144 {
00145 return g_dataset_id_get_data( r , AVULSION_DATA );
00146 }
00147
00148 Sed_riv
00149 sed_river_avulse( Sed_riv r )
00150 {
00151 eh_require( r );
00152
00153 if ( r )
00154 {
00155 double angle;
00156 double last_angle = sed_river_angle ( r );
00157 Avulsion_st* data = sed_river_avulsion_data( r );
00158
00159 eh_require( data );
00160
00161 if ( data && data->std_dev>0 )
00162 {
00163 GRand* rand = data->rand;
00164 double std_dev = data->std_dev;
00165 double min_angle = sed_river_min_angle(r);
00166 double max_angle = sed_river_max_angle(r);
00167
00168 std_dev = avulsion_scale_std_dev_up( std_dev , min_angle , max_angle );
00169 last_angle = avulsion_scale_angle_up ( last_angle , min_angle , max_angle );
00170 angle = avulsion ( rand , last_angle , std_dev );
00171 angle = avulsion_scale_angle_down( angle , min_angle , max_angle );
00172
00173 sed_river_set_angle( r , angle );
00174 }
00175 }
00176
00177 return r;
00178 }
00179
00194 Sed_cube
00195 sed_cube_avulse_river( Sed_cube c , Sed_riv r )
00196 {
00197
00198 if ( c )
00199 {
00200 Sed_riv* branch = sed_river_branches( r );
00201 Sed_riv* this_branch;
00202
00203 for ( this_branch=branch ; *this_branch ; this_branch++ )
00204 {
00205 sed_river_avulse( *this_branch );
00206 sed_cube_find_river_mouth( c , *this_branch );
00207 }
00208
00209 eh_free( branch );
00210 }
00211
00212 return c;
00213 }
00214
00215 void
00216 sed_cube_avulse_river_helper( Sed_riv r , Sed_cube c )
00217 {
00218 sed_cube_avulse_river( c , r );
00219 }
00220
00221 Sed_cube
00222 sed_cube_avulse_all_rivers( Sed_cube c )
00223 {
00224 return sed_cube_foreach_river( c , (GFunc)&sed_cube_avulse_river_helper , c );
00225 }
00226
00227