How to convert solid clockwise sense bspline surface boundaries to hole clockwise sense?

Hi All,

I have a Bspline Surface with a set of boundaries whose clockwise sense is set to "Solid". Is it possible through MDL API to get the equivalent set of boundaries on the same Bspline Surface whose clockwise sense is "Hole"?

Thanks & Regards,

kaab

Parents
  • It's not clear what you are asking.  What is your definition of 'solid' and 'hole'?

     
    Regards, Jon Summers
    LA Solutions

  • Hi Jon,

    To be more clear, I'll put my question this way. I have a BSpline Surface with 4 boundaries. If I see the Element Information for the Bspline Surface in MicroStation, under Geometry section, inside Trim Loop node, I see a field with name "Clockwise Sense" and its value is set to "Hole"

    Now, if I change the value to "Solid", MicroStation changes the display of the Bspline Surface such that the parts which were earlier holes now become filled and the ones which were earlier filled, now become holes. But, I've seen that the Trim loops shown in the Element Information dialog still remain the same.

    Now, I want to extract the boundaries of the holes shown for this new surface, using MDL API. Which API can I use for this purpose?

    Thanks & Regards,

    kaab

  • Unknown said:
    I want to extract the boundaries of the holes shown for this new B-spline surface, using MDL API

    How about the mdlBspline_api?

     
    Regards, Jon Summers
    LA Solutions

  • Thank you for the reply. mdlBspline APIs are always returning same boundaries regardless of clockwise sense value.

  • Unknown said:
    mdlBspline APIs are always returning same boundaries regardless of clockwise sense value

    So you've written some code?  Post a snippet here.  With some evidence, perhaps someone can help.

    I remain uncertain about your interpretation of 'solid' and 'hole' and whether they match MicroStation's implementation of a B-spline surface.  What is your purpose in creating a surface that is a 'hole'?

    Unknown said:
    if I change the value to "Solid", MicroStation changes the display of the Bspline Surface such that the parts which were earlier holes now become filled and the ones which were earlier filled, now become holes

    Can you post here a DGN model that illustrates your point?

     
    Regards, Jon Summers
    LA Solutions

  • Actually, I've figured out that my problem would be solved if I could get the total outermost boundary curve of the original BSpline Surface along with the boundaries present on the Bspline Surface when the clockwise sense is set to "Solid".

    I tried using mdlBSpline_extractBoundary function on the BSpline Surface after intentionally setting the values of numbounds and boundaries to 0. But, I got 3 separate BSpline Surfaces in the new element descriptor created by the API instead of bounding curves of the surface. Many a time, I've seen that extract boundary API fails to give correct boundary for the BSpline Surface. So, is there any alternate API to extract the whole boundary of the BSpline Surface?

  • Hi Jon,

    Here, I'm posting screenshots of the Bspline Surface with boundaries set to solid and hole clockwise sense:

    Bspline Surface with boundaries set to Solid clockwise sense

    Same Bspline Surface with boundaries set to Hole clockwise sense

    I'm also attaching the DGN file.

    TestDgn.dgn
  • Good screenshots!

     
    Regards, Jon Summers
    LA Solutions

  • PMFJI. First of all, I need to say I am not a Bspline expert. So my advice is just for your reference.

    I guess you construct your element by trimming a sphere. As a sphere, it is a closed surface, so it has no boundary. That is why you only extract 3 boundaries with mdlBspline_extractBoundary function.

    Then why ElementInfo show us 4 trim loops ? I analyzed your element with the below snippet and found there are two trim loops to contruct the bottom circle (I moved one of semi-circle slightly to show them clearly).

     MSElement        el;
     MSElementDescrP  edP = NULL;
     MSBsplineSurface bsSurface;
     if(SUCCESS != mdlAssoc_getElementDescr(&edP, NULL, 195, ACTIVEMODEL, FALSE))
        return -1;
     mdlBspline_convertToSurface(&bsSurface, edP);
     mdlElmdscr_freeAll (&edP);   edP = NULL;
     for (int i=0; i<bsSurface.numBounds; i++)
     {
           DPoint3d   *pPoints = (DPoint3d *)dlmSystem_mdlMalloc (bsSurface.boundaries[i].numPoints * sizeof(DPoint3d));
           for (int j=0; j<bsSurface.boundaries[i].numPoints; j++)
           {
               mdlBspline_evaluateSurfacePoint (&pPoints[j], NULL, NULL, NULL,
                             bsSurface.boundaries[i].points[j].x, bsSurface.boundaries[i].points[j].y, &bsSurface);
           }
           mdlShape_create (&el, NULL, pPoints, bsSurface.boundaries[i].numPoints, -1);
           mdlElement_add (&el);
           dlmSystem_mdlFree (pPoints); 
     }
     mdlBspline_freeSurface (&bsSurface);

    Regards,

     Yongan



  • Back to your post topic. If you want to create a hole clockwise sense bspline surface from a solid clockwise sense bspline surface, it is really simple. Just need to change the holeOrigin and recreate the surface again. Following is the code:

     MSElementDescrP  edP = NULL;
     MSBsplineSurface bsSurface;
     if(SUCCESS != mdlAssoc_getElementDescr(&edP, NULL, 195, ACTIVEMODEL, FALSE))
        return -1;
     mdlBspline_convertToSurface(&bsSurface, edP);
     mdlElmdscr_freeAll (&edP);   edP = NULL;
     bsSurface.holeOrigin = !bsSurface.holeOrigin;
     mdlBspline_createSurface (&edP, NULL, &bsSurface);
     mdlElmdscr_add (edP);
     mdlElmdscr_freeAll (&edP);
     mdlBspline_freeSurface (&bsSurface);
    HTH, Yongan



