Ejemplo n.º 1
0
/******************************************************************************
	Constructor: This is a constructor for the "Entry" object.  A linked list
	of these "Entry" objects is underlying structure of the main object.

	NOTE: the specific of handling different file types are handled here.
*/
struct csAts77ToCsrsEntry_* CSnewAts77ToCsrsEntry (struct csDatumCatalogEntry_* catPtr)
{
	struct csAts77ToCsrsEntry_* __This;

	/* Prepare for an error. */
	__This = NULL;

	/* Allocate some storage. */
	__This = (struct csAts77ToCsrsEntry_*) CS_malc (sizeof (struct csAts77ToCsrsEntry_));
	if (__This == NULL)
	{
		CS_erpt (cs_NO_MEM);
		goto error;
	}
	__This->next = NULL;
	__This->type = dtAts77ToCsrsNoneYet;
	__This->pointers.c2DatumPtr = NULL;

	/* Set up the file; construct a Canadian National Transformation,
	   Version 2 object.  It's smart enough to deal with the differences
	   between the Canadian format and the Australian variation. */
	__This->pointers.c2DatumPtr = CSnewDatumShiftCa2 (dtcTypeAustralian,catPtr->pathName,catPtr->bufferSize,catPtr->flags,catPtr->density);
	if (__This->pointers.c2DatumPtr == NULL)
	{
		goto error;
	}
	__This->type = dtAts77ToCsrsC2;
	return __This;

error:
	CSdeleteAts77ToCsrsEntry (__This);
	return NULL;
}
Ejemplo n.º 2
0
/******************************************************************************
        Constructor
*/
struct csGeoidHeight_* CSnewGeoidHeight (Const char *catalog)
{
	int index;
	struct csGeoidHeight_ *__This;
	struct csDatumCatalog_ *catPtr;
	struct csDatumCatalogEntry_ *catEntryPtr;
	struct csGeoidHeightEntry_* ghEntryPtr;
	struct csGeoidHeightEntry_* findPtr;

	/* Prepare for an error. */
	__This = NULL;
	catPtr = NULL;
	catEntryPtr = NULL;
	ghEntryPtr = NULL;

	__This = (struct csGeoidHeight_*) CS_malc (sizeof (struct csGeoidHeight_));
	if (__This == NULL)
	{
		CS_erpt (cs_NO_MEM);
		goto error;
	}
	__This->listHead = NULL;

	/* Open the catalog file. */
	catPtr = CSnewDatumCatalog (catalog);
	if (catPtr == NULL) goto error;

	/* For each entry in the catalog, we build an appropriate geoid height
	   grid file entry.  Right now, this is based on file names and file
	   extensions.  Not very good, but that's life. */

	index = 0;
	for (;;)
	{
		catEntryPtr = CSgetDatumCatalogEntry (catPtr,index++);
		if (catEntryPtr == NULL) break;
		ghEntryPtr = CSnewGeoidHeightEntry (catEntryPtr);
		if (ghEntryPtr == NULL)
		{
			goto error;
		}
		/* Keep the list in the same order as they appear in the file. */
		if (__This->listHead == NULL)
		{
			__This->listHead = ghEntryPtr;
		}
		else
		{
			for (findPtr = __This->listHead;findPtr->next != NULL;findPtr = findPtr->next);
			findPtr->next = ghEntryPtr;
		}
	}
	CSdeleteDatumCatalog (catPtr);
	catPtr = NULL;
	return __This;
error:
	if (catPtr != NULL) CSdeleteDatumCatalog (catPtr);
	if (__This != NULL) CS_free (__This);
	return NULL;
}
Ejemplo n.º 3
0
Archivo: CS_ntv2.c Proyecto: asir6/Colt
/******************************************************************************
	Constructor.  Can't have an object of this type without a data file.  Thus
	this constructor requires a data file and returns NULL in the event of a
	failure.  Currently, there is no use of the flags value.
*/
struct cs_NTv2_* CSnewNTv2 (Const char *filePath,long32_t bufferSize,ulong32_t flags,double density)
{
	int st;

	struct cs_NTv2_* thisPtr;

	/* Allocate and initialize the basic structure. */
	thisPtr = (struct cs_NTv2_ *)CS_malc (sizeof (struct cs_NTv2_));
	if (thisPtr == NULL)
	{
		CS_erpt (cs_NO_MEM);
	}
	else
	{
		st = CSinitNTv2 (thisPtr,filePath,bufferSize,flags,density);
		if (st != 0)
		{
			CSdeleteNTv2 (thisPtr);
			thisPtr = NULL;
		}
	}
	return thisPtr;
}
Ejemplo n.º 4
0
/******************************************************************************
Constructor */
struct csDatumShiftCa1_* CSnewDatumShiftCa1 (Const char *path,long bufferSize,unsigned long flags,double density)
{
	struct csDatumShiftCa1_ *__This = NULL;

	__This = (struct csDatumShiftCa1_ *)CS_malc (sizeof (struct csDatumShiftCa1_));
	if (__This == NULL)
	{
		CS_erpt (cs_NO_MEM);
		goto error;
	}
	__This->gridPtr = NULL;

	__This->gridPtr = CSnewGridFileCa1 (path,bufferSize,flags,density);
	if (__This->gridPtr == NULL) goto error;
	return __This;
error:
	if (__This != NULL)
	{
		if (__This->gridPtr != NULL) CSdeleteGridFileCa1 (__This->gridPtr);
		CS_free (__This);
	}
	return NULL;
}
Ejemplo n.º 5
0
/******************************************************************************
	Constructor  (for an 'Entry' sub object)
*/
struct csVertconUSEntry_* CSnewVertconUSEntry (struct csDatumCatalogEntry_* catPtr)
{
	extern char cs_DirsepC;
	extern char cs_ExtsepC;
	extern char csErrnam [];

	char *cp;
	struct csVertconUSEntry_* __This;

	/* Prepare for an error. */
	__This = NULL;

	/* Allocate some storage. */
	__This = (struct csVertconUSEntry_*) CS_malc (sizeof (struct csVertconUSEntry_));
	if (__This == NULL)
	{
		CS_erpt (cs_NO_MEM);
		goto error;
	}
	__This->next = NULL;
	__This->usGridPtr = NULL;

	/* Isolate the file name from the path, and the extension from the file name. */
	cp = strrchr (catPtr->pathName,cs_DirsepC);
	if (cp == NULL)
	{
		/* Is not supposed to happen, but we can't allow a bomb. */
		CS_stncp (csErrnam,catPtr->pathName,MAXPATH);
		CS_erpt (cs_DTC_PATH);
		goto error;
	}

	/* Isolate the extension on the file. */
	cp = strrchr (catPtr->pathName,cs_ExtsepC);
	if (cp == NULL)
	{
		/* Is not supposed to happen. */
		CS_stncp (csErrnam,catPtr->pathName,MAXPATH);
		CS_erpt (cs_NAD_EXT);
		goto error;
	}
	cp += 1;

	/* Report special errors concerning the extensions.  Again, specific
	   error messages will reduce frustration. */
	if (CS_stricmp (cp,"94"))
	{
		CS_erpt (cs_VCON_94);
		goto error;
	}
	/* Do what's appropriate for this extension. */
	if (!CS_stricmp (cp,"94"))
	{
		__This->usGridPtr = CSnewGridFileUS (catPtr->pathName,catPtr->bufferSize,catPtr->flags,catPtr->density);
		if (__This->usGridPtr == NULL)
		{
			goto error;
		}
	}
	/* When we know how to do the others, we add that stuff here. */
	else
	{
		CS_erpt (cs_VCON_EXT);
		goto error;
	}
	return __This;
error:
	CSdeleteVertconUSEntry (__This);
	return NULL;
}
Ejemplo n.º 6
0
/******************************************************************************
        Constructor
*/
struct csVertconUS_* CSnewVertconUS (Const char *catalog)
{
	int index;
	struct csVertconUS_ *__This;
	struct csDatumCatalog_ *catPtr;
	struct csDatumCatalogEntry_ *catEntryPtr;
	struct csVertconUSEntry_* vcEntryPtr;
	struct csVertconUSEntry_* findPtr;

	/* Prepare for an error. */
	__This = NULL;
	catPtr = NULL;
	catEntryPtr = NULL;
	vcEntryPtr = NULL;

	__This = (struct csVertconUS_*) CS_malc (sizeof (struct csVertconUS_));
	if (__This == NULL)
	{
		CS_erpt (cs_NO_MEM);
		goto error;
	}
	__This->cachePtr = NULL;
	__This->listHead = NULL;

	/* Open the catalog file. */
	catPtr = CSnewDatumCatalog (catalog);
	if (catPtr == NULL) goto error;

	/* For each entry in the catalog, we build an appropriate geoid height
	   grid file entry.  Right now, this is based on file names and file
	   extensions.  Not very good, but that's life. */

	index = 0;
	while (TRUE)												/*lint !e716 */
	{
		catEntryPtr = CSgetDatumCatalogEntry (catPtr,index++);
		if (catEntryPtr == NULL) break;
		vcEntryPtr = CSnewVertconUSEntry (catEntryPtr);
		if (vcEntryPtr == NULL)
		{
			goto error;
		}
		/* Keep the list in the same order as they appear in the file. */
		if (__This->listHead == NULL)
		{
			__This->listHead = vcEntryPtr;
		}
		else
		{
			for (findPtr = __This->listHead;findPtr->next != NULL;findPtr = findPtr->next);
			findPtr->next = vcEntryPtr;
		}
	}
	CSdeleteDatumCatalog (catPtr);
	catPtr = NULL;

	/* Having done that successfully, allocate a grid cell cache.  If
	   this fails, we can either report it as an error, or just leave it
	   alone.  Lets report it as an error. */
	__This->cachePtr = CSnewZGridCellCache (32);
	if (__This->cachePtr == NULL)
	{
		goto error;
	}

	/* OK, we ;re done. */
	return __This;
error:
	if (catPtr != NULL) CSdeleteDatumCatalog (catPtr);
	if (__This != NULL) CS_free (__This);
	return NULL;
}
Ejemplo n.º 7
0
/*****************************************************************************
	Constructor
*/
struct csGeoid99GridFile_* CSnewGeoid99GridFile (Const char *path,long32_t bufferSize,ulong32_t flags,double density)
{
	extern double cs_K360;
	extern char cs_DirsepC;
	extern char cs_ExtsepC;
	extern char csErrnam [];

	size_t readCount;
	long lngTmp;
	double lngMin, lngMax;
	char *cp1, *cp2;
	csFILE *fstr;
	struct csGeoid99GridFile_* __This;
	char cTemp [MAXPATH];
	struct csGeoid99Hdr_ geoid99Hdr;

	/* Prepare for an error. */
	__This = NULL;
	fstr = NULL;

	/* Malloc and initialize */
	__This = CS_malc (sizeof (struct csGeoid99GridFile_));
	if (__This == NULL)
	{
		CS_erpt (cs_NO_MEM);
		goto error;
	}
	CSinitGeoid99 (__This);

	/* Set default values for all members. */
	__This->bufferSize = bufferSize;
	if (__This->bufferSize < 0) __This->bufferSize = 0;

	/* Save file path/name. */
	CS_stncp (__This->filePath,path,sizeof (__This->filePath));
	CS_stncp (cTemp,path,sizeof (cTemp));

	/* Set up the type of file.  Get cp1 to point at the file
	   name, and cp2 to point at the extension.  We consider it
	   an error if we are not given a full path name.  Note,
	   we care not about the format of the drive specification.
	   But there must be at least one directory and there must
	   be an extension. */
	cp1 = strrchr (cTemp,cs_DirsepC);
	if (cp1 == NULL)
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_INV_FILE);
		goto error;
	}
	cp1 += 1;
	cp2 = strchr (cp1,cs_ExtsepC);
	if (cp2 == NULL)
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_INV_FILE);
		goto error;
	}
	*cp2++ = '\0';
	CS_stncp (__This->fileName,cp1,sizeof (__This->fileName));

	/* The thing should have a .bin extension to be processed by us. */
	if (CS_stricmp (cp2,"bin"))
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_INV_FILE);
		goto error;
	}

	/* Get the file information header. */
	fstr = CS_fopen (__This->filePath,_STRM_BINRD);
	if (fstr == NULL)
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_DTC_FILE);
		goto error;
	}
	readCount = CS_fread (&geoid99Hdr,1,sizeof (geoid99Hdr),fstr);
	if (readCount != sizeof (geoid99Hdr))
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_INV_FILE);
		goto error;
	}
	if (CS_ferror (fstr))
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_IOERR);
		goto error;
	}

	/* Determine the size of the file. */
	if (CS_fseek (fstr,0L,SEEK_END))
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_IOERR);
		goto error;
	}
	__This->fileSize = CS_ftell (fstr);
	if (__This->fileSize < 0L)
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_IOERR);
		goto error;
	}

	/* This constructor doesn't need the file any more. */
	CS_fclose (fstr);
	fstr = NULL;

	/* Swap the bytes if necessary.  In all the data files I've seen, iKind is 32
	   bit 1.  If it is a one in the structure, than the file is in the same byte
	   order as the machine we are running on, and swapping is unnecessary.  If
	   iKind is not a one, we assume that is because of byte order, and we do a
	   swap.  Note, however, that we preserve iKind as it was before swapping so
	   that we know whether to swap or not in the other functions in this code
	   module. */

	__This->iKind = geoid99Hdr.iKind;
	if (geoid99Hdr.iKind != 1L)
	{
		/* CSbswap is a variation on CS_bswap.  CSbswap always swaps. */
		CSbswap (&geoid99Hdr,cs_BSWP_Geoid99Hdr);
	}

	/* At this point, geoid99Hdr.iKind should be a one, or either the file
	   is corrupted, or we don't understand the file format properly. */

	if (geoid99Hdr.iKind != 1L)
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_INV_FILE);
		goto error;
	}

	/* Extract the important stuff from the header.  Note that the longitude in the header
	   is a zero thru 360 value, proceeding east from Greenwich.  This makes a lot of sense
	   since Alaska crosses the 190 degree crack.  However, it is inconsistent with
	   all the other stuff.  So, we do the following kludge, which is consistent with the
	   NADCON data files. */
	lngMin = geoid99Hdr.lngMin;
	lngMax = lngMin + (geoid99Hdr.lngDelta * (geoid99Hdr.lngCount - 1));
	if (lngMin >= 180.0 || lngMax > 180.0)
	{
		__This->coverage.southWest [LNG] = geoid99Hdr.lngMin - cs_K360;
	}
	else
	{
		__This->coverage.southWest [LNG] = geoid99Hdr.lngMin;
	}
	__This->coverage.southWest [LAT] = geoid99Hdr.latMin;
	__This->deltaLng = geoid99Hdr.lngDelta;
	__This->deltaLat = geoid99Hdr.latDelta;
	__This->coverage.northEast [LNG] = __This->coverage.southWest [LNG] + (geoid99Hdr.lngDelta * (geoid99Hdr.lngCount - 1));
	__This->coverage.northEast [LAT] = __This->coverage.southWest [LAT] + (geoid99Hdr.latDelta * (geoid99Hdr.latCount - 1));
	__This->coverage.density = (__This->deltaLng < __This->deltaLat) ? __This->deltaLng : __This->deltaLat;
	if (density != 0.0) __This->coverage.density = density;
	__This->elementCount = geoid99Hdr.lngCount;
	__This->recordCount = geoid99Hdr.latCount;
	__This->recordSize = geoid99Hdr.lngCount * (int)sizeof (float);

	/* Verify the integrity of the file. */
	lngTmp = __This->recordCount * __This->recordSize + sizeof (geoid99Hdr);
	if (lngTmp != __This->fileSize)
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_INV_FILE);
		goto error;
	}

	/* Now that we know recordSize, we can adjust the bufferSize for maximum
	   efficiency. */
	if (__This->bufferSize > __This->fileSize)
	{
		__This->bufferSize = __This->fileSize;
	}
	else
	{
		if (__This->bufferSize > (3 * __This->recordSize))
		{
			/* Maximum efficiency is obtained with a buffer size whch is
			   a multiple of the record size. */
			__This->bufferSize = (__This->bufferSize / __This->recordSize) * __This->recordSize;
		}
		else
		{
			/* We require a minimum buffer size of 3 records. */
			__This->bufferSize = 3 * __This->recordSize;
		}
	}

	return (__This);
