protected override void OnMouseUp(MouseEventArgs arg) { base.OnMouseUp(arg); IMxDocument document = null; try { // Get user point document = ArcMap.Document; IPoint mapPoint = ArcMap.ThisApplication.Display.DisplayTransformation.ToMapPoint(arg.X, arg.Y); // Get flow direction SetupOp setupOp = UrbanDelineationExtension.Extension.Setup; IRaster flowDir = setupOp.FlowDirection; if (flowDir == null) { MessageBox.Show(_appWindow, Properties.Resources.Error_NoFlowDirection, Properties.Resources.Category_UrbanDelineation); return; } IGeoDataset flowDirDataset = (IGeoDataset)flowDir; // Process point IPointCollection pointCollection = new MultipointClass(); ((IGeometry)pointCollection).SpatialReference = flowDirDataset.SpatialReference; mapPoint.Project(flowDirDataset.SpatialReference); IPoint[] points = new IPoint[] { mapPoint }; pointCollection.AddPoints(1, ref points[0]); // Get flow path geometry IPolyline flowPath = null; string outputDir = null; IDistanceOp distanceOp = new RasterDistanceOpClass(); try { IEnvelope outputExtent = _GetSurfaceOutputExtent(mapPoint); if (outputExtent == null) { setupOp.SetAnalysisEnvironment((IRasterAnalysisEnvironment)distanceOp); } else { // Expand to ensure full boundary of watershed is included. double cellWidth = ((IRasterAnalysisProps)setupOp.FlowDirection).PixelWidth; double cellHeight = ((IRasterAnalysisProps)setupOp.FlowDirection).PixelHeight; outputExtent.Expand(cellWidth * 3.0, cellHeight * 3.0, false); setupOp.SetAnalysisEnvironment((IRasterAnalysisEnvironment)distanceOp, outputExtent); } // The RasterDistanceOpClass does not properly clean up after itself, so we have to do it ourselves // To do this, we need to track the output directory and delete it, since we don't have direct access to the // dataset that is left behind. To delete the directory, it must contain only the temp files generated by // the RasterDistanceOpClass and no others, so we create one here. The directory is then deleted in the // finally clause. ((IRasterAnalysisEnvironment)distanceOp).OutWorkspace = _GetUniqueOutputWorkspace(); outputDir = ((IRasterAnalysisEnvironment)distanceOp).OutWorkspace.PathName; IGeometryCollection flowPaths = distanceOp.CostPathAsPolyline(pointCollection, flowDirDataset, flowDirDataset); if (flowPaths.GeometryCount > 0) { flowPath = flowPaths.get_Geometry(0) as IPolyline; } } finally { UrbanDelineationExtension.ReleaseComObject(distanceOp); try { if (Directory.Exists(outputDir)) { Directory.Delete(outputDir, true); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("FlowTracingTool.OnMouseUp: " + ex.GetType().FullName + ": " + ex.Message); } } // Add flow path to map if (flowPath != null && !flowPath.IsEmpty) { // Create graphic element flowPath.SpatialReference = flowDirDataset.SpatialReference; // Weed removes points that are in-line since flow path is generated with vertices for every cell, even if they are exactly in-line ((IPolycurve)flowPath).Weed(0.001); IElement flowElement = new LineElementClass(); ((IElementProperties3)flowElement).Name = ELEMENT_NAME; flowElement.Geometry = flowPath; // Set color ILineSymbol lineSymbol = ((ILineElement)flowElement).Symbol; IRgbColor color = lineSymbol.Color as IRgbColor; Color systemColor = Color.Red; color.Blue = systemColor.B; color.Red = systemColor.R; color.Green = systemColor.G; lineSymbol.Color = color; ((ILineElement)flowElement).Symbol = lineSymbol; ((IGraphicsContainer)document.FocusMap.BasicGraphicsLayer).AddElement(flowElement, 0); ((IDocumentDirty)document).SetDirty(); document.ActiveView.Refresh(); } } catch (Exception ex) { MessageBox.Show(_appWindow, ex.Message, Properties.Resources.Caption_Error, MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { UrbanDelineationExtension.ReleaseComObject(document); } }