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.17 by greg, Fri Mar 19 21:16:15 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 >                        free(old_ip);
103 >                        return(NULL);
104 >                }
105 >        }
106          ip->ns = nsamps;
107          return(ip);
108   }
# Line 100 | Line 122 | interp2_spacing(INTERP2 *ip, double mind)
122          ip->dmin = mind;
123   }
124  
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
125   /* Compute unnormalized weight for a position relative to a sample */
126   double
127   interp2_wti(INTERP2 *ip, const int i, double x, double y)
# Line 244 | Line 216 | influence_flood(INTERP2 *ip, const int i, unsigned sho
216                  influence_flood(ip, i, visited, xfi, yfi+1);
217   }
218  
219 + /* private call to compute sample influence maps */
220 + static void
221 + map_influence(INTERP2 *ip)
222 + {
223 +        unsigned short  visited[NI2DIM];
224 +        int             fgi[2];
225 +        int             i, j;
226 +
227 +        for (i = ip->ns; i--; ) {
228 +                for (j = NI2DIM; j--; ) {
229 +                        ip->da[i].infl[j] = 0;
230 +                        visited[j] = 0;
231 +                }
232 +                interp2_flagpos(fgi, ip, ip->spt[i][0], ip->spt[i][1]);
233 +
234 +                influence_flood(ip, i, visited, fgi[0], fgi[1]);
235 +        }
236 + }
237 +
238 + /* Modify smoothing parameter by the given factor */
239 + void
240 + interp2_smooth(INTERP2 *ip, double sf)
241 + {
242 +        float   old_smf = ip->smf;
243 +
244 +        if ((ip->smf *= sf) < NI2DSMF)
245 +                ip->smf = NI2DSMF;
246 +                                        /* need to recompute influence maps? */
247 +        if (ip->da != NULL && (old_smf*.85 > ip->smf) |
248 +                                (ip->smf > old_smf*1.15))
249 +                map_influence(ip);
250 + }
251 +
252 + /* private call-back to sort position index */
253 + static int
254 + cmp_spos(const void *p1, const void *p2)
255 + {
256 +        const SAMPORD   *so1 = (const SAMPORD *)p1;
257 +        const SAMPORD   *so2 = (const SAMPORD *)p2;
258 +
259 +        if (so1->dm > so2->dm)
260 +                return 1;
261 +        if (so1->dm < so2->dm)
262 +                return -1;
263 +        return 0;
264 + }
265 +
266 + /* private routine to order samples in a particular direction */
267 + static void
268 + sort_samples(SAMPORD *sord, const INTERP2 *ip, double ang)
269 + {
270 +        const double    cosd = cos(ang);
271 +        const double    sind = sin(ang);
272 +        int             i;
273 +
274 +        for (i = ip->ns; i--; ) {
275 +                sord[i].si = i;
276 +                sord[i].dm = cosd*ip->spt[i][0] + sind*ip->spt[i][1];
277 +        }
278 +        qsort(sord, ip->ns, sizeof(SAMPORD), cmp_spos);
279 + }
280 +
281   /* (Re)compute anisotropic basis function interpolant (normally automatic) */
282   int
283   interp2_analyze(INTERP2 *ip)
284   {
285          SAMPORD *sortord;
286          int     *rightrndx, *leftrndx, *endrndx;
287 <        int     i, j, bd;
287 >        int     i, bd;
288                                          /* sanity checks */
289          if (ip == NULL)
290                  return(0);
# Line 275 | Line 309 | interp2_analyze(INTERP2 *ip)
309          if (ip->grid2 <= FTINY*ip->dmin*ip->dmin)
310                  return(0);
311                                          /* allocate analysis data */
312 <        ip->da = (struct interp2_samp *)calloc( ip->ns,
313 <                                        sizeof(struct interp2_samp) );
312 >        ip->da = (struct interp2_samp *)malloc(
313 >                                sizeof(struct interp2_samp)*ip->ns );
314          if (ip->da == NULL)
315                  return(0);
316                                          /* allocate temporary arrays */
# Line 319 | Line 353 | interp2_analyze(INTERP2 *ip)
353                                          /* find nearest neighbors each side */
354              for (i = ip->ns; i--; ) {
355                  const int       ii = sortord[i].si;
356 +                int             j;
357                                          /* preload with large radii */
358                  ip->da[ii].dia[bd] =
359                  ip->da[ii].dia[bd+NI2DIR/2] = encode_diameter(ip,
# Line 343 | Line 378 | interp2_analyze(INTERP2 *ip)
378          free(rightrndx);
379          free(leftrndx);
380          free(endrndx);
381 <                                        /* fill influence maps */
382 <        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 <        }
381 >                                        /* map sample influence areas */
382 >        map_influence(ip);
383          return(1);                      /* all done */
384   }
385  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines