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; }
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; }
/*! * \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 ); }
/*! * \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); }
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; }
/*! * \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; }
/*! * \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); }
/*! * \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); }
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; }