Esempio n. 1
0
/**
 * recursively copy a tree of geometry
 */
static struct directory *
copy_tree(struct db_i *_dbip, struct directory *dp, struct resource *resp, struct clone_state *state)
{
    size_t i;
    union record *rp = (union record *)NULL;
    struct directory *mdp = (struct directory *)NULL;
    struct directory *copy = (struct directory *)NULL;

    struct bu_vls *copyname = NULL;
    struct bu_vls *nextname = NULL;

    /* get the name of what the object "should" get cloned to */
    copyname = get_name(_dbip, dp, state, 0);

    /* copy the object */
    if (dp->d_flags & RT_DIR_COMB) {

	if (db_version(_dbip) < 5) {
	    /* A v4 method of peeking into a combination */

	    int errors = 0;

	    /* get an in-memory record of this object */
	    if ((rp = db_getmrec(_dbip, dp)) == (union record *)0) {
		TCL_READ_ERR;
		goto done_copy_tree;
	    }
	    /*
	     * if it is a combination/region, copy the objects that
	     * make up the object.
	     */
	    for (i = 1; i < dp->d_len; i++) {
		if ((mdp = db_lookup(_dbip, rp[i].M.m_instname, LOOKUP_NOISY)) == RT_DIR_NULL) {
		    errors++;
		    bu_log("WARNING: failed to locate \"%s\"\n", rp[i].M.m_instname);
		    continue;
		}
		copy = copy_tree(_dbip, mdp, resp, state);
		if (!copy) {
		    errors++;
		    bu_log("WARNING: unable to fully clone \"%s\"\n", rp[i].M.m_instname);
		}
	    }

	    if (errors) {
		bu_log("WARNING: some elements of \"%s\" could not be cloned\n", dp->d_namep);
	    }

	    /* copy this combination itself */
	    copy_comb(_dbip, dp, (genptr_t)state);
	} else
	    /* A v5 method of peeking into a combination */
	    db_functree(_dbip, dp, copy_comb, copy_solid, resp, (genptr_t)state);
    } else if (dp->d_flags & RT_DIR_SOLID)
	/* leaf node -- make a copy the object */
	copy_solid(_dbip, dp, (genptr_t)state);
    else {
	Tcl_AppendResult(state->interp, "clone:  ", dp->d_namep, " is neither a combination or a primitive?\n", (char *)NULL);
	goto done_copy_tree;
    }

    nextname = get_name(_dbip, dp, state, 0);
    if (bu_vls_strcmp(copyname, nextname) == 0)
	bu_log("ERROR: unable to successfully clone \"%s\" to \"%s\"\n", dp->d_namep, bu_vls_addr(copyname));
    else
	copy = db_lookup(_dbip, bu_vls_addr(copyname), LOOKUP_QUIET);

 done_copy_tree:
    if (rp)
	bu_free((char *)rp, "copy_tree record[]");
    if (copyname)
	bu_free((char *)copyname, "free get_name() copyname");
    if (nextname)
	bu_free((char *)nextname, "free get_name() copyname");

    return copy;
}
Esempio n. 2
0
/**
 * make n copies of a v4 combination.
 */
static struct directory *
copy_v4_comb(struct db_i *_dbip, struct directory *proto, struct clone_state *state, int idx)
{
    struct directory *dp = (struct directory *)NULL;
    union record *rp = (union record *)NULL;
    size_t i;
    size_t j;

    /* make n copies */
    for (i = 0; i < state->n_copies; i++) {

	/* get a v4 in-memory reference to the object being copied */
	if ((rp = db_getmrec(_dbip, proto)) == (union record *)0) {
	    TCL_READ_ERR;
	    return NULL;
	}

	if (proto->d_flags & RT_DIR_REGION) {
	    if (!is_in_list(obj_list, rp[1].M.m_instname)) {
		bu_log("ERROR: clone internal error looking up %s\n", rp[1].M.m_instname);
		return NULL;
	    }
	    bu_vls_strcpy(&obj_list.names[idx].dest[i], bu_vls_addr(&obj_list.names[index_in_list(obj_list, rp[1].M.m_instname)].dest[i]));
	    /* bleh, odd convention going on here.. prefix regions with an 'r' */
	    *bu_vls_addr(&obj_list.names[idx].dest[i]) = 'r';
	} else {
	    struct bu_vls *name;
	    if (i==0)
		name = get_name(_dbip, proto, state, i);
	    else {
		dp = db_lookup(_dbip, bu_vls_addr(&obj_list.names[idx].dest[i-1]), LOOKUP_QUIET);
		if (!dp) {
		    continue;
		}
		name = get_name(_dbip, dp, state, i);
	    }
	    bu_vls_strcpy(&obj_list.names[idx].dest[i], bu_vls_addr(name));
	    bu_vls_free(name);
	}
	bu_strlcpy(rp[0].c.c_name, bu_vls_addr(&obj_list.names[idx].dest[i]), NAMESIZE);

	/* add the object to the directory */
	dp = db_diradd(_dbip, rp->c.c_name, RT_DIR_PHONY_ADDR, proto->d_len, proto->d_flags, &proto->d_minor_type);
	if ((dp == NULL) || (db_alloc(_dbip, dp, proto->d_len) < 0)) {
	    TCL_ALLOC_ERR;
	    return NULL;
	}

	for (j = 1; j < proto->d_len; j++) {
	    if (!is_in_list(obj_list, rp[j].M.m_instname)) {
		bu_log("ERROR: clone internal error looking up %s\n", rp[j].M.m_instname);
		return NULL;
	    }
	    snprintf(rp[j].M.m_instname, NAMESIZE, "%s", bu_vls_addr(&obj_list.names[index_in_list(obj_list, rp[j].M.m_instname)].dest[i]));
	}

	/* write the object to disk */
	if (db_put(_dbip, dp, rp, 0, dp->d_len) < 0) {
	    bu_log("ERROR: clone internal error writing to the database\n");
	    return NULL;
	}

	/* our responsibility to free the record */
	bu_free((char *)rp, "deallocate copy_v4_comb() db_getmrec() record");
    }

    return dp;
}
/*
 * This subroutine is called for a no-frills tree-walk,
 * with the provided subroutines being called when entering and
 * exiting combinations and at leaf (solid) nodes.
 *
 * This routine is recursive, so no variables may be declared static.
 *
 */
