[CONNECT C++] mdlElmdscr_addToChain losing contents?

Can somebody help me with this?

I got function that works on V8i that loops Bolts contents and clips them if they are inside fence.  

(I've cleaned the code a bit to have only the parts I am confused with.)

MSElementDescr *edP;
MSElementDescr *pComponent = boltDscr->h.firstElem;
while (NULL != pComponent)
{
	mdlElmdscr_new (&edP, NULL, &pComponent->el);
	edP->el.ehdr.complex = 0;
	edP->h.dgnModelRef = MASTERFILE;
	
	if (outEdP == NULL)
		mdlElmdscr_duplicate(&outEdP,  edP);
	else
		mdlElmdscr_addToChain (outEdP, edP);

	pComponent = pComponent->h.next;
}

The problem with the above on is that when I add the Descr to dgn, nothing related to bolt shows on the dgn(it's not NULL). But if I just write it to the dgn as it is, it works just fine (without the function that loops).

V8i code didnt have "edP->h.dgnModelRef = MASTERFILE;", but without it, it will just crash.

  • V8i code didnt have "edP->h.dgnModelRef = MASTERFILE;", but without it, it will just crash

    You were fortunate.  An element descriptor having a NULL model reference is normally invalid, unless you have just created that descriptor and not yet added it to a DGN model.

    MASTERFILE is a poor choice of name for that macro, because it expands to mdlModelRef_getActive(). Macro ACTIVEMODEL is a better choice because it's semantically accurate.  Both macros are there to make it easier to port legacy code to V8 from V7 when writing MDL.  With CONNECT, you should consider moving your code from element descriptors to C++ ElementHandle and EditElementHandle.

    MicroStationAPI ComplexStringHandler

    The MicroStationAPI provides class ChainHeaderHandler and its sub-class ComplexStringHandler.  The C++ way to construct a chain is...

    1. Call CreateChainHeaderElement to create your header
    2. Call AddComponentElement repeatedly to add components to the chain
      • You should test the proposed component using IsValidChainComponentType
    3. Call AddComponentComplete to finish the chain

    In my experience, the CONNECT classes work well.  Some MDL functions seem to have residual bugs when development work moved to C++ and MDL fell into disuse.

     
    Regards, Jon Summers
    LA Solutions

    Answer Verified By: ManuEce 

  • Thanks for the answer, I tried it with your tips, but I most likely did something wrong... 

    DgnModelRefP modelRef = ISessionMgr::GetActiveDgnModelP();
    EditElementHandle eehComplex;
    ComplexShapeHandler::CreateChainHeaderElement(eehComplex, NULL, true, modelRef->Is3d(), *modelRef);
    	
    const bool Owner = true;
    const bool IsUnmodified = true;
    
    DgnPlatform::EditElementHandle eeh(boltDscr, !Owner, IsUnmodified);
    if (eeh.IsValid())
    {
    	eeh.SetModelRef(ACTIVEMODEL);
    	
    	for (ChildEditElemIter childEeh (eeh); childEeh.IsValid (); childEeh = childEeh.ToNext ())
    	{
    		if(childEeh.IsValid())
    		{
    			if (SUCCESS == ComplexShapeHandler::IsValidChainComponentType(childEeh))
    			{
    				if (SUCCESS == ComplexShapeHandler::AddComponentElement(eehComplex, childEeh))
    				{
    					mdlOutput_message(L"addComponent: success");
    				}
    			}
    		}
    	}
    	
    	if(SUCCESS == ComplexShapeHandler::AddComponentComplete(eehComplex)) 
    	{
    		mdlElmdscr_duplicate (&outEdP, eehComplex.GetElementDescrP());
    	}
    
    }

    It mostly fails at "IsValidChainComponentType" and once at "AddComponentElement", but never once did it succeed.

  • It mostly fails at "IsValidChainComponentType"

    That method returns a bool, not a StatusInt.  Try this...

    if (ComplexShapeHandler::IsValidChainComponentType(childEeh))

    SUCCESS is defined to be zero, interpreted by C++ as false, so you're in fact accepting bad elements.

     
    Regards, Jon Summers
    LA Solutions

  • Ah... just assumed that it would be statusint as well as the other ones returns it... Didn't help with the problem thou.

    Now it just crashes microstation at "AddComponentElement", "Internal error: Access Violation".

  • Now it just crashes microstation at "AddComponentElement", "Internal error: Access Violation".

    What is the element it is attempting to add when that violation occurs?

    Can you share the DGN file that includes the bolt model?

     
    Regards, Jon Summers
    LA Solutions

  • Bolt contains 2 Cells("C10_60" is the correct one that is sent to function mentioned contains: Lines, Arcs, Shape, Line String). 

    Basically what the function did in V8i was to clip that shape element (all that was left outside fence, fence is created from cell "MMS10".  (afterwards added all the elements back with addToChain)

    Cellname: "C10_60"

    bolt_test.dgn

  • fence is created from cell "MMS10"

    How does that happen?  Cell MMS10 is a collection of open lines and arcs, not a closed shape.

     
    Regards, Jon Summers
    LA Solutions

  • It's custom function that reads from the cells descr and creates shape based on it and then just calls mdlFence_fromShape. But that doesn't really matter yet as I haven't included that part onto the current code yet, as the current code just crashes when it comes to "AddComponentElement"

  • mdlElmdscr_duplicate (&outEdP, eehComplex.GetElementDescrP())

    It's possible that eehComplex doesn't yet own a descriptor: Use PeekElementDescrCP to see whether this EditElementHandle already has an MSElementDescr.

    You may prefer to use the EditElementHandle copy constructor...

       const bool DuplicateDescr {true};
       EditElementHandle duplicate (eehComplex, DuplicateDescr); 
    

    Now duplicate is taking care of memory management for you, so you don't have to free the MSElementDescr.

     
    Regards, Jon Summers
    LA Solutions

  • I got it to work now, I had to re create the cell and add that first before the other elements.

    Thanks for all the helpful tips!