wiki:MapGuideRfc126

Version 4 (modified by jng, 11 years ago) ( diff )

--

MapGuide RFC 126 - Viewer selection optimization

This page contains a change request (RFC) for the MapGuide Open Source project. More MapGuide RFCs can be found on the RFCs page.

Status

RFC Template Version(1.0)
Submission Date
Last Modified
AuthorJackie Ng
RFC Statusdraft
Implementation Status
Proposed Milestone2.6
Assigned PSC guide(s)(when determined)
Voting History(vote date)
+1
+0
-0
-1
no vote

Overview

This RFC proposes to add a new version of QUERYMAPFEATURES in the mapagent that is designed to eliminate the need for additional round-tripping during selection operations.

Motivation

The current suite of client viewer applications all suffer from inefficent selections due to excessive roundtripping.

For example, the AJAX viewer will fire the following requests for a selection.

AJAX selection requests

For Fusion, the round-tripping is even worse:

Fusion selection requests

So what is the root problem for such excessive round-tripping? The answer is simply that QUERYMAPFEATURES does not fulfill the requirements that our current lineup of client-side viewers are demanding, so we have to make additional requests to other APIs or web extensions glue to work-around the shortcomings of this API. Some examples:

1) Select and give me back attributes of all features? Not possible. QUERYMAPFEATURES can only return attributes for one. That's why the AJAX viewer has to then make an additional call to getselectedfeatures.[php/jsp/aspx] and why Fusion has to make at least 4 extra requests (!!!) through various PHP glue (!!!!!) to get the required attribute information. We have a QueryFeatureProperties API that supposedly does this, but there is no way to tap into this API via the mapagent. We need a mapagent API that can do the query and selection persistence, but be able to give us the attributes of all selected features instead of one.

[Benefit: no additional requests for extra attribute data]

2) QUERYMAPFEATURES also modifies the server-side selection, so it requires a follow-up GETDYNAMICMAPOVERLAYIMAGE request to update the selection image. If we can utilise data URIs to return the actual selection image back inline (as base64 encoded content) as part of the response, this eliminates the extra request for the selection image. Not all browsers support data URIs (a certain browser from Microsoft for example), so we can workaround that by letting the client specify if they want the inline selection image (browsers that support data URIs will say "yes" and those that can't will say "no"). The current state of data URI support can be found here

[Benefit: no additional requests for browsers that support data URIs. Those that don't will fall back to existing behaviour of doing the additional GETDYNAMICMAPOVERLAYIMAGE request.]

3) QUERYMAPFEATURES for tooltip requests doesn't need attribute information, so don't include this information.

[Benefit: Less data through the wire]

Proposed Solution

This RFC introduces a new, enhanced version of QUERYMAPFEATURES that can satisify all of the above requirements, being a one-stop shop of all our viewer selection and tooltip needs. The key features of this API over the previous QUERYMAPFEATURES API is that:

a) the client can specify what bits of information they want. So for the above cases:

1) and 2) wants attribute information, with an inline selection image if they say it is possible 3) Only wants tooltip and hyperlink information

b) If requested, it returns attributes of all selected features instead of one. It turns out, that we already have an existing API in MgRenderingService that gets us half-way there (QueryFeatureProperties). The problem with the current implementation of QueryFeatureProperties is that it only records the layer name for each feature (as a special hard-coded property: _MgLayerName) and does not include other useful information such as the feature's bounding box (needed by the "Zoom to current feature" function of the AJAX viewer property pane). So we will offer a new internal API to MgRenderingService:

