📄 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 + -