/*                      B O O L W E A V E . H
 * BRL-CAD
 *
 * Copyright (c) 1993-2021 United States Government as represented by
 * the U.S. Army Research Laboratory.
 *
 * This library 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 library 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.
 */
/** @addtogroup rt_boolweave
 * @brief Boolean weaving of raytracing segments
 */
/** @{ */
/** @file rt/boolweave.h */

#ifndef RT_BOOLWEAVE_H
#define RT_BOOLWEAVE_H

#include "common.h"
#include "vmath.h"
#include "bu/bitv.h"
#include "bu/ptbl.h"
#include "rt/application.h"
#include "rt/resource.h"
#include "rt/seg.h"
#include "rt/ray_partition.h"

__BEGIN_DECLS

/*****************************************************************
 *                                                               *
 *  Internal routines in the RT library.                         *
 *  These routines are *not* intended for Applications to use.   *
 *  The interface to these routines may change significantly     *
 *  from release to release of this software.                    *
 *                                                               *
 *****************************************************************/

/**
 * @brief
 * Weave segs into partitions
 *
 * Weave a chain of segments into an existing set of partitions.  The
 * edge of each partition is an inhit or outhit of some solid (seg).
 *
 * NOTE: When the final partitions are completed, it is the user's
 * responsibility to honor the inflip and outflip flags.  They can not
 * be flipped here because an outflip=1 edge and an inflip=0 edge
 * following it may in fact be the same edge.  This could be dealt
 * with by giving the partition struct a COPY of the inhit and outhit
 * rather than a pointer, but that's more cycles than the neatness is
 * worth.
 *
 * Inputs -
 * Pointer to first segment in seg chain.
 * Pointer to head of circular doubly-linked list of
 * partitions of the original ray.
 *
 * Outputs -
 * Partitions, queued on doubly-linked list specified.
 *
 * Notes -
 * It is the responsibility of the CALLER to free the seg chain, as
 * well as the partition list that we return.
 */
RT_EXPORT extern void rt_boolweave(struct seg *out_hd,
				   struct seg *in_hd,
				   struct partition *PartHeadp,
				   struct application *ap);

/**
 * @brief
 * Eval booleans over partitions
 *
 * Consider each partition on the sorted & woven input partition list.
 * If the partition ends before this box's start, discard it
 * immediately.  If the partition begins beyond this box's end,
 * return.
 *
 * Next, evaluate the boolean expression tree for all regions that
 * have some presence in the partition.
 *
 * If 0 regions result, continue with next partition.
 *
 * If 1 region results, a valid hit has occurred, so transfer the
 * partition from the Input list to the Final list.
 *
 * If 2 or more regions claim the partition, then an overlap exists.
 *
 * If the overlap handler gives a non-zero return, then the
 * overlapping partition is kept, with the region ID being the first
 * one encountered.
 *
 * Otherwise, the partition is eliminated from further consideration.
 *
 * All partitions in the indicated range of the ray are evaluated.
 * All partitions which really exist (booleval is true) are appended
 * to the Final partition list.  All partitions on the Final partition
 * list have completely valid entry and exit information, except for
 * the last partition's exit information when a_onehit!=0 and a_onehit
 * is odd.
 *
 * The flag a_onehit is interpreted as follows:
 *
 * If a_onehit = 0, then the ray is traced to +infinity, and all hit
 * points in the final partition list are valid.
 *
 * If a_onehit != 0, the ray is traced through a_onehit hit points.
 * (Recall that each partition has 2 hit points, entry and exit).
 * Thus, if a_onehit is odd, the value of pt_outhit.hit_dist in the
 * last partition may be incorrect; this should not matter because the
 * application specifically said it only wanted pt_inhit there.  This
 * is most commonly seen when a_onehit = 1, which is useful for
 * lighting models.  Not having to correctly determine the exit point
 * can result in a significant savings of computer time.
 *
 * If a_onehit is negative, it indicates the number of non-air hits
 * needed.
 *
 * Returns -
 * 0 If more partitions need to be done
 * 1 Requested number of hits are available in FinalHdp
 *
 * The caller must free whatever is in both partition chains.
 *
 * NOTES for code improvements -
 *
 * With a_onehit != 0, it is difficult to stop at the 'enddist' value
 * (or the a_ray_length value), and always get correct results.  Need
 * to take into account some additional factors:
 *
 * 1) A region shouldn't be evaluated until all its solids have been
 * intersected, to prevent the "CERN" problem of out points being
 * wrong because subtracted solids aren't intersected yet.
 *
 * Maybe "all" solids don't have to be intersected, but some strong
 * statements are needed along these lines.
 *
 * A region is definitely ready to be evaluated IF all its solids
 * have been intersected.
 *
 * 2) A partition shouldn't be evaluated until all the regions within
 * it are ready to be evaluated.
 */
RT_EXPORT extern int rt_boolfinal(struct partition *InputHdp,
				  struct partition *FinalHdp,
				  fastf_t startdist,
				  fastf_t enddist,
				  struct bu_ptbl *regionbits,
				  struct application *ap,
				  const struct bu_bitv *solidbits);

/**
 * Increase the size of re_boolstack to double the previous size.
 * Depend on bu_realloc() to copy the previous data to the new area
 * when the size is increased.
 *
 * Return the new pointer for what was previously the last element.
 */
RT_EXPORT extern void rt_bool_growstack(struct resource *res);

__END_DECLS

#endif /* RT_BOOLWEAVE_H */

/** @} */

/*
 * Local Variables:
 * tab-width: 8
 * mode: C
 * indent-tabs-mode: t
 * c-file-style: "stroustrup"
 * End:
 * ex: shiftwidth=4 tabstop=8
 */
