Пример #1
0
static void ConvertToREAL4( size_t nrCells, void *buf, CSF_CR src)
{
	size_t i;

	i = (size_t)nrCells;

	if (IS_SIGNED(src))
	{
		POSTCOND(src == CR_INT4);
		INT4tREAL4(nrCells, buf);
	}
	else
	{
		POSTCOND(src == CR_UINT4);
		{
			do {
				i--;
				if ( ((UINT4 *)buf)[i] == MV_UINT4 )
					((UINT4 *)buf)[i] = MV_UINT4;
				else
					((REAL4 *)buf)[i] = (REAL4)((UINT4 *)buf)[i];
			    }
			while(i != 0);
		}
	}
}
Пример #2
0
static int BuildEllipse2(REAL8 xmajor_a, REAL8 yminor_b, REAL8 angle)
{
	int i,nrLines,xCeil;
	int lineStart,lineEndIncl;
	REAL8 xIncr,c=cos(angle),s=sin(angle);
	HOR_CUT_LINE *l;
	PRECOND(xmajor_a != 0);
	PRECOND(yminor_b != 0);
	xmajor_a /= Side();
	yminor_b /= Side();

	xCeil = (size_t)ceil(xmajor_a);
	nrLines = (xCeil*2)+1;
	l = (HOR_CUT_LINE *)ChkMalloc(sizeof(HOR_CUT_LINE)*nrLines);
	for(i=0; i < nrLines; i++) {
		/* mark not initialized */
		SET_MV_REAL4(&(l[i].start.f));
	}

	for (xIncr = 0; xIncr < xCeil; xIncr+=1) {
	 REAL8 y = sqrt( fabs(1-(sqr(xIncr)/sqr(xmajor_a)))*sqr(yminor_b));
	 Add2Lines(l,nrLines,xCeil,c,s, xIncr, y);
	 Add2Lines(l,nrLines,xCeil,c,s, xIncr,-y);
	 Add2Lines(l,nrLines,xCeil,c,s,-xIncr, y);
	 Add2Lines(l,nrLines,xCeil,c,s,-xIncr,-y);
	}
	if (0) {
	 REAL8 y;
	 xIncr = xmajor_a;
	 y = sqrt( fabs(1-(sqr(xIncr)/sqr(xmajor_a)))*sqr(yminor_b));
	 Add2Lines(l,nrLines,xCeil,c,s, xIncr, y);
	 Add2Lines(l,nrLines,xCeil,c,s, xIncr,-y);
	 Add2Lines(l,nrLines,xCeil,c,s,-xIncr, y);
	 Add2Lines(l,nrLines,xCeil,c,s,-xIncr,-y);
	}

	for(i=0; i < nrLines; i++) {
		/* mark not initialized */
		if (!IS_MV_REAL4(&(l[i].start.f)))
			break;
	}
	POSTCOND(i < nrLines);
	lineStart = i;
	for(i = nrLines-1; i >=0;i--) {
		/* mark not initialized */
		if (!IS_MV_REAL4(&(l[i].start.f)))
			break;
	}
	POSTCOND(i >= 0);
	lineEndIncl = i;
	
	for (i=lineStart ; i <= lineEndIncl; i++) {
		PRECOND(!IS_MV_REAL4(&(l[i].start.f)));
		l[i].start.i = (int)Rint(l[i].start.f);
		l[i].end.i   = (int)Rint(l[i].end.f);
	}
	return 1;
}
Пример #3
0
static void ConvertToINT4( size_t nrCells, void *buf, CSF_CR src)
{
	if (IS_SIGNED(src))
	{
		POSTCOND(src == CR_INT2);
		CONV_SMALL_TO_BIG(nrCells,buf, INT4, INT2);
	}
	else  
	{
		POSTCOND(src == CR_UINT2);
		CONV_SMALL_TO_BIG(nrCells,buf, INT4, UINT2);
	}
}
Пример #4
0
int tree_add_right(tree* my_tree, tree* adding)
{
	assert(my_tree != NULL);
	assert(adding != NULL);

	PRECOND(tree_check(my_tree -> head -> root, NULL) != TREE_CHECK_OK, TREE_BAD, "ADD LEFT ERROR: PRECONDITION FAILED\n");
	int tr_counter = 0;
	VERIFY1(tree_check(my_tree, &tr_counter) == TREE_CHECK_BAD, TREE_INJURED,	"# ADD RIGHT ERROR: [%08x] element, tree is broken\n", my_tree);
	tr_counter = 0;
	VERIFY1(tree_check(adding,  &tr_counter) == TREE_CHECK_BAD, TREE_ADD_INJURED,"# ADD RIGHT ERROR: [%08x] adding element, tree is broken\n", adding);

	if (my_tree -> right != NULL) return TREE_ALREADY_THERE;
	my_tree -> right = adding;
	
	if (adding -> papa != NULL)
	{
		if (adding -> papa -> left  == adding) adding -> papa -> left  = NULL;
		if (adding -> papa -> right == adding) adding -> papa -> right = NULL;
	}
	adding -> papa = my_tree;
	adding -> head = my_tree -> head;
	adding -> head -> size += tr_counter;
	assert(my_tree -> head);
	tree_save_head(adding, my_tree -> head);
	POSTCOND(tree_check(my_tree -> head -> root, NULL) != TREE_CHECK_OK, TREE_BAD, "ADD LEFT ERROR: POSTCONDITION FAILED\n");
	return TREE_OK;
}
Пример #5
0
static void Transform2(
	size_t nrCells,
	void  *buf,
	CSF_CR destCellRepr, /* the output representation */
	CSF_CR currCellRepr)  /* at start of while this is the representation
				read in the MAP-file */
{
  /* subsequent looping changes the to the new
   * converted type
   */
	while(currCellRepr != destCellRepr)
	{
		switch(currCellRepr)
		{
			case CR_INT1:    ConvertToINT2(nrCells, buf,
						currCellRepr);
					currCellRepr = CR_INT2;
					break;
			case CR_INT2:    ConvertToINT4(nrCells, buf, 
						currCellRepr);
					currCellRepr = CR_INT4;
					break;
			case CR_INT4:    ConvertToREAL4(nrCells, buf,
						currCellRepr);
					currCellRepr = CR_REAL4;
					break;
			case CR_UINT1: 	if (IS_SIGNED(destCellRepr))
					{
						ConvertToINT2(nrCells, buf,
							currCellRepr);
						currCellRepr = CR_INT2;
					}
					else
					{
						UINT1tUINT2(nrCells, buf);
						currCellRepr = CR_UINT2;
					}
					break;
			case CR_UINT2:   if (destCellRepr == CR_INT4)
					{
						ConvertToINT4(nrCells, buf,
							currCellRepr);
					 	currCellRepr = CR_INT4;
					 }
					 else
					 {
						UINT2tUINT4(nrCells, buf);
						currCellRepr = CR_UINT4;
					 }
					 break;
			case CR_UINT4:   ConvertToREAL4(nrCells, buf,
						currCellRepr);
					currCellRepr = CR_REAL4;
					break;
			default       :	POSTCOND(currCellRepr == CR_REAL4);
					REAL4tREAL8(nrCells, buf);
					currCellRepr = CR_REAL8;
		}
	}
}
Пример #6
0
/* Drains down from each nonzero point.
 * If one of the neighbors has a MV it will get a MV as output as well.
 * All of the lowest neighbors get an extra input from current cell.
 * Returns 1 if memory allocation fails, 0 otherwise.
 */
 static REAL8 DoDrain(
 		MAP_REAL8 *out,		 /* read-write output map */
 		const MAP_REAL8 *dem,	 /* dem map  */	
 		const MAP_REAL8 *points, /* points map  */	
 		int r,			 /* current cell row number */
 		int c)			 /* current cell column nr. */
{
	NODE 	*list = NULL;
	REAL8 	pntVal;			/* value in points.map */
	REAL8 	drainVal;		/* total value to drain down */

	PRECOND(points->Get(&pntVal, r, c, points));

	points->Get(&pntVal, r, c, points);
	list = LinkChkReal(list, r, c, pntVal);
	while(list != NULL)
	{
		int rowNr = list->rowNr;
		int colNr = list->colNr;
		drainVal = list->val.Real;
		list = RemFromList(list);
		if(HasLowerNeighbor(dem, points, rowNr, colNr))
		{	
			list = DoNeighbors(out, list, dem, points,
						rowNr, colNr, drainVal);
			if(list == NULL)
	  			return 1;
		}	
	}
	POSTCOND(list == NULL);
	return 0;
}
Пример #7
0
/* vfprintf-flavour of ErrorNested()
 * See ErrorNested() for full documentation.
 */
