1 module des.il.util; 2 3 import std.algorithm; 4 import std.exception; 5 import std.range; 6 import std.conv : to; 7 8 import des.util.stdext.algorithm; 9 import des.util.testsuite; 10 11 import des.math.linear.vector; 12 import des.math.util.accessstring; 13 14 /// 15 class ImageException : Exception 16 { 17 /// 18 this( string msg, string file=__FILE__, size_t line=__LINE__ ) @safe pure nothrow 19 { super( msg, file, line ); } 20 } 21 22 string coordinateAccessString( size_t N ) pure 23 { 24 if( N > 3 ) return ""; 25 26 string[] v1 = [ "x", "y", "z" ][0 .. N]; 27 string[] v2 = [ "abscissa", "ordinate", "applicate" ][0 .. N]; 28 29 return arrayAccessStringCtor( VVASES, VVASVS, v1, v2 ); 30 } 31 32 unittest 33 { 34 static assert( coordinateAccessString(4) == "" ); 35 static assert( coordinateAccessString(3) == "x y z|abscissa ordinate applicate" ); 36 static assert( coordinateAccessString(2) == "x y|abscissa ordinate" ); 37 static assert( isCompatibleArrayAccessStrings( 2, coordinateAccessString(2), VVASES, VVASVS ) ); 38 } 39 40 string sizeAccessString( size_t N ) pure 41 { 42 if( N > 3 ) return ""; 43 44 string[] v1 = [ "w", "h", "d" ][0 .. N]; 45 string[] v2 = [ "width", "height", "depth" ][0 .. N]; 46 47 return arrayAccessStringCtor( VVASES, VVASVS, v1, v2 ); 48 } 49 50 unittest 51 { 52 static assert( sizeAccessString(4) == "" ); 53 static assert( sizeAccessString(3) == "w h d|width height depth" ); 54 static assert( sizeAccessString(2) == "w h|width height" ); 55 static assert( isCompatibleArrayAccessStrings( 2, sizeAccessString(2), VVASES, VVASVS ) ); 56 } 57 58 string volumeAccessString( size_t N ) 59 { 60 if( N > 3 ) return ""; 61 62 string[] c1 = [ "x", "y", "z" ][0 .. N]; 63 string[] c2 = [ "abscissa", "ordinate", "applicate" ][0 .. N]; 64 65 string[] s1 = [ "w", "h", "d" ][0 .. N]; 66 string[] s2 = [ "width", "height", "depth" ][0 .. N]; 67 68 return arrayAccessStringCtor( VVASES, VVASVS, c1 ~ s1, c2 ~ s2 ); 69 } 70 71 unittest 72 { 73 static assert( volumeAccessString(4) == "" ); 74 static assert( volumeAccessString(3) == "x y z w h d|abscissa ordinate applicate width height depth" ); 75 static assert( volumeAccessString(2) == "x y w h|abscissa ordinate width height" ); 76 static assert( isCompatibleArrayAccessStrings( 4, volumeAccessString(2), VVASES, VVASVS ) ); 77 } 78 79 /// 80 alias CoordType = ptrdiff_t; 81 /// 82 alias CoordVector(size_t N,T=CoordType) = Vector!(N,T,coordinateAccessString(N)); 83 /// 84 alias SizeVector(size_t N,T=CoordType) = Vector!(N,T,sizeAccessString(N)); 85 /// 86 alias VolumeVector(size_t N,T=CoordType) = Vector!(N*2,T,volumeAccessString(N)); 87 88 /++ checks all components 89 Returns: 90 true if all is positive 91 +/ 92 bool isAllCompPositive(V)( in V v ) 93 if( is( typeof( v[0] ) ) && isNumeric!(typeof(v[0])) ) 94 { 95 foreach( e; v ) if( e < 0 ) return false; 96 return true; 97 } 98 99 /// 100 unittest 101 { 102 assert( isAllCompPositive( [1,2,3] ) ); 103 assert( isAllCompPositive( vec3( 1,2,3 ) ) ); 104 assert( isAllCompPositive( SizeVector!3( 1,2,3 ) ) ); 105 assert( !isAllCompPositive( [-1,2,3] ) ); 106 } 107 108 /++ get index of element in 1-dim array by N-dim coordinate 109 110 Params: 111 size = N-dim array of sizes by each dimension 112 crd = N-dim array of coordinates in N-dim space 113 114 Returns: 115 index in 1-dim array 116 +/ 117 size_t getIndex(size_t N)( in CoordType[N] size, in CoordType[N] crd ) pure 118 in 119 { 120 assert( isAllCompPositive( size ) ); 121 assert( isAllCompPositive( crd ) ); 122 assert( all!"a[0]>a[1]"( zip( size.dup, crd.dup ) ), "range violation" ); 123 } 124 body 125 { 126 size_t ret; 127 foreach( i; 0 .. N ) 128 { 129 auto v = reduce!((a,b)=>(a*=b))(1UL,size[0..i]); 130 ret += crd[i] * v; 131 } 132 return ret; 133 } 134 135 version(todos) pragma( msg, __FILE__,":", __LINE__, " TODO: add tests to indexCalc" ); 136 137 /++ get coordinate in N-dim space by N-dim size and line index 138 139 Params: 140 size = N-dim array of sizes by each dimension 141 index = index in 1-dim array 142 143 Retrurns: 144 N-dim array of coordinates in N-dim space 145 +/ 146 CoordType[N] getCoord(size_t N)( in CoordType[N] size, size_t index ) pure 147 in 148 { 149 assert( isAllCompPositive( size ) ); 150 assert( index <= getIndex( size, to!(CoordType[N])( amap!(a=>a-1)(size.dup) ) ), "range violation" ); 151 } 152 body 153 { 154 size_t buf = index; 155 CoordType[N] ret; 156 foreach_reverse( i; 0 .. N ) 157 { 158 auto vol = reduce!((a,b)=>(a*=b))(1U,size[0..i]); 159 ret[i] = buf / vol; 160 buf = buf % vol; 161 } 162 return ret; 163 } 164 165 unittest 166 { 167 CoordType[4] size = [ 10, 20, 30, 40 ]; 168 CoordType[4] crd = [ 3, 5, 8, 10 ]; 169 assert( eq( crd, getCoord( size, getIndex( size, crd ) ) ) ); 170 } 171 172 /++ get line index in origin array by layer line index and layer number 173 174 Params: 175 size = original size 176 K = number of dimension 177 lindex = line index in layer 178 lno = layer number 179 +/ 180 size_t getOrigIndexByLayerCoord(size_t N)( in CoordType[N] size, size_t K, size_t lindex, size_t lno ) pure 181 in { assert( K < N ); } body 182 { 183 auto lcrd = getCoord( removeStat( size, K ), lindex ); 184 return getIndex( size, pasteStat( lcrd, K, lno ) ); 185 } 186 187 /++ remove value from static array 188 189 Params: 190 arr = array 191 K = index to remove 192 +/ 193 T[N-1] removeStat(T,size_t N)( in T[N] arr, size_t K ) pure 194 in { assert( K < N ); } body 195 { 196 if( K == N-1 ) return cast(T[N-1])arr[0..$-1]; 197 else return to!(T[N-1])( arr[0..K] ~ arr[K+1..$] ); 198 } 199 200 /// 201 unittest 202 { 203 size_t[3] arr = [ 0, 1, 2 ]; 204 static assert( is( typeof( removeStat( arr, 0 ) ) == size_t[2] ) ); 205 206 assert( eq( removeStat( arr, 0 ), [1,2] ) ); 207 assert( eq( removeStat( arr, 1 ), [0,2] ) ); 208 assert( eq( removeStat( arr, 2 ), [0,1] ) ); 209 } 210 211 /++ paste value to static array 212 213 Params: 214 arr = array 215 K = index to paste 216 val = value to paste 217 +/ 218 T[N+1] pasteStat(T,size_t N)( in T[N] arr, size_t K, T val ) pure 219 in { assert( K <= N ); } body 220 { 221 if( K == N ) return to!(T[N+1])( arr ~ val ); 222 else return to!(T[N+1])( arr[0..K] ~ val ~ arr[K..$] ); 223 } 224 225 /// 226 unittest 227 { 228 size_t[3] arr = [ 0, 1, 2 ]; 229 static assert( is( typeof( pasteStat( arr, 0, 10 ) ) == size_t[4] ) ); 230 231 assert( eq( pasteStat( arr, 0, 10 ), [10,0,1,2] ) ); 232 assert( eq( pasteStat( arr, 1, 10 ), [0,10,1,2] ) ); 233 assert( eq( pasteStat( arr, 3, 10 ), [0,1,2,10] ) ); 234 }