MSCE开发中请尽量避免使用文件位置(FilePos)


如果您写过MDL程序的话,应该听说甚或使用过文件位置(File Position)这个重要概念。比如如下大量的MDL C函数都需要用到这个参数:

UInt32  mdlElement_getFilePos (int type, DgnModelRefP *pModelRef);
UInt32  mdlElement_getHeaderFilePos (UInt32 filePos, DgnModelRefP modelRef);
int  mdlElement_read (MSElementP pElement, DgnModelRefP modelRef, UInt32 filepos);
UInt32  mdlElement_rewrite (MSElementP newElem, MSElementP oldElem, UInt32 filePos);
UInt32  mdlElmdscr_read (MSElementDescrH elemDescrPP, UInt32 filePos, DgnModelRefP modelRef, int expandSharedCells, UInt32 *readFilePos);
UInt32  mdlElmdscr_readToMaster (MSElementDescrH elemDescrPP, UInt32 filePos, DgnModelRefP modelRef, int expandSharedCells, UInt32 *startFilePos);
UInt32  mdlElmdscr_rewrite (MSElementDescrP newElemDscr, MSElementDescrP oldElemDscr, UInt32 filePos);

文件位置是DGN文件中元素(Element)的一个属性,这个概念从V7DGN到V8DGN发生了根本性的变化,从V8i到CE又发生了一次变化。如果您的老代码是基于这个概念开发的,那升级起来会带来许多问题。

在V7DGN(即软件版本MicroStation 7.1以及之前的非常老旧的那些版本)时代,文件位置确实表示一个元素在DGN文件中的物理位置,文件开头位置为0,如果第一个元素有1K大小的话,则第二个元素的文件位置就是1K(由于第一个元素是从0开始计数的,所以第二个元素的位置是1K而非1K+1),以此类推。

到了V8DGN(即软件版本MicroStation V8开始直到今天的MSCE各版本)时代,DGN文件的格式被重新定义。文件位置仅仅表示一个元素在DGN文件中的位置索引,一般的图形元素从4000000开始计数,下一个元素的文件位置为4000001。从MSV8.0(即08.00.xx.xx)到MSV8i(即08.11.xx.xx)各版本中文件位置都能直接在元素属性对话框中显示出来,如下图是在MSV8i中查得的一个元素的文件位置属性:

从上图可以看出,一个复杂元素(此处为一个复杂形元素)的复杂头拥有一个独立的文件位置4001070,其下的三条线元素也都拥有单独的文件位置,它们分别是4001071、4001072、4001073。

但是,用MSCE打开这个DGN文件的话,我们无法从属性对话框中看到这个File Position属性了。用老式的键入命令Analyze Element在MSCE中分析这个复杂形元素的话,得到如下图所示结果:

我们不难发现,在MSCE中的元素虽然还有这个文件位置属性,但对于复杂元素来说,复杂头元素及其所有的子元素都拥有相同的一个文件位置值。如果你的旧代码是基于文件位置在读复杂元素中的子元素的话,那这样的代码在MSCE下必然出错。我改写了如下四个函数(fooElement_read、fooElement_rewrite、fooElmdscr_read、fooElmdscr_rewrite)帮助您升级V8i之前的旧代码到MSCE新代码。

//MSCE filePos concept changed dramatically, a complex element header and all its components share a same filePos,
//So read element from a filePos+offset doesn't work anymore.
struct MyStruct
{
	UInt32          offset;
	MSElementP      pEl;
	MSElementDescrP pEd;
};
int	traverseFunc(MSElementP pEl, void *params, int	Operation, UInt32 offset, MSElementDescrP pEd)
{
	MyStruct* pMyData = (MyStruct*)params;
	if (pMyData->offset == offset)
	{
		pMyData->pEl = pEl;
		pMyData->pEd = pEd;
		return !SUCCESS;
	}
	return SUCCESS;
}
void fooElement_read (MSElementP pEl, DgnModelRefP modelRef, UInt32 filePos, UInt32 offset)
{
	if (0 == offset)
	{
		mdlElement_read(pEl, modelRef, filePos);
		return;
	}
	MyStruct myData;
	MSElementDescrP edP = NULL;
	mdlElmdscr_read(&edP, filePos, modelRef, FALSE, NULL);
	myData.offset = offset;
	mdlElmdscr_operation(edP, traverseFunc, &myData, ELMD_ALL_ONCE);
	mdlElement_memcpy(pEl, myData.pEl);
	mdlElmdscr_freeAll(&edP);
}
void fooElmdscr_read(MSElementDescrH edPP, UInt32 filePos, UInt32 offset, DgnModelRefP modelRef, int expandSC, UInt32* readFilePos)
{
	if (0 == offset)
	{
		mdlElmdscr_read(edPP, filePos, modelRef, expandSC, readFilePos);
		return;
	}
	MyStruct myData;
	MSElementDescrP edP = NULL;
	mdlElmdscr_read(&edP, filePos, modelRef, expandSC, readFilePos);
	myData.offset = offset;
	mdlElmdscr_operation(edP, traverseFunc, &myData, ELMD_ALL_ONCE);
	mdlElmdscr_duplicateSingleEx(edPP, myData.pEd, true, true);
	mdlElmdscr_freeAll(&edP);
}
int	rewriteElementFunc(MSElementP pEl, void *params, int Operation, UInt32 offset, MSElementDescrP pEd)
{
	MyStruct* pMyData = (MyStruct*)params;
	if (pMyData->offset == offset)
	{
		mdlElmdscr_replaceElement(&pEd, pMyData->pEl);
		return !SUCCESS;
	}
	return SUCCESS;
}
void fooElement_rewrite(MSElementP newElP, MSElementP oldElP, UInt32 filePos, UInt32 offset)
{
	if (0 == offset)
	{
		mdlElement_rewrite(newElP, oldElP, filePos);
		return;
	}
	MyStruct myData;
	MSElementDescrP edP = NULL;
	mdlElmdscr_read(&edP, filePos, ACTIVEMODEL, FALSE, NULL);
	myData.offset = offset;
	myData.pEl = newElP;
	mdlElmdscr_operation(edP, rewriteElementFunc, &myData, ELMD_ALL_ONCE);
	mdlElmdscr_rewrite(edP, NULL, filePos);
	mdlElmdscr_freeAll(&edP);
}
int	rewriteElmdscrFunc(MSElementP pEl, void *params, int Operation, UInt32 offset, MSElementDescrP pEd)
{
	MyStruct* pMyData = (MyStruct*)params;
	if (pMyData->offset == offset)
	{
		mdlElmdscr_replaceDscr(&pEd, pMyData->pEd);
		return !SUCCESS;
	}
	return SUCCESS;
}
void fooElmdscr_rewrite(MSElementDescrP newEdP, MSElementDescrP oldEdP, UInt32 filePos, UInt32 offset)
{
	if (0 == offset)
	{
		mdlElmdscr_rewrite(newEdP, oldEdP, filePos);
		return;
	}
	MyStruct myData;
	MSElementDescrP edP = NULL;
	mdlElmdscr_read(&edP, filePos, ACTIVEMODEL, FALSE, NULL);
	myData.offset = offset;
	myData.pEd = newEdP;
	mdlElmdscr_operation(edP, rewriteElmdscrFunc, &myData, ELMD_ALL_ONCE);
	mdlElmdscr_rewrite(edP, NULL, filePos);
	mdlElmdscr_freeAll(&edP);
}

有关MicroStation软件的版本信息,请看如下文章:

MicroStation版本信息