// Calculate area of a face static double face_area(struct rt_bot_internal *bot, size_t face_num) { point_t ptA, ptB, ptC; double a, b, c, p; double area; VMOVE(ptA, &bot->vertices[bot->faces[face_num*3+0]*3]); VMOVE(ptB, &bot->vertices[bot->faces[face_num*3+1]*3]); VMOVE(ptC, &bot->vertices[bot->faces[face_num*3+2]*3]); a = DIST_PT_PT(ptA, ptB); b = DIST_PT_PT(ptB, ptC); c = DIST_PT_PT(ptC, ptA); p = (a + b + c)/2; area = sqrt(p*(p-a)*(p-b)*(p-c)); return area; }
HIDDEN int raydiff_hit(struct application *ap, struct partition *PartHeadp, struct seg *UNUSED(segs)) { point_t in_pt, out_pt; struct partition *part; fastf_t part_len = 0.0; struct raydiff_container *state = (struct raydiff_container *)(ap->a_uptr); /*rt_pr_seg(segs);*/ /*rt_pr_partitions(ap->a_rt_i, PartHeadp, "hits");*/ for (part = PartHeadp->pt_forw; part != PartHeadp; part = part->pt_forw) { VJOIN1(in_pt, ap->a_ray.r_pt, part->pt_inhit->hit_dist, ap->a_ray.r_dir); VJOIN1(out_pt, ap->a_ray.r_pt, part->pt_outhit->hit_dist, ap->a_ray.r_dir); part_len = DIST_PT_PT(in_pt, out_pt); if (part_len > state->tol) { state->have_diffs = 1; if (state->left && !bu_strncmp(part->pt_regionp->reg_name+1, state->left_name, strlen(state->left_name))) { RDIFF_ADD_DSEG(state->left, in_pt, out_pt); bu_log("LEFT diff vol (%s) (len: %f): %g %g %g -> %g %g %g\n", part->pt_regionp->reg_name, part_len, V3ARGS(in_pt), V3ARGS(out_pt)); continue; } if (state->right && !bu_strncmp(part->pt_regionp->reg_name+1, state->right_name, strlen(state->right_name))) { RDIFF_ADD_DSEG(state->right, in_pt, out_pt); bu_log("RIGHT diff vol (%s) (len: %f): %g %g %g -> %g %g %g\n", part->pt_regionp->reg_name, part_len, V3ARGS(in_pt), V3ARGS(out_pt)); continue; } /* If we aren't collecting segments, we already have our final answer */ if (!state->left && !state->right) return 0; } } return 0; }
/** * Gives a rough estimate of the maximum number of times a primitive's bounding * box diagonal will be sampled based on the sample density of the view. * * Practically, it is an estimate of the maximum number of pixels that would be * used if the diagonal line were drawn in the current view window. * * It is currently used in adaptive plot routines to help choose how many * sample points should be used for plotted curves. */ fastf_t primitive_diagonal_samples( struct rt_db_internal *ip, const struct rt_view_info *info) { point_t bbox_min, bbox_max; fastf_t primitive_diagonal_mm, samples_per_mm; fastf_t diagonal_samples; ip->idb_meth->ft_bbox(ip, &bbox_min, &bbox_max, info->tol); primitive_diagonal_mm = DIST_PT_PT(bbox_min, bbox_max); samples_per_mm = 1.0 / info->point_spacing; diagonal_samples = samples_per_mm * primitive_diagonal_mm; return diagonal_samples; }
static int aetolookat(ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { struct isst_s *isst; Togl *togl; vect_t vecdfoc; double x, y; double az, el; double mag_vec; if (objc < 4) { Tcl_WrongNumArgs(interp, 1, objv, "pathName az el"); return TCL_ERROR; } if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) return TCL_ERROR; isst = (struct isst_s *) Togl_GetClientData(togl); if (Tcl_GetDoubleFromObj(interp, objv[2], &x) != TCL_OK) return TCL_ERROR; if (Tcl_GetDoubleFromObj(interp, objv[3], &y) != TCL_OK) return TCL_ERROR; mag_vec = DIST_PT_PT(isst->camera.pos, isst->camera.focus); VSUB2(vecdfoc, isst->camera.pos, isst->camera.focus); VUNITIZE(vecdfoc); AZEL_FROM_V3DIR(az, el, vecdfoc); az = az * -DEG2RAD + x; el = el * -DEG2RAD + y; V3DIR_FROM_AZEL(vecdfoc, az, el); VUNITIZE(vecdfoc); VSCALE(vecdfoc, vecdfoc, mag_vec); VADD2(isst->camera.focus, isst->camera.pos, vecdfoc); isst->dirty = 1; return TCL_OK; }
static int zero_view(ClientData UNUSED(clientData), Tcl_Interp *interp, int UNUSED(objc), Tcl_Obj *const *objv) { struct isst_s *isst; Togl *togl; vect_t vec; double mag_vec; if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) return TCL_ERROR; isst = (struct isst_s *) Togl_GetClientData(togl); mag_vec = DIST_PT_PT(isst->camera.pos, isst->camera.focus); VSUB2(vec, isst->camera_focus_init, isst->camera.pos); VUNITIZE(vec); VSCALE(vec, vec, mag_vec); VADD2(isst->camera.focus, isst->camera.pos, vec); isst->dirty = 1; return TCL_OK; }
HIDDEN int raydiff_overlap(struct application *ap, struct partition *pp, struct region *reg1, struct region *reg2, struct partition *UNUSED(hp)) { point_t in_pt, out_pt; fastf_t overlap_len = 0.0; struct raydiff_container *state = (struct raydiff_container *)ap->a_uptr; VJOIN1(in_pt, ap->a_ray.r_pt, pp->pt_inhit->hit_dist, ap->a_ray.r_dir); VJOIN1(out_pt, ap->a_ray.r_pt, pp->pt_outhit->hit_dist, ap->a_ray.r_dir); overlap_len = DIST_PT_PT(in_pt, out_pt); if (overlap_len > state->tol) { RDIFF_ADD_DSEG(state->both, in_pt, out_pt); bu_log("OVERLAP (%s and %s) (len: %f): %g %g %g -> %g %g %g\n", reg1->reg_name, reg2->reg_name, overlap_len, V3ARGS(in_pt), V3ARGS(out_pt)); } return 0; }
/** * 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"); } } }
int delete_points(point_line_t **plta, int count, double tolerance) { int i; point_line_t *plt = NULL; point_line_t *previous_plt = NULL; /* point_line_t average_plt; */ int repeats = 0; int repeat_counter = 0; int removed = 0; if (!plta) { printf("WARNING: Unexpected call to delete_points with a NULL point array\n"); return 0; } if (count < 6) { printf("WARNING: Unexpected call to delete_points with insufficient points\n"); return 0; } /* INITIALIZE_POINT_LINE_T(average_plt); */ previous_plt = &(*plta)[0]; for (i=1; i < count; i++) { plt = &(*plta)[i]; if (DIST_PT_PT(previous_plt->val, plt->val) < tolerance) { repeats++; } else { /* not a repeat, so check if we need to remove the repeats * and the previous as convention. */ if (repeats >= 4) { /* 5+ repeated values in a row */ repeat_counter = 1; while (repeats >= 0 && repeat_counter <= count) { plt = &(*plta)[i-repeat_counter]; if (plt && plt->type) { /* zap */ #if PRINT_DEBUG bu_log("removed point: %d\n", plt->index); #endif INITIALIZE_POINT_LINE_T(*plt); repeats--; } repeat_counter++; } /* we're not necessarily condensed, so search for the * first non-null point and delete it as well. */ plt = &(*plta)[i-repeat_counter]; while (!plt || !plt->type) { repeat_counter--; plt = &(*plta)[i-repeat_counter]; } /* zap */ bu_log("removed REAL point: %d\n", plt->index); INITIALIZE_POINT_LINE_T(*plt); removed++; } repeats = 0; } previous_plt = plt; } #if PRINT_DEBUG if (removed > 0) bu_log("Found and removed %d invalid points\n", removed); #endif #if 0 bu_log("--- BEFORE ---\n"); print_array(plta, count); #endif /* resort the list, put nulls at the end */ count = condense_points(plta, count); #if 0 bu_log("--- AFTER ---\n"); print_array(plta, count); #endif return count; }
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[]"); }
int coplanar_2d_coord_sys(point_t *origin_pnt, vect_t *u_axis, vect_t *v_axis, const point_t *points_3d, int n) { int i = 0; int have_normal = 0; plane_t plane; fastf_t dist_pt_pt = 0.0; fastf_t vdot = 1.0; point_t p_farthest; int p_farthest_index = 0; vect_t normal = VINIT_ZERO; const struct bn_tol tol = {BN_TOL_MAGIC, BN_TOL_DIST/2.0, BN_TOL_DIST*BN_TOL_DIST/4.0, 1.0e-6, 1.0-1.0e-6}; /* Step 1 - find center point */ VSETALL(*origin_pnt, 0.0); for (i = 0; i < n; i++) { VADD2(*origin_pnt, *origin_pnt, points_3d[i]); } VSCALE(*origin_pnt, *origin_pnt, 1.0/n); /* Step 2 - find furthest points from the center point */ VSETALL(p_farthest, 0.0); for (i = 0; i < n; i++) { fastf_t curr_dist = DIST_PT_PT_SQ(*origin_pnt, points_3d[i]); if (curr_dist > dist_pt_pt) { dist_pt_pt = curr_dist; VMOVE(p_farthest, points_3d[i]); p_farthest_index = i; } } VSUB2(*u_axis, p_farthest, *origin_pnt); VUNITIZE(*u_axis); /* Step 3 - find normal vector of plane holding points */ i = 0; dist_pt_pt = DIST_PT_PT(*origin_pnt, p_farthest); while (i < n) { if (i != p_farthest_index) { vect_t temp_vect; fastf_t curr_vdot; VSUB2(temp_vect, points_3d[i], *origin_pnt); VUNITIZE(temp_vect); curr_vdot = fabs(VDOT(temp_vect, *u_axis)); if (curr_vdot < vdot) { if (!bn_mk_plane_3pts(plane, *origin_pnt, p_farthest, points_3d[i], &tol)) { VSET(normal, plane[0], plane[1], plane[2]); have_normal = 1; vdot = curr_vdot; } } } i++; } if (!have_normal) return -1; VUNITIZE(normal); /* Step 4 - use vectors from steps 2 and 3 to find y axis vector */ VCROSS(*v_axis, *u_axis, normal); VUNITIZE(*v_axis); return 0; }
void FindLoops(ON_Brep **b) { ON_3dPoint ptmatch, ptterminate, pstart, pend; int *curvearray; curvearray = static_cast<int*>(bu_malloc((*b)->m_C3.Count() * sizeof(int), "sketch edge list")); for (int i = 0; i < (*b)->m_C3.Count(); i++) { curvearray[i] = -1; } ON_SimpleArray<ON_Curve *> allsegments; ON_SimpleArray<ON_Curve *> loopsegments; int loop_complete; for (int i = 0; i < (*b)->m_C3.Count(); i++) { allsegments.Append((*b)->m_C3[i]); } int allcurvesassigned = 0; int assignedcount = 0; int curvecount = 0; int loopcount = 0; while (allcurvesassigned != 1) { int havefirstcurve = 0; while ((havefirstcurve == 0) && (curvecount < allsegments.Count())) { if (curvearray[curvecount] == -1) { havefirstcurve = 1; } else { curvecount++; } } // First, sort through things to assign curves to loops. loop_complete = 0; while ((loop_complete != 1) && (allcurvesassigned != 1)) { curvearray[curvecount] = loopcount; ptmatch = (*b)->m_C3[curvecount]->PointAtEnd(); ptterminate = (*b)->m_C3[curvecount]->PointAtStart(); for (int i = 0; i < allsegments.Count(); i++) { pstart = (*b)->m_C3[i]->PointAtStart(); pend = (*b)->m_C3[i]->PointAtEnd(); if (NEAR_ZERO(ptmatch.DistanceTo(pstart), ON_ZERO_TOLERANCE) && (curvearray[i] == -1)) { curvecount = i; ptmatch = pend; i = allsegments.Count(); if (NEAR_ZERO(pend.DistanceTo(ptterminate), ON_ZERO_TOLERANCE)) { loop_complete = 1; loopcount++; } } else { if (i == allsegments.Count() - 1) { loop_complete = 1; //If we reach this pass, loop had better be complete loopcount++; assignedcount = 0; for (int j = 0; j < allsegments.Count(); j++) { if (curvearray[j] != -1) assignedcount++; } if (allsegments.Count() == assignedcount) allcurvesassigned = 1; } } } } } double maxdist = 0.0; int largest_loop_index = 0; for (int i = 0; i <= loopcount ; i++) { ON_BoundingBox lbbox; for (int j = 0; j < (*b)->m_C3.Count(); j++) { if (curvearray[j] == i) { ON_Curve *currcurve = (*b)->m_C3[j]; currcurve->GetBoundingBox(lbbox, true); } } point_t minpt, maxpt; double currdist; VSET(minpt, lbbox.m_min[0], lbbox.m_min[1], lbbox.m_min[2]); VSET(maxpt, lbbox.m_max[0], lbbox.m_max[1], lbbox.m_max[2]); currdist = DIST_PT_PT(minpt, maxpt); if (currdist > maxdist) { maxdist = currdist; largest_loop_index = i; } } for (int i = 0; i < allsegments.Count(); i++) { if (curvearray[i] == largest_loop_index) loopsegments.Append((*b)->m_C3[i]); } (*b)->NewPlanarFaceLoop(0, ON_BrepLoop::outer, loopsegments, true); loopsegments.Empty(); // If there's anything left, make inner loops out of it for (int i = 0; i <= loopcount; i++) { if (i != largest_loop_index) { for (int j = 0; j < allsegments.Count(); j++) { if (curvearray[j] == i) loopsegments.Append((*b)->m_C3[j]); } (*b)->NewPlanarFaceLoop(0, ON_BrepLoop::inner, loopsegments, true); } loopsegments.Empty(); } bu_free(curvearray, "sketch edge list"); }
/** * master hook function for the 'tracker' command used to create * copies of objects along a spline path. */ int f_tracker(ClientData UNUSED(clientData), Tcl_Interp *interp, int argc, const char *argv[]) { size_t ret; struct spline s; vect_t *verts = (vect_t *)NULL; struct link *links = (struct link *)NULL; int opt; size_t i, j, k, inc; size_t n_verts, n_links; int arg = 1; FILE *points = (FILE *)NULL; char tok[81] = {0}, line[81] = {0}; char ch; fastf_t totlen = 0.0; fastf_t len, olen; fastf_t dist_to_next; fastf_t min, max, mid; fastf_t pt[3] = {0}; int no_draw = 0; /* allow interrupts */ if (setjmp(jmp_env) == 0) (void)signal(SIGINT, sig3); else return TCL_OK; bu_optind = 1; while ((opt = bu_getopt(argc, (char * const *)argv, "fh")) != EOF) { switch (opt) { case 'f': no_draw = 1; arg++; break; case 'h': Tcl_AppendResult(interp, "tracker [-fh] [# links] [increment] [spline.iges] [link...]\n\n", (char *)NULL); Tcl_AppendResult(interp, "-f:\tDo not draw the links as they are made.\n", (char *)NULL); Tcl_AppendResult(interp, "-h:\tPrint this message.\n\n", (char *)NULL); Tcl_AppendResult(interp, "\tThe prototype link(s) should be placed so that one\n", (char *)NULL); Tcl_AppendResult(interp, "\tpin's vertex lies on the origin and points along the\n", (char *)NULL); Tcl_AppendResult(interp, "\ty-axis, and the link should lie along the positive x-axis.\n\n", (char *)NULL); Tcl_AppendResult(interp, "\tIf two or more sublinks comprise the link, they are specified in this manner:\n", (char *)NULL); Tcl_AppendResult(interp, "\t<link1> <%% of total link> <link2> <%% of total link> ....\n", (char *)NULL); return TCL_OK; } } if (argc < arg+1) { Tcl_AppendResult(interp, MORE_ARGS_STR, "Enter number of links: ", (char *)NULL); return TCL_ERROR; } n_verts = atoi(argv[arg++])+1; if (argc < arg+1) { Tcl_AppendResult(interp, MORE_ARGS_STR, "Enter amount to increment parts by: ", (char *)NULL); return TCL_ERROR; } inc = atoi(argv[arg++]); if (argc < arg+1) { Tcl_AppendResult(interp, MORE_ARGS_STR, "Enter spline file name: ", (char *)NULL); return TCL_ERROR; } if ((points = fopen(argv[arg++], "r")) == NULL) { fprintf(stdout, "tracker: couldn't open points file %s.\n", argv[arg-1]); return TCL_ERROR; } if (argc < arg+1) { Tcl_AppendResult(interp, MORE_ARGS_STR, "Enter prototype link name: ", (char *)NULL); fclose(points); return TCL_ERROR; } /* Prepare vert list *****************************/ n_links = ((argc-3)/2)>1?((argc-3)/2):1; verts = (vect_t *)malloc(sizeof(vect_t) * n_verts * (n_links+2)); /* Read in links names and link lengths **********/ links = (struct link *)malloc(sizeof(struct link)*n_links); for (i = arg; i < (size_t)argc; i+=2) { double scan; bu_vls_strcpy(&links[(i-arg)/2].name, argv[i]); if (argc > arg+1) { sscanf(argv[i+1], "%lf", &scan); /* double to fastf_t */ links[(i-arg)/2].pct = scan; } else { links[(i-arg)/2].pct = 1.0; } totlen += links[(i-arg)/2].pct; } if (!ZERO(totlen - 1.0)) fprintf(stdout, "ERROR\n"); /* Read in knots from specified file *************/ do bu_fgets(line, 81, points); while (!BU_STR_EQUAL(strtok(line, ","), "112")); bu_strlcpy(tok, strtok(NULL, ","), sizeof(tok)); bu_strlcpy(tok, strtok(NULL, ","), sizeof(tok)); bu_strlcpy(tok, strtok(NULL, ","), sizeof(tok)); bu_strlcpy(tok, strtok(NULL, ","), sizeof(tok)); s.n_segs = atoi(tok); s.t = (fastf_t *)bu_malloc(sizeof(fastf_t) * (s.n_segs+1), "t"); s.k = (struct knot *)bu_malloc(sizeof(struct knot) * (s.n_segs+1), "k"); for (i = 0; i <= s.n_segs; i++) { bu_strlcpy(tok, strtok(NULL, ","), sizeof(tok)); if (strstr(tok, "P") != NULL) { bu_fgets(line, 81, points); bu_fgets(line, 81, points); bu_strlcpy(tok, strtok(line, ","), sizeof(tok)); } s.t[i] = atof(tok); } for (i = 0; i <= s.n_segs; i++) for (j = 0; j < 3; j++) { for (k = 0; k < 4; k++) { bu_strlcpy(tok, strtok(NULL, ","), sizeof(tok)); if (strstr(tok, "P") != NULL) { bu_fgets(line, 81, points); bu_fgets(line, 81, points); bu_strlcpy(tok, strtok(line, ","), sizeof(tok)); } s.k[i].c[j][k] = atof(tok); } s.k[i].pt[j] = s.k[i].c[j][0]; } fclose(points); /* Interpolate link vertices *********************/ for (i = 0; i < s.n_segs; i++) /* determine initial track length */ totlen += DIST_PT_PT(s.k[i].pt, s.k[i+1].pt); len = totlen/(n_verts-1); VMOVE(verts[0], s.k[0].pt); olen = 2*len; for (i = 0; (fabs(olen-len) >= VUNITIZE_TOL) && (i < 250); i++) { /* number of track iterations */ fprintf(stdout, "."); fflush(stdout); for (j = 0; j < n_links; j++) /* set length of each link based on current track length */ links[j].len = len * links[j].pct; min = 0; max = s.t[s.n_segs]; mid = 0; for (j = 0; j < n_verts+1; j++) /* around the track once */ for (k = 0; k < n_links; k++) { /* for each sub-link */ if ((k == 0) && (j == 0)) {continue;} /* the first sub-link of the first link is already in position */ min = mid; max = s.t[s.n_segs]; mid = (min+max)/2; interp_spl(mid, s, pt); dist_to_next = (k > 0) ? links[k-1].len : links[n_links-1].len; /* links[k].len;*/ while (fabs(DIST_PT_PT(verts[n_links*j+k-1], pt) - dist_to_next) >= VUNITIZE_TOL) { if (DIST_PT_PT(verts[n_links*j+k-1], pt) > dist_to_next) { max = mid; mid = (min+max)/2; } else { min = mid; mid = (min+max)/2; } interp_spl(mid, s, pt); if (fabs(min-max) <= VUNITIZE_TOL) {break;} } interp_spl(mid, s, verts[n_links*j+k]); } interp_spl(s.t[s.n_segs], s, verts[n_verts*n_links-1]); totlen = 0.0; for (j = 0; j < n_verts*n_links-1; j++) totlen += DIST_PT_PT(verts[j], verts[j+1]); olen = len; len = totlen/(n_verts-1); } fprintf(stdout, "\n"); /* Write out interpolation info ******************/ fprintf(stdout, "%ld Iterations; Final link lengths:\n", (unsigned long)i); for (i = 0; i < n_links; i++) fprintf(stdout, " %s\t%.15f\n", bu_vls_addr(&links[i].name), links[i].len); fflush(stdin); /* Place links on vertices ***********************/ fprintf(stdout, "Continue? [y/n] "); ret = fscanf(stdin, "%c", &ch); if (ret != 1) perror("fscanf"); if (ch == 'y') { struct clone_state state; struct directory **dps = (struct directory **)NULL; char *vargs[3]; for (i = 0; i < 2; i++) vargs[i] = (char *)bu_calloc(CLONE_BUFSIZE, sizeof(char), "alloc vargs[i]"); vargs[0][0] = 'e'; state.interp = interp; state.incr = inc; state.n_copies = 1; state.draw_obj = 0; state.miraxis = W; dps = (struct directory **)bu_calloc(n_links, sizeof(struct directory *), "alloc dps array"); /* rots = (vect_t *)bu_malloc(sizeof(vect_t)*n_links, "alloc rots");*/ for (i = 0; i < n_links; i++) { /* global dbip */ dps[i] = db_lookup(dbip, bu_vls_addr(&links[i].name), LOOKUP_QUIET); /* VSET(rots[i], 0, 0, 0);*/ } for (i = 0; i < n_verts-1; i++) { for (j = 0; j < n_links; j++) { if (i == 0) { VSCALE(state.trans, verts[n_links*i+j], local2base); } else VSUB2SCALE(state.trans, verts[n_links*(i-1)+j], verts[n_links*i+j], local2base); VSCALE(state.rpnt, verts[n_links*i+j], local2base); VSUB2(pt, verts[n_links*i+j], verts[n_links*i+j+1]); VSET(state.rot, 0, (M_PI - atan2(pt[Z], pt[X])), -atan2(pt[Y], sqrt(pt[X]*pt[X]+pt[Z]*pt[Z]))); VSCALE(state.rot, state.rot, RAD2DEG); /* VSUB2(state.rot, state.rot, rots[j]); VADD2(rots[j], state.rot, rots[j]); */ state.src = dps[j]; /* global dbip */ dps[j] = copy_object(dbip, &rt_uniresource, &state); bu_strlcpy(vargs[1], dps[j]->d_namep, CLONE_BUFSIZE); if (!no_draw || !is_dm_null()) { drawtrees(2, (const char **)vargs, 1); size_reset(); new_mats(); color_soltab(); refresh(); } fprintf(stdout, "."); fflush(stdout); } } fprintf(stdout, "\n"); bu_free(dps, "free dps array"); for (i = 0; i < 2; i++) bu_free(vargs[i], "free vargs[i]"); } free(s.t); free(s.k); free(links); free(verts); (void)signal(SIGINT, SIG_IGN); return TCL_OK; }
void shoot(char *UNUSED(buffer), com_table *UNUSED(ctp), struct rt_i *rtip) { int i; double bov = 0.0; /* back out value */ extern void init_ovlp(); if (!rtip) return; if (need_prep) { rt_clean(rtip); do_rt_gettrees(rtip, NULL, 0, &need_prep); } if (do_backout) { point_t ray_point; vect_t ray_dir; vect_t center_bsphere; fastf_t dist_to_target; vect_t dvec; fastf_t delta; for (i = 0; i < 3; ++i) { ray_point[i] = target(i); ray_dir[i] = direct(i); } if (bsphere_diameter < 0) set_diameter(rtip); /* * calculate the distance from a plane normal to the ray direction through the center of * the bounding sphere and a plane normal to the ray direction through the aim point. */ VADD2SCALE(center_bsphere, rtip->mdl_max, rtip->mdl_min, 0.5); dist_to_target = DIST_PT_PT(center_bsphere, ray_point); VSUB2(dvec, ray_point, center_bsphere); VUNITIZE(dvec); delta = dist_to_target*VDOT(ray_dir, dvec); /* * this should put us about a bounding sphere radius in front of the bounding sphere */ bov = bsphere_diameter + delta; } for (i = 0; i < 3; ++i) { target(i) = target(i) + (bov * -direct(i)); ap.a_ray.r_pt[i] = target(i); ap.a_ray.r_dir[i] = direct(i); } if (nirt_debug & DEBUG_BACKOUT) { bu_log("Backing out %g units to (%g %g %g), shooting dir is (%g %g %g)\n", bov * base2local, ap.a_ray.r_pt[0] * base2local, ap.a_ray.r_pt[1] * base2local, ap.a_ray.r_pt[2] * base2local, V3ARGS(ap.a_ray.r_dir)); } init_ovlp(); (void) rt_shootray(&ap); /* Restore pre-backout target values */ if (do_backout) { for (i = 0; i < 3; ++i) { target(i) = target(i) - (bov * -direct(i)); } } }
static int aerotate(ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { struct isst_s *isst; Togl *togl; vect_t vec, vecdpos, vecdfoc; double x, y; double az, el; double mag_pos, mag_focus; struct bu_vls tclstr = BU_VLS_INIT_ZERO; if (objc < 4) { Tcl_WrongNumArgs(interp, 1, objv, "pathName x y"); return TCL_ERROR; } if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) return TCL_ERROR; isst = (struct isst_s *) Togl_GetClientData(togl); if (Tcl_GetDoubleFromObj(interp, objv[2], &x) != TCL_OK) return TCL_ERROR; if (Tcl_GetDoubleFromObj(interp, objv[3], &y) != TCL_OK) return TCL_ERROR; mag_pos = DIST_PT_PT(isst->camera.pos, isst->camera_focus_init); mag_focus = DIST_PT_PT(isst->camera.focus, isst->camera_focus_init); VSUB2(vecdpos, isst->camera_focus_init, isst->camera.pos); VUNITIZE(vecdpos); AZEL_FROM_V3DIR(az, el, vecdpos); az = az * -DEG2RAD - x; el = el * -DEG2RAD + y; /* clamp to sane values */ while(az > 2*M_PI) az -= 2*M_PI; while(az < 0) az += 2*M_PI; if(el>M_PI_2) el=M_PI_2 - 0.001; if(el<-M_PI_2) el=-M_PI_2 + 0.001; V3DIR_FROM_AZEL(vecdpos, az, el); VSCALE(vecdpos, vecdpos, mag_pos); VADD2(isst->camera.pos, isst->camera_focus_init, vecdpos); if (mag_focus > 0) { VSUB2(vecdfoc, isst->camera_focus_init, isst->camera.focus); VUNITIZE(vecdfoc); AZEL_FROM_V3DIR(az, el, vecdfoc); az = az * -DEG2RAD - x; el = el * -DEG2RAD + y; /* clamp to sane values */ while(az > 2*M_PI) az -= 2*M_PI; while(az < 0) az += 2*M_PI; if(el>M_PI_2) el=M_PI_2 - 0.001; if(el<-M_PI_2) el=-M_PI_2 + 0.001; V3DIR_FROM_AZEL(vecdfoc, az, el); VSCALE(vecdfoc, vecdfoc, mag_focus); VADD2(isst->camera.focus, isst->camera_focus_init, vecdfoc); } /* Update the tcl copies of the az/el vars */ VSUB2(vec, isst->camera.focus, isst->camera.pos); VUNITIZE(vec); AZEL_FROM_V3DIR(az, el, vec); bu_vls_sprintf(&tclstr, "%f", az); Tcl_SetVar(interp, "az", bu_vls_addr(&tclstr), 0); bu_vls_sprintf(&tclstr, "%f", el); Tcl_SetVar(interp, "el", bu_vls_addr(&tclstr), 0); bu_vls_free(&tclstr); isst->dirty = 1; return TCL_OK; }
void FindLoops(ON_Brep **b, const ON_Line* revaxis, const fastf_t ang) { ON_3dPoint ptmatch, ptterminate, pstart, pend; int *curvearray; curvearray = static_cast<int*>(bu_malloc((*b)->m_C3.Count() * sizeof(int), "sketch edge list")); for (int i = 0; i < (*b)->m_C3.Count(); i++) { curvearray[i] = -1; } ON_SimpleArray<ON_Curve *> allsegments; ON_SimpleArray<ON_Curve *> loopsegments; int loop_complete; for (int i = 0; i < (*b)->m_C3.Count(); i++) { allsegments.Append((*b)->m_C3[i]); } int allcurvesassigned = 0; int assignedcount = 0; int curvecount = 0; int loopcount = 0; while (allcurvesassigned != 1) { int havefirstcurve = 0; while ((havefirstcurve == 0) && (curvecount < allsegments.Count())) { if (curvearray[curvecount] == -1) { havefirstcurve = 1; } else { curvecount++; } } // First, sort through things to assign curves to loops. loop_complete = 0; while ((loop_complete != 1) && (allcurvesassigned != 1)) { curvearray[curvecount] = loopcount; ptmatch = (*b)->m_C3[curvecount]->PointAtEnd(); ptterminate = (*b)->m_C3[curvecount]->PointAtStart(); for (int i = 0; i < allsegments.Count(); i++) { pstart = (*b)->m_C3[i]->PointAtStart(); pend = (*b)->m_C3[i]->PointAtEnd(); if (NEAR_ZERO(ptmatch.DistanceTo(pstart), ON_ZERO_TOLERANCE) && (curvearray[i] == -1)) { curvecount = i; ptmatch = pend; i = allsegments.Count(); if (NEAR_ZERO(pend.DistanceTo(ptterminate), ON_ZERO_TOLERANCE)) { loop_complete = 1; loopcount++; } } else { if (i == allsegments.Count() - 1) { loop_complete = 1; //If we reach this pass, loop had better be complete loopcount++; assignedcount = 0; for (int j = 0; j < allsegments.Count(); j++) { if (curvearray[j] != -1) assignedcount++; } if (allsegments.Count() == assignedcount) allcurvesassigned = 1; } } } } } double maxdist = 0.0; int largest_loop_index = 0; for (int i = 0; i <= loopcount ; i++) { ON_BoundingBox lbbox; for (int j = 0; j < (*b)->m_C3.Count(); j++) { if (curvearray[j] == i) { ON_Curve *currcurve = (*b)->m_C3[j]; currcurve->GetBoundingBox(lbbox, true); } } point_t minpt, maxpt; double currdist; VSET(minpt, lbbox.m_min[0], lbbox.m_min[1], lbbox.m_min[2]); VSET(maxpt, lbbox.m_max[0], lbbox.m_max[1], lbbox.m_max[2]); currdist = DIST_PT_PT(minpt, maxpt); if (currdist > maxdist) { maxdist = currdist; largest_loop_index = i; } } for (int i = 0; i < loopcount ; i++) { ON_PolyCurve* poly_curve = new ON_PolyCurve(); for (int j = 0; j < allsegments.Count(); j++) { if (curvearray[j] == i) { poly_curve->Append(allsegments[j]); } } ON_NurbsCurve *revcurve = ON_NurbsCurve::New(); poly_curve->GetNurbForm(*revcurve); ON_RevSurface* revsurf = ON_RevSurface::New(); revsurf->m_curve = revcurve; revsurf->m_axis = *revaxis; revsurf->m_angle = ON_Interval(0, ang); ON_BrepFace *face = (*b)->NewFace(*revsurf); if (i == largest_loop_index) { (*b)->FlipFace(*face); } } bu_free(curvearray, "sketch edge list"); }