[V8i C++] MstnElementSetTool and OnElementModifyClip() implmentation

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.

Parents
  • 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;

    1. Your function is declared to return a StatusInt, not a boolStatusInt SUCCESS == 0; bool true != 0
    2. You are in control of originalEdP, but you haven't freed it.

     
    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
  • Maybe try removing your override of OnPostInstall and just add the following instead:

    virtual UsesFence AllowFence () override {return USES_FENCE_Required;}

    Not sure why calling SetElemSource where you did in OnPostInstall wouldn't work...but it's not what tools like change attributes do, they override AllowFence.

    * Return USES_FENCE_Check if you still want your tool to use a selection set or pick if there isn't a fence active.

    If the above doesn't help, try removing the override of NeedAcceptPoint too (i.e. make tool as simple as possible).

    -B



Reply
  • Maybe try removing your override of OnPostInstall and just add the following instead:

    virtual UsesFence AllowFence () override {return USES_FENCE_Required;}

    Not sure why calling SetElemSource where you did in OnPostInstall wouldn't work...but it's not what tools like change attributes do, they override AllowFence.

    * Return USES_FENCE_Check if you still want your tool to use a selection set or pick if there isn't a fence active.

    If the above doesn't help, try removing the override of NeedAcceptPoint too (i.e. make tool as simple as possible).

    -B



Children