1
/***************************************************************************/
2
/* RSC IDENTIFIER: Source
9
* This component checks for input file errors and input parameter errors.
10
* If an invalid value is found, the error code is combined with the current
11
* error code using the bitwise or. This combining allows multiple error
12
* codes to be returned. The possible error codes are:
14
* SOURCE_NO_ERROR : No errors occurred in function
15
* SOURCE_INVALID_INDEX_ERROR : Index out of valid range (less than one
16
* or more than Source_Count)
17
* SOURCE_INVALID_NAME_ERROR : Source name not found
22
* Source is intended for reuse by any application that needs access to
28
* Further information on Source can be found in the Reuse Manual.
30
* Source originated from : U.S. Army Topographic Engineering Center (USATEC)
31
* Geospatial Information Division (GID)
33
* Alexandria, VA 22310-3864
37
* None apply to this component.
41
* Source has no restrictions.
45
* Source was tested and certified in the following environments:
47
* 1. Solaris 2.5 with GCC 2.8.1
48
* 2. MS Windows 95 with MS Visual C++ 6
54
* 01/07/2008 Changed SE90 values,
56
* (see extended explanation below)
58
* The modifications discussed below were made by Ned A. Ferris
61
* During Final Acceptance Testing (FAT) of the Coordinate
62
* Conversion Service and Application (CCS and CCA),
63
* 15 to 17 July 2007, Dr. Duane Brown (Navy) filed a
64
* discrepancy reported against the 90% Spherical Error values
65
* for DTED Levels 1 and 2. This DR was GEOTRANS-0013 which cross
66
* references with the BAE discrepancy report BAEts21981.
68
* Discussions with Dr. Brown and Dan Mullaney (NGA) regarding SE90
69
* values culminated at the MSP FAT DR TEM on 20 December 2007.
70
* At this technical exchange meeting, it was decided to replace
71
* the existing SE90 values with those calculated by an equation
72
* developed by Dr. Brown (see below). The formulas given below
73
* were extracted from a PowerPoint Presentation sent to NGMS by
74
* Dr. Brown; the actual derivations of the formulas were not documented.
76
* Given CE90 and LE90 and the following definitions:
78
* sqrt(x): the square root of x.
80
* sigma_xy: the standard deviation of the circular/ground components.
82
* ratio: the ratio of sigma_Z over sigma_xy
84
* Let sigma_xy = sqrt(CE90^2/chi-square_distribution(0.1,2))
85
* = sqrt(CE90^2/4.60517612509304)
87
* Let ratio = (sqrt(LE90^2/chi-square_distribution(0.1,1)))/sigma_xy
88
* = (sqrt(LE90^2/2.70554058545338))/sigma_xy
94
* (0.115864822 * ratio) +
95
* (0.6391671 * ratio^2) -
96
* (0.277130883 * ratio^3) +
97
* (0.148193487 * ratio^4) -
98
* (0.037837525 * ratio^5) +
99
* (0.003262523 * ratio^6)) * sigma_xy
101
* If ratio >= 5, then:
105
* (1.636566894*ratio) +
106
* (3.58376E-10*ratio^2) -
107
* (1.3613E-14*ratio^3) +
108
* (2.4342E-19*ratio^4) -
109
* (2.04984E-24*ratio^5) +
110
* (6.55643E-30*ratio^6)) * sigma_xy
112
* The 90% Spherical Error values in the Accuracy_Sources Source_Table
113
* were recalculated using the above formula (except for CIB and DFAD,
114
* see below). They were all rounded up to the nearest integer value.
115
* The ratio values were all less than 5, so only the first of the above
116
* two formulas was used.
118
* In addition, based on communications with Dan Mullaney on
119
* 27 December 2007, it was determined that:
121
* 1. CIB has no vertical accuracy standard.
123
* 2. DFAD is planimetric and doesn't have a vertical component.
125
* SE90 is therefore not applicable for either CIB or DFAS. The SE90
126
* values for all CIB and DFAD products were set to -1.
131
/***************************************************************************/
139
/***************************************************************************/
143
#define SOURCE_NAME_LENGTH 50
144
#define NUMBER_SOURCES 19
146
/***************************************************************************/
148
* GLOBAL DECLARATIONS
151
typedef struct Accuracy_Source_Value
153
char Name[SOURCE_NAME_LENGTH];
154
double CE; /* circular error */
155
double LE; /* linear error */
156
double SE; /* spherical error */
157
} Accuracy_Sources; /* defines an accuracy source */
161
static const Accuracy_Sources Source_Table[NUMBER_SOURCES] = {{"Unknown", -1, -1, -1},
162
{"User defined (1 meter)", 1, 1, 2},
163
{"GPS PPS", 20, 20, 26},
164
{"GPS SPS", 20, 20, 26},
165
{"1:25,000 City Map", 50, 20, 52},
166
{"1:50,000 Topographic Line Map (TLM)", 50, 20, 52},
167
{"1:50,000 Combat Chart", 50, 20, 52},
168
{"1:100,000 Topographic Line Map (TLM)", 100, 20, 100},
169
{"1:250,000 Joint Operations Graphic (JOG)", 250, 100, 258},
170
{"1:500,000 Tactical Pilotage Chart (TPC)", 1000, 150, 993},
171
{"1:1,000,000 Operational Navigation Chart (ONC)", 2000, 650, 2031},
172
{"Digital Terrain Elevation Data (DTED) Level 1", 50, 30, 55},
173
{"Digital Terrain Elevation Data (DTED) Level 2", 23, 18, 27},
174
{"Digital Feature Analysis Data (DFAD) Level 1", 130, -1, -1},
175
{"Digital Feature Analysis Data (DFAD) Level 2", 130, -1, -1},
176
{"Controlled Image Base (CIB) [>10m GSD]", 25, -1, -1},
177
{"Vector Smart Map (VMAP) Level 1", 250, 100, 258},
178
{"Vector Smart Map (VMAP) Level 2 (1:100,000)", 100, 20, 100},
179
{"Vector Smart Map (VMAP) Level 2 (1:50,000)", 50, 20, 52}};
183
/***************************************************************************/
187
void Source_Count (long *Count)
189
{ /* Begin Source_Count */
191
* The function Source_Count returns the number of source accuracies
193
* Count : number of accuracy sources (output)
196
*Count = NUMBER_SOURCES;
198
} /* End of Source_Count */
201
long Source_Index( const char *Name,
204
{ /* Begin Source_Index */
206
* The function Source_Index returns the index of the source accuracy with the
209
* Name : The source name being searched for. (input)
210
* Index : The index of the accuracy source with the (output)
213
char temp_name[SOURCE_NAME_LENGTH];
214
long error_code = SOURCE_NO_ERROR;
219
length = strlen(Name);
220
if (length > (SOURCE_NAME_LENGTH-1))
221
error_code |= SOURCE_INVALID_NAME_ERROR;
224
strcpy(temp_name,Name);
226
/* Convert to upper case */
227
/* for (i=0;i<length;i++)
228
temp_name[i] = (char)toupper(temp_name[i]);*/
230
/* Strip blank spaces */
231
/* while (pos < length)
233
if (isspace(temp_name[pos]))
235
for (i=pos;i<=length;i++)
236
temp_name[i] = temp_name[i+1];
242
/* Search for code */
244
while (i < NUMBER_SOURCES && strcmp(temp_name, Source_Table[i].Name))
248
if (i == NUMBER_SOURCES || strcmp(temp_name, Source_Table[i].Name))
249
error_code |= SOURCE_INVALID_NAME_ERROR;
254
} /* End Source_Index */
257
long Source_Name (const long Index,
259
{ /* Begin Source_Name */
261
* The function Source_Name returns the name of the source accuracy referenced by
264
* Index : The index of a given datum in the datum table. (input)
265
* Name : The accuracy source Name referenced by Index. (output)
268
long error_code = SOURCE_NO_ERROR;
270
if ((Index > 0) && (Index <= NUMBER_SOURCES))
271
strcpy(Name, Source_Table[Index-1].Name);
273
error_code |= SOURCE_INVALID_INDEX_ERROR;
275
} /* End Source_Name */
278
long Source_Accuracy (const long Index,
282
{ /* Begin Source_Accuracy */
284
* The function Source_Accuracy returns the accuracy values (CE, LE, SE)
285
* for the source referenced by index.
287
* Index : The index of a given datum in the datum table (input)
288
* CE : Circular error (output)
289
* LE : Linear error (output)
290
* SE : Spherical error (output)
293
long error_code = SOURCE_NO_ERROR;
295
if (Index > 0 && Index <= NUMBER_SOURCES)
297
*CE = Source_Table[Index-1].CE;
298
*LE = Source_Table[Index-1].LE;
299
*SE = Source_Table[Index-1].SE;
303
error_code |= SOURCE_INVALID_INDEX_ERROR;
306
} /* End Source_Accuracy */