error:
	CSdeleteGeoid99GridFile (__This);
	return NULL;
}
Ejemplo n.º 8
0
/*****************************************************************************
	This function would be a private function in C++.
	This function sets the currentCell member to the cell which covers the
	provided geographic coordinate.  Returns 0 on success or a negative value
	for a system error of some sort (i.e. file I/O).  Per the design of this
	object, this function is not to be called unless the provided source
	coordinate is within the coverage of the object.
*/
int CScalcGeoid99GridFile (struct csGeoid99GridFile_* __This,double* result,Const double* sourceLL)
{
	extern double cs_One;

	int eleNbr;
	int recNbr;
	int readCount;
	int checkCount;

	long lngTmp;
	long checkSeek;
	long fpos;
	long fposBegin;
	long fposEnd;
	long swapCount;

	char* chrPtr;
	float* fltPtr;

	double centerLL [2];
	double deltaLL [2];
	
	char swapSpec [16];

	/* Float array carries the 3x3 array as follows:
		         North

		W       6  7  8      E
		e       3  4  5      a
		s       0  1  2      s
		t                    t 
			     South          */
	float array [9];

	enum edgeEffects {	edgeNone = 0,
						edgeSouthwest,
						edgeSouth,
						edgeSoutheast,
						edgeEast,
						edgeNortheast,
						edgeNorth,
						edgeNorthwest,
						edgeWest
					 } edge;
	edge = edgeNone;

	/* We are not supposed to get here unless the sourceLL is within the coverage of the
	   file object.  We make sure of that now.  This makes life much easier below.  Use the
	   CStestGeoid99GridFile function to select the proper csGeoid99GridFile object. */
	if (sourceLL [LNG] < __This->coverage.southWest [LNG] || sourceLL [LNG] > __This->coverage.northEast [LNG] ||
	    sourceLL [LAT] < __This->coverage.southWest [LAT] || sourceLL [LAT] > __This->coverage.northEast [LAT])
	{
		CS_stncp (csErrnam,"CS_geoid99:1",MAXPATH);
		CS_erpt  (cs_ISER);
		goto error;
	}
	   
	/* Compute the basic indices to the cell in the data file.  We're supposed to come up
	   with a reference to the closest point.  Since we know the source coordinate is within
	   range, dealing with the edges is rather easy. */
	eleNbr = (long)(((sourceLL [LNG] - __This->coverage.southWest [LNG]) / __This->deltaLng) + 0.5);
	recNbr = (long)(((sourceLL [LAT] - __This->coverage.southWest [LAT]) / __This->deltaLat) + 0.5);

	/* Determine the if an edge effect applies. */
	if (recNbr < 1)
	{
		recNbr = 1;
		if (eleNbr < 1)
		{
			eleNbr = 1;
			edge = edgeSouthwest;
		}
		else if (eleNbr >= (__This->elementCount - 1))
		{
			eleNbr = __This->elementCount - 2;
			edge = edgeSoutheast;
		}
		else
		{
			edge = edgeSouth;
		}
	}
	else if (recNbr >= (__This->recordCount - 1))
	{
		if (eleNbr < 1)
		{
			eleNbr = 1;
			edge = edgeNorthwest;
		}
		else if (eleNbr >= (__This->elementCount - 1))
		{
			eleNbr = __This->elementCount - 2;
			edge = edgeNortheast;
		}
		else
		{
			edge = edgeNorth;
		}
	}
	else
	{
		if (eleNbr < 1)
		{
			eleNbr = 1;
			edge = edgeWest;
		}
		else if (eleNbr > (__This->elementCount -1))
		{
			eleNbr = __This->elementCount - 2;
			edge = edgeEast;
		}
		else
		{
			edge = edgeNone;
		}
	}

	/* Compute the minimal region of the file which we need to read. */
	fposBegin = sizeof (struct csGeoid99Hdr_) + (recNbr - 1) * __This->recordSize;
	fposEnd = fposBegin + (__This->recordSize * 3);
	if (fposEnd > __This->fileSize) fposEnd = __This->fileSize;
	
	/* Do we have a buffer?  Could have been released.  Maybe this is the
	   first access. */
	if (__This->dataBuffer == NULL)
	{
		__This->dataBuffer = CS_malc ((size_t)__This->bufferSize);
		if (__This->dataBuffer == NULL)
		{
			CS_erpt (cs_NO_MEM);
			goto error;
		}

		/* Make sure the rest of this stuff knows the buffer is empty.  These values
		   will fail to match any specific file position. */
		__This->bufferBeginPosition = -1L;
		__This->bufferEndPosition = -2L;
	}

	/* See if the stuff we want is in the buffer.  Careful here, all of the intended
	   range must be in the buffer, not just a portion of it. */
	if (fposBegin < __This->bufferBeginPosition || fposBegin > __This->bufferEndPosition ||
		fposEnd   < __This->bufferBeginPosition || fposEnd   > __This->bufferEndPosition)
	{
		/* The data we need is not there; we need to read it in.  Is the file open? */
		if (__This->strm == NULL)
		{
			__This->strm = CS_fopen (__This->filePath,_STRM_BINRD);
			if (__This->strm == NULL)
			{
				CS_stncp (csErrnam,__This->filePath,MAXPATH);
				CS_erpt (cs_DTC_FILE);
				goto error;
			}
			/* We do our own buffering, turn stream buffering off. */
			setvbuf (__This->strm,NULL,_IONBF,0);
		}

		/* Compute the starting position of the actual read. */
		if (__This->bufferSize >= __This->fileSize)
		{
			__This->bufferBeginPosition = 0L;
			__This->bufferEndPosition = __This->fileSize;
			readCount = __This->fileSize;
		}
		else
		{
			/* We need to doa partial read, the normal case.  Initialize for the
			   minimal case computed above, then expand as is possible.  Note, we
			   get here only when a read has to be done. */
			__This->bufferBeginPosition = fposBegin;
			__This->bufferEndPosition = fposEnd;
			readCount = __This->bufferEndPosition - __This->bufferBeginPosition;

			/* In this section, lngTmp is the number of additional records
			   which can fit in the buffer. */
			lngTmp = (__This->bufferSize - readCount) / __This->recordSize;
			if (lngTmp > 3L)
			{
				/* Move the beginning of the read up by one half of the
				   amount of extra space in the buffer; but never past the
				   beginning of record number 1. */
				lngTmp = lngTmp / 2;
				__This->bufferBeginPosition -= __This->recordSize * lngTmp;
				if (__This->bufferBeginPosition < sizeof (struct csGeoid99Hdr_))	/*lint !e574 */
				{
					__This->bufferBeginPosition = sizeof (struct csGeoid99Hdr_);
				}
				readCount = __This->bufferEndPosition - __This->bufferBeginPosition;
			}

			lngTmp = (__This->bufferSize - readCount) / __This->recordSize;
			if (lngTmp > 3L)
			{
				/* Move the end of the read back by the amount of extra
				   space in the buffer, but never past the end of the file. */
				__This->bufferEndPosition += __This->recordSize * lngTmp;
				if (__This->bufferEndPosition > __This->fileSize)
				{
					__This->bufferEndPosition = __This->fileSize;
				}
				readCount = __This->bufferEndPosition - __This->bufferBeginPosition;
			}

			lngTmp = (__This->bufferSize - readCount) / __This->recordSize;
			if (lngTmp > 0L)
			{
				/* In case the expanded end of read exceeded the end of the
				   file, we can move the beginning of the read up some more,
				   However, never more than the beginning of the first
				   data record. */
				__This->bufferBeginPosition -= __This->recordSize * lngTmp;
				if (__This->bufferBeginPosition < sizeof (struct csGeoid99Hdr_))	/*lint !e574 */
				{
					__This->bufferBeginPosition = sizeof (struct csGeoid99Hdr_);
				}
				readCount = __This->bufferEndPosition - __This->bufferBeginPosition;
			}

			/* Defensive programming. */
			if (readCount != __This->bufferSize)
			{
				CS_stncp (csErrnam,"CS_geoid99:2",MAXPATH);
				CS_erpt (cs_ISER);
				goto error;
			}
		}

		/* OK, read in the data. */
		checkSeek = CS_fseek (__This->strm,__This->bufferBeginPosition,SEEK_SET);
		if (checkSeek < 0L)
		{
			CS_stncp (csErrnam,__This->filePath,MAXPATH);
			CS_erpt (cs_IOERR);
			goto error;
		}
		checkCount = (long)CS_fread (__This->dataBuffer,1,(size_t)readCount,__This->strm);
		if (checkCount != readCount)
		{
			CS_stncp (csErrnam,__This->filePath,MAXPATH);
			CS_erpt (cs_INV_FILE);
			goto error;
		}
		if (CS_ferror (__This->strm))
		{
			CS_stncp (csErrnam,__This->filePath,MAXPATH);
			CS_erpt (cs_IOERR);
			goto error;
		}

		/* Under certain circumstances, it will be rather inefficient to swap bytes here.
		   However, we swap here to preclude the chance of swapping the data twice, and
		   the chance that unswapped floats appear to be Nan's or something ugly like
		   that.  So, this may be somewhat inefficient, but it is the safest place
		   to put the swap.  In general, Geoid99 files are in little endian order, and
		   Geoid 2003 files are in Big endian order.  Thus, by using the appropriate
		   files, you may be able to skip the whole issue of byte swapping here
		   altogether. */

		if (__This->iKind != 1L)
		{
			/* Here if some swapping has to be done.  Need to exercise some care.
			   If the whole file was read in, we have a header on the front which
			   we don't want to swap.  Otherwise, we can treat the buffer as an
			   array of floats, which is rather simple.
			   
			   In the code below, we use lngTmp as the number of bytes on the
			   front of the buffer which we must omit from the swapping process. */

			lngTmp = (long)sizeof (struct csGeoid99Hdr_) - __This->bufferBeginPosition;
			if (lngTmp < 0) lngTmp = 0L;
			
			swapCount = (__This->bufferEndPosition - (__This->bufferBeginPosition + lngTmp)) / sizeof (float);
			sprintf (swapSpec,"%ldf",swapCount);
			chrPtr = (char *)(__This->dataBuffer) + lngTmp;
			CSbswap (chrPtr,swapSpec);
		}

		/* We have the desired data in the buffer.  If we read in the whole file,
		   we close the stream now.  No need to have the file descriptor open. */
		if (__This->bufferSize == __This->fileSize)
		{
			CS_fclose (__This->strm);
			__This->strm = NULL;
		}
	}

	/* Compute the delta into the grid cell we will contruct below.  Note, we are using adjusted
	   recNbr and eleNbr variables here. */
	centerLL [LNG] = __This->coverage.southWest [LNG] + __This->deltaLng * (double)eleNbr;
	centerLL [LAT] = __This->coverage.southWest [LAT] + __This->deltaLat * (double)recNbr;
	deltaLL [LNG] = ((sourceLL [LNG] - centerLL [LNG]) / __This->deltaLng) + cs_One;
	deltaLL [LAT] = ((sourceLL [LAT] - centerLL [LAT]) / __This->deltaLat) + cs_One;

	/* OK, the necessary stuff should be in the buffer.  We do what is necessary to
	   populate the array.  Notice, we populate the array in a way that the edge
	   effects come out correct using a standard algorithm below. */
	switch (edge) {
	case edgeNone:
		fpos = sizeof (struct csGeoid99Hdr_) + (recNbr * __This->recordSize) + (eleNbr * sizeof (float));

		chrPtr = (char *)(__This->dataBuffer) + (fpos - __This->bufferBeginPosition);
		chrPtr += __This->recordSize;
		fltPtr = (float *)(chrPtr);
		array [6] = *(fltPtr - 1);
		array [7] = *fltPtr;
		array [8] = *(fltPtr + 1);

		chrPtr = (char *)(__This->dataBuffer) + (fpos - __This->bufferBeginPosition);
		fltPtr = (float *)(chrPtr);
		array [3] = *(fltPtr - 1);
		array [4] = *fltPtr;
		array [5] = *(fltPtr + 1);

		chrPtr = (char *)(__This->dataBuffer) + (fpos - __This->bufferBeginPosition);
		chrPtr -= __This->recordSize;
		fltPtr = (float *)(chrPtr);
		array [0] = *(fltPtr - 1);
		array [1] = *fltPtr;
		array [2] = *(fltPtr + 1);
		break;

	case edgeSouthwest:
		fpos = sizeof (struct csGeoid99Hdr_);
		chrPtr = (char *)(__This->dataBuffer) + (fpos - __This->bufferBeginPosition);
		fltPtr = (float *)(chrPtr);

		array [6] = array [7] = array [8] = *fltPtr;
		array [3] = array [4] = array [5] = *fltPtr;
		array [0] = array [1] = array [2] = *fltPtr;

		deltaLL [LNG] = deltaLL [LAT] = cs_One;
		break;

	case edgeSouth:
		fpos = sizeof (struct csGeoid99Hdr_) + eleNbr * sizeof (float);
		chrPtr = (char *)(__This->dataBuffer) + (fpos - __This->bufferBeginPosition);
		fltPtr = (float *)(chrPtr);

		array [6] = array [3] = array [0] = *(fltPtr - 1);
		array [7] = array [4] = array [1] = *fltPtr;
		array [8] = array [5] = array [2] = *(fltPtr + 1);

		deltaLL [LAT] = cs_One;
		break;

	case edgeSoutheast:
		fpos = sizeof (struct csGeoid99Hdr_) + (__This->elementCount - 1) * sizeof (float);
		chrPtr = (char *)(__This->dataBuffer) + (fpos - __This->bufferBeginPosition);
		fltPtr = (float *)(chrPtr);

		array [6] = array [7] = array [8] = *fltPtr;
		array [3] = array [4] = array [5] = *fltPtr;
		array [0] = array [1] = array [2] = *fltPtr;

		deltaLL [LNG] = deltaLL [LAT] = cs_One;
		break;

	case edgeEast:
		fpos = sizeof (struct csGeoid99Hdr_) + recNbr * __This->recordSize + (__This->elementCount - 1) * sizeof (float);
		chrPtr = (char *)(__This->dataBuffer) + (fpos - __This->bufferBeginPosition);
		chrPtr += __This->recordSize;
		fltPtr = (float *)(chrPtr);

		array [6] = array [7] = array [8] = *fltPtr;

		chrPtr = (char *)(__This->dataBuffer) + (fpos - __This->bufferBeginPosition);
		fltPtr = (float *)(chrPtr);
		array [3] = array [4] = array [5] = *fltPtr;

		chrPtr = (char *)(__This->dataBuffer) + (fpos - __This->bufferBeginPosition);
		chrPtr -= __This->recordSize;
		fltPtr = (float *)(chrPtr);
		array [0] = array [1] = array [2] = *fltPtr;

		deltaLL [LNG] = cs_One;
		break;

	case edgeNortheast:
		fpos = sizeof (struct csGeoid99Hdr_) + (__This->recordCount - 1) * __This->recordSize + (__This->elementCount - 1) * sizeof (float);
		chrPtr = (char *)(__This->dataBuffer) + (fpos - __This->bufferBeginPosition);
		fltPtr = (float *)(chrPtr);

		array [6] = array [7] = array [8] = *fltPtr;
		array [3] = array [4] = array [5] = *fltPtr;
		array [0] = array [1] = array [2] = *fltPtr;

		deltaLL [LNG] = deltaLL [LAT] = cs_One;
		break;

	case edgeNorth:
		fpos = sizeof (struct csGeoid99Hdr_) + (__This->recordCount - 1) * __This->recordSize + eleNbr * sizeof (float);
		chrPtr = (char *)(__This->dataBuffer) + (fpos - __This->bufferBeginPosition);
		fltPtr = (float *)(chrPtr);

		array [6] = array [3] = array [0] = *(fltPtr - 1);
		array [7] = array [4] = array [1] = *fltPtr;
		array [8] = array [5] = array [2] = *(fltPtr + 1);

		deltaLL [LAT] = cs_One;
		break;

	case edgeNorthwest:
		fpos = sizeof (struct csGeoid99Hdr_) + (__This->recordCount - 1) * __This->recordSize;
		chrPtr = (char *)(__This->dataBuffer) + (fpos - __This->bufferBeginPosition);
		fltPtr = (float *)(chrPtr);

		array [6] = array [7] = array [8] = *fltPtr;
		array [3] = array [4] = array [5] = *fltPtr;
		array [0] = array [1] = array [2] = *fltPtr;

		deltaLL [LNG] = deltaLL [LAT] = cs_One;
		break;

	case edgeWest:
		fpos = sizeof (struct csGeoid99Hdr_) + recNbr * __This->recordSize;
		chrPtr = (char *)(__This->dataBuffer) + (fpos - __This->bufferBeginPosition);
		chrPtr += __This->recordSize;
		fltPtr = (float *)(chrPtr);
		array [6] = array [7] = array [8] = *fltPtr;

		chrPtr = (char *)(__This->dataBuffer) + (fpos - __This->bufferBeginPosition);
		fltPtr = (float *)(chrPtr);
		array [3] = array [4] = array [5] = *fltPtr;

		chrPtr = (char *)(__This->dataBuffer) + (fpos - __This->bufferBeginPosition);
		chrPtr -= __This->recordSize;
		fltPtr = (float *)(chrPtr);
		array [0] = array [1] = array [2] = *fltPtr;

		deltaLL [LNG] = cs_One;
		break;
	}

	/* Do the calculations. */
	*result = CSgeoidQterp (deltaLL,array);
	return 0;

error:
	/* Release the resources allocated to this object.  The next call to this
	   object would then require a refresh. */
	CSreleaseGeoid99GridFile (__This);

	/* Negative return indicates a system error of sorts. */
	return -1;
}
Ejemplo n.º 9
0
/******************************************************************************
	Constructor
*/
struct csRgf93ToNtf_* CSnewRgf93ToNtf (Const char *catalog)
{
	int index;
	Const char *cp;
	struct csRgf93ToNtf_ *__This;
	struct csDatumCatalog_ *catPtr;
	struct csDatumCatalogEntry_ *catEntryPtr;
	struct csRgf93ToNtfEntry_* dtEntryPtr;
	struct csRgf93ToNtfEntry_* findPtr;

	/* Prepare for an error. */
	__This = NULL;
	catPtr = NULL;
	catEntryPtr = NULL;
	dtEntryPtr = NULL;

	__This = (struct csRgf93ToNtf_*) CS_malc (sizeof (struct csRgf93ToNtf_));
	if (__This == NULL)
	{
		CS_erpt (cs_NO_MEM);
		goto error;
	}
	__This->fallback = NULL;
	__This->cachePtr = NULL;
	__This->listHead = NULL;

	/* Open the catalog file. */
	catPtr = CSnewDatumCatalog (catalog);
	if (catPtr == NULL) goto error;

	/* Get a pointer to the fallback definition.  This will be NULL if there
	   is none. */
	cp = CSgetFallbackName (catPtr);
	if (cp != NULL && *cp != '\0')
	{
		__This->fallback = CSnewFallback (cp,catalog);
		if (__This->fallback == NULL)
		{
			goto error;
		}
	}

	/* For each entry in the catalong, we build an appropriate datum
	   shift entry.  Catalog entries must carry path names to each individual
	   file.  We do not play any games with extensions here. */

	index = 0;
	for (;;)
	{
		catEntryPtr = CSgetDatumCatalogEntry (catPtr,index++);
		if (catEntryPtr == NULL) break;
		dtEntryPtr = CSnewRgf93ToNtfEntry (catEntryPtr);
		if (dtEntryPtr == NULL)
		{
			goto error;
		}
		/* Keep the list in the same order as they appear in the file. */
		if (__This->listHead == NULL)
		{
			__This->listHead = dtEntryPtr;
		}
		else
		{
			for (findPtr = __This->listHead;findPtr->next != NULL;findPtr = findPtr->next);
			findPtr->next = dtEntryPtr;
		}
	}
	CSdeleteDatumCatalog (catPtr);
	catPtr = NULL;

	/* Having done that successfully, allocate a grid cell cache.  If
	   this fails, we can either report it as an error, or just leave it
	   alone.  Lets report it as an error. */
	__This->cachePtr = CSnewLLGridCellCache (32);
	if (__This->cachePtr == NULL)
	{
		goto error;
	}

	/* OK, it's ready to go. */
	return __This;

error:
	if (catPtr != NULL) CSdeleteDatumCatalog (catPtr);
	CSdeleteRgf93ToNtf (__This);
	return NULL;
}
Ejemplo n.º 10
0
struct cs_Dtcprm_ * EXP_LVL9 CSbdclu (	Const struct cs_Csprm_ *src_cs,
										Const struct cs_Csprm_ *dst_cs,
										int dat_err,
										int blk_err)
{
	extern csThread struct csDtcach_ *csDtcachP;
	extern csThread int csDtcachI;

	unsigned short srcPrjCode;
	unsigned short dstPrjCode;
	int ii;
	

	struct cs_Dtcprm_ *dtc_ptr;
	struct csDtcach_ *ch_ptr;
	struct csDtcach_ *tmp_ptr;
	struct csDtcach_ *last_chp;

	/* Make sure we're not converting between non-georeferenced and georeferenced. */
	srcPrjCode = src_cs->prj_code;
	dstPrjCode = dst_cs->prj_code;

	if (srcPrjCode == cs_PRJCOD_NRTHSRT) srcPrjCode = cs_PRJCOD_NERTH;
	if (dstPrjCode == cs_PRJCOD_NRTHSRT) dstPrjCode = cs_PRJCOD_NERTH;
	
	if ((srcPrjCode == cs_PRJCOD_NERTH) ^ (dstPrjCode == cs_PRJCOD_NERTH))	/*lint !e514 */
	{
		CS_erpt (cs_NOT_NERTH);
		goto error;
	}

	/* If we have not done so already, allocate the cache now. */
	if (csDtcachP == NULL)
	{
		if (csDtcachI <= 1) csDtcachI = 2;
		last_chp = NULL;
		for (ii = 0;ii < csDtcachI;ii++)
		{
			ch_ptr = (struct csDtcach_ *)CS_malc (sizeof (struct csDtcach_));
			if (ch_ptr == NULL)
			{
				CS_erpt (cs_NO_MEM);
				ch_ptr = csDtcachP;
				while (ch_ptr != NULL)
				{
					tmp_ptr = ch_ptr->next;
					CS_free (ch_ptr);
					ch_ptr = tmp_ptr;
				}
				csDtcachP = NULL;
				goto error;
			}
			if (ii == 0)
			{
				csDtcachP = ch_ptr;
			}
			else
			{
				last_chp->next = ch_ptr;				/*lint !e613 */
			}
			ch_ptr->prev = last_chp;
			ch_ptr->next = NULL;
			ch_ptr->dtc_ptr = NULL;
			last_chp = ch_ptr;
		}
	}

	/* Search the existing cache entries for the desired
	   datum combination.  While doing so, we maintain
	   last_chp as a pointer to the last cache entry
	   examined.  We will use this to add a new entry to
	   the cache if we don't find the one we are looking for. */

	dtc_ptr = NULL;
	ch_ptr = csDtcachP;
	last_chp = NULL;
	while (ch_ptr != NULL)
	{
		if (ch_ptr->dtc_ptr == NULL) break;
		if (!CS_stricmp (ch_ptr->dtc_ptr->srcKeyName,src_cs->csdef.dat_knm) &&
		    !CS_stricmp (ch_ptr->dtc_ptr->trgKeyName,dst_cs->csdef.dat_knm))
		{
			dtc_ptr = ch_ptr->dtc_ptr;
			break;
		}
		last_chp = ch_ptr;
		ch_ptr = ch_ptr->next;
	}

	if (dtc_ptr == NULL)
	{
		/* Didn't find one. */
		if (ch_ptr != NULL)
		{
			/* ch_ptr is pointing to an unused entry. */
			dtc_ptr = CS_dtcsu (src_cs,dst_cs,dat_err,blk_err);
			if (dtc_ptr == NULL) goto error;
			ch_ptr->dtc_ptr = dtc_ptr;
		}
		else
		{
			/* All entries in the cache are used. Last_chp
			   points to the last entry in the cache, which is
			   also the least recently used entry. */
			ch_ptr = last_chp;
			CS_dtcls (ch_ptr->dtc_ptr);
			dtc_ptr = ch_ptr->dtc_ptr = CS_dtcsu (src_cs,dst_cs,dat_err,blk_err);
			if (dtc_ptr == NULL) goto error;
		}
	}
	else
	{
		dtc_ptr->block_err = (short)blk_err;
	}

	if (ch_ptr != csDtcachP)
	{
		/* Push this cache entry to the top of the list. */
		ch_ptr->prev->next = ch_ptr->next;			/*lint !e613 */
		if (ch_ptr->next != NULL)					/*lint !e613 */
		{
			ch_ptr->next->prev = ch_ptr->prev;		/*lint !e613 */
		}
		ch_ptr->prev = NULL;						/*lint !e613 */
		ch_ptr->next = csDtcachP;					/*lint !e613 */
		csDtcachP->prev = ch_ptr;
		csDtcachP = ch_ptr;
	}
	return (dtc_ptr);

error:
	return (NULL);
}
Ejemplo n.º 11
0
struct cs_Japan_* CSnewJgd2kGridFile (Const char *path,long32_t bufferSize,ulong32_t flags,double density)
{
	extern double cs_Sec2Deg;		/* 1.0 / 3600.0 */
	extern char cs_DirsepC;
	extern char csErrnam [];

	int st;
	size_t rdCnt;

	char *cp;
	csFILE *bStrm = NULL;
	struct cs_Japan_ *thisPtr = NULL;

	char lineBufr [MAXPATH];

	struct csJgd2kGridRecord_ minRec;
	struct csJgd2kGridRecord_ maxRec;

	/* Allocate the object structure. */
	thisPtr = CS_malc (sizeof (struct cs_Japan_));
	if (thisPtr == NULL)
	{
		CS_erpt (cs_NO_MEM);
		goto error;
	}

	/* Initialize. */
	CSinitCoverage (&thisPtr->coverage);
	thisPtr->ewDelta = ( 45.0 / 3600.0);
	thisPtr->nsDelta = ( 30.0 / 3600.0);
	thisPtr->coverage.density = thisPtr->ewDelta;
	//if (thisPtr->nsDelta > thisPtr->ewDelta) 
	//{
	//	thisPtr->coverage->density = thisPtr->nsDelta;
	//}

