//
//	wkClassDefine.h
//
//	walk srcipt wk class define.
//	this file can include at visual stadio enveriment for tip
//

#ifndef __WKCLASSDEFINE_H_
#define __WKCLASSDEFINE_H_

/* ****************************************************************************

命名规则说明：

	for,if,while等循环和条件语句，cos,sin,pow等内部函数以及+,-,==,>=等都采用了c
的语法规则和命名，底层提供的两个类型string和array的成员函数采用的是stl的camel命
名规则，即命名中第一字母小写。

	walkSrcipt中已支持全对象化编程，所有从walk平台引出的功能将归于18个类。wk类
在脚本中类似与string和array，也是变量类型，因此wk成员函数的命名亦同样采用camel
命名规则。

**************************************************************************** */

//类的预声明
class array;
class string;
class wkPoint;

class wkDb;
class wkLayer;
class wkFeature;
class wkAnnotation;
class wkStyle;
class wkGeometry;
class wkPolygon;
class wkParts;
class wkPoints;
class wkBox;
class wkGdt;

class wkMultiType;

/* ==================================================
	支持的运算符（与c语言对等）:
	== , <= , >= , != , && , ||,
	++ , -- ,
	+= , -= , *= , /= , %= , &= , ^= , |= ,
	<<= , >>=,
	<< , >>

	? :

	+ , - , * , / ,
	< , > ,
	= , | , % ,
	^ , & , ~ , !

	支持的数据类型:
	void, bool, int, double,
	string, array, wkPoint

	不支持的c数据类型:
	char, long, short, float, unsigned, const 等
	不支持所有MS扩展的数据类型（如:BYTE,DWORD等）

	支持的walk对象:
	wkBox, wkView, wkGeoset, wkDb, wkLayer,
	wkFeature, wkAnnotation, wkStyle,
	wkGeometry, wkPolygon, wkParts, wkPoints,
	wkFile, wkRgn, wkGis, wkTrans, wkClean, wkDialog

	支持函数中的引用参数，如: void func(array &ar, wkDb &db)
	支持宏：#define, #ifdef, #ifndef, #else, #endif
	支持宏：#include

	不支持指针，不支持 new, 不支持 delete
	不支持自定义结构 struct
	不支持自定义类 class

	支持条件语句 if ... else ... 和 switch
	不支持 goto

	支持循环语句 for( ; ; ) 和 while()
	不支持 do ... while

	变量和对象实例作用域定义同c和c++语言
	支持变量定义时的初始化，如: int a=0;

	脚本被限制在walk环境中运行，因此
	不支持 console 标准输入与输出
================================================== */

#ifndef LPCTSTR
#define LPCTSTR char*
#endif

//不支持的c数据类型
#define signed no_use_signed
#define unsigned no_use_unsigned
#define short no_use_short
#define long no_use_long
#define float no_use_float
// 不支持 char, char*, 'a'

//不支持的c和c++保留字（部分）
#define const no_use_const
#define static no_use_static
#define goto no_use_goto
#define do no_use_do
#define enum no_use_enum
#define extern no_use_extern
#define new no_use_new
#define delete no_use_delete
#define struct no_use_struct
#define this no_use_this

#define define
#define function

//------------------------------------------------------------
//1. 基本系统函数
//	控制台 console
int consoleOpen(int act=0);	//	0--	打开console（控制台）
							//	1--	等待任意键（返回 key_value）
							//	2-- 清屏
							//	4--	根据当前颜色刷新屏幕
							//	5-- 获取字符颜色
							//	6-- 获取背景颜色
							//	7-- 获取输入环境的CodePage
							//	9-- 获取输出环境的CodePage
int consoleOpen(int act, int codePageID);
							//	8-- 设置输入环境的CodePage
							//	10-- 设置输出环境的CodePage
int consoleOpen(int act, int textColor, int backColor);
							//	3-- 设置当前颜色
								//	textColor: 字符颜色
								//	backColor: 背景颜色
								//		颜色：1--blue,2--green,4--red,8--增强
								//		白色(15)，黑色(0)

void consoleClose(bool bKeyHit);//	关闭console。
								// bKeyHit: true-- press any key continue
								// 脚本结束时系统会自动执行 consoleClose(true)
//	输入函数：
int		readInteger(string tip/*=""*/);//			从控制台读入整数
string	readString(string tip/*=""*/);//				从控制台读入字符串
double	readDouble(string tip/*=""*/);//				从控制台读入实数
//	输出函数：
void printf(string fmt, ...);//格式化输出到console，输出格式同c的printf
void print(...);	//		非格式化输出到console
void println(...);	//		输出并换行。同上

void message(string msg);//				弹出AfxMessageBox

void trace(string fmt, ...);//			在脚本编辑器输出栏格式化输出
							//			输出格式同c的printf

int getDataType(int);		//			获取数据类型: int dataType=ar[0];
int getDataType(bool);
int getDataType(double);
int getDataType(LPCTSTR);
int getDataType(wkPoint);
int getDataType(wkDb);
int getDataType(wkLayer);
int getDataType(wkFeature);
int getDataType(wkAnnotation);
int getDataType(wkStyle);
int getDataType(wkGeometry);
int getDataType(wkPolygon);
int getDataType(wkParts);
int getDataType(wkPoints);
int getDataType(wkBox);

//	数学函数：
double	sin(double x);//				计算弧度x的正弦值
double	cos(double x);//				计算弧度x的余弦值
double	tan(double x);//				计算弧度x的正切值
double	asin(double x);//				计算实数x的反正弦值
double	acos(double x);//				计算实数x的反余弦值
double	atan(double x);//				计算实数x的反正切值
double	atan2(double y,double x);//		计算点(x,y)的角度

double	sqrt(double x);//				计算x的开方
double	pow(double x,double y);//		计算x的y次方
double	exp(double x);//				Calculates the exponential
double	log(double x);//				Calculates the natural logarithm
double	log10(double x);//				Calculates the base-10 logarithm
double	ceil(double x);//				Calculates the ceiling of a value
double	floor(double x);//				Calculates the floor of a value
				//fmod 被 % 运算符替代，如 double a=10.0 % 3.0，结果 a=1.0

int		abs(int);//						取绝对值
double	abs(double);//					取绝对值

int		ord(string);//					字符转为整数
string	chr(int);//						整数转为字符

int		random();//						产生随机数
void	randomize();//					设置随机种子

//	转化函数：
int		parseInt(string s);//			把字符串转换成int，与atoi相同
double	parseDouble(string s);//		把字符串转换成double，与atof相同
int		atoi(string s);
double	atof(string s);

string	toString(int);//		把value转换成string，类似与Java中的value.toString()
string	toString(bool);
string	toString(double);
string	toString(LPCTSTR);
string	toString(array);
string	toString(wkPoint);
string	toString(wkBox);
string	toString(wkDb);
string	toString(wkLayer);
string	toString(wkFeature);
string	toString(wkAnnotation);
string	toString(wkStyle);
string	toString(wkGeometry);
string	toString(wkPolygon);
string	toString(wkParts);
string	toString(wkPoints);

void exit();	//终止程序运行



//时钟数
int clock();
//clocksPerSec：每秒时钟数
int clock(int &clocksPerSec);

//当前机器时间
double time();

/*************************************************************
	Var  |	Date/Time Component	 |	Valid Range
--------------------------------------------------------------
	year	Year					100 - 9999
	mon		Month					0 - 12
	mday	Day						0 - 31
	hour	Hour					0 - 23
	min		Minute					0 - 59
	sec		Second					0 - 59
	wday	Day of week				0  - 6 Sunday = 1
	yday	Day of year				0  - 365 January 1 = 1 
***************************************************************/
//按年月日和时分秒生成时间
double time(int year, int mon, int mday, int hour, int min, int sec);

// 详细时间
void timeTm(double tm, int& year, int& mon, int& mday, int& hour, int& min, int& sec);
// 取时间的年日和周日
void timeTm(double tm, int& yday, int& wday);
// 时间字符串
void timeTm(double tm, string& ascTime);

// 时间差
void timeSpan(double tm1, double tm2, int& day, int& hour, int& min, int& sec);
//------------------------------------------------------------


class wkPoint
{
public:
	double x, y, z;
};

//支持 string s="const string"+str;
//	注意：两个字符串常量不得相加！如：string s="s1"+"s2";
string operator+(string left, string right);

bool operator>(string left, string right);
bool operator>=(string left, string right);
bool operator<(string left, string right);
bool operator<=(string left, string right);

bool operator==(string left, LPCTSTR right);
bool operator==(LPCTSTR left, string right);
bool operator==(string left, string right);

bool operator!=(string left, LPCTSTR right);
bool operator!=(LPCTSTR left, string right);
bool operator!=(string left, string right);

//string 的用法同 mfc 的 CString
class string
{
public:
	string();
	string(LPCTSTR);

