?? queryproc.cpp
字號:
// QueryProc.cpp: implementation of the QueryProc class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "QueryPOI.h"
#include "QueryProc.h"
#pragma warning(disable:4786)
#include <set>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
const int MINRETCHARLEN = 256; // 返回的字符串最小長度
const int MINSEARCHDIST = 2000; //為了加快搜索速度,定義的最小搜索半徑,單位為米
const int MAXSEARCHDIST = 15000;//為了加快搜索速度,定義的最大搜索半徑,單位為米
const int MAXSEARCHCOUNT = 15; //返回搜索的最近要素的個數
//排序類
class less_ff
{
public:
bool operator () (const FeatXX &e,const FeatXX &a) const
{
return (e.dist < a.dist);
}
};
//信息集合類,可以按照距離查詢點的距離從近到遠排序
//以滿足查詢距離查詢點最近的若干個點或道路
class FeatXXContainer : public std::set<FeatXX,less_ff>
{
};
//從字段獲取字符串
void getString_Val(_variant_t val,CString& str)
{ if (val.vt ==VT_BSTR) str=(LPCTSTR)(_bstr_t)val.bstrVal; else str=_T(""); }
//找距離點p距離<=d的所有要素
//sNameField是要素的名稱字段名
//返回值按照距離從近到遠放在集合xxSet中
//可以附加SQL條件strsql,以滿足對部分要素的查詢要求
void SearchInDistance(IPointPtr p,double d,IFeatureClassPtr pFC,CString sNamdField,CString sSQL,FeatXXContainer &xxSet)
{
if (p==NULL || pFC==NULL) return;
if (d <0 ) d = -d;
//清除結果集
xxSet.clear();
IEnvelopePtr pScope(CLSID_Envelope);
ISpatialReferencePtr pSpatRef;
IGeometryPtr pGeomGraph;
double xx,yy;
IQueryFilterPtr pQFilter;
IFeatureCursorPtr pFeatCursor;
IFeaturePtr pFeat;
double dist;
IProximityOperatorPtr pProximity;
IFieldsPtr pFields;
long idxName;
_variant_t val;
CString str;
//構造一個正方形框
p->get_X(&xx); p->get_Y(&yy);
pScope->put_XMin(xx-d); pScope->put_XMax(xx+d);
pScope->put_YMin(yy-d); pScope->put_YMax(yy+d);
p->get_SpatialReference(&pSpatRef);
//pSpatRef->putref_SpatialReference(pSpatRef);
pScope->QueryInterface(&pGeomGraph);
pGeomGraph->putref_SpatialReference(pSpatRef);
//查找所有在靶區之內的要素
BSTR bsName;
pFC->get_ShapeFieldName(&bsName);
_bstr_t shpFdNameBSTR(bsName,TRUE);
ISpatialFilterPtr pSpatialFilt(CLSID_SpatialFilter);
pSpatialFilt->putref_Geometry(pGeomGraph);
pSpatialFilt->put_SpatialRel(esriSpatialRelEnvelopeIntersects);//esriSpatialRelRelation
pSpatialFilt->put_GeometryField(shpFdNameBSTR);
if (!sSQL.IsEmpty()) pSpatialFilt->put_WhereClause(sSQL.AllocSysString());
pFC->get_Fields(&pFields); //名稱字段的序號
pFields->FindField(sNamdField.AllocSysString(),&idxName);
long llid;
pFields->FindField(L"ID",&llid);
pQFilter = pSpatialFilt;
pFC->Search(pQFilter,VARIANT_FALSE,&pFeatCursor);
if (pFeatCursor == NULL) return;
p->QueryInterface(&pProximity); //以查詢點為中心
pFeatCursor->NextFeature(&pFeat);
while (pFeat)
{
FeatXX xxItem;
pFeat->get_Shape(&pGeomGraph);
if (!SUCCEEDED(pProximity->ReturnDistance(pGeomGraph,&dist))) {
pFeatCursor->NextFeature(&pFeat);
continue;
}
xxItem.dist = dist;
if (idxName != -1) //獲取要素名稱
{
pFeat->get_Value(idxName,&val);
getString_Val(val,str);
xxItem.name = (LPCTSTR)str;
}
if (llid != -1) //temp
{
pFeat->get_Value(llid,&val);
getString_Val(val,str);
xxItem.name += (LPCTSTR)str;
}
xxSet.insert(xxItem);
pFeatCursor->NextFeature(&pFeat);
}
int num = xxSet.size();
}
//構造返回的字符串信息
CString MakeReturnString(FeatXXContainer xxset)
{
CString s,ret;
FeatXX xx;
int i;
FeatXXContainer::iterator it;
for (i=0,it=xxset.begin(); i<MAXSEARCHCOUNT && it!=xxset.end(); i++,it++)
{
xx = *it;
if (i!=0) ret += "; ";
if (xx.dist > 1000)
s.Format ("距離%s %.1lf公里",xx.name,xx.dist/1000.);
else s.Format ("距離%s %d米",xx.name,(int)xx.dist);
ret += s;
}
return ret;
}
//查詢最近的POI
//輸入為GPS經緯度(WGS84),單位為十進制度,如(116.213,39.8026),不是請作相應的轉換
bool QueryProc::QueryNearestPOI (double l,double b,CString& ret)
{
if (pFCPOI == NULL)
{
if (!OpenPOIFeatureClass()) return false;
}
//將輸入的經緯度投影到WGS_1984_UTM_Zone_50N
IPointPtr p(CLSID_Point);
p->put_X(l); p->put_Y(b);
//將輸入的經緯度(l,b)投影到WGS_1984_UTM_Zone_50N
//創建地理SPR,賦予p
ISpatialReferenceFactoryPtr pSpatRefFact(CLSID_SpatialReferenceEnvironment);
IGeographicCoordinateSystemPtr pGCS;
pSpatRefFact->CreateGeographicCoordinateSystem(esriSRGeoCS_WGS1984,&pGCS);
if (pGCS == NULL) return false;
ISpatialReferencePtr pGeoSpatRef;
pGeoSpatRef = pGCS;
p->putref_SpatialReference(pGeoSpatRef);
ISpatialReferencePtr pPrjSpatRef;
pPrjSpatRef = createGeoSpatialReferenceWGS84_50N();
p->Project(pPrjSpatRef);
double dist = MINSEARCHDIST;
CString sSQL;
sSQL = ""; //可以附加查詢條件,這里沒有
FeatXXContainer xxSet;
SearchInDistance(p,dist,pFCPOI,fieldPOIName,sSQL,xxSet);
//一次性擴大搜索距離到最大
if (xxSet.size() <=0)
{
dist = MAXSEARCHDIST;
SearchInDistance(p,dist,pFCPOI,fieldPOIName,sSQL,xxSet);
}
//構造返回的字符串信息
ret = MakeReturnString (xxSet);
return true;
}
//查詢最近的街道
bool QueryProc::QueryNearestRoad (double l,double b,CString& ret)
{
if (pFCRoad == NULL)
{
if (!OpenRoadFeatureClass()) return false;
}
//將輸入的經緯度投影到WGS_1984_UTM_Zone_50N
IPointPtr p(CLSID_Point);
p->put_X(l); p->put_Y(b);
//將輸入的經緯度(l,b)投影到WGS_1984_UTM_Zone_50N
//創建地理SPR,賦予p
ISpatialReferenceFactoryPtr pSpatRefFact(CLSID_SpatialReferenceEnvironment);
IGeographicCoordinateSystemPtr pGCS;
pSpatRefFact->CreateGeographicCoordinateSystem(esriSRGeoCS_WGS1984,&pGCS);
if (pGCS == NULL) return false;
ISpatialReferencePtr pGeoSpatRef;
pGeoSpatRef = pGCS;
p->putref_SpatialReference(pGeoSpatRef);
ISpatialReferencePtr pPrjSpatRef;
pPrjSpatRef = createGeoSpatialReferenceWGS84_50N();
p->Project(pPrjSpatRef);
double dist = MINSEARCHDIST;
CString sSQL;
sSQL = ""; //可以附加查詢條件,這里沒有
FeatXXContainer xxSet;
SearchInDistance(p,dist,pFCRoad,fieldRoadName,sSQL,xxSet);
//一次性擴大搜索距離到最大
if (xxSet.size() <=0)
{
dist = MAXSEARCHDIST;
SearchInDistance(p,dist,pFCRoad,fieldRoadName,sSQL,xxSet);
}
//構造返回的字符串信息
ret = MakeReturnString (xxSet);
return true;
}
//=============================================================================
//創建缺省的SpatialReference
//即WGS_1984_UTM_Zone_50N
//=============================================================================
ISpatialReferencePtr QueryProc::createGeoSpatialReferenceWGS84_50N()
{
ISpatialReferenceFactoryPtr pSpatRefFact(CLSID_SpatialReferenceEnvironment);
IProjectedCoordinateSystemPtr pProjectedCoordinateSystem;
pSpatRefFact->CreateProjectedCoordinateSystem(esriSRProjCS_WGS1984UTM_50N,&pProjectedCoordinateSystem);
if (pProjectedCoordinateSystem == NULL) return NULL;
ISpatialReferencePtr pSpatRef;
pSpatRef = pProjectedCoordinateSystem;
return pSpatRef;
}
//打開道路及POI要素圖層
bool QueryProc::OpenPOIFeatureClass ()
{
//打開輸出輸入的工作空間
IWorkspacePtr pInWks;
IWorkspaceFactoryPtr pInWksFact;
pInWksFact.CreateInstance(__uuidof(ShapefileWorkspaceFactory));
pInWksFact->OpenFromFile ( inPutFilePath.AllocSysString(), 0L, &pInWks);
IFeatureWorkspacePtr pInFeatWks;
pInFeatWks = pInWks;
if (pInFeatWks == NULL) {
AfxMessageBox ("所選擇的路徑為非法工作空間路徑!");
return 0;
}
if (!SUCCEEDED(pInFeatWks->OpenFeatureClass(poiFileName.AllocSysString(),&pFCPOI)))
{
AfxMessageBox ("打開POI要素錯誤。請關閉其他所有使用該數據的應用程序,并確保數據無誤!");
return false;
}
return true;
}
//打開道路及POI要素圖層
bool QueryProc::OpenRoadFeatureClass ()
{
//打開輸出輸入的工作空間
IWorkspacePtr pInWks;
IWorkspaceFactoryPtr pInWksFact;
pInWksFact.CreateInstance(__uuidof(ShapefileWorkspaceFactory));
pInWksFact->OpenFromFile ( inPutFilePath.AllocSysString(), 0L, &pInWks);
IFeatureWorkspacePtr pInFeatWks;
pInFeatWks = pInWks;
if (pInFeatWks == NULL) {
AfxMessageBox ("所選擇的路徑為非法工作空間路徑!");
return 0;
}
if (!SUCCEEDED(pInFeatWks->OpenFeatureClass(roadFileName.AllocSysString(),&pFCRoad)))
{
AfxMessageBox ("打開POI要素錯誤。請關閉其他所有使用該數據的應用程序,并確保數據無誤!");
return false;
}
return true;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -