PageRenderTime 54ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/brlcad/branches/dmtogl/src/rt/viewweight.c

https://bitbucket.org/vrrm/brl-cad-copy-for-fast-history-browsing-in-git
C | 452 lines | 317 code | 61 blank | 74 comment | 52 complexity | 655ecbf27c6548800f022a95a9db1177 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, LGPL-2.1, Apache-2.0, AGPL-3.0, LGPL-3.0, GPL-3.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, 0BSD, BSD-3-Clause
  1. /* V I E W W E I G H T . C
  2. * BRL-CAD
  3. *
  4. * Copyright (c) 1988-2010 United States Government as represented by
  5. * the U.S. Army Research Laboratory.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public License
  9. * version 2.1 as published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this file; see the file named COPYING for more
  18. * information.
  19. */
  20. /** @file viewweight.c
  21. *
  22. * Ray Tracing program RTWEIGHT bottom half.
  23. *
  24. * This module outputs the weights and moments of a target model
  25. * using density values located in ".density" or "$HOME/.density"
  26. * Output is given in metric and english units, although input is
  27. * assumed in lbs/cu.in.
  28. *
  29. */
  30. #include "common.h"
  31. #include <stdlib.h>
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include <time.h>
  35. #include "vmath.h"
  36. #include "raytrace.h"
  37. #include "rtprivate.h"
  38. #include "db.h" /* Yes, I know I shouldn't be peeking, put I am only
  39. looking to see what units we prefer... */
  40. extern struct resource resource[];
  41. /* Viewing module specific "set" variables */
  42. struct bu_structparse view_parse[] = {
  43. {"", 0, (char *)0, 0, BU_STRUCTPARSE_FUNC_NULL}
  44. };
  45. const char title[] = "RT Weight";
  46. const char usage[] = "\
  47. Usage: rtweight [options] model.g objects...\n\
  48. Options:\n\
  49. -s # Grid size in pixels, default 512\n\
  50. -g # Grid cell width [and height] in mm\n\
  51. -G # Grid cell height [and width] in mm\n\
  52. -a Az Azimuth in degrees\n\
  53. -e Elev Elevation in degrees\n\
  54. -o file.out Weights and Moments output file\n\
  55. -M Read matrix, cmds on stdin\n\
  56. -r Report verbosely mass of each region\n\
  57. -x # Set librt debug flags\n\
  58. Files:\n\
  59. .density, OR\n\
  60. $HOME/.density\n\
  61. ";
  62. int noverlaps = 0;
  63. FILE *densityfp;
  64. char *densityfile;
  65. #define DENSITY_FILE ".density"
  66. #define MAXMATLS 32768
  67. fastf_t density[MAXMATLS];
  68. char *dens_name[MAXMATLS];
  69. struct datapoint {
  70. struct datapoint *next;
  71. vect_t centroid;
  72. fastf_t weight;
  73. fastf_t volume;
  74. };
  75. extern int rpt_overlap; /* report region verbosely */
  76. extern fastf_t cell_width; /* model space grid cell width */
  77. extern fastf_t cell_height; /* model space grid cell height */
  78. extern FILE *outfp; /* optional output file */
  79. extern char *outputfile; /* name of base of output file */
  80. extern int output_is_binary; /* !0 means output is binary */
  81. int
  82. hit(struct application *ap, struct partition *PartHeadp, struct seg *segp)
  83. {
  84. struct partition *pp;
  85. register struct xray *rp = &ap->a_ray;
  86. genptr_t addp;
  87. int part_count = 0;
  88. for ( pp = PartHeadp->pt_forw; pp != PartHeadp; pp = pp->pt_forw ) {
  89. register struct region *reg = pp->pt_regionp;
  90. register struct hit *ihitp = pp->pt_inhit;
  91. register struct hit *ohitp = pp->pt_outhit;
  92. register fastf_t depth;
  93. register struct datapoint *dp;
  94. if ( reg->reg_aircode )
  95. continue;
  96. /* fill in hit points and hit distances */
  97. VJOIN1(ihitp->hit_point, rp->r_pt, ihitp->hit_dist, rp->r_dir );
  98. VJOIN1(ohitp->hit_point, rp->r_pt, ohitp->hit_dist, rp->r_dir );
  99. depth = ohitp->hit_dist - ihitp->hit_dist;
  100. part_count++;
  101. /* add the datapoint structure in and then calculate it
  102. in parallel, the region structures are a shared resource */
  103. #if 0
  104. bu_log( "\nhit: partition %d\n", part_count );
  105. #endif
  106. dp = (struct datapoint *) bu_malloc( sizeof(struct datapoint), "dp");
  107. bu_semaphore_acquire( BU_SEM_SYSCALL );
  108. addp = reg->reg_udata;
  109. reg->reg_udata = (genptr_t) dp;
  110. dp->next = (struct datapoint *) addp;
  111. bu_semaphore_release( BU_SEM_SYSCALL );
  112. if ( density[ reg->reg_gmater ] < 0 ) {
  113. bu_log( "Material type %d used, but has no density file entry.\n", reg->reg_gmater );
  114. bu_semaphore_acquire( BU_SEM_SYSCALL );
  115. reg->reg_gmater = 0;
  116. bu_semaphore_release( BU_SEM_SYSCALL );
  117. }
  118. else if ( density[ reg->reg_gmater ] >= 0 ) {
  119. VBLEND2( dp->centroid, 0.5, ihitp->hit_point, 0.5, ohitp->hit_point );
  120. /* Compute mass in terms of grams */
  121. dp->weight = depth * density[reg->reg_gmater] *
  122. (fastf_t) reg->reg_los *
  123. cell_height * cell_height * 0.00001;
  124. dp->volume = depth * cell_height * cell_width;
  125. #if 0
  126. bu_semaphore_acquire( BU_SEM_SYSCALL );
  127. bu_log( "hit: reg_name=\"%s\"\n", reg->reg_name );
  128. bu_log( "hit: gmater=%d, los=%d, density=%gg/cc, depth=%gmm, wt=%gg\n",
  129. reg->reg_gmater, reg->reg_los, density[reg->reg_gmater],
  130. depth, dp->weight );
  131. bu_semaphore_release( BU_SEM_SYSCALL );
  132. #endif
  133. }
  134. }
  135. return 1; /* report hit to main routine */
  136. }
  137. int
  138. miss(register struct application *ap)
  139. {
  140. return 0;
  141. }
  142. int
  143. overlap(struct application *ap, struct partition *pp, struct region *reg1, struct region *reg2, struct partition *hp)
  144. {
  145. bu_semaphore_acquire( BU_SEM_SYSCALL );
  146. noverlaps++;
  147. bu_semaphore_release( BU_SEM_SYSCALL );
  148. return 0;
  149. }
  150. /*
  151. * V I E W _ I N I T
  152. *
  153. * Called at the start of a run.
  154. * Returns 1 if framebuffer should be opened, else 0.
  155. */
  156. int
  157. view_init(register struct application *ap, char *file, char *obj, int minus_o)
  158. {
  159. register size_t i;
  160. char buf[BUFSIZ+1];
  161. static char null = (char) 0;
  162. const char *curdir = getenv( "PWD" );
  163. const char *homedir = getenv( "HOME" );
  164. int line;
  165. /* make sure they're not NULL */
  166. if (!curdir)
  167. curdir = "."; /* current dir */
  168. if (!homedir)
  169. homedir = ""; /* drop to root */
  170. if ( !minus_o ) {
  171. outfp = stdout;
  172. output_is_binary = 0;
  173. }
  174. for ( i=1; i<MAXMATLS; i++ ) {
  175. density[i] = -1;
  176. dens_name[i] = &null;
  177. }
  178. #define maxm(a, b) (a>b?a:b)
  179. i = maxm(strlen(curdir), strlen(homedir)) + strlen(DENSITY_FILE) + 2;
  180. densityfile = bu_calloc( (unsigned int)i, 1, "densityfile");
  181. snprintf(densityfile, i, "%s/%s", curdir, DENSITY_FILE);
  182. if ( (densityfp=fopen( densityfile, "r" )) == (FILE *) 0 ) {
  183. snprintf(densityfile, i, "%s/%s", homedir, DENSITY_FILE);
  184. if ( (densityfp=fopen( densityfile, "r" )) == (FILE *) 0 ) {
  185. bu_log( "Unable to load density file \"%s\" for reading\n", densityfile);
  186. perror( densityfile );
  187. bu_exit( -1, NULL );
  188. }
  189. }
  190. /* Read in density in terms of grams/cm^3 */
  191. for (line = 1; feof( densityfp ) != EOF; line++) {
  192. int index;
  193. float dens;
  194. i = fscanf(densityfp, "%d %f %[^\n]", &index, &dens, buf);
  195. if (i == EOF)
  196. break;
  197. if (i != 3) {
  198. bu_log("error parsing line %d of density file.\n%d args recognized instead of 3\n", line, i);
  199. continue;
  200. }
  201. if ( index > 0 && index < MAXMATLS ) {
  202. density[ index ] = dens;
  203. dens_name[ index ] = bu_strdup(buf);
  204. } else
  205. bu_log( "Material index %d in \"%s\" is out of range.\n",
  206. index, densityfile );
  207. }
  208. ap->a_hit = hit;
  209. ap->a_miss = miss;
  210. ap->a_overlap = overlap;
  211. ap->a_onehit = 0;
  212. return 0; /* no framebuffer needed */
  213. }
  214. /* beginning of a frame */
  215. void
  216. view_2init(struct application *ap)
  217. {
  218. register struct region *rp;
  219. register struct rt_i *rtip = ap->a_rt_i;
  220. for ( BU_LIST_FOR( rp, region, &(rtip->HeadRegion) ) ) {
  221. rp->reg_udata = (genptr_t) NULL;
  222. }
  223. }
  224. /* end of each pixel */
  225. void view_pixel(struct application *ap)
  226. {
  227. }
  228. /* end of each line */
  229. void view_eol(struct application *ap)
  230. {
  231. }
  232. /* end of a frame */
  233. void view_end(struct application *ap)
  234. {
  235. register struct datapoint *dp;
  236. register struct region *rp;
  237. register fastf_t total_weight = 0;
  238. fastf_t sum_x = 0, sum_y = 0, sum_z = 0;
  239. struct rt_i *rtip = ap->a_rt_i;
  240. struct db_i *dbp = ap->a_rt_i->rti_dbip;
  241. fastf_t conversion = 1.0; /* Conversion factor for mass */
  242. fastf_t volume = 0;
  243. char units[128] = {0};
  244. char unit2[128] = {0};
  245. int MAX_ITEM = 0;
  246. time_t clock;
  247. struct tm *locltime;
  248. char *timeptr;
  249. /* default units */
  250. bu_strlcpy(units, "grams", sizeof(units));
  251. bu_strlcpy(unit2, bu_units_string(dbp->dbi_local2base), sizeof(unit2));
  252. (void) time( &clock );
  253. locltime = localtime( &clock );
  254. timeptr = asctime( locltime );
  255. /* This section is necessary because libbu doesn't yet
  256. * support (nor do BRL-CAD databases store) defaults
  257. * for mass. Once it does, this section should be
  258. * reorganized.*/
  259. if ( NEAR_ZERO(dbp->dbi_local2base - 304.8, SMALL_FASTF) ) {
  260. /* Feet */
  261. bu_strlcpy( units, "grams", sizeof(units) );
  262. } else if ( NEAR_ZERO(dbp->dbi_local2base - 25.4, SMALL_FASTF) ) {
  263. /* inches */
  264. conversion = 0.002204623; /* lbs./gram */
  265. bu_strlcpy( units, "lbs.", sizeof(units) );
  266. } else if ( NEAR_ZERO(dbp->dbi_local2base - 1.0, SMALL_FASTF) ) {
  267. /* mm */
  268. conversion = 0.001; /* kg/gram */
  269. bu_strlcpy( units, "kg", sizeof(units) );
  270. } else if ( NEAR_ZERO(dbp->dbi_local2base - 1000.0, SMALL_FASTF) ) {
  271. /* km */
  272. conversion = 0.001; /* kg/gram */
  273. bu_strlcpy( units, "kg", sizeof(units) );
  274. } else if ( NEAR_ZERO(dbp->dbi_local2base - 0.1, SMALL_FASTF) ) {
  275. /* cm */
  276. bu_strlcpy( units, "grams", sizeof(units) );
  277. } else {
  278. bu_log("Warning: base2mm=%g, using default of %s--%s\n",
  279. dbp->dbi_base2local, units, unit2 );
  280. }
  281. if ( noverlaps )
  282. bu_log( "%d overlap%c detected.\n\n", noverlaps,
  283. noverlaps==1 ? '\0' : 's' );
  284. fprintf( outfp, "RT Weight Program Output:\n" );
  285. fprintf( outfp, "\nDatabase Title: \"%s\"\n", dbp->dbi_title );
  286. fprintf( outfp, "Time Stamp: %s\n\nDensity Table Used:%s\n\n", timeptr, densityfile );
  287. fprintf( outfp, "Material Density(g/cm^3) Name\n" );
  288. { register int i;
  289. for ( i=1; i<MAXMATLS; i++ ) {
  290. if ( density[i] >= 0 )
  291. fprintf( outfp, "%5d %10.4f %s\n",
  292. i, density[i], dens_name[i] );
  293. } }
  294. if ( rpt_overlap ) {
  295. /* ^L is char code for FormFeed/NewPage */
  296. fprintf( outfp, " Weight by region (in %s, density given in g/cm^3):\n\n", units );
  297. fprintf( outfp, " Weight Matl LOS Material Name Density Name\n" );
  298. fprintf( outfp, " ------- ---- --- --------------- ------- -------------\n" );
  299. }
  300. for ( BU_LIST_FOR( rp, region, &(rtip->HeadRegion) ) ) {
  301. register fastf_t weight = 0;
  302. register size_t l = strlen(rp->reg_name);
  303. register fastf_t *ptr;
  304. /* */
  305. if ( MAX_ITEM < rp->reg_regionid )
  306. MAX_ITEM = rp->reg_regionid;
  307. /* */
  308. for ( dp = (struct datapoint *) rp->reg_udata;
  309. dp != (struct datapoint *) NULL; dp = dp->next ) {
  310. sum_x += dp->weight * dp->centroid[X];
  311. sum_y += dp->weight * dp->centroid[Y];
  312. sum_z += dp->weight * dp->centroid[Z];
  313. weight += dp->weight;
  314. volume += dp->volume;
  315. }
  316. weight *= conversion;
  317. total_weight += weight;
  318. ptr = (fastf_t *) bu_malloc( sizeof(fastf_t), "ptr" );
  319. *ptr = weight;
  320. rp->reg_udata = (genptr_t) ptr;
  321. l = l > 37 ? l-37 : 0;
  322. if ( rpt_overlap )
  323. fprintf( outfp, "%8.3f %4d %3d %-15.15s %7.4f %-37.37s\n",
  324. weight, rp->reg_gmater, rp->reg_los,
  325. dens_name[rp->reg_gmater],
  326. density[rp->reg_gmater], &rp->reg_name[l] );
  327. }
  328. if ( rpt_overlap ) {
  329. register int i;
  330. /*
  331. #define MAX_ITEM 10001
  332. fastf_t item_wt[MAX_ITEM];
  333. */
  334. fastf_t *item_wt;
  335. MAX_ITEM++;
  336. item_wt = (fastf_t *) bu_malloc( sizeof(fastf_t) * (MAX_ITEM + 1), "item_wt" );
  337. for ( i=1; i<=MAX_ITEM; i++ )
  338. item_wt[i] = -1.0;
  339. fprintf(outfp, " Weight by item number (in %s):\n\n", units);
  340. fprintf(outfp, "Item Weight Region Names\n" );
  341. fprintf(outfp, "---- -------- --------------------\n" );
  342. for ( BU_LIST_FOR( rp, region, &(rtip->HeadRegion) ) ) {
  343. register int i = rp->reg_regionid;
  344. if ( item_wt[i] < 0 )
  345. item_wt[i] = *(fastf_t *)rp->reg_udata;
  346. else
  347. item_wt[i] += *(fastf_t *)rp->reg_udata;
  348. }
  349. for ( i=1; i<MAX_ITEM; i++ ) {
  350. int CR = 0;
  351. if ( item_wt[i] < 0 )
  352. continue;
  353. fprintf(outfp, "%4d %8.3f ", i, item_wt[i] );
  354. for ( BU_LIST_FOR( rp, region, &(rtip->HeadRegion) ) ) {
  355. if ( rp->reg_regionid == i ) {
  356. register size_t l = strlen(rp->reg_name);
  357. l = l > 65 ? l-65 : 0;
  358. if ( CR )
  359. fprintf(outfp, " ");
  360. fprintf(outfp, "%-65.65s\n", &rp->reg_name[l] );
  361. CR = 1;
  362. }
  363. }
  364. }
  365. }
  366. volume *= (dbp->dbi_base2local*dbp->dbi_base2local*dbp->dbi_base2local);
  367. sum_x *= (conversion / total_weight) * dbp->dbi_base2local;
  368. sum_y *= (conversion / total_weight) * dbp->dbi_base2local;
  369. sum_z *= (conversion / total_weight) * dbp->dbi_base2local;
  370. fprintf( outfp, " RT Weight Program Output:\n" );
  371. fprintf( outfp, "\nDatabase Title: \"%s\"\n", dbp->dbi_title );
  372. fprintf( outfp, "Time Stamp: %s\n\n", timeptr );
  373. fprintf( outfp, "Total volume = %g %s^3\n\n", volume, unit2 );
  374. fprintf( outfp, "Centroid: X = %g %s\n", sum_x, unit2 );
  375. fprintf( outfp, " Y = %g %s\n", sum_y, unit2 );
  376. fprintf( outfp, " Z = %g %s\n", sum_z, unit2 );
  377. fprintf( outfp, "\nTotal mass = %g %s\n\n", total_weight, units );
  378. }
  379. void view_setup(void) {}
  380. /* Associated with "clean" command, before new tree is loaded */
  381. void view_cleanup(void) {}
  382. void application_init (void) {}
  383. /*
  384. * Local Variables:
  385. * mode: C
  386. * tab-width: 8
  387. * indent-tabs-mode: t
  388. * c-file-style: "stroustrup"
  389. * End:
  390. * ex: shiftwidth=4 tabstop=8
  391. */