	thisPtr->strm = NULL;
	thisPtr->bufferSize = 64 * sizeof (struct csJgd2kGridRecord_);
	if (bufferSize > 0UL) thisPtr->bufferSize = bufferSize;
	thisPtr->dataBuffer = NULL;
	CSinitGridCell (&thisPtr->lngCell);
	CSinitGridCell (&thisPtr->latCell);
	thisPtr->lngCell.deltaLng = thisPtr->ewDelta;
	thisPtr->lngCell.deltaLat = thisPtr->nsDelta;
	thisPtr->latCell.deltaLng = thisPtr->ewDelta;
	thisPtr->latCell.deltaLat = thisPtr->nsDelta;
	thisPtr->filePath [0] = '\0';
	thisPtr->fileName [0] = '\0';

	/* Capture the file name, etc. */
	CS_stncp (thisPtr->filePath,path,sizeof (thisPtr->filePath));
	CS_stncp (lineBufr,path,sizeof (thisPtr->filePath));
	cp = strrchr (lineBufr,cs_DirsepC);
	if (cp != NULL) CS_stncp (thisPtr->fileName,(cp + 1),sizeof (thisPtr->fileName));
	else CS_stncp (thisPtr->fileName,lineBufr,sizeof (thisPtr->fileName));

	/* Save the name for error message, audit trail purposes. */
	CS_stncp (thisPtr->lngCell.sourceId,thisPtr->fileName,sizeof (thisPtr->lngCell.sourceId));
	CS_stncp (thisPtr->latCell.sourceId,thisPtr->fileName,sizeof (thisPtr->latCell.sourceId));

	/* Make a binary file which we can use.  Note this verifies the existence
	   of the file. */
	st = CSmakeBinaryJgd2kFile (thisPtr);
	if (st != 0)
	{
		CS_stncp (csErrnam,thisPtr->filePath,MAXPATH);
		CS_erpt (cs_DTC_FILE);
		goto error;
	}

	/* If we're still here, we have a binary image of the named .par file.
	   We open it and extract the first two records which should be the
	   min and max of the coverage of the file. */
	bStrm = CS_fopen (thisPtr->filePath,_STRM_BINRD);
	if (bStrm == NULL)
	{
		CS_stncp (csErrnam,thisPtr->filePath,MAXPATH);
		CS_erpt (cs_FL_OPEN);
		goto error;
	}
	rdCnt = CS_fread (&minRec,sizeof (minRec),1,bStrm);
	if (rdCnt != 1)
	{
		CS_erpt (cs_IOERR);
		goto error;
	}
	rdCnt = CS_fread (&maxRec,sizeof (maxRec),1,bStrm);
	if (rdCnt != 1)
	{
		CS_erpt (cs_IOERR);
		goto error;
	}
	CS_fclose (bStrm);
	bStrm = NULL;

	if (minRec.meshCode != 1L || maxRec.meshCode != 2L)
	{
		CS_stncp (csErrnam,"CS_japan::1",MAXPATH);
		CS_erpt (cs_ISER);
		goto error;
	}

	/* Capture the min/max of the the file coverage in the coverage object. */
	thisPtr->coverage.southWest [LNG] = (double)(minRec.deltaLng) * cs_Sec2Deg;
	thisPtr->coverage.southWest [LAT] = (double)(minRec.deltaLat) * cs_Sec2Deg;
	thisPtr->coverage.northEast [LNG] = (double)(maxRec.deltaLng) * cs_Sec2Deg;
	thisPtr->coverage.northEast [LAT] = (double)(maxRec.deltaLat) * cs_Sec2Deg;

	/* We leave the binary file closed until such time as the host application
	   requests a conversion which actually requires access to the file.  It is
	   not uncommon for geodetic transformations to list grid interpolation
	   files in their definition which are rarely used. */
	return thisPtr;
error:
	if (bStrm != NULL)
	{
		CS_fclose (bStrm);
		bStrm = NULL;
	}
	CSdeleteJgd2kGridFile (thisPtr);
	return NULL;
}
Ejemplo n.º 12
0
struct cs_Dtdef_ * EXP_LVL3 CS_dtdef (Const char *dat_nam)
{
    extern char csErrnam [];

    extern double cs_DelMax;		/* 5,000.0 */
    extern double cs_RotMax;		/* 15.0    */
    extern double cs_SclMax;		/* 200.0   */

    int st;
    int flag;
    int crypt;

    csFILE *strm;
    struct cs_Dtdef_ *dtptr;

    __ALIGNMENT__1				/* For some versions of Sun compiler. */

    struct cs_Dtdef_ dtdef;

    /* Prepare for an error condition. */
    dtptr = NULL;
    strm = NULL;

    /* Give the application first shot at satisfying this request. */
    if (CS_usrDtDefPtr != NULL)
    {
        st = (*CS_usrDtDefPtr)(&dtdef,dat_nam);
        if (st < 0) return NULL;
        if (st == 0)
        {
            dtptr = (struct cs_Dtdef_ *)CS_malc (sizeof (struct cs_Dtdef_));
            if (dtptr == NULL)
            {
                CS_erpt (cs_NO_MEM);
                goto error;
            }
            memmove (dtptr,&dtdef,sizeof (*dtptr));
            return dtptr;
        }
    }

    /* Verify the name is OK. */
    CS_stncp (dtdef.key_nm,dat_nam,sizeof (dtdef.key_nm));
    st = CS_nampp (dtdef.key_nm);
    if (st != 0) goto error;

    /* Mark this name as unencrypted so that the comaprison function
       will work. */
    dtdef.fill [0] = '\0';

    /* Open the Datum Dictionary and test its magic number. */
    strm = CS_dtopn (_STRM_BINRD);
    if (strm == NULL) goto error;

    /* Search for the requested datum. */
    flag = CS_bins (strm,(long)sizeof (cs_magic_t),0L,sizeof (dtdef),&dtdef,(CMPFUNC_CAST)CS_dtcmp);
    if (flag < 0) goto error;

    /* Tell the user if we didn't find the requested datum. */
    if (!flag)
    {
        CS_stncp (csErrnam,dat_nam,MAXPATH);
        CS_erpt (cs_DT_NOT_FND);
        goto error;
    }
    else
    {
        /* The datum exists, malloc some memory for it. */
        dtptr = (struct cs_Dtdef_ *)CS_malc (sizeof (*dtptr));
        if (dtptr == NULL)
        {
            CS_erpt (cs_NO_MEM);
            goto error;
        }

        /* Read it in. */
        if (!CS_dtrd (strm,dtptr,&crypt))
        {
            goto error;
        }
    }

    /* We don't need the datum dictionary anymore. */
    if (!cs_DtStrmFlg)
    {
        CS_dtDictCls (strm);
    }
    strm = NULL;

    /* Verify that the values are not completely bogus. */
    if (fabs (dtptr->delta_X) > cs_DelMax ||
            fabs (dtptr->delta_Y) > cs_DelMax ||
            fabs (dtptr->delta_Z) > cs_DelMax ||
            fabs (dtptr->rot_X) > cs_RotMax    ||
            fabs (dtptr->rot_Y) > cs_RotMax    ||
            fabs (dtptr->rot_Z) > cs_RotMax    ||
            fabs (dtptr->bwscale) > cs_SclMax)
    {
        CS_stncp (csErrnam,dat_nam,MAXPATH);
        CS_erpt (cs_DTDEF_INV);
        goto error;
    }

    /* Return the initialized datum structure to the user. */
    return (dtptr);

error:
    if (strm != NULL) CS_dtDictCls (strm);
    if (dtptr != NULL)
    {
        CS_free (dtptr);
        dtptr = NULL;
    }
    return (dtptr);
}
Ejemplo n.º 13
0
EcsCsvStatus TcsNameMapper::ReadFromStream (char* pBuffer, size_t const bufferSize)
{
	if (NULL == pBuffer)
		return csvNoFile;

    EcsCsvStatus csvStatus  = csvOk;

    size_t const lastIndex = bufferSize - 1; // Last index of the stream buffer (file)

    // Temporary line buffer
	size_t lineBufferLength = 300; // Expected maximum length of a line
	char* pLineBuffer = (char*) CS_malc (lineBufferLength);
	if (NULL == pLineBuffer)
	{
		CS_erpt(cs_NO_MEM);
		return csvInternal;
	}

	size_t lineStart = 0; // Start index of the line
    bool isEOF = false;
	size_t i = 0; // Current index in the stream buffer (file)
	while(i < bufferSize && !isEOF)
	{
        // Current character from the buffer
		char const* curChar = &pBuffer[i];
        
        // Advance [i] to next line breaking character
		if ('\n' != *curChar && '\r' != *curChar)
		{
			// Pass any non-line breaking character;
			// [lineStart] we still keep at the line start position
			if (i != lastIndex)
			{
				++i;
				continue;
			}

            // Last line. Last line need to be processed. EOF is handled below.
		}

        // Line length
		// If the buffer did start with empty lines only, we're getting an 0-size length here
        size_t lineLength = i - lineStart;
		
		// Advance [i] beyond all ine breaking characters (\n & \r)
		while(i < bufferSize)
		{
			curChar = &pBuffer[i];
			if ('\n' == *curChar || '\r' == *curChar)
			{
				++i;
				continue;
			}

            break;
		}
        // Handle the end of the file
        if (i >= bufferSize - 1)
            isEOF = true;

		// Resize the temp line buffer if it is too small
		if (lineBufferLength < lineLength)
		{
			lineBufferLength = lineLength + (1 << 6);
			char* pReBuffered = (char*) CS_ralc (pLineBuffer, lineBufferLength);
			if (NULL == pReBuffered)
			{
				CS_erpt(cs_NO_MEM); //pLineBuffer still has to be free - see below
				return csvNoFile;
			}
			pLineBuffer = pReBuffered;
		}

        // Fill up temp line buffer with current line
		memset(pLineBuffer, '\0', lineBufferLength);
		memcpy(pLineBuffer, &pBuffer[lineStart], lineLength);

        // Next line starting position
		lineStart = i; //our next potential start; EOF doesn't matter here

		// Temporary line buffer (wide char)
        wchar_t wcharBuffer[1 << 10] = { L'\0' };
        mbstowcs(wcharBuffer, pLineBuffer, lineLength);
        wcharBuffer[lineLength] = L'\n'; // Add a newline character. This will be needed below in the csv support class.

        // Prepare a line stream
        std::wstringstream inStrm(wcharBuffer);
        inStrm.seekg(0);

		// Skip the line if it looks like a label line. Note that we
		// require a label line to be a valid CSV record, even though we
		// ignore the contents.
        // A data line need to start with a digit otherwise it is expected to be a label/comment line and we skip
		if (!isdigit(pLineBuffer[0]))
		{
            //// Validate the record
            //std::wstring lineBufferUnused;
            //csvStatus = csGetCsvRecord (lineBufferUnused, inStrm, Delimiters);
		    //if (csvOk != csvStatus)
			//    break;

            // Skip the line
            // Note that [i] and [lineStart] point already to the beginning of the next line, or EOF...
            continue;
		}
        
        // Create name map item (Data of one line)
        TcsNameMap nextItem;
        TcsCsvStatus status;
        // Read the data from the line
		csvStatus= nextItem.ReadFromStream (inStrm, status);
		if (csvStatus == csvOk)
		{
            // Add new item to mapping collection
			Add (nextItem);
		}
		else
		{
			continue;
		}
	}

    // Free temp line buffer
	CS_free(pLineBuffer);
	pLineBuffer = NULL;
	
	return csvStatus;
}
Ejemplo n.º 14
0
/******************************************************************************
	Constructor: This is a constructor for the "Entry" object.  A linked list
	of these "Entry" objects is underlying structure of the main object.

	NOTE: the specific of handling different file types are handled here.
*/
struct csNad27ToCsrsEntry_* CSnewNad27ToCsrsEntry (struct csDatumCatalogEntry_* catPtr)
{
	extern char cs_DirsepC;
	extern struct csNad27ToAts77_* csNad27ToAts77;
	extern struct csAts77ToCsrs_* csAts77ToCsrs;

	int st;
	char *cp;
	struct csNad27ToCsrsEntry_* __This;

	/* Prepare for an error. */
	__This = NULL;

	/* Allocate some storage. */
	__This = (struct csNad27ToCsrsEntry_*) CS_malc (sizeof (struct csNad27ToCsrsEntry_));
	if (__This == NULL)
	{
		CS_erpt (cs_NO_MEM);
		goto error;
	}
	__This->next = NULL;
	__This->type = dtNad27ToCsrsNoneYet;
	__This->density = catPtr->density;
	__This->pointers.c2DatumPtr = NULL;

