ThinkGeo.com    |     Documentation    |     Premium Support

Get line features nearest to clicked point

Hi,


My map has few layers;  Highway Layer, Secondary Highway Layer, Street Layer.  On map click event I want to highlight  closest feature to clicked point. 


It easy to highlight closest polygon to clicked point but I am having hardtime highlighting closest  line to clicked point. Can someone provide me few  hints or suggestions.


Is it feasible to highlight the closest  line/ point feature to clicked point ?


Thanks  in advance


Prava



Hi Prava, 
  
 It’s feasible. You can use the method “GetFeaturesNearestTo(BaseShape targetShape, GeographyUnit unitOfData, int numberOfItemsToFind, IEnumerable<string> returningColumnNames, double distanceLimits, DistanceUnit unitOfDistance)” of featureSource to return all the features inside specified “DistanceLimits”, and then check the WellknownType of the feature is WellKnownType.MultiLine or WellKnownType.Line. 
  
 Thanks, 
 Johnny 


Hi,


Here is the the helpful code. Please have a look at it>




Collection<Feature> features = featureSoruce.GetFeaturesNearestTo(e.Position, GeographyUnit.DecimalDegree, 10, new Collection<string>() { }, 100, DistanceUnit.Meter);

            Feature selectedFeature;
            foreach (Feature feature in features)
            {
                if (feature.GetWellKnownType() == WellKnownType.Line || feature.GetWellKnownType() == WellKnownType.Multiline)
                {
                    selectedFeature = feature;
                    break;
                }
            }


 


Thanks,


Johnny



Hi Johny,


Your code was really helpful. 


Thanks !


Prava



You are welcome. We will make a Code Community project from that idea. Thank you. code.thinkgeo.com/



Hi Johnny,


I have a question on  distance limit., what is an ideal value for it.  Given below is my code to find the nearest feature to clicked point.


MsSql2008FeatureLayer sqlLayer = (MsSql2008FeatureLayer)curLayer;

                        FeatureSource myFeaturesource =  sqlLayer.FeatureSource;

                        sqlLayer.Open();

                        Collection<FeatureSourceColumn> featureSourceColumn = sqlLayer.QueryTools.GetColumns();

                        Collection<string> returningColumnNames = new Collection<string>();

                        foreach (FeatureSourceColumn column in featureSourceColumn)

                        {

                            returningColumnNames.Add(column.ColumnName);

                        }

                        sqlLayer.Close();

                        sqlLayer.FeatureSource.Open(); 


BaseShape clickedPoint = new PointShape(X, Y);

 double bufferZone = 100.0;

 int featureCount = 20;


Collection<Feature> closestFeaturesII = featureSource.GetFeaturesNearestTo(clickedPoint, GeographyUnit.Feet,  featureCount, columnNames, bufferZone, DistanceUnit.Meter);

          


At certain zoom levels, eventhough I click  on top of highways, above function doesnot return any  features at all.  Can you tell me whay this is happening? I tried changing bufferzone  values to  100/200/300 and 500.0 but the issue was not resolved.


 


Thanks


Prava



In the case you are describing where you have to zoom in and out, I would recommend using a buffer in screen coordinates, instead of world coordinate. To do that, you are going to need the ExtentHelper class. Let say, that you are using a buffer of 10 in screen coordinate. That buffer is going to vary in world coordinate buffer. I made a little sample app for my testing and it is working great. Now I put the logic in your code and this is what I have. You may want to adapt it a little bit for your case.


 



  int screenBuffer = 10;
            ScreenPointF clickedPointF = ExtentHelper.ToScreenCoordinate(Map1.CurrentExtent, e.Position, (float)Map1.Width.Value, (float)Map1.Height.Value);
            ScreenPointF bufferPointF = new ScreenPointF(clickedPointF.X + screenBuffer, clickedPointF.Y);

            double distanceBuffer = ExtentHelper.GetWorldDistanceBetweenTwoScreenPoints(Map1.CurrentExtent, clickedPointF, bufferPointF,
                                                                (float)Map1.Width.Value, (float)Map1.Height.Value, Map1.MapUnit, DistanceUnit.Meter);


            int featureCount = 20;

            Collection closestFeaturesII = featureSource.GetFeaturesNearestTo(clickedPoint, GeographyUnit.Feet, featureCount, columnNames, distanceBuffer, DistanceUnit.Meter);
          



Hi Val,


It worked, thanks again !


Prava



You are welcome. If you have any other request, let us know.

I let you know that we made a Code Community project from your request in that post, Get Feature Clicked On (Web). code.thinkgeo.com/projects/show/featureclickedweb


Thank you.



Hi Val,


I added more than one  feature type to map, now I have road Layer, cities Layer and houses. When I click at house which is a point feature it should highlight  closest house but  sometimes  it highlights closest road. My logic is as follows; 


Step I : Foreach Layer in map find the closest feature and add to MemoryLayer1.


 foreach (Layer curLayer in layerOverlay.Layers)

{


 Collection<Feature> closestFeaturesI = myFeaturesource.GetFeaturesNearestTo( clickedPoint, NextGenProject.GeographyUnits, featureCount, returningColumnNames, bufferZone, NextGenProject.DistanceUnits);

                      


 foreach (Feature curFeature in closestFeatures)

   {

         myMemLayer.InternalFeatures.Add(curFeature);

   }


}


 


Step II : Repeat the logic to find the closest feature in MemoryLayer1.


 Collection<Feature> closestFeatures =myMemLayer.GetFeaturesNearestTo( clickedPoint,  NextGenProject.GeographyUnits, featureCount, returningColumnNames,  bufferZone, NextGenProject.DistanceUnits);

             


StepII : Highlight the first feature returned by Step II


HighlightLayer.Internalfeatures.add(  closestFeatures[0] )


 


Is there an alternative way of doing this?


Thanks


Prava


 



Prava,


You are close.
 
Just add an if statement on your last step, we only add point(houses) to the higlightLayer shown as following, hope it helps:

 

foreach (Feature closestFeature in closestFeatures)
{
      if (closestFeature.GetWellKnownType() == WellKnownType.Point)
      {
           HighlightLayer.Internalfeatures.add(closestFeature);
 
           //If you want to show all the house, just remove this.
           break;
      }
}


Any more questions just feel free to let me know.
 
Thanks.
 
Yale

Hi Yale,


The above code just highlights  houses(point features), my objective is to highlight closest feature it may be a house(Point Feature) / Roads(Line Feature) / Counties( Polygon Feature). If I click on map it should highlight the first closest feature. Right now if I click on roads it highlights closest road but if I click on house   it is highlighting closest roads. How can I  make it highlight closest feature? 


I am adding only one feature  in InMemory Layer and its geometry type and default style  can vary based on the feature added. Am I on right track or do I have to take a different approach?


 


Thanks


Prava



I suggest you check out the new Code Community project Get Feature Clicked On (Web) 2. I think this is going to respond to your concern. code.thinkgeo.com/projects/show/featuresclickedon2



Thanks !!



You are welcome. If you have any other questions, we are always happy to help.

Hi Val, this code takes awhile to execute which leaves the end user to wonder if it is doing anything (especially with many layers), is there any way to get an Ajax Progress going while it processes the logic in the Map Click Event?


Update - I was able to get it to work with the Ajax Update Panel as well as a Telerik LoadingPanel, took a little hack to get both of these to work but it's running slick now.  An even more elegant solution would be to invoke the built in Image Loader for the Map control itself, but this only seems to draw during the paint events and not during server side processes like the Click event?



Jason, 
  
  Thank you for your suggestions. I will ask the Web development team what they think and what other recommendations they might have for you. 
  
 Val.