void
db_preorder_traverse(struct directory *dp,
		     struct db_traverse *dtp)
{
    register size_t i;
    RT_CK_DB_TRAVERSE(dtp);
    RT_CK_DBI(dtp->dbip);
    if (dtp->resp) {
	RT_CK_RESOURCE(dtp->resp);
    }

    if (RT_G_DEBUG & DEBUG_DB)
	bu_log("db_preorder_traverse(%s) %p, %p, comb_enter=%lx, comb_exit=%lx, leaf=%lx, client_data=%p\n",
	       dp->d_namep,
	       (void *)dtp->dbip, (void *)dp,
	       (long unsigned int)dtp->comb_enter_func, (long unsigned int)dtp->comb_exit_func, (long unsigned int)dtp->leaf_func,
	       dtp->client_data);

    if (dp->d_flags & RT_DIR_COMB) {
	/* entering region */
	if (dtp->comb_enter_func)
	    dtp->comb_enter_func(dtp->dbip, dp, dtp->client_data);
	if (db_version(dtp->dbip) < 5) {
	    register union record *rp;
	    register struct directory *mdp;
	    /*
	     * Load the combination into local record buffer
	     * This is in external v4 format.
	     */
	    if ((rp = db_getmrec(dtp->dbip, dp)) == (union record *)0)
		return;
	    /* recurse */
	    for (i=1; i < dp->d_len; i++) {
		if ((mdp = db_lookup(dtp->dbip, rp[i].M.m_instname,
				     LOOKUP_NOISY)) == RT_DIR_NULL)
		    continue;
		db_preorder_traverse(mdp, dtp);
	    }
	    bu_free((char *)rp, "db_preorder_traverse[]");
	} else {
	    struct rt_db_internal in;
	    struct rt_comb_internal *comb;

	    if (rt_db_get_internal5(&in, dp, dtp->dbip, NULL, dtp->resp) < 0)
		return;

	    comb = (struct rt_comb_internal *)in.idb_ptr;

	    db_traverse_subtree(comb->tree, db_preorder_traverse, dtp);

	    rt_db_free_internal(&in);
	}
	/* exiting region */
	if (dtp->comb_exit_func)
	    dtp->comb_exit_func(dtp->dbip, dp, dtp->client_data);
    } else if (dp->d_flags & RT_DIR_SOLID || dp->d_major_type & DB5_MAJORTYPE_BINARY_MASK) {
	/* at leaf */
	if (dtp->leaf_func)
	    dtp->leaf_func(dtp->dbip, dp, dtp->client_data);
    } else {
	bu_log("db_preorder_traverse:  %s is neither COMB nor SOLID?\n",
	       dp->d_namep);
    }
}
Esempio n. 4
0
/**
 * make a copy of a v4 solid by adding it to our book-keeping list,
 * adding it to the db directory, and writing it out to disk.
 */
