1 /+ 2 The MIT License (MIT) 3 4 Copyright (c) <2013> <Oleg Butko (deviator), Anton Akzhigitov (Akzwar)> 5 6 Permission is hereby granted, free of charge, to any person obtaining a copy 7 of this software and associated documentation files (the "Software"), to deal 8 in the Software without restriction, including without limitation the rights 9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 copies of the Software, and to permit persons to whom the Software is 11 furnished to do so, subject to the following conditions: 12 13 The above copyright notice and this permission notice shall be included in 14 all copies or substantial portions of the Software. 15 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 THE SOFTWARE. 23 +/ 24 25 module des.il.region; 26 27 import std.algorithm; 28 import std.string; 29 import std.traits; 30 import des.math.linear.vector; 31 32 struct Region(size_t N,T) 33 if( N >= 1 && isNumeric!T ) 34 { 35 alias Vector!(N,T,"xyz"[0..N].spaceSep) ptype; 36 alias Vector!(N*2,T,("xyz"[0..N]~"whd"[0..N]).spaceSep) rtype; 37 38 alias Region!(N,T) selftype; 39 40 union 41 { 42 rtype vr; 43 ptype[2] pt; 44 } 45 46 alias vr this; 47 48 pure this(K)( in Region!(N,K) e ) { vr = e.vr; } 49 50 pure this(E...)( in E ext ) 51 if( is( typeof( rtype(ext) ) ) ) 52 { vr = rtype(ext); } 53 54 @property 55 { 56 ref ptype pos(){ return pt[0]; } 57 ref ptype size(){ return pt[1]; } 58 59 ptype pos() const { return pt[0]; } 60 ptype size() const { return pt[1]; } 61 62 ptype lim() const { return pt[0] + pt[1]; } 63 ptype lim( in ptype nl ) 64 { 65 pt[1] = nl - pt[0]; 66 return nl; 67 } 68 } 69 70 bool opBinaryRight(string op, E, alias string AS)( in Vector!(N,E,AS) p ) const 71 if( op == "in" && is(typeof(typeof(p).init[0] > rtype.init[0])) ) 72 { 73 foreach( i; 0 .. N ) 74 if( p[i] < vr[i] || p[i] >= vr[i] + vr[i+N] ) 75 return false; 76 return true; 77 } 78 79 static if(N==1) 80 { 81 bool opBinaryRight(string op, E)( in E p ) const 82 if( isNumeric!E && op == "in" ) 83 { return p >= vr[0] && p < vr[0] + vr[1]; } 84 } 85 86 bool opBinaryRight(string op, E)( in Region!(N,E) p ) const 87 if( is( generalType!(T,E) ) && op == "in" ) 88 { return ( p.pt[0] in this ) && ( p.pt[1] in this ); } 89 90 /+ logic and +/ 91 auto overlap(E)( in Region!(N,E) reg ) const 92 { 93 ptype r1, r2; 94 95 foreach( i; 0 .. N ) 96 { 97 r1[i] = min( max( pos[i], reg.pos[i] ), lim[i] ); 98 r2[i] = max( min( lim[i], reg.lim[i] ), pos[i] ); 99 } 100 101 return selftype( r1, r2 - r1 ); 102 } 103 104 auto overlapLocal(E)( in Region!(N,E) reg ) const 105 { 106 auto buf = overlap( selftype( ptype(reg.pt[0]) + pt[0], reg.pt[1] ) ); 107 return selftype( buf.pt[0] - pt[0], buf.pt[1] ); 108 } 109 110 auto expand(E)( in Region!(N,E) reg ) const 111 { 112 ptype r1, r2; 113 114 foreach( i; 0 .. N ) 115 { 116 r1[i] = min( pos[i], reg.pos[i], lim[i], reg.lim[i] ); 117 r2[i] = max( pos[i], reg.pos[i], lim[i], reg.lim[i] ); 118 } 119 120 return selftype( r1, r2 - r1 ); 121 } 122 123 auto expand(E)( in E pnt ) const 124 if( isCompatibleVector!(N,T,E) ) 125 { 126 ptype r1, r2; 127 128 foreach( i; 0 .. N ) 129 { 130 r1[i] = min( pos[i], lim[i], pnt[i] ); 131 r2[i] = max( pos[i], lim[i], pnt[i] ); 132 } 133 134 return selftype( r1, r2 - r1 ); 135 } 136 } 137 138 alias Region!(1,float) fRegion1; 139 alias Region!(2,float) fRegion2; 140 alias Region!(3,float) fRegion3; 141 142 alias Region!(1,int) iRegion1; 143 alias Region!(2,int) iRegion2; 144 alias Region!(3,int) iRegion3; 145 146 unittest 147 { 148 auto a = fRegion1( 1, 5 ); 149 assert( 2 in a ); 150 assert( 8 !in a ); 151 assert( a.lim[0] == 6 ); 152 auto b = fRegion1( 2, 3 ); 153 assert( b in a ); 154 } 155 156 unittest 157 { 158 auto a = fRegion1(1,5); 159 auto b = fRegion1(2,5); 160 assert( a.overlap(b) == b.overlap(a) ); 161 assert( a.overlap(b) == fRegion1(2,4) ); 162 163 assert( a.overlapLocal(b) == fRegion1(2,3) ); 164 } 165 166 unittest 167 { 168 auto a = fRegion1(1,2); 169 auto b = fRegion1(4,2); 170 assert( a.expand(b) = fRegion1(1,5) ); 171 } 172 173 unittest 174 { 175 auto a = fRegion3( vec3(0,0,0), vec3(1,1,1) ); 176 assert( vec3(.5,.2,.8) in a ); 177 assert( a == a.expand( vec3(.2,.3,.4) ) ); 178 assert( a != a.expand( vec3(1.2,.3,.4) ) ); 179 assert( fRegion3( vec3(0,0,0), vec3(1.2,1,1) ) == 180 a.expand( vec3(1.2,.3,.4) ) ); 181 }