Getting Started Common Acronyms FAQ Forum Help Forum Tips FTP Site Helpful GuidelinesInserting and Attaching images, videos, or files to postsProduct Community Directory SELECTsupport
Yongan.Fu[Bentley]:14170000 points just do a simply display ?
Yongan.Fu[Bentley]:Yes, you should put all points in _pts array. Consider performance issues, the _reducedPts array is created from _pts just used to display a profile of your data in dynamic mode.
Arpan: Yongan, with size for reduced points to MAX_PNT/10000, i am able to draw 14170000 points without any problem. More than that points are not showing in the design file. There is no crash but it simply not showing anything.
Arpan: Can't i experiment with DrawPointCloud with this version? Function is listed there in MicroStationAPI.chm.
Arpan: Is it compulsory to put all the points in _pts array? I am not getting the significance of this _reducedPts array.
Yongan.Fu[Bentley]: What is the max amount number of your points?
Yongan.Fu[Bentley]: Maybe new DrawPointCloud method will give us a help. (PointCloud will be published at next release)
And also Yongan, i also notice in _pts array you are putting all the points (MAX_PNT), i tried to split the points between the _pts array and _reducedPts arrays. But its showing half points only. Is it compulsory to put all the points in _pts array? I am not getting the significance of this _reducedPts array.
Regards, Arpan
Seems due to some limitation of DrawPointString3d. What is the max amount number of your points ? Maybe new DrawPointCloud method will give us a help. (PointCloud will be published at next release)
Thanks a lot Yongan to look into the matter. Here are my observations : 1) No of points = 4000000 a. With DRAW_PURPOSE_FitView case ------------- Working fine (Fit view working) b. With out DRAW_PURPOSE_FitView case ------------- Working fine (Fit view not working)
2) No of points = 10000000 a. With DRAW_PURPOSE_FitView case ------------- Crashing (Only after i am trying for fit view) b. Without DRAW_PURPOSE_FitView case ------------- Not Crashing (Fit view also not working)
If we give the size of _reducedPts as MAX_PNT/1000 (in case of 10000000), its working fine. Any idea guys, what is happening here?
Yongan.Fu[Bentley]:5000000 : Crash ! ! ! So, maybe DrawPointString3d has some limitation for its displayed points.
I tired to make it as simple as i can but still getting the problem. If i am using Fit view Draw Purpose but its getting MicroStation crashed also sometimes. I am not able to figure out the problem so posting code here....please have a look and tell what is the problem. Three main files are MyViewTransients.cpp, ViewTransients.cpp and MyViewTransients.h
Yongan.Fu[Bentley]:Please refer to my recorded AVI.
Yeah seems working perfectly on your side. But somehow i am not getting that behaviour. May b i have complicated my code unnecessarily. Looking to make it simple and will tell if i got it or not. One thing i am doing differently is may be declaring the point and reduced point array in the MyViewTransients struct and accessing them in the main function with g_oViewTransients.pts and g_oViewTransients.reducedpts. And accessing them direcly in _DrawTransients method. But i donot know will that make any problem here.
Yongan.Fu[Bentley]:appending "case DRAW_PURPOSE_FitView:" after "case DRAW_PURPOSE_UpdateDynamic:" can implement your required.
Did not work out Yongan.Fu Here is what i did:
switch (context->GetDrawPurpose()) { case DRAW_PURPOSE_Update: output->DrawPointString3d (No, pp, NULL); break; case DRAW_PURPOSE_UpdateDynamic: output->DrawPointString3d (No/100, rpp, NULL); break; case DRAW_PURPOSE_FitView: output->DrawPointString3d (No/100, rpp, NULL); break; }
I also tried by removing DrawPointString3d from UpdateDynamic(keeping only Break) also but stil could not get the fit view. and sometimes this is getting MicroStation Crashed by giving System Fault:253 error.
I tried with Jon's advice also mdlModelRef_getTransient() still it did not work. I still have to zoom in and out to find my points. I noticed one more thing Yongan, manual fit view from the toolbar was working nicely before splitting code to update and updateDynamic, but it is not after the breakup. Any idea?
Arpan: And i want to display all the points fit to my view, how can i achieve that?
...... case DRAW_PURPOSE_UpdateDynamic: case DRAW_PURPOSE_FitView: output->DrawPointString3d (MAX_PNT/100, _reducedPts, NULL); break; ......
Arpan: I am not able to get it working for Update and UpdateDynamics.
I am not able to get it working for Update and UpdateDynamics.
You are telling MicroStation to fit a view to elements in the active model. However, your code is drawing transients, which are not stored in the active model.
Transient elements are stored in the transient model, which you can obtain using mdlModelRef_getTransient(). Try adding that to your model list.
Regards, Jon Summers LA Solutions
Jon Summers: You don't allocate a DgnModelRefListP: Remember that views are zero-based: MDL index 1 is user view 2.
Thanks for correction Jon, but i am not able to get it working for Update and UpdateDynamics.
Thanks and Regards, Arpan
Arpan: DgnModelRefListP *modelRefListP = NULL; …
DgnModelRefListP *modelRefListP = NULL; …
You've misunderstood that API. You don't allocate a DgnModelRefListP: the API does it for you, and deallocation as well …
DgnModelRefListP modelRefListP = NULL; mdlModelRefList_create (&modelRefListP); mdlModelRefList_add (modelRefListP , ACTIVEMODEL); … mdlModelRefList_free (&modelRefListP);
Arpan: mdlView_fit (1, modelRefListP);
mdlView_fit (1, modelRefListP);
Remember that views are zero-based: MDL index 1 is user view 2.
I Noticed in Yongan.Fu's code before drawing two DrawPurposes (Update and UpdateDynamic), fit to zoom button in view toolbar was working and it was zooming to the points drawn. But after he divided code for Update and UpdateDynamic its not happening. I was trying to do it manually as well as through code. On checking help i tried with this piece of code
DgnModelRefListP *modelRefListP=NULL; modelRefListP = (DgnModelRefListP*)dlmSystem_mdlMalloc(sizeof(DgnModelRefListP)); mdlModelRefList_create (modelRefListP); mdlModelRefList_add (*modelRefListP , ACTIVEMODEL); mdlView_fit(1, *modelRefListP);
But its not working......are above lines of code for fit to zoom purpose only? Why it is not happening manually after dividing code to Update and UpdateDynamic?
Jon Summers:In the case of a collection of DPoint3d structs, <vector> is perfect:
I want to display all the points fit to my view, how can i achieve that? Also does these transient points get plot again and again to the design file on every mouse move or zoom?
Arpan: I am allocating memory to my _pts and _reducedPts array, where should I free up that memory?
I am allocating memory to my _pts and _reducedPts array, where should I free up that memory?
DPoint3d _pts[MAX_PNT], _reducedPts[MAX_PNT/100];
If you are declaring the variables as Yongan.Fu suggests, then those are local variables. Attempting to free memory for a local variable is illegal and will cause a crash.
If you have changed the code to perform dynamic allocation, then you should be using C++ new [] and delete [] (but see the section below).
As Brien suggested already, prefer the C++ Standard Library.
The standard library usually takes care of memory allocation and deallocation, so you don't have to. In the case of a collection of DPoint3d structs, <vector> is perfect:
#include <vector> // typedef clarifies usage typedef std::vector<DPoint3d> DPoint3dVector; void ExampleFunction () { DPoint3dVector points; // Add data to elastic array DPoint3d point1 = { 1, 2, 3 }; points.push_back (point1); // Add more data to elastic array DPoint3d point2 = { 2, 4, 3 }; points.push_back (point2); ASSERT (2 == points.size ()); // Use array with MDL function MSElement line; mdlLine_create (&line, NULL, &points [0], points.size ()); // points automatically deallocated when it falls out of scope }
Thanks a ton Yongan.Fu, I am getting the points in my screen now. :-) If you donot mind please can you explain what Update and UpdateDynamic handling in the code? Also i have couple of questions here.....as i am allocating memory to my _pts and _reducedPts array, where should i free up that memory? I tried with dlmSystem_mdlFree(_pts); dlmSystem_mdlFree(_reducedPts); at end of main function but its crashing the MicroStation. Should i free that memory?
And i want to display all the points fit to my view, how can i achieve that?
Yongan.Fu: I only capture two DrawPurposes (Update and UpdateDynamic) and take different actions for them.
Excellent! Thanks for that example.
const int MAX_PNT = 1000000; DPoint3d _pts[MAX_PNT], _reducedPts[MAX_PNT/100]; struct MyViewTransients : IViewTransients { void _DrawTransients (ViewContextP context, bool isPreUpdate) override { if (isPreUpdate) return; // Draw AFTER elements... IViewDrawP output = context->GetIViewDraw (); output->SetSymbology (0x0000ff00, 0, 4, 0); // opaque green, weight 4... switch (context->GetDrawPurpose()) { case DRAW_PURPOSE_UpdateDynamic: output->DrawPointString3d (MAX_PNT/100, _reducedPts, NULL); break; case DRAW_PURPOSE_Update: output->DrawPointString3d (MAX_PNT, _pts, NULL); break; } } }; extern "C" DLLEXPORT int MdlMain (int argc, char *argv[]) { static MyViewTransients s_ViewTransient; IViewManagerR iViewManager = IViewManager::GetManager(); double uor = mdlModelRef_getUorPerMaster (ACTIVEMODEL); int j=0; for (int i=0; i<MAX_PNT; i++) { _pts[i].x = uor * rand(); _pts[i].y = uor * rand(); _pts[i].z = uor * rand(); if (i%100) _reducedPts[j++] = _pts[i]; } iViewManager.AddViewTransientHandler (&s_ViewTransient); return SUCCESS; }
Thanks a lot Yongan.Fu
I tried on your lines and i also got it working. I think keeping _DrawTransient(..) function simple was the trick.
In my case that function consist of lots of things like :All switch case and other lines (which were not there in your code) was giving the problem(Apparently). But after removing all these lines....the code inside _DrawTransient(...) is executing again and again(Checked by displaying message in the _DrawTransient function), which was one problem i dissucssed in this topic intially with Jon. Now with this code i am not able to stop that behavior. As a result as i am increasing the MAX_PNT from 10000 to 100000 MicroStataion is crashing. Are you getting the same problem if you increase the MAX_PNT to 100000 or 1000000?
Thanks a lot, Arpan
Hi Arpan, I follow Brien's guide and get the correct display in my view.
Below is my code snippet. FYI
const int MAX_PNT = 10000; DPoint3d _pts[MAX_PNT]; struct MyViewTransients : IViewTransients { void _DrawTransients (ViewContextP context, bool isPreUpdate) override { if (isPreUpdate) return; // Draw AFTER elements... IViewDrawP output = context->GetIViewDraw (); output->SetSymbology (0x0000ff00, 0, 4, 0); // opaque green, weight 4... output->DrawPointString3d (MAX_PNT, _pts, NULL); } }; extern "C" DLLEXPORT int MdlMain (int argc, char *argv[]) { static MyViewTransients s_ViewTransient; IViewManagerR iViewManager = IViewManager::GetManager(); double uor = mdlModelRef_getUorPerMaster (ACTIVEMODEL); for (int i=0; i<MAX_PNT; i++) { _pts[i].x = uor * rand(); _pts[i].y = uor * rand(); _pts[i].z = uor * rand(); } iViewManager.AddViewTransientHandler (&s_ViewTransient); return SUCCESS; }
Brien Bastings:how do you debug anything?
Brien Bastings: it would be good to know if your code is getting called
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?
-B
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.
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); }
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: 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?
for(int k =0; k < 100; k++) { g_oViewTransients.FileAddPoint (PT[k]); }
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.
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
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: 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?
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);
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.
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 :
and in _DrawTransient function doing like this:
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?
Arpan: output->DrawPointString3d (jmdlEmbeddedDPoint3dArray_getCount(pMyArray), jmdlEmbeddedDPoint3dArray_getPtr(pMyArray, 0), NULL, NULL);
output->DrawPointString3d (jmdlEmbeddedDPoint3dArray_getCount(pMyArray), jmdlEmbeddedDPoint3dArray_getPtr(pMyArray, 0), NULL, NULL);
That line does exactly what you expect: it draws some points to the view. However, your computer is refreshing the screen at 50Hz, so the points are visible for only 20ms.
If you have unusually acute eyesight, you will spot them before they are erased by your display. Of course, if your eyesight is good enough to see those points, you are probably a super-hero and should be spending your time saving the world rather than writing code.
Transients exist to get around the problem of temporarily visible objects. As in my example, add your points to a transient pointer (mdlTransient_xxx).
Jon Summers:code analysis by telepathy, which is seldom the best approach.
That worked Jon, its firing only once now :-) I have completed the codig of my application but i could not see points at all :-( I have worked with that example only and have modified the MyViewTransients structure as :
================================================================================= struct MyViewTransients : Bentley::Ustn::IViewTransients { enum ViewMask { AllViews = 0x00FF, }; enum DisplayControl { InitialDisplay = 1, };
TransDescrP pTransient_; DPoint3dVector points_; CMessageTracer tracer_; DPoint3d *P_; //Added New one int cnt_; //Added New one MyViewTransients (); ~MyViewTransients ();
virtual void _DrawTransients (IViewContextP context, bool isPreUpdate); void AddPoint (const DPoint3d& point, DgnModelRefP modelRef = ACTIVEMODEL); void SetPoints (const DPoint3dVector& points); void CreateLine (MSElement* buffer); void CreateCircle (MSElement* buffer); void ReadPoints (); //Added New one
}; =================================================================================
and here is my _DrawTransients function : ================================================================================= void MyViewTransients::_DrawTransients (IViewContextP context, bool isPreUpdate) { if (isPreUpdate) return; bool pathPushed = false; char msg [128]; IViewDrawP output = context->GetIViewDraw (); sprintf (msg, "MyViewTransients::_DrawTransients Draw Purpose %d", context->GetDrawPurpose ()); tracer_.Message (msg); tracer_.Output (); // DrawPurpose enum in switch (context->GetDrawPurpose()) { case DRAW_PURPOSE_Pick: { tracer_.Message("DRAW_PURPOSE_Pick"); tracer_.Output(); // In order to support locate/AccuSnap, you must have an elementRef ... // should either push one or early return! if (NULL != context->GetIPickGeom()) { // Create dummy transient because we need its elementRef to build locate hit path... if (NULL == pTransient_) { MSElement buffer; CreateLine(&buffer); CreateCircle(&buffer); ReadPoints(); //Calling ReadPoint Functon EmbeddedDPoint3dArray *pMyArray; pMyArray = jmdlEmbeddedDPoint3dArray_new(); IViewDrawP output = context->GetIViewDraw(); jmdlEmbeddedDPoint3dArray_addDPoint3dArray(pMyArray, P_, cnt_); 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); dlmSystem_mdlFree(P_); 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; } } } =============================================================================== and here is my ReadPoint Function: ================================================================================ void MyViewTransients::ReadPoints() { FILE *fp; int totLines = 0; int space, eol =0; int c,j; char buffer[255]; char temp1; char val[50]; double x,y,z; cnt_ = 0; fp = dlmSystem_mdlFopen("c:\\samp","r"); space = 0; fseek(fp, 0, SEEK_SET); while(feof(fp) == 0) { c=fgetc(fp); if(c == 10) { totLines++; } } P_ = (DPoint3d*)dlmSystem_mdlCalloc(totLines, sizeof(DPoint3d)); fseek(fp, 0, SEEK_SET); j=0; while(feof(fp) == 0) { c=fgetc(fp); temp1 = (char)c; sprintf(buffer,"%c",c); if(c != 32 || c != 10) { val[j++]=temp1; } if(c == 32 && space == 0) { x =strtod(val,NULL); j=0; space = 1; } else if(c == 32 && space == 1) { y =strtod(val,NULL); j=0; space = 2; } else if(c == 10 && space == 2) { z =strtod(val,NULL); j=0; space = 0; P_[cnt_].x = x; P_[cnt_].y = y; P_[cnt_].z = z; cnt_++; } } dlmSystem_mdlFclose(fp); } ================================================================================ Obviously not taking chances with analysis by telepathy, so providing my code here. Please tell me what i am missing now? Thanks and Regards, Arpan
Arpan: Why the code inside MyViewTransients::_DrawTransients(…) executing again and again if I am doing Fit View?
Why the code inside MyViewTransients::_DrawTransients(…) executing again and again if I am doing Fit View?
In the code I provided, the transient pointer is a static variable. It's tested for non-NULL in the callback function, so it's only created once. If you have removed either the static qualification, or the test for non-NULL, then your code will be called repeatedly.
Of course, I'm guessing. Without seeing your code this is code analysis by telepathy, which is seldom the best approach.
Arpan: hope will achieve my results without any furthur problem.
hope will achieve my results without any furthur problem.
Not to be :-(
One question Jon, why the code inside MyViewTransients::_DrawTransients(.....) executing again and again if i am doing Fit View in the MicroStation? Any way to stop this behaviour?
Thanks Jon for explaining the fundamental things.
I am working with the project and hope will achieve my results without any furthur problem.
Arpan: On compilation I am getting error : error LNK2019: unresolved external symbol _jmdlEmbeddedDPoint3dArray_new referenced in function C:\PROGRA~1\Bentley\MICROS~1\MICROS~1\mdlapps\ViewTransients.dll : fatal error LNK1120: 1 unresolved externals
On compilation I am getting error :
error LNK2019: unresolved external symbol _jmdlEmbeddedDPoint3dArray_new referenced in function
C:\PROGRA~1\Bentley\MICROS~1\MICROS~1\mdlapps\ViewTransients.dll : fatal error LNK1120: 1 unresolved externals
That's not a compilation error, it's a linker error.
Let's understand what is happening when a project is built. The make file invokes the:
When the Visual C++ compiler detects a source code error it issues an error code C1234. Note the 'C' prefix. When the Visual C++ linker is unable to locate the compiled definition of a function in an object or library it issues an error code LNK234. Note the 'LNK' prefix.
Your error is fairly explanatory: your compilation has succeeded, but the linker can't find the definition of jmdlEmbeddedDPoint3dArray_new. Lookup that function in MDL help: it tells you to #include <embeddeddoublearray.fdf> in your source code, and to link with mtg.lib. In other words, you need to include mtg.lib in the project's linker options in your bmake (.mke) file:
DLM_LIBRARY_FILES = $(mdlLibs)BentleyDgn.lib \ $(mdlLibs)toolsubs.lib \ $(mdlLibs)ditemlib.lib \ $(mdlLibs)mdllib.lib \ $(mdlLibs)mdlbltin.lib
If you fire up MSDN help (or locate MSDN's web site) you can look up Microsoft compiler and linker errors.
Jon Summers: I've attached an incomplete example that may help
I've attached an incomplete example that may help
Thanks a Ton Jon, that really helped.....i was trying to working up with your example.
Now i am having DPoint3d Array and want it to convert to EmbeddedDPoint3dArray using jmdlEmbeddedDPoint3dArray_new () and jmdlEmbeddedDPoint3dArray_addDPoint3dArray(...) so that i can use output->DrawPointString3d (jmdlEmbeddedDPoint3dArray_getCount (pMyArray), jmdlEmbeddedDPoint3dArray_getPtr (pMyArray, 0), NULL).
I have included header file <msembeddedarray.h> and <embeddeddpoint3darray.fdf>.
On compilation i am getting error :
Any idea what i am doing wrong here?
Regards,
Arpan
Arpan: I checked the example given in the BDN community but still having some doubts.....
I checked the example given in the BDN community but still having some doubts.....
I've attached an incomplete example that may help. It's a work-in-progress, but it shows how to do what you want from a ViewContext.
It draws a line-string and a circle at the origin. Coordinates are hard-coded — it's not interactive.
Hi Guys,
I cheked the example given in the BDN community but still having some doubts.....
1) How to call ViewTransients::DrawTransients (IViewContextP context, bool isPreUpdate) method?
I am trying as ViewTransients::DrawTransients(Context, false);
But the question is how to pass the Context into the function? What i am having is
IViewManagerR viewManager = Bentley::Ustn::IViewManager::GetManager(); ViewportP viewPort = viewManager.GetViewport(1);
But how to get Context from here to pass it to the DrawTransients function?
2) I am trynig to use context->GetIDrawGeom() inside the DrawTransients function.
But i am getting errors like
D:\Lidar\basic\basic.cpp(203) : error C2027: use of undefined type 'Bentley::Ustn::ViewContext' C:\PROGRA~1\Bentley\MICROS~1\MICROS~1\mdl\include\mstypes.h(456) : see declaration of 'Bentley::Ustn::ViewContext' D:\Lidar\basic\basic.cpp(203) : error C2227: left of '->GetIDrawGeom' must point to class/struct/union/generic type D:\Lidar\basic\basic.cpp(203) : error C2227: left of '->DrawPointString3d' must point to class/struct/union/generic type
I tired to include Bentley::Ustn::IDrawGeom (and Bentley::Ustn::ViewContext also) and then IDrawGeomP drawGeom = context->GetIDrawGeom ();
But getting errors again :
D:\Lidar\basic\basic.cpp(201) : error C2867: 'Bentley::Ustn::IDrawGeom' : is not a namespace
D:\Lidar\basic\basic.cpp(203) : error C3622: 'Bentley::Ustn::IDrawGeom': a class declared as 'abstract' cannot be instantiated C:\PROGRA~1\Bentley\MICROS~1\MICROS~1\mdl\MicroStationAPI\interface\IViewDraw.h(523) : see declaration of Bentley::Ustn::IDrawGeom' D:\Lidar\basic\basic.cpp(203) : error C2027: use of undefined type 'Bentley::Ustn::ViewContext' C:\PROGRA~1\Bentley\MICROS~1\MICROS~1\mdl\include\mstypes.h(456) : see declaration of 'Bentley::Ustn::ViewContext' D:\Lidar\basic\basic.cpp(203) : error C2227: left of '->GetIDrawGeom' must pointto class/struct/union/generic type
I want to use DrawPointString3d(...) method and for that getting context and getting object of context->GetIDrawGeom (); is really important but somehow these two important things seems to be missing everywhere.
Can i get some simple example how to use DrawPointString3d(...) function??
Thanks and Regards,
Dear Phil,
I went to Bentley Developer Network and sent a request to join the group. Is this all the procedure? Or i have to register somewhere else also? I m just waiting for my request to be accepted.
Thanks,
Hi Mark,
Thanks for sending the link, however when i am trying to access the link i am getting this message.
Weblog not found Either the Weblog you are trying to access does not exist or you do not have permission to access it. If it is a Communities Weblog you need to be a member of that Community in order to participate.
Where i should register to get access to that link? Does my current account of Bentley communities not having the permissions to this link???