DRAW_PURPOSE_XXX combination

Hi Guys,

I am trying to display shape elements as a transient elements, which are quite big in number(> 50000). I am using _DrawTransients function and writing my code inside DRAW_PURPOSE_TransientChanged. Everyting is working fine and i am able to see the elements in the file. But when doing zooming and panning operations its taking some time, as the code inside DRAW_PURPOSE_TransientChanged is executing again and again. How can i avoid this behaviour? I tried to write code in DRAW_PURPOSE_UPDATE and DRAW_PURPOSE_FITVIEW also as described by Yongan in earlier posts. But didnot get the desired results.

Here is my code inside the DRAW_PURPOSE_TransientChanged.

IViewDrawP output = context->GetIViewDraw ();
DPoint3d shape[4];
DgnModelRefP modelRef= ACTIVEMODEL;
const double UORs = mdlModelRef_getUorPerMaster (modelRef);
DPoint3d pt;
DPoint3d point;
DVec3d go;
triangle* t = get_triangle(0);
for (int count = 0; count < get_size(); count++, t++) //get_size() > almost 50000
{
  if (t->next < 0) // if not deleted
  {
    if (t->V[0]) // if not infinite
    {
      for (int j = 0; j < 3; j++)
      {
         point.x = min_x + t->V[j][0];  //x Value
         point.y = min_y + t->V[j][1];  //y Value
         point.z = min_z + t->V[j][2];  //z Value
         mdlVec_scale (static_cast(&pt), static_cast(&point), UORs);
         mdlModelRef_getGlobalOrigin (modelRef, &go);
         mdlVec_addPoint (&pt, &pt, &go);
         shape[j].x = pt.x;
         shape[j].y = pt.y;
         shape[j].z = pt.z;
      }
    shape[3] = shape[0];
    output->DrawShape3d (4, shape, false, NULL);
   }
  }
}


Now here as the code is repeating again and again on zooming and panning operations, this for loop is getting executed again and again causing the slow down of process. Please help me how should i use the combination of DRAW_PURPOSE_XXX to achieve my results.

Thanks and Regards,
Arpan

Parents
  • Arpan:

    How should I use the combination of DRAW_PURPOSE_XXX to achieve my results?

    One result of our previous discussions on this topic is a View Transients Example project.

    This is a complete example that in many ways is similar to your code. During development, I asked myself the same question about DRAW_PURPOSE_XXX. That enumeration has about 20 values, not all which are self-evident.

    The View Transients Example shows some uses of DRAW_PURPOSE_XXX. However, it's by no means complete and is the result of empirical observation rather than any definitive knowledge of the MicroStationAPI.

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

  • Thanks for replying Jon,

    Jon Summers:
    One result of our previous discussions on this topic is a View Transients Example project.

    I had seen your example before and taken cue from that only to develop code for my requirement.
    In your example you are drawing only a line and a circle, which takes no time, so if it is getting called again and again on zooming and panning operations, its not making any visible effect of being redrawn.

    But in my case where i have to display so much of shapes, which is taking 3 or 4 seconds to display, and while zooming in or out i am getting that 3 or 4 seconds pause everytime, which is very irritating.

    I found the same problem while plotting the points also and at that time Yongan gave a code snippet where he copied some points to different array and then used that to speed up the process, and the reason he gave is this "Consider performance issues, the _reducedPts array is created from _pts just used to display a profile of your data in dynamic mode."

    I was hoping this to solve my problem again, but here i am not having array of points together, as i have to draw shapes using output->DrawShape3d(...), which will create one shape at a time, so i used for loop inside DRAW_PURPOSE_XXX to display the shapes.  Now this loop is taking some time and giving me problem while doing Zoom In or Zoom Out operations.

    Thanks & Regards,
    Arpan

  • CheckStop needs to be INSIDE the loop where you are displaying the shapes. CheckStop will never return false when you are initially called, because we wouldn't have bothered to call you otherwise. There is plenty of time to draw say 100 shapes, but not 1000000 shapes, etc.

     -B



  • set your condition statement in the for-loop to:  (count < get_size()) && ! context->CheckStop()

    when you needed enough time to reach the frame-border (200 millis per default) your loop will exit. make sure you do not anything that expects all elements to be redrawn at this time (or store number of drawn elements anywhere).

    btw.  mdlModelRef_getGlobalOrigin (modelRef, &go); should be outside the loop ! Avoids at least 150.000 function calls + assigments :)

    Michael



  • Brien Bastings:
    CheckStop needs to be INSIDE the loop where you are displaying the shapes.

    Thanks a lot with that help Brien, it is working fine now. :-)
    Michael Stark:
    btw. mdlModelRef_getGlobalOrigin (modelRef, &go); should be outside the loop ! Avoids at least 150.000 function calls + assigments .

    Thanks for pointing out Michael.

    Thanks to Jon too for looking into the matter.
    Seems to be working fine and now i can move ahead :)

    Regards,
    Arpan

  • Well Guys,
    I have some doubts regarding this again. Now as i Implemented solution told by Brien, i am not facing much problem of waiting while doing zooming operations, its working much smoothly now.
    But i found that the code inside the for loop is executing again and again. Actually i found this when after drawing shapes i tried to free up the memory, triangle*.
    So once i have my shapes on the screen, i freed up the memory and after that it threw error on zoom operation, as it went again inside the for loop and tried to get triangle* which i have already freed up. So do i have to hold on to large chunck of memory always till i am displaying the transient elements? (Really donot want to do that, as i have other operations to do while displaying the transient elements)

    Here is the piece of code and resulting msgs are attached while doing 2 or 3 zoom in operations:

    void MyViewTransients::DrawTriangles (IViewContextP context)
    {
        IViewDrawP output = context->GetIViewDraw ();
        char msg[256];
        sprintf(msg,"Start draw Shape = %d and context->CheckStop = %d", TINget_size(), context-     >CheckStop());
        mdlDialog_dmsgsPrint(msg);

        DPoint3d shape[4];
        DgnModelRefP modelRef= ACTIVEMODEL;
        const double UORs = mdlModelRef_getUorPerMaster (modelRef);
        DPoint3d pt;
        DPoint3d point;
        DVec3d go;
        mdlModelRef_getGlobalOrigin (modelRef, &go);
        triangle* t = get_triangle(0);
        for (int count = 0; (count < get_size()) && ! context->CheckStop(); count++, t++)
        {
           if (t->next < 0) // if not deleted
           {
             if (t->V[0]) // if not infinite
             {
               for (int j = 0; j < 3; j++)
               {
                  point.x = min_x + t->V[j][0];
                  point.y = min_y + t->V[j][1];
                  point.z = min_z + t->V[j][2];
                 if(count == 100)
                 {
                    sprintf(msg,"Here");
                    mdlDialog_dmsgsPrint(msg);
                  }
                  mdlVec_scale (static_cast(&pt), static_cast(&point), UORs);
                  mdlVec_addPoint (&pt, &pt, &go);
                  shape[j].x = pt.x;
                  shape[j].y = pt.y;
                  shape[j].z = pt.z;
               }
               shape[3] = shape[0];
               output->DrawShape3d (4, shape, false, NULL);
            }
           }
        }
    }

    Hope i made myself clear what is my doubt.

  • Message Center

    Arpan:
    mdlDialog_dmsgsPrint (msg)

    This has nothing to do with your question; however, you will find the Message Center much more useful than the DMSGS dialog.

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

  • Arpan:

    Once i have my shapes on the screen, I freed up the memory …

    triangle* t = get_triangle(0);

    It's difficult to analyse — we don't know where get_triangle() gets its data; you don't delete (triangle)in the code posted. Is triangle pointing to allocated memory, or should it be a triangle const* looking at data stored elsewhere?

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

  • Jon Summers:
    we don't know where get_triangle() gets its data;

    triangle* is a structure and i do calloc(...) to assign memory to this. get_triangle(0) gets the first set of values from this structure.

    Jon Summers:
    you don't delete (triangle)in the code posted. Is triangle pointing to allocated memory, or should it be a triangle const* looking at data stored elsewhere?

    I was trying to free up the memory by calling tahe free statement. Yeah this is not the complete code but i can give the information needed to solve the problem.

    Thanks and Regards,
    Arpan

  • Arpan:

    I was trying to free up the memory by calling the free statement …

    You're writing C++. Is there a reason why you are not using new and delete?

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

  • Jon Summers:
    [You're writing C++. Is there a reason why you are not using new and delete?

    No reason in particular Jon, till now i was thinking there is not much difference between delete and free. I shall find out the difference and replace it in my code.
    Thanks for pointing that out.

    Arpan

  • Arpan:

    I was thinking there is not much difference between delete and free …

    I noticed that you are using calloc, which indicates that you are allocating memory for an array of something. Using calloc is often dodgy because it's up to you, the programmer, to calculate object sizes. C++ new and delete have array equivalents new [] and delete [], take better care of array memory management, and enable the compiler to check your code.

    However, the C++ operators still require you to remember to deallocate memory that you previously allocated, a continual source of memory leaks for C and C++ programmers. From your previous comments, this may be an issue.

    What you might want to look at are the C++ Standard Library smart pointers. Smart pointers are very useful when you are not in full control of the lifetime of an object, because they can deallocate memory automatically when the object is no longer required. Hey presto! Fewer memory leaks.

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

Reply
  • Arpan:

    I was thinking there is not much difference between delete and free …

    I noticed that you are using calloc, which indicates that you are allocating memory for an array of something. Using calloc is often dodgy because it's up to you, the programmer, to calculate object sizes. C++ new and delete have array equivalents new [] and delete [], take better care of array memory management, and enable the compiler to check your code.

    However, the C++ operators still require you to remember to deallocate memory that you previously allocated, a continual source of memory leaks for C and C++ programmers. From your previous comments, this may be an issue.

    What you might want to look at are the C++ Standard Library smart pointers. Smart pointers are very useful when you are not in full control of the lifetime of an object, because they can deallocate memory automatically when the object is no longer required. Hey presto! Fewer memory leaks.

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

Children
  • Jon Summers:
    C++ new and delete have array equivalents new [] and delete [], take better care of array memory management, and enable the compiler to check your code.

    What you might want to look at are the C++ Standard Library smart pointers.

    I will have a look into these things Jon but still i have my doubt left for Transient elements in Microstation API.......Do i need to hold on to large chunck of memory always till i am displaying the transient elements,  As the function is repeatedly getting called up.

    Thanks,
    Arpan