Reply
  • Back to your post topic. If you want to create a hole clockwise sense bspline surface from a solid clockwise sense bspline surface, it is really simple. Just need to change the holeOrigin and recreate the surface again. Following is the code:

     MSElementDescrP  edP = NULL;
     MSBsplineSurface bsSurface;
     if(SUCCESS != mdlAssoc_getElementDescr(&edP, NULL, 195, ACTIVEMODEL, FALSE))
        return -1;
     mdlBspline_convertToSurface(&bsSurface, edP);
     mdlElmdscr_freeAll (&edP);   edP = NULL;
     bsSurface.holeOrigin = !bsSurface.holeOrigin;
     mdlBspline_createSurface (&edP, NULL, &bsSurface);
     mdlElmdscr_add (edP);
     mdlElmdscr_freeAll (&edP);
     mdlBspline_freeSurface (&bsSurface);
    HTH, Yongan



Children
  • Hi Yongan,

    Thank you very much for your detailed explanation about the Bspline Surface. I'm not sure about how this Bspline Surface is exactly created, since I have not created it. But, I've tried using your code snippet and observed that a new Bspline Surface with hole configuration is created. But, this is not exactly what I want. To even more clearly express my issue, kindly see screenshots for the below test case. It is more clear representation of my issue:

    I've the following Bspline surface, as shown in the below screenshot. When I use mdlBspline_extractSurface to extract the surface details, I get the boundary that is marked in red in the below screenshot.

    Now, I change the surface's clockwise sense to solid. The display of MicroStation is as shown in the below screenshot. But, I still get the same boundary as in the above screenshot when I extract surface details using mdlBspline_extractSurface() API.

    But, i want the boundary highlighted in red as shown in the below screenshot. How to get it using MDL API?

    I'm also attaching the V8 DGN file for the above test case.

    Thanks & Regards,

    kaab

    BspBoundary.dgn
  • Clearly understand your desired. For this case, I recommend you another approach (I haven't coded to test it):

    Convert this BsplineSurface to a sheet body and then get edge elements from this sheet body. You certainly need to dig into mdlKISolid_xxx functions.

    HTH, Yongan



  • Thank you for your suggestion, Yongan.

    Regards,

    kaab

  • I have coded to test my suggestion and can get a re-constructed simple SmartSurface as below:

    The code is simpler than I expected:

     MSElementDescrP  edP = NULL;
     KIBODY           *pBody = NULL;
     if(SUCCESS != mdlAssoc_getElementDescr(&edP, NULL, 199, ACTIVEMODEL, FALSE))
        return -1;
     mdlKISolid_elementToBody (&pBody, edP, ACTIVEMODEL);
     mdlElmdscr_freeAll (&edP);   edP = NULL;
     if (SUCCESS == mdlKISolid_bodyToElement (&edP, pBody, TRUE, -1, NULL, ACTIVEMODEL))
     {
        mdlKISolid_freeBody (pBody);
        mdlElmdscr_add (edP);
        mdlElmdscr_freeAll (&edP);
     }
    199 is the ElmentID of the Bspline surface which Trim Loop's Closewise Sense = Solid. The created SmartSurface has two arcs and two lines as its boundary.

    You can drop this SmartSurface to get these arcs and lines or use mdlKISolid_getEdgeList to get them.

    HTH, Yongan



  • Unknown said:
    mdlKISolid_bodyToElement (&edP, pBody, TRUE, -1, NULL, ACTIVEMODEL)

    1. The third BoolInt parameter is documented: TRUE for wireframe geometry, FALSE for surfaces.  Perhaps I misunderstand the MDL help, but how does your implementation create a SmartSurface and not a wireframe?
    2. MDL help tells us that mdlKISolid_bodyToElement is deprecated and to use mdlKISolid_bodyToElementD

     
    Regards, Jon Summers
    LA Solutions

  • Hi Jon,

    1. The third parameter "wireframe" has the following meaning which I found from MicroStation help file. Maybe it isn't the normal meaning as we expected.

    You can try to change this parameter from TRUE to FALSE, it will create Surface (type=18) element not a SmartSurface.

    2. Actually, mdlKISolid_bodyToElement call mdlKISolid_bodyToElementD with the last parameter set to TRUE. Thanks for your reminder.

    HTH, Yongan



  • Yongan: thanks for your detective work!  It's very helpful to understand those details.

    Unknown said:
    Change this parameter from TRUE to FALSE, it will create Surface (type=18) element not a SmartSurface

    Well, I would not have guessed that from the MDL documentation  8-)

     
    Regards, Jon Summers
    LA Solutions

  • Hi Yongan,

    Thank you very much for your reply. I've tried the code snippet given by you. Yes, that's what I needed. But, I've one concern with this approach. Since the given test case yields a single boundary, I can assume all the set of arcs and lines form a single loop / boundary. If there are multiple boundaries, then how can I distinguish which set of curves form which boundary?

    Thanks & Regards,

    kaab

  • Hi Kaab,

    If you have multiple boundaries you can use mdlKISolid_xxx functions to distinguish them as my below snippet:

     MSElementDescrP  edP = NULL;
     KIBODY           *pBody = NULL;
     if(SUCCESS != mdlAssoc_getElementDescr(&edP, NULL, 555, ACTIVEMODEL, FALSE))
        return -1;
     mdlKISolid_elementToBody (&pBody, edP, ACTIVEMODEL);
     mdlElmdscr_freeAll (&edP);   edP = NULL;
     if (SUCCESS == mdlKISolid_bodyToElementD (&edP, pBody, TRUE, -1, NULL, ACTIVEMODEL, TRUE))
     {
        int           faceCnt;
        KIENTITY_LIST *pFaceList = NULL;
        mdlKISolid_listCreate (&pFaceList);
        mdlKISolid_getFaceList (pFaceList, pBody);
        mdlKISolid_listCount (&faceCnt, pFaceList);
        for (int i=0; i<faceCnt; i++)
        {
            KIFACE *pFace;
            mdlKISolid_listNthEl (&pFace, pFaceList, i);
            if (SUCCESS == mdlKISolid_faceToElement (&edP, pFace, TRUE, -1, NULL, ACTIVEMODEL))
            {
               mdlElmdscr_setSymbology (edP, (UInt32 *)&i, NULL, NULL, NULL);
               mdlElmdscr_add (edP);
               mdlElmdscr_freeAll (&edP);   edP = NULL;
            }
        }
        mdlKISolid_listDelete (&pFaceList);
        mdlKISolid_freeBody (pBody);
     }
    I added another trim loop to your Bspline surface and the result is shown as below. Please note: the black and blue color are somewhat close.

    HTH,Yongan

     



    Answer Verified By: kaab 

  • Unknown said:
    If there are multiple boundaries, then how can I distinguish which set of curves form which boundary?

    As each face is processed, it yields a boundary object that is then converted to an element descriptor chain.  The chain is added to the active model in Yongan's example.

    You can identify those boundaries in several ways:

    1. If you want to work in-memory with the boundaries, add your identification data to the descriptor chain in pDescriptor->h.userData1
    2. If you want to work with the boundaries after they've been added to the model, you could use one of these:
      1. record the file position (returned by mdlElmdscr_add)
      2. record the Element ID

     
    Regards, Jon Summers
    LA Solutions

    Answer Verified By: kaab