class MG_MAPGUIDE_API MgRenderingService : public MgService
{
INTERNAL_API:
    /////////////////////////////////////////////////////////////////
    /// \brief
    /// The QueryFeatureProperties operation identifies those features that
    /// meet the specified spatial selection criteria. This operation
    /// is used to implement WMS feature info and returns property values
    /// for all features which match the spatial query
    ///
    /// \param map
    /// Input
    /// map object containing current state of map.
    /// \param layerNames
    /// Input
    /// Active layer names for which to query features
    /// \param filterGeometry
    /// Input
    /// geometry object specifying the selection area
    /// \param selectionVariant
    /// Input
    /// selection criterion - integer value corresponding to one of
    /// the MgFeatureSpatialOperations values
    /// \param featureFilter
    /// Input
    /// an XML selection string containing the required feature IDs
    /// \param maxFeatures
    /// Input
    /// the maximum number of features to return
    /// \param layerAttributeFilter
    /// Input
    /// bitmask values - 1=Visible, 2=Selectable, 4=HasTooltips
    ///
    /// \return
    /// An MgSelection instance identifying the features that meet the
    /// selection criteria. Returns null if no features are identified.
    ///
    virtual MgBatchPropertyCollection* QueryFeatureProperties(
        MgMap* map,
        MgStringCollection* layerNames,
        MgGeometry* filterGeometry,
        INT32 selectionVariant,
        CREFSTRING featureFilter,
        INT32 maxFeatures,
        INT32 layerAttributeFilter,
        bool bIncludeFeatureBBOX) = 0;
};

The existing public implementation of QueryFeatureProperties will be re-routed into this internal API with bIncludeFeatureBBOX = false to preserve existing response behaviour (for WFS, which uses this API). When bIncludeFeatureBBOX = true, a new _MgFeatureBoundingBox special property is included with each MgPropertyCollection of the MgBatchPropertyCollection that is returned.

To support computation of each feature's bounding box, the existing FeaturePropRenderer needs to be modified as such:

  • The constructor includes a boolean parameter bIncludeFeatureBBOX
  • Overriding the following methods of Renderer, to get and the bounding boxes of each stylized geometry. The FeaturePropRenderer does not actually stylize features per-se, but these methods still get passed the raw geometry that we're interested in for each iteration of the stylization loop.
    • ProcessMarker
    • ProcessPolyline
    • ProcessPolygon
  • The bounding box computation only happens if bIncludeFeatureBBOX = true

A new overload of QueryMapFeatures method will be added to MgHtmlController

class MG_MAPGUIDE_API MgHtmlController : public MgController
{
INTERNAL_API:
    //////////////////////////////////////////////////////////////////
    /// \brief
    /// Processes a QueryMapFeatures request from the Viewer
    ///
    /// \param mapName
    /// Name of the map
    /// \param layer
    /// Layer for which to provide feature descriptions
    /// \param selectionGeometry
    /// Geometry defining which features to select
    /// \param selectionVariant
    /// Specifies how features are selected
    /// \param maxFeatures
    /// Max number of feature descriptions to return
    /// \param persist
    /// Indicates if the returned selection set should be persisted in the session repository
    ///
    /// \return
    /// A byte reader containing the feature info
    ///
    MgByteReader* QueryMapFeatures(
        CREFSTRING mapName,
        MgStringCollection* layerNames,
        MgGeometry* selectionGeometry,
        INT32 selectionVariant,
        CREFSTRING featureFilter,
        INT32 maxFeatures,
        bool persist,
        INT32 layerAttributeFilter,
        INT32 requestData,
        CREFSTRING selectionColor,
        CREFSTRING selectionFormat);
};

This method will be invoked by v2.5.0 of the QUERYMAPFEATURES operation. v2.5.0 of QUERYMAPFEATURES includes the following extra parameters:

NameDescriptionRequired
REQUESTDATAA bitmask indicating the type of information to be returned to the clientYes
SELECTIONCOLORThe color of the inline selection imageYes
SELECTIONFORMATThe format of the inline selection imageNo

This new overload behaves mostly like the original QueryMapFeatures (clearing MgMap changes before API invocation and saving selection if persist = true) with the following differences.

The requestData parameter is a bitmask indicating the information the client viewer requires.

Attributes = 1 InlineSelection = 2 Tooltip = 4 Hyperlink = 8