void vfErrorNested(
	const char *fmt,  /* Format control, see printf() for a description */
	va_list marker )             /* Optional arguments */
{
        char *buf;

        PRECOND (errorNestLevel < 15);

        if (!errorNestLevel)
	{ /* reset bufs */
	  errorBuf[0] = '\0';
	  ptrs[errorNestLevel] = errorBuf;
	}
	buf = ptrs[errorNestLevel];

        /* print message in buf */
        (void)vsprintf(buf, fmt, marker );

        /* remove leading and trailing space and newlines 
         */
        (void)LeftRightTrim(buf);

	ptrs[errorNestLevel+1] = ptrs[errorNestLevel]+strlen(buf)+1;
	errorNestLevel++;
	POSTCOND(ptrs[errorNestLevel] < errorBuf+BUF_SIZE);
}
Пример #8
0
/* insert a record in a sorted array with unique ids
 * InsertSorted copies key to the appropriate place, moving
 * other elements if necessary. Therefore the array must
 * have space for one more element. NOTE that no records,
 * including the key (the new one),
 * must be equal (all unique id's)
 * returns the copied record (part of array)
 */
static void *InsertSorted(
 const void *key,    /* key to be inserted */
       void *base,   /* array of num+1 elements
                      * with element num being vacant
                      */
       size_t num,   /* number of elements initially in
                      * base
                      */
       size_t width, /* sizeof element */
       QSORT_CMP cmp)/* comparisson function */
{
 int x=0; /* num == 0 case */
 int c,l=0;
 int r=num-1;
 if (num == 0)
   goto done;
 do {
      x = (l+r)/2;
      if ( (c = cmp(key, ((char *)base)+(x*width))) < 0)
       r = x-1;
      else
       l = x+1;
       } while (( c != 0) && l <= r );
       POSTCOND(c != 0); /* NOT FOUND */
       if (c > 0)
           x++; /* insertion point is after x */
       PRECOND(x <= (int)num);
       if (x != (int)num) /* no memmove if insertion point is at end */
        /* move part of array after insertion point 1 to the right */
        (void)memmove( (((char *)base)+((x+1)*width)),
          (((char *)base)+(x*width)),
          (num-x)*width );
done:
       return memcpy((((char *)base)+(x*width)), key, width);
}
Пример #9
0
/* set a memory location to a missing value
 * SetMVcellRepr sets a memory location to a missing value
 * (using the application cell representation).
 * In general one should use assignment for
 * integers (e.g. v = MV_UINT1) or the macro's
 * SET_MV_REAL4 and SET_MV_REAL8
 *
 */
void SetMVcellRepr(
	CSF_CR cellRepr, /* cell representation, one of the CR_* constants */
	void *c)      /* write-only. location set to missing value */
{
	switch (cellRepr)
	{
		case CR_INT1  : *((INT1 *)c) = MV_INT1;
				break;
		case CR_INT2  : *((INT2 *)c) = MV_INT2;
				break;
		case CR_INT4  : *((INT4 *)c) = MV_INT4;
				break;
		case CR_UINT1 : *((UINT1 *)c) = MV_UINT1;
				break;
		case CR_UINT2 : *((UINT2 *)c) = MV_UINT2;
				break;
		case CR_REAL8 :
				((UINT4 *)c)[1] = MV_UINT4;
		default       : POSTCOND(
					cellRepr == CR_REAL8 ||
					cellRepr == CR_REAL4 ||
					cellRepr == CR_UINT4 );
				*((UINT4 *)c) = MV_UINT4;
	}
} 
Пример #10
0
static int BuildCircle(REAL8 radius)
{
	int i,nrLines,xFloor;
	REAL8 xIncr,lineStart,lineEndIncl;
	HOR_CUT_LINE *l;
	PRECOND(radius != 0);
	radius /= (Side()*2);

	xFloor = (size_t)floor(radius);
	radius *= radius;
	nrLines = (xFloor*2)+1;
	l = (HOR_CUT_LINE *)ChkMalloc(sizeof(HOR_CUT_LINE)*nrLines);
	for(i=0; i < nrLines; i++) {
		/* mark not initialized */
		SET_MV_REAL4(&(l[i].start.f));
	}

	for (xIncr = 0; xIncr <= xFloor; xIncr+=1) {
	 REAL8 y = floor(sqrt(radius-sqr(xIncr))); 
	 Add2Lines(l,nrLines,xFloor,1,0, xIncr, y);
	 Add2Lines(l,nrLines,xFloor,1,0, xIncr,-y);
	 Add2Lines(l,nrLines,xFloor,1,0,-xIncr, y);
	 Add2Lines(l,nrLines,xFloor,1,0,-xIncr,-y);
	}
	for(i=0; i < nrLines; i++) {
		/* mark not initialized */
		if (!IS_MV_REAL4(&(l[i].start.f)))
			break;
	}
	POSTCOND(i < nrLines);
	lineStart = i;
	for(i = nrLines-1; i >=0;i--) {
		/* mark not initialized */
		if (!IS_MV_REAL4(&(l[i].start.f)))
			break;
	}
	POSTCOND(i >= 0);
	lineEndIncl = i;
	
	for (i=(int)lineStart ; i <= (int)lineEndIncl; i++) {
		PRECOND(!IS_MV_REAL4(&(l[i].start.f)));
		l[i].start.i = (int)Rint(l[i].start.f);
		l[i].end.i   = (int)Rint(l[i].end.f);
	}
	return 1;
}
Пример #11
0
/* remove map from run time structure (LIBRARY_INTERNAL)
 * The map handle will become invalid.
 */
