ThinkGeo.com    |     Documentation    |     Premium Support

Help Implementing Interactive Point Features Layer from Shapefile

Hello,



I am currently working with a client, a transportation company, that works with the local port authority. We are using version 7.0 of the MVC Edition to implement our maps and are using the OpenStreetMap as the base layer for all our maps. The client recently asked for a new feature, adding a layer displaying certain bus stops to the maps.  This layer is in addition to other existing layers that may or may not be toggled on by the user. The client receives a database table biannually with all the stops.  The client wishes a certain subset of stops designated “Feeder Stops”, which can change daily, to be displayed on the map along with the ability to get additional information by interacting with the stop. We do not want to have to regenerate the shapefile every time a change occurs.  I have created a method to read in the data from the database and create a shapefile (point features) of all the stops (~7600 in my test data). I have also created a method for creating an index of the shapefile base on the Feeder Stops, so that only they get rendered (~1700 in my test data), and prevents the shapefile from needing to be regenerated. I suspect there will be some performance issues that I may need assistance resolving in the near future due to the number of features, but right now I am more concerned with basic implementation than performance tuning.



The client looked at some of the MapSuite demos, and they like the context menus for interacting with a stop.  It looks to me like there are two options for implementing this. Though I am not sure which would be better given the number of features.



Option 1:

Given the number of features, and the fact that OpenStreetMaps has many icons and labels, I would like the user to be able to easily tell when they are hovering over a feature that they can interact with.  Using the highlight overlay as in HighlightAFeatureWhileHovering and using the context menu as in ContextMenuToHighlightOverlay. would seem to be logical and is visually appealing.  I assume it should be possible to combine both methods, though I have only thus far attempted the highlighting.  It works well but I am encountering two issues.


        
  1. The highlight layer is always visible. Is it possible to tie this to whether the overlay containing the stops is toggled on in the overlay switcher?

  2.     
  3. The other issue, which seems more problematic is that the highlight overlay does not seem to use the index file for the shapefile, causing it to render all the features in the shapefile. Does the highlightoverlay not support using an index or am I possibly setting it up wrong? Using the collection of featureIDs to exclude of the featuresource is probably going to be impractical to the number of records that would need processed.


Option 2:

I have seen mention of a FeatureSourceMarkerOverlay that might also work. There are two issues with this method that I am seeing in some very brief testing.


        
  1. Once again the index file seems to be getting ignored and all the features are being rendered.

  2.     
  3. This is more minor, but the absence of highlighting the individual feature makes the map less visually appealing and possibly harder for the user to tell when they are hovering over something that they can interact with. Is it possible to achieve a highlighting effect with markers?


Finally, I have a general question after looking at these samples. Is it possible to use the built-in  highlightOverlay with multiple featuresources/layers or would I need create multiple custom layers and making use of AJAX calls to replicate this behavior if there are multiple layers visible that I desire highlighting on?


Hi Michael, 
  
 Sorry to reply you so late: 
  
 Option 1: 
 1. I think it’s possible, but you need write JS code for implement that, you need to bind the event on layer switcher(from OpenLayers) and set visible by the item you chosen, you can put your custom JS code in our OnMapCreating or OnMapCreated event. 
 2. HighlightOverlay don’t support index, but I think you can built ShapeFileFeatureLayer with index and try to get specified features from it then add them to HighlightOverlay.  
 Option 2: 
 1. Yes you’re right, FeatureSourceMarkerOverlay don’t support index also, because it render marker in memory and index don’t helpful to increase performance. If you want to filter the features, you also need do that with special function. 
 2. About this item I am sorry I am not very clear about the scenario, what’s the meaning about achieve a highlighting effect with markers, do you meant you want to implement a client side script which will highlight a marker when mouse hover on it? 
  
 For your last question, the HighlightOverlay is a special overlay, which looks more like a layer, so I think if you want to switch different styles, you can built a group of collection which contains different features, styles and contextMenu, so that you can switch them background. 
  
 Wish that’s helpful. 
  
 Regards, 
  
 Don

Thanks for the reply.



2. About this item I am sorry I am not very clear about the scenario, what’s the meaning about achieve a highlighting effect with markers, do you meant you want to implement a client side script which will highlight a marker when mouse hover on it? 



Yes, highlighting a maker on the client side when the mouse hovers over it is what I meant. The desire is so that the user can more easily tell it is something that they can interact with, since OpenStreetMaps has many markers built in. Currently, I am leaning to toward your suggestion regarding #2 with the HighlightOverlay for the current problem, but we have some other maps that use markers where highlighting makers on mouse over would potentially be helpful on.



I am going to do some more experimenting with this based on your comments, so I may have some more questions in the near future.

Hi Michael, 
  
 Thanks for your description, but I think the additional client side behavior still need to be implemented by write JavaScript code. 
  
 And any question please let me know. 
  
 Regards, 
  
 Don

Several more questions:



Also, a couple things to note:


        
  1. The client said that this layer will not be used often, but still I would like to try to maximize performance.

  2.     
  3. I realized that I made an error when calculating the “Feeder Stops”. In my test data, which should be representive of actual data, there are actually about 700 stops, that are considered “Feeder Stops”, not 1700. Better, but still a large number of features.


I resolved index issues by simply logging the IDs of the features that are indexed to a text file when the shapefile index is generated. That way I can simply pull  the needed features from the shapefilelayer that we create when the map is loaded, and manually add them to the FeatureSource of other layers/overlays that do not support using the index file.



It is my understanding that a ShapeFileFeature layer is less resource intensive than using markers. So I am thinking of using a LayerOverlay holding a ShapeFIleFeature layer for ZoomLevels 01-15, and then InMemoryMarkerOverlay set to display for ZoomLevels16-20 since it is my understanding that the InMemoryMarkerOverlay only renders the markers in the current extent. I am trying to tie the toggling of the two Overlays together, I have the LayerOverlay visible in the layer switcher. This is the code I am trying to use, though it does not appear to work correctly, since once the makers are visible they continue to render. Am I doing something wrong?


function toggleLayers(map) {
    var stopLayer = map.getLayersByName(“PAAC Feeder Stops”)[0];
 
    var markerOverlay = map.getLayersByName(“PAAC Feeder Stops Markers”)[0];




    var listener = function (object, element) {
        if (stopLayer.visibility) {
            markerOverlay.visibility = true;
        }
        else {
            markerOverlay.visibility = false;
        }
    }
    stopLayer.events.register(“visibilitychanged”this, listener);
}

Edit: I found the problem with the javascript code above.  The issue is that I should be using markerOverlay.setVisibility(bool), instead of markerOverlay.visibility = bool.

 

Next, since these are bus stops, we would like to label the stops with the individual name, and in the context menu have commands. In particular launching a Google Street View. I can build the url and go to the webpage via a javascript call, but in order to do this I would need information contained in the Feature. Likewise, the stop name is contained in the Feature, and would be needed for creating the Label.



I know from working with the SimpleMarkerOverlay that I can give a Marker a label by using the WebImage.Text property, but is there a way to pull information from the Feature corresponding to a Marker to render this?



Similarly, is there a way that I can access the coordinates of the feature that the Marker corresponds to client side, so that I can get them to build the url in my javascript function bound to the ContextMenuItems OnClientClick property?



Really, in general is there a way that I can bind the various features of the MarkerOverlay, such as Context Menu, Popups, etc. to use data from the Features in the underlying FeatureSource so that they would have different values depending on the Marker being interacted with by the user?  Using SimpleMarkers, MarkerValueItems, or MarkerClass is not feasible to due to the size of the dataset being worked with, the requirements, and the fact that all data items are unique?



I am open to any suggestions for alternatives if this cannot be achieved with using the InMemoryMarkerOverlay. The main requirement is the ability to display, label, and interact with Features (ideally based on data in the Feature’s columns rather than just the coordinates of the feature).

Hi Michael,  



For dynamic build popup I think you can view our HowDoISamples, the ClickEventToHighlightOverlay should be helpful. 



You can save the data what you wanted in Feature.ColumnValues, then read them and build a html for popup when click. 



For label I think you can try to add a inmemoryfeaturelayer, put points in it and only set the label style, that maybe works. 



Wish that’s helpful. 



Because your thread contains too many information, if I missed any question please let me know.



Regards, 



Don

Here is an update, I apologize for not getting back to this sooner, but I have been busy with other issues. 



I ended up using a hybrid approach to implement the desired feature for our map. I am using a ShapefileFeatureLayer that that uses an index to render bus stops desired at lower zoom levels where no interaction is desired, and the HighlightOverlay at higher levels where interaction is required. I managed this by recording the IDs of the features indexed when the shapefile is created into a textfile, and then manually adding those features from the ShapefileFeatureLayer to the HighlightOverlay when the map is created and the HighlightOverlay is setup. I then used custom javascript code to handle the layer visibility, and bind the toggling of both layers together.



We have noticed two additional issues using the HighlightOverlay which may be related:




        
  1. The context menu persists after a menu item is clicked. Is there a way to force it to close programmatically, so that the user does not have to left click the map to close it?

  2.     
  3. The menu also persists even if the layer it is bound to is toggled to be not visible while it is open, yet oddly the menu closes when the zoom level changes.


We are using the context menu items to open dialogue windows and additional browser windows and the menu staying open is causing a bit of a problem, particularly with the dialogues.



Also, I noticed a possible bug. We are using MapSuite MVC Edition v7.0, but I did not see this anywhere in the change lists. The HighlightOverlay does not seem to respect the isVisible property being set in the controller method where it is setup. In order to prevent the overlay from being visible initially I had to toggle the visibility property of the layer in the OnMapCreated event in the client-side script.



Finally, one other note when looking at the demos and viewing ASPX/Razor source it would probably be better to display the source code in such a way that it does not get rendered as HTML(prevents viewing javascript for example).


Hi Michael,  
  
 Thanks for your detail reply and I will let our developer knows your suggestion. 
  
 We will look into the possible issue. 
  
 And I just know our new coming 9.0 MVC edition have many enhancement, I am not sure whether these bugs you mentioned still there, but please feel free to let us know if you found any issue in new release. 
  
 Because daily build is paused, we cannot fix bug and modify source code now, so we will work for the problem after 9.0 release. 
  
 Regards, 
  
 Don