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
Arpan: How should I use the combination of DRAW_PURPOSE_XXX to achieve my results?
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
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.
Michael Stark: btw. mdlModelRef_getGlobalOrigin (modelRef, &go); should be outside the loop ! Avoids at least 150.000 function calls + assigments .
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.
Arpan: mdlDialog_dmsgsPrint (msg)
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.
Arpan: Once i have my shapes on the screen, I freed up the memory … triangle* t = get_triangle(0);
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?
Jon Summers:we don't know where get_triangle() gets its data;
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?
Arpan: I was trying to free up the memory by calling the free statement …
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?
Jon Summers:[You're writing C++. Is there a reason why you are not using new and delete?
Arpan
Arpan: I was thinking there is not much difference between delete and free …
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.
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.
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