void CsfUnloadMap(
  MAP *m) /* map handle */
{
  POSTCOND(CsfIsValidMap(m));

  mapList[m->mapListId] = NULL;
  m->mapListId = -1;
}
Пример #12
0
int tree_burn(tree* my_tree, int type, ...)
{
	PRECOND(my_tree == NULL,		TREE_ARG_TREE_NULL,	"TREE INIT: argumented head pointer is NULL\n");
	//PRECOND((my_tree -> type != TR_NONE)||(my_tree -> value != NULL), TREE_BAD, "TREE UNIT: tree has been already initialized");
	int _size = 0;
	VERIFY(tree_check(my_tree, &_size) != TREE_CHECK_OK, TREE_BAD, "TREE INIT: Initialization failed, tree is not ok");
	va_list vl;
	va_start(vl, type);
	char* str = NULL;
	double val = 0;
	int int_val = 0;
	if (my_tree -> value)
	{
		DBG_FREE fprintf(stdout, "[%08x] tree.cpp, tree_burn, my_tree -> value\n", my_tree -> value);
		free(my_tree -> value);
		my_tree -> value = NULL;
	}

	switch (type)
	{
	case TR_V:
	case TR_STR:
	case TR_F:
		str = va_arg(vl, char*);
		VERIFY(strlen(str) >= MAXLINE, TREE_BAD, "TREE INIT: Argumented string is out of range");
		my_tree -> value = (void*)calloc(strlen(str) + 2, sizeof(char));
		assert(my_tree -> value);
		strcpy((char*)(my_tree -> value), str);

		break;
	case TR_N:
		val = va_arg(vl, double);
		my_tree -> value = (void*) calloc(1, sizeof(double));
		assert(my_tree -> value);
		*((double*)(my_tree -> value)) = val;
		break;
	case TR_SIGN:
	case TR_ASSN:
	case TR_CMP:
		int_val = va_arg(vl, int);
		my_tree -> value = (void*) calloc(1, sizeof(int));
		assert(my_tree -> value);
		*((int*)(my_tree -> value)) = int_val;
		break;
	default:
		break;
	}

	my_tree -> type = type;

	_size = 0;
	
	va_end(vl);
	POSTCOND(tree_check(my_tree, &_size) != TREE_CHECK_OK, TREE_BAD, "TREE INIT: Initialization failed, tree is not ok in the end");
	return TREE_OK;
}
Пример #13
0
/* boot the CSF runtime library (LIBRARY_INTERNAL)
 * CsfBootCsfKernel creates the mapList and adds the function to
 *  close all files at a system exit
 *
 * NOTE
 * Note that CsfBootCsfKernel never returns if there isn't enough
 * memory to allocate an array of mapListLen pointers, or if
 * the atexit() call fails
 */
void CsfBootCsfKernel(void)
{
  POSTCOND(mapList == NULL);

  mapList = (MAP **)calloc(mapListLen,sizeof(MAP *));
  if (mapList == NULL) {
    (void)fprintf(stderr,"CSF_INTERNAL_ERROR: Not enough memory to use CSF-files\n");
    exit(1);
  }

  if (atexit(CsfCloseCsfKernel)) {
    (void)fprintf(stderr,"CSF_INTERNAL_ERROR: Impossible to close CSF-files automatically at exit\n");
    exit(1);
  }
}
Пример #14
0
/* read an attribute (LIBRARY_INTERNAL)
 * MgetAttribute reads an attribute if it is available.
 * Be aware that you can't pass a simple pointer to some 
 * (array of) structure(s) due to alignment en endian problems.
 * At some time there will be a separate get function for each attribute
 * returns 0 if the attribute is not found, arg id if
 * the attribute is found.
 */
CSF_ATTR_ID CsfGetAttribute(
	 MAP *m, /* map handle */
	 CSF_ATTR_ID id, /* id of attribute to be read */
	 size_t  elSize, /* size of each data-element */
	 size_t *nmemb, /* write-only. How many elSize members are read. */
	 void  *attr) /* write-only. buffer where attribute is read in.
	               * Must be big enough to hold buffer.
	               */
{
	ATTR_CNTRL_BLOCK b;
	CSF_FADDR pos;
	PRECOND(CsfValidSize(elSize));
	CHECKHANDLE_GOTO(m, error);

	if (! READ_ENABLE(m))
	{
		M_ERROR(NOACCESS);
		goto error;
	}

	if (CsfGetAttrBlock(m, id, &b) != 0) 
	{
		int i = CsfGetAttrIndex(id, &b);
		*nmemb =	b.attrs[i].attrSize;
		POSTCOND( ((*nmemb) % elSize) == 0);
		*nmemb /= elSize;
		POSTCOND( (*nmemb) > 0);
		pos =	b.attrs[i].attrOffset;
		(void)fseek(m->fp, (long)pos, SEEK_SET); 
		m->read(attr,elSize, (size_t)(*nmemb),m->fp);
		return(id);
	}
	else 
		*nmemb = 0;
error:	return(0);	/* not available  or an error */
} /* MgetAttribute */
Пример #15
0
/* compute (xUL,yUL) and nrRows, nrCols from some coordinates
 * RcomputeExtend computes parameters to create a raster maps
 * from minimum and maximum x and y coordinates, projection information,
 * cellsize and units. The resulting parameters are computed that the 
 * smallest raster map can be created that will include the two 
 * coordinates given, assuming a default angle of 0.
 * Which coordinates are the maximum or minimum are
 * determined by the function itself.
 */
void RcomputeExtend(
	REAL8 *xUL,     /* write-only, resulting xUL */
	REAL8 *yUL,     /* write-only, resulting yUL */
	size_t *nrRows, /* write-only, resulting nrRows */
	size_t *nrCols, /* write-only, resulting nrCols */
	double x_1,      /* first x-coordinate */ 
	double y_1,      /* first y-coordinate */
	double x_2,      /* second x-coordinate */
	double y_2,      /* second y-coordinate */
	CSF_PT projection, /* required projection */
	REAL8 cellSize, /* required cellsize, > 0 */
	double rounding) /* assure that (xUL/rounding), (yUL/rouding)
	                  * (xLL/rounding) and (yLL/rounding) will
	                 * will all be an integers values > 0 
	                 */
{
    /*
     * xUL ______
	   |    |
	   |    |
	   |    |
	   ------

     */
	double yLL,xUR = x_1 > x_2 ? x_1 : x_2;
	*xUL = x_1 < x_2 ? x_1 : x_2;
	*xUL = RoundDown(*xUL, rounding); /* Round down */
	xUR  = RoundUp(   xUR, rounding); /* Round up */
	POSTCOND(*xUL <= xUR);
	*nrCols = (size_t)ceil((xUR - *xUL)/cellSize);
	if (projection == PT_YINCT2B)
	{
		 yLL = y_1 > y_2 ? y_1 : y_2;  /* highest value at bottom */
		*yUL = y_1 < y_2 ? y_1 : y_2;  /* lowest value at top */
	        *yUL = RoundDown(*yUL, rounding);
	         yLL = RoundUp(   yLL, rounding);
	}
	else
	{
		 yLL = y_1 < y_2 ? y_1 : y_2;  /* lowest value at bottom */
		*yUL = y_1 > y_2 ? y_1 : y_2;  /* highest value at top */
	        *yUL = RoundUp(  *yUL, rounding);
	         yLL = RoundDown( yLL, rounding);
	}
	*nrRows = (size_t)ceil(fabs(yLL - *yUL)/cellSize);
}
Пример #16
0
static int QuickSort(INT4 partToSort,
                     INT4 nrCells,
                     const MAP_REAL8 *in, /* Read-write input map */
                     MAP_INT4 *tmp)       /* read-write index temporary map */
{
    int left = partToSort;
    int right = nrCells - 1;
    int i, pointer = 2;
    int *stack = NULL; /*  contains partitions to do */
    /* Perform quicksort on the tmp map and to modify the output map
     * later. 
     */
    do {
        if (right > left) {
            i = Partition(tmp, in, left, right);
            if (ChkReallocFree((void **)&stack, (pointer + 2) * sizeof(INT4)))
                return 1;


            if (i - left > right - i) {
                stack[pointer] = left;
                stack[pointer + 1] = i - 1;
                left = i + 1;
            } else {
                stack[pointer] = i + 1;
                stack[pointer + 1] = right;
                right = i - 1;
            }
            pointer += 2;
        } else {
            pointer -= 2; /* other partition */
            POSTCOND(pointer >= 0);

            left = stack[pointer];
            right = stack[pointer + 1];
        }
    } while (pointer != 0);
    PRECOND(stack != NULL);
    Free(stack);
    return 0;
}
Пример #17
0
static int CloneOption(
       const char *name)
{
       ATTRIBUTES a;
       if (FileStat(name) != 2)
       {
          return RetError(1,"file '%s' exists, give new (non-existing) name",name);
       }
       if (DefaultCloneAttr(&a))
              return 1;
       a.cloneCreation = TRUE;
        switch(MakeCloneMenu(&a, name))
        { 
            case 0: return 1;
            case 1: return CreateMap(name, &a);
            case 2: fprintf(stderr,"No map created\n");
                    return 0;
       }
        POSTCOND(FALSE);
        return 1;
}
Пример #18
0
static void Add2Lines(
	HOR_CUT_LINE *l,
	int nrLines,
	int xCeil,
	REAL8 c,
	REAL8 s, 
	REAL8 x, 
	REAL8 y )
{
	REAL8 xRot = (x*c)-(y*s);
	REAL8 yRot = (x*s)-(y*c);
	int   xInd = ((int)floor(xRot))+(int)xCeil;
	POSTCOND(xInd >= 0 && xInd < nrLines);
	if (IS_MV_REAL4(&(l[xInd].start.f)))
	{
		l[xInd].start.f = POSSIBLE_DATA_LOSS(REAL4,yRot);
		l[xInd].end.f =  POSSIBLE_DATA_LOSS(REAL4,yRot);
	}
	l[xInd].start.f = POSSIBLE_DATA_LOSS(REAL4,MIN(l[xInd].start.f, yRot));
	l[xInd].end.f   = POSSIBLE_DATA_LOSS(REAL4,MAX(l[xInd].end.f, yRot));
  (void)nrLines; // shut up compiler
}
Пример #19
0
static int EditOption(
       const char *name)
{
       ATTRIBUTES a;
       MAP *in = Mopen(name, M_READ_WRITE);
       if (in == NULL || ReadAttr(&a,in,FALSE))
       {
         if (in != NULL)
          Mclose(in);
         return RetError(1,"while reading '%s': %s",name,MstrError());
       }
       if (a.version != 2)
        return RetError(1,"'%s' is not a version 2 map, no edits possible");
       a.cloneCreation = FALSE;
        switch(MakeCloneMenu(&a, name))
        { 
            case 0: return 0;
            case 1: return SetAndCloseMap(in, &a);
            case 2: fprintf(stderr,"No map attributes written\n");
                    return 0;
        }
        POSTCOND(FALSE);
        return 1;
}
Пример #20
0
/* Calculates the spread value.
 * The value is determined according to friction and the position of the
 * neighbors. If the neighbors are corner neighbors, the average
 * friction is multiplied with the diagonal, else with the side.
 * Returns the spread value.
 */
static REAL8 CalcSpreadValue(
	INT4 *id,			/* write-only id */
	const MAP_REAL8 *outCost,	/* output costs */
	const MAP_INT4 *outId,		/* id map from spread */
	const MAP_REAL8 *friction,	/* friction map */
	int r,				/* row current cell */
	int c,				/* column curr. cell */
	REAL8 f)			/* friction value (r, c) */
{			
	REAL8 	costs, costVal, fricNxt, minCosts;
	int 	i, rNext, cNext;
	INT4 	newId = 0;		/* id spread point of min. cost */

	minCosts = REAL8_MAX;		/* minimum costs until now */
	FOR_ALL_LDD_NBS(i)
	{
		rNext = RNeighbor(r, i);
		cNext = CNeighbor(c, i);
		if(outCost->Get(&costVal, rNext, cNext, outCost) &&
		(friction->Get(&fricNxt, rNext, cNext, friction)))
		{
			costs = (f + fricNxt) / 2;
 			costs *= (Corner(i) == FALSE) SCALE;
			costs += costVal;	
			if(costs < minCosts)
			{ 	/* cheapest path from neighbor to r,c */	
				minCosts = costs;	
				outId->Get(&newId, rNext, cNext, outId);
				*id = newId;
				POSTCOND(*id != 0);
			}	
		}
	}	
	*id = newId;		/* id from cheapest neighbor */
	return minCosts;	/* minimum costs to get to r, c */	
}				
Пример #21
0
/* Parses a key, checks whether or not it is legal.
 * Returns
 * 1 if the key is illegal (a nested error message is printed)
 * , 0 if succesfull.
 */
static int ParseKey(
  LOOK_UP_KEY *k,  /* write-only key, if k->t == TEST_NOKEY
                   * then the end of file is reached
                   */
   CSF_VS vs)  /* value scale */
 {
      typedef enum STATE { STATE_START, STATE_LOWNUM, STATE_COMMA,
             STATE_HIGHNUM, STATE_HIGHTOKEN } STATE;
      STATE state = STATE_START;
      int t; /* token */
      long    startLineNr = LexGetLineNr();
  while(1)
  {
      t = LexGetToken();
      if (t >= 0 && LexGetLineNr() != startLineNr)
      {
        if (state == STATE_START) /* parsed empty line */
          startLineNr = LexGetLineNr();
        else
          t = LEX_EOL;
      }
      switch(state)
      {
    case STATE_START: switch(t) {
       case LEX_NUMBER:
      k->t = TEST_ONE;
          if (SetNumber(k, TRUE, vs))
            return 1;
          return 0;
           case '[' :
                 k->t = TEST_GE_INF;
                 state = STATE_LOWNUM;
                 break;
           case '<' :
                 k->t = TEST_GT_INF;
                 state = STATE_LOWNUM;
                 break;
           case 0   :
                 k->t = TEST_NOKEY;
                 return 0;
           default : return IllegalState(k,t,"$[<");
        } break;
        case STATE_LOWNUM:
     PRECOND(k->t == TEST_GE_INF || k->t == TEST_GT_INF);
         switch(t) {
       case LEX_NUMBER:
          if (SetNumber(k, TRUE, vs))
            return 1;
          state = STATE_COMMA;
          break;
       case ',':
      k->t = TEST_INF_INF;
          state = STATE_HIGHNUM;
          break;
           default : return IllegalState(k,t,"$,");
         } break;
        case STATE_COMMA:
          if (t != ',')
            return IllegalState(k,t,",");
          state = STATE_HIGHNUM;
          break;
        case STATE_HIGHNUM:
         POSTCOND(k->t==TEST_GE_INF||k->t==TEST_GT_INF ||k->t==TEST_INF_INF);
          switch(t) {
       case LEX_NUMBER:
          if (SetNumber(k, FALSE, vs))
            return 1;
          state = STATE_HIGHTOKEN;
          if (k->t != TEST_INF_INF && (k->l > k->h) )
          {
           k->t = TEST_ERROR; // pcrcalc/test69
           return RetErrorNested(1,"low value ('%g') of range larger than high value ('%g')", k->l,k->h);
          }
          break;
           case ']':
           case '>':
                 /* already set, by choosing
                  * intermediate states of k->t
                  */
                return 0;
           default : return IllegalState(k,t,"$]>");
          }break;
    case STATE_HIGHTOKEN:
         POSTCOND(k->t==TEST_GE_INF||k->t==TEST_GT_INF ||k->t==TEST_INF_INF);
         switch(t) {
           /* inc over enums, that's why particular order */
           case ']':
             k->t += 3;
             return 0;
           case '>':
             k->t += 6;
             return 0;
           default : return IllegalState(k,t,"]>");
         } break;
      } /* eoswitch state */
      } /* eowhile */
}
Пример #22
0
/* get the number of grey palette entries
 * MgetNrGreyPaletteEntries returns the number of grey tupels
 * of the grey palette. Each tuple is one UINT2
 * words describing the intensity: low, 0 is black, high is white.
 * returns
 *  the number of grey tuples,
 *  or 0 if not available or in case of error
 */
size_t MgetNrGreyPaletteEntries(MAP *m) /* the map to get it from */
{
	size_t s = (size_t)CsfAttributeSize(m, ATTR_ID_GREY_PAL);
	POSTCOND( (s % (sizeof(UINT2))) == 0);
	return s / (sizeof(UINT2));
}
Пример #23
0
/* Performs the spread function using the breadth-first strategy. 
 * All neighbors from current cell are checked on getting a cheaper path
 * from current cell. All cells in the coordlist are checked. Every time
 * a neighbor is found which gets a new cost value, its neighbors are
 * checked too.
 * Returns 0 if no error occurs, 1 otherwise. 
 */
