예제 #1
0
        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);
        }
예제 #2
0
파일: Graph.cs 프로젝트: Yud07/Pax-Infinium
        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);
            }
        }
예제 #3
0
        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
예제 #4
0
        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);
        }
예제 #5
0
파일: Graph.cs 프로젝트: junian/NeoGraph
        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;
        }
예제 #6
0
        /// <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);
        }
예제 #7
0
        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;
         }
     }
 }
예제 #9
0
        /// <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);
            }
        }
예제 #10
0
        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);
                    }
                }
            }
        }
예제 #12
0
        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);
        }
예제 #13
0
            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);
            }
예제 #14
0
        /// <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
예제 #15
0
        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);
        }
예제 #16
0
        /// <summary>
        /// Returns the minimum item
        /// </summary>
        /// <returns></returns>
        public T FindMin()
        {
            IndexedItem item = _priQueue.FindMin();

            return(item.Value);
        }
예제 #17
0
        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;
        }
예제 #18
0
파일: Graph.cs 프로젝트: junian/NeoGraph
        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;
        }
예제 #19
0
        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 профиля геологии");
            }
        }
예제 #20
0
 public KeyValuePair <TKey, TValue> PeekMin() => _heap.FindMin();