Hi guys,
On including the IViewManager.h to my application i got this error msg.
C:\PROGRA~1\Bentley\MICROS~1\MICROS~1\mdl\MicroStationAPI\interface\IViewManager.h(126) : error C2061: syntax error : identifier 'IRedrawOperation'
I checked the function in the documentation and its like this
void DoElementAgendaDynamics (ElementAgendaP, IRedrawOperation *, ClipDescrP)
and in the header file its like this
MSCORE_EXPORT void DoElementAgendaDynamics (ElementAgendaP, IRedrawOperation*, ClipDescrP);
So both looks same but still getting the error....any idea why?
Thanks and Regards,
Arpan
Please ignore the last post....i got it working.
I got the viewPort and still trying to find out how to get the viewContext from that.
Brien gave some hint about it in http://communities.bentley.com/Products/MicroStation/MicroStation_V8i/MicroStation_V8i_Programming/f/19569/t/47082.aspx but i didnot get what exactly he meant.
Regards, Arpan
Here is a blog posting on the topic : http://communities.bentley.com/Programs/Bentley_Developer_Network/b/bentley_developer_network-blog/archive/2010/01/22/using-the-iviewtransient-interface-to-display-data.aspx
HTH,
mark anderson [Bentley]
Visit me at https://communities.bentley.com/communities/other_communities/bentley_innovation/default.aspx
Jon Summers:add your points to a transient pointer (mdlTransient_xxx).
DPoint3dVector pts_; void FileAddPoint (const DPoint3d& point, DgnModelRefP modelRef = ACTIVEMODEL);
FileAddPoint's definition is like this :
void MyViewTransients::FileAddPoint (const DPoint3d& point, DgnModelRefP modelRef) { char msg [128]; sprintf (msg, "AddPoint %.1lf,%.1lf,%.1lf", point.x, point.y, point.z); tracer_.Message (msg); tracer_.Output (); const double UORs = mdlModelRef_getUorPerMaster (modelRef); DPoint3d pt; mdlVec_scale (static_cast(&pt), static_cast(&point), UORs); pts_.push_back (pt); }
Adding the points (DPoint3d *) array to pts_ using FileAddPoint function :
for(int k =0; k < 100; k++) { g_oViewTransients.FileAddPoint (PT[k]); }
and in _DrawTransient function doing like this:
EmbeddedDPoint3dArray *pMyArray; pMyArray = jmdlEmbeddedDPoint3dArray_new(); IViewDrawP output = context->GetIViewDraw(); jmdlEmbeddedDPoint3dArray_addDPoint3dArray(pMyArray, &pts_[0], pts_.size ()); IViewManagerR viewManager = Bentley::Ustn::IViewManager::GetManager(); ViewportP viewPort = viewManager.GetViewport(1); output->SetSymbology (viewPort->MakeTrgbColor (200, 100, 100, 0), 0, 1, 0); output->DrawPointString3d (jmdlEmbeddedDPoint3dArray_getCount(pMyArray), jmdlEmbeddedDPoint3dArray_getPtr(pMyArray, 0), NULL, NULL); jmdlEmbeddedDPoint3dArray_free(pMyArray);
Is this the correct way to add points to transient and then use those??
One more question do i have to add points one by one only using the for loop (Which will surely make routine slower again) or is there any way to add all the points on one go itself?
Thanks and Regards, Arpan
Arpan: EmbeddedDPoint3dArray *pMyArray; pMyArray = jmdlEmbeddedDPoint3dArray_new(); IViewDrawP output = context->GetIViewDraw(); jmdlEmbeddedDPoint3dArray_addDPoint3dArray(pMyArray, &pts_[0], pts_.size ()); IViewManagerR viewManager = Bentley::Ustn::IViewManager::GetManager(); ViewportP viewPort = viewManager.GetViewport(1); output->SetSymbology (viewPort->MakeTrgbColor (200, 100, 100, 0), 0, 1, 0); output->DrawPointString3d (jmdlEmbeddedDPoint3dArray_getCount(pMyArray), jmdlEmbeddedDPoint3dArray_getPtr(pMyArray, 0), NULL, NULL); jmdlEmbeddedDPoint3dArray_free(pMyArray);
This looks ok, I'd just use std::vector instead of the jmdlEmbedded array stuff. You should always use the viewport from the ViewContext that is supplied to you, context->GetViewport (), and if it's NULL you probably just want to early return because it means we're not drawing to the screen (or you can just skip setting up the symbology). Of course you're not really using the viewport, just a utility method to create a TBGR UInt32 from 0-255 red, green, blue values.
Do your points still not display AFTER you do a view update (Update View tool)...i.e. is it just the initial display that is the problem...I can tell you how to deal with that.
The IViewTransient inteface is a replacement for the mdlTransient_api...but it's vastly superior because you don't need to create elements if you just want to draw geometry and you have more control over how/when/why your geometry is displayed. You DO NOT need to use the mdlTransient_ api to display temporary graphics. Stuff drawn by your _DrawTransient method is back-stored just like using mdlTransient_ with DRAW_MODE_Normal.
-B
Brien: Do your points still not display after you do a view update (Update View tool) … i.e. is it just the initial display that is the problem … I can tell you how to deal with that.
Do your points still not display after you do a view update (Update View tool) … i.e. is it just the initial display that is the problem … I can tell you how to deal with that.
Yes, please!
Brien: The IViewTransient interface is a replacement for the mdlTransient_api.. You don't need to create elements if you just want to draw geometry and you have more control over how/when/why your geometry is displayed. You do not need to use the mdlTransient_ api to display temporary graphics. Stuff drawn by your _DrawTransient method is back-stored just like using mdlTransient_ with DRAW_MODE_Normal.
The IViewTransient interface is a replacement for the mdlTransient_api.. You don't need to create elements if you just want to draw geometry and you have more control over how/when/why your geometry is displayed. You do not need to use the mdlTransient_ api to display temporary graphics. Stuff drawn by your _DrawTransient method is back-stored just like using mdlTransient_ with DRAW_MODE_Normal.
Bliss: more enlightenment!
So we can use IDrawGeom->DrawXxx2d and its companions without having to create an MSElement first. What about the case where one wants the geometry to be snappable? mdlTransient_ creates the transient with an option for snappable; is that also available with the vastly superior IViewTransient interface?
Regards, Jon Summers LA Solutions
Since an IViewTransient is back-stored, in order to initially display one (or erase one that has been freed) without doing a full view update you need to to trigger a heal of the screen area where you're going to display your geometry.. You can use the RedrawElems class to accomplish this.
RedrawElems redrawElems;
redrawElems.SetDrawMode (initialDisplay ? DRAW_MODE_Normal : DRAW_MODE_Erase); redrawElems.SetDrawPurpose (DRAW_PURPOSE_TransientChanged); redrawElems.SetViews (0xffff);
redrawElems.DoRedraw (s_myViewTransient, false);
If you want to display geometry that is changing every dynamics frame/cursor motion you should be using an IViewDecoration and not an IViewTransient. When you use mdlTransient_addElement with DRAW_MODE_TempDraw instead of DRAW_MODE_Normal or DRAW_MODE_Hilite you are actually creating an IViewDecoration.
Jon Summers:So we can use IDrawGeom->DrawXxx2d and its companions without having to create an MSElement first. What about the case where one wants the geometry to be snappable? mdlTransient_ creates the transient with an option for snappable; is that also available with the vastly superior IViewTransient interface?
Sure, you can make an IViewTransient snappable. To put things in perspective, when you create a TransDescrP using the mdlTransient_api you are just using an IViewTransient that MicroStation has implemented that visits your elements in it's _DrawTransient method...i.e. mdlTransient_ doesn't do anything that you can't do yourself. All that's needed to make something snappable is an elementRef. AFTER Arpan gets something to display we can get into implementation specifics. :)
Brien Bastings:Do your points still not display AFTER you do a view update (Update View tool)
Brien Bastings:You can use the RedrawElems class to accomplish this.
RedrawElems redrawElems; redrawElems.SetDrawMode (g_oViewTransients.InitialDisplay ? DRAW_MODE_Normal : DRAW_MODE_Erase); redrawElems.SetDrawPurpose (DRAW_PURPOSE_TransientChanged); redrawElems.SetViews (0xffff); redrawElems.DoRedraw (g_oViewTransients, false);
and made following changes in the _DrawTransient() function...
if(NULL != context->GetViewport()) { output->SetSymbology (context->GetViewport()->MakeTrgbColor (200, 100, 100, 0), 0, 1, 0); EmbeddedDPoint3dArray *pMyArray; pMyArray = jmdlEmbeddedDPoint3dArray_new(); jmdlEmbeddedDPoint3dArray_addDPoint3dArray(pMyArray, &pts_[0], pts_.size ()); output->DrawPointString3d (jmdlEmbeddedDPoint3dArray_getCount(pMyArray), jmdlEmbeddedDPoint3dArray_getPtr(pMyArray, 0), NULL, NULL); jmdlEmbeddedDPoint3dArray_free(pMyArray); } else { sprintf(msg, "ViewPort NULL"); mdlOutput_messageCenter(MESSAGE_INFO, msg, msg, FALSE); return; }
Brien Bastings:You DO NOT need to use the mdlTransient_ api to display temporary graphics.
So you mean to say i donot need to push the points to a transient pointer?....like i was trying to do here
Brien Bastings:AFTER Arpan gets something to display
Arpan: So you mean to say I do not need to push the points to a transient pointer? for(int k =0; k < 100; k++) { g_oViewTransients.FileAddPoint (PT[k]); }
So you mean to say I do not need to push the points to a transient pointer?
g_oViewTransients is the name of your static variable that holds an instance of your ViewTransients class. That loop is simply adding a set of points to a class variable.
Brien means the mdlTransient_xxx functions are not needed in this case. But, since you appear not to be using that API, his comment may not apply in your case.
Lets keep things as simple as possible. This should be all the code you need:
struct ViewTransients : IViewTransients { void _DrawTransients (ViewContextP context, bool isPreUpdate) override { if (isPreUpdate) return; // Draw AFTER elements...
IViewDrawP output = context->GetIViewDraw ();
output->SetSymbology (0x00ff0000, 0, 1, 0); // opaque blue (color is TBGR packed int), weight 1... output->DrawPointString3d (pts_.size (), &pts_[0], NULL); } };
static ViewTransients s_viewTransients;
IViewManager::GetManager().AddViewMonitor (&s_viewMonitor);
If you call AddViewMonitor after the intial update you will need to update the view to see your transients (or use RedrawElems). For now don't worry about the initial display, just set a break point on _DrawTransients and manually update the view, does the break point get hit? What is the full version number for the V8i version you are using?
Arpan: void MyViewTransients::FileAddPoint (const DPoint3d& point, DgnModelRefP modelRef) { … }
void MyViewTransients::FileAddPoint (const DPoint3d& point, DgnModelRefP modelRef) { … }
If you've copied the AddPoint method from the example I posted, you'll need to add code to compensate for the model's global origin. Here's a revised method:
////////////////////////////////////////////////////////////////////// // AddPoint accepts a 3D point as a user would keyin: master units. // Before pushing the point onto the member <vector> DPoint3d collection, // this method scales it by UORs-per-master and adds the active model's global origin void MyViewTransients::AddPoint (const DPoint3d& point, DgnModelRefP modelRef) { char msg [128]; sprintf (msg, "AddPoint %.1lf,%.1lf,%.1lf", point.x, point.y, point.z); tracer_.Message (msg); tracer_.Output (); const double UORs = mdlModelRef_getUorPerMaster (modelRef); DPoint3d pt; mdlVec_scale (static_cast(&pt), static_cast(&point), UORs); DPoint3d go; mdlModelRef_getGlobalOrigin (modelRef, &go); mdlVec_addPoint (&pt, &pt, &go); points_.push_back (pt); }
Brien Bastings: IViewManager::GetManager().AddViewMonitor (&s_viewMonitor);
I donot know how to use AddViewMonitor(...). Will AddViewTransientHandler(...) won't work? My main() function is having code like this:
MyViewTransients g_oViewTransients; mdlSystem_setFunction (SYSTEM_UNLOAD_PROGRAM, OnUnload); Bentley::Ustn::IViewManager::GetManager ().AddViewTransientHandler (&g_oViewTransients);
Brien Bastings:does the break point get hit?
Brien Bastings:What is the full version number for the V8i version you are using?
Brien Bastings:try calling DrawPointString3d with just the one point...does that display?
here is _DrawTransient funciton :
void MyViewTransients::_DrawTransients (IViewContextP context, bool isPreUpdate) { if (isPreUpdate) return; bool pathPushed = false; char msg[128]; IViewDrawP output = context->GetIViewDraw (); switch (context->GetDrawPurpose()) { case DRAW_PURPOSE_Pick: { if (NULL != context->GetIPickGeom()) { if (NULL == pTransient_) { DPoint3d temp; temp.x = 6150001.27; temp.y = 1987199.4; temp.z = 14.78; FileAddPoint(temp); if(NULL != context->GetViewport()) { output->SetSymbology (0x00ff0000, 0, 1, 0); output->DrawPointString3d (pts_.size (), &pts_[0], NULL); } else { sprintf(msg, "ViewPort NULL"); mdlOutput_messageCenter(MESSAGE_INFO, msg, msg, FALSE); return; } tracer_.Message("added element(s) to transient cache"); tracer_.Output(); sprintf(msg, "Done"); mdlOutput_messageCenter(MESSAGE_INFO, msg, msg, FALSE); } pathPushed = true; } break; } break; case DRAW_PURPOSE_UpdateDynamic: { // Maybe you don't want to draw all the points during viewing operation dynamics? break; } case DRAW_PURPOSE_RangeCalculation: { // Can just display all the points...might want to optimize... break; } } }
FileAddPoint() function is the same as told by Jon in the last post.
On clicking Update view and Fit view also, its does not show anything in the screen. Message coming in message center is No Elements Found.
Forget about AddViewMonitor, I meant AddViewTransient, my bad.
So why can't you set a break point, I can't tell what might be happening...it would be good to know if your code is getting called...how do you debug anything?!? Do you get any output from your trace statements?
Brien Bastings:how do you debug anything?
Brien Bastings: it would be good to know if your code is getting called