	/* See if this is the special case where conversion required is through the
	   ATS77 facility. */
	cp = strrchr (catPtr->pathName,cs_DirsepC);
	if (cp != NULL) cp += 1;
	else cp = catPtr->pathName;
	if (!CS_strnicmp (cp,"Ats77ToCsrs",11))
	{
		/* Here if we have a Maritime Province reference. */
		__This->pointers.nad27ToCsrsViaXfrm = (struct csNad27ToCsrsXfrm_ *)CS_malc (sizeof (struct csNad27ToCsrsXfrm_));
		if (__This->pointers.nad27ToCsrsViaXfrm == NULL)
		{
			CS_erpt (cs_NO_MEM);
			goto error;
		}
		__This->pointers.nad27ToCsrsViaXfrm->nad27ToAts77 = NULL;
		__This->pointers.nad27ToCsrsViaXfrm->ats77ToCsrs = NULL;
		__This->type = dtNad27ToCsrsXfrm;
		st = CSn27a77Init ();
		if (st == 0)
		{
			__This->pointers.nad27ToCsrsViaXfrm->nad27ToAts77 = csNad27ToAts77;
			if (__This->density == 0.0)
			{
				__This->density = 0.100000;
			}
		}
		else
		{
			 goto error;
		}
		st = CSats77Init ();
		if (st == 0)
		{
			__This->pointers.nad27ToCsrsViaXfrm->ats77ToCsrs = csAts77ToCsrs;
			if (__This->density < 0.00833333333)
			{
				__This->density = 0.098333333333;
			}
		}
		else
		{
			goto error;
		}
	}
	else
	{
		/* Set up the file; construct a Canadian National Transformation,
		   Version 2 object.  It's smart enough to deal with the differences
		   between the Canadian format and the Australian variation. */
		__This->pointers.c2DatumPtr = CSnewDatumShiftCa2 (dtcTypeAustralian,catPtr->pathName,catPtr->bufferSize,catPtr->flags,catPtr->density);
		if (__This->pointers.c2DatumPtr == NULL)
		{
			goto error;
		}
		__This->type = dtNad27ToCsrsC2;
	}
	return __This;

error:
	CSdeleteNad27ToCsrsEntry (__This);
	return NULL;
}
Ejemplo n.º 15
0
Archivo: CS_ntv2.c Proyecto: asir6/Colt
int CSinitNTv2 (struct cs_NTv2_* thisPtr,Const char *filePath,long32_t bufferSize,
															  ulong32_t flags,
															  double density)
{
	extern double cs_Sec2Deg;
	extern char cs_DirsepC;
	extern char csErrnam [];

	short idx;
	short parIdx;

	int overlap;
	int seekStat;

	size_t readCnt;
	size_t readCntRq;
	size_t malcCnt;
	long32_t skipAmount;

	char *cp;
	struct csNTv2SubGrid_* subPtr;
	struct csNTv2SubGrid_* kidPtr;
	struct csNTv2SubGrid_* parPtr;

	union csNtv2Hdrs_ fileHdr;
	struct csNTv2SubHdr_ fileSubHdr;

	char ctemp [MAXPATH];

	csFILE* stream = NULL;

	/* Try to prevent a likely crash. */
	if (thisPtr == NULL)
	{
		CS_stncp (csErrnam,"CS_ntv2::1",MAXPATH);
		CS_erpt (cs_ISER);
		return -1;
	}

	/* In the event of an error; this eliminates duplicating this many many
	   times. */
	CS_stncp (csErrnam,filePath,MAXPATH);

	/* Initialize the structure to harmless values. */
	thisPtr->SubGridDir = NULL;
	thisPtr->fileImage = NULL;
	thisPtr->fileImageSize = 0;
	thisPtr->HdrRecCnt = 0;
	thisPtr->SubCount = 0;
	thisPtr->RecSize = 16;
	thisPtr->CellIsValid = FALSE;
	thisPtr->SubOverlap = (short)((flags & 0x01) != 0);
	thisPtr->IntType = csNTv2TypeNone;
	thisPtr->BufferSize = bufferSize;
	thisPtr->sourceId [0] = '\0';
	if (thisPtr->BufferSize <= 0) thisPtr->BufferSize = csNTv2BufrSz;
	if (thisPtr->BufferSize <= 4096) thisPtr->BufferSize = 4096;
	CSinitNTv2GridCell (&thisPtr->longitudeCell);
	CSinitNTv2GridCell (&thisPtr->latitudeCell);

	/* Deal with the file path. */
	CS_stncp (thisPtr->FilePath,filePath,sizeof (thisPtr->FilePath));

	/* Extract and save last 15 characters of the data file name. */
	cp = strrchr (thisPtr->FilePath,cs_DirsepC);
	if (cp == NULL) cp = thisPtr->FilePath;
	CS_stncp (ctemp,cp,sizeof (ctemp));
	cp = strrchr (ctemp,'.');
	if (cp != NULL) *cp = '\0';
	cp = ctemp;
	if (strlen (ctemp) > 15)
	{
		cp = ctemp + strlen (ctemp) - 15;
	}
	CS_stncp (thisPtr->FileName,cp,sizeof (thisPtr->FileName));

	/* Open the file. */
	stream = CS_fopen (thisPtr->FilePath,_STRM_BINRD);
	if (stream == NULL)
	{
		CS_erpt (cs_DTC_FILE);
		goto error;
	}
	setvbuf (stream,NULL,_IOFBF,(size_t)thisPtr->BufferSize);

	/* We've got a file.  Read the header. */
	readCnt = CS_fread (&fileHdr,1,sizeof (fileHdr),stream);
	if (CS_ferror (stream))
	{
		CS_erpt (cs_IOERR);
		goto error;
	}
	if (readCnt != sizeof (fileHdr))
	{
		CS_erpt (cs_INV_FILE);
		goto error;
	}

	/* Verify that this is the kind of file we know how to deal with. */
	if (strncmp (fileHdr.Canadian.titl01,"NUM_OREC",8))
	{
		/* Opps!!! Not a CaNTv2 file. */
		CS_erpt (cs_INV_FILE);
		goto error;
	}

	/* Determine the type/source of the file. */
	if (fileHdr.Canadian.titl02 [0] == 'N' &&
	    fileHdr.Canadian.titl02 [1] == 'U')
	{
		/* It appears that the file is Canadian. */
		thisPtr->IntType = csNTv2TypeCanada;
		skipAmount = sizeof (struct csNTv2HdrCa_);
		CS_bswap (&fileHdr.Canadian,cs_BSWP_NTv2HdrCa);
	}
	else if (fileHdr.Australian.titl02 [0] == 'N' &&
			 fileHdr.Australian.titl02 [1] == 'U')
	{
		/* It appears to be an Australian file. */
		thisPtr->IntType = csNTv2TypeAustralia;
		skipAmount = sizeof (struct csNTv2HdrAu_);
		CS_bswap (&fileHdr.Australian,cs_BSWP_NTv2HdrAu);
	}
	else
	{
		/* Opps!!! Don't know what kind of file it is. */
		CS_erpt (cs_INV_FILE);
		goto error;
	}

	/* Reposition the input file as is appropriate due to the
	   type of file.  A little hoeky, but it should be portable. */
	seekStat = CS_fseek (stream,skipAmount,SEEK_SET);
	if (seekStat != 0)
	{
		CS_erpt (cs_INV_FILE);
		goto error;
	}

	/* Extract the valuable stuff. */
	if (thisPtr->IntType == csNTv2TypeCanada)
	{
		thisPtr->HdrRecCnt = fileHdr.Canadian.num_orec;
		thisPtr->SubCount = fileHdr.Canadian.num_file;
		thisPtr->SubHdrRecCnt = fileHdr.Canadian.num_srec;
	}
	else
	{
		thisPtr->HdrRecCnt = fileHdr.Australian.num_orec;
		thisPtr->SubCount = fileHdr.Australian.num_file;
		thisPtr->SubHdrRecCnt = fileHdr.Australian.num_srec;
	}
	/* The rest of the header is pretty much useless. */

	/* Now, we deal with the sub-directories.  THese are very
	   important. */
	malcCnt = sizeof (struct csNTv2SubHdr_) * (ulong32_t)thisPtr->SubCount;
	thisPtr->SubGridDir = (struct csNTv2SubGrid_ *)CS_malc (malcCnt);
	if (thisPtr->SubGridDir == NULL)
	{
		CS_erpt (cs_NO_MEM);
		goto error;
	}

	/* Initialize (i.e. construct) each of the sub-grid items we just
	   allocated. */
	for (idx = 0;idx < thisPtr->SubCount;idx += 1)
	{
		subPtr = &thisPtr->SubGridDir [idx];

		/* Initialize to a boundary which will not match anything. */
		subPtr->SouthWest [LNG] = 180.0;
		subPtr->SouthWest [LAT] = 90.0;
		subPtr->NorthEast [LNG] = -180.0;
		subPtr->NorthEast [LAT] = -90.0;

		/* Remember, these values as extracted from the file itself are
		   WEST positive. */
		subPtr->SeReference [LNG] =  180.0;
		subPtr->SeReference [LAT] =   90.0;
		subPtr->NwReference [LNG] = -180.0;
		subPtr->NwReference [LAT] =  -90.0;

		subPtr->DeltaLng  = 0.0;
		subPtr->DeltaLat  = 0.0;
		subPtr->Density   = 0.0;
		subPtr->FirstRecord = -1;
		subPtr->GridRecCnt = 0;
		subPtr->ParentIndex = -1;
		subPtr->ChildIndex = -1;
		subPtr->RowCount = 0;
		subPtr->ElementCount = 0;
		subPtr->RowSize = 0;
		subPtr->Cacheable = FALSE;
		subPtr->Name [0] = '\0';
		subPtr->Parent [0] = '\0';
	}

	/* Once for each sub-grid in the file; read in the header.  At this point,
	   we just read them in.  Later on, we peruse the array and figure out
	   who the mamas and the papas are. */
	for (idx = 0;idx < thisPtr->SubCount;idx += 1)
	{
		/* Kludge to handle the variation in format.  Doing this right
		   would require duplication of a whole bunch of code. So . . . */
		readCntRq = sizeof (fileSubHdr);
		if (thisPtr->IntType == csNTv2TypeAustralia) readCntRq -= 4;

		readCnt = CS_fread (&fileSubHdr,1,readCntRq,stream);
		if (CS_ferror (stream))
		{
			CS_erpt (cs_IOERR);
			goto error;
		}
		if (readCnt != readCntRq)
		{
			CS_erpt (cs_INV_FILE);
			goto error;
		}
		if (strncmp (fileSubHdr.titl01,"SUB_NAME",8))
		{
			CS_erpt (cs_INV_FILE);
			goto error;
		}
		if (thisPtr->IntType == csNTv2TypeCanada)
		{
			CS_bswap (&fileSubHdr,cs_BSWP_NTv2SubHdrCA);
		}
		else
		{
			CS_bswap (&fileSubHdr,cs_BSWP_NTv2SubHdrAU);
		}

		/* Collect the useful stuff. */		
		subPtr = &thisPtr->SubGridDir [idx];

		/* Data for each sub-grid immediately follows the sub-grid header. */
		subPtr->FirstRecord = CS_ftell (stream);

		/* These boundaries are rational east positive boundaries. */
		subPtr->SouthWest [LNG] = -fileSubHdr.w_long * cs_Sec2Deg;
		subPtr->SouthWest [LAT] =  fileSubHdr.s_lat  * cs_Sec2Deg;
		subPtr->NorthEast [LNG] = -fileSubHdr.e_long * cs_Sec2Deg;
		subPtr->NorthEast [LAT] =  fileSubHdr.n_lat  * cs_Sec2Deg;

		/* These boundaries are the screwy west positive ones used in the
		   NTv2 format. */
		subPtr->SeReference [LNG] = fileSubHdr.e_long * cs_Sec2Deg;
		subPtr->SeReference [LAT] = fileSubHdr.s_lat  * cs_Sec2Deg;
		subPtr->NwReference [LNG] = fileSubHdr.w_long * cs_Sec2Deg;
		subPtr->NwReference [LAT] = fileSubHdr.n_lat  * cs_Sec2Deg;

		/* The remainder of this is pretty rational. */
		subPtr->DeltaLng  = fileSubHdr.long_inc * cs_Sec2Deg;
		subPtr->DeltaLat  = fileSubHdr.lat_inc  * cs_Sec2Deg;

		/* We do not use Density in the calculations.  It is only used to
		   select one sub-grid over another in the case of overlap.  Yes,
		   I know.  The sub-grids at the same level are not suppoded to
		   overlap; but they do.  Call it job security for you an me. */
		subPtr->Density = (subPtr->DeltaLat < subPtr->DeltaLng) ? subPtr->DeltaLat : subPtr->DeltaLng;

		/* If the user has specified a default density value, we use it. */
		if (density != 0.0)
		{
			subPtr->Density = density;
		}

		/* Save the name for reporting purposes. */
		CS_stncp (subPtr->Name,fileSubHdr.sub_name,9);
		CS_stncp (subPtr->Parent,fileSubHdr.parent,9);

		subPtr->GridRecCnt = fileSubHdr.gs_count;
		/* WEST Positive, dummy.  The extra .01 is to eliminate possible fuzz
		   in the double portion of the calculations. */
		subPtr->RowCount = (unsigned short)(((subPtr->NwReference [LAT] - subPtr->SeReference [LAT]) / subPtr->DeltaLat) + 1.01);
		subPtr->ElementCount = (unsigned short)(((subPtr->NwReference [LNG] - subPtr->SeReference [LNG]) / subPtr->DeltaLng) + 1.01);
		subPtr->RowSize = (unsigned short)(subPtr->ElementCount * thisPtr->RecSize);

		/* Certain sub grids are not cacheable.  In the Canadian file, the region
		   which is not cacheable is rather small.  We use the csCaNTv2KludgeTable
		   to handle it.  The one Austrailian sub-grid we've seen is screwed up,
		   so we disable cacheing (at least for now), for all Australian files.
		   Australian, in this context, means file in the old Australian format,
		   not necessarily data files covering Australian geography.
		   
		   In the case of the Spanish variation, parent grids overlap, and
		   therefore none of the sub-grids are cacheable. */
//???? 	subPtr->Cacheable = (short)((thisPtr->IntType == csNTv2TypeCanada) && (thisPtr->SubOverlap == 0));
		subPtr->Cacheable = FALSE;

		/* Skip over the data records in the file. */
		skipAmount = subPtr->GridRecCnt * thisPtr->RecSize;
		seekStat = CS_fseek (stream,skipAmount,SEEK_CUR);
		if (seekStat != 0)
		{
			CS_erpt (cs_INV_FILE);
			goto error;
		}
	}

	/* Now we figure out who the mammas and the pappas are.  Note, all we have
	   to work with are parent names.  Therefore, we have to work bassackwards.

	   End result of all of this, is that each child needs to have the index
	   of its parent; and each sub-grid that has a child needs to be so marked. */
	for (idx =  0;idx < thisPtr->SubCount;idx += 1)
	{
		kidPtr = &thisPtr->SubGridDir [idx];
		if (CS_stricmp (kidPtr->Parent,"NONE    "))
		{
			/* Its a child, find the parent. */
			for (parIdx = 0;parIdx < thisPtr->SubCount;parIdx += 1)
			{
				parPtr = &thisPtr->SubGridDir [parIdx];
				if (!CS_stricmp (kidPtr->Parent,parPtr->Name))
				{
					/* Save the index of the parent. */
					kidPtr->ParentIndex = parIdx;

					/* Mark the parent as having a child, if not already so marked. */
					if (parPtr->ChildIndex == -1 || parPtr->ChildIndex > idx)
					{
						parPtr->ChildIndex = idx;
					}
				}
			}
		} 
	}

	/* To accomodate the Spanish (and perhaps others in the future, we check the
	   parent grids in the list of sub-grids for overlap.  If overlap exists,
	   we turn on the SubOverlap flag.  Of course, if this flag is already on,
	   we have nothing to do.  If we did indeed turn on the SubOverlap flag,
	   we need to cruise through all the sub-grids and set the Cacheable flag
	   to false to assure that no data from this file makes it to the grid cell
	   cache. */
	if (thisPtr->SubOverlap == 0)
	{
		for (parIdx = 0;parIdx < thisPtr->SubCount && thisPtr->SubOverlap == 0;parIdx += 1)
		{
			parPtr = &thisPtr->SubGridDir [parIdx];
			/* Top level grids only, we know the children overlap. */
			if (parPtr->ParentIndex >= 0) continue;

			overlap = FALSE;
			for (idx = 0;idx < thisPtr->SubCount;idx += 1)
			{
				if (idx == parIdx) continue;
				subPtr = &thisPtr->SubGridDir [idx];
				if (subPtr->ParentIndex >= 0) continue;
				
				/* See if subPtr overlaps with parPtr. */
				overlap  = subPtr->SeReference [LNG] > parPtr->SeReference [LNG] &&
						   subPtr->SeReference [LAT] > parPtr->SeReference [LAT] &&
						   subPtr->SeReference [LNG] < parPtr->NwReference [LNG] &&
						   subPtr->SeReference [LAT] < parPtr->NwReference [LAT];
				overlap |= subPtr->NwReference [LNG] > parPtr->SeReference [LNG] &&
						   subPtr->NwReference [LAT] > parPtr->SeReference [LAT] &&
						   subPtr->NwReference [LNG] < parPtr->NwReference [LNG] &&
						   subPtr->NwReference [LAT] < parPtr->NwReference [LAT];
				if (overlap)
				{
					thisPtr->SubOverlap = TRUE;		/* for testing ease */
				}
			}
		}
	
		if (thisPtr->SubOverlap != 0)
		{
			for (idx = 0;idx < thisPtr->SubCount;idx += 1)
			{
				subPtr = &thisPtr->SubGridDir [idx];
				subPtr->Cacheable = FALSE;
			}
		}
	}

	/* OK, we should be ready to rock and roll.  We close the Stream until
	   we actually need it.  Often, we get constructed just so there is a
	   record of the coverage afforded by the file. */
	if (stream != NULL)
	{
		CS_fclose (stream);
		stream = NULL;
	}
	csErrnam [0] = '\0';
	return 0;

error:
	if (stream != NULL)
	{
		CS_fclose (stream);
		stream = NULL;
	}
	if (thisPtr->SubGridDir != NULL)
	{
		CS_free (thisPtr->SubGridDir);
		thisPtr->SubGridDir = NULL;
	}
	thisPtr->HdrRecCnt = 0;
	thisPtr->SubCount = 0;
	thisPtr->RecSize = 16;
	thisPtr->CellIsValid = FALSE;
	thisPtr->SubOverlap = (short)((flags & 0x01) != 0);
	thisPtr->IntType = csNTv2TypeNone;
	thisPtr->BufferSize = bufferSize;
	thisPtr->sourceId [0] = '\0';
	if (thisPtr->BufferSize <= 0) thisPtr->BufferSize = csNTv2BufrSz;
	if (thisPtr->BufferSize <= 4096) thisPtr->BufferSize = 4096;
	CSinitNTv2GridCell (&thisPtr->longitudeCell);
	CSinitNTv2GridCell (&thisPtr->latitudeCell);
	return -1;
}
Ejemplo n.º 16
0
struct cs_Csprm_ * EXP_LVL9 CSbcclu (Const char *cs_name)
{
	extern csThread struct csCscach_ *csCscachP;
	extern csThread int csCscachI;

	cs_Register struct csCscach_ *ch_ptr;

	int ii;

	struct csCscach_ *tmp_ptr;
	struct csCscach_ *last_chp;
	struct cs_Csprm_ *cs_ptr;

	char kyTemp [cs_KEYNM_DEF + 2];

	CS_stncp (kyTemp,cs_name,sizeof (kyTemp));
	if (CS_nampp (kyTemp) != 0) return ((struct cs_Csprm_ *)0);

	if (csCscachP == NULL)
	{
		/* Here to allocate the cache. */

		if (csCscachI <= 1) csCscachI = 2;
		last_chp = NULL;
		for (ii = 0;ii < csCscachI;ii++)
		{
			ch_ptr = (struct csCscach_ *)CS_malc (sizeof (struct csCscach_));
			if (ch_ptr == NULL)
			{
				CS_erpt (cs_NO_MEM);
				ch_ptr = csCscachP;
				while (ch_ptr != NULL)
				{
					tmp_ptr = ch_ptr->next;
					CS_free (ch_ptr);
					ch_ptr = tmp_ptr;
				}
				csCscachP = NULL;
				goto error;
			}
			if (ii == 0)
			{
				csCscachP = ch_ptr;
			}
			else
			{
				last_chp->next = ch_ptr;		/*lint !e613 */
			}
			ch_ptr->prev = last_chp;
			ch_ptr->next = NULL;
			ch_ptr->cs_ptr = NULL;
			ch_ptr->cs_nam [0] = '\0';
			last_chp = ch_ptr;
		}
	}

	/* At this point, we have a cache.  It may be empty, but
	   it exists and has more than one entry. */

	cs_ptr = NULL;
	ch_ptr = csCscachP;
	last_chp = NULL;
	while (ch_ptr != NULL)
	{
		if (ch_ptr->cs_ptr == NULL) break;
		if (!CS_stricmp (ch_ptr->cs_nam,kyTemp))
		{
			cs_ptr = ch_ptr->cs_ptr;
			break;
		}

		last_chp = ch_ptr;
		ch_ptr = ch_ptr->next;
	}

	/* If cs_ptr is NULL, we havn't found the one we are looking
	   for.  We must add it to the cache. */

	if (cs_ptr == NULL)
	{
		/* If ch_ptr is not NULL, it must point to the
		   first element in the linked list which is
		   unused.  We simply use this entry. */

		if (ch_ptr != NULL)
		{
			ch_ptr->cs_ptr = CS_csloc (kyTemp);
			if (ch_ptr->cs_ptr == NULL)
			{
				goto error;
			}
			(void)CS_stncp (ch_ptr->cs_nam,kyTemp,sizeof (ch_ptr->cs_nam));
			cs_ptr = ch_ptr->cs_ptr;
		}
		else
		{
			/* We need to reuse an existing entry.  We always
			   reuse that the last entry in the linked list
			   as it should be the least recently accessed
			   entry in the list. */

			ch_ptr = last_chp;
			CS_free (ch_ptr->cs_ptr);
			ch_ptr->cs_nam [0] = '\0';
			ch_ptr->cs_ptr = CS_csloc (kyTemp);
			(void)CS_stncp (ch_ptr->cs_nam,kyTemp,sizeof (ch_ptr->cs_nam));
			cs_ptr = ch_ptr->cs_ptr;
		}
	}

	/* OK, we should now have a coordinate system pointer.  All we
	   need to do is make this one first on the list as an indication
	   that it was the most recently accessed.  Of course, if it
	   is already the first on the list, we do not need to do
	   anything.  The following code assumes that the entry being
	   processed is not the first on the list (i.e. ch_ptr->prev
	   is not NULL). */

	if (ch_ptr != csCscachP)
	{
		/* Remove the current entry from the list. */

		ch_ptr->prev->next = ch_ptr->next;				/*lint !e613 */
		if (ch_ptr->next != NULL)						/*lint !e613 */
		{
			ch_ptr->next->prev = ch_ptr->prev;			/*lint !e613 */
		}

		/* Now we insert it at the top of the list. */

		ch_ptr->prev = NULL;							/*lint !e613 */
		ch_ptr->next = csCscachP;						/*lint !e613 */
		csCscachP->prev = ch_ptr;
		csCscachP = ch_ptr;
	}

	/* Return a pointer to the located coordinate system. */