	string& operator=(LPCTSTR lpsz);	//字符串赋值到string中
	string& operator=(string lpsz);		//字符串赋值到string中
	string& operator+=(LPCTSTR lpsz);	//字符串加到string的尾部
	string& operator+=(string lpsz);	//字符串加到string的尾部

	//单字符字符串存取方法
	string getAt(int index);//		取指定位置的字符（单字符字符串）
	void setAt(int index, LPCTSTR chr);//设置指定位置的字符（单字符字符串）
	void setAt(int index, string chr);

	void insertAt(int index, string str); //在index处插入字符串str
	void removeAt(int index, int count=1);//从index处开始删除count个字符

	string mid(int nFirst, int nCount);
	string mid(int nFirst);
	string left(int nCount);
	string right(int nCount);

	bool isEmpty();

	int getLength();

	// printf-like formatting using passed string
	void format(string lpszFormat, ...);

	void makeUpper();
	void makeLower();

	void makeReverse();

	int compare(string);
	int compareNoCase(string);

	int find(string);
	int reverseFind(string);

	void replace(string, string);

	void trimLeft(string);
	void trimLeft();
	void trimRight(string);
	void trimRight();

	string tokenize(string, int&);
};


class array
{
public:
	int	getSize();		//			返回int，返回数组中元素的个数
	void setSize(int);	//			设置数组大小

	wkMultiType& operator[](int nIndex);//	[]方法
	wkMultiType	getAt(int);	//				取特定位置的元素

	void removeAll();	//			数组清空
	void removeAt(int);	//			删除特定位置上的元素

	void insertAt(int, array&);	//	在特定位置插入给定元素
	void insertAt(int, bool);
	void insertAt(int, int);
	void insertAt(int, double);
	void insertAt(int, LPCTSTR);
	void insertAt(int, wkPoint);
	void insertAt(int, wkBox);
	void insertAt(int, wkDb);
	void insertAt(int, wkLayer);
	void insertAt(int, wkFeature);
	void insertAt(int, wkAnnotation);
	void insertAt(int, wkStyle);
	void insertAt(int, wkGeometry);
	void insertAt(int, wkPolygon);
	void insertAt(int, wkParts);
	void insertAt(int, wkPoints);

	void add(array&);	//			在最后插入给定元素
	void add(bool);
	void add(int);
	void add(double);
	void add(LPCTSTR);
	void add(string);
	void add(wkPoint);
	void add(wkBox);
	void add(wkDb);
	void add(wkLayer);
	void add(wkFeature);
	void add(wkAnnotation);
	void add(wkStyle);
	void add(wkGeometry);
	void add(wkPolygon);
	void add(wkParts);
	void add(wkPoints);

	void setAt(int, array&);//		设置特定位置的元素
	void setAt(int, bool);
	void setAt(int, int);
	void setAt(int, double);
	void setAt(int, LPCTSTR);
	void setAt(int, string&);
	void setAt(int, wkPoint);
	void setAt(int, wkBox);
	void setAt(int, wkDb);
	void setAt(int, wkLayer);
	void setAt(int, wkFeature);
	void setAt(int, wkAnnotation);
	void setAt(int, wkStyle);
	void setAt(int, wkGeometry);
	void setAt(int, wkPolygon);
	void setAt(int, wkParts);
	void setAt(int, wkPoints);

	void append(array&);//			把b的所有元素加在a的后面
	array& operator=(array&);	//	数组完全拷贝

	//	数组元素排序(true-升序, 或false-降序). 排序约束：
	//	数组元素的数据类型必须一致（单一数据类型）
	//	数组元素的数据类型只能是整型、浮点和字符串
	//	若不满足约束，则 sort 返回 false
	bool sort(bool bAscend=true);

	//============	矩阵运算 ====================
	// 矩阵相加。
	//	结果矩阵为array所有元素为double类型，若为两维数组，则存储和表达为A[i][j]。
	//	输入数组的元素可以是int类型或double类型
	//	下同
	array mtAdd(array b);
	// 矩阵相减
	array mtSubtract(array b);
	// 矩阵相乘
	array mtMultiply(array b);
	// 矩阵转置
	array mtTranspose(array b);
	// 高斯消元： AX+L=0
	//	为保证求解精度，高斯消元采用的是主元素消元法
	//	若要求n满秩矩阵N的逆阵N(-1)，可组成N*N(-1)-E=0，E为单位矩阵
	//		使用n次高斯消元，得到逆阵
	int mtGauss(array A, array L);
	/* 例子
int main()
{
	array a = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {3, 6, 9}};
	array b = {{3, 2, 1}, {6, 5, 4}, {9, 8, 7}, {6, 1, 7}};

	array c = a.mtAdd(b);
	message("a + b = " + toString(c));

	array d = a.mtSubtract(b);
	message("a - b = " + toString(d));

	array e = a.mtMultiply(b.mtTranspose());
	message("a * transpose(b) = " + toString(e));

	array p1 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 10}};
	array x1;
	int o1 = x1.mtGauss(p1, {3, 9, 10});
	message("p1 = " + toString(p1));
	if (o1 == 1)
		message("唯一解   x1 = " + toString(x1));
	else if (o1 == -1)
		message("无解\n");
	else if (o1 == 0)
		message("无数组解\n");
}
	*/
};

//	for array multiple return data type.
class wkMultiType : public string, public array
{
public:
	operator bool();
	operator int();
	operator double();
	//operator string();
	//operator array();
	operator wkPoint();
	operator wkBox();
	operator wkDb();
	operator wkLayer();
	operator wkFeature();
	operator wkAnnotation();
	operator wkStyle();
	operator wkGeometry();
	operator wkPolygon();
	operator wkParts();
	operator wkPoints();
};
bool operator>=(wkMultiType &left, wkMultiType right);
bool operator<=(wkMultiType &left, wkMultiType right);
bool operator!=(wkMultiType &left, wkMultiType right);
bool operator==(wkMultiType &left, wkMultiType right);
bool operator >(wkMultiType &left, wkMultiType right);
bool operator <(wkMultiType &left, wkMultiType right);



// wkView : 对应主图形窗口的操作
class wkView
{
public:
	int handle();

	//执行windows命令
	/*
			1.0 int shell(string command); 
			Only use WinExec(command) 
			command can be any shell command, like: calc, cmd, cleanmgr, odbcad32, logoff, regedit, sysdm.cpl,
			taskmgr, write, telnet, services.msc, osk, fonts, access.cpl and so on.
			
			2.0 int shell(string operation, string file, string parameters = "", int nShowCmd = SW_SHOWNORMAL);
			Use ShellExcute();
			string operation can be "open", "explore", "print" and so on;
			file is a document file or a path_to_folder;
			nShowCmd can be:
			SW_HIDE 0, SW_SHOWNORMAL 1, SW_SHOWMINIMIZED 2, SW_MAXIMIZE SW_SHOWMAXIMIZED 3,
			SW_SHOWNOACTIVATE 4, SW_SHOW 5, SW_MINIMIZE 6, SW_SHOWMINNOACTIVE 7, 
			SW_SHOWNA 8, SW_RESTORE 9, SW_SHOWDEFAULT 10
			
			3.0 int shell(string commandLine, bool waitThisProcess, int nShowCmd = SW_SHOWNORMAL);
			use CreateProcess() and WaitForSingleObject, Runs the application registered for the specified file extension.
			command line can be a shell command, 
			you can also just type "C:\\test.doc" when you wanna open the file, or an url like "www.zju.edu.cn".
			If waitThisProcess is true, it will wait the process(like "c:\\myTest.exe") until it is terminate.
			
			example:
			wkView v;
			int ret;
			ret = v.shell("osk");								if (ret > 32) message("osk");
			ret = v.shell("calc");								if (ret > 32) message("calc");
			ret = v.shell("cmd /C tree c: >>c:\aa.txt");		if (ret > 32) message("list c: to aa.txt");
			ret = v.shell("cmd /C copy c:\\aa.txt c:\\bb.doc");	if (ret > 32) message("copy aa.txt to bb.doc");
			ret = v.shell("explorer /select, c:\\aa.txt"); 		if (ret > 32) message("select f:\aa.txt");
			ret = v.shell("open", "c:\\aa.txt");				if (ret > 32) message("open aa.txt");
			ret = v.shell("explorer", "c:\\aa.txt");			if (ret > 32) message("explore aa.txt");	
			ret = v.shell("print", "c:\\aa.txt");				if (ret > 32) message("print aa.txt");
			ret = v.shell("new", "www.google.com");				if (ret > 32) message("new google.com");
			ret = v.shell("open", "http://www.zju.edu.cn");		if (ret > 32) message("open zju.edu.cn");
			ret = v.shell("c:\\bb.doc", false); 				if (ret > 32) message("not wait bb.doc"); 
			ret = v.shell("c:\\aa.txt", true); 					if (ret > 32) message("wait aa.txt");
	*/
	int shell(string command);
	int shell(string operation, string file, string parameters = "", int nShowCmd = 1/*SW_SHOWNORMAL*/);
	int shell(string commandLine, bool waitThisProcess/* = false*/, int nShowCmd = 5/*SW_SHOW*/);

	//执行一个walkScript脚本
	bool walkscript(string wspPath);
	bool walkscript(string wspPath, array params);
	bool walkscript(string wspPath, string args);

	//---------------------------------------
	//对话框
	//---------------------------------------

	//单行输入对话框
	string dlgInput(string title, string defText);
	//寻求确认对话框
	bool dlgQuestion(string question);
	//文件选择对话框
	// bOpen : true--打开文件，false--保存文件
	// defaultExt : 默认的文件扩展名
	// filter : 为过滤条件，如："WalkFloor 数据库 *.mdb|*.mdb|所有文件 *.*|*.*||"
	string dlgFile(bool bOpen, string defaultExt, string filter);
	//目录选择对话框
	string dlgFolder(string defFolder);

	//---------------------------------------
	//进程提示
	//---------------------------------------

	//开始进程提示
	void waitStart(string msg);
	//进程中提示
	void waitMessage(string msg, int i);
	//结束进程提示
	void waitEnd();

	//获取文件全路径并判断文件存在，若成功则返回全路径，否则为空
	string getVailFilePath(string file);
};

//	wkGeoset : 对工作空间的操作
class wkGeoset
{
public:
	int handle();

	// 获取工作空间名
	string getName();

	//获取工作空间名中的walk数据库个数
	int getDbCount();

	//获取工作空间中的数据库对象
	//at: db在geoset中的序号，从0开始。
	//	若at==-1, 则打开模板库，使用完后一定要使用 wkDb 的close().
	wkDb getDbAt(int at);

	//获取工作空间中的层数
	int getLayerCount();

	//获取工作空间中的层对象
	wkLayer getLayerAt(int at);
	wkLayer getLayer(string layer);
	wkLayer getLayer(string layer, wkDb db);

	//获取工作空间中的当前可编层
	wkLayer getEditableLayer();

	//将层从工作空间中移去
	void removeLayer(wkLayer layer);

	//从库中加入一层到工作空间中
	wkLayer addLayer(string layer, int dbAt);
	wkLayer addLayer(string layer, wkDb db);
	
	//置取投影和坐标系（参见Walk手册）
	int getSRS();
	void setSRS(int srs);

	//置取当前工作空间的长度单位
	int getLengthUnit();
	void setLengthUnit(int lengthUnit);

	//置取当前工作空间的面积单位
	int getAreaUnit();
	void setAreaUnit(int areaUnit);

	//置取当前工作空间的系统比例尺分母
	double getSystemScale();
	void setSystemScale(double sysScale);

	//获取当前工作空间地物文字空间分布的外接盒
	wkBox getBox();


	//-----------------------------------------------------------
	//以下 onConstrainGet 和 onConstrainSet 函数
	//	只能用在层的地物编辑和数据存取响应脚本中
	//-----------------------------------------------------------

	//获取层特定控制类型下的控制内容
	//	若层及控制类型不存在，则 return false
	bool onConstrainGet(int ctrlType, wkLayer layer, int& context);

	//设置层特定控制类型下的控制内容
	//	若层及控制类型不存在，则 return false
	//	若 context==9999, 则不改变控制内容，但清除该层该控制类型的脚本机器码
	bool onConstrainSet(int ctrlType, wkLayer layer, int context);

	//------------------------------------------------------------
	//----获取当前在控制的层
	wkLayer onConstrainGetLayer();
	//----获取当前在编(删改)的原地物ID或文字ID
	int onConstrainGetId();
	//----获取当前在编的新地物几何(可直接修改，不要free)
	wkGeometry onConstrainGetGeom();
	//----获取当前在编的新地物属性
	string onConstrainGetAttr(string fieldName);
	//----获取当前在编的文字(可直接修改，不要free)
	wkAnnotation onConstrainGetAnno();
	//----获取层加载时的过滤条件
	string onConstrainGetLoadFilter();

	//----放弃编辑，或层数据存取
	void onConstrainSetAbort();
	//----设置当前在编的新地物属性
	void onConstrainSetAttr(string fieldName, string newVal);
	//----设置层加载时的过滤条件
	void onConstrainSetLoadFilter(string loadFilter);
	//------------------------------------------------------------
};

//	wkDb : 对walk数据库的操作
class wkDb
{
public:
	int handle();

	// 获取数据库名称
	string getName();
	//	取得数据库类型：0--access库，1--dsn数据库
	int getType();

	//打开数据库
	// dbName: 数据库名，可以是ODBC名
	// bool bMDB: true--要打开的库是MDB库. false--是sql-server库
	// addToGeoset: true--将打开的数据库添加到geoset,要求该库必须是walk库
	//				false--不添加到geoset中，数据库使用完后必须close.
	bool open(string dbName, bool bMDB, bool addToGeoset);
	// 关闭数据库，且从工作空间中移去该库的所有层
	void close();

	//	判断层是否在库中
	bool isLayerExisted(string layerName);
	//	在库中创建一个简单层（不加入到geoset中）
	//	新层包含 FeatureId, StyleId, Geometry, CreateTime 四个字段
	//		若要在层中添加字段，可使用 execSQL
	bool createLayer(string layerName);
	//	在库中创建一个与fromLayer同结构的普通层
	//	bCopyData: true--从fromLayer复制数据到新层中
	bool createLayer(string layerName, string fromLayer, bool bCopyData);

	//--------------------------------------------
	//SQL
	//--------------------------------------------

	//执行普通SQL语句
	bool execSQL(string sql, bool warning);

	//从select语句获取数据（string数组）
	array getDataBySQL(string sql, int topLimit);

	//表是否在库中
	bool isTableExisted(string tableName);
	//获取库中的所有表名称
	array getTables();
	//获取库中的所有层名称
	array getLayers();
	//获取库中的所有视图名称
	array getViews();
	//获取一张表的所有字段名称
	array getTableFields(string tableName, bool bPrimaryOnly=false);

	//获取自动编号定义符
	//	在access中为 AutoIncrement，在sql-server中为 INT IDENTITY
	string getAutonumberDef();
	//获取表中自动编号字段名
	string getAotunumberField(string tableName);

	//获取表中一个字段的SQL类型
	//	参见 wcLayerConstant.h 中的 wcSQL_
	int getFieldSQLType(string tableName, string fieldName);
	//获取表中一个字段的长度
	int getFieldPrecision(string tableName, string fieldName);
	//获取表中一个字段的小数位
	int getFieldScale(string tableName, string fieldName);
	//获取表中一个字段是否允许为空
	bool getFieldNullability(string tableName, string fieldName);

	//----------------------------------
	//为sql语句解析的工具函数：
	//----------------------------------

	//	从src中查找字key（不处理单引号对内的字符部分）. 不区分大小写，返回位置
	int  sqlFind(string src, string key, int nFnd);
	//	分解str以delimiter分隔（不处理单引号对内的字符部分）的字符串组
	array sqlSubsByDeli(string str, string delimiter);
};

//	wkLayer : 对层的操作
class wkLayer
{
public:
	int handle();

	//获取层名
	string getName();

	//获取层所属的数据库
	wkDb getDb();

	//获取层已加载地物和文字的外接盒
	wkBox getBox();

	//置取层在工作空间中的上下次序（上层压盖下层）
	// wcLayerOrderTop(0)--在最上层，<0--层不在工作空间中
	int getOrder();
	// order: 参见 wcLayerConstant.h 的 wcLayerOrder
	void setOrder(int order);

	//获取层的属性字段名称（不含4个基本字段名）
	array getFieldnames();
	//获取字段的序号
	//	用于与wkFeature::getInfo和setInfo配合使用
	int getFieldIndex(string fieldName);

	//加载或卸载层地物属性信息
	// bLoad:	true--load all features info.
	//			false--unload(free) all unchanged features info.
	void loadInfo(bool bLoad=true);

	//层中地物和文字是否已增删改
	bool isDirty();

	//----------------------------------------
	//地物 feature 的获取、增加和删除
	//----------------------------------------

	//获取层中地物数
	int getFeatureCount();

	//获取地物
	wkFeature getFeatureAt(int at);
	wkFeature getFeature(int featureId);

	//向层中添加地物
	wkFeature addFeature(wkFeature fea);
	wkFeature addFeature(wkGeometry geom, int attrFromFeaId);
	wkFeature addFeature(wkGeometry geom);
	wkFeature addFeature(wkPoint pt);
	wkFeature addFeature(wkPoint pt, double angle);
	wkFeature addFeature(wkBox box, bool bRing);
	wkFeature addFeature(array pts, int linetype, bool bRing);
	wkFeature addFeature(wkPolygon poly);
	wkFeature addFeature(wkParts parts, bool bRing);
	wkFeature addFeature(wkPoints points, bool bRing);

	//删除层中的地物
	void deleteFeature(int featureId);
	// update Feature 在 wkFeature 中

	//----------------------------------------
	//文字和影像 annotation 的获取、增加和删除
	//----------------------------------------

	//获取层中文字和影像个数
	int getAnnotationCount();

	//获取层中文字和影像
	wkAnnotation getAnnotationAt(int at);
	wkAnnotation getAnnotation(int annotationId);

	//向层中添加文字和影像
	wkAnnotation addAnnotation(wkAnnotation ann);
	wkAnnotation addAnnotation(string text, wkPoint pt, int charH_01mm);
	wkAnnotation addAnnotation(string imagePath, array pts);

	//删除层中的文字和影像
	void deleteAnnotation(int annotationId);
	// update Annotation 在 wkAnnotation 中

	//----------------------------------------
	//式样 style 的获取、增加和删除
	//----------------------------------------

	//获取层中式样个数
	int getStyleCount();

	//获取层中式样
	wkStyle getStyleAt(int at);
	wkStyle getStyle(int styleId);

	//向层中添加式样
	wkStyle addStyle(wkStyle style);
	wkStyle addStyle(int type, string name, string note);

	//删除层中的式样（若该式样被层中的地物和文字使用，则删除无效）
	void deleteStyle(int styleId);

	//用src层（可不同库）式样刷新tar本层的指定式样。要求式样类型（点线面文字）相同。
	//目标式样的式样名、别名和StyleId不变。颜色、线宽等设置被刷新为源式样。
	//若源式样含内联ID（用户自定义矢量画法）则刷新目标符号库（及式样的内联ID）
	// tarStyleId：本层要被更新的式样
	// srcStyleId：它层式样, wkLayer srcLayer
	bool updateStyle(int tarStyleId, int srcStyleId, wkLayer srcLayer);

	//----------------------------------------
	//	层的类型和其他属性
	//----------------------------------------

	//层类型是否为隐式索引
	bool isIndexLayer();
	//获取隐式索引层的矩形范围的相关格子值（整型）
	array getCell(wkBox range);

	//层类型是否为属性索引
	bool isPIndexLayer();
	//获取属性索引字段名
	string getPIndexField();
	//设置属性索引字段名
	void setPIndexField(string field);
	//获取属性索引值
	string getPIndexValue();
	//设置属性索引值
	void setPIndexValue(string val);

	//----------------------------------------
	//	索引、加载与保存
	//----------------------------------------

	//重建索引
	void reindex();
	//仅更新fea索引
	void reindex(wkFeature fea);
	//仅更新ann索引
	void reindex(wkAnnotation ann);

	//按条件加载地物和文字
	void load(string feaFilter, string annFilter);

	//地物、文字和式样存盘
	void save();

	//移去层内的地物和文字（式样保留）
	void empty();

	//按隐式索引网格加载地物和文字
	void loadByCell(array cells);
	//按隐式索引网格卸载地物和文字
	void unloadByCell(array cells);

	//----获取存盘前删除的地物/文字Ids
	array getDelIds(bool bFeature);

	//-------------------------------------
	//层状态
	//-------------------------------------

	//层中地物和文字是否显示
	bool isVisiable();
	void setVisiable(bool b);
	//层中地物和文字是否可选
	bool isSelectable();
	void setSelectable(bool b);
	//层中地物和文字是否可编辑
	bool isEditable();
	void setEditable(bool b);

	//层中地物是否标签
	bool isLabelable();
	void setLabelable(bool b);
	//置取标签字段
	string getLabelField();
	void setLabelField(string field);
	//置取标签式样
	//在此获取的 wkStyle 要求使用 wkStyle.free() 释放空间
	wkStyle getLabelStyle();
	void setLabelStyle(wkStyle style);
	//置取标签格网规格
	int getLabelGrid();
	void setLabelGrid(int size);

	//-------------------------------------
	//可见范围受尺度控制
	//-------------------------------------

	//置取可见范围控制状态
	bool isZoomable();
	void setZoomable(bool b);
	//置取可见范围控制尺度
	double getZoomMin();
	double getZoomMax();
	void setZoomRange(double min, double max);

	//置取自动标签尺度控制状态
	bool isLabelZoomable();
	void setLabelZoomable(bool b);
	//置取自动标签控制尺度
	double getLabelZoomMin();
	double getLabelZoomMax();
	void setLabelZoomRange(double min, double max);

	//-------------------------------------
	//默认式样
	//-------------------------------------

	//置取默认式样
	//	参见	wcStyleConstant.h
	//		wcStyleType...
	int getDefaultStyleId(int wcStyleType);
	void setDefaultStyleId(int styleId);


	//-------------------------------------
	//查找地物
	//-------------------------------------

	//按矩形范围查找地物，结果加入Selection. 返回查找到的个数
	int searchFeature(wkBox range);
	//按位置查找地物，结果加入Selection. 返回查找到的个数
	int searchFeature(wkPoint pt);
	//按属性条件进行查找，如：
	//	layer.searchFeature("featureId>2000 and createTime>'2008-1-1'");
	int searchFeature(string condition);
	//查找与地物几何满足指定的9i关系的地物:
	//	参见 wcGeomConstant.h
	//		wcGeom9i...
	int searchFeature(wkGeometry geom, int wcGeom9i);

	//从内存中查找: 查找结果加入AnSelection. 返回查找到的个数
	int searchAnnotation(wkBox range);
	//查找文字，如：
	//	layer.searchAnnotation("砖");
	int searchAnnotation(string text);
	//按ref参考，以指定的mask查找所有含同值的annotation
	int searchAnnotation(wkAnnotation ref, int mask);
	//查找与指定地物几何满足指定的9i关系的annotation
	int searchAnnotation(wkGeometry geom, int relation9i);


	//-------------------------------------
	//打散地物和文字
	//-------------------------------------

	//将选中地物打散到目标层（允许设置UNDO）
	void scatterFeature(int nDisperseDef, wkLayer tarLayer, bool bUndoNeed);
	//将选中地物打散并裁剪trim到目标层
	void scatterFeature(int nDisperseDef, wkLayer tarLayer, wkGeometry trim, bool trimInside);

	//将选中文字串逐字符打散到目标层（允许设置UNDO）
	void scatterAnnotation(wkLayer tarLayer, bool bUndoNeed);


	//-------------------------------------
	//拓扑关系
	//-------------------------------------

	//获得层内与ring顶点重合的点地物id序列
	//	首点的位置firstAt_wc3x3 参见 wc3x3Constant.h
	//		wc3x3 ...
	array findPointBy(wkParts ring, int firstAt_wc3x3, bool clockwise);
	//获得层内以term1和term2为端点的线地物id数组
	array findLineBy(wkPoint term1, wkPoint term2);
	//获得以line为邻边的左右面地物，返回左右面个数
	int findPolygonBy(wkParts line, wkFeature &left, wkFeature &right);
	//获得以line为邻边的左右面地物，返回左右面个数, nocheck--true: 不检查其左右面合法性
	int findPolygonBy(wkParts line, wkFeature &left, wkFeature &right, bool nocheck);

	//对本层进行剖分检查，结果到"剖分检查层"
	//boundLayer: 境界层或边界层
	//nCheckContext:
	//	1--境界面缝隙/重叠/悬挂点检查
	//	2--本层面缝隙/重叠/悬挂点检查
	//	4--境界面与本层面相交检查
	//	8--本层（宗地）与边界线（界址线）缝隙检查
	//bool bEqualLine: true--检查悬挂点，false--不检查悬挂点
	//返回：0无错误，非0有错误。
	int topoCheck(wkLayer boundLayer, int nCheckContext, bool bEqualLine, double eps);

	//---- 缝隙处理/检查
	int crackNeaten(wkLayer boundLayer, bool bDangleCheck, bool bSelOnly, double eps, bool bCheckOnly);

	//---- 线与面相交检查（可剪断）
	//选中与面regionLayer相交的（本层）线物，并可剪断线（bSplitAsNeed=true）
	//	bSelOnly: 仅处理选中线物
	//【返回】相交的线物数
	int lineNeaten(wkLayer regionLayer, bool bSelOnly, double eps, bool bCheckOnly);

	//---- 由指定层地物向本层构面或线素整理
	//	若未指定层，则使用当前选中的所有线素来处理
	bool build(array from_wkLayers, double eps, bool bCleanOnly);

	//将本层（或本层选中bSelOnly=true）地物依附于他层baseLayer地物上
	bool attachTo(bool bSelOnly, wkLayer baseLayer, double eps);

	//几何数据整理
	int neaten(bool bXYNeat, bool bHNeat, wkBox range);//范围处理
	int neaten(int nDecimal);//精度对齐
	//	int neatenMask:
	//		  1: 0长线 short length of parts -- check and neaten
	//		  2: 0面积面 small area of parts -- check and neaten
	//		  4: 重点 overlap pt -- check and neaten
	//		  8: 3点弧折线化 3p arc -- check and discret
	//		 16: 曲线折线化 curve -- check and discret
	//		 32: 线自交 self-intersect of parts -- check and neaten
	//		 64: 线间重点 overlap of parts -- check only
	//		128: 3点弧中点居中 3p arc middle -- check and remiddle
	int neaten(double eps, int neatenMark);//几何数据处理

