| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- //
- // Copyright (c) 2017-2026, Manticore Software LTD (https://manticoresearch.com)
- // Copyright (c) 2001-2016, Andrew Aksyonoff
- // Copyright (c) 2008-2016, Sphinx Technologies Inc
- // All rights reserved
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of the GNU General Public License. You should have
- // received a copy of the GPL license along with this program; if you
- // did not, you can find it at http://www.gnu.org/
- //
- #include "exprgeodist.h"
- #include "sphinx.h"
- #include "exprtraits.h"
- #include <cmath>
- class ExprGeodist_c : public ISphExpr
- {
- public:
- ExprGeodist_c() = default;
- bool Setup ( const CSphQuery & tQuery, const ISphSchema & tSchema, CSphString & sError );
- float Eval ( const CSphMatch & tMatch ) const final;
- void FixupLocator ( const ISphSchema * pOldSchema, const ISphSchema * pNewSchema ) final;
- void Command ( ESphExprCommand eCmd, void * pArg ) final;
- uint64_t GetHash ( const ISphSchema & tSorterSchema, uint64_t uPrevHash, bool & bDisable ) final;
- ISphExpr * Clone() const final;
- protected:
- CSphAttrLocator m_tGeoLatLoc;
- CSphAttrLocator m_tGeoLongLoc;
- float m_fGeoAnchorLat;
- float m_fGeoAnchorLong;
- CSphString m_sAttrLat;
- CSphString m_sAttrLon;
- };
- bool ExprGeodist_c::Setup ( const CSphQuery & tQuery, const ISphSchema & tSchema, CSphString & sError )
- {
- if ( !tQuery.m_bGeoAnchor )
- {
- sError.SetSprintf ( "INTERNAL ERROR: no geoanchor, can not create geodist evaluator" );
- return false;
- }
- int iLat = tSchema.GetAttrIndex ( tQuery.m_sGeoLatAttr.cstr() );
- if ( iLat<0 )
- {
- sError.SetSprintf ( "unknown latitude attribute '%s'", tQuery.m_sGeoLatAttr.cstr() );
- return false;
- }
- int iLong = tSchema.GetAttrIndex ( tQuery.m_sGeoLongAttr.cstr() );
- if ( iLong<0 )
- {
- sError.SetSprintf ( "unknown latitude attribute '%s'", tQuery.m_sGeoLongAttr.cstr() );
- return false;
- }
- m_tGeoLatLoc = tSchema.GetAttr(iLat).m_tLocator;
- m_tGeoLongLoc = tSchema.GetAttr(iLong).m_tLocator;
- m_fGeoAnchorLat = tQuery.m_fGeoLatitude;
- m_fGeoAnchorLong = tQuery.m_fGeoLongitude;
- m_sAttrLat = tSchema.GetAttr(iLat).m_sName;
- m_sAttrLon = tSchema.GetAttr(iLong).m_sName;
- return true;
- }
- static inline double sphSqr ( double v )
- {
- return v*v;
- }
- float ExprGeodist_c::Eval ( const CSphMatch & tMatch ) const
- {
- const double R = 6384000;
- float plat = tMatch.GetAttrFloat ( m_tGeoLatLoc );
- float plon = tMatch.GetAttrFloat ( m_tGeoLongLoc );
- double dlat = plat - m_fGeoAnchorLat;
- double dlon = plon - m_fGeoAnchorLong;
- double a = sphSqr ( sin ( dlat/2 ) ) + cos(plat)*cos(m_fGeoAnchorLat)*sphSqr(sin(dlon/2));
- double c = 2*asin ( Min ( 1.0, sqrt(a) ) );
- return (float)(R*c);
- }
- void ExprGeodist_c::FixupLocator ( const ISphSchema * pOldSchema, const ISphSchema * pNewSchema )
- {
- sphFixupLocator ( m_tGeoLatLoc, pOldSchema, pNewSchema );
- sphFixupLocator ( m_tGeoLongLoc, pOldSchema, pNewSchema );
- }
- void ExprGeodist_c::Command ( ESphExprCommand eCmd, void * pArg )
- {
- if ( eCmd==SPH_EXPR_GET_DEPENDENT_COLS )
- {
- static_cast<StrVec_t*>(pArg)->Add(m_sAttrLat);
- static_cast<StrVec_t*>(pArg)->Add(m_sAttrLon);
- }
- }
- uint64_t ExprGeodist_c::GetHash ( const ISphSchema & tSorterSchema, uint64_t uPrevHash, bool & bDisable )
- {
- uint64_t uHash = sphCalcExprDepHash ( this, tSorterSchema, uPrevHash, bDisable );
- static const char * EXPR_TAG = "ExprGeodist_c";
- uHash = sphFNV64 ( EXPR_TAG, (int) strlen(EXPR_TAG), uHash );
- uHash = sphFNV64 ( &m_fGeoAnchorLat, sizeof(m_fGeoAnchorLat), uHash );
- uHash = sphFNV64 ( &m_fGeoAnchorLong, sizeof(m_fGeoAnchorLong), uHash );
- return uHash;
- }
- ISphExpr * ExprGeodist_c::Clone() const
- {
- auto * pClone = new ExprGeodist_c;
- pClone->m_tGeoLatLoc = m_tGeoLatLoc;
- pClone->m_tGeoLongLoc = m_tGeoLongLoc;
- pClone->m_fGeoAnchorLat = m_fGeoAnchorLat;
- pClone->m_fGeoAnchorLong = m_fGeoAnchorLong;
- pClone->m_sAttrLat = m_sAttrLat;
- pClone->m_sAttrLon = m_sAttrLon;
- return pClone;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ISphExpr * CreateExprGeodist ( const CSphQuery & tQuery, const ISphSchema & tSchema, CSphString & sError )
- {
- auto * pExpr = new ExprGeodist_c;
- if ( !pExpr->Setup ( tQuery, tSchema, sError ) )
- {
- pExpr->Release();
- return nullptr;
- }
- return pExpr;
- }
|