Beispiel #1
0
int TSplit::split(const char *token, const char *buf) {

    _CHECK_RS(token,NULL,-1);
    _CHECK_RS(buf,NULL,-1);

    char *pos = NULL;
    char *buf_pt = NULL;
    int buf_len = strlen(buf) + 1;
    int token_len = strlen(token);

	if (m_nBufLen < buf_len) {
		if (m_strBuf) {
			FREE_PT(m_strBuf);
		}
		m_strBuf = (char *)calloc(buf_len, 1);
		_CHECK_RS(m_strBuf, NULL, -1);
	}
	else {
		memset(m_strBuf, 0, m_nBufLen);
	}

	m_nCnt = 0;

    memcpy(m_strBuf, buf, buf_len);

    buf_pt = m_strBuf;
    while (1) {

		if (0 == buf_pt[0]) {
			if (0 < m_nCnt)
				m_Array[m_nCnt++] = (PVOID)"";
			break;
		}
        
        if (CheckExtend())
            return -1; 

        pos = strstr(buf_pt, token);
        if (!pos) {
            m_Array[m_nCnt++] = buf_pt;
            break;
        }   
        *pos = 0;
        if (pos != buf_pt)
            m_Array[m_nCnt++] = buf_pt;
		else
			m_Array[m_nCnt++] = (PVOID)"";
        buf_pt = pos + token_len;
    }   
    return 0;
}
Beispiel #2
0
void
part_compact(register struct application *ap, register struct partition *PartHeadp, fastf_t tolerance)
{

    fastf_t				gap;
    struct partition		*pp;
    struct partition		*nextpp;

    /* first eliminate zero thickness partitions */
    pp = PartHeadp->pt_forw;
    while ( pp != PartHeadp )
    {
	fastf_t comp_thickness;

	nextpp = pp->pt_forw;
	comp_thickness = pp->pt_outhit->hit_dist - pp->pt_inhit->hit_dist;
	if ( comp_thickness <= 0.0 )
	{
	    DEQUEUE_PT( pp );
	    FREE_PT( pp, ap->a_resource);
	}
	pp = nextpp;
    }

    for (pp = PartHeadp->pt_forw; pp != PartHeadp; pp = pp->pt_forw)  {
    top:		nextpp = pp->pt_forw;
    if (nextpp == PartHeadp)  {
	break;
    }
    if ( pp->pt_regionp->reg_regionid > 0 && nextpp->pt_regionp->reg_regionid > 0 ) {
	if (pp->pt_regionp->reg_regionid != nextpp->pt_regionp->reg_regionid)  {
	    continue;
	}
    } else if ( pp->pt_regionp->reg_regionid <= 0 && nextpp->pt_regionp->reg_regionid <= 0 ) {
	if ( pp->pt_regionp->reg_aircode != nextpp->pt_regionp->reg_aircode ) {
	    continue;
	}
    } else
	continue;

    gap = nextpp->pt_inhit->hit_dist - pp->pt_outhit->hit_dist;

    /* The following line is a diagnostic that is worth reusing:
     * bu_log("gap=%e\n", gap);
     */

    if (gap > tolerance)  {
	continue;
    }

    /* Eliminate the gap by collapsing the two partitions
     * into one.  The below lines have been commented out but
     * should be retained for debugging purposes.
     */
#if 0
    bu_log("part_comp: collapsing gap of %e mm between id=%d and id=%d air=%d and air=%d\n",
	   gap, pp->pt_regionp->reg_regionid,
	   nextpp->pt_regionp->reg_regionid, pp->pt_regionp->reg_aircode, nextpp->pt_regionp->reg_aircode);
#endif
    pp->pt_outseg = nextpp->pt_outseg;
    pp->pt_outhit = nextpp->pt_outhit;
    pp->pt_outflip = nextpp->pt_outflip;


    /*
     *  Dequeue and free the unwanted partition structure.
     *  Referenced segments, etc, will be freed by rt_shootray().
     */
    DEQUEUE_PT(nextpp);
    FREE_PT(nextpp, ap->a_resource);

    goto top;
    }

}
Beispiel #3
0
/**
 * Given a ray, shoot it at all the relevant parts of the model,
 * (building the HeadSeg chain), and then call rt_boolregions() to
 * build and evaluate the partition chain.  If the ray actually hit
 * anything, call the application's a_hit() routine with a pointer to
 * the partition chain, otherwise, call the application's a_miss()
 * routine.
 *
 * It is important to note that rays extend infinitely only in the
 * positive direction.  The ray is composed of all points P, where
 *
 * P = r_pt + K * r_dir
 *
 * for K ranging from 0 to +infinity.  There is no looking backwards.
 *
 * It is also important to note that the direction vector r_dir must
 * have unit length; this is mandatory, and is not ordinarily checked,
 * in the name of efficiency.
 *
 * Input:  Pointer to an application structure, with these mandatory fields:
 * a_ray.r_pt Starting point of ray to be fired
 * a_ray.r_dir UNIT VECTOR with direction to fire in (dir cosines)
 * a_hit Routine to call when something is hit
 * a_miss Routine to call when ray misses everything
 *
 * Calls user's a_miss() or a_hit() routine as appropriate.  Passes
 * a_hit() routine list of partitions, with only hit_dist fields
 * valid.  Normal computation deferred to user code, to avoid needless
 * computation here.
 *
 * Returns: whatever the application function returns (an int).
 *
 * NOTE: The application functions may call rt_shootray() recursively.
 * Thus, none of the local variables may be static.
 *
 * An open issue for execution in a PARALLEL environment is locking of
 * the statistics variables.
 */
