public static Network Bfs(Network start, int target) { Network solution = null; var fringe = new C5.IntervalHeap <Network>( // Use this heuristic for picking the next // item to process new NetworkHeuristic(), C5.MemoryType.Normal ); var discovered = new HashSet <string>(); fringe.Add(start); while (solution == null && fringe.Count > 0) { // Find network with lowest heuristic value var network = fringe.FindMin(); fringe.DeleteMin(); if (network == null) { continue; } #if VERBOSE Console.WriteLine(network.GetInvariant()); if (fringe.Count % 100 == 0) { Console.WriteLine($"Progress Report:\n FringeSize: {fringe.Count}\n Discovered: {discovered.Count}"); } #endif // Solution is found when network is solved // (e.g. has one node) and meets target depth if (network.Solved) { if (network.Depth <= target) { solution = network; } } // Seen this, store invariant discovered.Add(network.GetInvariant()); foreach (var child in network.GetChildren()) { var childinv = child.GetInvariant(); // Dont process if // - seen already // - cannot meet target because of constraints if (!discovered.Contains(childinv) && child.CanReachTarget(target)) { fringe.Add(child); } } } return(solution); }
public List <Vector3> AStar(Vector3 goal) { ClearNodeData(); foreach (Node n in nodes) { n.SetCostToGo(goal); } Node startN = GetNode(start); Node endN = GetNode(goal); if (startN == null || endN == null) { return(null); } var leafsPQueue = new C5.IntervalHeap <Node>(); // Priority Queue startN.costSoFar = 0; leafsPQueue.Add(startN); while (!leafsPQueue.IsEmpty) { Node leaf = leafsPQueue.FindMin(); leafsPQueue.DeleteMin(); if (leaf == endN) { break; } foreach (Node neighbor in leaf.neighbors) { int newCostSoFar = leaf.costSoFar + Game1.world.cubeDist(leaf.pos, neighbor.pos); if (neighbor.costSoFar > newCostSoFar) { neighbor.prev = leaf; neighbor.costSoFar = newCostSoFar; leafsPQueue.Add(neighbor); } } } if (endN.prev != null) { List <Vector3> result = new List <Vector3>(); Node node = endN; while (node.prev != null) { result.Add(node.prev.cube.gridPos); node = node.prev; } result.Reverse(); return(result); } else { return(null); } }
public static void DijstraSPA(int[,] Graph, int startNode, int EndNode) { char[] Color = new char[size]; Distance = new int[size]; Parent = new int?[size]; for (int v = 0; v < size; v++) { Color[v] = 'w'; Distance[v] = big; } var minHeap = new C5.IntervalHeap <Tuple <int, int> >(); Distance[startNode - 1] = 0; Parent[startNode - 1] = null; Color[startNode - 1] = 'g'; minHeap.Add(new Tuple <int, int>(Distance[startNode - 1], startNode)); while (!minHeap.IsEmpty) { int selMin = minHeap.FindMin().Item2; minHeap.DeleteMin(); // Black node = out of the heap for examination Color[selMin - 1] = 'b'; //if (selMin == EndNode) //{ // return Parent; //} for (int i = 0; i < size; i++) { if (Color[i] == 'b') { continue; } int currentNodeDist = Distance[selMin - 1]; int selectionDist = Distance[i]; int potentialDist = EdgeWeight[selMin - 1, i].Value; if (potentialDist == big) { continue; } if (currentNodeDist + potentialDist < selectionDist) { Distance[i] = currentNodeDist + potentialDist; Parent[i] = selMin; minHeap.Add(new Tuple <int, int>(Distance[i], i + 1)); Color[i] = 'g'; } } // for } // while } // DijstraSPA
internal static IReadOnlyList <T> KnnSearch <T>(this RBush <T> tree, object query, int n, Func <T, bool> predicate = null, double maxDist = -1) where T : ISpatialData { var distCalculator = new DistanceToSpatialCalculator(); if (maxDist > 0) { maxDist = maxDist * maxDist; //compare quadratic distances } List <T> result = new List <T>(); //priority queue var queue = new C5.IntervalHeap <IDistanceToSpatial>(new DistComparer()); RBush <T> .Node node = tree.Root; while (node != null) { foreach (ISpatialData child in node.Children) //for each child { var childDistData = distCalculator.CalculateDistanceToSpatial(query, child); //calc distance to box if (maxDist < 0 || childDistData.SquaredDistanceToBox <= maxDist) //check if distance less than max distance { queue.Add(childDistData); //add to queue } } //dequeue all objects that are items stored in RBush while (queue.Count > 0 && queue.FindMin().SpatialData is T) { var candidateWr = queue.DeleteMin(); //this item goes to result T candidate = (T)candidateWr.SpatialData; if (predicate == null || predicate.Invoke(candidate)) //if element satisfy the condition { result.Add(candidate); //add to result } if (n > 0 && result.Count == n) //if the desired amount is already in the result { return(result); //return result } } //process next element in queue if (queue.Count > 0) { node = queue.DeleteMin().SpatialData as RBush <T> .Node; } else { node = null; } } return(result); }
public void GenerateEuclideanOurNeoKruskalMST(int bucket) { if (VertexList.Count == 0) { return; } DateTime start = DateTime.Now; NeoDisjointSet <Vertex> disjointSet = new NeoDisjointSet <Vertex>(VertexList); EdgeSolution.Clear(); C5.IPriorityQueue <Edge>[] heap2 = new C5.IntervalHeap <Edge> [bucket]; C5.IPriorityQueue <Edge> heap = new C5.IntervalHeap <Edge>(new EdgeComparer()); for (int i = 0; i < heap2.Length; i++) { heap2[i] = new C5.IntervalHeap <Edge>(new EdgeComparer()); } //this.VisitedVertex = VertexList.Count; for (int i = 0; i < VertexList.Count - 1; i++) { for (int j = i + 1; j < VertexList.Count; j++) { Edge e = new Edge(VertexList[i], VertexList[j]); heap.Add(e); } } double max = heap.FindMax().Length; double min = heap.FindMin().Length; while (heap.Count > 0) { Edge s = heap.DeleteMin(); heap2[(int)Math.Floor((((s.Length - min) / (max - min)) * (bucket - 1)))].Add(s); } for (int i = 0; i < bucket && disjointSet.Count > 0; i++) { while (heap2[i].Count > 0 && disjointSet.Count > 0) { Edge s = heap2[i].DeleteMin(); if (!disjointSet.IsSameSet(s.VertexFirst, s.VertexSecond)) { disjointSet.Union(s.VertexFirst, s.VertexSecond); EdgeSolution.Add(s); } } } Debug.WriteLine((DateTime.Now - start).TotalMilliseconds + " ms"); //this.VisitedVertex = VertexList.Count; }
/// <summary> /// Search k nearest neighbors to given point or to to given line segment /// </summary> /// <typeparam name="T">type of RBush items</typeparam> /// <param name="tree">RBush object</param> /// <param name="x1">x coordinate of query point. /// Or if x2 and y2 not null, x coordinate of first endpoint of query line segment</param> /// <param name="y1">y coordinate of query point. /// Or if x2 and y2 not null, y coordinate of first endpoint of query line segment</param> /// <param name="n">number of nearest neighbors to get</param> /// <param name="predicate">condition for neighbors</param> /// <param name="maxDist">max distance for nearest neighbors</param> /// <param name="x2">if not null is x coordinate of second endpoint of query line segment</param> /// <param name="y2">if not null is y coordinate of second endpoint of query line segment</param> /// <returns></returns> public static IReadOnlyList <T> KnnSearch <T>(this RBush <T> tree, double x1, double y1, int n, Func <T, bool> predicate = null, double maxDist = -1, double?x2 = null, double?y2 = null) where T : ISpatialData { if (maxDist > 0) { maxDist = maxDist * maxDist; //All distances are quadratic!!! } List <T> result = new List <T>(); //priority queue C5.IntervalHeap <SpatialDataWrapper> queue = new C5.IntervalHeap <SpatialDataWrapper>(new DistComparer()); RBush <T> .Node node = tree.Root; while (node != null) { foreach (ISpatialData child in node.Children) //for each child { SpatialDataWrapper childDistData = new SpatialDataWrapper(child, x1, y1, x2, y2); //calc distance to box if (maxDist < 0 || childDistData.SquaredDistanceToBox <= maxDist) //check if distance less than max distance { queue.Add(childDistData); //add to queue } } //dequeue all objects that are items stored in RBush while (queue.Count > 0 && queue.FindMin().SpatialData is T) { SpatialDataWrapper candidate = queue.DeleteMin(); //this item goes to result T _candidate = (T)candidate.SpatialData; if (predicate == null || predicate.Invoke(_candidate)) //if element satisfy the condition { result.Add(_candidate); //add to result } if (n > 0 && result.Count == n) //if the desired amount is already in the result { return(result); //return result } } //process next element in queue if (queue.Count > 0) { node = queue.DeleteMin().SpatialData as RBush <T> .Node; } else { node = null; } } return(result); }
public static LinkedList<Node> BuildNodePathUsingAStarWithoutSystem(Node Start, Node Goal, HeuristicCalculator Calculator, NextStatesProvider Provider) { int expandedNodesCount = 0; bool found = false; TreeNode start = new TreeNode(Start); TreeNode goal = new TreeNode(null); var toExpand = new C5.IntervalHeap<TreeNode>(new TreeNodeCostComparer()); var discoveredTreeNodes = new Dictionary<int, TreeNode>(); start.Cost = Calculator.Calculate(Start.State, Goal.State); toExpand.Add(start); discoveredTreeNodes.Add(start.Node.State.GetHashCode(), start); while (toExpand.Count > 0) { TreeNode Current = toExpand.FindMin(); toExpand.DeleteMin(); if (Current.Node.State.Equals(Goal.State)) { goal = Current; found = true; break; } expandedNodesCount++; foreach (var nextNode in Provider.GetNodesWithNextStates(Current.Node)) { double Cost = Calculator.Calculate(nextNode.State, Goal.State); if (!discoveredTreeNodes.ContainsKey(nextNode.State.GetHashCode())) { TreeNode Tem = new TreeNode(nextNode, Current, Current.Cost + Cost); Current.Children.AddLast(Tem); discoveredTreeNodes.Add(nextNode.State.GetHashCode(), Tem); toExpand.Add(Tem); } else { CheckIfBetterPathWasFound(discoveredTreeNodes, Current, nextNode, Cost); } } } Console.WriteLine("Expanded {0} nodes", expandedNodesCount); if (!found) throw new PathNotFoundException("Path not found!"); return createPath(goal, start); }
/// <summary> /// Removes expired events /// </summary> public void DoExpirations() { while (_sortedEvents.Count > 0) { DeferredEventList list = _sortedEvents.FindMin(); if (Util.Clock.GetLongTickCount() >= list.ExpiresOn) { Delete(list); } else { break; } } }
/// <summary> /// Checks for retries that are ready to be applied /// </summary> private void CheckForReadyRetries() { List <DelayedMutation> needsRetry = new List <DelayedMutation>(); while (_delayedMutations.Count > 0) { DelayedMutation mut; lock (_delayedMutations) { mut = _delayedMutations.FindMin(); if (mut.ReadyOn > DateTime.Now) { break; } _delayedMutations.DeleteMin(); } try { mut.Execute(); } catch (Exception e) { _log.ErrorFormat("[Inworldz.Data.Inventory.Cassandra] Error while applying mutation {0} on retry {1}: {2}", mut.Identifier, mut.RetryCount + 1, e); mut.RetryCount++; if (mut.RetryCount == MAX_RETRIES) { _log.ErrorFormat("[Inworldz.Data.Inventory.Cassandra] CRITICAL: Retry limit reached, discarding mutation {0}", mut.Identifier); } else { needsRetry.Add(mut); } } } foreach (DelayedMutation delayedMutation in needsRetry) { ScheduleMutationRetry(delayedMutation); } }
private static void PrimMain() { while (Heap.Count > 0) { p z = Heap.FindMin(); int u = z.v; int du = z.w; Heap.DeleteMin(); if (!kt[u]) { continue; } kt[u] = false; d[u] = 0; if (u != S) { SaveGraph(trace[u]); } foreach (p canh in listCanh[u]) { int v = canh.v; int w = canh.w; if (d[v] > d[u] + w) { d[v] = d[u] + w; trace[v] = canh.ID; p xx = new p(); xx.v = v; xx.w = d[v]; Heap.Add(xx); } } } }
private static void DijkstraMain() { while (Heap.Count > 0) { p z = Heap.FindMin(); int u = z.v; int du = z.w; Heap.DeleteMin(); if (!kt[u]) { continue; } kt[u] = false; SaveGraph(u); if (u == T) { return; } foreach (p canh in listCanh[u]) { int v = canh.v; int w = canh.w; if (d[v] > d[u] + w) { d[v] = d[u] + w; trace[v] = u; p xx = new p(); xx.v = v; xx.w = d[v]; Heap.Add(xx); } } } }
public static void Dijkstra(DrawingSurface ds, int start) { if (ds.ContainsNegativeEdge()) { var err = new ErrorBox("Graph contains negative edges"); err.ShowDialog(); return; } Dictionary <int, List <Edge> > adjList = ds.GetDestAdjList(); var que = new C5.IntervalHeap <Edge>(new EdgeCompare()); double[] dist = Enumerable.Repeat((double)int.MaxValue, adjList.Count).ToArray(); int[] parent = Enumerable.Repeat(-1, adjList.Count).ToArray(); var visitedColor = Color.Green; var processedColor = Color.Yellow; var currentEdgeColor = Color.Red; que.Add(new Edge(ds.Vertices[start], ds.Vertices[start], 0, true)); dist[start] = 0; for (var i = 0; i < ds.Vertices.Count; ++i) { ds.Vertices[i].label = "INF"; } ds.Vertices[start].label = "0"; while (que.Count != 0) { var currEdge = que.FindMin(); que.DeleteMin(); var startVertex = (ds.Vertices[currEdge.end].fillColor == visitedColor) ? currEdge.start : currEdge.end; ReDrawCircle(ds, startVertex, visitedColor); foreach (var edge in adjList[startVertex]) { var currVertex = (edge.end != startVertex) ? edge.end : edge.start; ReDrawEdge(ds, edge, currentEdgeColor, 300); if (ds.Vertices[currVertex].fillColor != visitedColor) { ReDrawCircle(ds, currVertex, processedColor, 0); } Thread.Sleep(1000); if (dist[currVertex] > dist[startVertex] + edge.w) { dist[currVertex] = dist[startVertex] + edge.w; parent[currVertex] = startVertex; ds.Vertices[currVertex].label = $"{Math.Round(dist[currEdge.end], 3)}+{Math.Round(edge.w, 3)}"; ds.Invalidate(); Thread.Sleep(1000); que.Add(edge); } ds.Vertices[currVertex].label = (dist[currVertex] == int.MaxValue) ? "INF" : $"{dist[currVertex]}"; ReDrawEdge(ds, edge, Color.Gray, 0); } } msg.SetTitle("Dijkstra algorithm result:"); msg.MoveToCorner(ds.FindForm() as Form1); msg.StartMenu(); for (var target = 0; target < adjList.Count; ++target) { if (start != target) { var currWay = GetWay(start, target, parent); PrintWay(currWay, dist[target]); Thread.Sleep(1000); } } msg.WaitOne(); ClearEdges(ds); ClearVertices(ds); }
private bool AddIntersections(double start, double end, HatchNestingNode hatchNode) { //расчет пересечений с помощью логики сканирующей линии //сформировать очередь событий начала и конца каждого сегмента (вертикальные сегменты при этом не брать в расчет!) //перейти по очереди до start, получить пересекаемые отрезки и точки пересечения, //затем до end, получить пересекаемые отрезки и точки пересечения //БУДУТ ПОЛУЧЕНЫ ТОЧКИ ПЕРЕСЕЧЕНИЯ ТАМ, ГДЕ ВЕРТИКАЛЬНЫЙ СЕГМЕНТ СТЫКУЕТСЯ С НЕВЕРТИКАЛЬНЫМ //БУДУТ ДУБЛИРОВАТЬСЯ ТОЧКИ ПЕРЕСЕЧЕНИЙ В ТОЧКАХ СТЫКОВКИ ДВУХ СОСЕДНИХ СЕГМЕНТОВ КОНТУРА C5.IntervalHeap <SweepLineEvent> queue = new C5.IntervalHeap <SweepLineEvent>(); foreach (Curve2d curve2d in hatchNode.Boundary.GetCurves()) { LineSegment2d lineSegment2D = (LineSegment2d)curve2d; double p0x = lineSegment2D.StartPoint.X; double p1x = lineSegment2D.EndPoint.X; if (Math.Abs(p0x - p1x) < Tolerance.Global.EqualPoint) { continue;//вертикальные сегменты не интересуют } double segStart = double.NegativeInfinity; double segEnd = double.NegativeInfinity; if (p0x < p1x) { segStart = p0x; segEnd = p1x; } else { segStart = p1x; segEnd = p0x; } queue.Add(new SweepLineEvent(segStart, true, lineSegment2D)); queue.Add(new SweepLineEvent(segEnd, false, lineSegment2D)); } HashSet <LineSegment2d> currSegments = new HashSet <LineSegment2d>(); Action goThoughEvent = () => { SweepLineEvent e = queue.DeleteMin(); if (e.Start) { currSegments.Add(e.LineSegment2D); } else { currSegments.Remove(e.LineSegment2D); } }; while (queue.Count > 0 && queue.FindMin().Position < start)//пройти все события до start { goThoughEvent(); } //TODO: В ТЕКУЩЕМ НАБОРЕ СЕГМЕНТОВ МОГУТ НАХОДИТЬСЯ 2 СТЫКУЮЩИХСЯ СЕГМЕНТА, ДАЮЩИЕ В РЕЗУЛЬТАТЕ ОДНУ И ТУ ЖЕ ТОЧКУ ПЕРЕСЕЧЕНИЯ //если на одной из вертикалей только одна точка пересечения, то не учитывать ее bool result0 = false; foreach (LineSegment2d seg in currSegments)//получить пересечения { result0 = AddIntersection(seg, startVert, hatchNode, startVertSorted); } while (queue.Count > 0 && queue.FindMin().Position < end)//пройти все события до end { goThoughEvent(); } bool result1 = false; foreach (LineSegment2d seg in currSegments)//получить пересечения { result1 = AddIntersection(seg, endVert, hatchNode, endVertSorted); } return(result0 || result1); }
/// <summary> /// Find shortest path from one node to one other node /// with modified Dijkstra's DPA /// </summary> /// <param name="graph"></param> /// <param name="startNode"></param> /// <param name="endNode"></param> /// <returns></returns> public static Stack <int> GetSPWithDijkstra(int?[,] graph, int startNode, int endNode) { // Variable declaration and initialization bool[] visited = new bool[size]; int[] distance = new int[size]; int[] parent = new int[size]; Queue <int> ShortestPath = new Queue <int>(); // Assign default values to visited and distance array for (int v = 0; v < size; v++) { visited[v] = false; distance[v] = Helper.big; } // MinHeap for the algorithm // First int is for the distance // Second int is for the node number var minHeap = new C5.IntervalHeap <Tuple <int, int> >(); distance[startNode - 1] = 0; minHeap.Add(new Tuple <int, int>(distance[startNode - 1], startNode)); while (!minHeap.IsEmpty) { int selMin = minHeap.FindMin().Item2; minHeap.DeleteMin(); // This node is being visited for examination visited[selMin - 1] = true; // Found the destination. Terminate if (selMin == endNode) { int current = destination; Stack <int> shortestPathStack = new Stack <int>(); while (current != 0) { shortestPathStack.Push(current); current = parent[current - 1]; } return(shortestPathStack); } for (int i = 0; i < size; i++) { DijkstraCount++; // This node has been visited and examined if (visited[i] == true) { continue; } // There is no edge between the current node and the potential node // Helper.big and null mean the same thing // Prevent overflow If use Helper.big as max int value int?potentialDist = graph[selMin - 1, i]; if (potentialDist == Helper.big || potentialDist == null) { continue; } int currentNodeDist = distance[selMin - 1]; int selectionDist = distance[i]; if (currentNodeDist + potentialDist.Value < selectionDist) { distance[i] = currentNodeDist + potentialDist.Value; parent[i] = selMin; minHeap.Add(new Tuple <int, int>(distance[i], i + 1)); } } // for loop } // while loop // Cannot find the path, return null return(null); } // DijstraSPA
private bool VertexGuidedSearch(int iv, int iw) { var v = _nodes[iv]; var w = _nodes[iw]; f.Clear(); b.Clear(); f.Add(w); w.Value.InF = true; b.Add(v); v.Value.InB = true; w.Value.OutEnum = w.Value.Outgoing.GetEnumerator(); w.Value.OutEnum.MoveNext(); v.Value.InEnum = v.Value.Incoming.GetEnumerator(); v.Value.InEnum.MoveNext(); var fl = new C5.IntervalHeap <SGTNode <HKMSTNode> >(); var bl = new C5.IntervalHeap <SGTNode <HKMSTNode> >(); if (w.Value.OutEnum.Current != null) { fl.Add(w); } if (v.Value.InEnum.Current != null) { bl.Add(v); } // For ease of notation, we adopt the convention that the // minimum of an empty set is bigger than any other value and the maximum of an empty // set is smaller than any other value. SGTNode <HKMSTNode> u = null; SGTNode <HKMSTNode> z = null; if (fl.Count > 0) { u = fl.FindMin(); } if (bl.Count > 0) { z = bl.FindMax(); } while (fl.Count > 0 && bl.Count > 0 && (u == z || _nodeOrder.Query(z, u))) { // SEARCH-STEP(vertex u, vertex z) var x = u.Value.OutEnum.Current; var y = z.Value.InEnum.Current; u.Value.OutEnum.MoveNext(); z.Value.InEnum.MoveNext(); if (u.Value.OutEnum.Current == null) { fl.DeleteMin(); } if (z.Value.InEnum.Current == null) { bl.DeleteMax(); } if (x.Value.InB) { f.ForEach(item => item.Value.InF = false); b.ForEach(item => item.Value.InB = false); return(false); // Pair(uz.from, x.Current); } else if (y.Value.InF) { f.ForEach(item => item.Value.InF = false); b.ForEach(item => item.Value.InB = false); return(false); // Pair(y.Current, uz.to); } if (!x.Value.InF) { f.Add(x); x.Value.InF = true; x.Value.OutEnum = x.Value.Outgoing.GetEnumerator(); x.Value.OutEnum.MoveNext(); if (x.Value.OutEnum.Current != null) { fl.Add(x); } } if (!y.Value.InB) { b.Add(y); y.Value.InB = true; y.Value.InEnum = y.Value.Incoming.GetEnumerator(); y.Value.InEnum.MoveNext(); if (y.Value.InEnum.Current != null) { bl.Add(y); } } // End of SEARCH-STEP(vertex u, vertex z) if (fl.Count > 0) { u = fl.FindMin(); } if (bl.Count > 0) { z = bl.FindMax(); } } // let t = min({v}∪{x ∈ F|out(x) = null} and reorder the vertices in F< and B> as discussed previously. var vAndf = f.FindAll(item => item.Value.OutEnum.Current != null); vAndf.Add(v); var t = vAndf.Min(); // Let F< = { x ∈ F | x < t} and var fb = f.FindAll(item => item.Label < t.Label); // B > = { y ∈ B | y > t}. var bf = b.FindAll(item => item.Label > t.Label); if (t == v) { // move all vertices in fb just after t ... bf is empty foreach (var node in fb) { _nodeOrder.Remove(node); } if (fb.Count > 1) { fb = TopoSort(fb); } if (fb.Count > 0) { var prev = _nodeOrder.insertAfter(t, fb[0]); for (int i = 1; i < fb.Count; i++) { prev = _nodeOrder.insertAfter(prev, fb[i]); } } } if (t.Label < v.Label) { // move all vertices in fb just before t and all vertices in bf just before all vertices in fb // This is required as the articles states if (bf.Count > 1) { bf = TopoSort(bf); } if (fb.Count > 1) { fb = TopoSort(fb); } foreach (var node in bf) { _nodeOrder.Remove(node); } foreach (var node in fb) { _nodeOrder.Remove(node); } foreach (var item in fb) { bf.Add(item); } if (bf.Count > 0) { var prev = _nodeOrder.insertBefore(t, bf[bf.Count - 1]); if (bf.Count > 1) { for (int i = bf.Count - 2; i >= 0; i--) { prev = _nodeOrder.insertBefore(prev, bf[i]); } } } } // reset bools f.ForEach(item => item.Value.InF = false); b.ForEach(item => item.Value.InB = false); // all done add to Outgoing and Incoming _nodes[iv].Value.Outgoing.Add(_nodes[iw]); _nodes[iw].Value.Incoming.Add(_nodes[iv]); return(true); }
/// <summary> /// Returns the minimum item /// </summary> /// <returns></returns> public T FindMin() { IndexedItem item = _priQueue.FindMin(); return(item.Value); }
private bool VertexGuidedSearch(int iv, int iw) { var v = _nodes[iv]; var w = _nodes[iw]; f.Clear(); b.Clear(); f.Add(w); w.Value.InF = true; b.Add(v); v.Value.InB = true; w.Value.OutEnum = w.Value.Outgoing.GetEnumerator(); w.Value.OutEnum.MoveNext(); v.Value.InEnum = v.Value.Incoming.GetEnumerator(); v.Value.InEnum.MoveNext(); var fl = new C5.IntervalHeap<SGTNode<HKMSTNode>>(); var bl = new C5.IntervalHeap<SGTNode<HKMSTNode>>(); if (w.Value.OutEnum.Current != null) fl.Add(w); if (v.Value.InEnum.Current != null) bl.Add(v); // For ease of notation, we adopt the convention that the // minimum of an empty set is bigger than any other value and the maximum of an empty // set is smaller than any other value. SGTNode<HKMSTNode> u = null; SGTNode<HKMSTNode> z = null; if(fl.Count > 0) u = fl.FindMin(); if(bl.Count > 0) z = bl.FindMax(); while (fl.Count > 0 && bl.Count > 0 && (u == z || _nodeOrder.Query(z, u))) { // SEARCH-STEP(vertex u, vertex z) var x = u.Value.OutEnum.Current; var y = z.Value.InEnum.Current; u.Value.OutEnum.MoveNext(); z.Value.InEnum.MoveNext(); if (u.Value.OutEnum.Current == null) fl.DeleteMin(); if (z.Value.InEnum.Current == null) bl.DeleteMax(); if(x.Value.InB) { f.ForEach(item => item.Value.InF = false); b.ForEach(item => item.Value.InB = false); return false; // Pair(uz.from, x.Current); } else if (y.Value.InF) { f.ForEach(item => item.Value.InF = false); b.ForEach(item => item.Value.InB = false); return false; // Pair(y.Current, uz.to); } if (!x.Value.InF) { f.Add(x); x.Value.InF = true; x.Value.OutEnum = x.Value.Outgoing.GetEnumerator(); x.Value.OutEnum.MoveNext(); if (x.Value.OutEnum.Current != null) fl.Add(x); } if (!y.Value.InB) { b.Add(y); y.Value.InB = true; y.Value.InEnum = y.Value.Incoming.GetEnumerator(); y.Value.InEnum.MoveNext(); if (y.Value.InEnum.Current != null) bl.Add(y); } // End of SEARCH-STEP(vertex u, vertex z) if (fl.Count > 0) u = fl.FindMin(); if (bl.Count > 0) z = bl.FindMax(); } // let t = min({v}∪{x ∈ F|out(x) = null} and reorder the vertices in F< and B> as discussed previously. var vAndf = f.FindAll(item => item.Value.OutEnum.Current != null); vAndf.Add(v); var t = vAndf.Min(); // Let F< = { x ∈ F | x < t} and var fb = f.FindAll(item => item.Label < t.Label); // B > = { y ∈ B | y > t}. var bf = b.FindAll(item => item.Label > t.Label); if(t == v) { // move all vertices in fb just after t ... bf is empty foreach (var node in fb) _nodeOrder.Remove(node); if(fb.Count > 1) fb = TopoSort(fb); if (fb.Count > 0) { var prev = _nodeOrder.insertAfter(t, fb[0]); for (int i = 1; i < fb.Count; i++) prev = _nodeOrder.insertAfter(prev, fb[i]); } } if (t.Label < v.Label) { // move all vertices in fb just before t and all vertices in bf just before all vertices in fb // This is required as the articles states if (bf.Count > 1) bf = TopoSort(bf); if (fb.Count > 1) fb = TopoSort(fb); foreach (var node in bf) _nodeOrder.Remove(node); foreach (var node in fb) _nodeOrder.Remove(node); foreach (var item in fb) bf.Add(item); if (bf.Count > 0) { var prev = _nodeOrder.insertBefore(t, bf[bf.Count-1]); if(bf.Count > 1) { for (int i = bf.Count - 2; i >= 0; i--) prev = _nodeOrder.insertBefore(prev, bf[i]); } } } // reset bools f.ForEach(item => item.Value.InF = false); b.ForEach(item => item.Value.InB = false); // all done add to Outgoing and Incoming _nodes[iv].Value.Outgoing.Add(_nodes[iw]); _nodes[iw].Value.Incoming.Add(_nodes[iv]); return true; }
public void GenerateEuclideanOurNeoKruskalMST(int bucket) { if (VertexList.Count == 0) return; DateTime start = DateTime.Now; NeoDisjointSet<Vertex> disjointSet = new NeoDisjointSet<Vertex>(VertexList); EdgeSolution.Clear(); C5.IPriorityQueue<Edge>[] heap2 = new C5.IntervalHeap<Edge>[bucket]; C5.IPriorityQueue<Edge> heap = new C5.IntervalHeap<Edge>(new EdgeComparer()); for (int i = 0; i < heap2.Length; i++) { heap2[i] = new C5.IntervalHeap<Edge>(new EdgeComparer()); } //this.VisitedVertex = VertexList.Count; for (int i = 0; i < VertexList.Count - 1; i++) for (int j = i + 1; j < VertexList.Count; j++) { Edge e = new Edge(VertexList[i], VertexList[j]); heap.Add(e); } double max = heap.FindMax().Length; double min = heap.FindMin().Length; while (heap.Count > 0) { Edge s = heap.DeleteMin(); heap2[(int)Math.Floor((((s.Length - min) / (max - min)) * (bucket - 1)))].Add(s); } for (int i = 0; i < bucket && disjointSet.Count > 0; i++) { while (heap2[i].Count > 0 && disjointSet.Count > 0) { Edge s = heap2[i].DeleteMin(); if (!disjointSet.IsSameSet(s.VertexFirst, s.VertexSecond)) { disjointSet.Union(s.VertexFirst, s.VertexSecond); EdgeSolution.Add(s); } } } Debug.WriteLine((DateTime.Now - start).TotalMilliseconds + " ms"); //this.VisitedVertex = VertexList.Count; }
private void Create3dProfile(object arg) { try { if (doc != null) { List <ObjectId> toHighlight = new List <ObjectId>(); using (doc.LockDocument()) { Editor ed = doc.Editor; Database db = doc.Database; using (Transaction tr = db.TransactionManager.StartTransaction()) { //найти координату X начала профиля (крайнюю левую) double minx = double.PositiveInfinity; List <ObjectId> allSelected = new List <ObjectId>(soilHatchIds); foreach (ObjectId id in allSelected) { Entity ent = null; try { ent = (Entity)tr.GetObject(id, OpenMode.ForRead); } catch (Autodesk.AutoCAD.Runtime.Exception) { continue; } Extents3d?ext = ent.Bounds; if (ext != null) { Point3d minPt = ext.Value.MinPoint; if (minx > minPt.X) { minx = minPt.X; } } } //Штриховки должны быть заранее раскиданы по слоям в соответствии с ИГЭ! //пересчет всех точек штриховок в координаты: //X - положение отностиельно начала профиля с учетом горизонтального масштаба профиля, //Y - отметка расчитанная согласно базовой отметке с учетом вертикального масштаба профиля Matrix2d transform = new Matrix2d(new double[] { HorScaling, 0, 0, 0, VertScaling, 0, 0, 0, 1 }) * Matrix2d.Displacement(new Vector2d(-minx, -ElevBasePoint.Value.Y + ElevationInput / VertScaling)); C5.IntervalHeap <HatchEvent> eventQueue = new C5.IntervalHeap <HatchEvent>(); List <HatchData> allHatchData = new List <HatchData>(); List <Point2dCollection> selfintersectingLoops = new List <Point2dCollection>(); foreach (ObjectId id in soilHatchIds) { //получить все точки штриховок с учетом возможных дуг, сплайнов и проч //Для каждой штриховки создается набор композитных кривых, состоящих из линейных сегментов Hatch hatch = null; try { hatch = (Hatch)tr.GetObject(id, OpenMode.ForRead); } catch (Autodesk.AutoCAD.Runtime.Exception) { continue; } List <CompositeCurve2d> boundaries = new List <CompositeCurve2d>(); List <Extents2d> extends = new List <Extents2d>(); List <Point2dCollection> ptsCollList = new List <Point2dCollection>(); List <List <double> > ptParamsList = new List <List <double> >(); for (int i = 0; i < hatch.NumberOfLoops; i++) { HatchLoop hl = hatch.GetLoopAt(i); if (!hl.LoopType.HasFlag(HatchLoopTypes.SelfIntersecting) && !hl.LoopType.HasFlag(HatchLoopTypes.Textbox) && !hl.LoopType.HasFlag(HatchLoopTypes.TextIsland) && !hl.LoopType.HasFlag(HatchLoopTypes.NotClosed)) { List <Curve2d> curves = Utils.GetHatchLoopCurves(hl); List <Curve2d> compositeCurveElems = new List <Curve2d>(); double _minx = double.PositiveInfinity; double _miny = double.PositiveInfinity; double _maxx = double.NegativeInfinity; double _maxy = double.NegativeInfinity; Action <Point2d> updateExtends = new Action <Point2d>(p => { _minx = p.X < _minx ? p.X : _minx; _miny = p.Y < _miny ? p.Y : _miny; _maxx = p.X > _maxx ? p.X : _maxx; _maxy = p.Y > _maxy ? p.Y : _maxy; }); Point2dCollection ptsColl = new Point2dCollection(); List <double> ptParams = new List <double>(); double currParam = 0; foreach (Curve2d c in curves) { if (!(c is LineSegment2d)) { Interval interval = c.GetInterval(); PointOnCurve2d[] samplePts = c.GetSamplePoints(interval.LowerBound, interval.UpperBound, 0.02); Point2d[] pts = samplePts.Select(p => transform * p.Point).ToArray(); for (int n = 0; n < pts.Length - 1; n++) { LineSegment2d lineSeg = new LineSegment2d(pts[n], pts[n + 1]); compositeCurveElems.Add(lineSeg); ptsColl.Add(pts[n]); ptParams.Add(currParam); updateExtends(pts[n]); currParam += lineSeg.Length; } } else { LineSegment2d lineSeg = (LineSegment2d)c; lineSeg.TransformBy(transform); compositeCurveElems.Add(lineSeg); ptsColl.Add(lineSeg.StartPoint); ptParams.Add(currParam); updateExtends(lineSeg.StartPoint); currParam += lineSeg.Length; } } CompositeCurve2d boundary = new CompositeCurve2d(compositeCurveElems.ToArray()); Extents2d ext = new Extents2d(_minx, _miny, _maxx, _maxy); boundaries.Add(boundary); ptsCollList.Add(ptsColl); ptParamsList.Add(ptParams); extends.Add(ext); } } //контуры штриховок не могут иметь самопересечений! #region Проверка на пересечения //проверка на самопересечения //bool badBoundaries = false; HashSet <int> badBoundaries = new HashSet <int>(); HashSet <int> splitBoundaries = new HashSet <int>();//Если 2 контура в одной штриховке пересекаются, то разносить их по разным штриховкам //List<HatchData> decomposeHatchData = new List<HatchData>();//TODO: самопересекающиеся полигоны нужно разбить на отдельные по количеству самопересечний. for (int i = 0; i < boundaries.Count; i++) { CompositeCurve2d b = boundaries[i]; CurveCurveIntersector2d intersector = new CurveCurveIntersector2d(b, b); if (intersector.NumberOfIntersectionPoints > 0) { //если происходит только наложение??? badBoundaries.Add(i); selfintersectingLoops.Add(ptsCollList[i]); } } if (boundaries.Count > 1) { //проверка на взаимные пересечения. //Исп RBush для того чтобы избежать проверки на пересечение каждого с каждым и квадратичной сложности //(работает только если контуры разнесены) //Не брать в расчет пересечения по касательной RBush <Spatial> boundariesRBush = new RBush <Spatial>(); List <Spatial> spatialData = new List <Spatial>(); for (int i = 0; i < extends.Count; i++) { spatialData.Add(new Spatial(extends[i], i)); } boundariesRBush.BulkLoad(spatialData); foreach (Spatial s in spatialData) { IReadOnlyList <Spatial> nearestNeighbors = boundariesRBush.Search(s.Envelope); if (nearestNeighbors.Count > 1) { CompositeCurve2d thisCurve = boundaries[(int)s.Obj]; foreach (Spatial n in nearestNeighbors) { if (!s.Equals(n)) { CompositeCurve2d otherCurve = boundaries[(int)n.Obj]; CurveCurveIntersector2d intersector = new CurveCurveIntersector2d(thisCurve, otherCurve); if (intersector.NumberOfIntersectionPoints > 0 || intersector.OverlapCount > 0) { bool matches = false; //Проверить, что кривые не накладываются друг на друга по всей длине (то есть полностью совпадают) if (intersector.OverlapCount > 0) { //сумма длин всех интервалов перекрытия равна общей длине кривой double thisCurveOverlapLength = 0; double otherCurveOverlapLength = 0; for (int i = 0; i < intersector.OverlapCount; i++) { Interval[] intervals = intersector.GetOverlapRanges(i); Interval thisOverlapInterval = intervals[0]; thisCurveOverlapLength += thisOverlapInterval.Length; Interval otherOverlapInterval = intervals[1]; otherCurveOverlapLength += otherOverlapInterval.Length; } Interval thisCurveInterval = thisCurve.GetInterval(); Interval otherCurveInterval = otherCurve.GetInterval(); if (Utils.LengthIsEquals(thisCurveOverlapLength, thisCurveInterval.Length) && Utils.LengthIsEquals(otherCurveOverlapLength, otherCurveInterval.Length)) { matches = true; } } if (!matches) { splitBoundaries.Add((int)s.Obj); splitBoundaries.Add((int)n.Obj); } else { badBoundaries.Add((int)s.Obj); badBoundaries.Add((int)n.Obj); } } } } } } } splitBoundaries.ExceptWith(badBoundaries); List <HatchData> splitHatchData = new List <HatchData>(); if (badBoundaries.Count > 0 || splitBoundaries.Count > 0) { List <CompositeCurve2d> boundariesClear = new List <CompositeCurve2d>(); List <Extents2d> extendsClear = new List <Extents2d>(); List <Point2dCollection> ptsCollListClear = new List <Point2dCollection>(); List <List <double> > ptParamsListClear = new List <List <double> >(); for (int i = 0; i < boundaries.Count; i++) { if (!badBoundaries.Contains(i) && !splitBoundaries.Contains(i)) { boundariesClear.Add(boundaries[i]); extendsClear.Add(extends[i]); ptsCollListClear.Add(ptsCollList[i]); ptParamsListClear.Add(ptParamsList[i]); } } foreach (int index in splitBoundaries) { splitHatchData.Add(new HatchData( new HatchNestingNode( boundaries[index], extends[index], ptsCollList[index], ptParamsList[index], hatch))); } boundaries = boundariesClear; extends = extendsClear; ptsCollList = ptsCollListClear; ptParamsList = ptParamsListClear; } #endregion //определяется вложенность контуров штриховки //ЕСЛИ ШТРИХОВКА СОСТОИТ ИЗ 2 И БОЛЕЕ КОНТУРОВ, КОТОРЫЕ НЕ ВЛОЖЕНЫ ДРУГ В ДРУГА, //ТО ЭТИ КОНТУРЫ ДОЛЖНЫ РАССМАТРИВАТЬСЯ КАК ОТДЕЛЬНЫЕ ШТРИХОВКИ!!! HatchNestingTree hatchNestingTree = new HatchNestingTree(boundaries, extends, ptsCollList, ptParamsList, hatch); List <HatchData> currHatchData = hatchNestingTree.GetHatchData(); currHatchData.AddRange(splitHatchData);//добавить контуры, полученные из взаимно пересекающихся контуров //currHatchData.AddRange(decomposeHatchData); allHatchData.AddRange(currHatchData); //Каждая штриховка имеет диапазон по X от начала до конца по оси. //В общую очередь событий сохраняются события начала и конца штриховки foreach (HatchData hd in currHatchData) { hd.AddEventsToQueue(eventQueue); } } //Трассу разбить на отрезки, на которых будут вставлены прямолинейные сегменты штриховок Polyline alignmentPoly = null; try { alignmentPoly = (Polyline)tr.GetObject(AlignmentPolyId, OpenMode.ForRead); } catch (Autodesk.AutoCAD.Runtime.Exception) { return; } int segments = alignmentPoly.NumberOfVertices - 1; List <AlignmentSegment> alignmentSegments = new List <AlignmentSegment>(); Action <Point2d, Point2d> addAlignmentSegment = new Action <Point2d, Point2d>((p0, p1) => { double start = alignmentPoly.GetDistAtPoint(new Point3d(p0.X, p0.Y, 0)); double end = alignmentPoly.GetDistAtPoint(new Point3d(p1.X, p1.Y, 0)); if (Math.Abs(start - end) > Tolerance.Global.EqualPoint)//TODO: Это спорный момент - ведь может быть большое множество очень коротких участков подряд! { Vector2d startDir = p1 - p0; alignmentSegments.Add(new AlignmentSegment(start, end, p0, startDir)); } }); for (int i = 0; i < segments; i++) { SegmentType segmentType = alignmentPoly.GetSegmentType(i); Point2d startLoc = alignmentPoly.GetPoint2dAt(i); Point2d endLoc = alignmentPoly.GetPoint2dAt(i + 1); switch (segmentType) { case SegmentType.Line: addAlignmentSegment(startLoc, endLoc); break; case SegmentType.Arc: CircularArc2d arc = new CircularArc2d(startLoc, endLoc, alignmentPoly.GetBulgeAt(i), false); Interval interval = arc.GetInterval(); PointOnCurve2d[] samplePts = arc.GetSamplePoints(interval.LowerBound, interval.UpperBound, 0.1); for (int n = 0; n < samplePts.Length - 1; n++) { addAlignmentSegment(samplePts[n].Point, samplePts[n + 1].Point); } break; } } //проход по каждому отрезку трассы (диапазон отрезка - диапазон длины полилинии) HashSet <HatchData> currentHatchData = new HashSet <HatchData>(); foreach (AlignmentSegment alignmentSegment in alignmentSegments) { if (eventQueue.Count == 0) { break; //штриховки закончились } //Получить те штриховки, диапазон по X которых пересекается с диапазоном текущего отрезка //(СКАНИРУЮЩАЯ ЛИНИЯ: события - начало, конец штриховки) HashSet <HatchData> intervalHatchData = new HashSet <HatchData>(currentHatchData);//штриховки пришедшие из предыдущего участка остаются все //Собрать все события до конца сегмента //Если при проходе от начала до конца сегмента какая-то штриховка проходится полностью от начала до конца, то //все ее контуры без изменений должны быть переданы для создания М-полигона!!! (для них обход графа не нужен!) HashSet <HatchData> startedInsideInterval = new HashSet <HatchData>(); List <HatchData> hatchesCompletelyInsideInterval = new List <HatchData>(); while (eventQueue.Count > 0) { HatchEvent nextEvent = eventQueue.FindMin(); if (nextEvent.Position > alignmentSegment.End) { break; } else if (nextEvent.Start) { //добавить штриховку в текущий набор HatchData hd = eventQueue.DeleteMin().HatchData; currentHatchData.Add(hd); //добавлять в набор текущего интервла только в том случае, //если сканирующая линия еще не дошла до конца интервала if (nextEvent.Position < alignmentSegment.End && !Utils.LengthIsEquals(nextEvent.Position, alignmentSegment.End)) //Допуск нужен { startedInsideInterval.Add(hd); intervalHatchData.Add(hd); } } else { //убрать штриховку из текущего набора HatchData hd = eventQueue.DeleteMin().HatchData; currentHatchData.Remove(hd); if (startedInsideInterval.Contains(hd)) { hatchesCompletelyInsideInterval.Add(hd); } } } foreach (HatchData hd in hatchesCompletelyInsideInterval) { HatchSegmentData hsd = new HatchSegmentData(hd); alignmentSegment.HatchSegmentData.Add(hsd); hsd.Polygons = hd.GetAllBoundaries(); } intervalHatchData.ExceptWith(hatchesCompletelyInsideInterval); foreach (HatchData hd in intervalHatchData) { HatchSegmentData hsd = new HatchSegmentData(hd); alignmentSegment.HatchSegmentData.Add(hsd); //для каждой штриховки выполнить построение и обход графа сегмента штриховки HatchSegmentGraph graph = new HatchSegmentGraph(alignmentSegment.Start, alignmentSegment.End, hd, doc.Editor); //сохранить наборы полигонов для текущего диапазона hsd.Polygons = graph.Result; } } //для каждого диапазона создать полученные полигоны в 3d BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable; BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); BlockTableRecord btr = new BlockTableRecord();//Каждый профиль в отдельный блок btr.Name = Guid.NewGuid().ToString(); ObjectId btrId = bt.Add(btr); tr.AddNewlyCreatedDBObject(btr, true); foreach (AlignmentSegment alignmentSegment in alignmentSegments) { List <Entity> flatObjs = new List <Entity>(); foreach (HatchSegmentData hsd in alignmentSegment.HatchSegmentData) { //PlaneSurface hsd.GetNesting(); Dictionary <Point2dCollection, List <Point2dCollection> > bwhs = hsd.GetBoundariesWithHoles(); foreach (KeyValuePair <Point2dCollection, List <Point2dCollection> > bwh in bwhs) { //создать Region Region region = null; using (Polyline poly = new Polyline()) { for (int i = 0; i < bwh.Key.Count; i++) { poly.AddVertexAt(i, bwh.Key[i], 0, 0, 0); } poly.Closed = true; DBObjectCollection coll = new DBObjectCollection(); coll.Add(poly); try { DBObjectCollection regionColl = Region.CreateFromCurves(coll); foreach (DBObject dbo in regionColl) { region = (Region)dbo; break; } } catch { } } //из Region создать PlaneSurface if (region != null) { using (PlaneSurface planeSurface = new PlaneSurface()) { planeSurface.CreateFromRegion(region); planeSurface.LayerId = hsd.Hatch.LayerId; planeSurface.ColorIndex = 256; ObjectId planeSurfaceId = ms.AppendEntity(planeSurface); tr.AddNewlyCreatedDBObject(planeSurface, true); //вырезать отверстия в PlaneSurface foreach (Point2dCollection holePts2d in bwh.Value) { if (holePts2d.Count < 3) { continue; } using (Polyline poly = new Polyline()) { for (int i = 0; i < holePts2d.Count; i++) { poly.AddVertexAt(i, holePts2d[i], 0, 0, 0); } poly.Closed = true; ObjectIdCollection trimPolyColl = new ObjectIdCollection(); trimPolyColl.Add(ms.AppendEntity(poly)); tr.AddNewlyCreatedDBObject(poly, true); List <Point2d> ptsList = new List <Point2d>(holePts2d.ToArray()); Point2d pickPt2d = Utils.GetAnyPointInsidePoligon(ptsList, Utils.DirectionIsClockwise(ptsList)); try { AcadDB.Surface.TrimSurface(planeSurfaceId, new ObjectIdCollection(), trimPolyColl, new Vector3dCollection() { Vector3d.ZAxis }, new Point3d(pickPt2d.X, pickPt2d.Y, 0), -Vector3d.ZAxis, false, false); } catch /*(Exception ex)*/ { //Вывод в командную строку Utils.ErrorToCommandLine(doc.Editor, "Ошибка при попытке вырезания отверстия в поверхности" /*, ex*/); } //Удалить все объекты, добавленные в чертеж! poly.Erase(); } } flatObjs.Add((Entity)planeSurface.Clone()); //Удалить все объекты, добавленные в чертеж! planeSurface.Erase(); } region.Dispose(); } } } foreach (Entity ent in flatObjs) { ent.TransformBy(alignmentSegment.Transform); /*ms*/ btr.AppendEntity(ent); tr.AddNewlyCreatedDBObject(ent, true); ent.Dispose(); } } BlockReference br = new BlockReference(Point3d.Origin, btrId); ms.AppendEntity(br); tr.AddNewlyCreatedDBObject(br, true); if (selfintersectingLoops.Count > 0) { Utils.ErrorToCommandLine(doc.Editor, "Отбраковано самопересекающихся контуров штриховок - " + selfintersectingLoops.Count + " (отмечены на профиле)"); ObjectId layerId = Utils.CreateLayerIfNotExists("САМОПЕРЕСЕКАЮЩИЙСЯ КОНТУР ШТРИХОВКИ", db, tr, color: Color.FromColorIndex(ColorMethod.ByAci, 1), lineWeight: LineWeight.LineWeight200); Matrix2d returnTransform = transform.Inverse(); foreach (Point2dCollection pts in selfintersectingLoops) { using (Polyline selfIntersectingPoly = new Polyline()) { selfIntersectingPoly.LayerId = layerId; selfIntersectingPoly.ColorIndex = 256; for (int i = 0; i < pts.Count; i++) { Point2d pt = pts[i].TransformBy(returnTransform); selfIntersectingPoly.AddVertexAt(i, pt, 0, 0, 0); } toHighlight.Add(ms.AppendEntity(selfIntersectingPoly)); tr.AddNewlyCreatedDBObject(selfIntersectingPoly, true); //selfIntersectingPoly.Highlight(); } } } tr.Commit(); } } ps.Visible = false; if (toHighlight.Count > 0) { using (Transaction tr = doc.Database.TransactionManager.StartTransaction()) { foreach (ObjectId id in toHighlight) { Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead); ent.Highlight(); } tr.Commit(); } } } } catch (System.Exception ex) { GeologyConvertationCommand.ClosePalette(null, null); CommonException(ex, "Ошибка при создании 3d профиля геологии"); } }
public KeyValuePair <TKey, TValue> PeekMin() => _heap.FindMin();