int CStest8 (int verbose,int crypt) { extern char cs_MeKynm [128]; extern char cs_MeFunc [128]; extern double cs_Coords [3]; extern struct cs_Grptbl_ cs_CsGrptbl []; extern int cs_Error; int err_cnt; struct cs_Grptbl_ *tp; struct cs_Csgrplst_ *gp; struct cs_Csgrplst_ *grp_list; struct cs_Csprm_ *csprm; double xy [3]; double ll [3]; printf ("Exercising each coordinate system definition at least once.\n"); /* Loop through the group table and fetch a linked list for each group. Count the number in the group and add to the total in the group. */ err_cnt = 0; for (tp = cs_CsGrptbl;tp->group [0] != 0;tp += 1) { if (!CS_stricmp (tp->group,"LEGACY")) { continue; } CS_csgrp (tp->group,&grp_list); for (gp = grp_list;gp != NULL;gp = gp->next) { /* Activate this coordinate system. This ensures that every coordinate system is "set up" at least once in all of this. */ if (verbose) { printf ("Exercising coordinate system named %s.\n", gp->key_nm); } csprm = CS_csloc (gp->key_nm); if (csprm == NULL) { printf ("Couldn't setup coordinate system named %s.\n",gp->key_nm); err_cnt += 1; } else { /* Set information in case there is a floating point exception. */ CS_stncp (cs_MeKynm,gp->key_nm,sizeof (cs_MeKynm)); cs_Coords [0] = csprm->csdef.x_off; cs_Coords [1] = csprm->csdef.y_off; cs_Coords [2] = 0.0; /* Convert a coordinate, the false origin should be a safe one. */ xy [0] = csprm->csdef.x_off; xy [1] = csprm->csdef.y_off; xy [2] = 0.0; cs_Error = 0; CS_stncp (cs_MeFunc,"CS_cs2ll",sizeof (cs_MeFunc)); CS_cs2ll (csprm,ll,xy); CS_stncp (cs_MeFunc,"CS_ll2cs",sizeof (cs_MeFunc)); CS_ll2cs (csprm,xy,ll); CS_stncp (cs_MeFunc,"CS_csscl",sizeof (cs_MeFunc)); CS_csscl (csprm,ll); CS_stncp (cs_MeFunc,"CS_cscnv",sizeof (cs_MeFunc)); CS_cscnv (csprm,ll); if (cs_Error != 0) { printf ("Exercise of coordinate system %s failed.\n", csprm->csdef.key_nm); err_cnt += 1; } CS_free (csprm); } } CS_csgrpf (grp_list); } cs_MeKynm [0] = '\0'; cs_MeFunc [0] = '\0'; cs_Coords [0] = 0.0; cs_Coords [1] = 0.0; cs_Coords [2] = 0.0; return (err_cnt); }
int CStestC (bool verbose,long32_t duration) { int err_cnt; unsigned sequencer; struct cs_Grptbl_ *tp; struct cs_Csgrplst_ *gp; struct cs_Csgrplst_ *grp_list; struct cs_Csprm_ *csprm; double ll [3]; double xy [3]; double falseOrg [2]; double llAry [1][3]; double xyAry [1][3]; duration *= 10L; printf ("Trying very hard to produce a floating point exception.\n"); /* Loop through the group table and fetch a linked list for each group. Count the number in the group and add to the total in the group. */ err_cnt = 0; csprm = NULL; for (tp = cs_CsGrptbl;tp->group [0] != 0;tp += 1) { if (csprm != NULL) { CS_free (csprm); csprm = NULL; } if (!CS_stricmp (tp->group,"LEGACY")) { continue; } CS_csgrp (tp->group,&grp_list); for (gp = grp_list;gp != NULL;gp = gp->next) { if (csprm != NULL) { CS_free (csprm); csprm = NULL; } if (verbose) { printf ("Trying to cause a floating exception using %s.\n", gp->key_nm); } else { printf ("%s \r",gp->key_nm); } csprm = CS_csloc (gp->key_nm); if (csprm == NULL) { printf ("Couldn't setup coordinate system named %s.\n",gp->key_nm); err_cnt += 1; strcpy (cs_MeKynm,"???"); continue; } cs_MeFlag = 0; strcpy (cs_MeKynm,csprm->csdef.key_nm); sequencer = 0; while (CStestLLH (ll,csprm->cent_mer,&sequencer) == 0) { cs_Coords [LNG] = ll [0]; cs_Coords [LAT] = ll [1]; cs_Coords [HGT] = ll [2]; strcpy (cs_MeFunc,"CS_cssck"); CS_cssck (csprm,ll); if (cs_MeFlag) break; strcpy (cs_MeFunc,"CS_cssch"); CS_cssch (csprm,ll); if (cs_MeFlag) break; strcpy (cs_MeFunc,"CS_cscnv"); CS_cscnv (csprm,ll); if (cs_MeFlag) break; strcpy (cs_MeFunc,"CS_ll2cs"); CS_ll2cs (csprm,xy,ll); if (cs_MeFlag) break; llAry [0][0] = ll [0]; /* keep gcc compiler happy */ llAry [0][1] = ll [1]; llAry [0][2] = ll [2]; strcpy (cs_MeFunc,"CS_llchk"); CS_llchk (csprm,1,llAry); if (cs_MeFlag) break; } if (cs_MeFlag) { if (verbose) { printf ("\tLNG = %g, LAT = %g, HGT = %g \n",ll [0],ll [1],ll [2]); } err_cnt += 1; continue; } sequencer = 0; falseOrg [0] = csprm->csdef.x_off; falseOrg [1] = csprm->csdef.y_off; while (CStestXYZ (xy,falseOrg,&sequencer) == 0) { cs_Coords [XX] = xy [XX]; cs_Coords [YY] = xy [YY]; cs_Coords [ZZ] = xy [ZZ]; strcpy (cs_MeFunc,"CS_cs2ll"); CS_cs2ll (csprm,ll,xy); if (cs_MeFlag) break; strcpy (cs_MeFunc,"CS_llchk"); xyAry [0][0] = xy [0]; /* keep gcc compiler happy */ xyAry [0][1] = xy [1]; xyAry [0][2] = xy [2]; CS_xychk (csprm,1,xyAry); if (cs_MeFlag) break; } if (cs_MeFlag) { if (verbose) { printf ("\tXX = %g, YY = %g, ZZ = %g \n",xy [XX],xy [YY],xy [ZZ]); } err_cnt += 1; continue; } if (verbose) { printf (" \r"); } CS_free (csprm); csprm = NULL; } CS_csgrpf (grp_list); } printf (" \r"); return (err_cnt); }
int CStestE (bool verbose,long32_t duration) { bool special; int index; int status; int err_cnt; int isPseudo; long32_t il; struct cs_Grptbl_ *tp; struct cs_Csgrplst_ *gp; struct cs_Csgrplst_ *grp_list; struct cs_Csprm_ *csprm; double ll [3]; double xy [3]; double ll1 [3]; double lat_del; double low_lng; double low_lat; double hi_lng; double hi_lat; double ll_tol; double del_lng; double del_lat; duration *= 100L; printf ("Checking reversibility of all projections, smaller region/tolerance.\n"); /* Loop through the group table and fetch a linked list for each group. Count the number in the group and add to the total in the group. */ err_cnt = 0; csprm = NULL; for (tp = cs_CsGrptbl; tp->group [0] != 0; tp += 1) { if (csprm != NULL) { CS_free (csprm); csprm = NULL; } if (!CS_stricmp (tp->group,"LEGACY")) { continue; } CS_csgrp (tp->group,&grp_list); for (gp = grp_list; gp != NULL; gp = gp->next) { if (csprm != NULL) { CS_free (csprm); csprm = NULL; } if (verbose) { printf ("Testing %s for reversibility.\n", gp->key_nm); } else { printf ("%s \r",gp->key_nm); } csprm = CS_csloc (gp->key_nm); if (csprm == NULL) { printf ("Couldn't setup coordinate system named %s.\n",gp->key_nm); err_cnt += 1; continue; } strcpy (cs_MeKynm,csprm->csdef.key_nm); /* Is this one on the "special" list? */ special = false; for (index = 0; KcsTestEspecialList [index][0] != '\0'; index += 1) { if (!CS_stricmp (csprm->csdef.key_nm,KcsTestEspecialList [index])) { special = true; break; } } isPseudo = FALSE; if (csprm->prj_code == cs_PRJCOD_MRCATPV) { isPseudo = TRUE; } /* Get the useful range of the coordinate system and reduce it by about one half. */ if (special) { /* here to reduce by two thirds. */ low_lng = csprm->cent_mer + csprm->min_ll [LNG] + fabs (csprm->min_ll [LNG] * 0.6666); hi_lng = csprm->cent_mer + csprm->max_ll [LNG] - fabs (csprm->min_ll [LNG] * 0.6666); lat_del = csprm->max_ll [LAT] - csprm->min_ll [LAT]; low_lat = csprm->min_ll [LAT] + lat_del * 0.333333; hi_lat = csprm->max_ll [LAT] - lat_del * 0.333333; } else { /* Code that has been used for testE for many years before the "special fix", unedited. */ low_lng = csprm->cent_mer + csprm->min_ll [LNG] + fabs (csprm->min_ll [LNG] * 0.5); hi_lng = csprm->cent_mer + csprm->max_ll [LNG] - fabs (csprm->min_ll [LNG] * 0.5); lat_del = csprm->max_ll [LAT] - csprm->min_ll [LAT]; low_lat = csprm->min_ll [LAT] + lat_del * 0.5; hi_lat = csprm->max_ll [LAT] - lat_del * 0.5; } /* insure that there is a range of some sort. */ if ((hi_lng - low_lng) < cs_One) { low_lng = csprm->cent_mer - cs_Half; hi_lng = csprm->cent_mer + cs_Half; } if ((hi_lat - low_lat) < cs_One) { low_lat = ((csprm->max_ll [LAT] + csprm->min_ll [LAT]) * cs_Half) - cs_Half; hi_lat = low_lat + cs_One; } for (il = 0; il < duration; il += 1) { ll [LNG] = CStestRN (low_lng,hi_lng); ll [LNG] = CS_adj180 (ll [LNG]); ll [LAT] = CStestRN (low_lat,hi_lat); /* The pseudo Mercator cannot convert any point with latitude higher than 84. */ if (isPseudo && fabs (ll [LAT]) > 83.0) { continue; } /* For the two projections which account for 95% of the mapping in the world, we use a very small tolerance which approximates 5 millimeters on the earth. For the less important projections, we use a tolerance which approximates 50 millimeters. That is, for several projections, specifically the whole world type, the mathemagics simply doesn't produce the same level of accuracy as the two biggies do. As the Van der Grinten approaches the central meridian, however, we need to relax the tolerance to account for the mathematical discontinuity encountered there. */ if (csprm->prj_code == cs_PRJCOD_TRMER || csprm->prj_code == cs_PRJCOD_LM2SP) { ll_tol = 4.5E-08; } else if (csprm->prj_code == cs_PRJCOD_CSINI) { /* Cassini doesn't reverse very well. This is well known in the coordinate conversion community. Someone needs to figure out the math involved and improve the projection formulas. */ ll_tol = 2.5E-06; } else { ll_tol = 4.5E-07; } if (csprm->prj_code == cs_PRJCOD_VDGRN) { if (fabs (ll [0] - csprm->cent_mer) < 0.1) ll_tol = 1.0E-05; } /* Due to the polynomials, the Danish stuff does not invert well when you're not within the real domain of the polynomial; i.e. actually in the region being converted. Thus, randomly generated numbers like this do not invert well. The polynomial code uses the inverse to determine if a coordinate pair is within the useful range of the polynomial. The tolerance check is set to 4 centimeters. Adjusting for the latitude of Denmark, we use the following tolerance. */ if (csprm->prj_code == cs_PRJCOD_SYS34 || csprm->prj_code == cs_PRJCOD_SYS34_99 || csprm->prj_code == cs_PRJCOD_SYS34_01) { ll_tol = 7.0E-06; } /* Convert to X and Y, then back again. */ strcpy (cs_MeFunc,"CS_ll2cs"); status = CS_ll2cs (csprm,xy,ll); if (status != cs_CNVRT_NRML) continue; strcpy (cs_MeFunc,"CS_cs2ll"); status = CS_cs2ll (csprm,ll1,xy); if (status != cs_CNVRT_NRML) continue; /* Conversions were OK, see if we ended up with what we started with. */ del_lng = CS_adj180 (ll [0] - ll1 [0]); del_lat = ll [1] - ll1 [1]; if (fabs (del_lng) > ll_tol || fabs (del_lat) > ll_tol) { printf ("%s:: Couldn't reverse %f:%f.\n",csprm->csdef.key_nm,ll[0],ll[1]); printf ("\t\tdel_lng = %g,del_lat = %g.\n",del_lng,del_lat); err_cnt += 1; /* Uncomment the following for easier debugging. */ status = CS_ll2cs (csprm,xy,ll); status = CS_cs2ll (csprm,ll1,xy); } } CS_free (csprm); csprm = NULL; } CS_csgrpf (grp_list); } return (err_cnt); }
int EXP_LVL1 CS_cnvrt (Const char *src_cs,Const char *dst_cs,double coord [3]) { extern int cs_Error; extern csFILE* csDiagnostic; static char modl_name [] = "CS_cnvrt"; struct cs_Csprm_ *src_ptr; struct cs_Csprm_ *dst_ptr; struct cs_Dtcprm_ *dtc_ptr; int st; int status; int dt_st; double my_ll [3]; status = 0; /* Get a pointer to the two coordinate systems involved. */ if (csDiagnostic != 0) fprintf (csDiagnostic,"%s[%d] %s->%s\n",modl_name,__LINE__,src_cs,dst_cs); src_ptr = CSbcclu (src_cs); if (src_ptr == NULL) goto error; dst_ptr = CSbcclu (dst_cs); if (dst_ptr == NULL) goto error; if (csDiagnostic != 0) fprintf (csDiagnostic,"%s[%d] %p & %p\n",modl_name,__LINE__,src_ptr,dst_ptr); /* Get a pointer to the datum conversion required. */ dtc_ptr = CSbdclu (src_ptr,dst_ptr,cs_DTCFLG_DAT_F,cs_DTCFLG_BLK_W); if (dtc_ptr == NULL) goto error; if (csDiagnostic != 0) fprintf (csDiagnostic,"%s[%d] %p\n",modl_name,__LINE__,dtc_ptr); /* Convert the coordinate and return the result to the user. */ st = CS_cs2ll (src_ptr,my_ll,coord); if (csDiagnostic != 0) fprintf (csDiagnostic,"%s[%d] %d\n",modl_name,__LINE__,st); if (st != cs_CNVRT_NRML) { status |= cs_BASIC_SRCRNG; } dt_st = CS_dtcvt (dtc_ptr,my_ll,my_ll); if (csDiagnostic != 0) fprintf (csDiagnostic,"%s[%d] %d\n",modl_name,__LINE__,dt_st); if (dt_st != 0) { if (dt_st < 0) goto error; status |= cs_BASIC_DTCWRN; } st = CS_ll2cs (dst_ptr,coord,my_ll); if (csDiagnostic != 0) fprintf (csDiagnostic,"%s[%d] %d\n",modl_name,__LINE__,st); if (st != cs_CNVRT_NRML) { status |= cs_BASIC_DSTRNG; } /* That's it. */ if (csDiagnostic != 0) fprintf (csDiagnostic,"%s[%d] %d\n",modl_name,__LINE__,status); return (status); error: return (-cs_Error); }
CWnd* CcsTest::Calculate () { int status; CWnd* errorPtr; struct cs_Csprm_ *srcPtr; struct cs_Csprm_ *trgPtr; struct cs_Dtcprm_ *dtcPtr; double xy [3], ll [3]; char ctemp [512]; errorPtr = FetchSource (); if (errorPtr != NULL) goto error; xy [0] = m_SourceXY [0]; xy [1] = m_SourceXY [1]; if (m_ThreeDCalc) xy [2] = m_SourceXY [2]; else xy [2] = 0.0; // Set up the conversion. srcPtr = CSbcclu (m_SrcKeyName); if (srcPtr == NULL) { errorPtr = GetDlgItem (IDC_CSTST_SRCKEYNM); goto error; } trgPtr = CSbcclu (m_TrgKeyName); if (trgPtr == NULL) { errorPtr = GetDlgItem (IDC_CSTST_TRGKEYNM); goto error; } dtcPtr = CSbdclu (srcPtr,trgPtr,cs_DTCFLG_DAT_W,cs_DTCFLG_BLK_10); if (dtcPtr == NULL) { errorPtr = GetDlgItem (IDC_CSTST_SRCKEYNM); goto error; } // Do the conversion if (m_ThreeDCalc) { status = CS_cs3ll (srcPtr,ll,xy); } else { status = CS_cs2ll (srcPtr,ll,xy); } if (status == cs_CNVRT_OK) { m_SrcStatus = "OK"; } else if (status == cs_CNVRT_USFL) { m_SrcStatus = "Range"; } else if (status == cs_CNVRT_DOMN) { m_SrcStatus = "Domain"; } else if (status = cs_CNVRT_DEMO) { m_SrcStatus = "Demo"; } else { m_SrcStatus = "???"; } // Source Grid Scale and Convergence. m_SourceScale = CS_csscl (srcPtr,ll); m_SourceConvergence = CS_cscnv (srcPtr,ll); UpdateSource (); // Do the datum shift. if (m_ThreeDCalc) { status = CS_dtcvt3D (dtcPtr,ll,ll); } else { status = CS_dtcvt (dtcPtr,ll,ll); } if (status == 0) { m_TrgStatus.Empty (); } else if (status < 0) { m_TrgStatus = "DtErr"; errorPtr = GetDlgItem (IDC_CSTST_SRCKEYNM); goto error; } else { m_TrgStatus = "DtRng"; CS_errmsg (ctemp,sizeof (ctemp)); AfxMessageBox (ctemp); } // Target conversion if (m_ThreeDCalc) { status = CS_ll3cs (trgPtr,xy,ll); } else { status = CS_ll2cs (trgPtr,xy,ll); } if (m_TrgStatus.IsEmpty ()) { if (status == cs_CNVRT_OK) { m_TrgStatus = "OK"; } else if (status == cs_CNVRT_USFL) { m_TrgStatus = "Range"; } else if (status == cs_CNVRT_DOMN) { m_TrgStatus = "Domain"; } else if (status = cs_CNVRT_DEMO) { m_TrgStatus = "Demo"; } else { m_TrgStatus = "???"; } } m_TargetXY [0] = xy [0]; m_TargetXY [1] = xy [1]; if (m_ThreeDCalc) m_TargetXY [2] = xy [2]; else m_TargetXY [2] = 0.0; // Target Grid Scale and Convergence. m_TargetScale = CS_csscl (trgPtr,ll); m_TargetConvergence = CS_cscnv (trgPtr,ll); // Update the display UpdateTarget (); UpdateData (FALSE); return NULL; error: m_TrgStatus = "Error"; m_TargetXY [0] = 0.0; m_TargetXY [1] = 0.0; m_TargetXY [2] = 0.0; UpdateTarget (); UpdateData (FALSE); return errorPtr; }