int db_dirdelete(struct db_i *dbip, struct directory *dp) { struct directory *findp; struct directory **headp; RT_CK_DBI(dbip); RT_CK_DIR(dp); headp = &(dbip->dbi_Head[db_dirhash(dp->d_namep)]); if (dp->d_flags & RT_DIR_INMEM) { if (dp->d_un.ptr != NULL) bu_free(dp->d_un.ptr, "db_dirdelete() inmem ptr"); } if (*headp == dp) { RT_DIR_FREE_NAMEP(dp); /* frees d_namep */ *headp = dp->d_forw; /* Put 'dp' back on the freelist */ dp->d_forw = rt_uniresource.re_directory_hd; rt_uniresource.re_directory_hd = dp; return 0; } for (findp = *headp; findp != RT_DIR_NULL; findp = findp->d_forw) { if (findp->d_forw != dp) continue; RT_DIR_FREE_NAMEP(dp); /* frees d_namep */ findp->d_forw = dp->d_forw; /* Put 'dp' back on the freelist */ dp->d_forw = rt_uniresource.re_directory_hd; rt_uniresource.re_directory_hd = dp; return 0; } return -1; }
int bw_write(icv_image_t *bif, const char *filename) { unsigned char *data; FILE *fp; size_t ret, size; if (bif->color_space == ICV_COLOR_SPACE_RGB) { icv_rgb2gray_ntsc(bif); } else if (bif->color_space != ICV_COLOR_SPACE_GRAY) { bu_log("bw_write : Color Space conflict"); return -1; } data = data2uchar(bif); size = bif->height*bif->width; if (filename == NULL) { fp = stdout; } else { fp = fopen(filename, "wb"); if (fp == NULL) { bu_log("bw_write: Cannot open file for saving\n"); return -1; } } ret = fwrite(data, 1, size, fp); fclose(fp); bu_free(data, "bw_write : Unsigned Char data"); if (ret != size) { bu_log("bw_write : Short Write\n"); return -1; } return 0; }
void process_point(point_line_t *plt) { static int code_state = INT32_MAX; static int points = 0; static point_line_t *plta = NULL; if (!plt) { printf("WARNING: Unexpected call to process_point with a NULL point structure\n"); return; } /* state change, we're either starting or ending */ if (code_state != plt->code) { if (points > 0) { process_multi_group(&plta, points, TOL); printf("END OF BLOCK %d\n", code_state); /* finish up this batch */ bu_free((genptr_t)plta, "end point_line_t group"); plta = NULL; } if (plt->type) printf("BEGIN OF BLOCK %s (%d)\n", plt->type, plt->code); /* get ready for the new batch */ code_state = plt->code; points = 0; } /* allocate room for the new point */ if (!plta) plta = (point_line_t *) bu_malloc(sizeof(point_line_t), "begin point_line_t group"); else plta = (point_line_t *) bu_realloc(plta, sizeof(point_line_t) * (points + 1), "add point_line_t"); COPY_POINT_LINE_T(plta[points], *plt); points++; }
static int process_triangulation(struct db_tree_state *tsp, const struct db_full_path *pathp, struct _ged_client_data *dgcdp) { int result = 1; if (!BU_SETJUMP) { /* try */ nmg_triangulate_model(*tsp->ts_m, tsp->ts_tol); result = 0; } else { /* catch */ char *sofar = db_path_to_string(pathp); bu_vls_printf(dgcdp->gedp->ged_result_str, "WARNING: Triangulation of %s failed!\n", sofar); bu_free((void *)sofar, "path string"); } BU_UNSETJUMP; return result; }
void diff_free_result(struct diff_result *result) { unsigned int i = 0; if (result->obj_name) { bu_free(result->obj_name, "free name copy in diff result"); } BU_PUT(result->diff_tol, struct bn_tol); for (i = 0; i < BU_PTBL_LEN(result->param_diffs); i++) { struct diff_avp *avp = (struct diff_avp *)BU_PTBL_GET(result->param_diffs, i); diff_free_avp(avp); BU_PUT(avp, struct diff_avp); } bu_ptbl_free(result->param_diffs); BU_PUT(result->param_diffs, struct bu_ptbl); for (i = 0; i < BU_PTBL_LEN(result->attr_diffs); i++) { struct diff_avp *avp = (struct diff_avp *)BU_PTBL_GET(result->attr_diffs, i); diff_free_avp(avp); BU_PUT(avp, struct diff_avp); } bu_ptbl_free(result->attr_diffs); BU_PUT(result->attr_diffs, struct bu_ptbl); }
HIDDEN union tree * wdb_eval_bool(struct bu_list *hp) { int done=0; union tree *final_tree; struct tokens *tok; while (done != 1) { wdb_do_inter(hp); wdb_do_union_subtr(hp); done = wdb_do_paren(hp); } if (done == 1) { tok = BU_LIST_NEXT(tokens, hp); final_tree = tok->tp; BU_LIST_DEQUEUE(&tok->l); bu_free((char *)tok, "tok"); return(final_tree); } return (union tree *)NULL; }
static void process_triangulation(struct nmgregion *r, const struct db_full_path *pathp, struct db_tree_state *tsp) { if (!BU_SETJUMP) { /* try */ /* Write the facetized region to the output file */ output_nmg(r, pathp, tsp->ts_regionid, tsp->ts_gmater); } else { /* catch */ char *sofar; sofar = db_path_to_string(pathp); bu_log("FAILED in triangulator: %s\n", sofar); bu_free((char *)sofar, "sofar"); /* Sometimes the NMG library adds debugging bits when * it detects an internal error, before bombing out. */ RTG.NMG_debug = NMG_debug; /* restore mode */ /* Release any intersector 2d tables */ nmg_isect2d_final_cleanup(); /* Get rid of (m)any other intermediate structures */ if ((*tsp->ts_m)->magic == NMG_MODEL_MAGIC) { nmg_km(*tsp->ts_m); } else { bu_log("WARNING: tsp->ts_m pointer corrupted, ignoring it.\n"); } /* Now, make a new, clean model structure for next pass. */ *tsp->ts_m = nmg_mm(); } BU_UNSETJUMP; }
/** * B U _ D I R N A M E * * Given a filesystem pathname, return a pointer to a dynamic string * which is the parent directory of that file/directory. * * /usr/dir/file /usr/dir * @n /usr/dir/ /usr * @n /usr/file /usr * @n /usr/ / * @n /usr / * @n / / * @n . . * @n .. . * @n usr . * @n a/b a * @n a/ . * @n ../a/b ../a */ char * bu_dirname(const char *cp) { char *ret; char *slash; int len; /* Special cases */ if ( cp == NULL ) return bu_strdup("."); if ( strcmp( cp, "/" ) == 0 ) return bu_strdup("/"); if ( strcmp( cp, "." ) == 0 || strcmp( cp, ".." ) == 0 || strrchr(cp, '/') == NULL ) return bu_strdup("."); /* Make a duplicate copy of the string, and shorten it in place */ ret = bu_strdup(cp); /* A trailing slash doesn't count */ len = strlen(ret); if ( ret[len-1] == '/' ) ret[len-1] = '\0'; /* If no slashes remain, return "." */ if ( (slash = strrchr(ret, '/')) == NULL ) { bu_free( ret, "bu_dirname" ); return bu_strdup("."); } /* Remove trailing slash, unless it's at front */ if ( slash == ret ) ret[1] = '\0'; /* ret == "/" */ else *slash = '\0'; return ret; }
static void nmg_to_psurf(struct nmgregion *r, FILE *fp_psurf) /* NMG region to be converted. */ /* Jack format file to write vertex list to. */ { int i; int *map; /* map from v->index to Jack vert # */ struct bu_ptbl vtab; /* vertex table */ map = (int *)bu_calloc(r->m_p->maxindex, sizeof(int *), "Jack vert map"); /* Built list of vertex structs */ nmg_vertex_tabulate( &vtab, &r->l.magic ); /* XXX What to do if 0 vertices? */ /* Print list of unique vertices and convert from mm to cm. */ for (i = 0; i < BU_PTBL_END(&vtab); i++) { struct vertex *v; register struct vertex_g *vg; v = (struct vertex *)BU_PTBL_GET(&vtab, i); NMG_CK_VERTEX(v); vg = v->vg_p; NMG_CK_VERTEX_G(vg); NMG_INDEX_ASSIGN( map, v, i+1 ); /* map[v->index] = i+1 */ fprintf(fp_psurf, "%f\t%f\t%f\n", vg->coord[X] / 10., vg->coord[Y] / 10., vg->coord[Z] / 10.); } fprintf(fp_psurf, ";;\n"); jack_faces(r, fp_psurf, map); bu_ptbl( &vtab, BU_PTBL_FREE, 0 ); bu_free( (char *)map, "Jack vert map" ); }
void addtext(struct frame *fp, char *tp) { char *p; int length; #ifdef DEBUG fprintf(stderr, "addtext: %s\n", tp); #endif BU_CKMAG(&(fp->l.magic), MAGIC, "frame magic"); length = strlen(tp) + 1; /* length of text string and NULL */ length += 1; /* For the Space or newline */ if (fp->text) { length += fp->tp; } if (length > fp->tl || !fp->text) { fp->tl = (length/1024)*1024 + 1024; p = (char *) bu_malloc(fp->tl, "text area"); *p = '\0'; if (fp->text) { bu_strlcpy(p, fp->text, fp->tl); bu_free(fp->text, "text area"); } fp->text = p; } bu_strlcat(&fp->text[fp->tp], tp, fp->tl); if (*tp == ';') { bu_strlcat(&fp->text[fp->tp], "\n", fp->tl); } else { bu_strlcat(&fp->text[fp->tp], " ", fp->tl); } fp->tp += strlen(tp)+1; }
struct face_g_snurb * rt_nurb_region_from_srf(const struct face_g_snurb *srf, int dir, fastf_t param1, fastf_t param2, struct resource *res) { register int i; struct face_g_snurb *region; struct knot_vector new_knots; fastf_t *knot_vec = NULL; size_t maxorder = FMAX(srf->order[0], srf->order[1]); knot_vec = (fastf_t *)bu_calloc(maxorder * 2, sizeof(fastf_t), "knot vector"); /* Build the new knot vector in a local array, which gets copied * later in rt_nurb_s_refine(). */ new_knots.knots = &knot_vec[0]; if (dir == RT_NURB_SPLIT_ROW) { new_knots.k_size = srf->order[0] * 2; for (i = 0; i < srf->order[0]; i++) { knot_vec[i] = param1; knot_vec[i+srf->order[0]] = param2; } } else { new_knots.k_size = srf->order[1] * 2; for (i = 0; i < srf->order[1]; i++) { knot_vec[i] = param1; knot_vec[i+srf->order[1]] = param2; } } region = rt_nurb_s_refine(srf, dir, &new_knots, res); bu_free(knot_vec, "knot vector"); return region; }
/** * @brief This routine is called when a region is first encountered in the * hierarchy when processing a tree * * @param tsp tree state (for parsing the tree) * @param pathp A listing of all the nodes traversed to get to this node in the database * @param combp the combination record for this region */ int region_start(struct db_tree_state *tsp, const struct db_full_path *pathp, const struct rt_comb_internal *combp, void *client_data) { char *name; struct directory *dp; struct bu_vls str = BU_VLS_INIT_ZERO; struct user_data *your_stuff = (struct user_data *)client_data; RT_CK_DBTS(tsp); name = db_path_to_string(pathp); bu_log("region_start %s\n", name); bu_free(name, "reg_start name"); bu_log("data = %ld\n", your_stuff->data); rt_pr_tol(&your_stuff->tol); dp = DB_FULL_PATH_CUR_DIR(pathp); /* here is where the conversion should be done */ if (combp->region_flag) printf("Write this region (name=%s) as a part in your format:\n", dp->d_namep); else printf("Write this combination (name=%s) as an assembly in your format:\n", dp->d_namep); describe_tree(combp->tree, &str); printf("\t%s\n\n", bu_vls_addr(&str)); bu_vls_free(&str); return 0; }
/* * Called from db_walk_tree(). * * This routine must be prepared to run in parallel. */ union tree *do_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data)) { union tree *ret_tree; struct bu_list vhead; struct nmgregion *r; RT_CK_FULL_PATH(pathp); RT_CK_TREE(curtree); RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); BU_LIST_INIT(&vhead); { char *sofar = db_path_to_string(pathp); bu_log("\ndo_region_end(%d %d%%) %s\n", regions_tried, regions_tried>0 ? (regions_converted * 100) / regions_tried : 0, sofar); bu_free(sofar, "path string"); } if (curtree->tr_op == OP_NOP) return curtree; regions_tried++; if (verbose) bu_log("Attempting to process region %s\n", db_path_to_string(pathp)); ret_tree= process_boolean(curtree, tsp, pathp); if (ret_tree) r = ret_tree->tr_d.td_r; else { if (verbose) bu_log("\tNothing left of this region after Boolean evaluation\n"); regions_written++; /* don't count as a failure */ r = (struct nmgregion *)NULL; } regions_converted++; if (r != (struct nmgregion *)NULL) { struct shell *s; int empty_region=0; int empty_model=0; /* Kill cracks */ s = BU_LIST_FIRST(shell, &r->s_hd); while (BU_LIST_NOT_HEAD(&s->l, &r->s_hd)) { struct shell *next_s; next_s = BU_LIST_PNEXT(shell, &s->l); if (nmg_kill_cracks(s)) { if (nmg_ks(s)) { empty_region = 1; break; } } s = next_s; } /* kill zero length edgeuses */ if (!empty_region) { empty_model = nmg_kill_zero_length_edgeuses(*tsp->ts_m); } if (!empty_region && !empty_model) { process_triangulation(r, pathp, tsp); regions_written++; } if (!empty_model) nmg_kr(r); } /* * Dispose of original tree, so that all associated dynamic * memory is released now, not at the end of all regions. * A return of TREE_NULL from this routine signals an error, * and there is no point to adding _another_ message to our output, * so we need to cons up an OP_NOP node to return. */ db_free_tree(curtree, &rt_uniresource); /* Does an nmg_kr() */ BU_ALLOC(curtree, union tree); RT_TREE_INIT(curtree); curtree->tr_op = OP_NOP; return curtree; }
/* routine to output the faceted NMG representation of a BRL-CAD region */ static void output_nmg(struct nmgregion *r, const struct db_full_path *pathp, int UNUSED(region_id), int UNUSED(material_id)) { struct model *m; struct shell *s; struct vertex *v; char *region_name; NMG_CK_REGION(r); RT_CK_FULL_PATH(pathp); region_name = db_path_to_string(pathp); m = r->m_p; NMG_CK_MODEL(m); /* triangulate model */ nmg_triangulate_model(m, &tol); /* Output triangles */ if (verbose) { printf("Convert these triangles to your format for region %s\n", region_name); } else { printf("Converted %s\n", region_name); } for (BU_LIST_FOR(s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; /* vect_t facet_normal; */ NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; /* Grab the face normal if needed */ /* NMG_GET_FU_NORMAL(facet_normal, fu); */ for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; /* loop through the edges in this loop (facet) */ if (verbose) printf("\tfacet:\n"); for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); v = eu->vu_p->v_p; NMG_CK_VERTEX(v); if (verbose) printf("\t\t(%g %g %g)\n", V3ARGS(v->vg_p->coord)); } tot_polygons++; } } } bu_free(region_name, "region name"); }
/* * F B M _ F R E E */ HIDDEN void fbm_free(char *cp) { bu_free( cp, "fbm_specific" ); }
/** * Given a ray, shoot it at all the relevant parts of the model, * (building the HeadSeg chain), and then call rt_boolregions() to * build and evaluate the partition chain. If the ray actually hit * anything, call the application's a_hit() routine with a pointer to * the partition chain, otherwise, call the application's a_miss() * routine. * * It is important to note that rays extend infinitely only in the * positive direction. The ray is composed of all points P, where * * P = r_pt + K * r_dir * * for K ranging from 0 to +infinity. There is no looking backwards. * * It is also important to note that the direction vector r_dir must * have unit length; this is mandatory, and is not ordinarily checked, * in the name of efficiency. * * Input: Pointer to an application structure, with these mandatory fields: * a_ray.r_pt Starting point of ray to be fired * a_ray.r_dir UNIT VECTOR with direction to fire in (dir cosines) * a_hit Routine to call when something is hit * a_miss Routine to call when ray misses everything * * Calls user's a_miss() or a_hit() routine as appropriate. Passes * a_hit() routine list of partitions, with only hit_dist fields * valid. Normal computation deferred to user code, to avoid needless * computation here. * * Returns: whatever the application function returns (an int). * * NOTE: The application functions may call rt_shootray() recursively. * Thus, none of the local variables may be static. * * An open issue for execution in a PARALLEL environment is locking of * the statistics variables. */ int rt_vshootray(struct application *ap) { struct seg *HeadSeg; int ret; vect_t inv_dir; /* inverses of ap->a_ray.r_dir */ struct bu_bitv *solidbits; /* bits for all solids shot so far */ struct bu_ptbl *regionbits; /* bits for all involved regions */ char *status; struct partition InitialPart; /* Head of Initial Partitions */ struct partition FinalPart; /* Head of Final Partitions */ int nrays = 1; /* for now */ int vlen; int id; int i; struct soltab **ary_stp; /* array of pointers */ struct xray **ary_rp; /* array of pointers */ struct seg *ary_seg; /* array of structures */ struct rt_i *rtip; int done; #define BACKING_DIST (-2.0) /* mm to look behind start point */ rtip = ap->a_rt_i; RT_AP_CHECK(ap); if (!ap->a_resource) { ap->a_resource = &rt_uniresource; } RT_CK_RESOURCE(ap->a_resource); if (RT_G_DEBUG&(DEBUG_ALLRAYS|DEBUG_SHOOT|DEBUG_PARTITION)) { bu_log("\n**********mshootray cpu=%d %d, %d lvl=%d (%s)\n", ap->a_resource->re_cpu, ap->a_x, ap->a_y, ap->a_level, ap->a_purpose != (char *)0 ? ap->a_purpose : "?"); VPRINT("Pnt", ap->a_ray.r_pt); VPRINT("Dir", ap->a_ray.r_dir); } rtip->rti_nrays++; if (rtip->needprep) rt_prep(rtip); /* Allocate dynamic memory */ vlen = nrays * rtip->rti_maxsol_by_type; ary_stp = (struct soltab **)bu_calloc(vlen, sizeof(struct soltab *), "*ary_stp[]"); ary_rp = (struct xray **)bu_calloc(vlen, sizeof(struct xray *), "*ary_rp[]"); ary_seg = (struct seg *)bu_calloc(vlen, sizeof(struct seg), "ary_seg[]"); /**** for each ray, do this ****/ InitialPart.pt_forw = InitialPart.pt_back = &InitialPart; FinalPart.pt_forw = FinalPart.pt_back = &FinalPart; HeadSeg = RT_SEG_NULL; solidbits = rt_get_solidbitv(rtip->nsolids, ap->a_resource); if (BU_LIST_IS_EMPTY(&ap->a_resource->re_region_ptbl)) { BU_ALLOC(regionbits, struct bu_ptbl); bu_ptbl_init(regionbits, 7, "rt_shootray() regionbits ptbl"); } else { regionbits = BU_LIST_FIRST(bu_ptbl, &ap->a_resource->re_region_ptbl); BU_LIST_DEQUEUE(®ionbits->l); BU_CK_PTBL(regionbits); } /* Compute the inverse of the direction cosines */ if (!ZERO(ap->a_ray.r_dir[X])) { inv_dir[X]=1.0/ap->a_ray.r_dir[X]; } else { inv_dir[X] = INFINITY; ap->a_ray.r_dir[X] = 0.0; } if (!ZERO(ap->a_ray.r_dir[Y])) { inv_dir[Y]=1.0/ap->a_ray.r_dir[Y]; } else { inv_dir[Y] = INFINITY; ap->a_ray.r_dir[Y] = 0.0; } if (!ZERO(ap->a_ray.r_dir[Z])) { inv_dir[Z]=1.0/ap->a_ray.r_dir[Z]; } else { inv_dir[Z] = INFINITY; ap->a_ray.r_dir[Z] = 0.0; } /* * XXX handle infinite solids here, later. */ /* * If ray does not enter the model RPP, skip on. * If ray ends exactly at the model RPP, trace it. */ if (!rt_in_rpp(&ap->a_ray, inv_dir, rtip->mdl_min, rtip->mdl_max) || ap->a_ray.r_max < 0.0) { rtip->nmiss_model++; if (ap->a_miss) ret = ap->a_miss(ap); else ret = 0; status = "MISS model"; goto out; } /* For each type of solid to be shot at, assemble the vectors */ for (id = 1; id <= ID_MAX_SOLID; id++) { register int nsol; if ((nsol = rtip->rti_nsol_by_type[id]) <= 0) continue; /* For each instance of this solid type */ for (i = nsol-1; i >= 0; i--) { ary_stp[i] = rtip->rti_sol_by_type[id][i]; ary_rp[i] = &(ap->a_ray); /* XXX, sb [ray] */ ary_seg[i].seg_stp = SOLTAB_NULL; BU_LIST_INIT(&ary_seg[i].l); } /* bounding box check */ /* bit vector per ray check */ /* mark elements to be skipped with ary_stp[] = SOLTAB_NULL */ ap->a_rt_i->nshots += nsol; /* later: skipped ones */ if (OBJ[id].ft_vshot) { OBJ[id].ft_vshot(ary_stp, ary_rp, ary_seg, nsol, ap); } else { vshot_stub(ary_stp, ary_rp, ary_seg, nsol, ap); } /* set bits for all solids shot at for each ray */ /* append resulting seg list to input for boolweave */ for (i = nsol-1; i >= 0; i--) { register struct seg *seg2; if (ary_seg[i].seg_stp == SOLTAB_NULL) { /* MISS */ ap->a_rt_i->nmiss++; continue; } ap->a_rt_i->nhits++; /* For now, do it the slow way. sb [ray] */ /* MUST dup it -- all segs have to live till after a_hit() */ RT_GET_SEG(seg2, ap->a_resource); *seg2 = ary_seg[i]; /* struct copy */ /* rt_boolweave(seg2, &InitialPart, ap); */ bu_bomb("FIXME: need to call boolweave here"); /* Add seg chain to list of used segs awaiting reclaim */ #if 0 /* FIXME: need to use waiting_segs/finished_segs here in * conjunction with rt_boolweave() { register struct seg *seg3 = seg2; while (seg3->seg_next != RT_SEG_NULL) seg3 = seg3->seg_next; seg3->seg_next = HeadSeg; HeadSeg = seg2; } */ #endif } } /* * Ray has finally left known space. */ if (InitialPart.pt_forw == &InitialPart) { if (ap->a_miss) ret = ap->a_miss(ap); else ret = 0; status = "MISSed all primitives"; goto freeup; } /* * All intersections of the ray with the model have been computed. * Evaluate the boolean trees over each partition. */ done = rt_boolfinal(&InitialPart, &FinalPart, BACKING_DIST, INFINITY, regionbits, ap, solidbits); if (done > 0) goto hitit; if (FinalPart.pt_forw == &FinalPart) { if (ap->a_miss) ret = ap->a_miss(ap); else ret = 0; status = "MISS bool"; goto freeup; } /* * Ray/model intersections exist. Pass the list to the user's * a_hit() routine. Note that only the hit_dist elements of * pt_inhit and pt_outhit have been computed yet. To compute both * hit_point and hit_normal, use the * * RT_HIT_NORMAL(NULL, hitp, stp, rayp, 0); * * macro. To compute just hit_point, use * * VJOIN1(hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir); */ hitit: if (RT_G_DEBUG&DEBUG_SHOOT) rt_pr_partitions(rtip, &FinalPart, "a_hit()"); if (ap->a_hit) ret = ap->a_hit(ap, &FinalPart, HeadSeg/* &finished_segs */); else ret = 0; status = "HIT"; /* * Processing of this ray is complete. Free dynamic resources. */ freeup: { register struct partition *pp; /* Free up initial partition list */ for (pp = InitialPart.pt_forw; pp != &InitialPart;) { register struct partition *newpp; newpp = pp; pp = pp->pt_forw; FREE_PT(newpp, ap->a_resource); } /* Free up final partition list */ for (pp = FinalPart.pt_forw; pp != &FinalPart;) { register struct partition *newpp; newpp = pp; pp = pp->pt_forw; FREE_PT(newpp, ap->a_resource); } } /* Segs can't be freed until after a_hit() has returned */ #if 0 /* FIXME: depends on commented out code above */ if (HeadSeg) RT_FREE_SEG_LIST(HeadSeg, ap->a_resource); #endif out: bu_free((char *)ary_stp, "*ary_stp[]"); bu_free((char *)ary_rp, "*ary_rp[]"); bu_free((char *)ary_seg, "ary_seg[]"); if (solidbits != NULL) { bu_bitv_free(solidbits); } if (RT_G_DEBUG&(DEBUG_ALLRAYS|DEBUG_SHOOT|DEBUG_PARTITION)) { bu_log("----------mshootray cpu=%d %d, %d lvl=%d (%s) %s ret=%d\n", ap->a_resource->re_cpu, ap->a_x, ap->a_y, ap->a_level, ap->a_purpose != (char *)0 ? ap->a_purpose : "?", status, ret); } return ret; }
int main(int ac, char **av) { int fmt = 0; int ret = 0; int ac_offset = 0; const char *in_fmt = NULL; const char *out_fmt = NULL; mime_model_t in_type = MIME_MODEL_UNKNOWN; mime_model_t out_type = MIME_MODEL_UNKNOWN; struct bu_vls in_format = BU_VLS_INIT_ZERO; struct bu_vls in_path = BU_VLS_INIT_ZERO; struct bu_vls out_format = BU_VLS_INIT_ZERO; struct bu_vls out_path = BU_VLS_INIT_ZERO; struct bu_vls log = BU_VLS_INIT_ZERO; struct bu_vls input_opts = BU_VLS_INIT_ZERO; struct bu_vls output_opts = BU_VLS_INIT_ZERO; ac-=(ac>0); av+=(ac>0); // skip program name argv[0] if present ac_offset = (ac > 2) ? 2 : 0; // The last two argv entries must always be the input and output paths /* Handle anything else as options */ option::Stats stats(TopUsage, ac - ac_offset, av); option::Option *options = (option::Option *)bu_calloc(stats.options_max, sizeof(option::Option), "options"); option::Option *buffer= (option::Option *)bu_calloc(stats.buffer_max, sizeof(option::Option), "options"); option::Parser parse(TopUsage, ac - ac_offset, av, options, buffer); /* Now that we've parsed them, start using them */ if (options[HELP] || ac == 0) { if (options[HELP].arg) { int help_type_int = bu_file_mime(options[HELP].arg, MIME_MODEL); switch (help_type_int) { case MIME_MODEL_VND_FASTGEN: option::printUsage(std::cout, Fast4Usage); break; case MIME_MODEL_STL: option::printUsage(std::cout, STLUsage); break; default: option::printUsage(std::cout, TopUsage); break; } } else { option::printUsage(std::cout, TopUsage); // TODO - figure out how to get this info from each plugin to construct this table // on the fly... bu_log("\nSupported formats:\n"); bu_log(" ------------------------------------------------------------\n"); bu_log(" | Extension | File Format | Input | Output |\n"); bu_log(" |----------------------------------------------------------|\n"); bu_log(" | stl | STereoLithography | Yes | Yes |\n"); bu_log(" |------------|---------------------------|--------|--------|\n"); bu_log(" | obj | Wavefront Object | Yes | Yes |\n"); bu_log(" |------------|---------------------------|--------|--------|\n"); bu_log(" | step | STEP (AP203) | Yes | Yes |\n"); bu_log(" |------------|---------------------------|--------|--------|\n"); bu_log(" | iges | Initial Graphics | Yes | No |\n"); bu_log(" | | Exchange Specification | | |\n"); bu_log(" |----------------------------------------------------------|\n"); } goto cleanup; } /* Any args that weren't top level args will get passed to the * format specific arg processing routines, after we use the known * top level options and the path inputs to determine what the file * types in question are. Steps: * * 1. Reassemble the unknown args into strings. */ reassemble_argstr(&input_opts, &output_opts, options[UNKNOWN]); if (bu_vls_strlen(&input_opts) > 0) bu_log("Unknown options (input): %s\n", bu_vls_addr(&input_opts)); if (bu_vls_strlen(&output_opts) > 0) bu_log("Unknown options (output): %s\n", bu_vls_addr(&output_opts)); /* * 2. Use bu_argv_from_string to create new * arrays to be fed to the format specific option parsers.*/ /* TODO - determine whether we want to have a specific option prefix, * such as in- and out-, to identify an option as specific to the * input file format suboption parser only. i.e.: * * --in-tol=1.0 -> --tol=1.0 to the input file's suboptions only * --out-tol=2.0 -> --tol=2.0 to the input file's suboptions only * --tol=1.5 -> --tol=1.5 to both input and output suboptions * * consistent with top level --in-format and --out-format options * */ /* See if we have input and output files specified */ if (!extract_path(&in_path, av[ac-2])) { bu_vls_printf(&log, "Error: no input path identified: %s\n", av[ac-2]); ret = 1; } if (!extract_path(&out_path, av[ac-1])) { bu_vls_printf(&log, "Error: no output path identified: %s\n", av[ac-1]); ret = 1; } /* Make sure we have distinct input and output paths */ if (bu_vls_strlen(&in_path) > 0 && BU_STR_EQUAL(bu_vls_addr(&in_path), bu_vls_addr(&out_path))) { bu_vls_printf(&log, "Error: identical path specified for both input and output: %s\n", bu_vls_addr(&out_path)); ret = 1; } /* Find out what input file type we are dealing with */ if (options[IN_FORMAT]) { in_fmt = options[IN_FORMAT].arg; } else { /* If we aren't overridden by an option, it's worth doing file * introspection to see if the file contents identify the input * type solidly, provided we have that capability.*/ /* fake type introspection for testing: */ //bu_vls_sprintf(&in_format, "step"); } fmt = parse_model_string(&in_format, &log, in_fmt, av[ac-2]); in_type = (fmt < 0) ? MIME_MODEL_UNKNOWN : (mime_model_t)fmt; in_fmt = NULL; /* Identify output file type */ if (options[OUT_FORMAT]) out_fmt = options[OUT_FORMAT].arg; fmt = parse_model_string(&out_format, &log, out_fmt, av[ac-1]); out_type = (fmt < 0) ? MIME_MODEL_UNKNOWN : (mime_model_t)fmt; out_fmt = NULL; /* If we get to this point without knowing both input and output types, we've got a problem */ if (in_type == MIME_MODEL_UNKNOWN) { bu_vls_printf(&log, "Error: no format type identified for input path: %s\n", bu_vls_addr(&in_path)); ret = 1; } if (out_type == MIME_MODEL_UNKNOWN) { bu_vls_printf(&log, "Error: no format type identified for output path: %s\n", bu_vls_addr(&out_path)); ret = 1; } /* If everything isn't OK, we're done - report and clean up memory */ if (ret == 1) goto cleanup; /* If we've gotten this far, we know enough to try to convert. Until we * hook in conversion calls to libgcv, print a summary of the option * parsing results for debugging. */ in_fmt = bu_file_mime_str((int)in_type, MIME_MODEL); out_fmt = bu_file_mime_str((int)out_type, MIME_MODEL); bu_log("Input file format: %s\n", in_fmt); bu_log("Output file format: %s\n", out_fmt); bu_log("Input file path: %s\n", bu_vls_addr(&in_path)); bu_log("Output file path: %s\n", bu_vls_addr(&out_path)); switch (in_type) { case MIME_MODEL_VND_FASTGEN: fast4_arg_process(bu_vls_addr(&input_opts)); break; case MIME_MODEL_STL: stl_arg_process(bu_vls_addr(&input_opts)); default: break; } switch (out_type) { case MIME_MODEL_VND_FASTGEN: fast4_arg_process(bu_vls_addr(&output_opts)); break; case MIME_MODEL_STL: stl_arg_process(bu_vls_addr(&output_opts)); default: break; } /* Clean up */ cleanup: if (bu_vls_strlen(&log) > 0) bu_log("%s", bu_vls_addr(&log)); if (in_fmt) bu_free((char *)in_fmt, "input format string"); if (out_fmt) bu_free((char *)out_fmt, "output format string"); bu_free(options, "free options"); bu_free(buffer, "free buffer"); bu_vls_free(&in_format); bu_vls_free(&in_path); bu_vls_free(&out_format); bu_vls_free(&out_path); bu_vls_free(&log); bu_vls_free(&input_opts); bu_vls_free(&output_opts); return ret; }
int ged_killtree(struct ged *gedp, int argc, const char *argv[]) { struct directory *dp; int i; int c; struct killtree_data gktd; static const char *usage = "[-a|-f|-n] 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; } gktd.gedp = gedp; gktd.killrefs = 0; gktd.print = 0; gktd.force = 0; gktd.ac = 1; gktd.top = NULL; gktd.av = (char **)bu_calloc(1, sizeof(char *) * AV_STEP, "alloc av"); gktd.av_capacity = AV_STEP; BU_ASSERT(gktd.ac + argc + 2 < AV_STEP); /* potential -n opts */ gktd.av[0] = "killrefs"; gktd.av[1] = (char *)0; bu_optind = 1; while ((c = bu_getopt(argc, (char * const *)argv, "afn")) != -1) { switch (c) { case 'a': gktd.killrefs = 1; break; case 'n': gktd.print = 1; gktd.av[gktd.ac++] = bu_strdup("-n"); gktd.av[gktd.ac] = (char *)0; break; case 'f': gktd.force = 1; break; default: bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); bu_free(gktd.av, "free av (error)"); gktd.av = NULL; return GED_ERROR; } } argc -= (bu_optind - 1); argv += (bu_optind - 1); /* Objects that would be killed are in the first sublist */ if (gktd.print) bu_vls_printf(gedp->ged_result_str, "{"); for (i = 1; i < argc; i++) { if ((dp = db_lookup(gedp->ged_wdbp->dbip, argv[i], LOOKUP_NOISY)) == RT_DIR_NULL) continue; /* ignore phony objects */ if (dp->d_addr == RT_DIR_PHONY_ADDR) continue; /* stash the what's killed so we can find refs elsewhere */ gktd.top = argv[i]; db_functree(gedp->ged_wdbp->dbip, dp, killtree_callback, killtree_callback, gedp->ged_wdbp->wdb_resp, (void *)&gktd); } /* Close the sublist of would-be killed objects. Also open the * sublist of objects that reference the would-be killed objects. */ if (gktd.print) bu_vls_printf(gedp->ged_result_str, "} {"); if (gktd.killrefs && gktd.ac > 1) { gedp->ged_internal_call = 1; (void)ged_killrefs(gedp, gktd.ac, (const char **)gktd.av); gedp->ged_internal_call = 0; for (i = 1; i < gktd.ac; i++) { if (!gktd.print) bu_vls_printf(gedp->ged_result_str, "Freeing %s\n", gktd.av[i]); bu_free((void *)gktd.av[i], "killtree_data"); gktd.av[i] = NULL; } } if (gktd.print) bu_vls_printf(gedp->ged_result_str, "}"); bu_free(gktd.av, "free av"); gktd.av = NULL; return GED_OK; }
/* * Each word in the command buffer is the name of a treetop. */ void ph_gettrees(struct pkg_conn *UNUSED(pc), char *buf) { size_t n = 0; long max_argc = 0; char **argv = NULL; int argc = 0; struct rt_i *rtip = APP.a_rt_i; RT_CK_RTI(rtip); if (debug) fprintf(stderr, "ph_gettrees: %s\n", buf); /* Copy values from command line options into rtip */ rtip->useair = use_air; if (rt_dist_tol > 0) { rtip->rti_tol.dist = rt_dist_tol; rtip->rti_tol.dist_sq = rt_dist_tol * rt_dist_tol; } if (rt_perp_tol > 0) { rtip->rti_tol.perp = rt_perp_tol; rtip->rti_tol.para = 1 - rt_perp_tol; } for (n = 0; n < strlen(buf); n++) { if (isspace((int)buf[n])) max_argc++; } argv = (char **)bu_calloc(max_argc+1, sizeof(char *), "alloc argv"); if ((argc = bu_argv_from_string(argv, max_argc, buf)) <= 0) { /* No words in input */ (void)free(buf); bu_free(argv, "free argv"); return; } title_obj = bu_strdup(argv[0]); if (rtip->needprep == 0) { /* First clean up after the end of the previous frame */ if (debug)bu_log("Cleaning previous model\n"); view_end(&APP); view_cleanup(rtip); rt_clean(rtip); if (rdebug&RDEBUG_RTMEM_END) bu_prmem("After rt_clean"); } /* Load the desired portion of the model */ if (rt_gettrees(rtip, argc, (const char **)argv, npsw) < 0) fprintf(stderr, "rt_gettrees(%s) FAILED\n", argv[0]); bu_free(argv, "free argv"); /* In case it changed from startup time via an OPT command */ if (npsw > 1) { RTG.rtg_parallel = 1; } else RTG.rtg_parallel = 0; seen_gettrees = 1; (void)free(buf); prepare(); /* Acknowledge that we are ready */ if (pkg_send(MSG_GETTREES_REPLY, title_obj, strlen(title_obj)+1, pcsrv) < 0) fprintf(stderr, "MSG_START error\n"); }
int get_args(int argc, char **argv) { int ch; char *ifname; while ((ch = bu_getopt(argc, argv, OPT_STRING)) != -1) { switch (ch) { /* * BRL-CAD image-size options */ case 'a': autosize = 1; break; case 's': /* square file size */ file_height = file_width = atol(bu_optarg); autosize = 0; break; case 'n': file_height = atol(bu_optarg); autosize = 0; break; case 'w': file_width = atol(bu_optarg); autosize = 0; break; /* * application-specific options */ case 'c': make_cells = 1; break; case 'f': if (format != 0) bu_free(format, "format_string"); format = (char *)bu_malloc(strlen(bu_optarg)+1, "format string"); bu_strlcpy(format, bu_optarg, strlen(bu_optarg)+1); break; case '#': d_per_l = atoi(bu_optarg); break; default: print_usage(1); } } if (argc == 1 && isatty(fileno(stdin)) && isatty(fileno(stdout))) print_usage(0); if (format == 0) format = " %g"; /* * Establish the input stream */ switch (argc - bu_optind) { case 0: file_name = "stdin"; infd = 0; break; case 1: file_name = argv[bu_optind++]; ifname = bu_realpath(file_name, NULL); if ((infd = open(ifname, O_RDONLY)) == -1) { bu_free(ifname, "ifname alloc from bu_realpath"); bu_exit (1, "Cannot open file '%s'\n", file_name); } bu_free(ifname, "ifname alloc from bu_realpath"); fileinput = 1; break; default: print_usage(1); } if (argc > ++bu_optind) { print_usage(1); } return 1; /* OK */ }
static struct name_conv_list * Add_new_name(char *name, unsigned int obj, int type) { struct name_conv_list *ptr; if ( debug ) bu_log( "Add_new_name( %s, x%x, %d )\n", name, obj, type ); if ( type != ASSEMBLY_TYPE && type != PART_TYPE && type != CUT_SOLID_TYPE ) { bu_exit(EXIT_FAILURE, "Bad type for name (%s) in Add_new_name\n", name ); } /* Add a new name */ ptr = (struct name_conv_list *)bu_calloc( 1, sizeof( struct name_conv_list ), "Add_new_name: prev->next" ); ptr->next = (struct name_conv_list *)NULL; ptr->brlcad_name = bu_strdup( name ); ptr->obj = obj; if ( do_regex && type != CUT_SOLID_TYPE ) { regmatch_t pmatch; if ( regexec( ®_cmp, ptr->brlcad_name, 1, &pmatch, 0 ) == 0 ) { /* got a match */ bu_strlcpy( &ptr->brlcad_name[pmatch.rm_so], &ptr->brlcad_name[pmatch.rm_eo], MAX_LINE_SIZE ); } if ( debug ) bu_log( "\tafter reg_ex, name is %s\n", ptr->brlcad_name ); } else if ( type == CUT_SOLID_TYPE ) { bu_free( (char *)ptr->brlcad_name, "brlcad_name" ); ptr->brlcad_name = NULL; } ptr->solid_use_no = 0; ptr->comb_use_no = 0; if ( type != CUT_SOLID_TYPE ) { /* make sure brlcad_name is unique */ char *tmp; tmp = ptr->brlcad_name; ptr->brlcad_name = bu_strdup( Build_unique_name( ptr->brlcad_name ) ); bu_free( (char *)tmp, "brlcad_name" ); } if ( type == ASSEMBLY_TYPE ) { ptr->solid_name = NULL; return( ptr ); } else if ( type == PART_TYPE ) { struct bu_vls vls; bu_vls_init( &vls ); bu_vls_strcpy( &vls, "s." ); bu_vls_strcat( &vls, ptr->brlcad_name ); ptr->solid_name = bu_vls_strgrab( &vls ); } else { struct bu_vls vls; bu_vls_init( &vls ); bu_vls_strcpy( &vls, "s." ); bu_vls_strcat( &vls, ptr->brlcad_name ); ptr->solid_name = bu_vls_strgrab( &vls ); } /* make sure solid name is unique */ ptr->solid_name = bu_strdup( Build_unique_name( ptr->solid_name ) ); return( ptr ); }
/* * M A I N */ int main(int argc, char **argv) { unsigned char *inbuf; unsigned char *outbuf; int *rout, *gout, *bout; long int out_width; long int i; int eof_seen; if ( !get_args( argc, argv ) ) { (void)fputs(usage, stderr); bu_exit ( 1, NULL ); } /* autosize input? */ if ( fileinput && autosize ) { unsigned long int w, h; if ( fb_common_file_size(&w, &h, file_name, 3) ) { file_width = (long)w; } else { fprintf(stderr, "pixhalve: unable to autosize\n"); } } out_width = file_width/2; /* Allocate 1-scanline input & output buffers */ inbuf = malloc( 3*file_width+8 ); outbuf = malloc( 3*(out_width+2)+8 ); /* Allocate 5 integer arrays for each color */ /* each width+2 elements wide */ for ( i=0; i<5; i++ ) { rlines[i] = (int *)bu_calloc( (file_width+4)+1, sizeof(long), "rlines" ); glines[i] = (int *)bu_calloc( (file_width+4)+1, sizeof(long), "glines" ); blines[i] = (int *)bu_calloc( (file_width+4)+1, sizeof(long), "blines" ); } /* Allocate an integer array for each color, for output */ rout = (int *)bu_malloc( out_width * sizeof(long) + 8, "rout" ); gout = (int *)bu_malloc( out_width * sizeof(long) + 8, "gout" ); bout = (int *)bu_malloc( out_width * sizeof(long) + 8, "bout" ); /* * Prime the pumps with 5 lines of image. * Repeat the bottom most line three times to generate a "fill" * line on the bottom. This will have to be matched on the top. */ if ( fread( inbuf, 3, file_width, infp ) != file_width ) { perror(file_name); fprintf(stderr, "pixhalve: fread error\n"); bu_exit (1, NULL); } separate( &rlines[0][2], &glines[0][2], &blines[0][2], inbuf, file_width ); separate( &rlines[1][2], &glines[1][2], &blines[1][2], inbuf, file_width ); separate( &rlines[2][2], &glines[2][2], &blines[2][2], inbuf, file_width ); for ( i=3; i<5; i++ ) { if ( fread( inbuf, 3, file_width, infp ) != file_width ) { perror(file_name); fprintf(stderr, "pixhalve: fread error\n"); bu_exit (1, NULL); } separate( &rlines[i][2], &glines[i][2], &blines[i][2], inbuf, file_width ); } eof_seen = 0; for (;;) { filter3( rout, rlines, out_width ); filter5( gout, glines, out_width ); filter5( bout, blines, out_width ); combine( outbuf, rout, gout, bout, out_width ); if ( fwrite( (void*)outbuf, 3, out_width, stdout ) != out_width ) { perror("stdout"); bu_exit (2, NULL); } /* Ripple down two scanlines, and acquire two more */ if ( fread( inbuf, 3, file_width, infp ) != file_width ) { if ( eof_seen >= 2 ) break; /* EOF, repeat last line 2x for final output line */ eof_seen++; /* Fall through */ } ripple( rlines, 5 ); ripple( glines, 5 ); ripple( blines, 5 ); separate( &rlines[4][2], &glines[4][2], &blines[4][2], inbuf, file_width ); if ( fread( inbuf, 3, file_width, infp ) != file_width ) { if ( eof_seen >= 2 ) break; /* EOF, repeat last line 2x for final output line */ eof_seen++; /* Fall through */ } ripple( rlines, 5 ); ripple( glines, 5 ); ripple( blines, 5 ); separate( &rlines[4][2], &glines[4][2], &blines[4][2], inbuf, file_width ); } bu_free(rlines, "rlines"); bu_free(glines, "glines"); bu_free(blines, "blines"); bu_free(rout, "rout"); bu_free(gout, "gout"); bu_free(bout, "bout"); }
extern "C" void rt_nmg_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *tol) { struct model *m; struct nmgregion *r; struct shell *s; struct faceuse *fu; struct loopuse *lu; struct edgeuse *eu; int edge_index; long* brepi; RT_CK_DB_INTERNAL(ip); m = (struct model *)ip->idb_ptr; NMG_CK_MODEL(m); brepi = static_cast<long*>(bu_malloc(m->maxindex * sizeof(long), "rt_nmg_brep: brepi[]")); for (int i = 0; i < m->maxindex; i++) brepi[i] = -INT_MAX; for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) { for (BU_LIST_FOR(s, shell, &r->s_hd)) { for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; // Need to create ON_NurbsSurface based on plane of // face in order to have UV space in which to define // trimming loops. Bounding points are NOT on the // face plane, so another approach must be used. // // General approach: For all loops in the faceuse, // collect all the vertices. Find the center point of // all the vertices, and search for the point with the // greatest distance from that center point. Once // found, cross the vector between the center point // and furthest point with the normal of the face and // scale the resulting vector to have the same length // as the vector to the furthest point. Add the two // resulting vectors to find the first corner point. // Mirror the first corner point across the center to // find the second corner point. Cross the two // vectors created by the first two corner points with // the face normal to get the vectors of the other two // corners, and scale the resulting vectors to the // same magnitude as the first two. These four points // bound all vertices on the plane and form a suitable // staring point for a UV space, since all points on // all the edges are equal to or further than the // distance between the furthest vertex and the center // point. // ............. ............. // . .* . . // . . . . . // . . . . . // . . . * . // . . . . . // . . . . . // . . . . . // . * * . . // . . . . // . . . . // . . . . // . *. . . // . ... ...* . // . .... .... . // . * . // ........................... // const struct face_g_plane *fg = fu->f_p->g.plane_p; struct bu_ptbl vert_table; nmg_tabulate_face_g_verts(&vert_table, fg); point_t tmppt, center, max_pt; struct vertex **pt; VSET(tmppt, 0, 0, 0); VSET(max_pt, 0, 0, 0); int ptcnt = 0; for (BU_PTBL_FOR(pt, (struct vertex **), &vert_table)) { tmppt[0] += (*pt)->vg_p->coord[0]; tmppt[1] += (*pt)->vg_p->coord[1]; tmppt[2] += (*pt)->vg_p->coord[2]; ptcnt++; if (brepi[(*pt)->vg_p->index] == -INT_MAX) { ON_BrepVertex& vert = (*b)->NewVertex((*pt)->vg_p->coord, SMALL_FASTF); brepi[(*pt)->vg_p->index] = vert.m_vertex_index; } } VSET(center, tmppt[0]/ptcnt, tmppt[1]/ptcnt, tmppt[2]/ptcnt); fastf_t max_dist = 0.0; fastf_t curr_dist; for (BU_PTBL_FOR(pt, (struct vertex **), &vert_table)) { tmppt[0] = (*pt)->vg_p->coord[0]; tmppt[1] = (*pt)->vg_p->coord[1]; tmppt[2] = (*pt)->vg_p->coord[2]; curr_dist = DIST_PT_PT(center, tmppt); if (curr_dist > max_dist) { max_dist = curr_dist; VMOVE(max_pt, tmppt); } } bu_ptbl_free(&vert_table); int ccw = 0; vect_t vtmp, uv1, uv2, uv3, uv4, vnormal; // If an outer loop is found in the nmg with a cw // orientation, use a flipped normal to form the NURBS // surface for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { if (lu->orientation == OT_SAME && nmg_loop_is_ccw(lu, fg->N, tol) == -1) ccw = -1; } if (ccw != -1) { VSET(vnormal, fg->N[0], fg->N[1], fg->N[2]); } else { VSET(vnormal, -fg->N[0], -fg->N[1], -fg->N[2]); } VSUB2(uv1, max_pt, center); VCROSS(vtmp, uv1, vnormal); VADD2(uv1, uv1, vtmp); VCROSS(uv2, uv1, vnormal); VREVERSE(uv3, uv1); VCROSS(uv4, uv3, vnormal); VADD2(uv1, uv1, center); VADD2(uv2, uv2, center); VADD2(uv3, uv3, center); VADD2(uv4, uv4, center); ON_3dPoint p1 = ON_3dPoint(uv1); ON_3dPoint p2 = ON_3dPoint(uv2); ON_3dPoint p3 = ON_3dPoint(uv3); ON_3dPoint p4 = ON_3dPoint(uv4); (*b)->m_S.Append(sideSurface(p1, p4, p3, p2)); ON_Surface *surf = (*(*b)->m_S.Last()); int surfindex = (*b)->m_S.Count(); // Now that we have the surface, define the face ON_BrepFace& face = (*b)->NewFace(surfindex - 1); // With the surface and the face defined, make // trimming loops and create faces. To generate UV // coordinates for each from and to for the // edgecurves, the UV origin is defined to be v1, // v1->v2 is defined as the U domain, and v1->v4 is // defined as the V domain. vect_t u_axis, v_axis; VSUB2(u_axis, uv2, uv1); VSUB2(v_axis, uv4, uv1); fastf_t u_axis_dist = MAGNITUDE(u_axis); fastf_t v_axis_dist = MAGNITUDE(v_axis); // Now that the surface context is set up, add the loops. for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { int edges=0; if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; // loop is a single vertex ON_BrepLoop::TYPE looptype; // Check if this is an inner or outer loop if (lu->orientation == OT_SAME) { looptype = ON_BrepLoop::outer; } else { looptype = ON_BrepLoop::inner; } ON_BrepLoop& loop = (*b)->NewLoop(looptype, face); for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { ++edges; vect_t ev1, ev2; struct vertex_g *vg1, *vg2; vg1 = eu->vu_p->v_p->vg_p; NMG_CK_VERTEX_G(vg1); int vert1 = brepi[vg1->index]; VMOVE(ev1, vg1->coord); vg2 = eu->eumate_p->vu_p->v_p->vg_p; NMG_CK_VERTEX_G(vg2); int vert2 = brepi[vg2->index]; VMOVE(ev2, vg2->coord); // Add edge if not already added if (brepi[eu->e_p->index] == -INT_MAX) { /* always add edges with the small vertex index as from */ if (vg1->index > vg2->index) { int tmpvert = vert1; vert1 = vert2; vert2 = tmpvert; } // Create and add 3D curve ON_Curve* c3d = new ON_LineCurve((*b)->m_V[vert1].Point(), (*b)->m_V[vert2].Point()); c3d->SetDomain(0.0, 1.0); (*b)->m_C3.Append(c3d); // Create and add 3D edge ON_BrepEdge& e = (*b)->NewEdge((*b)->m_V[vert1], (*b)->m_V[vert2] , (*b)->m_C3.Count() - 1); e.m_tolerance = 0.0; brepi[eu->e_p->index] = e.m_edge_index; } // Regardless of whether the edge existed as // an object, it needs to be added to the // trimming loop vect_t u_component, v_component; ON_3dPoint vg1pt(vg1->coord); int orientation = 0; edge_index = brepi[eu->e_p->index]; if (vg1pt != (*b)->m_V[(*b)->m_E[edge_index].m_vi[0]].Point()) { orientation = 1; } // Now, make 2d trimming curves vect_t vect1, vect2; VSUB2(vect1, ev1, uv1); VSUB2(vect2, ev2, uv1); ON_2dPoint from_uv, to_uv; double u0, u1, v0, v1; surf->GetDomain(0, &u0, &u1); surf->GetDomain(1, &v0, &v1); VPROJECT(vect1, u_axis, u_component, v_component); from_uv.y = u0 + MAGNITUDE(u_component)/u_axis_dist*(u1-u0); from_uv.x = v0 + MAGNITUDE(v_component)/v_axis_dist*(v1-v0); VPROJECT(vect2, u_axis, u_component, v_component); to_uv.y = u0 + MAGNITUDE(u_component)/u_axis_dist*(u1-u0); to_uv.x = v0 + MAGNITUDE(v_component)/v_axis_dist*(v1-v0); ON_3dPoint S1, S2; ON_3dVector Su, Sv; surf->Ev1Der(from_uv.x, from_uv.y, S1, Su, Sv); surf->Ev1Der(to_uv.x, to_uv.y, S2, Su, Sv); ON_Curve* c2d = new ON_LineCurve(from_uv, to_uv); c2d->SetDomain(0.0, 1.0); int c2i = (*b)->m_C2.Count(); (*b)->m_C2.Append(c2d); edge_index = brepi[eu->e_p->index]; ON_BrepTrim& trim = (*b)->NewTrim((*b)->m_E[edge_index], orientation, loop, c2i); trim.m_type = ON_BrepTrim::mated; trim.m_tolerance[0] = 0.0; trim.m_tolerance[1] = 0.0; } } } (*b)->SetTrimIsoFlags(); } } bu_free(brepi, "rt_nmg_brep: brepi[]"); }
HIDDEN void killtree_callback(struct db_i *dbip, struct directory *dp, void *ptr) { struct killtree_data *gktdp = (struct killtree_data *)ptr; int ref_exists = 0; if (dbip == DBI_NULL) return; /* don't bother checking for references if the -f or -a flags are * presented to force a full kill and all references respectively. */ if (!gktdp->force && !gktdp->killrefs) ref_exists = find_reference(dbip, gktdp->top, dp->d_namep); /* if a reference exists outside of the subtree we're killing, we * don't kill this object or it'll create invalid reference * elsewhere in the database. do nothing. */ if (ref_exists) return; if (gktdp->print) { if (!gktdp->killrefs) bu_vls_printf(gktdp->gedp->ged_result_str, "%s ", dp->d_namep); else { if ((size_t)(gktdp->ac + 2) >= gktdp->av_capacity) { gktdp->av = (char **)bu_realloc(gktdp->av, sizeof(char *) * (gktdp->av_capacity + AV_STEP), "realloc av"); gktdp->av_capacity += AV_STEP; } gktdp->av[gktdp->ac++] = bu_strdup(dp->d_namep); gktdp->av[gktdp->ac] = (char *)0; bu_vls_printf(gktdp->gedp->ged_result_str, "%s ", dp->d_namep); } } else { _dl_eraseAllNamesFromDisplay(gktdp->gedp->ged_gdp->gd_headDisplay, gktdp->gedp->ged_wdbp->dbip, gktdp->gedp->ged_free_vlist_callback, dp->d_namep, 0, gktdp->gedp->freesolid); bu_vls_printf(gktdp->gedp->ged_result_str, "KILL %s: %s\n", (dp->d_flags & RT_DIR_COMB) ? "COMB" : "Solid", dp->d_namep); if (!gktdp->killrefs) { if (db_delete(dbip, dp) != 0 || db_dirdelete(dbip, dp) != 0) { bu_vls_printf(gktdp->gedp->ged_result_str, "an error occurred while deleting %s\n", dp->d_namep); } } else { if ((size_t)(gktdp->ac + 2) >= gktdp->av_capacity) { gktdp->av = (char **)bu_realloc(gktdp->av, sizeof(char *) * (gktdp->av_capacity + AV_STEP), "realloc av"); gktdp->av_capacity += AV_STEP; } gktdp->av[gktdp->ac++] = bu_strdup(dp->d_namep); gktdp->av[gktdp->ac] = (char *)0; if (db_delete(dbip, dp) != 0 || db_dirdelete(dbip, dp) != 0) { bu_vls_printf(gktdp->gedp->ged_result_str, "an error occurred while deleting %s\n", dp->d_namep); /* Remove from list */ bu_free((void *)gktdp->av[--gktdp->ac], "killtree_callback"); gktdp->av[gktdp->ac] = (char *)0; } } } }
/* * This is a helper routine used in txt_setup() to load a texture either from * a file or from a db object. The resources are released in txt_free() * (there is no specific unload_datasource function). */ HIDDEN int txt_load_datasource(struct txt_specific *texture, struct db_i *dbInstance, const unsigned long int size) { struct directory *dirEntry; RT_CK_DBI(dbInstance); if (texture == (struct txt_specific *)NULL) { bu_bomb("ERROR: txt_load_datasource() received NULL arg (struct txt_specific *)\n"); } bu_log("Loading texture %s [%s]...", texture->tx_datasrc==TXT_SRC_AUTO?"from auto-determined datasource":texture->tx_datasrc==TXT_SRC_OBJECT?"from a database object":texture->tx_datasrc==TXT_SRC_FILE?"from a file":"from an unknown source (ERROR)", bu_vls_addr(&texture->tx_name)); /* if the source is auto or object, we try to load the object */ if ((texture->tx_datasrc==TXT_SRC_AUTO) || (texture->tx_datasrc==TXT_SRC_OBJECT)) { /* see if the object exists */ if ((dirEntry=db_lookup(dbInstance, bu_vls_addr(&texture->tx_name), LOOKUP_QUIET)) == RT_DIR_NULL) { /* unable to find the texture object */ if (texture->tx_datasrc!=TXT_SRC_AUTO) { return -1; } } else { struct rt_db_internal *dbip; BU_ALLOC(dbip, struct rt_db_internal); RT_DB_INTERNAL_INIT(dbip); RT_CK_DB_INTERNAL(dbip); RT_CK_DIR(dirEntry); /* the object was in the directory, so go get it */ if (rt_db_get_internal(dbip, dirEntry, dbInstance, NULL, NULL) <= 0) { /* unable to load/create the texture database record object */ return -1; } RT_CK_DB_INTERNAL(dbip); RT_CK_BINUNIF(dbip->idb_ptr); /* keep the binary object pointer */ texture->tx_binunifp=(struct rt_binunif_internal *)dbip->idb_ptr; /* make it so */ /* release the database instance pointer struct we created */ RT_DB_INTERNAL_INIT(dbip); bu_free(dbip, "txt_load_datasource"); /* check size of object */ if (texture->tx_binunifp->count < size) { bu_log("\nWARNING: %s needs %d bytes, binary object only has %lu\n", bu_vls_addr(&texture->tx_name), size, texture->tx_binunifp->count); } else if (texture->tx_binunifp->count > size) { bu_log("\nWARNING: Binary object is larger than specified texture size\n\tBinary Object: %zu pixels\n\tSpecified Texture Size: %zu pixels\n...continuing to load using image subsection...", texture->tx_binunifp->count); } } } /* if we are auto and we couldn't find a database object match, or if source * is explicitly a file then we load the file. */ if (((texture->tx_datasrc==TXT_SRC_AUTO) && (texture->tx_binunifp==NULL)) || (texture->tx_datasrc==TXT_SRC_FILE)) { texture->tx_mp = bu_open_mapped_file_with_path(dbInstance->dbi_filepath, bu_vls_addr(&texture->tx_name), NULL); if (texture->tx_mp==NULL) return -1; /* FAIL */ if (texture->tx_mp->buflen < size) { bu_log("\nWARNING: %s needs %d bytes, file only has %lu\n", bu_vls_addr(&texture->tx_name), size, texture->tx_mp->buflen); } else if (texture->tx_mp->buflen > size) { bu_log("\nWARNING: Texture file size is larger than specified texture size\n\tInput File: %zu pixels\n\tSpecified Texture Size: %lu pixels\n...continuing to load using image subsection...", texture->tx_mp->buflen, size); } } bu_log("done.\n"); return 0; }
void texture_mix_free(texture_t *texture) { bu_free(texture->data, "texture data"); }
void texture_blend_free(struct texture_s *texture) { bu_free(texture->data, "texture data"); }
/** * Read a polygon file and convert it to an NMG shell * * A polygon file consists of the following: * * The first line consists of two integer numbers: the number of * points (vertices) in the file, followed by the number of polygons * in the file. This line is followed by lines for each of the * vertices. Each vertex is listed on its own line, as the 3tuple "X * Y Z". After the list of vertices comes the list of polygons. * each polygon is represented by a line containing 1) the number of * vertices in the polygon, followed by 2) the indices of the * vertices that make up the polygon. * * Implicitly returns r->s_p which is a new shell containing all the * faces from the polygon file. * * XXX This is a horrible way to do this. Lee violates his own rules * about not creating fundamental structures on his own... :-) * Retired in favor of more modern tessellation strategies. */ struct shell * nmg_polytonmg(FILE *fp, struct nmgregion *r, const struct bn_tol *tol) { int i, j, num_pts, num_facets, pts_this_face, facet; int vl_len; struct vertex **v; /* list of all vertices */ struct vertex **vl; /* list of vertices for this polygon*/ point_t p; struct shell *s; struct faceuse *fu; struct loopuse *lu; struct edgeuse *eu; plane_t plane; struct model *m; s = nmg_msv(r); m = s->r_p->m_p; nmg_kvu(s->vu_p); /* get number of points & number of facets in file */ if (fscanf(fp, "%d %d", &num_pts, &num_facets) != 2) bu_bomb("polytonmg() Error in first line of poly file\n"); else if (RTG.NMG_debug & DEBUG_POLYTO) bu_log("points: %d facets: %d\n", num_pts, num_facets); v = (struct vertex **) bu_calloc(num_pts, sizeof (struct vertex *), "vertices"); /* build the vertices */ for (i = 0; i < num_pts; ++i) { GET_VERTEX(v[i], m); v[i]->magic = NMG_VERTEX_MAGIC; } /* read in the coordinates of the vertices */ for (i=0; i < num_pts; ++i) { if (fscanf(fp, "%lg %lg %lg", &p[0], &p[1], &p[2]) != 3) bu_bomb("polytonmg() Error reading point"); else if (RTG.NMG_debug & DEBUG_POLYTO) bu_log("read vertex #%d (%g %g %g)\n", i, p[0], p[1], p[2]); nmg_vertex_gv(v[i], p); } vl = (struct vertex **)bu_calloc(vl_len=8, sizeof (struct vertex *), "vertex parameter list"); for (facet = 0; facet < num_facets; ++facet) { if (fscanf(fp, "%d", &pts_this_face) != 1) bu_bomb("polytonmg() error getting pt count for this face"); if (RTG.NMG_debug & DEBUG_POLYTO) bu_log("facet %d pts in face %d\n", facet, pts_this_face); if (pts_this_face > vl_len) { while (vl_len < pts_this_face) vl_len *= 2; vl = (struct vertex **)bu_realloc((char *)vl, vl_len*sizeof(struct vertex *), "vertex parameter list (realloc)"); } for (i=0; i < pts_this_face; ++i) { if (fscanf(fp, "%d", &j) != 1) bu_bomb("polytonmg() error getting point index for v in f"); vl[i] = v[j-1]; } fu = nmg_cface(s, vl, pts_this_face); lu = BU_LIST_FIRST(loopuse, &fu->lu_hd); /* XXX should check for vertex-loop */ eu = BU_LIST_FIRST(edgeuse, &lu->down_hd); NMG_CK_EDGEUSE(eu); if (bn_mk_plane_3pts(plane, eu->vu_p->v_p->vg_p->coord, BU_LIST_PNEXT(edgeuse, eu)->vu_p->v_p->vg_p->coord, BU_LIST_PLAST(edgeuse, eu)->vu_p->v_p->vg_p->coord, tol)) { bu_log("At %d in %s\n", __LINE__, __FILE__); bu_bomb("polytonmg() cannot make plane equation\n"); } else nmg_face_g(fu, plane); } for (i=0; i < num_pts; ++i) { if (BU_LIST_IS_EMPTY(&v[i]->vu_hd)) continue; FREE_VERTEX(v[i]); } bu_free((char *)v, "vertex array"); return s; }
HIDDEN int move_all_func(struct ged *gedp, int nflag, const char *old_name, const char *new_name) { int i; struct ged_display_list *gdlp; struct directory *dp; struct rt_db_internal intern; struct rt_comb_internal *comb; struct bu_ptbl stack; /* rename the record itself */ if ((dp = db_lookup(gedp->ged_wdbp->dbip, old_name, LOOKUP_NOISY)) == RT_DIR_NULL) return GED_ERROR; if (db_lookup(gedp->ged_wdbp->dbip, new_name, LOOKUP_QUIET) != RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "%s: already exists", new_name); return GED_ERROR; } /* if this was a sketch, we need to look for all the extrude * objects that might use it. * * This has to be done here, before we rename the (possible) sketch object * because the extrude will do a rt_db_get on the sketch when we call * rt_db_get_internal on it. */ if (dp->d_major_type == DB5_MAJORTYPE_BRLCAD && \ dp->d_minor_type == DB5_MINORTYPE_BRLCAD_SKETCH) { struct directory *dirp; for (i = 0; i < RT_DBNHASH; i++) { for (dirp = gedp->ged_wdbp->dbip->dbi_Head[i]; dirp != RT_DIR_NULL; dirp = dirp->d_forw) { if (dirp->d_major_type == DB5_MAJORTYPE_BRLCAD && \ dirp->d_minor_type == DB5_MINORTYPE_BRLCAD_EXTRUDE) { struct rt_extrude_internal *extrude; if (rt_db_get_internal(&intern, dirp, gedp->ged_wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0) { bu_log("Can't get extrude %s?\n", dirp->d_namep); continue; } extrude = (struct rt_extrude_internal *)intern.idb_ptr; RT_EXTRUDE_CK_MAGIC(extrude); if (BU_STR_EQUAL(extrude->sketch_name, old_name)) { if (nflag) { bu_vls_printf(gedp->ged_result_str, "%s ", dirp->d_namep); rt_db_free_internal(&intern); } else { bu_free(extrude->sketch_name, "sketch name"); extrude->sketch_name = bu_strdup(new_name); if (rt_db_put_internal(dirp, gedp->ged_wdbp->dbip, &intern, &rt_uniresource) < 0) { bu_log("oops\n"); } } } else rt_db_free_internal(&intern); } } } } if (!nflag) { /* Change object name in the directory. */ if (db_rename(gedp->ged_wdbp->dbip, dp, new_name) < 0) { bu_vls_printf(gedp->ged_result_str, "error in rename to %s, aborting", new_name); return GED_ERROR; } /* Change name in the file */ if (rt_db_get_internal(&intern, dp, gedp->ged_wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0) { bu_vls_printf(gedp->ged_result_str, "Database read error, aborting"); return GED_ERROR; } if (rt_db_put_internal(dp, gedp->ged_wdbp->dbip, &intern, &rt_uniresource) < 0) { bu_vls_printf(gedp->ged_result_str, "Database write error, aborting"); return GED_ERROR; } } bu_ptbl_init(&stack, 64, "combination stack for wdb_mvall_cmd"); /* Examine all COMB nodes */ for (i = 0; i < RT_DBNHASH; i++) { for (dp = gedp->ged_wdbp->dbip->dbi_Head[i]; dp != RT_DIR_NULL; dp = dp->d_forw) { if (nflag) { union tree *comb_leaf; int done=0; if (!(dp->d_flags & RT_DIR_COMB)) continue; if (rt_db_get_internal(&intern, dp, gedp->ged_wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0) continue; comb = (struct rt_comb_internal *)intern.idb_ptr; bu_ptbl_reset(&stack); /* visit each leaf in the combination */ comb_leaf = comb->tree; if (comb_leaf) { while (!done) { while (comb_leaf->tr_op != OP_DB_LEAF) { bu_ptbl_ins(&stack, (long *)comb_leaf); comb_leaf = comb_leaf->tr_b.tb_left; } if (BU_STR_EQUAL(comb_leaf->tr_l.tl_name, old_name)) { bu_vls_printf(gedp->ged_result_str, "%s ", dp->d_namep); } if (BU_PTBL_END(&stack) < 1) { done = 1; break; } comb_leaf = (union tree *)BU_PTBL_GET(&stack, BU_PTBL_END(&stack)-1); if (comb_leaf->tr_op != OP_DB_LEAF) { bu_ptbl_rm(&stack, (long *)comb_leaf); comb_leaf = comb_leaf->tr_b.tb_right; } } } rt_db_free_internal(&intern); } else { int comb_mvall_status = db_comb_mvall(dp, gedp->ged_wdbp->dbip, old_name, new_name, &stack); if (!comb_mvall_status) continue; if (comb_mvall_status == 2) { bu_ptbl_free(&stack); bu_vls_printf(gedp->ged_result_str, "Database write error, aborting"); return GED_ERROR; } } } } bu_ptbl_free(&stack); if (!nflag) { /* Change object name anywhere in the display list path. */ for (BU_LIST_FOR(gdlp, ged_display_list, gedp->ged_gdp->gd_headDisplay)) { int first = 1; int found = 0; struct bu_vls new_path = BU_VLS_INIT_ZERO; char *dupstr = strdup(bu_vls_addr(&gdlp->gdl_path)); char *tok = strtok(dupstr, "/"); while (tok) { if (BU_STR_EQUAL(tok, old_name)) { found = 1; if (first) { first = 0; bu_vls_printf(&new_path, "%s", new_name); } else bu_vls_printf(&new_path, "/%s", new_name); } else { if (first) { first = 0; bu_vls_printf(&new_path, "%s", tok); } else bu_vls_printf(&new_path, "/%s", tok); } tok = strtok((char *)NULL, "/"); } if (found) { bu_vls_free(&gdlp->gdl_path); bu_vls_printf(&gdlp->gdl_path, "%s", bu_vls_addr(&new_path)); } free((void *)dupstr); bu_vls_free(&new_path); } } return GED_OK; }
/** * handle a group of points of a particular type, with potentially * multiple sets delimited by triplicate points. */ void process_multi_group(point_line_t **plta, int count, double tolerance) { int i; point_line_t *plt = NULL; int points = 0; point_line_t *pltg = NULL; int marker = 0; point_line_t *prev_plt = NULL; if (!plta) { printf("WARNING: Unexpected call to process_multi_group with a NULL point array\n"); return; } #if PRINT_ARRAY static int print_counter = 0; if (print_counter == 0) { bu_log("--- BEFORE ---\n"); print_array(plta, count); } #endif /* remove points marked as bogus, 5-identical points in succession */ count = delete_points(plta, count, tolerance); #if PRINT_ARRAY if (print_counter == 0) { print_counter++; bu_log("--- AFTER ---\n"); print_array(plta, count); } #endif /* isolate groups and pass them on to the group processing routine */ for (i = 0; i < count; i++) { plt = &(*plta)[i]; if (!plt || !plt->type) { printf("WARNING: Unexpected NULL encountered while processing a point array (%d of %d)\n", i, count); continue; } /* if this is the first point of a group, allocate and initialize */ if (!prev_plt) { prev_plt = &(*plta)[i]; pltg = (point_line_t *) bu_malloc(sizeof(point_line_t), "begin point_line_t subgroup"); COPY_POINT_LINE_T(*pltg, *prev_plt); marker = 0; continue; } if (marker) { /* gobble up repeats points used as a marker, average new point */ if (DIST_PT_PT(prev_plt->val, plt->val) < tolerance) { prev_plt->val[X] = (prev_plt->val[X] + plt->val[X]) / 2.0; prev_plt->val[Y] = (prev_plt->val[Y] + plt->val[Y]) / 2.0; prev_plt->val[Z] = (prev_plt->val[Z] + plt->val[Z]) / 2.0; INITIALIZE_POINT_LINE_T(*plt); /* poof */ continue; } if (process_group(&pltg, points+1)) { bu_free((genptr_t)pltg, "end subgroup: point_line_t"); pltg = NULL; prev_plt = NULL; points = 0; marker = 0; --i; continue; } else { /* process_group is allowed to return non-zero if there are not enough points -- they get returned to the stack for processing again */ printf("warning, process_group returned 0\n"); } marker = 0; continue; } /* FIXME: shouldn't just average to the average, later points get weighted too much.. */ if (DIST_PT_PT(prev_plt->val, plt->val) < tolerance) { /* printf("%d: CLOSE DISTANCE of %f\n", plt->index, DIST_PT_PT(prev_plt->val, plt->val));*/ marker = points; (pltg[marker]).val[X] = (prev_plt->val[X] + plt->val[X]) / 2.0; (pltg[marker]).val[Y] = (prev_plt->val[Y] + plt->val[Y]) / 2.0; (pltg[marker]).val[Z] = (prev_plt->val[Z] + plt->val[Z]) / 2.0; continue; } if (!pltg) { printf("Blah! Error. Group array is null. Shouldn't be here!\n"); return; } pltg = (point_line_t *) bu_realloc(pltg, sizeof(point_line_t) * (points + 2), "add subgroup: point_line_t"); points++; COPY_POINT_LINE_T(pltg[points], *plt); prev_plt = plt; } printf("i: %d, count: %d", i, count); /* make sure we're not at the end of a list (i.e. no end marker, but we're at the end of this group */ if (points > 0) { if (process_group(&pltg, points+1)) { bu_free((genptr_t)pltg, "end point_line_t subgroup"); pltg = NULL; prev_plt = NULL; points = 0; marker = 0; } else { /* this one shouldn't return zero, we're at the end of a multiblock */ printf("ERROR, process_group returned 0\n"); } } }