[mapguide-commits] r7470 - in sandbox/jng/queryfeatures_v2: Common/MapGuideCommon/Controller Common/MapGuideCommon/Services Server/src/Services/Rendering Server/src/UnitTesting Web/src/HttpHandler

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Fri May 3 13:30:42 PDT 2013


Author: jng
Date: 2013-05-03 13:30:42 -0700 (Fri, 03 May 2013)
New Revision: 7470

Modified:
   sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Controller/HtmlController.cpp
   sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Controller/HtmlController.h
   sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/ProxyRenderingService.cpp
   sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/ProxyRenderingService.h
   sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/RenderingDefs.h
   sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/RenderingService.cpp
   sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/RenderingService.h
   sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/FeaturePropRenderer.cpp
   sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/FeaturePropRenderer.h
   sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/OpQueryFeatureProperties.cpp
   sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/RenderingOperationFactory.cpp
   sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/ServerRenderingService.cpp
   sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/ServerRenderingService.h
   sandbox/jng/queryfeatures_v2/Server/src/UnitTesting/TestRenderingService.cpp
   sandbox/jng/queryfeatures_v2/Web/src/HttpHandler/HttpQueryMapFeatures.cpp
   sandbox/jng/queryfeatures_v2/Web/src/HttpHandler/HttpQueryMapFeatures.h
   sandbox/jng/queryfeatures_v2/Web/src/HttpHandler/HttpResourceStrings.cpp
   sandbox/jng/queryfeatures_v2/Web/src/HttpHandler/HttpResourceStrings.h
Log:
This submission contains the following changes:
 - Add a new overload of QueryFeatureProperties to MgRenderingService with an extra parameter (bIncludeFeatureBBOX). If true, each feature will have an extra _MgFeatureBoundingBox property which contains the bounds of the feature (computed from the FeaturePropRenderer)
 - Add a new overload of QueryMapFeatures to MgHtmlController, with the following extra parameters:
   - requestData: A bitmask indicating what parts of the QueryMapFeatures response we would like
   - selectionColor: The color of the inline selection if requested in the requestData bitmask
   - selectionFormat: The image format of the inline selection if requested in the requestData bitmask
 - Update TestRenderingService::TestCase_QueryFeatures() to actually dump the MgFeatureInformation result to file for manual inspection.

Modified: sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Controller/HtmlController.cpp
===================================================================
--- sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Controller/HtmlController.cpp	2013-05-02 10:57:56 UTC (rev 7469)
+++ sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Controller/HtmlController.cpp	2013-05-03 20:30:42 UTC (rev 7470)
@@ -16,7 +16,13 @@
 //
 
 #include "MapGuideCommon.h"
+#include "Base64.h"
 
+#define REQUEST_ATTRIBUTES       1
+#define REQUEST_INLINE_SELECTION 2
+#define REQUEST_TOOLTIP          4
+#define REQUEST_HYPERLINK        8
+
 //////////////////////////////////////////////////////////////////
 // Construct a MgHtmlController object
 //
@@ -216,6 +222,175 @@
 }
 
 //////////////////////////////////////////////////////////////////
