Repository URL to install this package:
Version:
7.26.0-0.2 ▾
|
/* G - X X X . C
* BRL-CAD
*
* Copyright (c) 1993-2016 United States Government as represented by
* the U.S. Army Research Laboratory.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; see the file named COPYING for more
* information.
*
*/
/** @file conv/g-xxx.c
*
* Sample code for converting BRL-CAD models to some other format.
* This code assumes that your receiving format can handle CSG
* primitives and Boolean trees with transformation matrices
*
*/
#include "common.h"
/* system headers */
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "bio.h"
/* interface headers */
#include "vmath.h"
#include "bu/getopt.h"
#include "nmg.h"
#include "rt/geom.h"
#include "raytrace.h"
#include "wdb.h"
/*
* data container for your data. you create one of these with
* whatever fields you need. it gets passed to all of the callback
* functions for your application use as a client_data pointer.
*/
struct user_data {
long int data;
struct bn_tol tol;
};
/* This routine just produces an ascii description of the Boolean tree.
* In a real converter, this would output the tree in the desired format.
*/
void
describe_tree(union tree *tree,
struct bu_vls *str)
{
struct bu_vls left = BU_VLS_INIT_ZERO;
struct bu_vls right = BU_VLS_INIT_ZERO;
const char op_xor='^';
char op='\0';
BU_CK_VLS(str);
if (!tree) {
/* this tree has no members */
bu_vls_strcat(str, "-empty-");
return;
}
RT_CK_TREE(tree);
/* Handle all the possible node types.
* the first four are the most common types, and are typically
* the only ones found in a BRL-CAD database.
*/
switch (tree->tr_op) {
case OP_DB_LEAF: /* leaf node, this is a member */
/* Note: tree->tr_l.tl_mat is a pointer to a
* transformation matrix to apply to this member
*/
bu_vls_strcat(str, tree->tr_l.tl_name);
break;
case OP_UNION: /* union operator node */
op = DB_OP_UNION;
goto binary;
case OP_INTERSECT: /* intersection operator node */
op = DB_OP_INTERSECT;
goto binary;
case OP_SUBTRACT: /* subtraction operator node */
op = DB_OP_SUBTRACT;
goto binary;
case OP_XOR: /* exclusive "or" operator node */
op = op_xor;
binary: /* common for all binary nodes */
describe_tree(tree->tr_b.tb_left, &left);
describe_tree(tree->tr_b.tb_right, &right);
bu_vls_putc(str, '(');
bu_vls_vlscatzap(str, &left);
bu_vls_printf(str, " %c ", op);
bu_vls_vlscatzap(str, &right);
bu_vls_putc(str, ')');
break;
case OP_NOT:
bu_vls_strcat(str, "(!");
describe_tree(tree->tr_b.tb_left, str);
bu_vls_putc(str, ')');
break;
case OP_GUARD:
bu_vls_strcat(str, "(G");
describe_tree(tree->tr_b.tb_left, str);
bu_vls_putc(str, ')');
break;
case OP_XNOP:
bu_vls_strcat(str, "(X");
describe_tree(tree->tr_b.tb_left, str);
bu_vls_putc(str, ')');
break;
case OP_NOP:
bu_vls_strcat(str, "NOP");
break;
default:
bu_exit(1, "ERROR: describe_tree() got unrecognized op (%d)\n", tree->tr_op);
}
}
/**
* @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;
}
/**
* @brief This is called when all sub-elements of a region have been processed by leaf_func.
*
* @param tsp tree state
* @param pathp db path
* @param curtree current tree
*
* @return TREE_NULL if data in curtree was "stolen", otherwise db_walk_tree will
* clean up the data in the union tree * that is returned
*
* If it wants to retain the data in curtree it can by returning TREE_NULL. Otherwise
* db_walk_tree will clean up the data in the union tree * that is returned.
*
*/
union tree *
region_end (struct db_tree_state *tsp,
const struct db_full_path *pathp,
union tree *curtree,
void *UNUSED(client_data))
{
char *name;
RT_CK_DBTS(tsp);
name = db_path_to_string(pathp);
bu_log("region_end %s\n", name);
bu_free(name, "region_end name");
return curtree;
}
/* This routine is called by the tree walker (db_walk_tree)
* for every primitive encountered in the trees specified on the command line */
union tree *
primitive_func(struct db_tree_state *tsp,
const struct db_full_path *pathp,
struct rt_db_internal *ip,
void *UNUSED(client_data))
{
struct directory *dp;
char *name;
dp = DB_FULL_PATH_CUR_DIR(pathp);
RT_CK_DBTS(tsp);
name = db_path_to_string(pathp);
bu_log("leaf_func %s\n", name);
bu_free(name, "region_end name");
/* handle each type of primitive (see h/rtgeom.h) */
if (ip->idb_major_type == DB5_MAJORTYPE_BRLCAD) {
switch (ip->idb_type) {
/* most commonly used primitives */
case ID_TOR: /* torus */
{
struct rt_tor_internal *tor = (struct rt_tor_internal *)ip->idb_ptr;
printf("Write this torus (name=%s) in your format:\n", dp->d_namep);
printf("\tV=(%g %g %g)\n", V3ARGS(tor->v));
printf("\tnormal=(%g %g %g)\n", V3ARGS(tor->h));
printf("\tradius1 = %g\n", tor->r_a);
printf("\tradius2 = %g\n", tor->r_h);
break;
}
case ID_TGC: /* truncated general cone frustum */
case ID_REC: /* right elliptical cylinder */
{
/* This primitive includes circular cross-section
* cones and cylinders
*/
struct rt_tgc_internal *tgc = (struct rt_tgc_internal *)ip->idb_ptr;
printf("Write this TGC (name=%s) in your format:\n", dp->d_namep);
printf("\tV=(%g %g %g)\n", V3ARGS(tgc->v));
printf("\tH=(%g %g %g)\n", V3ARGS(tgc->h));
printf("\tA=(%g %g %g)\n", V3ARGS(tgc->a));
printf("\tB=(%g %g %g)\n", V3ARGS(tgc->b));
printf("\tC=(%g %g %g)\n", V3ARGS(tgc->c));
printf("\tD=(%g %g %g)\n", V3ARGS(tgc->d));
break;
}
case ID_ELL:
case ID_SPH:
{
/* spheres and ellipsoids */
struct rt_ell_internal *ell = (struct rt_ell_internal *)ip->idb_ptr;
printf("Write this ellipsoid (name=%s) in your format:\n", dp->d_namep);
printf("\tV=(%g %g %g)\n", V3ARGS(ell->v));
printf("\tA=(%g %g %g)\n", V3ARGS(ell->a));
printf("\tB=(%g %g %g)\n", V3ARGS(ell->b));
printf("\tC=(%g %g %g)\n", V3ARGS(ell->c));
break;
}
case ID_ARB8: /* convex primitive with from four to six faces */
{
int i;
/* this primitive may have degenerate faces
* faces are: 0123, 7654, 0347, 1562, 0451, 3267
* (points listed above in counter-clockwise order)
*/
struct rt_arb_internal *arb = (struct rt_arb_internal *)ip->idb_ptr;
printf("Write this ARB (name=%s) in your format:\n", dp->d_namep);
for (i=0; i<8; i++)
printf("\tpoint #%d: (%g %g %g)\n", i, V3ARGS(arb->pt[i]));
break;
}
/* other primitives, left as an exercise to the reader */
case ID_BOT: /* Bag O' Triangles */
case ID_ARS:
/* series of curves
* each with the same number of points
*/
case ID_HALF:
/* half universe defined by a plane */
case ID_POLY:
/* polygons (up to 5 vertices per) */
case ID_BSPLINE:
/* NURB surfaces */
case ID_NMG:
/* N-manifold geometry */
case ID_ARBN:
case ID_DSP:
/* Displacement map (terrain primitive) */
/* the DSP primitive may reference an external file or binunif object */
case ID_HF:
/* height field (terrain primitive) */
/* the HF primitive references an external file */
case ID_EBM:
/* extruded bit-map */
/* the EBM primitive references an external file */
case ID_VOL:
/* the VOL primitive references an external file */
case ID_PIPE:
case ID_PARTICLE:
case ID_RPC:
case ID_RHC:
case ID_EPA:
case ID_EHY:
case ID_ETO:
case ID_GRIP:
case ID_SKETCH:
case ID_EXTRUDE:
/* note that an extrusion references a sketch, make sure you convert
* the sketch also
*/
default:
bu_log("Primitive %s is an unsupported or unrecognized type (%d)\n", dp->d_namep, ip->idb_type);
break;
}
} else {
switch (ip->idb_major_type) {
case DB5_MAJORTYPE_BINARY_UNIF:
{
/* not actually a primitive, just a block of storage for data
* a uniform array of chars, ints, floats, doubles, ...
*/
struct rt_binunif_internal *bin = (struct rt_binunif_internal *)ip->idb_ptr;
if (bin)
printf("Found a binary object (%s)\n\n", dp->d_namep);
break;
}
default:
bu_log("Major type of %s is unrecognized type (%d)\n", dp->d_namep, ip->idb_major_type);
break;
}
}
return (union tree *) NULL;
}
static void
print_usage(const char *progname)
{
const char *usage = "[-xX lvl] [-a abs_tol] [-r rel_tol] [-n norm_tol] "
"[-o out_file] brlcad_db.g object(s)\n";
bu_exit(1, "Usage: %s %s", progname, usage);
}
int
main(int argc, char *argv[])
{
struct user_data your_data = {0, BN_TOL_INIT_ZERO};
int i;
int c;
char idbuf[132] = {0};
struct rt_i *rtip;
struct db_tree_state init_state;
bu_setprogname(argv[0]);
bu_setlinebuf(stderr);
/* calculational tolerances
* mostly used by NMG routines
*/
your_data.tol.magic = BN_TOL_MAGIC;
your_data.tol.dist = BN_TOL_DIST;
your_data.tol.dist_sq = your_data.tol.dist * your_data.tol.dist;
your_data.tol.perp = 1e-6;
your_data.tol.para = 1 - your_data.tol.perp;
/* Get command line arguments. */
while ((c = bu_getopt(argc, argv, "t:a:n:o:r:x:X:")) != -1) {
switch (c) {
case 't': /* calculational tolerance */
your_data.tol.dist = atof(bu_optarg);
your_data.tol.dist_sq = your_data.tol.dist * your_data.tol.dist;
case 'o': /* Output file name */
/* grab output file name */
break;
case 'x': /* librt debug flag */
sscanf(bu_optarg, "%x", &RTG.debug);
bu_printb("librt RT_G_DEBUG", RT_G_DEBUG, DEBUG_FORMAT);
bu_log("\n");
break;
case 'X': /* NMG debug flag */
sscanf(bu_optarg, "%x", &RTG.NMG_debug);
bu_printb("librt RTG.NMG_debug", RTG.NMG_debug, NMG_DEBUG_FORMAT);
bu_log("\n");
break;
default:
print_usage(argv[0]);
break;
}
}
if (bu_optind+1 >= argc) {
print_usage(argv[0]);
}
/* Open BRL-CAD database */
/* Scan all the records in the database and build a directory */
rtip=rt_dirbuild(argv[bu_optind], idbuf, sizeof(idbuf));
if (rtip == RTI_NULL) {
bu_exit(1, "g-xxx: rt_dirbuild failure\n");
}
init_state = rt_initial_tree_state;
bu_optind++;
/* Walk the trees named on the command line
* outputting combinations and primitives
*/
for (i=bu_optind; i<argc; i++) {
db_walk_tree(rtip->rti_dbip, argc - i, (const char **)&argv[i], 1 /* bu_avail_cpus() */,
&init_state, region_start, region_end, primitive_func, (void *) &your_data);
}
return 0;
}
/*
* Local Variables:
* mode: C
* tab-width: 8
* indent-tabs-mode: t
* c-file-style: "stroustrup"
* End:
* ex: shiftwidth=4 tabstop=8
*/