	return (cs_ptr);

error:
	return ((struct cs_Csprm_ *)0);
}
Ejemplo n.º 17
0
Archivo: CS_ntv2.c Proyecto: asir6/Colt
/* Interpolation Calculator
	The comment below is stale now that we store the entire grid file in memory,
	but is interesting nonetheless as it documents unusual properties of NTv2
	grids.

	====

	Due to a bust in the file format, we do not buffer up grid cells and stuff.
	There are a couple of sub-grids which overlap other grids in such a way that
	buffering can cause errors.  So, at least until (if ever) the data file is
	corrected, we do no buffering of the grid cells.

	Also, this file format is being adopted by others, such as the Australians.
	We don't know what they are going to do.  So to be safe, NO BUFFERING OF
	GRID CELLS.

	Also, due to the sub-grid nature of the data file, we do not buffer the
	data file in any special way; we simply use normal stream buffering.  We
	do, however, use a normal stream buffer of the size specified in the
	main object.
*/
int CScalcNTv2 (struct cs_NTv2_* thisPtr,double deltaLL [2],Const double source [2])
{
	extern double cs_Zero;				/* 0.0 */
	extern double cs_LlNoise;			/* 1.0E-12 */
	extern char csErrnam [MAXPATH];

	short onLimit;
	unsigned short eleNbr, rowNbr;

	int rtnValue;
	int swapping;

	csFILE* stream = NULL;
	size_t readCnt;
	long32_t filePosition;
	struct csNTv2SubGrid_ *cvtPtr;

	double wpLL [2];
	double seCell [2];
	double nwCell [2];

	struct TcsCaNTv2Data southEast;
	struct TcsCaNTv2Data southWest;
	struct TcsCaNTv2Data northEast;
	struct TcsCaNTv2Data northWest;

	/* Until we know differently. */
	rtnValue = csGRIDI_ST_SYSTEM;
	thisPtr->CellIsValid = FALSE;

	/* In case of an error.  This saves duplication of this many many times. */
	CS_stncp (csErrnam,thisPtr->FilePath,MAXPATH);

	/* Remember, source is East Positive.  All NTv2 files are West Positive. */

	/* Locate the appropriate sub-grid.  If there is none, than there is no
	   coverage.  There are two algorithms:  the original one and one invented
	   to cater to the Spaniards (and maybe some others in the future).
	   
	   In the original algorithm, we search through the top level of parent
	   grids looking for coverage.  The top level parents are those which have
	   no parent.  If none is found, there is no coverage.  If we locate a parent
	   which provides coverage, we examine all children of that parent looking
	   for a sub-grid; and so on.
	   
	   In the Spanish algorithm, we search all grids, and choose the grid which
	   produces the smallest cell size.  This is necessary as the grids are
	   allowed to overlap in the Spanish variation. */
	cvtPtr = CSlocateSubNTv2 (thisPtr,source);
	
	/* OK, if cvtPtr is not NULL, its a pointer to the appropriate sub grid
	   for this conversion. */
	if (cvtPtr != NULL)
	{
		/* NTv2 files consider west longitude to be positive. */
		wpLL [LNG] = -source [LNG];
		wpLL [LAT] =  source [LAT];

		/* Determine the status of onLimit.  This indicates if the point to be
		   converted actually resides on the northern or western edge of the
		   grid cell. */
		onLimit = 0;
		if (fabs (wpLL [LAT] - cvtPtr->NwReference [LAT]) <= cs_LlNoise) onLimit |= 1;
		if (fabs (wpLL [LNG] - cvtPtr->NwReference [LNG]) <= cs_LlNoise) onLimit |= 2;

		if (thisPtr->fileImage == NULL)
		{
			stream = CS_fopen (thisPtr->FilePath,_STRM_BINRD);
			if (stream == NULL)
			{
				CS_stncp (csErrnam,thisPtr->FilePath,MAXPATH);
				CS_erpt (cs_DTC_FILE);
				goto error;
			}
			setvbuf (stream,NULL,_IOFBF,(size_t)thisPtr->BufferSize);

			// Determine the size of the file.
			if (CS_fseek (stream,0L,SEEK_END))
			{
				CS_stncp (csErrnam,thisPtr->FilePath,MAXPATH);
				CS_erpt (cs_IOERR);
				goto error;
			}
			thisPtr->fileImageSize = CS_ftell (stream);
			if (thisPtr->fileImageSize < 0L)
			{
				CS_stncp (csErrnam,thisPtr->FilePath,MAXPATH);
				CS_erpt (cs_IOERR);
				goto error;
			}
			if (CS_fseek (stream, 0L, SEEK_SET))
			{
				CS_stncp (csErrnam,thisPtr->FilePath,MAXPATH);
				CS_erpt (cs_IOERR);
				goto error;
			}

			// Prepare memory
			thisPtr->fileImage = (char*)CS_malc(thisPtr->fileImageSize);
			if (thisPtr->fileImage == NULL)
			{
				CS_erpt (cs_NO_MEM);
				goto error;
			}

			// Copy everything into the memory
			readCnt = CS_fread(thisPtr->fileImage,
				1,
				thisPtr->fileImageSize,
				stream);
			if (CS_ferror(stream))
			{
				CS_erpt (cs_IOERR);
				goto error;
			}

			CS_fclose (stream); stream = NULL;
		}

		/* Compute onLimit for this point and the selected sub-grid regardless
		   of how we got here.  This should now only occur at the extreme edges
		   of the entire file coverage. */
		onLimit = 0;
		if (fabs (wpLL [LAT] - cvtPtr->NwReference [LAT]) <= cs_LlNoise) onLimit |= 1;
		if (fabs (wpLL [LNG] - cvtPtr->NwReference [LNG]) <= cs_LlNoise) onLimit |= 2;

		/* Compute the elements required for the file access.  This is common to
		   all cases of "onLimit". */
		eleNbr = (unsigned short)(((wpLL [LNG] - cvtPtr->SeReference [LNG]) / cvtPtr->DeltaLng) + cs_LlNoise);
		rowNbr = (unsigned short)(((wpLL [LAT] - cvtPtr->SeReference [LAT]) / cvtPtr->DeltaLat) + cs_LlNoise);

		/* Compute the boundaries of the specific cell we dealing with, assuming
		   onLimit is zero (which is the case 99.999% of the time). */
		seCell [LNG] = cvtPtr->SeReference [LNG] + cvtPtr->DeltaLng * (double)eleNbr;
		seCell [LAT] = cvtPtr->SeReference [LAT] + cvtPtr->DeltaLat * (double)rowNbr;
		nwCell [LNG] = seCell [LNG] + cvtPtr->DeltaLng;
		nwCell [LAT] = seCell [LAT] + cvtPtr->DeltaLng;

		/* Build the extent portions of the grid cells. */
		thisPtr->longitudeCell.seCorner [LNG] = seCell [LNG];
		thisPtr->longitudeCell.seCorner [LAT] = seCell [LAT];
		thisPtr->longitudeCell.nwCorner [LNG] = nwCell [LNG];
		thisPtr->longitudeCell.nwCorner [LAT] = nwCell [LAT];
		thisPtr->longitudeCell.deltaLng = cvtPtr->DeltaLng;
		thisPtr->longitudeCell.deltaLat = cvtPtr->DeltaLat;
		thisPtr->longitudeCell.density = cvtPtr->Density;

		thisPtr->latitudeCell.seCorner [LNG] = seCell [LNG];
		thisPtr->latitudeCell.seCorner [LAT] = seCell [LAT];
		thisPtr->latitudeCell.nwCorner [LNG] = nwCell [LNG];
		thisPtr->latitudeCell.nwCorner [LAT] = nwCell [LAT];
		thisPtr->latitudeCell.deltaLng = cvtPtr->DeltaLng;
		thisPtr->latitudeCell.deltaLat = cvtPtr->DeltaLat;
		thisPtr->latitudeCell.density = cvtPtr->Density;

		/* We could reduce the code complexity here by getting smart with the
		   onLimit thing.  However, this gets very tricky.  My excuse here is
		   that what is code below emulates the way the Canadians did it in
		   FORTRAN as best we can do in C. */
		if (onLimit == 0)
		{
			/* The normal case, probably about 99.9999 percent of the time.
			   Read the data into my record buffer. */
			filePosition = cvtPtr->FirstRecord + rowNbr * cvtPtr->RowSize + eleNbr * thisPtr->RecSize;

			if ((filePosition + sizeof(southEast) + sizeof(southWest)) > thisPtr->fileImageSize)
			{
				CS_erpt (cs_INV_FILE);
				goto error;
			}

			memcpy(&southEast, thisPtr->fileImage + filePosition, sizeof(southEast));
			/* Read southwest shifts. */
			memcpy(&southWest,
				   thisPtr->fileImage + filePosition + sizeof(southEast),
				   sizeof(southWest));

			/* Read northeast shifts. */
			filePosition += cvtPtr->RowSize;

			if ((filePosition + sizeof(northEast) + sizeof(northWest)) > thisPtr->fileImageSize)
			{
				CS_erpt (cs_INV_FILE);
				goto error;
			}

			memcpy(&northEast, thisPtr->fileImage + filePosition, sizeof(northEast));

			/* Read northwest shifts. */
			memcpy(&northWest,
				   thisPtr->fileImage + filePosition + sizeof(northEast),
				   sizeof(northWest));

			/* Swap as necessary. */
			swapping = CS_bswap (&southEast,cs_BSWP_NTv2Data);
			if (swapping)
			{
				CS_bswap (&southWest,cs_BSWP_NTv2Data);
				CS_bswap (&northEast,cs_BSWP_NTv2Data);
				CS_bswap (&northWest,cs_BSWP_NTv2Data);
			}

			/* Build the grid cell AA, BB, CC, and DD values. */
			thisPtr->longitudeCell.currentAA = southEast.del_lng;
			thisPtr->longitudeCell.currentBB = southWest.del_lng - southEast.del_lng;
			thisPtr->longitudeCell.currentCC = northEast.del_lng - southEast.del_lng;
			thisPtr->longitudeCell.currentDD = northWest.del_lng - southWest.del_lng - northEast.del_lng + southEast.del_lng;

			thisPtr->latitudeCell.currentAA = southEast.del_lat;
			thisPtr->latitudeCell.currentBB = southWest.del_lat - southEast.del_lat;
			thisPtr->latitudeCell.currentCC = northEast.del_lat - southEast.del_lat;
			thisPtr->latitudeCell.currentDD = northWest.del_lat - southWest.del_lat - northEast.del_lat + southEast.del_lat;
		}
		else if (onLimit == 1)
		{
			/* Point is on the extreme northern edge of the sub-grid.  This occurs
			   ocassionally.  In this case, the "northern" boundary of the grid cell
			   doesn't exist, and we must manufacture such.  This is called a
			   virtual cell in the Canadian documentation.  */
			filePosition = cvtPtr->FirstRecord + rowNbr * cvtPtr->RowSize + eleNbr * thisPtr->RecSize;

			if ((filePosition + sizeof(southEast) + sizeof(southWest)) > thisPtr->fileImageSize)
			{
				CS_erpt (cs_INV_FILE);
				goto error;
			}

			memcpy(&southEast, thisPtr->fileImage + filePosition, sizeof(southEast));
			/* Read southwest shifts. */
			memcpy(&southWest,
				   thisPtr->fileImage + filePosition + sizeof(southEast),
				   sizeof(southWest));

			/* Swap as necessary. */
			swapping = CS_bswap (&southEast,cs_BSWP_NTv2Data);
			if (swapping)
			{
				CS_bswap (&southWest,cs_BSWP_NTv2Data);
			}

			/* Do not attempt to read the northern boundary, it ain't there.
			   Compute the AA, BB, CC, DD values. */
			thisPtr->longitudeCell.currentAA = southEast.del_lng;
			thisPtr->longitudeCell.currentBB = southWest.del_lng - southEast.del_lng;
			thisPtr->longitudeCell.currentCC = cs_Zero;
			thisPtr->longitudeCell.currentDD = cs_Zero;

			thisPtr->latitudeCell.currentAA = southEast.del_lat;
			thisPtr->latitudeCell.currentBB = southWest.del_lat - southEast.del_lat;
			thisPtr->latitudeCell.currentCC = cs_Zero;
			thisPtr->latitudeCell.currentDD = cs_Zero;
			
			/* Adjust the grid cell boundaries to indicate that the northern
			   limits are the same as the southern limits.  I.e. a grid cell
			   that has zero height. */
			thisPtr->longitudeCell.nwCorner [LAT] = thisPtr->longitudeCell.seCorner [LAT] + cs_LlNoise;
			thisPtr->latitudeCell.nwCorner [LAT]  = thisPtr->latitudeCell.seCorner [LAT] + cs_LlNoise;
		}
		else if (onLimit == 2)
		{
			/* Point is on the extreme western edge of the sub-grid. */
			filePosition = cvtPtr->FirstRecord + rowNbr * cvtPtr->RowSize + eleNbr * thisPtr->RecSize;

			if ((filePosition + sizeof(southEast)) > thisPtr->fileImageSize)
			{
				CS_erpt (cs_INV_FILE);
				goto error;
			}

			memcpy(&southEast, thisPtr->fileImage + filePosition, sizeof(southEast));

			/* Don't read the south west, it ain't there. */

			filePosition += cvtPtr->RowSize;

			if ((filePosition + sizeof(northEast)) > thisPtr->fileImageSize)
			{
				CS_erpt (cs_INV_FILE);
				goto error;
			}

			memcpy(&northEast, thisPtr->fileImage + filePosition, sizeof(northEast));
			
			/* Don't read the northwest, it ain't there. */
			swapping = CS_bswap (&southEast,cs_BSWP_NTv2Data);
			if (swapping)
			{
				CS_bswap (&northEast,cs_BSWP_NTv2Data);
			}

			thisPtr->longitudeCell.currentAA = southEast.del_lng;
			thisPtr->longitudeCell.currentBB = cs_Zero;
			thisPtr->longitudeCell.currentCC = northEast.del_lng - southEast.del_lng;
			thisPtr->longitudeCell.currentDD = cs_Zero;

			thisPtr->latitudeCell.currentAA = southEast.del_lat;
			thisPtr->latitudeCell.currentBB = cs_Zero;
			thisPtr->latitudeCell.currentCC = northEast.del_lat - southEast.del_lat;
			thisPtr->latitudeCell.currentDD = cs_Zero;

			/* Adjust the grid cell boundaries to indicate that the eastern
			   limits are the same as the western limits.  I.e. a grid cell
			   that has zero width. */
			thisPtr->longitudeCell.nwCorner [LNG] = thisPtr->longitudeCell.seCorner [LNG] + cs_LlNoise;
			thisPtr->latitudeCell.nwCorner [LNG]  = thisPtr->latitudeCell.seCorner [LNG] + cs_LlNoise;
		}
		else  /* onLimit == 3 */
		{
			/* Point is actually the northwestern corner of the sub-grid. */
			filePosition = cvtPtr->FirstRecord + rowNbr * cvtPtr->RowSize + eleNbr * thisPtr->RecSize;

			if ((filePosition + sizeof(southEast)) > thisPtr->fileImageSize)
			{
				CS_erpt (cs_INV_FILE);
				goto error;
			}

			memcpy(&southEast, thisPtr->fileImage + filePosition, sizeof(southEast));

			/* Don't read anything else.  There's nothing there. */
			CS_bswap (&southEast,cs_BSWP_NTv2Data);

			/* Compute the AA, BB, CC, DD values. */
			thisPtr->longitudeCell.currentAA = southEast.del_lng;
			thisPtr->longitudeCell.currentBB = cs_Zero;
			thisPtr->longitudeCell.currentCC = cs_Zero;
			thisPtr->longitudeCell.currentDD = cs_Zero;

			thisPtr->latitudeCell.currentAA = southEast.del_lat;
			thisPtr->latitudeCell.currentBB = cs_Zero;
			thisPtr->latitudeCell.currentCC = cs_Zero;
			thisPtr->latitudeCell.currentDD = cs_Zero;

			/* Adjust the grid cell boundaries to indicate that the northeastern
			   limits are the same as the southwestern limits.  I.e. a grid cell
			   that has zero width and zero height. */
			thisPtr->longitudeCell.nwCorner [LNG] = thisPtr->longitudeCell.seCorner [LNG] + cs_LlNoise;
			thisPtr->latitudeCell.nwCorner [LNG]  = thisPtr->latitudeCell.seCorner [LNG] + cs_LlNoise;
			thisPtr->longitudeCell.nwCorner [LAT] = thisPtr->longitudeCell.seCorner [LAT] + cs_LlNoise;
			thisPtr->latitudeCell.nwCorner [LAT]  = thisPtr->latitudeCell.seCorner [LAT] + cs_LlNoise;
		}

		/* The cells are now valid, maybe.  We now work around a bust in the
		   Canadian NTV2_0.gsb grid data file. */
		thisPtr->CellIsValid = TRUE;

		/* Perform the interpolation calculation. */
		deltaLL [LNG] = CScalcNTv2GridCell (&thisPtr->longitudeCell,source);
		deltaLL [LAT] = CScalcNTv2GridCell (&thisPtr->latitudeCell,source);
		rtnValue = csGRIDI_ST_OK;
	}
	else
	{
		/* We didn't find a sub-grid.  The return value is +1 to indicate no
		   coverage. */
		deltaLL [LNG] = cs_Zero;
		deltaLL [LAT] = cs_Zero;
		rtnValue = csGRIDI_ST_COVERAGE;
	}
	csErrnam [0] = '\0';
	return rtnValue;
error:
	if (stream != NULL)
	{
		CS_fclose (stream); stream = NULL;
	}
	return csGRIDI_ST_SYSTEM;
}
Ejemplo n.º 18
0
int EXP_LVL7 CS_bins (csFILE *strm,long32_t start,long32_t eofPos,int rs,Const void *rec,int (*comp)(Const void *pp,Const void *qq))
{
	int st;
	int flag = -1;						/* initialization to keep gcc happy */
	size_t rd_cnt;

	long32_t nrecs;
	long32_t hi_rec;
	long32_t lo_rec;
	long32_t test_rec;
	long32_t test_pos;

	char *buff;

	/* Prepare for a possible error. */
	buff = NULL;

	/* Get a buffer which we can use for record I/O. */
	buff = (char *)CS_malc ((unsigned)rs);
	if (buff == NULL)
	{
		CS_erpt (cs_NO_MEM);
		goto error;
	}

	/* Compute the portion of the file which is to be
	   searched.  Quite often, we don't want to
	   search the whole thing. */
	if (start < 0L)
	{
		start = CS_ftell (strm);
		if (start < 0L)
		{
			CS_erpt (cs_IOERR);
			goto error;
		}
	}
	if (eofPos <= 0L)
	{
		st = CS_fseek (strm,0L,SEEK_END);
		if (st != 0)
		{
			CS_erpt (cs_IOERR);
			goto error;
		}
		eofPos = CS_ftell (strm);
		if (eofPos < 0L)
		{
			CS_erpt (cs_IOERR);
			goto error;
		}
	}

	/* Compute the number of records in the file
	   which are to be searched. */
	nrecs = (eofPos - start) / rs;

	/* If there are no records, we don't have a match,
	   any any record would appear at the start. */
	if (nrecs <= 0)
	{
		st = CS_fseek (strm,start,SEEK_SET);
		if (st != 0)
		{
			CS_erpt (cs_IOERR);
			goto error;
		}

		CS_free (buff);
		buff = NULL;

		return (0);
	}

	/* Set the starting and ending record numbers, where
	   the first record is numbered zero. */
	hi_rec = nrecs - 1;
	lo_rec = 0;

	/* Continue to search the records until we have
	   exhausted all possibilities.  The equal part
	   of this test is nescessary so that the last
	   record in the search gets compared for a match
	   or not. */
	test_pos = start;					/* initialization to keep gcc happy */
	while (lo_rec <= hi_rec)
	{
		/* Select the next record to be tested in terms
		   of record number. */
		test_rec = (hi_rec + lo_rec) / 2;

		/* Convert this to a file position. */
		test_pos = (long32_t)(test_rec * rs) + start;

		/* Read in the new test record. */
		st = CS_fseek (strm,test_pos,SEEK_SET);
		if (st != 0)
		{
			CS_erpt (cs_IOERR);
			goto error;
		}
		rd_cnt = CS_fread (buff,1,(unsigned)rs,strm);
		if (rd_cnt != (size_t)rs)
		{
			if (ferror (strm)) CS_erpt (cs_IOERR);
			else			   CS_erpt (cs_INV_FILE);
			goto error;
		}

		/* Compare with our search record. */
		flag = (*comp)(buff,rec);
		if (flag > 0)
		{
			/* Here if our test record is past where
			   our search record will be if it does
			   indeed exist.  We can exclude this
			   record (that we just read) and all
			   records past it from the search. */
			hi_rec = test_rec - 1;
		}
		else if (flag < 0)
		{
			/* Here if the test record is before where
			   our search record will be if it does
			   indeed exist.  We can exclude this
			   record and all which precede it from
			   the search. */
			lo_rec = test_rec + 1;
		}
		else
		{
			/* We have found a matching record.  Before
			   we return, we need to make sure that if
			   there are duplicate records in the file,
			   we are returning with the file positioned
			   to read the first of such duplicates. */
			do
			{
				test_pos -= (long32_t)rs;
				if (test_pos < start)
				{
					/* The last record tested is the
					   first in the search area.
					   Seek to search and break,
					   we're all done. */
					st = CS_fseek (strm,start,SEEK_SET);
					if (st != 0)
					{
						CS_erpt (cs_IOERR);
						goto error;
					}
					break;
				}

				/* Seek to the record just prior
				   to the last one tested and
				   read it in. */
				st = CS_fseek (strm,test_pos,SEEK_SET);
				if (st != 0)
				{
					CS_erpt (cs_IOERR);
					goto error;
				}
				rd_cnt = CS_fread (buff,1,(unsigned)rs,strm);
				if (rd_cnt != (size_t)rs)
				{
					if (ferror (strm)) CS_erpt (cs_IOERR);
					else               CS_erpt (cs_INV_FILE);
					goto error;
				}

				/* See if this record also matches
				   our key.  NOTE, that the read
				   positions the file back to the
				   last record tested, which is the
				   desired file position if the
				   match test fails. */
				flag = (*comp)(buff,rec);
			} while (flag == 0);

			/* Reset flag to zero, i.e. we got here because
			   we found a matching record. */
			flag = 0;

			/* Now we can return. */
			break;
		}
	}

	/* If flag is negative here, the file is correctly
	   positioned since we have read the record in and
	   the file is positioned for the next.  If flag
	   is greater than zero, we need to move the file
	   pointer back one record so that the user will
	   be able to re-read the current record. */
	if (flag > 0)
	{
		st = CS_fseek (strm,test_pos,SEEK_SET);
		if (st != 0)
		{
			CS_erpt (cs_IOERR);
			goto error;
		}
	}

	/* OK, return and tell the user if we found the
	   desired record or not. */

	CS_free (buff);
	buff = NULL;
	return (flag == 0);

error:
	if (buff != NULL) CS_free (buff);
	return (-1);
}
Ejemplo n.º 19
0
/*****************************************************************************
	Constructor
*/
struct csGeoid96GridFile_* CSnewGeoid96GridFile (Const char *path,long32_t bufferSize,ulong32_t flags,double density)
{
	extern char cs_DirsepC;
	extern char cs_ExtsepC;
	extern char csErrnam [];

