Esempio n. 1
0
/*
 * Validate 'point file data format string', determine and output the
 * point-cloud type. A valid null terminated string is expected as
 * input.  The function returns GED_ERROR if the format string is
 * invalid or if null pointers were passed to the function.
 */
int
str2type(const char *format_string, rt_pnt_type *pnt_type, struct bu_vls *ged_result_str)
{
    struct bu_vls str = BU_VLS_INIT_ZERO;
    char *temp_string = (char *)NULL;
    size_t idx = 0;
    size_t format_string_length = 0;
    int ret = GED_OK;

    if ((format_string == (char *)NULL) || (pnt_type == (rt_pnt_type *)NULL)) {
        bu_vls_printf(ged_result_str, "NULL pointer(s) passed to function 'str2type'.\n");
        ret = GED_ERROR;
    } else {
        format_string_length = strlen(format_string);

        /* remove any '?' from format string before testing for point-cloud type */
        for (idx = 0 ; idx < format_string_length ; idx++) {
            if (format_string[idx] != '?') {
                bu_vls_putc(&str, format_string[idx]);
            }
        }

        bu_vls_trimspace(&str);

        temp_string = bu_vls_addr(&str);
        bu_sort(temp_string, strlen(temp_string), sizeof(char), (int (*)(const void *a, const void *b, void *arg))compare_char, NULL);

        if (BU_STR_EQUAL(temp_string, "xyz")) {
            *pnt_type = RT_PNT_TYPE_PNT;
        } else if (BU_STR_EQUAL(temp_string, "bgrxyz")) {
            *pnt_type = RT_PNT_TYPE_COL;
        } else if (BU_STR_EQUAL(temp_string, "sxyz")) {
            *pnt_type = RT_PNT_TYPE_SCA;
        } else if (BU_STR_EQUAL(temp_string, "ijkxyz")) {
            *pnt_type = RT_PNT_TYPE_NRM;
        } else if (BU_STR_EQUAL(temp_string, "bgrsxyz")) {
            *pnt_type = RT_PNT_TYPE_COL_SCA;
        } else if (BU_STR_EQUAL(temp_string, "bgijkrxyz")) {
            *pnt_type = RT_PNT_TYPE_COL_NRM;
        } else if (BU_STR_EQUAL(temp_string, "ijksxyz")) {
            *pnt_type = RT_PNT_TYPE_SCA_NRM;
        } else if (BU_STR_EQUAL(temp_string, "bgijkrsxyz")) {
            *pnt_type = RT_PNT_TYPE_COL_SCA_NRM;
        } else {
            bu_vls_printf(ged_result_str, "Invalid format string '%s'", format_string);
            ret = GED_ERROR;
        }
    }

    bu_vls_free(&str);

    return ret;
}
Esempio n. 2
0
int
ged_lc(struct ged *gedp, int argc, const char *argv[])
{
    char *file_name = NULL;
    int file_name_flag_cnt = 0;
    int sort_column = 1;
    int sort_column_flag_cnt = 0;
    int find_duplicates_flag = 0;
    int skip_special_duplicates_flag = 0;
    int skip_subtracted_regions_flag = 0;
    int descending_sort_flag = 0;
    int unrecognized_flag_cnt = 0;

    int orig_argc;
    const char **orig_argv;

    static const char *usage = "[-d|-s] [-r] [-z] [-0|-1|-2|-3|-4|-5] [-f {FileName}] {GroupName}";

    int c;
    int error_cnt = 0;

    FILE *outfile = NULL;
    struct bu_vls *output;

    const char *group_name;

    size_t i,j;
    struct bu_ptbl results1 = BU_PTBL_INIT_ZERO;
    struct bu_ptbl results2 = BU_PTBL_INIT_ZERO;
    char *path;
    char *plan;
    struct db_full_path root;
    int matches;
    struct region_record *regions;
    size_t ignored_cnt = 0;

    /* The defaults are the minimum widths to accommodate column headers */
    size_t region_id_len_max = 2;
    size_t material_id_len_max = 3;
    size_t los_len_max = 3;
    size_t obj_len_max = 6;

    /* For the output at the end */
    size_t start, end, incr;

    /* initialize result */
    bu_vls_trunc(gedp->ged_result_str, 0);

    if (argc == 1) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s\n", usage);
	return GED_HELP;
    }

    GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
    GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);

    bu_optind = 1; /* re-init bu_getopt() */
    while ((c = bu_getopt(argc, (char * const *)argv, "dsrz012345f:")) != -1) {
	switch (c) {
	    case '0':
	    case '1':
	    case '2':
	    case '3':
	    case '4':
	    case '5':
		sort_column_flag_cnt++;
		sort_column = c - '0';
		break;
	    case 'f':
		file_name_flag_cnt++;
		file_name = bu_optarg;
		break;
	    case 's':
		skip_special_duplicates_flag = 1;
		/* FALLTHROUGH */
	    case 'd':
		find_duplicates_flag = 1;
		break;
	    case 'r':
		skip_subtracted_regions_flag = 1;
		break;
	    case 'z':
		descending_sort_flag = 1;
		break;
	    default:
		unrecognized_flag_cnt++;
	}
    }
    orig_argc = argc;
    orig_argv = argv;
    argc -= (bu_optind - 1);
    argv += (bu_optind - 1);

    /* Attempt to recreate the exact error messages from the original lc.tcl */

    if (file_name_flag_cnt > 1) {
	bu_vls_printf(gedp->ged_result_str, "Error: '-f' used more than once.\n");
	error_cnt++;
    }

    if (sort_column_flag_cnt > 1) {
	bu_vls_printf(gedp->ged_result_str, "Error: Sort column defined more than once.\n");
	error_cnt++;
    }

    if (file_name_flag_cnt + argc + unrecognized_flag_cnt > 3) {
	bu_vls_printf(gedp->ged_result_str, "Error: More than one group name and/or file name was specified.\n");
	error_cnt++;
    } else if (argc < 2) {
	if (file_name_flag_cnt && !file_name) {
	    bu_vls_printf(gedp->ged_result_str, "Error: Group name and file name not specified\n");
	} else {
	    bu_vls_printf(gedp->ged_result_str, "Error: Group name not specified.\n");
	}
        error_cnt++;
    } else if (argc + unrecognized_flag_cnt > 2) {
	bu_vls_printf(gedp->ged_result_str, "Error: More than one group name was specified.\n");
	error_cnt++;
    } else if (file_name_flag_cnt && !file_name) {
	bu_vls_printf(gedp->ged_result_str, "Error: File name not specified.\n");
	error_cnt++;
    }

    if (file_name) {
	char *norm_name;
	norm_name = bu_realpath(file_name, NULL);
	if (file_name[0] == '-') {
	    bu_vls_printf(gedp->ged_result_str, "Error: File name can not start with '-'.\n");
	    error_cnt++;
	} else if (bu_file_exists(file_name, NULL)) {
	    bu_vls_printf(gedp->ged_result_str, "Error: Output file %s already exists.\n",norm_name);
	    error_cnt++;
	} else {
	    outfile = fopen(file_name, "w");
	    if (!outfile) {
		bu_vls_printf(gedp->ged_result_str, "Error: %d\n", errno);
		error_cnt++;
	    }
	}
	bu_vls_printf(gedp->ged_result_str, "Output filename: %s\n", norm_name);
	bu_free(norm_name, "ged_lc");
	output = bu_vls_vlsinit();
    } else {
	output = gedp->ged_result_str;
    }

    if (error_cnt > 0) { return GED_ERROR; }

    group_name = argv[1];

    /* The 7 is for the "-name" and '\0' */
    plan = (char *) bu_malloc(sizeof(char) * (strlen(group_name) + 7), "ged_lc");
    sprintf(plan, "-name %s", group_name);
    matches = db_search(&results1, DB_SEARCH_TREE, plan, 0, NULL, gedp->ged_wdbp->dbip);
    if (matches < 1) {
	bu_vls_printf(gedp->ged_result_str, "Error: Group '%s' does not exist.\n", group_name);
	return GED_ERROR;
    }
    bu_free(plan, "ged_lc");
    db_search_free(&results1);

    if (skip_subtracted_regions_flag) {
	plan = "-type region ! -bool -";
    } else {
	plan = "-type region";
    }
    path = (char *) bu_malloc(sizeof(char) * (strlen(group_name) + 2), "ged_lc");
    sprintf(path, "/%s", group_name);
    db_string_to_path(&root, gedp->ged_wdbp->dbip, path);
    matches = db_search(&results2, DB_SEARCH_TREE, plan, root.fp_len, root.fp_names, gedp->ged_wdbp->dbip);
    bu_free(path, "ged_lc");
    if (matches < 1) { return GED_ERROR; }
    regions = (struct region_record *) bu_malloc(sizeof(struct region_record) * BU_PTBL_LEN(&results2), "ged_lc");
    for (i = 0; i < BU_PTBL_LEN(&results2); i++) {
	struct db_full_path *entry = (struct db_full_path *)BU_PTBL_GET(&results2, i);
	struct directory *dp_curr_dir = DB_FULL_PATH_CUR_DIR(entry);
	struct bu_attribute_value_set avs;

    	j = BU_PTBL_LEN(&results2) - i - 1 ;
	regions[j].ignore = 0;

	bu_avs_init_empty(&avs);
	db5_get_attributes(gedp->ged_wdbp->dbip, &avs, dp_curr_dir);

	regions[j].region_id = get_attr(&avs, "region_id");
	V_MAX(region_id_len_max, strlen(regions[j].region_id));
	regions[j].material_id = get_attr(&avs, "material_id");
	V_MAX(material_id_len_max, strlen(regions[j].material_id));
	regions[j].los = get_attr(&avs, "los");
	V_MAX(los_len_max, strlen(regions[j].los));
	regions[j].obj_name = dp_curr_dir->d_namep;
	V_MAX(obj_len_max, strlen(regions[j].obj_name));

	if (entry->fp_len > 1) {
	    struct directory *dp_parent = DB_FULL_PATH_GET(entry, entry->fp_len - 2);
	    regions[j].obj_parent = dp_parent->d_namep;
	} else {
	    regions[j].obj_parent = "--";
	}
    }

    if (find_duplicates_flag) {

	bu_sort((void *) regions, BU_PTBL_LEN(&results2), sizeof(struct region_record), cmp_regions, NULL);

	for (i = 1;  i < BU_PTBL_LEN(&results2); i++) {
	    int same;
	    if (skip_special_duplicates_flag) {
		same = !cmp_regions((void *)&(regions[i - 1]), (void *)&(regions[i]), NULL);
	    } else {
		same = !bu_strcmp(regions[i - 1].region_id, regions[i].region_id);
	    }
	    if (same) {
		regions[i].ignore = 1;
		ignored_cnt++;
	    }
	}

	if (ignored_cnt == BU_PTBL_LEN(&results2)) {
	    if (file_name) {
		print_cmd_args(output, orig_argc, orig_argv);
		bu_vls_printf(output, "No duplicate region_id\n");
		bu_vls_fwrite(outfile, output);
		fclose(outfile);
	    }
	    bu_vls_printf(gedp->ged_result_str, "No duplicate region_id\n");
	    bu_vls_printf(gedp->ged_result_str, "Done.\n");
	    bu_free(regions, "ged_lc");
	    return GED_ERROR;
	}
    }

    if (sort_column > 0) {
	bu_sort((void *) regions, BU_PTBL_LEN(&results2), sizeof(struct region_record), sort_regions, (void *)&sort_column);
    }

    if (file_name) {
	print_cmd_args(output, orig_argc, orig_argv);
    }

    bu_vls_printf(output, "List length: %d\n", BU_PTBL_LEN(&results2) - ignored_cnt);
    bu_vls_printf(output, "%-*s %-*s %-*s %-*s %s\n",
		  region_id_len_max + 1, "ID",
		  material_id_len_max + 1, "MAT",
		  los_len_max, "LOS",
		  obj_len_max,  "REGION",
		  "PARENT");
    end = BU_PTBL_LEN(&results2);
    if (descending_sort_flag) {
	start = end - 1; end = -1; incr = -1;
    } else {
	start = 0; incr = 1;
    }
    for (i = start; i != end; i += incr) {
	if (regions[i].ignore) { continue; }
	bu_vls_printf(output, "%-*s %-*s %-*s %-*s %s\n",
		      region_id_len_max + 1, regions[i].region_id,
		      material_id_len_max + 1, regions[i].material_id,
		      los_len_max, regions[i].los,
		      obj_len_max, regions[i].obj_name,
		      regions[i].obj_parent);
    }
    bu_vls_printf(gedp->ged_result_str, "Done.\n");

    if (file_name) {
	bu_vls_fwrite(outfile, output);
	fclose(outfile);
    }

    bu_free(regions, "ged_lc");

    return GED_OK;
}
/*
 * This is called (from viewshade() in shade.c) once for each hit point
 * to be shaded.  The purpose here is to fill in values in the shadework
 * structure.
 *
 * dp is a pointer to the shader-specific struct
 */
