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

Comparing ray/src/util/eplus_adduvf.c (file contents):
Revision 2.6 by greg, Tue Feb 11 22:01:44 2014 UTC vs.
Revision 2.15 by greg, Fri Feb 28 19:14:10 2014 UTC

# Line 16 | Line 16 | static const char RCSid[] = "$Id$";
16   #include "rtprocess.h"
17  
18   #ifndef NSAMPLES
19 < #define NSAMPLES        80000                   /* number of samples to use */
19 > #define NSAMPLES        80000                   /* default number of samples */
20   #endif
21  
22 + #define SURF_EPS        0.0005                  /* surface testing epsilon */
23 +
24   char            *progname;                      /* global argv[0] */
25  
26 + int             nsamps = NSAMPLES;              /* number of samples to use */
27 +
28   char            temp_octree[128];               /* temporary octree */
29  
30   const char      UVF_PNAME[] =
31 <                        "ZoneProperty:UserViewFactor:bySurfaceName";
31 >                        "ZoneProperty:UserViewFactors:bySurfaceName";
32  
33 + const char      SUBSURF_PNAME[] =
34 +                        "FenestrationSurface:Detailed";
35 +
36   const char      ADD_HEADER[] =
37                          "\n!+++ User View Factors computed by Radiance +++!\n\n";
38  
39   #define NAME_FLD        1                       /* name field always first? */
40  
41 + #define SS_BASE_FLD     4                       /* subsurface base surface */
42 + #define SS_VERT_FLD     10                      /* subsurface vertex count */
43 +
44   typedef struct {
45 <        const char      *pname;                 /* parameter type name */
45 >        const char      *pname;                 /* object type name */
46          short           zone_fld;               /* zone field index */
47          short           vert_fld;               /* vertex field index */
48   } SURF_PTYPE;           /* surface type we're interested in */
# Line 43 | Line 53 | const SURF_PTYPE       surf_type[] = {
53                  {"RoofCeiling:Detailed", 3, 9},
54                  {"Wall:Detailed", 3, 9},
55                  {NULL}
56 <        };
56 >        };                              /* IDF surface types */
57  
58   typedef struct s_zone {
59          const char      *zname;                 /* zone name */
60          struct s_zone   *next;                  /* next zone in list */
61          int             nsurf;                  /* surface count */
62 <        IDF_PARAMETER   *pfirst;                /* first matching parameter */
63 <        IDF_PARAMETER   *plast;                 /* last matching parameter */
62 >        int             ntotal;                 /* surfaces+subsurfaces */
63 >        IDF_OBJECT      *pfirst;                /* first matching object */
64 >        IDF_OBJECT      *plast;                 /* last before subsurfaces */
65 >        float           *area_redu;             /* subsurface area per surf. */
66   } ZONE;                 /* a list of collected zone surfaces */
67  
68   ZONE            *zone_list = NULL;      /* our list of zones */
69  
70 + LUTAB           zonesurf_lut =          /* zone surface lookup table */
71 +                        LU_SINIT(NULL,NULL);
72 +
73   IDF_LOADED      *our_idf = NULL;        /* loaded/modified IDF */
74  
75 + typedef struct {
76 +        FVECT           norm;           /* surface normal */
77 +        double          area;           /* surface area */
78 +        int             nv;             /* number of vertices */
79 +        FVECT           vl[3];          /* vertex list (extends struct) */
80 + } SURFACE;              /* a polygonal surface */
81 +
82 + typedef struct {
83 +        FVECT           sdir[3];        /* UVW unit sampling vectors */
84 +        double          poff;           /* W-offset for plane of polygon */
85 +        double          area_left;      /* area left to sample */
86 +        int             samp_left;      /* remaining samples */
87 +        int             wd;             /* output file descriptor */
88 + } POLYSAMP;             /* structure for polygon sampling */
89 +
90   /* Create a new zone and push to top of our list */
91   static ZONE *
92 < new_zone(const char *zname, IDF_PARAMETER *param)
92 > new_zone(const char *zname, IDF_OBJECT *param)
93   {
94          ZONE    *znew = (ZONE *)malloc(sizeof(ZONE));
95  
# Line 68 | Line 98 | new_zone(const char *zname, IDF_PARAMETER *param)
98          znew->zname = zname;                    /* assumes static */
99          znew->next = zone_list;
100          znew->pfirst = znew->plast = param;
101 <        znew->nsurf = 1;
101 >        znew->ntotal = znew->nsurf = 1;
102 >        znew->area_redu = NULL;
103          return(zone_list = znew);
104   }
105  
106   /* Add the detailed surface (polygon) to the named zone */
107   static ZONE *
108 < add2zone(IDF_PARAMETER *param, const char *zname)
108 > add2zone(IDF_OBJECT *param, const char *zname)
109   {
110 <        ZONE    *zptr;
110 >        IDF_FIELD       *nfp = idf_getfield(param, NAME_FLD);
111 >        ZONE            *zptr;
112 >        LUENT           *lep;
113  
114 +        if (nfp == NULL) {
115 +                fputs(progname, stderr);
116 +                fputs(": surface missing name field!\n", stderr);
117 +                return(NULL);
118 +        }
119          for (zptr = zone_list; zptr != NULL; zptr = zptr->next)
120                  if (!strcmp(zptr->zname, zname))
121                          break;
122 <        if (zptr == NULL)
123 <                return(new_zone(zname, param));
124 <                                                /* keep surfaces together */
125 <        if (!idf_movparam(our_idf, param, zptr->plast))
122 >        if (zptr == NULL) {
123 >                zptr = new_zone(zname, param);
124 >        } else {                                /* keep surfaces together */
125 >                if (!idf_movobject(our_idf, param, zptr->plast))
126 >                        return(NULL);
127 >                zptr->plast = param;
128 >                zptr->nsurf++;
129 >                zptr->ntotal++;
130 >        }
131 >                                                /* add to lookup table */
132 >        lep = lu_find(&zonesurf_lut, nfp->val);
133 >        if (lep == NULL)
134                  return(NULL);
135 <        zptr->plast = param;
136 <        zptr->nsurf++;
135 >        if (lep->data != NULL) {
136 >                fputs(progname, stderr);
137 >                fputs(": duplicate surface name '", stderr);
138 >                fputs(nfp->val, stderr);
139 >                fputs("'\n", stderr);
140 >                return(NULL);
141 >        }
142 >        lep->key = nfp->val;
143 >        lep->data = (char *)zptr;
144          return(zptr);
145   }
146  
147 < /* Return field for vertices in the given parameter */
147 > /* Add a subsurface by finding its base surface and the corresponding zone */
148 > static ZONE *
149 > add_subsurf(IDF_OBJECT *param)
150 > {
151 >        IDF_FIELD       *bfp = idf_getfield(param, SS_BASE_FLD);
152 >        ZONE            *zptr;
153 >        LUENT           *lep;
154 >
155 >        if (bfp == NULL) {
156 >                fputs(progname, stderr);
157 >                fputs(": missing base field name in subsurface!\n", stderr);
158 >                return(NULL);
159 >        }
160 >        lep = lu_find(&zonesurf_lut, bfp->val); /* find base zone */
161 >        if (lep == NULL || lep->data == NULL) {
162 >                fputs(progname, stderr);
163 >                fputs(": cannot find referenced base surface '", stderr);
164 >                fputs(bfp->val, stderr);
165 >                fputs("'\n", stderr);
166 >                return(NULL);
167 >        }
168 >        zptr = (ZONE *)lep->data;               /* add this subsurface */
169 >        if (!idf_movobject(our_idf, param, zptr->plast))
170 >                return(NULL);
171 >        zptr->ntotal++;
172 >        return(zptr);
173 > }
174 >
175 > /* Return field for vertices in the given object */
176   static IDF_FIELD *
177 < get_vlist(IDF_PARAMETER *param, const char *zname)
177 > get_vlist(IDF_OBJECT *param, const char *zname)
178   {
179 <        int             i = 0;
180 <        IDF_FIELD       *fptr;
181 <                                                /* check for surface type */
182 <        while (strcmp(surf_type[i].pname, param->pname))
183 <                if (surf_type[++i].pname == NULL)
184 <                        return(NULL);
179 > #define itm_len         (sizeof(IDF_FIELD)+6)
180 >        static char             fld_buf[4*itm_len];
181 >        static char             *next_fbp = fld_buf;
182 >        int                     i;
183 >        IDF_FIELD               *res;
184 >                                                /* check if subsurface */
185 >        if (!strcmp(param->pname, SUBSURF_PNAME)) {
186 >                if (zname != NULL) {
187 >                        LUENT   *lep = lu_find(&zonesurf_lut,
188 >                                        idf_getfield(param,SS_BASE_FLD)->val);
189 >                        if (strcmp((*(ZONE *)lep->data).zname, zname))
190 >                                return(NULL);
191 >                }
192 >                res = idf_getfield(param, SS_VERT_FLD);
193 >        } else {
194 >                i = 0;                          /* check for surface type */
195 >                while (strcmp(surf_type[i].pname, param->pname))
196 >                        if (surf_type[++i].pname == NULL)
197 >                                return(NULL);
198  
199 <        if (zname != NULL) {                    /* matches specified zone? */
200 <                fptr = idf_getfield(param, surf_type[i].zone_fld);
201 <                if (fptr == NULL || strcmp(fptr->val, zname))
199 >                if (zname != NULL) {            /* matches specified zone? */
200 >                        IDF_FIELD       *fptr = idf_getfield(param, surf_type[i].zone_fld);
201 >                        if (fptr == NULL || strcmp(fptr->val, zname))
202 >                                return(NULL);
203 >                }
204 >                res = idf_getfield(param, surf_type[i].vert_fld);
205 >        }
206 >        if (!res->val[0]) {                     /* hack for missing #vert */
207 >                IDF_FIELD       *fptr;
208 >                if (next_fbp >= fld_buf+sizeof(fld_buf))
209 >                        next_fbp = fld_buf;
210 >                i = 0;                          /* count vertices */
211 >                for (fptr = res->next; fptr != NULL; fptr = fptr->next)
212 >                        ++i;
213 >                if (i % 3)
214                          return(NULL);
215 +                fptr = res->next;
216 +                res = (IDF_FIELD *)next_fbp; next_fbp += itm_len;
217 +                res->next = fptr;
218 +                res->rem = "";
219 +                sprintf(res->val, "%d", i/3);
220          }
221 <                                                /* return field for #verts */
222 <        return(idf_getfield(param, surf_type[i].vert_fld));
221 >        return(res);
222 > #undef itm_len
223   }
224  
225 + /* Get/allocate surface polygon */
226 + static SURFACE *
227 + get_surface(IDF_FIELD *fptr)
228 + {
229 +        SURFACE *surf;
230 +        int     nv;
231 +        FVECT   e1, e2, vc;
232 +        int     i, j;
233 +                                        /* get number of vertices */
234 +        if (fptr == NULL || (nv = atoi(fptr->val)) < 3) {
235 +                fputs(progname, stderr);
236 +                fputs(": bad vertex count for surface!\n", stderr);
237 +                return(NULL);
238 +        }
239 +        surf = (SURFACE *)malloc(sizeof(SURFACE)+sizeof(FVECT)*(nv-3));
240 +        if (surf == NULL)
241 +                return(NULL);
242 +        surf->nv = nv;
243 +        for (i = nv; i--; )             /* reverse vertex order/orientation */
244 +                for (j = 0; j < 3; j++) {
245 +                        fptr = fptr->next;
246 +                        if (fptr == NULL) {
247 +                                fputs(progname, stderr);
248 +                                fputs(": missing vertex in get_surface()\n", stderr);
249 +                                free(surf);
250 +                                return(NULL);
251 +                        }
252 +                        if ((surf->vl[i][j] = atof(fptr->val)) == 0 &&
253 +                                                        !isflt(fptr->val)) {
254 +                                fputs(progname, stderr);
255 +                                fputs(": bad vertex in get_surface()\n", stderr);
256 +                                free(surf);
257 +                                return(NULL);
258 +                        }
259 +                }
260 +                                        /* compute area and normal */
261 +        surf->norm[0] = surf->norm[1] = surf->norm[2] = 0;
262 +        VSUB(e1, surf->vl[1], surf->vl[0]);
263 +        for (i = 2; i < nv; i++) {
264 +                VSUB(e2, surf->vl[i], surf->vl[0]);
265 +                fcross(vc, e1, e2);
266 +                surf->norm[0] += vc[0];
267 +                surf->norm[1] += vc[1];
268 +                surf->norm[2] += vc[2];
269 +                VCOPY(e1, e2);
270 +        }
271 +        surf->area = .5 * normalize(surf->norm);
272 +        if (surf->area == 0) {
273 +                fputs(progname, stderr);
274 +                fputs(": degenerate polygon in get_surface()\n", stderr);
275 +                free(surf);
276 +                return(NULL);
277 +        }
278 +        return(surf);
279 + }
280 +
281   /* Convert surface to Radiance with modifier based on unique name */
282   static int
283 < rad_surface(IDF_PARAMETER *param, FILE *ofp)
283 > rad_surface(IDF_OBJECT *param, FILE *ofp)
284   {
285          const char      *sname = idf_getfield(param,NAME_FLD)->val;
286          IDF_FIELD       *fptr = get_vlist(param, NULL);
287 <        int             nvert, i;
287 >        const char      **fargs;
288 >        int             nvert, i, j;
289  
290          if (fptr == NULL || (nvert = atoi(fptr->val)) < 3) {
291                  fprintf(stderr, "%s: bad surface '%s'\n", progname, sname);
292                  return(0);
293          }
294 +        fargs = (const char **)malloc(sizeof(const char *)*3*nvert);
295 +        if (fargs == NULL)
296 +                return(0);
297          fprintf(ofp, "\nvoid glow '%s'\n0\n0\n4 1 1 1 0\n", sname);
298          fprintf(ofp, "\n'%s' polygon 's_%s'\n0\n0\n%d\n", sname, sname, 3*nvert);
299 <        while (nvert--) {
300 <                for (i = 3; i--; ) {
299 >        for (j = nvert; j--; ) {                /* get arguments in reverse */
300 >                for (i = 0; i < 3; i++) {
301                          fptr = fptr->next;
302                          if (fptr == NULL || !isflt(fptr->val)) {
303                                  fprintf(stderr,
# Line 134 | Line 305 | rad_surface(IDF_PARAMETER *param, FILE *ofp)
305                                                  progname, param->pname, sname);
306                                  return(0);
307                          }
308 +                        fargs[3*j + i] = fptr->val;
309 +                }
310 +        }
311 +        for (j = 0; j < nvert; j++) {           /* output reversed verts */
312 +                for (i = 0; i < 3; i++) {
313                          fputc('\t', ofp);
314 <                        fputs(fptr->val, ofp);
314 >                        fputs(fargs[3*j + i], ofp);
315                  }
316                  fputc('\n', ofp);
317          }
318 +        free(fargs);
319          return(!ferror(ofp));
320   }
321  
322 + /* Convert subsurface to Radiance with modifier based on unique name */
323 + static double
324 + rad_subsurface(IDF_OBJECT *param, FILE *ofp)
325 + {
326 +        const char      *sname = idf_getfield(param,NAME_FLD)->val;
327 +        SURFACE         *surf = get_surface(get_vlist(param, NULL));
328 +        double          area;
329 +        int             i;
330 +
331 +        if (surf == NULL) {
332 +                fprintf(stderr, "%s: bad subsurface '%s'\n", progname, sname);
333 +                return(-1.);
334 +        }
335 +        fprintf(ofp, "\nvoid glow '%s'\n0\n0\n4 1 1 1 0\n", sname);
336 +        fprintf(ofp, "\n'%s' polygon 'ss_%s'\n0\n0\n%d\n",
337 +                                                sname, sname, 3*surf->nv);
338 +        for (i = 0; i < surf->nv; i++) {        /* offset vertices */
339 +                FVECT   vert;
340 +                VSUM(vert, surf->vl[i], surf->norm, 2.*SURF_EPS);
341 +                fprintf(ofp, "\t%.12f %.12f %.12f\n", vert[0], vert[1], vert[2]);
342 +        }
343 +        area = surf->area;
344 +        free(surf);
345 +        if (ferror(ofp))
346 +                return(-1.);
347 +        return(area);
348 + }
349 +
350   /* Start rcontrib process */
351   static int
352   start_rcontrib(SUBPROC *pd, ZONE *zp)
353   {
354 < #define BASE_AC         5
354 > #define BASE_AC         6
355          static char     *base_av[BASE_AC] = {
356 <                                "rcontrib", "-ff", "-h", "-x", "1"
356 >                                "rcontrib", "-V+", "-fff", "-h", "-x", "1"
357                          };
358          char            cbuf[300];
359          char            **av;
360          FILE            *ofp;
361 <        IDF_PARAMETER   *pptr;
362 <        int             i, n;
361 >        IDF_OBJECT      *pptr;
362 >        IDF_FIELD       *fptr;
363 >        int             i, j, n;
364                                                  /* start oconv command */
365          sprintf(cbuf, "oconv - > '%s'", temp_octree);
366          if ((ofp = popen(cbuf, "w")) == NULL) {
# Line 163 | Line 369 | start_rcontrib(SUBPROC *pd, ZONE *zp)
369                  return(0);
370          }
371                                                  /* allocate argument list */
372 <        av = (char **)malloc(sizeof(char *)*(BASE_AC+4+2*zp->nsurf));
372 >        av = (char **)malloc(sizeof(char *)*(BASE_AC+4+2*(zp->ntotal)));
373          if (av == NULL)
374                  return(0);
375          for (i = 0; i < BASE_AC; i++)
376                  av[i] = base_av[i];
377 <        sprintf(cbuf, "%d", NSAMPLES);
377 >        sprintf(cbuf, "%d", nsamps);
378          av[i++] = "-c";
379 <        av[i++] = cbuf;                         /* add modifier arguments */
380 <        for (n = zp->nsurf, pptr = zp->pfirst; n--; pptr = pptr->dnext) {
381 <                IDF_FIELD       *fptr = idf_getfield(pptr,NAME_FLD);
379 >        av[i++] = cbuf;                         /* add modifiers & surfaces */
380 >        for (n = 0, pptr = zp->pfirst; n < zp->nsurf; n++, pptr = pptr->dnext) {
381 >                fptr = idf_getfield(pptr,NAME_FLD);
382                  if (fptr == NULL || !fptr->val[0]) {
383                          fputs(progname, stderr);
384 <                        fputs(": missing name for surface parameter\n", stderr);
384 >                        fputs(": missing name for surface object\n", stderr);
385                          return(0);
386                  }
387                  if (!rad_surface(pptr, ofp))    /* add surface to octree */
# Line 183 | Line 389 | start_rcontrib(SUBPROC *pd, ZONE *zp)
389                  av[i++] = "-m";
390                  av[i++] = fptr->val;
391          }
392 +                                                /* now subsurfaces */
393 +        if (zp->ntotal > zp->nsurf) {
394 +                if (zp->area_redu != NULL)
395 +                        memset(zp->area_redu, 0, sizeof(float)*zp->nsurf);
396 +                else if ((zp->area_redu = (float *)calloc(zp->nsurf,
397 +                                                sizeof(float))) == NULL)
398 +                        return(0);
399 +        }
400 +        for ( ; n < zp->ntotal; n++, pptr = pptr->dnext) {
401 +                double          ssarea;
402 +                const char      *bname;
403 +                IDF_OBJECT      *pptr1;
404 +                fptr = idf_getfield(pptr,NAME_FLD);
405 +                if (fptr == NULL || !fptr->val[0]) {
406 +                        fputs(progname, stderr);
407 +                        fputs(": missing name for subsurface object\n", stderr);
408 +                        return(0);
409 +                }
410 +                                                /* add subsurface to octree */
411 +                if ((ssarea = rad_subsurface(pptr, ofp)) < 0)
412 +                        return(0);
413 +                                                /* mark area for subtraction */
414 +                bname = idf_getfield(pptr,SS_BASE_FLD)->val;
415 +                for (j = 0, pptr1 = zp->pfirst;
416 +                                j < zp->nsurf; j++, pptr1 = pptr1->dnext)
417 +                        if (!strcmp(idf_getfield(pptr1,NAME_FLD)->val, bname)) {
418 +                                zp->area_redu[j] += ssarea;
419 +                                break;
420 +                        }
421 +                av[i++] = "-m";
422 +                av[i++] = fptr->val;
423 +        }
424          if (pclose(ofp) != 0) {                 /* finish oconv */
425                  fputs(progname, stderr);
426                  fputs(": error running oconv process\n", stderr);
# Line 190 | Line 428 | start_rcontrib(SUBPROC *pd, ZONE *zp)
428          }
429          av[i++] = temp_octree;                  /* add final octree argument */
430          av[i] = NULL;
431 <        if (!open_process(pd, av)) {            /* start process */
431 >        if (open_process(pd, av) <= 0) {        /* start process */
432                  fputs(progname, stderr);
433                  fputs(": cannot start rcontrib process\n", stderr);
434                  return(0);
# Line 200 | Line 438 | start_rcontrib(SUBPROC *pd, ZONE *zp)
438   #undef BASE_AC
439   }
440  
203 typedef struct {
204        FVECT           sdir[3];        /* XYZ unit sampling vectors */
205        double          poff;           /* Z-offset for plane of polygon */
206        double          area_left;      /* area left to sample */
207        int             samp_left;      /* remaining samples */
208        int             wd;             /* output file descriptor */
209 } POLYSAMP;             /* structure for polygon sampling */
210
441   /* Initialize polygon sampling */
442   static Vert2_list *
443 < init_poly(POLYSAMP *ps, IDF_FIELD *f0, int nv)
443 > init_poly(POLYSAMP *ps, IDF_FIELD *f0)
444   {
445 <        IDF_FIELD       *fptr = f0;
446 <        int             i, j;
447 <        FVECT           *vl3, e1, e2, vc;
448 <        Vert2_list      *vl2 = polyAlloc(nv);
449 <
445 >        SURFACE         *surf;
446 >        Vert2_list      *vl2;
447 >        int             i;
448 >                                        /* get 3-D polygon vertices */
449 >        if ((surf = get_surface(f0)) == NULL)
450 >                return(NULL);
451 >        vl2 = polyAlloc(surf->nv);
452          if (vl2 == NULL)
453                  return(NULL);
222        vl2->p = ps;
223                                        /* get 3-D vertices */
224        vl3 = (FVECT *)malloc(sizeof(FVECT)*nv);
225        if (vl3 == NULL)
226                return(NULL);
227        for (i = nv; i--; )             /* reverse vertex ordering */
228                for (j = 0; j < 3; j++) {
229                        if (fptr == NULL) {
230                                fputs(progname, stderr);
231                                fputs(": missing vertex in init_poly()\n", stderr);
232                                return(NULL);
233                        }
234                        vl3[i][j] = atof(fptr->val);
235                        fptr = fptr->next;
236                }
237                                        /* compute area and normal */
238        ps->sdir[2][0] = ps->sdir[2][1] = ps->sdir[2][2] = 0;
239        VSUB(e1, vl3[1], vl3[0]);
240        for (i = 2; i < nv; i++) {
241                VSUB(e2, vl3[i], vl3[0]);
242                fcross(vc, e1, e2);
243                ps->sdir[2][0] += vc[0];
244                ps->sdir[2][1] += vc[1];
245                ps->sdir[2][2] += vc[2];
246                VCOPY(e1, e2);
247        }
248        ps->area_left = .5 * normalize(ps->sdir[2]);
249        if (ps->area_left == .0) {
250                fputs(progname, stderr);
251                fputs(": degenerate polygon in init_poly()\n", stderr);
252                return(0);
253        }
454                                          /* create X & Y axes */
455 <        VCOPY(ps->sdir[0], e1);
456 <        normalize(ps->sdir[0]);
455 >        VCOPY(ps->sdir[2], surf->norm);
456 >        VSUB(ps->sdir[0], surf->vl[1], surf->vl[0]);
457 >        if (normalize(ps->sdir[0]) == 0)
458 >                return(NULL);
459          fcross(ps->sdir[1], ps->sdir[2], ps->sdir[0]);
460                                          /* compute plane offset */
461 <        ps->poff = DOT(vl3[0], ps->sdir[2]);
461 >        ps->poff = DOT(surf->vl[0], ps->sdir[2]);
462                                          /* assign 2-D vertices */
463 <        for (i = 0; i < nv; i++) {
464 <                vl2->v[i].mX = DOT(vl3[i], ps->sdir[0]);
465 <                vl2->v[i].mY = DOT(vl3[i], ps->sdir[1]);
463 >        for (i = 0; i < surf->nv; i++) {
464 >                vl2->v[i].mX = DOT(surf->vl[i], ps->sdir[0]);
465 >                vl2->v[i].mY = DOT(surf->vl[i], ps->sdir[1]);
466          }
467 <        free(vl3);                      /* it's ready! */
467 >        ps->area_left = surf->area;
468 >        free(surf);                     /* it's ready! */
469 >        vl2->p = (void *)ps;
470          return(vl2);
471   }
472  
# Line 280 | Line 484 | sample_triangle(const Vert2_list *vl2, int a, int b, i
484          for (i = 3; i--; ) {
485                  orig[i] = vl2->v[a].mX*ps->sdir[0][i] +
486                                  vl2->v[a].mY*ps->sdir[1][i] +
487 <                                (ps->poff+.001)*ps->sdir[2][i];
487 >                                (ps->poff+SURF_EPS)*ps->sdir[2][i];
488                  ab[i] = (vl2->v[b].mX - vl2->v[a].mX)*ps->sdir[0][i] +
489                                  (vl2->v[b].mY - vl2->v[a].mY)*ps->sdir[1][i];
490                  ac[i] = (vl2->v[c].mX - vl2->v[a].mX)*ps->sdir[0][i] +
# Line 334 | Line 538 | sample_triangle(const Vert2_list *vl2, int a, int b, i
538   }
539  
540   /* Sample the given surface */
541 < static int
542 < sample_surface(IDF_PARAMETER *param, int wd)
541 > static double
542 > sample_surface(IDF_OBJECT *param, int wd)
543   {
340        IDF_FIELD       *fptr = get_vlist(param, NULL);
544          POLYSAMP        psamp;
545 +        double          area;
546          int             nv;
547          Vert2_list      *vlist2;
548                                          /* set up our polygon sampler */
549 <        if (fptr == NULL || (nv = atoi(fptr->val)) < 3 ||
346 <                        (vlist2 = init_poly(&psamp, fptr->next, nv)) == NULL) {
549 >        if ((vlist2 = init_poly(&psamp, get_vlist(param, NULL))) == NULL) {
550                  fprintf(stderr, "%s: bad polygon %s '%s'\n",
551                                  progname, param->pname,
552                                  idf_getfield(param,NAME_FLD)->val);
553 <                return(0);
553 >                return(-1.);
554          }
555 <        psamp.samp_left = NSAMPLES;     /* assign samples & destination */
555 >        psamp.samp_left = nsamps;       /* assign samples & destination */
556          psamp.wd = wd;
557 +                                        /* hack for subsurface sampling */
558 +        psamp.poff += 2.*SURF_EPS * !strcmp(param->pname, SUBSURF_PNAME);
559 +
560 +        area = psamp.area_left;         /* remember starting surface area */
561                                          /* sample each subtriangle */
562          if (!polyTriangulate(vlist2, &sample_triangle))
563 <                return(0);
563 >                return(-1.);
564          polyFree(vlist2);               /* clean up and return */
565 <        return(1);
565 >        return(area);
566   }
567  
568   /* Compute User View Factors using open rcontrib process */
569   static int
570   compute_uvfs(SUBPROC *pd, ZONE *zp)
571   {
572 <        IDF_PARAMETER   *pptr, *pout, *pptr1;
572 >        IDF_OBJECT      *pptr, *pout, *pptr1;
573          float           *uvfa;
574          char            uvfbuf[24];
575          int             n, m;
576 <                                                /* create output parameter */
577 <        pout = idf_newparam(our_idf, UVF_PNAME,
578 <                        "    ! computed by Radiance\n        ", zp->plast);
576 >                                                /* create output object */
577 >        pout = idf_newobject(our_idf, UVF_PNAME,
578 >                        "    ! computed by Radiance\n        ", our_idf->plast);
579          if (pout == NULL) {
580                  fputs(progname, stderr);
581 <                fputs(": cannot create new IDF parameter\n", stderr);
581 >                fputs(": cannot create new IDF object\n", stderr);
582                  return(0);
583          }
584          if (!idf_addfield(pout, zp->zname,
# Line 381 | Line 588 | compute_uvfs(SUBPROC *pd, ZONE *zp)
588                  return(0);
589          }
590                                                  /* allocate read buffer */
591 <        uvfa = (float *)malloc(sizeof(float)*3*zp->nsurf);
591 >        uvfa = (float *)malloc(sizeof(float)*3*zp->ntotal);
592          if (uvfa == NULL)
593                  return(0);
594                                                  /* UVFs from each surface */
595 <        for (n = zp->nsurf, pptr = zp->pfirst; n--; pptr = pptr->dnext) {
595 >        for (n = 0, pptr = zp->pfirst; n < zp->ntotal; n++, pptr = pptr->dnext) {
596                  double  vfsum = 0;
597 +                double  adj_factor;
598                                                  /* send samples to rcontrib */
599 <                if (!sample_surface(pptr, pd->w))
599 >                if ((adj_factor = sample_surface(pptr, pd->w)) < 0)
600                          return(0);
601 +                if (zp->area_redu == NULL)
602 +                        adj_factor = 1.;
603 +                else                            /* comp. for subsurface area */
604 +                        adj_factor /= adj_factor - zp->area_redu[n];
605                                                  /* read results */
606 <                if (readbuf(pd->r, (char *)uvfa, sizeof(float)*3*zp->nsurf) !=
607 <                                sizeof(float)*3*zp->nsurf) {
606 >                if (readbuf(pd->r, (char *)uvfa, sizeof(float)*3*zp->ntotal) !=
607 >                                sizeof(float)*3*zp->ntotal) {
608                          fputs(progname, stderr);
609                          fputs(": read error from rcontrib process\n", stderr);
610                          return(0);
611                  }
612                                                  /* append UVF fields */
613                  for (m = 0, pptr1 = zp->pfirst;
614 <                                m < zp->nsurf; m++, pptr1 = pptr1->dnext) {
615 <                        vfsum += uvfa[3*m + 1];
616 <                        if (pptr1 == pptr) {
617 <                                if (uvfa[3*m + 1] > .001)
618 <                                        fprintf(stderr,
614 >                                m < zp->ntotal; m++, pptr1 = pptr1->dnext) {
615 >                        const double    uvf = uvfa[3*m + 1] * adj_factor;
616 >                        vfsum += uvf;
617 >                        if (pptr1 == pptr && uvf > .001)
618 >                                fprintf(stderr,
619                  "%s: warning - non-zero self-VF (%.1f%%) for surface '%s'\n",
620 <                                                progname, 100.*uvfa[3*m + 1],
620 >                                                progname, 100.*uvf,
621                                                  idf_getfield(pptr,NAME_FLD)->val);
622 <                                continue;       /* don't record self-factor */
411 <                        }
412 <                        sprintf(uvfbuf, "%.4f", uvfa[3*m + 1]);
622 >                        sprintf(uvfbuf, "%.4f", uvf);
623                          if (!idf_addfield(pout,
624                                          idf_getfield(pptr,NAME_FLD)->val, NULL) ||
625                                  !idf_addfield(pout,
626                                          idf_getfield(pptr1,NAME_FLD)->val, NULL) ||
627                                  !idf_addfield(pout, uvfbuf,
628 <                                                (n || m < zp->nsurf-2) ?
629 <                                                        "\n        " : "\n\n")) {
628 >                                                (n+m < 2*zp->ntotal-2) ?
629 >                                                "\n        " : "\n\n")) {
630                                  fputs(progname, stderr);
631                                  fputs(": error adding UVF fields\n", stderr);
632                                  return(0);
# Line 464 | Line 674 | main(int argc, char *argv[])
674   {
675          int             incl_comments = 1;
676          char            *origIDF, *revIDF;
677 <        IDF_PARAMETER   *pptr;
677 >        IDF_OBJECT      *pptr;
678          int             i;
679  
680 <        progname = argv[0];
681 <        if (argc > 2 && !strcmp(argv[1], "-c")) {
682 <                incl_comments = -1;             /* output header only */
683 <                ++argv; --argc;
684 <        }
685 <        if ((argc < 2) | (argc > 3)) {
686 <                fputs("Usage: ", stderr);
687 <                fputs(progname, stderr);
688 <                fputs(" [-c] Model.idf [Revised.idf]\n", stderr);
689 <                return(1);
690 <        }
691 <        origIDF = argv[1];
692 <        revIDF = (argc == 2) ? argv[1] : argv[2];
680 >        progname = *argv++; argc--;             /* get options if any */
681 >        while (argc > 1 && argv[0][0] == '-')
682 >                switch (argv[0][1]) {
683 >                case 'c':                       /* elide comments */
684 >                        incl_comments = -1;             /* header only */
685 >                        argv++; argc--;
686 >                        continue;
687 >                case 's':                       /* samples */
688 >                        nsamps = 1000*atoi(*++argv);
689 >                        argv++; argc -= 2;
690 >                        continue;
691 >                default:
692 >                        fputs(progname, stderr);
693 >                        fputs(": unknown option '", stderr);
694 >                        fputs(argv[0], stderr);
695 >                        fputs("'\n", stderr);
696 >                        goto userr;
697 >                }
698 >        if ((argc < 1) | (argc > 2))
699 >                goto userr;
700 >        origIDF = argv[0];
701 >        revIDF = (argc == 1) ? argv[0] : argv[1];
702                                                  /* load Input Data File */
703          our_idf = idf_load(origIDF);
704          if (our_idf == NULL) {
# Line 490 | Line 709 | main(int argc, char *argv[])
709                  return(1);
710          }
711                                                  /* remove existing UVFs */
712 <        if ((pptr = idf_getparam(our_idf, UVF_PNAME)) != NULL) {
713 <                IDF_PARAMETER   *pnext;
712 >        if ((pptr = idf_getobject(our_idf, UVF_PNAME)) != NULL) {
713 >                IDF_OBJECT      *pnext;
714                  fputs(progname, stderr);
715                  fputs(": removing previous User View Factors\n", stderr);
716                  do {
717                          pnext = pptr->pnext;
718 <                        idf_delparam(our_idf, pptr);
718 >                        idf_delobject(our_idf, pptr);
719                  } while (pnext != NULL);
720          }
721                                                  /* add to header */
# Line 506 | Line 725 | main(int argc, char *argv[])
725                  idf_add2hdr(our_idf, ADD_HEADER);
726                                                  /* gather zone surfaces */
727          for (i = 0; surf_type[i].pname != NULL; i++)
728 <                for (pptr = idf_getparam(our_idf, surf_type[i].pname);
728 >                for (pptr = idf_getobject(our_idf, surf_type[i].pname);
729                                  pptr != NULL; pptr = pptr->pnext) {
730                          IDF_FIELD       *fptr = idf_getfield(pptr,
731                                                          surf_type[i].zone_fld);
# Line 518 | Line 737 | main(int argc, char *argv[])
737                          if (add2zone(pptr, fptr->val) == NULL)
738                                  return(1);
739                  }
740 +                                                /* add subsurfaces */
741 +        for (pptr = idf_getobject(our_idf, SUBSURF_PNAME);
742 +                        pptr != NULL; pptr = pptr->pnext)
743 +                if (add_subsurf(pptr) == NULL)
744 +                        return(1);
745                                                  /* run rcontrib on each zone */
746          if (!compute_zones())
747                  return(1);
# Line 530 | Line 754 | main(int argc, char *argv[])
754                  return(1);
755          }
756          return(0);                              /* finito! */
757 + userr:
758 +        fputs("Usage: ", stderr);
759 +        fputs(progname, stderr);
760 +        fputs(" [-c][-s Ksamps] Model.idf [Revised.idf]\n", stderr);
761 +        return(1);
762   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines