EPS二次开发简单整理(一)

2020.1.3

一、添加命令函数

  1. 编写好AA.h与AA.cpp文件后,打开“QCJInterface.cpp”文件。添加功能函数头文件;

  2. 在接口文件(“QCJInterface.cpp”)中的GetSDLCommandInfo函数中添加命令说明

void GetSDLCommandInfo( CArray<SDLCmdInfo, SDLCmdInfo> &CmdInfoList )
{
	//添加本模块命令
	SDLCmdInfo info;
	info.strCmd = _T("QCJ");
	info.strScript = _T("二次开发样例!");
	CmdInfoList.Add(info);
	info.strCmd = "TestFunction",			info.strScript = "命令测试",				CmdInfoList.Add(info);
}
  1. 在ExecFunction添加命令,将命令与类名联系起来;
void* CQCJInterface::ExecFunction( CString strCmd, CString& strParameters, UINT nReason /* = 0 */ )
{
	//用于返回的指针(必须初始化为NULL)
	CDlgBase* pDlgBase = NULL;
	//使用本模块资源(变量生命周期内有效)
	CQCJLocalResource localRes;
	//在这里启动自已的功能
	if ( !strCmd.CompareNoCase(_T("TestFunction")) ) {
		//构造对象
		pDlgBase = new CQCJEveryone(m_pMap);
		//创建对象
		pDlgBase->Create(CQCJEveryone::IDD);
		//设置类名(功能的名称标识)
		pDlgBase->SetClassName(_T("CQCJEveryone"));
		//功能对话框名称
		pDlgBase->SetDlgName(_T("二次开发样例"));
	}
	//返回对象指针供系统处理
	return pDlgBase;
}

二、添加检查程序

  1. 在接口cpp文件(“QCJInterface.cpp”)中添加功能函数头文件及检查模块头文件
#include "CheckModel.h"
  1. 在接口文件中增加一个注册命令的函数(函数名可任意)
class CQCJInterface : public CSDLInterface
{
public:
	CQCJInterface();
	virtual ~CQCJInterface();
   
	//重载ExecFunction功能接口函数
	virtual void* ExecFunction(CString strCmd, CString &strParameters, UINT nReason = 0);
	BOOL ExecFunction_CheckFunction(  CString strCmd , CString& strParameters , UINT nReason );
	virtual BOOL OnCallBackMessage(CString strMsg, void *pData, int nFlags );
private:
	//增加一个注册命令的函数(函数名可任意)
	void RegisterCommand();
	void RegisterCheckModel();
	CLicenseTimerDlg *dlg ;
};

具体实现为:

void CQCJInterface::RegisterCommand()
{
	//设置模块名称
	SetModulName( _T("QCJ.DLL  平台扩展模块样例") );
	//调用父类的RegisterCmd函数注册命令(cmdID命令或者strCmd命令)
	CArray<SDLCmdInfo, SDLCmdInfo> CmdInfoList;
	GetSDLCommandInfo(CmdInfoList);
	for (int i=0; i<CmdInfoList.GetSize(); i++)
	{
		if (CmdInfoList[i].cmdID)
			RegisterCmd(CmdInfoList[i].cmdID, CmdInfoList[i].strScript);
		else
			RegisterCmd(CmdInfoList[i].strCmd, CmdInfoList[i].strScript);
	}
	RegisterCheckModel();
}
void CQCJInterface::RegisterCheckModel()
{
	CCheckManager* p = m_pMap->GetCheckManager();
	p->RegisterCheckModel(new COverlapCheck());
}
  1. 重载ExecFunction功能接口函数
BOOL CQCJInterface::ExecFunction_CheckFunction(  CString strCmd , CString& strParameters , UINT nReason )
{
	BOOL bShowOutput = TRUE;
	CStringArray strCmdInfos;
	ScanString( strCmd, ".", strCmdInfos );
	CString strGroupName = strCmdInfos[1];
	CString strCheckName = strCmdInfos[2];
	CCheckModel* check = NULL;
	CStringArray strOldCheckFunctionList;
	//数据标准类
	strOldCheckFunctionList.Add("扩展检查");
	if ( strCheckName == "地物符号压盖检查" )
	{
		check = new COverlapCheck();
	}	
	if ( check )
	{
		check->ExecuteCheck( m_pMap, strParameters, nReason );
		delete check;
		check = NULL;
	}
	return TRUE;
}

三、EPS中字体大小判断

房屋注记中,结构注记为中文,层数注记为英文。

1:1000图形中,结构注记字体宽度为300,层数注记宽度为240,单位为厘米。

