MDL function which return the level name of an object

Hello everybody,

Is there any MDL function which return directley the level name where an object is created ?

Actually, I use the two mdl function in order to get the level name as follows:

wnomNiveau[DKM_MAX_LEVEL_NAME_LENGTH]  type MSWChar 

idNiveau type UInt32 

elmDscrP  type MSElementDescr*

 

mdlElement_getProperties ( &niveau , NULL , NULL , NULL, NULL , NULL, NULL, NULL, &mselmDscrP->el );
mdlLevel_getName( wnomNiveau, DKM_MAX_LEVEL_NAME_LENGTH, MASTERFILE, idNiveau );

that's work fine, but, I'd like to know if is there an MDL function which allows the recuperation of the level name directly from the mselmDscrP->el variable without use of the variable idNiveau.

Thanks.

Parents
  • Unknown said:

    Is there any MDL function which return directley the level name where an object is created ?

    Actually you can get levelID using mdlElmdscr_getProperties(). But it does not give correct results on nested cells.

    void      mdlElmdscr_getProperties
    (
    UInt32*      level ,
    UInt32*      ggNum ,
    int*      dgnClass ,
    int*      locked ,
    int*      newElm ,
    int*      modified ,
    int*      viewIndepend ,
    int*      solidHole ,
    MSElementDescrCP      pElementDescr
    );

    Unknown said:

    mdlElement_getProperties ( &niveau , NULL , NULL , NULL, NULL , NULL, NULL, NULL, &mselmDscrP->el ); 
    mdlLevel_getName( wnomNiveau, DKM_MAX_LEVEL_NAME_LENGTH, MASTERFILE, idNiveau );

    Your method seems correct but it fails for cell headers or solids because they start with a header element and it returns 0 as levelID. You may check this on MicroStation element information dialog by navigating cells or solids.

    Instead, I am getting level ID of first graphics element inside an element descriptor.

    // Element function to get level of first graphics element after the header
    int akElmfunc_getLevel
    (
       MSElementUnion *elP, /* <=> element to be modified */
       UInt32 *levelID, /* => user parameter ( level of elmdscr ) */
       DgnModelRefP fileNum, /* => file # for current elem */
       MSElementDescr *elmDscrP, /* => element descr for elem */
       MSElementDescr **newDscrPP /* <= if replacing entire descr */
    )
    {

        if(elP->ehdr.isGraphics)
        {
            // Get level of the first graphics element
            mdlElement_getProperties (levelID, NULL, NULL, NULL, NULL, NULL, NULL, NULL, elP);
            return (MODIFY_STATUS_ABORT); // Level got, abort process
        }
        return (MODIFY_STATUS_NOCHANGE);
    }

    // Get level ID of an element descriptor

    int akElmdscr_getLevel
    (
       MSElementDescr **edP,
       ULong *levelid
    )

    {
        int status;

        *levelid = 0;

        #if defined (MSVERSION) && (MSVERSION >= 0x8b0)
            status = mdlModify_elementDescr2(edP,ACTIVEMODEL,MODIFY_REQUEST_NOHEADERS, akElmfunc_getLevel,levelid,0);
        #else
            status = mdlModify_elementDescr(edP,ACTIVEMODEL,MODIFY_REQUEST_NOHEADERS, akElmfunc_getLevel,levelid,0);
        #endif

        return status;

    }

    Alternatively, you may use mdlElmdscr_operation() instead of mdlModify_elementDescr(), but I prefered mdlModify_elementDescr() because it has option to filter some unneeded elements like headers.

    Hope this helps.

    Kind regards,

    Sedat Alis
    AEC Technology Inc.

    Answer Verified By: cdiTech 

Reply
  • Unknown said:

    Is there any MDL function which return directley the level name where an object is created ?

    Actually you can get levelID using mdlElmdscr_getProperties(). But it does not give correct results on nested cells.

    void      mdlElmdscr_getProperties
    (
    UInt32*      level ,
    UInt32*      ggNum ,
    int*      dgnClass ,
    int*      locked ,
    int*      newElm ,
    int*      modified ,
    int*      viewIndepend ,
    int*      solidHole ,
    MSElementDescrCP      pElementDescr
    );

    Unknown said:

    mdlElement_getProperties ( &niveau , NULL , NULL , NULL, NULL , NULL, NULL, NULL, &mselmDscrP->el ); 
    mdlLevel_getName( wnomNiveau, DKM_MAX_LEVEL_NAME_LENGTH, MASTERFILE, idNiveau );

    Your method seems correct but it fails for cell headers or solids because they start with a header element and it returns 0 as levelID. You may check this on MicroStation element information dialog by navigating cells or solids.

    Instead, I am getting level ID of first graphics element inside an element descriptor.

    // Element function to get level of first graphics element after the header
    int akElmfunc_getLevel
    (
       MSElementUnion *elP, /* <=> element to be modified */
       UInt32 *levelID, /* => user parameter ( level of elmdscr ) */
       DgnModelRefP fileNum, /* => file # for current elem */
       MSElementDescr *elmDscrP, /* => element descr for elem */
       MSElementDescr **newDscrPP /* <= if replacing entire descr */
    )
    {

        if(elP->ehdr.isGraphics)
        {
            // Get level of the first graphics element
            mdlElement_getProperties (levelID, NULL, NULL, NULL, NULL, NULL, NULL, NULL, elP);
            return (MODIFY_STATUS_ABORT); // Level got, abort process
        }
        return (MODIFY_STATUS_NOCHANGE);
    }

    // Get level ID of an element descriptor

    int akElmdscr_getLevel
    (
       MSElementDescr **edP,
       ULong *levelid
    )

    {
        int status;

        *levelid = 0;

        #if defined (MSVERSION) && (MSVERSION >= 0x8b0)
            status = mdlModify_elementDescr2(edP,ACTIVEMODEL,MODIFY_REQUEST_NOHEADERS, akElmfunc_getLevel,levelid,0);
        #else
            status = mdlModify_elementDescr(edP,ACTIVEMODEL,MODIFY_REQUEST_NOHEADERS, akElmfunc_getLevel,levelid,0);
        #endif

        return status;

    }

    Alternatively, you may use mdlElmdscr_operation() instead of mdlModify_elementDescr(), but I prefered mdlModify_elementDescr() because it has option to filter some unneeded elements like headers.

    Hope this helps.

    Kind regards,

    Sedat Alis
    AEC Technology Inc.

    Answer Verified By: cdiTech 

Children
  • thanks colleagues the ahmet's post resolves my problem
  • Dear Bentley Developers,

    Can you update mdlElmdscr_getProperties() function to return Level ID of first graphics element?

    Kind regards,

    Sedat Alis
    AEC Technology Inc.

  • Unknown said:
    Can you update mdlElmdscr_getProperties() function to return Level ID of first graphics element?

    I assume that you're discussing a complex element descriptor, such as  a cell.

    If that function were to return a property of the first element, how would you ever discover the properties of other elements in the descriptor chain?  It's easy enough to write your own function that examines the properties of the first graphic element in a complex descriptor...

    MSElementDescr* FirstGraphicComponent (MSElementDescr const* pComplex)
    {
      //  Get complex element from somewhere
      MSElementDescr* pComponent = pComplex->h.firstElem;
      while (pComponent)
      {
        if (pComponent->el.ehdr.IsGraphics)
         return pComponent;
        pComponent = pComponent->h.next;
      }
      return NULL;
    }

     
    Regards, Jon Summers
    LA Solutions

  • Unknown said:

    I assume that you're discussing a complex element descriptor, such as  a cell.

    You are right, complex elements must return correct level ID too.

    Unknown said:

    If that function were to return a property of the first element, how would you ever discover the properties of other elements in the descriptor chain?  It's easy enough to write your own function that examines the properties of the first graphic element in a complex descriptor...

    MSElementDescr* FirstGraphicComponent (MSElementDescr const* pComplex)
    {
      //  Get complex element from somewhere
      MSElementDescr* pComponent = pComplex->h.firstElem;
      while (pComponent)
      {
        if (pComponent->el.ehdr.IsGraphics)
         return pComponent;
        pComponent = pComponent->h.next;
      }
      return NULL;
    }

    A good alternative, thanks.

    Actually I mentioned to fix the problem on an existing function mdlElmdscr_getProperties().

    Kind regards,

    Sedat Alis
    AEC Technology Inc.

  • Ahmet, there is no problem with the existing function, as the cell-header has no level assigned, it MUST NOT return any of the underlying elements level-Id. As soon as you have underlying elements on different levels it will always return the false one. And even if all underlying elements are on the same level, there's no reason to return a level for the cell-header when no one is assigned.



  • Michael Stark said:

    Ahmet, there is no problem with the existing function, as the cell-header has no level assigned, it MUST NOT return any of the underlying elements level-Id. As soon as you have underlying elements on different levels it will always return the false one. And even if all underlying elements are on the same level, there's no reason to return a level for the cell-header when no one is assigned.

    Michael thank you. Actually if you think all component elements of an element descriptor can be on different levels, it is not meaningful for mdlElemdscr_getProperties to return the level of the first element. We assume that all elements inside the element descriptor is in the same level otherwise it can't return a single level ID.

    Kind regards,

    Sedat Alis
    AEC Technology Inc.

  • Unknown said:
    We assume that all elements inside the element descriptor is in the same level otherwise it can't return a single level ID.

    Thought so, and in your case this assumption might work and last for long time. Nevertheless the API was made (and had to work) for general purposes, so Jon's solution is the one you have to choose.

    I permanently create cells with at least 2 different levels, 3D/2D/Text is strictly distinct at our application, and even those components might consist of different levels inside (i.e. a chair has different 3D levels for the wooden and textile parts). So your assumption should not result in changes in the API, even not as an optional switch/flag. We are programmers, we need to understand the underlying structures and their restricitions. Such discussion are good to show even differences in the viewpoint of different developers. Together we will almost find a solution, and (hopefully) understand why this or that decision was made by the APi developers.



  • Unknown said:
    We assume that all elements inside the element descriptor is in the same level otherwise it can't return a single level ID

    What about a cell?  A cell would be rather dull if its components could sit on only one level!

     
    Regards, Jon Summers
    LA Solutions

  • Thanks Michael and Jon. As a result of this conversation, let's say mdlElmdscr_getProperties must return a list of levels. :)

    Kind regards,

    Sedat Alis
    AEC Technology Inc.

  • Unknown said:
    let's say mdlElmdscr_getProperties must return a list of levels

    while, at a first glance, this might seem to make sense, it doesn't ! For elements that have no level assigned, it still must return a level ID of 0. Otherwise you are always in need to know if a specific element type has a level by it's own, or by underlying objects. This becomes more critical whenever new elementtypes are invoked, I currently do not know which of the elements have it's own level-setting I would have to guess, with the current functionality I can test against a LEVEL_NULL_ID and dive into the enumeration of Childs/Chain-members if neccessary. It will be even a question of time consumption. Imagine a cell with some thousands of elements in it, it would take an amount of time to run through those to collect all level information. Good if you need them all, bad if you doesn't. It would be nice to have a function that returns a list of level-ID's for a given elementdescriptor, but this should be an additonal one, so you can call it when really neccessary.