/****************************************************************************** What we call the Frame/Wolfe tranformation is an approximation of the Seven Parameter transformation. The following approximations apply: 1> The cosine of all rotation angles is one. 2> The sine of all rotation angles is equal to the angle itself. 3> The product of two sine terms is zero. */ int EXP_LVL9 CSframeS (struct cs_GxXform_* gxXfrm) { extern double cs_One; /* 1.0 */ extern double cs_Sec2Rad; /* 4.848...E-06 */ double trgScale; struct csFrame_ *frame; frame = &gxXfrm->xforms.frame; frame->srcERad = gxXfrm->srcDatum.e_rad; frame->srcESqr = gxXfrm->srcDatum.ecent * gxXfrm->srcDatum.ecent; frame->trgERad = gxXfrm->trgDatum.e_rad; frame->trgESqr = gxXfrm->trgDatum.ecent * gxXfrm->trgDatum.ecent; frame->deltaX = gxXfrm->gxDef.parameters.geocentricParameters.deltaX; frame->deltaY = gxXfrm->gxDef.parameters.geocentricParameters.deltaY; frame->deltaZ = gxXfrm->gxDef.parameters.geocentricParameters.deltaZ; frame->rotX = gxXfrm->gxDef.parameters.geocentricParameters.rotateX * cs_Sec2Rad; frame->rotY = gxXfrm->gxDef.parameters.geocentricParameters.rotateY * cs_Sec2Rad; frame->rotZ = gxXfrm->gxDef.parameters.geocentricParameters.rotateZ * cs_Sec2Rad; trgScale = cs_One + (gxXfrm->gxDef.parameters.geocentricParameters.scale * 1.0E-06); if (fabs (trgScale) < 1.0E-06) { // An actual scale factor of zero would produce a floating point // exception. Can't allow that. CS_erpt (cs_ISER); } else { frame->scale = cs_One + (gxXfrm->gxDef.parameters.geocentricParameters.scale * 1.0E-06); } frame->errorValue = gxXfrm->errorValue; frame->cnvrgValue = gxXfrm->cnvrgValue; frame->maxIterations = gxXfrm->maxIterations; gxXfrm->frwrd2D = (cs_FRWRD2D_CAST)CSframeF2; gxXfrm->frwrd3D = (cs_FRWRD3D_CAST)CSframeF3; gxXfrm->invrs2D = (cs_INVRS2D_CAST)CSframeI2; gxXfrm->invrs3D = (cs_INVRS3D_CAST)CSframeI3; gxXfrm->inRange = (cs_INRANGE_CAST)CSframeL; gxXfrm->release = (cs_RELEASE_CAST)CSframeR; gxXfrm->destroy = (cs_DESTROY_CAST)CSframeD; return 0; }
Const char * EXP_LVL7 CSnad27ToAts77Log (Const double ll_27 [2]) { Const char *cp; cp = NULL; /* Make sure we have been initialized. */ if (csNad27ToAts77 == NULL) { CS_erpt (cs_DTC_NO_SETUP); } else { cp = CSsourceNad27ToAts77 (csNad27ToAts77,ll_27); } return (cp == NULL || *cp == '\0') ? "<unavailable>" : cp; }
Const char * EXP_LVL7 CSdhdnToEtrf89Log (Const double ll_50 [2]) { Const char *cp; cp = NULL; /* Make sure we have been initialized. */ if (csDhdnToEtrf89 == NULL) { CS_erpt (cs_DTC_NO_SETUP); } else { cp = CSsourceDhdnToEtrf89 (csDhdnToEtrf89,ll_50); } return (cp == NULL || *cp == '\0') ? "<unavailable>" : cp; }
int EXP_LVL1 CS_llFromMgrs (double latLng [2],const char* mgrsString) { extern struct cs_Mgrs_ *cs_MgrsPtr; int status; if (cs_MgrsPtr == NULL) { CS_erpt (cs_MGRS_NOSET); status = -1; } else { status = CScalcLlFromMgrs (cs_MgrsPtr,latLng,mgrsString); } return status; }
/****************************************************************************** Calculation function. Calculates the conversion from Ats77 to NAD83. */ int CScalcAts77ToCsrsEntry (struct csAts77ToCsrsEntry_* __This,double* ll_csrs,Const double *ll_ats77,struct csLLGridCellCache_ *cachePtr) { extern char csErrnam []; int status; switch (__This->type){ case dtAts77ToCsrsC2: status = CScalcDatumShiftCa2 (__This->pointers.c2DatumPtr,ll_csrs,ll_ats77,cachePtr); break; case dtAts77ToCsrsNoneYet: default: /* Minus one indicates a fatal error. In this case, it is an internal software error. */ CS_stncp (csErrnam,"CS_dtAts77ToCsrs:1",MAXPATH); CS_erpt (cs_ISER); status = -1; break; } return status; }
/* The following function returns the mesh code appropriate for the given geographic coordinates provided. Note, it is expected that the calling module deals with the rounding to the appropriate grid point. This function returns a zero to indicate an error. Zero is not, under any circumstances, a valid mesh code. */ ulong32_t EXP_LVL9 CSjpnLlToMeshCode (const double ll [2]) { extern char csErrnam []; ulong32_t mesh; ulong32_t iLat, iLng; /* Verify that we are in the proper range. This prevents many nasty situations such as overflow. */ if (ll [0] < 120.0 || ll [0] > 160.0 || ll [1] < 20.0 || ll [1] > 60.0) { CS_stncp (csErrnam,"CS_jpnMeshCode:1",MAXPATH); CS_erpt (cs_ISER); return 0; } /* Compute the mesh numbers for each value. */ iLat = ((ulong32_t)CS_degToSec (ll [1])) / 30; iLng = ((ulong32_t)CS_degToSec (ll [0] - 100.0)) / 45; /* We do the last two digits; these range from 0 thru 9. Each increment in longitude represents 45 seconds of longitude. Each increment in latitude represents 30 seconds of latitude. */ mesh = iLng % 10; mesh += (iLat % 10) * 10; /* Next two digits, range from 0 thru 7. Each increment of longitude represents 7.5 minutes (450 seconds). Each increment of latitude represents 5 minutes (300 seconds). */ mesh += ((iLng / 10) % 8) * 100; mesh += ((iLat / 10) % 8) * 1000; /* Now for the last set of four digits. Each increment of latitude represents 40 minutes (2400 sceonds) and each increment of longitude repsents 12 degree (3600 seconds) of longitude. Note that we biased the longitude by 100 degrees above. */ mesh += ((iLng / 80) % 100) * 10000; mesh += ((iLat / 80) % 100) * 1000000; return mesh; }
int EXP_LVL1 CS_cs2WktEx (char *bufr,size_t bufrSize,const char *csKeyName,int flavor,unsigned short flags) { int rtnValue = -1; struct cs_Dtdef_ *dtDefPtr = 0; struct cs_Eldef_ *elDefPtr = 0; struct cs_Csdef_ *csDefPtr = 0; if (bufrSize > 0) { *bufr = '\0'; csDefPtr = CS_csdef (csKeyName); if (csDefPtr != 0) { if (csDefPtr->dat_knm [0] == '\0') { CS_erpt (cs_WKT_NODTREF); } else { dtDefPtr = CS_dtdef (csDefPtr->dat_knm); if (dtDefPtr != 0) { elDefPtr = CS_eldef (dtDefPtr->ell_knm); if (elDefPtr != 0) { rtnValue = CScs2WktEx (bufr,bufrSize,flavor,csDefPtr,dtDefPtr,elDefPtr,flags); /*lint !e64 */ CS_free (elDefPtr); elDefPtr = 0; } CS_free (dtDefPtr); dtDefPtr = 0; } } CS_free (csDefPtr); csDefPtr = 0; } } return rtnValue; }
int EXP_LVL1 CS_mgrsFromLl (char* result,double latLng [2],int prec) { extern struct cs_Mgrs_ *cs_MgrsPtr; int size; int status; size = 6 + prec + prec; if (cs_MgrsPtr == NULL) { CS_erpt (cs_MGRS_NOSET); status = -1; } else { size = 6 + prec + prec; status = CScalcMgrsFromLl (cs_MgrsPtr,result,size,latLng,prec); } return status; }
/****************************************************************************** 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; }
/********************************************************************** ** status = CSvrtcon29To88 (deltaHgt,ll_83); ** ** double *deltaHgt; the calculated change in orthometric height ** is returned here. ** double ll_83 [3]; the longitude ([0]) and the latitude ([1]) of ** the point at which the change in orthometric ** height is to be determined. ** int status; returns zero if conversion took place as expected, ** +1 if conversion failed due to out of range ** error, -1 for all other errors. ** ** In the event of a +1 return value, deltaHgt is set to zero. **********************************************************************/ int EXP_LVL7 CSvrtcon29To88 (double* deltaHgt,Const double ll_83 [3]) { extern double cs_Zero; int status; double result; result = cs_Zero; /* Make sure we have been initialized. */ if (csVertconUS == NULL) { CS_erpt (cs_DTC_NO_SETUP); status = -1; } else { /* Note, this function returns the shift in millimeters. */ status = CScalcVertconUS (csVertconUS,&result,ll_83); if (status == 0) result *= 0.001; } *deltaHgt = result; return status; }
/****************************************************************************** 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; }
/****************************************************************************** Calculation function. Calculates the conversion from RGF93 to NTF. */ int CScalcRgf93ToNtfEntry (struct csRgf93ToNtfEntry_* __This,double* llNtf,Const double *llRgf93,struct csLLGridCellCache_ *cachePtr) { extern char csErrnam []; int status; switch (__This->type){ case dtRgf93ToNtfTxt: status = CScalcRgf93ToNtfTxt (__This->pointers.txtDatumPtr,llNtf,llRgf93); break; case dtRgf93ToNtfC2: status = CScalcDatumShiftCa2 (__This->pointers.c2DatumPtr,llNtf,llRgf93,cachePtr); break; case dtRgf93ToNtfNone: default: /* Minus one indicates a fatal error. In this case, it is an internal software error. */ CS_stncp (csErrnam,"CS_dtRgf93ToNtf:1",MAXPATH); CS_erpt (cs_ISER); status = -1; break; } return status; }
/****************************************************************************** Calculate the geoid height, given the specific "Entry" item which is to be used. */ int CScalcGeoidHeightEntry (struct csGeoidHeightEntry_* __This,double* geoidHgt,Const double *ll84) { extern char csErrnam []; int status; status = -1; if (__This != NULL) { switch (__This->type) { case csGeoidHgtTypeGeoid96: status = CScalcGeoid96GridFile (__This->pointers.geoid96Ptr,geoidHgt,ll84); break; case csGeoidHgtTypeGeoid99: status = CScalcGeoid99GridFile (__This->pointers.geoid99Ptr,geoidHgt,ll84); break; case csGeoidHgtTypeOsgm91: status = CScalcOsgm91 (__This->pointers.osgm91Ptr,geoidHgt,ll84); break; case csGeoidHgtTypeBynGridFile: status = CScalcBynGridFile (__This->pointers.bynGridFilePtr,geoidHgt,ll84); break; case csGeoidHgtTypeEgm96: status = CScalcEgm96 (__This->pointers.egm96Ptr,geoidHgt,ll84); break; case csGeoidHgtTypeWorld: case csGeoidHgtTypeAustralia: case csGeoidHgtTypeNone: default: CS_stncp (csErrnam,"CS_usGridFile:3",MAXPATH); CS_erpt (cs_ISER); break; } } return status; }
int EXP_LVL9 CSazmedI (Const struct cs_Azmed_ *azmed,double ll [2],Const double xy [2]) { extern char csErrnam []; extern double cs_Radian; /* 57.29577..... */ extern double cs_Zero; /* 0.0 */ extern double cs_Half; /* 0.5 */ extern double cs_One; /* 1.0 */ extern double cs_Mone; /*-1.0 */ extern double cs_Three; /* 3.0 */ extern double cs_Six; /* 6.0 */ extern double cs_AnglTest; /* 0.001 seconds of arc, in radians. */ extern double cs_NPTest; /* 0.001 seconds of arc short of the north pole, in radians. */ int rtn_val; int itr_cnt; double x = 0.0; /* initialized to keep the gcc compiler happy */ double y = 0.0; /* initialized to keep the gcc compiler happy */ double c; double lat = 0.0; /* initialized to keep the gcc compiler happy */ double del_lng; double rho; double sin_c; double cos_c; double Az; double sin_Az; double cos_Az; double cos_psi; double last_lat; double A; double B; double D; double D_third; double D_fourth; double E; double E_sq; double E_third; double sin_E; double F; double M; double psi; double tmp1; double tmp2; double my_xy [2]; rtn_val = cs_CNVRT_NRML; /* There are two formulae, one for the sphere and one for the ellipsoid. If the ecentricity of the datum in use is 0.0 exactly, we shall use the spherical formulae. The calculations which immediately follow are required by both cases. First, we remove the false origin, return to the normal X/Y quadrant, and unrotate the coordinates. */ if (azmed->quad == 0) { my_xy [XX] = xy [XX] - azmed->x_off; my_xy [YY] = xy [YY] - azmed->y_off; } else { CS_quadI (&my_xy [XX],&my_xy [YY],xy,azmed->x_off, azmed->y_off, azmed->quad); } x = azmed->cos_Az * my_xy [XX] + azmed->sin_Az * my_xy [YY]; y = azmed->cos_Az * my_xy [YY] - azmed->sin_Az * my_xy [XX]; /* Rho is the radius of the circle whose center is at the origin and goes thorugh the current point. */ rho = sqrt (x * x + y * y); if (rho < azmed->one_mm) { /* The coordinate is essentially the origin. We do the following to avoid a atan2(0,0). If the origin is either pole, the longitude will be undefined. */ if (azmed->aspect == cs_AZMED_NORTH || azmed->aspect == cs_AZMED_SOUTH) { rtn_val = cs_CNVRT_INDF; } ll [LNG] = azmed->org_lng * cs_Radian; ll [LAT] = azmed->org_lat * cs_Radian; return (rtn_val); } if (rho >= azmed->max_rho) { /* Opps!!! The x and/or y is so large it is outside the circle which defines the extent of the coordinate system. Convert xy to lie on the bounding circle at the apropriate azimuth. */ rtn_val = cs_CNVRT_RNG; x *= azmed->max_rho / rho; y *= azmed->max_rho / rho; rho = azmed->max_rho; } /* Now we can convert back to lat/longs. We know that rho is not zero which implies that at least one of x and y is not zero. */ del_lng = cs_Zero; if (azmed->ecent == 0.0) { /* Here for the sphere. The sine and cosine functions shouldnever return a value greater than one. Thus, the asin ()'s here should be OK without any checking. */ c = rho / azmed->ka; sin_c = sin (c); cos_c = cos (c); switch (azmed->aspect) { case cs_AZMED_NORTH: del_lng = atan2 (x,-y); lat = asin (cos_c); break; case cs_AZMED_SOUTH: del_lng = atan2 (x,y); lat = -asin (cos_c); break; case cs_AZMED_EQUATOR: c = rho / azmed->ka; tmp1 = x * sin (c); tmp2 = rho * cos (c); del_lng = atan2 (tmp1,tmp2); tmp1 = (y / rho) * sin_c; if (fabs (tmp1) > cs_One) { tmp1 = (tmp1 >= 0.0) ? cs_One : cs_Mone; } lat = asin (tmp1); break; case cs_AZMED_GUAM: lat = azmed->org_lat; itr_cnt = 16; for (;;) { last_lat = lat; tmp1 = x * x * tan (lat) / azmed->two_ka; lat = azmed->org_lat + (y - tmp1) / azmed->ka; if (fabs (lat - last_lat) < cs_AnglTest) { break; } if (--itr_cnt <= 0) { rtn_val = cs_CNVRT_RNG; break; } } /* Longitude is undefined at the poles. */ if (fabs (lat) < cs_NPTest) { del_lng = x / (azmed->ka * cos (lat)); } break; case cs_AZMED_OBLIQUE: tmp1 = cos_c * azmed->sin_org_lat; tmp1 += (y / rho) * sin_c * azmed->cos_org_lat; if (fabs (tmp1) > cs_One) { tmp1 = (tmp1 >= 0.0) ? cs_One : cs_Mone; } lat = asin (tmp1); tmp1 = x * sin_c; tmp2 = rho * cos_c * azmed->cos_org_lat; tmp2 -= y * sin_c * azmed->sin_org_lat; del_lng = atan2 (tmp1,tmp2); break; default: CS_stncp (csErrnam,"CS_azmed:3",MAXPATH); CS_erpt (cs_ISER); rtn_val = -1; break; } } else { /* Here for the ellisoid. We've already dealt with x and y == 0. */ switch (azmed->aspect) { case cs_AZMED_NORTH: del_lng = atan2 (x,-y); lat = CSmmIcal (&azmed->mmcofI,(azmed->Mp - rho)); break; case cs_AZMED_SOUTH: del_lng = atan2 (x,y); lat = CSmmIcal (&azmed->mmcofI,(rho - azmed->Mp)); break; case cs_AZMED_GUAM: itr_cnt = 16; lat = azmed->org_lat; for (;;) { last_lat = lat; tmp1 = sin (lat); tmp1 = cs_One - azmed->e_sq * tmp1 * tmp1; tmp1 = x * x * tan (lat) * sqrt (tmp1); tmp1 = y - tmp1 / azmed->two_ka; M = azmed->M1 + tmp1; lat = CSmmIcal (&azmed->mmcofI,M); if (fabs (lat - last_lat) < cs_AnglTest) { break; } if (--itr_cnt <= 0) { rtn_val = cs_CNVRT_RNG; break; } } /* Longitude is undefined at the poles. */ if (fabs (lat) < cs_NPTest) { tmp1 = sin (lat); tmp1 = cs_One - azmed->e_sq * tmp1 * tmp1; del_lng = x * sqrt (tmp1) / (azmed->ka * cos (lat)); } break; case cs_AZMED_EQUATOR: case cs_AZMED_OBLIQUE: Az = atan2 (x,y); sin_Az = sin (Az); cos_Az = cos (Az); A = -azmed->e_sq_cos_sq * cos_Az * cos_Az / azmed->one_esq; B = cs_Three * azmed->e_sq * (cs_One - A) * azmed->sin_cos * cos_Az / azmed->one_esq; D = rho / azmed->N1; D_third = D * D * D; D_fourth = D_third * D; E = D; E -= A * (cs_One + A) * D_third / cs_Six; E -= B * (cs_One + cs_Three * A) * D_fourth / 24.0; E_sq = E * E; E_third = E_sq * E; sin_E = sin (E); F = cs_One - (A * E_sq * cs_Half) - (B * E_third / cs_Six); /*lint !e834 */ tmp1 = azmed->sin_org_lat * cos (E); tmp2 = azmed->cos_org_lat * sin_E * cos_Az; psi = asin (tmp1 + tmp2); /* Psi is essentially the latitude of the point adjusted for the affect of the ellipsoid. Thus, it can be zero, and it can be the equivalent of +-90 degrees. In analyzing the following, note that: 1) E is the ellipsoidally adjusted angular distance from the origin to the point; 2) the formula is actually equation 5-4 of Synder, reorganized to produce the delta longitude. Thus, I conclude that delta longitude goes to zero as cos(psi) approaches zero. */ cos_psi = cos (psi); if (fabs (cos_psi) > cs_AnglTest) { del_lng = asin (sin_Az * sin_E / cos (psi)); } /* Now, the latitude. We have a similar problem, but now with sin (psi) == 0. As psi approaches zero, this whole mess reduces to lat = psi, which is zero, of course. */ if (fabs (psi) > cs_AnglTest) { tmp1 = azmed->e_sq * F * azmed->sin_org_lat / sin (psi); tmp2 = tan (psi) / azmed->one_esq; lat = atan ((cs_One - tmp1) * tmp2); } else { lat = cs_Zero; } break; default: CS_stncp (csErrnam,"CS_azmed:",MAXPATH); CS_erpt (cs_ISER); rtn_val = -1; break; } } /* Longitude is undefined, mathematically, at either pole. */ if (rtn_val >= 0) { if (fabs (lat) > cs_NPTest) rtn_val = cs_CNVRT_INDF; /* Longitudes are always normalized for this projection. */ ll [LNG] = (del_lng + azmed->org_lng) * cs_Radian; ll [LAT] = lat * cs_Radian; } return (rtn_val); }
/****************************************************************************** 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; }
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); }
int EXP_LVL9 CSazmedF (Const struct cs_Azmed_ *azmed,double xy [2],Const double ll [2]) { extern char csErrnam [MAXPATH]; extern double cs_Degree; /* 1.0 / RADIAN */ extern double cs_Pi; /* 3.14159... */ extern double cs_Two_pi; /* 2 PI */ extern double cs_Mpi; /* -3.14159.... */ extern double cs_Pi_o_2; /* PI over 2 */ extern double cs_Mpi_o_2; /* Minus PI over 2 */ extern double cs_Zero; /* 0.0 */ extern double cs_One; /* 1.0 */ extern double cs_Mone; /*-1.0 */ extern double cs_Two; /* 2.0 */ extern double cs_Four; /* 4.0 */ extern double cs_Six; /* 6.0 */ extern double cs_Seven; /* 7.0 */ extern double cs_Eight; /* 8.0 */ extern double cs_NPTest; /* 0.001 seconds of arc short of the north pole in radians. */ extern double cs_AnglTest; /* 0.001 seconds of arc in radians. */ extern double cs_AnglTest1; /* 1.0 - 0.001 seconds of arc in radians. Could also be considered to be the cosine of cs_AnglTest. */ int rtn_val; double lng; /* The given longitude, after conversion to radians. */ double lat; /* The given latitude after conversion to radians. */ double x = 0.0; /* initialized to keep the gcc compiler happy */ double y = 0.0; /* initialized to keep the gcc compiler happy */ double M; double N; double H; double H_sq; double H_sq_7; double GH; double rho; double psi; double del_lng; double sin_del_lng; double cos_del_lng; double sin_lat; double cos_lat; double cos_c; double c; double Az; double sin_Az; double cos_Az; double s; double s_sq; double s_third; double s_fourth; double s_fifth; double tmp1; double tmp2; double tmp3; double tmp4; rtn_val = cs_CNVRT_NRML; /* There are two formulae, one for the sphere and one for the ellipsoid. If the ecentricity of the dataum in use is 0.0 exactly, we shall use the spherical formulae. There is a miminal amount of stuff which is common to both which we perform first. */ lng = cs_Degree * ll [LNG]; lat = cs_Degree * ll [LAT]; if (fabs (lat) > cs_NPTest) { rtn_val = cs_CNVRT_INDF; if (fabs (lat) > cs_Pi_o_2) { rtn_val = cs_CNVRT_RNG; lat = CS_adj1pi (lat); } } del_lng = lng - azmed->org_lng; if (del_lng > cs_Pi && azmed->org_lng < 0.0) del_lng -= cs_Two_pi; else if (del_lng < cs_Mpi && azmed->org_lng > 0.0) del_lng += cs_Two_pi; if (del_lng > cs_Pi || del_lng <= cs_Mpi) { /* Note, the inverse can't distinguish between -180 and +180; therefore we return a range status for -180. */ rtn_val = cs_CNVRT_RNG; del_lng = CS_adj2pi (del_lng); } sin_del_lng = sin (del_lng); cos_del_lng = cos (del_lng); sin_lat = sin (lat); cos_lat = cos (lat); /* See if the datum is a sphere or an ellipsoid. */ if (azmed->ecent == 0.0) { /* Here for the sphere. */ switch (azmed->aspect) { case cs_AZMED_NORTH: tmp1 = (cs_Pi_o_2 - lat) * azmed->ka; x = tmp1 * sin_del_lng; y = -tmp1 * cos_del_lng; break; case cs_AZMED_SOUTH: tmp1 = (cs_Pi_o_2 + lat) * azmed->ka; x = tmp1 * sin_del_lng; y = tmp1 * cos_del_lng; break; case cs_AZMED_EQUATOR: cos_c = cos_lat * cos_del_lng; c = acos (cos_c); if (fabs (c) < cs_AnglTest) { /* At the origin. */ tmp1 = cs_Zero; } else if (cos_c < -cs_AnglTest1) { /* AntiPodal */ rtn_val = cs_CNVRT_RNG; tmp1 = azmed->ka * cs_Pi; } else { /* Normal */ tmp1 = azmed->ka * c / sin (c); } x = tmp1 * cos_lat * sin_del_lng; y = tmp1 * sin_lat; break; case cs_AZMED_GUAM: x = azmed->ka * del_lng * cos_lat; tmp1 = x * x * tan (lat) / azmed->two_ka; y = azmed->ka * (lat - azmed->org_lat) + tmp1; break; case cs_AZMED_OBLIQUE: cos_c = azmed->sin_org_lat * sin_lat + azmed->cos_org_lat * cos_lat * cos_del_lng; c = acos (cos_c); /* C is the angular distance from the origin. A zero value indicates the orgin which would cause a division by sin (0); but otherwise is a perfectly normal value for this projection. As c approaches PI, however, we approach the point opposite the origin, and this point is not well defined. */ if (fabs (c) <= cs_AnglTest) { /* The origin. */ tmp1 = cs_Zero; } else if (cos_c < -cs_AnglTest1) { /* Antipodal to the origin. */ rtn_val = cs_CNVRT_RNG; tmp1 = azmed->ka * cs_Pi; } else { /* Normal, We can divide by sin (c). */ tmp1 = azmed->ka * (c / sin (c)); } x = tmp1 * cos_lat * sin_del_lng; y = tmp1 * (azmed->cos_org_lat * sin_lat - azmed->sin_org_lat * cos_lat * cos_del_lng); break; default: CS_stncp (csErrnam,"CS_azmed:1",MAXPATH); CS_erpt (cs_ISER); rtn_val = -1; break; } } else { switch (azmed->aspect) { case cs_AZMED_NORTH: M = CSmmFcal (&azmed->mmcofF,lat,sin_lat,cos_lat); rho = azmed->Mp - M; x = rho * sin_del_lng; y = -rho * cos_del_lng; break; case cs_AZMED_SOUTH: M = CSmmFcal (&azmed->mmcofF,lat,sin_lat,cos_lat); rho = azmed->Mp + M; x = rho * sin_del_lng; y = rho * cos_del_lng; break; case cs_AZMED_GUAM: M = CSmmFcal (&azmed->mmcofF,lat,sin_lat,cos_lat); tmp1 = sqrt (azmed->e_sq * sin_lat * sin_lat); x = azmed->ka * del_lng * cos_lat / tmp1; tmp2 = tan (lat) * x * x * tmp1 / azmed->two_ka; y = M - azmed->M1 + tmp2; /*lint !e834 */ break; case cs_AZMED_EQUATOR: case cs_AZMED_OBLIQUE: /* Compute Az, the azimuth of the point with respect to the origin on the ellipsoid. Psi is the latitude of the point, adjusted for the ellipsoid. This is zero or cs_Pi_o_2 if the latitude is a pole (don't want to divide by cos (lat) in this case. */ if (fabs (lat) > cs_NPTest) { /* Point is a pole. */ psi = (lat > 0.0) ? cs_Pi_o_2 : cs_Mpi_o_2; } else { /* Cosine (lat) will not be zero, we can compute psi safely. */ tmp1 = azmed->e_sq * sin_lat * sin_lat; N = azmed->ka / sqrt (cs_One - tmp1); tmp2 = (azmed->one_esq * tan (lat)) + azmed->psi_t1 / (N * cos_lat); psi = atan (tmp2); } tmp3 = (azmed->cos_org_lat * tan (psi)) - (azmed->sin_org_lat * cos_del_lng); /* Tmp3 and sin_del_lng will both be zero if the point is the origin. Most atan2's (not all) will bomb if both args are zero. */ if (fabs (sin_del_lng) > cs_AnglTest) { Az = atan2 (sin_del_lng,tmp3); sin_Az = sin (Az); cos_Az = cos (Az); } else { /* del_lng is zero, we do a quick and dirty atan2. */ sin_Az = cs_Zero; if (tmp3 >= 0.0) { Az = cs_Zero; cos_Az = cs_One; } else { Az = cs_Mpi; cos_Az = cs_Mone; } } /* Ok, we have the azimuth. Need to compute the angular distance to the point on the ellipsoid. In the case of small angles, the sine and the angle are equivalent. */ if (fabs (sin_Az) < cs_AnglTest) { /* Here to avoid a divide by sin (Az). */ tmp4 = azmed->cos_org_lat * sin (psi) - azmed->sin_org_lat * cos (psi); s = asin (tmp4); if (cos_Az < 0.0) { s = -s; } } else { s = asin (sin_del_lng * cos (psi) / sin_Az); } /* S is essentially the angular distance over a sphere. Convert to c, the linear distance over the ellipsoid, via a power series calculation. */ s_sq = s * s; s_third = s_sq * s; s_fourth = s_sq * s_sq; s_fifth = s_fourth * s; H = azmed->e_cos_p1 * cos_Az / azmed->rt_one_esq; H_sq = H * H; H_sq_7 = cs_Seven * H_sq; GH = azmed->G * H; tmp2 = H_sq * (cs_Four - H_sq_7); tmp2 -= azmed->G_sq_3 * (cs_One - H_sq_7); tmp1 = cs_One; tmp1 -= s_sq * H_sq * (cs_One - H_sq) / cs_Six; tmp1 += (s_third / cs_Eight) * GH * (cs_One - cs_Two * H_sq); tmp1 += (s_fourth / 120.0) * tmp2; tmp1 -= (s_fifth / 48.0) * GH; c = azmed->N1 * s * tmp1; x = c * sin_Az; y = c * cos_Az; break; default: CS_stncp (csErrnam,"CS_azmed:2",MAXPATH); CS_erpt (cs_ISER); rtn_val = -1; break; } } /* Add the rotation, quad effect, and offset. */ if (rtn_val >= 0) { xy [XX] = azmed->cos_Az * x - azmed->sin_Az * y; xy [YY] = azmed->cos_Az * y + azmed->sin_Az * x; if (azmed->quad == 0) { xy [XX] += azmed->x_off; xy [YY] += azmed->y_off; } else { CS_quadF (xy,xy [XX],xy [YY],azmed->x_off,azmed->y_off, azmed->quad); } } return (rtn_val); }
int EXP_LVL7 CS_tmpfn (char *tmp_fnm) { extern char cs_Dir []; extern char *cs_DirP; char cc_save; int count; char *cp; /* Establish the drive and the directory. */ cc_save = *cs_DirP; *cs_DirP = '\0'; cp = CS_stcpy (tmp_fnm,cs_Dir); *cs_DirP = cc_save; /* Add a file name. */ cp = CS_stcpy (cp,"DEL_ME.$"); /* Add an extension which will make this file unique in the directory. Hopefully, we will never need to iterate more than once since tempoary files should always be deleted after their use. */ count = 0; strcpy (unique,"ZZ"); do { count++; if (count >= 676) { CS_erpt (cs_TMPFN_MAXED); return (-1); } /* Bump the unique portion of the name by one, wrapping arround if necessary. */ if (unique [1] >= 'Z') { unique [1] = 'A'; if (unique [0] >= 'Z') { unique [0] = 'A'; } else unique [0]++; } else unique [1]++; /* Add the unique two character name generated above to the result. */ (void) CS_stcpy (cp,unique); /* We continue generating names until we find one that doesn't exist. In this case, access does just what we need it to. */ } while (CS_access (tmp_fnm,0) == 0); /* If we get here, we have made a unique name. */ return (0); }
int EXP_LVL7 CS_ips (csFILE *strm,short rs,long32_t eofPos,int (*comp)(Const void *pp,Const void *qq)) { int st; size_t rec_cnt; /* Record count */ size_t buf_siz; /* Buffer size */ size_t rd_cnt; /* Read check. */ size_t wr_cnt; /* Write check. */ long32_t beg; /* File position of the beginning of the portion of the file which we are to sort but remains unsorted. */ long32_t end; /* File position of the end of the portion of the file which we are to sort but remains unsorted. */ void *buff; /* Pointer to malloc'ed sort buffer. */ /* Prepare for a possible error. */ buff = NULL; /* Establish the extrema of the sort. We support sorting only a portion of a file. */ beg = CS_ftell (strm); if (beg < 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; } end = CS_ftell (strm); if (end < 0L) { CS_erpt (cs_IOERR); goto error; } st = CS_fseek (strm,beg,SEEK_SET); if (st != 0) { CS_erpt (cs_IOERR); goto error; } } else { end = eofPos; } /* If there is nothing to sort, we done. */ if (end <= beg) { return 0; } /* Set up our buffer area. */ buf_siz = (size_t)(end - beg); buff = malloc (buf_siz); if (buff == NULL) { CS_erpt (cs_NO_MEM); goto error; } /* Compute some basic parameters for the sort. */ rec_cnt = buf_siz / (unsigned short)rs; /* Read in the entire file. */ rd_cnt = CS_fread (buff,1,buf_siz,strm); if (rd_cnt != buf_siz) { if (ferror (strm)) CS_erpt (cs_IOERR); else CS_erpt (cs_INV_FILE); goto error; } /* Sort it. */ qsort (buff,rec_cnt,rs,(int (_cdecl *)(Const void *pp,Const void *qq))comp); /*lint !e732 */ /* Write it back out. */ st = CS_fseek (strm,beg,SEEK_SET); if (st != 0) { CS_erpt (cs_IOERR); goto error; } wr_cnt = CS_fwrite (buff,1,buf_siz,strm); if (wr_cnt != buf_siz) { if (ferror (strm)) CS_erpt (cs_IOERR); else CS_erpt (cs_DISK_FULL); goto error; } /* Clean up */ CS_fseek (strm,beg,SEEK_SET); free (buff); return (1); error: if (buff != NULL) free (buff); return (-1); }
int EXP_LVL1 CS_cs2Wkt (char *bufr,size_t bufrSize,const char *csKeyName,int flavor) { int rtnValue = -1; const char* flavoredCsNamePtr = 0; const char* flavoredDtNamePtr = 0; const char* flavoredElNamePtr = 0; const char* msiCsNamePtr = 0; const char* msiDtNamePtr = 0; const char* msiElNamePtr = 0; struct cs_Dtdef_ *dtDefPtr = 0; struct cs_Eldef_ *elDefPtr = 0; struct cs_Csdef_ *csDefPtr = 0; if (bufrSize > 0) { *bufr = '\0'; csDefPtr = CS_csdef (csKeyName); if (csDefPtr != 0) { if (csDefPtr->dat_knm [0] == '\0') { CS_erpt (cs_WKT_NODTREF); } else { dtDefPtr = CS_dtdef (csDefPtr->dat_knm); if (dtDefPtr != 0) { elDefPtr = CS_eldef (dtDefPtr->ell_knm); if (elDefPtr != 0) { msiCsNamePtr = csDefPtr->key_nm; msiDtNamePtr = dtDefPtr->key_nm; msiElNamePtr = elDefPtr->key_nm; /* now flavor that name */ if (flavor == wktFlvrEsri) { if (msiCsNamePtr != 0) /*lint !e774 */ { flavoredCsNamePtr = CS_msiName2Esri(msiCsNamePtr); } if (msiDtNamePtr != 0) /*lint !e774 */ { flavoredDtNamePtr = CS_msiDtmName2Esri(msiDtNamePtr, 0); } if (msiElNamePtr != 0) /*lint !e774 */ { flavoredElNamePtr = CS_msiElpName2Esri(msiElNamePtr); } } else if (flavor == wktFlvrOracle) { if (msiCsNamePtr != 0) /*lint !e774 */ { flavoredCsNamePtr=CS_msiName2Oracle(msiCsNamePtr); } if (msiDtNamePtr != 0) /*lint !e774 */ { flavoredDtNamePtr=CS_msiDtmName2Oracle(msiDtNamePtr, 0); } if (msiElNamePtr != 0) /*lint !e774 */ { flavoredElNamePtr=CS_msiElpName2Oracle(msiElNamePtr); } } if (flavoredCsNamePtr != 0) { CS_stncp (csDefPtr->key_nm,flavoredCsNamePtr,cs_KEYNM_MAX); } if (flavoredDtNamePtr != 0) { CS_stncp (csDefPtr->dat_knm,flavoredDtNamePtr,cs_KEYNM_MAX); CS_stncp (dtDefPtr->key_nm,flavoredDtNamePtr,cs_KEYNM_MAX); } if (flavoredElNamePtr != 0) { CS_stncp (dtDefPtr->ell_knm,flavoredElNamePtr,cs_KEYNM_MAX); CS_stncp (elDefPtr->key_nm,flavoredElNamePtr,cs_KEYNM_MAX); } rtnValue = CScs2Wkt (bufr,bufrSize,flavor,csDefPtr,dtDefPtr,elDefPtr); /*lint !e64 */ CS_free (elDefPtr); elDefPtr = 0; } CS_free (dtDefPtr); dtDefPtr = 0; } } CS_free (csDefPtr); csDefPtr = 0; } } return rtnValue; }
/****************************************************************************** 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; }
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); }
int EXP_LVL3 CScs2WktEx (char *csWktBufr,size_t bufrSize,enum ErcWktFlavor flavor,const struct cs_Csdef_ *cs_def,const struct cs_Dtdef_ *dt_def,const struct cs_Eldef_ *el_def,unsigned short flags) { extern double cs_One; extern double cs_K90; extern double cs_Degree; extern char csErrnam []; extern struct cs_Prjtab_ cs_Prjtab []; int status; short prjCode; double tmpDbl; double primeMer; double unitFactor; const char *kCp; const char *prjNmPtr; const char *prmNmFalseEasting; const char *prmNmFalseNorthing; const char *prmNmScaleFactor; const char *prmNmCentralMeridian; const char *prmNmLatitudeOfOrigin; const char *prmNmStandardParallel1; const char *prmNmStandardParallel2; const char *prmNmYAxisAzimuth; const char *prmNmAzimuth; const char *prmNmLongitudeOfCenter; const char *prmNmLatitudeOfCenter; const char *prmNmLongitudeOf1stPoint; const char *prmNmLatitudeOf1stPoint; const char *prmNmLongitudeOf2ndPoint; const char *prmNmLatitudeOf2ndPoint; const char *prmNmLatitudeOfStdParall; struct cs_Dtdef_ *dtDefPtr; struct cs_Prjtab_ *prjPtr; char refDtmName [24]; char baseName [24]; char cTemp [64]; char datmWkt [512]; char pmerWkt [512]; char geogWkt [512]; char parmWkt [512]; char unitWkt [128]; char projWkt [1024]; char geoAxis [1024]; char prjAxis [1024]; char geoTranWkt [1024]; char projection [64]; char gcsName [128]; char dtmName [128]; char csysWktName [96]; status = 0; refDtmName [0] = '\0'; dtDefPtr = 0; if (cs_def == 0) { CS_stncp (csErrnam,"CS_cs2Wkt:1",MAXPATH); CS_erpt (cs_ISER); goto error; } /* Make sure we have a datum pointer. */ if (dt_def == NULL) { /* The calling application did not provide a specific datum definition. We use the datum name in the Coordinate System definition to obtain a definition fomr the dictionary. */ if (cs_def->dat_knm [0] == '\0') { /* Oops!!! No datum definition in the coordinate system definition. If we were to output something special for a cartographic definition, i.e. a coordinate system referenced directly to an ellipsoid, we would do that here. */ CS_erpt (cs_NO_REFERNCE); goto error; } /* We need to free this definition, we stash it in a new pointer variable. */ dtDefPtr = CS_dtdef (cs_def->dat_knm); if (dtDefPtr == NULL) { /* If the coordinate system definition came from the dictionary, this shouldn't happen. If the application got the cs_Csdef_ data from somewhere else, it is possible. */ CS_erpt (cs_NO_REFERNCE); goto error; } dt_def = dtDefPtr; } if (el_def != 0) { if (CS_stricmp (dt_def->ell_knm,el_def->key_nm)) { CS_erpt (cs_WKT_INCNSIST); goto error; } } /* Locate the projection in the projection table. We need this for access to the flag word for this projection. */ for (prjPtr = cs_Prjtab;prjPtr->code != cs_PRJCOD_END;prjPtr += 1) { if (!strcmp (cs_def->prj_knm,prjPtr->key_nm)) break; } if (prjPtr->code == cs_PRJCOD_END) { CS_erpt (cs_UNKWN_PROJ); goto error; } prjCode = prjPtr->code; prjNmPtr = 0; if (prjCode == cs_PRJCOD_SWISS && (flavor == wktFlvrEsri || flavor == wktFlvrOracle)) { prjNmPtr = CSwktPrjCode2Name (cs_PRJCOD_RSKEW,flavor); } else if (prjCode == cs_PRJCOD_LMTAN) { prjNmPtr = CSwktPrjCode2Name (cs_PRJCOD_LM1SP,flavor); } else if (prjPtr->code == cs_PRJCOD_UNITY) { prjNmPtr = "LL"; } else { prjNmPtr = CSwktPrjCode2Name (prjCode,flavor); } if (prjNmPtr == 0 || *prjNmPtr == '\0') { /* This projection is not supported by this flavor of WKT. */ CS_stncp (csErrnam,prjPtr->descr,MAXPATH); CS_erpt (cs_WKT_PRJSUPRT); goto error; } /* Locate the datum definition, if there is one. We can't do anything that isn't referenced to a datum. */ if (dt_def == NULL) /*lint !e774 */ { /* The calling application did not provide a specific deatum definition. We use the datum name in the Coordinate System definition to obtain a definition fomr the dictionary. */ if (cs_def->dat_knm [0] == '\0') { /* Oops!!! No datum definition in the coordinate system definition. If we were to output something special for a cartographic definition, i.e. a coordinate system referenced directly to an ellipsoid, we would do that here. */ CS_erpt (cs_NO_REFERNCE); goto error; } dtDefPtr = CS_dtdef (cs_def->dat_knm); if (dtDefPtr == NULL) { /* If the coordinate system definition came from the dictionary, this shouldn't happen. If the application got the cs_Csdef_ data from somewhere else, it is possible. */ CS_erpt (cs_NO_REFERNCE); goto error; } /* Capture the name of referenced datum which we will be using. */ CS_stncp (refDtmName,cs_def->dat_knm,sizeof (refDtmName)); /* I don't have to locate the ellipsoid, CSdt2WktEx will do that. */ status = CSdt2WktEx (datmWkt,sizeof (datmWkt),geoTranWkt,sizeof (geoTranWkt),flavor,dtDefPtr,0,flags); CS_free (dtDefPtr); dtDefPtr = 0; } else { CS_stncp (refDtmName,dt_def->key_nm,sizeof (refDtmName)); status = CSdt2WktEx (datmWkt,sizeof (datmWkt),geoTranWkt,sizeof (geoTranWkt),flavor,dt_def,el_def,flags); } if (status != 0) { /* CSdt2WktEx will have reported the nature of the error. */ goto error; } /* Deal with the quad/axis situation. */ geoAxis [0] = '\0'; prjAxis [0] = '\0'; if (cs_def->quad != 0 && cs_def->quad != 1) { if ((prjPtr->flags & cs_PRJFLG_GEOGR) != 0) { switch (cs_def->quad) { default: case 0: case 1: CS_stncp (geoAxis,",AXIS[\"Lon\",EAST],AXIS[\"Lat\",NORTH]",sizeof (prjAxis)); break; case 2: CS_stncp (geoAxis,",AXIS[\"Lon\",WEST],AXIS[\"Lat\",NORTH]",sizeof (prjAxis)); break; case 3: CS_stncp (geoAxis,",AXIS[\"Lon\",WEST],AXIS[\"Lat\",SOUTH]",sizeof (prjAxis)); break; case 4: CS_stncp (geoAxis,",AXIS[\"Lon\",EAST],AXIS[\"Lat\",SOUTH]",sizeof (prjAxis)); break; case -1: CS_stncp (geoAxis,",AXIS[\"Lat\",NORTH],AXIS[\"Lon\",EAST]",sizeof (prjAxis)); break; case -2: CS_stncp (geoAxis,",AXIS[\"Lat\",NORTH],AXIS[\"Lon\",WEST]",sizeof (prjAxis)); break; case -3: CS_stncp (geoAxis,",AXIS[\"Lat\",SOUTH],AXIS[\"Lon\",WEST]",sizeof (prjAxis)); break; case -4: CS_stncp (geoAxis,",AXIS[\"Lat\",SOUTH],AXIS[\"Lon\",EAST]",sizeof (prjAxis)); break; } } else { switch (cs_def->quad) { default: case 0: case 1: CS_stncp (prjAxis,",AXIS[\"X\",EAST],AXIS[\"Y\",NORTH]",sizeof (prjAxis)); break; case 2: CS_stncp (prjAxis,",AXIS[\"X\",WEST],AXIS[\"Y\",NORTH]",sizeof (prjAxis)); break; case 3: CS_stncp (prjAxis,",AXIS[\"X\",WEST],AXIS[\"Y\",SOUTH]",sizeof (prjAxis)); break; case 4: CS_stncp (prjAxis,",AXIS[\"X\",EAST],AXIS[\"Y\",SOUTH]",sizeof (prjAxis)); break; case -1: CS_stncp (prjAxis,",AXIS[\"Y\",NORTH],AXIS[\"X\",EAST]",sizeof (prjAxis)); break; case -2: CS_stncp (prjAxis,",AXIS[\"Y\",NORTH],AXIS[\"X\",WEST]",sizeof (prjAxis)); break; case -3: CS_stncp (prjAxis,",AXIS[\"Y\",SOUTH],AXIS[\"X\",WEST]",sizeof (prjAxis)); break; case -4: CS_stncp (prjAxis,",AXIS[\"Y\",SOUTH],AXIS[\"X\",EAST]",sizeof (prjAxis)); break; } } } /* Locate the base. The base is what this coordinate system is referenced to. For example, the definition of UTM27-13 defines how to get from LL27 to UTM27-13. Therefore, LL27 is the base for that coordinate system. */ if ((prjPtr->flags & cs_PRJFLG_GEOGR) != 0) { /* This is a geographic coordinate system, so the base name is whatever the coordinate system name is. */ CS_stncp (baseName,cs_def->key_nm,sizeof (baseName)); } else { /* Otherwise, basename is the name of a geographic coordinate system referenced to the same datum as the projected coordinate system. We have a function which will find this for us. If we don't have one, we are in trouble. */ CSllCsFromDt (baseName,sizeof baseName,refDtmName); if (!CS_csIsValid (baseName)) { CS_stncp (csErrnam,cs_def->key_nm,MAXPATH); CS_erpt (cs_WKT_NOLLBASE); return -1; } } /* Manufacture the prime meridian. */ CS_stncp (pmerWkt,"PRIMEM[\"Greenwich\",0]",sizeof (pmerWkt)); if ((prjPtr->flags & cs_PRJFLG_GEOGR) != 0 && cs_def->org_lng != 0.0) { int orgLng = (int)cs_def->org_lng; switch (orgLng) { case 0: primeMer = 0.0; CS_stncp (pmerWkt,"PRIMEM[\"Greenwich\",0]",sizeof (pmerWkt)); break; case 2: primeMer = 2.337229166666667; CS_stncp (pmerWkt,"PRIMEM[\"Paris\",2.337229166666667]",sizeof (pmerWkt)); break; case 9: primeMer = 9.13190611111111; CS_stncp (pmerWkt,"PRIMEM[\"Lisbon\",9.13190611111111]",sizeof (pmerWkt)); break; case -17: primeMer = -17.4; CS_stncp (pmerWkt,"PRIMEM[\"Ferro\",-17.4]",sizeof (pmerWkt)); break; case -74: primeMer = -74.08175; CS_stncp (pmerWkt,"PRIMEM[\"Bogota\",-74.08175]",sizeof (pmerWkt)); break; default: break; } } /* We will always need the GEOGCS object. If this is a geographic coordinate system definition, than that's all we'll need. If this is a Projective coordinate system, the unit is the default for internal coordinates within CS-MAP, namely the degree. Only if this is a Geographic Coordinate system, is the actual unit of the definition of importance to us here. */ kCp = CSmsiUnitName2WktName ("DEGREE",flavor); if (kCp == 0 || *kCp == '\0') { kCp = "Degree"; } sprintf (unitWkt,"UNIT[\"%s\",0.017453292519943295]",kCp); if ((prjPtr->flags & cs_PRJFLG_GEOGR) != 0) { /* This is a geographic coordinate system, extract the unit information from the definition. */ kCp = CSmsiUnitName2WktName (cs_def->unit,flavor); if (kCp == 0) { /* Just in case the flavor does not define angular units... */ kCp = "Degree"; unitFactor = cs_Degree; } else { unitFactor = CS_unitlu (cs_UTYP_ANG,cs_def->unit) * cs_Degree; } sprintf (unitWkt,"UNIT[\"%s\",%.14f]",kCp,unitFactor); } /* If we are mapping names, the GCS name and the Datum name need to be mapped, and then configured for the active flavor. First, we do the default in case anything goes wrong in the mapping process. */ sprintf (geogWkt,"GEOGCS[\"%s\",%s,%s,%s%s]",baseName,datmWkt,pmerWkt,unitWkt,geoAxis); if ((flags & cs_WKTFLG_MAPNAMES) != 0) { CS_stncp (dtmName,baseName,sizeof (dtmName)); CS_stncp (gcsName,baseName,sizeof (gcsName)); if (flavor == wktFlvrEsri) { kCp = CS_msiDtmName2Esri (dt_def->key_nm,0); if (kCp != 0) { if (*kCp != 'D' || *(kCp + 1) != '_') { CS_stcpy (dtmName,"D_"); CS_stncp (&dtmName [2],kCp,sizeof (dtmName) - 2); CS_stcpy (gcsName,"GCS_"); CS_stncp (&gcsName [4],kCp,sizeof (gcsName) - 4); } else { CS_stncp (dtmName,kCp,sizeof (dtmName)); CS_stcpy (gcsName,"GCS_"); CS_stncp (&gcsName [4],kCp+2,sizeof (gcsName) - 4); } } } else if (flavor == wktFlvrOracle) { kCp = CS_msiDtmName2Oracle (dt_def->key_nm,0); if (kCp != 0) { CS_stncp (dtmName,kCp,sizeof (dtmName)); if ((prjPtr->flags & cs_PRJFLG_GEOGR) != 0) { sprintf (gcsName,"Longitude / Latitude (%s)",kCp); } else { CS_stncp (gcsName,kCp,sizeof (gcsName)); } } } sprintf (geogWkt,"GEOGCS[\"%s\",%s,%s,%s%s]",gcsName,datmWkt,pmerWkt,unitWkt,geoAxis); } if ((prjPtr->flags & cs_PRJFLG_GEOGR) != 0) { /* If this is a geographic coordinate system, we're done. */ CS_stncp (csWktBufr,geogWkt,(int)bufrSize); } else { /* We get here only if the coordinate system is of the projected type. */ /* Do the linear unit for the projWkt. */ unitFactor = CS_unitlu (cs_UTYP_LEN,cs_def->unit); kCp = CSmsiUnitName2WktName (cs_def->unit,flavor); if (kCp == 0 || *kCp == '\0') { CS_stncp (csErrnam,cs_def->unit,MAXPATH); CS_erpt (cs_WKT_UNITMAP); return -1; } sprintf (unitWkt,"UNIT[\"%s\",%.14f]",kCp,unitFactor); prmNmFalseEasting = CSwktPrmEnum2Name (csWktPrmFalseEasting,flavor); prmNmFalseNorthing = CSwktPrmEnum2Name (csWktPrmFalseNorthing,flavor); prmNmScaleFactor = CSwktPrmEnum2Name (csWktPrmScaleAtCenter,flavor); prmNmCentralMeridian = CSwktPrmEnum2Name (csWktPrmLongitudeOfOrg,flavor); prmNmLatitudeOfOrigin = CSwktPrmEnum2Name (csWktPrmLatitudeOfOrg,flavor); prmNmStandardParallel1 = CSwktPrmEnum2Name (csWktPrmStdParallel1,flavor); prmNmStandardParallel2 = CSwktPrmEnum2Name (csWktPrmStdParallel2,flavor); prmNmYAxisAzimuth = CSwktPrmEnum2Name (csWktPrmYaxisAzimuth,flavor); prmNmAzimuth = CSwktPrmEnum2Name (csWktPrmAzimuth,flavor); prmNmLongitudeOfCenter = CSwktPrmEnum2Name (csWktPrmLongitudeOfCtr,flavor); prmNmLatitudeOfCenter = CSwktPrmEnum2Name (csWktPrmLatitudeOfCtr,flavor); prmNmLongitudeOf1stPoint = CSwktPrmEnum2Name (csWktPrmLngFirstPoint,flavor); prmNmLatitudeOf1stPoint = CSwktPrmEnum2Name (csWktPrmLatFirstPoint,flavor); prmNmLongitudeOf2ndPoint = CSwktPrmEnum2Name (csWktPrmLngSecondPoint,flavor); prmNmLatitudeOf2ndPoint = CSwktPrmEnum2Name (csWktPrmLatSecondPoint,flavor); prmNmLatitudeOfStdParall = CSwktPrmEnum2Name (csWktPrmLatOfStdParall,flavor); /* Build the projection and parameter portions of this thing. */ parmWkt [0] = '\0'; CS_stcpy (projection,prjNmPtr); switch (prjCode) { case cs_PRJCOD_TRMER: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.12f]",prmNmScaleFactor,cs_def->scl_red); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfOrigin,cs_def->org_lat); strcat (parmWkt,cTemp); break; case cs_PRJCOD_ALBER: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmStandardParallel1,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmStandardParallel2,cs_def->prj_prm2); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfOrigin,cs_def->org_lat); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->org_lng); strcat (parmWkt,cTemp); break; case cs_PRJCOD_MRCAT: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmStandardParallel1,cs_def->prj_prm2); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfOrigin,cs_def->org_lat); strcat (parmWkt,cTemp); break; case cs_PRJCOD_AZMED: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmYAxisAzimuth,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->org_lng); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfOrigin,cs_def->org_lat); strcat (parmWkt,cTemp); break; case cs_PRJCOD_PLYCN: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfOrigin,cs_def->org_lat); strcat (parmWkt,cTemp); break; case cs_PRJCOD_AZMEA: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->org_lng); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfOrigin,cs_def->org_lat); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmYAxisAzimuth,cs_def->prj_prm1); strcat (parmWkt,cTemp); break; case cs_PRJCOD_EDCNC: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmStandardParallel1,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmStandardParallel2,cs_def->prj_prm2); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfOrigin,cs_def->org_lat); strcat (parmWkt,cTemp); break; case cs_PRJCOD_MILLR: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfOrigin,cs_def->org_lat); strcat (parmWkt,cTemp); break; case cs_PRJCOD_NZLND: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfOrigin,cs_def->org_lat); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->org_lng); strcat (parmWkt,cTemp); break; case cs_PRJCOD_SINUS: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->prj_prm1); strcat (parmWkt,cTemp); break; case cs_PRJCOD_EDCYL: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmStandardParallel1,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfOrigin,cs_def->org_lat); strcat (parmWkt,cTemp); break; case cs_PRJCOD_VDGRN: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->prj_prm1); strcat (parmWkt,cTemp); break; case cs_PRJCOD_CSINI: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfOrigin,cs_def->org_lat); strcat (parmWkt,cTemp); break; case cs_PRJCOD_ROBIN: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->prj_prm1); strcat (parmWkt,cTemp); break; case cs_PRJCOD_BONNE: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmStandardParallel1,cs_def->prj_prm1); strcat (parmWkt,cTemp); break; case cs_PRJCOD_EKRT4: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->prj_prm1); strcat (parmWkt,cTemp); break; case cs_PRJCOD_EKRT6: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->prj_prm1); strcat (parmWkt,cTemp); break; case cs_PRJCOD_MOLWD: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->prj_prm1); strcat (parmWkt,cTemp); break; case cs_PRJCOD_PSTRO: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfOrigin,cs_def->org_lat); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.12f]",prmNmScaleFactor,cs_def->scl_red); strcat (parmWkt,cTemp); break; case cs_PRJCOD_PSTROSL: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfOrigin,cs_def->org_lat); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmStandardParallel1,cs_def->prj_prm1); strcat (parmWkt,cTemp); /* Kludge time again. If the flavor is ESRI, we change the rpojection name based on the origin latitude. Sorry about that, but this WKT stuff is maddening. */ if (flavor == wktFlvrEsri) { if (cs_def->org_lat < -89.0) { CS_stncp (projection,"Stereographic_South_Pole",sizeof (projection)); } else if (cs_def->org_lat < -89.0) { CS_stncp (projection,"Stereographic_North_Pole",sizeof (projection)); } } break; case cs_PRJCOD_OSTRO: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfOrigin,cs_def->org_lat); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->org_lng); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.12f]",prmNmScaleFactor,cs_def->scl_red); strcat (parmWkt,cTemp); break; case cs_PRJCOD_LM1SP: case cs_PRJCOD_LMTAN: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.12f]",prmNmScaleFactor,cs_def->scl_red); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->org_lng); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfOrigin,cs_def->org_lat); strcat (parmWkt,cTemp); break; case cs_PRJCOD_LM2SP: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->org_lng); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfOrigin,cs_def->org_lat); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmStandardParallel1,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmStandardParallel2,cs_def->prj_prm2); strcat (parmWkt,cTemp); break; case cs_PRJCOD_UTM: tmpDbl = 500000.00 / unitFactor; sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,tmpDbl); strcat (parmWkt,cTemp); tmpDbl = (cs_def->prj_prm2 >= 0.0) ? 0.0 : 10000000.0; tmpDbl /= unitFactor; sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,tmpDbl); strcat (parmWkt,cTemp); tmpDbl = (double)(-183 + (6 * (int)cs_def->prj_prm1)); /*lint !e790 */ sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,tmpDbl); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",0.9996]",prmNmScaleFactor); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",0.000]",prmNmLatitudeOfOrigin); strcat (parmWkt,cTemp); break; case cs_PRJCOD_TRMRS: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.12f]",prmNmScaleFactor,cs_def->scl_red); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfOrigin,cs_def->org_lat); strcat (parmWkt,cTemp); break; case cs_PRJCOD_HOM1XY: case cs_PRJCOD_RSKEW: case cs_PRJCOD_RSKEWC: case cs_PRJCOD_RSKEWO: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.12f]",prmNmScaleFactor,cs_def->scl_red); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmAzimuth,cs_def->prj_prm3); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLongitudeOfCenter,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfCenter,cs_def->prj_prm2); strcat (parmWkt,cTemp); break; case cs_PRJCOD_HOM2XY: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.12f]",prmNmScaleFactor,cs_def->scl_red); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLongitudeOf1stPoint,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOf1stPoint,cs_def->prj_prm2); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLongitudeOf2ndPoint,cs_def->prj_prm3); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOf2ndPoint,cs_def->prj_prm4); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfCenter,cs_def->org_lat); strcat (parmWkt,cTemp); break; case cs_PRJCOD_GAUSSK: sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.12f]",prmNmScaleFactor,cs_def->scl_red); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmCentralMeridian,cs_def->prj_prm1); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfOrigin,cs_def->org_lat); strcat (parmWkt,cTemp); break; case cs_PRJCOD_SWISS: CS_stncp (projection,prjNmPtr,sizeof (projection)); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseEasting,cs_def->x_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.3f]",prmNmFalseNorthing,cs_def->y_off); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.12f]",prmNmScaleFactor,cs_One); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmAzimuth,cs_K90); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLongitudeOfCenter,cs_def->org_lng); strcat (parmWkt,cTemp); sprintf (cTemp,",PARAMETER[\"%s\",%.14f]",prmNmLatitudeOfCenter,cs_def->org_lat); strcat (parmWkt,cTemp); break; } /*lint !e744 */ /* Need to determine the name we will assign to this definition. We generate a default value which is used if anything else fails. */ CS_stncp (csysWktName,cs_def->key_nm,sizeof (csysWktName)); if ((flags & cs_WKTFLG_MAPNAMES) != 0) { if (flavor == wktFlvrEsri) { kCp = CS_msiName2Esri (cs_def->key_nm); if (kCp != 0) { CS_stncp (csysWktName,kCp,sizeof (csysWktName)); } } else if (flavor == wktFlvrOracle) { kCp = CS_msiName2Oracle (cs_def->key_nm); if (kCp != 0) { CS_stncp (csysWktName,kCp,sizeof (csysWktName)); } } } /* Construct the final string. */ sprintf (projWkt,"PROJCS[\"%s\",%s,PROJECTION[\"%s\"]%s,%s%s]",csysWktName,geogWkt,projection,parmWkt,unitWkt,prjAxis); CS_stncp (csWktBufr,projWkt,(int)bufrSize); } if (dtDefPtr != 0) { CS_free (dtDefPtr); } return 0; error: if (dtDefPtr != 0) { CS_free (dtDefPtr); } return -1; }
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); }
int EXP_LVL9 CSparm7S (struct cs_GxXform_* gxXfrm) { extern double cs_One; extern double cs_Sec2Rad; /* 4.848136E-06 */ struct csParm7_ *parm7; double trgScale; double sinAlpha, cosAlpha; double sinBeta, cosBeta; double sinGamma, cosGamma; parm7 = &gxXfrm->xforms.parm7; parm7->srcERad = gxXfrm->srcDatum.e_rad; parm7->srcESqr = gxXfrm->srcDatum.ecent * gxXfrm->srcDatum.ecent; parm7->trgERad = gxXfrm->trgDatum.e_rad; parm7->trgESqr = gxXfrm->trgDatum.ecent * gxXfrm->trgDatum.ecent; parm7->deltaX = gxXfrm->gxDef.parameters.geocentricParameters.deltaX; parm7->deltaY = gxXfrm->gxDef.parameters.geocentricParameters.deltaY; parm7->deltaZ = gxXfrm->gxDef.parameters.geocentricParameters.deltaZ; sinAlpha = sin (gxXfrm->gxDef.parameters.geocentricParameters.rotateX * cs_Sec2Rad); cosAlpha = cos (gxXfrm->gxDef.parameters.geocentricParameters.rotateX * cs_Sec2Rad); sinBeta = sin (gxXfrm->gxDef.parameters.geocentricParameters.rotateY * cs_Sec2Rad); cosBeta = cos (gxXfrm->gxDef.parameters.geocentricParameters.rotateY * cs_Sec2Rad); sinGamma = sin (gxXfrm->gxDef.parameters.geocentricParameters.rotateZ * cs_Sec2Rad); cosGamma = cos (gxXfrm->gxDef.parameters.geocentricParameters.rotateZ * cs_Sec2Rad); /* View the following as the development of a 3x3 orthogonal rotation matirx: rt12 = rotate matrix row 1 column 2 */ parm7->rt11 = cosBeta * cosGamma; parm7->rt21 = -cosBeta * sinGamma; parm7->rt31 = sinBeta; parm7->rt12 = cosAlpha * sinGamma + sinAlpha * sinBeta * cosGamma; parm7->rt22 = cosAlpha * cosGamma - sinAlpha * sinBeta * sinGamma; parm7->rt32 = -sinAlpha * cosBeta; parm7->rt13 = sinAlpha * sinGamma - cosAlpha * sinBeta * cosGamma; parm7->rt23 = sinAlpha * cosGamma + cosAlpha * sinBeta * sinGamma; parm7->rt33 = cosAlpha * cosBeta; trgScale = cs_One + (gxXfrm->gxDef.parameters.geocentricParameters.scale * 1.0E-06); if (fabs (trgScale) < 1.0E-06) { CS_erpt (cs_ISER); } else { parm7->scale = (cs_One + (gxXfrm->gxDef.parameters.geocentricParameters.scale * 1.0E-06)); } parm7->errorValue = gxXfrm->errorValue; parm7->cnvrgValue = gxXfrm->cnvrgValue; parm7->maxIterations = gxXfrm->maxIterations; gxXfrm->frwrd2D = (cs_FRWRD2D_CAST)CSparm7F2; gxXfrm->frwrd3D = (cs_FRWRD3D_CAST)CSparm7F3; gxXfrm->invrs2D = (cs_INVRS2D_CAST)CSparm7I2; gxXfrm->invrs3D = (cs_INVRS3D_CAST)CSparm7I3; gxXfrm->inRange = (cs_INRANGE_CAST)CSparm7L; gxXfrm->release = (cs_RELEASE_CAST)CSparm7R; gxXfrm->destroy = (cs_DESTROY_CAST)CSparm7D; return 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; }
/****************************************************************************** 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; }
int EXP_LVL9 CSpstroF (Const struct cs_Pstro_ *pstro,double xy [2],Const double ll [2]) { extern char csErrnam [MAXPATH]; extern double cs_Degree; /* 1.0 / RADIAN */ extern double cs_Half; /* 0.5 */ extern double cs_One; /* 1.0 */ extern double cs_Pi; /* 3.14159... */ extern double cs_Pi_o_2; /* PI over 2 */ extern double cs_Pi_o_4; /* PI over 4 */ extern double cs_NPTest; /* 0.001 seconds of arc short of the north pole, in radians. */ extern double cs_Huge; /* Huge value, but not too huge. */ int rtn_val; double lng; /* The given longitude, after conversion to radians. */ double lat; /* The given latitude after conversion to radians. */ double x; double y; double del_lng; double sin_del_lng; double cos_del_lng; double sin_lat; double t; double rho; double tmp1; double tmp2; double tmp3; rtn_val = cs_CNVRT_NRML; /* There are two formulae, one for the sphere and one for the ellipsoid. If the ecentricity of the dataum in use is 0.0 exactly, we shall use the spherical formulae. */ lat = cs_Degree * ll [LAT]; if (fabs (lat) > cs_NPTest) { rtn_val = cs_CNVRT_INDF; if (fabs (lat) > cs_Pi_o_2) { rtn_val = cs_CNVRT_RNG; lat = CS_adj1pi (lat); } } lng = cs_Degree * ll [LNG]; /* We first adjust the following so that we can use much of the code below for the southern polar aspect without duplicating it with minor sign changes. */ if (pstro->aspect == cs_STERO_SOUTH && pstro->ecent != 0.0) { lat = -lat; del_lng = pstro->org_lng - lng; } else { del_lng = lng - pstro->org_lng; } if (fabs (del_lng) > cs_Pi) del_lng = CS_adj2pi (del_lng); sin_del_lng = sin (del_lng); cos_del_lng = cos (del_lng); sin_lat = sin (lat); /* See if the datum is a sphere or an ellipsoid. */ if (pstro->ecent == 0.0) { /* Here for the sphere. */ switch (pstro->aspect) { case cs_STERO_NORTH: tmp1 = cs_Pi_o_4 - (lat * cs_Half); tmp1 = pstro->two_ka * tan (tmp1); x = tmp1 * sin_del_lng; y = -tmp1 * cos_del_lng; break; case cs_STERO_SOUTH: tmp1 = cs_Pi_o_4 + (lat * cs_Half); tmp1 = pstro->two_ka * tan (tmp1); x = tmp1 * sin_del_lng; y = tmp1 * cos_del_lng; break; default: x = y = -cs_Huge; CS_stncp (csErrnam,"CS_pstro:1",MAXPATH); CS_erpt (cs_ISER); rtn_val = -1; break; } /*lint !e744 */ } else { /* Here for an ellipsoid model of the earth. */ tmp1 = pstro->ecent * sin_lat; tmp2 = (cs_One - tmp1) / (cs_One + tmp1); tmp2 = pow (tmp2,pstro->e_o_2); tmp3 = lat * cs_Half; t = tan (cs_Pi_o_4 - tmp3) / tmp2; switch (pstro->aspect) { case cs_STERO_NORTH: rho = pstro->two_ka * t / pstro->e_term; x = rho * sin_del_lng; y = -rho * cos_del_lng; break; case cs_STERO_SOUTH: rho = pstro->two_ka * t / pstro->e_term; x = -rho * sin_del_lng; y = rho * cos_del_lng; break; default: x = y = -cs_Huge; CS_stncp (csErrnam,"CS_pstro:1",MAXPATH); CS_erpt (cs_ISER); rtn_val = -1; break; } /*lint !e744 */ } /* Adjust for the selected quadrant, and, finally, add false easting and false northing. */ xy [XX] = x; /*lint !e644 */ xy [YY] = y; /*lint !e644 */ if (pstro->quad == 0) { xy [XX] = x + pstro->x_off; xy [YY] = y + pstro->y_off; } else { CS_quadF (xy,x,y,pstro->x_off,pstro->y_off,pstro->quad); } return (rtn_val); }
int EXP_LVL9 CSparm7I2 (struct csParm7_ *parm7,double* trgLl,Const double* srcLl) { int ii; int lngOk; int latOk; int rtnVal; double guess [3]; double newLl [3]; double epsilon [3]; /* Assume everything goes OK until we know different. */ rtnVal = 0; epsilon [0] = epsilon [1] = parm7->cnvrgValue; /* keep gcc compiler happy */ /* First, we copy the WGS-84 lat/longs to the local array. This is the default result which the user may want in the event of a fatal error. Note, we assume such has been done below, even if there has not been an error. */ trgLl [LNG] = guess [LNG] = srcLl [LNG]; trgLl [LAT] = guess [LAT] = srcLl [LAT]; trgLl [HGT] = srcLl [HGT]; /* To improve performancce, we could use CS_bw3dInvrs here to get our guess. That function will probably reduce the number of iterations require below substantially. */ /* Start a loop which will iterate as many as maxIteration times. */ for (ii = 0;ii < parm7->maxIterations;ii++) { /* Assume we are done until we know different. */ lngOk = latOk = TRUE; /* Compute the WGS-84 lat/long for our current guess. */ rtnVal = CSparm7F2 (parm7,newLl,guess); if (rtnVal != 0) { /* Oopps!! We must have been given some pretty strange coordinate values. */ break; } /* See how far we are off. */ epsilon [LNG] = srcLl [LNG] - newLl [LNG]; epsilon [LAT] = srcLl [LAT] - newLl [LAT]; /* If our guess at the longitude is off by more than small, we adjust our guess by the amount we are off. */ if (fabs (epsilon [LNG]) > parm7->cnvrgValue) { lngOk = FALSE; guess [LNG] += epsilon [LNG]; } /* If our guess longitude is off by more than small, we adjust our guess by the amount we are off. */ if (fabs (epsilon [LAT]) > parm7->cnvrgValue) { latOk = FALSE; guess [LAT] += epsilon [LAT]; } /* If our current guess produces a newLl that is within samllValue of srcLl, we are done. */ if (lngOk && latOk) break; } /* If we didn't resolve in maxIteration tries, we issue a warning message. Usually, three or four iterations does the trick. */ if (ii >= parm7->maxIterations ) { CS_erpt (cs_7P_CNVRG); /* Issue a warning if we're close, a fatal if we are still way off. In any case, we return the last computed value. We could have gotten very fancy with this stuff, but it would have had serious affects on the performance. So we just check epsilon here as we know we have an error and this doesn't happen very often. */ rtnVal = 1; if (fabs (epsilon [LNG]) > parm7->errorValue || fabs (epsilon [LAT]) > parm7->errorValue) { /* This is not supposed to happen. It will not happen if the input coordinates are anywhere reasonable. However, since the contract is that once created, a transformation always returns a rational result, with perhaps a warning status, we return a +1 here. If you prefer a fatal, change this value to -1. */ rtnVal = 1; } } /* If we are not returning fatal error status, we return the last computed value even if we are returning a warning status. It may be of value, often is. */ if (rtnVal >= 0) { trgLl [LNG] = guess [LNG]; trgLl [LAT] = guess [LAT]; } return rtnVal; }
/****************************************************************************** Calculate inverse datum shift, the second main man. Note that this is a deviation from using the exact code used by the governmental products. The different government supplied programs use the same algorothm, but with slightly different implementation details. Here we use the same details for all objects. Returns 0 for expected result -1 for hard/fatal failure +1 for no data coverage, unshifted result returned +2 for no data coverage, fallback used successfully */ int CSinverseAts77ToCsrs (struct csAts77ToCsrs_* __This,double* ll_ats77,Const double *ll_csrs) { static int itmax = 10; static double small = 1.0E-9; /* this is degrees */ short lng_ok; short lat_ok; int ii; int status; double guess [3]; double epsilon [2]; double newResult [3]; guess [LNG] = ll_csrs [LNG]; guess [LAT] = ll_csrs [LAT]; guess [HGT] = ll_csrs [HGT]; /* Start a loop which will iterate up to 10 times. The Canadians and the Aussies max out at 4. We would duplicate theirs, but since this is an inverse, we'll do a little better than they do. */ for (ii = 1;ii < itmax;ii++) { /* Assume we are done until we know different. */ lng_ok = lat_ok = TRUE; /* Compute the NAD83 lat/long for our current guess. */ status = CScalcAts77ToCsrs (__This,newResult,guess); /* If there is no data for this lat/long, we use the fallback in one is available. */ if (status != 0) { if (status > 0 && __This->fallback != NULL) { status = CScalcFallbackInverse (__This->fallback,ll_ats77,ll_csrs); } return (status); } /* See how far we are off. */ epsilon [LNG] = ll_csrs [LNG] - newResult [LNG]; epsilon [LAT] = ll_csrs [LAT] - newResult [LAT]; /* If our guess at the longitude is off by more than small, we adjust our guess by the amount we are off. */ if (fabs (epsilon [LNG]) > small) { lng_ok = FALSE; guess [LNG] += epsilon [LNG]; } if (fabs (epsilon [LAT]) > small) { lat_ok = FALSE; guess [LAT] += epsilon [LAT]; } /* If our current guess produces a newResult that is within small of original, we are done. */ if (lng_ok && lat_ok) break; } /* If we didn't resolve in four tries, we issue a warning message. Casual reading of the NADCON code would lead one to believe that they do five iterations, but four is all they really do. */ if (ii >= itmax) { CS_erpt (cs_NADCON_ICNT); return (1); } /* Adjust the ll66 value to the computed value, now that we know that it should be correct. */ ll_ats77 [LNG] = guess [LNG]; ll_ats77 [LAT] = guess [LAT]; return 0; }