Revision: 72373 http://sourceforge.net/p/brlcad/code/72373 Author: starseeker Date: 2019-02-08 18:28:41 +0000 (Fri, 08 Feb 2019) Log Message: ----------- Probably breaks gqa and mater (definitely breaks rtweight) but have reached a point where things build and the new analyze density unit tests are passing so need to checkpoint.
Modified Paths: -------------- brlcad/trunk/include/analyze.h brlcad/trunk/src/libanalyze/analyze_private.h brlcad/trunk/src/libanalyze/api.c brlcad/trunk/src/libanalyze/check_options.c brlcad/trunk/src/libanalyze/density.cxx brlcad/trunk/src/libanalyze/tests/CMakeLists.txt brlcad/trunk/src/libged/gqa.c brlcad/trunk/src/libged/mater.cxx brlcad/trunk/src/rt/CMakeLists.txt Added Paths: ----------- brlcad/trunk/src/libanalyze/tests/density.cxx Removed Paths: ------------- brlcad/trunk/src/libanalyze/tests/density.c Modified: brlcad/trunk/include/analyze.h =================================================================== --- brlcad/trunk/include/analyze.h 2019-02-08 00:43:55 UTC (rev 72372) +++ brlcad/trunk/include/analyze.h 2019-02-08 18:28:41 UTC (rev 72373) @@ -146,14 +146,76 @@ }; /** - * Routine to parse a .density file + * Loading information from a .density file and querying it. */ -ANALYZE_EXPORT extern int parse_densities_buffer(char *buf, - size_t len, - struct density_entry **densities, - struct bu_vls *result_str, - int *num_densities); +#if defined(__cplusplus) +extern "C" { +#endif +struct analyze_densities_impl; +struct analyze_densities { + struct analyze_densities_impl *i; +}; +#if defined(__cplusplus) +} +#endif +ANALYZE_EXPORT extern int analyze_densities_create(struct analyze_densities **a); +ANALYZE_EXPORT extern void analyze_densities_destroy(struct analyze_densities *a); +ANALYZE_EXPORT extern int analyze_densities_init(struct analyze_densities *a); +ANALYZE_EXPORT extern void analyze_densities_clear(struct analyze_densities *a); + +/* Update an entry if one matching id already exists, else create a new entry. + * Unlike the loading and writing functions, this command uses g/mm^3 */ +ANALYZE_EXPORT extern int analyze_densities_set(struct analyze_densities *a, long int id, fastf_t density, const char *name, struct bu_vls *msgs); + +/* Accepts a buffer, typically read from a .density file. Expects units of g/cm^3. + * (TODO - Ugh - need to come up with a way to define the units in the file so we aren't + * tied to that forever...) */ +ANALYZE_EXPORT extern int analyze_densities_load(struct analyze_densities *a, const char *buff, struct bu_vls *msgs); + +/* Creates a .density buffer from a, writing units of g/cm^3. Returns length of buff + * (TODO - Ugh - need to come up with a way to define the units so we aren't + * tied to g/cm^3 that forever...) */ +ANALYZE_EXPORT extern long int analyze_densities_write(char **buff, struct analyze_densities *a); + +/* This mapping will be unique - each id may have at most one entry in the database. Caller + * is responsible for freeing the resulting string. */ +ANALYZE_EXPORT extern char *analyze_densities_name(struct analyze_densities *a, long int id); + +/* Because this mapping is not guaranteed to be unique, this function has to be + * a bit more sophisticated in what it does. + * + * If ids is NULL or max_ids == 0, it will return the count of the ids + * associated with name in the database. + * + * If an ids array is available, it returns two pieces of data - the id array + * of length max_ids (defined by the caller) will hold up to max_ids material + * IDs that have the specified name. In this mode, the return code will either + * be the number of IDs written to ids (if positive) or the number of + * additional ids found that would not fit in the ids array (if negative). + */ +ANALYZE_EXPORT extern long int analyze_densities_id(long int *ids, long int max_ids, struct analyze_densities *a, const char *name); + +/* Note: to use a name for density lookup, supply one of the outputs of + * analyze_densities_id to this function. + * + * Density is returned in g/mm^3 */ +ANALYZE_EXPORT extern fastf_t analyze_densities_density(struct analyze_densities *a, long int id); + +/* Provide a means to iterate over all defined densities. To get the lowest valid id, + * supply -1 to curr_id. Given a valid id, supply it to curr_id to get the next highest + * id. When there isn't a valid next id, -1 is returned. To count the number of density + * definitions active, do the following: + * + * long int curr_id = -1; + * long int dcnt = 0; + * while ((curr_id = analyze_densities_next(a, curr_id)) != -1) dcnt++; + * + */ +ANALYZE_EXPORT extern long int analyze_densities_next(struct analyze_densities *a, long int curr_id); + + + /** * region_pair for gqa */ Modified: brlcad/trunk/src/libanalyze/analyze_private.h =================================================================== --- brlcad/trunk/src/libanalyze/analyze_private.h 2019-02-08 00:43:55 UTC (rev 72372) +++ brlcad/trunk/src/libanalyze/analyze_private.h 2019-02-08 18:28:41 UTC (rev 72373) @@ -120,8 +120,7 @@ struct per_obj_data *objs; struct per_region_data *reg_tbl; - struct density_entry *densities; - int num_densities; + struct analyze_densities *densities; /* the parameters */ int num_views; Modified: brlcad/trunk/src/libanalyze/api.c =================================================================== --- brlcad/trunk/src/libanalyze/api.c 2019-02-08 00:43:55 UTC (rev 72372) +++ brlcad/trunk/src/libanalyze/api.c 2019-02-08 18:28:41 UTC (rev 72373) @@ -87,8 +87,20 @@ /* examine each partition until we get back to the head */ for (pp=PartHeadp->pt_forw; pp != PartHeadp; pp = pp->pt_forw) { - struct density_entry *de; + fastf_t grams_per_cu_mm; + long int material_id = pp->pt_regionp->reg_gmater; + + if (state->default_den) { + /* Aluminium 7xxx series as default material */ + fastf_t default_density = 2.74; /* Aluminium, 7079-T6 */ + material_id = -1; + grams_per_cu_mm = default_density; + } else { + grams_per_cu_mm = analyze_densities_density(state->densities, material_id); + } + + /* inhit info */ dist = pp->pt_outhit->hit_dist - pp->pt_inhit->hit_dist; VJOIN1(pt, ap->a_ray.r_pt, pp->pt_inhit->hit_dist, ap->a_ray.r_dir); @@ -139,30 +151,16 @@ } /* make sure mater index is within range of densities */ - if (pp->pt_regionp->reg_gmater >= state->num_densities) { - if(state->default_den == 0) { - bu_semaphore_acquire(ANALYZE_SEM_WORKER); - bu_vls_printf(state->log_str, "Density index %d on region %s is outside of range of table [1..%d]\nSet GIFTmater on region or add entry to density table\n", - pp->pt_regionp->reg_gmater, - pp->pt_regionp->reg_name, - state->num_densities); /* XXX this should do something else */ - bu_semaphore_release(ANALYZE_SEM_WORKER); - return ANALYZE_ERROR; - } + if (material_id < 0 && state->default_den == 0) { + bu_semaphore_acquire(ANALYZE_SEM_WORKER); + bu_vls_printf(state->log_str, "Density index %d on region %s is not in density table.\nSet GIFTmater on region or add entry to density table\n", + pp->pt_regionp->reg_gmater, + pp->pt_regionp->reg_name); /* XXX this should do something else */ + bu_semaphore_release(ANALYZE_SEM_WORKER); + return ANALYZE_ERROR; } - /* make sure the density index has been set */ - bu_semaphore_acquire(ANALYZE_SEM_WORKER); - if(state->default_den || state->densities[pp->pt_regionp->reg_gmater].magic != DENSITY_MAGIC) { - BU_GET(de, struct density_entry); /* Aluminium 7xxx series as default material */ - de->magic = DENSITY_MAGIC; - de->grams_per_cu_mm = 2.74; - de->name = "Aluminium, 7079-T6"; - } else { - de = state->densities + pp->pt_regionp->reg_gmater; - } - bu_semaphore_release(ANALYZE_SEM_WORKER); - if (de->magic == DENSITY_MAGIC) { + { struct per_region_data *prd; vect_t cmass; vect_t lenTorque; @@ -213,7 +211,7 @@ } /* accumulate the total mass values */ - val = de->grams_per_cu_mm * dist * (pp->pt_regionp->reg_los * 0.01); + val = grams_per_cu_mm * dist * (pp->pt_regionp->reg_los * 0.01); ap->A_LENDEN += val; prd = ((struct per_region_data *)pp->pt_regionp->reg_udata); @@ -269,14 +267,6 @@ } bu_semaphore_release(ANALYZE_SEM_STATS); - } else { - bu_semaphore_acquire(ANALYZE_SEM_WORKER); - bu_vls_printf(state->log_str, "Density index %d from region %s is not set.\nAdd entry to density table\n", - pp->pt_regionp->reg_gmater, pp->pt_regionp->reg_name); - bu_semaphore_release(ANALYZE_SEM_WORKER); - - state->aborted = 1; - return ANALYZE_ERROR; } } @@ -495,38 +485,36 @@ HIDDEN int densities_from_file(struct current_state *state, char *name) { - struct stat sb; - - FILE *fp = (FILE *)NULL; + struct bu_vls msgs = BU_VLS_INIT_ZERO; + struct bu_mapped_file *dfile = NULL; char *buf = NULL; int ret = 0; - size_t sret = 0; - fp = fopen(name, "rb"); - if (fp == (FILE *)NULL) { - bu_log("Could not open file - %s\n", name); + if (!bu_file_exists(name, NULL)) { + bu_log("Could not find density file - %s\n", name); return ANALYZE_ERROR; } - if (stat(name, &sb)) { - bu_log("Could not read file - %s\n", name); - fclose(fp); + dfile = bu_open_mapped_file(name, "densities file"); + if (!dfile) { + bu_log("Could not open density file - %s\n", name); return ANALYZE_ERROR; } - state->densities = (struct density_entry *)bu_calloc(128, sizeof(struct density_entry), "density entries"); - state->num_densities = 128; + buf = (char *)(dfile->buf); - /* a mapped file would make more sense here */ - buf = (char *)bu_malloc(sb.st_size+1, "density buffer"); - sret = fread(buf, sb.st_size, 1, fp); - if (sret != 1) - perror("fread"); - ret = parse_densities_buffer(buf, (unsigned long)sb.st_size, &(state->densities), NULL, &state->num_densities); - bu_free(buf, "density buffer"); - fclose(fp); + (void)analyze_densities_create(&(state->densities)); - return ret; + ret = analyze_densities_load(state->densities, buf, &msgs); + + if (bu_vls_strlen(&msgs)) { + bu_log("Problem reading densities file:\n%s\n", bu_vls_cstr(&msgs)); + } + bu_vls_free(&msgs); + + bu_close_mapped_file(dfile); + + return (ret <= 0) ? -1 : 0; } @@ -538,6 +526,7 @@ HIDDEN int densities_from_database(struct current_state *state, struct rt_i *rtip) { + struct bu_vls msgs = BU_VLS_INIT_ZERO; struct directory *dp; struct rt_db_internal intern; struct rt_binunif_internal *bu; @@ -562,15 +551,18 @@ RT_CHECK_BINUNIF (bu); - state->densities = (struct density_entry *)bu_calloc(128, sizeof(struct density_entry), "density entries"); - state->num_densities = 128; + (void)analyze_densities_create(&(state->densities)); - /* Acquire one extra byte to accommodate parse_densities_buffer() - * (i.e. it wants to write an EOS in buf[bu->count]). - */ - buf = (char *)bu_malloc(bu->count+1, "density buffer"); + buf = (char *)bu_calloc(bu->count+1, sizeof(char), "density buffer"); memcpy(buf, bu->u.int8, bu->count); - ret = parse_densities_buffer(buf, bu->count, &(state->densities), NULL, &state->num_densities); + + ret = analyze_densities_load(state->densities, buf, &msgs); + + if (bu_vls_strlen(&msgs)) { + bu_log("Problem reading densities file:\n%s\n", bu_vls_cstr(&msgs)); + } + bu_vls_free(&msgs); + bu_free((void *)buf, "density buffer"); return ret; @@ -908,10 +900,10 @@ if (state->analysis_flags & ANALYSIS_MASS) { if (state->mass_tolerance < 0.0) { double max_den = 0.0; - int i; - for (i = 0; i < state->num_densities; i++) { - if (state->densities[i].grams_per_cu_mm > max_den) - max_den = state->densities[i].grams_per_cu_mm; + long int curr_id = -1; + while ((curr_id = analyze_densities_next(state->densities, curr_id)) != -1) { + if (analyze_densities_density(state->densities, curr_id) > max_den) + max_den = analyze_densities_density(state->densities, curr_id); } state->mass_tolerance = state->span[X] * state->span[Y] * state->span[Z] * 0.1 * max_den; bu_log("Setting mass tolerance to %g gram\n", state->mass_tolerance); Modified: brlcad/trunk/src/libanalyze/check_options.c =================================================================== --- brlcad/trunk/src/libanalyze/check_options.c 2019-02-08 00:43:55 UTC (rev 72372) +++ brlcad/trunk/src/libanalyze/check_options.c 2019-02-08 18:28:41 UTC (rev 72373) @@ -101,14 +101,8 @@ bu_vls_free(state->log_str); if (state->densities != NULL) { - for (i = 0; i < state->num_densities; ++i) { - if (state->densities[i].name != 0) - bu_free(state->densities[i].name, "density name"); - } - - bu_free(state->densities, "densities"); + analyze_densities_destroy(state->densities); state->densities = NULL; - state->num_densities = 0; } if (state->m_lenTorque != NULL) Modified: brlcad/trunk/src/libanalyze/density.cxx =================================================================== --- brlcad/trunk/src/libanalyze/density.cxx 2019-02-08 00:43:55 UTC (rev 72372) +++ brlcad/trunk/src/libanalyze/density.cxx 2019-02-08 18:28:41 UTC (rev 72373) @@ -1,4 +1,4 @@ -/* D E N S I T Y . C +/* D E N S I T Y . C X X * BRL-CAD * * Copyright (c) 2009-2019 United States Government as represented by @@ -22,14 +22,91 @@ #include <stdlib.h> #include <string.h> +#include <map> +#include <string> +#include <sstream> + #include "analyze.h" -int -parse_densities_buffer(char *obuf, size_t len, struct density_entry **densities, struct bu_vls *result_str, int *num_densities) +#define MAX_MATERIAL_ID 9999999999 +#define MAX_MATERIAL_CNT 10000000000 + +struct analyze_densities_impl { + std::map<long int,std::string> id2name; + std::map<long int,fastf_t> id2density; + std::multimap<std::string, long int> name2id; +}; + +extern "C" int +analyze_densities_init(struct analyze_densities *a) { + if (!a) return -1; + a->i = new analyze_densities_impl; + return (!a->i) ? -1 : 0; +} + +extern "C" void +analyze_densities_clear(struct analyze_densities *a) +{ + if (!a) return; + if (!a->i) return; + a->i->id2name.clear(); + a->i->id2density.clear(); + a->i->name2id.clear(); + delete a->i; +} + +extern "C" int +analyze_densities_create(struct analyze_densities **a) +{ + if (!a) return -1; + (*a) = new analyze_densities; + return analyze_densities_init(*a); +} +extern "C" void +analyze_densities_destroy(struct analyze_densities *a) +{ + if (!a) return; + analyze_densities_clear(a); + delete a; +} + +extern "C" int +analyze_densities_set(struct analyze_densities *a, long int id, fastf_t density, const char *name, struct bu_vls *msgs) +{ + if (!a || !a->i) return -1; + if (id < 0 || density < 0 || !name) return -1; + + if (id > MAX_MATERIAL_ID) { + if (msgs) { + bu_vls_printf(msgs, "Error: material id %ld is large than MAX_MATERIAL_ID (%ld)\n", id, MAX_MATERIAL_ID); + } + return -1; + } + + if (a->i->id2density.size() == MAX_MATERIAL_CNT) { + if (msgs) { + bu_vls_printf(msgs, "Error: analyze densities database is full - maximum density count of %ld has been reached\n", MAX_MATERIAL_CNT); + } + return -1; + } + + a->i->id2name[id] = std::string(name); + a->i->id2density[id] = density; + a->i->name2id.insert(std::pair<std::string, long int>(std::string(name), id)); + return 0; +} + +static int +parse_densities_line(struct analyze_densities *a, const char *obuf, size_t len, struct bu_vls *result_str) +{ + double density = -1; + char *name = NULL; + long int material_id = -1; + + int have_density = 0; char *p, *q, *last; long idx; - double density; char *buf = (char *)bu_malloc(sizeof(char)*len+1, "buffer copy"); memcpy(buf, obuf, len); @@ -62,30 +139,47 @@ continue; } + if (have_density) { + bu_free(buf, "free buf copy"); + bu_free(name, "free name copy"); + if (result_str) { + bu_vls_printf(result_str, "Error processing line: \"%s\"\nExtra content after density entry\n", obuf); + } + return -1; + } + idx = strtol(p, &q, 10); if (q == (char *)NULL) { bu_free(buf, "free buf copy"); - bu_vls_printf(result_str, "could not convert idx\n"); - return ANALYZE_ERROR; + if (result_str) { + bu_vls_printf(result_str, "Error processing line: \"%s\"\ncould not convert idx\n", obuf); + } + return -1; } if (idx < 0) { bu_free(buf, "free buf copy"); - bu_vls_printf(result_str, "bad density index (%ld < 0)\n", idx); - return ANALYZE_ERROR; + if (result_str) { + bu_vls_printf(result_str, "Error processing line: \"%s\"\nbad density index (%ld < 0)\n", obuf, idx); + } + return -1; } density = strtod(q, &p); if (q == p) { bu_free(buf, "free buf copy"); - bu_vls_printf(result_str, "could not convert density\n"); - return ANALYZE_ERROR; + if (result_str) { + bu_vls_printf(result_str, "Error processing line: \"%s\"\ncould not convert density\n", obuf); + } + return -1; } if (density < 0.0) { bu_free(buf, "free buf copy"); - bu_vls_printf(result_str, "bad density (%lf < 0)\n", density); - return ANALYZE_ERROR; + if (result_str) { + bu_vls_printf(result_str, "Error processing line: \"%s\"\nbad density (%lf < 0)\n", obuf, density); + } + return -1; } /* Skip tabs and spaces */ @@ -99,18 +193,23 @@ else q = last; - while (idx >= *num_densities) { - *densities = (struct density_entry *)bu_realloc(*densities, sizeof(struct density_entry)*(*num_densities)*2, - "density entries"); - *num_densities *= 2; + + /* Trim off comments and ws, if any. */ + std::string wstr(p); + std::string nstr; + size_t ep = wstr.find_first_of("#"); + if (ep != std::string::npos) { + wstr = wstr.substr(0, ep); } - - (*densities)[idx].magic = DENSITY_MAGIC; + ep = wstr.find_last_not_of(" \t\n\v\f\r"); + size_t sp = wstr.find_first_not_of(" \t\n\v\f\r"); + nstr = wstr.substr(sp, ep-sp+1); /* since BRL-CAD does computation in mm, but the table is in * grams / (cm^3) we convert the table on input */ - (*densities)[idx].grams_per_cu_mm = density / 1000.0; - (*densities)[idx].name = bu_strdup(p); + density = density / 1000.0; + name = bu_strdup(nstr.c_str()); + material_id = idx; p = q; @@ -118,20 +217,147 @@ while (*p && (*p == '\t' || *p == ' ' || *p == '\n')) p++; } -#ifdef PRINT_DENSITIES - for (idx = 0; idx < *num_densities; idx++) - if ((*densities)[idx].magic == DENSITY_MAGIC) - bu_vls_printf(&_ged_current_gedp->ged_result_str, "%4d %6g %s\n", - idx, - (*densities)[idx].grams_per_cu_mm, - (*densities)[idx].name); -#endif + /* Whatever we saw, if it wasn't a valid definition bail now */ + if (!name || material_id == -1 || density < 0) { + return -1; + } + /* If we have a valid definition, try to insert it */ + if (analyze_densities_set(a, material_id, density, name, result_str) < 0) { + bu_free(buf, "free buf copy"); + if (result_str) { + bu_vls_printf(result_str, "Error inserting density %ld,%g,%s\n", material_id, density, name); + } + bu_free(name, "free name copy"); + return -1; + + } + + bu_free(name, "free name copy"); bu_free(buf, "free buf copy"); - return ANALYZE_OK; + return 0; } +extern "C" int +analyze_densities_load(struct analyze_densities *a, const char *buff, struct bu_vls *msgs) +{ + if (!a || !a->i || !buff) return 0; + std::string dbuff(buff); + std::istringstream ss(dbuff); + std::string line; + int dcnt = 0; + while (std::getline(ss, line)) { + struct bu_vls lmsg = BU_VLS_INIT_ZERO; + int ret = parse_densities_line(a, line.c_str(), line.length(), &lmsg); + if (ret < 0) { + if (msgs && bu_vls_strlen(&lmsg)) { + bu_vls_printf(msgs, "%s", bu_vls_cstr(&lmsg)); + } + } else { + dcnt++; + } + bu_vls_free(&lmsg); + } + return dcnt; +} + +extern "C" long int +analyze_densities_write(char **buff, struct analyze_densities *a) +{ + if (!a || !a->i || !buff) return 0; + std::string obuff; + std::ostringstream os(obuff); + + std::map<long int,std::string>::iterator id_it; + for (id_it = a->i->id2name.begin(); id_it != a->i->id2name.end(); id_it++) { + long int nid = id_it->first; + std::string nname = id_it->second; + fastf_t ndensity = analyze_densities_density(a, nid); + os << nid << "\t" << ndensity * 1000 << "\t" << nname << "\n"; + } + + std::string ostring = os.str(); + (*buff) = bu_strdup(ostring.c_str()); + + return (long int)ostring.length(); +} + + +extern "C" char * +analyze_densities_name(struct analyze_densities *a, long int id) +{ + if (!a || !a->i || id < 0) return NULL; + if (a->i->id2name.find(id) == a->i->id2name.end()) { + return NULL; + } + return bu_strdup(a->i->id2name[id].c_str()); +} + +extern "C" long int +analyze_densities_id(long int *ids, long int max_ids, struct analyze_densities *a, const char *name) +{ + int mcnt = 0; + std::multimap<std::string, long int>::iterator m_it; + std::pair<std::multimap<std::string, long int>::iterator, std::multimap<std::string, long int>::iterator> eret; + if (!a || !a->i || !name) return -1; + eret = a->i->name2id.equal_range(std::string(name)); + for (m_it = eret.first; m_it != eret.second; m_it++) { + mcnt++; + } + + if (!ids || max_ids == 0) { + return mcnt; + } + + /* Have an id buffer, return what we can */ + if (mcnt > 0) { + int ccnt = 0; + for (m_it = eret.first; m_it != eret.second; m_it++) { + if (ccnt < max_ids) { + ids[ccnt] = m_it->second; + ccnt++; + } + } + } + + return (mcnt > max_ids) ? (max_ids - mcnt) : mcnt; +} + +extern "C" fastf_t +analyze_densities_density(struct analyze_densities *a, long int id) +{ + if (!a || !a->i || id < 0) return -1.0; + if (a->i->id2density.find(id) == a->i->id2density.end()) { + return -1.0; + } + return a->i->id2density[id]; +} + +extern "C" long int +analyze_densities_next(struct analyze_densities *a, long int id) +{ + if (!a || !a->i) return -1; + if (id < 0) { + if (a->i->id2density.size()) { + std::map<long int,fastf_t>::iterator i = a->i->id2density.begin(); + return i->first; + } else { + return -1; + } + } + std::map<long int,fastf_t>::iterator idc = a->i->id2density.find(id); + if (idc != a->i->id2density.end()) { + std::map<long int,fastf_t>::iterator idn = std::next(idc); + if (idn != a->i->id2density.end()) { + return idn->first; + } else { + return -1; + } + } + return -1; +} + /* * Local Variables: * tab-width: 8 Modified: brlcad/trunk/src/libanalyze/tests/CMakeLists.txt =================================================================== --- brlcad/trunk/src/libanalyze/tests/CMakeLists.txt 2019-02-08 00:43:55 UTC (rev 72372) +++ brlcad/trunk/src/libanalyze/tests/CMakeLists.txt 2019-02-08 18:28:41 UTC (rev 72373) @@ -1,7 +1,15 @@ -BRLCAD_ADDEXEC(tester_density density.c "libanalyze;libbu" NO_INSTALL) BRLCAD_ADDEXEC(tester_raydiff raydiff.c "libanalyze;libbu" NO_INSTALL) BRLCAD_ADDEXEC(tester_sp solid_partitions.c "libanalyze;libbu" NO_INSTALL) +##################################### +# analyze_densities testing # +##################################### +BRLCAD_ADDEXEC(analyze_densities density.cxx "libanalyze;libbu" NO_INSTALL) + +add_test(NAME analyze_densities_null COMMAND analyze_densities) +add_test(NAME analyze_densities_std COMMAND analyze_densities std) + + CMAKEFILES(raydiff.g) CMAKEFILES(CMakeLists.txt) Deleted: brlcad/trunk/src/libanalyze/tests/density.c =================================================================== --- brlcad/trunk/src/libanalyze/tests/density.c 2019-02-08 00:43:55 UTC (rev 72372) +++ brlcad/trunk/src/libanalyze/tests/density.c 2019-02-08 18:28:41 UTC (rev 72373) @@ -1,71 +0,0 @@ -/* T E S T _ D E N S I T Y . C - * BRL-CAD - * - * Copyright (c) 2011-2019 United States Government as represented by - * the U.S. Army Research Laboratory. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this file; see the file named COPYING for more - * information. - */ - -#include "common.h" - -#include <sys/stat.h> -#include "analyze.h" - -int -main(int argc, char **argv) -{ - struct density_entry *densities = NULL; - static int num_densities = 1028; - - struct stat sb; - FILE *fp = (FILE *)NULL; - char *buf = NULL; - int ret = 0; - int i; - - if (argc < 2) { - bu_log("Error - please supply density file\n"); - bu_exit(EXIT_FAILURE, NULL); - } - - fp = fopen(argv[1], "rb"); - if (fp == (FILE *)NULL) { - bu_log("Error - file %s not opened\n", argv[1]); - bu_exit(EXIT_FAILURE, NULL); - } - - if (stat(argv[1], &sb)) { - bu_log("Error - file %s not stat successfully\n", argv[1]); - bu_exit(EXIT_FAILURE, NULL); - } - - buf = (char *)bu_malloc(sb.st_size+1, "density buffer"); - ret = fread(buf, sb.st_size, 1, fp); - if (ret != 1) { - bu_log("Error reading file %s\n", argv[1]); - bu_exit(EXIT_FAILURE, NULL); - } - - densities = (struct density_entry *)bu_calloc(num_densities, sizeof(struct density_entry), "density entries"); - - ret = parse_densities_buffer(buf, (unsigned long)sb.st_size, &densities, NULL, &num_densities); - - for (i = 0; i < num_densities; i++) { - if (densities[i].name) - bu_log("densities[%i]: %s, %f\n", i, densities[i].name, densities[i].grams_per_cu_mm); - } - - return 0; -} Added: brlcad/trunk/src/libanalyze/tests/density.cxx =================================================================== --- brlcad/trunk/src/libanalyze/tests/density.cxx (rev 0) +++ brlcad/trunk/src/libanalyze/tests/density.cxx 2019-02-08 18:28:41 UTC (rev 72373) @@ -0,0 +1,324 @@ +/* D E N S I T Y . C X X + * BRL-CAD + * + * Copyright (c) 2011-2019 United States Government as represented by + * the U.S. Army Research Laboratory. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this file; see the file named COPYING for more + * information. + */ + +#include "common.h" + +#include <set> + +#include "analyze.h" + +const char *simple_buff = "1 7.8295 steel"; + +const char *test_buff = +"# Test density file with comments and bad input\n" +"2 7.82 Carbon Tool Steel\n" +"3 2.7 Aluminum, 6061-T6\n" +"4 2.74 Aluminum, 7079-T6\n" +"# Incomplete line following\n" +" Copper, pure\n" +" 6 19.32 Gold, pure\n" +" 7 8.03 Stainless, 18Cr-8Ni\n" +"# Comment\n" +" 8 7.47 Stainless 27Cr\n" +"\n" +" 9 7.715 Steel, tool\n" +"\n" +"# Blank line above\n" +"# Comment following valid data on the line below\n" +" 10 7.84 Carbon Steel # used for widgets\n" +" 12 3.00 Gunner\n" +" 14 10.00 Fuel\n" +"# Material ID too high \n" +"99999999999 70.84 Kryptonite\n"; + +const char *tbuff_out_ctrl = +"2 7.82 Carbon Tool Steel\n" +"3 2.7 Aluminum, 6061-T6\n" +"4 2.74 Aluminum, 7079-T6\n" +"6 19.32 Gold, pure\n" +"7 8.03 Stainless, 18Cr-8Ni\n" +"8 7.47 Stainless 27Cr\n" +"9 7.715 Steel, tool\n" +"10 7.84 Carbon Steel\n" +"12 3 Gunner\n" +"14 10 Fuel\n"; + +int +dtest_validate(struct analyze_densities *a, long int id, fastf_t density, const char *name) +{ + char *db_name = analyze_densities_name(a, id); + if (!db_name) { + bu_log("Error - could not find name for id %ld\n", id); + return -1; + } + if (!BU_STR_EQUAL(name, db_name)) { + bu_log("Error - found incorrect name for %ld (%s instead of %s)\n", id, db_name, name); + bu_free(db_name, "free name"); + return -1; + } + bu_free(db_name, "free name"); + + fastf_t db_density = analyze_densities_density(a, id); + if (db_density < 0) { + bu_log("Error - could not find density for id %ld\n", id); + return -1; + } + if (!NEAR_EQUAL(density, db_density, SMALL_FASTF)) { + bu_log("Error - found incorrect density for %ld (%g instead of %g)\n", id, db_density, density); + return -1; + } + + long int max_ids = 3; + long int ids[3] = {-1, -1, -1}; + long int idcnt = analyze_densities_id((long int *)ids, max_ids, a, name); + if (idcnt == 0) { + bu_log("Error - could not find any ids associated with name %s\n", name); + return -1; + } + int have_correct_id = 0; + for (long int i = 0; i < max_ids; i++) { + if (ids[i] >= 0 && ids[i] == id) { + have_correct_id = 1; + break; + } + } + if (!have_correct_id) { + bu_log("Error - could not find correct id (%ld) associated with name %s\n", id, name); + return -1; + } + + return 0; +} + +int +dtest_insert(struct analyze_densities *a, long int id, fastf_t density, const char *name, struct bu_vls *msgs) +{ + if (analyze_densities_set(a, id, density, name, msgs)) { + bu_log("Error inserting density: %s\n", bu_vls_cstr(msgs)); + return -1; + } + if (dtest_validate(a, id, density, name)) { + return -1; + } + return 0; +} + +int +main(int argc, char **argv) +{ + struct bu_vls msgs = BU_VLS_INIT_ZERO; + struct analyze_densities *a; + + if (!argc || !argv) { + return -1; + } + + /* Test behaviors with an empty database */ + if (argc == 1) { + long int max_ids = 2; + long int ids[2]; + + analyze_densities_create(&a); + + if (analyze_densities_name(a, 0)) { + bu_log("Error - empty database returned a non-NULL name on id lookup??\n"); + goto analyze_density_fail; + } + if (analyze_densities_id((long int *)ids, max_ids, a, "Aluminum") != 0) { + bu_log("Error - empty database returned a non-NULL id set on name lookup??\n"); + goto analyze_density_fail; + } + if (analyze_densities_density(a, 0) >= 0) { + bu_log("Error - empty database returned a density on id lookup??\n"); + goto analyze_density_fail; + } + if (analyze_densities_load(a, NULL, &msgs) != 0) { + bu_log("Error - loading NULL buffer returned a non-zero density count??\nMsg: %s", bu_vls_cstr(&msgs)); + goto analyze_density_fail; + } + if (analyze_densities_load(a, "", &msgs) != 0) { + bu_log("Error - loading empty buffer returned a non-zero density count??Msg: %s\n", bu_vls_cstr(&msgs)); + goto analyze_density_fail; + } + if (analyze_densities_next(a, -1) != -1) { + bu_log("Error - found initial \"next\" iterator in empty database??\n"); + goto analyze_density_fail; + } + if (analyze_densities_next(a, 0) != -1) { + bu_log("Error - found \"next\" iterator in empty database with invalid id??\n"); + goto analyze_density_fail; + } + + analyze_densities_destroy(a); + bu_vls_free(&msgs); + return 0; + } + + if (BU_STR_EQUAL(argv[1], "std")) { + + std::set<long int> valid_ids = {0,2,15,4,31}; + + analyze_densities_create(&a); + + /* Initialize with several values */ + if (dtest_insert(a, 0, 0.007715, "Steel", &msgs)) { + goto analyze_density_fail; + } + if (dtest_insert(a, 2, 0.00782, "Carbon Tool Steel", &msgs)) { + goto analyze_density_fail; + } + if (dtest_insert(a, 15, 0.0027, "Aluminum, 6061-T6", &msgs)) { + goto analyze_density_fail; + } + if (dtest_insert(a, 4, 0.00274, "Aluminum, 7079-T6", &msgs)) { + goto analyze_density_fail; + } + + /* Check assignment and duplicate id behaviors given existing entries */ + + /* Redefine id 0 */ + if (dtest_insert(a, 0, 0.001, "Light Steel", &msgs)) { + goto analyze_density_fail; + } + + /* Rename id 15 */ + if (dtest_insert(a, 15, 0.0027, "Aluminum", &msgs)) { + goto analyze_density_fail; + } + + /* Add another id for Carbon Tool Steel */ + if (dtest_insert(a, 31, analyze_densities_density(a, 2), "Carbon Tool Steel", &msgs)) { + goto analyze_density_fail; + } + + /* Check that we can retrieve both IDs for Carbon Tool Steel */ + long int max_ids = 2; + long int ids[2] = {-1, -1}; + long int idcnt = analyze_densities_id((long int *)ids, max_ids, a, "Carbon Tool Steel"); + if (idcnt != 2) { + bu_log("Error - could not find both ids for Carbon Tool Steel\n"); + goto analyze_density_fail; + } + std::set<long int> exp_cts = {2,31}; + std::set<long int> found_cts; + for (long int i = 0; i < 2; i++) { + found_cts.insert(ids[i]); + } + if (found_cts != exp_cts) { + bu_log("Error - could not find both ids for Carbon Tool Steel\n"); + goto analyze_density_fail; + } + + /* Check that we can iterate over the database */ + std::set<long int> found_ids; + long int curr_id = -1; + while ((curr_id = analyze_densities_next(a, curr_id)) != -1) { + if (valid_ids.find(curr_id) == valid_ids.end()) { + bu_log("Error - found invalid id %ld while iterating\n", curr_id); + goto analyze_density_fail; + } else { + found_ids.insert(curr_id); + } + } + if (found_ids != valid_ids) { + std::set<long int>::iterator f_it; + bu_log("Error - did not find the exact set of all valid ids while iterating\nFound: "); + for (f_it = found_ids.begin(); f_it != found_ids.end(); f_it++) { + bu_log("%ld ", *f_it); + } + bu_log("\nExpecting: "); + for (f_it = valid_ids.begin(); f_it != valid_ids.end(); f_it++) { + bu_log("%ld ", *f_it); + } + bu_log("\n"); + goto analyze_density_fail; + } + + /* Clear the database */ + analyze_densities_clear(a); + analyze_densities_init(a); + curr_id = -1; + long int id_cnt = 0; + while ((curr_id = analyze_densities_next(a, curr_id)) != -1) id_cnt++; + if (id_cnt) { + bu_log("Error - analyze_densities_clear + analyze_densities_init failed to rest the database: found %ld entities\n", id_cnt); + goto analyze_density_fail; + } + + /* Test loading from buffers */ + long int sb_cnt = analyze_densities_load(a, simple_buff, &msgs); + if (!sb_cnt) { + bu_log("Error - could not find id in simple test buffer: %s\n", bu_vls_cstr(&msgs)); + goto analyze_density_fail; + } + if (sb_cnt != 1) { + bu_log("Error - found %ld ids in test buffer, but expected 1\n", sb_cnt); + goto analyze_density_fail; + } + + analyze_densities_clear(a); + analyze_densities_init(a); + + long int tb_cnt = analyze_densities_load(a, test_buff, &msgs); + if (!tb_cnt) { + bu_log("Error - could not find ids in test buffer: %s\n", bu_vls_cstr(&msgs)); + goto analyze_density_fail; + } + if (tb_cnt != 10) { + bu_log("Error - found %ld ids in test buffer, but expected 10\n", tb_cnt); + goto analyze_density_fail; + } + + /* Test writing out a buffer */ + char *tbuff_out; + long int tbuff_len = analyze_densities_write(&tbuff_out, a); + if (!tbuff_len) { + bu_log("Error - unable to write out buffer!\n"); + goto analyze_density_fail; + } + + if (!BU_STR_EQUAL(tbuff_out, tbuff_out_ctrl)) { + bu_log("Error - buffer does not match!\n"); + bu_log("Expected:\n%s", tbuff_out_ctrl); + bu_log("Got:\n%s", tbuff_out); + goto analyze_density_fail; + } + + analyze_densities_destroy(a); + bu_vls_free(&msgs); + return 0; + } + +analyze_density_fail: + analyze_densities_destroy(a); + bu_vls_free(&msgs); + return -1; +} + +/* + * Local Variables: + * mode: C + * tab-width: 8 + * indent-tabs-mode: t + * c-file-style: "stroustrup" + * End: + * ex: shiftwidth=4 tabstop=8 + */ + Property changes on: brlcad/trunk/src/libanalyze/tests/density.cxx ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Modified: brlcad/trunk/src/libged/gqa.c =================================================================== --- brlcad/trunk/src/libged/gqa.c 2019-02-08 00:43:55 UTC (rev 72372) +++ brlcad/trunk/src/libged/gqa.c 2019-02-08 18:28:41 UTC (rev 72373) @@ -163,8 +163,7 @@ } ged_gqa_plot; /* the entries in the density table */ -struct density_entry *densities = NULL; -static int num_densities; +struct analyze_densities *densities = NULL; /* summary data structure for objects specified on command line */ static struct per_obj_data { @@ -749,44 +748,41 @@ * 0 on success * !0 on failure */ -int +HIDDEN int get_densities_from_file(char *name) { - struct stat sb; - - FILE *fp = (FILE *)NULL; + struct bu_vls msgs = BU_VLS_INIT_ZERO; + struct bu_mapped_file *dfile = NULL; char *buf = NULL; int ret = 0; - size_t sret = 0; - fp = fopen(name, "rb"); - if (fp == (FILE *)NULL) { - bu_vls_printf(_ged_current_gedp->ged_result_str, "Could not open file - %s\n", name); + if (!bu_file_exists(name, NULL)) { + bu_vls_printf(_ged_current_gedp->ged_result_str, "Could not find density file - %s\n", name); return GED_ERROR; } - if (stat(name, &sb)) { - bu_vls_printf(_ged_current_gedp->ged_result_str, "Could not read file - %s\n", name); - fclose(fp); + dfile = bu_open_mapped_file(name, "densities file"); + if (!dfile) { + bu_vls_printf(_ged_current_gedp->ged_result_str, "Could not open density file - %s\n", name); return GED_ERROR; } - densities = (struct density_entry *)bu_calloc(128, sizeof(struct density_entry), "density entries"); - num_densities = 128; + buf = (char *)(dfile->buf); - /* a mapped file would make more sense here */ - buf = (char *)bu_malloc(sb.st_size+1, "density buffer"); - sret = fread(buf, sb.st_size, 1, fp); - if (sret != 1) - perror("fread"); - ret = parse_densities_buffer(buf, (unsigned long)sb.st_size, &densities, _ged_current_gedp->ged_result_str, &num_densities); - bu_free(buf, "density buffer"); - fclose(fp); + (void)analyze_densities_create(&densities); - return ret; + ret = analyze_densities_load(densities, buf, &msgs); + + if (bu_vls_strlen(&msgs)) { + bu_vls_printf(_ged_current_gedp->ged_result_str, "Problem reading densities file:\n%s\n", bu_vls_cstr(&msgs)); + } + bu_vls_free(&msgs); + + bu_close_mapped_file(dfile); + + return (ret <= 0) ? GED_ERROR : GED_OK; } - /** * Returns * 0 on success @@ -795,6 +791,7 @@ int get_densities_from_database(struct rt_i *rtip) { + struct bu_vls msgs = BU_VLS_INIT_ZERO; struct directory *dp; struct rt_db_internal intern; struct rt_binunif_internal *bu; @@ -820,15 +817,18 @@ RT_CHECK_BINUNIF (bu); - densities = (struct density_entry *)bu_calloc(128, sizeof(struct density_entry), "density entries"); - num_densities = 128; + (void)analyze_densities_create(&densities); - /* Acquire one extra byte to accommodate parse_densities_buffer() - * (i.e. it wants to write an EOS in buf[bu->count]). - */ buf = (char *)bu_malloc(bu->count+1, "density buffer"); memcpy(buf, bu->u.int8, bu->count); - ret = parse_densities_buffer(buf, bu->count, &densities, _ged_current_gedp->ged_result_str, &num_densities); + + ret = analyze_densities_load(densities, buf, &msgs); + + if (bu_vls_strlen(&msgs)) { + bu_vls_printf(_ged_current_gedp->ged_result_str, "Problem reading densities file:\n%s\n", bu_vls_cstr(&msgs)); + } + bu_vls_free(&msgs); + bu_free((void *)buf, "density buffer"); return ret; @@ -993,8 +993,10 @@ /* examine each partition until we get back to the head */ for (pp=PartHeadp->pt_forw; pp != PartHeadp; pp = pp->pt_forw) { - struct density_entry *de; + long int material_id = pp->pt_regionp->reg_gmater; + fastf_t grams_per_cu_mm = analyze_densities_density(densities, material_id); + /* inhit info */ dist = pp->pt_outhit->hit_dist - pp->pt_inhit->hit_dist; VJOIN1(pt, ap->a_ray.r_pt, pp->pt_inhit->hit_dist, ap->a_ray.r_dir); @@ -1068,135 +1070,121 @@ } /* make sure mater index is within range of densities */ - if (pp->pt_regionp->reg_gmater >= num_densities) { + if (pp->pt_regionp->reg_gmater < 0) { bu_semaphore_acquire(GED_SEM_WORKER); - bu_vls_printf(_ged_current_gedp->ged_result_str, "density index %d on region %s is outside of range of table [1..%d]\nSet GIFTmater on region or add entry to density table\n", + bu_vls_printf(_ged_current_gedp->ged_result_str, "density index %d on region %s is outside of range\nSet GIFTmater on region or add entry to density table\n", pp->pt_regionp->reg_gmater, - pp->pt_regionp->reg_name, - num_densities); /* XXX this should do something else */ + pp->pt_regionp->reg_name); bu_semaphore_release(GED_SEM_WORKER); return GED_ERROR; } else { - /* make sure the density index has been set */ - de = &densities[pp->pt_regionp->reg_gmater]; - if (de->magic == DENSITY_MAGIC) { - struct per_region_data *prd; - vect_t cmass; - vect_t lenTorque; - fastf_t Lx = state->span[0]/state->steps[0]; - fastf_t Ly = state->span[1]/state->steps[1]; - fastf_t Lz = state->span[2]/state->steps[2]; - fastf_t Lx_sq; - fastf_t Ly_sq; - fastf_t Lz_sq; - fastf_t cell_area; - int los; + struct per_region_data *prd; + vect_t cmass; + vect_t lenTorque; + fastf_t Lx = state->span[0]/state->steps[0]; + fastf_t Ly = state->span[1]/state->steps[1]; + fastf_t Lz = state->span[2]/state->steps[2]; + fastf_t Lx_sq; + fastf_t Ly_sq; + fastf_t Lz_sq; + fastf_t cell_area; + int los; - switch (state->i_axis) { - case 0: - Lx_sq = dist*pp->pt_regionp->reg_los*0.01; - Lx_sq *= Lx_sq; - Ly_sq = Ly*Ly; - Lz_sq = Lz*Lz; - cell_area = Ly_sq; - break; - case 1: - Lx_sq = Lx*Lx; - Ly_sq = dist*pp->pt_regionp->reg_los*0.01; - Ly_sq *= Ly_sq; - Lz_sq = Lz*Lz; - cell_area = Lx_sq; - break; - case 2: - default: - Lx_sq = Lx*Lx; - Ly_sq = Ly*Ly; - Lz_sq = dist*pp->pt_regionp->reg_los*0.01; - Lz_sq *= Lz_sq; - cell_area = Lx_sq; - break; - } + switch (state->i_axis) { + case 0: + Lx_sq = dist*pp->pt_regionp->reg_los*0.01; + Lx_sq *= Lx_sq; + Ly_sq = Ly*Ly; + Lz_sq = Lz*Lz; + cell_area = Ly_sq; + break; + case 1: + Lx_sq = Lx*Lx; + Ly_sq = dist*pp->pt_regionp->reg_los*0.01; + Ly_sq *= Ly_sq; + Lz_sq = Lz*Lz; + cell_area = Lx_sq; + break; + case 2: + default: + Lx_sq = Lx*Lx; + Ly_sq = Ly*Ly; + Lz_sq = dist*pp->pt_regionp->reg_los*0.01; + Lz_sq *= Lz_sq; + cell_area = Lx_sq; + break; + } - /* factor in the density of this object weight - * computation, factoring in the LOS percentage - * material of the object - */ - los = pp->pt_regionp->reg_los; + /* factor in the density of this object weight + * computation, factoring in the LOS percentage + * material of the object + */ + los = pp->pt_regionp->reg_los; - if (los < 1) { - bu_semaphore_acquire(GED_SEM_WORKER); - bu_vls_printf(_ged_current_gedp->ged_result_str, "bad LOS (%d) on %s\n", los, pp->pt_regionp->reg_name); - bu_semaphore_release(GED_SEM_WORKER); - } + if (los < 1) { + bu_semaphore_acquire(GED_SEM_WORKER); + bu_vls_printf(_ged_current_gedp->ged_result_str, "bad LOS (%d) on %s\n", los, pp->pt_regionp->reg_name); + bu_semaphore_release(GED_SEM_WORKER); + } - /* accumulate the total weight values */ - val = de->grams_per_cu_mm * dist * (pp->pt_regionp->reg_los * 0.01); - ap->A_LENDEN += val; + /* accumulate the total weight values */ + val = grams_per_cu_mm * dist * (pp->pt_regionp->reg_los * 0.01); + ap->A_LENDEN += val; - prd = ((struct per_region_data *)pp->pt_regionp->reg_udata); - /* accumulate the per-region per-view weight values */ - bu_semaphore_acquire(GED_SEM_STATS); - prd->r_lenDensity[state->i_axis] += val; + prd = ((struct per_region_data *)pp->pt_regionp->reg_udata); + /* accumulate the per-region per-view weight values */ + bu_semaphore_acquire(GED_SEM_STATS); + prd->r_lenDensity[state->i_axis] += val; - /* accumulate the per-object per-view weight values */ - prd->optr->o_lenDensity[state->i_axis] += val; + /* accumulate the per-object per-view weight values */ + prd->optr->o_lenDensity[state->i_axis] += val; - if (analysis_flags & ANALYSIS_CENTROIDS) { - /* calculate the center of mass for this partition */ - VJOIN1(cmass, pt, dist*0.5, ap->a_ray.r_dir); + if (analysis_flags & ANALYSIS_CENTROIDS) { + /* calculate the center of mass for this partition */ + VJOIN1(cmass, pt, dist*0.5, ap->a_ray.r_dir); - /* calculate the lenTorque for this partition (i.e. centerOfMass * lenDensity) */ - VSCALE(lenTorque, cmass, val); + /* calculate the lenTorque for this partition (i.e. centerOfMass * lenDensity) */ + VSCALE(lenTorque, cmass, val); - /* accumulate per-object per-view torque values */ - VADD2(&prd->optr->o_lenTorque[state->i_axis*3], &prd->optr->o_lenTorque[state->i_axis*3], lenTorque); + /* accumulate per-object per-view torque values */ + VADD2(&prd->optr->o_lenTorque[state->i_axis*3], &prd->optr->o_lenTorque[state->i_axis*3], lenTorque); - /* accumulate the total lenTorque */ - VADD2(&state->m_lenTorque[state->i_axis*3], &state->m_lenTorque[state->i_axis*3], lenTorque); + /* accumulate the total lenTorque */ + VADD2(&state->m_lenTorque[state->i_axis*3], &state->m_lenTorque[state->i_axis*3], lenTorque); - if (analysis_flags & ANALYSIS_MOMENTS) { - vectp_t moi; - vectp_t poi = &state->m_poi[state->i_axis*3]; - fastf_t dx_sq = cmass[X]*cmass[X]; - fastf_t dy_sq = cmass[Y]*cmass[Y]; - fastf_t dz_sq = cmass[Z]*cmass[Z]; - fastf_t mass = val * cell_area; - static const fastf_t ONE_TWELFTH = 1.0 / 12.0; + if (analysis_flags & ANALYSIS_MOMENTS) { + vectp_t moi; + vectp_t poi = &state->m_poi[state->i_axis*3]; + fastf_t dx_sq = cmass[X]*cmass[X]; + fastf_t dy_sq = cmass[Y]*cmass[Y]; + fastf_t dz_sq = cmass[Z]*cmass[Z]; + fastf_t mass = val * cell_area; + static const fastf_t ONE_TWELFTH = 1.0 / 12.0; - /* Collect moments and products of inertia for the current object */ - moi = &prd->optr->o_moi[state->i_axis*3]; - moi[X] += ONE_TWELFTH*mass*(Ly_sq + Lz_sq) + mass*(dy_sq + dz_sq); - moi[Y] += ONE_TWELFTH*mass*(Lx_sq + Lz_sq) + mass*(dx_sq + dz_sq); - moi[Z] += ONE_TWELFTH*mass*(Lx_sq + Ly_sq) + mass*(dx_sq + dy_sq); - poi = &prd->optr->o_poi[state->i_axis*3]; - poi[X] -= mass*cmass[X]*cmass[Y]; - poi[Y] -= mass*cmass[X]*cmass[Z]; - poi[Z] -= mass*cmass[Y]*cmass[Z]; + /* Collect moments and products of inertia for the current object */ + moi = &prd->optr->o_moi[state->i_axis*3]; + moi[X] += ONE_TWELFTH*mass*(Ly_sq + Lz_sq) + mass*(dy_sq + dz_sq); + moi[Y] += ONE_TWELFTH*mass*(Lx_sq + Lz_sq) + mass*(dx_sq + dz_sq); + moi[Z] += ONE_TWELFTH*mass*(Lx_sq + Ly_sq) + mass*(dx_sq + dy_sq); + poi = &prd->optr->o_poi[state->i_axis*3]; + poi[X] -= mass*cmass[X]*cmass[Y]; + poi[Y] -= mass*cmass[X]*cmass[Z]; + poi[Z] -= mass*cmass[Y]*cmass[Z]; - /* Collect moments and products of inertia for all objects */ - moi = &state->m_moi[state->i_axis*3]; - moi[X] += ONE_TWELFTH*mass*(Ly_sq + Lz_sq) + mass*(dy_sq + dz_sq); - moi[Y] += ONE_TWELFTH*mass*(Lx_sq + Lz_sq) + mass*(dx_sq + dz_sq); - moi[Z] += ONE_TWELFTH*mass*(Lx_sq + Ly_sq) + mass*(dx_sq + dy_sq); - poi = &state->m_poi[state->i_axis*3]; - poi[X] -= mass*cmass[X]*cmass[Y]; - poi[Y] -= mass*cmass[X]*cmass[Z]; - poi[Z] -= mass*cmass[Y]*cmass[Z]; - } + /* Collect moments and products of inertia for all objects */ + moi = &state->m_moi[state->i_axis*3]; + moi[X] += ONE_TWELFTH*mass*(Ly_sq + Lz_sq) + mass*(dy_sq + dz_sq); + moi[Y] += ONE_TWELFTH*mass*(Lx_sq + Lz_sq) + mass*(dx_sq + dz_sq); + moi[Z] += ONE_TWELFTH*mass*(Lx_sq + Ly_sq) + mass*(dx_sq + dy_sq); + poi = &state->m_poi[state->i_axis*3]; + poi[X] -= mass*cmass[X]*cmass[Y]; + poi[Y] -= mass*cmass[X]*cmass[Z]; + poi[Z] -= mass*cmass[Y]*cmass[Z]; } + } - bu_semaphore_release(GED_SEM_STATS); - - } else { - bu_semaphore_acquire(GED_SEM_WORKER); - bu_vls_printf(_ged_current_gedp->ged_result_str, "density index %d from region %s is not set.\nAdd entry to density table\n", - pp->pt_regionp->reg_gmater, pp->pt_regionp->reg_name); - bu_semaphore_release(GED_SEM_WORKER); - - aborted = 1; - return GED_ERROR; - } + bu_semaphore_release(GED_SEM_STATS); } } @@ -1658,10 +1646,10 @@ if (analysis_flags & ANALYSIS_WEIGHTS) { if (weight_tolerance < 0.0) { double max_den = 0.0; - int i; - for (i = 0; i < num_densities; i++) { - if (densities[i].grams_per_cu_mm > max_den) - max_den = densities[i].grams_per_cu_mm; + long int curr_id = -1; + while ((curr_id = analyze_densities_next(densities, curr_id)) != -1) { + if (analyze_densities_density(densities, curr_id) > max_den) + max_den = analyze_densities_density(densities, curr_id); } weight_tolerance = span[X] * span[Y] * span[Z] * 0.1 * max_den; bu_vls_printf(_ged_current_gedp->ged_result_str, "setting weight tolerance to %g %s\n", Modified: brlcad/trunk/src/libged/mater.cxx =================================================================== --- brlcad/trunk/src/libged/mater.cxx 2019-02-08 00:43:55 UTC (rev 72372) +++ brlcad/trunk/src/libged/mater.cxx 2019-02-08 18:28:41 UTC (rev 72373) @@ -311,17 +311,13 @@ _ged_mater_mat_id(struct ged *gedp, int argc, const char *argv[]) { int names_from_ids = 0; - int num_densities = 128; - struct density_entry *densities = (struct density_entry *)bu_calloc(num_densities, sizeof(struct density_entry), "density entries"); + struct analyze_densities *densities; struct bu_mapped_file *dfile = NULL; char *dbuff = NULL; struct bu_mapped_file *mfile = NULL; char *mbuff = NULL; - std::map<std::string, int> n2d; - std::map<int, std::string> d2n; std::set<std::string> listed_materials; std::set<std::string> defined_materials; - std::set<std::string> g_materials; std::map<std::string,std::string> listed_to_defined; if (BU_STR_EQUAL(argv[1], "--names-from-ids")) { @@ -348,6 +344,8 @@ /* OK, we know what we're doing - start reading inputs */ + analyze_densities_create(&densities); + dfile = bu_open_mapped_file(argv[1], "densities file"); if (!dfile) { bu_vls_printf(gedp->ged_result_str, "could not open density file %s", argv[1]); @@ -355,39 +353,23 @@ } dbuff = (char *)(dfile->buf); - if (parse_densities_buffer(dbuff, dfile->buflen, &densities, NULL, &num_densities) != ANALYZE_OK) { - bu_vls_printf(gedp->ged_result_str, "could not parse density file %s", argv[1]); + struct bu_vls pbuff_msgs = BU_VLS_INIT_ZERO; + if (analyze_densities_load(densities, dbuff, &pbuff_msgs) == 0) { + bu_vls_printf(gedp->ged_result_str, "could not parse density file %s: %s", argv[1], bu_vls_cstr(&pbuff_msgs)); bu_close_mapped_file(dfile); + bu_vls_free(&pbuff_msgs); return GED_ERROR; - } else { - /* Populate the name->material_id map from the density file */ - int found_duplicate = 0; - for (int idx = 0; idx < num_densities; idx++) { - if (densities[idx].magic == DENSITY_MAGIC) { - if (n2d.find(std::string(densities[idx].name)) != n2d.end()) { - found_duplicate = 1; - bu_vls_printf(gedp->ged_result_str, "density file contains multiple densities for %s", densities[idx].name); - } - n2d[std::string(densities[idx].name)] = idx; - defined_materials.insert(std::string(densities[idx].name)); - bu_free(densities[idx].name, "free density name"); - } - } - std::map<std::string, int>::iterator n2d_it; - for (n2d_it = n2d.begin(); n2d_it != n2d.end(); n2d_it++) { - d2n[n2d_it->second] = n2d_it->first; - } - bu_free(densities, "density_entry array"); - bu_close_mapped_file(dfile); - if (found_duplicate) { - return GED_ERROR; - } } // For simplicity, let the complex -> simple map know to map known materials to themselves - std::set<std::string>::iterator s_it; - for (s_it = defined_materials.begin(); s_it != defined_materials.end(); s_it++) { - listed_to_defined.insert(std::pair<std::string, std::string>(*s_it, *s_it)); + long int curr_id = -1; + long int id_cnt = 0; + while ((curr_id = analyze_densities_next(densities, curr_id)) != -1) { + id_cnt++; + char *cname = analyze_densities_name(densities, curr_id); + listed_to_defined.insert(std::pair<std::string, std::string>(std::string(cname), std::string(cname))); + defined_materials.insert(std::string(cname)); + bu_free(cname, "free name copy"); } if (argc == 3 && !names_from_ids) { @@ -439,11 +421,12 @@ } const char *mat_id = bu_avs_get(&avs, "material_id"); const char *oname = bu_avs_get(&avs, "material_name"); - if (d2n.find(std::stoi(mat_id)) == d2n.end()) { + if (analyze_densities_density(densities, std::stol(mat_id)) < 0) { bu_vls_printf(gedp->ged_result_str, "Warning: no name found in density file for material_id %s on object %s, skipping\n", mat_id, dp->d_namep); if (oname) { - if (n2d.find(std::string(oname)) != n2d.end()) { - bu_vls_printf(gedp->ged_result_str, "Material id collision: object %s has material_name \"%s\" and material_id %s, but the specified density file defines \"%s\" as material_id %s.\n", dp->d_namep, oname, mat_id, oname, std::to_string(n2d.find(std::string(oname))->second).c_str()); + long int found_id_cnt = analyze_densities_id(NULL, 0, densities, oname); + if (found_id_cnt) { + bu_vls_printf(gedp->ged_result_str, "Material id collision: object %s has material_name \"%s\" and material_id %s, but the specified density file defines \"%s\" as a different material id.\n", dp->d_namep, oname, mat_id, oname); } else { bu_vls_printf(gedp->ged_result_str, "Unknown material: object %s has material_name %s, which is not a material defined in the specified density file.\n", dp->d_namep, oname); } @@ -452,9 +435,9 @@ continue; } // Found a name, assign it if it doesn't match - std::string nname = d2n[std::stoi(mat_id)]; - if (!oname || nname.compare(std::string(oname))) { - (void)bu_avs_add(&avs, "material_name", nname.c_str()); + char *nname = analyze_densities_name(densities, std::stol(mat_id)); + if (!oname || !BU_STR_EQUAL(nname,oname)) { + (void)bu_avs_add(&avs, "material_name", nname); if (db5_update_attributes(dp, &avs, gedp->ged_wdbp->dbip)) { bu_vls_printf(gedp->ged_result_str, "Error: failed to update object %s attributes\n", dp->d_namep); bu_avs_free(&avs); @@ -464,6 +447,7 @@ // Already has correct name, no need to update bu_avs_free(&avs); } + bu_free(nname, "free name"); } return GED_OK; } else { @@ -498,7 +482,13 @@ continue; } - int nid = n2d[listed_to_defined[std::string(oname)]]; + long int wids[1]; + int id_found_cnt = analyze_densities_id((long int *)wids, 1, densities, listed_to_defined[std::string(oname)].c_str()); + if (!id_found_cnt) { + bu_vls_printf(gedp->ged_result_str, "Error: failed to find ID for %s\n", oname); + return GED_ERROR; + } + int nid = wids[0]; if (!mat_id || std::stoi(mat_id) != nid) { (void)bu_avs_add(&avs, "material_id", std::to_string(nid).c_str()); if (db5_update_attributes(dp, &avs, gedp->ged_wdbp->dbip)) { Modified: brlcad/trunk/src/rt/CMakeLists.txt =================================================================== --- brlcad/trunk/src/rt/CMakeLists.txt 2019-02-08 00:43:55 UTC (rev 72372) +++ brlcad/trunk/src/rt/CMakeLists.txt 2019-02-08 18:28:41 UTC (rev 72373) @@ -81,7 +81,7 @@ BRLCAD_ADDEXEC(rtsil "${LIBRTUIF_SOURCES};viewsil.c" "${CMAKE_THREAD_LIBS_INIT};librt;libnmg;libfb;liboptical;libicv;${M_LIBRARY}") -BRLCAD_ADDEXEC(rtweight "${LIBRTUIF_SOURCES};viewweight.c" "${CMAKE_THREAD_LIBS_INIT};librt;libnmg;libfb;liboptical;libicv;${M_LIBRARY}") +BRLCAD_ADDEXEC(rtweight "${LIBRTUIF_SOURCES};viewweight.c" "${CMAKE_THREAD_LIBS_INIT};librt;libnmg;libfb;liboptical;libicv;libanalyze;${M_LIBRARY}") set_property(TARGET rtweight APPEND PROPERTY COMPILE_DEFINITIONS "RT_TXT_OUTPUT") BRLCAD_ADDEXEC(rtxray "${LIBRTUIF_SOURCES};viewxray.c" "${CMAKE_THREAD_LIBS_INIT};librt;libnmg;libfb;liboptical;libicv;${M_LIBRARY}") This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. _______________________________________________ BRL-CAD Source Commits mailing list brlcad-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/brlcad-commits