static int PerformSpread(
	MAP_REAL8 *outCost, 		/* read-write output costs */
	MAP_INT4 *outId,		/* read-write output id map */
	NODE *coordList,		/* read-write list of cells */
	const MAP_REAL8 *friction,	/* friction map */
	const MAP_REAL8 *maxCost)	/* max cost map */
{
	int 	rNext, cNext, rowNr, colNr, i;
	REAL8 	f;        	/* friction of current cell */
	REAL8 	s, newS;	/* old & new spreadval. of curr. cell */

     	PRECOND(outCost->GetGetTest(outCost) == GET_MV_TEST);
     	PRECOND(outId->GetGetTest(outId) == GET_MV_TEST);
     	PRECOND(friction->GetGetTest(friction) == GET_MV_TEST);
     	PRECOND(maxCost->GetGetTest(maxCost) == GET_MV_TEST);

	while(coordList != NULL)
	{
	 INT4 id;	 /* id of current cell */
	 rowNr = coordList->rowNr; /* cell from which is spread */
	 colNr = coordList->colNr; /* (source cell ) */
	 coordList = RemFromList(coordList);  /* unable */
	 id = Set0BitMatrix(inList,rowNr,colNr);
	 POSTCOND(id != 0); /* was set */

	 AppDynamicProgress();

	 FOR_ALL_LDD_NBS(i)
	 {   /* find new spread value for all neighbors */
	  rNext = RNeighbor(rowNr, i);	
	  cNext = CNeighbor(colNr, i);

	  if(friction->Get(&f, rNext, cNext, friction) &&
	 	outId->Get(&id, rNext, cNext, outId))
	  {
	  	INT4 newId = 0;
	  	if(id != 0)
	  	 outCost->Get(&s, rNext, cNext, outCost); /* already visited */

	 	newS = CalcSpreadValue(&newId, outCost,
	 	       outId, friction, rNext, cNext, f);
	 					
	 	if(newId != 0 && (id == 0 || AppCastREAL4(newS) < s))
		{
		/* a cheaper or first route to this cell
		 * found, inspect the neighbors too. 
		 */
		 	REAL8 maxCostVal;
			BOOL maxCostReached ;
	  	 	maxCost->Get(&maxCostVal, rNext, cNext, maxCost); 
			maxCostReached = maxCostVal <= newS;
			if (!maxCostReached)
			{
			 outCost->Put(newS, rNext, cNext, outCost); /* new costs */
			 outId->Put(newId, rNext, cNext, outId); /* new id */

			 coordList = AddToList(coordList, rNext, cNext);
			 if(coordList == NULL)
				return 1;
			}
		}
	   }
	}
      }
   /* POSTCOND(coordList == NULL); */
   return 0;
}
Пример #24
0
int RuseAs(
	MAP *m,          /* map handle */
	CSF_CR useType)   /* CR_UINT1,CR_INT4, CR_REAL4, CR_REAL8, VS_BOOLEAN or VS_LDD */
{ 

  CSF_CR inFileCR = RgetCellRepr(m);
  CSF_VS inFileVS = RgetValueScale(m);
  int hasInFileCellReprType2 =  HasInFileCellReprType2(inFileCR);

  /* it is very unconvenient that both, VS and CR are taken as arguments
   * for this function, and previously were used in the switch statement
   * now, at least 'special conversions' handled first
   */
  if((int)useType == VS_BOOLEAN){
    switch(inFileVS) {
      case VS_LDD:
      case VS_DIRECTION: {
        M_ERROR(CANT_USE_AS_BOOLEAN);
        return 1;
      }
      case VS_BOOLEAN: {
        POSTCOND(inFileCR == CR_UINT1);
        m->appCR = CR_UINT1;
        m->file2app = same;
        m->app2file = same;
        return 0;
      }
      default: {
        if((!hasInFileCellReprType2) && WRITE_ENABLE(m)) {
          /* cellrepr is old one, we can't write that */
          M_ERROR(CANT_USE_WRITE_BOOLEAN);
          return 1;
        }
        m->appCR = CR_UINT1;
        m->file2app  = ConvFuncBool(inFileCR);
        m->app2file = ConvFunc(inFileCR, CR_UINT1);
        return 0;
      }
    }
  }
  else if ((int)useType == VS_LDD){
    switch(inFileVS) {
      case VS_LDD: {
        POSTCOND(inFileCR == CR_UINT1);
        m->appCR = CR_UINT1;
        m->file2app = same;
        m->app2file = same;
        return 0;
      }
      case VS_CLASSIFIED: 
      case VS_NOTDETERMINED: {
        switch(inFileCR) {
          case CR_UINT1: {
            m->appCR = CR_UINT1;
            m->file2app  = UINT1tLdd;
            m->app2file = same;
            return 0;
          }
          case CR_INT2: {
            if(WRITE_ENABLE(m)) {
              M_ERROR(CANT_USE_WRITE_LDD);
              return 1;
            }
            m->appCR = CR_UINT1;
            m->file2app  = INT2tLdd;
            m->app2file = illegal;
            return 0;
          }
          default: {
            /* This should never happen.
             * Shut up compiler.
             */
            assert(0);
          }
        }
      }
      default: {
        M_ERROR(CANT_USE_AS_LDD);
        return 1;
      }
    }
  }

  switch(useType) {
    case CR_UINT1:
    case CR_INT4 :
    case CR_REAL4:
    case CR_REAL8: {
      if((!hasInFileCellReprType2) && WRITE_ENABLE(m)) {
        /* cellrepr is old one, we can't write that */
        M_ERROR(CANT_USE_WRITE_OLDCR);
        return 1;
      }
      m->appCR = useType;
      m->file2app  = ConvFunc(useType, inFileCR);
      m->app2file = ConvFunc(inFileCR, useType);
      POSTCOND(m->file2app != NULL);
      return 0;
    }
    default: {
      M_ERROR(ILLEGAL_USE_TYPE);
      return 1;
    }
  }
  /* NOTREACHED */
}
Пример #25
0
/* Calculates one pixel from output map, given the input maps.
 * Puts all values of input pixels in a list and determines the value of
 * the output pixel according to these values and the overlapping areas.
 * Returns 0 if no error occurs, 1 otherwise.
 */
