예제 #1
0
void   imageEdgeTrackCurrentDomainCb(
  Widget	w,
  XtPointer	client_data,
  XtPointer	call_data)
{
  ThreeDViewStruct	*view_struct = (ThreeDViewStruct *) client_data;
  WlzObject		*domain;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  /* get the current domain */
  if(view_struct->curr_domain[globals.current_domain] &&
     (WlzArea(view_struct->curr_domain[globals.current_domain], &errNum) > 0)){
    domain = WlzAssignObject(view_struct->curr_domain[globals.current_domain],
			     NULL);
    imageEdgeTrackDomain(view_struct, globals.current_domain, domain);
    WlzFreeObj(domain);
  }

  if( errNum != WLZ_ERR_NONE ){
    MAPaintReportWlzError(globals.topl, "imageEdgeTrackCurrentDomainCb", errNum);
  }
  return;
}
예제 #2
0
static int WlzSize(
  WlzObject	*obj,
  WlzErrorNum	*dstErr)
{
  int	size;
  WlzErrorNum	errNum=WLZ_ERR_NONE;

  if( obj ){
    switch(obj->type){
    case WLZ_2D_DOMAINOBJ:
      size = WlzArea(obj, &errNum);
      break;

    case WLZ_3D_DOMAINOBJ:
      size = WlzVolume(obj, &errNum);
      break;

    case WLZ_EMPTY_OBJ:
      size = 0;
      break;

    default:
      size = -1;
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }
  else {
    size = -1;
    errNum = WLZ_ERR_OBJECT_NULL;
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return size;
}
예제 #3
0
/*! 
* \ingroup      WlzDomainOps
* \brief        Calculate the volume of the input 3D domain object.
*
* \return       Volume of input 3D object, -1 on error.
* \param    obj	Input object pointer.
* \param    wlzErr	Error return.
* \par      Source:
*                WlzVolume.c
*/
WlzLong WlzVolume(
  WlzObject 	*obj,
  WlzErrorNum 	*wlzErr)
{
  WlzObject		*tmpobj;
  WlzPlaneDomain	*pldom;
  WlzDomain		domain;
  WlzValues		values;
  WlzLong		vol = -1,
  			p;
  WlzErrorNum		errNum = WLZ_ERR_NONE; 

  /* check the object */
  if( obj == NULL )
  {
    if(*wlzErr)
    {
      *wlzErr = WLZ_ERR_OBJECT_NULL;
    }
    return( -1 );
  }

  switch( obj->type ){

  case WLZ_2D_DOMAINOBJ:
    return(WlzArea(obj, wlzErr));

  case WLZ_3D_DOMAINOBJ:
    if( obj->domain.core == NULL ){
      if(*wlzErr)
      {
        *wlzErr = WLZ_ERR_DOMAIN_NULL;
      }
      return -1;
    }

    if( obj->domain.core->type != WLZ_PLANEDOMAIN_DOMAIN )
    {
      if(*wlzErr)
      {
        *wlzErr = WLZ_ERR_DOMAIN_TYPE;
      }
      return -1;
    }
    break;

  case WLZ_EMPTY_OBJ:
    if(*wlzErr)
    {
      *wlzErr = WLZ_ERR_NONE;
    }
    return 0;

  default:
    if(wlzErr)
    {
      *wlzErr = WLZ_ERR_OBJECT_TYPE;
    }
    return( -1 );

  }

  /* scan through planes calculating the area */
  vol = 0;
  values.core = NULL;
  pldom = obj->domain.p;
  for(p=0; (p <= (pldom->lastpl - pldom->plane1)) && (errNum == WLZ_ERR_NONE);
      p++){
    domain = pldom->domains[p];
    if( domain.core ){
      tmpobj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domain, values, NULL, NULL,
      			   &errNum);
      if(tmpobj) {
	vol += WlzArea(tmpobj , &errNum);
	WlzFreeObj( tmpobj );
      }
    }
  }
  if(errNum != WLZ_ERR_NONE)
  {
    vol = -1;
  }
  if(wlzErr)
  {
    *wlzErr = errNum;
  }

  return( vol );
}
예제 #4
0
/*! 
* \ingroup      WlzAllocation
* \brief        Make in interval values table to match the input object
The table will have linkcount set to zero.
*
* \return       New interval values table.
* \param    type	Required table type.
* \param    obj	Input object.
* \param    bckgrnd	Values table background value.
* \param    dstErr	Error return.
* \par Constraints
 The woolz object type must resolve to WLZ_GREY_TAB_INTL using
 WlzGreyTableTypeToTableType()or an error will be reported and NULL
 returned.  For historical reasons
 the type encodes the table type as well as the grey-value type.
 
* \par      Source:
*                WlzMakeIntervalValues.c
*/
WlzIntervalValues *
WlzMakeIntervalValues(WlzObjectType	type,
		      WlzObject 	*obj,
		      WlzPixelV		bckgrnd,
		      WlzErrorNum	*dstErr)
{
  WlzValues 		v;
  WlzValueIntervalLine 	*vil;
  WlzValueLine 		*val;
  WlzGreyP 		g;
  WlzIntervalWSpace 	iwsp;
  WlzIntervalDomain 	*idom;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  /* check the values table type */
  v.i = NULL;
  (void) WlzGreyTableTypeToTableType(type, &errNum);
  if( errNum == WLZ_ERR_NONE ){
    (void) WlzGreyTableTypeToGreyType(type, &errNum);
  }

  /* check the object */
  if( (errNum == WLZ_ERR_NONE) && (obj == NULL) ){
    errNum = WLZ_ERR_OBJECT_NULL;
  }

  if( errNum == WLZ_ERR_NONE ){
    switch( obj->type ){

    case WLZ_2D_DOMAINOBJ:
      if( obj->domain.core == NULL ){
	errNum = WLZ_ERR_DOMAIN_NULL;
	break;
      }
      idom = obj->domain.i;
      break;

    case WLZ_EMPTY_OBJ:
    default:
      errNum = WLZ_ERR_DOMAIN_TYPE;
      break;
    }
  }

  /*
   * allocate space for basic, per line and per interval structures
   */
  if((errNum == WLZ_ERR_NONE) &&
     ((v.i = (WlzIntervalValues *) 
      AlcCalloc(sizeof(WlzIntervalValues)
		+ (idom->lastln - idom->line1 + 1)
		* sizeof(WlzValueIntervalLine) +
		WlzIntervalCount(idom, NULL) * sizeof(WlzValueLine), 1))
     == NULL) ){
    errNum = WLZ_ERR_MEM_ALLOC;
  }

  if( errNum == WLZ_ERR_NONE ){
    vil = (WlzValueIntervalLine *) (v.i + 1);
    val = (WlzValueLine *) (vil + idom->lastln - idom->line1 + 1);
    v.i->bckgrnd = bckgrnd;
    switch( WlzGreyTableTypeToGreyType(type, NULL) ){

    case WLZ_GREY_INT:
      g.inp = (int *) AlcCalloc(WlzArea(obj, NULL), sizeof(int));
      break;

    case WLZ_GREY_SHORT:
      g.shp = (short *) AlcCalloc(WlzArea(obj, NULL), sizeof(short));
      break;

    case WLZ_GREY_UBYTE:
      g.ubp = (WlzUByte *) AlcCalloc(WlzArea(obj, NULL), sizeof(WlzUByte));
      break;

    case WLZ_GREY_FLOAT:
      g.flp = (float *) AlcCalloc(WlzArea(obj, NULL), sizeof(float));
      break;

    case WLZ_GREY_DOUBLE:
      g.dbp = (double *) AlcCalloc(WlzArea(obj, NULL), sizeof(double));
      break;

    case WLZ_GREY_RGBA:
      g.rgbp = (WlzUInt *) AlcCalloc(WlzArea(obj, NULL), sizeof(WlzUInt));
      break;

    default:
      WlzFreeValues( v );
      v.i = NULL;
      errNum = WLZ_ERR_GREY_TYPE;
      break;
    }
  }
  if( (errNum == WLZ_ERR_NONE) && (g.inp == NULL) ){
    WlzFreeValues( v );
    v.i = NULL;
    errNum = WLZ_ERR_MEM_ALLOC;
  }

  /*
   * fill in structure values and initialise scanning
   */
  if( errNum == WLZ_ERR_NONE ){
    v.i->type = type;
    v.i->freeptr = AlcFreeStackPush(v.i->freeptr, (void *)g.inp, NULL);
    v.i->line1 = idom->line1;
    v.i->lastln = idom->lastln;
    v.i->kol1 = idom->kol1;
    v.i->width = idom->lastkl - idom->kol1 + 1;
    v.i->vil = vil;
    v.i->linkcount = 0;
    v.i->original_table.core = NULL;
    vil--;
    if((errNum = WlzInitRasterScan(obj, &iwsp,
    				   WLZ_RASTERDIR_ILIC)) != WLZ_ERR_NONE ){
      WlzFreeValues( v );
      v.i = NULL;
    }
  }

  /*
   * fill in the line and interval structures,
     note grey-type already checked.
   */
  if( errNum == WLZ_ERR_NONE ){
    while((errNum == WLZ_ERR_NONE) &&
          (errNum = WlzNextInterval(&iwsp)) == WLZ_ERR_NONE){
      if (iwsp.nwlpos != 0) {
	vil += iwsp.nwlpos;
	vil->vtbint = val;
      }
      vil->nintvs++;
      val->vkol1 = iwsp.lftpos - v.i->kol1;
      val->vlastkl = iwsp.rgtpos - v.i->kol1;
      switch( WlzGreyTableTypeToGreyType(type, NULL) ){

      case WLZ_GREY_INT:
	val->values.inp = g.inp;
	g.inp += iwsp.colrmn;
	break;

      case WLZ_GREY_SHORT:
	val->values.shp = g.shp;
	g.shp += iwsp.colrmn;
	break;

      case WLZ_GREY_UBYTE:
	val->values.ubp = g.ubp;
	g.ubp += iwsp.colrmn;
	break;

      case WLZ_GREY_FLOAT:
	val->values.flp = g.flp;
	g.flp += iwsp.colrmn;
	break;

      case WLZ_GREY_DOUBLE:
	val->values.dbp = g.dbp;
	g.dbp += iwsp.colrmn;
	break;

      case WLZ_GREY_RGBA:
	val->values.rgbp = g.rgbp;
	g.rgbp += iwsp.colrmn;
	break;

      default:
        errNum = WLZ_ERR_GREY_TYPE;
	break;
      }
      val++;
    }
    switch( errNum ){
    case WLZ_ERR_NONE:
    case WLZ_ERR_EOO:
      errNum = WLZ_ERR_NONE;
      break;
    default:
      WlzFreeValues( v );
      v.i = NULL;
      break;
    }
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return(v.i);
}
예제 #5
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;
}
예제 #6
0
/*!
* \return	Transformed object.
* \ingroup	WlzTransform
* \brief	Transform an object using the given view-transform.
*		Typically this is for mapping section data back into
*		the 3D space of the reference image/reconstruction.
* \param	srcObj			Given source object.
* \param	viewStr			Given view transform.
* \param	dstErr			Destination error pointer, may be NULL.
*/
WlzObject *Wlz3DViewTransformObj(
    WlzObject		*srcObj,
    WlzThreeDViewStruct	*viewStr,
    WlzErrorNum		*dstErr)
{
    WlzErrorNum		errNum=WLZ_ERR_NONE;
    AlcErrno		alcErr = ALC_ER_NONE;
    WlzObject		*dstObj=NULL;
    int			area;
    int			i, k, p, xp, yp, line;
    int			plane1, lastpl, line1, lastln, kol1, lastkl;
    WlzIVertex3		*vertices;
    int			numVtxs, vtxIdx;
    WlzIntervalWSpace	iwsp;
    WlzGreyWSpace		gwsp;
    WlzDomain		domain, tmpDomain;
    WlzValues		values;
    int			numInts, itvlFlg;
    WlzInterval		*itvl;


    /* check the object */
    if( srcObj == NULL ) {
        errNum = WLZ_ERR_OBJECT_NULL;
    }
    else {
        switch( srcObj->type ) {

        case WLZ_2D_DOMAINOBJ:
            if( srcObj->domain.core == NULL ) {
                errNum = WLZ_ERR_DOMAIN_NULL;
            }
            area = WlzArea(srcObj, &errNum);
            if( area == 0 ) {
                dstObj = WlzMakeEmpty(&errNum);
            }
            break;

        case WLZ_2D_POLYGON: /* to be done at some time to 3D polyline */
        case WLZ_BOUNDLIST: /* convert to 3D polylines */
        case WLZ_TRANS_OBJ:
            errNum = WLZ_ERR_OBJECT_TYPE;
            break;

        default:
            errNum = WLZ_ERR_OBJECT_TYPE;
            break;
        }
    }

    /* create the voxel list */
    if( (errNum == WLZ_ERR_NONE) && (dstObj == NULL) ) {
        numVtxs = sizeof(WlzIVertex3) * (area+4);

        vertices = AlcMalloc(sizeof(WlzIVertex3) * (area+4));
        numVtxs = 0;
        if( vertices ) {
            errNum = WlzInitRasterScan(srcObj, &iwsp, WLZ_RASTERDIR_ILIC);
        }
        else {
            errNum = WLZ_ERR_MEM_ALLOC;
        }

        if( errNum == WLZ_ERR_NONE ) {
            while( (errNum = WlzNextInterval(&iwsp)) == WLZ_ERR_NONE ) {
                float x, y, z;

                if((iwsp.linpos < (int) viewStr->minvals.vtY) ||
                        (iwsp.linpos > (int) viewStr->maxvals.vtY)) {
                    continue;
                }
                yp = iwsp.linpos - (int) viewStr->minvals.vtY;
                for(k=iwsp.lftpos; k <= iwsp.rgtpos; k++) {
                    if((k < (int) viewStr->minvals.vtX) ||
                            (k > (int) viewStr->maxvals.vtX)) {
                        continue;
                    }
                    xp = k - (int) viewStr->minvals.vtX;
                    x = (float )(viewStr->xp_to_x[xp] + viewStr->yp_to_x[yp]);
                    y = (float )(viewStr->xp_to_y[xp] + viewStr->yp_to_y[yp]);
                    z = (float )(viewStr->xp_to_z[xp] + viewStr->yp_to_z[yp]);
                    vertices[numVtxs].vtX = WLZ_NINT(x);
                    vertices[numVtxs].vtY = WLZ_NINT(y);
                    vertices[numVtxs].vtZ = WLZ_NINT(z);
                    numVtxs++;
                }
            }

            if(errNum == WLZ_ERR_EOO) /* Reset error from end of object */
            {
                errNum = WLZ_ERR_NONE;
            }
        }
    }

    /* sort wrt planes, lines, kols */
    if( (errNum == WLZ_ERR_NONE) && (dstObj == NULL) ) {
        qsort((void *) vertices, (size_t) numVtxs, sizeof(WlzIVertex3),
              compareVtxVal);

        /* create planedomain */
        plane1 = vertices[0].vtZ;
        lastpl = vertices[numVtxs - 1].vtZ;
        line1 = vertices[0].vtY;
        lastln = line1;
        kol1 = vertices[0].vtX;
        lastkl = kol1;
        for(i=1; i < numVtxs; i++) {
            if( kol1 > vertices[i].vtX ) {
                kol1 = vertices[i].vtX;
            }
            if( lastkl < vertices[i].vtX ) {
                lastkl = vertices[i].vtX;
            }
            if( line1 > vertices[i].vtY ) {
                line1 = vertices[i].vtY;
            }
            if( lastln < vertices[i].vtY ) {
                lastln = vertices[i].vtY;
            }
        }
        if( (domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN,
                                           plane1, lastpl,
                                           line1, lastln,
                                           kol1, lastkl,
                                           &errNum)) == NULL ) {
            AlcFree((void *) vertices);
        }
    }

    /* for each plane count intervals and make domain */
    if( (errNum == WLZ_ERR_NONE) && (dstObj == NULL) ) {

        vtxIdx = 0;
        for(p=plane1; p <= lastpl; p++) {

            /* increment vertex index to current plane */
            while( vertices[vtxIdx].vtZ < p ) {
                vtxIdx++;
            }

            /* check for empty domain */
            if( vertices[vtxIdx].vtZ > p ) {
                domain.p->domains[p - plane1].i = NULL;
                continue;
            }

            /* estimate intervals - foreach pixel add one,
            foreach adjacent pixel on the same line subtract one */
            numInts = 1;
            kol1 = vertices[vtxIdx].vtX;
            lastkl = kol1;
            for(i=vtxIdx+1; i < numVtxs; i++) {
                if( vertices[i].vtZ > p ) {
                    break;
                }
                numInts++;
                if((vertices[i].vtY == vertices[i-1].vtY) &&
                        ((vertices[i].vtX == (vertices[i-1].vtX)) ||
                         (vertices[i].vtX == (vertices[i-1].vtX + 1))
                        )) {
                    numInts--;
                }
                if(kol1 > vertices[i].vtX) {
                    kol1 = vertices[i].vtX;
                }
                if(lastkl < vertices[i].vtX) {
                    lastkl = vertices[i].vtX;
                }
            }
            line1 = vertices[vtxIdx].vtY;
            lastln = vertices[i-1].vtY;

            /* make the domain and add the intervals pointer */
            tmpDomain.i = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_INTVL,
                                                line1, lastln,
                                                kol1, lastkl,
                                                &errNum);
            itvl = (WlzInterval *) AlcMalloc(sizeof(WlzInterval)*numInts);
            tmpDomain.i->freeptr = AlcFreeStackPush(tmpDomain.i->freeptr,
                                                    (void *) itvl,
                                                    &alcErr);
            if(alcErr != ALC_ER_NONE) {
                errNum = WLZ_ERR_MEM_ALLOC;
            }
            /* one more loop to add the intervals */
            itvl->ileft = vertices[vtxIdx].vtX - kol1;
            line = vertices[vtxIdx].vtY;
            itvlFlg = 1; /* interval started */
            numInts = 1;
            for(i=vtxIdx+1; i < numVtxs; i++) {

                /* new plane -> interval finished if started */
                if( vertices[i].vtZ > p ) {
                    if( itvlFlg ) {
                        itvl[numInts-1].iright = vertices[i-1].vtX - kol1;
                        WlzMakeInterval(line, tmpDomain.i, numInts, itvl);
                        itvl += numInts;
                        itvlFlg = 0; /* interval finished */
                        numInts = 0;
                    }
                    break;
                }

                /* check if new interval */
                if( !itvlFlg ) {
                    itvl->ileft = vertices[i].vtX - kol1;
                    line = vertices[i].vtY;
                    itvlFlg = 1;
                    numInts = 1;
                    continue; /* no further tests */
                }

                /* check for gap  - increment interval count */
                if((vertices[i].vtY == line) &&
                        ((vertices[i].vtX - vertices[i-1].vtX) > 1)) {
                    itvl[numInts-1].iright = vertices[i-1].vtX - kol1;
                    numInts++;
                    itvl[numInts-1].ileft = vertices[i].vtX - kol1;
                    itvlFlg = 1;
                }

                /* check for new-line */
                if( line < vertices[i].vtY ) {
                    itvl[numInts-1].iright = vertices[i-1].vtX - kol1;
                    WlzMakeInterval(line, tmpDomain.i, numInts, itvl);
                    itvl += numInts;
                    itvl->ileft = vertices[i].vtX - kol1;
                    line = vertices[i].vtY;
                    itvlFlg = 1;
                    numInts = 1;
                }

            }

            /* complete the last interval */
            if( itvlFlg ) {
                itvl[numInts-1].iright = vertices[i-1].vtX - kol1;
                WlzMakeInterval(line, tmpDomain.i, numInts, itvl);
                itvl += numInts;
            }

            /* add the domain to the planedomain */
            domain.p->domains[p - plane1] =
                WlzAssignDomain(tmpDomain, &errNum);
            (void) WlzIntervalCount(tmpDomain.i, 0);

        }

    }

    /* create the new object */
    if( (errNum == WLZ_ERR_NONE) && (dstObj == NULL) ) {
        values.core = NULL;
        dstObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values,
                             NULL, NULL, &errNum);
    }

    /* check for grey-level data */
    if((errNum == WLZ_ERR_NONE) && dstObj &&
            (dstObj->type != WLZ_EMPTY_OBJ) && srcObj->values.core ) {
        WlzPixelV	bckgrnd;
        WlzObject	*tmpObj;
        WlzValues	tmpValues;
        WlzDVertex3	vtx;
        WlzGreyValueWSpace	*gVWSp = NULL;
        WlzObjectType	valueTbType;

        /* explicit intialisation to satisfy strict ANSI on SGI */
        bckgrnd = WlzGetBackground(srcObj, &errNum);
        valueTbType = WlzGreyTableType(WLZ_GREY_TAB_RAGR,
                                       bckgrnd.type, NULL);

        /* make a voxel table */
        values.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY,
                                         plane1, lastpl, bckgrnd,
                                         NULL, &errNum);
        dstObj->values = WlzAssignValues(values, &errNum);

        /* set up grey-value random access to original
           and loop through planes setting values */
        gVWSp = WlzGreyValueMakeWSp(srcObj, NULL);
        for(p=plane1; p <= lastpl; p++) {

            /* check for empty domain */
            if( domain.p->domains[p-plane1].core == NULL ) {
                continue;
            }

            /* make a value table */
            tmpObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domain.p->domains[p-plane1],
                                 values.vox->values[p-plane1], NULL, NULL, &errNum);
            tmpValues.v = WlzNewValueTb(tmpObj, valueTbType, bckgrnd, &errNum);
            values.vox->values[p-plane1] = WlzAssignValues(tmpValues, &errNum);
            tmpObj->values = WlzAssignValues(tmpValues, &errNum);

            /* transfer values */
            errNum = WlzInitGreyScan(tmpObj, &iwsp, &gwsp);
            while((errNum == WLZ_ERR_NONE) &&
                    ((errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE)) {

                for(i=0;  i<iwsp.colrmn; i++) {
                    vtx.vtX = iwsp.colpos + i;
                    vtx.vtY = iwsp.linpos;
                    vtx.vtZ = p;
                    Wlz3DSectionTransformVtx(&vtx, viewStr);
                    WlzGreyValueGet(gVWSp, 0.0,
                                    WLZ_NINT(vtx.vtY), WLZ_NINT(vtx.vtX));
                    switch( gwsp.pixeltype ) {
                    case WLZ_GREY_LONG:
                        *(gwsp.u_grintptr.lnp+i) = gVWSp->gVal[0].lnv;
                        break;
                    case WLZ_GREY_INT:
                        *(gwsp.u_grintptr.inp+i) = gVWSp->gVal[0].inv;
                        break;
                    case WLZ_GREY_SHORT:
                        *(gwsp.u_grintptr.shp+i) = gVWSp->gVal[0].shv;
                        break;
                    case WLZ_GREY_UBYTE:
                        *(gwsp.u_grintptr.ubp+i) = gVWSp->gVal[0].ubv;
                        break;
                    case WLZ_GREY_FLOAT:
                        *(gwsp.u_grintptr.flp+i) = gVWSp->gVal[0].flv;
                        break;
                    case WLZ_GREY_DOUBLE:
                        *(gwsp.u_grintptr.dbp+i) = gVWSp->gVal[0].dbv;
                        break;
                    case WLZ_GREY_RGBA:
                        *(gwsp.u_grintptr.rgbp+i) = gVWSp->gVal[0].rgbv;
                        break;
                    case WLZ_GREY_BIT: /* not sure what to do with these */
                    default:
                        break;
                    }
                }
            }
            if(errNum == WLZ_ERR_EOO) /* Reset error from end of object */
            {
                errNum = WLZ_ERR_NONE;
            }
            WlzFreeObj(tmpObj);
        }

        WlzGreyValueFreeWSp(gVWSp);
    }

    /* clean temp allocation */
    if( vertices ) {
        AlcFree((void *) vertices);
    }

    if( dstErr ) {
        *dstErr = errNum;
    }
    return dstObj;
}
예제 #7
0
파일: WlzSplitObj.c 프로젝트: dscho/Woolz
/*!
* \return	Woolz error code.
* \ingroup	WlzBinaryOps
* \brief	Splits the reference object into component objects cliped
*		from the reference object, with the bounding box of each
*		of the component objects determined using the pre-processed
*		object. The component objects are returned in size order.
* \param	refObj			Reference object.
* \param	ppObj			Pre-processed object which is
*					normalised to values in the range
*					0 - 255 as WlzUByte greys.
* \param	bWidth			Border width.
* \param	bgdFrac			Minimum fraction of values which are
* 					background values, with range
*					[0.0+ - 1.0-].
* \param	sigma			Histogram smoothing parameter used
*					by WlzHistogramCnvGauss().
* \param	compThrMethod		Method for computing threshold, used
*					in call to WlzCompThresholdVT().
* \param	nReqComp		Number of required components.
* \param	dstNComp		Destination pointer for the number of
*					components extracted, must not be NULL.
* \param	dstComp			Destination pointer for the extracted
*					components, must not be NULL.
*/
WlzErrorNum	WlzSplitObj(WlzObject *refObj, WlzObject *ppObj,
			      int bWidth, double bgdFrac, double sigma,
			      WlzCompThreshType compThrMethod,
			      int nReqComp, int *dstNComp,
			      WlzObject ***dstComp)
{
  int		dim,
  		idC;
  WlzObject	*hObj = NULL,
  		*tObj = NULL;
  WlzObject 	**comp = NULL;
  WlzBox	box;
  WlzPixelV	tV;
  WlzSplitObjData split;
  WlzThresholdType tType;
  WlzConnectType lCon;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  const int	maxComp = 1024;

  split.nLComp = 0;
  split.compI = NULL;
  split.lCompSz = NULL;
  split.lComp = NULL;
  if((refObj == NULL) || (ppObj == NULL))
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if((refObj->domain.core == NULL) || (ppObj->domain.core == NULL))
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if((refObj->values.core == NULL) || (ppObj->values.core == NULL))
  {
    errNum = WLZ_ERR_VALUES_NULL;
  }
  else if(refObj->type != ppObj->type)
  {
    errNum = WLZ_ERR_OBJECT_TYPE;
  }
  else if((dstNComp == NULL) || (dstComp == NULL))
  {
    errNum = WLZ_ERR_PARAM_NULL;
  }
  else if((bgdFrac < DBL_EPSILON) || (bgdFrac > (1.0 - DBL_EPSILON)))
  {
    errNum = WLZ_ERR_PARAM_DATA;
  }
  else
  {
    switch(refObj->type)
    {
      case WLZ_2D_DOMAINOBJ:
	dim = 2;
        lCon = WLZ_8_CONNECTED;
	break;
      case WLZ_3D_DOMAINOBJ:
	dim = 3;
        lCon = WLZ_26_CONNECTED;
	break;
      default:
        errNum = WLZ_ERR_OBJECT_TYPE;
	break;
    }
  }
  /* Compute threshold value and type from histogram. */
  if(errNum == WLZ_ERR_NONE)
  {
    hObj = WlzAssignObject(
    	   WlzHistogramObj(ppObj, 256, 0.0, 1.0, &errNum), NULL);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzHistogramCnvGauss(hObj, sigma, 0);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzCompThresholdVT(hObj, compThrMethod, bgdFrac, 0.0,
    			        0.0, &tV, &tType);
  }
  (void )WlzFreeObj(hObj); hObj = NULL;
  /* Threshold object. */
  if(errNum == WLZ_ERR_NONE)
  {
    tObj = WlzAssignObject(
     	   WlzThreshold(ppObj, tV, tType, &errNum), NULL);
  }
  /* Label to get connected components. */
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzLabel(tObj, &(split.nLComp), &(split.lComp), maxComp, 0, lCon);
  }
  /* Sort connected components by size. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(split.nLComp < nReqComp)
    {
      nReqComp = split.nLComp;
    }
    if(((split.compI = (int *)AlcMalloc(sizeof(int) *
                                        split.nLComp)) == NULL) ||
       ((split.lCompSz = (int *)AlcMalloc(sizeof(int) *
                                          split.nLComp)) == NULL))
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    idC = 0; 
    while((errNum == WLZ_ERR_NONE) && (idC < split.nLComp))
    {
      split.compI[idC] = idC;
      split.lCompSz[idC] = (dim == 2)? WlzArea(split.lComp[idC], &errNum):
      				       WlzVolume(split.lComp[idC], &errNum);
      ++idC;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    /* Sort component indices by component size. */
    AlgQSort(split.compI, split.nLComp, sizeof(int), &split,
    	     WlzSplitObjSortSzFn);
    /* Allocate array for cliped component objects. */
    if((comp = (WlzObject **)AlcCalloc(sizeof(WlzObject *),
    				       split.nLComp)) == NULL)
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  /* Compute bounding box and clip objects from the reference object. */
  if(errNum == WLZ_ERR_NONE)
  {
    idC = 0;
    while((errNum == WLZ_ERR_NONE) && (idC < nReqComp))
    {
      if(dim == 2)
      {
        box.i2 = WlzBoundingBox2I(split.lComp[split.compI[idC]], &errNum);
	if(errNum == WLZ_ERR_NONE)
	{
	  box.i2.xMin -= bWidth;
	  box.i2.yMin -= bWidth;
	  box.i2.xMax += bWidth;
	  box.i2.yMax += bWidth;
	  comp[idC] = WlzClipObjToBox2D(refObj, box.i2, &errNum);
	}
      }
      else /* dim == 3 */
      {
        box.i3 = WlzBoundingBox3I(split.lComp[split.compI[idC]], &errNum);
	if(errNum == WLZ_ERR_NONE)
	{
	  box.i3.xMin -= bWidth;
	  box.i3.yMin -= bWidth;
	  box.i3.zMin -= bWidth;
	  box.i3.xMax += bWidth;
	  box.i3.yMax += bWidth;
	  box.i3.zMax += bWidth;
	  comp[idC] = WlzClipObjToBox3D(refObj, box.i3, &errNum);
	}
      }
      ++idC;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    *dstNComp = nReqComp;
    *dstComp = comp;
  }
  /* Free temporary storage. */
  if(split.lComp)
  {
    for(idC = 0; idC < split.nLComp; ++idC)
    {
      (void )WlzFreeObj(split.lComp[idC]);
    }
    AlcFree(split.lComp);
  }
  AlcFree(split.compI);
  AlcFree(split.lCompSz);
  (void )WlzFreeObj(tObj);
  return(errNum);
}
예제 #8
0
파일: WlzSplitObj.c 프로젝트: dscho/Woolz
/*!
* \return	Woolz error code.
* \ingroup	WlzBinaryOps
* \brief	Splits the given montage object into component objects
*		clipped from the montage object.  The montage object
*		must be composed of component images embedded in a
*		background, with little variation in the background
*		values.
* \param	mObj			Montage object, which must be either
*					a WLZ_2D_DOMAINOBJ or a
*					WLZ_3D_DOMAINOBJ with values.
* \param	gapV			Value for the uniform background.
*					Must be either WLZ_GREY_INT or
*					WLZ_GREY_RGBA.
* \param	tol			Tolerance (fraction) for the
*					variation in background values.
* \param	bWidth			Additional boundary width added
*					to detected images before they are
*					clipped.
* \param	minArea			Minimum area for a valid component
*					image, must be greater than zero.
* \param	maxComp			Maximum number of components.
* \param	dstNComp		Destination pointer for the number of
*					components extracted, must not be NULL.
* \param	dstComp			Destination pointer for the extracted
*					components, must not be NULL.
*/
WlzErrorNum 	WlzSplitMontageObj(WlzObject *mObj, WlzPixelV gapV,
				      double tol, int bWidth, int minArea,
				      int maxComp,
				      int *dstNComp, WlzObject ***dstComp)
{
  int		id0,
  		id1,
		area,
		nLComp = 0;
  WlzObject	*gObj = NULL,
  		*tObj = NULL;
  WlzObject	**lComp;
  WlzGreyType	objG;
  WlzBox	box;
  WlzPixelV	gapLV,
  		gapHV;
  WlzConnectType lCon;
  int		tI[8];
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  tol = WLZ_CLAMP(tol, 0.0, 1.0);
  if(mObj == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if(minArea < 1)
  {
    errNum = WLZ_ERR_PARAM_DATA;
  }
  else
  {
    switch(mObj->type)
    {
      case WLZ_2D_DOMAINOBJ:
	lCon = WLZ_4_CONNECTED;
        break;
      case WLZ_3D_DOMAINOBJ:
	lCon = WLZ_6_CONNECTED;
        break;
      default:
        errNum = WLZ_ERR_OBJECT_TYPE;
	break;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    objG = WlzGreyTypeFromObj(mObj, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    switch(gapV.type)
    {
      case WLZ_GREY_INT: /* FALLTHROUGH */
      case WLZ_GREY_RGBA:
        break;
      default:
	errNum = WLZ_ERR_GREY_TYPE;
	break;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(objG == WLZ_GREY_RGBA)
    {
      if(gapV.type != WLZ_GREY_RGBA)
      {
        (void )WlzValueConvertPixel(&gapV, gapV, WLZ_GREY_RGBA);
      }
    }
    else
    {
      if(gapV.type != WLZ_GREY_INT)
      {
        (void )WlzValueConvertPixel(&gapV, gapV, WLZ_GREY_INT);
      }
    }
    gapLV.type = gapHV.type = gapV.type;
    if(gapV.type == WLZ_GREY_INT)
    {
      tI[0] = gapV.v.inv * tol;
      gapLV.v.inv = gapV.v.inv - tI[0];
      gapHV.v.inv = gapV.v.inv + tI[0];
      tObj = WlzThreshold(mObj, gapLV, WLZ_THRESH_HIGH, &errNum);
      if((errNum == WLZ_ERR_NONE) && (tObj != NULL))
      {
	gObj = WlzThreshold(tObj, gapHV, WLZ_THRESH_LOW, &errNum);
      }
      (void )WlzFreeObj(tObj);
      tObj = NULL;
    }
    else /* gapV.type == WLZ_GREY_RGBA */
    {
	tI[0] = WLZ_RGBA_RED_GET(gapV.v.rgbv);
	tI[1] = (int )floor((double )(tI[0]) * tol);
	tI[2] = tI[0] - tI[1];
	tI[5] = tI[0] + tI[1];
	tI[0] = WLZ_RGBA_GREEN_GET(gapV.v.rgbv);
	tI[1] = (int )floor((double )(tI[0]) * tol);
	tI[3] = tI[0] - tI[1];
	tI[6] = tI[0] + tI[1];
	tI[0] = WLZ_RGBA_BLUE_GET(gapV.v.rgbv);
	tI[1] = (int )floor((double )(tI[0]) * tol);
	tI[4] = tI[0] - tI[1];
	tI[7] = tI[0] + tI[1];
	tI[2] = WLZ_CLAMP(tI[2], 0, 255);
	tI[3] = WLZ_CLAMP(tI[3], 0, 255);
	tI[4] = WLZ_CLAMP(tI[4], 0, 255);
	WLZ_RGBA_RGBA_SET(gapLV.v.rgbv, tI[2], tI[3], tI[4], 255);
	tI[5] = WLZ_CLAMP(tI[5], 0, 255);
	tI[6] = WLZ_CLAMP(tI[6], 0, 255);
	tI[7] = WLZ_CLAMP(tI[7], 0, 255);
	WLZ_RGBA_RGBA_SET(gapHV.v.rgbv, tI[5], tI[6], tI[7], 255);
        gObj = WlzRGBABoxThreshold(mObj, gapLV, gapHV, &errNum);
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    tObj = WlzDiffDomain(mObj, gObj, &errNum);
  }
  (void )WlzFreeObj(gObj);
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzLabel(tObj, &nLComp, &lComp, maxComp, 0, lCon);
  }
  (void )WlzFreeObj(tObj);
  if(errNum == WLZ_ERR_NONE)
  {
    /* Get rid of small objects using minArea as the threshold. */
    id0 = 0;
    id1 = 0;
    while(id0 < nLComp)
    {
      switch((*(lComp + id0))->type)
      {
        case WLZ_2D_DOMAINOBJ:
	  area = WlzArea(*(lComp + id0), NULL);
	  break;
        case WLZ_3D_DOMAINOBJ:
	  area = WlzVolume(*(lComp + id0), NULL);
	  break;
        default:
          area = 0;
	  break;
      }
      if(area >= minArea)
      {
        *(lComp + id1) = *(lComp + id0);
        ++id1;
      }
      else
      {
        (void )WlzFreeObj(*(lComp + id0));
	*(lComp + id0) = NULL;
      }
      ++id0;
    }
    nLComp = id1;
  }
  if(errNum == WLZ_ERR_NONE)
  {
    /* Clip rectangular objects from the montage object. */
    id0 = 0;
    while((errNum == WLZ_ERR_NONE) && (id0 < nLComp))
    {
      if(tObj->type == WLZ_2D_DOMAINOBJ)
      {
        box.i2 = WlzBoundingBox2I(*(lComp + id0), &errNum);
	box.i2.xMin -= bWidth;
	box.i2.yMin -= bWidth;
	box.i2.xMax += bWidth;
	box.i2.yMax += bWidth;
	(void )WlzFreeObj(*(lComp + id0));
	*(lComp + id0) = WlzClipObjToBox2D(mObj, box.i2, &errNum);
      }
      else /* tObj->type == WLZ_3D_DOMAINOBJ */
      {
        box.i3 = WlzBoundingBox3I(*(lComp + id0), &errNum);
	box.i3.xMin -= bWidth;
	box.i3.yMin -= bWidth;
	box.i3.zMin -= bWidth;
	box.i3.xMax += bWidth;
	box.i3.yMax += bWidth;
	box.i3.zMax += bWidth;
	(void )WlzFreeObj(*(lComp + id0));
	*(lComp + id0) = WlzClipObjToBox3D(mObj, box.i3, &errNum);
      }
      ++id0;
    }
  }
  *dstNComp = nLComp;
  *dstComp = lComp;
  return(errNum);
}
예제 #9
0
void getViewDomains(
  ThreeDViewStruct	*view_struct)
{
  int		i, j, numOverlays;
  WlzObject	*allDomainsObj=NULL, *tmpObj;
  WlzPixelV	thresh;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  /* check initialisation */
  if( !view_struct->wlzViewStr->initialised ){
    if( init_view_struct( view_struct ) ){
      errNum = WLZ_ERR_UNSPECIFIED;
    }
  }

  /* check for painted object */

  /* clear any current domains */
  numOverlays = globals.cmapstruct->num_overlays +
    globals.cmapstruct->num_solid_overlays;
  for(i=0; i <= numOverlays; i++){
    if( view_struct->curr_domain[i] ){
      errNum = WlzFreeObj(view_struct->curr_domain[i]);
      view_struct->curr_domain[i] = NULL;
    }
    if( errNum != WLZ_ERR_NONE ){
      break;
    }
  }

  /* get the union of all domains */
  if( errNum == WLZ_ERR_NONE ){
    thresh.type = WLZ_GREY_INT;
    thresh.v.inv = globals.cmapstruct->ovly_cols[DOMAIN_1];
    tmpObj = WlzThreshold(view_struct->painted_object,
			  thresh, WLZ_THRESH_HIGH, &errNum);
    if( (errNum == WLZ_ERR_NONE) && tmpObj ){
      if( WlzArea(tmpObj, &errNum) > 0 ){
	allDomainsObj = WlzAssignObject(tmpObj, &errNum);
      }
      else {
	errNum = WlzFreeObj(tmpObj);
      }
    }
  }

  /* segment the painted section image to establish each domain object */
  if( (errNum == WLZ_ERR_NONE) && allDomainsObj ){
    WlzPixelV	min, max;
    int		max_i=numOverlays;

    /* get maximum number of domains */
    WlzGreyRange(allDomainsObj, &min, &max);
    WlzValueConvertPixel(&max, max, WLZ_GREY_INT);

    while( (max_i > 0) && (globals.cmapstruct->ovly_cols[max_i] > max.v.inv) ){
      max_i--;
    }

    for(i=1; i <= max_i; i++){
      tmpObj = get_domain_from_object(view_struct->painted_object, i);
      if( tmpObj ){
	view_struct->curr_domain[i] = WlzAssignObject(tmpObj, NULL);
      }
    }
  }

  /* propogate from previous section 
     asking for confirmation if a domain will be changed by
     propogation.
     This will either be if the current domain exists or if the 
     propogating domain overlaps the union of all existing domains */
  if( (errNum == WLZ_ERR_NONE) && (globals.propogate||globals.propogate_sel) ){
    for(i=1; (i <= numOverlays) && (errNum == WLZ_ERR_NONE); i++){
      /* test for propogate currently selected domain only */
      if((!globals.propogate) && (i != globals.current_domain)){
	continue;
      }
      if((view_struct->prev_domain[i]) &&
	 (view_struct->prev_domain[i]->type != WLZ_EMPTY_OBJ)){
	if( allDomainsObj ){
	  /* first check if there is a curr_domain */
	  int needConfirm = 0;
	  if((view_struct->curr_domain[i]) && 
	     (view_struct->curr_domain[i]->type != WLZ_EMPTY_OBJ)){
	    needConfirm = 1;
	  }
	  else {
	    tmpObj = WlzIntersect2(view_struct->prev_domain[i],
				   allDomainsObj, &errNum);
	    if( tmpObj && (WlzArea(tmpObj, &errNum) > 0) ){
	      needConfirm = 1;
	      WlzFreeObj(tmpObj);
	    }
	  }
	  if( (errNum == WLZ_ERR_NONE) && needConfirm ){
	    if( HGU_XmUserConfirm(view_struct->dialog,
				  "Warning: propogation may modify\n"
				  "    one or more existing domains.\n"
				  "    Propogate anyway?",
				  "Yes", "No", 0) ){
	      if( view_struct->curr_domain[i] ){
		tmpObj = WlzUnion2(view_struct->curr_domain[i],
				   view_struct->prev_domain[i], &errNum);
		WlzFreeObj(view_struct->curr_domain[i]);
		view_struct->curr_domain[i] = 
		  WlzAssignObject(tmpObj, NULL);
	      }
	      else {
		view_struct->curr_domain[i] =
		  WlzAssignObject(view_struct->prev_domain[i], NULL);
	      }
	      globals.domain_changed_since_saved[i] = 1;
	    }
	  }
	  else {
	    view_struct->curr_domain[i] =
	      WlzAssignObject(view_struct->prev_domain[i], NULL);
	    globals.domain_changed_since_saved[i] = 1;
	  }
	}
	else {
	  view_struct->curr_domain[i] =
	    WlzAssignObject(view_struct->prev_domain[i], &errNum);
	  globals.domain_changed_since_saved[i] = 1;
	}
      }
    }
  }

  /* put all objects onto painted image in reverse dominance order */
  for(j=numOverlays; (j > 0) && (errNum == WLZ_ERR_NONE); j--){
    i = globals.priority_to_domain_lut[j];
    if( view_struct->curr_domain[i] ){
      if( i > globals.cmapstruct->num_overlays )
      {
	if( set_grey_values_from_domain(view_struct->curr_domain[i],
					view_struct->painted_object,
					globals.cmapstruct->ovly_cols[i],
					255) ){
	  break;
	}
      }
      else
      {
	if( set_grey_values_from_domain(view_struct->curr_domain[i],
					view_struct->painted_object,
					globals.cmapstruct->ovly_cols[i],
					globals.cmapstruct->ovly_planes) ){
	  break;
	}
      }
    }
  }      

  /* redisplay the view */
  if( errNum != WLZ_ERR_NONE ){
    MAPaintReportWlzError(globals.topl, "getViewDomains", errNum);
  }
  else{
    redisplay_view_cb(view_struct->canvas, view_struct, NULL);
  }

  return;
}