+// Processes a QueryMapFeatures request from the Viewer
+//
+MgByteReader* MgHtmlController::QueryMapFeatures(
+    CREFSTRING mapName,
+    MgStringCollection* layerNames,
+    MgGeometry* selectionGeometry,
+    INT32 selectionVariant,
+    CREFSTRING featureFilter,
+    INT32 maxFeatures,
+    bool persist,
+    INT32 layerAttributeFilter,
+    INT32 requestData,
+    CREFSTRING selectionColor,
+    CREFSTRING selectionFormat)
+{
+    Ptr<MgByteReader> result;
+    Ptr<MgFeatureInformation> featureInfo;
+    Ptr<MgBatchPropertyCollection> attributes;
+    Ptr<MgByteReader> inlineSelectionImg;
+    Ptr<MgSelection> newSelection;
+
+    // Create a Resource Service instance
+    Ptr<MgResourceService> resourceService = (MgResourceService*)GetService(MgServiceType::ResourceService);
+
+    // Create MgMap
+    Ptr<MgMap> map = new MgMap();
+    map->Open(resourceService, mapName);
+
+    // Make sure we clear any track changes - these are not applicable for AJAX.
+    Ptr<MgNamedCollection> changeLists = map->GetChangeLists();
+    if (changeLists->GetCount() > 0)
+    {
+        map->ClearChanges();
+        map->Save(resourceService);
+    }
+
+    // Create Proxy Rendering Service instance
+    Ptr<MgRenderingService> service = (MgRenderingService*)(GetService(MgServiceType::RenderingService));
+
+    //Any of these bits requires a QueryFeatures() call
+    if (((requestData & REQUEST_INLINE_SELECTION) == REQUEST_INLINE_SELECTION) ||
+        ((requestData & REQUEST_TOOLTIP) == REQUEST_TOOLTIP) ||
+        ((requestData & REQUEST_HYPERLINK) == REQUEST_HYPERLINK))
+    {
+        // Call the C++ API
+        featureInfo = service->QueryFeatures(map, layerNames, selectionGeometry,
+            selectionVariant, featureFilter, maxFeatures, layerAttributeFilter);
+    }
+
+    if (persist)
+    {
+        //save the selection set in the session repository
+        Ptr<MgSelection> selection;
+        if (NULL != featureInfo.p)
+            selection = featureInfo->GetSelection();
+        if(!selection)
+            selection = new MgSelection(map);
+        selection->Save(resourceService, mapName);
+        newSelection = SAFE_ADDREF(selection.p);
+    }
+
+    // Render an image of this selection if requested
+    if (((requestData & REQUEST_INLINE_SELECTION) == REQUEST_INLINE_SELECTION) && NULL != newSelection.p)
+    {
+        try
+        {
+            Ptr<MgColor> selColor = new MgColor(selectionColor);
+            Ptr<MgRenderingOptions> renderOpts = new MgRenderingOptions(selectionFormat, MgRenderingOptions::RenderLayers | MgRenderingOptions::RenderSelection | MgRenderingOptions::KeepSelection, selColor);
+            inlineSelectionImg = service->RenderDynamicOverlay(map, newSelection, renderOpts);
+        }
+        catch (MgException* ex)
+        {
+            SAFE_RELEASE(ex);
+        }
+    }
+
+    if ((requestData & REQUEST_ATTRIBUTES) == REQUEST_ATTRIBUTES)
+    {
+        attributes = service->QueryFeatureProperties(map, layerNames, selectionGeometry, selectionVariant, L"", -1, layerAttributeFilter, true);
+    }
+
+    result = CollectQueryMapFeaturesResult(requestData, featureInfo, newSelection, attributes, inlineSelectionImg);
+
+    // Return XML
+    return result.Detach();
+}
+
+MgByteReader* MgHtmlController::CollectQueryMapFeaturesResult(INT32 requestData,
+                                                              MgFeatureInformation* featInfo,
+                                                              MgSelection* selectionSet,
+                                                              MgBatchPropertyCollection* attributes, 
+                                                              MgByteReader* inlineSelection)
+{
+    STRING xml;
+    STRING tooltip;
+    STRING hyperlink;
+    STRING xmlSelection = selectionSet? selectionSet->ToXml(false): L"";
+
+    if (NULL != featInfo)
+    {
+        tooltip = featInfo->GetTooltip();
+        hyperlink = featInfo->GetHyperlink();
+    }
+
+    // TODO: define a schema for this XML
+    xml.append(L"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<FeatureInformation>\n");
+
+    size_t len = xmlSelection.length();
+    if(len > 0)
+    {
+        xml.reserve(len + 2048);
+        xml.append(xmlSelection);
+    }
+    else
+    {
+        xml.reserve(2048);
+        xml.append(L"<FeatureSet />\n");
+    }
+
+    if (((requestData & REQUEST_TOOLTIP) == REQUEST_TOOLTIP) && !tooltip.empty())
+    {
+        xml.append(L"<Tooltip>");
+        xml.append(MgUtil::ReplaceEscapeCharInXml(tooltip));
+        xml.append(L"</Tooltip>\n");
+    }
+    else
+        xml.append(L"<Tooltip />\n");
+
+    if (((requestData & REQUEST_HYPERLINK) == REQUEST_HYPERLINK) && !hyperlink.empty())
+    {
+        xml.append(L"<Hyperlink>");
+        xml.append(MgUtil::ReplaceEscapeCharInXml(hyperlink));
+        xml.append(L"</Hyperlink>\n");
+    }
+    else
+        xml.append(L"<Hyperlink />\n");
+
+    if (((requestData & REQUEST_INLINE_SELECTION) == REQUEST_INLINE_SELECTION) && NULL != inlineSelection)
+    {
+        xml.append(L"<InlineSelectionImage>\n");
+        Ptr<MgByteSink> imgSink = new MgByteSink(inlineSelection);
+        Ptr<MgByte> imgBuffer = imgSink->ToBuffer();
+        string b64;
+        b64.resize(len, '\0');
+        Base64::Encode((char*)b64.c_str(), (const unsigned char*)imgBuffer->Bytes(), imgBuffer->GetLength());
+        STRING wb64 = MgUtil::MultiByteToWideChar(b64);
+        xml.append(L"</InlineSelectionImage>\n");
+    }
+    else
+        xml.append(L"<InlineSelectionImage />\n");
+
+    if (((requestData & REQUEST_ATTRIBUTES) == REQUEST_ATTRIBUTES) && NULL != attributes)
+    {
+        xml.append(L"<Attributes>\n");
+        Ptr<MgByteReader> attrXml = attributes->ToXml();
+        xml.append(attrXml->ToString());
+        xml.append(L"</Attributes>\n");
+    }
+    else
+        xml.append(L"<Attributes />\n");
+
+    xml.append(L"</FeatureInformation>\n");
+
+    string xmlDoc = MgUtil::WideCharToMultiByte(xml);
+    STRING mimeType = L"text/xml";
+    return MgUtil::GetByteReader(xmlDoc, &mimeType);
+}
+
+//////////////////////////////////////////////////////////////////
 // Generates JavaScript code that can be embedded in an HTML response
 // to a non-viewer initiated web application request. The returned code
 // forces a synchronization of the client-side view with any changes made to the Map Model.

Modified: sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Controller/HtmlController.h
===================================================================
--- sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Controller/HtmlController.h	2013-05-02 10:57:56 UTC (rev 7469)
+++ sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Controller/HtmlController.h	2013-05-03 20:30:42 UTC (rev 7470)
@@ -112,7 +112,7 @@
 
     //////////////////////////////////////////////////////////////////
     /// \brief
-    /// Processes a DescribeMapFeatures request from the Viewer
+    /// Processes a QueryMapFeatures request from the Viewer
     ///
     /// \param mapName
     /// Name of the map
@@ -142,6 +142,39 @@
 
     //////////////////////////////////////////////////////////////////
     /// \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);
+
+    //////////////////////////////////////////////////////////////////
+    /// \brief
     /// Processes a GetLayerImageMap request from the Viewer and returns an image map
     /// for the visible features on the specified map layer
     ///
@@ -236,6 +269,16 @@
 
     //////////////////////////////////////////////////////////////////
     /// \brief
+    /// Assembles the composite QueryMapFeatures result
+    ///
+    virtual MgByteReader* CollectQueryMapFeaturesResult(INT32 requestData, 
+                                                        MgFeatureInformation* featInfo,
+                                                        MgSelection* selectionSet,
+                                                        MgBatchPropertyCollection* attributes, 
+                                                        MgByteReader* inlineSelection);
+
+    //////////////////////////////////////////////////////////////////
+    /// \brief
     /// Dispose this object.
     ///
     /// \return

Modified: sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/ProxyRenderingService.cpp
===================================================================
--- sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/ProxyRenderingService.cpp	2013-05-02 10:57:56 UTC (rev 7469)
+++ sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/ProxyRenderingService.cpp	2013-05-03 20:30:42 UTC (rev 7470)
@@ -803,6 +803,72 @@
     return (MgBatchPropertyCollection*)cmd.GetReturnValue().val.m_obj;
 }
 
+/////////////////////////////////////////////////////////////////
+/// \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.
+///
+MgBatchPropertyCollection* MgProxyRenderingService::QueryFeatureProperties(
+    MgMap* map,
+    MgStringCollection* layerNames,
+    MgGeometry* filterGeometry,
+    INT32 selectionVariant,
+    CREFSTRING featureFilter,
+    INT32 maxFeatures,
+    INT32 layerAttributeFilter,
+    bool bIncludeFeatureBBOX)
+{
+    MgCommand cmd;
+    cmd.ExecuteCommand(m_connProp,                                      // Connection
+                        MgCommand::knObject,                            // Return type expected
+                        MgRenderingServiceOpId::QueryFeatureProperties2,// Command Code
+                        8,                                              // No of arguments
+                        Rendering_Service,                              // Service Id
+                        BUILD_VERSION(2,6,0),                           // Operation version
+                        MgCommand::knObject, map,                       // Argument#1
+                        MgCommand::knObject, layerNames,                // Argument#2
+                        MgCommand::knObject, filterGeometry,            // Argument#3
+                        MgCommand::knInt32,  selectionVariant,          // Argument#4
+                        MgCommand::knString, &featureFilter,            // Argument#5
+                        MgCommand::knInt32,  maxFeatures,               // Argument#6
+                        MgCommand::knInt32,  layerAttributeFilter,      // Argument#7
+                        MgCommand::knInt8,   (INT8)bIncludeFeatureBBOX, // Argument#8
+                        MgCommand::knNone);                             // End of arguments
+
+    SetWarning(cmd.GetWarningObject());
+
+    return (MgBatchPropertyCollection*)cmd.GetReturnValue().val.m_obj;
+}
+
 //////////////////////////////////////////////////////////////////
 /// \brief
 /// Sets the connection properties for the Proxy Service.  This
@@ -937,4 +1003,4 @@
     SetWarning(cmd.GetWarningObject());
 
     return (MgByteReader*)cmd.GetReturnValue().val.m_obj;
-}
+}
\ No newline at end of file

Modified: sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/ProxyRenderingService.h
===================================================================
--- sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/ProxyRenderingService.h	2013-05-02 10:57:56 UTC (rev 7469)
+++ sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/ProxyRenderingService.h	2013-05-03 20:30:42 UTC (rev 7470)
@@ -669,6 +669,50 @@
         bool bKeepSelection,
         ProfileRenderMapResult* profileRenderMapResult);
 
+    /////////////////////////////////////////////////////////////////
+    /// \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);
+
 protected:
 
     //////////////////////////////////////////////////////////////////