static int CalcPixel(
	MAP *out,		/* write-only output map */
 	MAP **in,		/* read-only list input maps */
 	size_t nrCoverCells,	/* min. nr. non-MV cells for non-MV */
 	size_t nrMaps,		/* nr. of input maps */
 	double rOut,		/* row number pixel */
 	double cOut,		/* column number pixel */
 	BOOL aligned,		/* maps are aligned */
 	REAL8 angle)		/* angle of output map */
{		
	PTYPE 	tlX, tlY, trX, trY, brX, brY, blX, blY;
	double 	r, c;
	DATA 	*list = NULL;  	/* areas and values of input cells */
   	size_t 	i, nrList = 0;	/* number of items in list */
	POINT2D 	*outputCell;	/* polygon of output cell */
   	size_t 	nr = 4;		/* nr of points of cell */
   	CSF_VS	vs;		/* value scale of first input map */

	if(nrCoverCells > 0 && nrMaps > 1)
		raster = InitRaster(raster); /* initialize the raster */

   	/* Determine the four corners of output pixel */
   	RrowCol2Coords(out, rOut, cOut, &tlX, &tlY); /* top left */
   	RrowCol2Coords(out, rOut, cOut + 1, &trX, &trY); /* top right */
   	RrowCol2Coords(out, rOut + 1, cOut, &blX, &blY); /* bottom left */
   	RrowCol2Coords(out, rOut + 1, cOut + 1, &brX, &brY); /* bottom right */
	outputCell = PutInPol(tlX, tlY, trX, trY, brX, brY, blX, blY);
	if(outputCell == NULL)
		return 1;

	POSTCOND(outputCell[0].x == outputCell[nr].x);
	POSTCOND(outputCell[0].y == outputCell[nr].y);

	/* Get pixel on every input map */
	for(i = 0; i < nrMaps; i++)
	{
		MAP 	*X = in[i];	/* input map number i */
		PTYPE 	tlC, tlR, trC, trR, brC, brR, blC, blR;
		PTYPE 	tlX2, tlY2, trX2, trY2, brX2, brY2, blX2, blY2;
   		double 	leftB, belowB, rightB, upperB;	/* boundaries */

		/* Corners: (tlX, tlY), (trX, trY), (blX, blY) and
		 * (brX, brY). Translate for input map.
		 */
   		Rcoords2RowCol(X, tlX, tlY, &tlC, &tlR); /* top left */
   		Rcoords2RowCol(X, trX, trY, &trC, &trR); /* top right */
   		Rcoords2RowCol(X, blX, blY, &blC, &blR); /* bottom left */
   		Rcoords2RowCol(X, brX, brY, &brC, &brR); /* bottom right */

   		/* Boundaries in the input map */
   		rightB = ceil(MaxPoint(tlR, trR, blR, brR));	
   		belowB = ceil(MaxPoint(tlC, trC, blC, brC));	
   		leftB = floor(MinPoint(tlR, trR, blR, brR));	
   		upperB = floor(MinPoint(tlC, trC, blC, brC));	
   		
		PRECOND(upperB <= belowB);
		PRECOND(leftB <= rightB);

		/* Check all cells between the boundaries */
		for(r = upperB; r < belowB; r++)
		{
			REAL8 *currRow;
			if(0 <= r && r <= RgetNrRows(X))
		 	 currRow = (REAL8 *)CacheGetRow(in, i,  r);

			for(c = leftB; c < rightB; c++)
		 	{  /* Cells that might be in pixel */
   			    POINT2D *inputCell;  /* polygon input cell */

			    if(r < 0 || RgetNrRows(X) <= r || c < 0 ||
			       RgetNrCols(X) <= c)
			    	continue;

   			    /* Top left & right, bottom left & right */
   			    RrowCol2Coords(X, r, c, &tlX2, &tlY2);
   			    RrowCol2Coords(X, r, c+1, &trX2, &trY2);
   			    RrowCol2Coords(X, r+1, c, &blX2, &blY2);
   			    RrowCol2Coords(X, r+1, c+1, &brX2, &brY2);
			    inputCell = PutInPol(tlX2, tlY2, trX2, trY2,
					brX2, brY2, blX2, blY2);
			    if(inputCell == NULL)
				return 1;

			    POSTCOND(inputCell[0].x == inputCell[nr].x);
			    POSTCOND(inputCell[0].y == inputCell[nr].y);

			    /* Add item to list for cell */
			    if(AddCell(&list, raster, &nrList, inputCell,
				  outputCell, currRow, X, nrMaps,
				   (size_t)c, nrCoverCells, aligned, angle))
				      return 1;
			    Free(inputCell);	/* deallocate */
		 	}
		}
	}	 

	/* calculate output value of pixel according value scale */
	vs = RgetValueScale(in[0]);
	if(vs != VS_DIRECTION)
		CalcScalarOut(out, (size_t)rOut, (size_t)cOut, nrList, list, nrCoverCells, nrMaps);
	else
		CalcDirectionOut(out, (size_t) rOut, (size_t) cOut, nrList, list, nrCoverCells, nrMaps);

	Free(outputCell);		/* deallocate */
	Free(list);			/* deallocate */
	return 0;			/* successfully terminated */
}
Пример #26
0
/* seek to space for attribute  (LIBRARY_INTERNAL)
 * CsfSeekAttrSpace seeks to the a point in the file where
 * the attribute must be stored and update the attribute control
 * blocks accordingly.
 * Writing can still fail since there is no check if that space is really
 * avalaible on the device. After this call returns the file is already
 * seeked to the point the functions returns.
 * returns the file position or 0 in case of error.
 *
 * Merrno
 * ATTRDUPL
 * NOACCESS
 * WRITE_ERROR
 */
CSF_FADDR32 CsfSeekAttrSpace(
	MAP *m,       		/* map handle */
	CSF_ATTR_ID id,               /* attribute identification only for check if avalaible */
	size_t size)            /* size to be seeked to */
{
	ATTR_CNTRL_BLOCK b;
	CSF_FADDR32 currBlockPos, prevBlockPos=USED_UNINIT_ZERO, newPos, endBlock, resultPos=0;
	int noPosFound;
	int i;

	if (MattributeAvail(m ,id))
	{
		M_ERROR(ATTRDUPL);
		goto error;
	}

	if (! WRITE_ENABLE(m))
	{
		M_ERROR(NOACCESS);
		goto error;
	}

	currBlockPos = m->main.attrTable;
        noPosFound = 1;
	while (noPosFound)
	{
		if (currBlockPos == 0)
		{
			if (m->main.attrTable == 0)
			{ /* FIRST BLOCK */
				newPos =( (CSF_FADDR)(m->raster.nrRows)*
					   (CSF_FADDR)(m->raster.nrCols)*
					  (CSF_FADDR)(CELLSIZE(RgetCellRepr(m))))
					  + ADDR_DATA;
				m->main.attrTable = newPos;
			}
			else
			{ /* NEW/NEXT BLOCK */
				newPos = b.attrs[LAST_ATTR_IN_BLOCK].attrOffset
					+
					b.attrs[LAST_ATTR_IN_BLOCK].attrSize;
				b.next = newPos;
				if (CsfWriteAttrBlock(m, prevBlockPos, &b))
				{
					M_ERROR(WRITE_ERROR);
					resultPos = 0;
				}
			}
			InitBlock(&b);
			b.attrs[0].attrOffset =
				newPos + SIZE_OF_ATTR_CNTRL_BLOCK;
			currBlockPos = newPos;
			noPosFound = 0;
		}
		else
			CsfReadAttrBlock(m, currBlockPos, &b);
		i = 0; /* this is also the right index if a new block
			   is added ! */
		while (noPosFound  && i < NR_ATTR_IN_BLOCK)
			switch (b.attrs[i].attrId)
			{
				case END_OF_ATTRS:
					POSTCOND(i >= 1);
					/* i >= 1 , no block otherwise */
					b.attrs[i].attrOffset =
						b.attrs[i-1].attrOffset  +
						b.attrs[i-1].attrSize;
					noPosFound = 0;
                                        break;
				case ATTR_NOT_USED:
					if (i == NR_ATTR_IN_BLOCK)
						endBlock = b.next;
					else
						endBlock = b.attrs[i+1].attrOffset;
					if ( (size_t)( endBlock - b.attrs[i].attrOffset) >= size)
						/* this position can
							hold the attr */
						noPosFound = 0;
                                        else
                                            i++;
                                        break;
				 default:
                                            i++;
			} /* switch */
/*		if (b.next == 0)
                     ? When did I change this CW
		       remember this block position since it may be have
		       to rewritten
*/
		prevBlockPos = currBlockPos;
		if (noPosFound)
			currBlockPos = b.next;
 	} /* while */

	b.attrs[i].attrSize = size;
	b.attrs[i].attrId   = id;
	resultPos = b.attrs[i].attrOffset;

	if (CsfWriteAttrBlock(m, currBlockPos, &b))
	{
		M_ERROR(WRITE_ERROR);
		resultPos = 0;
	}
	fseek(m->fp, (long)resultPos, SEEK_SET); /* fsetpos() is better */
error:	return resultPos;
} /* CsfSeekAttrSpace */
Пример #27
0
/* kk
 * returns allocated list of records, NULL in case of error (stored
 * in ErrorNested
 */
