[C++\C# MSCE] 获得隔离集所有元素

符老师  ,如何获得隔离集里面所有元素(这些元素不一定选中,SelectionSetManager这个不能用)   求符老师指导

Parents
  • 可以调用mdlScanCritera_xxx这套函数来扫描。其中有mdlScanCritera_setDisplaySetTest (pScanCriteria, true)来控制对显示集里面的元素的过滤。



  • 顺便问一下符老师      如何判断view存不存在隔离集?

  • 您可以试试这个函数elementRef_isInDisplaySet

  • scanCriteria调用方法不对。你仅创建了scanCriteria并设置了扫描条件,但没有调用关键的mdlScanCriteria_scan函数来启动扫描呀。给你一个我以前写的可以正常工作的调用方法供参考:

    int scanCallback(ElementRefP elRef, void* arg, ScanCriteriaP pSC)
    {
    	ElementAgendaP agdP = reinterpret_cast<ElementAgendaP>(arg);
    	agdP->Insert(elRef, pSC->GetModelRef());
    
    	return SUCCESS;
    }
    void scanDemo()
    {
    	ElementAgenda       eleList;
        ScanCriteriaP       pScanCriteria = ScanCriteria::Create();
        //pScanCriteria->SetDrawnElements();
        pScanCriteria->SetModelRef(ACTIVEMODEL);
    	pScanCriteria->AddSingleElementTypeTest(2); 
    	pScanCriteria->AddSingleElementTypeTest(106);  // 106 = Extended Element
    	//pScanCriteria->AddSingleElementTypeTest(MSElementTypes::LINE_ELM);
    	//pScanCriteria->AddSingleElementTypeTest(MSElementTypes::LINE_STRING_ELM);
    	//pScanCriteria->SetReturnType (MSSCANCRIT_ITERATE_ELMREF, FALSE, FALSE);
        mdlScanCriteria_setReturnType(pScanCriteria, MSSCANCRIT_ITERATE_ELMREF, FALSE, FALSE);
        pScanCriteria->SetElemRefCallback((PFScanElemRefCallback)scanCallback, &eleList);
        pScanCriteria->Scan();
        ScanCriteria::Delete(pScanCriteria);
    	WPrintfString wStr(L"agenda size = %d", (int)eleList.size());
    	mdlDialog_dmsgsPrint(wStr);
    	WString myString, elDescr;
    	for (ElementHandle eh : eleList)
    	{
    		eh.GetHandler().GetDescription(eh, elDescr, 100);
    		myString.Sprintf(L"ElemType = %s(%d), ElementId=%d",
    			elDescr.GetWCharCP(), eh.GetElementType(), eh.GetElementId());
    		mdlDialog_dmsgsPrint(myString.GetWCharCP());
    	}
    }

    我是在尽量调用面向对象的方法,你可以都改成函数调用形式,其实都是一样的。对象方式下好像没有与DisplaySet相关的函数。



    Answer Verified By: Andy 

  • 符老师   我测试过了  mdlScanCritera_setDisplaySetTest就是不会进   设置元素类型  我这也会进    ,是不是还要设置   view之类的呢?   还有model?以及  是否包含 参考的model(因为我的在参考model中)?

  • 如果含有参考模型中的元素,则需要逐个模型(model)去Scan,因为这个ScanCriteria每次只能扫描一个模型(model)。你需要先获得当前模型下的所有模型,然后对每个模型调用一次这个Scan,在每次调用时通过setModel去改变模型,其他条件保持不变。



  • 不行   符老师   当前model隔离也不行   感觉这个mdlScanCritera_setDisplaySetTest  冇 用 ..... 

Reply Children
  • 我测试怎么是正确的呢?本来我的模型中有如下四个Shape元素:

    在我不调用mdlScanCriteria_setDisplaySetTest(scP, true);时,扫描出来的就是这四个元素。

    执行DisplaySet过滤后效果如下,扫描出来的也就是这两个元素。

    测试代码如下:

    int OnScanCallback(ElementRefP elmRef, CallbackArgP callbackArg, ScanCriteriaP scP)
    {
    	WPrintfString wStr(L"id:%d, type:%d\n", elmRef->GetElementId(), elmRef->GetElementType());
    	mdlDialog_dmsgsPrint(wStr);
    	return SUCCESS;
    }
    void userScanFunc()
    {
    	ScanCriteriaP scP = mdlScanCriteria_create();
    	mdlScanCriteria_setModel(scP, ACTIVEMODEL);
    	mdlScanCriteria_setDrawnElements(scP);
    	mdlScanCriteria_setDisplaySetTest(scP, true);
    	mdlScanCriteria_setElementTypeTest(scP, NULL, 0);
    	mdlScanCriteria_addSingleElementTypeTest(scP, SHAPE_ELM);
    	mdlScanCriteria_setReturnType(scP, MSSCANCRIT_ITERATE_ELMREF, 0, 0);
    	mdlScanCriteria_setElemRefCallback(scP, (PFScanElemRefCallback)OnScanCallback, NULL);
    	mdlScanCriteria_scan(scP, NULL, NULL, NULL);
    	mdlScanCriteria_free(scP);
    }

    我推测是否你的DGN文件是ORD操作过的,我发现ORD软件会在一个DGN的字典模型(Dictionary Model)中写入很多图形元素,从而将MS的工作机制打乱。不知是有意为之而是没有深入了解DGN的结果造成的结果。



    Answer Verified By: Andy 

  • DGN是ORD新建的    不是都是在ms基础上做的.....这还能影响么?

  • 是的。这也是我最近发现的问题。ORD软件错误地使用了字典模型,将许多图形元素都放入了字典模型中。在ScanCritiera中无论用setModel设置到哪个具体的图形模型,字典模型中的元素都会被扫描出来的。



  • Andy,你好!

    我又让我们公司专门负责ORD产品的工程师帮我创建了一个ORD的DGN,发现在其字典模型中并没有普通的几何元素。但我手头有其他单位用户提供的ORD的DGN确实发现了这种怪异情况。不知道您的DGN是否正常?

    你可以在你的DGN中执行如下函数,查看列出的结果中是否有平普通的图形元素,比如Type为6的Shape等。

    void fileAnalyze(WCharCP unparsed)
        {
        DgnFileP pDgnFile = ISessionMgr::GetActiveDgnFile();
    
        //Only ControlElements in DictionaryModel
        DgnModelR dictionaryModel = pDgnFile->GetDictionaryModel();
        UInt32 nCntAll = dictionaryModel.GetElementCount(DgnModelSections::All);
        UInt32 nCntDic = dictionaryModel.GetElementCount(DgnModelSections::Dictionary);
        UInt32 nCntMod = dictionaryModel.GetElementCount(DgnModelSections::Model);
        UInt32 nCntCtrl = dictionaryModel.GetElementCount(DgnModelSections::ControlElements);
        UInt32 nCntGrp = dictionaryModel.GetElementCount(DgnModelSections::GraphicElements);
        WString myString, elDescr;
        myString.Sprintf(L"DictionaryModel: nCntAll=%d, nCntDic=%d, nCntMod=%d, nCtrl=%d, nCntGrp=%d", nCntAll, nCntDic, nCntMod, nCntCtrl, nCntGrp);
        mdlDialog_dmsgsPrint(myString.GetWCharCP());
    
    	int cnt = 0;
        PersistentElementRefList *pElemRefList = dictionaryModel.GetControlElementsP();
        for (PersistentElementRefP const& elemRef : *pElemRefList)
            {
            ElementHandle eh(elemRef);
            eh.GetHandler().GetDescription(eh, elDescr, 100);
            myString.Sprintf(L"ElemType = %s(%d), ElementId=%d", 
                elDescr.GetWCharCP(), elemRef->GetElementType(), elemRef->GetElementId());
            mdlDialog_dmsgsPrint(myString.GetWCharCP());
    		if (cnt++ > 300)
    			break;
            }
        }
    



    Answer Verified By: Andy 

  • 我新建了一个可以的  用这个代码可以