	//层全视
	void wholeView();
};

// wkFeature : 对地物的操作
class wkFeature
{
public:
	int handle();

	//取地物id
	int getId();

	//置取地物的式样id
	int getStyleId();
	void setStyleId(int styleId);

	//置取地物的修改状态
	bool isModified();
	void setModified(bool bModified);

	//从feature中获得geometry指针. 不得free
	wkGeometry getGeometry();
	//重置 geometry
	void setGeometry(wkGeometry geom);
	//重置 geometry，并对Feature重建索引
	void setGeometry(wkGeometry geom, wkLayer layer);

	//置取地物中的属性信息
	string getInfo(wkLayer layer, string field);
	string getInfo(wkLayer layer, int fieldIndex);
	void setInfo(wkLayer layer, string field, string val);
	void setInfo(wkLayer layer, int fieldIndex, string val);
};

// wkAnnotation : 对文字和影像的操作
class wkAnnotation
{
public:
	int handle();

	//取文字或影像的id
	int getId();

	//置取式样id
	int getStyleId();
	void setStyleId(int styleId);

	//置取修改状态
	bool isModified();
	void setModified(bool bModified);

	//置取文字串或影像路径
	string getText();
	void setText(string text);

	//是否为影像
	bool isDib();

	//置取文字或影像定位点（文字1个定位点，影像为4个）
	wkPoint getRefPt(int at);
	void setRefPt(wkPoint pt, int at);

	//置取文字块信息（尺度以0.1mm为单位，角度以0.1度为单位）
	//	mask 参见 wcAnnoConstant.h
	//		wcAnnoInsPos ... wcAnnoFeatureID
	int getInfo(int mask);
	void setInfo(int mask, int val);
};

// wkStyle : 对式样的操作
class wkStyle
{
public:
	int handle();

	//获取式样id
	int getId();

	//获取式样类型
	//	参见	wcStyleConstant.h
	//		wcStyleType...
	int getType();

	//置取式样名
	string getName();
	void setName(string name);

	//置取式样说明
	string getNote();
	void setNote(string note);

	//创建式样
	//	参见	wcStyleConstant.h
	void create(wkLayer refLayer, int wcStyleType, string name, string note);
	//释放创建的式样
	void free();

	//是否为用户自定义式样
	//	点符号、线符号和面符号式样号>255 为用户自定义式样
	bool isUserStyle();

	//置取点线面符号的式样号，文字字体名，位图符号名
	//	面边界的式样号要使用 getInfo或setInfo 的 mask=15
	//	点线面式样号亦可使用 getInfo(wcStyleStyle);
	//	参见 wcStyleConstant.h 的 wcWalkPen, wcPattern
	string getStyle();
	void setStyle(string style);

	//获取式样信息
	//	maks 参见 wcStyleConstant.h
	//		wcStyleColor ... wcStyleBorderTransparent
	int getInfo(int mask);
	void setInfo(int mask, int val);
};

// wkGeometry :	对地物几何体的操作
class wkGeometry
{
public:
	int handle();

	//创建几何体
	//	凡是create得geometry, 就必须free
	void create(wkPoint pt);
	void create(wkPoint pt, double angle);
	void create(wkBox box, bool bRing);
	void create(array pts, int linetype, bool bRing);
	void create(wkGeometry geom);
	void create(wkPolygon poly);
	void create(wkParts parts, bool bRing);
	void create(wkPoints points, bool bRing);
	void free();

	//几何类型：
	//	参见 wcGeomConstant.h
	//		wcGeomPoint-点, wcGeomLine=线, wcGeomRegion面
	int type();

	//-------------------------------------
	//	多边形
	//-------------------------------------

	//获取多边形个数
	int getPolygonCount();
	//获取多边形
	wkPolygon getPolygonAt(int at);
	//添加一个多边形
	void insertPolygonAt(wkPolygon poly);
	//删除一个多边形
	void deletePolygonAt(int at);
	//替换一个多边形
	void replacePolygonAt(wkPolygon poly, int at);

	//-------------------------------------
	//	线（及环）
	//-------------------------------------

	//获取线（及环）个数
	int getPartsCount();
	//获取线
	wkParts getPartsAt(int at);
	//插入线或环
	void insertPartsAt(wkParts parts, bool bRing, int at);
	//删除线
	void deletePartsAt(int at);
	//替换线
	void replacePartsAt(wkParts parts, int at);

	//-------------------------------------
	//	点和有向点
	//-------------------------------------

	//获取独立点数（不含线中的点）
	int getPointCount();
	//获取点
	wkPoint getPointAt(int at);
	//插入点
	void insertPointAt(wkPoint point, int at);
	//删除点
	void deletePointAt(int at);
	//替换点
	void replacePointAt(wkPoint point, int at);

	//-------------------------------------
	// OGC（线和面几何体）所支持的计算
	//-------------------------------------

	//求与他地物的九交关系
	//	参见 wcGeomConstant.h
	//		wcGeom9i...
	int get9i(wkGeometry B);
	//	r8bool 两个几何体"内、界、外"的3x3九交关系（每个关系按位存放）
	//		设：this--A; 内: iA, iB; 界：dA, dB; 外: oA, oB;
	//		判两要素相交(^)只有1-true或0-false
	//		0x87654321:  1--iA^iB, 2--iA^dB, 3--iA^oB
	//					 4--dA^iB, 5--dA^dB, 6--dA^oB
	//					 7--oA^iB, 8--oA^dB, 9--oA^oB==true（该位忽略）
	//		注：由于两个几何体的外必为交，因此只返回8个关系。
	//			此处定义的r8bool严格符合OGC的规定
	//  lineTouch	是否含线触
 	//	pointTouch	是否含点触
	int get9i(wkGeometry B, int &r8bool, int &lineTouch, int &pointTouch);

	//获取与他地物的布尔计算结果
	//	参见 wcGeomConstant.h
	//		wcGeomOpIntersect	0	//求交
	//		wcGeomOpUnion		1	//求和
	//		wcGeomOpDifference	2	//求差
	wkGeometry boolOp(wkGeometry B, int wcGeomOp);
	//求两个地物的共线: wcGeomOpOverline==10 多parts
	//求两个地物的悬挂点：wcGeomOpDangle==11 多点
	wkGeometry boolOp(wkGeometry B, int wcGeomOp, double eps);

	//获得本地物擦除B地物的结果
	//	trim_out: true--将B在本地物的外边部分擦除，false--将B落在本地物内部的部分擦除
	//	若本geometry为点，B为线，则返回geometry为被截断的多个parts
	wkGeometry trim(wkGeometry B, bool trim_out);

	//求平面坐标面积
	double area();
	//求椭球面积（平方米）
	// dn, de： 几何坐标转为赤道和含500公里标准高斯坐标所需平移量
	// b54:  1-计算54椭球，0-计算80椭球面积
	// bDegree: 几何体坐标单位：1-度，0-米
	double area(double dn, double de, bool b54, bool bDegree);

	//周长
	double perimeter();

	//型心点。面地物的型心点必在面内最大内接圆的中心
	wkPoint centroid();

	//地物的外接矩形(ogc称为envelope)
	wkBox bounds();

	//求本地物的凸包
	wkGeometry convex();
	//求 points 的凸包
	wkGeometry convex(array points);

	//生成地物缓冲区
	//	参见： wcToolConstant.h
	//	wcEndcap 缓冲区端点类型
	//	wcJoin 缓冲区转折处类型
	//	wcPenAlign	缓冲方向
	wkGeometry buffer(double offset, int wcEndcap, int wcJoin, int wcPenAlign);
	wkGeometry buffer(array geometrys, double offset, int wcEndcap, int wcJoin, int wcPenAlign);

	//	几何体完整性检查
	//		eps--重点限差、判定尖刺的限差、相触限差
	//	参见 wcGeomConstant.h
	//		wcGeomCheck--检查项标志
	bool isNormal(double eps, int wcGeomCheck, wkPoint& errorPos);

	//本地物与他地物的距离
	double distance(wkGeometry geom);
	//本地物与点的距离
	double distance(wkPoint pt);

	// 6参数线性变换
	// X=a0+a1*x+a2*y
	// Y=b0+b1*x+b2*y
	void transform(double a0, double a1, double a2, double b0, double b1, double b2);
	// 平移 (等价于：a0=dx, a1=1, a2=0, b0=dy, b1=0, b2=1)
	// X=dx+x
	// Y=dy+y
	void transform(double dx, double dy);

	//顺向
	void putInOrder();
	//拓扑重构
	void rebuild();
	//按面积调整多边形(只调整第一个多边形)
	void adjByArea(double newArea, array &fixedPoints);

	// 反向
	void putInOtherOrder();

	//判断点是否包含在几何体中
	bool contain(wkPoint pt);
};

