⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 queryproc.cpp

📁 兴趣点POI(Point of Interests)的查询程序。可以根据条件按照最近方式搜索到POI点
💻 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 + -