zOPER_EXPORT zSHORT OPERATION GetDistanceRectangle( zDECIMAL *pdSouthLatitude, zDECIMAL *pdEastLongitude, zDECIMAL *pdNorthLatitude, zDECIMAL *pdWestLongitude, zDECIMAL dLatitude, zDECIMAL dLongitude, zDECIMAL dDistance, zLONG lFlag ) { zCHAR szDecimal[ 32 ]; ZDecimal d; ZDecimal d2; d = dDistance; double dDist = (double) d; if ( (lFlag & 0x80000000) == 0 ) dDist /= GEO::KM2MI; // convert to kilometers // A degree is approximately 112 kilometers. So we will do a quick // approximation and then do "search until close enough". d = dLatitude; double dLat1 = d; d = dLongitude; double dLon1 = d; double dLat2 = GetLatitudeAtDistanceFromPoint( dLat1, dLon1, dDist ); double dLon2 = GetLongitudeAtDistanceFromPoint( dLat1, dLon1, dDist ); int nTrys = 0; double dPrev = dLat2; double dCalcDist = ApproxDistance( dLat1, dLon1, dLat2, dLon1, 0x80000000 ); double dDelta = dDist - dCalcDist; double dDeltaMin = dDelta; double dMin = dLat2; while ( dDelta > 0.01 || dDelta < -0.01 ) { nTrys++; dPrev = dLat2; dLat2 += dDelta / 112; dCalcDist = ApproxDistance( dLat1, dLon1, dLat2, dLon1, 0x80000000 ); dDelta = dDist - dCalcDist; if ( dDelta < dDeltaMin && dDelta > -dDeltaMin ) { dDeltaMin = dDelta; dMin = dLat2; } if ( nTrys > 50 ) { dLat2 = dMin; d = dDeltaMin; SysConvertDecimalToString( &d, szDecimal, 6 ); TraceLineS( "LatitudeDelta: ", szDecimal ); break; } } d = dLat2; *pdNorthLatitude = d; d2 = dLat1 * 2; *pdSouthLatitude = d2 - d; nTrys = 0; dPrev = dLon2; dCalcDist = ApproxDistance( dLat1, dLon1, dLat1, dLon2, 0x80000000 ); dDelta = dDist - dCalcDist; dDeltaMin = dDelta; dMin = dLon2; while ( dDelta > 0.01 || dDelta < -0.01 ) { nTrys++; dPrev = dLon2; dLon2 += dDelta / 100; dCalcDist = ApproxDistance( dLat1, dLon1, dLat1, dLon2, 0x80000000 ); dDelta = dDist - dCalcDist; if ( dDelta < dDeltaMin && dDelta > -dDeltaMin ) { dDeltaMin = dDelta; dMin = dLon2; } if ( nTrys > 50 ) { dLon2 = dMin; d = dDeltaMin; SysConvertDecimalToString( &d, szDecimal, 6 ); TraceLineS( "LongitudeDelta: ", szDecimal ); break; } } d = dLon2; *pdWestLongitude = d; d2 = dLon1 * 2; *pdEastLongitude = d2 - d; if ( (lFlag & 0x80000000) == 0 ) dDelta *= GEO::KM2MI; // convert to miles return( (zSHORT) (dDelta * 100.0) ); }
zSHORT fnGetCurrencyText( LPDOMAINDATA lpDomainData ) { LPDOMAIN lpDomain; zLPCONTEXT lpContext; zSHORT nRC; zCHAR sz[ 200 ]; zPCHAR lpAttrValue; zCHAR cAttrType; zULONG uAttrLength; zBOOL bWasNull = FALSE; zCHAR szThou[ 10 ]; zCHAR szDecPt[ 10 ]; zLONG lPrecision; zDECIMAL dDecimal; zDECIMAL dNullDecimal; lpDomain = (LPDOMAIN) SysGetPointerFromHandle( lpDomainData->lpViewAttribute->hDomain ); SysAssignDecimalFromNull( &dNullDecimal ); if ( lpDomainData->lpViewAttribute->cType != zTYPE_DECIMAL ) { *sz = lpDomainData->lpViewAttribute->cType; *(sz + 1) = 0; strcat_s( sz, zsizeof( sz ), ", " ); strcat_s( sz, zsizeof( sz ), lpDomainData->lpViewEntity->szName ); MessageSend( lpDomainData->zView, "", "Domain System Error", sz, zMSGQ_DOMAIN_ERROR, 0 ); return( zCALL_ERROR ); } // determine output data type switch ( lpDomainData->cType ) { case zTYPE_STRING: // Get a pointer to the attribute value. nRC = GetValueFromRecord( lpDomainData->zView, lpDomainData->lpViewEntity, lpDomainData->lpViewAttribute, &lpAttrValue, &cAttrType, &uAttrLength ); if ( nRC ) return( zCALL_ERROR ); // if there is no lpRecord, lpAttrValue returns a null... if ( lpAttrValue == 0 ) lpAttrValue = (zPCHAR) &dNullDecimal; // Get the decimal characteristics. if ( lpDomainData->pszContextName && *lpDomainData->pszContextName ) { if ( GetContext( &lpContext, lpDomain, lpDomainData->pszContextName ) ) { // Get the formatting characters. nRC = fnGetDecimalFmtStrings( lpContext, szThou, szDecPt, &lPrecision ); } else { MessageSend( lpDomainData->zView, "", "Domain System Error", "Invalid Context for Currency Text", zMSGQ_DOMAIN_ERROR, 0 ); return( zCALL_ERROR ); } } else { GetDefaultContext( &lpContext, lpDomain ); fnGetDecimalFmtStrings( lpContext, szThou, szDecPt, &lPrecision ); } // Convert the decimal to a basic string. if ( SysCompareDecimalToNull( (zPDECIMAL) lpAttrValue ) == 0 ) { *((zPCHAR) lpDomainData->lpData) = 0; strcpy_s( sz, zsizeof( sz ), "0.0" ); bWasNull = TRUE; } else { SysAssignDecimalFromDecimal( &dDecimal, (zPDECIMAL) lpAttrValue ); SysConvertDecimalToString( &dDecimal, sz, (zSHORT) lPrecision ); } // Convert the decimal string to correct precision and international // formatting characters. if ( szThou[ 0 ] == 0 ) { if ( szDecPt[ 0 ] == 0 ) fnFormatDecimalString( sz, 0, 0, lpDomain->lDecimalFormat ); else fnFormatDecimalString( sz, 0, szDecPt, lPrecision ); } // Convert the string decimal to the character string. fnFormatCurrencyText( lpDomainData->zView, sz, szThou, szDecPt, lPrecision ); // Return the formatted decimal, unless the return area is not // large enough, in that case fill it with '*'. if ( lpDomainData->uMaxStringLength && zstrlen( sz ) > lpDomainData->uMaxStringLength ) { zmemset( (zPCHAR) lpDomainData->lpData, '*', lpDomainData->uMaxStringLength ); *((zPCHAR) lpDomainData->lpData + lpDomainData->uMaxStringLength) = 0; nRC = zCALL_ERROR; } else { strcpy_s( (zPCHAR) lpDomainData->lpData, lpDomainData->uMaxStringLength, sz ); nRC = bWasNull ? -1 : 0; } break; default: *sz = lpDomainData->cType; *(sz + 1) = 0; strcat_s( sz, zsizeof( sz ), ", " ); strcat_s( sz, zsizeof( sz ), lpDomainData->lpViewEntity->szName ); MessageSend( lpDomainData->zView, "", "Domain System Error", sz, zMSGQ_DOMAIN_ERROR, 0 ); return( zCALL_ERROR ); } return( 0 ); }