/** * R T _ P G _ P L O T */ int rt_pg_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info)) { size_t i; size_t p; /* current polygon number */ struct rt_pg_internal *pgp; BU_CK_LIST_HEAD(vhead); RT_CK_DB_INTERNAL(ip); pgp = (struct rt_pg_internal *)ip->idb_ptr; RT_PG_CK_MAGIC(pgp); for (p = 0; p < pgp->npoly; p++) { struct rt_pg_face_internal *pp; pp = &pgp->poly[p]; RT_ADD_VLIST(vhead, &pp->verts[3*(pp->npts-1)], BN_VLIST_LINE_MOVE); for (i=0; i < pp->npts; i++) { RT_ADD_VLIST(vhead, &pp->verts[3*i], BN_VLIST_LINE_DRAW); } } return 0; /* OK */ }
/** * R T _ P G _ P L O T _ P O L Y * * Convert to vlist, draw as polygons. */ int rt_pg_plot_poly(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol)) { size_t i; size_t p; /* current polygon number */ struct rt_pg_internal *pgp; BU_CK_LIST_HEAD(vhead); RT_CK_DB_INTERNAL(ip); pgp = (struct rt_pg_internal *)ip->idb_ptr; RT_PG_CK_MAGIC(pgp); for (p = 0; p < pgp->npoly; p++) { struct rt_pg_face_internal *pp; vect_t aa, bb, norm; pp = &pgp->poly[p]; if (pp->npts < 3) continue; VSUB2(aa, &pp->verts[3*(0)], &pp->verts[3*(1)]); VSUB2(bb, &pp->verts[3*(0)], &pp->verts[3*(2)]); VCROSS(norm, aa, bb); VUNITIZE(norm); RT_ADD_VLIST(vhead, norm, BN_VLIST_POLY_START); RT_ADD_VLIST(vhead, &pp->verts[3*(pp->npts-1)], BN_VLIST_POLY_MOVE); for (i=0; i < pp->npts-1; i++) { RT_ADD_VLIST(vhead, &pp->verts[3*i], BN_VLIST_POLY_DRAW); } RT_ADD_VLIST(vhead, &pp->verts[3*(pp->npts-1)], BN_VLIST_POLY_END); } return 0; /* OK */ }
void plot_ellipse( struct bu_list *vhead, const vect_t center, const vect_t axis_a, const vect_t axis_b, int num_points) { int i; point_t p; fastf_t radian, radian_step; radian_step = M_2PI / num_points; ellipse_point_at_radian(p, center, axis_a, axis_b, radian_step * (num_points - 1)); RT_ADD_VLIST(vhead, p, BN_VLIST_LINE_MOVE); radian = 0; for (i = 0; i < num_points; ++i) { ellipse_point_at_radian(p, center, axis_a, axis_b, radian); RT_ADD_VLIST(vhead, p, BN_VLIST_LINE_DRAW); radian += radian_step; } }
int rt_superell_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info)) { int i; struct rt_superell_internal *eip; fastf_t top[16*3]; fastf_t middle[16*3]; fastf_t bottom[16*3]; BU_CK_LIST_HEAD(vhead); RT_CK_DB_INTERNAL(ip); eip = (struct rt_superell_internal *)ip->idb_ptr; RT_SUPERELL_CK_MAGIC(eip); rt_superell_16pts(top, eip->v, eip->a, eip->b); rt_superell_16pts(bottom, eip->v, eip->b, eip->c); rt_superell_16pts(middle, eip->v, eip->a, eip->c); RT_ADD_VLIST(vhead, &top[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE); for (i=0; i<16; i++) { RT_ADD_VLIST(vhead, &top[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW); } RT_ADD_VLIST(vhead, &bottom[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE); for (i=0; i<16; i++) { RT_ADD_VLIST(vhead, &bottom[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW); } RT_ADD_VLIST(vhead, &middle[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE); for (i=0; i<16; i++) { RT_ADD_VLIST(vhead, &middle[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW); } return 0; }
void rt_metaball_plot_sph(struct bu_list *vhead, point_t *center, fastf_t radius) { fastf_t top[16*3], middle[16*3], bottom[16*3]; point_t a, b, c; int i; BU_CK_LIST_HEAD(vhead); VSET(a, radius, 0, 0); VSET(b, 0, radius, 0); VSET(c, 0, 0, radius); rt_ell_16pts(top, *center, a, b); rt_ell_16pts(bottom, *center, b, c); rt_ell_16pts(middle, *center, a, c); RT_ADD_VLIST(vhead, &top[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE); for (i = 0; i < 16; i++) RT_ADD_VLIST(vhead, &top[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW); RT_ADD_VLIST(vhead, &bottom[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE); for (i = 0; i < 16; i++) RT_ADD_VLIST(vhead, &bottom[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW); RT_ADD_VLIST(vhead, &middle[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE); for (i = 0; i < 16; i++) RT_ADD_VLIST(vhead, &middle[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW); }
int rt_revolve_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info)) { struct rt_revolve_internal *rip; size_t nvert, narc, nadd, nseg, i, j, k; point2d_t *verts; struct rt_curve *crv; vect_t ell[16], cir[16], ucir[16], height, xdir, ydir, ux, uy, uz, rEnd, xEnd, yEnd; fastf_t cos22_5 = 0.9238795325112867385; fastf_t cos67_5 = 0.3826834323650898373; int *endcount = NULL; point_t add, add2, add3; BU_CK_LIST_HEAD(vhead); RT_CK_DB_INTERNAL(ip); rip = (struct rt_revolve_internal *)ip->idb_ptr; RT_REVOLVE_CK_MAGIC(rip); nvert = rip->skt->vert_count; verts = rip->skt->verts; crv = &rip->skt->curve; if (rip->ang < M_2PI) { narc = ceil(rip->ang * 8 * M_1_PI); } else { narc = 16; } VSCALE(xEnd, rip->r, cos(rip->ang)); VCROSS(rEnd, rip->axis3d, rip->r); /* using rEnd for temp storage */ VSCALE(yEnd, rEnd, sin(rip->ang)); VADD2(rEnd, xEnd, yEnd); VMOVE(uz, rip->axis3d); VMOVE(ux, rip->r); VCROSS(uy, uz, ux); VUNITIZE(ux); VUNITIZE(uy); VUNITIZE(uz); /* setup unit circle to be scaled */ VMOVE(ucir[ 0], ux); VREVERSE(ucir[ 8], ucir[0]); VSCALE(xdir, ux, cos22_5); VSCALE(ydir, uy, cos67_5); VADD2(ucir[ 1], xdir, ydir); VREVERSE(ucir[ 9], ucir[1]); VREVERSE(xdir, xdir); VADD2(ucir[ 7], xdir, ydir); VREVERSE(ucir[15], ucir[7]); VSCALE(xdir, ux, M_SQRT1_2); VSCALE(ydir, uy, M_SQRT1_2); VADD2(ucir[ 2], xdir, ydir); VREVERSE(ucir[10], ucir[2]); VREVERSE(xdir, xdir); VADD2(ucir[ 6], xdir, ydir); VREVERSE(ucir[14], ucir[6]); VSCALE(xdir, ux, cos67_5); VSCALE(ydir, uy, cos22_5); VADD2(ucir[ 3], xdir, ydir); VREVERSE(ucir[11], ucir[3]); VREVERSE(xdir, xdir); VADD2(ucir[ 5], xdir, ydir); VREVERSE(ucir[13], ucir[5]); VMOVE(ucir[ 4], uy); VREVERSE(ucir[12], ucir[4]); /* find open endpoints, and determine which points are used */ if (nvert) endcount = (int *)bu_calloc(nvert, sizeof(int), "endcount"); nseg = rip->skt->curve.count; for (i=0; i<nseg; i++) { uint32_t *lng; struct line_seg *lsg; struct carc_seg *csg; struct nurb_seg *nsg; struct bezier_seg *bsg; lng = (uint32_t *)rip->skt->curve.segment[i]; switch (*lng) { case CURVE_LSEG_MAGIC: lsg = (struct line_seg *)lng; endcount[lsg->start]++; endcount[lsg->end]++; break; case CURVE_CARC_MAGIC: csg = (struct carc_seg *)lng; if (csg->radius <= 0.0) break; endcount[csg->start]++; endcount[csg->end]++; break; case CURVE_BEZIER_MAGIC: bsg = (struct bezier_seg *)lng; endcount[bsg->ctl_points[0]]++; endcount[bsg->ctl_points[bsg->degree]]++; break; case CURVE_NURB_MAGIC: nsg = (struct nurb_seg *)lng; endcount[nsg->ctl_points[0]]++; endcount[nsg->ctl_points[nsg->c_size-1]]++; break; default: bu_log("rt_revolve_prep: ERROR: unrecognized segment type!\n"); break; } } /* draw circles */ for (i=0; i<nvert; i++) { if (endcount[i] == 0) continue; VSCALE(height, uz, verts[i][Y]); for (j=0; j<narc; j++) { VSCALE(cir[j], ucir[j], verts[i][X]); VADD3(ell[j], rip->v3d, cir[j], height); } RT_ADD_VLIST(vhead, ell[0], BN_VLIST_LINE_MOVE); for (j=1; j<narc; j++) { RT_ADD_VLIST(vhead, ell[j], BN_VLIST_LINE_DRAW); } if (narc < 16) { VSCALE(cir[narc], rEnd, verts[i][X]); VADD3(ell[narc], rip->v3d, cir[narc], height); RT_ADD_VLIST(vhead, ell[narc], BN_VLIST_LINE_DRAW); } else { RT_ADD_VLIST(vhead, ell[0], BN_VLIST_LINE_DRAW); } } /* convert endcounts to store which endpoints are odd */ for (i=0, j=0; i<rip->skt->vert_count; i++) { if (endcount[i] % 2 != 0) { /* add 'i' to list, insertion sort by vert[i][Y] */ for (k=j; k>0; k--) { if ((ZERO(verts[i][Y] - verts[endcount[k-1]][Y]) && verts[i][X] > verts[endcount[k-1]][X]) || (!ZERO(verts[i][Y] - verts[endcount[k-1]][Y]) && verts[i][Y] < verts[endcount[k-1]][Y])) { endcount[k] = endcount[k-1]; } else { break; } } endcount[k] = i; j++; } } nadd = j; while (j < rip->skt->vert_count) { endcount[j++] = -1; } /* draw sketch outlines */ for (i=0; i<narc; i++) { curve_to_vlist(vhead, ttol, rip->v3d, ucir[i], uz, rip->skt, crv); for (j=0; j<nadd; j++) { if (j+1 < nadd && ZERO(verts[endcount[j]][Y] - verts[endcount[j+1]][Y])) { VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d); VJOIN1(add2, add, verts[endcount[j]][X], ucir[i]); VJOIN1(add3, add, verts[endcount[j+1]][X], ucir[i]); RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_MOVE); RT_ADD_VLIST(vhead, add3, BN_VLIST_LINE_DRAW); j++; } else { VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d); VJOIN1(add2, add, verts[endcount[j]][X], ucir[i]); RT_ADD_VLIST(vhead, add, BN_VLIST_LINE_MOVE); RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_DRAW); } } } if (narc < 16) { curve_to_vlist(vhead, ttol, rip->v3d, rEnd, uz, rip->skt, crv); for (j=0; j<nadd; j++) { if (j+1 < nadd && ZERO(verts[endcount[j]][Y] - verts[endcount[j+1]][Y])) { VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d); VJOIN1(add2, add, verts[endcount[j]][X], rEnd); VJOIN1(add3, add, verts[endcount[j+1]][X], rEnd); RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_MOVE); RT_ADD_VLIST(vhead, add3, BN_VLIST_LINE_DRAW); j++; } else { VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d); VJOIN1(add2, add, verts[endcount[j]][X], rEnd); RT_ADD_VLIST(vhead, add, BN_VLIST_LINE_MOVE); RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_DRAW); } } for (j=0; j<nadd; j+=2) { if (!ZERO(verts[endcount[j]][Y] - verts[endcount[j+1]][Y])) { VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d); VJOIN1(add2, rip->v3d, verts[endcount[j+1]][Y], rip->axis3d); RT_ADD_VLIST(vhead, add, BN_VLIST_LINE_MOVE); RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_DRAW); } } } if (nvert) bu_free(endcount, "endcount"); return 0; }
int rt_hyp_plot(struct bu_list *vhead, struct rt_db_internal *incoming, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info)) { int i, j; /* loop indices */ struct rt_hyp_internal *hyp_in; struct hyp_specific *hyp; vect_t majorAxis[8], /* vector offsets along major axis */ minorAxis[8], /* vector offsets along minor axis */ heightAxis[7], /* vector offsets for layers */ Bunit; /* unit vector along semi-minor axis */ vect_t ell[16]; /* stores 16 points to draw ellipses */ vect_t ribs[16][7]; /* assume 7 layers for now */ fastf_t scale; /* used to calculate semi-major/minor axes for top/bottom */ fastf_t cos22_5 = 0.9238795325112867385; fastf_t cos67_5 = 0.3826834323650898373; BU_CK_LIST_HEAD(vhead); RT_CK_DB_INTERNAL(incoming); hyp_in = (struct rt_hyp_internal *)incoming->idb_ptr; RT_HYP_CK_MAGIC(hyp_in); hyp = hyp_internal_to_specific(hyp_in); VCROSS(Bunit, hyp->hyp_H, hyp->hyp_Au); VUNITIZE(Bunit); VMOVE(heightAxis[0], hyp->hyp_H); VSCALE(heightAxis[1], heightAxis[0], 0.5); VSCALE(heightAxis[2], heightAxis[0], 0.25); VSETALL(heightAxis[3], 0); VREVERSE(heightAxis[4], heightAxis[2]); VREVERSE(heightAxis[5], heightAxis[1]); VREVERSE(heightAxis[6], heightAxis[0]); for (i = 0; i < 7; i++) { /* determine Z height depending on i */ scale = sqrt(MAGSQ(heightAxis[i])*(hyp->hyp_c * hyp->hyp_c)/(hyp->hyp_r1 * hyp->hyp_r1) + 1); /* calculate vectors for offset */ VSCALE(majorAxis[0], hyp->hyp_Au, hyp->hyp_r1 * scale); VSCALE(majorAxis[1], majorAxis[0], cos22_5); VSCALE(majorAxis[2], majorAxis[0], M_SQRT1_2); VSCALE(majorAxis[3], majorAxis[0], cos67_5); VREVERSE(majorAxis[4], majorAxis[3]); VREVERSE(majorAxis[5], majorAxis[2]); VREVERSE(majorAxis[6], majorAxis[1]); VREVERSE(majorAxis[7], majorAxis[0]); VSCALE(minorAxis[0], Bunit, hyp->hyp_r2 * scale); VSCALE(minorAxis[1], minorAxis[0], cos22_5); VSCALE(minorAxis[2], minorAxis[0], M_SQRT1_2); VSCALE(minorAxis[3], minorAxis[0], cos67_5); VREVERSE(minorAxis[4], minorAxis[3]); VREVERSE(minorAxis[5], minorAxis[2]); VREVERSE(minorAxis[6], minorAxis[1]); VREVERSE(minorAxis[7], minorAxis[0]); /* calculate ellipse */ VADD3(ell[ 0], hyp->hyp_V, heightAxis[i], majorAxis[0]); VADD4(ell[ 1], hyp->hyp_V, heightAxis[i], majorAxis[1], minorAxis[3]); VADD4(ell[ 2], hyp->hyp_V, heightAxis[i], majorAxis[2], minorAxis[2]); VADD4(ell[ 3], hyp->hyp_V, heightAxis[i], majorAxis[3], minorAxis[1]); VADD3(ell[ 4], hyp->hyp_V, heightAxis[i], minorAxis[0]); VADD4(ell[ 5], hyp->hyp_V, heightAxis[i], majorAxis[4], minorAxis[1]); VADD4(ell[ 6], hyp->hyp_V, heightAxis[i], majorAxis[5], minorAxis[2]); VADD4(ell[ 7], hyp->hyp_V, heightAxis[i], majorAxis[6], minorAxis[3]); VADD3(ell[ 8], hyp->hyp_V, heightAxis[i], majorAxis[7]); VADD4(ell[ 9], hyp->hyp_V, heightAxis[i], majorAxis[6], minorAxis[4]); VADD4(ell[10], hyp->hyp_V, heightAxis[i], majorAxis[5], minorAxis[5]); VADD4(ell[11], hyp->hyp_V, heightAxis[i], majorAxis[4], minorAxis[6]); VADD3(ell[12], hyp->hyp_V, heightAxis[i], minorAxis[7]); VADD4(ell[13], hyp->hyp_V, heightAxis[i], majorAxis[3], minorAxis[6]); VADD4(ell[14], hyp->hyp_V, heightAxis[i], majorAxis[2], minorAxis[5]); VADD4(ell[15], hyp->hyp_V, heightAxis[i], majorAxis[1], minorAxis[4]); /* draw ellipse */ RT_ADD_VLIST(vhead, ell[15], BN_VLIST_LINE_MOVE); for (j = 0; j < 16; j++) { RT_ADD_VLIST(vhead, ell[j], BN_VLIST_LINE_DRAW); } /* add ellipse's points to ribs */ for (j = 0; j < 16; j++) { VMOVE(ribs[j][i], ell[j]); } } /* draw ribs */ for (i = 0; i < 16; i++) { RT_ADD_VLIST(vhead, ribs[i][0], BN_VLIST_LINE_MOVE); for (j = 1; j < 7; j++) { RT_ADD_VLIST(vhead, ribs[i][j], BN_VLIST_LINE_DRAW); } } BU_PUT(hyp, struct hyp_specific); return 0; }
/********************************************************** * Code for identifying semi-flat patches in bots * and creating wireframe edges **********************************************************/ extern "C" int rt_bot_adaptive_plot(struct rt_db_internal *ip, const struct rt_view_info *info) { struct rt_bot_internal *bot; RT_CK_DB_INTERNAL(ip); BU_CK_LIST_HEAD(info->vhead); bot = (struct rt_bot_internal *)ip->idb_ptr; RT_BOT_CK_MAGIC(bot); vect_t gvects[6]; VSET(gvects[0], -1,0,0); VSET(gvects[1], 0,-1,0); VSET(gvects[2], 0,0,-1); VSET(gvects[3], 1,0,0); VSET(gvects[4], 0,1,0); VSET(gvects[5], 0,0,1); if (bot->num_vertices <= 0 || !bot->vertices || bot->num_faces <= 0 || !bot->faces) return 0; /* Declare key containers */ double *face_normals= (double *)bu_calloc(bot->num_faces * 3, sizeof(double), "normals"); /* Stash all the initial categorization test results - can be re-used later */ // unsigned int *categorization_results = (unsigned int *)bu_calloc(sizeof(unsigned int) * bot->num_faces * 6, "categorization results"); /* Initial group assignments */ unsigned int *groups = (unsigned int *)bu_calloc(bot->num_faces, sizeof(unsigned int), "groups"); /* Initially, patch breakdown is made in a faces -> patch_id map */ unsigned int *patches= (unsigned int *)bu_calloc(bot->num_faces, sizeof(unsigned int), "patch_id_numbers"); /* Don't know yet how big these needs to be */ unsigned int *vert_to_face = NULL; /* Sanity check vertex indices in face definitions */ for (unsigned int i = 0; i < bot->num_faces; ++i) { if ((unsigned int)bot->faces[i*3+0] > (unsigned int)(bot->num_vertices)) return 0; if ((unsigned int)bot->faces[i*3+1] > (unsigned int)(bot->num_vertices)) return 0; if ((unsigned int)bot->faces[i*3+2] > (unsigned int)(bot->num_vertices)) return 0; } /* Pre-compute face normals once */ for (unsigned int i = 0; i < bot->num_faces; i++) { vect_t a, b, norm_dir; VSUB2(a, &bot->vertices[bot->faces[i*3+1]*3], &bot->vertices[bot->faces[i*3]*3]); VSUB2(b, &bot->vertices[bot->faces[i*3+2]*3], &bot->vertices[bot->faces[i*3]*3]); VCROSS(norm_dir, a, b); VUNITIZE(norm_dir); face_normals[i*3]=norm_dir[0]; face_normals[i*3+1]=norm_dir[1]; face_normals[i*3+2]=norm_dir[2]; } /* Calculate categorization results and assign groups */ for (unsigned int i = 0; i < bot->num_faces; i++) { int result_max = 0; double result = 0.0; double vdot = 0.0; vect_t norm_dir; VSET(norm_dir, face_normals[i*3], face_normals[i*3+1], face_normals[i*3+2]); for (unsigned int j=0; j < 6; j++) { vdot = VDOT(gvects[j],norm_dir); //categorization_results[i*j] = vdot; if (vdot > result) { result_max = j; result = vdot; } } groups[i] = result_max; } bu_free(face_normals, "face_normals"); /* Determine the maximum number of faces associated with any one vertex */ unsigned int *vert_face_cnt = (unsigned int *)bu_calloc(bot->num_vertices, sizeof(unsigned int), "vert face cnt"); for (unsigned int i = 0; i < bot->num_faces; i++) { vert_face_cnt[bot->faces[i*3+0]]++; vert_face_cnt[bot->faces[i*3+1]]++; vert_face_cnt[bot->faces[i*3+2]]++; } unsigned int max_face_cnt = 0; for (unsigned int i = 0; i < bot->num_vertices; i++) { if (vert_face_cnt[i] > max_face_cnt) max_face_cnt = vert_face_cnt[i]; } /* Now, allocate a 2D array that can hold the full vert->face map * and populate it */ vert_to_face = (unsigned int *)bu_calloc(bot->num_vertices * max_face_cnt, sizeof(unsigned int), "map"); unsigned int *vert_sizes = (unsigned int *)bu_calloc(bot->num_vertices, sizeof(unsigned int), "map"); for (unsigned int i = 0; i < bot->num_faces; i++) { for (unsigned int j = 0; j < 3; j++) { unsigned int vert = bot->faces[i*3+j]; unsigned int k = vert_sizes[vert]; /* rows are vertex indexes, columns hold the faces */ /* Need to increment face index by one so we can reference * the first face and still use the true/false test that 0 allows */ vert_to_face[max_face_cnt * vert + k] = i + 1; vert_sizes[vert]++; //bu_log("vert_to_face(%d,%d)[%d] = %d\n", vert, k, max_face_cnt * vert + k, i + 1); } } /* Order the groups by number of bots */ /* Note - needed only when group boarders are not enforced in patch building */ // unsigned int group_cnt[6] = {0}; unsigned int ordered_groups[6] = {0,1,2,3,4,5}; /* for (unsigned int i = 0; i < bot->num_faces; i++) { group_cnt[groups[i]]++; } for (unsigned int i = 0; i < 6; i++) { unsigned int more = 0; for (unsigned int j = 0; j < 6; j++) { if (group_cnt[j] > group_cnt[i]) more++; } ordered_groups[more] = i; } */ // All faces must belong to some patch - continue until all faces are processed unsigned int patch_cnt = 0; for (unsigned int i = 0; i < 6; i++) { int unused = 0; while (unused != -1) { unsigned int face_stp = 0; // Start a new patch unused = -1; patch_cnt++; // Find remaining face in group while (unused == -1 && face_stp < bot->num_faces) { if (ordered_groups[i] == groups[face_stp] && !patches[face_stp]) { unused = face_stp; } face_stp++; } if (unused != -1) { std::queue<unsigned int> face_queue; face_queue.push(unused); patches[unused] = patch_cnt; while (!face_queue.empty()) { unsigned int face_num = face_queue.front(); face_queue.pop(); for (unsigned int k = 0; k < 3; k++) { unsigned int vert_id = bot->faces[face_num*3+k]; for (unsigned int l = 0; l < vert_face_cnt[vert_id]; l++) { unsigned int new_face = vert_to_face[max_face_cnt * vert_id + l] - 1; if (groups[new_face] == ordered_groups[i] && !patches[new_face]) { face_queue.push(new_face); patches[new_face] = patch_cnt; } } } } } } } bu_free(groups, "groups"); bu_free(vert_to_face, "vert_to_face"); unsigned int *patch_vert_cnt = vert_sizes; memset(patch_vert_cnt, 0, bot->num_vertices * sizeof(unsigned int)); unsigned int *vert_edge_status = (unsigned int *)bu_calloc(bot->num_vertices, sizeof(unsigned int), "vert status"); for (unsigned int i = 0; i < patch_cnt; i++) { memset(patch_vert_cnt, 0, bot->num_vertices * sizeof(unsigned int)); for (unsigned int j = 0; j < bot->num_faces; j++) { if (patches[j] == i+1) { patch_vert_cnt[bot->faces[j*3+0]]++; patch_vert_cnt[bot->faces[j*3+1]]++; patch_vert_cnt[bot->faces[j*3+2]]++; } } for (unsigned int j = 0; j < bot->num_vertices; j++) { if (patch_vert_cnt[j] && patch_vert_cnt[j] != vert_face_cnt[j]) { vert_edge_status[j]++; } } } bu_free(patches, "patches"); bu_free(patch_vert_cnt, "patch_vert_cnt"); bu_free(vert_face_cnt, "vert_face_cnt"); for (unsigned int j = 0; j < bot->num_faces; j++) { if (vert_edge_status[bot->faces[j*3+0]] && vert_edge_status[bot->faces[j*3+1]]) { RT_ADD_VLIST(info->vhead, &(bot->vertices[bot->faces[j*3+0]*3]), BN_VLIST_LINE_MOVE); RT_ADD_VLIST(info->vhead, &(bot->vertices[bot->faces[j*3+1]*3]), BN_VLIST_LINE_DRAW); } if (vert_edge_status[bot->faces[j*3+1]] && vert_edge_status[bot->faces[j*3+2]]) { RT_ADD_VLIST(info->vhead, &(bot->vertices[bot->faces[j*3+1]*3]), BN_VLIST_LINE_MOVE); RT_ADD_VLIST(info->vhead, &(bot->vertices[bot->faces[j*3+2]*3]), BN_VLIST_LINE_DRAW); } if (vert_edge_status[bot->faces[j*3+2]] && vert_edge_status[bot->faces[j*3+0]]) { RT_ADD_VLIST(info->vhead, &(bot->vertices[bot->faces[j*3+2]*3]), BN_VLIST_LINE_MOVE); RT_ADD_VLIST(info->vhead, &(bot->vertices[bot->faces[j*3+0]*3]), BN_VLIST_LINE_DRAW); } } bu_free(vert_edge_status, "vert status"); return 0; }
/** * Brute force through all possible plane intersections. * Generate all edge lines, then intersect the line with all * the other faces to find the vertices on that line. * If the geometry is correct, there will be no more than two. * While not the fastest strategy, this will produce an accurate * plot without requiring extra bookkeeping. * Note that the vectors will be drawn in no special order. */ int rt_arbn_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *tol, const struct rt_view_info *UNUSED(info)) { struct rt_arbn_internal *aip; size_t i; size_t j; size_t k; BU_CK_LIST_HEAD(vhead); RT_CK_DB_INTERNAL(ip); aip = (struct rt_arbn_internal *)ip->idb_ptr; RT_ARBN_CK_MAGIC(aip); for (i = 0; i < aip->neqn - 1; i++) { for (j = i + 1; j < aip->neqn; j++) { double dot; int point_count; /* # points on this line */ point_t a, b; /* start and end points */ vect_t dist; VSETALL(a, 0); VSETALL(b, 0); /* If normals are parallel, no intersection */ dot = VDOT(aip->eqn[i], aip->eqn[j]); if (BN_VECT_ARE_PARALLEL(dot, tol)) continue; /* Have an edge line, isect with all other planes */ point_count = 0; for (k = 0; k < aip->neqn; k++) { size_t m; point_t pt; size_t next_k; next_k = 0; if (k == i || k == j) continue; if (bn_mkpoint_3planes(pt, aip->eqn[i], aip->eqn[j], aip->eqn[k]) < 0) continue; /* See if point is outside arb */ for (m = 0; m < aip->neqn; m++) { if (i == m || j == m || k == m) continue; if (VDOT(pt, aip->eqn[m])-aip->eqn[m][3] > tol->dist) { next_k = 1; break; } } if (next_k != 0) continue; if (point_count <= 0) { RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_MOVE); VMOVE(a, pt); } else if (point_count == 1) { VSUB2(dist, pt, a); if (MAGSQ(dist) < tol->dist_sq) continue; RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW); VMOVE(b, pt); } else { VSUB2(dist, pt, a); if (MAGSQ(dist) < tol->dist_sq) continue; VSUB2(dist, pt, b); if (MAGSQ(dist) < tol->dist_sq) continue; bu_log("rt_arbn_plot() error, point_count=%d (>2) on edge %zu/%zu, non-convex\n", point_count+1, i, j); VPRINT(" a", a); VPRINT(" b", b); VPRINT("pt", pt); RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW); /* draw it */ } point_count++; } /* Point counts of 1 are (generally) not harmful, * occurring on pyramid peaks and the like. */ } } return 0; }