exprgeodist.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. //
  2. // Copyright (c) 2017-2026, Manticore Software LTD (https://manticoresearch.com)
  3. // Copyright (c) 2001-2016, Andrew Aksyonoff
  4. // Copyright (c) 2008-2016, Sphinx Technologies Inc
  5. // All rights reserved
  6. //
  7. // This program is free software; you can redistribute it and/or modify
  8. // it under the terms of the GNU General Public License. You should have
  9. // received a copy of the GPL license along with this program; if you
  10. // did not, you can find it at http://www.gnu.org/
  11. //
  12. #include "exprgeodist.h"
  13. #include "sphinx.h"
  14. #include "exprtraits.h"
  15. #include <cmath>
  16. class ExprGeodist_c : public ISphExpr
  17. {
  18. public:
  19. ExprGeodist_c() = default;
  20. bool Setup ( const CSphQuery & tQuery, const ISphSchema & tSchema, CSphString & sError );
  21. float Eval ( const CSphMatch & tMatch ) const final;
  22. void FixupLocator ( const ISphSchema * pOldSchema, const ISphSchema * pNewSchema ) final;
  23. void Command ( ESphExprCommand eCmd, void * pArg ) final;
  24. uint64_t GetHash ( const ISphSchema & tSorterSchema, uint64_t uPrevHash, bool & bDisable ) final;
  25. ISphExpr * Clone() const final;
  26. protected:
  27. CSphAttrLocator m_tGeoLatLoc;
  28. CSphAttrLocator m_tGeoLongLoc;
  29. float m_fGeoAnchorLat;
  30. float m_fGeoAnchorLong;
  31. CSphString m_sAttrLat;
  32. CSphString m_sAttrLon;
  33. };
  34. bool ExprGeodist_c::Setup ( const CSphQuery & tQuery, const ISphSchema & tSchema, CSphString & sError )
  35. {
  36. if ( !tQuery.m_bGeoAnchor )
  37. {
  38. sError.SetSprintf ( "INTERNAL ERROR: no geoanchor, can not create geodist evaluator" );
  39. return false;
  40. }
  41. int iLat = tSchema.GetAttrIndex ( tQuery.m_sGeoLatAttr.cstr() );
  42. if ( iLat<0 )
  43. {
  44. sError.SetSprintf ( "unknown latitude attribute '%s'", tQuery.m_sGeoLatAttr.cstr() );
  45. return false;
  46. }
  47. int iLong = tSchema.GetAttrIndex ( tQuery.m_sGeoLongAttr.cstr() );
  48. if ( iLong<0 )
  49. {
  50. sError.SetSprintf ( "unknown latitude attribute '%s'", tQuery.m_sGeoLongAttr.cstr() );
  51. return false;
  52. }
  53. m_tGeoLatLoc = tSchema.GetAttr(iLat).m_tLocator;
  54. m_tGeoLongLoc = tSchema.GetAttr(iLong).m_tLocator;
  55. m_fGeoAnchorLat = tQuery.m_fGeoLatitude;
  56. m_fGeoAnchorLong = tQuery.m_fGeoLongitude;
  57. m_sAttrLat = tSchema.GetAttr(iLat).m_sName;
  58. m_sAttrLon = tSchema.GetAttr(iLong).m_sName;
  59. return true;
  60. }
  61. static inline double sphSqr ( double v )
  62. {
  63. return v*v;
  64. }
  65. float ExprGeodist_c::Eval ( const CSphMatch & tMatch ) const
  66. {
  67. const double R = 6384000;
  68. float plat = tMatch.GetAttrFloat ( m_tGeoLatLoc );
  69. float plon = tMatch.GetAttrFloat ( m_tGeoLongLoc );
  70. double dlat = plat - m_fGeoAnchorLat;
  71. double dlon = plon - m_fGeoAnchorLong;
  72. double a = sphSqr ( sin ( dlat/2 ) ) + cos(plat)*cos(m_fGeoAnchorLat)*sphSqr(sin(dlon/2));
  73. double c = 2*asin ( Min ( 1.0, sqrt(a) ) );
  74. return (float)(R*c);
  75. }
  76. void ExprGeodist_c::FixupLocator ( const ISphSchema * pOldSchema, const ISphSchema * pNewSchema )
  77. {
  78. sphFixupLocator ( m_tGeoLatLoc, pOldSchema, pNewSchema );
  79. sphFixupLocator ( m_tGeoLongLoc, pOldSchema, pNewSchema );
  80. }
  81. void ExprGeodist_c::Command ( ESphExprCommand eCmd, void * pArg )
  82. {
  83. if ( eCmd==SPH_EXPR_GET_DEPENDENT_COLS )
  84. {
  85. static_cast<StrVec_t*>(pArg)->Add(m_sAttrLat);
  86. static_cast<StrVec_t*>(pArg)->Add(m_sAttrLon);
  87. }
  88. }
  89. uint64_t ExprGeodist_c::GetHash ( const ISphSchema & tSorterSchema, uint64_t uPrevHash, bool & bDisable )
  90. {
  91. uint64_t uHash = sphCalcExprDepHash ( this, tSorterSchema, uPrevHash, bDisable );
  92. static const char * EXPR_TAG = "ExprGeodist_c";
  93. uHash = sphFNV64 ( EXPR_TAG, (int) strlen(EXPR_TAG), uHash );
  94. uHash = sphFNV64 ( &m_fGeoAnchorLat, sizeof(m_fGeoAnchorLat), uHash );
  95. uHash = sphFNV64 ( &m_fGeoAnchorLong, sizeof(m_fGeoAnchorLong), uHash );
  96. return uHash;
  97. }
  98. ISphExpr * ExprGeodist_c::Clone() const
  99. {
  100. auto * pClone = new ExprGeodist_c;
  101. pClone->m_tGeoLatLoc = m_tGeoLatLoc;
  102. pClone->m_tGeoLongLoc = m_tGeoLongLoc;
  103. pClone->m_fGeoAnchorLat = m_fGeoAnchorLat;
  104. pClone->m_fGeoAnchorLong = m_fGeoAnchorLong;
  105. pClone->m_sAttrLat = m_sAttrLat;
  106. pClone->m_sAttrLon = m_sAttrLon;
  107. return pClone;
  108. }
  109. ///////////////////////////////////////////////////////////////////////////////
  110. ISphExpr * CreateExprGeodist ( const CSphQuery & tQuery, const ISphSchema & tSchema, CSphString & sError )
  111. {
  112. auto * pExpr = new ExprGeodist_c;
  113. if ( !pExpr->Setup ( tQuery, tSchema, sError ) )
  114. {
  115. pExpr->Release();
  116. return nullptr;
  117. }
  118. return pExpr;
  119. }