Thus based on the value of requestData, we do the following:

  • If Tooltip flag set or Hyperlink flag set: Call existing MgRenderingService::QueryMapFeatures and store the result
  • If Attributes flag set: Call new internal MgRenderingService::QueryFeatureProperties and store the result
  • If InlineSelection flag set: Call MgRenderingService::RenderDynamicOverlay for selection only and convert the response to a base64 string

Depending on the requestData masked value, we will have a MgFeatureInformation (containing the tooltip, hyperlink and selection set), a MgBatchPropertyCollection containing the selected feature attributes and a STRING (containing the base64 selection image). Then we construct the appropriate XML response based on what pieces of data we have.

Here's a rectangular selection query would look like this:

TBD

Or if the browser supports data URIs

TBD

And produces a response like this (without inline selection):

TBD

And a response like this (with inline selection):

TBD

A tooltip/hyperlink query, would look like this:

TBD

and produces a response like this (note the lack of attributes. Previously, this was always included whether we wanted it or not):

TBD

Inline selection images are rendered out as inline base64 string, inside the <Content> element of the <InlineSelectionImage> element, avoiding an additional GETDYNAMICMAPOVERLAYIMAGE request. This exploits the new Data URI feature supported by most modern browsers, the AJAX and Fusion viewers can do the capability checks client-side to determine whether to request an inline selection. Attributes of all features are grouped by their respective layer name.

The inline image does not have the mime-type prepended to the string. It is included as a separate <MimeType> element of the <InlineSelectionImage> element. Browsers that can support data URIs can assemble the final data URI from these components. Non-browser clients should be able to have the necessary means to process the base64 content based on the given <MimeType> value.

As a result of this implementation, we are effectively batching up a series of operations server-side that previously would've been done with individual HTTP requests. Doing all this work in one shot eliminates the need for these additional requests.

On the viewer front, although we can't make a true "one size fits all" model that can accommodate both viewers, we can at least provide enough base information in the response for client viewers to reshape and re-project into their desired form. Some client-side processing will be required by both the AJAX and Fusion viewers.

The AJAX viewer will need some slight modifications to deal with the new QUERYMAPFEATURES response as the structure differs from what is returned by getselectedfeatures.[php/jsp/aspx], but the content is the same. Selected features can be grouped by layer name and each individual selected feature has a bounding box for the "Zoom to current feature" function to work. If data URIs are supported, the viewer needs to simply check the content of the InlineSelectionImage property in the response. If it is not empty, it can be assigned straight into the <img> element that holds the selection image, otherwise we proceeed as normal and send off a GETDYNAMICMAPOVERLAYIMAGE request for that image. With the implementation of this RFC, getselectedfeatures.[php/jsp/ajax] will no longer be required and can be removed.

For Fusion, it gets a bit more complicated as it makes various calls to assorted PHP scripts (SaveSelection.php, GetSelectionProperties.php, etc). This asynchronous call chain of PHP scripts needs to be refactored so that it only needs to send the new QUERYMAPFEATURES request and process its response as it does all the things that these PHP scripts were previously needed for. In addition, it's client-side selection structure is radically different from that of the AJAX viewer. Given the very early stage of this RFC, discussion with Fusion developers is needed to determine if the sample responses proposed here is enough to replicate the existing client-side selection model and this RFC will be updated accordingly based on developer feedback.

Implications

This RFC is a mapagent API addition. No existing APIs are affected. No additions are made to the MapGuide Web Extension API.

The AJAX and Fusion viewers will be updated to take advantage of this new version of QUERYMAPFEATURES

Test Plan

Test AJAX and Fusion viewers with sample selections and verify the selection set data matches the previous implementation.

Verify that the invocations of QueryFeatureProperties from WFS does not include our newly introduced special property.

Funding / Resources

Community

Attachments (4)

Download all attachments as: .zip

Note: See TracWiki for help on using the wiki.