Modified: sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/RenderingDefs.h
===================================================================
--- sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/RenderingDefs.h	2013-05-02 10:57:56 UTC (rev 7469)
+++ sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/RenderingDefs.h	2013-05-03 20:30:42 UTC (rev 7470)
@@ -39,6 +39,7 @@
     static const int RenderMap4                 = 0x1111E90B;
     static const int RenderDynamicOverlay2      = 0x1111E90C;
     static const int RenderMap5                 = 0x1111E90D;
+    static const int QueryFeatureProperties2    = 0x1111E90E;
 };
 /// \endcond
 

Modified: sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/RenderingService.cpp
===================================================================
--- sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/RenderingService.cpp	2013-05-02 10:57:56 UTC (rev 7469)
+++ sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/RenderingService.cpp	2013-05-03 20:30:42 UTC (rev 7470)
@@ -48,3 +48,16 @@
 {
     delete this;
 }
+
+MgBatchPropertyCollection* MgRenderingService::QueryFeatureProperties(
+    MgMap* map,
+    MgStringCollection* layerNames,
+    MgGeometry* filterGeometry,
+    INT32 selectionVariant,
+    CREFSTRING featureFilter,
+    INT32 maxFeatures,
+    INT32 layerAttributeFilter,
+    bool bIncludeFeatureBBOX)
+{
+    throw new MgNotImplementedException(L"MgRenderingService.QueryFeatureProperties", __LINE__, __WFILE__, NULL, L"", NULL);
+}
\ No newline at end of file

Modified: sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/RenderingService.h
===================================================================
--- sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/RenderingService.h	2013-05-02 10:57:56 UTC (rev 7469)
+++ sandbox/jng/queryfeatures_v2/Common/MapGuideCommon/Services/RenderingService.h	2013-05-03 20:30:42 UTC (rev 7470)
@@ -671,6 +671,50 @@
         bool bKeepSelection,
         ProfileRenderMapResult* profileRenderMapResult) = 0;
 
+    /////////////////////////////////////////////////////////////////
+    /// \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);
+
 protected:
 
     /////////////////////////////////////////////////////////////////

Modified: sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/FeaturePropRenderer.cpp
===================================================================
--- sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/FeaturePropRenderer.cpp	2013-05-02 10:57:56 UTC (rev 7469)
+++ sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/FeaturePropRenderer.cpp	2013-05-03 20:30:42 UTC (rev 7470)
@@ -21,17 +21,22 @@
 #include "FeaturePropRenderer.h"
 #include "RS_FeatureReader.h"
 
+#define SPECIAL_PROP_LAYER_NAME     L"_MgLayerName"
+#define SPECIAL_PROP_BOUNDING_BOX   L"_MgFeatureBoundingBox"
 
-FeaturePropRenderer::FeaturePropRenderer(MgSelection* selection, int maxFeatures, double mapScale)
+FeaturePropRenderer::FeaturePropRenderer(MgSelection* selection, int maxFeatures, double mapScale, bool bIncludeFeatureBBOX)
 : FeatureInfoRenderer(selection, maxFeatures, mapScale)
 {
     m_featprops = new MgBatchPropertyCollection();
+    m_currentFeature = NULL;
+    m_bIncludeFeatureBBOX = bIncludeFeatureBBOX;
 }
 
 
 FeaturePropRenderer::~FeaturePropRenderer()
 {
     SAFE_RELEASE(m_featprops);
+    SAFE_RELEASE(m_currentFeature);
 }
 
 
@@ -69,12 +74,21 @@
     }
     */
 
+    SAFE_RELEASE(m_currentFeature);
     Ptr<MgPropertyCollection> featureProps = new MgPropertyCollection(true, true);
+    m_currentFeature = SAFE_ADDREF(featureProps.p);
 
     //Add the layer name as a property with a special ID
-    Ptr<MgStringProperty> layerNameProperty = new MgStringProperty(L"_MgLayerName", m_layerInfo->name());
+    Ptr<MgStringProperty> layerNameProperty = new MgStringProperty(SPECIAL_PROP_LAYER_NAME, m_layerInfo->name());
     featureProps->Add(layerNameProperty);
 
+    //Add bounding box if we're instructed to
+    if (m_bIncludeFeatureBBOX)
+    {
+        Ptr<MgStringProperty> boundingBoxProperty = new MgStringProperty(SPECIAL_PROP_BOUNDING_BOX, L"");
+        featureProps->Add(boundingBoxProperty);
+    }
+
     //for each property in the property mapping, add to the
     //return property collection
 
@@ -109,3 +123,78 @@
     // set to false to disable processing of hyperlinks
     return false;
 }
