Getting ViewContext from IViewManager

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

Parents Reply
  • 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,

    Arpan

Children
  • Arpan:

    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.

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

    ViewTransients-MicroStationAPI.zip
  • Jon Summers:

    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 :

    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

    Any idea what i am doing wrong here?

    Regards,

    Arpan

  • Build, Compile, or Link?

    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

    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:

    1. compiler to convert your source code (*.h, *.cpp) to intermediate object modules (*.obj)
    2. linker to merge your object modules (*.obj) and resolve function calls with external libraries (*.lib, *.dll)

    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.

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

  • Thanks Jon for explaining the fundamental things.

    I am working with the project and hope will achieve my results without any furthur problem.

  • Arpan:

    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 and Regards,
    Arpan

  • Arpan:

    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.

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

  • 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:
    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).

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

  • Jon Summers:
    add your points to a transient pointer (mdlTransient_xxx).

    Was trying to do that only........but not getting the result. In your example you are using mdlTransient_addElement(...) to add the Line and Ellipse elements. But i need to use DrawPointString3d(...) function to add the points. I could not see any mdlTransient_xxx function to add the points. Here is what i did :
    Added these things in struct MyViewTransients:

    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