1 /**************************************************************************/
2 /*  Copyright 2012 Tim Day                                                */
3 /*                                                                        */
4 /*  This file is part of Evolvotron                                       */
5 /*                                                                        */
6 /*  Evolvotron is free software: you can redistribute it and/or modify    */
7 /*  it under the terms of the GNU General Public License as published by  */
8 /*  the Free Software Foundation, either version 3 of the License, or     */
9 /*  (at your option) any later version.                                   */
10 /*                                                                        */
11 /*  Evolvotron is distributed in the hope that it will be useful,         */
12 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
13 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
14 /*  GNU General Public License for more details.                          */
15 /*                                                                        */
16 /*  You should have received a copy of the GNU General Public License     */
17 /*  along with Evolvotron.  If not, see <http://www.gnu.org/licenses/>.   */
18 /**************************************************************************/
19 
20 /*! \file
21   \brief Interfaces and implementation for specific Function classes.
22   As much as possible of the implementation should be pushed into the FunctionBoilerplate template.
23 */
24 
25 #ifndef _functions_filter_h_
26 #define _functions_filter_h_
27 
28 #include "common.h"
29 
30 #include "function_boilerplate.h"
31 
32 //------------------------------------------------------------------------------------------
33 
34 FUNCTION_BEGIN(FunctionFilter2D,2,1,false,0)
35 
36   //! Evaluate function.
evaluate(const XYZ & p)37   virtual const XYZ evaluate(const XYZ& p) const
38     {
39       return
40 	arg(0)(p)
41 	-(
42 	  arg(0)(p+XYZ(param(0),0.0,0.0))
43 	  +arg(0)(p+XYZ(-param(0),0.0,0.0))
44 	  +arg(0)(p+XYZ(0.0,param(1),0.0))
45 	  +arg(0)(p+XYZ(0.0,-param(1),0.0))
46 	  )/4.0;
47     }
48 
49 FUNCTION_END(FunctionFilter2D)
50 
51 //------------------------------------------------------------------------------------------
52 
53 FUNCTION_BEGIN(FunctionFilter3D,3,1,false,0)
54 
55   //! Evaluate function.
evaluate(const XYZ & p)56   virtual const XYZ evaluate(const XYZ& p) const
57     {
58       return
59 	arg(0)(p)
60 	-(
61 	  arg(0)(p+XYZ(param(0),0.0,0.0))
62 	  +arg(0)(p+XYZ(-param(0),0.0,0.0))
63 	  +arg(0)(p+XYZ(0.0,param(1),0.0))
64 	  +arg(0)(p+XYZ(0.0,-param(1),0.0))
65 	  +arg(0)(p+XYZ(0.0,0.0,param(2)))
66 	  +arg(0)(p+XYZ(0.0,0.0,-param(2)))
67 	  )/6.0;
68     }
69 
70 FUNCTION_END(FunctionFilter3D)
71 
72 //------------------------------------------------------------------------------------------
73 
74 //! Function returning average value of evenly spaced samples between two points
75 FUNCTION_BEGIN(FunctionAverageSamples,3,1,true,FnIterative)
76 
77   //! Evaluate function.
evaluate(const XYZ & p)78   virtual const XYZ evaluate(const XYZ& p) const
79     {
80       const XYZ baseline(param(0),param(1),param(2));
81 
82       XYZ p0;
83       XYZ p1;
84       XYZ delta;
85 
86       if (iterations()==1)
87 	{
88 	  p0=p;
89 	  p1=p;
90 	  delta=XYZ(0.0,0.0,0.0);
91 	}
92       else
93 	{
94 	  // In the case of two iterations the samples will be at p0 and p1
95 	  p0=p-baseline;
96 	  p1=p+baseline;
97 	  delta=(p1-p0)/(iterations()-1);
98 	}
99 
100       XYZ ret(0.0,0.0,0.0);
101       XYZ ps=p0;
102 
103       for (uint i=0;i<iterations();i++)
104 	{
105 	  ret+=arg(0)(ps);
106 	  ps+=delta;
107 	}
108       ret/=iterations();
109       return ret;
110     }
111 
112 FUNCTION_END(FunctionAverageSamples)
113 
114 //------------------------------------------------------------------------------------------
115 
116 //! Similar to average samples except one end has a higher weighting
117 FUNCTION_BEGIN(FunctionStreak,3,1,true,FnIterative)
118 
119   //! Evaluate function.
evaluate(const XYZ & p)120   virtual const XYZ evaluate(const XYZ& p) const
121     {
122       const XYZ baseline(param(0),param(1),param(2));
123 
124       XYZ p0;
125       XYZ p1;
126       XYZ delta;
127 
128       if (iterations()==1)
129 	{
130 	  p0=p;
131 	  p1=p;
132 	  delta=XYZ(0.0,0.0,0.0);
133 	}
134       else
135 	{
136 	  p0=p;
137 	  p1=p+baseline;
138 	  delta=(p1-p0)/(iterations()-1);
139 	}
140 
141       XYZ ret(0.0,0.0,0.0);
142       XYZ ps=p0;
143       real w=0.0;
144 
145       for (uint i=0;i<iterations();i++)
146 	{
147 	  const real k=1.0-static_cast<real>(i)/iterations();
148 	  ret+=k*arg(0)(ps);
149 	  w+=k;
150 	  ps+=delta;
151 	}
152       ret/=w;
153       return ret;
154     }
155 
156 FUNCTION_END(FunctionStreak)
157 
158 //------------------------------------------------------------------------------------------
159 
160 //! Average of samples around a ring
161 FUNCTION_BEGIN(FunctionAverageRing,1,1,true,FnIterative)
162 
163   //! Evaluate function.
evaluate(const XYZ & p)164   virtual const XYZ evaluate(const XYZ& p) const
165     {
166       if (iterations()==1) return arg(0)(p);
167 
168       const real da=2.0*M_PI/iterations();
169       XYZ ret(0.0,0.0,0.0);
170       for (uint i=0;i<iterations();i++)
171 	{
172 	  const real a=i*da;
173 	  const XYZ delta(param(0)*cos(a),param(0)*sin(a),0.0);
174 	  ret+=arg(0)(p+delta);
175 	}
176       return ret/iterations();
177     }
178 
179 FUNCTION_END(FunctionAverageRing)
180 
181 //------------------------------------------------------------------------------------------
182 
183 //! Like FunctionAverageRing but subtract off the centre value
184 FUNCTION_BEGIN(FunctionFilterRing,1,1,true,FnIterative)
185 
186   //! Evaluate function.
evaluate(const XYZ & p)187   virtual const XYZ evaluate(const XYZ& p) const
188     {
189       if (iterations()==1) return XYZ(0.0,0.0,0.0);
190 
191       const real da=2.0*M_PI/iterations();
192       XYZ ret(0.0,0.0,0.0);
193       for (uint i=0;i<iterations();i++)
194 	{
195 	  const real a=i*da;
196 	  const XYZ delta(param(0)*cos(a),param(0)*sin(a),0.0);
197 	  ret+=arg(0)(p+delta);
198 	}
199       return ret/iterations()-arg(0)(p);
200     }
201 
202 FUNCTION_END(FunctionFilterRing)
203 
204 //------------------------------------------------------------------------------------------
205 
206 //! Function similar to FunctionAverageSamples but doing convolution
207 FUNCTION_BEGIN(FunctionConvolveSamples,3,2,true,FnIterative)
208 
209   //! Evaluate function.
evaluate(const XYZ & p)210   virtual const XYZ evaluate(const XYZ& p) const
211     {
212       const XYZ baseline(param(0),param(1),param(2));
213 
214       XYZ p0;
215       XYZ p1;
216       XYZ delta;
217 
218       if (iterations()==1)
219 	{
220 	  p0=p;
221 	  p1=p;
222 	  delta=XYZ(0.0,0.0,0.0);
223 	}
224       else
225 	{
226 	  p0=p-baseline;
227 	  p1=p+baseline;
228 	  delta=(p1-p0)/(iterations()-1);
229 	}
230 
231       XYZ ret(0.0,0.0,0.0);
232       XYZ pd(0.0,0.0,0.0);
233 
234       for (uint i=0;i<iterations();i++)
235 	{
236 	  //! \todo Hmmm.. this is cross product, not inner product
237 	  ret+=(arg(0)(p+pd)*arg(1)(pd));
238 	  pd+=delta;
239 	}
240       ret/=iterations();
241       return ret;
242     }
243 
244 FUNCTION_END(FunctionConvolveSamples)
245 
246 //------------------------------------------------------------------------------------------
247 
248 //! Function summing decreasing amounts of higher frequency versions of image
249 FUNCTION_BEGIN(FunctionAccumulateOctaves,0,1,true,FnIterative)
250 
251   //! Evaluate function.
evaluate(const XYZ & p)252   virtual const XYZ evaluate(const XYZ& p) const
253     {
254       XYZ ret(0.0,0.0,0.0);
255       real k=0.0;
256       for (uint i=0;i<iterations();i++)
257 	{
258 	  const real scale=(1<<i);
259 	  const real iscale=1.0/scale;
260 	  ret+=iscale*(arg(0)(scale*p));
261 	  k+=iscale;
262 	}
263       ret/=k;
264       return ret;
265     }
266 
267 FUNCTION_END(FunctionAccumulateOctaves)
268 
269 //------------------------------------------------------------------------------------------
270 
271 #endif
272 
273