+
+void FeaturePropRenderer::ProcessPolygon(LineBuffer*   lb,
+                                         RS_FillStyle& fill)
+{
+    if (!m_bIncludeFeatureBBOX)
+        return;
+
+    const RS_Bounds& featBounds = lb->bounds();
+    Ptr<MgStringProperty> bbox = dynamic_cast<MgStringProperty*>(m_currentFeature->GetItem(SPECIAL_PROP_BOUNDING_BOX));
+    STRING val;
+    STRING buf;
+    MgUtil::DoubleToString(featBounds.minx, buf);
+    val += buf;
+    MgUtil::DoubleToString(featBounds.miny, buf);
+    val += L" ";
+    val += buf;
+    MgUtil::DoubleToString(featBounds.maxx, buf);
+    val += L" ";
+    val += buf;
+    MgUtil::DoubleToString(featBounds.maxy, buf);
+    val += L" ";
+    val += buf;
+    bbox->SetValue(val);
+}
+
+void FeaturePropRenderer::ProcessPolyline(LineBuffer*    lb,
+                                          RS_LineStroke& lsym)
+{
+    if (!m_bIncludeFeatureBBOX)
+        return;
+
+    const RS_Bounds& featBounds = lb->bounds();
+    Ptr<MgStringProperty> bbox = dynamic_cast<MgStringProperty*>(m_currentFeature->GetItem(SPECIAL_PROP_BOUNDING_BOX));
+    STRING val;
+    STRING buf;
+    MgUtil::DoubleToString(featBounds.minx, buf);
+    val += buf;
+    MgUtil::DoubleToString(featBounds.miny, buf);
+    val += L" ";
+    val += buf;
+    MgUtil::DoubleToString(featBounds.maxx, buf);
+    val += L" ";
+    val += buf;
+    MgUtil::DoubleToString(featBounds.maxy, buf);
+    val += L" ";
+    val += buf;
+    bbox->SetValue(val);
+}
+
+void FeaturePropRenderer::ProcessMarker(LineBuffer*   lb,
+                                        RS_MarkerDef& mdef,
+                                        bool          allowOverpost,
+                                        RS_Bounds*    bounds)
+{
+    if (!m_bIncludeFeatureBBOX)
+        return;
+
+    //Should we inflate this a bit to represent an actual box?
+    const RS_Bounds& featBounds = lb->bounds();
+    Ptr<MgStringProperty> bbox = dynamic_cast<MgStringProperty*>(m_currentFeature->GetItem(SPECIAL_PROP_BOUNDING_BOX));
+    STRING val;
+    STRING buf;
+    MgUtil::DoubleToString(featBounds.minx, buf);
+    val += buf;
+    MgUtil::DoubleToString(featBounds.miny, buf);
+    val += L" ";
+    val += buf;
+    MgUtil::DoubleToString(featBounds.maxx, buf);
+    val += L" ";
+    val += buf;
+    MgUtil::DoubleToString(featBounds.maxy, buf);
+    val += L" ";
+    val += buf;
+    bbox->SetValue(val);
+}
\ No newline at end of file

Modified: sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/FeaturePropRenderer.h
===================================================================
--- sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/FeaturePropRenderer.h	2013-05-02 10:57:56 UTC (rev 7469)
+++ sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/FeaturePropRenderer.h	2013-05-03 20:30:42 UTC (rev 7470)
@@ -31,7 +31,8 @@
 public:
     FeaturePropRenderer(MgSelection* selection,
                         int maxFeatures,
-                        double mapScale);
+                        double mapScale,
+                        bool bIncludeFeatureBBOX);
     virtual ~FeaturePropRenderer();
 
     ///////////////////////////////////
@@ -49,6 +50,17 @@
     virtual bool SupportsTooltips();
     virtual bool SupportsHyperlinks();
 
+    virtual void ProcessPolygon(LineBuffer*   lb,
+                                RS_FillStyle& fill);
+
+    virtual void ProcessPolyline(LineBuffer*    lb,
+                                 RS_LineStroke& lsym);
+
+    virtual void ProcessMarker(LineBuffer*   lb,
+                               RS_MarkerDef& mdef,
+                               bool          allowOverpost,
+                               RS_Bounds*    bounds = NULL);
+
     MgBatchPropertyCollection* GetProperties()
     {
         return SAFE_ADDREF(m_featprops);
@@ -56,6 +68,8 @@
 
 private:
     MgBatchPropertyCollection* m_featprops;
+    MgPropertyCollection* m_currentFeature;
+    bool m_bIncludeFeatureBBOX;
 };
 
 #endif

Modified: sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/OpQueryFeatureProperties.cpp
===================================================================
--- sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/OpQueryFeatureProperties.cpp	2013-05-02 10:57:56 UTC (rev 7469)
+++ sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/OpQueryFeatureProperties.cpp	2013-05-03 20:30:42 UTC (rev 7470)
@@ -60,7 +60,7 @@
 
     ACE_ASSERT(m_stream != NULL);
 
-    if (7 == m_packet.m_NumArguments)
+    if (7 == m_packet.m_NumArguments || 8 == m_packet.m_NumArguments)
     {
         Ptr<MgMap> map = (MgMap*)m_stream->GetObject();
         Ptr<MgResourceIdentifier> resource = map->GetResourceId();
@@ -81,6 +81,11 @@
         INT32 layerAttributeFilter = 3;
         m_stream->GetInt32(layerAttributeFilter);
 
+        bool bIncludeFeatureBBOX = false;
+        if (8 == m_packet.m_NumArguments)
+        {
+            m_stream->GetBoolean(bIncludeFeatureBBOX);
+        }
         BeginExecution();
 
         MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();
@@ -97,14 +102,26 @@
         MG_LOG_OPERATION_MESSAGE_ADD_INT32(maxFeatures);
         MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
         MG_LOG_OPERATION_MESSAGE_ADD_INT32(layerAttributeFilter);
+        if (8 == m_packet.m_NumArguments)
+        {
+            MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+            MG_LOG_OPERATION_MESSAGE_ADD_BOOL(bIncludeFeatureBBOX);
+        }
         MG_LOG_OPERATION_MESSAGE_PARAMETERS_END();
 
         Validate();
 
-        Ptr<MgBatchPropertyCollection> info =
-            m_service->QueryFeatureProperties(map, layerNames, geom, selectionVariant,
-            featureFilter, maxFeatures, layerAttributeFilter);
-
+        Ptr<MgBatchPropertyCollection> info;
+        if (8 == m_packet.m_NumArguments)
+        {
+            info = m_service->QueryFeatureProperties(map, layerNames, geom, selectionVariant,
+                featureFilter, maxFeatures, layerAttributeFilter, bIncludeFeatureBBOX);
+        }
+        else
+        {
+            info = m_service->QueryFeatureProperties(map, layerNames, geom, selectionVariant,
+                featureFilter, maxFeatures, layerAttributeFilter);
+        }
         EndExecution(info);
     }
     else

Modified: sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/RenderingOperationFactory.cpp
===================================================================
--- sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/RenderingOperationFactory.cpp	2013-05-02 10:57:56 UTC (rev 7469)
+++ sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/RenderingOperationFactory.cpp	2013-05-03 20:30:42 UTC (rev 7470)
@@ -180,6 +180,17 @@
                 L"MgRenderingOperationFactory.GetOperation", __LINE__, __WFILE__, NULL, L"", NULL);
         }
         break;
+    case MgRenderingServiceOpId::QueryFeatureProperties2:
+        switch (VERSION_NO_PHASE(operationVersion))
+        {
+        case VERSION_SUPPORTED(2,6):
+            handler.reset(new MgOpQueryFeatureProperties());
+            break;
+        default:
+            throw new MgInvalidOperationVersionException(
+                L"MgRenderingOperationFactory.GetOperation", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+        break;
     case MgRenderingServiceOpId::RenderMapLegend:
         switch (VERSION_NO_PHASE(operationVersion))
         {

Modified: sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/ServerRenderingService.cpp
===================================================================
--- sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/ServerRenderingService.cpp	2013-05-02 10:57:56 UTC (rev 7469)
+++ sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/ServerRenderingService.cpp	2013-05-03 20:30:42 UTC (rev 7470)
@@ -864,10 +864,9 @@
                                                                             INT32 maxFeatures)
 {
     // Call updated QueryFeatureProperties API
-    return QueryFeatureProperties(map, layerNames, filterGeometry, selectionVariant, L"", maxFeatures, 3 /*visible and selectable*/);
+    return QueryFeatureProperties(map, layerNames, filterGeometry, selectionVariant, L"", maxFeatures, 3 /*visible and selectable*/, false);
 }
 
-
 ///////////////////////////////////////////////////////////////////////////////
 MgBatchPropertyCollection* MgServerRenderingService::QueryFeatureProperties(MgMap* map,
                                                                             MgStringCollection* layerNames,
@@ -877,6 +876,19 @@
                                                                             INT32 maxFeatures,
                                                                             INT32 layerAttributeFilter)
 {
+    return QueryFeatureProperties(map, layerNames, filterGeometry, selectionVariant, L"", maxFeatures, layerAttributeFilter, false);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+MgBatchPropertyCollection* MgServerRenderingService::QueryFeatureProperties(MgMap* map,
+                                                                            MgStringCollection* layerNames,
+                                                                            MgGeometry* filterGeometry,
+                                                                            INT32 selectionVariant, // Within, Touching, Topmost
+                                                                            CREFSTRING featureFilter,
+                                                                            INT32 maxFeatures,
+                                                                            INT32 layerAttributeFilter,
+                                                                            bool bIncludeFeatureBBOX)
+{
     Ptr<MgBatchPropertyCollection> ret;
 
     MG_TRY()
@@ -886,7 +898,7 @@
         maxFeatures = INT_MAX;
 
     Ptr<MgSelection> sel;   //TODO: do we need this for this API? new MgSelection(map);
-    FeaturePropRenderer fpr(sel, maxFeatures, map->GetViewScale());
+    FeaturePropRenderer fpr(sel, maxFeatures, map->GetViewScale(), bIncludeFeatureBBOX);
 
     RenderForSelection(map, layerNames, filterGeometry, selectionVariant, featureFilter, maxFeatures, layerAttributeFilter, &fpr);
 

Modified: sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/ServerRenderingService.h
===================================================================
--- sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/ServerRenderingService.h	2013-05-02 10:57:56 UTC (rev 7469)
+++ sandbox/jng/queryfeatures_v2/Server/src/Services/Rendering/ServerRenderingService.h	2013-05-03 20:30:42 UTC (rev 7470)
@@ -173,6 +173,16 @@
                                         INT32 maxFeatures,
                                         INT32 layerAttributeFilter);
 
+    virtual MgBatchPropertyCollection* QueryFeatureProperties(
+                                        MgMap* map,
+                                        MgStringCollection* layerNames,
+                                        MgGeometry* filterGeometry,
+                                        INT32 selectionVariant,
+                                        CREFSTRING featureFilter,
+                                        INT32 maxFeatures,
+                                        INT32 layerAttributeFilter,
+                                        bool bIncludeFeatureBBOX);
+
 private:
     // used for tile generation
     MgByteReader* RenderTile(MgMap* map,

Modified: sandbox/jng/queryfeatures_v2/Server/src/UnitTesting/TestRenderingService.cpp
===================================================================
--- sandbox/jng/queryfeatures_v2/Server/src/UnitTesting/TestRenderingService.cpp	2013-05-02 10:57:56 UTC (rev 7469)
+++ sandbox/jng/queryfeatures_v2/Server/src/UnitTesting/TestRenderingService.cpp	2013-05-03 20:30:42 UTC (rev 7470)
@@ -744,6 +744,10 @@
         Ptr<MgPolygon> poly1 = CreateSelectionPolygon(map, 0.3, 0.3);
         Ptr<MgFeatureInformation> fi1 = m_svcRendering->QueryFeatures(map, layerNames1, poly1, MgFeatureSpatialOperations::Within, -1);
 
+        Ptr<MgByteReader> br1 = fi1->ToXml();
+        Ptr<MgByteSink> sink1 = new MgByteSink(br1);
+        sink1->ToFile(L"../UnitTestFiles/QueryFeatures75k.xml");
+
         // call the API using a scale of 12000
         map->SetViewScale(12000.0);
 
@@ -752,6 +756,10 @@
         layerNames2->Add(L"Parcels");
         Ptr<MgPolygon> poly2 = CreateSelectionPolygon(map, 0.05, 0.05);
         Ptr<MgFeatureInformation> fi2 = m_svcRendering->QueryFeatures(map, layerNames2, poly2, MgFeatureSpatialOperations::Within, -1);
+
+        Ptr<MgByteReader> br2 = fi2->ToXml();
+        Ptr<MgByteSink> sink2 = new MgByteSink(br2);
+        sink2->ToFile(L"../UnitTestFiles/QueryFeatures12k.xml");
     }
     catch (MgException* e)
     {

Modified: sandbox/jng/queryfeatures_v2/Web/src/HttpHandler/HttpQueryMapFeatures.cpp
===================================================================
--- sandbox/jng/queryfeatures_v2/Web/src/HttpHandler/HttpQueryMapFeatures.cpp	2013-05-02 10:57:56 UTC (rev 7469)
+++ sandbox/jng/queryfeatures_v2/Web/src/HttpHandler/HttpQueryMapFeatures.cpp	2013-05-03 20:30:42 UTC (rev 7470)
@@ -70,6 +70,17 @@
 
     // Get the feature filter
     m_featureFilter = params->GetParameterValue(MgHttpResourceStrings::reqRenderingFeatureFilter);
+
+    INT32 version = m_userInfo->GetApiVersion();
+    if (version == MG_API_VERSION(2,6,0))
+    {
+        m_requestData = 1 | 2 | 4 | 8;
+        STRING strReqData = params->GetParameterValue(MgHttpResourceStrings::reqRenderingRequestData);
+        if (strReqData.empty())
+            m_requestData = MgUtil::StringToInt32(strReqData);
+        m_selectionFormat = params->GetParameterValue(MgHttpResourceStrings::reqRenderingSelectionFormat);
+        m_selectionColor = params->GetParameterValue(MgHttpResourceStrings::reqRenderingSelectionColor);
+    }
 }
 
 /// <summary>
@@ -120,9 +131,17 @@
 
     // Call the HTML controller to process the request
     MgHtmlController controller(m_siteConn);
-    Ptr<MgByteReader> featureDescriptionInfo = controller.QueryMapFeatures(
-        m_mapName, layerNames, filterGeometry, selectionVariant, m_featureFilter, m_maxFeatures, m_persist, m_layerAttributeFilter);
-
+    Ptr<MgByteReader> featureDescriptionInfo;
+    
+    INT32 version = m_userInfo->GetApiVersion();
+    if (version == MG_API_VERSION(1, 0, 0))
+    {
+        featureDescriptionInfo = controller.QueryMapFeatures(m_mapName, layerNames, filterGeometry, selectionVariant, m_featureFilter, m_maxFeatures, m_persist, m_layerAttributeFilter);
+    }
+    else if (version == MG_API_VERSION(2, 6, 0))
+    {
+        featureDescriptionInfo = controller.QueryMapFeatures(m_mapName, layerNames, filterGeometry, selectionVariant, m_featureFilter, m_maxFeatures, m_persist, m_layerAttributeFilter, m_requestData, m_selectionColor, m_selectionFormat);
+    }
     //Convert to alternate response format, if necessary
     ProcessFormatConversion(featureDescriptionInfo);
 
@@ -131,3 +150,24 @@
 
     MG_HTTP_HANDLER_CATCH_AND_THROW_EX(L"MgHttpQueryMapFeatures.Execute")
 }
+
+/// <summary>
+/// This method is responsible for checking if
+/// a valid version was given
+/// </summary>
+/// <returns>Returns nothing</returns>
+void MgHttpQueryMapFeatures::ValidateOperationVersion()
+{
+    MG_HTTP_HANDLER_TRY()
+
+    // There are multiple supported versions
+    INT32 version = m_userInfo->GetApiVersion();
+    if (version != MG_API_VERSION(1,0,0) &&
+        version != MG_API_VERSION(2,6,0))
+    {
+        throw new MgInvalidOperationVersionException(
+        L"MgHttpQueryMapFeatures.ValidateOperationVersion", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    MG_HTTP_HANDLER_CATCH_AND_THROW(L"MgHttpQueryMapFeatures.ValidateOperationVersion");
+}

Modified: sandbox/jng/queryfeatures_v2/Web/src/HttpHandler/HttpQueryMapFeatures.h
===================================================================
--- sandbox/jng/queryfeatures_v2/Web/src/HttpHandler/HttpQueryMapFeatures.h	2013-05-02 10:57:56 UTC (rev 7469)
+++ sandbox/jng/queryfeatures_v2/Web/src/HttpHandler/HttpQueryMapFeatures.h	2013-05-03 20:30:42 UTC (rev 7470)
@@ -51,6 +51,9 @@
     /// </returns>
     MgRequestClassification GetRequestClassification() { return MgHttpRequestResponseHandler::mrcViewer; }
 
+protected:
+    virtual void ValidateOperationVersion();
+
 private:
     STRING  m_mapName;
     STRING  m_layerNames;
@@ -60,6 +63,11 @@
     INT32   m_maxFeatures;
     INT32   m_layerAttributeFilter;
     bool    m_persist;
+
+    //New for 2.6
+    INT32   m_requestData;
+    STRING  m_selectionColor;
+    STRING  m_selectionFormat;
 };
 
 #endif  // _FS_DESCRIBE_MAP_FEATURES_H

Modified: sandbox/jng/queryfeatures_v2/Web/src/HttpHandler/HttpResourceStrings.cpp
===================================================================
--- sandbox/jng/queryfeatures_v2/Web/src/HttpHandler/HttpResourceStrings.cpp	2013-05-02 10:57:56 UTC (rev 7469)
+++ sandbox/jng/queryfeatures_v2/Web/src/HttpHandler/HttpResourceStrings.cpp	2013-05-03 20:30:42 UTC (rev 7470)
@@ -230,6 +230,9 @@
 const STRING MgHttpResourceStrings::reqRenderingSelectionVariant = L"SELECTIONVARIANT";
 const STRING MgHttpResourceStrings::reqRenderingGeometry = L"GEOMETRY";
 const STRING MgHttpResourceStrings::reqRenderingFeatureFilter = L"FEATUREFILTER";
+const STRING MgHttpResourceStrings::reqRenderingRequestData = L"REQUESTDATA";
+const STRING MgHttpResourceStrings::reqRenderingSelectionFormat = L"REQUESTDATA";
+
 const STRING MgHttpResourceStrings::reqRenderingBaseMapLayerGroupName = L"BASEMAPLAYERGROUPNAME";
 const STRING MgHttpResourceStrings::reqRenderingTileColumn = L"TILECOL";
 const STRING MgHttpResourceStrings::reqRenderingTileRow = L"TILEROW";

Modified: sandbox/jng/queryfeatures_v2/Web/src/HttpHandler/HttpResourceStrings.h
===================================================================
--- sandbox/jng/queryfeatures_v2/Web/src/HttpHandler/HttpResourceStrings.h	2013-05-02 10:57:56 UTC (rev 7469)
+++ sandbox/jng/queryfeatures_v2/Web/src/HttpHandler/HttpResourceStrings.h	2013-05-03 20:30:42 UTC (rev 7470)
@@ -177,6 +177,8 @@
     static const STRING reqRenderingClip;
     static const STRING reqRenderingBehavior;
     static const STRING reqRenderingSelectionColor;
+    static const STRING reqRenderingRequestData;
+    static const STRING reqRenderingSelectionFormat;
 
     // PREDEFINED TILE REQUEST PARAMETERS
     static const STRING reqTileMapDefinition;



More information about the mapguide-commits mailing list