int main(int argc, char **argv) { struct bu_rb_tree *palette; /* Pixel palette */ char *inf_name; /* name of input stream */ char *outf_name; /* " " output " */ unsigned char *buf; /* the current input pixel */ FILE *infp = NULL; /* input stream */ int ch; /* current char in command line */ struct pixel *pp; /* * Process the command line */ while ((ch = bu_getopt(argc, argv, optstring)) != -1) switch (ch) { case '#': if (sscanf(bu_optarg, "%d", &pixel_size) != 1) { bu_log("Invalid pixel size: '%s'\n", bu_optarg); print_usage(); } break; case '?': default: print_usage(); } switch (argc - bu_optind) { case 0: infp = stdin; /* Break intentionally missing */ case 1: outfp = stdout; /* Break intentionally missing */ case 2: break; default: print_usage(); } /* * Open input and output files, as necessary */ if (infp == NULL) { inf_name = argv[bu_optind]; if ((infp = fopen(inf_name, "r")) == NULL) bu_exit(1, "Cannot open input file '%s'\n", inf_name); if (outfp == NULL) { outf_name = argv[++bu_optind]; if ((outfp = fopen(outf_name, "w")) == NULL) bu_exit(1, "Cannot open output file '%s'\n", outf_name); } } /* * Ensure that infp is kosher, */ if (infp == stdin) { if (isatty(fileno(stdin))) { bu_log("FATAL: pixcount reads only from file or pipe\n"); print_usage(); } } palette = bu_rb_create1("Pixel palette", (int (*)(void))compare_pixels); bu_rb_uniq_on1(palette); /* * Read the input stream into the palette */ buf = (unsigned char *) bu_malloc(pixel_size * sizeof(unsigned char), "pixel buffer"); while (fread((void *)buf, pixel_size * sizeof(unsigned char), 1, infp) == 1) { pp = lookup_pixel(palette, buf); BU_CKMAG(pp, PIXEL_MAGIC, "pixel"); ++(pp->p_count); } bu_free((void *)buf, "pixel buffer"); bu_rb_walk1(palette, (void (*)(void))print_pixel, BU_RB_WALK_INORDER); return 0; }
/* * M A I N ( ) */ int main (int argc, char **argv) { char *label[2]; /* Labels of edge endpoints */ int ch; /* Command-line character */ int i; int numeric = 0; /* Use vertex indices (vs. labels)? */ long index[2]; /* Indices of edge endpoints */ double weight; /* Edge weight */ bu_rb_tree *dictionary; /* Dictionary of vertices */ struct bridge *bp; /* The current bridge */ struct vertex *up; /* An uncivilized neighbor of vup */ struct vertex *vcp; /* The civilized vertex of bp */ struct vertex *vup; /* The uncivilized vertex of bp */ struct vertex *vertex[2]; /* The current edge */ struct neighbor *neighbor[2]; /* Their neighbors */ struct neighbor *np; /* A neighbor of vup */ int (*po[2])(); /* Priority queue order functions */ while ((ch = bu_getopt(argc, argv, OPT_STRING)) != EOF) switch (ch) { case 'n': numeric = 1; break; case '?': default: print_usage(); bu_exit (ch != '?', NULL); return(0); } /* * Initialize the dictionary */ dictionary = bu_rb_create1("Dictionary of vertices", numeric ? compare_vertex_indices : compare_vertex_labels); bu_rb_uniq_on1(dictionary); /* * Read in the graph */ while (get_edge(stdin, index, label, &weight, numeric)) { for (i = 0; i < 2; ++i) /* For each end of the edge... */ { vertex[i] = lookup_vertex(dictionary, index[i], label[i]); neighbor[i] = mk_neighbor(VERTEX_NULL, weight); BU_LIST_INSERT(&(vertex[i] -> v_neighbors), &(neighbor[i] -> l)); } neighbor[0] -> n_vertex = vertex[1]; neighbor[1] -> n_vertex = vertex[0]; } /* * Initialize the priority queue */ po[PRIOQ_INDEX] = compare_bridge_indices; po[PRIOQ_WEIGHT] = compare_bridge_weights; prioq = bu_rb_create("Priority queue of bridges", 2, po); bu_rb_walk1(dictionary, add_to_prioq, INORDER); if (debug) { print_prioq(); bu_rb_walk1(dictionary, print_vertex, INORDER); } /* * Grow a minimum spanning tree, using Prim's algorithm... * * While there exists a min-weight bridge (to a vertex v) in the queue * Dequeue the bridge * If the weight is finite * Output the bridge * Mark v as civilized * For every uncivilized neighbor u of v * if uv is cheaper than u's current bridge * dequeue u's current bridge * enqueue bridge(uv) */ weight = 0.0; while ((bp = extract_min()) != BRIDGE_NULL) { if (debug) { bu_log("extracted min-weight bridge <x%x>, leaving...\n", bp); print_prioq(); } BU_CKMAG(bp, BRIDGE_MAGIC, "bridge"); vcp = bp -> b_vert_civ; vup = bp -> b_vert_unciv; BU_CKMAG(vup, VERTEX_MAGIC, "vertex"); if (is_finite_bridge(bp)) { BU_CKMAG(vcp, VERTEX_MAGIC, "vertex"); if (numeric) (void) printf("%ld %ld %g\n", vcp -> v_index, vup -> v_index, bp -> b_weight); else (void) printf("%s %s %g\n", vcp -> v_label, vup -> v_label, bp -> b_weight); weight += bp -> b_weight; } free_bridge(bp); vup -> v_civilized = 1; if (debug) { bu_log("Looking for uncivilized neighbors of...\n"); print_vertex((void *) vup, 0); } while (BU_LIST_WHILE(np, neighbor, &(vup -> v_neighbors))) { BU_CKMAG(np, NEIGHBOR_MAGIC, "neighbor"); up = np -> n_vertex; BU_CKMAG(up, VERTEX_MAGIC, "vertex"); if (up -> v_civilized == 0) { BU_CKMAG(up -> v_bridge, BRIDGE_MAGIC, "bridge"); if (compare_weights(np -> n_weight, up -> v_bridge -> b_weight) < 0) { del_from_prioq(up); if (debug) { bu_log("After the deletion of bridge <x%x>...\n", up -> v_bridge); print_prioq(); } up -> v_bridge -> b_vert_civ = vup; up -> v_bridge -> b_weight = np -> n_weight; add_to_prioq((void *) up, 0); if (debug) { bu_log("Reduced bridge <x%x> weight to %g\n", up -> v_bridge, up -> v_bridge -> b_weight); print_prioq(); } } else if (debug) bu_log("bridge <x%x>'s weight of %g stands up\n", up -> v_bridge, up -> v_bridge -> b_weight); } else if (debug) bu_log("Skipping civilized neighbor <x%x>\n", up); BU_LIST_DEQUEUE(&(np -> l)); } } bu_log("MST weight: %g\n", weight); return 0; }