ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/interp2d.c
(Generate patch)

Comparing ray/src/common/interp2d.c (file contents):
Revision 2.12 by greg, Fri Feb 15 19:15:16 2013 UTC vs.
Revision 2.16 by greg, Thu Mar 11 01:58:59 2021 UTC

# Line 23 | Line 23 | static const char RCSid[] = "$Id$";
23   * to reduce the influence of distant neighbors.  This yields a
24   * smooth interpolation regardless of how the sample points are
25   * initially distributed.  Evaluation is accelerated by use of
26 < * a fast approximation to the atan2(y,x) function and an array
27 < * of flags indicating where weights are (nearly) zero.
26 > * a fast approximation to the atan2(y,x) function and a low-res
27 > * map indicating where sample weights are significant.
28   ****************************************************************/
29  
30   #include <stdio.h>
# Line 41 | Line 41 | typedef struct {
41          float   dm;             /* distance measure in this direction */
42   } SAMPORD;
43  
44 + /* private routine to encode sample diameter with range checks */
45 + static int
46 + encode_diameter(const INTERP2 *ip, double d)
47 + {
48 +        const int       ed = ENCODE_DIA(ip, d);
49 +
50 +        if (ed <= 0)
51 +                return(0);
52 +        if (ed >= 0xffff)
53 +                return(0xffff);
54 +        return(ed);
55 + }
56 +
57   /* Allocate a new set of interpolation samples (caller assigns spt[] array) */
58   INTERP2 *
59   interp2_alloc(int nsamps)
# Line 57 | Line 70 | interp2_alloc(int nsamps)
70          nip->ns = nsamps;
71          nip->dmin = 1;          /* default minimum diameter */
72          nip->smf = NI2DSMF;     /* default smoothing factor */
73 +        nip->c_data = NULL;
74          nip->da = NULL;
75                                  /* caller must assign spt[] array */
76          return(nip);
# Line 66 | Line 80 | interp2_alloc(int nsamps)
80   INTERP2 *
81   interp2_realloc(INTERP2 *ip, int nsamps)
82   {
83 +        INTERP2 *old_ip = ip;
84 +
85          if (ip == NULL)
86                  return(interp2_alloc(nsamps));
87          if (nsamps <= 1) {
# Line 79 | Line 95 | interp2_realloc(INTERP2 *ip, int nsamps)
95                  ip->da = NULL;
96          }
97          ip = (INTERP2 *)realloc(ip, sizeof(INTERP2)+sizeof(float)*2*(nsamps-1));
98 <        if (ip == NULL)
99 <                return(NULL);
98 >        if (ip == NULL) {
99 >                if (nsamps <= ip->ns)
100 >                        ip = old_ip;
101 >                else
102 >                        return(NULL);
103 >        }
104          ip->ns = nsamps;
105          return(ip);
106   }
# Line 100 | Line 120 | interp2_spacing(INTERP2 *ip, double mind)
120          ip->dmin = mind;
121   }
122  
103 /* Modify smoothing parameter by the given factor */
104 void
105 interp2_smooth(INTERP2 *ip, double sf)
106 {
107        if ((ip->smf *= sf) < NI2DSMF)
108                ip->smf = NI2DSMF;
109 }
110
111 /* private call-back to sort position index */
112 static int
113 cmp_spos(const void *p1, const void *p2)
114 {
115        const SAMPORD   *so1 = (const SAMPORD *)p1;
116        const SAMPORD   *so2 = (const SAMPORD *)p2;
117
118        if (so1->dm > so2->dm)
119                return 1;
120        if (so1->dm < so2->dm)
121                return -1;
122        return 0;
123 }
124
125 /* private routine to order samples in a particular direction */
126 static void
127 sort_samples(SAMPORD *sord, const INTERP2 *ip, double ang)
128 {
129        const double    cosd = cos(ang);
130        const double    sind = sin(ang);
131        int             i;
132
133        for (i = ip->ns; i--; ) {
134                sord[i].si = i;
135                sord[i].dm = cosd*ip->spt[i][0] + sind*ip->spt[i][1];
136        }
137        qsort(sord, ip->ns, sizeof(SAMPORD), &cmp_spos);
138 }
139
140 /* private routine to encode sample diameter with range checks */
141 static int
142 encode_diameter(const INTERP2 *ip, double d)
143 {
144        const int       ed = ENCODE_DIA(ip, d);
145
146        if (ed <= 0)
147                return(0);
148        if (ed >= 0xffff)
149                return(0xffff);
150        return(ed);
151 }
152
123   /* Compute unnormalized weight for a position relative to a sample */
124   double
125   interp2_wti(INTERP2 *ip, const int i, double x, double y)
# Line 244 | Line 214 | influence_flood(INTERP2 *ip, const int i, unsigned sho
214                  influence_flood(ip, i, visited, xfi, yfi+1);
215   }
216  
217 + /* private call to compute sample influence maps */
218 + static void
219 + map_influence(INTERP2 *ip)
220 + {
221 +        unsigned short  visited[NI2DIM];
222 +        int             fgi[2];
223 +        int             i, j;
224 +
225 +        for (i = ip->ns; i--; ) {
226 +                for (j = NI2DIM; j--; ) {
227 +                        ip->da[i].infl[j] = 0;
228 +                        visited[j] = 0;
229 +                }
230 +                interp2_flagpos(fgi, ip, ip->spt[i][0], ip->spt[i][1]);
231 +
232 +                influence_flood(ip, i, visited, fgi[0], fgi[1]);
233 +        }
234 + }
235 +
236 + /* Modify smoothing parameter by the given factor */
237 + void
238 + interp2_smooth(INTERP2 *ip, double sf)
239 + {
240 +        float   old_smf = ip->smf;
241 +
242 +        if ((ip->smf *= sf) < NI2DSMF)
243 +                ip->smf = NI2DSMF;
244 +                                        /* need to recompute influence maps? */
245 +        if (ip->da != NULL && (old_smf*.85 > ip->smf) |
246 +                                (ip->smf > old_smf*1.15))
247 +                map_influence(ip);
248 + }
249 +
250 + /* private call-back to sort position index */
251 + static int
252 + cmp_spos(const void *p1, const void *p2)
253 + {
254 +        const SAMPORD   *so1 = (const SAMPORD *)p1;
255 +        const SAMPORD   *so2 = (const SAMPORD *)p2;
256 +
257 +        if (so1->dm > so2->dm)
258 +                return 1;
259 +        if (so1->dm < so2->dm)
260 +                return -1;
261 +        return 0;
262 + }
263 +
264 + /* private routine to order samples in a particular direction */
265 + static void
266 + sort_samples(SAMPORD *sord, const INTERP2 *ip, double ang)
267 + {
268 +        const double    cosd = cos(ang);
269 +        const double    sind = sin(ang);
270 +        int             i;
271 +
272 +        for (i = ip->ns; i--; ) {
273 +                sord[i].si = i;
274 +                sord[i].dm = cosd*ip->spt[i][0] + sind*ip->spt[i][1];
275 +        }
276 +        qsort(sord, ip->ns, sizeof(SAMPORD), cmp_spos);
277 + }
278 +
279   /* (Re)compute anisotropic basis function interpolant (normally automatic) */
280   int
281   interp2_analyze(INTERP2 *ip)
282   {
283          SAMPORD *sortord;
284          int     *rightrndx, *leftrndx, *endrndx;
285 <        int     i, j, bd;
285 >        int     i, bd;
286                                          /* sanity checks */
287          if (ip == NULL)
288                  return(0);
# Line 275 | Line 307 | interp2_analyze(INTERP2 *ip)
307          if (ip->grid2 <= FTINY*ip->dmin*ip->dmin)
308                  return(0);
309                                          /* allocate analysis data */
310 <        ip->da = (struct interp2_samp *)calloc( ip->ns,
311 <                                        sizeof(struct interp2_samp) );
310 >        ip->da = (struct interp2_samp *)malloc(
311 >                                sizeof(struct interp2_samp)*ip->ns );
312          if (ip->da == NULL)
313                  return(0);
314                                          /* allocate temporary arrays */
# Line 319 | Line 351 | interp2_analyze(INTERP2 *ip)
351                                          /* find nearest neighbors each side */
352              for (i = ip->ns; i--; ) {
353                  const int       ii = sortord[i].si;
354 +                int             j;
355                                          /* preload with large radii */
356                  ip->da[ii].dia[bd] =
357                  ip->da[ii].dia[bd+NI2DIR/2] = encode_diameter(ip,
# Line 343 | Line 376 | interp2_analyze(INTERP2 *ip)
376          free(rightrndx);
377          free(leftrndx);
378          free(endrndx);
379 <                                        /* fill influence maps */
380 <        for (i = ip->ns; i--; ) {
348 <                unsigned short  visited[NI2DIM];
349 <                int             fgi[2];
350 <
351 <                for (j = NI2DIM; j--; ) visited[j] = 0;
352 <                interp2_flagpos(fgi, ip, ip->spt[i][0], ip->spt[i][1]);
353 <                influence_flood(ip, i, visited, fgi[0], fgi[1]);
354 <        }
379 >                                        /* map sample influence areas */
380 >        map_influence(ip);
381          return(1);                      /* all done */
382   }
383  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines