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.
ManuEce said: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.
MASTERFILE
mdlModelRef_getActive()
ACTIVEMODEL
ElementHandle
EditElementHandle
The MicroStationAPI provides class ChainHeaderHandler and its sub-class ComplexStringHandler. The C++ way to construct a chain is...
ChainHeaderHandler
ComplexStringHandler
CreateChainHeaderElement
AddComponentElement
IsValidChainComponentType
AddComponentComplete
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.
ManuEce said:It mostly fails at "IsValidChainComponentType"
That method returns a bool, not a StatusInt. Try this...
bool
StatusInt
if (ComplexShapeHandler::IsValidChainComponentType(childEeh))
SUCCESS is defined to be zero, interpreted by C++ as false, so you're in fact accepting bad elements.
SUCCESS
false
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".
ManuEce said: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?
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
ManuEce said: fence is created from cell "MMS10"
How does that happen? Cell MMS10 is a collection of open lines and arcs, not a closed shape.
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"
ManuEce said:mdlElmdscr_duplicate (&outEdP, eehComplex.GetElementDescrP())
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.
eehComplex
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.
duplicate
MSElementDescr
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!