Re: Tracking element changes - as they happen?

MicroStation V8i

This is where you can find and contribute to discussions, ideas, and other information about MicroStation V8i.

Tracking element changes - as they happen?

  • rated by 0 members
  • This post has 29 Replies |
  • 1 Follower
  • Legacy C-style Global Variables

    John: What on earth is dgnBuf? Another cryptic microstation tag-along that the developers have not yet managed to factor out?

    MDL implements C; it is long in the tooth. MDL provides many public global variables, which Dan has illuminated in his table taken from the MDL documentation. dgnBuf is a scratchpad that you can use to store a temporary MSElement while your command is active.

    If you view object-oriented programming and encapsulation as good things, then C-style global variables are a bad thing. But they've worked for several decades and have permitted long-term portability of code which, along with the lack of DGN format changes, have benefitted MicroStation users and developers alike.

    The MicroStationAPI is C++. It emphasises object-oriented programming and encapsulation. It provides classes that avoid those public global variables. The VBA IPrimitiveCommandEvents interface provides a wrapper around the MicroStationAPI primitive command handler.

    With each new version of MicroStation, the MicroStationAPI contains more public classes that we can use. In some cases, they provide functionality not available with MDL; in other cases, they replace MDL functions.  They are at the same time making those public global variables less relevant.

    Regards, Jon Summers
    LA Solutions

  • Michael,

    Seems like you have developed an 'independent' way of dealing with 'dependencies'. Isn't this going to be a problem for interoperability, in the long term ?

    It sounds like Bentley hasn't thought through the way dependencies work within nested cells, or should they really be objects? I understand that dotNet does not have callback functions, but event functions which are associated with interfaces. The way you are programming does not sound very object or component oriented?

    End user programming tools like GC rely on scripting, but struggles to access stuff implemented in 'proper' compiled or semi-complied code like MDL, C++, C# etc. Apparently, C#, VBA and dotNet interOpts PInvokes provide a bridge. How will you ensure that your parametric elements can talk to, propagate to and from, other parametric objects? After all, the whole point of parametrics is going beyond the elements themselves to include the relationships between them. The last thing you want is for your elements, cells to be 'islands', I think?

    Too many callbacks: It sounds like MDL developers can ask for wake-up calls from any and every hotel in town. Do you know of a better way of doing things? This must cause problems. I hear Sketchup has an Observer class in Ruby, which sounds very much like callbacks, but a bit more OO? And they have some big performance and other issues. I wonder if LabView's StateCharts or MetaCase can be used to organise callbacks? StateCharts look like they are based on Petri graphs that define events in a dependency graph. I guess, if this is defined for your parametric 'cell' or object, then the call backs could be reduced or trapped locally? MetaCase sort of does the same, providing a 'better than UML' way of UI modeling.

    Dependencies graphs is central to GC, and the directed acyclic flavour seems to be a lot less complicated than the old state machine main loop environment. A lot of work on the 'front line' will rely on simple 'scripts' or 'batch file' type hacks to take the next step in productivity. Waiting around for developers to provide the plugin or vertical is not in itself enough. I guess its a Long Tail thing. GC and its DAG working promises to be a powerful middle ground and bridge between end-user and vendor programming.

  • johnds:

    Errrrrrrrrrrrrrrrrrrrrrrrrrrrrrm, dgnBuf??? What on earth is dgnBuf? Another cryptic microstation tag-along that the developers have not yet managed to factor out?

    Hehe, no, seriously, what is dgnBuf? More importantly, will I find all your suggestions in the .NET (or as Jon would say - VB COM interop) API's?

    Time for sleep now, 12pm in london, yawn!

     

    MDL Variable Types

    Variable

    Type

    Description

    dgnBuf

    MSElement*

    Holds all the information on the current element in dgn-buf. All elements are loaded into this buffer by a locate or element manipulation commands.

    statedata

    MSStateData

    Contains all the information on the current state function. Defined in global.h

    tcb

    Tcb*

    “Terminal Control Block” holds all the information on the current DGN file.  Defined in tcb.h

    mgds_modes

    Mgds_modes

    Contains the mode information about the current execu-tion of MicroStation. Defined in <global.h>

    graphConfig

    MSGraphConfig

    Contains the graphics configuration.  Defined in global.h

    mdlCommandNumber

    long

    Contains the command number of the most recently started MDL application command.

    userPrefsP

    UserPrefs*

    Contains miscelaneous user preferences. Defined in userpref.h

    mgdsPrompt[35]

    char

    Holds the text for the prompt. The default is "uStn>".

    render_designLightP

    void*

    Allows to define custom light source for rendering. ligh source is defined in light.h

    msTransientElmP

    TransDescrP

    A general purpose transient descriptor

    mdlErrno

    int

    Error number for various MDL functions

     dgnBuf is defined in gen_dloadlib.h

    About .NET:

    In .NET is available almost all, but it depends on your level of knowledge of programming in native languages (pointers etc.), whether you will be able to use all correctly. The best bet for you would be to forget about .NET for a while and point to C/C++, because all we suggested here is MDL - not DGN COM Object.

    But if your pointer knowledge is good, following is the way to get dgnBufP in C#:

    [DllImport("kernel32.dll", SetLastError = true)]
    internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr GetModuleHandle(string lpModuleName);

    IntPtr dgnBufPointer()
    {
      IntPtr ustndll = GetModuleHandle("ustation.dll");

      if (ustndll != null)
      {
        IntPtr dgnBufPAddr = GetProcAddress(ustndll, "dgnBufP");
        if (dgnBufPAddr != null)
        {
          return Marshal.ReadIntPtr(dgnBufPAddr);
        }
      }

      return IntPtr.Zero;

    }

    Then to get dgnBuf use:

    IntPtr dgnBufP = dgnBufPointer();
    IntPtr dgnBuf = Marshal.ReadIntPtr(dgnBufP);

    HTH, Dan

     

  • Nice one Dan, cheers.

    Errrrrrrrrrrrrrrrrrrrrrrrrrrrrrm, dgnBuf??? What on earth is dgnBuf? Another cryptic microstation tag-along that the developers have not yet managed to factor out?

    Hehe, no, seriously, what is dgnBuf? More importantly, will I find all your suggestions in the .NET (or as Jon would say - VB COM interop) API's?

    Time for sleep now, 12pm in london, yawn!

  • John

    my parametric application is not like the one you think of, in fact it is a parametric part-builder for complex things (like a whole side of a building), but it has a strong alphanumerical component. Imagine a 3D office inventar, you can build up everything.

    At some time we wanted tables and chairs to keep their formation, i.e. when you move them, but on the other hand let each of them be touchable as single element. This is something you can achive with groups (named and unnamed) and the group lock (move single or all), but after copying the whole group the named group is gone (the numbered groups mostly stay).

    Meanwhile and after talking to our customers we decided to let this functionality stay as it is and use some other ways of filtering, accessing and grouping objects. There are sometimes different views at the importance of this and that in the view of a developer and a customer :)

    For real time changes the dependency API is worthless (as Jon said), but maybe you like to restrict changes to your elements and those you depend on, then it is really a good choice.

    Michael

  •  

    Jon Summers:
    Take the tag functionality as an example: tag an element, then move that host element. The tags move only after you've provided a datapoint; they don't move while you move the host element.  In developer terminology, they don't update during dynamics events.

    OK, so they don't move because dynamics makes a copy of element, so the only way would be somehow monitor changes on dgnBuf and handle them together with all previously suggested stuff...

     

    John:

    You can try this:

    • register global input monitor
    • handle all changes on dgnBuf
    • or if you are not familiar with global input monitoring
    • if incomming command is modifier, save dgnBuf state and wait for input
    • if input begins with datapoint, start view motion callback (monitores same cursor moves as dynamics)
    • get element from dgnBuf and if it is different from saved state modify all another dependent elements
    • for mouse position in world coordinates use mdlSystem_getCursorPosition and correct transform
    • on each another datapoint check dgnBuf state, still global input monitor lets you know all needed

    Dan

  • Dan: Why to do it like this if there is dependency API made for it?

    The Dependency API provide post-change notification that something happened to another element. It doesn't tell that something is happening now, which is what John wants.

    [Edit] Take the tag functionality as an example …

    MicroStation V8i

    Tag an element, then move that host element. The tags move during dynamics. The move command has been enhanced to pick up dependent elements before showing them dynamically.

    MicroStation V8.5

    Tag an element, then move that host element. The tags move only after you've provided a datapoint; they don't move while you move the host element.  In developer terminology, they don't update during dynamics events.

    Regards, Jon Summers
    LA Solutions

  • johnds:
    What I found very usefull, and in fact I could'nt have done without it, is that your acad plugin can tell acad that you want to monitor ALL mouse events, and therefore, whenever an acad entity gets modified (for e.g you drag a handle), you can then intruct all associated geometry to update itself based on whatever parametric constrains you may have attached to it- in real time.

    This is also possible in MicroStation, you can set mdlView_setFunction + VIEW_MOTION / VIEW_NOMOTION in combination with mdlSystem_getCursorPosition, mdlInput_waitForMessage or mdlInput_setFunction to know what command is now active and so on...

    But why to do it like this if there is dependency API made for it?

    Dan

  • Yeah, youre correct, dependency != parametrics.

    What I was hoping, after you suggested looking at the Dep api, was hopefully to leverage whatever functionality it may already have, and build on it.

    But it seems that all parameric logic will have to be done by me, which I dont mind doing, I had just thought that there may be a system inplace already that I could make use of.

    Thoughts?

    John

  • Thanks for the info Michael,

    It's interesting you say you have developed your own parametric elements for many years, but it seems you have encountered some difficulty in doing so, I suppose to a legacy of a 'progressing' Microstation.

    I have already developed a Parametric system for Autocad (well, I was until I got fedup with acad's terrible rendering capabilities and even worse export functionality).

    However, all the parametric logic controlling the acad geometry was completely written by me, no use of internals whatsoever.

    What I found very usefull, and in fact I could'nt have done without it, is that your acad plugin can tell acad that you want to monitor ALL mouse events, and therefore, whenever an acad entity gets modified (for e.g you drag a handle), you can then intruct all associated geometry to update itself based on whatever parametric constrains you may have attached to it- in real time.

    So this happens without having to firstly invoke some 'edit' command of my own creation.

    This is all done using the .net api too, so really easy peasy (no offense to c/c++ guys).

    Now, it is this functionality which I am trying to emulate in MS, which I hope is possible, otherwise my plugin will have to have it's own 'move' or 'modify' commands where i can use the IPrimitiveComandEvents blah blah interfaces to track 'dynamics' events.

    Hehe, oh happy days.

    John.

  • Dependency != Parametrics

    John: I think I shall veer completely off the Dependency path given its current limited 'parametric' functionality

    If what you want is parametrics, then the Dependency API is a red herring. MicroStation has provided Dimension-Driven-Design (AKA parametrics or DDD) and an API for a long time. The API for DDD is provided by the mdlCons_xxx and mdlVar_xxx interfaces.

    Regards, Jon Summers
    LA Solutions

  • John

    As one of the guys who has done some development with the dependencies, I would suggest to use it, as long a you really like to keep things together but as separated elements :). It's the only way to keep your elements from being touched by mistake without your app loaded or informed.

    Your best bet for your own relations is to keep an eye at the Element-Id's, but you will be left alone if someone touches the elements in a kind that those Element-Id's are changed.

    I've developed my own parametric elements now for over 10 years - in the end I still live with nested cells in combination with user-linkages, XML-fragments and dependencies.

    I still use dependencies to prevent my elements, but give up the try to implement a functionality that keeps (nested) named groups after copying them - a feature that  I missed. The problems why I gave up, are not the dependencies, but the complexity of managing the nested groups and the number of callbacks that where called when creating all the needed new groups. I even had to manage the updates of 'my' elements, so that they reappear in the correct named group. In the end I even brought that into my cell management and ended up with one nesting possibility more (with some additional complexity to searches through the cell). But as you mentioned you don't want to merge the elements, this is even necc. if someone else should be able to touch them. But exactly then you need to be informed.

    You could track all commands and element changes,but sometimes you will only be informed that 'your' element is about to be deleted - can you decide if it is replaced by another one and which one ?

    Not an easy stuff, in each case I suggest doing your development in a native code (C++) app, to be not to far from MDL and MicroStationAPI

    Michael

  • Jon: I haven't suggested that Tags are what you want: I cited tags as an example of the Dependency API in action.

    Jon, I never implied that that is what I thought you were suggesting! I think you need to liven up a little, and stop being so

    pedantic. Anyway, before I stray off the original forum topic...Geeked

    I think I shall veer completely off the Dependency path, and do it all myself, as I had done in Autocad, given it's current limited 'parametric' functionality.

    Thanks for all the info so far.

    John.

  • John: Tags are not what I want, but I will see what this Dependency API is all about

    I haven't suggested that Tags are what you want: I cited tags as an example of the Dependency API in action. Dependencies are used in many areas of MicroStation V8, including but not limited to …

    • Tags
    • Dimensions
    • Associative Patterning

    History

    Dominic: it looks like the callback functions were developed for associative elements like dimensions early on, and later revamped for V8, when the Dependency Manager appeared

    MicroStation/J had several technologies that grew independently, such as tags & dimensions. Those technologies added a 32-bit association ID to elements so that the relationships could be coordinated. The APIs were fragile because the association ID could inadvertently become lost or duplicated.

    Bentley developed the Dependency Manager as part of V8 to provide a uniform approach to managing relationships between elements. V8 also introduced the 64-bit element ID as part of each & every element, not an afterthought as was the association ID.

    By publishing the Dependency API Bentley make it possible for developers to use the same logic. However, to judge from the limited number of questions posted about the Dependency API, few developers have ventured along this path.

    Regards, Jon Summers
    LA Solutions

  • Dominic: But, instrumentation control and data acquisition are...

    Interesting though this conversation may be, it's veered far off the original topic of this thread.

    You may want to post to a more appropriate Forum.

    Regards, Jon Summers
    LA Solutions

  •  

    Yes.. But, instrumentation control and data acquisition are only one side of what NI does. Check out their development tools based on 'G', a visual dataflow programming language originally developed for the Macintosh as far back as 1986. Apparently, Lego Mindstorms NXT was based on 'G'. NI has developed tools for multiple programming approaches. Modelica is also another programming language / platform that is popular in the simulation world.

    Simulation platforms have been dealing with componentising objects and behaviours, hierarchial models / solvers, multi-domain design, ETO-style port-based modeling, digital mockups, KBE ... etc for a comparatively long time, even before dotNet and Java.

     

     

  • National Instruments, Inc

    Dominic: I was amazed to find out that LabView is a $600m company. Anyone have experience with LabView?

    LabVIEW™ is a product — the vendor is National Instruments They've been around for about as long as Bentley Systems. Their speciality is instrumentation control and data acquisition.

    Regards, Jon Summers
    LA Solutions

  • Dependency-Example.zip

    Hi All,

    Trawling through past posts that mention 'dependency API' it looks like the callback functions were developed for associative elements like dimensions early on, and later revamped for V8, when the Dependency Manager appeared. See attached zip.

    At the moment, we have the beginnings of pervasive end-user programming (spearheaded by GC, and even Design++?), a lot more dynamic relationships between elements, either in the form of 1/. Graphic to graphic: Dynamic Views, GC symbolic views, XFM,  geometric constraints modeling in PowerCivils 2/. Graphic to non-graphic: To support bi-directional parametric updates between schedules and graphics, hot links between structural design and analysis apps, energy modeling feedback. etc 3/. Non-graphic to non-graphic: ProjectWise dependency tracking, OpenPlant data integration...Promis-E  associated document tracking...

    Managing change propagation is nothing new to coders, but how will end-user programming be integrated into the mix?

    GC's data modeling constructs are being embedded into the dgn. The last standalone version 8.11.8.202 has an interesting dialogue "Parametric Modeling (PM) Settings" that appears to give the user the option to control the propagation / dependencies between elements.  At the moment, if you dimension a GC construct associatively, Mstn bombs when there is a change. Apparently, the shadowy Bentley Interoperability Platform are working on gluing everything together, and the end user programming bits will be able propagate to and from the Bentley bits, in due course.

    MDL-only API: I guess this should change? I wonder how this is going to be implemented across the managed / non-managed code gulf. Will all Mstn elements like associative dimensions, patterns, feature solids etc be re-written as GC features? I guess that the Dependency API would become part of GC's DAG transaction manager? Will there need to be an overarching D-Cubed-style two-pass constraints manager that decides which order the dependency chains are fired, and on which core ? Will Garbage Collection / undo's / transactions need to be updated to cater for data modeling and well as the normal event-based scenario? The whole dotNet reflection, wrappers, Interops, overloading stuff seems like a huge uncharted 'no man's land' where a lot of grown men are on their knees poking the spot in front of them with a bayonet, hoping not to hit a mine.

    Hopefully, Bentley will be more transparent than Revit. Looking at some of the forum discussions, the dependency mechanism is not very well documented and a lot of plugin developers manage their dependencies independently, especially to avoid the dreaded 'regen all'. I hear CATIA is similarly opaque about its dependency management . Maybe things will be simpler with DAG-based tools like Grasshopper (and GC). GH is integrating its SDK into RhinoCommon for V5. GH is also interesting as it licences components from QuantumWhale, which is due incorporate LINQ . Who knows? Maybe T-Splines, RhinoDirect, RhinoParametrics and RhinoBIM will be able to feed off each other and allow the user to modify objects produced by the other plugins without losing their design intent / behaviour. I.e. no return to the old 'zombie' artifact days. Hello synergistic Interoperability.

    I was amazed to find out that LabView is a $600m company. They seem to be a pioneering force as far as integrating end-user programming (using visual programming interfaces, state charts etc) and professional coding, data modeling and even parallel processing. Anyone have experience with LabView? Or MZ-Platform?

     

    Dominic

     

     

     

     

  • John: How would you even monitor every command?

    mdlInput_setMonitorFunction

    Regards, Jon Summers
    LA Solutions

  • Thanks Jon, I will take a look at the Dependency API, and try find this box demo.

    Tags are not what I want, but I will see what this Dep API is all about.

    Cheers.

  • Dependency API

    John: I would like to be able to 'connect' element A to element B, so that when element B gets moved or modified, then element A goes along with it

    That's a different question, the answer to which is the MDL Dependency API. For an example, look at tags. Define a tag set, tag an element, then move that element. The tags move with the host.

    You can achieve the same using the MDL Dependency API. Mark Anderson provided an example some years ago called BoxDemo.

    Regards, Jon Summers
    LA Solutions

  • Yeah, but then the elements would move as a 'whole', and I dont want that.

     I also want to allow the user to modify any number of connected elements 'individually', and have the rest of the connected elements 'react' to those changes. See what I mean?

    Kinda like what GC does.

  • How would you even monitor every function?

  • johnds:
    I would like to be able to 'connect'  element A to element B, so that when element B gets moved or modified, then element A goes along with it, in real time.

    How about to add those connected elements into cell or graphic group?

    Dan

  • I think it would be easier to write your own "extended move function" then to monitor every function in MicroStation, that could move an element.

  • Hmmm, well, I would like to be able to 'connect'  element A to element B, so that when element B gets moved or modified, then element A goes along with it, in real time.

    Is this possible in MS?

    cheers

    John.

  • AFAIK there's no way to intercept the dynamics event of another MDL task.

    Why do you want to do that?

    Regards, Jon Summers
    LA Solutions

  • Hi Jon,

    Thanks for the info, however, the Dynamics events interfaces, as far as I understand it, only work for commands YOU intend on implementing. What I want to know is, how can I be notified when an element is being changed, by say, one of Microstations commands, like Move, for example, not one of my commands.

    So, if you have a line, and you click on it's start point, then move it around, I want my AddIn to know about it, to track that movement, know what I mean?

    Regards

    John.

  • Dynamics Events

    In MicroStation terminology, you are asking about dynamics events. As the user provides data points and moves the cursor, MicroStation's primitive command state machine provides the information you want.

    It looks like you are interested in the VBA events, so I suggest you look at the documentation about IPrimitiveCommandEvents and ILocateCommandEvents. Each provides a _Dynamics event callback.

    Model Change Events

    The IChangeTrackEvents notifies you when an element has been added, modified or deleted. Your interpretation is therefore correct.

    It's useful to know, for example, when a shape element has changed. You can measure its area and update a related text or tag element.

    Regards, Jon Summers
    LA Solutions

  • Hi guys,

    Is there a means of tracking the changes being made to an element as hey happen? ie, you click on the start point of a line, say, and as you move it, you get notified (cursor position, the element being changed etc).

    Is this possible?

    I know of the IChangeTrackEvents interface, but I think that only pre/post notifies you of a change event, but not as it happens (dragging etc).

     

    Regards

    John.

Page 1 of 1 (30 items)