I want to "fence clip" elements. My tool implements OnElementModifyClip() as follows:
virtual StatusInt FenceTool::OnElementModifyClip (EditElemHandleR el, FenceParamsP fp, FenceClipFlags options) override { MSElementDescr *originalEdP=el.ExtractElemDescr(); ClipDescrP clipDescrP=NULL; mdlClip_getFence( &clipDescrP ); MSElementDescr *insideEdP=NULL, *outsideEdP=NULL; mdlClip_element( &insideEdP, &outsideEdP, el.GetElemDescrP(), ACTIVEMODEL, clipDescrP, tcb->lstvw ); el.SetElemDescr( insideEdP, true, false ); mdlElmdscr_freeAll ( &outsideEdP ); mdlClip_free( &clipDescrP ); return true; }
I have verified that the extracted EditElemHandle is "clipped" (I changed the weight on insideEdP and added it to the file). However, I'm not sure that I'm correctly passing the clipped element back out. OnElementModifyClip() is called for each element in the fence, but once all elements are processed and BEFORE OnElementModify() is called, MIcroStation crashes.
Unknown said:MSElementDescr *originalEdP=el.ExtractElemDescr();
From MicroStationAPI help: Extract and take ownership of the MSElementDescr associated with this EditElemHandle
Unknown said:mdlClip_element (&insideEdP, &outsideEdP, el.GetElemDescrP(), ...)
Is that EditElemHandle still valid? Why not use the originalEdP you just extracted?
Unknown said:el.SetElemDescr( insideEdP, true, false );
Now you've reassigned that EditElemHandle.
Unknown said:return true;
Regards, Jon Summers LA Solutions
Well darn... I missed the incorrect function definition for OnElementModifyClip(). I'll fix that.
Well - I still get an ugly crash. I perform the clipping in OnElementModifyClip(), but I'm not sure how to update/replace the incomming EditElemHandle with the one or two new MSElementDescr's from mdlClip_element(). Also, since the clip was done explicitedly (mdlClip_element), should one call __super::OnElementModifyClip()?
I don't know why you are overriding this method, the base class implementation handles doing the clipping and you will get the clip output in OnElementModify.
The code you've shown isn't going to handle the various fence modes correctly, or even just the case where the clip of a single element results in disjoint geometry (it is invalid to call SetElemDescr with an edP chain...code that takes an ElemHandle does not follow next pointers!)
If you remove your override of OnElementModifyClip what doesn't work?
-B * I feel like we've had this conversation before?!?
I start with a long narrow shape and a fence set for "clip":
And I have OnPostInstall() setting element source to SOURCE_Fence. WantDynamics() returns false. NeedAcceptPoint() returns false also. OnElementModify() simply increases the weight of the element passed in, and return SUCCESS. I don't get any clipping:
When I use MicroStation Change Attributes to do the same thing, I get:
Here is the code:
struct FenceTestTool : MstnElementSetTool { private: public: FenceTestTool::FenceTestTool(int cmdNumber, int cmdName, int cmdPrompt) { SetCmdNumber( cmdNumber ); SetCmdName( cmdName, cmdPrompt ); } /*---------------------------------------------------------------------------------**//** +---------------+---------------+---------------+---------------+---------------+------*/ virtual StatusInt FenceTestTool::OnElementModify (EditElemHandleR elHandle) override { printf("ID=%ld\n", elHandle.GetElemRef()->GetElemID() ); UInt32 color=2, weight=9; mdlElement_setSymbology( elHandle.GetElementP(), NULL, &weight, NULL ); return SUCCESS; } /*---------------------------------------------------------------------------------**//** +---------------+---------------+---------------+---------------+---------------+------*/ virtual bool FenceTestTool::NeedAcceptPoint ( ) override { switch ( GetElemSource() ) { case SOURCE_Fence: case SOURCE_SelectionSet: return false; default: return true; } return false; } virtual bool FenceTestTool::WantDynamics () override { return false; } /*---------------------------------------------------------------------------------**//** +---------------+---------------+---------------+---------------+---------------+------*/ virtual void FenceTestTool::OnRestartCommand () override { // Must restart or call ExitTool! FenceTestTool* newTool = new FenceTestTool ( GetCmdNumber(), GetCmdName(), GetCmdPrompt() ); newTool->InstallTool (); } /*---------------------------------------------------------------------------------**//** +---------------+---------------+---------------+---------------+---------------+------*/ virtual void FenceTestTool::OnPostInstall () override { SetElemSource (SOURCE_Fence); __super::OnPostInstall(); } }; // end of FenceTestTool
Okay, I think I know what the missing piece is now, add the following if you want the same clip behavior as the change attributes tool. virtual ClipResult GetFenceClipResult () override {return CLIP_RESULT_NewElements;}
Also, take out your printf, it's going to crash de-referencing a null ElementRef (the clipped geometry isn't persistent).
HTH
-B
Answer Verified By: Bruce Reeves SRNS