static void
copy_v4_solid(struct db_i *_dbip, struct directory *proto, struct clone_state *state, int idx)
{
    struct directory *dp = (struct directory *)NULL;
    union record *rp = (union record *)NULL;
    size_t i, j;

    /* make n copies */
    for (i = 0; i < state->n_copies; i++) {
	struct bu_vls *name;

	if (i==0)
	    name = get_name(_dbip, proto, state, i);
	else {
	    dp = db_lookup(_dbip, bu_vls_addr(&obj_list.names[idx].dest[i-1]), LOOKUP_QUIET);
	    if (!dp) {
		continue;
	    }
	    name = get_name(_dbip, dp, state, i);
	}

	/* XXX: this can probably be optimized. */
	bu_vls_strcpy(&obj_list.names[idx].dest[i], bu_vls_addr(name));
	bu_vls_free(name);

	/* add the object to the directory */
	dp = db_diradd(_dbip, bu_vls_addr(&obj_list.names[idx].dest[i]), RT_DIR_PHONY_ADDR, proto->d_len, proto->d_flags, &proto->d_minor_type);
	if ((dp == RT_DIR_NULL) || (db_alloc(_dbip, dp, proto->d_len) < 0)) {
	    TCL_ALLOC_ERR;
	    return;
	}

	/* get an in-memory reference to the object being copied */
	if ((rp = db_getmrec(_dbip, proto)) == (union record *)0) {
	    TCL_READ_ERR;
	    return;
	}

	if (rp->u_id == ID_SOLID) {
	    bu_strlcpy(rp->s.s_name, dp->d_namep, NAMESIZE);

	    /* mirror */
	    if (state->miraxis != W) {
		/* XXX er, this seems rather wrong .. but it's v4 so punt */
		rp->s.s_values[state->miraxis] += 2 * (state->mirpos - rp->s.s_values[state->miraxis]);
		for (j = 3+state->miraxis; j < 24; j++)
		    rp->s.s_values[j] = -rp->s.s_values[j];
	    }
	    /* translate */
	    if (state->trans[W] > SMALL_FASTF)
		/* assumes primitive's first parameter is its position */
		VADD2(rp->s.s_values, rp->s.s_values, state->trans);
	    /* rotate */
	    if (state->rot[W] > SMALL_FASTF) {
		mat_t r;
		vect_t vec, ovec;

		if (state->rpnt[W] > SMALL_FASTF)
		    VSUB2(rp->s.s_values, rp->s.s_values, state->rpnt);
		MAT_IDN(r);
		bn_mat_angles(r, state->rot[X], state->rot[Y], state->rot[Z]);
		for (j = 0; j < 24; j+=3) {
		    VMOVE(vec, rp->s.s_values+j);
		    MAT4X3VEC(ovec, r, vec);
		    VMOVE(rp->s.s_values+j, ovec);
		}
		if (state->rpnt[W] > SMALL_FASTF)
		    VADD2(rp->s.s_values, rp->s.s_values, state->rpnt);
	    }
	} else
	    bu_log("mods not available on %s\n", proto->d_namep);

	/* write the object to disk */
	if (db_put(_dbip, dp, rp, 0, dp->d_len) < 0) {
	    bu_log("ERROR: clone internal error writing to the database\n");
	    return;
	}
    }
    if (rp)
	bu_free((char *)rp, "copy_solid record[]");

    return;
}
void
db_functree(struct db_i *dbip,
	    struct directory *dp,
	    void (*comb_func) (struct db_i *, struct directory *, void *),
	    void (*leaf_func) (struct db_i *, struct directory *, void *),
	    struct resource *resp,
	    void *client_data)
{
    register size_t i;

    RT_CK_DBI(dbip);
    if (resp) {
	RT_CK_RESOURCE(resp);
    }

    if ((!dp) || (!comb_func && !leaf_func)) {
	return; /* nothing to do */
    }

    if (RT_G_DEBUG&DEBUG_DB) {
	bu_log("db_functree(%s) %p, %p, comb=%lx, leaf=%lx, client_data=%p\n",
	       dp->d_namep, (void *)dbip, (void *)dp,
	       (long unsigned int)comb_func, (long unsigned int)leaf_func,
	       client_data);
    }

    if (dp->d_flags & RT_DIR_COMB) {
	if (db_version(dbip) < 5) {
	    register union record *rp;
	    register struct directory *mdp;
	    /*
	     * Load the combination into local record buffer
	     * This is in external v4 format.
	     */
	    if ((rp = db_getmrec(dbip, dp)) == (union record *)0)
		return;

	    /* recurse */
	    for (i=1; i < dp->d_len; i++) {
		if ((mdp = db_lookup(dbip, rp[i].M.m_instname, LOOKUP_NOISY)) == RT_DIR_NULL)
		    continue;
		db_functree(dbip, mdp, comb_func, leaf_func, resp, client_data);
	    }
	    bu_free((char *)rp, "db_functree record[]");
	} else {
	    struct rt_db_internal in;
	    struct rt_comb_internal *comb;

	    if (rt_db_get_internal5(&in, dp, dbip, NULL, resp) < 0)
		return;

	    comb = (struct rt_comb_internal *)in.idb_ptr;
	    db_functree_subtree(dbip, comb->tree, comb_func, leaf_func, resp, client_data);
	    rt_db_free_internal(&in);
	}

	/* Finally, the combination itself */
	if (comb_func)
	    comb_func(dbip, dp, client_data);

    } else if (dp->d_flags & RT_DIR_SOLID || dp->d_major_type & DB5_MAJORTYPE_BINARY_MASK) {
	if (leaf_func)
	    leaf_func(dbip, dp, client_data);
    } else {
	bu_log("db_functree:  %s is neither COMB nor SOLID?\n",
	       dp->d_namep);
    }
}