static LOOK_UP_KEY *ReadLookupRecs(
  size_t  *nrCols,  /* write-only */
  size_t  *nrRecs,  /* write-only */
  size_t  nrKeysExp,/* numbers of keys expected, only relevant
                  * if vsTargetValue != VS_UNDEFINED
                  * this is exclusive the targetColumn
                  */
  CSF_VS vsTargetVal, /* if VS_UNDEFINED then skip test on exact number
                      * of columns (= nrKeysExp+1)
                      */
  FILE *tableFile)
{
  size_t n,nrK,c = DetectNrColsTable(tableFile);
  LOOK_UP_KEY *k = NULL;
  long recStartAt=0;
  if (c == 0)
    goto error;

  if (c == 1 && vsTargetVal != VS_UNDEFINED )
  {
   ErrorNested("only 1 column found");
   return NULL;
  }

  if (vsTargetVal != VS_UNDEFINED && c != (nrKeysExp+1))
  {
   ErrorNested("contains %s columns ('%d' read,'%d' expected)",
    (c < (nrKeysExp+1) ? "not enough" : "too many"), c, nrKeysExp+1);
   goto error;
  }

  LexInstall(tableFile,  "[]<>,");
  for (nrK = n = 0; /* break from code */ ; n++)
  {
    CSF_VS vs = VS_UNDEFINED;
    if (n == nrK)
    {
      nrK += 40;
      if (ChkReallocFree((void **)&k,nrK * sizeof(LOOK_UP_KEY)))
        return NULL;
    }
    if (vsTargetVal != VS_UNDEFINED && (n%c) == nrKeysExp)
     vs = vsTargetVal;
    ParseKey(k+n, vs);
    if (k[n].t == TEST_NOKEY) {
     if ( (n%c)==0 )
      break;
     else
          goto notEnough;
    }
    if (k[n].t == TEST_ERROR)
    {
      ErrorNested("while reading at line '%ld' column '%d'",
      LexGetLineNr(), (n%c)+1);
      goto error;
    }
    if (vsTargetVal != VS_UNDEFINED && (n%c) == nrKeysExp
        && k[n].t != TEST_ONE )
    {
      ErrorNested(
      "value field at line '%ld' column '%d' is not a single value"
      , LexGetLineNr(), (n%c)+1);
      goto error;
    }
    if ( (n%c)==0) /* start new record */
    {
     if (recStartAt == LexGetLineNr()) /* prev had more */
     {
      ErrorNested(
      "Too many columns on line '%ld', expected '%d' columns",
      recStartAt,c);
      goto error;
     }
     recStartAt = LexGetLineNr();
          }
          else /* add to this record */
    {
     if (recStartAt != LexGetLineNr()) /* this does not have enough */
     {
notEnough:
      ErrorNested(
      "Not enough columns on line '%ld', expected '%d' columns",
      recStartAt,c);
      goto error;
     }
    }
  } /* eofor */
  POSTCOND( (n % c) == 0);
  *nrCols = c;
  *nrRecs = n/c;
  return k;
error:
  Free(k);
  return NULL;
}
Пример #28
0
/* read a lookup or cross table
 * ReadLookupTable reads a table in matrix or table format.
 * The exact number of columns is not checked, unless outputVs
 * not equal to VS_UNDEFINED.
 * The number of actual columns read is plus one for the key column
 * Errors are printed in ErrorNested.
 * Returns the lookup table or NULL in case of an error.
 */
LOOK_UP_TABLE *ReadLookupTable(
  FILE *f,            /* the tablefile */
  const CSF_VS *keyVs, /* valuescales of key columns,
                       * undefined if outputVs == VS_UNDEFINED
                       */
  size_t  nrKeys,      /* > 0
                       * undefined if outputVs == VS_UNDEFINED
                       */
  CSF_VS outputVs)     /* VS_UNDEFINED if we don't care */
{
  size_t r,c,nrCols, nrRecs;
  LOOK_UP_KEY *k;
  LOOK_UP_TABLE *t;
  size_t nrColsExp;
  BOOL matrRead = (nrKeys == 2 && app2dMatrix);
  k = ReadLookupRecs(&nrCols, &nrRecs, nrKeys,
                      matrRead ? VS_UNDEFINED : outputVs, f);
  if (outputVs == VS_UNDEFINED)
  {
          nrColsExp = nrCols;
    nrKeys = nrCols-1;
    keyVs = NULL;
  }
  else
        nrColsExp = nrCols;
  if (k == NULL || (t = ChkMalloc(sizeof(LOOK_UP_TABLE))) == NULL)
    return NULL;
  t->nrKeys = nrKeys;
  t->keyVs = NULL; t->records = NULL;
  t->searchMethod = SEARCH_LINEAR;

  if (matrRead)
  { /* build lookup from matrix and check matrix output/target values */
    size_t i;
    t->nrRecords = (nrRecs-1)*(nrCols-1);
    t->nrMatrCols = nrCols-1;
    t->nrKeys = 2; /* CW */
    if (t->nrRecords <= 0)
    {
      ErrorNested("matrix must have at least 2 rows and 2 columns");
      goto error;
    }
    if (AllocLookupTable(t))
      goto error;
    for (r=0,i=0; i < nrRecs*nrCols; i++)
     if ( (i/nrCols) != 0     /* not first row */
         && (i%nrCols) != 0 ) /* not first col */
      {
    /* col index is key 0 */
    t->records[r][0] = k[i%nrCols];
    /* row index is key 1 */
    t->records[r][1] = k[nrCols*(i/nrCols)];
    /* outputValue */
    t->records[r++][2] = k[i];
    if (CheckMatrixCell(i/nrCols,i%nrCols,k+i,outputVs))
      goto error;
      }
    POSTCOND(r == t->nrRecords);
  }
  else /* table (not matrix) */
  {
    t->nrRecords = nrRecs;
    if (nrColsExp > nrCols)
    {
      ErrorNested("not enough columns, read '%d' expected '%d' columns",
                  nrCols, nrColsExp);
      goto error;
    }
    if (AllocLookupTable(t))
      goto error;
    for(r=0; r < nrRecs; r++)
     (void)memcpy(t->records[r],k+(nrCols*r),nrColsExp*sizeof(LOOK_UP_KEY));
  }

  Free(k);
  if (keyVs != NULL)
   (void)memcpy(t->keyVs, keyVs, t->nrKeys*sizeof(CSF_VS));
  else for (r = 0; r < t->nrKeys; r++)
        t->keyVs[r] = VS_UNDEFINED;
  t->keyVs[t->nrKeys] = outputVs;

  /* adjust for directional
   */
   nrCols = nrKeys + (outputVs != VS_UNDEFINED);
   for (c=0; c<nrCols; c++)
   if (t->keyVs[c] == VS_DIRECTION)
    for (r=0; r<t->nrRecords; r++)
    {
      if (LOW_DEFINED(t->records[r][c].t))
       CnvrtDirectional(&(t->records[r][c].l));
      if (HIGH_DEFINED(t->records[r][c].t))
       CnvrtDirectional(&(t->records[r][c].h));
    }
  return t;
error:
  Free(k);
  FreeLookupTable(t);
  return NULL;
}
Пример #29
0
/* Determines all lowest neighbors and gives them output.
 * All lowest neighbors from current cell are put at the beginning of 
 * the list (depth-first) and the stream is added to their output value.
 * Returns list if successful, NULL when memory allocation failed.
 */
