Bentley Communities
Bentley Communities
  • Site
  • User
  • Site
  • Search
  • User
  • Welcome
  • Products
  • Support
  • About
  • More
  • Cancel
MicroStation
  • Product Communities
  • More
MicroStation
MicroStation Wiki Writing An MDL Application To Output Custom Placemarks To Google Earth
    • Sign in

    • +MicroStation Wiki
    • +Administration Wiki
    • +Annotations Wiki
    • +Bentley View Wiki
    • +MicroStation PowerDraft
    • -Programming Wiki
      • A class to help create and modify text element
      • A Complete Example
      • A MicroStation VBA Example With Bentley ProjectWise
      • AddIn Development Using VB.NET
      • C# .NET Template with IPrimitiveCommandEvents Class
      • Capturing Graphics in Dynamic Views
      • Compiling MDL Applications
      • Database Manipulation
      • Debugging Native Code MDL Applications
      • Developing Code in VBA
      • Developing MicroStation Applications For DWG Files
      • Drag and Drop in MicroStation
      • Error: "Cannot save changes to VBA project 'Support' because it is read-only"
      • Getting And Setting Elements Using Graphic Groups In VBA [CS]
      • Getting Started with Visual Basic
      • How To Write A Recursive Routine In MicroStation VBA [CS]
      • Introducing Segment3D Methods In MicroStation V8 2004 Edition
      • Known issues in MDL and MicroStationAPI
      • Launching VBA Applications As Initapps Or Dgnapps [CS]
      • Learning MicroStation Addins Step by Step
      • MDL - Getting Started With XAttributes In MicroStation V8 XM Edition
      • MDL - Native Code Application Development
      • MDL Or MicroStation BASIC Choosing The Right Tool [TN]
      • MFC Dialog And Native Window Support
      • Microsoft Office VBA Patch Utility
      • MicroStation BASIC FAQ
      • MicroStation BASIC Limits [FAQ]
      • MicroStation Developer Documentation and Example Code
      • MicroStation Programming Advice
      • MicroStation SDK
      • MicroStation V8 Programming Tools Readme
      • MicroStation V8 VBA Programming Resources [CS]
      • MicroStation V8 XM Edition View Code Updates
      • MicroStation VBA Resources Revisited [CS]
      • Migrating Dimension Code To MicroStation V8
      • Migrating MDL Applications To Native Code
      • Mouse Wheel Events And The Visual Basic 6.0 IDE
      • Porting MDL Applications To MicroStation V8
      • Reading Elements From A Microsoft Access Database With VBA [CS]
      • Running MDL Applications
      • Scanning For MicroStation V8 Elements In VBA [CS]
      • Unleash A Workspace Wizard Automating Workspace Creation With MicroStation V8 And VBA [CS]
      • Using VBA To Detect The Current Or Last Used Command
      • Using VBA To Programmatically Export A VBA Project [CS]
      • Using VBA To Programmatically Import A VBA Projects Components And References [CS]
      • VBA -- Creating A Complex Application
      • VBA Interface Error: failed creating the comp manager - 0x80040583
      • VBA interface error: unable to get IDE
      • vba recording
      • Working With Levels In MicroStation VBA [CS]
      • Writing An MDL Application To Output Custom Placemarks To Google Earth
      • [V8i C++] PointCloud IPointCloudChannelDisplayHandler
    • +Visualization Wiki

     
     Questions about this article, topic, or product? Click here. 

    Writing An MDL Application To Output Custom Placemarks To Google Earth

    Writing your own method to transfer MicroStation data to Google Earth is relatively easy and straightforward. Google Earth reads in data from the KML format, a variety of XML, or from the KMZ format, which is simply a zipped KML file. All that is needed to export to either format is to call mdlKml_exportToFile(), which can be found in kmlexport.fdf along with MicroStation's other functions for dealing with Google Earth. This article offers a quick introduction to using mdlKml_exportToFile().
    Step One: Basic export to Google Earth

    First, we will create and initialize our IKmlCoordinateRemapper object. This object is used to translate between MicroStation UORs and the WGS84 coordinates that Google Earth uses. If the remapper cannot be initialized, the design file has not been geolocated and cannot be exported to Google Earth. Thus, it is a good idea to always make initializing the remapper one of the first steps in your application.


        IKmlCoordinateRemapperP    pRemapper;
        if (SUCCESS != mdlKml_getRemapper (&pRemapper, MASTERFILE))
            return;

     

     


    Next, we load the user's default Google Earth export settings and grab a handle on the user's resource file.


        KmlExportSettings  settings;
        mdlKml_getDefaultExportSettings (&settings);

        RscFileHandle              rscHandle;
        mdlResource_openFile (&rscHandle, NULL, FALSE);

     


    With that done, we get the user's currently selected MicroStation view to use as our Google Earth file's default view.


        int viewToExport = mdlWindow_getSelectedViewIndex ();

     


    Next, we define the filename and location for our Google Earth file. The filename used determines whether the Google Earth file is output as a compressed KMZ archive or an uncompressed KML file. KMZ is the recommended output format because the files are exponentially smaller and KMZ files can contain their associated raster data and link icons, making them more portable.


        char const*         fileName = "C:\\Example.kmz";


    Finally, we define a name and description for our example file, then call mdlKml_exportToFile() with the values we have just defined. Do not concern yourself with the null value -- that is just a placeholder for the deprecated KmlExportStatistics object.


        MSWChar const*      wName    = L"Example";
        MSWChar const*      wDescr   = L"An example KMZ file.";
        mdlKml_exportToFile (fileName, wName, wDescr, NULL, MASTERFILE, &settings, pRemapper,
                             viewToExport, rscHandle);


    After making this call, Example.kmz should be created and ready to go -- all that is left is to clean up after ourselves by freeing the remapper and resource file handle.


        mdlKml_freeRemapper (&pRemapper);
        mdlResource_closeFile (rscHandle);

     


    Step Two: Creating a custom placemark provider

    With the basics covered, we can now move on to the slightly more complex topic of creating custom Google Earth placemarks based on MicroStation element data. The IKmlElementPlacemarkProvider interface exists for this purpose. In order to use it, we only need to implement the ProvideElementPlacemark method and provide correct values for pName, pDescription, and pLocation. If any of the icon variables are left null, the default icon style will be used.

    The following example implementation scans each element for Engineering Link information and if it is found, fills in the fields necessary to generate a placemark. It also uses Google Earth's capability to use custom icons for different placemarks.


    /*===============================================================**//**
    * @bsiclass                                    BSI           04/06
    +================+==============+==============+=============+=======*/
    class ExamplePlacemarkProvider : public IKmlElementPlacemarkProvider
    {
    public:
    /*---------------------------------------------------------------**//**
    * @bsimethod                                   BSI           04/06
    +----------------+--------------+--------------+-------------+-------*/   
    virtual bool ProvideElementPlacemark
    (
    MSWChar*        pName,              /* <= Name for the new placemark */
    MSWChar*        pDescription,       /* <= Description for the new placemark */
    DPoint3d*       pLocation,          /* <= Placemark location in UORs */
    int*            pIconX,             /* <= X coordinate for placemark icon */
    int*            pIconY,             /* <= Y coordinate for placemark icon */
    int*            pIconWidth,         /* <= Width of placemark icon */
    int*            pIconHeight,        /* <= Height of placemark icon */
    double*         pIconScale,         /* <= Scale of placemark icon and its label text */
    char*           pLinkIconFileName,  /* <= Location of the icon file */
    MSElementDescrP pElement            /* => Current element */
    )
        {
        char        description[1024], url[1024], string[4096];
        // Find an Engineering Link attached to the element.
        if (mdlTag_extractURL (url,
                               description,
                               const_cast <MSElementP> (&pElement->el),
                               (pElement->h).dgnModelRef))
            {
            // Fills in the same name and target values for the new placemark as the
            // Engineering Link.
            sprintf (string, "<a href=\"%s\">%s</a>", url, description);
            mdlCnv_convertMultibyteToUnicode (description, -1, pName, 1024);
            mdlCnv_convertMultibyteToUnicode (string, -1, pDescription, 1024);
            // Gets the element's location in UORs.
            DVector3d range;
            mdlElement_extractRange (&range, &pElement->el);
            mdlVec_addPoint (pLocation, &range.org, &range.end);
            mdlVec_scale (pLocation, pLocation, .5);
            // Helper function to acquire icon information for the new placemark.
            GetIcon (url, pIconX, pIconY, pIconWidth, pIconHeight, pIconScale,
                     pLinkIconFileName);
           
            // Return true to inform the exporter that a placemark should be generated for
            // this element.
            return true;
            }
        // Return false to inform the exporter that a placemark should not be generated for
        // this element.
        return false;
        }

    /*---------------------------------------------------------------**//**
    * @bsimethod                                   BSI           04/06
    +----------------+--------------+--------------+-------------+-------*/   
    void GetIcon
    (
    char*               url,                /* => Link URL */
    int*                pIconX,             /* <= X coordinate for icon
                                                  Distance from left most edge in pixels */                   
    int*                pIconY,             /* <= Y coordinate for icon
                                                  Distance from bottom most edge in pixels */
    int*                pIconWidth,         /* <= Width of icon in pixels */
    int*                pIconHeight,        /* <= Height of icon in pixels */
    double*             pIconScale,         /* <= Scale of icon */
    char*               pLinkIconFileName   /* <= Location of the icon file */
    )
        {
        struct  PlacemarkIcon
            {
            char        m_extension[MAXEXTENSIONLENGTH];
            int         m_iconIndexX;       /* X index of icon from left most edge */
            int         m_iconIndexY;       /* Y index of icon from bottom most edge */
            };
        PlacemarkIcon   extensionIcons[] =
            {
            {"url", 5, 7},
            {"dgn", 0, 7},
            {"jpg", 6, 7},
            {"gif", 6, 7},
            {"tif", 6, 7},
            {"gif", 6, 7},
            {"doc", 3, 7},
            {"pdf", 2, 7},
            {"mpg", 7, 7},
            {"wav", 8, 7},
            {"mp3", 8, 7},
            {"xls", 4, 7},
            {"dwg", 1, 7},
            {"dxf", 1, 7},
            };
        int         iconIndex = 0;
        char        extension[MAXEXTENSIONLENGTH];
        extension[0] = '\0';
        mdlFile_parseName (url, NULL, NULL, NULL, extension);
       
        // Find an icon appropriate for the link's file extension.  Default to
        // "url" if extension is not found.
        if (0 != strlen (extension))
            {
            for (int i=0; i < sizeof (extensionIcons)/sizeof (PlacemarkIcon); i++)
                {
                if (0 == strcmpi (extension, extensionIcons[i].m_extension))
                    {
                    iconIndex = i;
                    }
                }
            }
        // MicroStation's default custom placemark icons file. 
        // Distributed in Workspace\System\Image, so a relative path is OK.
        sprintf (pLinkIconFileName, "GELinkIcons.png");
        // Height and width of each icon in pixels
        *pIconWidth = 32;
        *pIconHeight = 32;
        // Translate the index of the icon to be used into pixel coordinates.
        *pIconX = extensionIcons[iconIndex].m_iconIndexX * *pIconWidth;
        *pIconY = extensionIcons[iconIndex].m_iconIndexY * *pIconHeight;
        // 1.0 is the default icon scale, but 0.7 is readable without being obnoxious.
        *pIconScale = .7;
        }
    );  // ExamplePlaceMarkProvider 

     

    Step Three: Tying it all together

    Now that the placemark provider has been written, we can register it with the Google Earth exporter and translate our MicroStation document along with its link to KML. To do this, we need to declare a pointer to our provider, then pass that pointer to mdlKml_registerElementPlacemarkProvider() to inform the exporter that we have a callback method.


        ExamplePlacemarkProvider*   pPlacemarkProvider;
        pPlacemarkProvider = new ExamplePlacemarkProvider;
        mdlKml_registerElementPlacemarkProvider (pPlacemarkProvider);

     

     


    After calling, mdlKml_exportToFile(), our placemark provider should be processed and a Google Earth file created. Once this has happened, the placemark provider should be unregistered using mdlKml_unregisterElementPlacemarkProvider().


        mdlKml_unregisterElementPlacemarkProvider (pPlacemarkProvider);
        delete pPlacemarkProvider;

     

     


    The entire resulting function can be seen below:


    void myGoogleEarthExport ()
        {
        IKmlCoordinateRemapperP    pRemapper;
        if (SUCCESS != mdlKml_getRemapper (&pRemapper, MASTERFILE))
            return;
        KmlExportSettings  settings;
        mdlKml_getDefaultExportSettings (&settings);
        RscFileHandle              rscHandle;
        mdlResource_openFile (&rscHandle, NULL, FALSE);
        int viewToExport = mdlWindow_getSelectedViewIndex ();    char const*         fileName = "C:\\Example.kmz";
        MSWChar const*      wName    = L"Example";
        MSWChar const*      wDescr   = L"An example KMZ file.";
        ExamplePlacemarkProvider*   pPlacemarkProvider;
        pPlacemarkProvider = new ExamplePlacemarkProvider;
        mdlKml_registerElementPlacemarkProvider (pPlacemarkProvider);
        mdlKml_exportToFile (fileName, wName, wDescr, NULL, MASTERFILE, &settings, pRemapper,
                             viewToExport, rscHandle);
        mdlKml_unregisterElementPlacemarkProvider (pPlacemarkProvider);
        delete pPlacemarkProvider;
           mdlKml_freeRemapper (&pRemapper);
        mdlResource_closeFile (rscHandle);
        }

     

    • Share
    • History
    • More
    • Cancel
    • Dan Koval Created by Bentley Colleague Dan Koval
    • When: Thu, Sep 5 2013 4:32 PM
    • Revisions: 1
    • Comments: 0
    Recommended
    Related
    Communities
    • Home
    • Getting Started
    • Community Central
    • Products
    • Support
    • Secure File Upload
    • Feedback
    Support and Services
    • Home
    • Product Support
    • Downloads
    • Subscription Services Portal
    Training and Learning
    • Home
    • About Bentley Institute
    • My Learning History
    • Reference Books
    Social Media
    •    LinkedIn
    •    Facebook
    •    Twitter
    •    YouTube
    •    RSS Feed
    •    Email

    © 2021 Bentley Systems, Incorporated  |  Contact Us  |  Privacy |  Terms of Use  |  Cookies