/*! * \return New convex hull values. * \ingroup WlzConvexHull * \brief Fill in parameters of the convex hull into the values table. * \param cvh Given convex hull. * \param obj Given object. * \param dstErr Destination error pointer, may be NULL. */ static WlzConvHullValues *WlzMakeConvexHullValues3d( WlzObject *cvh, WlzObject *obj, WlzErrorNum *dstErr) { WlzValues rtnvalues, *valuess, values; WlzObject *obj1, *obj2; WlzDomain *domains1, *domains2; WlzPixelV bckgrnd; int p; WlzErrorNum errNum=WLZ_ERR_NONE; /* this is only called after a successful call to WlzObjToConvexPolygon therefore the given convex hull object and object have been checked and match */ rtnvalues.c = NULL; bckgrnd.type = WLZ_GREY_UBYTE; bckgrnd.v.ubv = 0; /* make a voxeltable and calculate the convex hull values for each plane */ if((rtnvalues.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_CONV_HULL, cvh->domain.p->plane1, cvh->domain.p->lastpl, bckgrnd, NULL, &errNum)) != NULL){ domains1 = cvh->domain.p->domains; domains2 = obj->domain.p->domains; valuess = rtnvalues.vox->values; for(p=cvh->domain.p->plane1; p <= cvh->domain.p->lastpl; p++, domains1++, domains2++, valuess++){ if( (*domains1).core != NULL ){ values.core = NULL; obj1 = WlzMakeMain(WLZ_2D_POLYGON, *domains1, values, NULL, NULL, NULL); obj2 = WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains2, values, NULL, NULL, NULL); if((values.c = WlzMakeConvexHullValues(obj1, obj2, &errNum)) != NULL){ *valuess = WlzAssignValues(values, NULL); } else { WlzFreeObj(obj2); WlzFreeObj(obj1); WlzFreeVoxelValueTb(rtnvalues.vox); rtnvalues.vox = NULL; break; } WlzFreeObj(obj2); WlzFreeObj(obj1); } } } if( dstErr ){ *dstErr = errNum; } return rtnvalues.c; }
void file_menu_init( Widget topl) { Widget rc, form, toggle; Visual *visual; Arg arg[1]; char fileStr[128]; FILE *fp; WlzEffFormat image_type=WLZEFF_FORMAT_WLZ; /* set the top-level title */ set_topl_title(NULL); /* get the visual explicitly */ visual = HGU_XmWidgetToVisual(topl); XtSetArg(arg[0], XmNvisual, visual); /* create the read-model file selection dialog */ read_model_dialog = XmCreateFileSelectionDialog(topl, "read_model_dialog", arg, 1); XtAddCallback(read_model_dialog, XmNokCallback, read_reference_object_cb, (XtPointer) WLZEFF_FORMAT_WLZ); XtAddCallback(read_model_dialog, XmNokCallback, PopdownCallback, NULL); XtAddCallback( read_model_dialog, XmNcancelCallback, PopdownCallback, NULL); XtAddCallback(read_model_dialog, XmNmapCallback, FSBPopupCallback, NULL); XtManageChild( read_model_dialog ); /* create the read-obj file selection dialog */ read_obj_dialog = HGU_XmCreateExtFFObjectFSB(topl, "read_obj_dialog", read_reference_object_cb, NULL); if((rc = XtNameToWidget(read_obj_dialog, "*.formatFormRC"))){ /* add a form to include file type and fill-blanks toggle */ form = XtVaCreateManagedWidget("read_file_form", xmFormWidgetClass, rc, XmNborderWidth, 0, NULL); /* add a fill-blanks toggles */ toggle = XtVaCreateManagedWidget("fill_blanks", xmToggleButtonGadgetClass, form, XmNindicatorOn, True, XmNindicatorType, XmN_OF_MANY, XmNset, False, XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, NULL); toggle = XtVaCreateManagedWidget("min_domain", xmToggleButtonGadgetClass, form, XmNindicatorOn, True, XmNindicatorType, XmN_OF_MANY, XmNset, True, XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, toggle, NULL); } HGU_XmExtFFObjectFSBSetType(read_obj_dialog, WLZEFF_FORMAT_WLZ); XtManageChild( read_obj_dialog ); /* add to the save restore list */ HGU_XmSaveRestoreAddWidget( read_obj_dialog, HGU_XmFSD_SaveFunc, (XtPointer) XtName(topl), NULL, NULL ); /* create the write-obj file selection dialog */ write_obj_dialog = HGU_XmCreateExtFFObjectFSB(topl, "write_obj_dialog", write_reference_object_cb, NULL); HGU_XmExtFFObjectFSBSetType(write_obj_dialog, WLZEFF_FORMAT_WLZ); /* initialise the reference file list pulldown */ if( !globals.sectViewFlg ){ Widget cascade; if((cascade = XtNameToWidget(globals.topl, "*file_menu*_pulldown*Recent"))){ globals.resourceFile = (String) AlcMalloc(sizeof(char) * (strlen(getenv("HOME")) + 16)); sprintf(globals.resourceFile, "%s/%s", getenv("HOME"), ".maRecentFiles"); globals.fileList = HGU_XmFileListCreateList(globals.resourceFile, NULL); HGU_XmFileListResetMenu(globals.fileList, cascade, referenceFileListCb); } } /* add to the save restore list */ HGU_XmSaveRestoreAddWidget( write_obj_dialog, HGU_XmFSD_SaveFunc, (XtPointer) XtName(topl), NULL, NULL ); /* create the object properties dialog */ obj_props_dialog_init( topl ); globals.file = NULL; globals.obj = NULL; globals.orig_obj = NULL; globals.fb_obj = NULL; globals.origObjExtType = image_type; /* setup the theiler directory and menu item - check for stage */ XtGetApplicationResources(topl, &globals, set_att_res, XtNumber(set_att_res), NULL, 0); /* check the logfile */ if( globals.logfile ){ if( (globals.logfileFp = fopen(globals.logfile, "w")) == NULL ){ fprintf(stderr, "MAPaint: something wrong with the logfile %s\n" "Please check name and permissions\n" "Logging not enabled\n\007", globals.logfile); } else { char timeBuf[16]; struct hostent *hstnt; fprintf(stderr, "MAPaint: logging enabled to %s\n", globals.logfile); MAPaintLogData("Filename", globals.logfile, 0, NULL); MAPaintLogData("User", getenv("USER"), 0, NULL); #if defined (LINUX2) || defined (DARWIN) strcpy(timeBuf, "00/00/00"); #else tmpTime = time(NULL); cftime(timeBuf, "%d/%m/%Y", &tmpTime); #endif /* LINUX2 */ MAPaintLogData("Date", timeBuf, 0, NULL); #if defined (LINUX2) || defined (DARWIN) strcpy(timeBuf, "00.00"); #else cftime(timeBuf, "%H.%M", &tmpTime); #endif /* LINUX2 */ MAPaintLogData("Time", timeBuf, 0, NULL); hstnt = gethostbyname(getenv("HOST")); MAPaintLogData("Host", getenv("HOST"), 0, NULL); MAPaintLogData("Hostname", hstnt->h_name, 0, NULL); } } else { globals.logfileFp = NULL; } /* check base directory - if the string has come from the resources then we need to duplicate it to allow it to be freed possibly some memory leakage here */ /* note: only non-NULL if set by the user, if NULL then attempt to find the cdrom or copied data */ if( globals.base_theiler_dir ){ globals.base_theiler_dir = AlcStrDup( globals.base_theiler_dir ); } /* else { FILE *pp;*/ /* search for the Theiler mode directory as per the CDROM should search local disc first */ /*#if defined (LINUX2) if((pp = popen("find /mnt -maxdepth 4 -name Models", "r"))){ while( fscanf(pp, "%s", fileStr) != EOF ){ if( strstr(fileStr, "Models") ){ globals.base_theiler_dir = AlcStrDup(fileStr); break; } } pclose(pp); } #elif defined (DARWIN) if( (pp = popen("find /Volumes -maxdepth 4 -name Models", "r")) ){ while( fscanf(pp, "%s", fileStr) != EOF ){ if( strstr(fileStr, "Models") ){ globals.base_theiler_dir = AlcStrDup(fileStr); break; } } pclose(pp); } #elif defined (SUNOS4) || defined (SUNOS5) if( pp = popen("find /cdrom -maxdepth 4 -name Models", "r") ){ while( fscanf(pp, "%s", fileStr) != EOF ){ if( strstr(fileStr, "Models") ){ globals.base_theiler_dir = AlcStrDup(fileStr); break; } } pclose(pp); } #else globals.base_theiler_dir = NULL; #endif }*/ if( globals.theiler_stage ){ char *tStr; if((tStr = theilerString(globals.theiler_stage))){ globals.theiler_stage = AlcStrDup(tStr); } else { globals.theiler_stage = NULL; } } theiler_menu_init( topl ); /* check for an initial reference file else check Theiler stage */ if( initial_reference_file != NULL ){ WlzObject *obj; /* open the reference object file and install */ if( (fp = fopen(initial_reference_file, "r")) ){ HGU_XmSetHourGlassCursor(topl); if((obj = WlzReadObj( fp, NULL ))){ WlzDomain domain; WlzValues values; WlzObject *newObj; switch( obj->type ){ case WLZ_2D_DOMAINOBJ: domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, 0, 0, obj->domain.i->line1, obj->domain.i->lastln, obj->domain.i->kol1, obj->domain.i->lastkl, NULL); domain.p->domains[0] = WlzAssignDomain(obj->domain, NULL); values.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, 0, 0, WlzGetBackground(obj, NULL), NULL, NULL); values.vox->values[0] = WlzAssignValues(obj->values, NULL); newObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values, NULL, NULL, NULL); WlzFreeObj(obj); obj = newObj; globals.origObjType = WLZ_2D_DOMAINOBJ; break; case WLZ_3D_DOMAINOBJ: globals.origObjType = WLZ_3D_DOMAINOBJ; break; default: HGU_XmUserError(globals.topl, "Read Reference Object:\n" " The reference object must be a 2- or 3-D woolz\n" " grey-level image. Please select an alternate\n" " object", XmDIALOG_FULL_APPLICATION_MODAL); WlzFreeObj( obj ); /* set hour glass cursor */ HGU_XmUnsetHourGlassCursor(globals.topl); return; } HGU_XmFileListAddFile(globals.fileList, initial_reference_file, image_type); HGU_XmFileListWriteResourceFile(globals.fileList, globals.resourceFile); MAPaintLogData("ReferenceFile", initial_reference_file, 0, NULL); install_paint_reference_object( obj ); /* set the globals reference file */ globals.file = initial_reference_file; /* set the title of the top-level window */ set_topl_title(globals.file); } else { /* if it fails to read, check the file name or the file content for special options */ if( strstr(initial_reference_file, "MAPaint") ){ /* standard MAPaint startup */ globals.app_name = "MAPaint"; /* set the title of the top-level window */ set_topl_title(globals.file); } else if( strstr(initial_reference_file, "SectionView") ){ /* restricted section view startup */ globals.app_name = "SectionView"; globals.sectViewFlg = 1; /* set the title of the top-level window */ set_topl_title(globals.file); } else if( theilerString(initial_reference_file) ){ /* load in theiler stage anatomy etc. */ globals.app_name = "SectionView"; globals.sectViewFlg = 1; set_theiler_stage_cb(topl, theilerString(initial_reference_file), NULL); } else { char strBuf[33]; /* check the content */ rewind(fp); fscanf(fp, "%32s", strBuf); if( strstr(strBuf, "MAPaint") ){ /* standard MAPaint startup */ globals.app_name = "MAPaint"; /* set the title of the top-level window */ set_topl_title(globals.file); } else if( strstr(strBuf, "SectionView") ){ /* restricted section view startup */ globals.app_name = "SectionView"; globals.sectViewFlg = 1; /* set the title of the top-level window */ set_topl_title(globals.file); } else if( theilerString(strBuf) ){ /* load in theiler stage anatomy etc. */ globals.app_name = "SectionView"; globals.sectViewFlg = 1; set_theiler_stage_cb(topl, theilerString(strBuf), NULL); } } /* set the globals reference file */ globals.file = NULL; } (void) fclose( fp ); HGU_XmUnsetHourGlassCursor(topl); } } else if( globals.theiler_stage ){ globals.app_name = "MAPaint"; set_theiler_stage_cb(topl, theilerString(globals.theiler_stage), NULL); } /* reset the colormap */ if( globals.sectViewFlg == 1 ){ init_paint_cmapstruct(globals.topl); } /* check for an initial domain file */ if( initial_domain_file != NULL ){ WlzObject *obj; /* open the domain object file and put it in as a 3D feedback option */ if( (fp = fopen(initial_domain_file, "rb")) ){ HGU_XmSetHourGlassCursor(topl); if((obj = WlzReadObj( fp, NULL ))){ if( globals.fb_obj ){ WlzFreeObj(globals.fb_obj); } globals.fb_obj = WlzAssignObject(obj, NULL); setup_ref_display_list_cb(read_obj_dialog, NULL, NULL); } (void) fclose( fp ); HGU_XmUnsetHourGlassCursor(topl); } } return; }
/*! * \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 Rescaled object. * \ingroup WlzTransform * \brief Rescales the given 3D domain object using an integer scale. * \param gObj Given object. * \param scale Integer scale factor. * \param expand If zero use \f$\frac{1}{scale}\f$. * \param dstErr Destination error pointer, may be NULL. */ WlzObject *WlzIntRescaleObj3D(WlzObject *gObj, int scale, int expand, WlzErrorNum *dstErr) { int gPIdx, nPIdx; WlzDomain gDom, nDom; WlzValues gVal, nVal, dumVal; WlzObject *gTObj = NULL, *nTObj = NULL, *rObj = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; WlzIBox3 nBox; nDom.core = NULL; nVal.core = NULL; dumVal.core = NULL; gDom = gObj->domain; gVal = gObj->values; if(expand) { nBox.xMin = gDom.p->kol1 * scale; nBox.xMax = ((gDom.p->lastkl + 1) * scale) - 1; nBox.yMin = gDom.p->line1 * scale; nBox.yMax = ((gDom.p->lastln + 1) * scale) - 1; nBox.zMin = gDom.p->plane1 * scale; nBox.zMax = ((gDom.p->lastpl + 1) * scale) - 1; } else { nBox.xMin = gDom.p->kol1 / scale; nBox.xMax = gDom.p->lastkl / scale; nBox.yMin = gDom.p->line1 / scale; nBox.yMax = gDom.p->lastln / scale; nBox.zMin = gDom.p->plane1 / scale; nBox.zMax = gDom.p->lastpl / scale; } nDom.p = WlzMakePlaneDomain(gDom.p->type, nBox.zMin, nBox.zMax, nBox.yMin, nBox.yMax, nBox.xMin, nBox.xMax, &errNum); if(errNum == WLZ_ERR_NONE) { if(gVal.core && (gVal.core->type != WLZ_EMPTY_OBJ)) { if(WlzGreyTableIsTiled(gVal.core->type)) { errNum = WLZ_ERR_VALUES_TYPE; } else { nVal.vox = WlzMakeVoxelValueTb(gVal.vox->type, nBox.zMin, nBox.zMax, WlzGetBackground(gObj, NULL), NULL, &errNum); } } } if(errNum == WLZ_ERR_NONE) { nPIdx = nBox.zMin; while((errNum == WLZ_ERR_NONE) && (nPIdx <= nBox.zMax)) { gPIdx = (expand)? nPIdx / scale: nPIdx * scale; if(nVal.vox) { gTObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, *(gDom.p->domains + gPIdx), *(gVal.vox->values + gPIdx), NULL, NULL, &errNum); } else { gTObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, *(gDom.p->domains + gPIdx), dumVal, NULL, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { nTObj = WlzIntRescaleObj2D(gTObj, scale, expand, &errNum); } (void )WlzFreeObj(gTObj); gTObj = NULL; if(errNum == WLZ_ERR_NONE) { *(nDom.p->domains + nPIdx) = WlzAssignDomain(nTObj->domain, NULL); if(nVal.vox) { *(nVal.vox->values + nPIdx) = WlzAssignValues(nTObj->values, NULL); } } (void )WlzFreeObj(nTObj); nTObj = NULL; ++nPIdx; } } if(errNum == WLZ_ERR_NONE) { rObj = WlzMakeMain(gObj->type, nDom, nVal, NULL, NULL, &errNum); } else { (void )WlzFreePlaneDomain(nDom.p); (void )WlzFreeVoxelValueTb(nVal.vox); } if(dstErr) { *dstErr = errNum; } return(rObj); }
static WlzObject *WlzGreyMask3d( WlzObject *obj, WlzObject *mask, WlzPixelV maskVal, WlzErrorNum *dstErr) { WlzObject *rtnObj=NULL; WlzObject *tmpMask, *obj1, *obj2; WlzDomain *domains; WlzValues values, *valuess, *newvaluess; WlzPlaneDomain *pdom; int p; WlzErrorNum errNum=WLZ_ERR_NONE; /* check the object - it is non-NULL and 3D but the domain needs checking */ if( obj->domain.p == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; } else { switch( obj->domain.p->type ){ case WLZ_2D_DOMAINOBJ: /* check there is a valuetable */ if( obj->values.core == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } break; case WLZ_EMPTY_DOMAIN: return WlzMakeEmpty(dstErr); default: errNum = WLZ_ERR_DOMAIN_TYPE; break; } } /* check the mask */ if( errNum == WLZ_ERR_NONE ){ if( mask == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; } else { /* set some local variables */ pdom = obj->domain.p; domains = obj->domain.p->domains; valuess = obj->values.vox->values; /* create a new voxel object, initially no values */ values.vox = WlzMakeVoxelValueTb(obj->values.vox->type, obj->values.vox->plane1, obj->values.vox->lastpl, obj->values.vox->bckgrnd, obj, NULL); rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, obj->domain, values, NULL, NULL, NULL); newvaluess = rtnObj->values.vox->values; /* switch on mask type - a 2D mask is applied to each plane */ switch( mask->type ){ case WLZ_2D_DOMAINOBJ: case WLZ_2D_POLYGON: case WLZ_BOUNDLIST: case WLZ_EMPTY_OBJ: for(p=pdom->plane1; p <= pdom->lastpl; p++, domains++, valuess++){ if( (*domains).core ){ obj1 = WlzAssignObject( WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *valuess, NULL, NULL, NULL), NULL); if((obj2 = WlzGreyMask(obj1, mask, maskVal, &errNum)) != NULL){ newvaluess[p - pdom->plane1] = WlzAssignValues(obj->values, NULL); WlzFreeObj(obj2); } WlzFreeObj(obj1); } } break; case WLZ_3D_DOMAINOBJ: /* switch on plane domain type - polygon and boundlist are legal but need transforming first. */ switch( obj->domain.p->type ){ WlzDomain *maskDoms; case WLZ_PLANEDOMAIN_DOMAIN: maskDoms = mask->domain.p->domains; for(p=pdom->plane1; p <= pdom->lastpl; p++, domains++, valuess++){ if(((*domains).core)){ if((p >= mask->domain.p->plane1) && (p <= mask->domain.p->lastpl) && (maskDoms[p - mask->domain.p->plane1].core) ){ values.core = NULL; tmpMask = WlzMakeMain(WLZ_2D_DOMAINOBJ, maskDoms[p - mask->domain.p->plane1], values, NULL, NULL, NULL); } else { tmpMask = WlzMakeEmpty(NULL); } obj1 = WlzAssignObject( WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *valuess, NULL, NULL, NULL), NULL); if((obj2 = WlzGreyMask(obj1, tmpMask, maskVal, &errNum)) != NULL){ newvaluess[p - pdom->plane1] = WlzAssignValues(obj2->values, NULL); WlzFreeObj(obj2); } WlzFreeObj(obj1); WlzFreeObj(tmpMask); } } break; case WLZ_PLANEDOMAIN_POLYGON: maskDoms = mask->domain.p->domains; for(p=pdom->plane1; p <= pdom->lastpl; p++, domains++, valuess++){ if(((*domains).core)){ if((p >= mask->domain.p->plane1) && (p <= mask->domain.p->lastpl) && (maskDoms[p - mask->domain.p->plane1].core) ){ values.core = NULL; tmpMask = WlzMakeMain(WLZ_2D_POLYGON, maskDoms[p - mask->domain.p->plane1], values, NULL, NULL, NULL); } else { tmpMask = WlzMakeEmpty(NULL); } obj1 = WlzAssignObject( WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *valuess, NULL, NULL, NULL), NULL); if((obj2 = WlzGreyMask(obj1, tmpMask, maskVal, &errNum)) != NULL){ newvaluess[p - pdom->plane1] = WlzAssignValues(obj2->values, NULL); WlzFreeObj(obj2); } WlzFreeObj(obj1); WlzFreeObj(tmpMask); } } break; case WLZ_PLANEDOMAIN_BOUNDLIST: maskDoms = mask->domain.p->domains; for(p=pdom->plane1; p <= pdom->lastpl; p++, domains++, valuess++){ if(((*domains).core)){ if((p >= mask->domain.p->plane1) && (p <= mask->domain.p->lastpl) && (maskDoms[p - mask->domain.p->plane1].core) ){ values.core = NULL; tmpMask = WlzMakeMain(WLZ_BOUNDLIST, maskDoms[p - mask->domain.p->plane1], values, NULL, NULL, NULL); } else { tmpMask = WlzMakeEmpty(NULL); } obj1 = WlzAssignObject( WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *valuess, NULL, NULL, NULL), NULL); if((obj2 = WlzGreyMask(obj1, tmpMask, maskVal, &errNum)) != NULL){ newvaluess[p - pdom->plane1] = WlzAssignValues(obj2->values, NULL); WlzFreeObj(obj2); } WlzFreeObj(obj1); WlzFreeObj(tmpMask); } } break; default: errNum = WLZ_ERR_DOMAIN_TYPE; WlzFreeObj(rtnObj); rtnObj = NULL; break; } break; default: errNum = WLZ_ERR_OBJECT_NULL; WlzFreeObj(rtnObj); rtnObj = NULL; break; } } } if( dstErr ){ *dstErr = errNum; } return rtnObj; }
/*! * \ingroup WlzValuesUtils * \brief static function to implement WlzGreyTransfer for 3D objects. * * \return woolz object * \param obj destination object * \param srcObj source object * \param dstErr error return * \par Source: * WlzGreyTransfer.c */ static WlzObject *WlzGreyTransfer3d( WlzObject *obj, WlzObject *srcObj, WlzErrorNum *dstErr) { WlzObject *rtnObj=NULL; WlzObject *obj1, *obj2, *tmpObj; WlzDomain *domains; WlzValues values, *valuess; WlzPlaneDomain *pdom; int p; WlzErrorNum errNum=WLZ_ERR_NONE; /* check the object - it is non-NULL and 3D but the domain needs checking */ if( obj->domain.p == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; } else { switch( obj->domain.p->type ){ case WLZ_2D_DOMAINOBJ: /* check there is a valuetable */ if( obj->values.core == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } else if(WlzGreyTableIsTiled(obj->values.core->type)) { errNum = WLZ_ERR_VALUES_TYPE; } break; default: errNum = WLZ_ERR_DOMAIN_TYPE; break; } } /* check the source object */ if( errNum == WLZ_ERR_NONE ){ if( srcObj == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; } else { switch( srcObj->type ){ case WLZ_3D_DOMAINOBJ: if( srcObj->domain.p ){ switch( srcObj->domain.p->type ){ case WLZ_2D_DOMAINOBJ: break; default: errNum = WLZ_ERR_DOMAIN_TYPE; break; } } else { errNum = WLZ_ERR_DOMAIN_NULL; } break; case WLZ_EMPTY_OBJ: return WlzCopyObject(obj, dstErr); default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } } /* now we have a 3D obj and 3D srcObject so run through the source and map values as required */ if( errNum == WLZ_ERR_NONE ){ WlzDomain *objDoms; WlzValues *objVals; /* attach a voxel table with empty values list */ values.vox = WlzMakeVoxelValueTb(obj->values.vox->type, obj->domain.p->plane1, obj->domain.p->lastpl, obj->values.vox->bckgrnd, NULL, NULL); rtnObj = WlzMakeMain(obj->type, obj->domain, values, NULL, NULL, &errNum); /* set some local variables */ pdom = rtnObj->domain.p; domains = rtnObj->domain.p->domains; valuess = rtnObj->values.vox->values; objDoms = obj->domain.p->domains; objVals = obj->values.vox->values; /* calculate the new valuetables */ for(p=pdom->plane1; p <= pdom->lastpl; p++, domains++, valuess++, objDoms++, objVals++){ if(((*domains).core)){ obj1 = WlzMakeMain(WLZ_2D_DOMAINOBJ, *objDoms, *objVals, NULL, NULL, &errNum); obj1 = WlzAssignObject(obj1, &errNum); if((p >= srcObj->domain.p->plane1) && (p <= srcObj->domain.p->lastpl) && (srcObj->domain.p->domains[p-srcObj->domain.p->plane1].core)){ obj2 = WlzMakeMain(WLZ_2D_DOMAINOBJ, srcObj->domain.p->domains[p-srcObj->domain.p->plane1], srcObj->values.vox->values[p-srcObj->domain.p->plane1], NULL, NULL, &errNum); } else { obj2 = WlzMakeEmpty(NULL); } obj2 = WlzAssignObject(obj2, &errNum); tmpObj = WlzGreyTransfer(obj1, obj2, &errNum); *valuess = WlzAssignValues(tmpObj->values, &errNum); WlzFreeObj(obj1); WlzFreeObj(obj2); WlzFreeObj(tmpObj); } } } if( dstErr ){ *dstErr = errNum; } return rtnObj; }
/*! * \return New 3D object. * \ingroup WlzAllocation * \brief Constructs a 3D domain object from 2D domain objects read * from the given files. Each file is read in turn and added * to the 3D object. An empty plane can be specified by * setting the file string to NULL. Either all or none of * the 2D objects must have values. When the 2D objects * have values then the background value of the first 2D * object is set to be the background value of the 3D object. * \param nFileStr Number of file strings. * \param fileStr File strings. * \param plane1 The plane coordinate of the first * 2D object. * \param xSz Column voxel size. * \param ySz Line voxel size. * \param zSz Plane voxel size. * \param dstErr Destination error pointer, may be NULL. */ WlzObject *WlzConstruct3DObjFromFile(int nFileStr, char **fileStr, int plane1, float xSz, float ySz, float zSz, WlzErrorNum *dstErr) { int idx, lastpl; WlzDomain dom3D; WlzValues val3D; WlzObject *obj2D = NULL, *obj3D = NULL; WlzPixelV bgd; FILE *fP = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; dom3D.core = NULL; val3D.core = NULL; lastpl = plane1 + nFileStr - 1; if((nFileStr <= 0) || (fileStr == NULL) || (*fileStr == NULL)) { errNum = WLZ_ERR_PARAM_NULL; } else { if((fP = fopen(*fileStr, "r")) == NULL) { errNum = WLZ_ERR_READ_EOF; } else { obj2D = WlzReadObj(fP, &errNum); (void )fclose(fP); fP = NULL; } } if(errNum == WLZ_ERR_NONE) { switch(obj2D->type) { case WLZ_EMPTY_OBJ: break; case WLZ_2D_DOMAINOBJ: if(obj2D->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* Make a plane domain, set column and line bounds later. */ if(errNum == WLZ_ERR_NONE) { dom3D.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, plane1, lastpl, 0, 1, 0, 1, &errNum); } if(errNum == WLZ_ERR_NONE) { dom3D.p->voxel_size[0] = xSz; dom3D.p->voxel_size[1] = ySz; dom3D.p->voxel_size[2] = zSz; } /* Make a voxel value table. */ if(errNum == WLZ_ERR_NONE) { if(obj2D->values.core) { bgd = WlzGetBackground(obj2D, &errNum); if(errNum == WLZ_ERR_NONE) { val3D.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, plane1, lastpl, bgd, NULL, &errNum); } } } idx = 0; while((errNum == WLZ_ERR_NONE) && (idx < nFileStr)) { if(obj2D) { switch(obj2D->type) { case WLZ_EMPTY_OBJ: break; case WLZ_2D_DOMAINOBJ: if(obj2D->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } if(errNum == WLZ_ERR_NONE) { *(dom3D.p->domains + idx) = WlzAssignDomain(obj2D->domain, NULL); if(val3D.core) { if((obj2D->domain.core != NULL) && (obj2D->values.core == NULL)) { errNum = WLZ_ERR_VALUES_NULL; } else { *(val3D.vox->values + idx) = WlzAssignValues(obj2D->values, NULL); } } } WlzFreeObj(obj2D); obj2D = NULL; } if(errNum == WLZ_ERR_NONE) { ++idx; if((idx < nFileStr) && *(fileStr + idx)) { if((fP = fopen(*(fileStr + idx), "r")) == NULL) { errNum = WLZ_ERR_READ_EOF; } else { obj2D = WlzReadObj(fP, &errNum); (void )fclose(fP); fP = NULL; } } } } if(errNum == WLZ_ERR_NONE) { errNum = WlzStandardPlaneDomain(dom3D.p, val3D.vox); } if(errNum == WLZ_ERR_NONE) { obj3D = WlzMakeMain(WLZ_3D_DOMAINOBJ, dom3D, val3D, NULL, NULL, &errNum); } if(errNum != WLZ_ERR_NONE) { if(dom3D.core) { (void )WlzFreeDomain(dom3D); } if(val3D.core) { (void )WlzFreeValues(val3D); } } if(dstErr) { *dstErr = errNum; } return(obj3D); }
/*! * \return Distance object which shares the given foreground object's * domain and has integer distance values, null on error. * \ingroup WlzMorphologyOps * \brief Computes the distance of every pixel/voxel in the foreground * object from the reference object. * * A distance transform maps all position within a forground * domain to their distances from a reference domain. * The distance transforms implemented within this function * use efficient morphological primitives. * * Given two domains, * \f$\Omega_r\f$ the reference domain and \f$\Omega_f\f$ * the domain specifying the region of interest, * a domain with a thin shell \f$\Omega_i\f$ * is iteratively expanded from it's initial domain * corresponding to the reference domain \f$\Omega_r\f$. * At each iteration * \f$\Omega_i\f$ is dilated and clipped * by it's intersection with \f$\Omega_f\f$ until \f$\Omega_i\f$ * becomes the null domain \f$\emptyset\f$. * At each iteration the current distance is recorded in a value * table which * covers the domain \f$\Omega_f\f$. * * An octagonal distance scheme may be used in which * the distance metric is alternated between 4 and 8 * connected for 2D and 6 and 26 connectivities in 3D. * See: G. Borgefors. "Distance Transformations in Arbitrary * Dimensions" CVGIP 27:321-345, 1984. * * An approximate Euclidean distance transform may be computed * by: Scaling the given foreground and reference objects using * the given approximation scale parameter, dilating the * reference domain using a sphere with a radius having the same * value as the scale parameter and then finaly sampling the * scaled distances. * \param forObj Foreground object. * \param refObj Reference object. * \param dFn Distance function which must be * appropriate to the dimension of * the foreground and reference objects. * \param dParam Parameter required for distance * function. Currently only * WLZ_APX_EUCLIDEAN_DISTANCE requires a * parameter. In this case the parameter * is the approximation scale. * \param dstErr Destination error pointer, may be NULL. */ WlzObject *WlzDistanceTransform(WlzObject *forObj, WlzObject *refObj, WlzDistanceType dFn, double dParam, WlzErrorNum *dstErr) { int idP, lastP, dim, notDone = 1; double scale; WlzObject *tmpObj, *sObj = NULL, *sForObj = NULL, *sRefObj = NULL, *dilObj = NULL, *dstObj = NULL, *difObj = NULL, *curItrObj = NULL; WlzObject *bothObj[2]; WlzDomain *difDoms; WlzPixelV dstV, bgdV; WlzValues *difVals; WlzAffineTransform *tr = NULL; WlzConnectType con; WlzObjectType dstGType; WlzErrorNum errNum = WLZ_ERR_NONE; WlzValues difVal, dstVal, nullVal; /* By defining WLZ_DIST_TRANSFORM_ENV these normalization parameters * are read from the environment. This is useful for optimization. */ #ifndef WLZ_DIST_TRANSFORM_ENV const #endif /* ! WLZ_DIST_TRANSFORM_ENV */ /* These normalizarion factors have been choosen to minimize the sum of * squares of the deviation of the distance values from Euclidean values * over a radius 100 circle or sphere, where the distances are computed * from the circumference of the sphere towards it's centre. The values * were established by experiment. */ double nrmDist4 = 0.97, nrmDist6 = 0.91, nrmDist8 = 1.36, nrmDist18 = 1.34, nrmDist26 = 1.60; #ifdef WLZ_DIST_TRANSFORM_ENV double val; char *envStr; if(((envStr = getenv("WLZ_DIST_TRANSFORM_NRMDIST4")) != NULL) && (sscanf(envStr, "%lg", &val) == 1)) { nrmDist4 = val; } if(((envStr = getenv("WLZ_DIST_TRANSFORM_NRMDIST6")) != NULL) && (sscanf(envStr, "%lg", &val) == 1)) { nrmDist6 = val; } if(((envStr = getenv("WLZ_DIST_TRANSFORM_NRMDIST8")) != NULL) && (sscanf(envStr, "%lg", &val) == 1)) { nrmDist8 = val; } if(((envStr = getenv("WLZ_DIST_TRANSFORM_NRMDIST18")) != NULL) && (sscanf(envStr, "%lg", &val) == 1)) { nrmDist18 = val; } if(((envStr = getenv("WLZ_DIST_TRANSFORM_NRMDIST26")) != NULL) && (sscanf(envStr, "%lg", &val) == 1)) { nrmDist26 = val; } #endif /* WLZ_DIST_TRANSFORM_ENV */ scale = dParam; nullVal.core = NULL; /* Check parameters. */ if((forObj == NULL) || (refObj == NULL)) { errNum = WLZ_ERR_OBJECT_NULL; } else if(((forObj->type != WLZ_2D_DOMAINOBJ) && (forObj->type != WLZ_3D_DOMAINOBJ)) || ((refObj->type != WLZ_POINTS) && (refObj->type != forObj->type))) { errNum = WLZ_ERR_OBJECT_TYPE; } else if((forObj->domain.core == NULL) || (refObj->domain.core == NULL)) { errNum = WLZ_ERR_DOMAIN_NULL; } if(errNum == WLZ_ERR_NONE) { bgdV.type = WLZ_GREY_INT; bgdV.v.inv = 0; dstV.type = WLZ_GREY_DOUBLE; dstV.v.dbv = 0.0; switch(forObj->type) { case WLZ_2D_DOMAINOBJ: switch(dFn) { case WLZ_4_DISTANCE: /* FALLTHROUGH */ case WLZ_8_DISTANCE: /* FALLTHROUGH */ case WLZ_OCTAGONAL_DISTANCE: /* FALLTHROUGH */ case WLZ_APX_EUCLIDEAN_DISTANCE: dim = 2; break; default: errNum = WLZ_ERR_PARAM_DATA; break; } break; case WLZ_3D_DOMAINOBJ: switch(dFn) { case WLZ_6_DISTANCE: /* FALLTHROUGH */ case WLZ_18_DISTANCE: /* FALLTHROUGH */ case WLZ_26_DISTANCE: /* FALLTHROUGH */ case WLZ_OCTAGONAL_DISTANCE: /* FALLTHROUGH */ case WLZ_APX_EUCLIDEAN_DISTANCE: dim = 3; break; default: errNum = WLZ_ERR_PARAM_DATA; break; } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if(errNum == WLZ_ERR_NONE) { switch(dFn) { case WLZ_4_DISTANCE: con = WLZ_4_CONNECTED; break; case WLZ_6_DISTANCE: con = WLZ_6_CONNECTED; break; case WLZ_8_DISTANCE: con = WLZ_8_CONNECTED; break; case WLZ_18_DISTANCE: con = WLZ_18_CONNECTED; break; case WLZ_26_DISTANCE: con = WLZ_26_CONNECTED; break; case WLZ_OCTAGONAL_DISTANCE: con = (dim == 2)? WLZ_8_CONNECTED: WLZ_26_CONNECTED; break; case WLZ_APX_EUCLIDEAN_DISTANCE: con = (dim == 2)? WLZ_8_CONNECTED: WLZ_26_CONNECTED; if(scale < 1.0) { errNum = WLZ_ERR_PARAM_DATA; } break; case WLZ_EUCLIDEAN_DISTANCE: errNum = WLZ_ERR_UNIMPLEMENTED; break; default: errNum = WLZ_ERR_PARAM_DATA; break; } } /* Create scaled domains and a sphere domain for structual erosion if the * distance function is approximate Euclidean. */ if(errNum == WLZ_ERR_NONE) { if(dFn == WLZ_APX_EUCLIDEAN_DISTANCE) { tr = (dim == 2)? WlzAffineTransformFromScale(WLZ_TRANSFORM_2D_AFFINE, scale, scale, 0.0, &errNum): WlzAffineTransformFromScale(WLZ_TRANSFORM_3D_AFFINE, scale, scale, scale, &errNum); if(errNum == WLZ_ERR_NONE) { tmpObj = WlzMakeMain(forObj->type, forObj->domain, nullVal, NULL, NULL, &errNum); if(tmpObj) { sForObj = WlzAssignObject( WlzAffineTransformObj(tmpObj, tr, WLZ_INTERPOLATION_NEAREST, &errNum), NULL); (void )WlzFreeObj(tmpObj); } } if(errNum == WLZ_ERR_NONE) { if(refObj->type == WLZ_POINTS) { sRefObj = WlzPointsToDomObj(refObj->domain.pts, scale, &errNum); } else /* type == WLZ_2D_DOMAINOBJ || type == WLZ_3D_DOMAINOBJ */ { tmpObj = WlzMakeMain(refObj->type, refObj->domain, nullVal, NULL, NULL, &errNum); if(errNum == WLZ_ERR_NONE) { sRefObj = WlzAssignObject( WlzAffineTransformObj(tmpObj, tr, WLZ_INTERPOLATION_NEAREST, &errNum), NULL); } } (void )WlzFreeObj(tmpObj); } if(errNum == WLZ_ERR_NONE) { sObj = WlzAssignObject( WlzMakeSphereObject(forObj->type, scale, 0.0, 0.0, 0.0, &errNum), NULL); } (void )WlzFreeAffineTransform(tr); } else { sForObj = WlzAssignObject( WlzMakeMain(forObj->type, forObj->domain, nullVal, NULL, NULL, &errNum), NULL); if(errNum == WLZ_ERR_NONE) { if(refObj->type == WLZ_POINTS) { sRefObj = WlzPointsToDomObj(refObj->domain.pts, 1.0, &errNum); } else { sRefObj = WlzAssignObject( WlzMakeMain(refObj->type, refObj->domain, nullVal, NULL, NULL, &errNum), NULL); } } } } /* Create new values for the computed distances. */ if(errNum == WLZ_ERR_NONE) { dstGType = WlzGreyTableType(WLZ_GREY_TAB_RAGR, WLZ_GREY_INT, NULL); if(dim == 2) { dstVal.v = WlzNewValueTb(sForObj, dstGType, bgdV, &errNum); } else { dstVal.vox = WlzNewValuesVox(sForObj, dstGType, bgdV, &errNum); } } /* Create a distance object using the foreground object's domain and * the new distance values. */ if(errNum == WLZ_ERR_NONE) { dstObj = WlzMakeMain(sForObj->type, sForObj->domain, dstVal, NULL, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { bothObj[0] = sForObj; errNum = WlzGreySetValue(dstObj, dstV); } /* Dilate the reference object while setting the distances in each * dilated shell. */ while((errNum == WLZ_ERR_NONE) && notDone) { if(dFn == WLZ_APX_EUCLIDEAN_DISTANCE) { dstV.v.dbv += 1.0; } else { switch(con) { case WLZ_4_CONNECTED: dstV.v.dbv += nrmDist4; break; case WLZ_6_CONNECTED: dstV.v.dbv += nrmDist6; break; case WLZ_8_CONNECTED: dstV.v.dbv += nrmDist8; break; case WLZ_18_CONNECTED: dstV.v.dbv += nrmDist18; break; case WLZ_26_CONNECTED: dstV.v.dbv += nrmDist26; break; default: errNum = WLZ_ERR_CONNECTIVITY_TYPE; break; } } if(dFn == WLZ_APX_EUCLIDEAN_DISTANCE) { dilObj = WlzStructDilation(sRefObj, sObj, &errNum); } else { dilObj = WlzDilation(sRefObj, con, &errNum); } if(errNum == WLZ_ERR_NONE) { switch(sForObj->type) { case WLZ_2D_DOMAINOBJ: curItrObj = WlzAssignObject( WlzIntersect2(dilObj, sForObj, &errNum), NULL); break; case WLZ_3D_DOMAINOBJ: bothObj[1] = dilObj; curItrObj = WlzAssignObject( WlzIntersectN(2, bothObj, 1, &errNum), NULL); break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } (void)WlzFreeObj(dilObj); /* Create difference object for the expanding shell. */ if(errNum == WLZ_ERR_NONE) { difObj = WlzDiffDomain(curItrObj, sRefObj, &errNum); } if((difObj == NULL) || WlzIsEmpty(difObj, &errNum)) { notDone = 0; } else { /* Assign the distance object's values to the difference object * and set all it's values to the current distance. */ if(errNum == WLZ_ERR_NONE) { switch(sForObj->type) { case WLZ_2D_DOMAINOBJ: difObj->values = WlzAssignValues(dstObj->values, NULL); errNum = WlzGreySetValue(difObj, dstV); break; case WLZ_3D_DOMAINOBJ: /* 3D is more complex than 2D: Need to create a temporary * voxel valuetable and assign the individual 2D values. */ difVal.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, difObj->domain.p->plane1, difObj->domain.p->lastpl, bgdV, NULL, &errNum); if(errNum == WLZ_ERR_NONE) { difObj->values = WlzAssignValues(difVal, NULL); difDoms = difObj->domain.p->domains; difVals = difObj->values.vox->values; idP = difObj->domain.p->plane1; lastP = difObj->domain.p->lastpl; while(idP <= lastP) { if((*difDoms).core) { dstVal = dstObj->values.vox->values[idP - dstObj->domain.p->plane1]; *difVals = WlzAssignValues(dstVal, NULL); } ++idP; ++difDoms; ++difVals; } if(difObj->domain.p->lastpl > difObj->domain.p->plane1) { errNum = WlzGreySetValue(difObj, dstV); } } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } (void )WlzFreeObj(sRefObj); sRefObj = WlzAssignObject(curItrObj, NULL); (void )WlzFreeObj(curItrObj); } (void )WlzFreeObj(difObj); difObj = NULL; if(dFn == WLZ_OCTAGONAL_DISTANCE) { /* Alternate connectivities for octagonal distance. */ if(dim == 2) { con = (con == WLZ_4_CONNECTED)? WLZ_8_CONNECTED: WLZ_4_CONNECTED; } else /* dim == 3 */ { con = (con == WLZ_6_CONNECTED)? WLZ_26_CONNECTED: WLZ_6_CONNECTED; } } } (void )WlzFreeObj(sObj); (void )WlzFreeObj(sForObj); (void )WlzFreeObj(sRefObj); (void )WlzFreeObj(curItrObj); if((errNum == WLZ_ERR_NONE) && (dFn == WLZ_APX_EUCLIDEAN_DISTANCE)) { tmpObj = WlzDistSample(dstObj, dim, scale, &errNum); (void )WlzFreeObj(dstObj); dstObj = tmpObj; } if(errNum != WLZ_ERR_NONE) { (void )WlzFreeObj(dstObj); dstObj = NULL; } if(dstErr) { *dstErr = errNum; } return(dstObj); }
static WlzObject *WlzGreyTemplate3d( WlzObject *obj, WlzObject *tmpl, WlzPixelV tmplVal, WlzErrorNum *dstErr) { WlzObject *rtnObj=NULL; WlzObject *tmpObj = NULL, *obj1 = NULL, *obj2 = NULL; WlzDomain domain, *domains; WlzValues values, *valuess; WlzPlaneDomain *pdom; int p; WlzErrorNum errNum=WLZ_ERR_NONE; /* check the object - it is non-NULL and 3D but the domain needs checking */ if( obj->domain.p == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; } else { switch( obj->domain.p->type ){ case WLZ_2D_DOMAINOBJ: /* check there is a valuetable */ if( obj->values.core == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } else if( WlzGreyTableIsTiled(obj->values.core->type) ){ errNum = WLZ_ERR_VALUES_TYPE; } break; default: errNum = WLZ_ERR_DOMAIN_TYPE; break; } } /* check the template and create the return object */ if( errNum == WLZ_ERR_NONE ){ if( tmpl == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; } else { values.core = NULL; switch( tmpl->type ){ case WLZ_2D_DOMAINOBJ: pdom = obj->domain.p; if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, pdom->plane1, pdom->lastpl, pdom->line1, pdom->lastpl, pdom->kol1, pdom->lastkl, &errNum)) != NULL){ domain.p->voxel_size[0] = pdom->voxel_size[0]; domain.p->voxel_size[1] = pdom->voxel_size[1]; domain.p->voxel_size[2] = pdom->voxel_size[2]; for(p=pdom->plane1; p <= pdom->lastpl; p++){ domain.p->domains[p - pdom->plane1] = WlzAssignDomain(tmpl->domain, NULL); } rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values, NULL, NULL, &errNum); } break; case WLZ_2D_POLYGON: pdom = obj->domain.p; if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, pdom->plane1, pdom->lastpl, pdom->line1, pdom->lastpl, pdom->kol1, pdom->lastkl, &errNum)) != NULL){ domain.p->voxel_size[0] = pdom->voxel_size[0]; domain.p->voxel_size[1] = pdom->voxel_size[1]; domain.p->voxel_size[2] = pdom->voxel_size[2]; obj1 = WlzPolyToObj(tmpl->domain.poly, WLZ_SIMPLE_FILL, &errNum); for(p=pdom->plane1; p <= pdom->lastpl; p++){ domain.p->domains[p - pdom->plane1] = WlzAssignDomain(obj1->domain, NULL); } WlzFreeObj(obj1); rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values, NULL, NULL, &errNum); } break; case WLZ_BOUNDLIST: pdom = obj->domain.p; if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, pdom->plane1, pdom->lastpl, pdom->line1, pdom->lastpl, pdom->kol1, pdom->lastkl, &errNum)) != NULL){ domain.p->voxel_size[0] = pdom->voxel_size[0]; domain.p->voxel_size[1] = pdom->voxel_size[1]; domain.p->voxel_size[2] = pdom->voxel_size[2]; obj1 = WlzBoundToObj(tmpl->domain.b, WLZ_SIMPLE_FILL, &errNum); for(p=pdom->plane1; p <= pdom->lastpl; p++){ domain.p->domains[p - pdom->plane1] = WlzAssignDomain(obj1->domain, NULL); } WlzFreeObj(obj1); rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values, NULL, NULL, &errNum); } break; case WLZ_3D_DOMAINOBJ: if( tmpl->domain.p ){ switch( tmpl->domain.p->type ){ case WLZ_2D_DOMAINOBJ: domain.p = tmpl->domain.p; break; case WLZ_PLANEDOMAIN_POLYGON: case WLZ_PLANEDOMAIN_CONV_HULL: pdom = tmpl->domain.p; if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, pdom->plane1, pdom->lastpl, pdom->line1, pdom->lastpl, pdom->kol1, pdom->lastkl, &errNum)) != NULL){ domain.p->voxel_size[0] = pdom->voxel_size[0]; domain.p->voxel_size[1] = pdom->voxel_size[1]; domain.p->voxel_size[2] = pdom->voxel_size[2]; for(p=pdom->plane1; p <= pdom->lastpl; p++){ if( pdom->domains[p-pdom->plane1].core ){ obj1 = WlzPolyToObj(pdom->domains[p-pdom->plane1].poly, WLZ_SIMPLE_FILL, &errNum); domain.p->domains[p - pdom->plane1] = WlzAssignDomain(obj1->domain, NULL); } WlzFreeObj(obj1); } values.core = NULL; rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values, NULL, NULL, &errNum); } break; case WLZ_PLANEDOMAIN_BOUNDLIST: pdom = tmpl->domain.p; if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, pdom->plane1, pdom->lastpl, pdom->line1, pdom->lastpl, pdom->kol1, pdom->lastkl, &errNum)) != NULL){ domain.p->voxel_size[0] = pdom->voxel_size[0]; domain.p->voxel_size[1] = pdom->voxel_size[1]; domain.p->voxel_size[2] = pdom->voxel_size[2]; for(p=pdom->plane1; p <= pdom->lastpl; p++){ if( pdom->domains[p-pdom->plane1].core ){ obj1 = WlzBoundToObj(pdom->domains[p-pdom->plane1].b, WLZ_SIMPLE_FILL, &errNum); domain.p->domains[p - pdom->plane1] = WlzAssignDomain(obj1->domain, NULL); } WlzFreeObj(obj1); } values.core = NULL; rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values, NULL, NULL, &errNum); } break; default: errNum = WLZ_ERR_DOMAIN_TYPE; break; } if( errNum == WLZ_ERR_NONE ){ rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values, NULL, NULL, &errNum); } } else { errNum = WLZ_ERR_DOMAIN_NULL; } break; case WLZ_EMPTY_OBJ: return WlzMakeEmpty(dstErr); default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } } /* now we have a 3D obj and 3D template so run through the template and map values as required, note we must check that all the valuetables have the same type ie switch to obj type if necessary */ if( errNum == WLZ_ERR_NONE ){ WlzDomain *objDoms; WlzValues *objVals; WlzGreyType gtype=WLZ_GREY_UBYTE; /* attach a voxel table with empty values list */ values.vox = WlzMakeVoxelValueTb(obj->values.vox->type, rtnObj->domain.p->plane1, rtnObj->domain.p->lastpl, obj->values.vox->bckgrnd, NULL, NULL); rtnObj->values = WlzAssignValues(values, NULL); /* set some local variables */ pdom = rtnObj->domain.p; domains = rtnObj->domain.p->domains; valuess = rtnObj->values.vox->values; objDoms = obj->domain.p->domains; objVals = obj->values.vox->values; /* calculate the new valuetables */ for(p=pdom->plane1; p <= pdom->lastpl; p++, domains++, valuess++){ if(((*domains).core)){ if((p >= obj->domain.p->plane1) && (p <= obj->domain.p->lastpl) && (objDoms[p - obj->domain.p->plane1].core) ){ tmpObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, objDoms[p - obj->domain.p->plane1], objVals[p - obj->domain.p->plane1], NULL, NULL, NULL); gtype = WlzGreyTableTypeToGreyType(tmpObj->values.core->type, NULL); } else { tmpObj = WlzMakeEmpty(NULL); } tmpObj = WlzAssignObject(tmpObj, NULL); values.core = NULL; obj1 = WlzAssignObject( WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, values, NULL, NULL, NULL), NULL); if((obj2 = WlzGreyTemplate(tmpObj, obj1, tmplVal, &errNum)) != NULL){ *valuess = WlzAssignValues(obj2->values, NULL); WlzFreeObj(obj2); } WlzFreeObj(obj1); WlzFreeObj(tmpObj); } } /* now check all valuetables have the same grey type */ domains = rtnObj->domain.p->domains; valuess = rtnObj->values.vox->values; for(p=pdom->plane1; p <= pdom->lastpl; p++, domains++, valuess++){ if((*domains).core && (WlzGreyTableTypeToGreyType((*valuess).core->type, NULL) != gtype)){ obj1 = WlzAssignObject( WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *valuess, NULL, NULL, NULL), NULL); if((obj2 = WlzConvertPix(obj1, gtype, &errNum)) != NULL){ /* substitute the valuetable in the voxel table array */ WlzFreeValues(*valuess); *valuess = WlzAssignValues(obj2->values, NULL); WlzFreeObj(obj2); } WlzFreeObj(obj1); } } } if( dstErr ){ *dstErr = errNum; } return rtnObj; }
/*! * \return New 3D domain object. * \ingroup WlzArithmetic * \brief Computes a new 3D object which shares the domain of the given * object, but which has grey values that are the result of * applying the given function to the grey values of the * given object. * \param sObj Given source domain object with values. * \param fn Scalar function to be applied. * \param dstErr Destination error pointer, may be NULL. */ static WlzObject *WlzScalarFn3D(WlzObject *sObj, WlzFnType fn, WlzErrorNum *dstErr) { int idx, off; WlzPixelV sBgd, dBgd; WlzValues dVal; WlzObject *sObj2D, *dObj2D, *dObj = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; if(errNum == WLZ_ERR_NONE) { sBgd = WlzGetBackground(sObj, &errNum); } if(errNum == WLZ_ERR_NONE) { dBgd = WlzScalarFnPixel(sBgd, fn, &errNum); } if(errNum == WLZ_ERR_NONE) { dVal.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, sObj->domain.p->plane1, sObj->domain.p->lastpl, dBgd, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { for(idx = sObj->domain.p->plane1; idx <= sObj->domain.p->lastpl; ++idx) { off = idx - sObj->domain.p->plane1; dObj2D = NULL; sObj2D = WlzMakeMain(WLZ_2D_DOMAINOBJ, *(sObj->domain.p->domains + off), *(sObj->values.vox->values + off), NULL, NULL, &errNum); if(errNum == WLZ_ERR_NONE) { dObj2D = WlzScalarFn2D(sObj2D, fn, &errNum); } WlzFreeObj(sObj2D); if(errNum == WLZ_ERR_NONE) { *(dVal.vox->values + off) = WlzAssignValues(dObj2D->values, NULL); } WlzFreeObj(dObj2D); } } if(errNum == WLZ_ERR_NONE) { dObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, sObj->domain, dVal, NULL, NULL, &errNum); } if(dstErr) { *dstErr = errNum; } return(dObj); }
static WlzObject *WlzIndexToRGBA3D( WlzObject *obj, unsigned char colormap[3][256], WlzErrorNum *dstErr) { WlzObject *obj1, *temp; WlzPlaneDomain *pdom, *npdom; WlzVoxelValues *voxtab, *nvoxtab; WlzDomain *domains, *ndomains, domain; WlzValues *values, *nvalues, vals; int i, nplanes; WlzErrorNum errNum=WLZ_ERR_NONE; /* no need to check the object pointer or type because this procedure can only be accessed via WlzIndexToRGBA. The domain and valuetable must be checked however */ obj1 = NULL; if( obj->domain.p == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; } else if( obj->values.vox == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } /* check types */ if( errNum == WLZ_ERR_NONE ){ switch( obj->domain.p->type ){ case WLZ_PLANEDOMAIN_DOMAIN: break; default: errNum = WLZ_ERR_PLANEDOMAIN_TYPE; break; } } if( errNum == WLZ_ERR_NONE ){ switch( obj->values.vox->type ){ case WLZ_VOXELVALUETABLE_GREY: break; default: errNum = WLZ_ERR_VOXELVALUES_TYPE; break; } } /* make new planedomain and voxelvaluetable */ if( errNum == WLZ_ERR_NONE ){ pdom = obj->domain.p; voxtab = obj->values.vox; npdom = WlzMakePlaneDomain(pdom->type, pdom->plane1, pdom->lastpl, pdom->line1, pdom->lastln, pdom->kol1, pdom->lastkl, &errNum); } if((errNum == WLZ_ERR_NONE) && ((nvoxtab = WlzMakeVoxelValueTb(voxtab->type, voxtab->plane1, voxtab->lastpl, voxtab->bckgrnd, NULL, &errNum)) == NULL) ){ WlzFreePlaneDomain(npdom); } if( errNum == WLZ_ERR_NONE ){ /* set up variables */ domains = pdom->domains; ndomains = npdom->domains; values = voxtab->values; nvalues = nvoxtab->values; nplanes = pdom->lastpl - pdom->plane1 + 1; /* copy voxel_sizes */ for(i=0; i < 3; i++){ npdom->voxel_size[i] = pdom->voxel_size[i]; } } /* convert each plane */ while( (errNum == WLZ_ERR_NONE) && nplanes-- ){ if(((*domains).core == NULL) || ((*values).core == NULL)){ (*ndomains).core = NULL; (*nvalues).core = NULL; } else if((temp = WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *values, NULL, NULL, &errNum)) != NULL){ if( temp->domain.i != NULL ){ if((obj1 = WlzIndexToRGBA(temp, colormap, &errNum)) != NULL){ if( obj1->type == WLZ_2D_DOMAINOBJ ){ *ndomains = WlzAssignDomain(obj1->domain, NULL); *nvalues = WlzAssignValues(obj1->values, NULL); } else { (*ndomains).core = NULL; (*nvalues).core = NULL; } WlzFreeObj(obj1); } } else { (*ndomains).core = NULL; (*nvalues).core = NULL; } } else { WlzFreePlaneDomain(npdom); WlzFreeVoxelValueTb( nvoxtab ); break; } domains++; ndomains++; values++; nvalues++; } /* return a new object */ if( errNum == WLZ_ERR_NONE ){ domain.p = npdom; vals.vox = nvoxtab; if((obj1 = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, vals, NULL, obj, &errNum)) != NULL){ /* nvoxtab->original = obj1; */ nvoxtab->original_table = WlzAssignValues(obj->values, NULL); } else { WlzFreePlaneDomain( npdom ); WlzFreeVoxelValueTb( nvoxtab ); } } if( dstErr ){ *dstErr = errNum; } return obj1; }
/*! * \return New 3D domain object with corresponding WLZ_GREY_RGBA values. * \ingroup WlzValuesUtils * \brief Creates a WLZ_GREY_RGBA valued object from the given compound * array. This is a static function which will always be called * with valid parameters so they aren't checked. * \param cObj Compound array object. * \param cSpc The colour space. * \param dstErr Destination error pointer may be NULL. */ static WlzObject *WlzCompoundToRGBA3D(WlzCompoundArray *cObj, WlzRGBAColorSpace cSpc, WlzErrorNum *dstErr) { WlzIBox3 bBox; WlzDomain dom; WlzValues val; WlzPixelV bgd; WlzObject *rObj = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; dom.core = NULL; val.core = NULL; bgd.v.rgbv = 0; bgd.type = WLZ_GREY_RGBA; bBox = WlzBoundingBox3I((WlzObject *)cObj, &errNum); if(errNum == WLZ_ERR_NONE) { dom.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, bBox.zMin, bBox.zMax, bBox.yMin, bBox.yMax, bBox.xMin, bBox.xMax, &errNum); } if(errNum == WLZ_ERR_NONE) { val.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, bBox.zMin, bBox.zMax, bgd, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { rObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, dom, val, NULL, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { int idP, nPl; nPl = bBox.zMax - bBox.zMin + 1; for(idP = 0; idP < nPl; ++idP) { if(errNum == WLZ_ERR_NONE) { int idC; WlzObject *rObj2 = NULL; WlzCompoundArray *cObj2 = NULL; WlzErrorNum errNum2 = WLZ_ERR_NONE; cObj2 = WlzMakeCompoundArray(WLZ_COMPOUND_ARR_2, 1, cObj->n, NULL, WLZ_2D_DOMAINOBJ, &errNum2); idC = 0; while((errNum2 == WLZ_ERR_NONE) && (idC < cObj->n)) { int idP2, nPl2; WlzDomain dom2; WlzValues val2; dom2.core = NULL; val2.core = NULL; if((cObj->o[idC] != NULL) && (cObj->o[idC]->type == WLZ_3D_DOMAINOBJ)) { idP2 = bBox.zMin + idP - cObj->o[idC]->domain.p->plane1; nPl2 = cObj->o[idC]->domain.p->lastpl - cObj->o[idC]->domain.p->plane1 + 1; if((idP2 >= 0) && (idP2 <= nPl2)) { dom2 = *(cObj->o[idC]->domain.p->domains + idP2); val2 = *(cObj->o[idC]->values.vox->values + idP2); } } cObj2->o[idC] = (dom2.core == NULL)? WlzMakeEmpty(&errNum2): WlzMakeMain(WLZ_2D_DOMAINOBJ, dom2, val2, NULL, NULL, &errNum2); ++idC; } if(errNum2 == WLZ_ERR_NONE) { rObj2 = WlzCompoundToRGBA2D(cObj2, cSpc, &errNum2); } if(errNum2 == WLZ_ERR_NONE) { dom.p->domains[idP] = WlzAssignDomain(rObj2->domain, NULL); val.vox->values[idP] = WlzAssignValues(rObj2->values, NULL); } (void )WlzFreeObj(rObj2); (void )WlzFreeObj((WlzObject *)cObj2); if(errNum2 != WLZ_ERR_NONE) { errNum = errNum2; } } } } if(errNum != WLZ_ERR_NONE) { if(rObj != NULL) { (void )WlzFreeObj(rObj); rObj = NULL; } else { (void )WlzFreePlaneDomain(dom.p); (void )WlzFreeVoxelValueTb(val.vox); } } if(dstErr) { *dstErr = errNum; } return(rObj); }
int main(int argc, char **argv) { WlzObject *obj1 = NULL, *obj = NULL, **objlist = NULL, *rtnObj = NULL; WlzObjectType type = (WlzObjectType) -1; int i, n, nmax, p; FILE *inFile; char optList[] = "d:mn:h"; int option; int meanFlg=0; WlzPixelV bckgrnd; WlzValues values; const char *errMsg; WlzErrorNum errNum = WLZ_ERR_NONE; /* setup the return object type and background */ bckgrnd.type = WLZ_GREY_INT; bckgrnd.v.inv = 0; /* read the argument list and check for an input file */ opterr = 0; nmax = 100; rtnObj = NULL; while( (option = getopt(argc, argv, optList)) != EOF ){ switch( option ){ /* read in a target domain over which to capture the occupancy, set grey type to WLZ_GREY_INT and value to zero */ case 'd': if((inFile = fopen(optarg, "rb")) != NULL){ if((obj = WlzReadObj(inFile, &errNum)) != NULL){ if( (rtnObj = WlzAddValuesTable(obj, WLZ_GREY_INT, bckgrnd, &errNum)) == NULL ){ (void )WlzStringFromErrorNum(errNum, &errMsg); fprintf(stderr, "%s: Failed to add values table to occupancy object: %s\n", argv[0], errMsg); return 1; } errNum = WlzGreySetValue(rtnObj, bckgrnd); WlzFreeObj(obj); } else { fprintf(stderr, "%s: Can't read occupancy domain file\n", argv[0]); usage(argv[0]); } fclose(inFile); } else { fprintf(stderr, "%s: Can't open occupancy domain file\n", argv[0]); usage(argv[0]); } break; case 'm': meanFlg = 1; break; case 'n': nmax = atoi(optarg); if( nmax < 1 ){ fprintf(stderr, "%s: nmax = %d is invalid\n", argv[0], nmax); usage(argv[0]); return( 1 ); } break; case 'h': default: usage(argv[0]); return( 1 ); } } inFile = stdin; if( optind < argc ){ if( (inFile = fopen(*(argv+optind), "rb")) == NULL ){ fprintf(stderr, "%s: can't open file %s\n", argv[0], *(argv+optind)); usage(argv[0]); return( 1 ); } } /* allocate space for the object pointers */ if( (objlist = (WlzObject **) AlcMalloc(sizeof(WlzObject *) * nmax)) == NULL ){ (void )fprintf(stderr, "%s: memory allocation failed.\n", argv[0]); return( 1 ); } /* read objects accumulating compatible types */ n = 0; while( ((obj = WlzAssignObject(WlzReadObj(inFile, NULL), NULL)) != NULL) && (n < nmax) ) { if( type == -1 && (obj->type == WLZ_2D_DOMAINOBJ || obj->type == WLZ_3D_DOMAINOBJ) ){ type = obj->type; } if( obj->type == type ){ objlist[n++] = WlzAssignObject(obj, NULL); } else { WlzFreeObj( obj ); } } if( type == WLZ_EMPTY_OBJ ){ return( 0 ); } /* check for occupancy object */ if( rtnObj ){ /* check type against return object - must be the same */ if( type != rtnObj->type ){ fprintf(stderr, "%s: Occupancy domain object type does not match\n" " inout domain type\n", argv[0]); usage(argv[0]); return 1; } } else { /* use the union of input domains as the occupancy object */ if((obj1 = WlzUnionN(n, objlist, 1, &errNum)) == NULL) { (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to perform union (%s).\n", argv[0], errMsg); return(1); } rtnObj = WlzAddValuesTable(obj1, WLZ_GREY_INT, bckgrnd, &errNum); errNum = WlzGreySetValue(rtnObj, bckgrnd); WlzFreeObj(obj1); } /* now add 1 to each pixel for each domain */ bckgrnd.v.inv = 1; for(i=0; i < n; i++){ if((obj1 = WlzIntersect2(rtnObj, objlist[i], &errNum)) != NULL){ if( obj1->type != WLZ_EMPTY_OBJ ){ if( obj1->type == WLZ_2D_DOMAINOBJ ){ obj1->values = WlzAssignValues(rtnObj->values, &errNum); } else { values.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, obj1->domain.p->plane1, obj1->domain.p->lastpl, bckgrnd, NULL, &errNum); obj1->values = WlzAssignValues(values, &errNum); for(p=obj1->domain.p->plane1; p <= obj1->domain.p->lastpl; p++){ values.vox->values[p-obj1->domain.p->plane1] = WlzAssignValues(rtnObj->values.vox->values[p-rtnObj->domain.p->plane1], &errNum); } } errNum = WlzGreyScalarAddValue(obj1, bckgrnd); } WlzFreeObj(obj1); } } /* output occupancy object */ if( rtnObj ){ if( meanFlg ){ bckgrnd.v.inv = 255; errNum = WlzGreyScalarMultValue(rtnObj, bckgrnd); bckgrnd.v.inv = n; errNum = WlzGreyScalarDivValue(rtnObj, bckgrnd); } WlzWriteObj(stdout, rtnObj); } /* freespace so purify can check for leaks */ while( n-- ){ WlzFreeObj(objlist[n]); } AlcFree((void *) objlist); return( 0 ); }
WlzObject *WlzAddValuesTable( WlzObject *obj, WlzGreyType gtype, WlzPixelV bckgrnd, WlzErrorNum *dstErr) { WlzObject *rtnObj=NULL; WlzObjectType type; WlzValues values, *valuess; WlzDomain *domains; WlzObject *tmpObj; int p; WlzErrorNum errNum=WLZ_ERR_NONE; /* check inputs */ if( obj == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; } else { switch( obj->type ){ case WLZ_2D_DOMAINOBJ: type = WlzGreyTableType(WLZ_GREY_TAB_RAGR, gtype, NULL); values.v = WlzNewValueTb(obj, type, bckgrnd, &errNum); rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, obj->domain, values, NULL, NULL, &errNum); break; case WLZ_3D_DOMAINOBJ: values.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, obj->domain.p->plane1, obj->domain.p->lastpl, bckgrnd, NULL, &errNum); rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, obj->domain, values, NULL, NULL, &errNum); domains = rtnObj->domain.p->domains; valuess = rtnObj->values.vox->values; type = WlzGreyTableType(WLZ_GREY_TAB_RAGR, WLZ_GREY_INT, &errNum); for(p=0; p < (rtnObj->domain.p->lastpl - rtnObj->domain.p->plane1 + 1); p++, domains++, valuess++){ if( (*domains).core ){ values.core = NULL; tmpObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, values, NULL, NULL, NULL); values.v = WlzNewValueTb(tmpObj, type, bckgrnd, &errNum); *valuess = WlzAssignValues(values, NULL); WlzFreeObj(tmpObj); } } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if( dstErr ){ *dstErr = errNum; } return rtnObj; }
void referenceFileListCb( Widget w, XtPointer client_data, XtPointer call_data) { HGU_XmFileListCallbackStruct *cbs= (HGU_XmFileListCallbackStruct *) client_data; WlzObject *obj; Widget cascade; WlzErrorNum errNum=WLZ_ERR_NONE; HGU_XmSetHourGlassCursor(globals.topl); if( cbs == NULL ){ /* clear list selection */ HGU_XmFileListClearList(globals.fileList); HGU_XmFileListWriteResourceFile(globals.fileList, globals.resourceFile); if((cascade = XtNameToWidget(globals.topl, "*file_menu*_pulldown*Recent"))){ HGU_XmFileListResetMenu(globals.fileList, cascade, referenceFileListCb); } } else if((obj = HGU_XmFileListReadObject(w, cbs, &errNum))){ WlzDomain domain; WlzValues values; WlzObject *newObj; switch( obj->type ){ case WLZ_2D_DOMAINOBJ: if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, 0, 0, obj->domain.i->line1, obj->domain.i->lastln, obj->domain.i->kol1, obj->domain.i->lastkl, &errNum))){ domain.p->domains[0] = WlzAssignDomain(obj->domain, NULL); if((values.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, 0, 0, WlzGetBackground(obj, NULL), NULL, &errNum))){ values.vox->values[0] = WlzAssignValues(obj->values, NULL); newObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values, NULL, NULL, NULL); WlzFreeObj(obj); obj = newObj; } } globals.origObjType = WLZ_2D_DOMAINOBJ; break; case WLZ_3D_DOMAINOBJ: globals.origObjType = WLZ_3D_DOMAINOBJ; break; default: HGU_XmUserError(globals.topl, "Read Reference Object:\n" " The reference object must be a 2- or 3-D\n" " grey-level image. Please select an alternate\n" " object", XmDIALOG_FULL_APPLICATION_MODAL); WlzFreeObj( obj ); /* set hour glass cursor */ HGU_XmUnsetHourGlassCursor(globals.topl); return; } MAPaintLogData("ReferenceFile", refFileList[0], 0, NULL); install_paint_reference_object( obj ); /* set the title of the top-level window */ set_topl_title(cbs->file); globals.file = AlcStrDup(cbs->file); globals.origObjExtType = cbs->format; /* add to the file list and write file */ HGU_XmFileListAddFile(globals.fileList, cbs->file, cbs->format); HGU_XmFileListWriteResourceFile(globals.fileList, globals.resourceFile); if((cascade = XtNameToWidget(globals.topl, "*file_menu*_pulldown*Recent"))){ HGU_XmFileListResetMenu(globals.fileList, cascade, referenceFileListCb); } } HGU_XmUnsetHourGlassCursor(globals.topl); if( errNum != WLZ_ERR_NONE ){ MAPaintReportWlzError(globals.topl, "ReferenceFileListCb", errNum); } return; }
/*! * \return Object with transformed grey-values. * \ingroup WlzArithmetic * \brief Apply a binary operation (add subtract etc) to * each pixel value in the given object. The operand value * is in <tt>pval</tt>. * \param o1 Input object * \param pval Pixel value for binary operation. * \param op Opertor * \param dstErr Error return. * \par Source: * WlzScalarArithmeticOp.c */ WlzObject *WlzScalarBinaryOp2( WlzObject *o1, WlzPixelV pval, WlzBinaryOperatorType op, WlzErrorNum *dstErr) { WlzObject *obj=NULL, *tmp3; WlzErrorNum errNum=WLZ_ERR_NONE; WlzValues values; WlzPixelV old_bckgrnd, new_bckgrnd; WlzGreyType new_grey_type; int p; /* check object pointers */ if( (o1 == NULL) ){ errNum = WLZ_ERR_OBJECT_NULL; } /* check object types - WLZ_EMPTY_OBJ is legal */ if( errNum == WLZ_ERR_NONE ){ switch( o1->type ){ case WLZ_2D_DOMAINOBJ: /* FALLTHROUGH */ case WLZ_3D_DOMAINOBJ: /* FALLTHROUGH */ case WLZ_TRANS_OBJ: break; case WLZ_EMPTY_OBJ: obj = WlzMakeEmpty(&errNum); break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* check domains and valuetables */ if( (errNum == WLZ_ERR_NONE) && (obj == NULL) ){ switch( o1->type ){ case WLZ_2D_DOMAINOBJ: if( (o1->domain.core == NULL) ){ errNum = WLZ_ERR_DOMAIN_NULL; break; } if( (o1->values.core == NULL) ){ errNum = WLZ_ERR_VALUES_NULL; break; } break; case WLZ_3D_DOMAINOBJ: if( (o1->domain.core == NULL) ){ errNum = WLZ_ERR_DOMAIN_NULL; break; } if( (o1->domain.p->type != WLZ_PLANEDOMAIN_DOMAIN) ){ errNum = WLZ_ERR_PLANEDOMAIN_TYPE; break; } if( (o1->values.core == NULL) ){ errNum = WLZ_ERR_VALUES_NULL; break; } if( (o1->values.vox->type != WLZ_VOXELVALUETABLE_GREY) ){ errNum = WLZ_ERR_VOXELVALUES_TYPE; break; } break; case WLZ_TRANS_OBJ: if( (o1->domain.core == NULL) ){ errNum = WLZ_ERR_DOMAIN_NULL; break; } if( (o1->values.core == NULL) ){ errNum = WLZ_ERR_VALUES_NULL; break; } if((values.obj = WlzScalarBinaryOp2(o1->values.obj, pval, op, &errNum)) != NULL){ obj = WlzMakeMain(WLZ_TRANS_OBJ, o1->domain, values, NULL, NULL, &errNum); break; } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* set up temporary object */ if((errNum == WLZ_ERR_NONE) && (obj == NULL)){ switch( o1->type ){ case WLZ_2D_DOMAINOBJ: values.core = NULL; if( (tmp3 = WlzMakeMain(WLZ_2D_DOMAINOBJ, o1->domain, values, NULL, NULL, &errNum)) == NULL ){ break; } old_bckgrnd = WlzGetBackground(o1, NULL); switch( WlzGreyTableTypeToGreyType(o1->values.core->type, NULL) ){ case WLZ_GREY_INT: /* FALLTHROUGH */ case WLZ_GREY_SHORT: /* FALLTHROUGH */ case WLZ_GREY_FLOAT: /* FALLTHROUGH */ case WLZ_GREY_DOUBLE: new_grey_type = WlzGreyTableTypeToGreyType(o1->values.core->type, NULL); new_bckgrnd = old_bckgrnd; break; case WLZ_GREY_UBYTE: new_grey_type = WLZ_GREY_SHORT; new_bckgrnd.type = WLZ_GREY_SHORT; new_bckgrnd.v.shv = old_bckgrnd.v.ubv; break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } if(errNum == WLZ_ERR_NONE){ values.v = WlzNewValueTb(tmp3, WlzGreyTableType(WLZ_GREY_TAB_RAGR, new_grey_type, NULL), new_bckgrnd, &errNum); tmp3->values = WlzAssignValues( values, NULL ); } break; case WLZ_3D_DOMAINOBJ: values.core = NULL; if((tmp3 = WlzMakeMain(WLZ_3D_DOMAINOBJ, o1->domain, values, NULL, NULL, &errNum)) == NULL){ break; } /* now a new destination voxeltable */ old_bckgrnd = WlzGetBackground(o1, NULL); switch( old_bckgrnd.type ){ case WLZ_GREY_INT: /* FALLTHROUGH */ case WLZ_GREY_SHORT: /* FALLTHROUGH */ case WLZ_GREY_FLOAT: /* FALLTHROUGH */ case WLZ_GREY_DOUBLE: new_grey_type = old_bckgrnd.type; new_bckgrnd = old_bckgrnd; break; case WLZ_GREY_UBYTE: new_grey_type = WLZ_GREY_SHORT; new_bckgrnd.type = WLZ_GREY_SHORT; new_bckgrnd.v.shv = old_bckgrnd.v.ubv; break; default: errNum = WLZ_ERR_GREY_TYPE; break; } if(errNum == WLZ_ERR_NONE){ values.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, tmp3->domain.p->plane1, tmp3->domain.p->lastpl, new_bckgrnd, NULL, &errNum); if( values.vox == NULL ){break;} for(p=tmp3->domain.p->plane1; p <= tmp3->domain.p->lastpl; p++){ WlzValues values2d; /* currently test for NULL domain to imply WLZ_EMPTY_DOMAIN */ if( tmp3->domain.p->domains[p-tmp3->domain.p->plane1].core == NULL ){ values2d.core = NULL; } else { WlzObject *tmp2d; values2d.core = NULL; if((tmp2d = WlzMakeMain(WLZ_2D_DOMAINOBJ, tmp3->domain.p->domains[p-tmp3->domain.p->plane1], values2d, NULL, NULL, &errNum)) != NULL){ values2d.v = WlzNewValueTb( tmp2d, WlzGreyTableType(WLZ_GREY_TAB_RAGR, new_grey_type, NULL), new_bckgrnd, &errNum); WlzFreeObj( tmp2d ); } } values.vox->values[p-tmp3->domain.p->plane1] = WlzAssignValues(values2d, NULL); } tmp3->values = WlzAssignValues(values, NULL); } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* apply operation and free space */ if((errNum == WLZ_ERR_NONE) && (obj == NULL)){ if((errNum = WlzScalarBinaryOp(o1, pval, tmp3, op)) != WLZ_ERR_NONE){ WlzFreeObj( tmp3 ); } else { obj = tmp3; } } if( dstErr ){ *dstErr = errNum; } return obj; }
void read_reference_object_cb( Widget w, XtPointer client_data, XtPointer call_data) { XmFileSelectionBoxCallbackStruct *cbs = (XmFileSelectionBoxCallbackStruct *) call_data; WlzEffFormat image_type; WlzObject *obj; String icsfile; WlzDomain domain; WlzValues values; WlzObject *newObj; WlzErrorNum errNum=WLZ_ERR_NONE; /* set hour glass cursor */ HGU_XmSetHourGlassCursor(globals.topl); /* read the new reference object note the switch is to allow direct read given the image type to include the model input options */ if( client_data ){ image_type = (WlzEffFormat) client_data; if((icsfile = HGU_XmGetFileStr(globals.topl, cbs->value, cbs->dir))){ obj = WlzEffReadObj(NULL, icsfile, image_type, 0, 0, 0, &errNum); AlcFree(icsfile); } else { obj = NULL; } } else { obj = HGU_XmReadExtFFObject(read_obj_dialog, cbs, &image_type, &errNum); } if( obj == NULL){ HGU_XmUserError(globals.topl, "Read Reference Object:\n" " No reference object read - either the\n" " selected file is empty or it is not the\n" " correct object type - please check the\n" " file or make a new selection", XmDIALOG_FULL_APPLICATION_MODAL); /* set hour glass cursor */ HGU_XmUnsetHourGlassCursor(globals.topl); return; } if( obj->values.core == NULL ){ HGU_XmUserError(globals.topl, "Read Reference Object:\n" " The reference object must have a grey-\n" " value table. Please select an alternate\n" " object", XmDIALOG_FULL_APPLICATION_MODAL); WlzFreeObj( obj ); /* set hour glass cursor */ HGU_XmUnsetHourGlassCursor(globals.topl); return; } /* install the new reference object */ switch( obj->type ){ case WLZ_2D_DOMAINOBJ: if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, 0, 0, obj->domain.i->line1, obj->domain.i->lastln, obj->domain.i->kol1, obj->domain.i->lastkl, &errNum))){ domain.p->domains[0] = WlzAssignDomain(obj->domain, NULL); if((values.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, 0, 0, WlzGetBackground(obj, NULL), NULL, &errNum))){ values.vox->values[0] = WlzAssignValues(obj->values, NULL); newObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values, obj->plist, NULL, &errNum); WlzFreeObj(obj); obj = newObj; } } globals.origObjType = WLZ_2D_DOMAINOBJ; break; case WLZ_3D_DOMAINOBJ: globals.origObjType = WLZ_3D_DOMAINOBJ; break; default: HGU_XmUserError(globals.topl, "Read Reference Object:\n" " The reference object must be a 2- or 3-D\n" " grey-level image. Please select an alternate\n" " object", XmDIALOG_FULL_APPLICATION_MODAL); WlzFreeObj( obj ); /* set hour glass cursor */ HGU_XmUnsetHourGlassCursor(globals.topl); return; } globals.origObjExtType = image_type; /* set title and reference file list */ if((icsfile = HGU_XmGetFileStr(globals.topl, cbs->value, cbs->dir))) { Widget cascade; HGU_XmFileListAddFile(globals.fileList, icsfile, image_type); HGU_XmFileListWriteResourceFile(globals.fileList, globals.resourceFile); if((cascade = XtNameToWidget(globals.topl, "*file_menu*_pulldown*Recent"))){ HGU_XmFileListResetMenu(globals.fileList, cascade, referenceFileListCb); } if( XmStringGetLtoR(cbs->value, XmSTRING_DEFAULT_CHARSET, &icsfile) ) { set_topl_title(icsfile); globals.file = icsfile; } } MAPaintLogData("ReferenceFile", globals.file, 0, NULL); /* clear feedback object and install new reference object */ if( errNum == WLZ_ERR_NONE ){ if( globals.fb_obj ){ WlzFreeObj(globals.fb_obj); globals.fb_obj = NULL; } install_paint_reference_object( obj ); } /* set hour glass cursor */ HGU_XmUnsetHourGlassCursor(globals.topl); if( errNum != WLZ_ERR_NONE ){ MAPaintReportWlzError(globals.topl, "read_reference_object_cb", errNum); } return; }
static WlzObject *WlzSelect1InN( WlzObject *obj, int first_pl, int last_pl, int step, WlzErrorNum *dstErr) { WlzObject *nobj=NULL; int p, new_p, new_plane1, new_lastpl; WlzDomain domain; WlzValues values; WlzErrorNum errNum=WLZ_ERR_NONE; /* check the object */ if( obj == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; } if( errNum == WLZ_ERR_NONE ){ domain.core = NULL; values.core = NULL; switch( obj->type ){ case WLZ_3D_DOMAINOBJ: if( obj->domain.core == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; break; } if( obj->domain.core->type == WLZ_EMPTY_DOMAIN ){ return WlzMakeEmpty(dstErr); } break; case WLZ_EMPTY_OBJ: return WlzMakeEmpty(dstErr); default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* check the parameters */ if( errNum == WLZ_ERR_NONE ){ if( first_pl > last_pl ){ errNum = WLZ_ERR_PARAM_DATA; } else if( step <= 0 ){ errNum = WLZ_ERR_PARAM_DATA; } /* check for empty object */ else if((first_pl > obj->domain.p->lastpl) || (last_pl < obj->domain.p->plane1) ){ return WlzMakeEmpty(dstErr); } } /* make a new planedomain and voxel table as required */ if( errNum == WLZ_ERR_NONE ){ for(p=first_pl; p <= last_pl; p += step){ if( p >= obj->domain.p->plane1 ){ new_plane1 = p / step; break; } } for(;p <= last_pl; p += step){ if( p > obj->domain.p->lastpl ){ break; } new_lastpl = p / step; } if((domain.p = WlzMakePlaneDomain(obj->domain.p->type, new_plane1, new_lastpl, obj->domain.p->line1, obj->domain.p->lastln, obj->domain.p->kol1, obj->domain.p->lastkl, &errNum)) != NULL){ domain.p->voxel_size[0] = obj->domain.p->voxel_size[0]; domain.p->voxel_size[1] = obj->domain.p->voxel_size[1]; domain.p->voxel_size[2] = step * (obj->domain.p->voxel_size[2]); if( obj->values.core != NULL ){ if( (values.vox = WlzMakeVoxelValueTb(obj->values.vox->type, new_plane1, new_lastpl, obj->values.vox->bckgrnd, obj, &errNum)) == NULL ){ (void) WlzFreePlaneDomain(domain.p); } } } } /* set domain and voxel values */ if( errNum == WLZ_ERR_NONE ){ for(p=first_pl; p <= last_pl; p += step){ if( p < obj->domain.p->plane1 ){ continue; } if( p > obj->domain.p->lastpl ){ break; } new_p = (p / step) - domain.p->plane1; domain.p->domains[new_p] = WlzAssignDomain(obj->domain.p->domains[p - obj->domain.p->plane1], NULL); if( obj->values.core != NULL ){ values.vox->values[new_p] = WlzAssignValues( obj->values.vox->values[p - obj->domain.p->plane1], NULL); } } } if( errNum == WLZ_ERR_NONE ){ nobj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values, NULL, NULL, &errNum); } if( dstErr ){ *dstErr = errNum; } return nobj; }
/*! * \return New 3D object. * \ingroup WlzAllocation * \brief Constructs a 3D domain object from 2D domain objects. Each * 2D object is assigned in turn to the 3D object no domains * or values are copied. An empty can be specified by * setting the 2D object to NULL. Either all or none of * the 2D objects must have values. When the 2D objects * have values then the background value of the first 2D * object is set to be the background value of the 3D object. * \param nObjs Number of objects. * \param objs The 2D objects, the first of which * MUST not be NULL. * \param plane1 The plane coordinate of the first * 2D object. * \param xSz Column voxel size. * \param ySz Line voxel size. * \param zSz Plane voxel size. * \param dstErr Destination error pointer, may be NULL. */ WlzObject *WlzConstruct3DObjFromObj(int nObjs, WlzObject **objs, int plane1, float xSz, float ySz, float zSz, WlzErrorNum *dstErr) { int idx, lastpl; WlzDomain dom3D; WlzValues val3D; WlzObject *obj2D, *obj3D = NULL; WlzPixelV bgd; WlzErrorNum errNum = WLZ_ERR_NONE; dom3D.core = NULL; val3D.core = NULL; lastpl = plane1 + nObjs - 1; if((nObjs <= 0) || (objs == NULL)) { errNum = WLZ_ERR_PARAM_NULL; } else if((obj2D = *objs) == NULL) { errNum = WLZ_ERR_OBJECT_NULL; } else { switch(obj2D->type) { case WLZ_EMPTY_OBJ: break; case WLZ_2D_DOMAINOBJ: if(obj2D->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* Make a plane domain, set column and line bounds later. */ if(errNum == WLZ_ERR_NONE) { dom3D.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, plane1, lastpl, 0, 1, 0, 1, &errNum); } if(errNum == WLZ_ERR_NONE) { dom3D.p->voxel_size[0] = xSz; dom3D.p->voxel_size[1] = ySz; dom3D.p->voxel_size[2] = zSz; } /* Make a voxel value table. */ if(errNum == WLZ_ERR_NONE) { if(obj2D->values.core) { bgd = WlzGetBackground(obj2D, &errNum); if(errNum == WLZ_ERR_NONE) { val3D.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, plane1, lastpl, bgd, NULL, &errNum); } } } for(idx = 0; (errNum == WLZ_ERR_NONE) && (idx < nObjs); ++idx) { obj2D = *(objs + idx); if(obj2D) { switch(obj2D->type) { case WLZ_EMPTY_OBJ: break; case WLZ_2D_DOMAINOBJ: if(obj2D->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } if(errNum == WLZ_ERR_NONE) { *(dom3D.p->domains + idx) = WlzAssignDomain(obj2D->domain, NULL); if(val3D.core) { if((obj2D->domain.core != NULL) && (obj2D->values.core == NULL)) { errNum = WLZ_ERR_VALUES_NULL; } else { *(val3D.vox->values + idx) = WlzAssignValues(obj2D->values, NULL); } } } } } if(errNum == WLZ_ERR_NONE) { errNum = WlzStandardPlaneDomain(dom3D.p, val3D.vox); } if(errNum == WLZ_ERR_NONE) { obj3D = WlzMakeMain(WLZ_3D_DOMAINOBJ, dom3D, val3D, NULL, NULL, &errNum); } if(errNum != WLZ_ERR_NONE) { if(dom3D.core) { (void )WlzFreeDomain(dom3D); } if(val3D.core) { (void )WlzFreeValues(val3D); } } if(dstErr) { *dstErr = errNum; } return(obj3D); }
/*! * \return New Woolz object. * \ingroup WlzAllocation * \brief Creates a new or adds to an existing 3D spatial domain * object using a rectangular buffer of values to a single * plane of the given current object (which may be NULL or * empty if the object is to be created). * The returned object will share domains and values of * planes other than the given plane with the current object. * \param cObj Given current object. * \param og Origin of rectangular buffer. * \param sz Buffer size (note 2D). * \param gType Grey type which must be consistent * with the current object (if it is * valid) and the buffer of values. * \param bufSz Number of values in the buffer * (ie sz.vtX * sz.vtY). * \param bufP Given buffer of values. * \param dstErr Destination error pointer, may be NULL. */ WlzObject *WlzBuildObj3(WlzObject *cObj, WlzIVertex3 og, WlzIVertex2 sz, WlzGreyType gType, int bufSz, WlzGreyP bufP, WlzErrorNum *dstErr) { int nPlnReq = 1; WlzDomain cDom, nDom; WlzValues cVal, nVal; WlzObject *nObj = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; cDom.core = NULL; nDom.core = NULL; cVal.core = NULL; nVal.core = NULL; if(cObj) { WlzGreyType cGType = WLZ_GREY_ERROR;; switch(cObj->type) { case WLZ_EMPTY_OBJ: cObj = NULL; break; case WLZ_3D_DOMAINOBJ: if(cObj->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } else if(cObj->values.core == NULL) { errNum = WLZ_ERR_VALUES_NULL; } else { cDom = cObj->domain; cVal = cObj->values; cGType = WlzGreyTypeFromObj(cObj, &errNum); } if((errNum == WLZ_ERR_NONE) && (cGType != gType)) { errNum = WLZ_ERR_GREY_TYPE; } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* Create a new object with new plane domain and voxel values. */ if(errNum == WLZ_ERR_NONE) { WlzIBox3 nBox; WlzPixelV bgdV; float vxSz[3]; nBox.xMin = og.vtX; nBox.yMin = og.vtY; nBox.zMin = og.vtZ; nBox.xMax = og.vtX + sz.vtX - 1; nBox.yMax = og.vtY + sz.vtY - 1; nBox.zMax = og.vtZ; if(cObj) { nPlnReq = (og.vtZ < cDom.p->plane1) || (og.vtZ > cDom.p->lastpl) || ((*(cDom.p->domains + og.vtZ - cDom.p->plane1)).core == NULL); nBox.xMin = ALG_MIN(nBox.xMin, cDom.p->kol1); nBox.yMin = ALG_MIN(nBox.yMin, cDom.p->line1); nBox.zMin = ALG_MIN(nBox.zMin, cDom.p->plane1); nBox.xMax = ALG_MAX(nBox.xMax, cDom.p->lastkl); nBox.yMax = ALG_MAX(nBox.yMax, cDom.p->lastln); nBox.zMax = ALG_MAX(nBox.zMax, cDom.p->lastpl); vxSz[0] = cDom.p->voxel_size[0]; vxSz[1] = cDom.p->voxel_size[1]; vxSz[2] = cDom.p->voxel_size[2]; bgdV = WlzGetBackground(cObj, &errNum); } else { vxSz[0] = vxSz[1] = vxSz[2] = 1.0f; bgdV.type = WLZ_GREY_INT; bgdV.v.inv = 0; } if(errNum == WLZ_ERR_NONE) { nDom.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, nBox.zMin, nBox.zMax, nBox.yMin, nBox.yMax, nBox.xMin, nBox.xMax, &errNum); } if(errNum == WLZ_ERR_NONE) { nVal.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, nBox.zMin, nBox.zMax, bgdV, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { nDom.p->voxel_size[0] = vxSz[0]; nDom.p->voxel_size[1] = vxSz[1]; nDom.p->voxel_size[2] = vxSz[2]; nObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, nDom, nVal, NULL, NULL, &errNum); } } /* Set the domain and values on each plane for the new object. */ if(errNum == WLZ_ERR_NONE) { int idZ; for(idZ = nDom.p->plane1; idZ <= nDom.p->lastpl; ++idZ) { int idP; WlzDomain nDom2; WlzValues nVal2; nDom2.core = NULL; nVal2.core = NULL; idP = idZ - nDom.p->plane1; if(idZ == og.vtZ) { /* Plane with buffer. */ WlzIVertex2 og2, sz2; WlzObject *cObj2 = NULL, *nObj2 = NULL; og2.vtX = og.vtX; og2.vtY = og.vtY; sz2.vtX = sz.vtX; sz2.vtY = sz.vtY; if(nPlnReq == 0) { int idP; idP = idZ - cDom.p->plane1; cObj2 = WlzMakeMain(WLZ_2D_DOMAINOBJ, *(cDom.p->domains + idP), *(cVal.vox->values + idP), NULL, NULL, &errNum); } nObj2 = WlzBuildObj2(cObj2, og2, sz2, gType, bufSz, bufP, &errNum); if(errNum == WLZ_ERR_NONE) { nDom2 = WlzAssignDomain(nObj2->domain, NULL); nVal2 = WlzAssignValues(nObj2->values, NULL); } (void )WlzFreeObj(cObj2); (void )WlzFreeObj(nObj2); } else if((idZ >= cDom.p->plane1) && (idZ <= cDom.p->lastpl)) { /* Not buffer plane, but previously existing plane. */ int idQ; idQ = idZ - cDom.p->plane1; nDom2 = WlzAssignDomain(*(cDom.p->domains + idQ), NULL); nVal2 = WlzAssignValues(*(cVal.vox->values + idQ), NULL); } if(errNum == WLZ_ERR_NONE) { *(nDom.p->domains + idP) = nDom2; *(nVal.vox->values + idP) = nVal2; } else { break; } } } if(dstErr) { *dstErr = errNum; } return(nObj); }
/*! * \return New Woolz object without holes or NULL on error. * \ingroup WlzDomainOps * \brief Fills the holes in the given object's domain (which are by * definition not connected to the outside). When the given * object's domain has more than one component part, the * object should first be labeled, this function should then be * called for each of the labeled parts and then the union of * the filled domains should be formed. * \param srcObj Given 3D domain object. * \param dstErr Destination error pointer, may be NULL. */ WlzObject *WlzDomainFill3D( WlzObject *srcObj, WlzErrorNum *dstErr) { int nPln = 0; WlzObject *bndObj = NULL, *filObj = NULL, *gvnObj = NULL, *sedObj = NULL, *shlObj = NULL; WlzPixelV zeroV; WlzValues nullVal; WlzErrorNum errNum = WLZ_ERR_NONE; nullVal.core = NULL; zeroV.type = WLZ_GREY_UBYTE; zeroV.v.ubv = 0; if(srcObj == NULL) { errNum = WLZ_ERR_OBJECT_NULL; } else if(srcObj->type != WLZ_3D_DOMAINOBJ) { errNum = WLZ_ERR_OBJECT_TYPE; } else if(srcObj->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } else { gvnObj = WlzMakeMain(srcObj->type, srcObj->domain, nullVal, NULL, NULL, &errNum); } /* Create a then shell 1 voxel thick just inside the given objects's * domain. */ if(errNum == WLZ_ERR_NONE) { WlzObject *difObj = NULL; difObj = WlzAssignObject( WlzBoundaryDomain(gvnObj, &errNum), NULL); if(errNum == WLZ_ERR_NONE) { WlzIBox3 clipBox; /* Clip the dilated shell domain to make sure it stays within the * bounding box of the given object then all planes will align. */ clipBox.xMin = gvnObj->domain.p->kol1; clipBox.yMin = gvnObj->domain.p->line1; clipBox.zMin = gvnObj->domain.p->plane1; clipBox.xMax = gvnObj->domain.p->lastkl; clipBox.yMax = gvnObj->domain.p->lastln; clipBox.zMax = gvnObj->domain.p->lastpl; shlObj = WlzAssignObject( WlzClipObjToBox3D(difObj, clipBox, &errNum), NULL); } (void )WlzFreeObj(difObj); } /* Make sure that the bounding box of the thin shell domain fits it and * that it's first and last planes have interrvals. */ if(errNum == WLZ_ERR_NONE) { errNum = WlzStandardPlaneDomain(shlObj->domain.p, NULL); } /* Create a value table for the shell object with values set to zero. */ if(errNum == WLZ_ERR_NONE) { WlzValues val; WlzObjectType tType; tType = WlzGreyTableType(WLZ_GREY_TAB_INTL, WLZ_GREY_UBYTE, NULL); val.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, shlObj->domain.p->plane1, shlObj->domain.p->lastpl, zeroV, NULL, &errNum); if(errNum == WLZ_ERR_NONE) { int p; nPln = shlObj->domain.p->lastpl - shlObj->domain.p->plane1 + 1; shlObj->values = WlzAssignValues(val, NULL); #ifdef _OPENMP #pragma omp parallel for shared(shlObj) #endif for(p = 0; p < nPln; ++p) { if(errNum == WLZ_ERR_NONE) { WlzDomain dom2; WlzErrorNum errNum2; dom2 = shlObj->domain.p->domains[p]; if(dom2.core) { WlzValues val2; WlzObject *shlObj2; shlObj2 = WlzMakeMain(WLZ_2D_DOMAINOBJ, dom2, nullVal, NULL, NULL, &errNum2); if(errNum2 == WLZ_ERR_NONE) { val2.i = WlzMakeIntervalValues(tType, shlObj2, zeroV, &errNum2); /* WlzMakeIntervalValues() sets all values to zero. */ } if(errNum2 == WLZ_ERR_NONE) { shlObj->values.vox->values[p] = WlzAssignValues(val2, NULL); } (void )WlzFreeObj(shlObj2); if(errNum2 == WLZ_ERR_NONE) { #ifdef _OPENMP #pragma omp critical { #endif if((errNum == WLZ_ERR_NONE) && (errNum2 != WLZ_ERR_NONE)) { errNum = errNum2; } #ifdef _OPENMP } #endif } } } } } } /* Compute the (plane-wise) boundary list for the given object. */ if(errNum == WLZ_ERR_NONE) { bndObj = WlzObjToBoundary(gvnObj, 0, &errNum); } /* Sweep down through the boundary object setting the values of * those voxels in the shell object to a non zero value when they * correspond to top level boundaries. */ if(errNum == WLZ_ERR_NONE) { int p; #ifdef _OPENMP #pragma omp parallel for shared(bndObj,shlObj) #endif for(p = 0; p < nPln; ++p) { if(errNum == WLZ_ERR_NONE) { WlzDomain bDom2; bDom2 = bndObj->domain.p->domains[p]; if(bDom2.core) { WlzDomain iDom2; WlzValues iVal2; WlzObject *iObj2 = NULL; WlzGreyValueWSpace *gVWSp = NULL; WlzErrorNum errNum2 = WLZ_ERR_NONE; iDom2 = shlObj->domain.p->domains[p]; iVal2 = shlObj->values.vox->values[p]; iObj2 = WlzMakeMain(WLZ_2D_DOMAINOBJ, iDom2, iVal2, NULL, NULL, &errNum2); if(errNum == WLZ_ERR_NONE) { gVWSp = WlzGreyValueMakeWSp(iObj2, &errNum2); } if(errNum2 == WLZ_ERR_NONE) { WlzBoundList *bnd, *bnd2; bnd2 = bDom2.b; for(bnd = bnd2; bnd != NULL; bnd = bnd->next) { if(bnd->poly != NULL) { WlzPolygonDomain *ply; ply = bnd->poly; if(ply) { int i; WlzIVertex2 *vtx; vtx = ply->vtx; for(i = 0; i < ply->nvertices; ++i) { WlzGreyValueGet(gVWSp, 0, vtx[i].vtY, vtx[i].vtX); *(gVWSp->gPtr[0].ubp) = 255; } } } } } else { #ifdef _OPENMP #pragma omp critical { #endif if(errNum == WLZ_ERR_NONE) { errNum = errNum2; } #ifdef _OPENMP } #endif } (void )WlzFreeObj(iObj2); WlzGreyValueFreeWSp(gVWSp); } } } } /* Threshold the shell object, throwing away all but where the voxels * are set to create a seed domain. Then remove the value table from * the shell object and free it as it's no longer needed. */ if(errNum == WLZ_ERR_NONE) { WlzObject *tObj = NULL; WlzPixelV tV; tV.type = WLZ_GREY_UBYTE; tV.v.ubv = 1; tObj = WlzAssignObject( WlzThreshold(shlObj, tV, WLZ_THRESH_HIGH, &errNum), NULL); if(errNum == WLZ_ERR_NONE) { sedObj = WlzAssignObject( WlzMakeMain(tObj->type, tObj->domain, nullVal, NULL, NULL, &errNum), NULL); } (void )WlzFreeObj(tObj); tObj = NULL; if(errNum == WLZ_ERR_NONE) { tObj = WlzAssignObject( WlzMakeMain(shlObj->type, shlObj->domain, nullVal, NULL, NULL, &errNum), NULL); } (void )WlzFreeObj(shlObj); shlObj = NULL; if(errNum == WLZ_ERR_NONE) { shlObj = tObj; tObj = NULL; } (void )WlzFreeObj(tObj); #ifdef WLZ_DOMOMAINFILL3D_DEBUG { FILE *fP; fP = fopen("debug-shlObj-00.wlz", "w"); (void )WlzWriteObj(fP, shlObj); (void )fclose(fP); } #endif } /* Label the shell domain using 26-connectivity in 3D and then * keep only those component objects which intersect the seed domain. * Then free the shell and seed domains replacing the shell domain * with the union of the intersecting labeled component objects. * Finaly free the intersecting component objects, keeping only the * new shell domain. */ if(errNum == WLZ_ERR_NONE) { int i, j, nCSObj = 0; WlzIBox3 bBox; WlzObject **csObj = NULL; bBox = WlzBoundingBox3I(shlObj, &errNum); if(errNum == WLZ_ERR_NONE) { int maxCSObj; maxCSObj = ((bBox.xMax - bBox.xMin + 1) * (bBox.yMax - bBox.yMin + 1) * (bBox.zMax - bBox.zMin + 1)) / 8; if(maxCSObj < 8) { maxCSObj = 8; } errNum = WlzLabel(shlObj, &nCSObj, &csObj, maxCSObj, 0, WLZ_26_CONNECTED); } if(errNum == WLZ_ERR_NONE) { for(i = 0; i < nCSObj; ++i) { if(!WlzHasIntersection(csObj[i], sedObj, &errNum)) { (void )WlzFreeObj(csObj[i]); csObj[i] = NULL; } } } if(errNum == WLZ_ERR_NONE) { /* Squeeze out any NULL objects reseting their number.*/ for(i = 0, j = 0; i < nCSObj; ++i) { if(csObj[i]) { csObj[j++] = csObj[i]; } } nCSObj = j; } if(errNum == WLZ_ERR_NONE) { WlzObject *iObj = NULL, *uObj = NULL; uObj = WlzAssignObject( WlzUnionN(nCSObj, csObj, 0, &errNum), NULL); iObj = WlzAssignObject( WlzIntersect2(uObj, shlObj, &errNum), NULL); (void )WlzFreeObj(uObj); (void )WlzFreeObj(shlObj); shlObj = iObj; #ifdef WLZ_DOMOMAINFILL3D_DEBUG { FILE *fP; fP = fopen("debug-shlObj-01.wlz", "w"); (void )WlzWriteObj(fP, shlObj); (void )fclose(fP); } #endif } if(csObj) { for(i = 0; i < nCSObj; ++i) { (void )WlzFreeObj(csObj[i]); } (void )AlcFree(csObj); } } /* Sweep down through the boundary lists again creating new boundary lists * which do not have boundaries that do not intersect the new shell domain. * Then create a new filled object from these boundary lists. */ if(errNum == WLZ_ERR_NONE) { int p, nPlnFil; WlzDomain filDom; nPlnFil = shlObj->domain.p->lastpl - shlObj->domain.p->plane1 + 1; filDom.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, shlObj->domain.p->plane1, shlObj->domain.p->lastpl, shlObj->domain.p->line1, shlObj->domain.p->lastln, shlObj->domain.p->kol1, shlObj->domain.p->lastkl, &errNum); #ifdef _OPENMP #pragma omp parallel for shared(bndObj,shlObj) #endif for(p = 0; p < nPlnFil; ++p) { if(errNum == WLZ_ERR_NONE) { WlzDomain bDom2; bDom2 = bndObj->domain.p->domains[p]; if(bDom2.core) { WlzDomain sDom2; WlzObject *fObj2 = NULL; WlzBoundList *newBnd = NULL; WlzErrorNum errNum2 = WLZ_ERR_NONE; sDom2 = shlObj->domain.p->domains[p]; if(sDom2.core) { newBnd = WlzDomFill3DDoBound2D(bDom2.b, sDom2, &errNum2); if(newBnd != NULL) { fObj2 = WlzBoundToObj(newBnd, WLZ_SIMPLE_FILL, &errNum2); (void )WlzFreeBoundList(newBnd); } if(errNum2 == WLZ_ERR_NONE) { if(fObj2) { filDom.p->domains[p] = WlzAssignDomain(fObj2->domain, NULL); } } else { #ifdef _OPENMP #pragma omp critical { #endif if(errNum == WLZ_ERR_NONE) { errNum = errNum2; } #ifdef _OPENMP } #endif } (void )WlzFreeObj(fObj2); } } } } if(errNum == WLZ_ERR_NONE) { errNum = WlzStandardPlaneDomain(filDom.p, NULL); } if(errNum == WLZ_ERR_NONE) { WlzObject *tObj0 = NULL, *tObj1 = NULL; /* Put back any isolated voxels this function has removed. */ tObj0 = WlzAssignObject( WlzMakeMain(srcObj->type, filDom, nullVal, NULL, NULL, &errNum), NULL); if(errNum == WLZ_ERR_NONE) { tObj1 = WlzUnion2(gvnObj, tObj0, &errNum); } if(errNum == WLZ_ERR_NONE) { filObj = WlzMakeMain(tObj1->type, tObj1->domain, nullVal, NULL, NULL, &errNum); } (void )WlzFreeObj(tObj0); (void )WlzFreeObj(tObj1); } } (void )WlzFreeObj(bndObj); (void )WlzFreeObj(gvnObj); (void )WlzFreeObj(shlObj); (void )WlzFreeObj(sedObj); if((errNum != WLZ_ERR_NONE) && (filObj != NULL)) { (void )WlzFreeObj(filObj); filObj = NULL; } if(dstErr) { *dstErr = errNum; } return(filObj); }
/*! * \return New Woolz domain object with gradient grey values or NULL * on error. * \ingroup WlzValuesFilters * \brief Computes the magnitude of the gray values in the * 3 given Woolz 3D domain objects. * \param srcObj0 First object. * \param srcObj1 Second object. * \param srcObj2 Third object. * \param dstErr Destination error pointer, may * be null. */ static WlzObject *WlzGreyMagnitude3D(WlzObject *srcObj0, WlzObject *srcObj1, WlzObject *srcObj2, WlzErrorNum *dstErr) { int idN, idP, nPlanes; WlzDomain dstDom; WlzValues dstVal; WlzObject *dstObj2D, *istObj = NULL, *dstObj = NULL; WlzObject *srcObjA[3], *iObj3DA[3], *iObj2DA[3]; WlzPixelV bgdV; WlzErrorNum errNum = WLZ_ERR_NONE; dstDom.core = NULL; dstVal.core = NULL; iObj3DA[0] = iObj3DA[1] = iObj3DA[2] = NULL; if((srcObj0->domain.core->type != WLZ_PLANEDOMAIN_DOMAIN) || (srcObj1->domain.core->type != WLZ_PLANEDOMAIN_DOMAIN) || (srcObj2->domain.core->type != WLZ_PLANEDOMAIN_DOMAIN)) { errNum = WLZ_ERR_DOMAIN_TYPE; } else if ((srcObj0->values.core->type != WLZ_VOXELVALUETABLE_GREY) || (srcObj1->values.core->type != WLZ_VOXELVALUETABLE_GREY) || (srcObj2->values.core->type != WLZ_VOXELVALUETABLE_GREY)) { errNum = WLZ_ERR_VALUES_TYPE; } else { srcObjA[0] = srcObj0; srcObjA[1] = srcObj1; srcObjA[2] = srcObj2; istObj = WlzIntersectN(3, srcObjA, 0, &errNum); } if(errNum == WLZ_ERR_NONE) { if(istObj->type == WLZ_EMPTY_OBJ) { dstObj = istObj; } else { dstDom = WlzAssignDomain(istObj->domain, NULL); WlzFreeObj(istObj); idN = 0; while((errNum == WLZ_ERR_NONE) && (idN < 3)) { iObj3DA[idN] = WlzMakeMain(WLZ_3D_DOMAINOBJ, dstDom, srcObjA[idN]->values, NULL, NULL, &errNum); ++idN; } if(errNum == WLZ_ERR_NONE) { idP = 0; nPlanes = dstDom.p->lastpl - dstDom.p->plane1 + 1; while((errNum == WLZ_ERR_NONE) && (idP < nPlanes)) { if((dstDom.p->domains + idN)->core == NULL) { (dstVal.vox->values + idP)->core = NULL; } else { dstObj2D = NULL; iObj2DA[0] = iObj2DA[1] = iObj2DA[2] = NULL; idN = 0; /* Make 2D objects. */ while((errNum == WLZ_ERR_NONE) && (idN < 3)) { iObj2DA[idN] = WlzMakeMain(WLZ_2D_DOMAINOBJ, *(iObj3DA[idN]->domain.p->domains + idP), *(iObj3DA[idN]->values.vox->values + idP), NULL, NULL, &errNum); ++idN; } /* Compute magnitude. */ if(errNum == WLZ_ERR_NONE) { dstObj2D = WlzGreyMagnitude2D3(iObj2DA[0], iObj2DA[1], iObj2DA[2], &errNum); } /* If first plane get grey type and background, then create new * 3D object with new voxel values. */ if((idP == 0) && (errNum == WLZ_ERR_NONE)) { bgdV = WlzGetBackground(iObj2DA[0], &errNum); if(errNum == WLZ_ERR_NONE) { dstVal.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY, dstDom.p->plane1, dstDom.p->lastpl, bgdV, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { dstObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, dstDom, dstVal, NULL, NULL, &errNum); } } /* Add 2D values to the 3D objects values. */ if(errNum == WLZ_ERR_NONE) { *(dstVal.vox->values + idP) = WlzAssignValues(dstObj2D->values, NULL); } /* Free temporary 2D object. */ if(dstObj2D) { WlzFreeObj(dstObj2D); } idN = 0; while(idN < 3) { if(iObj2DA[idN]) { WlzFreeObj(iObj2DA[idN]); } ++idN; } } ++idP; } } /* Free 3D intersection gradient objects. */ idN = 0; while(idN < 3) { if(iObj3DA[idN]) { WlzFreeObj(iObj3DA[idN]); } ++idN; } /* Decrement link count to the destination 3D domain. */ (void )WlzFreeDomain(dstDom); } } if((errNum != WLZ_ERR_NONE) && (dstObj != NULL)) { WlzFreeObj(dstObj); dstObj = NULL; } if(dstErr) { *dstErr = errNum; } return(dstObj); }