/************************************************************************* snaphu tile-mode source file Written by Curtis W. Chen Copyright 2002 Board of Trustees, Leland Stanford Jr. University Please see the supporting documentation for terms of use. No warranty. *************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "snaphu.h" /* function: SetupTile() * --------------------- * Sets up tile parameters and output file names for the current tile. */ void SetupTile(long nlines, long linelen, paramT *params, tileparamT *tileparams, outfileT *outfiles, outfileT *tileoutfiles, long tilerow, long tilecol){ long ni, nj; char tempstring[MAXTMPSTRLEN], path[MAXSTRLEN], basename[MAXSTRLEN]; char *tiledir; /* set parameters for current tile */ ni=ceil((nlines+(params->ntilerow-1)*params->rowovrlp) /(double )params->ntilerow); nj=ceil((linelen+(params->ntilecol-1)*params->colovrlp) /(double )params->ntilecol); tileparams->firstrow=tilerow*(ni-params->rowovrlp); tileparams->firstcol=tilecol*(nj-params->colovrlp); if(tilerow==params->ntilerow-1){ tileparams->nrow=nlines-(params->ntilerow-1)*(ni-params->rowovrlp); }else{ tileparams->nrow=ni; } if(tilecol==params->ntilecol-1){ tileparams->ncol=linelen-(params->ntilecol-1)*(nj-params->colovrlp); }else{ tileparams->ncol=nj; } /* set output files */ tiledir=params->tiledir; ParseFilename(outfiles->outfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->outfile,tempstring,MAXSTRLEN); if(strlen(outfiles->initfile)){ ParseFilename(outfiles->initfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->initfile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->initfile,"",MAXSTRLEN); } if(strlen(outfiles->flowfile)){ ParseFilename(outfiles->flowfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->flowfile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->flowfile,"",MAXSTRLEN); } if(strlen(outfiles->eifile)){ ParseFilename(outfiles->eifile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->eifile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->eifile,"",MAXSTRLEN); } if(strlen(outfiles->rowcostfile)){ ParseFilename(outfiles->rowcostfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->rowcostfile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->rowcostfile,"",MAXSTRLEN); } if(strlen(outfiles->colcostfile)){ ParseFilename(outfiles->colcostfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->colcostfile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->colcostfile,"",MAXSTRLEN); } if(strlen(outfiles->mstrowcostfile)){ ParseFilename(outfiles->mstrowcostfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->mstrowcostfile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->mstrowcostfile,"",MAXSTRLEN); } if(strlen(outfiles->mstcolcostfile)){ ParseFilename(outfiles->mstcolcostfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->mstcolcostfile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->mstcolcostfile,"",MAXSTRLEN); } if(strlen(outfiles->mstcostsfile)){ ParseFilename(outfiles->mstcostsfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->mstcostsfile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->mstcostsfile,"",MAXSTRLEN); } if(strlen(outfiles->corrdumpfile)){ ParseFilename(outfiles->corrdumpfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->corrdumpfile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->corrdumpfile,"",MAXSTRLEN); } if(strlen(outfiles->rawcorrdumpfile)){ ParseFilename(outfiles->rawcorrdumpfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->rawcorrdumpfile,tempstring,MAXSTRLEN); }else{ StrNCopy(tileoutfiles->rawcorrdumpfile,"",MAXSTRLEN); } if(strlen(outfiles->costoutfile)){ ParseFilename(outfiles->costoutfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld", tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol); StrNCopy(tileoutfiles->costoutfile,tempstring,MAXSTRLEN); }else{ sprintf(tempstring,"%s/%s%s%ld_%ld.%ld", tiledir,TMPTILEROOT,TMPTILECOSTSUFFIX,tilerow,tilecol, tileparams->ncol); StrNCopy(tileoutfiles->costoutfile,tempstring,MAXSTRLEN); } tileoutfiles->outfileformat=TMPTILEOUTFORMAT; } /* function: GrowRegions() * ----------------------- * Grows contiguous regions demarcated by arcs whose residual costs are * less than some threshold. Numbers the regions sequentially from 0. */ void GrowRegions(void **costs, short **flows, long nrow, long ncol, incrcostT **incrcosts, outfileT *outfiles, paramT *params){ long i, row, col, maxcol; long arcrow, arccol, arcnum, fromdist, arcdist; long regioncounter, *regionsizes, regionsizeslen, *thisregionsize; long closestregiondist, closestregion, lastfromdist; long costthresh, minsize, maxcost; short **regions; nodeT **nodes; nodeT *source, *from, *to, *ground; char regionfile[MAXSTRLEN]; bucketT bkts[1]; /* error checking */ fprintf(sp1,"Growing reliable regions\n"); minsize=params->minregionsize; costthresh=params->tilecostthresh; if(minsize>nrow*ncol){ fprintf(sp0,"Minimum region size cannot exceed tile size\nAbort\n"); exit(ABNORMAL_EXIT); } /* loop over all arcs */ for(arcrow=0;arcrow<2*nrow-1;arcrow++){ if(arcrowsize=maxcost+2; bkts->minind=0; bkts->maxind=bkts->size-1; bkts->curr=0; bkts->wrapped=FALSE; bkts->bucketbase=(nodeT **)MAlloc(bkts->size*sizeof(nodeT *)); bkts->bucket=bkts->bucketbase; for(i=0;isize;i++){ bkts->bucket[i]=NULL; } /* initialize region variables */ regioncounter=-1; regionsizeslen=INITARRSIZE; regionsizes=(long *)MAlloc(regionsizeslen*sizeof(long)); for(row=0;rownext=NULL; source->prev=NULL; source->group=INBUCKET; source->outcost=0; bkts->bucket[0]=source; bkts->curr=0; lastfromdist=0; /* increment the region counter */ if(++regioncounter>=regionsizeslen){ regionsizeslen+=INITARRSIZE; regionsizes=(long *)ReAlloc(regionsizes, regionsizeslen*sizeof(long)); } thisregionsize=®ionsizes[regioncounter]; /* set up */ (*thisregionsize)=0; closestregiondist=VERYFAR; /* loop to grow region */ while(TRUE){ /* set from node to closest node in circular bucket structure */ from=ClosestNode(bkts); /* break if we can't grow any more and the region is big enough */ if(from==NULL){ if(*thisregionsize>=minsize){ /* no more nonregion nodes, and current region is big enough */ break; }else{ /* no more nonregion nodes, but current region still too small */ /* merge with another region */ MergeRegions(nodes,source,regionsizes,closestregion,nrow,ncol); regioncounter--; break; } }else{ fromdist=from->outcost; if(fromdist>lastfromdist){ if(regionsizes[regioncounter]>=minsize){ /* region grown to all nodes within mincost, is big enough */ break; } if(fromdist>closestregiondist){ /* another region closer than new node, so merge regions */ MergeRegions(nodes,source,regionsizes,closestregion,nrow,ncol); regioncounter--; break; } } } /* make from node a part of the current region */ from->incost=regioncounter; (*thisregionsize)++; lastfromdist=fromdist; /* scan from's neighbors */ arcnum=0; while((to=RegionsNeighborNode(from,&arcnum,nodes, &arcrow,&arccol,nrow,ncol))!=NULL){ /* get cost of arc to the to node */ arcdist=incrcosts[arcrow][arccol].negcost; /* see if to node is already in another region */ if(to->incost>=0){ /* keep track of which neighboring region is closest */ if(to->incost!=regioncounter && arcdistincost; } }else{ /* to node is not in another region */ /* compare distance of new nodes to temp labels */ if(arcdist<(to->outcost)){ /* if to node is already in a (circular) bucket, remove it */ if(to->group==INBUCKET){ BucketRemove(to,to->outcost,bkts); } /* update to node */ to->outcost=arcdist; to->pred=from; /* insert to node into appropriate (circular) bucket */ BucketInsert(to,arcdist,bkts); if(arcdistcurr){ bkts->curr=arcdist; } } } } } } } } fprintf(sp2,"Tile partitioned into %ld regions\n",regioncounter+1); /* write regions array */ /* write as shorts if multiple tiles */ if(params->ntilerow > 1 || params->ntilecol>1){ regions=(short **)Get2DMem(nrow,ncol,sizeof(short *),sizeof(short)); for(row=0;rowLARGESHORT){ fprintf(sp0, "Number of regions in tile exceeds max allowed\nAbort\n"); exit(ABNORMAL_EXIT); } regions[row][col]=nodes[row][col].incost; } } sprintf(regionfile,"%s%s",outfiles->outfile,REGIONSUFFIX); fprintf(sp2,"Writing region data to file %s\n",regionfile); Write2DArray((void **)regions,regionfile,nrow,ncol,sizeof(short)); } /* free memory */ Free2DArray((void **)nodes,nrow); Free2DArray((void **)regions,nrow); free(bkts->bucketbase); } /* function: GrowConnCompMask() * ---------------------------- * Grows contiguous regions demarcated by arcs whose residual costs are * less than some threshold. Numbers the regions sequentially from 1. * Writes out byte file of connected component mask, with 0 for any pixels * not assigned to a component. */ void GrowConnCompsMask(void **costs, short **flows, long nrow, long ncol, incrcostT **incrcosts, outfileT *outfiles, paramT *params){ long i, row, col, maxcol; long arcrow, arccol, arcnum; long regioncounter, *regionsizes, regionsizeslen, *thisregionsize; long *sortedregionsizes; long costthresh, minsize, maxncomps, ntied, newnum; nodeT **nodes; nodeT *source, *from, *to, *ground; unsigned char **components; bucketT bkts[1]; /* error checking */ fprintf(sp1,"Growing connected component mask\n"); minsize=params->minconncompfrac*nrow*ncol; maxncomps=params->maxncomps; costthresh=params->conncompthresh; if(minsize>nrow*ncol){ fprintf(sp0,"Minimum region size cannot exceed tile size\nAbort\n"); exit(ABNORMAL_EXIT); } /* loop over all arcs */ for(arcrow=0;arcrow<2*nrow-1;arcrow++){ if(arcrowsize=1; bkts->minind=0; bkts->maxind=0; bkts->wrapped=FALSE; bkts->bucketbase=(nodeT **)MAlloc(sizeof(nodeT *)); bkts->bucket=bkts->bucketbase; bkts->bucket[0]=NULL; /* initialize region variables */ regioncounter=0; regionsizeslen=INITARRSIZE; regionsizes=(long *)MAlloc(regionsizeslen*sizeof(long)); for(row=0;rownext=NULL; source->prev=NULL; source->group=INBUCKET; source->outcost=0; bkts->bucket[0]=source; bkts->curr=0; /* increment the region counter */ if(++regioncounter>=regionsizeslen){ regionsizeslen+=INITARRSIZE; regionsizes=(long *)ReAlloc(regionsizes, regionsizeslen*sizeof(long)); } thisregionsize=®ionsizes[regioncounter]; /* set up */ (*thisregionsize)=0; /* loop to grow region */ while(TRUE){ /* set from node to closest node in circular bucket structure */ from=ClosestNode(bkts); /* break if we can't grow any more and the region is big enough */ if(from==NULL){ if(regionsizes[regioncounter]>=minsize){ /* no more nonregion nodes, and current region is big enough */ break; }else{ /* no more nonregion nodes, but current region still too small */ /* zero out the region */ RenumberRegion(nodes,source,0,nrow,ncol); regioncounter--; break; } } /* make from node a part of the current region */ from->incost=regioncounter; (*thisregionsize)++; /* scan from's neighbors */ arcnum=0; while((to=RegionsNeighborNode(from,&arcnum,nodes, &arcrow,&arccol,nrow,ncol))!=NULL){ /* see if to can be reached */ if(to->incost<0 && incrcosts[arcrow][arccol].negcost==0 && to->group!=INBUCKET){ /* update to node */ to->pred=from; BucketInsert(to,0,bkts); } } } } } } fprintf(sp2,"%ld connected components formed\n",regioncounter); /* make sure we don't have too many components */ if(regioncounter>maxncomps){ /* copy regionsizes array and sort to find new minimum region size */ fprintf(sp2,"Keeping only %ld connected components\n",maxncomps); sortedregionsizes=(long *)MAlloc(regioncounter*sizeof(long)); for(i=0;i=0 && sortedregionsizes[i]==minsize){ ntied++; i--; } /* zero out regions that are too small */ newnum=-1; for(row=0;row0){ if(regionsizes[i]0)){ /* region too small, so zero it out */ RenumberRegion(nodes,&(nodes[row][col]),0,nrow,ncol); }else{ /* keep region, assign it new region number */ /* temporarily assign negative of new number to avoid collisions */ RenumberRegion(nodes,&(nodes[row][col]),newnum--,nrow,ncol); } } } } /* flip temporary negative region numbers so they are positive */ for(row=0;row255){ fprintf(sp0,"Number of connected components too large for byte data\n" "Abort\n"); exit(ABNORMAL_EXIT); } components[row][col]=(unsigned char )(nodes[row][col].incost); } } fprintf(sp1,"Writing connected components to file %s\n", outfiles->conncompfile); Write2DArray((void **)components,outfiles->conncompfile,nrow,ncol, sizeof(unsigned char)); /* free memory */ Free2DArray((void **)nodes,nrow); Free2DArray((void **)components,nrow); free(bkts->bucketbase); } /* function: ThickenCosts() * ------------------------ */ long ThickenCosts(incrcostT **incrcosts, long nrow, long ncol){ long row, col, templong, maxcost; double n; /* initialize variable storing maximum cost */ maxcost=-LARGELONG; /* loop over row arcs and convolve */ for(row=0;rowLARGESHORT){ fprintf(sp0,"WARNING: COSTS CLIPPED IN ThickenCosts()\n"); incrcosts[row][col].negcost=LARGESHORT; }else{ incrcosts[row][col].negcost=templong; } if(incrcosts[row][col].negcost>maxcost){ maxcost=incrcosts[row][col].negcost; } } } /* loop over column arcs and convolve */ for(row=nrow-1;row<2*nrow-1;row++){ for(col=0;colLARGESHORT){ fprintf(sp0,"WARNING: COSTS CLIPPED IN ThickenCosts()\n"); incrcosts[row][col].negcost=LARGESHORT; }else{ incrcosts[row][col].negcost=templong; } if(incrcosts[row][col].negcost>maxcost){ maxcost=incrcosts[row][col].negcost; } } } /* return maximum cost */ return(maxcost); } /* function: RegionsNeighborNode() * ------------------------------- * Return the neighboring node of the given node corresponding to the * given arc number. */ nodeT *RegionsNeighborNode(nodeT *node1, long *arcnumptr, nodeT **nodes, long *arcrowptr, long *arccolptr, long nrow, long ncol){ long row, col; row=node1->row; col=node1->col; while(TRUE){ switch((*arcnumptr)++){ case 0: if(col!=ncol-1){ *arcrowptr=nrow-1+row; *arccolptr=col; return(&nodes[row][col+1]); } break; case 1: if(row!=nrow-1){ *arcrowptr=row; *arccolptr=col; return(&nodes[row+1][col]); } break; case 2: if(col!=0){ *arcrowptr=nrow-1+row; *arccolptr=col-1; return(&nodes[row][col-1]); } break; case 3: if(row!=0){ *arcrowptr=row-1; *arccolptr=col; return(&nodes[row-1][col]); } break; default: return(NULL); } } } /* function: ClearBuckets() * ------------------------ * Removes any nodes in the bucket data structure passed, and resets * their distances to VERYFAR. Assumes bukets indexed from 0. */ void ClearBuckets(bucketT *bkts){ nodeT *currentnode, *nextnode; long i; /* loop over all buckets */ for(i=0;isize;i++){ /* clear the bucket */ nextnode=bkts->bucketbase[i]; while(nextnode!=NULL){ currentnode=nextnode; nextnode=currentnode->next; currentnode->group=NOTINBUCKET; currentnode->outcost=VERYFAR; currentnode->pred=NULL; } bkts->bucketbase[i]=NULL; } /* reset bucket parameters */ bkts->minind=0; bkts->maxind=bkts->size-1; bkts->wrapped=FALSE; } /* function: MergeRegions() * ------------------------ * */ void MergeRegions(nodeT **nodes, nodeT *source, long *regionsizes, long closestregion, long nrow, long ncol){ long nextnodelistlen, nextnodelistnext, arcnum, arcrow, arccol, regionnum; nodeT *from, *to, **nextnodelist; /* initialize */ nextnodelistlen=INITARRSIZE; nextnodelist=(nodeT **)MAlloc(nextnodelistlen*sizeof(nodeT **)); nextnodelist[0]=source; nextnodelistnext=1; regionnum=source->incost; /* find all nodes in current region and switch their regions */ while(nextnodelistnext){ from=nextnodelist[--nextnodelistnext]; from->incost=closestregion; arcnum=0; while((to=RegionsNeighborNode(from,&arcnum,nodes, &arcrow,&arccol,nrow,ncol))!=NULL){ if(to->incost==regionnum){ if(nextnodelistnext>=nextnodelistlen){ nextnodelistlen+=INITARRSIZE; nextnodelist=(nodeT **)ReAlloc(nextnodelist, nextnodelistlen*sizeof(nodeT *)); } nextnodelist[nextnodelistnext++]=to; } } } /* update size of region to which we are merging */ regionsizes[closestregion]+=regionsizes[regionnum]; /* free memory */ free(nextnodelist); } /* function: RenumberRegion() * -------------------------- * */ void RenumberRegion(nodeT **nodes, nodeT *source, long newnum, long nrow, long ncol){ long nextnodelistlen, nextnodelistnext, arcnum, arcrow, arccol, regionnum; nodeT *from, *to, **nextnodelist; /* initialize */ nextnodelistlen=INITARRSIZE; nextnodelist=(nodeT **)MAlloc(nextnodelistlen*sizeof(nodeT **)); nextnodelist[0]=source; nextnodelistnext=1; regionnum=source->incost; /* find all nodes in current region and switch their regions */ while(nextnodelistnext){ from=nextnodelist[--nextnodelistnext]; from->incost=newnum; arcnum=0; while((to=RegionsNeighborNode(from,&arcnum,nodes, &arcrow,&arccol,nrow,ncol))!=NULL){ if(to->incost==regionnum){ if(nextnodelistnext>=nextnodelistlen){ nextnodelistlen+=INITARRSIZE; nextnodelist=(nodeT **)ReAlloc(nextnodelist, nextnodelistlen*sizeof(nodeT *)); } nextnodelist[nextnodelistnext++]=to; } } } /* free memory */ free(nextnodelist); } /* function: AssembleTiles() * ------------------------- */ void AssembleTiles(outfileT *outfiles, paramT *params, long nlines, long linelen){ long tilerow, tilecol, ntilerow, ntilecol, ntiles, rowovrlp, colovrlp; long i, j, k, ni, nj, dummylong, costtypesize; long nrow, ncol, prevnrow, prevncol, nextnrow, nextncol; long n, ncycle, nflowdone, nflow, candidatelistsize, candidatebagsize; long nnodes, maxnflowcycles, arclen, narcs, sourcetilenum, flowmax; long *totarclens; long ***scndrycosts; double avgarclen; float **unwphase, **nextunwphase, **lastunwphase, **tempunwphase; float *unwphaseabove, *unwphasebelow; void **costs, **nextcosts, **lastcosts, **tempcosts; void *costsabove, *costsbelow; short **scndryflows, **bulkoffsets, **regions, **nextregions, **lastregions; short **tempregions, *regionsbelow, *regionsabove; short *nscndrynodes, *nscndryarcs; incrcostT **incrcosts; totalcostT totalcost, oldtotalcost; nodeT *source; nodeT **scndrynodes, ***scndryapexes; signed char **iscandidate; signed char notfirstloop; candidateT *candidatebag, *candidatelist; nodesuppT **nodesupp; scndryarcT **scndryarcs; bucketT *bkts; char filename[MAXSTRLEN]; /* set up */ fprintf(sp1,"Assembling tiles\n"); ntilerow=params->ntilerow; ntilecol=params->ntilecol; ntiles=ntilerow*ntilecol; rowovrlp=params->rowovrlp; colovrlp=params->colovrlp; ni=ceil((nlines+(ntilerow-1)*rowovrlp)/(double )ntilerow); nj=ceil((linelen+(ntilecol-1)*colovrlp)/(double )ntilecol); nrow=0; ncol=0; flowmax=params->scndryarcflowmax; if(params->costmode==TOPO){ costtypesize=sizeof(costT); }else if(params->costmode==DEFO){ costtypesize=sizeof(costT); }else if(params->costmode==SMOOTH){ costtypesize=sizeof(smoothcostT); } /* get memory */ regions=(short **)Get2DMem(ni,nj,sizeof(short *),sizeof(short)); nextregions=(short **)Get2DMem(ni,nj,sizeof(short *),sizeof(short)); lastregions=(short **)Get2DMem(ni,nj,sizeof(short *),sizeof(short)); regionsbelow=(short *)MAlloc(nj*sizeof(short)); regionsabove=(short *)MAlloc(nj*sizeof(short)); unwphase=(float **)Get2DMem(ni,nj,sizeof(float *),sizeof(float)); nextunwphase=(float **)Get2DMem(ni,nj,sizeof(float *),sizeof(float)); lastunwphase=(float **)Get2DMem(ni,nj,sizeof(float *),sizeof(float)); unwphaseabove=(float *)MAlloc(nj*sizeof(float)); unwphasebelow=(float *)MAlloc(nj*sizeof(float)); scndrynodes=(nodeT **)MAlloc(ntiles*sizeof(nodeT *)); nodesupp=(nodesuppT **)MAlloc(ntiles*sizeof(nodesuppT *)); scndryarcs=(scndryarcT **)MAlloc(ntiles*sizeof(scndryarcT *)); scndrycosts=(long ***)MAlloc(ntiles*sizeof(long **)); nscndrynodes=(short *)MAlloc(ntiles*sizeof(short)); nscndryarcs=(short *)MAlloc(ntiles*sizeof(short)); totarclens=(long *)MAlloc(ntiles*sizeof(long)); bulkoffsets=(short **)Get2DMem(ntilerow,ntilecol,sizeof(short *), sizeof(short)); costs=(void **)Get2DRowColMem(ni+2,nj+2,sizeof(void *),costtypesize); nextcosts=(void **)Get2DRowColMem(ni+2,nj+2,sizeof(void *),costtypesize); lastcosts=(void **)Get2DRowColMem(ni+2,nj+2,sizeof(void *),costtypesize); costsabove=(void *)MAlloc(nj*costtypesize); costsbelow=(void *)MAlloc(nj*costtypesize); /* trace regions and parse secondary nodes and arcs for each tile */ bulkoffsets[0][0]=0; for(tilerow=0;tilerowmaxcyclefraction); while(TRUE){ fprintf(sp1,"Flow increment: %ld (Total improvements: %ld)\n", nflow,ncycle); /* set up the incremental (residual) cost arrays */ SetupIncrFlowCosts((void **)scndrycosts,incrcosts,scndryflows,nflow,ntiles, ntiles,nscndryarcs,params); /* set the tree root (equivalent to source of shortest path problem) */ sourcetilenum=(long )ntilecol*floor(ntilerow/2.0)+floor(ntilecol/2.0); source=&scndrynodes[sourcetilenum][0]; /* run the solver, and increment nflowdone if no cycles are found */ n=TreeSolve(scndrynodes,nodesupp,NULL,source,&candidatelist,&candidatebag, &candidatelistsize,&candidatebagsize,bkts,scndryflows, (void **)scndrycosts,incrcosts,scndryapexes,iscandidate,0, nflow,NULL,NULL,NULL,ntiles,nscndrynodes,ntiles,nscndryarcs, ntiles,0,NULL,params); /* evaluate and save the total cost (skip if first loop through nflow) */ if(notfirstloop){ oldtotalcost=totalcost; totalcost=EvaluateTotalCost((void **)scndrycosts,scndryflows,ntiles,0, nscndryarcs,params); if(totalcost>oldtotalcost || (n>0 && totalcost==oldtotalcost)){ fprintf(sp0,"Unexpected increase in total cost. Breaking loop\n"); break; } } /* consider this flow increment done if not too many neg cycles found */ ncycle+=n; if(n<=maxnflowcycles){ nflowdone++; }else{ nflowdone=1; } /* break if we're done with all flow increments or problem is convex */ if(nflowdone>=params->maxflow){ break; } /* update flow increment */ nflow++; if(nflow>params->maxflow){ nflow=1; notfirstloop=TRUE; } } /* end loop until no more neg cycles */ /* free some memory */ for(i=0;ibucketbase); /* integrate phase from secondary network problem */ IntegrateSecondaryFlows(linelen,nlines,scndrynodes,nodesupp,scndryarcs, nscndryarcs,scndryflows,bulkoffsets,outfiles,params); /* free remaining memory */ for(i=0;irmtmptile){ for(tilerow=0;tilerowtiledir,LOGFILEROOT,tilerow,tilecol); unlink(filename); } } rmdir(params->tiledir); } } /* function: ReadNextRegion() * -------------------------- */ void ReadNextRegion(long tilerow, long tilecol, long nlines, long linelen, outfileT *outfiles, paramT *params, short ***nextregionsptr, float ***nextunwphaseptr, void ***nextcostsptr, long *nextnrowptr, long *nextncolptr){ long nexttilelinelen, nexttilenlines, costtypesize; tileparamT nexttileparams[1]; outfileT nexttileoutfiles[1]; char nextfile[MAXSTRLEN], tempstring[MAXTMPSTRLEN]; char path[MAXSTRLEN], basename[MAXSTRLEN]; /* size of the data type for holding cost data depends on cost mode */ if(params->costmode==TOPO){ costtypesize=sizeof(costT); }else if(params->costmode==DEFO){ costtypesize=sizeof(costT); }else if(params->costmode==SMOOTH){ costtypesize=sizeof(smoothcostT); } /* use SetupTile() to set filenames only; tile params overwritten below */ SetupTile(nlines,linelen,params,nexttileparams,outfiles,nexttileoutfiles, tilerow,tilecol); nexttilenlines=nexttileparams->nrow; nexttilelinelen=nexttileparams->ncol; /* set tile parameters, overwriting values set by SetupTile() above */ SetTileReadParams(nexttileparams,nexttilenlines,nexttilelinelen, tilerow,tilecol,nlines,linelen,params); /* read region data */ ParseFilename(outfiles->outfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld%s", params->tiledir,TMPTILEROOT,basename,tilerow,tilecol, nexttilelinelen,REGIONSUFFIX); StrNCopy(nextfile,tempstring,MAXSTRLEN); Read2DArray((void ***)nextregionsptr,nextfile, nexttilelinelen,nexttilenlines, nexttileparams,sizeof(short *),sizeof(short)); /* read unwrapped phase data */ if(TMPTILEOUTFORMAT==ALT_LINE_DATA){ ReadAltLineFilePhase(nextunwphaseptr,nexttileoutfiles->outfile, nexttilelinelen,nexttilenlines,nexttileparams); }else if(TMPTILEOUTFORMAT==FLOAT_DATA){ Read2DArray((void ***)nextunwphaseptr,nexttileoutfiles->outfile, nexttilelinelen,nexttilenlines,nexttileparams, sizeof(float *),sizeof(float)); }else{ fprintf(sp0,"Cannot read format of unwrapped phase tile data\nAbort\n"); exit(ABNORMAL_EXIT); } /* read cost data */ if(params->p<0){ Read2DRowColFile((void ***)nextcostsptr,nexttileoutfiles->costoutfile, nexttilelinelen,nexttilenlines,nexttileparams, costtypesize); }else{ fprintf(sp0,"Tile reassembly not enabled in Lp mode\nAbort\n"); exit(ABNORMAL_EXIT); } /* flip sign of wrapped phase if flip flag is set */ FlipPhaseArraySign(*nextunwphaseptr,params, nexttileparams->nrow,nexttileparams->ncol); /* set outputs */ (*nextnrowptr)=nexttileparams->nrow; (*nextncolptr)=nexttileparams->ncol; } /* function: SetTileReadParams() * ----------------------------- * Set parameters for reading the nonoverlapping piece of each tile. * ni and nj are the numbers of rows and columns in this particular tile. * The meanings of these variables are different for the last row * and column. */ void SetTileReadParams(tileparamT *tileparams, long nexttilenlines, long nexttilelinelen, long tilerow, long tilecol, long nlines, long linelen, paramT *params){ long rowovrlp, colovrlp; /* set temporary variables */ rowovrlp=params->rowovrlp; colovrlp=params->colovrlp; /* row parameters */ if(tilerow==0){ tileparams->firstrow=0; }else{ tileparams->firstrow=ceil(rowovrlp/2.0); } if(tilerow!=params->ntilerow-1){ tileparams->nrow=nexttilenlines-floor(rowovrlp/2.0)-tileparams->firstrow; }else{ tileparams->nrow=nexttilenlines-tileparams->firstrow; } /* column parameters */ if(tilecol==0){ tileparams->firstcol=0; }else{ tileparams->firstcol=ceil(colovrlp/2.0); } if(tilecol!=params->ntilecol-1){ tileparams->ncol=nexttilelinelen-floor(colovrlp/2.0)-tileparams->firstcol; }else{ tileparams->ncol=nexttilelinelen-tileparams->firstcol; } } /* function: ReadEdgesAboveAndBelow() * ---------------------------------- */ void ReadEdgesAboveAndBelow(long tilerow, long tilecol, long nlines, long linelen, paramT *params, outfileT *outfiles, short *regionsabove, short *regionsbelow, float *unwphaseabove, float *unwphasebelow, void *costsabove, void *costsbelow){ long ni, nj, readtilelinelen, readtilenlines, costtypesize; long ntilerow, ntilecol, rowovrlp, colovrlp; tileparamT tileparams[1]; outfileT outfilesabove[1], outfilesbelow[1]; float **unwphaseaboveptr, **unwphasebelowptr; void **costsaboveptr, **costsbelowptr; short **regionsaboveptr, **regionsbelowptr; char tempstring[MAXTMPSTRLEN], readregionfile[MAXSTRLEN]; char path[MAXSTRLEN], basename[MAXSTRLEN]; /* set temporary variables */ ntilerow=params->ntilerow; ntilecol=params->ntilecol; rowovrlp=params->rowovrlp; colovrlp=params->colovrlp; ni=ceil((nlines+(ntilerow-1)*rowovrlp)/(double )ntilerow); nj=ceil((linelen+(ntilecol-1)*colovrlp)/(double )ntilecol); /* size of the data type for holding cost data depends on cost mode */ if(params->costmode==TOPO){ costtypesize=sizeof(costT); }else if(params->costmode==DEFO){ costtypesize=sizeof(costT); }else if(params->costmode==SMOOTH){ costtypesize=sizeof(smoothcostT); } /* set names of files with SetupTile() */ /* tile parameters set by SetupTile() will be overwritten below */ if(tilerow!=0){ SetupTile(nlines,linelen,params,tileparams,outfiles,outfilesabove, tilerow-1,tilecol); } if(tilerow!=ntilerow-1){ SetupTile(nlines,linelen,params,tileparams,outfiles,outfilesbelow, tilerow+1,tilecol); } /* temporary pointers, so we can use Read2DArray() with 1D output array */ unwphaseaboveptr=&unwphaseabove; unwphasebelowptr=&unwphasebelow; costsaboveptr=&costsabove; costsbelowptr=&costsbelow; regionsaboveptr=®ionsabove; regionsbelowptr=®ionsbelow; /* set some reading parameters */ if(tilecol==0){ tileparams->firstcol=0; }else{ tileparams->firstcol=ceil(colovrlp/2.0); } if(tilecol!=params->ntilecol-1){ readtilelinelen=nj; tileparams->ncol=readtilelinelen-floor(colovrlp/2.0)-tileparams->firstcol; }else{ readtilelinelen=linelen-(ntilecol-1)*(nj-colovrlp); tileparams->ncol=readtilelinelen-tileparams->firstcol; } tileparams->nrow=1; /* read last line of tile above */ readtilenlines=ni; if(tilerow!=0){ tileparams->firstrow=readtilenlines-floor(rowovrlp/2.0)-1; /* read region data */ ParseFilename(outfiles->outfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld%s", params->tiledir,TMPTILEROOT,basename,tilerow-1,tilecol, readtilelinelen,REGIONSUFFIX); StrNCopy(readregionfile,tempstring,MAXSTRLEN); Read2DArray((void ***)®ionsaboveptr,readregionfile, readtilelinelen,readtilenlines, tileparams,sizeof(short *),sizeof(short)); /* read unwrapped phase data */ if(TMPTILEOUTFORMAT==ALT_LINE_DATA){ ReadAltLineFilePhase(&unwphaseaboveptr,outfilesabove->outfile, readtilelinelen,readtilenlines,tileparams); }else if(TMPTILEOUTFORMAT==FLOAT_DATA){ Read2DArray((void ***)&unwphaseaboveptr,outfilesabove->outfile, readtilelinelen,readtilenlines,tileparams, sizeof(float *),sizeof(float)); } /* flip sign of wrapped phase if flip flag is set */ FlipPhaseArraySign(unwphaseaboveptr,params, tileparams->nrow,tileparams->ncol); /* read costs data */ tileparams->firstrow--; Read2DRowColFileRows((void ***)&costsaboveptr,outfilesabove->costoutfile, readtilelinelen,readtilenlines,tileparams, costtypesize); /* remove temporary tile cost file unless told to save it */ if(params->rmtmptile && !strlen(outfiles->costoutfile)){ unlink(outfilesabove->costoutfile); } } /* read first line of tile below */ if(tilerow!=ntilerow-1){ if(tilerow==params->ntilerow-2){ readtilenlines=nlines-(ntilerow-1)*(ni-rowovrlp); } tileparams->firstrow=ceil(rowovrlp/2.0); /* read region data */ ParseFilename(outfiles->outfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld%s", params->tiledir,TMPTILEROOT,basename,tilerow+1,tilecol, readtilelinelen,REGIONSUFFIX); StrNCopy(readregionfile,tempstring,MAXSTRLEN); Read2DArray((void ***)®ionsbelowptr,readregionfile, readtilelinelen,readtilenlines, tileparams,sizeof(short *),sizeof(short)); /* read unwrapped phase data */ if(TMPTILEOUTFORMAT==ALT_LINE_DATA){ ReadAltLineFilePhase(&unwphasebelowptr,outfilesbelow->outfile, readtilelinelen,readtilenlines,tileparams); }else if(TMPTILEOUTFORMAT==FLOAT_DATA){ Read2DArray((void ***)&unwphasebelowptr,outfilesbelow->outfile, readtilelinelen,readtilenlines,tileparams, sizeof(float *),sizeof(float)); } /* flip the sign of the wrapped phase if flip flag is set */ FlipPhaseArraySign(unwphasebelowptr,params, tileparams->nrow,tileparams->ncol); /* read costs data */ Read2DRowColFileRows((void ***)&costsbelowptr,outfilesbelow->costoutfile, readtilelinelen,readtilenlines,tileparams, costtypesize); }else{ /* remove temporoary tile cost file for last row unless told to save it */ if(params->rmtmptile && !strlen(outfiles->costoutfile)){ SetupTile(nlines,linelen,params,tileparams,outfiles,outfilesbelow, tilerow,tilecol); unlink(outfilesbelow->costoutfile); } } } /* function: TraceRegions() * ------------------------ * Trace edges of region data to form nodes and arcs of secondary * (ie, region-level) network problem. Primary nodes and arcs are * those of the original, pixel-level network problem. Flows along * edges are computed knowing the unwrapped phase values of edges * of adjacent tiles. Costs along edges are approximated in that they * are calculated from combining adjacent cost parameters, not from * using the exact method in BuildCostArrays(). */ void TraceRegions(short **regions, short **nextregions, short **lastregions, short *regionsabove, short *regionsbelow, float **unwphase, float **nextunwphase, float **lastunwphase, float *unwphaseabove, float *unwphasebelow, void **costs, void **nextcosts, void **lastcosts, void *costsabove, void *costsbelow, long prevnrow, long prevncol, long tilerow, long tilecol, long nrow, long ncol, nodeT **scndrynodes, nodesuppT **nodesupp, scndryarcT **scndryarcs, long ***scndrycosts, short *nscndrynodes, short *nscndryarcs, long *totarclens, short **bulkoffsets, paramT *params){ long i, j, row, col, nnrow, nncol, tilenum, costtypesize; long nnewnodes, nnewarcs, npathsout, flowmax, totarclen; long nupdatednontilenodes, updatednontilenodesize, ntilecol; short **flows; short **rightedgeflows, **loweredgeflows, **leftedgeflows, **upperedgeflows; short *inontilenodeoutarc; void **rightedgecosts, **loweredgecosts, **leftedgecosts, **upperedgecosts; nodeT **primarynodes, **updatednontilenodes; nodeT *from, *to, *nextnode, *tempnode; nodesuppT *fromsupp, *tosupp; /* initialize */ ntilecol=params->ntilecol; nnrow=nrow+1; nncol=ncol+1; primarynodes=(nodeT **)Get2DMem(nnrow,nncol,sizeof(nodeT *),sizeof(nodeT)); for(row=0;rowscndryarcflowmax; updatednontilenodesize=INITARRSIZE; nupdatednontilenodes=0; /* size of the data type for holding cost data depends on cost mode */ if(params->costmode==TOPO){ costtypesize=sizeof(costT); }else if(params->costmode==DEFO){ costtypesize=sizeof(costT); }else if(params->costmode==SMOOTH){ costtypesize=sizeof(smoothcostT); } /* get memory */ updatednontilenodes=(nodeT **)MAlloc(updatednontilenodesize*sizeof(nodeT *)); inontilenodeoutarc=(short *)MAlloc(updatednontilenodesize*sizeof(short)); flows=(short **)Get2DRowColMem(nrow+1,ncol+1,sizeof(short *),sizeof(short)); rightedgeflows=(short **)Get2DMem(nrow,1,sizeof(short *),sizeof(short)); leftedgeflows=(short **)Get2DMem(nrow,1,sizeof(short *),sizeof(short)); upperedgeflows=(short **)Get2DMem(1,ncol,sizeof(short *),sizeof(short)); loweredgeflows=(short **)Get2DMem(1,ncol,sizeof(short *),sizeof(short)); rightedgecosts=(void **)Get2DMem(nrow,1,sizeof(void *),costtypesize); leftedgecosts=(void **)Get2DMem(nrow,1,sizeof(void *),costtypesize); upperedgecosts=(void **)Get2DMem(1,ncol,sizeof(void *),costtypesize); loweredgecosts=(void **)Get2DMem(1,ncol,sizeof(void *),costtypesize); /* parse flows for this tile */ CalcFlow(unwphase,&flows,nrow,ncol); /* set up cost and flow arrays for boundaries */ SetUpperEdge(ncol,tilerow,tilecol,costs,costsabove,unwphase,unwphaseabove, upperedgecosts,upperedgeflows,params, bulkoffsets); SetLowerEdge(nrow,ncol,tilerow,tilecol,costs,costsbelow,unwphase, unwphasebelow,loweredgecosts,loweredgeflows, params,bulkoffsets); SetLeftEdge(nrow,prevncol,tilerow,tilecol,costs,lastcosts,unwphase, lastunwphase,leftedgecosts,leftedgeflows,params, bulkoffsets); SetRightEdge(nrow,ncol,tilerow,tilecol,costs,nextcosts,unwphase, nextunwphase,rightedgecosts,rightedgeflows, params,bulkoffsets); /* trace edges between regions */ while(nextnode!=NULL){ /* get next primary node from stack */ from=nextnode; nextnode=nextnode->next; from->group=NOTINBUCKET; /* find number of paths out of from node */ npathsout=FindNumPathsOut(from,params,tilerow,tilecol,nnrow,nncol,regions, nextregions,lastregions,regionsabove, regionsbelow,prevncol); /* secondary node exists if region edges fork */ if(npathsout>2){ /* mark primary node to indicate that secondary node exists for it */ from->group=ONTREE; /* create secondary node if not already created in another tile */ if((from->row!=0 || tilerow==0) && (from->col!=0 || tilecol==0)){ /* create the secondary node */ nnewnodes++; scndrynodes[tilenum]=(nodeT *)ReAlloc(scndrynodes[tilenum], nnewnodes*sizeof(nodeT)); nodesupp[tilenum]=(nodesuppT *)ReAlloc(nodesupp[tilenum], nnewnodes*sizeof(nodesuppT)); scndrynodes[tilenum][nnewnodes-1].row=tilenum; scndrynodes[tilenum][nnewnodes-1].col=nnewnodes-1; nodesupp[tilenum][nnewnodes-1].row=from->row; nodesupp[tilenum][nnewnodes-1].col=from->col; nodesupp[tilenum][nnewnodes-1].noutarcs=0; nodesupp[tilenum][nnewnodes-1].neighbornodes=NULL; nodesupp[tilenum][nnewnodes-1].outarcs=NULL; } /* create the secondary arc to this node if it doesn't already exist */ if(from->pred!=NULL && ((from->row==from->pred->row && (from->row!=0 || tilerow==0)) || (from->col==from->pred->col && (from->col!=0 || tilecol==0)))){ TraceSecondaryArc(from,scndrynodes,nodesupp,scndryarcs,scndrycosts, &nnewnodes,&nnewarcs,tilerow,tilecol,flowmax, nrow,ncol,prevnrow,prevncol,params,costs, rightedgecosts,loweredgecosts,leftedgecosts, upperedgecosts,flows,rightedgeflows,loweredgeflows, leftedgeflows,upperedgeflows,&updatednontilenodes, &nupdatednontilenodes,&updatednontilenodesize, &inontilenodeoutarc,&totarclen); } } /* scan neighboring primary nodes and place path candidates into stack */ RegionTraceCheckNeighbors(from,&nextnode,primarynodes,regions, nextregions,lastregions,regionsabove, regionsbelow,tilerow,tilecol,nnrow,nncol, scndrynodes,nodesupp,scndryarcs,&nnewnodes, &nnewarcs,flowmax,nrow,ncol,prevnrow,prevncol, params,costs,rightedgecosts,loweredgecosts, leftedgecosts,upperedgecosts,flows, rightedgeflows,loweredgeflows,leftedgeflows, upperedgeflows,scndrycosts,&updatednontilenodes, &nupdatednontilenodes,&updatednontilenodesize, &inontilenodeoutarc,&totarclen); } /* reset temporary secondary node and arc pointers in data structures */ /* secondary node row, col stored level, incost of primary node pointed to */ /* update nodes in this tile */ for(i=0;ilevel][tempnode->incost]; } } /* update nodes not in this tile that were affected (that have new arcs) */ for(i=0;irow; col=updatednontilenodes[i]->col; j=inontilenodeoutarc[i]; tempnode=nodesupp[row][col].neighbornodes[j]; nodesupp[row][col].neighbornodes[j] =&scndrynodes[tempnode->level][tempnode->incost]; } /* update secondary arcs */ for(i=0;ilevel][tempnode->incost]; from=scndryarcs[tilenum][i].from; tempnode=scndryarcs[tilenum][i].to; scndryarcs[tilenum][i].to =&scndrynodes[tempnode->level][tempnode->incost]; to=scndryarcs[tilenum][i].to; /* update secondary arc pointers in nodesupp strcutres */ fromsupp=&nodesupp[from->row][from->col]; j=0; while(fromsupp->neighbornodes[j]!=to){ j++; } fromsupp->outarcs[j]=&scndryarcs[tilenum][i]; tosupp=&nodesupp[to->row][to->col]; j=0; while(tosupp->neighbornodes[j]!=from){ j++; } tosupp->outarcs[j]=&scndryarcs[tilenum][i]; } /* set outputs */ nscndrynodes[tilenum]=nnewnodes; nscndryarcs[tilenum]=nnewarcs; totarclens[tilenum]=totarclen; /* free memory */ Free2DArray((void **)primarynodes,nnrow); Free2DArray((void **)flows,2*nrow-1); Free2DArray((void **)rightedgeflows,nrow); Free2DArray((void **)leftedgeflows,nrow); Free2DArray((void **)upperedgeflows,1); Free2DArray((void **)loweredgeflows,1); Free2DArray((void **)rightedgecosts,nrow); Free2DArray((void **)leftedgecosts,nrow); Free2DArray((void **)upperedgecosts,1); Free2DArray((void **)loweredgecosts,1); } /* function: FindNumPathsOut() * --------------------------- * Check all outgoing arcs to see how many paths out there are. */ long FindNumPathsOut(nodeT *from, paramT *params, long tilerow, long tilecol, long nnrow, long nncol, short **regions, short **nextregions, short **lastregions, short *regionsabove, short *regionsbelow, long prevncol){ long npathsout, ntilerow, ntilecol, fromrow, fromcol; /* initialize */ ntilerow=params->ntilerow; ntilecol=params->ntilecol; fromrow=from->row; fromcol=from->col; npathsout=0; /* rightward arc */ if(fromcol!=nncol-1){ if(fromrow==0 || fromrow==nnrow-1 || regions[fromrow-1][fromcol]!=regions[fromrow][fromcol]){ npathsout++; } }else{ if(fromrow==0 || fromrow==nnrow-1 || (tilecol!=ntilecol-1 && nextregions[fromrow-1][0]!=nextregions[fromrow][0])){ npathsout++; } } /* downward arc */ if(fromrow!=nnrow-1){ if(fromcol==0 || fromcol==nncol-1 || regions[fromrow][fromcol]!=regions[fromrow][fromcol-1]){ npathsout++; } }else{ if(fromcol==0 || fromcol==nncol-1 || (tilerow!=ntilerow-1 && regionsbelow[fromcol]!=regionsbelow[fromcol-1])){ npathsout++; } } /* leftward arc */ if(fromcol!=0){ if(fromrow==0 || fromrow==nnrow-1 || regions[fromrow][fromcol-1]!=regions[fromrow-1][fromcol-1]){ npathsout++; } }else{ if(fromrow==0 || fromrow==nnrow-1 || (tilecol!=0 && (lastregions[fromrow][prevncol-1] !=lastregions[fromrow-1][prevncol-1]))){ npathsout++; } } /* upward arc */ if(fromrow!=0){ if(fromcol==0 || fromcol==nncol-1 || regions[fromrow-1][fromcol-1]!=regions[fromrow-1][fromcol]){ npathsout++; } }else{ if(fromcol==0 || fromcol==nncol-1 || (tilerow!=0 && regionsabove[fromcol-1]!=regionsabove[fromcol])){ npathsout++; } } /* return number of paths out of node */ return(npathsout); } /* function: RegionTraceCheckNeighbors() * ------------------------------------- */ void RegionTraceCheckNeighbors(nodeT *from, nodeT **nextnodeptr, nodeT **primarynodes, short **regions, short **nextregions, short **lastregions, short *regionsabove, short *regionsbelow, long tilerow, long tilecol, long nnrow, long nncol, nodeT **scndrynodes, nodesuppT **nodesupp, scndryarcT **scndryarcs, long *nnewnodesptr, long *nnewarcsptr, long flowmax, long nrow, long ncol, long prevnrow, long prevncol, paramT *params, void **costs, void **rightedgecosts, void **loweredgecosts, void **leftedgecosts, void **upperedgecosts, short **flows, short **rightedgeflows, short **loweredgeflows, short **leftedgeflows, short **upperedgeflows, long ***scndrycosts, nodeT ***updatednontilenodesptr, long *nupdatednontilenodesptr, long *updatednontilenodesizeptr, short **inontilenodeoutarcptr, long *totarclenptr){ long fromrow, fromcol; nodeT *to, *nextnode; /* initialize */ fromrow=from->row; fromcol=from->col; nextnode=(*nextnodeptr); /* check rightward arc */ if(fromcol!=nncol-1){ to=&primarynodes[fromrow][fromcol+1]; if(fromrow==0 || fromrow==nnrow-1 || regions[fromrow-1][fromcol]!=regions[fromrow][fromcol]){ if(to!=from->pred){ to->pred=from; if(to->group==NOTINBUCKET){ to->group=INBUCKET; to->next=nextnode; nextnode=to; }else if(to->group==ONTREE && (fromrow!=0 || tilerow==0)){ TraceSecondaryArc(to,scndrynodes,nodesupp,scndryarcs,scndrycosts, nnewnodesptr,nnewarcsptr,tilerow,tilecol,flowmax, nrow,ncol,prevnrow,prevncol,params,costs, rightedgecosts,loweredgecosts,leftedgecosts, upperedgecosts,flows,rightedgeflows, loweredgeflows,leftedgeflows,upperedgeflows, updatednontilenodesptr,nupdatednontilenodesptr, updatednontilenodesizeptr,inontilenodeoutarcptr, totarclenptr); } } } } /* check downward arc */ if(fromrow!=nnrow-1){ to=&primarynodes[fromrow+1][fromcol]; if(fromcol==0 || fromcol==nncol-1 || regions[fromrow][fromcol]!=regions[fromrow][fromcol-1]){ if(to!=from->pred){ to->pred=from; if(to->group==NOTINBUCKET){ to->group=INBUCKET; to->next=nextnode; nextnode=to; }else if(to->group==ONTREE && (fromcol!=0 || tilecol==0)){ TraceSecondaryArc(to,scndrynodes,nodesupp,scndryarcs,scndrycosts, nnewnodesptr,nnewarcsptr,tilerow,tilecol,flowmax, nrow,ncol,prevnrow,prevncol,params,costs, rightedgecosts,loweredgecosts,leftedgecosts, upperedgecosts,flows,rightedgeflows, loweredgeflows,leftedgeflows,upperedgeflows, updatednontilenodesptr,nupdatednontilenodesptr, updatednontilenodesizeptr,inontilenodeoutarcptr, totarclenptr); } } } } /* check leftward arc */ if(fromcol!=0){ to=&primarynodes[fromrow][fromcol-1]; if(fromrow==0 || fromrow==nnrow-1 || regions[fromrow][fromcol-1]!=regions[fromrow-1][fromcol-1]){ if(to!=from->pred){ to->pred=from; if(to->group==NOTINBUCKET){ to->group=INBUCKET; to->next=nextnode; nextnode=to; }else if(to->group==ONTREE && (fromrow!=0 || tilerow==0)){ TraceSecondaryArc(to,scndrynodes,nodesupp,scndryarcs,scndrycosts, nnewnodesptr,nnewarcsptr,tilerow,tilecol,flowmax, nrow,ncol,prevnrow,prevncol,params,costs, rightedgecosts,loweredgecosts,leftedgecosts, upperedgecosts,flows,rightedgeflows, loweredgeflows,leftedgeflows,upperedgeflows, updatednontilenodesptr,nupdatednontilenodesptr, updatednontilenodesizeptr,inontilenodeoutarcptr, totarclenptr); } } } } /* check upward arc */ if(fromrow!=0){ to=&primarynodes[fromrow-1][fromcol]; if(fromcol==0 || fromcol==nncol-1 || regions[fromrow-1][fromcol-1]!=regions[fromrow-1][fromcol]){ if(to!=from->pred){ to->pred=from; if(to->group==NOTINBUCKET){ to->group=INBUCKET; to->next=nextnode; nextnode=to; }else if(to->group==ONTREE && (fromcol!=0 || tilecol==0)){ TraceSecondaryArc(to,scndrynodes,nodesupp,scndryarcs,scndrycosts, nnewnodesptr,nnewarcsptr,tilerow,tilecol,flowmax, nrow,ncol,prevnrow,prevncol,params,costs, rightedgecosts,loweredgecosts,leftedgecosts, upperedgecosts,flows,rightedgeflows, loweredgeflows,leftedgeflows,upperedgeflows, updatednontilenodesptr,nupdatednontilenodesptr, updatednontilenodesizeptr,inontilenodeoutarcptr, totarclenptr); } } } } /* set return values */ *nextnodeptr=nextnode; } /* function: SetUpperEdge() * ------------------------ */ void SetUpperEdge(long ncol, long tilerow, long tilecol, void **voidcosts, void *voidcostsabove, float **unwphase, float *unwphaseabove, void **voidupperedgecosts, short **upperedgeflows, paramT *params, short **bulkoffsets){ long col, reloffset; double dphi, dpsi; costT **upperedgecosts, **costs, *costsabove; smoothcostT **upperedgesmoothcosts, **smoothcosts, *smoothcostsabove; long nshortcycle; /* typecast generic pointers to costT pointers */ upperedgecosts=(costT **)voidupperedgecosts; costs=(costT **)voidcosts; costsabove=(costT *)voidcostsabove; upperedgesmoothcosts=(smoothcostT **)voidupperedgecosts; smoothcosts=(smoothcostT **)voidcosts; smoothcostsabove=(smoothcostT *)voidcostsabove; /* see if tile is in top row */ if(tilerow!=0){ /* set up */ nshortcycle=params->nshortcycle; reloffset=bulkoffsets[tilerow-1][tilecol]-bulkoffsets[tilerow][tilecol]; /* loop over all arcs on the boundary */ for(col=0;col0.5){ dpsi-=1.0; } if(params->costmode==TOPO || params->costmode==DEFO){ upperedgecosts[0][col].offset=nshortcycle*dpsi; upperedgecosts[0][col].sigsq=ceil((costs[0][col].sigsq +costsabove[col].sigsq)/2.0); if(costs[0][col].dzmax>costsabove[col].dzmax){ upperedgecosts[0][col].dzmax=costs[0][col].dzmax; }else{ upperedgecosts[0][col].dzmax=costsabove[col].dzmax; } if(costs[0][col].laycostcostmode==SMOOTH){ upperedgesmoothcosts[0][col].offset=nshortcycle*dpsi; upperedgesmoothcosts[0][col].sigsq= ceil((smoothcosts[0][col].sigsq+smoothcostsabove[col].sigsq)/2.0); }else{ fprintf(sp0,"Illegal cost mode in SetUpperEdge(). This is a bug.\n"); exit(ABNORMAL_EXIT); } } }else{ if(params->costmode==TOPO || params->costmode==DEFO){ for(col=0;colcostmode==SMOOTH){ for(col=0;colntilerow-1){ /* set up */ nshortcycle=params->nshortcycle; flowlimhi=LARGESHORT; flowlimlo=-LARGESHORT; flowhistogram=(long *)CAlloc(flowlimhi-flowlimlo+1,sizeof(long)); minflow=flowlimhi; maxflow=flowlimlo; /* loop over all arcs on the boundary */ for(col=0;colmaxflow){ if(tempflow>flowlimhi){ fprintf(sp0,"Overflow in tile offset\nAbort\n"); exit(ABNORMAL_EXIT); } maxflow=tempflow; } flowhistogram[tempflow-flowlimlo]++; dpsi=dphi-floor(dphi); if(dpsi>0.5){ dpsi-=1.0; } if(params->costmode==TOPO || params->costmode==DEFO){ loweredgecosts[0][col].offset=nshortcycle*dpsi; loweredgecosts[0][col].sigsq=ceil((costs[nrow-2][col].sigsq +costsbelow[col].sigsq)/2.0); if(costs[nrow-2][col].dzmax>costsbelow[col].dzmax){ loweredgecosts[0][col].dzmax=costs[nrow-2][col].dzmax; }else{ loweredgecosts[0][col].dzmax=costsbelow[col].dzmax; } if(costs[nrow-2][col].laycostcostmode==SMOOTH){ loweredgesmoothcosts[0][col].offset=nshortcycle*dpsi; loweredgesmoothcosts[0][col].sigsq= ceil((smoothcosts[nrow-2][col].sigsq +smoothcostsbelow[col].sigsq)/2.0); }else{ fprintf(sp0,"Illegal cost mode in SetLowerEdge(). This is a bug.\n"); exit(ABNORMAL_EXIT); } } /* set bulk tile offset equal to mode of flow histogram */ nmax=0; reloffset=0; for(iflow=minflow;iflow<=maxflow;iflow++){ if(flowhistogram[iflow-flowlimlo]>nmax){ nmax=flowhistogram[iflow-flowlimlo]; reloffset=iflow; } } bulkoffsets[tilerow+1][tilecol]=bulkoffsets[tilerow][tilecol]-reloffset; /* subtract relative tile offset from edge flows */ for(col=0;colcostmode==TOPO || params->costmode==DEFO){ for(col=0;colcostmode==SMOOTH){ for(col=0;colnshortcycle; reloffset=bulkoffsets[tilerow][tilecol]-bulkoffsets[tilerow][tilecol-1]; /* loop over all arcs on the boundary */ for(row=0;row0.5){ dpsi-=1.0; } if(params->costmode==TOPO || params->costmode==DEFO){ leftedgecosts[row][0].offset=(TILEDPSICOLFACTOR*nshortcycle*dpsi); leftedgecosts[row][0].sigsq= ceil((costs[row+nrow-1][0].sigsq +lastcosts[row+nrow-1][prevncol-2].sigsq)/2.0); if(costs[row+nrow-1][0].dzmax>lastcosts[row+nrow-1][prevncol-2].dzmax){ leftedgecosts[row][0].dzmax=costs[row+nrow-1][0].dzmax; }else{ leftedgecosts[row][0].dzmax=lastcosts[row+nrow-1][prevncol-2].dzmax; } if(costs[row+nrow-1][0].laycost >lastcosts[row+nrow-1][prevncol-2].laycost){ leftedgecosts[row][0].laycost=costs[row+nrow-1][0].laycost; }else{ leftedgecosts[row][0].laycost =lastcosts[row+nrow-1][prevncol-2].laycost; } }else if(params->costmode==SMOOTH){ leftedgesmoothcosts[row][0].offset =(TILEDPSICOLFACTOR*nshortcycle*dpsi); leftedgesmoothcosts[row][0].sigsq= ceil((smoothcosts[row+nrow-1][0].sigsq +lastsmoothcosts[row+nrow-1][prevncol-2].sigsq)/2.0); }else{ fprintf(sp0,"Illegal cost mode in SetLeftEdge(). This is a bug.\n"); exit(ABNORMAL_EXIT); } } }else{ if(params->costmode==TOPO || params->costmode==DEFO){ for(row=0;rowcostmode==SMOOTH){ for(row=0;rowntilecol-1){ /* set up */ nshortcycle=params->nshortcycle; flowlimhi=LARGESHORT; flowlimlo=-LARGESHORT; flowhistogram=(long *)CAlloc(flowlimhi-flowlimlo+1,sizeof(long)); minflow=flowlimhi; maxflow=flowlimlo; /* loop over all arcs on the boundary */ for(row=0;rowmaxflow){ if(tempflow>flowlimhi){ fprintf(sp0,"Overflow in tile offset\nAbort\n"); exit(ABNORMAL_EXIT); } maxflow=tempflow; } flowhistogram[tempflow-flowlimlo]++; dpsi=dphi-floor(dphi); if(dpsi>0.5){ dpsi-=1.0; } if(params->costmode==TOPO || params->costmode==DEFO){ rightedgecosts[row][0].offset=(TILEDPSICOLFACTOR*nshortcycle*dpsi); rightedgecosts[row][0].sigsq =ceil((costs[row+nrow-1][ncol-2].sigsq +nextcosts[row+nrow-1][0].sigsq)/2.0); if(costs[row+nrow-1][ncol-2].dzmax>nextcosts[row+nrow-1][0].dzmax){ rightedgecosts[row][0].dzmax=costs[row+nrow-1][ncol-2].dzmax; }else{ rightedgecosts[row][0].dzmax=nextcosts[row+nrow-1][0].dzmax; } if(costs[row+nrow-1][ncol-2].laycost>nextcosts[row+nrow-1][0].laycost){ rightedgecosts[row][0].laycost=costs[row+nrow-1][ncol-2].laycost; }else{ rightedgecosts[row][0].laycost=nextcosts[row+nrow-1][0].laycost; } }else if(params->costmode==SMOOTH){ rightedgesmoothcosts[row][0].offset =(TILEDPSICOLFACTOR*nshortcycle*dpsi); rightedgesmoothcosts[row][0].sigsq =ceil((smoothcosts[row+nrow-1][ncol-2].sigsq +nextsmoothcosts[row+nrow-1][0].sigsq)/2.0); }else{ fprintf(sp0,"Illegal cost mode in SetRightEdge(). This is a bug.\n"); exit(ABNORMAL_EXIT); } } /* set bulk tile offset equal to mode of flow histogram */ if(tilerow==0){ nmax=0; reloffset=0; for(iflow=minflow;iflow<=maxflow;iflow++){ if(flowhistogram[iflow-flowlimlo]>nmax){ nmax=flowhistogram[iflow-flowlimlo]; reloffset=iflow; } } bulkoffsets[tilerow][tilecol+1]=bulkoffsets[tilerow][tilecol]+reloffset; }else{ reloffset=bulkoffsets[tilerow][tilecol+1]-bulkoffsets[tilerow][tilecol]; } /* subtract relative tile offset from edge flows */ for(row=0;rowcostmode==TOPO || params->costmode==DEFO){ for(row=0;rowcostmode==SMOOTH){ for(row=0;rowpred==NULL || (tilerow!=0 && primaryhead->row==0 && primaryhead->pred->row==0) || (tilecol!=0 && primaryhead->col==0 && primaryhead->pred->col==0)){ return; } /* set up */ ntilerow=params->ntilerow; ntilecol=params->ntilecol; nnrow=nrow+1; nncol=ncol+1; tilenum=tilerow*ntilecol+tilecol; scndrycostarr=(long *)MAlloc((2*flowmax+2)*sizeof(long)); tileedgearcweight=params->tileedgeweight; nshortcycle=params->nshortcycle; zerocost=FALSE; arroffset=0; /* loop to determine appropriate value for arroffset */ while(TRUE){ /* initialize variables */ arclen=0; sumsigsqinv=0; for(nflow=1;nflow<=2*flowmax;nflow++){ scndrycostarr[nflow]=0; } /* loop over primary arcs on secondary arc again to get costs */ primarytail=primaryhead->pred; tempnode=primaryhead; while(TRUE){ /* get primary arc just traversed */ arclen++; if(tempnode->col==primarytail->col+1){ /* rightward arc */ primaryarcdir=1; primaryarccol=primarytail->col; if(primarytail->row==0){ /* top edge */ if(tilerow==0){ zerocost=TRUE; }else{ primaryarcrow=0; costs=upperedgecosts; flows=upperedgeflows; calccostnrow=2; } }else if(primarytail->row==nnrow-1){ /* bottom edge */ if(tilerow==ntilerow-1){ zerocost=TRUE; }else{ primaryarcrow=0; costs=loweredgecosts; flows=loweredgeflows; calccostnrow=2; } }else{ /* normal arc */ primaryarcrow=primarytail->row-1; costs=tilecosts; flows=tileflows; calccostnrow=nrow; } }else if(tempnode->row==primarytail->row+1){ /* downward arc */ primaryarcdir=1; if(primarytail->col==0){ /* left edge */ if(tilecol==0){ zerocost=TRUE; }else{ primaryarcrow=primarytail->row; primaryarccol=0; costs=leftedgecosts; flows=leftedgeflows; calccostnrow=0; } }else if(primarytail->col==nncol-1){ /* right edge */ if(tilecol==ntilecol-1){ zerocost=TRUE; }else{ primaryarcrow=primarytail->row; primaryarccol=0; costs=rightedgecosts; flows=rightedgeflows; calccostnrow=0; } }else{ /* normal arc */ primaryarcrow=primarytail->row+nrow-1; primaryarccol=primarytail->col-1; costs=tilecosts; flows=tileflows; calccostnrow=nrow; } }else if(tempnode->col==primarytail->col-1){ /* leftward arc */ primaryarcdir=-1; primaryarccol=primarytail->col-1; if(primarytail->row==0){ /* top edge */ if(tilerow==0){ zerocost=TRUE; }else{ primaryarcrow=0; costs=upperedgecosts; flows=upperedgeflows; calccostnrow=2; } }else if(primarytail->row==nnrow-1){ /* bottom edge */ if(tilerow==ntilerow-1){ zerocost=TRUE; }else{ primaryarcrow=0; costs=loweredgecosts; flows=loweredgeflows; calccostnrow=2; } }else{ /* normal arc */ primaryarcrow=primarytail->row-1; costs=tilecosts; flows=tileflows; calccostnrow=nrow; } }else{ /* upward arc */ primaryarcdir=-1; if(primarytail->col==0){ /* left edge */ if(tilecol==0){ zerocost=TRUE; }else{ primaryarcrow=primarytail->row-1; primaryarccol=0; costs=leftedgecosts; flows=leftedgeflows; calccostnrow=0; } }else if(primarytail->col==nncol-1){ /* right edge */ if(tilecol==ntilecol-1){ zerocost=TRUE; }else{ primaryarcrow=primarytail->row-1; primaryarccol=0; costs=rightedgecosts; flows=rightedgeflows; calccostnrow=0; } }else{ /* normal arc */ primaryarcrow=primarytail->row+nrow-2; primaryarccol=primarytail->col-1; costs=tilecosts; flows=tileflows; calccostnrow=nrow; } } /* keep absolute cost of arc to the previous node */ if(!zerocost){ flows[primaryarcrow][primaryarccol]-=primaryarcdir*arroffset; nomcost=EvalCost(costs,flows,primaryarcrow,primaryarccol,calccostnrow, params); for(nflow=1;nflow<=flowmax;nflow++){ flows[primaryarcrow][primaryarccol]+=(primaryarcdir*nflow); poscost=EvalCost(costs,flows,primaryarcrow,primaryarccol, calccostnrow,params); flows[primaryarcrow][primaryarccol]-=(2*primaryarcdir*nflow); negcost=EvalCost(costs,flows,primaryarcrow,primaryarccol, calccostnrow,params); flows[primaryarcrow][primaryarccol]+=(primaryarcdir*nflow); templongdouble=(scndrycostarr[nflow]+(poscost-nomcost)); if(templongdouble>LARGELONG){ scndrycostarr[nflow]=LARGELONG; }else if(templongdouble<-LARGELONG){ scndrycostarr[nflow]=-LARGELONG; }else{ scndrycostarr[nflow]+=(poscost-nomcost); } templongdouble=(scndrycostarr[nflow+flowmax]+(negcost-nomcost)); if(templongdouble>LARGELONG){ scndrycostarr[nflow+flowmax]=LARGELONG; }else if(templongdouble<-LARGELONG){ scndrycostarr[nflow+flowmax]=-LARGELONG; }else{ scndrycostarr[nflow+flowmax]+=(negcost-nomcost); } } flows[primaryarcrow][primaryarccol]+=primaryarcdir*arroffset; if(params->costmode==TOPO || params->costmode==DEFO){ sigsq=((costT **)costs)[primaryarcrow][primaryarccol].sigsq; }else if(params->costmode==SMOOTH){ sigsq=((smoothcostT **)costs)[primaryarcrow][primaryarccol].sigsq; } sumsigsqinv+=(1.0/sigsq); } /* break if found the secondary arc tail */ if(primarytail->group==ONTREE){ break; } /* move up the tree */ tempnode=primarytail; primarytail=primarytail->pred; } /* end while loop for tracing secondary arc for costs */ /* break if we have a zero-cost arc on the edge of the full array */ if(zerocost){ break; } /* find flow index with minimum cost */ mincost=0; mincostflow=0; for(nflow=1;nflow<=flowmax;nflow++){ if(scndrycostarr[nflow]row==primarytail->row && (primaryhead->row==0 || primaryhead->row==nnrow-1)) || (primaryhead->col==primarytail->col && (primaryhead->col==0 || primaryhead->col==nncol-1))){ for(nflow=1;nflow<=2*flowmax;nflow++){ tempdouble=scndrycostarr[nflow]*tileedgearcweight; if(tempdouble>LARGELONG){ scndrycostarr[nflow]=LARGELONG; }else if(tempdouble<-LARGELONG){ scndrycostarr[nflow]=-LARGELONG; }else{ scndrycostarr[nflow]=LRound(tempdouble); } } sumsigsqinv*=tileedgearcweight; } /* store sum of primary cost variances at end of secondary cost array */ tempdouble=sumsigsqinv*nshortcycle*nshortcycle; if(tempdoublerow==0 && tilerow!=0){ scndrytail=FindScndryNode(scndrynodes,nodesupp, (tilerow-1)*ntilecol+tilecol, prevnrow,primarytail->col); }else if(primarytail->col==0 && tilecol!=0){ scndrytail=FindScndryNode(scndrynodes,nodesupp, tilerow*ntilecol+(tilecol-1), primarytail->row,prevncol); }else{ scndrytail=FindScndryNode(scndrynodes,nodesupp,tilenum, primarytail->row,primarytail->col); } if(primaryhead->row==0 && tilerow!=0){ scndryhead=FindScndryNode(scndrynodes,nodesupp, (tilerow-1)*ntilecol+tilecol, prevnrow,primaryhead->col); }else if(primaryhead->col==0 && tilecol!=0){ scndryhead=FindScndryNode(scndrynodes,nodesupp, tilerow*ntilecol+(tilecol-1), primaryhead->row,prevncol); }else{ scndryhead=FindScndryNode(scndrynodes,nodesupp,tilenum, primaryhead->row,primaryhead->col); } /* see if there is already arc between secondary head, tail */ row=scndrytail->row; col=scndrytail->col; for(i=0;irow==primaryhead->row && tempnode->col==primaryhead->col) || (nodesupp[row][col].outarcs[i]!=NULL && tempnode->row==scndryhead->row && tempnode->col==scndryhead->col)){ /* see if secondary arc traverses only one primary arc */ primarydummy=primaryhead->pred; if(primarydummy->group!=ONTREE){ /* arc already exists, free memory for cost array (will trace again) */ free(scndrycostarr); /* set up dummy node */ primarydummy->group=ONTREE; nnewnodes=++(*nnewnodesptr); scndrynodes[tilenum]=(nodeT *)ReAlloc(scndrynodes[tilenum], nnewnodes*sizeof(nodeT)); scndrydummy=&scndrynodes[tilenum][nnewnodes-1]; nodesupp[tilenum]=(nodesuppT *)ReAlloc(nodesupp[tilenum], nnewnodes*sizeof(nodesuppT)); suppdummy=&nodesupp[tilenum][nnewnodes-1]; scndrydummy->row=tilenum; scndrydummy->col=nnewnodes-1; suppdummy->row=primarydummy->row; suppdummy->col=primarydummy->col; suppdummy->noutarcs=0; suppdummy->neighbornodes=NULL; suppdummy->outarcs=NULL; /* recursively call TraceSecondaryArc() to set up arcs */ TraceSecondaryArc(primarydummy,scndrynodes,nodesupp,scndryarcs, scndrycosts,nnewnodesptr,nnewarcsptr,tilerow,tilecol, flowmax,nrow,ncol,prevnrow,prevncol,params,tilecosts, rightedgecosts,loweredgecosts,leftedgecosts, upperedgecosts,tileflows,rightedgeflows, loweredgeflows,leftedgeflows,upperedgeflows, updatednontilenodesptr,nupdatednontilenodesptr, updatednontilenodesizeptr,inontilenodeoutarcptr, totarclenptr); TraceSecondaryArc(primaryhead,scndrynodes,nodesupp,scndryarcs, scndrycosts,nnewnodesptr,nnewarcsptr,tilerow,tilecol, flowmax,nrow,ncol,prevnrow,prevncol,params,tilecosts, rightedgecosts,loweredgecosts,leftedgecosts, upperedgecosts,tileflows,rightedgeflows, loweredgeflows,leftedgeflows,upperedgeflows, updatednontilenodesptr,nupdatednontilenodesptr, updatednontilenodesizeptr,inontilenodeoutarcptr, totarclenptr); }else{ /* only one primary arc; just delete other secondary arc */ /* find existing secondary arc (must be in this tile) */ /* swap direction of existing secondary arc if necessary */ arcnum=0; while(TRUE){ if(scndryarcs[tilenum][arcnum].from==primarytail && scndryarcs[tilenum][arcnum].to==primaryhead){ break; }else if(scndryarcs[tilenum][arcnum].from==primaryhead && scndryarcs[tilenum][arcnum].to==primarytail){ scndryarcs[tilenum][arcnum].from=primarytail; scndryarcs[tilenum][arcnum].to=primaryhead; break; } arcnum++; } /* assign cost of this secondary arc to existing secondary arc */ free(scndrycosts[tilenum][arcnum]); scndrycosts[tilenum][arcnum]=scndrycostarr; /* update direction data in secondary arc structure */ if(primarytail->col==primaryhead->col+1){ scndryarcs[tilenum][arcnum].fromdir=RIGHT; }else if(primarytail->row==primaryhead->row+1){ scndryarcs[tilenum][arcnum].fromdir=DOWN; }else if(primarytail->col==primaryhead->col-1){ scndryarcs[tilenum][arcnum].fromdir=LEFT; }else{ scndryarcs[tilenum][arcnum].fromdir=UP; } } /* we're done */ return; } } /* set up secondary arc datastructures */ nnewarcs=++(*nnewarcsptr); scndryarcs[tilenum]=(scndryarcT *)ReAlloc(scndryarcs[tilenum], nnewarcs*sizeof(scndryarcT)); newarc=&scndryarcs[tilenum][nnewarcs-1]; newarc->arcrow=tilenum; newarc->arccol=nnewarcs-1; scndrycosts[tilenum]=(long **)ReAlloc(scndrycosts[tilenum], nnewarcs*sizeof(long *)); scndrycosts[tilenum][nnewarcs-1]=scndrycostarr; /* update secondary node data */ /* store primary nodes in nodesuppT neighbornodes[] arrays since */ /* secondary node addresses change in ReAlloc() calls in TraceRegions() */ supptail=&nodesupp[scndrytail->row][scndrytail->col]; supphead=&nodesupp[scndryhead->row][scndryhead->col]; supptail->noutarcs++; supptail->neighbornodes=(nodeT **)ReAlloc(supptail->neighbornodes, supptail->noutarcs *sizeof(nodeT *)); supptail->neighbornodes[supptail->noutarcs-1]=primaryhead; primarytail->level=scndrytail->row; primarytail->incost=scndrytail->col; supptail->outarcs=(scndryarcT **)ReAlloc(supptail->outarcs, supptail->noutarcs *sizeof(scndryarcT *)); supptail->outarcs[supptail->noutarcs-1]=NULL; supphead->noutarcs++; supphead->neighbornodes=(nodeT **)ReAlloc(supphead->neighbornodes, supphead->noutarcs *sizeof(nodeT *)); supphead->neighbornodes[supphead->noutarcs-1]=primarytail; primaryhead->level=scndryhead->row; primaryhead->incost=scndryhead->col; supphead->outarcs=(scndryarcT **)ReAlloc(supphead->outarcs, supphead->noutarcs *sizeof(scndryarcT *)); supphead->outarcs[supphead->noutarcs-1]=NULL; /* keep track of updated secondary nodes that were not in this tile */ if(scndrytail->row!=tilenum){ if(++(*nupdatednontilenodesptr)==(*updatednontilenodesizeptr)){ (*updatednontilenodesizeptr)+=INITARRSIZE; (*updatednontilenodesptr)=(nodeT **)ReAlloc((*updatednontilenodesptr), (*updatednontilenodesizeptr) *sizeof(nodeT *)); (*inontilenodeoutarcptr)=(short *)ReAlloc((*inontilenodeoutarcptr), (*updatednontilenodesizeptr) *sizeof(short)); } (*updatednontilenodesptr)[*nupdatednontilenodesptr-1]=scndrytail; (*inontilenodeoutarcptr)[*nupdatednontilenodesptr-1]=supptail->noutarcs-1; } if(scndryhead->row!=tilenum){ if(++(*nupdatednontilenodesptr)==(*updatednontilenodesizeptr)){ (*updatednontilenodesizeptr)+=INITARRSIZE; (*updatednontilenodesptr)=(nodeT **)ReAlloc((*updatednontilenodesptr), (*updatednontilenodesizeptr) *sizeof(nodeT *)); (*inontilenodeoutarcptr)=(short *)ReAlloc((*inontilenodeoutarcptr), (*updatednontilenodesizeptr) *sizeof(short)); } (*updatednontilenodesptr)[*nupdatednontilenodesptr-1]=scndryhead; (*inontilenodeoutarcptr)[*nupdatednontilenodesptr-1]=supphead->noutarcs-1; } /* set up node data in secondary arc structure */ newarc->from=primarytail; newarc->to=primaryhead; /* set up direction data in secondary arc structure */ tempnode=primaryhead->pred; if(tempnode->col==primaryhead->col+1){ newarc->fromdir=RIGHT; }else if(tempnode->row==primaryhead->row+1){ newarc->fromdir=DOWN; }else if(tempnode->col==primaryhead->col-1){ newarc->fromdir=LEFT; }else{ newarc->fromdir=UP; } /* add number of primary arcs in secondary arc to counter */ (*totarclenptr)+=arclen; } /* function: FindScndryNode() * -------------------------- */ nodeT *FindScndryNode(nodeT **scndrynodes, nodesuppT **nodesupp, long tilenum, long primaryrow, long primarycol){ long nodenum; nodesuppT *nodesuppptr; /* set temporary variables */ nodesuppptr=nodesupp[tilenum]; /* loop over all nodes in the tile until we find a match */ nodenum=0; while(nodesuppptr[nodenum].row!=primaryrow || nodesuppptr[nodenum].col!=primarycol){ nodenum++; } return(&scndrynodes[tilenum][nodenum]); } /* function: IntegrateSecondaryFlows() * ----------------------------------- */ void IntegrateSecondaryFlows(long linelen, long nlines, nodeT **scndrynodes, nodesuppT **nodesupp, scndryarcT **scndryarcs, short *nscndryarcs, short **scndryflows, short **bulkoffsets, outfileT *outfiles, paramT *params){ FILE *outfp; float **unwphase, **tileunwphase, **mag, **tilemag; float *outline; long row, col, colstart, nrow, ncol, nnrow, nncol, maxcol; long readtilelinelen, readtilenlines, nextcoloffset, nextrowoffset; long tilerow, tilecol, ntilerow, ntilecol, rowovrlp, colovrlp; long ni, nj, tilenum; double tileoffset; short **regions, **tileflows; char realoutfile[MAXSTRLEN], readfile[MAXSTRLEN], tempstring[MAXTMPSTRLEN]; char path[MAXSTRLEN], basename[MAXSTRLEN]; signed char writeerror; tileparamT readtileparams[1]; outfileT readtileoutfiles[1]; /* set up */ fprintf(sp1,"Integrating secondary flows\n"); ntilerow=params->ntilerow; ntilecol=params->ntilecol; rowovrlp=params->rowovrlp; colovrlp=params->colovrlp; ni=ceil((nlines+(ntilerow-1)*rowovrlp)/(double )ntilerow); nj=ceil((linelen+(ntilecol-1)*colovrlp)/(double )ntilecol); nextcoloffset=0; writeerror=FALSE; /* get memory */ regions=(short **)Get2DMem(ni,nj,sizeof(short *),sizeof(short)); tileflows=(short **)Get2DRowColMem(ni+2,nj+2,sizeof(short *),sizeof(short)); tileunwphase=(float **)Get2DMem(ni,nj,sizeof(float *),sizeof(float)); tilemag=(float **)Get2DMem(ni,nj,sizeof(float *),sizeof(float)); unwphase=(float **)Get2DMem(ni,linelen,sizeof(float *),sizeof(float)); mag=(float **)Get2DMem(ni,linelen,sizeof(float *),sizeof(float)); outline=(float *)MAlloc(2*linelen*sizeof(float)); /* flip sign of bulk offsets if flip flag is set */ /* do this and flip flow signs instead of flipping phase signs */ if(params->flipphasesign){ for(row=0;rowoutfile,realoutfile); /* process each tile row */ for(tilerow=0;tilerowfirstcol; readtilenlines=readtileparams->nrow; readtilelinelen=readtileparams->ncol; /* set tile read parameters */ SetTileReadParams(readtileparams,readtilenlines,readtilelinelen, tilerow,tilecol,nlines,linelen,params); colstart+=readtileparams->firstcol; nrow=readtileparams->nrow; ncol=readtileparams->ncol; nnrow=nrow+1; nncol=ncol+1; /* read unwrapped phase */ /* phase sign not flipped for positive baseline */ /* since flow will be flipped if necessary */ if(TMPTILEOUTFORMAT==ALT_LINE_DATA){ ReadAltLineFile(&tilemag,&tileunwphase,readtileoutfiles->outfile, readtilelinelen,readtilenlines,readtileparams); }else if(TMPTILEOUTFORMAT==FLOAT_DATA){ Read2DArray((void ***)&tileunwphase,readtileoutfiles->outfile, readtilelinelen,readtilenlines,readtileparams, sizeof(float *),sizeof(float)); } /* read regions */ ParseFilename(outfiles->outfile,path,basename); sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld%s", params->tiledir,TMPTILEROOT,basename,tilerow,tilecol, readtilelinelen,REGIONSUFFIX); StrNCopy(readfile,tempstring,MAXSTRLEN); Read2DArray((void ***)®ions,readfile,readtilelinelen,readtilenlines, readtileparams,sizeof(short *),sizeof(short)); /* remove temporary files unless told so save them */ if(params->rmtmptile){ unlink(readtileoutfiles->outfile); unlink(readfile); } /* zero out primary flow array */ for(row=0;row<2*nrow+1;row++){ if(rowoutfileformat==ALT_LINE_DATA){ if(fwrite(mag[row],sizeof(float),linelen,outfp)!=linelen || fwrite(unwphase[row],sizeof(float),linelen,outfp)!=linelen){ writeerror=TRUE; break; } }else if(outfiles->outfileformat==ALT_SAMPLE_DATA){ for(col=0;colflipphasesign){ phaseflipsign=-1; }else{ phaseflipsign=1; } /* loop over all arcs in tile */ for(arcnum=0;arcnumrow==tilenum){ primaryfromrow=nodesupp[scndryfrom->row][scndryfrom->col].row; primaryfromcol=nodesupp[scndryfrom->row][scndryfrom->col].col; }else if(scndryfrom->row==tilenum-ntilecol){ primaryfromrow=0; primaryfromcol=nodesupp[scndryfrom->row][scndryfrom->col].col; }else if(scndryfrom->row==tilenum-1){ primaryfromrow=nodesupp[scndryfrom->row][scndryfrom->col].row; primaryfromcol=0; }else{ primaryfromrow=0; primaryfromcol=0; } if(scndryto->row==tilenum){ thisrow=nodesupp[scndryto->row][scndryto->col].row; thiscol=nodesupp[scndryto->row][scndryto->col].col; }else if(scndryto->row==tilenum-ntilecol){ thisrow=0; thiscol=nodesupp[scndryto->row][scndryto->col].col; }else if(scndryto->row==tilenum-1){ thisrow=nodesupp[scndryto->row][scndryto->col].row; thiscol=0; }else{ thisrow=0; thiscol=0; } /* set initial direction out of secondary arc head */ switch(scndryarcs[tilenum][arcnum].fromdir){ case RIGHT: nextrow=thisrow; nextcol=thiscol+1; tileflows[thisrow][thiscol]-=nflow; break; case DOWN: nextrow=thisrow+1; nextcol=thiscol; tileflows[nnrow+thisrow][thiscol]-=nflow; break; case LEFT: nextrow=thisrow; nextcol=thiscol-1; tileflows[thisrow][thiscol-1]+=nflow; break; default: nextrow=thisrow-1; nextcol=thiscol; tileflows[nnrow+thisrow-1][thiscol]+=nflow; break; } /* use region data to trace path between secondary from, to */ while(!(nextrow==primaryfromrow && nextcol==primaryfromcol)){ /* move to next node */ prevrow=thisrow; prevcol=thiscol; thisrow=nextrow; thiscol=nextcol; /* check rightward arc */ if(thiscol!=nncol-1){ if(thisrow==0 || thisrow==nnrow-1 || regions[thisrow-1][thiscol]!=regions[thisrow][thiscol]){ if(!(thisrow==prevrow && thiscol+1==prevcol)){ tileflows[thisrow][thiscol]-=nflow; nextcol++; } } } /* check downward arc */ if(thisrow!=nnrow-1){ if(thiscol==0 || thiscol==nncol-1 || regions[thisrow][thiscol]!=regions[thisrow][thiscol-1]){ if(!(thisrow+1==prevrow && thiscol==prevcol)){ tileflows[nnrow+thisrow][thiscol]-=nflow; nextrow++; } } } /* check leftward arc */ if(thiscol!=0){ if(thisrow==0 || thisrow==nnrow-1 || regions[thisrow][thiscol-1]!=regions[thisrow-1][thiscol-1]){ if(!(thisrow==prevrow && thiscol-1==prevcol)){ tileflows[thisrow][thiscol-1]+=nflow; nextcol--; } } } /* check upward arc */ if(thisrow!=0){ if(thiscol==0 || thiscol==nncol-1 || regions[thisrow-1][thiscol-1]!=regions[thisrow-1][thiscol]){ if(!(thisrow-1==prevrow && thiscol==prevcol)){ tileflows[nnrow+thisrow-1][thiscol]+=nflow; nextrow--; } } } } } } }