EPS中1个汉字占2个英文(数字)的大小,获取的字体宽度为1个汉字的占位和高度,英文及数字为汉字大小的一半
建成房屋内结构和层数注记
房屋结构及层数注记宽度为(单位:米):

汉字注记宽度计算
数字宽度计算

四、植被面中符号宽度

植被面内符号带有线宽
植被面符号线宽可以通过pGeo->GetLineWidth() 函数获取。

符号线宽为 (单位:m) :
植被面内部符号线宽

五、Cross_P函数返回值说明

Cross_P 是求两条线段交点情况的函数,有时候需要判断多段线位置关系,需要根据多段线内线段之间的相互关系进行判断。

DllExport int Cross_P(CPoint3D &p,
				const CPoint3D &p1,
				const CPoint3D &p2,
				const CPoint3D &p3,
				const CPoint3D &p4, 
				int*  pResRelation1 = NULL,
				int*  pResRelation2 = NULL );
函数返回值 说明
0 线段相交,交点为p
1 交点为线1上第一点
2 交点为线上1第二点
3 交点为线2上第一点
4 交点为线上2第二点
-1 平行
-2 有一个单点线
-4 线段无关,所在直线相交

六、图形外接矩形关键点序号

关键点分别为左上(0)、左中(1)、左下(2)、中上(6)、中间(7)、中下(8)、右上(3)、右中(4)、右下点(5)。

	0---------6---------3
	|		            |
	1		  7         4
	|		            |        
	2---------8---------5  

七、高程点的范围

通过程序可以获取高程点圆面的圆心坐标C,根据C点可以获取高程点外接矩形范围。
高程点范围示意
1:1000图中,高程点的点在图形中是个圆形,圆心为0.25m,高程注记只显示小数点后 2 位,高程注记的数字宽度为 1.2 m,高度为 2.4 m,所以外接矩形的四点范围为:

左上角坐标
左下角坐标
右下角坐标
右上角坐标

八、EPS中坐标系

屏幕坐标系为测量坐标系,导出之后的XY为平面坐标系颠倒之后的值。
EPS中屏幕坐标系与输出坐标系

九、内存泄漏问题

  1. EPS中使用的SymbolProcess 符号打散函数和Scatter 注记打散函数,如
 CGeObjList k_InnerObjList;	 	
 CMarkNoteList k_MarkList;		
 CMarkNoteList k_NoteList;		
 //对地物内部符号进行打散,保存在内存里
 m_pMap->SymbolProcess(find_k_GeoList[i6], k_InnerObjList,  k_MarkList, k_NoteList);
 k_MList[g2]->Scatter(subNotePtList,false,iScale);

这两个函数获得的图形对象和注记对象,是保存在系统内存中, 使用完之后对其产生的CMarkNoteList subNotePtList 等一定要在使用完及时Free()函数,如

 k_InnerObjList.Free()

如果函数中多次使用SymbolProcessScatter函数,而且函数中使用的CMarkNoteListCGeObjList为同一个变量,需要在下一次使用打散函数之前就Free掉,而不能等到多次符号打散之后再Free,会造成指针指向的对象未释放就指向了新的对象,未释放的空间就一直留在内存里。

  1. 另一方面,要对存在内存中的CGeoBase 等数据(如打散函数产生的对象列表)Free(),若CGeObjListCMarkNoteList指向图幅中已有地物,则不能用Free(),不可删除,否则重复调用该图层中地物时会报错,只能令其为NULL,若指向打散后的内存中的对象,则用delete删除掉,前提也是该对象不重复使用;
CGeoBase* pGeo=NULL;
  1. 指针对象的NewdeleteMallocFree应成对使用,可以避免内存泄漏;

使用delete之后,要对指针赋值NULL,否则还会有内存泄漏问题。

CstringArray* strArray = new CstringArray;
If(strArray)
{
	Delete strArray;
	StrArray = NULL;
}
  1. VC++中可以使用函数帮助确定内存泄漏的文件和位置。

头文件 中添加:

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <windows.h>
  • 函数体* 中添加:
_CrtDumpMemoryLeaks();
  1. Cstring中GetBuffer()ReleaseBuffer()也应成对使用。

GetBuffer() 主要作用是将字符串的缓冲区长度锁定,releaseBuffer则是解除锁定,使得CString对象在以后的代码中继续可以实现长度自适应增长的功能。

发布了3 篇原创文章 · 获赞 0 · 访问量 276

猜你喜欢

转载自blog.csdn.net/moneymyone/article/details/103849562