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 }