int
rt_vshootray(struct application *ap)
{
    struct seg *HeadSeg;
    int ret;
    vect_t inv_dir;	/* inverses of ap->a_ray.r_dir */
    struct bu_bitv *solidbits;	/* bits for all solids shot so far */
    struct bu_ptbl *regionbits;	/* bits for all involved regions */
    char *status;
    struct partition InitialPart;	/* Head of Initial Partitions */
    struct partition FinalPart;	/* Head of Final Partitions */
    int nrays = 1;			/* for now */
    int vlen;
    int id;
    int i;
    struct soltab **ary_stp;	/* array of pointers */
    struct xray **ary_rp;	/* array of pointers */
    struct seg *ary_seg;	/* array of structures */
    struct rt_i *rtip;
    int done;

#define BACKING_DIST (-2.0)		/* mm to look behind start point */
    rtip = ap->a_rt_i;
    RT_AP_CHECK(ap);
    if (!ap->a_resource) {
	ap->a_resource = &rt_uniresource;
    }
    RT_CK_RESOURCE(ap->a_resource);

    if (RT_G_DEBUG&(DEBUG_ALLRAYS|DEBUG_SHOOT|DEBUG_PARTITION)) {
	bu_log("\n**********mshootray cpu=%d  %d, %d lvl=%d (%s)\n",
	       ap->a_resource->re_cpu,
	       ap->a_x, ap->a_y,
	       ap->a_level,
	       ap->a_purpose != (char *)0 ? ap->a_purpose : "?");
	VPRINT("Pnt", ap->a_ray.r_pt);
	VPRINT("Dir", ap->a_ray.r_dir);
    }

    rtip->rti_nrays++;
    if (rtip->needprep)
	rt_prep(rtip);

    /* Allocate dynamic memory */
    vlen = nrays * rtip->rti_maxsol_by_type;
    ary_stp = (struct soltab **)bu_calloc(vlen, sizeof(struct soltab *),
					  "*ary_stp[]");
    ary_rp = (struct xray **)bu_calloc(vlen, sizeof(struct xray *),
				       "*ary_rp[]");
    ary_seg = (struct seg *)bu_calloc(vlen, sizeof(struct seg),
				      "ary_seg[]");

    /**** for each ray, do this ****/

    InitialPart.pt_forw = InitialPart.pt_back = &InitialPart;
    FinalPart.pt_forw = FinalPart.pt_back = &FinalPart;

    HeadSeg = RT_SEG_NULL;

    solidbits = rt_get_solidbitv(rtip->nsolids, ap->a_resource);

    if (BU_LIST_IS_EMPTY(&ap->a_resource->re_region_ptbl)) {
	BU_ALLOC(regionbits, struct bu_ptbl);
	bu_ptbl_init(regionbits, 7, "rt_shootray() regionbits ptbl");
    } else {
	regionbits = BU_LIST_FIRST(bu_ptbl, &ap->a_resource->re_region_ptbl);
	BU_LIST_DEQUEUE(&regionbits->l);
	BU_CK_PTBL(regionbits);
    }

    /* Compute the inverse of the direction cosines */
    if (!ZERO(ap->a_ray.r_dir[X])) {
	inv_dir[X]=1.0/ap->a_ray.r_dir[X];
    } else {
	inv_dir[X] = INFINITY;
	ap->a_ray.r_dir[X] = 0.0;
    }
    if (!ZERO(ap->a_ray.r_dir[Y])) {
	inv_dir[Y]=1.0/ap->a_ray.r_dir[Y];
    } else {
	inv_dir[Y] = INFINITY;
	ap->a_ray.r_dir[Y] = 0.0;
    }
    if (!ZERO(ap->a_ray.r_dir[Z])) {
	inv_dir[Z]=1.0/ap->a_ray.r_dir[Z];
    } else {
	inv_dir[Z] = INFINITY;
	ap->a_ray.r_dir[Z] = 0.0;
    }

    /*
     * XXX handle infinite solids here, later.
     */

    /*
     * If ray does not enter the model RPP, skip on.
     * If ray ends exactly at the model RPP, trace it.
     */
    if (!rt_in_rpp(&ap->a_ray, inv_dir, rtip->mdl_min, rtip->mdl_max)  ||
	ap->a_ray.r_max < 0.0) {
	rtip->nmiss_model++;
	if (ap->a_miss)
	    ret = ap->a_miss(ap);
	else
	    ret = 0;
	status = "MISS model";
	goto out;
    }

    /* For each type of solid to be shot at, assemble the vectors */
    for (id = 1; id <= ID_MAX_SOLID; id++) {
	register int nsol;

	if ((nsol = rtip->rti_nsol_by_type[id]) <= 0) continue;

	/* For each instance of this solid type */
	for (i = nsol-1; i >= 0; i--) {
	    ary_stp[i] = rtip->rti_sol_by_type[id][i];
	    ary_rp[i] = &(ap->a_ray);	/* XXX, sb [ray] */
	    ary_seg[i].seg_stp = SOLTAB_NULL;
	    BU_LIST_INIT(&ary_seg[i].l);
	}
	/* bounding box check */
	/* bit vector per ray check */
	/* mark elements to be skipped with ary_stp[] = SOLTAB_NULL */
	ap->a_rt_i->nshots += nsol;	/* later: skipped ones */
	if (OBJ[id].ft_vshot) {
	    OBJ[id].ft_vshot(ary_stp, ary_rp, ary_seg, nsol, ap);
	} else {
	    vshot_stub(ary_stp, ary_rp, ary_seg, nsol, ap);
	}


	/* set bits for all solids shot at for each ray */

	/* append resulting seg list to input for boolweave */
	for (i = nsol-1; i >= 0; i--) {
	    register struct seg *seg2;

	    if (ary_seg[i].seg_stp == SOLTAB_NULL) {
		/* MISS */
		ap->a_rt_i->nmiss++;
		continue;
	    }
	    ap->a_rt_i->nhits++;

	    /* For now, do it the slow way.  sb [ray] */
	    /* MUST dup it -- all segs have to live till after a_hit() */
	    RT_GET_SEG(seg2, ap->a_resource);
	    *seg2 = ary_seg[i];	/* struct copy */
	    /* rt_boolweave(seg2, &InitialPart, ap); */
	    bu_bomb("FIXME: need to call boolweave here");

	    /* Add seg chain to list of used segs awaiting reclaim */

#if 0
	    /* FIXME: need to use waiting_segs/finished_segs here in
	     * conjunction with rt_boolweave()
	     {
	     register struct seg *seg3 = seg2;
	     while (seg3->seg_next != RT_SEG_NULL)
	     seg3 = seg3->seg_next;
	     seg3->seg_next = HeadSeg;
	     HeadSeg = seg2;
	     }
	    */
#endif
	}
    }

    /*
     * Ray has finally left known space.
     */
    if (InitialPart.pt_forw == &InitialPart) {
	if (ap->a_miss)
	    ret = ap->a_miss(ap);
	else
	    ret = 0;
	status = "MISSed all primitives";
	goto freeup;
    }

    /*
     * All intersections of the ray with the model have been computed.
     * Evaluate the boolean trees over each partition.
     */
    done = rt_boolfinal(&InitialPart, &FinalPart, BACKING_DIST, INFINITY, regionbits, ap, solidbits);

    if (done > 0) goto hitit;

    if (FinalPart.pt_forw == &FinalPart) {
	if (ap->a_miss)
	    ret = ap->a_miss(ap);
	else
	    ret = 0;
	status = "MISS bool";
	goto freeup;
    }

    /*
     * Ray/model intersections exist.  Pass the list to the user's
     * a_hit() routine.  Note that only the hit_dist elements of
     * pt_inhit and pt_outhit have been computed yet.  To compute both
     * hit_point and hit_normal, use the
     *
     * RT_HIT_NORMAL(NULL, hitp, stp, rayp, 0);
     *
     * macro.  To compute just hit_point, use
     *
     * VJOIN1(hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir);
     */
hitit:
    if (RT_G_DEBUG&DEBUG_SHOOT) rt_pr_partitions(rtip, &FinalPart, "a_hit()");

    if (ap->a_hit)
	ret = ap->a_hit(ap, &FinalPart, HeadSeg/* &finished_segs */);
    else
	ret = 0;
    status = "HIT";

    /*
     * Processing of this ray is complete.  Free dynamic resources.
     */
freeup:
    {
	register struct partition *pp;

	/* Free up initial partition list */
	for (pp = InitialPart.pt_forw; pp != &InitialPart;) {
	    register struct partition *newpp;
	    newpp = pp;
	    pp = pp->pt_forw;
	    FREE_PT(newpp, ap->a_resource);
	}
	/* Free up final partition list */
	for (pp = FinalPart.pt_forw; pp != &FinalPart;) {
	    register struct partition *newpp;
	    newpp = pp;
	    pp = pp->pt_forw;
	    FREE_PT(newpp, ap->a_resource);
	}
    }

    /* Segs can't be freed until after a_hit() has returned */
#if 0
    /* FIXME: depends on commented out code above */
    if (HeadSeg)
	RT_FREE_SEG_LIST(HeadSeg, ap->a_resource);
#endif

out:
    bu_free((char *)ary_stp, "*ary_stp[]");
    bu_free((char *)ary_rp, "*ary_rp[]");
    bu_free((char *)ary_seg, "ary_seg[]");

    if (solidbits != NULL) {
	bu_bitv_free(solidbits);
    }
    if (RT_G_DEBUG&(DEBUG_ALLRAYS|DEBUG_SHOOT|DEBUG_PARTITION)) {
	bu_log("----------mshootray cpu=%d  %d, %d lvl=%d (%s) %s ret=%d\n",
	       ap->a_resource->re_cpu,
	       ap->a_x, ap->a_y,
	       ap->a_level,
	       ap->a_purpose != (char *)0 ? ap->a_purpose : "?",
	       status, ret);
    }
    return ret;
}
Beispiel #4
0
/**
 * NOTE that the [0] element here corresponds with the caller's (1)
 * element.
 */