//	wkPolygon : 对多边形的操作
class wkPolygon
{
public:
	int handle();

	//获取多边形中的环数
	int getRingCount();

	//获取多边形中的环
	wkParts getRingAt(int at);

	//插入一个环（bHole--true为插入洞，否则为外环）
	void insertRingAt(wkParts ring, bool bHole);

	//删除一个环
	void deleteRingAt(int at);

	//替换一个环
	void replaceRingAt(wkParts ring, int at);

	//创建一个多边形
	void create(wkPolygon poly);
	void create(array pts, int linetype);

	//释放创建的多边形
	void free();
};

//	对线（及环）的操作
class wkParts
{
public:
	int handle();

	//-------------------------------------
	//	对线串的操作
	//-------------------------------------

	//获取线串（同线型）个数
	int getPointsCount();
	//获取一个线串
	wkPoints getPointsAt(int at);
	//插入一个线串
	void insertPointsAt(wkPoints point, int at);
	//删除一个线串
	void deletePointsAt(int at);
	//替换一个线串
	void replacePointsAt(wkPoints point, int at);

	//-------------------------------------
	//	对线顶点的操作
	//-------------------------------------

	//获取线的顶点个数
	int getVertexCount();
	//获取一个顶点
	wkPoint getVertexAt(int at);
	//插入一个顶点
	void insertVertexAt(wkPoint pt, int at);
	//删除一个顶点
	void deleteVertextAt(int at);
	//替换一个顶点
	void replaceVertexAt(wkPoint point, int at);
	//获取距离点refPt最近的顶点at
	int nearestVertexAt(wkPoint refPt);

	//-------------------------------------
	//	创建及属性和其他操作
	//-------------------------------------

	//创建线
	void create(wkParts parts);
	void create(array pts, int linetype);
	//创建圆弧或扇形. startAngle,endAngle: 以弧度为单位
	void create(wkPoint c0, double r, double startAngle, double endAngle, bool bChord);

	//释放创建的串
	void free();

	//是否为闭合线
	bool isClosed();
	
	//要求闭合，得出来的才正确
	bool isClockwise();

	//获取线的近角顶点
	//	参见 wc3x3Constant.h
	//		wc3x3 ...
	wkPoint getCorner(int nCorner_wc3x3);

	//将线（必须是环）首点移到指定的顶点上
	bool shiftHeadTo(wkPoint vertex);

	//反向
	void reverse();

	//求线等间隔的n个切点以及切点处的切线方向（弧度）
	//	切点的z值存放切线方向
	array inters(int n);
};

// wkPoints : 对线串（唯一线型的点流）的操作
class wkPoints
{
public:
	int handle();

	//置取线串线型
	// 参见 wcGeomConstant.h 的 wcGeomLine
	int getLinetype();
	void setLinetype(int linetype);

	//获取线串中的点个数
	int getPointCount();
	//获取线串中的点
	wkPoint getPointAt(int at);
	//向线串中插点
	void insertPointAt(wkPoint pt, int at);
	//从线串中删除点
	void deletePointAt(int at);
	//替换线串中的点
	void replacePointAt(wkPoint pt, int at);

	//创建线串
	void create(wkPoints points);
	void create(array pts, int linetype);
	//释放创建的线串
	void free();
};

// wkBox : 对实数矩形的操作
class wkBox
{
public:
	// 矩形盒是否为空
	bool isEmpty();

	// 获取矩形盒宽和高
	double w();
	double h();
	//获取矩形盒的中心
	wkPoint center();
	//获取矩形盒左下角点
	wkPoint min();
	//获取矩形盒右上角点
	wkPoint max();

	//点加入到矩形盒中
	void add(double x, double y);
	void add(wkPoint pt);
	void add(wkBox box);

	//膨胀矩形盒
	void inflate(double dx, double dy);
	//平移矩形盒
	void offset(double dx, double dy);
	//与另一个矩形盒是否有相交（有重叠）
	bool intersect(wkBox box);
};

// wkGis : 对GIS工具的操作
class wkGis
{
public:
	bool vail();

	//对专题要素数组分级 
	// vals		专题要素数组（整数）
	// wcReclass	分级方法, 参见 wcToolConstant.h
 	// reclass_number	分级数
 	// reclass_round		分级精度. 如高程地模取500（5米）的整倍数
	//返回： array 分级值（各级左闭界）数组（整数）
	array classfication(array vals, int wcReclass, int reclass_number, int reclass_round);

	//-----------------------------------------
	//	GIS网络分析
	//		这里得到的geometry必须free
	//	route 路网所在层
	//	routePowers 路网层的路段耗时字段名
	//	routeDirects 路网层的路段单向通行字段名
	//	crossTime 路网交叉口通过平均耗时
	//-----------------------------------------

	//求中心点pos的服务区（边界rBestLine）
	wkGeometry findServiceArea(wkPoint pos,
			wkLayer route, string routePowers, string routeDirects, double crossTime,
			double serviceRange, bool bConvex, double eps);
	//求投递员到投递点的最佳路线 (bReturned--返回邮局)
	array findBestPostRoute(array posters, array dealLocs,
			wkLayer route, string routePowers, string routeDirects, double crossTime,
			bool bReturned, double eps);
	//求点pos到各医院之中的最近医院的路径
	wkGeometry findNearestHosptal(wkPoint pos, array hosptals,
			wkLayer route, string routePowers, string routeDirects, double crossTime,
			double eps);
	//求两点间的最短路径
	wkGeometry findBestRoute2Pos(wkPoint fromPt, wkPoint toPt,
			wkLayer route, string routePowers, string routeDirects, double crossTime,
			double eps);

	//聚类分析（分级或分区）：
	// dim: 1--1维，2--2维，3--3维
	// data: 待分级的数据，1维要求为double数组，2维和3维要求为wkPoint数组
	//	m: 初始分区个数
	// 【返回】聚类后的各元素的区间编号(int类型数组)
	array clustering(int dim, array &data, int m);

	// 求线ln的平行侧点的顶点集合
	//	offset: 偏移
	//	bLeft: true--平行线在线ln的左侧，false--在右侧
	//【返回】平行线
	wkGeometry dlPoints(wkPoints ln, double offset, bool bLeft);
	//将线分裂为两条轴线
	//【返回】若成功则几何体包含2个parts，每个parts为一轴线
	wkGeometry dlPoints(wkPoints ln);
	//在线ln1与线ln2中内插(如台阶)
	//insertLineNum: 内插线个数
	//【返回】: 几何体包含指定个数parts，每个parts为一内插线
	wkGeometry dlPoints(wkPoints ln1, wkPoints ln2, int insertLineNum);
	//以线ln1向线ln2做垂线或均分
	//	offset: 间隔(若<=0，则使用轴线1的顶点)
	//	bVert: true--做轴1到轴2的垂线，false--做两轴均分
	//【返回】几何体含2个parts，每个parts为线间隔点列
	wkGeometry dlPoints(wkPoints ln1, wkPoints ln2, double offset, bool bVert);

	//从db的table中按filter条件获取Geometry和FeatureID
	//【返回】wkGeometry数组
	array getGeometry(wkDb db, string table, string filter);
	array getGeometry(wkDb db, string table, string filter, array &featureIds);
};

// wkClean : 线素整理和构面
class wkClean
{
public:
	int handle();

	//创建线素容器（range为容器空间范围）
	void create(wkBox range);
	//释放创建的线素容器
	void free();

	//向线素容器中添加线
	void addLine(wkParts line);
	void addLine(wkGeometry line);

	//线与容器中的线进行equal op: 1-xor/ 2-or/ 3-diff，结果加入容器
	int equalLine(wkParts line, double eps, int equalOp_1xor_2or_3diff);
	int equalLine(wkGeometry line, double eps, int equalOp_1xor_2or_3diff);

	//线与容器中的线进行xor，结果加入容器
	int xorOverLine(wkParts line, double eps);
	int xorOverLine(wkGeometry line, double eps);
	//线与容器中的线进行or（等价于Clean），结果加入容器
	int orOverLine(wkParts line, double eps);
	int orOverLine(wkGeometry line, double eps);
	//线与容器中的线进行diff，结果加入容器
	int diffOverLine(wkParts line, double eps);
	int diffOverLine(wkGeometry line, double eps);
	//线与容器中的线进行and，结果加入容器
	int andOverLine(wkParts line, double eps);
	int andOverLine(wkGeometry line, double eps);

	//将线素容器中的线构成弧段
	int combineToArc();

	//从线素容器中取第一条弧段（这里得到的parts必须free）
	wkParts getFirstArc();
	//从线素容器中取下一条弧段（若取得的parts为空，则结束）
	wkParts getNextArc();

	//清理线素容器中的超短线
	bool cleanZero(double eps);

	//-------------------------------------------------
	//---------- build 后，下列函数可用 ---------------
	//-------------------------------------------------

	//用线素容器中的线素构面
	bool build(double eps);

	//获取弧段个数
	int getArcCount();
	//获取多边形个数
	int getPolygonCount();