int
bbd_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
{
    register struct bbd_specific *bbd_sp = (struct bbd_specific *)dp;
    union tree *tp;
    struct bbd_img *bi;
    struct imgdist id[MAX_IMAGES];
    size_t i;

    /* check the validity of the arguments we got */
    RT_AP_CHECK(ap);
    RT_CHECK_PT(pp);
    CK_bbd_SP(bbd_sp);

    if (rdebug&RDEBUG_SHADE) {
	bu_struct_print("bbd_render Parameters:",
			bbd_print_tab, (char *)bbd_sp);
	bu_log("pixel %d %d\n", ap->a_x, ap->a_y);
	bu_log("bbd region: %s\n", pp->pt_regionp->reg_name);
    }
    tp = pp->pt_regionp->reg_treetop;
    if (tp->tr_a.tu_op != OP_SOLID) {
	bu_log("%s:%d region %s rendering bbd should have found OP_SOLID, not %d\n",
	       __FILE__, __LINE__, pp->pt_regionp->reg_name, tp->tr_a.tu_op);
	bu_bomb("\n");
    }


    swp->sw_transmit = 1.0;
    VSETALL(swp->sw_color, 0.0);
    VSETALL(swp->sw_basecolor, 1.0);

    i = 0;
    for (BU_LIST_FOR(bi, bbd_img, &bbd_sp->imgs)) {
	/* find out if the ray hits the plane */
	id[i].index = i;
	id[i].bi = bi;
	id[i].status = bn_isect_line3_plane(&id[i].dist,
					    ap->a_ray.r_pt, ap->a_ray.r_dir,
					    bi->img_plane, &ap->a_rt_i->rti_tol);
	i++;
    }

    bu_sort(id, bbd_sp->img_count, sizeof(id[0]), &imgdist_compare, NULL);

    for (i = 0; i < bbd_sp->img_count && swp->sw_transmit > 0.0; i++) {
	if (id[i].status > 0) do_ray_image(ap, pp, swp, bbd_sp, id[i].bi, id[i].dist);
    }
    if (rdebug&RDEBUG_SHADE) {
	bu_log("color %g %g %g\n", V3ARGS(swp->sw_color));
    }
    /* shader must perform transmission/reflection calculations
     *
     * 0 < swp->sw_transmit <= 1 causes transmission computations
     * 0 < swp->sw_reflect <= 1 causes reflection computations
     */
    if (swp->sw_reflect > 0 || swp->sw_transmit > 0) {
	int level = ap->a_level;
	ap->a_level = 0; /* Bogus hack to keep rr_render from giving up */
	(void)rr_render(ap, pp, swp);
	ap->a_level = level;
    }
    if (rdebug&RDEBUG_SHADE) {
	bu_log("color %g %g %g\n", V3ARGS(swp->sw_color));
    }
    return 1;
}
Esempio n. 4
0
int main(int argc, char *argv[]) {
    int i, g; /* generation and parent counters */
    int parent1, parent2;
    int gop;
    fastf_t total_fitness = 0.0f;
    struct fitness_state fstate;
    struct population pop = {NULL, NULL, NULL, NULL, NULL, 0};
    char dbname[256] = {0};
    struct beset_options opts = {DEFAULT_POP_SIZE, DEFAULT_GENS, DEFAULT_RES, 0, 0, 0, 0};
    struct individual *tmp = NULL;
    int  ac;
    struct db_i *source_db;


    ac = parse_args(argc, argv, &opts);
    if (argc - ac != 3)
	usage();


    /* read source model into fstate.rays */
    fit_prep(&fstate, opts.res, opts.res);
    fit_store(argv[ac+2], argv[ac+1], &fstate);


    /* initialize population and spawn initial individuals */
    pop_init(&pop, opts.pop_size);
    pop_spawn(&pop);

    source_db = db_open(argv[ac+1], DB_OPEN_READWRITE);
    db_dirbuild(source_db);
    pop.db_c = db_create("testdb", 5);
    db_close(pop.db_c);


    for (g = 1; g < opts.gens; g++ ) {
#ifdef VERBOSE
	printf("\nGeneration %d:\n"
	       "--------------\n", g);
#endif

	total_fitness = 0.0f;

	snprintf(dbname, 256, "gen%.3d", g);
	pop.db_c = db_create(dbname, 5);

	pop_gop(REPRODUCE, argv[ac+2], NULL, argv[ac+2], NULL, source_db, pop.db_c, &rt_uniresource);


	/* calculate sum of all fitnesses and find
	 * the most fit individual in the population
	 * note: need to calculate outside of main pop
	 * loop because it's needed for pop_wrand_ind()*/
	for (i = 0; i < pop.size; i++) {
	    fit_diff(NL(pop.parent[i].id), pop.db_p, &fstate);
	    pop.parent[i].fitness = fstate.fitness;
	    total_fitness += FITNESS;
	}
	/* sort population - used for keeping top N and dropping bottom M */
	bu_sort((void *)pop.parent, pop.size, sizeof(struct individual), cmp_ind, NULL);

	/* remove lower M of individuals */
	for (i = 0; i < opts.kill_lower; i++) {
	    total_fitness -= pop.parent[i].fitness;
	}


	printf("Most fit from %s was %s with a fitness of %g\n", dbname, NL(pop.parent[pop.size-1].id), pop.parent[pop.size-1].fitness);
	printf("%6.8g\t%6.8g\t%6.8g\n", total_fitness/pop.size, pop.parent[0].fitness, pop.parent[pop.size-1].fitness);
	for (i = 0; i < pop.size; i++) {

	    pop.child[i].id = i;

	    /* keep upper N */
	    if (i >= pop.size - opts.keep_upper) {
		pop_gop(REPRODUCE, NL(pop.parent[i].id), NULL, NL(pop.child[i].id), NULL,
			pop.db_p, pop.db_c, &rt_uniresource);
		continue;
	    }

	    /* Choose a random genetic operation and
	     * a parent which the op will be performed on*/
	    gop = pop_wrand_gop();
	    parent1 = pop_wrand_ind(pop.parent, pop.size, total_fitness, opts.kill_lower);
	    /* only need 1 more individual, can't crossover, so reproduce */
	    if (gop == CROSSOVER && i >= pop.size-opts.keep_upper-1)gop=REPRODUCE;

	    if (gop & (REPRODUCE | MUTATE)) {
#ifdef VERBOSE
		printf("r(%s)\t ---------------> (%s)\n", NL(pop.parent[parent1].id), NL(pop.child[i].id));
#endif
		/* perform the genetic operation and output the child to the child database */
		pop_gop(gop, NL(pop.parent[parent1].id), NULL, NL(pop.child[i].id), NULL,
			pop.db_p, pop.db_c, &rt_uniresource);
	    } else {
		/* If we're performing crossover, we need a second parent */
		parent2 = pop_wrand_ind(pop.parent, pop.size, total_fitness, opts.kill_lower);
		++i;
		pop.child[i].id = i;

#ifdef VERBOSE
		printf("x(%s, %s) --> (%s, %s)\n", NL(pop.parent[parent1].id), NL(pop.parent[parent2].id), pop.child[i-1].id, pop.child[i].id);
#endif
		/* perform the genetic operation and output the children to the child database */
		pop_gop(gop, NL(pop.parent[parent1].id), NL(pop.parent[parent2].id), NL(pop.child[i-1].id), NL(pop.child[i].id),
			pop.db_p, pop.db_c, &rt_uniresource);
	    }

	}


	/* Close parent db and move children
	 * to parent database and population
	 * Note: pop size is constant so we
	 * can keep the storage from the previous
	 * pop.parent for the next pop.child*/
	db_close(pop.db_p);
	pop.db_p = pop.db_c;
	tmp = pop.child;
	pop.child = pop.parent;
	pop.parent = tmp;

    }
    db_close(pop.db_p);

#ifdef VERBOSE
    printf("\nFINAL POPULATION\n"
	   "----------------\n");
    for (i = 0; i < pop.size; i++)
	printf("%s\tf:%.5g\n", NL(pop.child[i].id),
	       pop.child[i].fitness);
#endif


    pop_clean(&pop);
    fit_clean(&fstate);
    return 0;
}
Esempio n. 5
0
int
main(int argc, char **argv)
{
    int arg_1[6] = {5, 2, 6, -15, 168, 3};
    int exp_1[6] = {-15, 2, 3, 5, 6, 168};
    unsigned int arg_2[8] = {56, 4, 7, 156, 2, 0, 23, 8};
    unsigned int exp_2[8] = {0, 2, 4, 7, 8, 23, 56, 156};
    fastf_t arg_3[5] = {5.5, 3.8, -5.5, 1, -7};
    fastf_t exp_3[5] = {-7, -5.5, 1, 3.8, 5.5};
    fastf_t arg_4[7] = {7.42, -5.2, -5.9, 7.36, 7.0, 0, 7.36};
    fastf_t exp_4[7] = {-5.9, -5.2, 0, 7.0, 7.36, 7.36, 7.42};
    char arg_5[4][256] = {"Zfg", "ZFg", "azf", "bzf"};
    char exp_5[4][256] = {"ZFg", "Zfg", "azf", "bzf"};
    char arg_6[3][256] = {"test", "BAB", "aab"};
    char exp_6[3][256] = {"BAB", "aab", "test"};
    fastf_t cmp_7 = -2;
    fastf_t arg_7[9] = {-3, 7, -9, 34, 33, -34, 0, -12, 6};
    fastf_t exp_7[9] = {-3, 0, -9, 6, 7, -12, -34, 33, 34};
    fastf_t cmp_8 = 3;
    fastf_t arg_8[5] = {-5, 23, 5.5, 0, 2};
    fastf_t exp_8[5] = {2, 5.5, 0, -5, 23};
    fastf_t arg_9[5] = {0, 0, 0, 0, 0};
    fastf_t exp_9[5] = {0, 0, 0, 0, 0};
    fastf_t arg_10[5] = {INFINITY, 5, 5.2, 0, -INFINITY};
    fastf_t exp_10[5] = {-INFINITY, 0, 5, 5.2, INFINITY};
    int i, function_num;

    if (argc != 2)
	bu_exit(1, "ERROR: wrong number of parameters");
    sscanf(argv[1], "%d", &function_num);
    switch (function_num) {
	case 1:
	    bu_sort(&arg_1, 6, sizeof(int), comp_1, NULL);
	    for (i = 0; i < 6; i++)
		if (arg_1[i] != exp_1[i])
		    return 1;
	    break;
	case 2:
	    bu_sort(&arg_2, 8, sizeof(int), comp_1, NULL);
	    for (i = 0; i < 8; i++)
		if (arg_2[i] != exp_2[i])
		    return 1;
	    break;
	case 3:
	    bu_sort(&arg_3, 5, sizeof(fastf_t), comp_2, NULL);
	    for (i = 0; i < 5; i++)
		if (!EQUAL(arg_3[i], exp_3[i]))
		    return 1;
	    break;
	case 4:
	    bu_sort(&arg_4, 7, sizeof(fastf_t), comp_2, NULL);
	    for (i = 0; i < 7; i++)
		if (!EQUAL(arg_4[i], exp_4[i]))
		    return 1;
	    break;
	case 5:
	    bu_sort(&arg_5, 4, sizeof(char[256]), comp_3, NULL);
	    for (i = 0; i < 4; i++)
		if (bu_strcmp(arg_5[i], exp_5[i]) != 0)
		    return 1;
	    break;
	case 6:
	    bu_sort(&arg_6, 3, sizeof(char[256]), comp_3, NULL);
	    for (i = 0; i < 3; i++)
		if (bu_strcmp(arg_6[i], exp_6[i]) != 0)
		    return 1;
	    break;
	case 7:
	    bu_sort(&arg_7, 9, sizeof(fastf_t), comp_4, &cmp_7);
	    for (i = 0; i < 9; i++)
		if (!EQUAL(arg_7[i], exp_7[i]))
		    return 1;
	    break;
	case 8:
	    bu_sort(&arg_8, 5, sizeof(fastf_t), comp_4, &cmp_8);
	    for (i = 0; i < 5; i++)
		if (!EQUAL(arg_8[i], exp_8[i]))
		    return 1;
	    break;
	case 9:
	    bu_sort(&arg_9, 5, sizeof(fastf_t), comp_2, NULL);
	    for (i = 0; i < 5; i++)
		if (!EQUAL(arg_9[i], exp_9[i]))
		    return 1;
	    break;
	case 10:
	    bu_sort(&arg_10, 5, sizeof(fastf_t), comp_2, NULL);
	    for (i = 0; i < 5; i++)
		if ((!EQUAL(arg_10[i], exp_10[i]) && (!isinf(arg_10[i]) || !isinf(exp_10[i]))) || ((exp_10[i] < 0) != (arg_10[i] < 0)))
		    return 1;
	    break;
    }
    return 0;
}
int
ged_edcodes(struct ged *gedp, int argc, const char *argv[])
{
    int i;
    int nflag = 0;
    int status;
    int sort_by_ident=0;
    int sort_by_region=0;
    int c;
    char **av;
    FILE *fp = NULL;
    char tmpfil[MAXPATHLEN] = {0};
    const char *editstring = NULL;

    static const char *usage = "[-i|-n|-r|-E editor] object(s)";

    GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
    GED_CHECK_READ_ONLY(gedp, GED_ERROR);
    GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);

    /* initialize result */
    bu_vls_trunc(gedp->ged_result_str, 0);

    /* must be wanting help */
    if (argc == 1) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_HELP;
    }

    bu_optind = 1;
    while ((c = bu_getopt(argc, (char * const *)argv, "E:inr")) != -1) {
	switch (c) {
	    case 'E' :
		editstring = bu_optarg;
		break;
	    case 'i':
		sort_by_ident = 1;
		break;
	    case 'n':
		nflag = 1;
		break;
	    case 'r':
		sort_by_region = 1;
		break;
	}
    }

    if ((nflag + sort_by_ident + sort_by_region) > 1) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_ERROR;
    }

    argc -= bu_optind - 1;
    argv += bu_optind - 1;

    if (nflag) {
	struct directory *dp;

	for (i = 1; i < argc; ++i) {
	    if ((dp = db_lookup(gedp->ged_wdbp->dbip, argv[i], LOOKUP_NOISY)) != RT_DIR_NULL) {
		status = edcodes_collect_regnames(gedp, dp, 0);

		if (status != EDCODES_OK) {
		    if (status == EDCODES_HALT)
			bu_vls_printf(gedp->ged_result_str, "%s: nesting is too deep\n", argv[0]);

		    return GED_ERROR;
		}
	    }
	}

	return GED_OK;
    }

    fp = bu_temp_file(tmpfil, MAXPATHLEN);
    if (!fp)
	return GED_ERROR;

    av = (char **)bu_malloc(sizeof(char *)*(argc + 2), "ged_edcodes av");
    av[0] = "wcodes";
    av[1] = tmpfil;
    for (i = 2; i < argc + 1; ++i)
	av[i] = (char *)argv[i-1];

    av[i] = NULL;

    (void)fclose(fp);

    if (ged_wcodes(gedp, argc + 1, (const char **)av) == GED_ERROR) {
	bu_file_delete(tmpfil);
	bu_free((void *)av, "ged_edcodes av");
	return GED_ERROR;
    }

    if (sort_by_ident || sort_by_region) {
	char **line_array;
	char aline[RT_MAXLINE];
	FILE *f_srt;
	int line_count=0;
	int j;

	if ((f_srt=fopen(tmpfil, "r+")) == NULL) {
	    bu_vls_printf(gedp->ged_result_str, "%s: Failed to open temp file for sorting\n", argv[0]);
	    bu_file_delete(tmpfil);
	    return GED_ERROR;
	}

	/* count lines */
	while (bu_fgets(aline, RT_MAXLINE, f_srt)) {
	    line_count++;
	}

	/* build array of lines */
	line_array = (char **)bu_calloc(line_count, sizeof(char *), "edcodes line array");

	/* read lines and save into the array */
	rewind(f_srt);
	line_count = 0;
	while (bu_fgets(aline, RT_MAXLINE, f_srt)) {
	    line_array[line_count] = bu_strdup(aline);
	    line_count++;
	}

	/* sort the array of lines */
	if (sort_by_ident) {
	    bu_sort((void *)line_array, line_count, sizeof(char *), edcodes_id_compare, NULL);
	} else {
	    bu_sort((void *)line_array, line_count, sizeof(char *), edcodes_reg_compare, NULL);
	}

	/* rewrite the temp file using the sorted lines */
	rewind(f_srt);
	for (j = 0; j < line_count; j++) {
	    fprintf(f_srt, "%s", line_array[j]);
	    bu_free(line_array[j], "ged_edcodes line array element");
	}
	bu_free((char *)line_array, "ged_edcodes line array");
	fclose(f_srt);
    }

    if (_ged_editit(editstring, tmpfil)) {
	av[0] = "rcodes";
	av[2] = NULL;
	status = ged_rcodes(gedp, 2, (const char **)av);
    } else
	status = GED_ERROR;

    bu_file_delete(tmpfil);
    bu_free((void *)av, "ged_edcodes av");
    return status;
}