smunoz

How to find the altitude value for a point in a shapefile

Discussion created by smunoz on Jun 6, 2012
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[z] as IFeature;
                    tempDist = proximity.ReturnDistance(testFeature.Shape);

                    try {
                        double elevation = (double)((IFeature)selectedFeatures[z]).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;
        }

Outcomes