	//获得组成多边形的弧段号at序列（polygonAt从0开始）
	//若，弧段号<0，该弧段在本多边形逆时针；弧段号>0，该弧段在本多边形顺时针
	array getPolygonArcs(int polygonAt);

	//获取多边形（polygonAt从0开始；这里得到的geometry必须free）
	wkGeometry getPolygonAt(int polygonAt);

	//按弧段号获取弧段（arcNo不为0，这里得到的parts必须free），
	wkParts getArcAt(int arcNo);
};

// wkFile : 对 FILE 的操作
class wkFile
{
public:
	int handle();

	//*****************************************************
	//	文本文件的读写操作
	//	【example】:
	//	wkFile file;
	//	if (!file.open("c:\\walk\\readme.txt", "rt")) return;
	//	while(!file.eof())
	//	{
	//		string line=file.gets();
	//		message(line);
	//	}
	//	file.close();
	//*****************************************************
	//按指定方式wcFileMode打开文件fileName
	//	参见 wcToolConstant.h
	bool open(string fileName, string wcFileMode);
	//关闭文件
	void close();
	//是否到文件尾
	bool eof();

	//从文件中获取一行
	string gets();
	//向文件中写一行
	void puts(string str);

	//*****************************************************
	//	ini的读写操作
	//	【example】:
	//	wkFile ini;
	//	ini.iniWrite("mySec", "myKey", "hello", "c:\\walk\\walk.ini");
	//*****************************************************
	//置取INI文件的值
	string iniGet(string section, string key, string defaults, string iniFile);
	void iniWrite(string section, string key, string val, string iniFile);

	//*****************************************************
	//	fileInfo -- 获取文件信息
	//		reference: MFC 的 CFileFind.
	//	【example】:
	//	wkFile find;
	//	bool suc=find.findFile("c:\\walk\\*.mdb");
	//	while(suc)
	//	{
	//		suc=find.findNextFile();
	//		message(find.findFileGet(wcFileName));
	//	}
	//	find.findClose();
	//*****************************************************
	bool findFile(string fileName);
		//fileFind object is constructed and searches a directory for a specified file name
		//fileName: a string containing the name of the file to find. If you pass "" for fileName, FindFile does a wildcard (*.*) search.
		//	if used for file find, this wkFile object is never used for fopen.
		// ** must use findClose() to disconstruct this wkFile object.

	//Continues a file search from a previous call to findFile
	bool findNextFile();

	//must call to close findFile as finished.
	void findClose();

	//getMask: wcFileName-- Gets the name, including the extension, of the found file
 	//	wcFilePath-- Gets the whole path of the found file.
	//	wcFileTitle-- Gets the title of the found file. The title does not include the extension.
	//	wcFileURL-- Gets the URL, including the file path, of the found file.
	//	wcRoot-- Gets the root directory of the found file.
	string findFileGet(int getMask);

	//isMask: IsArchived-- Determines if the found file is archived.
	//	IsCompressed-- Determines if the found file is compressed.
	//	IsDirectory-- Determines if the found file is a directory.
	//	IsDots-- Determines if the name of the found file has the name "." or "..", indicating that is actually a directory.
	//	IsHidden-- Determines if the found file is hidden.
	//	IsNormal-- Determines if the found file is normal (in other words, has no other attributes).
	//	IsReadOnly-- Determines if the found file is read-only.
	//	IsSystem-- Determines if the found file is a system file.
	//	IsTemporary-- Determines if the found file is temporary.
	bool findFileIs(int isMask);

	//	you can use the return value in timeTm(...) to retreive more detail time info.
	//timeMask: wcCreationTime-- Gets the time the file was created.
	//	wcLastAccessTime-- Gets the time that the file was last accessed.
	//	wcLastWriteTime-- Gets the time the file was last changed and saved.
	double findFileTime(int timeMask);
 
	//Gets the length of the found file
	//bM: false-- in bytes.
	//	true-- in million bytes. 2^20. if length<1M, then return 1.
	int findFileLength(bool bM=false);

	//copy file
	bool copyFile(string existingFileName, string newFileName, bool bFailIfExists);
	//delete file
	bool deleteFile(string fileName);

};

// wkRgn : 对实数区域（对应GDI的Region）的操作
class wkRgn
{
public:
	int handle();

	//由几何体创建一个区域
	void create(wkGeometry geom);
	//释放创建的区域
	void free();

	//将几何体按指定方式wcRgnOp加入区域
	//	参见	wcToolConstant.h
	void op(wkGeometry geom, int wcRgnOp);
	//判断点是否可见（是否在区域内）
	bool isPtVisible(wkPoint pt);
	//判断矩形与区域是否有交或重叠
	bool isRectIntersect(wkBox rect);
};

// wkDialog : 对自定义无模态对话框的操作（参见 wcDialogConstant.h）
class wkDialog
{
public:
	int handle();

	//创建无模式交互对话框(目前仅支持系统内置的无模式交互对话框)
	//	对话框的 ok 和 cancel 按钮均可关闭对话框，或：
	//		dlg.show(wdIdDialog, wdSwHide);
	void create(string caption);
	//	wspFile  响应对话框消息处理脚本文件名. 若未指定，则使用当前脚本响应消息
	void create(string caption, string wspFile);

	//设置要响应的消息
	void setAction(int ctrlId, int ctrlMsg);
	void setAction(int mapMsg);

	//响应控件消息和图形主窗口消息action.
	//	ctrlId：发送该消息的控件，若为0，表明为图形主窗口的消息
	int getAction(int &ctrlId);

	//【推荐】以循环等待模式响应控件消息
	//	典型例子：
	//	while(1){
	//		int act=dlg.peekAction(ctrlId);
	//		if (act == -1)//用户直接终止对话框
	//			break;
	//		...
	//	}
	int peekAction(int &ctrlId);

	//由Walk对话框内部句柄构造wkDialog实例
	//	如【通用属性表编辑器】中的“执行脚本”向脚本传递对话框的hWnd
	//	脚本响应方式为：
	//	void main(array args){ wkDialog dlg; dlg.from(atoi(args[0])); ...}
	bool from(int hWnd);

	//显示对话框
	void show(bool bestFit=true);
	//显示或隐藏控件:
	//	若 ctrlId=0（对话框）且wdSw非wdSwShow则关闭对话框
	void show(int ctrlId, int wdSw);

	//添加控件
	//	wdSty 参见 wcDialogConstant.h 的“添加控件时的扩展式样”
	//添加具有文字标题的控件，如静态文字、复选、多选、按钮控件
	int addCtrl(int ctrlId, int wdCtrl_Type, int x, int y, int width, int height,
				int wdSty, string title);
	//添加无标题的控件，如文字编辑、单列表、下拉列表控件
	int addCtrl(int ctrlId, int wdCtrl_Type, int x, int y, int width, int height,
				int wdSty);
	//添加多列列表控件
	int addCtrl(int ctrlId, int wdCtrl_Type, int x, int y, int width, int height,
				int wdSty, int LVS_EX);
	//添加一个静态文字串
	int addCtrl(string text, int x, int y);

	//设置对话框或控件的位置和大小
	void move(int ctrlId, int x, int y, int width, int height);
	//不改变大小，只改变位置
	void move(int ctrlId, int x, int y);

	//在控件上显示图片
	//用法：dlg.setPic(id, "c:\\test.bmp");
	bool setPic(int ctrlId, string picPath);

	//置取对话框控件标题
	string getText(int ctrlId);
	void setText(int ctrlId, string text);

	//置取控件的check状态 for checkButton, radioButton
	int getCheck(int ctrlId);
	int setCheck(int ctrlId, int check);

	//获取控件信息
	//	参见 wcDialogConstant.h 的 wdMask
	int getInfo(int ctrlId, int mask);


	//=====================================================
	// 多行控件：listBox, comboBox, listCtrl
	//=====================================================

	//置取指定行的文字串
	string getText(int ctrlId, int item);
	void setText(int ctrlId, int item, string text);

	//清除所有行
	void clear(int ctrlId);

	//获取行数
	int  count(int ctrlId);

	//置取当前选中行
	int  getCurSel(int ctrlId);
	void setCurSel(int ctrlId, int item);

	//置取指定行是否选中
	bool getSel(int ctrlId, int item);
	void setSel(int ctrlId, int item, bool bSelected);

	//置取指定行的数据
	int getData(int ctrlId, int item);
	int setData(int ctrlId, int item, int data);

	//增删指定行
	int insertItem(int ctrlId, int item, string text);
	int deleteItem(int ctrlId, int item);

	//=====================================================
	// 表控件：listCtrl
	//=====================================================

	//置取指定行的check状态
	bool getCheck(int ctrlId, int item);
	void setCheck(int ctrlId, int item, bool check);

	//增删列（LVCFMT 参见 wcDialogConstant.h）
	int  insertColumn(int ctrlId, int column, string colName, int LVCFMT, int width);
	bool deleteColumn(int ctrlId, int column);

