Пример #1
0
/*!
* \return	Woolz error code.
* \ingroup	WlzTransform
* \brief	Sets the interval for the profile for the given point
* 		with respect to the given object.
* \param	obj		Given object.
* \param	pos		Given point with respect to the given
* 				object.
* \param	wSp		profile walking work space.
*/
static WlzErrorNum WlzProfileSetIDom(
  WlzObject *obj,
  WlzIVertex3 pos,
  WlzProfileWalkWSp *pWSp)
{
  int		msk;
  WlzInterval	*itv;
  WlzIntervalLine *itvLn;
  WlzErrorNum 	errNum = WLZ_ERR_NONE;

  msk = (pWSp->inside << 1) |
        (WlzInsideDomain(obj, pos.vtZ, pos.vtY, pos.vtX, &errNum) != 0);
  if(errNum == WLZ_ERR_NONE)
  {
    itvLn = pWSp->domain.i->intvlines + 0;
    switch(msk)
    {
      case 1:  /* Was out, now in. Start new interval. */
	itv = itvLn->intvs + itvLn->nintvs;
	itv->ileft = itv->iright = pWSp->index;
	pWSp->inside = 1;
	++(itvLn->nintvs);
	break;
      case 3:  /* Was in,  still in. Just update interval. */
	itv = itvLn->intvs + itvLn->nintvs - 1;
	itv->iright = pWSp->index;
	break;
      default: /* Either was in, now out or was out, still out. */
	break;
    }
  }
  return(errNum);
}
Пример #2
0
/*!
* \return	Object containing the point (x,y).
* \ingroup	WlzBinaryOps
* \brief	Takes a WLZ_2D_DOMAINOBJ, calls WlzLabel to split the domain
* 		and returns the one containing point(x,y).
* \param	obj		Given WLZ_2D_DOMAINOBJ object.
* \param	x		Column coordinate.
* \param	y		Line coordinate.
* \param	dstErr		Destination error code pointer, may be NULL.
*/
WlzObject *Wlz2DContains(WlzObject *obj,
                          double x,
                          double y,
                          WlzErrorNum *dstErr) {


   WlzObject    *retObj = NULL;
   WlzObject	**objArray;

   int          i, nobjs;
   /* int          maxNobjs=1024; */
   int          maxNobjs=2048;
   int 		found = 0;

   WlzErrorNum  errNum=WLZ_ERR_NONE;
   WlzConnectType connectivity = WLZ_8_CONNECTED;

   /*
   fprintf(stderr, "entering Wlz2DContains %f,%f\n", x,y);
   fflush(stderr);
   */

   if(obj->type != WLZ_2D_DOMAINOBJ) return (NULL);

   /* get array of domains */
   if(obj != NULL) {
      errNum = WlzLabel(obj,
                        &nobjs,
                        &objArray,
                        maxNobjs,
                        0,
                        connectivity);
   }
   /*
   fprintf(stderr, "got array of %d objects\n", nobjs);
   fflush(stderr);
   */

   /* select the required domain */
   /* ie the one which contains clicked point */

   if((errNum == WLZ_ERR_NONE) && (nobjs > 0)) {
      for(i=0; i<nobjs; i++) {
	 /*
	 fprintf(stderr, "checking domain # %d\n", i);
	 fflush(stderr);
	 */
	 if(WlzInsideDomain(objArray[i],
			    0.0,
			    y,
			    x,
			    &errNum)) {
	    if(errNum == WLZ_ERR_NONE) {
	       found = 1;
	       /*
	       fprintf(stderr, "domain # %d contains point\n", i);
	       fflush(stderr);
	       */
	       break;
	    } else {
	       (void )fprintf(stderr,
	                      "WlzInsideDomain, Wlz error: %d\n",
			      (int )errNum);
	       fflush(stderr);
	    }
	 } else {
	    WlzFreeObj(objArray[i]);
	 }
      }
      if((found == 1) && (errNum == WLZ_ERR_NONE)) {
	 /* retObj = objArray[i]; */
	 retObj = WlzCopyObject(objArray[i], &errNum);
	 WlzFreeObj(objArray[i]);
	 if(errNum != WLZ_ERR_NONE) {
	    (void )fprintf(stderr,
	                   "WlzCopyObject, Wlz error: %d\n",
			   (int )errNum);
	    fflush(stderr);
	 }
      }
   }

   *dstErr = errNum;
   /*
   fprintf(stderr, "leaving Wlz2DContains\n");
   fflush(stderr);
   */
   return retObj;
}
Пример #3
0
void warpSetSignalDomain(
  WlzIVertex2	*selVtx)
{
  WlzErrorNum	errNum=WLZ_ERR_NONE;
  WlzPixelV	threshV, threshV1;
  WlzObject	*obj, *obj1;
  WlzUInt	combineMode;

  /* image processing sequence */
  if( warpGlobals.sgnlThreshObj == NULL ){
    warpSetSignalThreshObj();
  }
  if( warpGlobals.sgnlThreshObj ){
    obj1 = WlzAssignObject(warpGlobals.sgnlThreshObj, &errNum);
  }
  else {
    return;
  }

  /* threshold the resultant image */
  if( errNum == WLZ_ERR_NONE ){
    switch( warpGlobals.thresholdType ){
    case WLZ_RGBA_THRESH_NONE:
      break;

    case WLZ_RGBA_THRESH_SINGLE:
      threshV.type = WLZ_GREY_INT;
      threshV.v.inv = warpGlobals.threshRangeLow;
      if( obj1 ){
	/* clear signal object */
	if( warpGlobals.sgnlObj ){
	  WlzFreeObj(warpGlobals.sgnlObj);
	}
	  
	if((obj = WlzThreshold(obj1, threshV, WLZ_THRESH_HIGH, &errNum)) && (WlzVolume(obj, &errNum) > 0)){
	  obj = WlzAssignObject(obj, &errNum);
	  WlzFreeObj(obj1);
	  threshV.v.inv = warpGlobals.threshRangeHigh + 1;
	  if((obj1 = WlzThreshold(obj, threshV, WLZ_THRESH_LOW, &errNum)) && (WlzVolume(obj1, &errNum) > 0)){
	    warpGlobals.sgnlObj = WlzAssignObject(obj1, &errNum);
	  }
	  else {
	    if( obj1 ){
	      WlzFreeObj(obj1);
	    }
	    warpGlobals.sgnlObj = NULL;
	  }
	  WlzFreeObj(obj);
	}
	else {
	  if( obj ) {
	    WlzFreeObj(obj);
	  }
	  WlzFreeObj(obj1);
	  warpGlobals.sgnlObj = NULL;
	}
      }
      break;

    case WLZ_RGBA_THRESH_MULTI:
      /* clear signal object */
      if( warpGlobals.sgnlObj ){
	WlzFreeObj(warpGlobals.sgnlObj);
      }

      /* set the thresholds and combine mode */
      threshV.type = WLZ_GREY_RGBA;
      WLZ_RGBA_RGBA_SET(threshV.v.rgbv,
			warpGlobals.threshRangeRGBLow[0],
			warpGlobals.threshRangeRGBLow[1],
			warpGlobals.threshRangeRGBLow[2],
			255);
      threshV1.type = WLZ_GREY_RGBA;
      WLZ_RGBA_RGBA_SET(threshV1.v.rgbv,
			warpGlobals.threshRangeRGBHigh[0],
			warpGlobals.threshRangeRGBHigh[1],
			warpGlobals.threshRangeRGBHigh[2],
			255);
      WLZ_RGBA_RGBA_SET(combineMode,
			WLZ_BO_AND, WLZ_BO_AND, WLZ_BO_AND, 255);

      /* use multi-threshold */
      if((obj = WlzRGBAMultiThreshold(obj1, threshV, threshV1,
				      combineMode, &errNum))){
	if( WlzIsEmpty(obj, &errNum) ){
	    WlzFreeObj(obj);
	    warpGlobals.sgnlObj = NULL;
	} else {
	    warpGlobals.sgnlObj = WlzAssignObject(obj, &errNum);
	}
      }
      else {
	warpGlobals.sgnlObj = NULL;
      }
      WlzFreeObj(obj1);
      break;

    case WLZ_RGBA_THRESH_BOX:
      /* clear signal object */
      if( warpGlobals.sgnlObj ){
	WlzFreeObj(warpGlobals.sgnlObj);
      }

      /* use box-threshold */
      if((obj = WlzRGBABoxThreshold(obj1,
				    warpGlobals.lowRGBPoint,
				    warpGlobals.highRGBPoint,
				    &errNum))){
	if( WlzIsEmpty(obj, &errNum) ){
	    WlzFreeObj(obj);
	    warpGlobals.sgnlObj = NULL;
	} else {
	    warpGlobals.sgnlObj = WlzAssignObject(obj, &errNum);
	}
      }
      else {
	warpGlobals.sgnlObj = NULL;
      }
      WlzFreeObj(obj1);	  
      break;

    case WLZ_RGBA_THRESH_SLICE:
      /* clear signal object */
      if( warpGlobals.sgnlObj ){
	WlzFreeObj(warpGlobals.sgnlObj);
      }

      /* use slice-threshold */
      if((obj = WlzRGBASliceThreshold(obj1,
				      warpGlobals.lowRGBPoint,
				      warpGlobals.highRGBPoint,
				      &errNum))){
	if( WlzIsEmpty(obj, &errNum) ){
	    WlzFreeObj(obj);
	    warpGlobals.sgnlObj = NULL;
	} else {
	    warpGlobals.sgnlObj = WlzAssignObject(obj, &errNum);
	}
      }
      else {
	warpGlobals.sgnlObj = NULL;
      }
      WlzFreeObj(obj1);	  
      break;

    case WLZ_RGBA_THRESH_SPHERE:
      /* clear signal object */
      if( warpGlobals.sgnlObj ){
	WlzFreeObj(warpGlobals.sgnlObj);
      }

      /* use Ellipsoid-threshold */
      if((obj = WlzRGBAEllipsoidThreshold(obj1,
					  warpGlobals.lowRGBPoint,
					  warpGlobals.highRGBPoint,
					  warpGlobals.colorEllipseEcc,
					  &errNum))){
	if( WlzIsEmpty(obj, &errNum) ){
	    WlzFreeObj(obj);
	    warpGlobals.sgnlObj = NULL;
	} else {
	    warpGlobals.sgnlObj = WlzAssignObject(obj, &errNum);
	}
      }
      else {
	warpGlobals.sgnlObj = NULL;
      }
      WlzFreeObj(obj1);	  
      break;

    default:
      errNum = WLZ_ERR_PARAM_DATA;
      if( obj1 ){
	WlzFreeObj(obj1);
      }
      if( warpGlobals.sgnlObj ){
	WlzFreeObj(warpGlobals.sgnlObj);
	warpGlobals.sgnlObj = NULL;
      }
      break;
    }
  }

  /* check for local mode */
  if( warpGlobals.sgnlObj && !warpGlobals.globalThreshFlg ){
    if( selVtx != NULL ){
      warpGlobals.globalThreshVtx = *selVtx;
    }
    /* extract a local domain if the vertex is sensible */
    if( warpGlobals.globalThreshVtx.vtX != -10000 ){
      WlzObject	**objs=NULL;
      int	i, numObjs;
      double	x, y;
      obj1 = NULL;
      x = warpGlobals.globalThreshVtx.vtX;
      y = warpGlobals.globalThreshVtx.vtY;
      errNum = WlzLabel(warpGlobals.sgnlObj, &numObjs, &objs, 8192, 0,
			WLZ_4_CONNECTED);
      if( (errNum == WLZ_ERR_INT_DATA) && (numObjs == 8192) ){
	WlzObject	*tmpObj1, *tmpObj2;
	WlzDomain	domain;
	WlzValues	values;

	/* try again, smaller domain */
	for(i=0; i < numObjs; i++){
	  WlzFreeObj( objs[i] );
	}
	AlcFree((void *) objs);
	objs = NULL;
	numObjs = 0;
	domain.i = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_RECT,
					 y - 80, y + 80,
					 x - 80, x + 80, &errNum);
	values.core = NULL;
	if((tmpObj1 = WlzMakeMain(warpGlobals.sgnlObj->type, domain, values,
				  NULL, NULL, &errNum))){
	  if((tmpObj2 = WlzIntersect2(warpGlobals.sgnlObj, tmpObj1, &errNum))){
	    tmpObj2->values = WlzAssignValues(warpGlobals.sgnlObj->values, NULL);
	    errNum = WlzLabel(warpGlobals.sgnlObj, &numObjs, &objs, 8192, 0,
			      WLZ_4_CONNECTED);
	    WlzFreeObj(tmpObj2);
	    if((errNum == WLZ_ERR_INT_DATA) && (numObjs == 8192) ){
	      errNum = WLZ_ERR_NONE;
	    }
	  }
	  WlzFreeObj(tmpObj1);
	}
	
      }
      if( errNum == WLZ_ERR_NONE ){

	for(i=0; i < numObjs; i++){
	  if( WlzInsideDomain( objs[i], 0.0, y, x, NULL ) ){
	    obj1 = WlzMakeMain(objs[i]->type,
			       objs[i]->domain,
			       objs[i]->values,
			       NULL, NULL, NULL);
	    obj1 = WlzAssignObject(obj1, NULL);
	  }
	  WlzFreeObj( objs[i] );
	}
	AlcFree((void *) objs);
      }
      if( obj1 ){
	WlzFreeObj(warpGlobals.sgnlObj);
	warpGlobals.sgnlObj = obj1;
      }
    }
    else {
      WlzFreeObj(warpGlobals.sgnlObj);
      warpGlobals.sgnlObj = NULL;
    }
  }

  /* check for increment mode */
  if( warpGlobals.incrThreshFlg && sgnlIncrObj() ){
    if( warpGlobals.sgnlObj ){
      if((obj1 = WlzUnion2(warpGlobals.sgnlObj, sgnlIncrObj(),
			   &errNum))){
	WlzFreeObj(warpGlobals.sgnlObj);
	warpGlobals.sgnlObj = WlzAssignObject(obj1, &errNum);
      }
    }
    else {
      warpGlobals.sgnlObj = WlzAssignObject(sgnlIncrObj(),
					    &errNum);
    }
  }

  if( errNum != WLZ_ERR_NONE ){
    MAPaintReportWlzError(globals.topl, "warpSetSignalDomain", errNum);
  }
  return;
}
Пример #4
0
int main(
  int   argc,
  char  **argv)
{
  WlzObject     	*obj1, *obj2;
  int			verboseFlg=0;
  char			*nameStr;
  double		xsize=1.0, ysize=1.0, zsize=1.0;
  int			i, j;
  double		dist, minDist;
  double		dist1, dist2, dist3, dist4;
  int			numVtxs1, numVtxs2;
  WlzDVertex3		*edgeVtxs1, *edgeVtxs2;
  WlzDVertex3		cmVtx1, cmVtx2;
  double		vol1, vol2;
  double		mass1, mass2;
  WlzErrorNum	errNum=WLZ_ERR_NONE;

  /* check input arguments */
  nameStr = argv[0];
  argv++;
  argc--;
  while( argc > 0 )
  {
    switch( argv[0][1] )
    {
    case 'h':
      usage(nameStr);
      return 0;

    case 'v':
      verboseFlg = 1;
      break;

    default:
      usage(nameStr);
      return 1;
    }
    argc--;
    argv++;
  }

  /* read the objects */
  if((obj1 = WlzReadObj(stdin, NULL)) &&
     (obj2 = WlzReadObj(stdin, NULL)) ){

    if( obj1->type != obj2->type ){
      return 1;
    }
    if((obj1->type != WLZ_2D_DOMAINOBJ) &&
       (obj1->type != WLZ_3D_DOMAINOBJ)){
      usage(nameStr);
      return 1;
    }

    /* get edge vertices */
    numVtxs1 = WlzEdgeVertices(obj1, &edgeVtxs1, NULL);
    numVtxs2 = WlzEdgeVertices(obj2, &edgeVtxs2, NULL);

    /* renormalise with pixel sizes */
    if( obj1->type == WLZ_3D_DOMAINOBJ ){
      xsize = obj1->domain.p->voxel_size[0];
      ysize = obj1->domain.p->voxel_size[1];
      zsize = obj1->domain.p->voxel_size[2];

      for(i=0; i < numVtxs1; i++){
	edgeVtxs1[i].vtX *= xsize;
	edgeVtxs1[i].vtY *= ysize;
	edgeVtxs1[i].vtZ *= zsize;
      }
      for(i=0; i < numVtxs2; i++){
	edgeVtxs2[i].vtX *= xsize;
	edgeVtxs2[i].vtY *= ysize;
	edgeVtxs2[i].vtZ *= zsize;
      }
    }

    /* get centre of mass vertices */
    if( obj1->type == WLZ_2D_DOMAINOBJ ){
      WlzDVertex2	vtx2;

      vtx2 = WlzCentreOfMass2D(obj1, 0, &mass1, &errNum);
      cmVtx1.vtX = vtx2.vtX;
      cmVtx1.vtY = vtx2.vtY;
      cmVtx1.vtZ = 0.0;

      vtx2 = WlzCentreOfMass2D(obj2, 0, &mass2, &errNum);
      cmVtx2.vtX = vtx2.vtX;
      cmVtx2.vtY = vtx2.vtY;
      cmVtx2.vtZ = 0.0;
    }
    else {
      cmVtx1 = WlzCentreOfMass3D(obj1, 0, &mass1, &errNum);
      cmVtx2 = WlzCentreOfMass3D(obj2, 0, &mass2, &errNum);
      cmVtx1.vtX *= xsize;
      cmVtx1.vtY *= ysize;
      cmVtx1.vtZ *= zsize;
      cmVtx2.vtX *= xsize;
      cmVtx2.vtY *= ysize;
      cmVtx2.vtZ *= zsize;
    }

    /* find distance between centres of mass */
    dist1 = vtxDist(cmVtx1, cmVtx2);

    /* find cm 1 to surface 2 dist */
    if( numVtxs2 > 0 ){
      minDist = vtxDist(cmVtx1, edgeVtxs2[0]);
      for(j=0; j < numVtxs2; j++){
	dist = vtxDist(cmVtx1, edgeVtxs2[j]);
	if( dist < minDist ){
	  minDist = dist;
	}
      }
      dist2 = minDist;
      if( !WlzInsideDomain(obj2, cmVtx1.vtZ/zsize,
			   cmVtx1.vtY/ysize, cmVtx1.vtX/xsize,
			   &errNum) ){
	dist2 *= -1.0;
      }
    }
    else {
      dist2 = 0.0;
    }

    /* find surface 1 to cm 2 dist */
    if( numVtxs1 > 0 ){
      minDist = vtxDist(cmVtx2, edgeVtxs1[0]);
      for(j=0; j < numVtxs1; j++){
	dist = vtxDist(cmVtx2, edgeVtxs1[j]);
	if( dist < minDist ){
	  minDist = dist;
	}
      }
      dist3 = minDist;
      if( !WlzInsideDomain(obj1, cmVtx2.vtZ/zsize,
			   cmVtx2.vtY/ysize, cmVtx2.vtX/xsize,
			   &errNum) ){
	dist3 *= -1.0;
      }
    }
    else {
      dist3 = 0.0;
    }

    /* find min distance between surfaces */
    if( (numVtxs1 > 0) && (numVtxs2 > 0) ){
      minDist = vtxDist(edgeVtxs1[0], edgeVtxs2[0]);
      for(i=0; i < numVtxs1; i++){
	for(j=0; j < numVtxs2; j++){
	  dist = vtxDist(edgeVtxs1[i], edgeVtxs2[j]);
	  if( dist < minDist ){
	    minDist = dist;
	  }
	}
      }
      dist4 = minDist;
    }
    else {
      dist4 = 0.0;
    }

    /* get the volumes */
    if( obj1->type == WLZ_2D_DOMAINOBJ ){
      vol1 = WlzArea(obj1, &errNum);
      vol2 = WlzArea(obj2, &errNum);
    }
    else {
      vol1 = WlzVolume(obj1, &errNum);
      vol2 = WlzVolume(obj2, &errNum);
      vol1 *= xsize*ysize*zsize;
      vol2 *= xsize*ysize*zsize;
    }

    /* print it */
    fprintf(stdout, "%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n",
	    vol1, vol2, mass1, mass2, dist1, dist2, dist3, dist4);
  }

  return 0;
}
Пример #5
0
/*! 
* \return       projection object
* \ingroup      WlzTransform
* \brief        Use the view transform to define a projection from
*		3D to 2D. Currently only the domain is projected as
*		an opaque shadow.
*		This is old code temporarily kept for compatibility.
* \param    obj	source 3D object
* \param    viewStr	view structure defining the projection
* \param    intFunc	grey-value summation function
* \param    intFuncData data to be passed to the integration function
* \param    dstErr	error return
*/
WlzObject *WlzGetProjectionFromObject(
  WlzObject		*obj,
  WlzThreeDViewStruct 	*viewStr,
  Wlz3DProjectionIntFn 	intFunc,
  void			*intFuncData,
  WlzErrorNum		*dstErr)
{
  WlzObject		*rtnObj=NULL,
  			*obj1;
  WlzThreeDViewStruct	*viewStr1=NULL;
  WlzDomain		domain;
  WlzValues		values;
  WlzGreyType		srcGType = WLZ_GREY_UBYTE,
  			dstGType = WLZ_GREY_UBYTE;
  WlzPixelV		pixval;
  WlzPixelP		pixptr;
  WlzIntervalWSpace	iwsp;
  WlzGreyWSpace		gwsp;
  WlzGreyValueWSpace	*gVWSp = NULL;
  WlzDVertex3		vtx, vtx1;
  double		x, y, z;
  double		*s_to_x=NULL;
  double		*s_to_y=NULL;
  double		*s_to_z=NULL;
  int			k, xp, yp, s, sp;
  int			length = 0, size = 0, occupiedFlg;
  WlzErrorNum 	errNum=WLZ_ERR_NONE;

  /* check inputs */
  if( obj == NULL ){
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if( obj->type != WLZ_3D_DOMAINOBJ ){
    errNum = WLZ_ERR_OBJECT_TYPE;
  }
  else if( obj->domain.core == NULL ){
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if( obj->domain.core->type != WLZ_PLANEDOMAIN_DOMAIN ){
    errNum = WLZ_ERR_DOMAIN_TYPE;
  }

  if( (errNum == WLZ_ERR_NONE) && (viewStr == NULL) ){
    errNum = WLZ_ERR_OBJECT_NULL;
  }

  /* create new view transform */
  if( errNum == WLZ_ERR_NONE ){
    if((viewStr1 = WlzMake3DViewStruct(WLZ_3D_VIEW_STRUCT, &errNum)) != NULL){
      /* need to worry about fixed line mode here sometime */
      viewStr1->fixed = viewStr->fixed;
      viewStr1->theta = viewStr->theta;
      viewStr1->phi = viewStr->phi;
      viewStr1->zeta = viewStr->zeta;
      viewStr1->dist = viewStr->dist;
      viewStr1->scale = viewStr->scale;
      viewStr1->voxelSize[0] = viewStr->voxelSize[0];
      viewStr1->voxelSize[1] = viewStr->voxelSize[1];
      viewStr1->voxelSize[2] = viewStr->voxelSize[2];
      viewStr1->voxelRescaleFlg = viewStr->voxelRescaleFlg;
      viewStr1->interp = viewStr->interp;
      viewStr1->view_mode = viewStr->view_mode;
      viewStr1->up = viewStr->up;

      /* now intialize it */
      /* could optimise by setting fixed point to object centre */
      if( (errNum = WlzInit3DViewStruct(viewStr1, obj)) != WLZ_ERR_NONE ){
	WlzFree3DViewStruct(viewStr1);
	viewStr1 = NULL;
      }
    }
  }

  /* set up orthogonal line parameters & luts */
  if( errNum == WLZ_ERR_NONE ){
    length = WLZ_NINT(viewStr1->maxvals.vtZ) -
      WLZ_NINT(viewStr1->minvals.vtZ) + 1;
    s_to_x = (double *) AlcMalloc(sizeof(double) * length );
    s_to_y = (double *) AlcMalloc(sizeof(double) * length );
    s_to_z = (double *) AlcMalloc(sizeof(double) * length );

    /* transform a perpendicular vector */
    vtx.vtX = 0.0;
    vtx.vtY = 0.0;
    vtx.vtZ = 1.0;
    Wlz3DSectionTransformInvVtx(&vtx, viewStr1);
    vtx1.vtX = 0.0;
    vtx1.vtY = 0.0;
    vtx1.vtZ = 0.0;
    Wlz3DSectionTransformInvVtx(&vtx1, viewStr1);
    vtx.vtX -= vtx1.vtX;
    vtx.vtY -= vtx1.vtY;
    vtx.vtZ -= vtx1.vtZ;

    /* assign lut values */
    s = (int )(WLZ_NINT(viewStr1->minvals.vtZ) - viewStr1->dist);
    for(sp=0; sp < length; sp++, s++){
      s_to_x[sp] = s * vtx.vtX;
      s_to_y[sp] = s * vtx.vtY;
      s_to_z[sp] = s * vtx.vtZ;
    }
  }

  /* if there is an integration function then allocate space for
     the grey-level array */
  if( (errNum == WLZ_ERR_NONE) && (intFunc) ){
    srcGType = WlzGreyTypeFromObj(obj, &errNum);
    switch( srcGType ){
    case WLZ_GREY_LONG:
      size = sizeof(WlzLong)*length;
      break;
    case WLZ_GREY_INT:
      size = sizeof(int)*length;
      break;
    case WLZ_GREY_SHORT:
      size = sizeof(short)*length;
      break;
    case WLZ_GREY_UBYTE:
      size = sizeof(WlzUByte)*length;
      break;
    case WLZ_GREY_FLOAT:
      size = sizeof(float)*length;
      break;
    case WLZ_GREY_DOUBLE:
      size = sizeof(double)*length;
      break;
    case WLZ_GREY_RGBA:
      size = sizeof(int)*length;
      break;
    default:
      errNum = WLZ_ERR_GREY_TYPE;
      break;
    }
    if( (pixptr.p.inp = (int *) AlcMalloc(size)) == NULL ){
      errNum = WLZ_ERR_MEM_ALLOC;
    }
    pixptr.type = srcGType;

    /* set up the grey-value workspace for random access */
    gVWSp = WlzGreyValueMakeWSp(obj, &errNum);
  }

  /* create rectangular projection image */
  if( errNum == WLZ_ERR_NONE ){
    if((domain.i = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_RECT,
				     WLZ_NINT(viewStr1->minvals.vtY),
				     WLZ_NINT(viewStr1->maxvals.vtY),
				     WLZ_NINT(viewStr1->minvals.vtX),
				     WLZ_NINT(viewStr1->maxvals.vtX),
					 &errNum)) != NULL){
      values.core = NULL;
      if((rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domain, values, NULL, NULL,
			       &errNum)) != NULL){
	/* note the grey-values required are determined by the integration
	   function. Here we use WlzUByte and reset later if needed */
	dstGType = WLZ_GREY_UBYTE;
	pixval.type = WLZ_GREY_UBYTE;
	pixval.v.ubv = (WlzUByte )0;
	if((values.v = WlzNewValueTb(rtnObj,
				     WlzGreyTableType(WLZ_GREY_TAB_RECT,
						      dstGType, NULL),
				     pixval, &errNum)) != NULL){
	  rtnObj->values = WlzAssignValues(values, &errNum);
	}
	else {
	  WlzFreeObj(rtnObj);
	  rtnObj = NULL;
	}
      }
      else {
	WlzFreeDomain(domain);
	domain.core = NULL;
      }
    }
  }

  /* scan image setting values */
  if( errNum == WLZ_ERR_NONE ){
    errNum = WlzInitGreyScan(rtnObj, &iwsp, &gwsp);
  }
  if( errNum == WLZ_ERR_NONE ){
    while( (errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE ){
      yp = iwsp.linpos - WLZ_NINT(viewStr1->minvals.vtY);
      for(k=iwsp.lftpos; k <= iwsp.rgtpos; k++){
	xp = k - WLZ_NINT(viewStr1->minvals.vtX);
	vtx.vtX = viewStr1->xp_to_x[xp] + viewStr1->yp_to_x[yp];
	vtx.vtY = viewStr1->xp_to_y[xp] + viewStr1->yp_to_y[yp];
	vtx.vtZ = viewStr1->xp_to_z[xp] + viewStr1->yp_to_z[yp];

	/* get the projection values */
	/* if no function then just check for occupancy */
	if( intFunc == NULL ){
	  occupiedFlg = 0;
	  sp = (int )(viewStr1->dist - WLZ_NINT(viewStr1->minvals.vtZ));
	  for(; !occupiedFlg && (sp < length); sp++){
	    x = vtx.vtX + s_to_x[sp];
	    y = vtx.vtY + s_to_y[sp];
	    z = vtx.vtZ + s_to_z[sp];
	    if( WlzInsideDomain(obj, z, y, x, &errNum) ){
	      occupiedFlg = 1;
	    }
	  }
	  sp = (int )(viewStr1->dist - WLZ_NINT(viewStr1->minvals.vtZ) - 1);
	  for(; !occupiedFlg && (sp >= 0); sp--){
	    x = vtx.vtX + s_to_x[sp];
	    y = vtx.vtY + s_to_y[sp];
	    z = vtx.vtZ + s_to_z[sp];
	    if( WlzInsideDomain(obj, z, y, x, &errNum) ){
	      occupiedFlg = 1;
	    }
	  }

	  /* set the integrated value - only WlzUByte at the moment */
	  *(gwsp.u_grintptr.ubp) = (WlzUByte )occupiedFlg;
	  gwsp.u_grintptr.ubp++;
	}
	/* use integration function */
	else {
	  /* set array of pixel values */
	  for(sp=0; sp < length; sp++){
	    x = vtx.vtX + s_to_x[sp];
	    y = vtx.vtY + s_to_y[sp];
	    z = vtx.vtZ + s_to_z[sp];
	    WlzGreyValueGet(gVWSp, WLZ_NINT(z), WLZ_NINT(y),
			    WLZ_NINT(x));
	    switch( srcGType ){
	    case WLZ_GREY_LONG:
	      pixptr.p.lnp[sp] = gVWSp->gVal[0].lnv;
	      break;
	    case WLZ_GREY_INT:
	      pixptr.p.inp[sp] = gVWSp->gVal[0].inv;
	      break;
	    case WLZ_GREY_SHORT:
	      pixptr.p.shp[sp] = gVWSp->gVal[0].shv;
	      break;
	    case WLZ_GREY_UBYTE:
	      pixptr.p.ubp[sp] = gVWSp->gVal[0].ubv;
	      break;
	    case WLZ_GREY_FLOAT:
	      pixptr.p.flp[sp] = gVWSp->gVal[0].flv;
	      break;
	    case WLZ_GREY_DOUBLE:
	      pixptr.p.dbp[sp] = gVWSp->gVal[0].dbv;
	      break;
	    case WLZ_GREY_RGBA:
	      pixptr.p.rgbp[sp] = gVWSp->gVal[0].rgbv;
	      break;
	    default:
	      errNum = WLZ_ERR_GREY_TYPE;
	      break;
	    }
	  }
	  /* call integration function and seet value */
	  intFunc(pixptr, length, (int )(viewStr1->dist -
		                         WLZ_NINT(viewStr1->minvals.vtZ)),
		  intFuncData, &errNum);
	}
      }
    }
    (void )WlzEndGreyScan(&iwsp, &gwsp);
    if(errNum == WLZ_ERR_EOO)	   /* Reset error from end of intervals */ 
    {
      errNum = WLZ_ERR_NONE;
    }

    /* if no integration function then threshold - binary only */
    if( intFunc == NULL ){
      pixval.v.ubv = 1;
      rtnObj = WlzAssignObject(rtnObj, NULL);
      if((obj1 = WlzThreshold(rtnObj, pixval, WLZ_THRESH_HIGH,
                              &errNum)) != NULL){
	WlzFreeObj(rtnObj);
	values.core = NULL;
	rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, obj1->domain, values, NULL, NULL,
			     &errNum);
	WlzFreeObj(obj1);
      }
      else {
	WlzFreeObj(rtnObj);
	rtnObj = NULL;
      }
    }
  }

  /* clear space */
  if( viewStr1 ){
    errNum = WlzFree3DViewStruct(viewStr1);
  }
  if( s_to_x ){
    AlcFree( s_to_x );
  }
  if( s_to_y ){
    AlcFree( s_to_y );
  }
  if( s_to_z ){
    AlcFree( s_to_z );
  }

  /* check error and return */
  if( dstErr ){
    *dstErr = errNum;
  }
  return rtnObj;
}