= !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 [wiki:MapGuideRfcs RFCs] page.
== Status ==
||RFC Template Version||(1.0)||
||Submission Date||||
||Last Modified||||
||Author||Jackie Ng||
||RFC Status||draft||
||Implementation Status||||
||Proposed Milestone||2.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.
[[Image(selection_ajax.PNG)]]
For Fusion, the round-tripping is even worse:
[[Image(selection_fusion.PNG)]]
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 [http://en.wikipedia.org/wiki/Data_URI_scheme#Web_browser_support 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.6.0 of the QUERYMAPFEATURES operation. v2.6.0 of QUERYMAPFEATURES includes the following extra parameters:
||Name||Description||Required||
||REQUESTDATA||A bitmask indicating the type of information to be returned to the client||Yes||
||SELECTIONCOLOR||The color of the inline selection image||Yes||
||SELECTIONFORMAT||The format of the inline selection image||No||
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.
A rectangular selection query (assuming no support for data URIs) would look like this (note the value of REQUESTDATA):
{{{
OPERATION:QUERYMAPFEATURES
VERSION:2.6.0
PERSIST:1
MAPNAME:Sheboygan
SESSION:2da80b84-b5a1-11e2-8000-080027004461_en_MTI3LjAuMC4x0B060B050B04
SEQ:0.5907083495985717
LAYERNAMES:Parcels
GEOMETRY:POLYGON((-87.71863496334385 43.74829197543962, -87.71830632635577 43.74829197543962, -87.71830632635577 43.747986812522115, -87.71863496334385 43.747986812522115, -87.71863496334385 43.74829197543962))
SELECTIONVARIANT:INTERSECTS
CLIENTAGENT:Ajax Viewer
REQUESTDATA:1
SELECTIONCOLOR:0x0000FFFF
SELECTIONFORMAT:PNG
MAXFEATURES:-1
}}}
Or if the browser supports data URIs (note the value of REQUESTDATA):
{{{
OPERATION:QUERYMAPFEATURES
VERSION:2.6.0
PERSIST:1
MAPNAME:Sheboygan
SESSION:2da80b84-b5a1-11e2-8000-080027004461_en_MTI3LjAuMC4x0B060B050B04
SEQ:0.5907083495985717
LAYERNAMES:Parcels
GEOMETRY:POLYGON((-87.71863496334385 43.74829197543962, -87.71830632635577 43.74829197543962, -87.71830632635577 43.747986812522115, -87.71863496334385 43.747986812522115, -87.71863496334385 43.74829197543962))
SELECTIONVARIANT:INTERSECTS
CLIENTAGENT:Ajax Viewer
REQUESTDATA:3
SELECTIONCOLOR:0x0000FFFF
SELECTIONFORMAT:PNG
MAXFEATURES:-1
}}}
And produces a response like this (without inline selection):
{{{
DiQAAA==
_MgLayerNamestringParcels_MgFeatureBoundingBoxstring-87.719208640129452 43.747730625310957 -87.71745819670727 43.748609259038986Description1stringORIG. PLATZonestringEXMAcreagestring3.21Lot DimensionsstringIRREGOwnerstringCITY OF SHEBOYGANDescription2stringALL OF BLOCKS 186 & 187, ANDDescription3stringVACATED S. 11TH ST. BETWEENBilling Addressstring828 CENTER AVELot Size (SqFt)string140000Description4stringSD BLOCKS, EXCEPT THE W 10'
}}}
And a response like this (with inline selection):
{{{
DiQAAA==
image/png
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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAZ/gMIpdt1/ZbrLQAAAABJRU5ErkJggg==
_MgLayerNamestringParcels_MgFeatureBoundingBoxstring-87.719208640129452 43.747730625310957 -87.71745819670727 43.748609259038986Description1stringORIG. PLATZonestringEXMAcreagestring3.21Lot DimensionsstringIRREGOwnerstringCITY OF SHEBOYGANDescription2stringALL OF BLOCKS 186 & 187, ANDDescription3stringVACATED S. 11TH ST. BETWEENBilling Addressstring828 CENTER AVELot Size (SqFt)string140000Description4stringSD BLOCKS, EXCEPT THE W 10'
}}}
A tooltip/hyperlink query, would look like this:
{{{
OPERATION:QUERYMAPFEATURES
VERSION:2.6.0
PERSIST:0
MAPNAME:Sheboygan
SESSION:c46f34fc-b5a1-11e2-8000-080027004461_en_MTI3LjAuMC4x0B060B050B04
SEQ:0.03694401495158672
LAYERNAMES:Islands,Hydrography,CityLimits,Parcels,Roads
GEOMETRY:POLYGON((-87.72742956817393 43.74290470419973, -87.72740966091371 43.74290470419973, -87.72740966091371 43.7428847969395, -87.72742956817393 43.7428847969395, -87.72742956817393 43.74290470419973))
SELECTIONVARIANT:INTERSECTS
MAXFEATURES:1
LAYERATTRIBUTEFILTER:5
REQUESTDATA:12
CLIENTAGENT:Ajax Viewer
}}}
and produces a response like this (note the lack of attributes. Previously, this was always included whether we wanted it or not):
{{{
Parcel\nName: WHITE, RICHARD\nAddress: 1627 INDIANA AVE
}}}
Inline selection images are rendered out as inline base64 string, inside the element of the 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 element of the 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 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 {{{}}} 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.
Because we have the bounding box of individual features client-side, we gain an additional benefit by eliminating a GETFEATURESETENVELOPE request for the "Zoom to Selection" command, as we can instead compute the aggregate bounding box based on the bounding boxes of our selected features and use that instead for calculating the desired zoom level/location. In fact, the AJAX viewer will get new APIs to access this new information:
{{{
function GetSelectedBounds()
Returns the bounding box of the selected features. Returns null if no features are selected. The box is a Bounds object:
Bounds {
minx; /* The min x coordinate of this bounding box */
miny; /* The min y coordinate of this bounding box */
maxx; /* The max x coordinate of this bounding box */
maxy; /* The max y coordinate of this bounding box */
}
function GetSelectedFeatures()
Returns the selection set including attributes of selected features. The selection set is structured like so:
{
layerName1 : [
{ //feature 1 in layerName1
values: [
{ name: "attribute1", value: "value1" },
{ name: "attribute2", value: "value2" },
{ name: "attribute3", value: "value3" },
...
{ name: "attributeN", value: "valueN" }
]
zoom: { minx: , miny: , maxx: , maxy: }
},
{ //feature 2 in layerName1
values: [
{ name: "attribute1", value: "value1" },
{ name: "attribute2", value: "value2" },
{ name: "attribute3", value: "value3" },
...
{ name: "attributeN", value: "valueN" }
]
zoom: { minx: , miny: , maxx: , maxy: }
},
...,
{ //feature N in layerName1
values: [
{ name: "attribute1", value: "value1" },
{ name: "attribute2", value: "value2" },
{ name: "attribute3", value: "value3" },
...
{ name: "attributeN", value: "valueN" }
]
zoom: { minx: , miny: , maxx: , maxy: }
}
], layerName2 : [
...
],
...,
layerNameN : [
...
]
}
}}}
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.
With these modifications in place, the AJAX Viewer request chain for a single selection looks like this (assuming browser support for data URIs):
[[Image(AjaxViewerAfter.PNG)]]
And the Fusion Viewer request chain for a single selection looks like this:
[[Image(FusionAfter.PNG)]]
The last request is a GETDYNAMICOVERLAYIMAGE request. The reason we cannot currently eliminate the sending of this 3rd request is because the OpenLayers.Layer.MapGuide class is yet not aware of the changes in this RFC.
Modifying OpenLayers.Layer.MapGuide to accept an inline selection image data URI will eliminate the need for this 3rd request.
Similarly, the request to SaveSelection.php may not even be needed either as QUERYMAPFEATURES supports selection set persistence.
Such changes however, are not within the scope of this RFC.
== 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