static NODE *DoNeighbors(
	MAP_REAL8 * out,		/* read-write output map */
	NODE *list,			/* read-write list 	 */
	const MAP_REAL8 * dem,		/* dem map */
	const MAP_REAL8 * points, 	/* points map */
	int r,				/* current cell row */
	int c,				/* current cell column */
	REAL8 drainVal)			/* value to drain down */
{	
	NODE 	*list2 = NULL;		/* list of lowest neighbors */
	REAL8 	dropMax = 0;		/* maximal drop value */
	REAL8 	dropVal = 0;		/* maximal drop value */
	int 	i, nrPaths = 0;		/* nr of outgoing paths	*/
	REAL8 	demVal, newDem, outVal, pntVal; /* dem value
	 		* and output value of old and new cell and the
	 		* point value of both to check on MV.
	 		*/

  	PRECOND(dem->GetGetTest(dem) == GET_MV_TEST);
  	PRECOND(points->GetGetTest(points) == GET_MV_TEST);
  	PRECOND(out->GetGetTest(out) == GET_MV_TEST);
	PRECOND(dem->Get(&demVal, r, c, dem));
	PRECOND(out->Get(&outVal, r, c, out));

	dem->Get(&demVal, r, c, dem);	/* height original cell */
	out->Get(&outVal, r, c, out);	/* output original cell */

	for(i = 1; i <= NR_LDD_DIR; i++)
	{	/* check all neighbors */
		int 	rNext = RNeighbor(r, i);
		int 	cNext = CNeighbor(c, i);

		if(dem->Get(&newDem, rNext, cNext, dem) &&   /* no MV */
		points->Get(&pntVal, rNext, cNext, points) &&/* no MV */
		(i != LDD_PIT) &&		  /* skip cell itself */
		(0 < (demVal - newDem)))   /* lower than current cell */
		{
			REAL8 dist = (Corner(i) == FALSE) SCALE;

			dropVal = (demVal - newDem) / dist;
			if(dropMax <= dropVal)
			{
				NODE *tmp;
				if(dropMax < dropVal)
				{
				/* all previous found neighbors
				 * were not the lowest -> reset.
				 */
					list2 = FreeList(list2);
					POSTCOND(list2 == NULL);
					nrPaths = 0;
					dropMax = dropVal;
				}	
				nrPaths++;
				tmp = LinkToList(list2, rNext, cNext);
				if(tmp == NULL)
				{
					FreeList(list2);
					FreeList(list);
					return NULL;
				}
				list2 = tmp;
			}
		}
	}
	drainVal /= nrPaths;	/* divide between steepest paths */
	while(list2 != NULL)
	{ 
		PRECOND(out->Get(&outVal, list2->rowNr, list2->colNr,
								out));
		out->Get(&outVal, list2->rowNr, list2->colNr, out);
		outVal += drainVal;
		out->Put(outVal, list2->rowNr, list2->colNr, out);
		list = LinkChkReal(list, list2->rowNr, list2->colNr,
							drainVal);
		if(list == NULL)
		{
			FreeList(list2);
			return NULL;
		}
		list2 = RemFromList(list2);
	}
	POSTCOND(list != NULL); /* result HasLowerNeighbor was TRUE */
	return list;
}	
Пример #30
0
int main(int argc, char *argv[]) {
    MAP *out, *clone = NULL;
    int c;
    size_t colNr[3] = {0 /*X*/, 1 /*Y*/, 2 /*V*/}; /* internal indices */
    const char *mv = "1e31";
    char *cloneFileName;
    COMP_CELL compCell = NOTHING;
    CSF_CR cellRepr;
    CSF_VS valueScale = VS_UNDEFINED;
    int parseVal;
    int sepChar = ',';

    if (InstallArgs(argc, argv, "x#y#v#m*(BLNOSDV)(atHM)(hl)s*", "col2map", __DATE__))
        goto failure;
    while ((c = GetOpt()) != 0)
        switch (c) {
        case 'x':
            parseVal = (*((const int *)OptArg)) - 1;
            if (parseVal < 0) {
                Error("-x: x column should be greater than 0");
                goto failure;
            }
            colNr[POS_X] = (size_t)parseVal;
            break;
        case 'y':
            parseVal = (*((const int *)OptArg)) - 1;
            if (parseVal < 0) {
                Error("-y: y column should be greater than 0");
                goto failure;
            }
            colNr[POS_Y] = (size_t)parseVal;
            break;
        case 'v':
            parseVal = (*((const int *)OptArg)) - 1;
            if (parseVal < 0) {
                Error("-v: value column should be greater than 0");
                goto failure;
            }
            colNr[POS_V] = (size_t)parseVal;
            break;
        case 'm':
            mv = (const char *)OptArg;
            break;
        case 'a':
            compCell = AVERAGE;
            break;
        case 'H':
            compCell = HIGHEST;
            break;
        case 'h':
            compCell = MAJORITY;
            break;
        case 'M':
            compCell = LOWEST;
            break;
        case 'l':
            compCell = MINORITY;
            break;
        case 't':
            compCell = TOTAL;
            break;
        case 's':
            sepChar = ((const char *)OptArg)[0];
            if (isdigit(sepChar)) {
                Error("-s: separator must be a non-digit (not [0-9])");
                goto failure;
            }
            break;
#include "case_vs.h"
        }

    argv = ArgArguments(&argc);
    if (argv == NULL)
        goto failure;
    if (AppArgCountCheck(argc, 3, 3, USAGE))
        goto failure;
    if (AppInputTest(argv[1]))
        goto failure;

    /* open the clone map */
    clone = AppOpenClone(&cloneFileName, NULL);
    if (clone == NULL)
        goto failure;

    if (valueScale == VS_UNDEFINED) {
        valueScale = RgetValueScale(clone);
        cellRepr = RgetCellRepr(clone);
    } else
        cellRepr = AppDefaultCellRepr(valueScale);

    if (!RvalueScale2(valueScale)) {
        Error("clone map '%s' has an illegal value scale", cloneFileName);
        goto failure2;
    }

    if (compCell == NOTHING) { /* defaults */
        switch (valueScale) {
        case VS_SCALAR:
            compCell = AVERAGE;
            break;
        case VS_DIRECTION:
            compCell = DIR_AVERAGE;
            break;
        default:
            compCell = MAJORITY;
            break;
        }
    } else {
        BOOL conflict = FALSE;
        CSF_VS vs = valueScale;
        switch (compCell) {
        case AVERAGE:
            conflict = (vs != VS_SCALAR && vs != VS_DIRECTION);
            if (vs == VS_DIRECTION)
                compCell = DIR_AVERAGE;
            break;
        case LOWEST:
        case HIGHEST:
            conflict = (vs != VS_SCALAR && vs != VS_ORDINAL);
            break;
        case MAJORITY:
        case MINORITY:
            conflict = (vs == VS_SCALAR || vs == VS_DIRECTION);
            break;
        case TOTAL:
            conflict = vs != VS_SCALAR;
            break;
        default:
            POSTCOND(FALSE);
        }
        if (conflict) {
            CompCellError(compCell, vs);
            goto failure2;
        }
    }

    out = Rdup(argv[2], clone, cellRepr, valueScale);
    if (out == NULL) {
        Error("output map '%s' can not be created", argv[2]);
        goto failure2;
    }
    Mclose(clone);
    clone = NULL;
    RuseAs(out, CR_REAL8);

    if (Col2Map(out, argv[1], compCell, mv, colNr, sepChar)) {
        Mclose(out);
        (void)remove(argv[2]);
        goto failure;
    }

    Mclose(out);
    AppEnd();
    exit(0);
    return 0;

failure2:
    if (clone == NULL)
        Mclose(clone);
failure:
    AppEnd();
    exit(1);
    return 1;
} /* main */