	size_t readCount;
	long lngTmp;
	char *cp1, *cp2;
	csFILE *fstr;
	struct csGeoid96GridFile_* __This;
	char cTemp [MAXPATH];
	struct csNadconFileHdr_ nadconHdr;

	/* Prepare for an error. */
	__This = NULL;
	fstr = NULL;

	/* Malloc and initialize */
	__This = CS_malc (sizeof (struct csGeoid96GridFile_));
	if (__This == NULL)
	{
		CS_erpt (cs_NO_MEM);
		goto error;
	}
	CSinitGeoid96 (__This);

	/* Set default values for all members. */
	__This->bufferSize = bufferSize;
	if (__This->bufferSize < 0) __This->bufferSize = 0;

	/* Save file path/name. */
	CS_stncp (__This->filePath,path,sizeof (__This->filePath));
	CS_stncp (cTemp,path,sizeof (cTemp));

	/* Set up the type of file.  Get cp1 to point at the file
	   name, and cp2 to point at the extension.  We consider it
	   an error if we are not given a full path name.  Note,
	   we care not about the format of the drive specification.
	   But there must be at least one directory and there must
	   be an extension. */
	cp1 = strrchr (cTemp,cs_DirsepC);
	if (cp1 == NULL)
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_INV_FILE);
		goto error;
	}
	cp1 += 1;
	cp2 = strchr (cp1,cs_ExtsepC);
	if (cp2 == NULL)
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_INV_FILE);
		goto error;
	}
	*cp2++ = '\0';
	CS_stncp (__This->fileName,cp1,sizeof (__This->fileName));

	/* The thing should have a .geo extension to be processed by us. */
	if (CS_stricmp (cp2,"geo"))
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_INV_FILE);
		goto error;
	}

	/* Get the file information header. */
	fstr = CS_fopen (__This->filePath,_STRM_BINRD);
	if (fstr == NULL)
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_DTC_FILE);
		goto error;
	}
	readCount = CS_fread (&nadconHdr,1,sizeof (nadconHdr),fstr);
	if (readCount != sizeof (nadconHdr))
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_INV_FILE);
		goto error;
	}
	if (CS_ferror (fstr))
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_IOERR);
		goto error;
	}

	/* Determine the size of the file. */
	if (CS_fseek (fstr,0L,SEEK_END))
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_IOERR);
		goto error;
	}
	__This->fileSize = CS_ftell (fstr);
	if (__This->fileSize < 0L)
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_IOERR);
		goto error;
	}

	/* This constructor doesn't need the file any more. */
	CS_fclose (fstr);
	fstr = NULL;

	/* Swap the bytes if necessary. */
	CS_bswap (&nadconHdr,cs_BSWP_NadconFileHdr);

	/* The extra stuff here is required as conversions of floats to doubles
	   does not always provide precise results.  To get the precise results we
	   require, we assume that the value (which is in degrees) is an intergal
	   number of seconds. */
	lngTmp = (long)(((double)nadconHdr.del_lng * 3600.0) + 0.4);
	__This->deltaLng = ((double)lngTmp / 3600.0);
	lngTmp = (long)(((double)nadconHdr.del_lat * 3600.0) + 0.4);
	__This->deltaLat = ((double)lngTmp / 3600.0);

	/* Now we can do the rest of this stuff. */
	__This->coverage.southWest [LNG] = nadconHdr.min_lng;
	__This->coverage.southWest [LAT] = nadconHdr.min_lat;
	__This->coverage.northEast [LNG] = nadconHdr.min_lng + (__This->deltaLng * (nadconHdr.ele_cnt - 1));
	__This->coverage.northEast [LAT] = nadconHdr.min_lat + (__This->deltaLat * (nadconHdr.rec_cnt - 1));
	__This->coverage.density = (__This->deltaLng < __This->deltaLat) ? __This->deltaLng : __This->deltaLat;
	if (density != 0.0) __This->coverage.density = density;
	__This->elementCount = nadconHdr.ele_cnt;
	__This->recordCount = nadconHdr.rec_cnt;
	__This->recordSize = nadconHdr.ele_cnt * (int)sizeof (float) + (int)sizeof (long);

	/* Verify the integrity of the file. */
	lngTmp = (__This->recordCount + 1) * __This->recordSize;
	if (lngTmp != __This->fileSize)
	{
		CS_stncp (csErrnam,__This->filePath,MAXPATH);
		CS_erpt (cs_INV_FILE);
		goto error;
	}

	/* Now that we know recordSize, we can adjust the bufferSize for maximum
	   efficiency. */
	if (__This->bufferSize > __This->fileSize)
	{
		__This->bufferSize = __This->fileSize;
	}
	else
	{
		if (__This->bufferSize > (3 * __This->recordSize))
		{
			/* Maximum efficiency is obtained with a buffer size whch is
			   a multiple of the record size. */
			__This->bufferSize = (__This->bufferSize / __This->recordSize) * __This->recordSize;
		}
		else
		{
			/* We require a minimum buffer size of 3 records. */
			__This->bufferSize = 3 * __This->recordSize;
		}
	}

	return (__This);
error:
	CSdeleteGeoid96GridFile (__This);
	return NULL;
}
Ejemplo n.º 20
0
/******************************************************************************
	Constructor: This is a constructor for the "Entry" object.  A linked list
	of these "Entry" objects is underlying structure of the main object.

	NOTE: the specific of handling different file types is handled here.
*/
struct csRgf93ToNtfEntry_* CSnewRgf93ToNtfEntry (struct csDatumCatalogEntry_* catPtr)
{
	extern char cs_DirsepC;
	extern char cs_ExtsepC;
	extern char csErrnam [];

	char *cp;
	struct csRgf93ToNtfEntry_* __This;

	/* Prepare for an error. */
	__This = NULL;

	/* Allocate some storage. */
	__This = (struct csRgf93ToNtfEntry_*) CS_malc (sizeof (struct csRgf93ToNtfEntry_));
	if (__This == NULL)
	{
		CS_erpt (cs_NO_MEM);
		goto error;
	}
	__This->next = NULL;
	__This->type = dtRgf93ToNtfNone;
	__This->pointers.txtDatumPtr = NULL;
	__This->pointers.c2DatumPtr = NULL;         /* Yes, redundant! */

	/* Issue an error if information in the catalog file is
	   inconsistent.  That is, if the extension is not one of the
	   two supported. */
	cp = strrchr (catPtr->pathName,cs_DirsepC);
	if (cp == NULL)
	{
		/* Can't find a path specification in the path name. */
		CS_stncp (csErrnam,catPtr->pathName,MAXPATH);
		CS_erpt (cs_DTC_PATH);
		goto error;
	}
	cp = strchr (cp,cs_ExtsepC);
	if (cp == NULL || strlen (cp) != 4)
	{
		/* Can't find an extension in the file name. */
		CS_stncp (csErrnam,catPtr->pathName,MAXPATH);
		CS_erpt (cs_DTC_PATH);
		goto error;
	}
	

	/* Process the entry according to the extension on the file name. */
	cp += 1;                                /* bump past the separator*/
	if (!CS_stricmp (cp,"TXT"))
	{
		/* Construct a text file object.  In the past 10 years, there has only
		   one.  But with htis new implementation (Nov 2008) we supported
		   multiple .txt files as well as multiple .gsb files. */
		__This->pointers.txtDatumPtr = CSnewRgf93ToNtfTxt (catPtr->pathName,catPtr->bufferSize,catPtr->flags,catPtr->density);
		__This->type = dtRgf93ToNtfTxt;
	}
	else if (!CS_stricmp (cp,"GSB"))
	{
		/* Construct a Canadian National Transformation Version 2 object. */
		__This->pointers.c2DatumPtr = CSnewDatumShiftCa2 (dtcTypeCanadian2,catPtr->pathName,catPtr->bufferSize,catPtr->flags,catPtr->density);
		if (__This->pointers.c2DatumPtr == NULL)
		{
			goto error;
		}
		__This->type = dtRgf93ToNtfC2;
	}
	else
	{
		CS_stncp (csErrnam,catPtr->pathName,MAXPATH);
		CS_erpt (cs_NAD_EXT);
		goto error;
	}

	/* Return a pointer to t2he 'constructed' entry object. */
	return __This;
error:
	CSdeleteRgf93ToNtfEntry (__This);
	return NULL;
}
Ejemplo n.º 21
0
/******************************************************************************
	Constructor: for the "Entry" sub-object.  A linked list of these "Entry"
	objects is the basic structure of the main object.
*/
struct csGeoidHeightEntry_* CSnewGeoidHeightEntry (struct csDatumCatalogEntry_* catPtr)
{
	extern char cs_DirsepC;
	extern char cs_ExtsepC;
	extern char csErrnam [];

	char *cp;
	struct csGeoidHeightEntry_* __This;

	/* Prepare for an error. */
	__This = NULL;

	/* Allocate some storage. */
	__This = (struct csGeoidHeightEntry_*) CS_malc (sizeof (struct csGeoidHeightEntry_));
	if (__This == NULL)
	{
		CS_erpt (cs_NO_MEM);
		goto error;
	}
	__This->next = NULL;
	__This->type = csGeoidHgtTypeNone;
	__This->pointers.geoid96Ptr = NULL;

	/* Isolate the file name from the path, and the extension from the file name. */
	cp = strrchr (catPtr->pathName,cs_DirsepC);
	if (cp == NULL)
	{
		/* Is not supposed to happen, but we can't allow a bomb. */
		CS_stncp (csErrnam,catPtr->pathName,MAXPATH);
		CS_erpt (cs_DTC_PATH);
		goto error;
	}

	/* Isolate the extension on the file. */
	cp = strrchr (catPtr->pathName,cs_ExtsepC);
	if (cp == NULL)
	{
		/* Is not supposed to happen. */
		CS_stncp (csErrnam,catPtr->pathName,MAXPATH);
		CS_erpt (cs_NAD_EXT);
		goto error;
	}
	cp += 1;

	/* Do what's appropriate for this extension. */
	if (!CS_stricmp (cp,"GEO"))
	{
		/* Must not set the type until allocated for correct error handling. */
		__This->pointers.geoid96Ptr = CSnewGeoid96GridFile (catPtr->pathName,catPtr->bufferSize,catPtr->flags,catPtr->density);
		if (__This->pointers.geoid96Ptr == NULL)
		{
			goto error;
		}
		__This->type = csGeoidHgtTypeGeoid96;
	}
	else if (!CS_stricmp (cp,"bin"))
	{
		/* These are supposed to be Geoid99 type files. */
		/* Must not set the type until allocated for correct error handling. */
		__This->pointers.geoid99Ptr = CSnewGeoid99GridFile (catPtr->pathName,catPtr->bufferSize,catPtr->flags,catPtr->density);
		if (__This->pointers.geoid99Ptr == NULL)
		{
			goto error;
		}
		__This->type = csGeoidHgtTypeGeoid99;
	}
	else if (!CS_stricmp (cp,"txt"))
	{
		/* These are supposed to be OSGM91 type files. */
		/* Must not set the type until allocated for correct error handling. */
		__This->pointers.osgm91Ptr = CSnewOsgm91 (catPtr->pathName,catPtr->bufferSize,catPtr->flags,catPtr->density);
		if (__This->pointers.osgm91Ptr == NULL)
		{
			goto error;
		}
		__This->type = csGeoidHgtTypeOsgm91;
	}	/* When we know how to do the others, we add that stuff here. */
	else if (!CS_stricmp (cp,"byn"))
	{
		/* Must not set the type until allocated for correct error handling. */
		__This->pointers.bynGridFilePtr = CSnewBynGridFile (catPtr->pathName,catPtr->bufferSize,catPtr->flags,catPtr->density);
		if (__This->pointers.bynGridFilePtr == NULL)
		{
			goto error;
		}
		__This->type = csGeoidHgtTypeBynGridFile;
	}
   else if (!CS_stricmp (cp,"grd"))
   {
      /* Must not set the type until allocated for correct error handling. */
      __This->pointers.egm96Ptr = CSnewEgm96 (catPtr->pathName,catPtr->bufferSize,catPtr->flags,catPtr->density);
      if (__This->pointers.egm96Ptr == NULL)
      {
         goto error;
      }
      __This->type = csGeoidHgtTypeEgm96;
   }
	else
	{
		CS_erpt (cs_GHGT_EXT);
		goto error;
	}
	return __This;
error:
	CSdeleteGeoidHeightEntry (__This);
	return NULL;
}