/*! * \ingroup WlzAllocation * \brief Free a histogram domain. * * \return Error number, values: from WlzFreeDomain(). * \param hist Histogram domain to be freed. * \par Source: * WlzFreeSpace.c */ WlzErrorNum WlzFreeHistogramDomain(WlzHistogramDomain *hist) { WlzDomain domain; domain.hist = hist; return( WlzFreeDomain(domain) ); }
/*! * \ingroup WlzAllocation * \brief Free an interval domain - convenience link to WlzFreeDomain() * * \return Error number, values: from WlzFreeDomain(). * \param idom interval domain pointer to be freed. * \par Source: * WlzFreeSpace.c */ WlzErrorNum WlzFreeIntervalDomain(WlzIntervalDomain *idom) { WlzDomain domain; domain.i = idom; return( WlzFreeDomain(domain) ); }
/*! * \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 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 2D Woolz object or NULL on error. * \ingroup WlzTransform * \brief Creates a new 2D Woolz object with a single line which * is the profile from the given start position to the * given end position. This function assumes that it is * given either a 2 or 3D spatial domain object and that * this object has a non-NULL domain. See WlzProfileLine(). * \param gObj Given Woolz object. * \param sPos Start position. * \param ePos End position. * \param dstErr Destination error pointer, may be NULL. */ static WlzObject *WlzProfileLnSD( WlzObject *gObj, WlzIVertex3 sPos, WlzIVertex3 ePos, WlzErrorNum *dstErr) { WlzDomain rDom = {0}; WlzValues rVal = {0}; WlzObject *rObj = NULL; WlzGreyP rPix = {0}; WlzGreyValueWSpace *gVWSp = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; rDom.i = WlzProfileLineIDom(gObj, sPos, ePos, &errNum); if(errNum == WLZ_ERR_NONE) { if(gObj->values.core) { gVWSp = WlzGreyValueMakeWSp(gObj, &errNum); if(errNum == WLZ_ERR_NONE) { int len; size_t gSz; len = rDom.i->lastkl - rDom.i->kol1 +1; if((gSz = WlzGreySize(gVWSp->gType)) == 0) { errNum = WLZ_ERR_GREY_TYPE; } else if((rPix.v = AlcMalloc(len * gSz)) == NULL) { errNum = WLZ_ERR_MEM_ALLOC; } } if(errNum == WLZ_ERR_NONE) { WlzPixelV bgd; WlzObjectType tType; bgd.type = gVWSp->gType; bgd.v = gVWSp->gBkd; tType = WlzGreyValueTableType(0, WLZ_GREY_TAB_RECT, gVWSp->gType, NULL); rVal.r = WlzMakeRectValueTb(tType, rDom.i->line1, rDom.i->lastln, rDom.i->kol1, (rDom.i->lastkl - rDom.i->kol1) + 1, bgd, rPix.inp, &errNum); } } } if(errNum == WLZ_ERR_NONE) { rObj = WlzMakeMain(gObj->type, rDom, rVal, NULL, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { errNum = WlzProfileWalkValues(gObj, rObj, gVWSp, sPos, ePos, &errNum); } if(errNum != WLZ_ERR_NONE) { if(rObj) { (void )WlzFreeObj(rObj); rObj = NULL; } else { if(rVal.core) { (void )WlzFreeDomain(rDom); (void )WlzFreeValues(rVal); } else { AlcFree(rPix.v); } } } if(dstErr) { *dstErr = errNum; } return(rObj); }
/*! * \ingroup WlzAllocation * \brief Free space allocated to a woolz object. * * \return Error number, values: WLZ_ERR_NONE, WLZ_ERR_MEM_FREE * \param obj Object to be freed. * \par Source: * WlzFreeSpace.c */ WlzErrorNum WlzFreeObj(WlzObject *obj) { int i; WlzCompoundArray *ca = (WlzCompoundArray *) obj; WlzErrorNum errNum = WLZ_ERR_NONE; WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_FN|WLZ_DBG_LVL_1), ("WlzFreeObj FE %p\n", obj)); /* check the object pointer and linkcount */ if (obj == NULL){ return( WLZ_ERR_NONE ); } if( WlzUnlink(&(obj->linkcount), &errNum) ){ /* Check linkcount */ switch( obj->type ){ case WLZ_2D_DOMAINOBJ: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_2D_DOMAINOBJ " "%p %d %p %d %p\n", obj, (obj->domain.i), (obj->domain.i?obj->domain.i->linkcount: 0), (obj->values.core), ((obj->values.core)? obj->values.core->linkcount: 0), (obj->plist))); errNum = WlzFreeDomain(obj->domain); if((errNum == WLZ_ERR_NONE) && (obj->values.core != NULL)) { if(WlzGreyTableIsTiled(obj->values.core->type) == WLZ_GREY_TAB_TILED) { errNum = WlzFreeTiledValues(obj->values.t); } else { errNum = WlzFreeValueTb(obj->values.v); } } if(errNum == WLZ_ERR_NONE) { errNum = WlzFreePropertyList(obj->plist); } if(errNum == WLZ_ERR_NONE) { errNum = WlzFreeObj(obj->assoc); } break; case WLZ_3D_DOMAINOBJ: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_3D_DOMAINOBJ %p, " "%d %p %d %p\n", obj, obj->domain.i, (obj->domain.p? obj->domain.p->linkcount: 0), obj->values.core, (obj->values.core? obj->values.core->linkcount: 0), obj->plist)); errNum = WlzFreePlaneDomain(obj->domain.p); if((errNum == WLZ_ERR_NONE) && (obj->values.core != NULL)){ if(WlzGreyTableIsTiled(obj->values.core->type) == WLZ_GREY_TAB_TILED) { errNum = WlzFreeTiledValues(obj->values.t); } else { errNum = WlzFreeVoxelValueTb(obj->values.vox); } } if(errNum == WLZ_ERR_NONE) { errNum = WlzFreePropertyList(obj->plist); } if(errNum == WLZ_ERR_NONE) { errNum = WlzFreeObj(obj->assoc); } break; case WLZ_TRANS_OBJ: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_TRANS_OBJ %p, " "%d %p %d %p\n", obj, obj->domain.t, ((obj->domain.t)?(obj->domain.t)->linkcount: 0), obj->values.obj, ((obj->values.obj)?(obj->values.obj)->linkcount: 0), obj->plist)); if( WlzFreeAffineTransform(obj->domain.t) || WlzFreeObj(obj->values.obj) || WlzFreePropertyList(obj->plist) || WlzFreeObj(obj->assoc) ){ errNum = WLZ_ERR_MEM_FREE; } break; case WLZ_2D_POLYGON: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_2D_POLYGON %p\n", obj, obj->domain.poly)); errNum = WlzFreePolyDmn(obj->domain.poly); break; case WLZ_BOUNDLIST: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_BOUNDLIST %p\n", obj, obj->domain.b)); errNum = WlzFreeBoundList(obj->domain.b); break; case WLZ_CONTOUR: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_CONTOUR %p\n", obj, obj->domain.ctr)); errNum = WlzFreeContour(obj->domain.ctr); break; case WLZ_CONV_HULL: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_CONV_HULL %p %p\n", obj, obj->domain.core, obj->values.core)); if(obj->domain.core) { switch(obj->domain.core->type) { case WLZ_CONVHULL_DOMAIN_2D: errNum = WlzFreeConvexHullDomain2(obj->domain.cvh2); break; case WLZ_CONVHULL_DOMAIN_3D: errNum = WlzFreeConvexHullDomain3(obj->domain.cvh3); break; default: errNum = WLZ_ERR_DOMAIN_TYPE; break; } } break; case WLZ_CMESH_2D: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_CMESH_2D %p, " "%d %p %d %p\n", obj, obj->domain.cm2, ((obj->domain.cm2)? (obj->domain.cm2)->linkcount: 0), obj->values.x, ((obj->values.x)? (obj->values.x)->linkcount: 0), obj->plist)); errNum = WlzCMeshFree2D(obj->domain.cm2); if((errNum == WLZ_ERR_NONE) && (obj->values.core != NULL)) { errNum = WlzFreeIndexedValues(obj->values.x); } if((errNum == WLZ_ERR_NONE) && (obj->plist != NULL)) { errNum = WlzFreePropertyList(obj->plist); } if((errNum == WLZ_ERR_NONE) && (obj->assoc != NULL)) { errNum = WlzFreeObj(obj->assoc); } break; case WLZ_CMESH_2D5: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_CMESH_2D5 %p, " "%d %p %d %p\n", obj, obj->domain.cm2d5, ((obj->domain.cm2d5)? (obj->domain.cm2d5)->linkcount: 0), obj->values.x, ((obj->values.x)? (obj->values.x)->linkcount: 0), obj->plist)); errNum = WlzCMeshFree2D5(obj->domain.cm2d5); if((errNum == WLZ_ERR_NONE) && (obj->values.core != NULL)) { errNum = WlzFreeIndexedValues(obj->values.x); } if((errNum == WLZ_ERR_NONE) && (obj->plist != NULL)) { errNum = WlzFreePropertyList(obj->plist); } if((errNum == WLZ_ERR_NONE) && (obj->assoc != NULL)) { errNum = WlzFreeObj(obj->assoc); } break; case WLZ_CMESH_3D: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_CMESH_3D %p, " "%d %p %d %p\n", obj, obj->domain.cm3, ((obj->domain.cm3)?(obj->domain.cm3)->linkcount: 0), obj->values.x, ((obj->values.x)?(obj->values.x)->linkcount: 0), obj->plist)); errNum = WlzCMeshFree3D(obj->domain.cm3); if((errNum == WLZ_ERR_NONE) && (obj->values.core != NULL)) { errNum = WlzFreeIndexedValues(obj->values.x); } if((errNum == WLZ_ERR_NONE) && (obj->plist != NULL)) { errNum = WlzFreePropertyList(obj->plist); } if((errNum == WLZ_ERR_NONE) && (obj->assoc != NULL)) { errNum = WlzFreeObj(obj->assoc); } break; case WLZ_POINTS: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_POINTS %p\n", obj, obj->domain.pts)); errNum = WlzFreeDomain(obj->domain); if((errNum == WLZ_ERR_NONE) && (obj->values.core != NULL)) { errNum = WlzFreePointValues(obj->values.pts); } if((errNum == WLZ_ERR_NONE) && (obj->plist != NULL)) { errNum = WlzFreePropertyList(obj->plist); } if((errNum == WLZ_ERR_NONE) && (obj->assoc != NULL)) { errNum = WlzFreeObj(obj->assoc); } break; case WLZ_HISTOGRAM: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_CONV_HULL %p\n", obj, obj->domain.hist)); errNum = WlzFreeDomain(obj->domain); break; case WLZ_RECTANGLE: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_RECTANGLE %p\n", obj, obj->domain.r)); errNum = WlzFreeDomain(obj->domain); break; case WLZ_AFFINE_TRANS: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_AFFINE_TRANS\n", obj)); errNum = WlzFreeAffineTransform(obj->domain.t); break; case WLZ_LUT: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_LUT\n", obj)); errNum = WlzFreeDomain(obj->domain); if(errNum == WLZ_ERR_NONE) { errNum = WlzFreeLUTValues(obj->values); } break; case WLZ_COMPOUND_ARR_1: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_COMPOUND_ARR_1\n", ca)); for (i=0; i<ca->n; i++){ if( WlzFreeObj(ca->o[i]) != WLZ_ERR_NONE ){ errNum = WLZ_ERR_MEM_FREE; } } break; case WLZ_COMPOUND_ARR_2: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_COMPOUND_ARR_2\n", ca)); for (i=0; i<ca->n; i++){ if( WlzFreeObj(ca->o[i]) != WLZ_ERR_NONE ){ errNum = WLZ_ERR_MEM_FREE; } } break; case WLZ_PROPERTY_OBJ: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_PROPERTY_OBJ\n", obj)); errNum = WlzFreePropertyList(obj->plist); break; case WLZ_EMPTY_OBJ: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p WLZ_EMPTY_OBJ\n", obj)); break; default: WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1), ("WlzFreeObj %p %d\n", obj, (int )(obj->type))); errNum = WLZ_ERR_OBJECT_TYPE; break; } /* End of switch */ AlcFree((void *) obj); } return( errNum ); }
/*! * \ingroup WlzAllocation * \brief Free a planedomain * * \return Error number, values: WLZ_ERR_NONE and errors from WlzFreeAffineTransform(), WlzFreeDomain(), WlzFreeBoundList(), WlzFreePolyDmn(). * \param planedm Pointer to planedomain structure to be freed. * \par Source: * WlzFreeSpace.c */ WlzErrorNum WlzFreePlaneDomain(WlzPlaneDomain *planedm) { WlzDomain *domains; int nplanes; WlzErrorNum errNum = WLZ_ERR_NONE; /* check the object pointer and linkcount */ if (planedm == NULL){ return( WLZ_ERR_NONE ); } if( WlzUnlink(&(planedm->linkcount), &errNum) ){ nplanes = planedm->lastpl - planedm->plane1 + 1; domains = planedm->domains; switch( planedm->type ){ case WLZ_PLANEDOMAIN_DOMAIN: while( nplanes-- ){ errNum |= WlzFreeDomain( *domains ); domains++; } break; case WLZ_PLANEDOMAIN_POLYGON: while( nplanes-- ){ errNum |= WlzFreePolyDmn((*domains).poly); domains++; } break; case WLZ_PLANEDOMAIN_BOUNDLIST: while( nplanes-- ){ errNum |= WlzFreeBoundList((*domains).b); domains++; } break; case WLZ_PLANEDOMAIN_HISTOGRAM: while( nplanes-- ){ errNum |= WlzFreeDomain(*domains); domains++; } break; case WLZ_PLANEDOMAIN_AFFINE: while( nplanes-- ){ errNum |= WlzFreeAffineTransform((*domains).t); domains++; } break; default: return( WLZ_ERR_PLANEDOMAIN_TYPE ); } AlcFree((void *) planedm->domains); AlcFree((void *) planedm); } return( errNum ); }
/*! * \return New Woolz domain object with maximal domain and grey * values which encode the gradient's direction or NULL * on error. * \ingroup WlzFeatures * \brief Computes the maximal domain and gradient direction of * given Woolz 2D domain object. * \note All the objects domains are known to be the same. * \param grdM Gradient magnitude. * \param grdY Gradient (partial derivative) * through lines. * \param grdX Gradient (partial derivative) * through columns. * \param minThrV Minimum gradient value to * consider. * \param dstErr Destination error pointer, may * be null. */ static WlzObject *WlzNMSuppress2D(WlzObject *grdM, WlzObject *grdY, WlzObject *grdX, WlzPixelV minThrV, WlzErrorNum *dstErr) { int idN, inLen, outLen, inLnIdx = 0; WlzGreyType gType, bufType; WlzIVertex2 bufSz, inPos, outPos, orgPos; WlzValues tmpVal; WlzDomain dstDom, grdDom; WlzIntervalWSpace tmpIWSp = {0}, grdMIWSp = {0}, grdYIWSp = {0}, grdXIWSp = {0}; WlzGreyWSpace tmpGWSp, grdMGWSp, grdYGWSp, grdXGWSp; WlzPixelV zeroV; WlzGreyP grdMBufGP, grdYBufGP, grdXBufGP; WlzDynItvPool pool; WlzObject *dstObj = NULL, *tmpObj = NULL; void *grdYBuf = NULL, *grdXBuf = NULL; void **grdMBuf = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; tmpVal.core = NULL; pool.itvBlock = NULL; dstDom.core = NULL; if((grdM->type != WLZ_2D_DOMAINOBJ) || (grdY->type != WLZ_2D_DOMAINOBJ) || (grdX->type != WLZ_2D_DOMAINOBJ)) { errNum = WLZ_ERR_OBJECT_NULL; } else if((grdM->domain.core == NULL) || (grdY->domain.core == NULL) || (grdX->domain.core == NULL)) { errNum = WLZ_ERR_DOMAIN_NULL; } else if((grdM->values.core == NULL) || (grdY->values.core == NULL) || (grdX->values.core == NULL)) { errNum = WLZ_ERR_VALUES_NULL; } else { /* Find required buffer type (WLZ_GREY_DOUBLE or WLZ_GREY_INT). */ bufType = WLZ_GREY_INT; gType = WlzGreyTableTypeToGreyType(grdM->values.core->type, &errNum); if(errNum == WLZ_ERR_NONE) { if((gType == WLZ_GREY_FLOAT) || (gType == WLZ_GREY_DOUBLE)) { bufType = WLZ_GREY_DOUBLE; } else { gType = WlzGreyTableTypeToGreyType(grdY->values.core->type, &errNum); if(errNum == WLZ_ERR_NONE) { if((gType == WLZ_GREY_FLOAT) || (gType == WLZ_GREY_DOUBLE)) { bufType = WLZ_GREY_DOUBLE; } else { gType = WlzGreyTableTypeToGreyType(grdX->values.core->type, &errNum); if(errNum == WLZ_ERR_NONE) { if((gType == WLZ_GREY_FLOAT) || (gType == WLZ_GREY_DOUBLE)) { bufType = WLZ_GREY_DOUBLE; } } } } } } } /* Convert minimum gradient threshold value. */ if(errNum == WLZ_ERR_NONE) { if(bufType == WLZ_GREY_INT) { errNum = WlzValueConvertPixel(&minThrV, minThrV, WLZ_GREY_INT); } else /* bufType == WLZ_GREY_DOUBLE */ { errNum = WlzValueConvertPixel(&minThrV, minThrV, WLZ_GREY_DOUBLE); } } if(errNum == WLZ_ERR_NONE) { grdDom = grdM->domain; /* Make destination object with WLZ_GREY_UBYTE greys. */ zeroV.type = WLZ_GREY_UBYTE; zeroV.v.inv = 0; tmpVal.v = WlzNewValueTb(grdM, WlzGreyTableType(WLZ_GREY_TAB_RAGR, WLZ_GREY_UBYTE, NULL), zeroV, &errNum); if(errNum == WLZ_ERR_NONE) { /* Use the input domain while calculating the new maximal domain. */ tmpObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, grdM->domain, tmpVal, NULL, NULL, &errNum); } } /* Initialize the memory pool with some size of block. Any +ve number * greater than the maximum number of intervals in any destination line * would work but the fewer allocations then the more efficient the code, * hence this attempt to guess the required number of intervals in the * destination domain. */ if(errNum == WLZ_ERR_NONE) { pool.itvsInBlock = (((grdDom.i->lastkl - grdDom.i->kol1 + 1) * (grdDom.i->lastln - grdDom.i->line1 + 1)) / 64) + grdDom.i->lastkl - grdDom.i->kol1 + 1024; } /* Make gradient buffers. */ if(errNum == WLZ_ERR_NONE) { bufSz.vtY = 3; bufSz.vtX = grdDom.i->lastkl - grdDom.i->kol1 + 1; if(bufType == WLZ_GREY_INT) { if((AlcInt2Malloc((int ***)&grdMBuf, bufSz.vtY, bufSz.vtX) != ALC_ER_NONE) || ((grdYBuf = AlcMalloc(sizeof(int) * bufSz.vtX)) == NULL) || ((grdXBuf = AlcMalloc(sizeof(int) * bufSz.vtX)) == NULL)) { errNum = WLZ_ERR_MEM_ALLOC; } else { grdYBufGP.inp = (int *)grdYBuf; grdXBufGP.inp = (int *)grdXBuf; } } else /* bufType == WLZ_GREY_DOUBLE */ { if((AlcDouble2Malloc((double ***)&grdMBuf, bufSz.vtY, bufSz.vtX) != ALC_ER_NONE) || ((grdYBuf = AlcMalloc(sizeof(double) * bufSz.vtX)) == NULL) || ((grdXBuf = AlcMalloc(sizeof(double) * bufSz.vtX)) == NULL)) { errNum = WLZ_ERR_MEM_ALLOC; } else { grdYBufGP.dbp = (double *)grdYBuf; grdXBufGP.dbp = (double *)grdXBuf; } } } /* Make destination interval domain with interval lines but not intervals. */ if(errNum == WLZ_ERR_NONE) { dstDom.i = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_INTVL, grdDom.i->line1, grdDom.i->lastln, grdDom.i->kol1, grdDom.i->lastkl, &errNum); } if(errNum == WLZ_ERR_NONE) { /* Scan down through the gradient objects. */ if(((errNum = WlzInitGreyScan(tmpObj, &tmpIWSp, &tmpGWSp)) == WLZ_ERR_NONE) && ((errNum = WlzInitGreyScan(grdM, &grdMIWSp, &grdMGWSp)) == WLZ_ERR_NONE) && ((errNum = WlzInitGreyScan(grdY, &grdYIWSp, &grdYGWSp)) == WLZ_ERR_NONE) && ((errNum = WlzInitGreyScan(grdX, &grdXIWSp, &grdXGWSp)) == WLZ_ERR_NONE)) { orgPos.vtX = grdDom.i->kol1; orgPos.vtY = grdDom.i->line1; while((errNum == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&grdMIWSp)) == WLZ_ERR_NONE)) { inLen = grdMIWSp.rgtpos - grdMIWSp.lftpos + 1; inPos.vtX = grdMIWSp.lftpos - orgPos.vtX; /* Process any lines between this and the last by clearing the * gradient magnitude buffer . */ if(grdMIWSp.nwlpos > 0) { idN = (grdMIWSp.nwlpos >= 3)? 3: grdMIWSp.nwlpos; while(--idN >= 0) { inPos.vtY = grdMIWSp.linpos - orgPos.vtY - idN; inLnIdx = (3 + inPos.vtY) % 3; if(bufType == WLZ_GREY_INT) { WlzValueSetInt(*((int **)grdMBuf + inLnIdx), 0, bufSz.vtX); } else /* bufType == WLZ_GREY_DOUBLE */ { WlzValueSetDouble(*((double **)grdMBuf + inLnIdx), 0, bufSz.vtX); } } } /* Copy intervals to values buffers. */ if(bufType == WLZ_GREY_INT) { grdMBufGP.inp = *((int **)grdMBuf + inLnIdx); } else /* bufType == WLZ_GREY_DOUBLE */ { grdMBufGP.dbp = *((double **)grdMBuf + inLnIdx); } WlzValueCopyGreyToGrey(grdMBufGP, inPos.vtX, bufType, grdMGWSp.u_grintptr, 0, grdMGWSp.pixeltype, inLen); if(grdMIWSp.intrmn == 0) { while((errNum == WLZ_ERR_NONE) && (tmpIWSp.linpos < grdMIWSp.linpos)) { outPos.vtY = tmpIWSp.linpos - orgPos.vtY; if(outPos.vtY >= 0) { outLen = tmpIWSp.rgtpos - tmpIWSp.lftpos + 1; outPos.vtX = tmpIWSp.lftpos - orgPos.vtX; WlzValueCopyGreyToGrey(grdYBufGP, 0, bufType, grdYGWSp.u_grintptr, 0, grdYGWSp.pixeltype, outLen); WlzValueCopyGreyToGrey(grdXBufGP, 0, bufType, grdXGWSp.u_grintptr, 0, grdXGWSp.pixeltype, outLen); if(bufType == WLZ_GREY_INT) { errNum = WlzNMSuppress2DBufI(dstDom.i, (int **)grdMBuf, (int *)grdYBuf, (int *)grdXBuf, &pool, tmpGWSp.u_grintptr.ubp, outLen, outPos, orgPos, minThrV.v.inv); } else /* bufType == WLZ_GREY_DOUBLE */ { errNum = WlzNMSuppress2DBufD(dstDom.i, (double **)grdMBuf, (double *)grdYBuf, (double *)grdXBuf, &pool, tmpGWSp.u_grintptr.ubp, outLen, outPos, orgPos, minThrV.v.dbv); } } if(errNum == WLZ_ERR_NONE) { errNum = WlzNextGreyInterval(&tmpIWSp); } if(errNum == WLZ_ERR_NONE) { errNum = WlzNextGreyInterval(&grdYIWSp); } if(errNum == WLZ_ERR_NONE) { errNum = WlzNextGreyInterval(&grdXIWSp); } } } } if(errNum == WLZ_ERR_EOO) { errNum = WLZ_ERR_NONE; } } if(tmpIWSp.gryptr == &tmpGWSp) { (void )WlzEndGreyScan(&tmpIWSp, &tmpGWSp); } if(grdMIWSp.gryptr == &grdMGWSp) { (void )WlzEndGreyScan(&grdMIWSp, &grdMGWSp); } if(grdYIWSp.gryptr == &grdYGWSp) { (void )WlzEndGreyScan(&grdYIWSp, &grdYGWSp); } if(grdXIWSp.gryptr == &grdXGWSp) { (void )WlzEndGreyScan(&grdXIWSp, &grdXGWSp); } } if(errNum == WLZ_ERR_NONE) { if((errNum = WlzStandardIntervalDomain(dstDom.i)) == WLZ_ERR_NONE) { dstObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, dstDom, tmpVal, NULL, NULL, &errNum); } } if(tmpObj) { WlzFreeObj(tmpObj); } if(errNum != WLZ_ERR_NONE) { if(tmpObj == NULL) { if(dstDom.core) { (void )WlzFreeDomain(dstDom); } if(tmpVal.core) { (void )WlzFreeValues(tmpVal); } } } if(grdMBuf) { Alc2Free(grdMBuf); } if(grdYBuf) { AlcFree(grdYBuf); } if(grdXBuf) { AlcFree(grdXBuf); } if(dstErr) { *dstErr = errNum; } return(dstObj); }
/*! * \return projection object * \ingroup WlzTransform * \brief Use the view transform to define a projection from * 3D to 2D. Currently only the domain is projected as * an opaque shadow. * This is old code temporarily kept for compatibility. * \param obj source 3D object * \param viewStr view structure defining the projection * \param intFunc grey-value summation function * \param intFuncData data to be passed to the integration function * \param dstErr error return */ WlzObject *WlzGetProjectionFromObject( WlzObject *obj, WlzThreeDViewStruct *viewStr, Wlz3DProjectionIntFn intFunc, void *intFuncData, WlzErrorNum *dstErr) { WlzObject *rtnObj=NULL, *obj1; WlzThreeDViewStruct *viewStr1=NULL; WlzDomain domain; WlzValues values; WlzGreyType srcGType = WLZ_GREY_UBYTE, dstGType = WLZ_GREY_UBYTE; WlzPixelV pixval; WlzPixelP pixptr; WlzIntervalWSpace iwsp; WlzGreyWSpace gwsp; WlzGreyValueWSpace *gVWSp = NULL; WlzDVertex3 vtx, vtx1; double x, y, z; double *s_to_x=NULL; double *s_to_y=NULL; double *s_to_z=NULL; int k, xp, yp, s, sp; int length = 0, size = 0, occupiedFlg; WlzErrorNum errNum=WLZ_ERR_NONE; /* check inputs */ if( obj == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; } else if( obj->type != WLZ_3D_DOMAINOBJ ){ errNum = WLZ_ERR_OBJECT_TYPE; } else if( obj->domain.core == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; } else if( obj->domain.core->type != WLZ_PLANEDOMAIN_DOMAIN ){ errNum = WLZ_ERR_DOMAIN_TYPE; } if( (errNum == WLZ_ERR_NONE) && (viewStr == NULL) ){ errNum = WLZ_ERR_OBJECT_NULL; } /* create new view transform */ if( errNum == WLZ_ERR_NONE ){ if((viewStr1 = WlzMake3DViewStruct(WLZ_3D_VIEW_STRUCT, &errNum)) != NULL){ /* need to worry about fixed line mode here sometime */ viewStr1->fixed = viewStr->fixed; viewStr1->theta = viewStr->theta; viewStr1->phi = viewStr->phi; viewStr1->zeta = viewStr->zeta; viewStr1->dist = viewStr->dist; viewStr1->scale = viewStr->scale; viewStr1->voxelSize[0] = viewStr->voxelSize[0]; viewStr1->voxelSize[1] = viewStr->voxelSize[1]; viewStr1->voxelSize[2] = viewStr->voxelSize[2]; viewStr1->voxelRescaleFlg = viewStr->voxelRescaleFlg; viewStr1->interp = viewStr->interp; viewStr1->view_mode = viewStr->view_mode; viewStr1->up = viewStr->up; /* now intialize it */ /* could optimise by setting fixed point to object centre */ if( (errNum = WlzInit3DViewStruct(viewStr1, obj)) != WLZ_ERR_NONE ){ WlzFree3DViewStruct(viewStr1); viewStr1 = NULL; } } } /* set up orthogonal line parameters & luts */ if( errNum == WLZ_ERR_NONE ){ length = WLZ_NINT(viewStr1->maxvals.vtZ) - WLZ_NINT(viewStr1->minvals.vtZ) + 1; s_to_x = (double *) AlcMalloc(sizeof(double) * length ); s_to_y = (double *) AlcMalloc(sizeof(double) * length ); s_to_z = (double *) AlcMalloc(sizeof(double) * length ); /* transform a perpendicular vector */ vtx.vtX = 0.0; vtx.vtY = 0.0; vtx.vtZ = 1.0; Wlz3DSectionTransformInvVtx(&vtx, viewStr1); vtx1.vtX = 0.0; vtx1.vtY = 0.0; vtx1.vtZ = 0.0; Wlz3DSectionTransformInvVtx(&vtx1, viewStr1); vtx.vtX -= vtx1.vtX; vtx.vtY -= vtx1.vtY; vtx.vtZ -= vtx1.vtZ; /* assign lut values */ s = (int )(WLZ_NINT(viewStr1->minvals.vtZ) - viewStr1->dist); for(sp=0; sp < length; sp++, s++){ s_to_x[sp] = s * vtx.vtX; s_to_y[sp] = s * vtx.vtY; s_to_z[sp] = s * vtx.vtZ; } } /* if there is an integration function then allocate space for the grey-level array */ if( (errNum == WLZ_ERR_NONE) && (intFunc) ){ srcGType = WlzGreyTypeFromObj(obj, &errNum); switch( srcGType ){ case WLZ_GREY_LONG: size = sizeof(WlzLong)*length; break; case WLZ_GREY_INT: size = sizeof(int)*length; break; case WLZ_GREY_SHORT: size = sizeof(short)*length; break; case WLZ_GREY_UBYTE: size = sizeof(WlzUByte)*length; break; case WLZ_GREY_FLOAT: size = sizeof(float)*length; break; case WLZ_GREY_DOUBLE: size = sizeof(double)*length; break; case WLZ_GREY_RGBA: size = sizeof(int)*length; break; default: errNum = WLZ_ERR_GREY_TYPE; break; } if( (pixptr.p.inp = (int *) AlcMalloc(size)) == NULL ){ errNum = WLZ_ERR_MEM_ALLOC; } pixptr.type = srcGType; /* set up the grey-value workspace for random access */ gVWSp = WlzGreyValueMakeWSp(obj, &errNum); } /* create rectangular projection image */ if( errNum == WLZ_ERR_NONE ){ if((domain.i = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_RECT, WLZ_NINT(viewStr1->minvals.vtY), WLZ_NINT(viewStr1->maxvals.vtY), WLZ_NINT(viewStr1->minvals.vtX), WLZ_NINT(viewStr1->maxvals.vtX), &errNum)) != NULL){ values.core = NULL; if((rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domain, values, NULL, NULL, &errNum)) != NULL){ /* note the grey-values required are determined by the integration function. Here we use WlzUByte and reset later if needed */ dstGType = WLZ_GREY_UBYTE; pixval.type = WLZ_GREY_UBYTE; pixval.v.ubv = (WlzUByte )0; if((values.v = WlzNewValueTb(rtnObj, WlzGreyTableType(WLZ_GREY_TAB_RECT, dstGType, NULL), pixval, &errNum)) != NULL){ rtnObj->values = WlzAssignValues(values, &errNum); } else { WlzFreeObj(rtnObj); rtnObj = NULL; } } else { WlzFreeDomain(domain); domain.core = NULL; } } } /* scan image setting values */ if( errNum == WLZ_ERR_NONE ){ errNum = WlzInitGreyScan(rtnObj, &iwsp, &gwsp); } if( errNum == WLZ_ERR_NONE ){ while( (errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE ){ yp = iwsp.linpos - WLZ_NINT(viewStr1->minvals.vtY); for(k=iwsp.lftpos; k <= iwsp.rgtpos; k++){ xp = k - WLZ_NINT(viewStr1->minvals.vtX); vtx.vtX = viewStr1->xp_to_x[xp] + viewStr1->yp_to_x[yp]; vtx.vtY = viewStr1->xp_to_y[xp] + viewStr1->yp_to_y[yp]; vtx.vtZ = viewStr1->xp_to_z[xp] + viewStr1->yp_to_z[yp]; /* get the projection values */ /* if no function then just check for occupancy */ if( intFunc == NULL ){ occupiedFlg = 0; sp = (int )(viewStr1->dist - WLZ_NINT(viewStr1->minvals.vtZ)); for(; !occupiedFlg && (sp < length); sp++){ x = vtx.vtX + s_to_x[sp]; y = vtx.vtY + s_to_y[sp]; z = vtx.vtZ + s_to_z[sp]; if( WlzInsideDomain(obj, z, y, x, &errNum) ){ occupiedFlg = 1; } } sp = (int )(viewStr1->dist - WLZ_NINT(viewStr1->minvals.vtZ) - 1); for(; !occupiedFlg && (sp >= 0); sp--){ x = vtx.vtX + s_to_x[sp]; y = vtx.vtY + s_to_y[sp]; z = vtx.vtZ + s_to_z[sp]; if( WlzInsideDomain(obj, z, y, x, &errNum) ){ occupiedFlg = 1; } } /* set the integrated value - only WlzUByte at the moment */ *(gwsp.u_grintptr.ubp) = (WlzUByte )occupiedFlg; gwsp.u_grintptr.ubp++; } /* use integration function */ else { /* set array of pixel values */ for(sp=0; sp < length; sp++){ x = vtx.vtX + s_to_x[sp]; y = vtx.vtY + s_to_y[sp]; z = vtx.vtZ + s_to_z[sp]; WlzGreyValueGet(gVWSp, WLZ_NINT(z), WLZ_NINT(y), WLZ_NINT(x)); switch( srcGType ){ case WLZ_GREY_LONG: pixptr.p.lnp[sp] = gVWSp->gVal[0].lnv; break; case WLZ_GREY_INT: pixptr.p.inp[sp] = gVWSp->gVal[0].inv; break; case WLZ_GREY_SHORT: pixptr.p.shp[sp] = gVWSp->gVal[0].shv; break; case WLZ_GREY_UBYTE: pixptr.p.ubp[sp] = gVWSp->gVal[0].ubv; break; case WLZ_GREY_FLOAT: pixptr.p.flp[sp] = gVWSp->gVal[0].flv; break; case WLZ_GREY_DOUBLE: pixptr.p.dbp[sp] = gVWSp->gVal[0].dbv; break; case WLZ_GREY_RGBA: pixptr.p.rgbp[sp] = gVWSp->gVal[0].rgbv; break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } /* call integration function and seet value */ intFunc(pixptr, length, (int )(viewStr1->dist - WLZ_NINT(viewStr1->minvals.vtZ)), intFuncData, &errNum); } } } (void )WlzEndGreyScan(&iwsp, &gwsp); if(errNum == WLZ_ERR_EOO) /* Reset error from end of intervals */ { errNum = WLZ_ERR_NONE; } /* if no integration function then threshold - binary only */ if( intFunc == NULL ){ pixval.v.ubv = 1; rtnObj = WlzAssignObject(rtnObj, NULL); if((obj1 = WlzThreshold(rtnObj, pixval, WLZ_THRESH_HIGH, &errNum)) != NULL){ WlzFreeObj(rtnObj); values.core = NULL; rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, obj1->domain, values, NULL, NULL, &errNum); WlzFreeObj(obj1); } else { WlzFreeObj(rtnObj); rtnObj = NULL; } } } /* clear space */ if( viewStr1 ){ errNum = WlzFree3DViewStruct(viewStr1); } if( s_to_x ){ AlcFree( s_to_x ); } if( s_to_y ){ AlcFree( s_to_y ); } if( s_to_z ){ AlcFree( s_to_z ); } /* check error and return */ if( dstErr ){ *dstErr = errNum; } return rtnObj; }
int main(int argc, char **argv) { int dim = 3, nSPts, nIPts, nOPts, option, planeFlg = 0, planeIdx = 0, ok = 1, usage = 0; double delta, tau, sAlpha, iAlpha, oAlpha, iDist, oDist, samFac = 1.0; WlzObject *dObj = NULL; WlzBox bBox0, bBox1; WlzVertexP sPts, iPts, oPts; WlzPixelV bgdV; WlzDomain outDom; WlzValues dumVal; WlzObject *outObj = NULL; FILE *fP = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; char *sFileStr, *iFileStr, *oFileStr, *outObjFileStr; const char *errMsg; static char optList[] = "h23o:S:I:O:a:b:c:d:e:D:M:T:X:", defFileStr[] = "-"; bgdV.type = WLZ_GREY_DOUBLE; outDom.core = NULL; dumVal.core = NULL; sPts.v = iPts.v = oPts.v = NULL; /* Parse the command line. */ opterr = 0; sFileStr = iFileStr = oFileStr = outObjFileStr = defFileStr; while(ok && ((option = getopt(argc, argv, optList)) != -1)) { switch(option) { case '2': dim = 2; break; case '3': dim = 3; break; case 'o': outObjFileStr = optarg; break; case 'S': sFileStr = optarg; break; case 'I': iFileStr = optarg; break; case 'O': oFileStr = optarg; break; case 'a': if(sscanf(optarg, "%lg", &sAlpha) != 1) { usage = 1; } break; case 'b': if(sscanf(optarg, "%lg", &iAlpha) != 1) { usage = 1; } break; case 'c': if(sscanf(optarg, "%lg", &oAlpha) != 1) { usage = 1; } break; case 'd': if(sscanf(optarg, "%lg", &iDist) != 1) { usage = 1; } break; case 'e': if(sscanf(optarg, "%lg", &oDist) != 1) { usage = 1; } break; case 'D': if(sscanf(optarg, "%lg", &delta) != 1) { usage = 1; } break; case 'M': if(sscanf(optarg, "%lg", &samFac) != 1) { usage = 1; } break; case 'T': if(sscanf(optarg, "%lg", &tau) != 1) { usage = 1; } break; case 'X': if(sscanf(optarg, "%d", &planeIdx) != 1) { usage = 1; } else { planeFlg = 1; } break; case 'h': default: usage = 1; break; } } if(ok && (optind < argc)) { usage = 1; } if((outObjFileStr == NULL) || (*outObjFileStr == '\0') || (sFileStr == NULL) || (*sFileStr == '\0') || (iFileStr == NULL) || (*iFileStr == '\0') || (oFileStr == NULL) || (*oFileStr == '\0')) { usage = 1; } ok = ok && !usage; /* Read the surface, inside and outside points. */ if(ok) { if(strcmp(sFileStr, "-")) { if((fP = fopen(sFileStr, "r")) == NULL) { ok = 0; errNum = WLZ_ERR_READ_EOF; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to open surface points file %s (%s).\n", *argv, sFileStr, errMsg); } } else { fP = stdin; } } if(ok) { sPts = WlzCFPReadVtxArray(fP, dim, &nSPts, &errNum); if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to read points from file %s (%s).\n", *argv, sFileStr, errMsg); } } if(fP) { if(strcmp(sFileStr, "-")) { (void )fclose(fP); } fP = NULL; } if(ok) { if(strcmp(sFileStr, "-")) { if((fP = fopen(iFileStr, "r")) == NULL) { ok = 0; errNum = WLZ_ERR_READ_EOF; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to open inside points file %s (%s).\n", *argv, iFileStr, errMsg); } } else { fP = stdin; } } if(ok) { iPts = WlzCFPReadVtxArray(fP, dim, &nIPts, &errNum); if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to read points from file %s (%s).\n", *argv, sFileStr, errMsg); } } if(fP) { if(strcmp(iFileStr, "-")) { (void )fclose(fP); } fP = NULL; } if(ok) { if(strcmp(sFileStr, "-")) { if((fP = fopen(oFileStr, "r")) == NULL) { ok = 0; errNum = WLZ_ERR_READ_EOF; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to open outside points file %s (%s).\n", *argv, oFileStr, errMsg); } } else { fP = stdin; } } if(ok) { oPts = WlzCFPReadVtxArray(fP, dim, &nOPts, &errNum); if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to read points from file %s (%s).\n", *argv, oFileStr, errMsg); } } if(fP) { if(strcmp(oFileStr, "-")) { (void )fclose(fP); } fP = NULL; } if(ok) { bgdV.v.dbv = oDist; bgdV.type = WLZ_GREY_DOUBLE; switch(dim) { case 2: errNum = WLZ_ERR_UNIMPLEMENTED; break; case 3: /* Compute ounding box of points. */ bBox0.d3 = WlzBoundingBoxVtx3D(nSPts, sPts.d3, NULL); bBox1.d3 = WlzBoundingBoxVtx3D(nIPts, iPts.d3, NULL); bBox0.d3 = WlzBoundingBoxUnion3D(bBox0.d3, bBox1.d3); bBox1.d3 = WlzBoundingBoxVtx3D(nOPts, oPts.d3, NULL); bBox0.d3 = WlzBoundingBoxUnion3D(bBox0.d3, bBox1.d3); /* Create distance object that will be used to accumulate distance values. If only a 2D contour is required then create a distance object with a single plane. */ dObj = WlzMakeCuboid((planeFlg)? planeIdx: (int )floor(bBox0.d3.zMin) - 2, (planeFlg)? planeIdx: (int )ceil(bBox0.d3.zMax) + 2, (int )floor(bBox0.d3.yMin) - 2, (int )ceil(bBox0.d3.yMax) + 2, (int )floor(bBox0.d3.xMin) - 2, (int )ceil(bBox0.d3.xMax) + 2, WLZ_GREY_DOUBLE, bgdV, NULL, NULL, &errNum); if((dObj == NULL) || (errNum != WLZ_ERR_NONE)) { ok = 0; if(errNum == WLZ_ERR_NONE) { errNum = WLZ_ERR_MEM_ALLOC; } (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to allocate distance object (%s).\n", *argv, errMsg); } /* Compute contour using given distance object. */ outDom.ctr = WlzContourFromPoints(dObj, WLZ_VERTEX_D3, nSPts, sPts, sAlpha, nIPts, iPts, iDist, iAlpha, nOPts, oPts, oDist, oAlpha, delta, tau, samFac, &errNum); WlzFreeObj(dObj); break; } if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to compute contour from points (%s).\n", *argv, errMsg); } } /* Compute the contour from the point sets. */ if(ok) { outObj = WlzMakeMain(WLZ_CONTOUR, outDom, dumVal, NULL, NULL, &errNum); if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: Failed to create output woolz object (%s).\n", argv[0], errMsg); } if(outObj) { outDom.core = NULL; } } /* Write out the contour object. */ if(ok) { if(strcmp(outObjFileStr, "-")) { if((fP = fopen(outObjFileStr, "w")) == NULL) { ok = 0; errNum = WLZ_ERR_WRITE_EOF; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to open output object file %s (%s).\n", *argv, outObjFileStr, errMsg); } } else { fP = stdout; } if(ok) { if((errNum = WlzWriteObj(fP, outObj)) != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to write output object to file %s (%s).\n", *argv, outObjFileStr, errMsg); } } if(strcmp(outObjFileStr, "-")) { (void )fclose(fP); } fP = NULL; } AlcFree(sPts.v); AlcFree(iPts.v); AlcFree(oPts.v); (void )WlzFreeDomain(outDom); (void )WlzFreeObj(outObj); /* Tidy up and exit. */ if(usage) { (void )fprintf(stderr, "Usage: %s%s", *argv, "WlzContourFromPoints [-h] [-2] [-3] [-o<out object>]\n" " [-S<surface points file>]\n" " [-I<inside points file>] [-O<outside points file>]\n" " [-a#] [-b#] [-c#] [-d#] [-e#] [-D#] [-M#] [-T#]\n" " [-X#]\n" "Options:\n" " -h Print this usage message.\n" " -2 Points are 2D and contour is a curve in 2D.\n" " -3 Points are 3D and contour is a surface in 3D.\n" " -o Output object file name.\n" " -S On surface points file.\n" " -I Inside points file.\n" " -O Outside points file.\n" " -a Surface points alpha value.\n" " -b Inside points alpha value.\n" " -c Outside points alpha value.\n" " -d Inside points distance value.\n" " -e Outside points distance value.\n" " -D Delta multiorder spline soothing value.\n" " -M Distance object sampling factor (can be used to reduce the\n" " number of surface facets.)\n" " -T Tau multiorder spline soothing value.\n" " -X Plane for 2D contour from 3D point sets.\n" "Computes a contour from three point sets: inside; outside and on a\n" "surface.\n" "All points are given using the following ascii format:\n" " <vertex x> <vertex y> [<vertex z>]\n"); } return(!ok); }
/*! * \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); }