Monday Jun 10, 2013

Another sample using the V2 API (but with json files)

In this example we'll show how to display content from a json file on a background map tile layer. So the interactive (vector layer) content is from a file (or datapack) rather a database instance.

The sample application displays lines from USA (DC) to (capitals of) other countries color coded by the number of US visitors to that country in 2009, as shown in the screenshot below.

The data is stored, and read, from a json file which looks something like:

{"type": "FeatureCollection",
  "collectionName": "theme0",
 "srs": 8307,
  "geodetic": true,
  "bbox": [-180, -41.28054, 180,88.93291],
  "attr_names": ["COUNTRY_CODE","COUNTRY","NUM_VISITORS"],
  "attr_types": ["string","string","double"],
  "features": [{"type": "Feature","_id": "MEX",
                    "geometry": {"type": "LineString",
                                      "coordinates": [-77.03201,38.88951,-77.21086,38.77556, ... ]},
  properties": {"COUNTRY_CODE": "MEX","COUNTRY": "MEXICO","NUM_VISITORS": "1945000"}
 }, ... 

The attr_name and attr_types is a extension of the geojson format used for Mapviewer specific reasons.

Broadly speaking, the application code does the following:

Sets up the client map object.
Sets the url for the mapviewer instance and the resources (images for UI components) it needs.
Adds a tile layer.
Adds a country layer.
Adds a layer for visitors from US to other countires (flows layer).
Sets up the color scheme for the flows layer.
Sets up the mouseover interaction and tooltips.

The code is

<!DOCTYPE html>
<html>
  <head>
    <title>Number of US visitors to abroad in 2009</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script src="/mvdemo/gv.js" type="text/javascript"></script>
    <script>
      document.write('<'+'script src="'+MV.gv.mapviewer_baseURL+
      '/jslib/v2/oraclemapsv2.js"'+' type="text/javascript"><'+'/script>');
    </script>
    <script language="JavaScript" type="text/javascript">
      OM.gv.proxyEnabled =false;
      OM.gv.setResourcePath(MV.gv.mapviewer_baseURL+"/jslib/v2/images/");

      var map = null;
      var flowsLayer = null;
      var countriesLayer = null;
 
      $(document).ready(function()
      {        
        var baseURL  = MV.gv.mapviewer_baseURL;
        var center = new OM.geometry.Point(20,30,8307); 
        map = new OM.Map(document.getElementById('map'),
        {mapviewerURL: baseURL}) ;
                
        var tilelayer = new OM.layer.ElocationTileLayer("oracle.maps");
        map.addLayer(tilelayer) ;  
        
        
        countriesLayer = new OM.layer.VectorLayer("countries",
        {
          def:{
            type:OM.layer.VectorLayer.TYPE_DATAPACK,
            url:"/mvdemo/datapacks/world_countries.json"
          }
        }
      );
        
        var colorStyle = new OM.style.Color({"stroke":"#cc9999",
          strokeThickness:1, strokeOpacity:0.8});
        countriesLayer.setRenderingStyle(colorStyle);
        countriesLayer.enableInfoWindow(false);
        countriesLayer.enableFeatureSelection(true);
        countriesLayer.setSelectStyle(new OM.style.Color(
                       {fill:"#ff0000", fillOpacity:0.8,stroke:"#cc9999", 
                        strokeThickness:4, strokeOpacity:0.5}))
        map.addLayer(countriesLayer);
        
        flowsLayer = new OM.layer.VectorLayer("flows", 
        {
          def:{
            type:OM.layer.VectorLayer.TYPE_DATAPACK, 
             url:"usa_visitors_geodetic.json"
          }
        });          
        flowsLayer.addListener(OM.event.MouseEvent.MOUSE_OUT, hideCountry);
        flowsLayer.addListener(OM.event.MouseEvent.MOUSE_OVER, showCountry);
       
        var hoverStyle = new OM.style.Color({fill:"#ffffff"});
        flowsLayer.setBringToTopOnMouseOver(false);
        flowsLayer.setToolTipCustomizer(getTooltip);
        flowsLayer.enableInfoWindow(false);
        flowsLayer.enableFeatureHover(true);
        flowsLayer.setHoverStyle(hoverStyle);
        
        setupFlowStyles(flowsLayer);
        map.addLayer(flowsLayer);
        
        map.setMapCenter( center );
        map.setMapZoomLevel(2) ;
        map.init() ;
      });
      
      function getTooltip(feature)
      {
        return feature.getAttributes()["COUNTRY"]+", "+feature.getAttributes()["NUM_VISITORS"];
      }
      
      function setupFlowStyles(layer)
      {
        var lines = [];
        var fillColors = 
        // 10 color multihue sequential OrRd
//['#FFF9F2','#FFF7EC','#FEE8C8','#FDD49E','#FDBB84','#FC8D59','#EF6548','#D7301F','#B30000','#7F0000'];
        // 10 color qualitative paired
['#A6CEE3','#B2DF8A','#FB9A99','#FDBF6F','#CAB2D6','#FF7F00','#1F78B4',
'#6A3D9A','#E31A1C','#33A02C'];
        for(var i=0; i<10; i++)
        {
          var lineStyle = new OM.style.Line({fillWidth:6, fill:fillColors[i], 
                                             strokeThickness:1, stroke:fillColors[i]});
          lines[i] = lineStyle;
        }
        
        var bucketStyle = new OM.style.BucketStyle(
        {
          styles: lines,
          numClasses:10, 
          classification:'logarithmic',  
          defaultStyle: lines[0]
        });
        
        layer.setRenderingStyle(bucketStyle, ["NUM_VISITORS"]);
        
      }
     
      function showCountry(evt)
      {
        var feature = evt.feature;
        var selectedFeature;
        var destFeature = countriesLayer.getFeature(feature.id);
        if (destFeature)
        {
          selectedFeature=countriesLayer.selectFeature(destFeature);
          //countriesLayer.bringForward();
          document.getElementById("text").innerHTML = "# of visitors from USA to "+ 
          feature.getAttributes()["COUNTRY"] + " = " + 
          feature.getAttributes()["NUM_VISITORS"];
        }
                
      }

      function hideCountry(evt)
      {
        var feature = evt.feature;
        var selectedFeature;
        var destFeature = countriesLayer.getFeature(feature.id);
        if (destFeature)
        {
          selectedFeature = countriesLayer.deselectFeature(destFeature);
          //countriesLayer.sendBackward();
        }
      }
    </script>       
  </head>
  <body>
    <DIV id="map" style="width:99%;height:94%"></DIV>
    <span id="text">Country: </span>
  </body>
</html>

There are two vector layers. The flows layers is the number of visitors from the US while the countries layer (country boundary) is used to highlight the destination country on a mouse-over.

Now let's go through various code snippets.

The setResourcePath() method is used to tell the client lib where the images and icons, for the various UI components such as the navigation panel, can be found.

After setting the initial map center and background tile layer (oracle.maps) we add the countries vector layer from a json file (OM.layer.VectorLayer.TYPE_DATAPACK).

        countriesLayer = new OM.layer.VectorLayer("countries",
        {
          def:{
            type:OM.layer.VectorLayer.TYPE_DATAPACK,
            url:"/mvdemo/datapacks/world_countries.json"
          }
        }
      );

Then we set up it rendering (line) and selection (red color fill) styles. And similarly the flows layer,

       flowsLayer = new OM.layer.VectorLayer("flows", 
        {
          def:{
            type:OM.layer.VectorLayer.TYPE_DATAPACK, 
            // json file is in same directory as the html (sample code) file  
            url:"usa_visitors_geodetic.json"
          }
        });          

with listener for mouse over and mouse out to handle the highlighting and updating the message area.

        flowsLayer.addListener(OM.event.MouseEvent.MOUSE_OUT, hideCountry);
        flowsLayer.addListener(OM.event.MouseEvent.MOUSE_OVER, showCountry);

Next we set up the hover style, enable info-windows, and the advanced styles for the layer itself. The advanced style is defined and used in setupFlowStyles(flowsLayer) which defines 10 line styles of the specified colors, and then a bucket style using the line styles and a built-in classification scheme.

      function setupFlowStyles(layer)
      {
        var lines = [];
        // colors from colorbrewer2.org 
        var fillColors = 
        // 10 color multihue sequential OrRd
//['#FFF9F2','#FFF7EC','#FEE8C8','#FDD49E','#FDBB84','#FC8D59','#EF6548','#D7301F','#B30000','#7F0000'];
        // 10 color qualitative paired
['#A6CEE3','#B2DF8A','#FB9A99','#FDBF6F','#CAB2D6','#FF7F00','#1F78B4','#6A3D9A',
'#E31A1C','#33A02C'];
        for(var i=0; i<10; i++)
        {
          var lineStyle = new OM.style.Line({fillWidth:6, fill:fillColors[i], 
                                             strokeThickness:1, stroke:fillColors[i]});
          lines[i] = lineStyle;
        }
        
        var bucketStyle = new OM.style.BucketStyle(
        {
          styles: lines,
          numClasses:10, 
          classification:'logarithmic',  //built-in scheme 
          defaultStyle: lines[0]
        });
        
        layer.setRenderingStyle(bucketStyle, ["NUM_VISITORS"]);
        
      }

The setRenderingStyle specifies the bucketStyle to use and the attribute column whose value determines the bucket or style for a given feature.

Lastly, the event listeners showCountry and hideCountry highlight and de-highlight the destination country. The id attribute of a flowsLayer feature is the country code (e.g. "_id": "MEX") and this is also the id column in the countries layer. Since the feature itself is passed in to mouse-over event handler we can use its id to fetch, and highlight, the destination country from the countries layer.

This is done in the showCountry() method

 

      function showCountry(evt)
      {
        var feature = evt.feature;
        var selectedFeature;
        var destFeature = countriesLayer.getFeature(feature.id);
        if (destFeature)
        {
          selectedFeature=countriesLayer.selectFeature(destFeature);
          //update the message area
          document.getElementById("text").innerHTML = "# of visitors from USA to "
          + feature.getAttributes()["COUNTRY"] + " = " + 
          feature.getAttributes()["NUM_VISITORS"];
        }              
      }



MapViewer 11.1.1.7.1 new config settings for vector layers

In 11.1.1.7.1 the data server which sends vector layers (theme-based FOI) to the client is restricted by default. The config file mds.xml (located in the same directory as mapviewerConfig.xml) has to be updated to allow the data server to access and serve up layers from desired data sources.

The relevant readme.txt entry is

- Map Data Server (MDS), the vector theme streaming server of MapViewer, is now in 
  lock-down mode by default and will not allow themes to be streamed to a client unless 
  explicitly configured otherwise. You will need to manually edit the 
  WEB-INF/conf/mds.xml file to control which data sources and which themes can be 
  streamed to a HTML5 application client. 
  A MapViewer restart is required for the changes to take effect.

OBIEE 11.1.1.7 MapViewer error when previewing tile layers

In OBIEE 11.1.1.7 (with MapViewer 11.1.1.7 deployed in Weblogic) you may see an 500 - internal server error when previewing map tile layers in the MapViewer manage map tile layers admin page.

If so you need to modify the web.xml as described in the readme.

On certain WLS domains (mostly when ADF run-time library is deployed), you
  may see errors when trying to preview tile layers. To fix this issue, modify
the weblogic.xml descriptor file found in mapviewer.ear's WEB-INF/ folder, and
uncomment the entry for the jstl 1.2 library as shown below (note the jsf
section should remain commented-out):

<library-ref>
    <library-name>jstl</library-name>
    <specification-version>1.2</specification-version>
  </library-ref>

<!--
<library-ref>
    <library-name>jsf</library-name>
    <specification-version>2.0</specification-version>
    <exact-match>false</exact-match>
</library-ref>
-->

If you upgraded obiee from a previous 11.1.1.x release you may see this error anytime you access the mapviewer admin pages. The fix is to redeploy mapviewer.


About

Official blog for Oracle FMW MapViewer and related products.

Search

Categories
Archives
« June 2013 »
SunMonTueWedThuFriSat
      
1
2
3
4
5
7
8
9
11
12
13
14
15
16
17
18
20
21
22
23
24
25
27
28
29
30
      
Today