Hello everyone,I am trying to find the altitude of any point in a shapefile. My current algorithm is too slow, and I need to find if there is another quicker method to do that. Currently, I use the Envelope property of the IPoint and IIdentify2.Identifiy method to find the features closest to the point. Once I have them, I use the IProximityOperator and the ReturnDistance method to find the closest feature to the point, and once I found it I use the elevation attribute. The problem is on IIdentify2.Identify method, is terribly slow (1 second per call aprox.), and I need to call this function many times to show a graphic with the ground elevation. Is there a better way to find the altitude of a point in a shapefile?PD: I paste part of the code here, so you can see how I'm doing. In order to make it easy to read, I won't paste the complete code, just the important parts.
public static List<object> getClosestFeatures(ref AxMapControl map, int elevationLayerIndex, IPoint point, int pixelThreshold) {
IEnvelope searchEnvelope = point.Envelope;
searchEnvelope.CenterAt(point);
List<object> selectedFeatures = new List<object>();
//The elevation layer will always be the last one
layer = map.get_Layer(elevationLayerIndex);
geoLayer = layer as IGeoFeatureLayer;
if (geoLayer.Selectable && geoLayer.FeatureClass != null) {
IIdentify2 identifier = geoLayer as IIdentify2;
for (; foundIDs == null && pixelsThreshold < 20; pixelsThreshold++) {
double searchDist = Math.Pow(50, pixelsThreshold);
searchEnvelope.Width = searchDist;
searchEnvelope.Height = searchDist;
//Look for IFeatures around the location
foundIDs = identifier.Identify(searchEnvelope, null); // ==> the problem is here: too slow!!
}
}
// Add the features to the collection and clear the current ID array
if (foundIDs != null) {
IFeatureIdentifyObj featureIdentifyObject;
IRowIdentifyObject rowIdentifyObject;
IFeature foundFeature;
for (int j = 0; j < foundIDs.Count; j++) {
object objElement = foundIDs.get_Element(j);
if (objElement is IFeatureIdentifyObj) {
featureIdentifyObject = objElement as IFeatureIdentifyObj;
rowIdentifyObject = featureIdentifyObject as IRowIdentifyObject;
foundFeature = rowIdentifyObject.Row as IFeature;
selectedFeatures.Add(foundFeature);
}
}
foundIDs.RemoveAll();
}
return selectedFeatures;
}
private static int getElevationWithThreshold(ref AxMapControl map, int elevationLayerIndex, string layerFullPath, IPoint pSearchPt, out double finalElevation) {
IProximityOperator proximity;
IFeature testFeature;
List<object> selectedFeatures = new List<object>();
double tempDist;
int result = -1;
//Increment the pixel threshold until we find any features, if the intial threshold is -1
int initialPixelThreshold = 1;
selectedFeatures = getClosestFeatures(ref map, elevationLayerIndex, pSearchPt, ref initialPixelThreshold);
if (selectedFeatures.Count >= 1) {
//Check the elevation values of all the selected features. There have to be at least 2 different ones
int indexElevation = ((IFeature)selectedFeatures[0]).Fields.FindField(MainThreadBase.layers.getElevationAttribute(layerFullPath));
//Initialise some variables before entering the loop
double bestDistance = double.MaxValue;
double bestFeature_elevation = double.MaxValue;
// Find the closest feature to the cursor position
proximity = pSearchPt.Envelope as IProximityOperator;
for (int z = 0; z < selectedFeatures.Count; z++) {
testFeature = selectedFeatures as IFeature;
tempDist = proximity.ReturnDistance(testFeature.Shape);
try {
double elevation = (double)((IFeature)selectedFeatures).get_Value(indexElevation);
//Have we clicked ON the feature?
if (tempDist < 2) {
finalElevation = elevation;
return 1;
}
if (tempDist < bestDistance) {
bestDistance = tempDist;
bestFeature_elevation = elevation;
}
}
catch (Exception e) {
LogFile.appendLine_error(e);
break;
}
}
finalElevation = bestFeature_elevation;
result = 1;
}
else {
finalElevation = double.MaxValue;
}
return result;
}