void displayDomains(void) { DomainListItem *newItem; HGUDlpListItem *item; WlzObject *obj1; WlzErrorNum errNum; /* check globals and domain list */ if((globals.obj == NULL) || (globals.dmnList == NULL) || (HGUDlpListCount(globals.dmnList) <= 0)){ return; } /* loop through domains and display the boundlist */ item = HGUDlpListHead(globals.dmnList); while( item ){ newItem = (DomainListItem *) HGUDlpListEntryGet(globals.dmnList, item); if( !newItem->currBound ){ /* get the section thought the domain */ if( newItem->obj ){ if( obj1 = WlzGetSectionFromObject(newItem->obj, globals.wlzViewStr, WLZ_INTERPOLATION_NEAREST, &errNum) ){ WlzObject *tmpBoundary; obj1 = WlzAssignObject(obj1, NULL); tmpBoundary = WlzObjToBoundary(obj1, 1, &errNum); newItem->currBound = WlzAssignObject(tmpBoundary, NULL); WlzFreeObj(obj1); } } } /* display it */ if( newItem->currBound ){ if( obj1 ){ if( newItem == globals.currDmnListItem ){ DisplayBoundPiece(globals.dpy, globals.win, globals.gc_blue, obj1->domain.b); } else { DisplayBoundPiece(globals.dpy, globals.win, globals.gc_red, obj1->domain.b); } WlzFreeObj(obj1); } } item = HGUDlpListNext(globals.dmnList, item); } return; }
/*! * \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 void * \brief Outputs the mesh and displaced mesh of the given mesh * transform as Postscript to the standard error output. * \param mObj Given mesh transform object. * \param sObj Source object. * \param dilObj Dilated object. * \param outObj Transformed object. */ static void WlzCMeshOutputPS(WlzObject *mObj, WlzObject *sObj, WlzObject *dilObj, WlzObject *outObj) { int idE, idN, useElm; double scale; double *dsp; WlzDVertex2 pos, offset; WlzDVertex2 elmVx[3]; WlzDBox2 bBox; WlzCMeshNod2D *nod; WlzCMeshElm2D *elm; WlzCMesh2D *mesh; WlzIndexedValues *ixv; WlzObject *bObj = NULL; char buf[100]; (void )fprintf(stderr, "%%!\n" "/Times-Courier findfont\n" "1 scalefont\n" "setfont\n" "1 setlinecap\n" "1 setlinejoin\n" "0.01 setlinewidth\n"); if((mObj != NULL) && (mObj->type == WLZ_CMESH_2D) && ((mesh = mObj->domain.cm2) != NULL) && ((ixv = mObj->values.x) != NULL)) { /* Compute the bounding box of the mesh transform. */ bBox.xMin = bBox.yMin = DBL_MAX; bBox.xMax = bBox.yMax = DBL_MIN; for(idN = 0; idN < mesh->res.nod.maxEnt; ++idN) { nod = (WlzCMeshNod2D *)AlcVectorItemGet(mesh->res.nod.vec, idN); if(nod->idx >= 0) { if(nod->pos.vtX < bBox.xMin) { bBox.xMin = nod->pos.vtX; } else if(nod->pos.vtX > bBox.xMax) { bBox.xMax = nod->pos.vtX; } if(nod->pos.vtY < bBox.yMin) { bBox.yMin = nod->pos.vtY; } else if(nod->pos.vtY > bBox.yMax) { bBox.yMax = nod->pos.vtY; } dsp = (double *)WlzIndexedValueGet(ixv, idN); pos.vtX = nod->pos.vtX + dsp[0]; pos.vtY = nod->pos.vtY + dsp[1]; if(pos.vtX < bBox.xMin) { bBox.xMin = pos.vtX; } else if(pos.vtX > bBox.xMax) { bBox.xMax = pos.vtX; } if(pos.vtY < bBox.yMin) { bBox.yMin = pos.vtY; } else if(pos.vtY > bBox.yMax) { bBox.yMax = pos.vtY; } } } if(((pos.vtX = fabs(bBox.xMax - bBox.xMin)) > 1.0) && ((pos.vtY = fabs(bBox.yMax - bBox.yMin)) > 1.0)) { /* Compute scale and offset for an A4 page. */ if((4.0 * pos.vtX) > (3.0 * pos.vtY)) { scale = 500.0 / (bBox.xMax - bBox.xMin); } else { scale = 700.0 / (bBox.yMax - bBox.yMin); } offset.vtX = (bBox.xMin * scale) - 50; offset.vtY = (bBox.yMin * -scale) - 750; (void )fprintf(stderr, "255 0 0 setrgbcolor\n"); for(idE = 0; idE < mesh->res.elm.maxEnt; ++idE) { elm = (WlzCMeshElm2D *)AlcVectorItemGet(mesh->res.elm.vec, idE); if(elm->idx >= 0) { for(idN = 0; idN < 3; ++idN) { pos = elm->edu[idN].nod->pos; elmVx[idN].vtX = (pos.vtX * scale) - offset.vtX; elmVx[idN].vtY = (pos.vtY * -scale) - offset.vtY; } (void )fprintf(stderr, "%g %g moveto " "%g %g lineto " "%g %g lineto " "%g %g lineto " "stroke\n", elmVx[0].vtX, elmVx[0].vtY, elmVx[1].vtX, elmVx[1].vtY, elmVx[2].vtX, elmVx[2].vtY, elmVx[0].vtX, elmVx[0].vtY); WLZ_VTX_2_ADD3(pos, elmVx[0], elmVx[1], elmVx[2]); WLZ_VTX_2_SCALE(pos, pos, 0.333333); (void )sprintf(buf, "%d", elm->idx); (void )fprintf(stderr, "%g %g moveto " "(%s) show\n", pos.vtX, pos.vtY, buf); } } (void )fprintf(stderr, "0 0 255 setrgbcolor\n"); for(idE = 0; idE < mesh->res.elm.maxEnt; ++idE) { elm = (WlzCMeshElm2D *)AlcVectorItemGet(mesh->res.elm.vec, idE); if(elm->idx >= 0) { /* Display only those elements that have all nodes inside the * domain. useElm = ((elm->edg[0].nod->flags | elm->edg[1].nod->flags | elm->edg[2].nod->flags) & WLZ_CMESH_NOD_FLAG_OUTSIDE) == 0; */ useElm = 1; if(useElm) { for(idN = 0; idN < 3; ++idN) { pos = elm->edu[idN].nod->pos; dsp = (double *)WlzIndexedValueGet(ixv, elm->edu[idN].nod->idx); pos.vtX += dsp[0]; pos.vtY += dsp[1]; elmVx[idN].vtX = (pos.vtX * scale) - offset.vtX; elmVx[idN].vtY = (pos.vtY * -scale) - offset.vtY; } (void )fprintf(stderr, "%g %g moveto " "%g %g lineto " "%g %g lineto " "%g %g lineto " "stroke\n", elmVx[0].vtX, elmVx[0].vtY, elmVx[1].vtX, elmVx[1].vtY, elmVx[2].vtX, elmVx[2].vtY, elmVx[0].vtX, elmVx[0].vtY); WLZ_VTX_2_ADD3(pos, elmVx[0], elmVx[1], elmVx[2]); WLZ_VTX_2_SCALE(pos, pos, 0.333333); (void )sprintf(buf, "%d", elm->idx); (void )fprintf(stderr, "%g %g moveto " "(%s) show\n", pos.vtX, pos.vtY, buf); } } } (void )fprintf(stderr, "0 255 0 setrgbcolor\n"); if((bObj = WlzObjToBoundary(sObj, 1, NULL)) != NULL) { WlzBndOutputPS(bObj->domain.b, scale, offset); } (void )fprintf(stderr, "0 255 255 setrgbcolor\n"); if((bObj = WlzObjToBoundary(dilObj, 1, NULL)) != NULL) { WlzBndOutputPS(bObj->domain.b, scale, offset); } (void )fprintf(stderr, "127 0 127 setrgbcolor\n"); if((bObj = WlzObjToBoundary(outObj, 1, NULL)) != NULL) { WlzBndOutputPS(bObj->domain.b, scale, offset); } (void )fprintf(stderr, "showpage\n"); } } }
void setup_ref_display_list_cb( Widget w, XtPointer client_data, XtPointer call_data) { WlzPlaneDomain *planedmn; WlzThreeDViewStruct *viewStr; WlzErrorNum errNum=WLZ_ERR_NONE; if( globals.obj == NULL || globals.obj->type != WLZ_3D_DOMAINOBJ || globals.ref_display_list == 0){ return; } /* create a new display list */ glDeleteLists(globals.ref_display_list, 1); globals.ref_display_list = glGenLists( (GLsizei) 1 ); planedmn = globals.obj->domain.p; /* create the reference object 3D display DisplayList */ glNewList( globals.ref_display_list, GL_COMPILE ); glBegin(GL_LINES); glColor3f(1.0, 0.0, 0.0); glIndexi( (int) HGU_XGetColorPixel(globals.dpy, globals.cmap, 1.0, 0.0, 0.0) ); glVertex3i(planedmn->kol1, planedmn->line1, planedmn->plane1); glVertex3i(planedmn->lastkl, planedmn->line1, planedmn->plane1); glVertex3i(planedmn->kol1, planedmn->line1, planedmn->lastpl); glVertex3i(planedmn->lastkl, planedmn->line1, planedmn->lastpl); glVertex3i(planedmn->kol1, planedmn->lastln, planedmn->plane1); glVertex3i(planedmn->lastkl, planedmn->lastln, planedmn->plane1); glVertex3i(planedmn->kol1, planedmn->lastln, planedmn->lastpl); glVertex3i(planedmn->lastkl, planedmn->lastln, planedmn->lastpl); glColor3f(0.0, 1.0, 0.0); glIndexi( (int) HGU_XGetColorPixel(globals.dpy, globals.cmap, 0.0, 1.0, 0.0) ); glVertex3i(planedmn->kol1, planedmn->line1, planedmn->plane1); glVertex3i(planedmn->kol1, planedmn->lastln, planedmn->plane1); glVertex3i(planedmn->kol1, planedmn->line1, planedmn->lastpl); glVertex3i(planedmn->kol1, planedmn->lastln, planedmn->lastpl); glVertex3i(planedmn->lastkl, planedmn->line1, planedmn->plane1); glVertex3i(planedmn->lastkl, planedmn->lastln, planedmn->plane1); glVertex3i(planedmn->lastkl, planedmn->line1, planedmn->lastpl); glVertex3i(planedmn->lastkl, planedmn->lastln, planedmn->lastpl); glColor3f(0.0, 0.0, 1.0); glIndexi( (int) HGU_XGetColorPixel(globals.dpy, globals.cmap, 0.0, 0.0, 1.0) ); glVertex3i(planedmn->kol1, planedmn->line1, planedmn->plane1); glVertex3i(planedmn->kol1, planedmn->line1, planedmn->lastpl); glVertex3i(planedmn->kol1, planedmn->lastln, planedmn->plane1); glVertex3i(planedmn->kol1, planedmn->lastln, planedmn->lastpl); glVertex3i(planedmn->lastkl, planedmn->line1, planedmn->plane1); glVertex3i(planedmn->lastkl, planedmn->line1, planedmn->lastpl); glVertex3i(planedmn->lastkl, planedmn->lastln, planedmn->plane1); glVertex3i(planedmn->lastkl, planedmn->lastln, planedmn->lastpl); glEnd(); if( globals.fb_obj && (globals.fb_obj->type == WLZ_3D_DOMAINOBJ) ){ WlzObject *obj1, *boundobj; WlzValues values; int z, step; /* establish the step size */ planedmn = globals.fb_obj->domain.p; step = (planedmn->lastkl - planedmn->kol1) / 6; z = (planedmn->lastln - planedmn->line1) / 6; step = WLZ_MIN(step, z); z = (planedmn->lastpl - planedmn->plane1) / 6; step = WLZ_MIN(step, z); /* set up const z boundaries */ glColor3f(1.0, 1.0, 1.0); glIndexi((int) HGU_XGetColorPixel(globals.dpy, globals.cmap, 1.0, 1.0, 1.0)); (void) glLineWidth( (GLfloat) 2.0 ); for(z=planedmn->plane1+step/2; z <= planedmn->lastpl; z += step) { values.core = NULL; obj1 = WlzMakeMain(WLZ_2D_DOMAINOBJ, planedmn->domains[z - planedmn->plane1], values, NULL, NULL, NULL); if( obj1->domain.core != NULL ) { boundobj = WlzObjToBoundary(obj1, 1, &errNum); if( boundobj != NULL ) { MAOpenGLDisplayBoundList(boundobj->domain.b, (float) z ); WlzFreeObj( boundobj ); } if( errNum != WLZ_ERR_NONE ){ break; } } WlzFreeObj( obj1 ); } (void) glLineWidth( (GLfloat) 1.0 ); /* set up const y boundaries */ if( errNum == WLZ_ERR_NONE ){ glColor3f(1.0, 1.0, 0.0); glIndexi((int) HGU_XGetColorPixel(globals.dpy, globals.cmap, 1.0, 1.0, 0.0)); if((viewStr = WlzMake3DViewStruct(WLZ_3D_VIEW_STRUCT, &errNum))){ viewStr->theta = WLZ_M_PI / 2.0; viewStr->phi = WLZ_M_PI / 2.0; viewStr->dist = planedmn->line1 - step/2; errNum = WlzInit3DViewStruct(viewStr, globals.fb_obj); for(z=viewStr->dist+step; (errNum == WLZ_ERR_NONE) && (z <= planedmn->lastln); z += step) { Wlz3DSectionIncrementDistance(viewStr, (double) step); if((obj1 = WlzGetSectionFromObject(globals.fb_obj, viewStr, WLZ_INTERPOLATION_NEAREST, &errNum))){ obj1 = WlzAssignObject(obj1, NULL); boundobj = WlzObjToBoundary(obj1, 1, &errNum); if( boundobj != NULL ) { /* convert boundary coordinates to voxel coordinates */ Wlz3DSectionTransformYBound(boundobj->domain.b, viewStr); MAOpenGLDisplayYBoundList(boundobj->domain.b, (float) z); WlzFreeObj( boundobj ); } WlzFreeObj( obj1 ); } } WlzFree3DViewStruct(viewStr); } } /* set up const x boundaries */ if( errNum == WLZ_ERR_NONE ){ glIndexi((int) HGU_XGetColorPixel(globals.dpy, globals.cmap, 1.0, 1.0, 0.0)); glColor3f(1.0, 1.0, 0.0); if((viewStr = WlzMake3DViewStruct(WLZ_3D_VIEW_STRUCT, &errNum))){ viewStr->theta = 0.0; viewStr->phi = WLZ_M_PI / 2.0; viewStr->dist = planedmn->kol1 - step/2; errNum = WlzInit3DViewStruct(viewStr, globals.fb_obj); for(z=viewStr->dist+step; (errNum == WLZ_ERR_NONE) && (z <= planedmn->lastkl); z += step) { Wlz3DSectionIncrementDistance(viewStr, (double) step); if((obj1 = WlzGetSectionFromObject(globals.fb_obj, viewStr, WLZ_INTERPOLATION_NEAREST, &errNum))){ obj1 = WlzAssignObject(obj1, NULL); boundobj = WlzObjToBoundary(obj1, 1, &errNum); if( boundobj != NULL ) { /* convert boundary coordinates to voxel coordinates */ Wlz3DSectionTransformXBound(boundobj->domain.b, viewStr); MAOpenGLDisplayXBoundList(boundobj->domain.b, (float) z); WlzFreeObj( boundobj ); } WlzFreeObj( obj1 ); } } WlzFree3DViewStruct(viewStr); } } } if( errNum == WLZ_ERR_NONE ){ glIndexi( (int) HGU_XGetColorPixel(globals.dpy, globals.cmap, 1.0, 1.0, 1.0) ); glColor3f(1.0, 1.0, 1.0); glEndList(); WLZ_VTX_3_SET(globals.bbox_vtx, planedmn->kol1 - 2.0, planedmn->line1 - 2.0, planedmn->plane1 - 2.0); WLZ_VTX_3_SET(globals.bbox_size, planedmn->lastkl - planedmn->kol1 + 4.0, planedmn->lastln - planedmn->line1 + 4.0, planedmn->lastpl - planedmn->plane1 + 4.0); glFogf(GL_FOG_DENSITY, 0.25/globals.bbox_size.vtX); MAOpenGLDrawScene( globals.canvas ); } else { MAPaintReportWlzError(globals.topl, "setup_ref_display_list_cb", errNum); } return; }
int WlzEdgeVertices( WlzObject *obj, WlzDVertex3 **vtxs, WlzErrorNum *dstErr) { int numVtxs = 0, n; WlzDVertex3 *rtnVtxs=NULL, *tmpVtxs; WlzErrorNum errNum=WLZ_ERR_NONE; WlzObject *obj1, *obj2; int i, j; WlzValues values; WlzPlaneDomain *planedmn; /* check object */ if( obj == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; } else { switch( obj->type ){ case WLZ_2D_DOMAINOBJ: if((obj1 = WlzObjToBoundary(obj, 1, &errNum)) != NULL){ numVtxs = WlzEdgeVerticesBound(obj1->domain.b, &rtnVtxs, 0, &errNum); WlzFreeObj(obj1); } break; case WLZ_3D_DOMAINOBJ: if( obj->domain.core == NULL){ errNum = WLZ_ERR_DOMAIN_NULL; } else { switch( obj->domain.core->type ){ case WLZ_PLANEDOMAIN_DOMAIN: planedmn = obj->domain.p; values.core = NULL; for(i=planedmn->plane1; i <= planedmn->lastpl; i++){ if( planedmn->domains[i-planedmn->plane1].core ){ obj2 = WlzMakeMain(WLZ_2D_DOMAINOBJ, planedmn->domains[i-planedmn->plane1], values, NULL, NULL, NULL); if( (n = WlzEdgeVertices(obj2, &tmpVtxs, &errNum)) > 0){ if( numVtxs > 0 ){ rtnVtxs = AlcRealloc(rtnVtxs, sizeof(WlzDVertex3)*(numVtxs+n)); } else { rtnVtxs = AlcMalloc(sizeof(WlzDVertex3)*n); } for(j=0; j < n; j++){ tmpVtxs[j].vtZ = i; rtnVtxs[numVtxs+j] = tmpVtxs[j]; } AlcFree(tmpVtxs); numVtxs += n; } WlzFreeObj(obj2); } } break; case WLZ_PLANEDOMAIN_POLYGON: case WLZ_PLANEDOMAIN_BOUNDLIST: break; case WLZ_EMPTY_DOMAIN: if( dstErr ){ *dstErr = errNum; } return numVtxs; default: errNum = WLZ_ERR_DOMAIN_TYPE; } } break; case WLZ_2D_POLYGON: numVtxs = WlzEdgeVerticesPoly(obj->domain.poly, &rtnVtxs, 0, &errNum); break; case WLZ_BOUNDLIST: numVtxs = WlzEdgeVerticesBound(obj->domain.b, &rtnVtxs, 0, &errNum); break; case WLZ_EMPTY_OBJ: if( dstErr ){ *dstErr = errNum; } return numVtxs; default: errNum = WLZ_ERR_OBJECT_TYPE; } } if( dstErr ){ *dstErr = errNum; } *vtxs = rtnVtxs; return numVtxs; }
int main(int argc, char *argv[]) { int ok, bnd = 0, con, option, usage = 0; char *inFileStr, *forFileStr, *refFileStr, *outFileStr; double dParam = 10.0; FILE *fP = NULL; WlzObject *tObj0, *tObj1, *forObj = NULL, *refObj = NULL, *dstObj = NULL; WlzDistanceType dFn; WlzErrorNum errNum = WLZ_ERR_NONE; const char *errMsgStr; static char optList[] = "bhd:f:p:o:"; const char fileStrDef[] = "-"; const WlzConnectType defDFn = WLZ_OCTAGONAL_DISTANCE; /* Parse the argument list and check for input files. */ opterr = 0; inFileStr = (char *)fileStrDef; forFileStr = (char *)fileStrDef; outFileStr = (char *)fileStrDef; dFn = defDFn; while((option = getopt(argc, argv, optList)) != EOF) { switch(option) { case 'b': bnd = 1; break; case 'd': if(sscanf(optarg, "%d", &con) != 1) { usage = 1; } else { switch(con) { case 0: dFn = WLZ_EUCLIDEAN_DISTANCE; break; case 1: dFn = WLZ_OCTAGONAL_DISTANCE; break; case 2: dFn = WLZ_APX_EUCLIDEAN_DISTANCE; break; case 4: dFn = WLZ_4_DISTANCE; break; case 6: dFn = WLZ_6_DISTANCE; break; case 8: dFn = WLZ_8_DISTANCE; break; case 18: dFn = WLZ_18_DISTANCE; break; case 26: dFn = WLZ_26_DISTANCE; break; default: usage = 1; break; } } break; case 'f': forFileStr = optarg; break; case 'p': if(sscanf(optarg, "%lg", &dParam) != 1) { usage = 1; } break; case 'o': outFileStr = optarg; break; case 'h': default: usage = 1; break; } } ok = !usage; if(ok && (optind < argc)) { if((optind + 1) != argc) { usage = 1; ok = 0; } else { refFileStr = argv[optind]; } } /* Read the reference object. */ if(ok) { if((refFileStr == NULL) || (*refFileStr == '\0') || ((fP = (strcmp(refFileStr, "-")? fopen(refFileStr, "r"): stdin)) == NULL) || ((refObj = WlzAssignObject(WlzReadObj(fP, &errNum), NULL)) == NULL)) { ok = 0; (void )fprintf(stderr, "%s: Failed to read reference object from file %s.\n", argv[0], refFileStr); } if(fP && strcmp(refFileStr, "-")) { (void )fclose(fP); fP = NULL; } } /* Read the foreground object. */ if(ok) { if((forFileStr == NULL) || (*forFileStr == '\0') || ((fP = (strcmp(forFileStr, "-")? fopen(forFileStr, "r"): stdin)) == NULL) || ((forObj = WlzAssignObject(WlzReadObj(fP, &errNum), NULL)) == NULL)) { ok = 0; (void )fprintf(stderr, "%s: Failed to read foreground object from file %s.\n", argv[0], forFileStr); } if(fP && strcmp(forFileStr, "-")) { (void )fclose(fP); fP = NULL; } } /* Check object types and parse the promote the default distance function * if required. */ if(ok) { if(refObj->type != forObj->type) { ok = 0; (void )fprintf(stderr, "%s: Foreground and reference object types differ.\n", argv[0]); } } if((errNum == WLZ_ERR_NONE) && bnd) { tObj0 = tObj1 = NULL; tObj0 = WlzObjToBoundary(refObj, 1, &errNum); if(errNum == WLZ_ERR_NONE) { tObj1 = WlzBoundaryToObj(tObj0, WLZ_VERTEX_FILL, &errNum); } if(errNum == WLZ_ERR_NONE) { (void )WlzFreeObj(refObj); refObj = tObj1; tObj1 = NULL; } (void )WlzFreeObj(tObj0); (void )WlzFreeObj(tObj1); } /* Compute the distance transform object. */ if(ok) { dstObj = WlzAssignObject( WlzDistanceTransform(forObj, refObj, dFn, dParam, &errNum), NULL); if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsgStr); (void )fprintf(stderr, "%s: Failed to compute distance object, %s.\n", argv[0], errMsgStr); } } /* Output the distance transform object. */ if(ok) { if((fP = (strcmp(outFileStr, "-")? fopen(outFileStr, "w"): stdout)) == NULL) { ok = 0; (void )fprintf(stderr, "%s: Failed to open output file %s.\n", argv[0], outFileStr); } } if(ok) { errNum = WlzWriteObj(fP, dstObj); if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsgStr); (void )fprintf(stderr, "%s: Failed to write output object, %s.\n", argv[0], errMsgStr); } } (void )WlzFreeObj(forObj); (void )WlzFreeObj(refObj); (void )WlzFreeObj(dstObj); if(usage) { (void )fprintf(stderr, "Usage: %s [-b] [-d#] [-f#] [-p#] [-o#] [-h] [<Reference input file>]\n" "Computes a distance transform object which has the domain of the\n" "foreground object and values which are the distance from the reference\n" "object.\n" "Options are:\n" " -b Use the boundary of the reference object.\n" " -d Distance function:\n" " 0: Euclidean (2D and 3D, unimplemented)\n" " 1: octagonal (2D and 3D) - default\n" " 2: approximate Euclidean (2D and 3D)\n" " 4: 4-connected (2D)\n" " 8: 8-connected (2D)\n" " 6: 6-connected (3D)\n" " 18: 18-connected (3D)\n" " 26: 26-connected (3D)\n" " -f The foreground object file.\n" " -p Distance function parameter, which is curently only used for\n" " approximate Euclidean distance transforms. The value should\n" " be >= 1, with larger values giving greater accuracy at the\n" " cost of increased time. Default value - 10.0.\n" " -o Output object file.\n" " -h Help - prints this usage message\n", argv[0]); } return(!ok); }
/*! * \return Centrality feature value in range [0.0-1.0]. * \ingroup WlzFeatures * \brief Computes the centrality of a feature domain with respect * to a boundary domain, where the domains are 2D. See * WlzCentrality(). * \param fObj Feature domain object. * \param bObj Boundary domain object. * \param nRay Number of equally spaced rays projected * from the centre of mass. * \param binFlg Treat as binary object if non-zero. * \param dstMaxR Destination pointer for maximum * boundary radius, may be NULL. * \param dstErr Destination error pointer, may be NULL. */ static double WlzCentrality2D(WlzObject *fObj, WlzObject *bObj, int nRay, int binFlg, double *dstMaxR, WlzErrorNum *dstErr) { int idx; double cent = 0.0, fNum = 0.0, fDnm = 0.0, maxR = 0.0; WlzIVertex2 pos; WlzDVertex2 cmV; double *pTbl = NULL; WlzObject *tmpObj, *bndObj = NULL; WlzGreyP gPix; WlzGreyWSpace gWsp; WlzIntervalWSpace iWsp; WlzErrorNum errNum = WLZ_ERR_NONE; /* Get centre of mass of the boundary object. */ cmV = WlzCentreOfMass2D(bObj, 1, NULL, &errNum); /* Get boundary of the boundary domain. */ if(errNum == WLZ_ERR_NONE) { bndObj = WlzObjToBoundary(bObj, 0, &errNum); } /* Make sure the boundary is 8-connected. */ if(errNum == WLZ_ERR_NONE) { tmpObj = WlzBoundTo8Bound(bndObj, &errNum); (void )WlzFreeObj(bndObj); bndObj = tmpObj; } /* Compute polar maximum boundary table. */ if(errNum == WLZ_ERR_NONE) { if((pTbl = (double *)AlcMalloc(nRay * sizeof(double))) == NULL) { errNum = WLZ_ERR_MEM_ALLOC; } } if(errNum == WLZ_ERR_NONE) { WlzCentralityCompPolarTbl2D(cmV, nRay, pTbl, bndObj); if(dstMaxR != NULL) { for(idx = 0; idx < nRay; ++idx) { if(pTbl[idx] > maxR) { maxR = pTbl[idx]; } } } } (void )WlzFreeObj(bndObj); /* Scan through feature domain adding to feature values. */ if(errNum == WLZ_ERR_NONE) { if(binFlg != 0) { errNum = WlzInitRasterScan(fObj, &iWsp, WLZ_RASTERDIR_ILIC); while((errNum = WlzNextInterval(&iWsp)) == WLZ_ERR_NONE) { pos.vtY = iWsp.linpos; for(pos.vtX = iWsp.lftpos; pos.vtX <= iWsp.rgtpos; ++pos.vtX) { WlzCentralityUpdate2D(&fNum, &fDnm, cmV, nRay, pTbl, 1.0, pos); } } } else { errNum = WlzInitGreyScan(fObj, &iWsp, &gWsp); while((errNum = WlzNextGreyInterval(&iWsp)) == WLZ_ERR_NONE) { gPix = gWsp.u_grintptr; pos.vtY = iWsp.linpos; for(pos.vtX = iWsp.lftpos; pos.vtX <= iWsp.rgtpos; ++pos.vtX) { switch(gWsp.pixeltype) { case WLZ_GREY_INT: WlzCentralityUpdate2D(&fNum, &fDnm, cmV, nRay, pTbl, *(gPix.inp)++, pos); break; case WLZ_GREY_SHORT: WlzCentralityUpdate2D(&fNum, &fDnm, cmV, nRay, pTbl, *(gPix.shp)++, pos); break; case WLZ_GREY_UBYTE: WlzCentralityUpdate2D(&fNum, &fDnm, cmV, nRay, pTbl, *(gPix.ubp)++, pos); break; case WLZ_GREY_FLOAT: WlzCentralityUpdate2D(&fNum, &fDnm, cmV, nRay, pTbl, *(gPix.flp)++, pos); break; case WLZ_GREY_DOUBLE: WlzCentralityUpdate2D(&fNum, &fDnm, cmV, nRay, pTbl, *(gPix.dbp)++, pos); break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } } } if(errNum == WLZ_ERR_EOO) { errNum = WLZ_ERR_NONE; } } if(errNum == WLZ_ERR_NONE) { cent = (fabs(fDnm) > DBL_EPSILON)? fNum / fDnm: DBL_MAX; if(dstMaxR != NULL) { *dstMaxR = maxR; } } AlcFree(pTbl); if(dstErr) { *dstErr = errNum; } return(cent); }