#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <signal.h>
#include <limits.h>
#include <float.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "snaphu.h"
extern char dumpresults_global;
extern char requestedstop_global;
extern FILE *sp0, *sp1, *sp2, *sp3;
extern nodeT NONTREEARC[1];
extern void (*CalcCost)(void **, long, long, long, long, long,
paramT *, long *, long *);
extern long (*EvalCost)(void **, short **, long, long, long, paramT *);
FILE *OpenOutputFile(char *outfile, char *realoutfile);
static
long ThickenCosts(incrcostT **incrcosts, long nrow, long ncol);
static
nodeT *RegionsNeighborNode(nodeT *node1, long *arcnumptr, nodeT **nodes,
long *arcrowptr, long *arccolptr,
long nrow, long ncol);
static
int ClearBuckets(bucketT *bkts);
static
int MergeRegions(nodeT **nodes, nodeT *source, long *regionsizes,
long closestregion, long nrow, long ncol);
static
int RenumberRegion(nodeT **nodes, nodeT *source, long newnum,
long nrow, long ncol);
static
int ReadNextRegion(long tilerow, long tilecol, long nlines, long linelen,
outfileT *outfiles, paramT *params,
short ***nextregionsptr, float ***nextunwphaseptr,
void ***nextcostsptr,
long *nextnrowptr, long *nextncolptr);
static
int SetTileReadParams(tileparamT *tileparams, long nexttilenlines,
long nexttilelinelen, long tilerow, long tilecol,
long nlines, long linelen, paramT *params);
static
int 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);
static
int 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, int *nscndrynodes,
int *nscndryarcs, long *totarclens, short **bulkoffsets,
paramT *params);
static
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);
static
int 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);
static
int SetUpperEdge(long ncol, long tilerow, long tilecol, void **voidcosts,
void *voidcostsabove, float **unwphase,
float *unwphaseabove, void **voidupperedgecosts,
short **upperedgeflows, paramT *params, short **bulkoffsets);
static
int SetLowerEdge(long nrow, long ncol, long tilerow, long tilecol,
void **voidcosts, void *voidcostsbelow,
float **unwphase, float *unwphasebelow,
void **voidloweredgecosts, short **loweredgeflows,
paramT *params, short **bulkoffsets);
static
int SetLeftEdge(long nrow, long prevncol, long tilerow, long tilecol,
void **voidcosts, void **voidlastcosts, float **unwphase,
float **lastunwphase, void **voidleftedgecosts,
short **leftedgeflows, paramT *params, short **bulkoffsets);
static
int SetRightEdge(long nrow, long ncol, long tilerow, long tilecol,
void **voidcosts, void **voidnextcosts,
float **unwphase, float **nextunwphase,
void **voidrightedgecosts, short **rightedgeflows,
paramT *params, short **bulkoffsets);
static
short AvgSigSq(short sigsq1, short sigsq2);
static
int TraceSecondaryArc(nodeT *primaryhead, nodeT **scndrynodes,
nodesuppT **nodesupp, scndryarcT **scndryarcs,
long ***scndrycosts, long *nnewnodesptr,
long *nnewarcsptr, long tilerow, long tilecol,
long flowmax, long nrow, long ncol,
long prevnrow, long prevncol, paramT *params,
void **tilecosts, void **rightedgecosts,
void **loweredgecosts, void **leftedgecosts,
void **upperedgecosts, short **tileflows,
short **rightedgeflows, short **loweredgeflows,
short **leftedgeflows, short **upperedgeflows,
nodeT ***updatednontilenodesptr,
long *nupdatednontilenodesptr,
long *updatednontilenodesizeptr,
short **inontilenodeoutarcptr, long *totarclenptr);
static
nodeT *FindScndryNode(nodeT **scndrynodes, nodesuppT **nodesupp,
long tilenum, long primaryrow, long primarycol);
static
int IntegrateSecondaryFlows(long linelen, long nlines, nodeT **scndrynodes,
nodesuppT **nodesupp, scndryarcT **scndryarcs,
int *nscndryarcs, short **scndryflows,
short **bulkoffsets, outfileT *outfiles,
paramT *params);
static
int ParseSecondaryFlows(long tilenum, int *nscndryarcs, short **tileflows,
short **regions, short **scndryflows,
nodesuppT **nodesupp, scndryarcT **scndryarcs,
long nrow, long ncol, long ntilerow, long ntilecol,
paramT *params);
static
int AssembleTileConnComps(long linelen, long nlines,
outfileT *outfiles, paramT *params);
static
int ConnCompSizeNPixCompare(const void *ptr1, const void *ptr2);
int 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;
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;
}
if(params->minregionsize > (tileparams->nrow)*(tileparams->ncol)){
fflush(NULL);
fprintf(sp0,"Minimum region size cannot exceed tile size\nAbort\n");
exit(ABNORMAL_EXIT);
}
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->conncompfile)){
ParseFilename(outfiles->conncompfile,path,basename);
sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld",
tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol);
StrNCopy(tileoutfiles->conncompfile,tempstring,MAXSTRLEN);
}else{
StrNCopy(tileoutfiles->conncompfile,"",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);
}
if(strlen(outfiles->logfile)){
ParseFilename(outfiles->logfile,path,basename);
sprintf(tempstring,"%s/%s%s_%ld_%ld.%ld",
tiledir,TMPTILEROOT,basename,tilerow,tilecol,tileparams->ncol);
StrNCopy(tileoutfiles->logfile,tempstring,MAXSTRLEN);
}else{
StrNCopy(tileoutfiles->logfile,"",MAXSTRLEN);
}
tileoutfiles->outfileformat=TMPTILEOUTFORMAT;
return(0);
}
signed char **SetUpDoTileMask(infileT *infiles, long ntilerow, long ntilecol){
long row, col;
signed char **dotilemask;
tileparamT readparams[1];
memset(readparams,0,sizeof(tileparamT));
dotilemask=(signed char **)Get2DMem(ntilerow,ntilecol,sizeof(signed char *),
sizeof(signed char));
if(strlen(infiles->dotilemaskfile)){
readparams->nrow=ntilerow;
readparams->ncol=ntilecol;
readparams->firstrow=0;
readparams->firstcol=0;
Read2DArray((void ***)&dotilemask,infiles->dotilemaskfile,ntilecol,
ntilerow,readparams,sizeof(signed char *),sizeof(signed char));
}else{
for(row=0;row<ntilerow;row++){
for(col=0;col<ntilecol;col++){
dotilemask[row][col]=1;
}
}
}
return(dotilemask);
}
int GrowRegions(void **costs, short **flows, long nrow, long ncol,
incrcostT **incrcosts, outfileT *outfiles,
tileparamT *tileparams, 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;
long costtypesize;
short **regions;
nodeT **nodes;
nodeT *source, *from, *to, *ground;
char regionfile[MAXSTRLEN];
bucketT bkts[1];
void **growregionscosts;
tileparamT temptileparams[1];
void (*tempcalccostfnptr)();
long (*tempevalcostfnptr)();
memset(regionfile,0,MAXSTRLEN);
memset(bkts,0,sizeof(bucketT));
memset(temptileparams,0,sizeof(tileparamT));
fprintf(sp1,"Growing reliable regions\n");
minsize=params->minregionsize;
costthresh=params->tilecostthresh;
closestregion=0;
tempcalccostfnptr=CalcCost;
tempevalcostfnptr=EvalCost;
if(params->p >= 0){
if(params->costmode==TOPO){
costtypesize=sizeof(costT);
CalcCost=CalcCostTopo;
EvalCost=EvalCostTopo;
}else if(params->costmode==DEFO){
costtypesize=sizeof(costT);
CalcCost=CalcCostDefo;
EvalCost=EvalCostDefo;
}else if(params->costmode==SMOOTH){
costtypesize=sizeof(smoothcostT);
CalcCost=CalcCostSmooth;
EvalCost=EvalCostSmooth;
}else{
fflush(NULL);
fprintf(sp0,"Illegal cost mode in GrowRegions(). This is a bug.\n");
exit(ABNORMAL_EXIT);
}
temptileparams->firstrow=0;
temptileparams->firstcol=0;
temptileparams->nrow=nrow;
temptileparams->ncol=ncol;
growregionscosts=NULL;
Read2DRowColFile((void ***)&growregionscosts,outfiles->costoutfile,
ncol,nrow,temptileparams,costtypesize);
}else{
growregionscosts=costs;
}
for(arcrow=0;arcrow<2*nrow-1;arcrow++){
if(arcrow<nrow-1){
maxcol=ncol;
}else{
maxcol=ncol-1;
}
for(arccol=0;arccol<maxcol;arccol++){
ReCalcCost(growregionscosts,incrcosts,flows[arcrow][arccol],
arcrow,arccol,1,nrow,params);
if(incrcosts[arcrow][arccol].negcost<incrcosts[arcrow][arccol].poscost){
incrcosts[arcrow][arccol].poscost=incrcosts[arcrow][arccol].negcost;
}
incrcosts[arcrow][arccol].poscost
=-(incrcosts[arcrow][arccol].poscost-costthresh);
if(incrcosts[arcrow][arccol].poscost<0){
incrcosts[arcrow][arccol].poscost=0;
}
}
}
maxcost=ThickenCosts(incrcosts,nrow,ncol);
ground=NULL;
nodes=(nodeT **)Get2DMem(nrow,ncol,sizeof(nodeT *),sizeof(nodeT));
InitNodeNums(nrow,ncol,nodes,ground);
InitNodes(nrow,ncol,nodes,ground);
bkts->size=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;i<bkts->size;i++){
bkts->bucket[i]=NULL;
}
regioncounter=-1;
regionsizeslen=INITARRSIZE;
regionsizes=(long *)MAlloc(regionsizeslen*sizeof(long));
for(row=0;row<nrow;row++){
for(col=0;col<ncol;col++){
nodes[row][col].incost=-1;
}
}
for(row=0;row<nrow;row++){
for(col=0;col<ncol;col++){
if(nodes[row][col].incost<0){
ClearBuckets(bkts);
source=&nodes[row][col];
source->next=NULL;
source->prev=NULL;
source->group=INBUCKET;
source->outcost=0;
bkts->bucket[0]=source;
bkts->curr=0;
lastfromdist=0;
if(++regioncounter>=regionsizeslen){
regionsizeslen+=INITARRSIZE;
regionsizes=(long *)ReAlloc(regionsizes,
regionsizeslen*sizeof(long));
}
thisregionsize=®ionsizes[regioncounter];
(*thisregionsize)=0;
closestregiondist=VERYFAR;
while(TRUE){
from=ClosestNode(bkts);
if(from==NULL){
if(*thisregionsize>=minsize){
break;
}else{
MergeRegions(nodes,source,regionsizes,closestregion,nrow,ncol);
regioncounter--;
break;
}
}else{
fromdist=from->outcost;
if(fromdist>lastfromdist){
if(regionsizes[regioncounter]>=minsize){
break;
}
if(fromdist>closestregiondist){
MergeRegions(nodes,source,regionsizes,closestregion,nrow,ncol);
regioncounter--;
break;
}
}
}
from->incost=regioncounter;
(*thisregionsize)++;
lastfromdist=fromdist;
arcnum=0;
while((to=RegionsNeighborNode(from,&arcnum,nodes,
&arcrow,&arccol,nrow,ncol))!=NULL){
arcdist=incrcosts[arcrow][arccol].negcost;
if(to->incost>=0){
if(to->incost!=regioncounter && arcdist<closestregiondist){
closestregiondist=arcdist;
closestregion=to->incost;
}
}else{
if(arcdist<(to->outcost)){
if(to->group==INBUCKET){
BucketRemove(to,to->outcost,bkts);
}
to->outcost=arcdist;
to->pred=from;
BucketInsert(to,arcdist,bkts);
if(arcdist<bkts->curr){
bkts->curr=arcdist;
}
}
}
}
}
}
}
}
fprintf(sp2,"Tile partitioned into %ld regions\n",regioncounter+1);
if(params->ntilerow > 1 || params->ntilecol>1){
regions=(short **)Get2DMem(nrow,ncol,sizeof(short *),sizeof(short));
for(row=0;row<nrow;row++){
for(col=0;col<ncol;col++){
if(nodes[row][col].incost>LARGESHORT){
fflush(NULL);
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));
}else{
regions=NULL;
}
CalcCost=tempcalccostfnptr;
EvalCost=tempevalcostfnptr;
if(params->p >= 0){
Free2DArray((void **)growregionscosts,2*nrow-1);
}
Free2DArray((void **)nodes,nrow);
if(regions!=NULL){
Free2DArray((void **)regions,nrow);
}
free(bkts->bucketbase);
return(0);
}
int 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;
unsigned long outtypemax, outtypesize;
nodeT **nodes;
nodeT *source, *from, *to, *ground;
unsigned char *ucharbuf;
unsigned int *uintbuf;
void *outbufptr;
bucketT bkts[1];
char realoutfile[MAXSTRLEN];
FILE *conncompfp;
memset(bkts,0,sizeof(bucketT));
fprintf(sp1,"Growing connected component mask\n");
minsize=params->minconncompfrac*nrow*ncol;
maxncomps=params->maxncomps;
costthresh=params->conncompthresh;
if(minsize>nrow*ncol){
fflush(NULL);
fprintf(sp0,"Minimum region size cannot exceed tile size\nAbort\n");
exit(ABNORMAL_EXIT);
}
for(arcrow=0;arcrow<2*nrow-1;arcrow++){
if(arcrow<nrow-1){
maxcol=ncol;
}else{
maxcol=ncol-1;
}
for(arccol=0;arccol<maxcol;arccol++){
ReCalcCost(costs,incrcosts,flows[arcrow][arccol],
arcrow,arccol,1,nrow,params);
if(incrcosts[arcrow][arccol].negcost<incrcosts[arcrow][arccol].poscost){
incrcosts[arcrow][arccol].poscost=incrcosts[arcrow][arccol].negcost;
}
incrcosts[arcrow][arccol].poscost
=-(incrcosts[arcrow][arccol].poscost-costthresh);
if(incrcosts[arcrow][arccol].poscost<0){
incrcosts[arcrow][arccol].poscost=0;
}
}
}
ThickenCosts(incrcosts,nrow,ncol);
ground=NULL;
nodes=(nodeT **)Get2DMem(nrow,ncol,sizeof(nodeT *),sizeof(nodeT));
InitNodeNums(nrow,ncol,nodes,ground);
InitNodes(nrow,ncol,nodes,ground);
bkts->size=1;
bkts->minind=0;
bkts->maxind=0;
bkts->wrapped=FALSE;
bkts->bucketbase=(nodeT **)MAlloc(sizeof(nodeT *));
bkts->bucket=bkts->bucketbase;
bkts->bucket[0]=NULL;
regioncounter=0;
regionsizeslen=INITARRSIZE;
regionsizes=(long *)MAlloc(regionsizeslen*sizeof(long));
for(row=0;row<nrow;row++){
for(col=0;col<ncol;col++){
nodes[row][col].incost=-1;
}
}
for(row=0;row<nrow;row++){
for(col=0;col<ncol;col++){
if(nodes[row][col].incost<0){
ClearBuckets(bkts);
source=&nodes[row][col];
source->next=NULL;
source->prev=NULL;
source->group=INBUCKET;
source->outcost=0;
bkts->bucket[0]=source;
bkts->curr=0;
if(++regioncounter>=regionsizeslen){
regionsizeslen+=INITARRSIZE;
regionsizes=(long *)ReAlloc(regionsizes,
regionsizeslen*sizeof(long));
}
thisregionsize=®ionsizes[regioncounter];
(*thisregionsize)=0;
while(TRUE){
from=ClosestNode(bkts);
if(from==NULL){
if(regionsizes[regioncounter]>=minsize){
break;
}else{
RenumberRegion(nodes,source,0,nrow,ncol);
regioncounter--;
break;
}
}
from->incost=regioncounter;
(*thisregionsize)++;
arcnum=0;
while((to=RegionsNeighborNode(from,&arcnum,nodes,
&arcrow,&arccol,nrow,ncol))!=NULL){
if(to->incost<0 && incrcosts[arcrow][arccol].negcost==0
&& to->group!=INBUCKET){
to->pred=from;
BucketInsert(to,0,bkts);
}
}
}
}
}
}
fprintf(sp2,"%ld connected components formed\n",regioncounter);
if(regioncounter>maxncomps){
fprintf(sp2,"Keeping only %ld connected components\n",maxncomps);
sortedregionsizes=(long *)MAlloc(regioncounter*sizeof(long));
for(i=0;i<regioncounter;i++){
sortedregionsizes[i]=regionsizes[i+1];
}
qsort((void *)sortedregionsizes,regioncounter,sizeof(long),LongCompare);
minsize=sortedregionsizes[regioncounter-maxncomps];
ntied=0;
i=regioncounter-maxncomps-1;
while(i>=0 && sortedregionsizes[i]==minsize){
ntied++;
i--;
}
newnum=-1;
for(row=0;row<nrow;row++){
for(col=0;col<ncol;col++){
i=nodes[row][col].incost;
if(i>0){
if(regionsizes[i]<minsize
|| (regionsizes[i]==minsize && (ntied--)>0)){
RenumberRegion(nodes,&(nodes[row][col]),0,nrow,ncol);
}else{
RenumberRegion(nodes,&(nodes[row][col]),newnum--,nrow,ncol);
}
}
}
}
for(row=0;row<nrow;row++){
for(col=0;col<ncol;col++){
nodes[row][col].incost=-nodes[row][col].incost;
}
}
}
ucharbuf=(unsigned char *)MAlloc(ncol*sizeof(unsigned char));
uintbuf=(unsigned int *)MAlloc(ncol*sizeof(unsigned int));
if(params->conncompouttype==CONNCOMPOUTTYPEUCHAR){
outtypemax=UCHAR_MAX;
outtypesize=(int )sizeof(unsigned char);
outbufptr=(void *)ucharbuf;
}else if(params->conncompouttype==CONNCOMPOUTTYPEUINT){
outtypemax=UINT_MAX;
outtypesize=(int )sizeof(unsigned int);
outbufptr=(void *)uintbuf;
}else{
fflush(NULL);
fprintf(sp0,"Bad conncompouttype in GrowConnCompMask()\n");
exit(ABNORMAL_EXIT);
}
fprintf(sp1,"Writing connected components to file %s"
" as %d-byte unsigned ints\n",
outfiles->conncompfile,((int )outtypesize));
conncompfp=OpenOutputFile(outfiles->conncompfile,realoutfile);
for(row=0;row<nrow;row++){
for(col=0;col<ncol;col++){
if(nodes[row][col].incost>outtypemax){
fflush(NULL);
fprintf(sp0,"Number of connected components too large for output type\n"
"Abort\n");
exit(ABNORMAL_EXIT);
}
uintbuf[col]=(unsigned int)(nodes[row][col].incost);
}
if(params->conncompouttype==CONNCOMPOUTTYPEUCHAR){
for(col=0;col<ncol;col++){
ucharbuf[col]=(unsigned char )uintbuf[col];
}
}
if(fwrite(outbufptr,outtypesize,ncol,conncompfp)!=ncol){
fflush(NULL);
fprintf(sp0,"Error while writing to file %s (device full?)\nAbort\n",
realoutfile);
exit(ABNORMAL_EXIT);
}
}
if(fclose(conncompfp)){
fflush(NULL);
fprintf(sp0,"WARNING: problem closing file %s (disk full?)\n",
outfiles->conncompfile);
}
Free2DArray((void **)nodes,nrow);
free(bkts->bucketbase);
free(uintbuf);
free(ucharbuf);
return(0);
}
static
long ThickenCosts(incrcostT **incrcosts, long nrow, long ncol){
long row, col, templong, maxcost;
double n;
maxcost=-LARGEINT;
for(row=0;row<nrow-1;row++){
for(col=0;col<ncol;col++){
templong=2*incrcosts[row][col].poscost;
n=2.0;
if(col!=0){
templong+=incrcosts[row][col-1].poscost;
n+=1.0;
}
if(col!=ncol-1){
templong+=incrcosts[row][col+1].poscost;
n+=1.0;
}
templong=LRound(templong/n);
if(templong>LARGESHORT){
fflush(NULL);
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;
}
}
}
for(row=nrow-1;row<2*nrow-1;row++){
for(col=0;col<ncol-1;col++){
templong=2*incrcosts[row][col].poscost;
n=2.0;
if(row!=nrow-1){
templong+=incrcosts[row-1][col].poscost;
n+=1.0;
}
if(row!=2*nrow-2){
templong+=incrcosts[row+1][col].poscost;
n+=1.0;
}
templong=LRound(templong/n);
if(templong>LARGESHORT){
fflush(NULL);
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(maxcost);
}
static
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);
}
}
}
static
int ClearBuckets(bucketT *bkts){
nodeT *currentnode, *nextnode;
long i;
for(i=0;i<bkts->size;i++){
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;
}
bkts->minind=0;
bkts->maxind=bkts->size-1;
bkts->wrapped=FALSE;
return(0);
}
static
int MergeRegions(nodeT **nodes, nodeT *source, long *regionsizes,
long closestregion, long nrow, long ncol){
long nextnodelistlen, nextnodelistnext, arcnum, arcrow, arccol, regionnum;
nodeT *from, *to, **nextnodelist;
nextnodelistlen=INITARRSIZE;
nextnodelist=(nodeT **)MAlloc(nextnodelistlen*sizeof(nodeT **));
nextnodelist[0]=source;
nextnodelistnext=1;
regionnum=source->incost;
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;
}
}
}
regionsizes[closestregion]+=regionsizes[regionnum];
free(nextnodelist);
return(0);
}
static
int RenumberRegion(nodeT **nodes, nodeT *source, long newnum,
long nrow, long ncol){
long nextnodelistlen, nextnodelistnext, arcnum, arcrow, arccol, regionnum;
nodeT *from, *to, **nextnodelist;
nextnodelistlen=INITARRSIZE;
nextnodelist=(nodeT **)MAlloc(nextnodelistlen*sizeof(nodeT **));
nextnodelist[0]=source;
nextnodelistnext=1;
regionnum=source->incost;
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(nextnodelist);
return(0);
}
int 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 nnondecreasedcostiter;
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;
int *nscndrynodes, *nscndryarcs;
incrcostT **incrcosts;
totalcostT totalcost, oldtotalcost, mintotalcost;
nodeT *source;
nodeT **scndrynodes, ***scndryapexes;
signed char **iscandidate;
signed char notfirstloop;
candidateT *candidatebag, *candidatelist;
nodesuppT **nodesupp;
scndryarcT **scndryarcs;
bucketT *bkts;
char filename[MAXSTRLEN];
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;
prevnrow=0;
if(params->costmode==TOPO){
costtypesize=sizeof(costT);
CalcCost=CalcCostTopo;
EvalCost=EvalCostTopo;
}else if(params->costmode==DEFO){
costtypesize=sizeof(costT);
CalcCost=CalcCostDefo;
EvalCost=EvalCostDefo;
}else if(params->costmode==SMOOTH){
costtypesize=sizeof(smoothcostT);
CalcCost=CalcCostSmooth;
EvalCost=EvalCostSmooth;
}else{
fflush(NULL);
fprintf(sp0,"Illegal cost mode in AssembleTiles(). Abort\n");
exit(ABNORMAL_EXIT);
}
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=(int *)MAlloc(ntiles*sizeof(int));
nscndryarcs=(int *)MAlloc(ntiles*sizeof(int));
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);
bulkoffsets[0][0]=0;
for(tilerow=0;tilerow<ntilerow;tilerow++){
for(tilecol=0;tilecol<ntilecol;tilecol++){
if(tilecol==0){
ReadNextRegion(tilerow,0,nlines,linelen,outfiles,params,
&nextregions,&nextunwphase,&nextcosts,
&nextnrow,&nextncol);
prevnrow=nrow;
nrow=nextnrow;
}
prevncol=ncol;
ncol=nextncol;
tempregions=lastregions;
lastregions=regions;
regions=nextregions;
nextregions=tempregions;
tempunwphase=lastunwphase;
lastunwphase=unwphase;
unwphase=nextunwphase;
nextunwphase=tempunwphase;
tempcosts=lastcosts;
lastcosts=costs;
costs=nextcosts;
nextcosts=tempcosts;
if(tilecol!=ntilecol-1){
ReadNextRegion(tilerow,tilecol+1,nlines,linelen,outfiles,params,
&nextregions,&nextunwphase,&nextcosts,
&nextnrow,&nextncol);
}
ReadEdgesAboveAndBelow(tilerow,tilecol,nlines,linelen,params,
outfiles,regionsabove,regionsbelow,
unwphaseabove,unwphasebelow,
costsabove,costsbelow);
TraceRegions(regions,nextregions,lastregions,regionsabove,regionsbelow,
unwphase,nextunwphase,lastunwphase,unwphaseabove,
unwphasebelow,costs,nextcosts,lastcosts,costsabove,
costsbelow,prevnrow,prevncol,tilerow,tilecol,
nrow,ncol,scndrynodes,nodesupp,scndryarcs,
scndrycosts,nscndrynodes,nscndryarcs,totarclens,
bulkoffsets,params);
}
}
arclen=0;
narcs=0;
for(i=0;i<ntiles;i++){
arclen+=totarclens[i];
narcs+=nscndryarcs[i];
}
avgarclen=arclen/narcs;
for(i=0;i<ntiles;i++){
for(j=0;j<nscndryarcs[i];j++){
if(scndrycosts[i][j][2*flowmax+1]!=ZEROCOSTARC){
for(k=1;k<=2*flowmax;k++){
scndrycosts[i][j][k]=(long )ceil(scndrycosts[i][j][k]/avgarclen);
}
scndrycosts[i][j][2*flowmax+1]=LRound(scndrycosts[i][j][2*flowmax+1]
/avgarclen);
if(scndrycosts[i][j][2*flowmax+1]<0){
scndrycosts[i][j][2*flowmax+1]=0;
}
}
}
}
Free2DArray((void **)regions,ni);
Free2DArray((void **)nextregions,ni);
Free2DArray((void **)lastregions,ni);
Free2DArray((void **)unwphase,ni);
Free2DArray((void **)nextunwphase,ni);
Free2DArray((void **)lastunwphase,ni);
Free2DArray((void **)costs,ni);
Free2DArray((void **)nextcosts,ni);
Free2DArray((void **)lastcosts,ni);
free(costsabove);
free(costsbelow);
free(unwphaseabove);
free(unwphasebelow);
free(regionsabove);
free(regionsbelow);
scndryflows=(short **)MAlloc(ntiles*sizeof(short *));
iscandidate=(signed char **)MAlloc(ntiles*sizeof(signed char*));
scndryapexes=(nodeT ***)MAlloc(ntiles*sizeof(nodeT **));
incrcosts=(incrcostT **)MAlloc(ntiles*sizeof(incrcostT *));
nnodes=0;
for(i=0;i<ntiles;i++){
scndryflows[i]=(short *)CAlloc(nscndryarcs[i],sizeof(short));
iscandidate[i]=(signed char *)MAlloc(nscndryarcs[i]*sizeof(signed char));
scndryapexes[i]=(nodeT **)MAlloc(nscndryarcs[i]*sizeof(nodeT *));
incrcosts[i]=(incrcostT *)MAlloc(nscndryarcs[i]*sizeof(incrcostT));
nnodes+=nscndrynodes[i];
}
InitNetwork(scndryflows,&dummylong,&ncycle,&nflowdone,&dummylong,&nflow,
&candidatebagsize,&candidatebag,&candidatelistsize,
&candidatelist,NULL,NULL,&bkts,&dummylong,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,ntiles,0,¬firstloop,&totalcost,params);
oldtotalcost=totalcost;
mintotalcost=totalcost;
nnondecreasedcostiter=0;
CalcCost=CalcCostNonGrid;
EvalCost=EvalCostNonGrid;
SetNonGridNetworkFunctionPointers();
fprintf(sp1,"Running optimizer for secondary network\n");
fprintf(sp1,"Number of nodes in secondary network: %ld\n",nnodes);
maxnflowcycles=LRound(nnodes*params->maxcyclefraction);
while(TRUE){
fprintf(sp1,"Flow increment: %ld (Total improvements: %ld)\n",
nflow,ncycle);
SetupIncrFlowCosts((void **)scndrycosts,incrcosts,scndryflows,nflow,ntiles,
ntiles,nscndryarcs,params);
sourcetilenum=(long )ntilecol*floor(ntilerow/2.0)+floor(ntilecol/2.0);
source=&scndrynodes[sourcetilenum][0];
SetupTreeSolveNetwork(scndrynodes,NULL,scndryapexes,iscandidate,
ntiles,nscndrynodes,ntiles,nscndryarcs,
ntiles,0);
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,nnodes,params);
if(notfirstloop){
oldtotalcost=totalcost;
totalcost=EvaluateTotalCost((void **)scndrycosts,scndryflows,ntiles,0,
nscndryarcs,params);
if(totalcost<mintotalcost){
mintotalcost=totalcost;
}
if(totalcost>oldtotalcost || (n>0 && totalcost==oldtotalcost)){
fflush(NULL);
fprintf(sp1,"Caution: Unexpected increase in total cost\n");
}
if(totalcost>=mintotalcost){
nnondecreasedcostiter++;
}else{
nnondecreasedcostiter=0;
}
}
ncycle+=n;
if(n<=maxnflowcycles){
nflowdone++;
}else{
nflowdone=1;
}
if(nnondecreasedcostiter>=2*params->maxflow){
fflush(NULL);
fprintf(sp0,"WARNING: No overall cost reduction for too many iterations."
" Breaking loop\n");
break;
}
if(nflowdone>=params->maxflow){
break;
}
nflow++;
if(nflow>params->maxflow){
nflow=1;
notfirstloop=TRUE;
}
}
for(i=0;i<ntiles;i++){
for(j=0;j<nscndryarcs[i];j++){
free(scndrycosts[i][j]);
}
}
Free2DArray((void **)scndrycosts,ntiles);
Free2DArray((void **)scndryapexes,ntiles);
Free2DArray((void **)iscandidate,ntiles);
Free2DArray((void **)incrcosts,ntiles);
free(candidatebag);
free(candidatelist);
free(bkts->bucketbase);
if(strlen(outfiles->conncompfile)){
AssembleTileConnComps(linelen,nlines,outfiles,params);
}
IntegrateSecondaryFlows(linelen,nlines,scndrynodes,nodesupp,scndryarcs,
nscndryarcs,scndryflows,bulkoffsets,outfiles,params);
for(i=0;i<ntiles;i++){
for(j=0;j<nscndrynodes[i];j++){
free(nodesupp[i][j].neighbornodes);
free(nodesupp[i][j].outarcs);
}
}
Free2DArray((void **)nodesupp,ntiles);
Free2DArray((void **)scndrynodes,ntiles);
Free2DArray((void **)scndryarcs,ntiles);
Free2DArray((void **)scndryflows,ntiles);
free(nscndrynodes);
free(nscndryarcs);
Free2DArray((void **)bulkoffsets,ntilerow);
if(params->rmtmptile){
fflush(NULL);
fprintf(sp1,"Removing temporary directory %s\n",params->tiledir);
for(tilerow=0;tilerow<ntilerow;tilerow++){
for(tilecol=0;tilecol<ntilecol;tilecol++){
sprintf(filename,"%s/%s%ld_%ld",
params->tiledir,LOGFILEROOT,tilerow,tilecol);
unlink(filename);
}
}
rmdir(params->tiledir);
}
if(params->rowovrlp<ni || params->colovrlp<nj){
fflush(NULL);
fprintf(sp1,
"SUGGESTION: Try increasing tile overlap and/or size"
" if solution has edge artifacts\n");
}
return(0);
}
static
int 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];
memset(nexttileparams,0,sizeof(tileparamT));
memset(nexttileoutfiles,0,sizeof(outfileT));
memset(nextfile,0,MAXSTRLEN);
memset(tempstring,0,MAXSTRLEN);
memset(path,0,MAXSTRLEN);
memset(basename,0,MAXSTRLEN);
if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){
costtypesize=sizeof(costT);
}else if(CalcCost==CalcCostSmooth){
costtypesize=sizeof(smoothcostT);
}else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1
|| CalcCost==CalcCostL2 || CalcCost==CalcCostLP){
costtypesize=sizeof(short);
}else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir
|| CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){
costtypesize=sizeof(bidircostT);
}else{
fflush(NULL);
fprintf(sp0,"ERROR: Bad CalcCost func ptr in ReadNextRegion()\n");
exit(ABNORMAL_EXIT);
}
SetupTile(nlines,linelen,params,nexttileparams,outfiles,nexttileoutfiles,
tilerow,tilecol);
nexttilenlines=nexttileparams->nrow;
nexttilelinelen=nexttileparams->ncol;
SetTileReadParams(nexttileparams,nexttilenlines,nexttilelinelen,
tilerow,tilecol,nlines,linelen,params);
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));
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{
fflush(NULL);
fprintf(sp0,"Cannot read format of unwrapped phase tile data\nAbort\n");
exit(ABNORMAL_EXIT);
}
Read2DRowColFile((void ***)nextcostsptr,nexttileoutfiles->costoutfile,
nexttilelinelen,nexttilenlines,nexttileparams,
costtypesize);
FlipPhaseArraySign(*nextunwphaseptr,params,
nexttileparams->nrow,nexttileparams->ncol);
(*nextnrowptr)=nexttileparams->nrow;
(*nextncolptr)=nexttileparams->ncol;
return(0);
}
static
int SetTileReadParams(tileparamT *tileparams, long nexttilenlines,
long nexttilelinelen, long tilerow, long tilecol,
long nlines, long linelen, paramT *params){
long rowovrlp, colovrlp;
rowovrlp=params->rowovrlp;
colovrlp=params->colovrlp;
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;
}
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;
}
return(0);
}
static
int 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];
memset(tileparams,0,sizeof(tileparamT));
memset(outfilesabove,0,sizeof(outfileT));
memset(outfilesbelow,0,sizeof(outfileT));
memset(tempstring,0,MAXSTRLEN);
memset(readregionfile,0,MAXSTRLEN);
memset(path,0,MAXSTRLEN);
memset(basename,0,MAXSTRLEN);
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);
if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){
costtypesize=sizeof(costT);
}else if(CalcCost==CalcCostSmooth){
costtypesize=sizeof(smoothcostT);
}else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1
|| CalcCost==CalcCostL2 || CalcCost==CalcCostLP){
costtypesize=sizeof(short);
}else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir
|| CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){
costtypesize=sizeof(bidircostT);
}else{
fflush(NULL);
fprintf(sp0,"ERROR: Bad CalcCost func ptr in ReadEdgesAboveAndBelow()\n");
exit(ABNORMAL_EXIT);
}
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);
}
unwphaseaboveptr=&unwphaseabove;
unwphasebelowptr=&unwphasebelow;
costsaboveptr=&costsabove;
costsbelowptr=&costsbelow;
regionsaboveptr=®ionsabove;
regionsbelowptr=®ionsbelow;
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;
readtilenlines=ni;
if(tilerow!=0){
tileparams->firstrow=readtilenlines-floor(rowovrlp/2.0)-1;
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));
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));
}
FlipPhaseArraySign(unwphaseaboveptr,params,
tileparams->nrow,tileparams->ncol);
tileparams->firstrow--;
Read2DRowColFileRows((void ***)&costsaboveptr,outfilesabove->costoutfile,
readtilelinelen,readtilenlines,tileparams,
costtypesize);
if(params->rmtmptile && !strlen(outfiles->costoutfile)){
unlink(outfilesabove->costoutfile);
}
}
if(tilerow!=ntilerow-1){
if(tilerow==params->ntilerow-2){
readtilenlines=nlines-(ntilerow-1)*(ni-rowovrlp);
}
tileparams->firstrow=ceil(rowovrlp/2.0);
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));
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));
}
FlipPhaseArraySign(unwphasebelowptr,params,
tileparams->nrow,tileparams->ncol);
Read2DRowColFileRows((void ***)&costsbelowptr,outfilesbelow->costoutfile,
readtilelinelen,readtilenlines,tileparams,
costtypesize);
}else{
if(params->rmtmptile && !strlen(outfiles->costoutfile)){
SetupTile(nlines,linelen,params,tileparams,outfiles,outfilesbelow,
tilerow,tilecol);
unlink(outfilesbelow->costoutfile);
}
}
return(0);
}
static
int 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, int *nscndrynodes,
int *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;
ntilecol=params->ntilecol;
nnrow=nrow+1;
nncol=ncol+1;
primarynodes=(nodeT **)Get2DMem(nnrow,nncol,sizeof(nodeT *),sizeof(nodeT));
for(row=0;row<nnrow;row++){
for(col=0;col<nncol;col++){
primarynodes[row][col].row=row;
primarynodes[row][col].col=col;
primarynodes[row][col].group=NOTINBUCKET;
primarynodes[row][col].pred=NULL;
primarynodes[row][col].next=NULL;
}
}
nextnode=&primarynodes[0][0];
tilenum=tilerow*ntilecol+tilecol;
scndrynodes[tilenum]=NULL;
nodesupp[tilenum]=NULL;
scndryarcs[tilenum]=NULL;
scndrycosts[tilenum]=NULL;
nnewnodes=0;
nnewarcs=0;
totarclen=0;
flowmax=params->scndryarcflowmax;
updatednontilenodesize=INITARRSIZE;
nupdatednontilenodes=0;
if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){
costtypesize=sizeof(costT);
}else if(CalcCost==CalcCostSmooth){
costtypesize=sizeof(smoothcostT);
}else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1
|| CalcCost==CalcCostL2 || CalcCost==CalcCostLP){
costtypesize=sizeof(short);
}else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir
|| CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){
costtypesize=sizeof(bidircostT);
}else{
fflush(NULL);
fprintf(sp0,"ERROR: Bad CalcCost func ptr in TraceRegions()\n");
exit(ABNORMAL_EXIT);
}
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);
CalcFlow(unwphase,&flows,nrow,ncol);
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);
while(nextnode!=NULL){
from=nextnode;
nextnode=nextnode->next;
from->group=NOTINBUCKET;
npathsout=FindNumPathsOut(from,params,tilerow,tilecol,nnrow,nncol,regions,
nextregions,lastregions,regionsabove,
regionsbelow,prevncol);
if(npathsout>2){
from->group=ONTREE;
if((from->row!=0 || tilerow==0) && (from->col!=0 || tilecol==0)){
nnewnodes++;
if(nnewnodes > SHRT_MAX){
fflush(NULL);
fprintf(sp0,"Exceeded maximum number of secondary nodes\n"
"Decrease TILECOSTTHRESH and/or increase MINREGIONSIZE\n");
exit(ABNORMAL_EXIT);
}
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;
}
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);
}
}
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);
}
for(i=0;i<nnewnodes;i++){
for(j=0;j<nodesupp[tilenum][i].noutarcs;j++){
tempnode=nodesupp[tilenum][i].neighbornodes[j];
nodesupp[tilenum][i].neighbornodes[j]
=&scndrynodes[tempnode->level][tempnode->incost];
}
}
for(i=0;i<nupdatednontilenodes;i++){
row=updatednontilenodes[i]->row;
col=updatednontilenodes[i]->col;
j=inontilenodeoutarc[i];
tempnode=nodesupp[row][col].neighbornodes[j];
nodesupp[row][col].neighbornodes[j]
=&scndrynodes[tempnode->level][tempnode->incost];
}
for(i=0;i<nnewarcs;i++){
tempnode=scndryarcs[tilenum][i].from;
scndryarcs[tilenum][i].from
=&scndrynodes[tempnode->level][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;
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];
}
nscndrynodes[tilenum]=nnewnodes;
nscndryarcs[tilenum]=nnewarcs;
totarclens[tilenum]=totarclen;
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);
return(0);
}
static
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;
ntilerow=params->ntilerow;
ntilecol=params->ntilecol;
fromrow=from->row;
fromcol=from->col;
npathsout=0;
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++;
}
}
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++;
}
}
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++;
}
}
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(npathsout);
}
static
int 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;
fromrow=from->row;
fromcol=from->col;
nextnode=(*nextnodeptr);
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);
}
}
}
}
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);
}
}
}
}
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);
}
}
}
}
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);
}
}
}
}
*nextnodeptr=nextnode;
return(0);
}
static
int 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;
upperedgecosts=(costT **)voidupperedgecosts;
costs=(costT **)voidcosts;
costsabove=(costT *)voidcostsabove;
upperedgesmoothcosts=(smoothcostT **)voidupperedgecosts;
smoothcosts=(smoothcostT **)voidcosts;
smoothcostsabove=(smoothcostT *)voidcostsabove;
if(tilerow!=0){
nshortcycle=params->nshortcycle;
reloffset=bulkoffsets[tilerow-1][tilecol]-bulkoffsets[tilerow][tilecol];
for(col=0;col<ncol;col++){
dphi=(unwphaseabove[col]-unwphase[0][col])/TWOPI;
upperedgeflows[0][col]=(short )LRound(dphi)-reloffset;
dpsi=dphi-floor(dphi);
if(dpsi>0.5){
dpsi-=1.0;
}
if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){
upperedgecosts[0][col].offset=(short )LRound(nshortcycle*dpsi);
upperedgecosts[0][col].sigsq=AvgSigSq(costs[0][col].sigsq,
costsabove[col].sigsq);
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].laycost<costsabove[col].laycost){
upperedgecosts[0][col].laycost=costs[0][col].laycost;
}else{
upperedgecosts[0][col].laycost=costsabove[col].laycost;
}
}else if(CalcCost==CalcCostSmooth){
upperedgesmoothcosts[0][col].offset=(short )LRound(nshortcycle*dpsi);
upperedgesmoothcosts[0][col].sigsq
=AvgSigSq(smoothcosts[0][col].sigsq,smoothcostsabove[col].sigsq);
}else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1
|| CalcCost==CalcCostL2 || CalcCost==CalcCostLP){
((short **)voidupperedgecosts)[0][col]=
(((short **)voidcosts)[0][col]+((short *)voidcostsabove)[col])/2;
}else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir
|| CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){
((bidircostT **)voidupperedgecosts)[0][col].posweight=
(((bidircostT **)voidcosts)[0][col].posweight
+((bidircostT *)voidcostsabove)[col].posweight)/2;
((bidircostT **)voidupperedgecosts)[0][col].negweight=
(((bidircostT **)voidcosts)[0][col].negweight
+((bidircostT *)voidcostsabove)[col].negweight)/2;
}else{
fflush(NULL);
fprintf(sp0,"Illegal cost mode in SetUpperEdge(). This is a bug.\n");
exit(ABNORMAL_EXIT);
}
}
}else{
if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){
for(col=0;col<ncol;col++){
upperedgecosts[0][col].offset=LARGESHORT/2;
upperedgecosts[0][col].sigsq=LARGESHORT;
upperedgecosts[0][col].dzmax=LARGESHORT;
upperedgecosts[0][col].laycost=0;
}
}else if(CalcCost==CalcCostSmooth){
for(col=0;col<ncol;col++){
upperedgesmoothcosts[0][col].offset=0;
upperedgesmoothcosts[0][col].sigsq=LARGESHORT;
}
}else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1
|| CalcCost==CalcCostL2 || CalcCost==CalcCostLP){
for(col=0;col<ncol;col++){
((short **)voidupperedgecosts)[0][col]=0;
}
}else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir
|| CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){
for(col=0;col<ncol;col++){
((bidircostT **)voidupperedgecosts)[0][col].posweight=0;
((bidircostT **)voidupperedgecosts)[0][col].negweight=0;
}
}else{
fflush(NULL);
fprintf(sp0,"Illegal cost mode in SetUpperEdge(). This is a bug.\n");
exit(ABNORMAL_EXIT);
}
}
return(0);
}
static
int SetLowerEdge(long nrow, long ncol, long tilerow, long tilecol,
void **voidcosts, void *voidcostsbelow,
float **unwphase, float *unwphasebelow,
void **voidloweredgecosts, short **loweredgeflows,
paramT *params, short **bulkoffsets){
long *flowhistogram;
long col, iflow, reloffset, nmax;
long flowlimhi, flowlimlo, maxflow, minflow, tempflow;
double dphi, dpsi;
costT **loweredgecosts, **costs, *costsbelow;
smoothcostT **loweredgesmoothcosts, **smoothcosts, *smoothcostsbelow;
long nshortcycle;
loweredgecosts=(costT **)voidloweredgecosts;
costs=(costT **)voidcosts;
costsbelow=(costT *)voidcostsbelow;
loweredgesmoothcosts=(smoothcostT **)voidloweredgecosts;
smoothcosts=(smoothcostT **)voidcosts;
smoothcostsbelow=(smoothcostT *)voidcostsbelow;
if(tilerow!=params->ntilerow-1){
nshortcycle=params->nshortcycle;
flowlimhi=LARGESHORT;
flowlimlo=-LARGESHORT;
flowhistogram=(long *)CAlloc(flowlimhi-flowlimlo+1,sizeof(long));
minflow=flowlimhi;
maxflow=flowlimlo;
for(col=0;col<ncol;col++){
dphi=(unwphase[nrow-1][col]-unwphasebelow[col])/TWOPI;
tempflow=(short )LRound(dphi);
loweredgeflows[0][col]=tempflow;
if(tempflow<minflow){
if(tempflow<flowlimlo){
fflush(NULL);
fprintf(sp0,"Overflow in tile offset\nAbort\n");
exit(ABNORMAL_EXIT);
}
minflow=tempflow;
}
if(tempflow>maxflow){
if(tempflow>flowlimhi){
fflush(NULL);
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(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){
loweredgecosts[0][col].offset=(short )LRound(nshortcycle*dpsi);
loweredgecosts[0][col].sigsq=AvgSigSq(costs[nrow-2][col].sigsq,
costsbelow[col].sigsq);
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].laycost<costsbelow[col].laycost){
loweredgecosts[0][col].laycost=costs[nrow-2][col].laycost;
}else{
loweredgecosts[0][col].laycost=costsbelow[col].laycost;
}
}else if(CalcCost==CalcCostSmooth){
loweredgesmoothcosts[0][col].offset=(short )LRound(nshortcycle*dpsi);
loweredgesmoothcosts[0][col].sigsq
=AvgSigSq(smoothcosts[nrow-2][col].sigsq,smoothcostsbelow[col].sigsq);
}else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1
|| CalcCost==CalcCostL2 || CalcCost==CalcCostLP){
((short **)voidloweredgecosts)[0][col]=
(((short **)voidcosts)[nrow-2][col]
+((short *)voidcostsbelow)[col])/2;
}else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir
|| CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){
((bidircostT **)voidloweredgecosts)[0][col].posweight=
(((bidircostT **)voidcosts)[nrow-2][col].posweight
+((bidircostT *)voidcostsbelow)[col].posweight)/2;
((bidircostT **)voidloweredgecosts)[0][col].negweight=
(((bidircostT **)voidcosts)[nrow-2][col].negweight
+((bidircostT *)voidcostsbelow)[col].negweight)/2;
}else{
fflush(NULL);
fprintf(sp0,"Illegal cost mode in SetLowerEdge(). This is a bug.\n");
exit(ABNORMAL_EXIT);
}
}
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;
for(col=0;col<ncol;col++){
loweredgeflows[0][col]-=reloffset;
}
free(flowhistogram);
}else{
if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){
for(col=0;col<ncol;col++){
loweredgecosts[0][col].offset=LARGESHORT/2;
loweredgecosts[0][col].sigsq=LARGESHORT;
loweredgecosts[0][col].dzmax=LARGESHORT;
loweredgecosts[0][col].laycost=0;
}
}else if(CalcCost==CalcCostSmooth){
for(col=0;col<ncol;col++){
loweredgesmoothcosts[0][col].offset=0;
loweredgesmoothcosts[0][col].sigsq=LARGESHORT;
}
}else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1
|| CalcCost==CalcCostL2 || CalcCost==CalcCostLP){
for(col=0;col<ncol;col++){
((short **)voidloweredgecosts)[0][col]=0;
}
}else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir
|| CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){
for(col=0;col<ncol;col++){
((bidircostT **)voidloweredgecosts)[0][col].posweight=0;
((bidircostT **)voidloweredgecosts)[0][col].negweight=0;
}
}else{
fflush(NULL);
fprintf(sp0,"Illegal cost mode in SetLowerEdge(). This is a bug.\n");
exit(ABNORMAL_EXIT);
}
}
return(0);
}
static
int SetLeftEdge(long nrow, long prevncol, long tilerow, long tilecol,
void **voidcosts, void **voidlastcosts, float **unwphase,
float **lastunwphase, void **voidleftedgecosts,
short **leftedgeflows, paramT *params, short **bulkoffsets){
long row, reloffset;
double dphi, dpsi;
costT **leftedgecosts, **costs, **lastcosts;
smoothcostT **leftedgesmoothcosts, **smoothcosts, **lastsmoothcosts;
long nshortcycle;
leftedgecosts=(costT **)voidleftedgecosts;
costs=(costT **)voidcosts;
lastcosts=(costT **)voidlastcosts;
leftedgesmoothcosts=(smoothcostT **)voidleftedgecosts;
smoothcosts=(smoothcostT **)voidcosts;
lastsmoothcosts=(smoothcostT **)voidlastcosts;
if(tilecol!=0){
nshortcycle=params->nshortcycle;
reloffset=bulkoffsets[tilerow][tilecol]-bulkoffsets[tilerow][tilecol-1];
for(row=0;row<nrow;row++){
dphi=(unwphase[row][0]
-lastunwphase[row][prevncol-1])/TWOPI;
leftedgeflows[row][0]=(short )LRound(dphi)-reloffset;
dpsi=dphi-floor(dphi);
if(dpsi>0.5){
dpsi-=1.0;
}
if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){
leftedgecosts[row][0].offset=(short )LRound(TILEDPSICOLFACTOR
*nshortcycle*dpsi);
leftedgecosts[row][0].sigsq
=AvgSigSq(costs[row+nrow-1][0].sigsq,
lastcosts[row+nrow-1][prevncol-2].sigsq);
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(CalcCost==CalcCostSmooth){
leftedgesmoothcosts[row][0].offset
=(short )LRound(TILEDPSICOLFACTOR*nshortcycle*dpsi);
leftedgesmoothcosts[row][0].sigsq
=AvgSigSq(smoothcosts[row+nrow-1][0].sigsq,
lastsmoothcosts[row+nrow-1][prevncol-2].sigsq);
}else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1
|| CalcCost==CalcCostL2 || CalcCost==CalcCostLP){
((short **)voidleftedgecosts)[row][0]=
(((short **)voidcosts)[row+nrow-1][0]
+((short **)voidlastcosts)[row+nrow-1][prevncol-2])/2;
}else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir
|| CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){
((bidircostT **)voidleftedgecosts)[row][0].posweight=
(((bidircostT **)voidcosts)[row+nrow-1][0].posweight
+((bidircostT **)voidlastcosts)[row+nrow-1][prevncol-2].posweight)
/2;
((bidircostT **)voidleftedgecosts)[row][0].negweight=
(((bidircostT **)voidcosts)[row+nrow-1][0].negweight
+((bidircostT **)voidlastcosts)[row+nrow-1][prevncol-2].negweight)
/2;
}else{
fflush(NULL);
fprintf(sp0,"Illegal cost mode in SetLeftEdge(). This is a bug.\n");
exit(ABNORMAL_EXIT);
}
}
}else{
if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){
for(row=0;row<nrow;row++){
leftedgecosts[row][0].offset=LARGESHORT/2;
leftedgecosts[row][0].sigsq=LARGESHORT;
leftedgecosts[row][0].dzmax=LARGESHORT;
leftedgecosts[row][0].laycost=0;
}
}else if(CalcCost==CalcCostSmooth){
for(row=0;row<nrow;row++){
leftedgesmoothcosts[row][0].offset=0;
leftedgesmoothcosts[row][0].sigsq=LARGESHORT;
}
}else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1
|| CalcCost==CalcCostL2 || CalcCost==CalcCostLP){
for(row=0;row<nrow;row++){
((short **)voidleftedgecosts)[row][0]=0;
}
}else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir
|| CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){
for(row=0;row<nrow;row++){
((bidircostT **)voidleftedgecosts)[row][0].posweight=0;
((bidircostT **)voidleftedgecosts)[row][0].negweight=0;
}
}else{
fflush(NULL);
fprintf(sp0,"Illegal cost mode in SetLeftEdge(). This is a bug.\n");
exit(ABNORMAL_EXIT);
}
}
return(0);
}
static
int SetRightEdge(long nrow, long ncol, long tilerow, long tilecol,
void **voidcosts, void **voidnextcosts,
float **unwphase, float **nextunwphase,
void **voidrightedgecosts, short **rightedgeflows,
paramT *params, short **bulkoffsets){
long *flowhistogram;
long row, iflow, reloffset, nmax;
long flowlimhi, flowlimlo, maxflow, minflow, tempflow;
double dphi, dpsi;
costT **rightedgecosts, **costs, **nextcosts;
smoothcostT **rightedgesmoothcosts, **smoothcosts, **nextsmoothcosts;
long nshortcycle;
rightedgecosts=(costT **)voidrightedgecosts;
costs=(costT **)voidcosts;
nextcosts=(costT **)voidnextcosts;
rightedgesmoothcosts=(smoothcostT **)voidrightedgecosts;
smoothcosts=(smoothcostT **)voidcosts;
nextsmoothcosts=(smoothcostT **)voidnextcosts;
if(tilecol!=params->ntilecol-1){
nshortcycle=params->nshortcycle;
flowlimhi=LARGESHORT;
flowlimlo=-LARGESHORT;
flowhistogram=(long *)CAlloc(flowlimhi-flowlimlo+1,sizeof(long));
minflow=flowlimhi;
maxflow=flowlimlo;
for(row=0;row<nrow;row++){
dphi=(nextunwphase[row][0]
-unwphase[row][ncol-1])/TWOPI;
tempflow=(short )LRound(dphi);
rightedgeflows[row][0]=tempflow;
if(tempflow<minflow){
if(tempflow<flowlimlo){
fflush(NULL);
fprintf(sp0,"Overflow in tile offset\nAbort\n");
exit(ABNORMAL_EXIT);
}
minflow=tempflow;
}
if(tempflow>maxflow){
if(tempflow>flowlimhi){
fflush(NULL);
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(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){
rightedgecosts[row][0].offset=(short )LRound(TILEDPSICOLFACTOR
*nshortcycle*dpsi);
rightedgecosts[row][0].sigsq
=AvgSigSq(costs[row+nrow-1][ncol-2].sigsq,
nextcosts[row+nrow-1][0].sigsq);
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(CalcCost==CalcCostSmooth){
rightedgesmoothcosts[row][0].offset
=(short )LRound(TILEDPSICOLFACTOR*nshortcycle*dpsi);
rightedgesmoothcosts[row][0].sigsq
=AvgSigSq(smoothcosts[row+nrow-1][ncol-2].sigsq,
nextsmoothcosts[row+nrow-1][0].sigsq);
}else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1
|| CalcCost==CalcCostL2 || CalcCost==CalcCostLP){
((short **)voidrightedgecosts)[row][0]=
(((short **)voidcosts)[row+nrow-1][ncol-2]
+((short **)voidnextcosts)[row+nrow-1][0])/2;
}else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir
|| CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){
((bidircostT **)voidrightedgecosts)[row][0].posweight=
(((bidircostT **)voidcosts)[row+nrow-1][ncol-2].posweight
+((bidircostT **)voidnextcosts)[row+nrow-1][ncol-2].posweight)/2;
((bidircostT **)voidrightedgecosts)[row][0].negweight=
(((bidircostT **)voidcosts)[row+nrow-1][ncol-2].negweight
+((bidircostT **)voidnextcosts)[row+nrow-1][ncol-2].negweight)/2;
}else{
fflush(NULL);
fprintf(sp0,"Illegal cost mode in SetRightEdge(). This is a bug.\n");
exit(ABNORMAL_EXIT);
}
}
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];
}
for(row=0;row<nrow;row++){
rightedgeflows[row][0]-=reloffset;
}
free(flowhistogram);
}else{
if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){
for(row=0;row<nrow;row++){
rightedgecosts[row][0].offset=LARGESHORT/2;
rightedgecosts[row][0].sigsq=LARGESHORT;
rightedgecosts[row][0].dzmax=LARGESHORT;
rightedgecosts[row][0].laycost=0;
}
}else if(CalcCost==CalcCostSmooth){
for(row=0;row<nrow;row++){
rightedgesmoothcosts[row][0].offset=0;
rightedgesmoothcosts[row][0].sigsq=LARGESHORT;
}
}else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1
|| CalcCost==CalcCostL2 || CalcCost==CalcCostLP){
for(row=0;row<nrow;row++){
((short **)voidrightedgecosts)[row][0]=0;
}
}else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir
|| CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){
for(row=0;row<nrow;row++){
((bidircostT **)voidrightedgecosts)[row][0].posweight=0;
((bidircostT **)voidrightedgecosts)[row][0].negweight=0;
}
}else{
fflush(NULL);
fprintf(sp0,"Illegal cost mode in SetRightEdge(). This is a bug.\n");
exit(ABNORMAL_EXIT);
}
}
return(0);
}
static
short AvgSigSq(short sigsq1, short sigsq2){
int sigsqavg;
if(sigsq1==LARGESHORT || sigsq2==LARGESHORT){
return(LARGESHORT);
}
sigsqavg=(int )ceil(0.5*(((int )sigsq1)+((int )sigsq2)));
sigsqavg=LClip(sigsqavg,-LARGESHORT,LARGESHORT);
return((short )sigsqavg);
}
static
int TraceSecondaryArc(nodeT *primaryhead, nodeT **scndrynodes,
nodesuppT **nodesupp, scndryarcT **scndryarcs,
long ***scndrycosts, long *nnewnodesptr,
long *nnewarcsptr, long tilerow, long tilecol,
long flowmax, long nrow, long ncol,
long prevnrow, long prevncol, paramT *params,
void **tilecosts, void **rightedgecosts,
void **loweredgecosts, void **leftedgecosts,
void **upperedgecosts, short **tileflows,
short **rightedgeflows, short **loweredgeflows,
short **leftedgeflows, short **upperedgeflows,
nodeT ***updatednontilenodesptr,
long *nupdatednontilenodesptr,
long *updatednontilenodesizeptr,
short **inontilenodeoutarcptr, long *totarclenptr){
long i, row, col, nnewnodes, arclen, ntilerow, ntilecol, arcnum;
long tilenum, nflow, primaryarcrow, primaryarccol, poscost, negcost, nomcost;
long nnrow, nncol, calccostnrow, nnewarcs, arroffset, nshortcycle;
long mincost, mincostflow, minweight, maxcost;
long *scndrycostarr;
double sigsq, sumsigsqinv, tempdouble, tileedgearcweight;
short **flows;
void **costs;
nodeT *tempnode, *primarytail, *scndrytail, *scndryhead;
nodeT *primarydummy, *scndrydummy;
nodesuppT *supptail, *supphead, *suppdummy;
scndryarcT *newarc;
signed char primaryarcdir, zerocost;
if(primaryhead->pred==NULL
|| (tilerow!=0 && primaryhead->row==0 && primaryhead->pred->row==0)
|| (tilecol!=0 && primaryhead->col==0 && primaryhead->pred->col==0)){
return(0);
}
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;
sigsq=0;
while(TRUE){
arclen=0;
sumsigsqinv=0;
for(nflow=1;nflow<=2*flowmax;nflow++){
scndrycostarr[nflow]=0;
}
primarytail=primaryhead->pred;
tempnode=primaryhead;
while(TRUE){
arclen++;
if(tempnode->col==primarytail->col+1){
primaryarcdir=1;
primaryarccol=primarytail->col;
if(primarytail->row==0){
if(tilerow==0){
zerocost=TRUE;
}else{
primaryarcrow=0;
costs=upperedgecosts;
flows=upperedgeflows;
calccostnrow=2;
}
}else if(primarytail->row==nnrow-1){
if(tilerow==ntilerow-1){
zerocost=TRUE;
}else{
primaryarcrow=0;
costs=loweredgecosts;
flows=loweredgeflows;
calccostnrow=2;
}
}else{
primaryarcrow=primarytail->row-1;
costs=tilecosts;
flows=tileflows;
calccostnrow=nrow;
}
}else if(tempnode->row==primarytail->row+1){
primaryarcdir=1;
if(primarytail->col==0){
if(tilecol==0){
zerocost=TRUE;
}else{
primaryarcrow=primarytail->row;
primaryarccol=0;
costs=leftedgecosts;
flows=leftedgeflows;
calccostnrow=0;
}
}else if(primarytail->col==nncol-1){
if(tilecol==ntilecol-1){
zerocost=TRUE;
}else{
primaryarcrow=primarytail->row;
primaryarccol=0;
costs=rightedgecosts;
flows=rightedgeflows;
calccostnrow=0;
}
}else{
primaryarcrow=primarytail->row+nrow-1;
primaryarccol=primarytail->col-1;
costs=tilecosts;
flows=tileflows;
calccostnrow=nrow;
}
}else if(tempnode->col==primarytail->col-1){
primaryarcdir=-1;
primaryarccol=primarytail->col-1;
if(primarytail->row==0){
if(tilerow==0){
zerocost=TRUE;
}else{
primaryarcrow=0;
costs=upperedgecosts;
flows=upperedgeflows;
calccostnrow=2;
}
}else if(primarytail->row==nnrow-1){
if(tilerow==ntilerow-1){
zerocost=TRUE;
}else{
primaryarcrow=0;
costs=loweredgecosts;
flows=loweredgeflows;
calccostnrow=2;
}
}else{
primaryarcrow=primarytail->row-1;
costs=tilecosts;
flows=tileflows;
calccostnrow=nrow;
}
}else{
primaryarcdir=-1;
if(primarytail->col==0){
if(tilecol==0){
zerocost=TRUE;
}else{
primaryarcrow=primarytail->row-1;
primaryarccol=0;
costs=leftedgecosts;
flows=leftedgeflows;
calccostnrow=0;
}
}else if(primarytail->col==nncol-1){
if(tilecol==ntilecol-1){
zerocost=TRUE;
}else{
primaryarcrow=primarytail->row-1;
primaryarccol=0;
costs=rightedgecosts;
flows=rightedgeflows;
calccostnrow=0;
}
}else{
primaryarcrow=primarytail->row+nrow-2;
primaryarccol=primarytail->col-1;
costs=tilecosts;
flows=tileflows;
calccostnrow=nrow;
}
}
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);
tempdouble=(scndrycostarr[nflow]+(poscost-nomcost));
if(tempdouble>LARGEINT){
scndrycostarr[nflow]=LARGEINT;
}else if(tempdouble<-LARGEINT){
scndrycostarr[nflow]=-LARGEINT;
}else{
scndrycostarr[nflow]+=(poscost-nomcost);
}
tempdouble=(scndrycostarr[nflow+flowmax]+(negcost-nomcost));
if(tempdouble>LARGEINT){
scndrycostarr[nflow+flowmax]=LARGEINT;
}else if(tempdouble<-LARGEINT){
scndrycostarr[nflow+flowmax]=-LARGEINT;
}else{
scndrycostarr[nflow+flowmax]+=(negcost-nomcost);
}
}
flows[primaryarcrow][primaryarccol]+=primaryarcdir*arroffset;
if(CalcCost==CalcCostTopo || CalcCost==CalcCostDefo){
sigsq=((costT **)costs)[primaryarcrow][primaryarccol].sigsq;
}else if(CalcCost==CalcCostSmooth){
sigsq=((smoothcostT **)costs)[primaryarcrow][primaryarccol].sigsq;
}else if(CalcCost==CalcCostL0 || CalcCost==CalcCostL1
|| CalcCost==CalcCostL2 || CalcCost==CalcCostLP){
minweight=((short **)costs)[primaryarcrow][primaryarccol];
if(minweight<1){
sigsq=LARGESHORT;
}else{
sigsq=1.0/(double )minweight;
}
}else if(CalcCost==CalcCostL0BiDir || CalcCost==CalcCostL1BiDir
|| CalcCost==CalcCostL2BiDir || CalcCost==CalcCostLPBiDir){
minweight=LMin(((bidircostT **)costs)[primaryarcrow][primaryarccol]
.posweight,
((bidircostT **)costs)[primaryarcrow][primaryarccol]
.negweight);
if(minweight<1){
sigsq=LARGESHORT;
}else{
sigsq=1.0/(double )minweight;
}
}
if(sigsq<LARGESHORT){
sumsigsqinv+=(1.0/sigsq);
}
}
if(primarytail->group==ONTREE){
break;
}
tempnode=primarytail;
primarytail=primarytail->pred;
}
if(zerocost){
break;
}
mincost=0;
maxcost=0;
mincostflow=0;
for(nflow=1;nflow<=flowmax;nflow++){
if(scndrycostarr[nflow]<mincost){
mincost=scndrycostarr[nflow];
mincostflow=nflow;
}
if(scndrycostarr[flowmax+nflow]<mincost){
mincost=scndrycostarr[flowmax+nflow];
mincostflow=-nflow;
}
if(scndrycostarr[nflow]>maxcost){
maxcost=scndrycostarr[nflow];
}
if(scndrycostarr[flowmax+nflow]>maxcost){
maxcost=scndrycostarr[flowmax+nflow];
}
}
if(maxcost==mincost){
zerocost=TRUE;
sumsigsqinv=0;
}
if(mincostflow==0){
break;
}
if(mincostflow==flowmax){
arroffset-=((long )floor(1.5*flowmax));
}else if(mincostflow==-flowmax){
arroffset+=((long )floor(1.5*flowmax));
}else{
arroffset-=mincostflow;
}
}
if(primaryhead==primarytail){
free(scndrycostarr);
return(0);
}
if(zerocost){
scndrycostarr[0]=0;
for(nflow=1;nflow<=2*flowmax;nflow++){
scndrycostarr[nflow]=0;
}
scndrycostarr[2*flowmax+1]=ZEROCOSTARC;
}else{
if((primaryhead->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>LARGEINT){
scndrycostarr[nflow]=LARGEINT;
}else if(tempdouble<-LARGEINT){
scndrycostarr[nflow]=-LARGEINT;
}else{
scndrycostarr[nflow]=LRound(tempdouble);
}
}
sumsigsqinv*=tileedgearcweight;
}
tempdouble=sumsigsqinv*nshortcycle*nshortcycle;
if(tempdouble<LARGEINT){
scndrycostarr[2*flowmax+1]=LRound(tempdouble);
}else{
scndrycostarr[2*flowmax+1]=LARGEINT;
}
scndrycostarr[0]=arroffset;
}
if(primarytail->row==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);
}
row=scndrytail->row;
col=scndrytail->col;
for(i=0;i<nodesupp[row][col].noutarcs;i++){
tempnode=nodesupp[row][col].neighbornodes[i];
if((nodesupp[row][col].outarcs[i]==NULL
&& tempnode->row==primaryhead->row
&& tempnode->col==primaryhead->col)
|| (nodesupp[row][col].outarcs[i]!=NULL
&& tempnode->row==scndryhead->row
&& tempnode->col==scndryhead->col)){
primarydummy=primaryhead->pred;
if(primarydummy->group!=ONTREE){
free(scndrycostarr);
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;
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{
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++;
}
free(scndrycosts[tilenum][arcnum]);
scndrycosts[tilenum][arcnum]=scndrycostarr;
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;
}
}
return(0);
}
}
nnewarcs=++(*nnewarcsptr);
if(nnewarcs > SHRT_MAX){
fflush(NULL);
fprintf(sp0,"Exceeded maximum number of secondary arcs\n"
"Decrease TILECOSTTHRESH and/or increase MINREGIONSIZE\n");
exit(ABNORMAL_EXIT);
}
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;
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;
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;
}
newarc->from=primarytail;
newarc->to=primaryhead;
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;
}
(*totarclenptr)+=arclen;
return(0);
}
static
nodeT *FindScndryNode(nodeT **scndrynodes, nodesuppT **nodesupp,
long tilenum, long primaryrow, long primarycol){
long nodenum;
nodesuppT *nodesuppptr;
nodesuppptr=nodesupp[tilenum];
nodenum=0;
while(nodesuppptr[nodenum].row!=primaryrow
|| nodesuppptr[nodenum].col!=primarycol){
nodenum++;
}
return(&scndrynodes[tilenum][nodenum]);
}
static
int IntegrateSecondaryFlows(long linelen, long nlines, nodeT **scndrynodes,
nodesuppT **nodesupp, scndryarcT **scndryarcs,
int *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];
memset(readtileparams,0,sizeof(tileparamT));
memset(readtileoutfiles,0,sizeof(outfileT));
memset(realoutfile,0,MAXSTRLEN);
memset(readfile,0,MAXSTRLEN);
memset(tempstring,0,MAXSTRLEN);
memset(path,0,MAXSTRLEN);
memset(basename,0,MAXSTRLEN);
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;
nrow=0;
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));
if(params->flipphasesign){
for(row=0;row<ntilerow;row++){
for(col=0;col<ntilecol;col++){
bulkoffsets[row][col]*=-1;
}
}
}
outfp=OpenOutputFile(outfiles->outfile,realoutfile);
for(tilerow=0;tilerow<ntilerow;tilerow++){
nextrowoffset=0;
for(tilecol=0;tilecol<ntilecol;tilecol++){
SetupTile(nlines,linelen,params,readtileparams,outfiles,
readtileoutfiles,tilerow,tilecol);
colstart=readtileparams->firstcol;
readtilenlines=readtileparams->nrow;
readtilelinelen=readtileparams->ncol;
SetTileReadParams(readtileparams,readtilenlines,readtilelinelen,
tilerow,tilecol,nlines,linelen,params);
colstart+=readtileparams->firstcol;
nrow=readtileparams->nrow;
ncol=readtileparams->ncol;
nnrow=nrow+1;
nncol=ncol+1;
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));
}
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));
if(params->rmtmptile){
unlink(readtileoutfiles->outfile);
unlink(readfile);
}
for(row=0;row<2*nrow+1;row++){
if(row<nrow){
maxcol=ncol;
}else{
maxcol=ncol+1;
}
for(col=0;col<maxcol;col++){
tileflows[row][col]=0;
}
}
tilenum=tilerow*ntilecol+tilecol;
ParseSecondaryFlows(tilenum,nscndryarcs,tileflows,regions,scndryflows,
nodesupp,scndryarcs,nrow,ncol,ntilerow,ntilecol,
params);
mag[0][colstart]=tilemag[0][0];
if(tilecol==0){
tileoffset=TWOPI*nextcoloffset;
}else{
tileoffset=TWOPI*nextrowoffset;
}
unwphase[0][colstart]=tileunwphase[0][0]+tileoffset;
for(col=1;col<ncol;col++){
mag[0][colstart+col]=tilemag[0][col];
unwphase[0][colstart+col]
=(float )((double )unwphase[0][colstart+col-1]
+(double )tileunwphase[0][col]
-(double )tileunwphase[0][col-1]
+tileflows[nnrow][col]*TWOPI);
}
if(tilecol!=ntilecol-1){
nextrowoffset=(LRound((unwphase[0][colstart+ncol-1]
-tileunwphase[0][ncol-1])/TWOPI)
+tileflows[nnrow][nncol-1]
+bulkoffsets[tilerow][tilecol]
-bulkoffsets[tilerow][tilecol+1]);
}
for(row=1;row<nrow;row++){
for(col=0;col<ncol;col++){
mag[row][colstart+col]=tilemag[row][col];
unwphase[row][colstart+col]
=(float )((double )unwphase[row-1][colstart+col]
+(double )tileunwphase[row][col]
-(double )tileunwphase[row-1][col]
-tileflows[row][col]*TWOPI);
}
}
if(tilecol==0 && tilerow!=ntilerow-1){
nextcoloffset=(LRound((unwphase[nrow-1][colstart]
-tileunwphase[nrow-1][0])/TWOPI)
-tileflows[nnrow-1][0]
+bulkoffsets[tilerow][tilecol]
-bulkoffsets[tilerow+1][tilecol]);
}
}
for(row=0;row<nrow;row++){
if(outfiles->outfileformat==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;col<linelen;col++){
outline[2*col]=mag[row][col];
outline[2*col+1]=unwphase[row][col];
}
if(fwrite(outline,sizeof(float),2*linelen,outfp)!=2*linelen){
writeerror=TRUE;
break;
}
}else{
if(fwrite(unwphase[row],sizeof(float),linelen,outfp)!=linelen){
writeerror=TRUE;
break;
}
}
}
if(writeerror){
fflush(NULL);
fprintf(sp0,"Error while writing to file %s (device full?)\nAbort\n",
realoutfile);
exit(ABNORMAL_EXIT);
}
}
fprintf(sp1,"Output written to file %s\n",realoutfile);
if(fclose(outfp)){
fflush(NULL);
fprintf(sp0,"WARNING: problem closing file %s (disk full?)\n",realoutfile);
}
Free2DArray((void **)regions,ni);
Free2DArray((void **)tileflows,ni);
Free2DArray((void **)tileunwphase,ni);
Free2DArray((void **)tilemag,ni);
Free2DArray((void **)unwphase,ni);
Free2DArray((void **)mag,ni);
free(outline);
return(0);
}
static
int ParseSecondaryFlows(long tilenum, int *nscndryarcs, short **tileflows,
short **regions, short **scndryflows,
nodesuppT **nodesupp, scndryarcT **scndryarcs,
long nrow, long ncol, long ntilerow, long ntilecol,
paramT *params){
nodeT *scndryfrom, *scndryto;
long arcnum, nnrow, nncol, nflow, primaryfromrow, primaryfromcol;
long prevrow, prevcol, thisrow, thiscol, nextrow, nextcol;
signed char phaseflipsign;
if(params->flipphasesign){
phaseflipsign=-1;
}else{
phaseflipsign=1;
}
for(arcnum=0;arcnum<nscndryarcs[tilenum];arcnum++){
nflow=phaseflipsign*scndryflows[tilenum][arcnum];
if(nflow){
nnrow=nrow+1;
nncol=ncol+1;
scndryfrom=scndryarcs[tilenum][arcnum].from;
scndryto=scndryarcs[tilenum][arcnum].to;
if(scndryfrom->row==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;
}
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;
}
while(!(nextrow==primaryfromrow && nextcol==primaryfromcol)){
prevrow=thisrow;
prevcol=thiscol;
thisrow=nextrow;
thiscol=nextcol;
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++;
}
}
}
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++;
}
}
}
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--;
}
}
}
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--;
}
}
}
}
}
}
return(0);
}
static
int AssembleTileConnComps(long linelen, long nlines,
outfileT *outfiles, paramT *params){
int ipass;
long k;
long row, col, colstart, nrow, ncol;
long readtilelinelen, readtilenlines;
long tilerow, tilecol, ntilerow, ntilecol, rowovrlp, colovrlp;
long ni, nj, tilenum;
unsigned int iconncomp, iconncompmax;
long ntileconncomp, nconncomp;
long ntileconncompmem, nconncompmem, nmemold;
char realoutfile[MAXSTRLEN], readfile[MAXSTRLEN], tempstring[MAXTMPSTRLEN];
char path[MAXSTRLEN], basename[MAXSTRLEN];
signed char writeerror;
tileparamT readtileparams[1];
outfileT readtileoutfiles[1];
unsigned int *tilemapping;
unsigned int **tileconncomps, **tilerowconncomps;
unsigned char **ucharbuf;
unsigned char *ucharoutbuf;
conncompsizeT *tileconncompsizes, *conncompsizes;
FILE *outfp;
memset(readtileparams,0,sizeof(tileparamT));
memset(readtileoutfiles,0,sizeof(outfileT));
memset(realoutfile,0,MAXSTRLEN);
memset(readfile,0,MAXSTRLEN);
memset(tempstring,0,MAXSTRLEN);
memset(path,0,MAXSTRLEN);
memset(basename,0,MAXSTRLEN);
fprintf(sp1,"Assembling tile connected components\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);
writeerror=FALSE;
nrow=0;
conncompsizes=NULL;
nconncomp=0;
nconncompmem=0;
tileconncompsizes=NULL;
ntileconncompmem=0;
iconncompmax=0;
tileconncomps=(unsigned int **)Get2DMem(ni,nj,sizeof(unsigned int *),
sizeof(unsigned int));
tilerowconncomps=(unsigned int **)Get2DMem(ni,linelen,sizeof(unsigned int *),
sizeof(unsigned int));
ucharbuf=(unsigned char **)Get2DMem(ni,nj,sizeof(unsigned char *),
sizeof(unsigned char));
ucharoutbuf=(unsigned char *)MAlloc(linelen*sizeof(unsigned char));
tilemapping=NULL;
outfp=OpenOutputFile(outfiles->conncompfile,realoutfile);
for(ipass=0;ipass<2;ipass++){
for(tilerow=0;tilerow<ntilerow;tilerow++){
for(tilecol=0;tilecol<ntilecol;tilecol++){
SetupTile(nlines,linelen,params,readtileparams,outfiles,
readtileoutfiles,tilerow,tilecol);
colstart=readtileparams->firstcol;
readtilenlines=readtileparams->nrow;
readtilelinelen=readtileparams->ncol;
SetTileReadParams(readtileparams,readtilenlines,readtilelinelen,
tilerow,tilecol,nlines,linelen,params);
colstart+=readtileparams->firstcol;
nrow=readtileparams->nrow;
ncol=readtileparams->ncol;
tilenum=tilerow*ntilecol+tilecol;
if(params->conncompouttype==CONNCOMPOUTTYPEUCHAR){
Read2DArray((void ***)&ucharbuf,readtileoutfiles->conncompfile,
readtilelinelen,readtilenlines,readtileparams,
sizeof(unsigned char *),sizeof(unsigned char));
for(row=0;row<nrow;row++){
for(col=0;col<ncol;col++){
tileconncomps[row][col]=(unsigned int )ucharbuf[row][col];
}
}
}else{
Read2DArray((void ***)&tileconncomps,readtileoutfiles->conncompfile,
readtilelinelen,readtilenlines,readtileparams,
sizeof(unsigned int *),sizeof(unsigned int));
}
if(ipass==0){
ntileconncomp=0;
for(k=0;k<ntileconncompmem;k++){
tileconncompsizes[k].tilenum=tilenum;
tileconncompsizes[k].icomptile=k+1;
tileconncompsizes[k].icompfull=0;
tileconncompsizes[k].npix=0;
}
for(row=0;row<nrow;row++){
for(col=0;col<ncol;col++){
iconncomp=tileconncomps[row][col];
if(iconncomp>0){
while(iconncomp>ntileconncompmem){
nmemold=ntileconncompmem;
ntileconncompmem+=CONNCOMPMEMINCR;
tileconncompsizes
=(conncompsizeT *)ReAlloc(tileconncompsizes,
(ntileconncompmem
*sizeof(conncompsizeT)));
for(k=nmemold;k<ntileconncompmem;k++){
tileconncompsizes[k].tilenum=tilenum;
tileconncompsizes[k].icomptile=k+1;
tileconncompsizes[k].icompfull=0;
tileconncompsizes[k].npix=0;
}
}
if(tileconncompsizes[iconncomp-1].npix==0){
tileconncompsizes[iconncomp-1].icomptile=iconncomp;
ntileconncomp++;
}
tileconncompsizes[iconncomp-1].npix++;
if(iconncomp>iconncompmax){
iconncompmax=iconncomp;
}
}
}
}
nmemold=nconncompmem;
if(ntileconncomp>0){
nconncompmem+=ntileconncomp;
conncompsizes=(conncompsizeT *)ReAlloc(conncompsizes,
(nconncompmem
*sizeof(conncompsizeT)));
}
for(k=0;k<ntileconncompmem;k++){
if(tileconncompsizes[k].npix>0){
conncompsizes[nconncomp].tilenum=tileconncompsizes[k].tilenum;
conncompsizes[nconncomp].icomptile=tileconncompsizes[k].icomptile;
conncompsizes[nconncomp].icompfull=0;
conncompsizes[nconncomp].npix=tileconncompsizes[k].npix;
nconncomp++;
}
}
}else{
for(k=0;k<iconncompmax;k++){
tilemapping[k]=0;
}
for(k=0;k<nconncomp;k++){
if(conncompsizes[k].tilenum==tilenum){
iconncomp=conncompsizes[k].icomptile;
tilemapping[iconncomp-1]=conncompsizes[k].icompfull;
}
}
for(row=0;row<nrow;row++){
for(col=0;col<ncol;col++){
iconncomp=tileconncomps[row][col];
if(iconncomp>0){
tilerowconncomps[row][colstart+col]=tilemapping[iconncomp-1];
}else{
tilerowconncomps[row][colstart+col]=0;
}
}
}
if(params->rmtmptile){
unlink(readtileoutfiles->conncompfile);
}
}
}
if(ipass>0){
for(row=0;row<nrow;row++){
if(params->conncompouttype==CONNCOMPOUTTYPEUCHAR){
for(k=0;k<linelen;k++){
ucharoutbuf[k]=(unsigned char)tilerowconncomps[row][k];
}
if(fwrite(ucharoutbuf,sizeof(unsigned char),linelen,outfp)
!=linelen){
writeerror=TRUE;
break;
}
}else{
if(fwrite(tilerowconncomps[row],
sizeof(unsigned int),linelen,outfp)!=linelen){
writeerror=TRUE;
break;
}
}
}
if(writeerror){
fflush(NULL);
fprintf(sp0,"Error while writing to file %s (device full?)\nAbort\n",
realoutfile);
exit(ABNORMAL_EXIT);
}
}
}
if(ipass==0){
qsort(conncompsizes,nconncomp,sizeof(conncompsizeT),
ConnCompSizeNPixCompare);
if(nconncomp>params->maxncomps){
nconncomp=params->maxncomps;
}
for(k=0;k<nconncomp;k++){
conncompsizes[k].icompfull=k+1;
}
tilemapping=(unsigned int *)MAlloc(iconncompmax*sizeof(unsigned int));
}
}
fprintf(sp1,"Assembled connected components (%ld) output written to file %s\n",
nconncomp,realoutfile);
if(fclose(outfp)){
fflush(NULL);
fprintf(sp0,"WARNING: problem closing file %s (disk full?)\n",
realoutfile);
}
Free2DArray((void **)tileconncomps,ni);
Free2DArray((void **)tilerowconncomps,ni);
Free2DArray((void **)ucharbuf,ni);
free(ucharoutbuf);
if(ntileconncompmem>0){
free(tileconncompsizes);
}
if(nconncompmem>0){
free(conncompsizes);
}
free(tilemapping);
return(0);
}
static
int ConnCompSizeNPixCompare(const void *ptr1, const void *ptr2){
return(((conncompsizeT *)ptr2)->npix-((conncompsizeT *)ptr1)->npix);
}