/* voxm_splat.h --- voxel-based modeling of antialiased 3D objects */
/* Last edited on 2016-04-02 13:06:27 by stolfilocal */

#ifndef voxm_splat_H
#define voxm_splat_H

#define _GNU_SOURCE
#include <stdint.h>

#include <bool.h>
#include <r3.h>
#include <r3_path.h>
#include <ppv_array.h>

/* VOXEL-BASED SOLID MODELING 

  The procedures in this interface generate models of 3D objects by
  "painting" or "splatting", them into a tomogram -- a 3D array of
  voxels.
  
  The array must have non-trivial size along axes 0, 1, and 2, which are
  identified with the coordinate axes {Z}, {Y} and {X}, in that order.
  That is, the index 0 selects an horizontal layer of the array, index 1
  selects a row in that layer parallel to the {X} axis, and index 2
  selects a voxel in that row.
  
  For the purpose of this module, each voxel is imagined as a cube of
  unit size with integer corner coordinates. If an array has {N=a.size[j]}
  voxels along some axis {j}, the voxels are supposed to span
  the coordinate interval {[0 _ N]} along that axis. The index {i=ix[j]}
  of a voxel along that axis ranges from 0 to {N-1}; the voxel spans the
  range {[i _ i+1]} on that axis, and its center is at {i+0.5}.
  
  Voxel values in a tomogram {a} (/samples/) are unsigned integers from
  0 to {MAXVAL = 2^a.bps}. They are interpreted as fractional
  (/occupancy values/) between 0.0 and 1.0; where voxel value 0 means
  occupancy 0.0, {MAXVAL} means 1.0, and other voxel values interpolate
  linearly between them.
  
  Futhermore, the occupancy values 0.0 and 1.0 are assumed to mean that
  the center of the voxel is well outside or well inside the object,
  respectively. Intermetiate values are used in a /fuzzy layer/ near the
  object boundary to improve the smoothness of its implied surface,
  which is asumed to be the locus of points with occupancy 0.5. */

/* SINGLE VOXEL SPLATTING */
 
void voxm_splat_voxel(ppv_array_t *a, int32_t kx, int32_t ky, int32_t kz, double val, bool_t sub);
 /* Modifies the stored value {oldv} of voxel {kx} of row {ky} of layer {kz} of {a} 
   with the value {val}, after quantizing {val} to an unsigned integer {newv}.
   
   Specifically, if {sub} is false, stores into the voxel the maximum of
   {oldv} and {newv}. If {sub} is true, stores instead the minimum of
   {oldv} and {MAXVAL-newv}.
   
   Note that {kx,ky,kz} are indices {2,1,0} of {a}, in that order. */

/* SPLATTING OBJECTS FROM OCCUPANCY FUNCTIONS */

typedef double voxm_splat_obfun_t(r3_t *p);
  /* Type of the occupancy function of a fuzzy object, that 
    returns 0 if {p} is well outside the object, 1 if it
    is well inside it, and fractional values in the fuzzy layer. */
   
void voxm_splat_object
  ( ppv_array_t *a,
    voxm_splat_obfun_t *obj,
    r3_path_state_t *S,
    double maxR,
    bool_t sub
  );
  /* Splats into the voxel array {a} the object defined by the occupancy function
    {obj}, modified by the matrix {S.M} and translated by {S.p}.
    The matrix {S.M} must be an isometry (a rotation or a reflection).
    
    Assumes that the modified and translated object has zero occupancy
    at any point that differs more than {maxR} units from {S.p} along
    any axes. Note that this range must completely include any fuzzy
    layer. */

void voxm_splat_object_multi
  ( ppv_array_t *a,
    voxm_splat_obfun_t *obj,
    int32_t ns,
    r3_path_state_t S[],
    double maxR,
    bool_t sub
  );
  /* Splats into the voxel array {a} the object {obj} modified by the
    matrces {S[k].M} and translated by {S[k].p}, for {k} in {0..ns-1}.
    Assumes that the modified object extends at most {maxR} units from
    its reference point, for any {k}. */

#endif