void
BU_FORTRAN(frshot, FRSHOT)(int *nloc,			/* input & output */
			   double *indist,		/* output only */
			   double *outdist,
			   int *region_ids,
			   struct context *context,
			   struct rt_i **rtip,		/* input only */
			   double *pt,
			   double *dir)
{
    struct application ap;
    register struct partition *pp;
    int ret;
    register int i;

    RT_CHECK_RTI(*rtip);

    if (*nloc <= 0) {
	bu_log("ERROR frshot: nloc=%d\n", *nloc);
	*nloc = 0;
	return;
    }

    RT_APPLICATION_INIT(&ap);
    ap.a_ray.r_pt[X] = pt[0];
    ap.a_ray.r_pt[Y] = pt[1];
    ap.a_ray.r_pt[Z] = pt[2];
    ap.a_ray.r_dir[X] = dir[0];
    ap.a_ray.r_dir[Y] = dir[1];
    ap.a_ray.r_dir[Z] = dir[2];
    VUNITIZE(ap.a_ray.r_dir);
    ap.a_hit = fr_hit;
    ap.a_miss = fr_miss;
    ap.a_level = 0;
    ap.a_onehit = *nloc * 2;
    ap.a_resource = &rt_uniresource;
    rt_uniresource.re_magic = RESOURCE_MAGIC;
    ap.a_purpose = "frshot";
    ap.a_rt_i = *rtip;

    /*
     * Actually fire the ray.  The list of results will be linked to
     * fr_global_head by fr_hit(), for further use below.
     *
     * It is a bit risky to rely on the segment structures pointed to
     * by the partition list to still be valid, because rt_shootray
     * has already put them back on the free segment queue.  However,
     * they will remain unchanged until the next call to
     * rt_shootray(), so copying out the data here will work fine.
     */
    ret = rt_shootray(&ap);

    if (ret <= 0) {
	/* Signal no hits */
	*nloc = 0;
	return;
    }

    /* Copy hit information from linked list to argument arrays */
    pp = fr_global_head.pt_forw;
    if (pp == &fr_global_head) {
	*nloc = 0;
	return;
    }
    for (i=0; i < *nloc; i++, pp=pp->pt_forw) {
	register struct context *ctp;

	if (pp == &fr_global_head) break;
	indist[i] = pp->pt_inhit->hit_dist;
	outdist[i] = pp->pt_outhit->hit_dist;
	/* This might instead be reg_regionid ?? */
	region_ids[i] = pp->pt_regionp->reg_bit+1;
	ctp = &context[i];
	ctp->co_stp = pp->pt_inseg->seg_stp;
	VMOVE(ctp->co_vpriv, pp->pt_inhit->hit_vpriv);
	ctp->co_priv = pp->pt_inhit->hit_private;
	ctp->co_inflip = pp->pt_inflip;
    }
    *nloc = i;	/* Will have been incremented above, if successful */

    /* Free linked list storage */
    for (pp = fr_global_head.pt_forw; pp != &fr_global_head;) {
	register struct partition *newpp;

	newpp = pp;
	pp = pp->pt_forw;
	FREE_PT(newpp, (&rt_uniresource));
    }
}
Beispiel #5
0
TSplit::~TSplit() {
	if (m_strBuf)
		FREE_PT(m_strBuf);
	if (m_Array)
		FREE_PT(m_Array);
}