source: trunk/src/seismic_processing/glass/src/modules/Glock/Glock.cpp @ 2176

Revision 2176, 19.1 KB checked in by paulf, 13 years ago (diff)

added from hydra_proj, new version

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 *   THIS FILE IS UNDER RCS - DO NOT MODIFY UNLESS YOU HAVE
3 *   CHECKED IT OUT USING THE COMMAND CHECKOUT.
4 *
5 *    $Id$
6 *
7 *    Revision history:
8 *     $Log$
9 *     Revision 1.2  2006/05/22 16:01:25  paulf
10 *     added from hydra_proj, new version
11 *
12 *     Revision 1.3  2005/10/17 06:34:31  davidk
13 *     Modified the way phase weighting is handled in the locator.  The person who
14 *     originally put it in, did not understand how the least square solver worked and
15 *     wrongly applied the weighting values.
16 *     Now weighting is done in integral increments ranging from 0 to 4.
17 *     Currently any phase with weight below (GLOCK_WEIGHT_GRANULARITY/2)
18 *     is not passed to the solver.
19 *
20 *     Revision 1.2  2005/10/13 22:21:58  davidk
21 *     Fixed a bug where the locator was performing multiple relocations with the same
22 *     starting location, instead of refining the location by using the results of the
23 *     previous location as the starting point for the next.
24 *     Made an aesthetic change to the calculation of the depth coefficient.
25 *
26 *     Revision 1.1.1.1  2005/06/22 19:30:48  michelle
27 *     new directory tree built from files in HYDRA_NEWDIR_2005-06-20 tagged hydra and earthworm projects
28 *
29 *     Revision 1.8  2005/02/28 23:42:11  davidk
30 *     Downgraded a debug message.
31 *
32 *     Revision 1.7  2005/02/15 20:02:46  davidk
33 *     Modified the gap calculation (for the origin) in the locator, so that it is limited
34 *     to P-class (within 110 degrees distance) and PKPdf phases.
35 *     This way some flukily associated S or ancillary phase doesn't affect the
36 *     quality of the gap metric.
37 *
38 *     Revision 1.6  2004/12/02 17:51:20  davidk
39 *     Incorporated phase-based LocWeight values, that cause different phases
40 *     to contribute different amounts to affecting the location. Utilized LocWeight
41 *     in weight values submittted to the Solver, and in determining RMS, so
42 *     that picks that aren't weighted in the solution to not adversly skew
43 *     the RMS value even if they have a high residual value. (This is particularly
44 *     important with phases like P'P', that have huge residual values, but should
45 *     be associated with the origin, yet not contribute to it's location.
46 *
47 *     Revision 1.5  2004/11/30 02:48:52  davidk
48 *     Found bug where input params for the dtdz vertical slowness parameter
49 *     were being input in degrees (same unit as dtdx).  Converted the output
50 *     from degrees to km, before using it to adjust the origin depth.
51 *
52 *     Inverted the dtdz coefficient so that it was negative instead, the same way
53 *     the other coefficients were.
54 *
55 *     Revision 1.4  2004/11/01 06:33:21  davidk
56 *     Modified to work with new hydra traveltime library.
57 *     Cleaned up struct ITravelTime references.
58 *
59 *     Revision 1.3  2004/09/16 01:09:38  davidk
60 *     Added a configable variable for the number of Iterations that the Locator-Solver runs
61 *     each time an origin is modified.  Initialized it to the previously hardcoded value of 3-net-1.
62 *
63 *     Cleaned up logging messages.
64 *     Downgraded some debugging messages.
65 *
66 *     Revision 1.2  2004/04/01 22:09:18  davidk
67 *     v1.11 update
68 *     Now utilizes OPCalc routines for calculating Origin/Pick association params.
69 *
70 *     Revision 1.3  2003/11/07 22:42:29  davidk
71 *     Added RCS Header.
72 *     Added function Locate_InitOrigin() that initializes a blank
73 *     origin Structure for use with the locator.
74 *     Added CompareOrigins() function for comparing the "quality"
75 *     of two origin estimates for the same quake.
76 *     Used function in code that formerly compared origins based on
77 *     RMS values.
78 *
79 *     Revision 1.3  2003/11/07 22:38:59  davidk
80 *     Added RCS Header.
81 *     Added two member functions: Locate_InitOrigin() and CompareOrigins().
82 *
83 *
84 **********************************************************/
85
86// glock.cpp
87
88#include <windows.h>
89#include <stdio.h>
90#include <math.h>
91#include <Debug.h>
92#include <ISolve.h>
93#include <opcalc.h>
94#include "glock.h"
95#include "GlockMod.h"
96//#include "date.h"
97//#include "str.h"
98extern "C" {
99#include "utility.h"
100}
101
102#define RAD2DEG  57.29577951308
103#define DEG2RAD 0.01745329251994
104#define MAX_BELIEVABLE_DISTANCE_FOR_P_PHASE 110.0
105
106extern "C" {
107void __cdecl qsortd (double *base, unsigned num);
108}
109
110extern CMod *pMod;
111
112#define ITER_SUCCESS    0
113#define ITER_NODATA             1
114#define ITER_DEPTH              2
115
116// Carl 120303
117static double pPickDistArray[OPCALC_MAX_PICKS];
118static double pPickAzmArray[OPCALC_MAX_PICKS];
119
120/*
121static int PickAzmComp(const void *az1, const void *az2) {
122        double azm1;
123        double azm2;
124        memmove(&azm1, az1, sizeof(double));
125        memmove(&azm2, az2, sizeof(double));
126        if(azm1 < azm2)
127                return -1;
128        if(azm1 > azm2)
129                return 1;
130        return 0;
131}
132
133// End Carl 120303
134
135static int PickDistComp(const void *elem1, const void *elem2) {
136        PICK *pck1;
137        PICK *pck2;
138        memmove(&pck1, elem1, sizeof(PICK *));
139        memmove(&pck2, elem2, sizeof(PICK *));
140        CDebug::Log(DEBUG_MINOR_INFO,"Comp() %.2f %.2f\n", pck1->dDelta, pck2->dDelta);
141        if(pck1->dDelta < pck2->dDelta)
142                return -1;
143        if(pck1->dDelta > pck2->dDelta)
144                return 1;
145        return 0;
146}
147***************************************************/
148
149//---------------------------------------------------------------------------------------CWave
150CGlock::CGlock() {
151//      DebugOn();
152        for(int i=0; i<4; i++)
153                bFree[i] = true;
154  CDebug::SetModuleName("CGlock");
155}
156
157//---------------------------------------------------------------------------------------~CWave
158CGlock::~CGlock() {
159}
160
161//---------------------------------------------------------------------------------------Locate
162// Locate earthquake with constraints. E.G. set tnez to "TZ" to allow free
163// origin time and depth, tnez set to "TNE" is a fixed depth solution.
164// T = Time, N = North, E = East, Z = Depth
165int CGlock::Locate(char *ent, char *mask) {
166        int i;
167        int res;
168
169  // Carl 120303  - reversed each one of the true/false definitions
170        for(i=0; i<4; i++)
171                bFree[i] = false;
172        for(i=0; i<(int)strlen(mask); i++) {
173                switch(mask[i]) {
174                case 't':
175                case 'T':
176                        bFree[0] = true;
177                        break;
178                case 'n':
179                case 'N':
180                        bFree[1] = true;
181                        break;
182                case 'e':
183                case 'E':
184                        bFree[2] = true;
185                        break;
186                case 'z':
187                case 'Z':
188                        bFree[3] = true;
189                        break;
190                default:
191                        return 7001;
192                }
193        }
194        res = Locate(ent);
195        for(i=0; i<4; i++)
196                bFree[i] = true;
197        return res;
198}
199
200//---------------------------------------------------------------------------------------Locate
201// Locate earthquake (retrieve data from glint, update event in glint)
202int CGlock::Locate(char *ent) {
203        PICK *pck;
204        double torg;
205        double dis;
206        double azm;
207  double dDistKM;
208        int res;
209        bool fix;
210        bool btemp;
211  static bool bParamsInitialized = false;
212
213
214
215  if(!bParamsInitialized)
216  {
217    pGlnt = pMod->pGlint;
218    pTT = pMod->pTT;
219    OPCalc_SetTravelTimePointer(pTT);
220    pSlv = pMod->pSolve;
221    bParamsInitialized = true;
222  }
223
224
225        pOrg = pGlnt->getOrigin(ent);
226        if(!pOrg)
227                return 1;
228  if(pOrg->nPh < 4)  // we need atleast 4 phases for hypocenter processing
229    return(1);
230
231        torg = pOrg->dT;
232  nPck = 0;
233  int iPickRef=0;
234        while(pck = pGlnt->getPicksFromOrigin(pOrg, &iPickRef)) 
235  {
236    // DK 011404  record the min and max pick id's used in this
237    //            location for debugging purposes
238    if(nPck == 0)
239    {
240      strcpy(pOrg->idMinPick, pck->idPick);
241      strcpy(pOrg->idMaxPick, pck->idPick);
242    }
243    else
244    {
245      if(strcmp(pOrg->idMinPick,pck->idPick) > 0)
246        strcpy(pOrg->idMinPick, pck->idPick);
247      else if(strcmp(pOrg->idMaxPick,pck->idPick) < 0)
248        strcpy(pOrg->idMaxPick, pck->idPick);
249    }
250
251                geo_to_km_deg(pOrg->dLat, pOrg->dLon, pck->dLat, pck->dLon, &dDistKM, &dis, &azm);
252//              CDebug::Log(DEBUG_MINOR_INFO,"Locate(): PCK:%s t:%.2f lat:%.4f lon:%.4f elev:%.4f dis:%.2f azm:%.2f\n",
253//                      pck->idPick, pck->dT-torg, pck->dLat, pck->dLon, pck->dElev, dis, azm);
254                pPick[nPck++] = pck;
255        }
256
257  // DK Added 081303
258  ORIGIN oBest, oCurrent, oNext;
259  memcpy(&oCurrent,pOrg,sizeof(ORIGIN));
260  Locate_InitOrigin(&oNext, pOrg->idOrigin);
261  Locate_InitOrigin(&oBest, pOrg->idOrigin);
262
263        fix = false;
264  /* Note we must loop through two times before we start looping
265     through locator iterations.  Something about the first time
266     through calcs residuals for the existing origin, and the
267     second time loads the solver's matrix.  So the 3rd Iterate()
268     call is the first one that results in an actual relocation.
269   **************************************************************/
270        for(nIter=0; nIter<(pMod->iNumLocatorIterations+2); nIter++) {
271                if(fix) {
272                        btemp = bFree[3];
273                        bFree[3] = false;
274    }  // end if(fix)
275    res = Iterate(true, &oCurrent, &oNext);
276          CDebug::Log(DEBUG_MINOR_INFO,"Locate(): Trying location: %.4f %.4f %.4f - %.2f (%.f/%.1f-%3d)\n", 
277                oCurrent.dLat, oCurrent.dLon, oCurrent.dZ, 
278                oCurrent.dT, oCurrent.dAff, oCurrent.dRms, oCurrent.nEq);
279                if(fix) {
280                        fix = false;
281                        bFree[3] = btemp;
282    }  // end if(fix)
283    if(CompareOrigins(&oBest, &oCurrent) > 0)
284      memcpy(&oBest,&oCurrent, sizeof(ORIGIN));
285
286                switch(res) {
287                case ITER_SUCCESS:
288                        break;
289                case ITER_NODATA:
290                        pOrg->nEq = 0;
291                        pOrg->dRms = 0;
292                        return 0;
293                        break;
294                case ITER_DEPTH:
295                        fix = true;
296                        break;
297                }
298    // make the next origin the current one and reprocess
299    memcpy(&oCurrent,&oNext, sizeof(ORIGIN));
300  }  // end for 3 iterations
301  /* process the last origin */
302  res = Iterate(false, &oCurrent, &oNext);
303          CDebug::Log(DEBUG_MINOR_INFO,"Locate(): Trying location: %.4f %.4f %.4f - %.2f (%.1f-%3d)\n", 
304                oCurrent.dLat, oCurrent.dLon, oCurrent.dZ, 
305                oCurrent.dT, oCurrent.dRms, oCurrent.nEq);
306    if(CompareOrigins(&oBest, &oCurrent) > 0)
307      memcpy(&oBest,&oCurrent, sizeof(ORIGIN));
308
309  /* reset the originpick information to the best. */
310  res = Iterate(false, &oBest, &oNext);
311
312  if(oBest.nPh > 4)
313    memcpy(pOrg,&oBest, sizeof(ORIGIN));
314  else
315  {
316          CDebug::Log(DEBUG_MAJOR_INFO,"Locate(): Unable to generate location using "
317                                 "atleast 4 phases for Origin %s nPh:%d nEq:%d\n",
318                oBest.idOrigin, oBest.nPh, oBest.nEq);
319    return(1);
320  }
321
322        CDebug::Log(DEBUG_MAJOR_INFO,"Locate(): Chose location : %.4f %.4f %.4f - %.2f (%.1f-%3d)\n", 
323              oBest.dLat, oBest.dLon, oBest.dZ, 
324              oBest.dT, oBest.dRms, oBest.nEq);
325        return 0;
326} // end Locate()
327
328//---------------------------------------------------------------------------------------Iterate
329int CGlock::Iterate(bool solve, ORIGIN * poCurrent, ORIGIN * poNext) 
330{
331        /*
332  PICK *pck;
333        TTT *ttt;
334        double tres;
335        double coef[4];
336        int j;
337        double tobs;
338        double tcal;
339        double d;
340        double azm;
341        double toa;
342        double z;
343        double sum;
344        double torg;
345        double lat;
346        double lon;
347        double dep;
348  */
349
350  int iRetCode;
351
352        int i,j;
353        double *stp;
354        int nvar;
355        int ivar;
356       
357        nvar = 0;
358        for(i=0; i<4; i++)
359                if(bFree[i]) nvar++;
360        if(nvar < 1)
361                solve = false;
362        if(solve)
363                pSlv->Init(nvar);
364
365  iRetCode = ProcessLocation(solve, poCurrent, pPick, nPck);
366
367        nIter++;
368        if(poCurrent->nEq < 4)
369                return ITER_SUCCESS;
370        if(!solve)
371                return ITER_SUCCESS;
372
373        // Iterate solution
374        stp = pSlv->Solve();
375        j = 0;
376
377  memcpy(poNext,poCurrent,sizeof(ORIGIN));
378  poNext->nEq=0;
379  poNext->dRms=10000.0;
380
381        for(ivar=0; ivar<4; ivar++) {
382                if(bFree[ivar]) {
383                        switch(ivar) {
384                        case 0:
385                                poNext->dT      += stp[j++];
386                                break;
387                        case 1:
388                                poNext->dLat    += stp[j++];
389                                break;
390                        case 2:
391                                poNext->dLon    += stp[j++];
392                                break;
393                        case 3:
394                                poNext->dZ      += stp[j++] * DEG2KM;
395                                break;
396                        }
397                }
398        }
399        if(poNext->dZ < 0.0)
400                return ITER_DEPTH;
401        if(poNext->dZ > 800.0)
402                return ITER_DEPTH;
403
404  // DK 061903
405  while(poNext->dLon > 180.0)
406  {
407    CDebug::Log(DEBUG_MAJOR_INFO,"Locate(): adjusting origin(%.2f,%6.2f,%7.2f,%3.0f) original(%.2f,%6.2f,%7.2f,%3.0f)\n",
408                poNext->dT,poNext->dLat,poNext->dLon,poNext->dZ, poCurrent->dT,poCurrent->dLat,poCurrent->dLon,poCurrent->dZ);
409    poNext->dLon-=360.0;
410  }
411  while(poNext->dLon < -180.0)
412  {
413    CDebug::Log(DEBUG_MAJOR_INFO,"Locate(): adjusting origin(%.2f,%6.2f,%7.2f,%3.0f) original(%.2f,%6.2f,%7.2f,%3.0f)\n",
414                poNext->dT,poNext->dLat,poNext->dLon,poNext->dZ, poCurrent->dT,poCurrent->dLat,poCurrent->dLon,poCurrent->dZ);
415    poNext->dLon+=360.0;
416  }
417  while(poNext->dLat > 90.0)
418  {
419    CDebug::Log(DEBUG_MAJOR_INFO,"Locate(): adjusting origin(%.2f,%6.2f,%7.2f,%3.0f) original(%.2f,%6.2f,%7.2f,%3.0f)\n",
420                poNext->dT,poNext->dLat,poNext->dLon,poNext->dZ, poCurrent->dT,poCurrent->dLat,poCurrent->dLon,poCurrent->dZ);
421    poNext->dLat=180.0 - poNext->dLat;
422  }
423  while(poNext->dLat < -90.0)
424  {
425    CDebug::Log(DEBUG_MAJOR_INFO,"Locate(): adjusting origin(%.2f,%6.2f,%7.2f,%3.0f) original(%.2f,%6.2f,%7.2f,%3.0f)\n",
426                poNext->dT,poNext->dLat,poNext->dLon,poNext->dZ, poCurrent->dT,poCurrent->dLat,poCurrent->dLon,poCurrent->dZ);
427    poNext->dLat=-180.0 - poNext->dLat;
428  }
429
430        // Update solution
431
432  CDebug::Log(DEBUG_MINOR_INFO,"Locate(%s,%d): Solve moved origin(%.2f,%6.2f,%7.2f,%3.0f) original(%.2f,%6.2f,%7.2f,%3.0f)\n",
433              poCurrent->idOrigin,poCurrent->iOrigin, poNext->dT,poNext->dLat,poNext->dLon,poNext->dZ, poCurrent->dT,poCurrent->dLat,poCurrent->dLon,poCurrent->dZ);
434        return ITER_SUCCESS;
435
436}  // end Iterate()
437
438//---------------------------------------------------------------------------------------Affinity
439// Calculates affinity factors for each associated phase. For now it is just the ratio
440// of a stations distance to N times the modal distance, where N is to be determined.
441
442#define GLOCK_WEIGHT_GRANULARITY  0.25
443
444int CGlock::AddPickCoefficientsForSolve(PICK * pPick, const ORIGIN * pOrg)
445{
446  int j = 0;
447  double coef[4];
448  int i;
449
450  if(bFree[0]) 
451    coef[j++] = 1.0;
452  if(bFree[1]) 
453    coef[j++] = -cos(DEG2RAD*pPick->dAzm)*pPick->ttt.dtdx;
454  if(bFree[2]) 
455    coef[j++] = -sin(DEG2RAD*pPick->dAzm)*cos(DEG2RAD*pOrg->dLat) * pPick->ttt.dtdx;
456  if(bFree[3]) 
457    coef[j++] = -pPick->ttt.dtdz; 
458
459  i = (pPick->ttt.dLocWeight + (GLOCK_WEIGHT_GRANULARITY/2)) / GLOCK_WEIGHT_GRANULARITY;
460  if(pSlv)
461  {
462    for(j=0; j < i; j++)
463      pSlv->Equation(coef, pPick->tRes);
464    return(0);
465  }
466  else
467  {
468    return(-1);
469  }
470}  // end AddPickCoefficientsForSolve()
471
472// Function called by Iterate to calculate Origin and Origin/Link
473// params, and to suggest better locations.
474int CGlock::ProcessLocation(bool solve, ORIGIN * pOrg, PICK ** pPick, int nPck) 
475{
476
477  // Initialize origin vars
478        int nEq = 0;
479  int i;
480
481        double sum = 0.0;
482  double dWeight = 0.0;
483  PICK * pck;
484  int iRetCode;
485  double dGap;
486
487  PhaseType  ptPhase;
488  PhaseClass pcPhase;
489
490  // Set default RMS to absurd level.  Shouldn't this be an affinity setting.
491  pOrg->dRms = 10000.0;
492
493
494//  CDebug::Log(DEBUG_MAJOR_INFO,"Locate(I): Org(%6.3f,%8.3f,%5.1f - %.2f)\n",
495//              pOrg->dLat, pOrg->dLon, pOrg->dZ, pOrg->dT);
496
497        for(i=0; i<nPck; i++) 
498  {
499                pck = pPick[i];
500    iRetCode = OPCalc_CalculateOriginPickParams(pck,pOrg);
501    if(iRetCode == -1)
502    {
503      CDebug::Log(DEBUG_MINOR_ERROR,"ProcessLocation(): OPCalc_CalculateOriginPickParams  failed with "
504                                    "terminal error.  See logfile.  Returning!\n");
505      return(-1);
506    }
507    else if(iRetCode == 1)
508    {
509      // could not find TravelTimeTable entry for pOrg,pck
510      CDebug::Log(DEBUG_MINOR_INFO,"ProcessLocation(): OPCalc_CalculateOriginPickParams() could not "
511                                    "find TTT entry for Org,Pick!\n");
512      continue;
513    }
514
515    // calculate solve coefficients if desired
516    if(solve)
517      AddPickCoefficientsForSolve(pck, pOrg);
518   
519    // accumulate statistics
520    sum += pck->tRes*pck->tRes*pck->ttt.dLocWeight;
521
522    dWeight += pck->ttt.dLocWeight;
523
524    // copy the delta/azimuth of the pick to proper arrays for
525    // further calculations
526    pPickDistArray[nEq] = pck->dDelta;
527
528    // DK 021105  Change gap calculation to only use P-Class phases
529    // that way if we pull in random S, PPP, and SKiKP phases,
530    // they won't affect the gap "quality" of the solution.
531    ptPhase = GetPhaseType(pck->ttt.szPhase);
532    pcPhase = GetPhaseClass(ptPhase);
533    if(( (pcPhase == PHASECLASS_P) && (pck->dDelta < MAX_BELIEVABLE_DISTANCE_FOR_P_PHASE )) || 
534       (ptPhase == PHASE_PKPdf)
535      )
536      pPickAzmArray[nEq] = pck->dAzm;
537    else
538      pPickAzmArray[nEq] = -1.0;
539
540
541    // increment the number of picks used to locate the origin
542    nEq++;
543   
544    // keep the arrays from being overrun
545    if(nEq > OPCALC_MAX_PICKS)
546      break;
547  }  // end for each pick in the Pick Array
548
549  // if we didn't use atleast one pick.  Give up and go home.
550  if(nEq < 1)
551          return(1);
552
553
554  // Record the number of equations used to calc the location
555  pOrg->nEq = nEq;
556
557  // Record the residual standard deviation
558  pOrg->dRms = sqrt(sum/dWeight);
559
560  /* Calculate Pick Azimuth statistics for the Origin (Gap)
561   ****************************************************/
562  // Sort the pick-azimuth array
563  qsortd(pPickAzmArray, nEq);
564
565  // If the Pick wasn't a P-class Pick, then we gave it a negative azm,
566  // so igonre all of the negative azm picks (which are all at the beginning
567  // since the array has been sorted
568        for(i=0; i<nEq-2; i++) 
569  {
570    if(pPickAzmArray[i] >= 0.0)
571      break;
572  }
573
574  CDebug::Log(DEBUG_MINOR_INFO,
575              "ProcessLocation(): Calculating Gap for Org %d(%5.1f, %6.1f, %3.0f) based on %d valid picks: ",
576              pOrg->iOrigin, pOrg->dLat, pOrg->dLon, pOrg->dZ, nEq - i);
577  // Calculate the gap for the last-to-first wrap
578        dGap = pPickAzmArray[i] + 360.0 - pPickAzmArray[nEq-1];
579        for(; i<nEq-1; i++) 
580  {
581    // for each gap between two picks, record only if largest so far
582    if(pPickAzmArray[i+1] - pPickAzmArray[i] > dGap)
583      dGap = pPickAzmArray[i+1] - pPickAzmArray[i];
584        }
585        pOrg->dGap = dGap;
586
587  /* Calculate Pick Distance statistics for the Origin
588   ****************************************************/
589  // Sort the pick-distance array
590  qsortd(pPickDistArray, nEq);
591
592  // Calculate the minimum station distance for the origin
593        pOrg->dDelMin = pPickDistArray[0];
594
595  // Calculate the maximum station distance for the origin
596        pOrg->dDelMax = pPickDistArray[nEq-1];
597
598  // Calculate the median station distance for the origin
599        pOrg->dDelMod = 0.5*(pPickDistArray[nEq/2] + pPickDistArray[(nEq-1)/2]);
600
601
602  /* Calculate the Affinity for the Origin (and Picks)
603   ****************************************************/
604  iRetCode = OPCalc_CalcOriginAffinity(pOrg, pPick, nPck);
605  if(iRetCode)
606  {
607    CDebug::Log(DEBUG_MINOR_ERROR,
608                "Error: ProcessLocation(): OPCalc_CalcOriginAffinity() return (%d)\n",
609                iRetCode);
610    return(iRetCode);
611  }
612     
613  CDebug::Log(DEBUG_MINOR_INFO,"END Locate(): dRms:%.2f nEq:%d\n",
614              pOrg->dRms, nEq);
615  return(0);
616}  // End Process Location()
617
618
619// Function to initialize the comparison parameters for
620// relative solution quality.
621void  CGlock::Locate_InitOrigin(ORIGIN * pOrigin, const char * idOrigin)
622{
623  // set the comparison criteria to something really high/bad
624  memset(pOrigin,0,sizeof(ORIGIN));
625  pOrigin->dRms = 10000.0;
626  strncpy(pOrigin->idOrigin, idOrigin, sizeof(pOrigin->idOrigin));
627  pOrigin->idOrigin[sizeof(pOrigin->idOrigin)-1] = 0x00;
628}
629
630
631// Standard compare function.  returns -1 if Origin1 is "better"
632// than Origin2, 1 if vice-versa, and 0 if they are of equal
633// quality.
634int CGlock::CompareOrigins(ORIGIN * po1, ORIGIN * po2)
635{
636  if(po1->dAff > po2->dAff)
637    return(-1);
638  if(po1->dAff < po2->dAff)
639    return(1);
640  //else
641  return(0);
642}  // end CompareOrigins()
643
644
Note: See TracBrowser for help on using the repository browser.