Esempio n. 1
0
/**
 * 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;
}
Esempio n. 2
0
/**
 * Returns -
 *  0 OK
 * !0 failure
 */
int
rt_arbn_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
{
    struct rt_arbn_internal *aip;
    vect_t work;
    fastf_t f;
    size_t i;
    size_t j;
    size_t k;
    int *used = (int *)0;	/* plane eqn use count */
    const struct bn_tol *tol = &rtip->rti_tol;

    RT_CK_DB_INTERNAL(ip);
    aip = (struct rt_arbn_internal *)ip->idb_ptr;
    RT_ARBN_CK_MAGIC(aip);

    used = (int *)bu_malloc(aip->neqn*sizeof(int), "arbn used[]");

    /*
     * ARBN must be convex.  Test for concavity.
     * Byproduct is an enumeration of all the vertices,
     * which are used to make the bounding RPP.  No need
     * to call the bbox routine, as the work must be duplicated
     * here to count faces.
     */

    /* Zero face use counts
     * and make sure normal vectors are unit vectors
     */
    for (i = 0; i < aip->neqn; i++) {
	double normalLen = MAGNITUDE(aip->eqn[i]);
	double scale;
	if (ZERO(normalLen)) {
	    bu_log("arbn has zero length normal vector\n");
	    return 1;
	}
	scale = 1.0 / normalLen;
	HSCALE(aip->eqn[i], aip->eqn[i], scale);
	used[i] = 0;
    }
    for (i = 0; i < aip->neqn-2; i++) {
	for (j=i+1; j<aip->neqn-1; j++) {
	    double dot;

	    /* 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 higher numbered planes */
	    for (k=j+1; k<aip->neqn; k++) {
		size_t m;
		size_t next_k;
		point_t pt;

		next_k = 0;

		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;

		VMINMAX(stp->st_min, stp->st_max, pt);

		/* Increment "face used" counts */
		used[i]++;
		used[j]++;
		used[k]++;
	    }
	}
    }

    /* If any planes were not used, then arbn is not convex */
    for (i = 0; i < aip->neqn; i++) {
	if (used[i] != 0) continue;	/* face was used */
	bu_log("arbn(%s) face %zu unused, solid is not convex\n",
	       stp->st_name, i);
	bu_free((char *)used, "arbn used[]");
	return -1;		/* BAD */
    }
    bu_free((char *)used, "arbn used[]");

    stp->st_specific = (void *)aip;
    ip->idb_ptr = ((void *)0);	/* indicate we stole it */

    VADD2SCALE(stp->st_center, stp->st_min, stp->st_max, 0.5);
    VSUB2SCALE(work, stp->st_max, stp->st_min, 0.5);

    f = work[X];
    if (work[Y] > f) f = work[Y];
    if (work[Z] > f) f = work[Z];
    stp->st_aradius = f;
    stp->st_bradius = MAGNITUDE(work);
    return 0;			/* OK */
}