	//置取指定行指定列的文字串
	//	若 item=-1, 则取相应列的标题文字串
	string getItemText(int ctrlId, int item, int subItem);
	bool setItemText(int ctrlId, int item, int subItem, string text);
};

// wkTrans : 对坐标变换的操作
class wkTrans
{
public:
	//----------------------------------------------------------
	//经纬度与高斯平面直角坐标的变换
	//----------------------------------------------------------
	/*
	例子：将中国区某地含带号的层的54高斯坐标转换为经纬度
		wkTrans trans;
		double oriCL, offE, offN=0;
		//获取中央子午线和中央子午线的高斯坐标
		trans.gaosi2Jwd(layer.getFeatureAt(0).getGeometry().centroid().x, oriCL, offE);
		trans.gaosi2Jwd(layer, oriCL, offE, offN);
	*/
	//b54: true为北京54坐标系，false为西安80坐标系
	//oriCL: 高斯投影带中央子午线，以度为单位
	//经纬度坐标以度为单位（下同），高斯坐标以中央子午线为纵轴，赤道为横轴
	wkPoint gaosi2Jwd(wkPoint gaosiPt, int b54, double oriCL);
	wkPoint jwd2Gaosi(wkPoint jwdPt, int b54, double oriCL);

	//由含代号的高斯横坐标gaosiE推算中央子午线和横轴偏移量（高斯纵轴距中央子午线的距离）
	//返回值无意义。
	// 如，由geometry计算： gaosi2Jwd(geom.centroid().x, oriCL, offE);
	//	然后做变换：	gaosi2Jwd(geom, b54, oriCL, offE, 0);
	wkPoint gaosi2Jwd(double gaosiE, double &oriCL, double &offE);

	//返回值无意义。offN, offE: 赤道和中央子午线的高斯坐标
	wkPoint gaosi2Jwd(wkGeometry geom, int b54, double oriCL, double offE, double offN);
	wkPoint gaosi2Jwd(wkAnnotation ann, int b54, double oriCL, double offE, double offN);
	//返回值无意义。offN, offE: 赤道和中央子午线的高斯坐标
	wkPoint jwd2Gaosi(wkGeometry geom, int b54, double oriCL, double offE, double offN);
	wkPoint jwd2Gaosi(wkAnnotation ann, int b54, double oriCL, double offE, double offN);

	//返回值无意义。offN, offE: 赤道和中央子午线的高斯坐标
	//变换后，自动重建索引
	wkPoint gaosi2Jwd(wkLayer layer, int b54, double oriCL, double offE, double offN);
	//返回值无意义。offN, offE: 赤道和中央子午线的高斯坐标
	//变换后，自动重建索引
	wkPoint jwd2Gaosi(wkPoint layer, int b54, double oriCL, double offE, double offN);


	int handle();//仅对 trans 和 project 以及 3D 有效

	//----------------------------------------------------------
	//根据两个坐标系的一组同名点坐标进行两个坐标系间的坐标转换
	//	trans
	//----------------------------------------------------------

	//根据两坐标系同名点集xPoints和uPoints创建转换模型
	// wcTrans	配准模型号, 参见 wcToolConstant.h
	bool transCreate(array xPoints, array uPoints, int wcTrans);
	bool transCreate(string fromWtsFile);
	//释放创建的转换模型
	void transFree();

	//按转换模型进行坐标转换
	void trans(wkPoint aPoint);
	void trans(wkGeometry geom);
	void trans(wkAnnotation ann);
	void trans(wkLayer layer);

	//获取转换模型信息
	array transInfo(int mask);
	//保存转换模型
	bool transSave(string toWtsFile);

	//----------------------------------------------
	//地图投影容器
	// project
	//----------------------------------------------
	/*
	例子：将layer层变换到亚尔伯斯等积圆锥投影（Albers），
		投影中心东经108度，切割纬度25和45度
		wkTrans layerTrans;
		layerTrans.projectCreate(layer);
		wkTrans toTrans;
		toTrans.projectCreate("+proj=aea +lat_1=25 +lat_2=45 +lon_0=108 +ellps=WGS84");
		layerTrans.project(layer, toTrans);
		layerTrans.projectFree();
		geosetTrans.projectFree();
	*/

	//创建地图投影容器
	//	fromProj4 -- 地图投影，遵守 http://trac.osgeo.org/proj/ 中的投影约定。
	bool projectCreate(string fromProj4);
	//由层的坐标系创建地图投影容器
	bool projectCreate(wkLayer fromLayer);
	//由工作空间的当前坐标系创建地图投影容器
	bool projectCreate(wkGeoset fromGeoset);
	//由另一个地图投影创建地图投影容器
	bool projectCreate(wkTrans fromTrans);
	// 由设置对话框创建地图投影容器
	bool projectCreate();

	//释放创建的地图投影容器
	void projectFree();

	//对点/矩形盒/几何体/文字定位/层从本坐标系投影到它坐标系toPJ
	//	若不指定toPj，取geoset的坐标系为目标坐标系
	bool project(wkPoint pt);
	bool project(wkPoint pt, wkTrans toPj);
	bool project(wkBox bx);
	bool project(wkBox bx, wkTrans toPj);
	bool project(wkGeometry geom);
	bool project(wkGeometry geom, wkTrans toPj);
	bool project(wkAnnotation ann);
	bool project(wkAnnotation ann, wkTrans toPj);
	bool project(wkLayer layer);
	bool project(wkLayer layer, wkTrans toPj);
	//将Geoset投影到新坐标系（并将newPj作为Geoset的坐标系）：
	//	所有层重新投影，并归化层的zoomMax/Min到新的Geoset坐标单位上
	bool project(wkGeoset geoset, wkTrans newPj);

	//获取地图投影定义串，参见 http://trac.osgeo.org/proj/
	string projectGet();
	// 获取详细参数：0--proj4, 1--unit, 2--type, 3--取得具有相同大地基准的LatLong（经纬度）投影定义串
	string projectGet(int wcWhich);

	//将本投影容器设置到层中
	bool projectSet(wkLayer toLayer);
	//将本投影容器设置到Geoset中
	bool projectSet(wkGeoset toGeoset);
	//将本投影容器设置到库walklayers表的层中
	bool projectSet(string layerName, wkDb db);
	//将本投影容器的详细参数
	bool projectSet(string param, int wcWhich);
	//据geoset的新旧坐标单位(7--米, 13--度)重新设置层的zoomMax/min
	bool projectSet(int oldGeosetUnit, int newGeosetUnit, wkLayer layer);

	//------------------------------
	// 日照和3D
	//------------------------------
	bool view3DCreate();
	
	void view3DFree();
	
	void view3DAdd(wkGeometry& geom, double height=0);
	
	void view3DSetSun(double height,double azimuth=0);

	bool view3DGet3D(int buildId, array geomArray);
	bool view3DGet3D(array arrayOfGeomArray); /* CArray<CGM_ObjectArray*,CGM_ObjectArray*> &arr */

	bool view3DGetShade(int buildId, array geomArray);
	bool view3DGetShade(array arrayOfGeomArray);

	bool view3DGetLight(int buildId, array geomArray);
	bool view3DGetLight(array &arr);
	
	void view3DSetPerspectiveView(double height, double azimuth, double distance);
	void view3DSetPerspectiveView(double height, double azimuth, wkPoint &centerPoint, double distance);
	void view3DSetPerspectiveView(wkPoint &eyePoint, wkPoint &targetPoint, wkPoint &topPoint, double eyeDistance);
	
	void view3DSetOrthographicView(double height,double azimuth);
	void view3DSetOrthographicView(wkPoint &eyePoint, wkPoint &targetPoint, wkPoint &topPoint);
	
	bool view3DGetProject(bool isContainShade, array& geomArray, array& info);
	
	bool view3DTestSunPt(wkPoint &pt, bool &isVisible);
	bool view3DTestSunPts(array& ptArr, array &res);

	bool view3DTestViewPt(wkPoint &pt, bool &isVisible);
	bool view3DTestViewPts(array &ptArr, array &res);
	
	bool view3DTestSunLn(wkPoint &p1, wkPoint &p2, array& pointArr);
	bool view3DTestViewLn(wkPoint &p1, wkPoint &p2, array& pointArr);
	
	void view3DGetAngles(int year,int month,int day,int hour,int minute,int second,
			 			  double longitude,double latitude,double &height,double &azimuth);
	
	//orthographic (正视): 0, perspectiv (透视): 1
	void view3DProjection(wkPoint p, int orthographic_perspectiv);  
	void view3DProjection(wkGeometry geom, int orthographic_perspectiv);
	//geomArr: Point array or geometry array;
	void view3DProjection(array geomArr, int orthographic_perspectiv);
	

	//////////////////////////////////////////////////////////////////////////
};

#endif //__WKCLASSDEFINE_H_

////////////////////////// define end ///////////////////////////////
/////////////////////////////////////////////////////////////////////

