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.2 by greg, Sun Feb 9 22:19:30 2014 UTC vs.
Revision 2.11 by greg, Sat Feb 15 01:31:36 2014 UTC

# Line 7 | Line 7 | static const char RCSid[] = "$Id$";
7   *      G.Ward for LBNL
8   */
9  
10 #include <stdio.h>
10   #include <stdlib.h>
11 < #include <string.h>
11 > #include "rtio.h"
12 > #include "rtmath.h"
13 > #include "random.h"
14   #include "eplus_idf.h"
15   #include "triangulate.h"
16   #include "rtprocess.h"
17  
18   #ifndef NSAMPLES
19 < #define NSAMPLES        100000                  /* 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 < char            temp_octree[128];                       /* temporary octree */
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 <                        "!+++ User View Factors computed by Radiance +++!\n";
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 */
49  
50   const SURF_PTYPE        surf_type[] = {
51                  {"BuildingSurface:Detailed", 4, 10},
52 +                {"Floor:Detailed", 3, 9},
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   } ZONE;                 /* a list of collected zone surfaces */
66  
67   ZONE            *zone_list = NULL;      /* our list of zones */
68  
69 + LUTAB           zonesurf_lut =          /* zone surface lookup table */
70 +                        LU_SINIT(NULL,NULL);
71 +
72   IDF_LOADED      *our_idf = NULL;        /* loaded/modified IDF */
73  
74 + typedef struct {
75 +        FVECT           norm;           /* surface normal */
76 +        double          area;           /* surface area */
77 +        int             nv;             /* number of vertices */
78 +        FVECT           vl[3];          /* vertex list (extends struct) */
79 + } SURFACE;              /* a polygonal surface */
80 +
81 + typedef struct {
82 +        FVECT           sdir[3];        /* UVW unit sampling vectors */
83 +        double          poff;           /* W-offset for plane of polygon */
84 +        double          area_left;      /* area left to sample */
85 +        int             samp_left;      /* remaining samples */
86 +        int             wd;             /* output file descriptor */
87 + } POLYSAMP;             /* structure for polygon sampling */
88 +
89   /* Create a new zone and push to top of our list */
90   static ZONE *
91 < new_zone(const char *zname, IDF_PARAMETER *param)
91 > new_zone(const char *zname, IDF_OBJECT *param)
92   {
93          ZONE    *znew = (ZONE *)malloc(sizeof(ZONE));
94  
# Line 64 | Line 97 | new_zone(const char *zname, IDF_PARAMETER *param)
97          znew->zname = zname;                    /* assumes static */
98          znew->next = zone_list;
99          znew->pfirst = znew->plast = param;
100 <        znew->nsurf = 1;
100 >        znew->ntotal = znew->nsurf = 1;
101          return(zone_list = znew);
102   }
103  
104   /* Add the detailed surface (polygon) to the named zone */
105   static ZONE *
106 < add2zone(IDF_PARAMETER *param, const char *zname)
106 > add2zone(IDF_OBJECT *param, const char *zname)
107   {
108 <        ZONE    *zptr;
108 >        IDF_FIELD       *nfp = idf_getfield(param, NAME_FLD);
109 >        ZONE            *zptr;
110 >        LUENT           *lep;
111  
112 +        if (nfp == NULL) {
113 +                fputs(progname, stderr);
114 +                fputs(": surface missing name field!\n", stderr);
115 +                return(NULL);
116 +        }
117          for (zptr = zone_list; zptr != NULL; zptr = zptr->next)
118                  if (!strcmp(zptr->zname, zname))
119                          break;
120 <        if (zptr == NULL)
121 <                return(new_zone(zname, param));
122 <                                                /* keep surfaces together */
123 <        if (!idf_movparam(our_idf, param, zptr->plast))
120 >        if (zptr == NULL) {
121 >                zptr = new_zone(zname, param);
122 >        } else {                                /* keep surfaces together */
123 >                if (!idf_movobject(our_idf, param, zptr->plast))
124 >                        return(NULL);
125 >                zptr->plast = param;
126 >                zptr->nsurf++;
127 >                zptr->ntotal++;
128 >        }
129 >                                                /* add to lookup table */
130 >        lep = lu_find(&zonesurf_lut, nfp->val);
131 >        if (lep == NULL)
132                  return(NULL);
133 <        zptr->plast = param;
134 <        zptr->nsurf++;
133 >        if (lep->data != NULL) {
134 >                fputs(progname, stderr);
135 >                fputs(": duplicate surface name '", stderr);
136 >                fputs(nfp->val, stderr);
137 >                fputs("'\n", stderr);
138 >                return(NULL);
139 >        }
140 >        lep->key = nfp->val;
141 >        lep->data = (char *)zptr;
142          return(zptr);
143   }
144  
145 < /* Determine if a parameter is a surface in the indicated zone */
146 < static int
147 < in_zone(IDF_PARAMETER *param, const char *zname)
145 > /* Add a subsurface by finding its base surface and the corresponding zone */
146 > static ZONE *
147 > add_subsurf(IDF_OBJECT *param)
148   {
149 +        IDF_FIELD       *bfp = idf_getfield(param, SS_BASE_FLD);
150 +        ZONE            *zptr;
151 +        LUENT           *lep;
152 +
153 +        if (bfp == NULL) {
154 +                fputs(progname, stderr);
155 +                fputs(": missing base field name in subsurface!\n", stderr);
156 +                return(NULL);
157 +        }
158 +        lep = lu_find(&zonesurf_lut, bfp->val); /* find base zone */
159 +        if (lep == NULL || lep->data == NULL) {
160 +                fputs(progname, stderr);
161 +                fputs(": cannot find referenced base surface '", stderr);
162 +                fputs(bfp->val, stderr);
163 +                fputs("'\n", stderr);
164 +                return(NULL);
165 +        }
166 +        zptr = (ZONE *)lep->data;               /* add this subsurface */
167 +        if (!idf_movobject(our_idf, param, zptr->plast))
168 +                return(NULL);
169 +        zptr->ntotal++;
170 +        return(zptr);
171 + }
172 +
173 + /* Return field for vertices in the given object */
174 + static IDF_FIELD *
175 + get_vlist(IDF_OBJECT *param, const char *zname)
176 + {
177          int             i = 0;
178 <        IDF_FIELD       *fptr;
178 >                                                /* check if subsurface */
179 >        if (!strcmp(param->pname, SUBSURF_PNAME)) {
180 >                if (zname != NULL) {
181 >                        LUENT   *lep = lu_find(&zonesurf_lut,
182 >                                        idf_getfield(param,SS_BASE_FLD)->val);
183 >                        if (strcmp((*(ZONE *)lep->data).zname, zname))
184 >                                return(NULL);
185 >                }
186 >                return(idf_getfield(param, SS_VERT_FLD));
187 >        }
188                                                  /* check for surface type */
189          while (strcmp(surf_type[i].pname, param->pname))
190                  if (surf_type[++i].pname == NULL)
191 <                        return(0);
192 <                                                /* get zone field */
193 <        fptr = idf_getfield(param, surf_type[i].zone_fld);
194 <        if (fptr == NULL)
195 <                return(0);
196 <                                                /* check for match */
197 <        if (strcmp(fptr->arg, zname))
106 <                return(0);
191 >                        return(NULL);
192 >
193 >        if (zname != NULL) {                    /* matches specified zone? */
194 >                IDF_FIELD       *fptr = idf_getfield(param, surf_type[i].zone_fld);
195 >                if (fptr == NULL || strcmp(fptr->val, zname))
196 >                        return(NULL);
197 >        }
198                                                  /* return field for #verts */
199 <        return(surf_type[i].vert_fld);
199 >        return(idf_getfield(param, surf_type[i].vert_fld));
200   }
201  
202 + /* Get/allocate surface polygon */
203 + static SURFACE *
204 + get_surface(IDF_FIELD *fptr)
205 + {
206 +        SURFACE *surf;
207 +        int     nv;
208 +        FVECT   e1, e2, vc;
209 +        int     i, j;
210 +                                        /* get number of vertices */
211 +        if (fptr == NULL || (nv = atoi(fptr->val)) < 3) {
212 +                fputs(progname, stderr);
213 +                fputs(": bad vertex count for surface!\n", stderr);
214 +                return(NULL);
215 +        }
216 +        surf = (SURFACE *)malloc(sizeof(SURFACE)+sizeof(FVECT)*(nv-3));
217 +        if (surf == NULL)
218 +                return(NULL);
219 +        surf->nv = nv;
220 +        for (i = nv; i--; )             /* reverse vertex order/orientation */
221 +                for (j = 0; j < 3; j++) {
222 +                        fptr = fptr->next;
223 +                        if (fptr == NULL) {
224 +                                fputs(progname, stderr);
225 +                                fputs(": missing vertex in get_surface()\n", stderr);
226 +                                free(surf);
227 +                                return(NULL);
228 +                        }
229 +                        if ((surf->vl[i][j] = atof(fptr->val)) == 0 &&
230 +                                                        !isflt(fptr->val)) {
231 +                                fputs(progname, stderr);
232 +                                fputs(": bad vertex in get_surface()\n", stderr);
233 +                                free(surf);
234 +                                return(NULL);
235 +                        }
236 +                }
237 +                                        /* compute area and normal */
238 +        surf->norm[0] = surf->norm[1] = surf->norm[2] = 0;
239 +        VSUB(e1, surf->vl[1], surf->vl[0]);
240 +        for (i = 2; i < nv; i++) {
241 +                VSUB(e2, surf->vl[i], surf->vl[0]);
242 +                fcross(vc, e1, e2);
243 +                surf->norm[0] += vc[0];
244 +                surf->norm[1] += vc[1];
245 +                surf->norm[2] += vc[2];
246 +                VCOPY(e1, e2);
247 +        }
248 +        surf->area = .5 * normalize(surf->norm);
249 +        if (surf->area == 0) {
250 +                fputs(progname, stderr);
251 +                fputs(": degenerate polygon in get_surface()\n", stderr);
252 +                free(surf);
253 +                return(NULL);
254 +        }
255 +        return(surf);
256 + }
257 +
258   /* Convert surface to Radiance with modifier based on unique name */
259   static int
260 < rad_surface(const char *zname, IDF_PARAMETER *param, FILE *ofp)
260 > rad_surface(IDF_OBJECT *param, FILE *ofp)
261   {
262 <        const char      *sname = idf_getfield(param, NAME_FLD)->arg;
263 <        IDF_FIELD       *fptr = idf_getfield(param, in_zone(param, zname));
264 <        int             nvert, i;
262 >        const char      *sname = idf_getfield(param,NAME_FLD)->val;
263 >        IDF_FIELD       *fptr = get_vlist(param, NULL);
264 >        const char      **fargs;
265 >        int             nvert, i, j;
266  
267 <        if (fptr == NULL || (nvert = atoi(fptr->arg)) < 3) {
267 >        if (fptr == NULL || (nvert = atoi(fptr->val)) < 3) {
268                  fprintf(stderr, "%s: bad surface '%s'\n", progname, sname);
269                  return(0);
270          }
271 +        fargs = (const char **)malloc(sizeof(const char *)*3*nvert);
272 +        if (fargs == NULL)
273 +                return(0);
274          fprintf(ofp, "\nvoid glow '%s'\n0\n0\n4 1 1 1 0\n", sname);
275          fprintf(ofp, "\n'%s' polygon 's_%s'\n0\n0\n%d\n", sname, sname, 3*nvert);
276 <        while (nvert--) {
277 <                for (i = 3; i--; ) {
276 >        for (j = nvert; j--; ) {                /* get arguments in reverse */
277 >                for (i = 0; i < 3; i++) {
278                          fptr = fptr->next;
279 <                        if (fptr == NULL) {
279 >                        if (fptr == NULL || !isflt(fptr->val)) {
280                                  fprintf(stderr,
281 <                                "%s: missing vertex fields in surface '%s'\n",
282 <                                                progname, sname);
281 >                                        "%s: missing/bad vertex for %s '%s'\n",
282 >                                                progname, param->pname, sname);
283                                  return(0);
284                          }
285 +                        fargs[3*j + i] = fptr->val;
286 +                }
287 +        }
288 +        for (j = 0; j < nvert; j++) {           /* output reversed verts */
289 +                for (i = 0; i < 3; i++) {
290                          fputc('\t', ofp);
291 <                        fputs(fptr->arg, ofp);
291 >                        fputs(fargs[3*j + i], ofp);
292                  }
293                  fputc('\n', ofp);
294          }
295 +        free(fargs);
296          return(!ferror(ofp));
297   }
298  
299 < /* Strat rcontrib process */
299 > /* Convert subsurface to Radiance with modifier based on unique name */
300   static int
301 + rad_subsurface(IDF_OBJECT *param, FILE *ofp)
302 + {
303 +        const char      *sname = idf_getfield(param,NAME_FLD)->val;
304 +        SURFACE         *surf = get_surface(idf_getfield(param,SS_VERT_FLD));
305 +        int             i;
306 +
307 +        if (surf == NULL) {
308 +                fprintf(stderr, "%s: bad subsurface '%s'\n", progname, sname);
309 +                return(0);
310 +        }
311 +        fprintf(ofp, "\nvoid glow '%s'\n0\n0\n4 1 1 1 0\n", sname);
312 +        fprintf(ofp, "\n'%s' polygon 'ss_%s'\n0\n0\n%d\n",
313 +                                                sname, sname, 3*surf->nv);
314 +        for (i = 0; i < surf->nv; i++) {        /* offset vertices */
315 +                FVECT   vert;
316 +                VSUM(vert, surf->vl[i], surf->norm, 2.*SURF_EPS);
317 +                fprintf(ofp, "\t%.12f %.12f %.12f\n", vert[0], vert[1], vert[2]);
318 +        }
319 +        free(surf);
320 +        return(!ferror(ofp));
321 + }
322 +
323 + /* Start rcontrib process */
324 + static int
325   start_rcontrib(SUBPROC *pd, ZONE *zp)
326   {
327 < #define BASE_AC         3
327 > #define BASE_AC         6
328          static char     *base_av[BASE_AC] = {
329 <                                "rcontrib", "-ff", "-h"
329 >                                "rcontrib", "-V+", "-fff", "-h", "-x", "1"
330                          };
331          char            cbuf[300];
332          char            **av;
333          FILE            *ofp;
334 <        IDF_PARAMETER   *pptr;
334 >        IDF_OBJECT      *pptr;
335 >        IDF_FIELD       *fptr;
336          int             i, n;
337                                                  /* start oconv command */
338          sprintf(cbuf, "oconv - > '%s'", temp_octree);
# Line 160 | Line 342 | start_rcontrib(SUBPROC *pd, ZONE *zp)
342                  return(0);
343          }
344                                                  /* allocate argument list */
345 <        av = (char **)malloc(sizeof(char *)*(BASE_AC+4+2*zp->nsurf));
345 >        av = (char **)malloc(sizeof(char *)*(BASE_AC+4+2*(zp->ntotal)));
346          if (av == NULL)
347                  return(0);
348          for (i = 0; i < BASE_AC; i++)
349                  av[i] = base_av[i];
350 <        sprintf(cbuf, "%d", NSAMPLES);
350 >        sprintf(cbuf, "%d", nsamps);
351          av[i++] = "-c";
352 <        av[i++] = cbuf;                         /* add modifier arguments */
353 <        for (n = zp->nsurf, pptr = zp->pfirst; n--; pptr = pptr->dnext) {
354 <                IDF_FIELD       *fptr = idf_getfield(pptr, NAME_FLD);
355 <                if (fptr == NULL) {
352 >        av[i++] = cbuf;                         /* add modifiers & surfaces */
353 >        for (n = 0, pptr = zp->pfirst; n < zp->nsurf; n++, pptr = pptr->dnext) {
354 >                fptr = idf_getfield(pptr,NAME_FLD);
355 >                if (fptr == NULL || !fptr->val[0]) {
356                          fputs(progname, stderr);
357 <                        fputs(": missing name for surface parameter\n", stderr);
357 >                        fputs(": missing name for surface object\n", stderr);
358                          return(0);
359                  }
360 +                if (!rad_surface(pptr, ofp))    /* add surface to octree */
361 +                        return(0);
362                  av[i++] = "-m";
363 <                av[i++] = fptr->arg;
364 <                if (!rad_surface(zp->zname, pptr, ofp))
363 >                av[i++] = fptr->val;
364 >        }
365 >                                                /* now subsurfaces */
366 >        for ( ; n < zp->ntotal; n++, pptr = pptr->dnext) {
367 >                fptr = idf_getfield(pptr,NAME_FLD);
368 >                if (fptr == NULL || !fptr->val[0]) {
369 >                        fputs(progname, stderr);
370 >                        fputs(": missing name for subsurface object\n", stderr);
371                          return(0);
372 +                }
373 +                if (!rad_subsurface(pptr, ofp)) /* add surface to octree */
374 +                        return(0);
375 +                av[i++] = "-m";
376 +                av[i++] = fptr->val;
377          }
378          if (pclose(ofp) != 0) {                 /* finish oconv */
379                  fputs(progname, stderr);
# Line 187 | Line 382 | start_rcontrib(SUBPROC *pd, ZONE *zp)
382          }
383          av[i++] = temp_octree;                  /* add final octree argument */
384          av[i] = NULL;
385 <        if (!open_process(pd, av)) {            /* start process */
385 >        if (open_process(pd, av) <= 0) {        /* start process */
386                  fputs(progname, stderr);
387                  fputs(": cannot start rcontrib process\n", stderr);
388                  return(0);
# Line 197 | Line 392 | start_rcontrib(SUBPROC *pd, ZONE *zp)
392   #undef BASE_AC
393   }
394  
395 + /* Initialize polygon sampling */
396 + static Vert2_list *
397 + init_poly(POLYSAMP *ps, IDF_FIELD *f0)
398 + {
399 +        SURFACE         *surf;
400 +        Vert2_list      *vl2;
401 +        int             i;
402 +                                        /* get 3-D polygon vertices */
403 +        if ((surf = get_surface(f0)) == NULL)
404 +                return(NULL);
405 +        vl2 = polyAlloc(surf->nv);
406 +        if (vl2 == NULL)
407 +                return(NULL);
408 +                                        /* create X & Y axes */
409 +        VCOPY(ps->sdir[2], surf->norm);
410 +        VSUB(ps->sdir[0], surf->vl[1], surf->vl[0]);
411 +        if (normalize(ps->sdir[0]) == 0)
412 +                return(NULL);
413 +        fcross(ps->sdir[1], ps->sdir[2], ps->sdir[0]);
414 +                                        /* compute plane offset */
415 +        ps->poff = DOT(surf->vl[0], ps->sdir[2]);
416 +                                        /* assign 2-D vertices */
417 +        for (i = 0; i < surf->nv; i++) {
418 +                vl2->v[i].mX = DOT(surf->vl[i], ps->sdir[0]);
419 +                vl2->v[i].mY = DOT(surf->vl[i], ps->sdir[1]);
420 +        }
421 +        ps->area_left = surf->area;
422 +        free(surf);                     /* it's ready! */
423 +        vl2->p = (void *)ps;
424 +        return(vl2);
425 + }
426 +
427 + /* Generate samples on 2-D triangle */
428 + static int
429 + sample_triangle(const Vert2_list *vl2, int a, int b, int c)
430 + {
431 +        POLYSAMP        *ps = (POLYSAMP *)vl2->p;
432 +        float           *samp;
433 +        FVECT           orig;
434 +        FVECT           ab, ac;
435 +        double          area;
436 +        int             i, j, ns;
437 +                                        /* compute sampling axes */
438 +        for (i = 3; i--; ) {
439 +                orig[i] = vl2->v[a].mX*ps->sdir[0][i] +
440 +                                vl2->v[a].mY*ps->sdir[1][i] +
441 +                                (ps->poff+SURF_EPS)*ps->sdir[2][i];
442 +                ab[i] = (vl2->v[b].mX - vl2->v[a].mX)*ps->sdir[0][i] +
443 +                                (vl2->v[b].mY - vl2->v[a].mY)*ps->sdir[1][i];
444 +                ac[i] = (vl2->v[c].mX - vl2->v[a].mX)*ps->sdir[0][i] +
445 +                                (vl2->v[c].mY - vl2->v[a].mY)*ps->sdir[1][i];
446 +        }
447 +                                        /* compute number of samples to take */
448 +        area = .5*(vl2->v[a].mX*vl2->v[b].mY - vl2->v[b].mX*vl2->v[a].mY +
449 +                        vl2->v[b].mX*vl2->v[c].mY - vl2->v[c].mX*vl2->v[b].mY +
450 +                        vl2->v[c].mX*vl2->v[a].mY - vl2->v[a].mX*vl2->v[c].mY);
451 +        if (area < .0) {
452 +                fputs(progname, stderr);
453 +                fputs(": negative triangle area in sample_triangle()\n", stderr);
454 +                return(0);
455 +        }
456 +        if (area >= ps->area_left) {
457 +                ns = ps->samp_left;
458 +                ps->area_left = 0;
459 +        } else {
460 +                ns = (ps->samp_left*area/ps->area_left + .5);
461 +                ps->samp_left -= ns;
462 +                ps->area_left -= area;
463 +        }
464 +        if (ns <= 0)                    /* XXX should be error? */
465 +                return(1);
466 +                                        /* buffer sample rays */
467 +        samp = (float *)malloc(sizeof(float)*6*ns);
468 +        if (samp == NULL)
469 +                return(0);
470 +        for (i = ns; i--; ) {           /* stratified Monte Carlo sampling */
471 +                double  sv[4];
472 +                FVECT   dv;
473 +                multisamp(sv, 4, (i+frandom())/(double)ns);
474 +                sv[0] *= sv[1] = sqrt(sv[1]);
475 +                sv[1] = 1. - sv[1];
476 +                for (j = 3; j--; )
477 +                        samp[i*6 + j] = orig[j] + sv[0]*ab[j] + sv[1]*ac[j];
478 +                sv[2] = sqrt(sv[2]);
479 +                sv[3] *= 2.*PI;
480 +                dv[0] = tcos(sv[3]) * sv[2];
481 +                dv[1] = tsin(sv[3]) * sv[2];
482 +                dv[2] = sqrt(1. - sv[2]*sv[2]);
483 +                for (j = 3; j--; )
484 +                        samp[i*6 + 3 + j] = dv[0]*ps->sdir[0][j] +
485 +                                                dv[1]*ps->sdir[1][j] +
486 +                                                dv[2]*ps->sdir[2][j] ;
487 +        }
488 +                                        /* send to our process */
489 +        writebuf(ps->wd, (char *)samp, sizeof(float)*6*ns);
490 +        free(samp);                     /* that's it! */
491 +        return(1);
492 + }
493 +
494 + /* Sample the given surface */
495 + static int
496 + sample_surface(IDF_OBJECT *param, int wd)
497 + {
498 +        POLYSAMP        psamp;
499 +        int             nv;
500 +        Vert2_list      *vlist2;
501 +                                        /* set up our polygon sampler */
502 +        if ((vlist2 = init_poly(&psamp, get_vlist(param, NULL))) == NULL) {
503 +                fprintf(stderr, "%s: bad polygon %s '%s'\n",
504 +                                progname, param->pname,
505 +                                idf_getfield(param,NAME_FLD)->val);
506 +                return(0);
507 +        }
508 +        psamp.samp_left = nsamps;       /* assign samples & destination */
509 +        psamp.wd = wd;
510 +                                        /* hack for subsurface sampling */
511 +        psamp.poff += 2.*SURF_EPS * !strcmp(param->pname, SUBSURF_PNAME);
512 +                                        /* sample each subtriangle */
513 +        if (!polyTriangulate(vlist2, &sample_triangle))
514 +                return(0);
515 +        polyFree(vlist2);               /* clean up and return */
516 +        return(1);
517 + }
518 +
519   /* Compute User View Factors using open rcontrib process */
520   static int
521 < compute_uvfs(SUBPROC *pd, ZONE *sp)
521 > compute_uvfs(SUBPROC *pd, ZONE *zp)
522   {
523 <        
523 >        IDF_OBJECT      *pptr, *pout, *pptr1;
524 >        float           *uvfa;
525 >        char            uvfbuf[24];
526 >        int             n, m;
527 >                                                /* create output object */
528 >        pout = idf_newobject(our_idf, UVF_PNAME,
529 >                        "    ! computed by Radiance\n        ", our_idf->plast);
530 >        if (pout == NULL) {
531 >                fputs(progname, stderr);
532 >                fputs(": cannot create new IDF object\n", stderr);
533 >                return(0);
534 >        }
535 >        if (!idf_addfield(pout, zp->zname,
536 >                        "    !- Zone Name\n        ")) {
537 >                fputs(progname, stderr);
538 >                fputs(": cannot add zone name field\n", stderr);
539 >                return(0);
540 >        }
541 >                                                /* allocate read buffer */
542 >        uvfa = (float *)malloc(sizeof(float)*3*zp->ntotal);
543 >        if (uvfa == NULL)
544 >                return(0);
545 >                                                /* UVFs from each surface */
546 >        for (n = 0, pptr = zp->pfirst; n < zp->ntotal; n++, pptr = pptr->dnext) {
547 >                double  vfsum = 0;
548 >                                                /* send samples to rcontrib */
549 >                if (!sample_surface(pptr, pd->w))
550 >                        return(0);
551 >                                                /* read results */
552 >                if (readbuf(pd->r, (char *)uvfa, sizeof(float)*3*zp->ntotal) !=
553 >                                sizeof(float)*3*zp->ntotal) {
554 >                        fputs(progname, stderr);
555 >                        fputs(": read error from rcontrib process\n", stderr);
556 >                        return(0);
557 >                }
558 >                                                /* append UVF fields */
559 >                for (m = 0, pptr1 = zp->pfirst;
560 >                                m < zp->ntotal; m++, pptr1 = pptr1->dnext) {
561 >                        vfsum += uvfa[3*m + 1];
562 >                        if (pptr1 == pptr && uvfa[3*m + 1] > .001)
563 >                                fprintf(stderr,
564 >                "%s: warning - non-zero self-VF (%.1f%%) for surface '%s'\n",
565 >                                                progname, 100.*uvfa[3*m + 1],
566 >                                                idf_getfield(pptr,NAME_FLD)->val);
567 >                        sprintf(uvfbuf, "%.4f", uvfa[3*m + 1]);
568 >                        if (!idf_addfield(pout,
569 >                                        idf_getfield(pptr,NAME_FLD)->val, NULL) ||
570 >                                !idf_addfield(pout,
571 >                                        idf_getfield(pptr1,NAME_FLD)->val, NULL) ||
572 >                                !idf_addfield(pout, uvfbuf,
573 >                                                (n+m < 2*zp->ntotal-2) ?
574 >                                                "\n        " : "\n\n")) {
575 >                                fputs(progname, stderr);
576 >                                fputs(": error adding UVF fields\n", stderr);
577 >                                return(0);
578 >                        }
579 >                }
580 >                if (vfsum < 0.95)
581 >                        fprintf(stderr,
582 >                "%s: warning - missing %.1f%% of energy from surface '%s'\n",
583 >                                        progname, 100.*(1.-vfsum),
584 >                                        idf_getfield(pptr,NAME_FLD)->val);
585 >        }
586 >        free(uvfa);                             /* clean up and return */
587 >        return(1);
588   }
589  
590   /* Compute zone User View Factors */
# Line 210 | Line 593 | compute_zones(void)
593   {
594          ZONE    *zptr;
595                                                  /* temporary octree name */
596 <        if (temp_filename(temp_octree, sizeof(temp_octree), TEMPLATE) == NULL) {
214 <                fputs(progname, stderr);
215 <                fputs(": cannot create temporary octree\n", stderr);
216 <                return(0);
217 <        }
596 >        mktemp(strcpy(temp_octree, TEMPLATE));
597                                                  /* compute each zone */
598          for (zptr = zone_list; zptr != NULL; zptr = zptr->next) {
599                  SUBPROC rcproc;
# Line 240 | Line 619 | main(int argc, char *argv[])
619   {
620          int             incl_comments = 1;
621          char            *origIDF, *revIDF;
622 <        IDF_PARAMETER   *pptr;
622 >        IDF_OBJECT      *pptr;
623          int             i;
624  
625 <        progname = argv[0];
626 <        if (argc > 2 && !strcmp(argv[1], "-c")) {
627 <                incl_comments = -1;             /* output header only */
628 <                ++argv; --argc;
629 <        }
630 <        if ((argc < 2) | (argc > 3)) {
631 <                fputs("Usage: ", stderr);
632 <                fputs(progname, stderr);
633 <                fputs(" [-c] Model.idf [Revised.idf]\n", stderr);
634 <                return(1);
635 <        }
636 <        origIDF = argv[1];
637 <        revIDF = (argc == 2) ? argv[1] : argv[2];
625 >        progname = *argv++; argc--;             /* get options if any */
626 >        while (argc > 1 && argv[0][0] == '-')
627 >                switch (argv[0][1]) {
628 >                case 'c':                       /* elide comments */
629 >                        incl_comments = -1;             /* header only */
630 >                        argv++; argc--;
631 >                        continue;
632 >                case 's':                       /* samples */
633 >                        nsamps = 1000*atoi(*++argv);
634 >                        argv++; argc -= 2;
635 >                        continue;
636 >                default:
637 >                        fputs(progname, stderr);
638 >                        fputs(": unknown option '", stderr);
639 >                        fputs(argv[0], stderr);
640 >                        fputs("'\n", stderr);
641 >                        goto userr;
642 >                }
643 >        if ((argc < 1) | (argc > 2))
644 >                goto userr;
645 >        origIDF = argv[0];
646 >        revIDF = (argc == 1) ? argv[0] : argv[1];
647                                                  /* load Input Data File */
648          our_idf = idf_load(origIDF);
649          if (our_idf == NULL) {
# Line 266 | Line 654 | main(int argc, char *argv[])
654                  return(1);
655          }
656                                                  /* remove existing UVFs */
657 <        if ((pptr = idf_getparam(our_idf, UVF_PNAME)) != NULL) {
658 <                IDF_PARAMETER   *pnext;
657 >        if ((pptr = idf_getobject(our_idf, UVF_PNAME)) != NULL) {
658 >                IDF_OBJECT      *pnext;
659                  fputs(progname, stderr);
660                  fputs(": removing previous User View Factors\n", stderr);
661                  do {
662                          pnext = pptr->pnext;
663 <                        idf_delparam(our_idf, pptr);
663 >                        idf_delobject(our_idf, pptr);
664                  } while (pnext != NULL);
665          }
666                                                  /* add to header */
# Line 282 | Line 670 | main(int argc, char *argv[])
670                  idf_add2hdr(our_idf, ADD_HEADER);
671                                                  /* gather zone surfaces */
672          for (i = 0; surf_type[i].pname != NULL; i++)
673 <                for (pptr = idf_getparam(our_idf, surf_type[i].pname);
673 >                for (pptr = idf_getobject(our_idf, surf_type[i].pname);
674                                  pptr != NULL; pptr = pptr->pnext) {
675                          IDF_FIELD       *fptr = idf_getfield(pptr,
676                                                          surf_type[i].zone_fld);
# Line 291 | Line 679 | main(int argc, char *argv[])
679                                  fputs(": warning - missing zone field\n", stderr);
680                                  continue;
681                          }
682 <                        if (add2zone(pptr, fptr->arg) == NULL)
682 >                        if (add2zone(pptr, fptr->val) == NULL)
683                                  return(1);
684                  }
685 +                                                /* add subsurfaces */
686 +        for (pptr = idf_getobject(our_idf, SUBSURF_PNAME);
687 +                        pptr != NULL; pptr = pptr->pnext)
688 +                if (add_subsurf(pptr) == NULL)
689 +                        return(1);
690                                                  /* run rcontrib on each zone */
691          if (!compute_zones())
692                  return(1);
# Line 306 | Line 699 | main(int argc, char *argv[])
699                  return(1);
700          }
701          return(0);                              /* finito! */
702 + userr:
703 +        fputs("Usage: ", stderr);
704 +        fputs(progname, stderr);
705 +        fputs(" [-c][-s Ksamps] Model.idf [Revised.idf]\n", stderr);
706 +        return(1);
707   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines