private async void MyDrawObject_DrawComplete(object sender, DrawEventArgs args) { try { _myDrawObject.IsEnabled = false; if (_cts != null) { _cts.Cancel(); } _cts = new CancellationTokenSource(); QueryTask queryTask = new QueryTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/TaxParcel/AssessorsParcelCharacteristics/MapServer/1"); Query query = new Query() { Geometry = args.Geometry, ReturnGeometry = true, OutSpatialReference = MyMap.SpatialReference }; QueryResult parcelsToIntersectResult = await queryTask.ExecuteTaskAsync(query, _cts.Token); List <Graphic> graphicList = new List <Graphic>(); graphicList.Add(new Graphic() { Geometry = args.Geometry }); SimplifyResult simplifiedIntersectGeometryResult = await _geometryService.SimplifyTaskAsync(graphicList, _cts.Token); IntersectResult intersectedParcelsResult = await _geometryService.IntersectTaskAsync(parcelsToIntersectResult.FeatureSet.ToList(), simplifiedIntersectGeometryResult.Results[0].Geometry, _cts.Token); Random random = new Random(); foreach (Graphic g in intersectedParcelsResult.Results) { SimpleFillSymbol symbol = new SimpleFillSymbol() { Fill = new System.Windows.Media.SolidColorBrush( System.Windows.Media.Color.FromArgb(255, (byte)random.Next(0, 255), (byte)random.Next(0, 255), (byte)random.Next(0, 255))), BorderBrush = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Black), BorderThickness = 1 }; g.Symbol = symbol; _intersectGraphicsLayer.Graphics.Add(g); } } catch (Exception ex) { if (ex is ServiceException) { MessageBox.Show(String.Format("{0}: {1}", (ex as ServiceException).Code.ToString(), (ex as ServiceException).Details[0]), "Error", MessageBoxButton.OK); return; } } }
// Main simplifying function. // Should be called asynchronously to show status texts at each step. public IEnumerable <string> ApplySimplifyingStep() { SimplifyResult = SimplifyResult.CannotSimplifyAgain; List <Graph> newGraphParts = new List <Graph>(); // PREPROCESSING 1: If the graph is not connected, then consider each component separately. foreach (Graph graphPart in GraphParts) { newGraphParts.AddRange(graphPart.SplitDisonnectedComponents()); } if (newGraphParts.Count > GraphParts.Count) { // When no simplification is done in a simplify step, then it can be said // that the graph can no longer be simplified. // Here, we did a simplification and we may simplify again in the next step. SimplifyResult = SimplifyResult.CanSimplifyAgain; GraphParts = newGraphParts; } yield return("PREPROCESS STEP 1: Seperated disconnected components..."); newGraphParts = new List <Graph>(); // PREPROCESSING 2: If the graph has cut-vertices, then test each block separately. foreach (Graph graphPart in GraphParts) { CutVerticesFinder cvf = new CutVerticesFinder(); List <Node> cutNodes = cvf.FindCutVertices(graphPart); if (cutNodes != null && cutNodes.Count > 1) { SimplifyResult = SimplifyResult.CanSimplifyAgain; // Since we consider "blocks" we need to add back the edges incident to // cut nodes to get blocks including cut nodes and their edges. List <Edge> edgesToAddBack = new List <Edge>(); foreach (Node cutNode in cutNodes) { List <Edge> edges = graphPart.GetEdges(cutNode); edgesToAddBack.AddRange(edges); // Cut nodes AND their edges are removed, // they will be added back to corresponding blocks. edges.ForEach(e => graphPart.Edges.Remove(e)); graphPart.Nodes.Remove(cutNode); } foreach (Graph disonnectedComponent in graphPart.SplitDisonnectedComponents()) { // Now we add back the edges. foreach (Edge edgeToAddBack in edgesToAddBack) { Node nodeInComponent = disonnectedComponent.Nodes.FirstOrDefault(n => n == edgeToAddBack.Node1 || n == edgeToAddBack.Node2); if (nodeInComponent != null) { Node cutNode = edgeToAddBack.Node1 == nodeInComponent ? edgeToAddBack.Node2 : edgeToAddBack.Node1; disonnectedComponent.AddNode(cutNode); disonnectedComponent.AddEdge(edgeToAddBack); } } newGraphParts.Add(disonnectedComponent); } } else { newGraphParts.Add(graphPart); } } GraphParts = newGraphParts; yield return("PREPROCESS STEP 2: If the graph has cut vertices, seperated all blocks of the graph..."); // PREPROCESSING 3: Each vertex of degree 2 plus its incident edges can be replaced by a single edge. foreach (Graph graphPart in GraphParts) { for (int i = 0; i < graphPart.Nodes.Count; i++) { List <Edge> edges = graphPart.GetEdges(graphPart.Nodes[i]); if (edges.Count == 1) { // Node with degree 1 is irrelevant to planarity, we can just remove. // This step may even be not needed (already removed previously). graphPart.Edges.Remove(edges[0]); graphPart.Nodes.Remove(graphPart.Nodes[i]); i--; SimplifyResult = SimplifyResult.CanSimplifyAgain; } if (edges.Count == 2) { // Node with degree 2, delete node and merge edges. Node node1 = edges[0].Node1 == graphPart.Nodes[i] ? edges[0].Node2 : edges[0].Node1; Node node2 = edges[1].Node1 == graphPart.Nodes[i] ? edges[1].Node2 : edges[1].Node1; graphPart.Edges.Remove(edges[0]); graphPart.Edges.Remove(edges[1]); graphPart.Nodes.Remove(graphPart.Nodes[i]); graphPart.GetOrCreateEdge(node1, node2); i--; SimplifyResult = SimplifyResult.CanSimplifyAgain; } } } yield return("PREPROCESS STEP 3: Each vertex of degree 2 plus its incident edges is replaced by a single edge..."); // Remove planar components from "GraphParts" or determine if any of components are non-planar List <Graph> partsToRemove = new List <Graph>(); foreach (Graph graphPart in GraphParts) { int n = graphPart.Nodes.Count; int e = graphPart.Edges.Count; if (n < 5 || e < 9) { partsToRemove.Add(graphPart); } else if (e > 3 * n - 6) { PlanarityResult = PlanarityResult.NonPlanar; } } foreach (Graph graph in partsToRemove) { GraphParts.Remove(graph); } if (GraphParts.Count == 0) { PlanarityResult = PlanarityResult.Planar; } yield return("PREPROCESS STEP 4: Removed planar components..."); }