コード例 #1
0
        public void CreateAndWriteGraph()
        {
            //Instantiate property set manager necessary to gather alignment names
            PropertySetManager psmPipeline = new PropertySetManager(
                Application.DocumentManager.MdiActiveDocument.Database,
                PSetDefs.DefinedSets.DriPipelineData);

            PSetDefs.DriPipelineData driPipelineData = new PSetDefs.DriPipelineData();

            //Counter to count all disjoined graphs
            int graphCount = 0;
            //Flag to signal the entry point subgraph
            bool isEntryPoint = false;
            //Stringbuilder to collect all disjoined graphs
            StringBuilder sbAll = new StringBuilder();

            sbAll.AppendLine("digraph G {");

            while (GraphEntities.Count > 0)
            {
                //Increment graph counter
                graphCount++;

                //Collection to keep track of visited nodes
                //To prevent looping for ever
                //And to be able to handle disjoined piping networks
                HashSet <Handle> visitedHandles = new HashSet <Handle>();

                //Determine starting entity
                //Criteria: Only one child -> means an end node AND largest DN of all not visited
                //Currently only for one network
                //Disjoined networks are not handled yet

                GraphEntity ge = GraphEntities.Where(x => x.Cons.Length == 1).MaxBy(x => x.LargestDn()).FirstOrDefault();

                //prdDbg(ge.OwnerHandle.ToString());
                if (ge == null)
                {
                    //throw new System.Exception("No entity found!");
                    prdDbg("ERROR: Graph not complete!!!");
                    foreach (var item in GraphEntities)
                    {
                        Entity owner = item.Owner;
                        Line   line  = new Line();
                        line.Layer      = "0";
                        line.StartPoint = new Point3d();
                        switch (owner)
                        {
                        case Polyline pline:
                            line.EndPoint = pline.GetPointAtDist(pline.Length / 2);
                            break;

                        case BlockReference br:
                            line.EndPoint = br.Position;
                            break;

                        default:
                            break;
                        }
                        line.AddEntityToDbModelSpace(Application.DocumentManager.MdiActiveDocument.Database);
                    }
                    break;
                }

                //Flag the entry point subgraph
                isEntryPoint = true;

                //Variable to cache previous handle to avoid backreferences
                Handle previousHandle = default;

                //Collection to collect the edges
                HashSet <Edge> edges = new HashSet <Edge>();

                //Collection to collect the subgraphs
                Dictionary <string, Subgraph> subgraphs = new Dictionary <string, Subgraph>();

                //Using a stack traversing strategy
                Stack <GraphEntity> stack = new Stack <GraphEntity>();
                //Put the first element on to the stack manually
                stack.Push(ge);
                //Iterate the stack until no connected nodes left
                while (stack.Count > 0)
                {
                    //Fetch the topmost entity on stack
                    GraphEntity current = stack.Pop();

                    //Determine the subgraph it is part of
                    string alName = psmPipeline.ReadPropertyString(current.Owner, driPipelineData.BelongsToAlignment);
                    //Fetch or create new subgraph object
                    Subgraph subgraph;
                    if (subgraphs.ContainsKey(alName))
                    {
                        subgraph = subgraphs[alName];
                    }
                    else
                    {
                        subgraph = new Subgraph(dB, ComponentTable, alName);
                        subgraphs.Add(alName, subgraph);
                    }
                    subgraph.Nodes.Add(current.OwnerHandle);

                    if (isEntryPoint)
                    {
                        subgraph.isEntryPoint = isEntryPoint;
                        isEntryPoint          = false;
                    }

                    //Iterate over current node's children
                    foreach (Con con in current.Cons)
                    {
                        //Find the child the con is referencing to
                        GraphEntity child = GraphEntities.Where(x => x.OwnerHandle == con.ConHandle).FirstOrDefault();
                        //if it is the con refering back to the parent -> skip it
                        if (child == default || child.OwnerHandle == current.OwnerHandle)
                        {
                            continue;
                        }
                        //Also skip if child has already been visited
                        //This prevents from making circular graphs I think
                        //Comment next line out to test circular graphs
                        //if (visitedHandles.Contains(child.OwnerHandle)) continue; <-- First solution
                        //Solution with caching of previous handle, it I don't think it works when backtracking to a branch -> there will be a double arrow
                        if (previousHandle != null && previousHandle == child.OwnerHandle)
                        {
                            continue;
                        }
                        //Try to control which cons get written by their type
                        //Build string
                        string ownEnd = con.OwnEndType.ToString();
                        string conEnd = con.ConEndType.ToString();
                        string key    = ownEnd + "-" + conEnd;
                        if (!allowedCombinations[key])
                        {
                            continue;
                        }

                        //Tries to prevent duplicate Main-Main edges by eliminating upstream Main-Main instance
                        //Doesn't work if recursion just returned from a branch, because previous is set the the
                        //Last node on the branch
                        if (key == "Main-Main" && con.ConHandle == previousHandle)
                        {
                            continue;
                        }

                        //Record the edge between nodes
                        edges.Add(new Edge(current.OwnerHandle, child.OwnerHandle));
                        //edges.Add(new Edge(current.OwnerHandle, child.OwnerHandle, key));
                        //If this child node is in visited collection -> skip, so we don't ger circular referencing
                        if (visitedHandles.Contains(child.OwnerHandle))
                        {
                            continue;
                        }
                        //If the node has not been visited yet, then put it on the stack
                        stack.Push(child);
                    }
                    //When current iteration completes, put the current node handle in the visited collection
                    visitedHandles.Add(current.OwnerHandle);
                    //Cache current node handle to avoid backreference
                    previousHandle = current.OwnerHandle;
                }

                //Write collected data
                //Stringbuilder to contain the overall file
                //This must be refactored when working with disjoined networks
                StringBuilder sb = new StringBuilder();
                sb.AppendLine($"subgraph G_{graphCount} {{"); //First line of file stating a graph
                                                              //Set the shape of the nodes for whole graph
                sb.AppendLine("node [shape=record];");

                //Write edges
                foreach (Edge edge in edges)
                {
                    sb.AppendLine(edge.ToString("->"));
                }

                //Write subgraphs
                int i = 0;
                foreach (var sg in subgraphs)
                {
                    i++;
                    sb.Append(sg.Value.WriteSubgraph(i));
                }

                //Add closing curly brace correspoinding to the first line
                sb.AppendLine("}");
                //Append current disjoined graph to all collector
                sbAll.Append(sb.ToString());

                //using (System.IO.StreamWriter file = new System.IO.StreamWriter($"C:\\Temp\\MyGraph_{graphCount}.dot"))
                //{
                //    file.WriteLine(sb.ToString()); // "sb" is the StringBuilder
                //}

                //Modify the GraphEntities to remove visited entities
                GraphEntities = GraphEntities.ExceptWhere(x => visitedHandles.Contains(x.OwnerHandle)).ToHashSet();
            }

            //Closing brace of the main graph
            sbAll.AppendLine("}");

            //Check or create directory
            if (!Directory.Exists(@"C:\Temp\"))
            {
                Directory.CreateDirectory(@"C:\Temp\");
            }

            //Write the collected graphs to one file
            using (System.IO.StreamWriter file = new System.IO.StreamWriter($"C:\\Temp\\MyGraph.dot"))
            {
                file.WriteLine(sbAll.ToString()); // "sb" is the StringBuilder
            }
        }
コード例 #2
0
        public void AddEntityToPOIs(Entity ent)
        {
            switch (ent)
            {
            case Polyline pline:
                switch (GetPipeSystem(pline))
                {
                case PipeSystemEnum.Ukendt:
                    prdDbg($"Wrong type of pline supplied: {pline.Handle}");
                    return;

                case PipeSystemEnum.Stål:
                    POIs.Add(new POI(pline, pline.StartPoint.To2D(), EndType.Start, PSM, DriGraph));
                    POIs.Add(new POI(pline, pline.EndPoint.To2D(), EndType.End, PSM, DriGraph));
                    break;

                case PipeSystemEnum.Kobberflex:
                case PipeSystemEnum.AluPex:
                    #region STIK        //Find forbindelse til forsyningsrøret
                    Point3d pt    = pline.StartPoint;
                    var     query = allPipes.Where(x =>
                                                   pt.IsOnCurve(x, 0.025) &&
                                                   pline.Handle != x.Handle &&
                                                   GetPipeSystem(x) == PipeSystemEnum.Stål);

                    if (query.FirstOrDefault() != default)
                    {
                        Polyline parent = query.FirstOrDefault();
                        POIs.Add(new POI(parent, parent.GetClosestPointTo(pt, false).To2D(), EndType.StikAfgrening, PSM, DriGraph));
                    }

                    pt = pline.EndPoint;
                    if (query.FirstOrDefault() != default)
                    {
                        //This shouldn't happen now, because AssignPlinesAndBlocksToAlignments
                        //guarantees that the end point is never on a supply pipe
                        Polyline parent = query.FirstOrDefault();
                        POIs.Add(new POI(parent, parent.GetClosestPointTo(pt, false).To2D(), EndType.StikAfgrening, PSM, DriGraph));
                    }
                    #endregion

                    //Tilføj almindelige ender til POIs
                    POIs.Add(new POI(pline, pline.StartPoint.To2D(), EndType.StikStart, PSM, DriGraph));
                    POIs.Add(new POI(pline, pline.EndPoint.To2D(), EndType.StikEnd, PSM, DriGraph));
                    break;

                default:
                    throw new System.Exception("Supplied a new PipeSystemEnum! Add to code kthxbai.");
                }
                break;

            case BlockReference br:
                Transaction      tx  = br.Database.TransactionManager.TopTransaction;
                BlockTableRecord btr = br.BlockTableRecord.Go <BlockTableRecord>(tx);
                foreach (Oid oid in btr)
                {
                    if (!oid.IsDerivedFrom <BlockReference>())
                    {
                        continue;
                    }
                    BlockReference nestedBr = oid.Go <BlockReference>(tx);
                    if (!nestedBr.Name.Contains("MuffeIntern"))
                    {
                        continue;
                    }
                    Point3d wPt = nestedBr.Position;
                    wPt = wPt.TransformBy(br.BlockTransform);
                    EndType endType;
                    if (nestedBr.Name.Contains("BRANCH"))
                    {
                        endType = EndType.Branch;
                    }
                    else
                    {
                        endType = EndType.Main;
                        //Handle special case of AFGRSTUDS
                        //which does not coincide with an end on polyline
                        //but is situated somewhere along the polyline
                        if (br.RealName() == "AFGRSTUDS")
                        {
                            PropertySetManager psmPipeline =
                                new PropertySetManager(dB, PSetDefs.DefinedSets.DriPipelineData);
                            PSetDefs.DriPipelineData driPipelineData = new PSetDefs.DriPipelineData();

                            string branchAlName = psmPipeline.ReadPropertyString(br, driPipelineData.BranchesOffToAlignment);
                            if (branchAlName.IsNoE())
                            {
                                prdDbg(
                                    $"WARNING! Afgrstuds {br.Handle} has no BranchesOffToAlignment value.\n" +
                                    $"This happens if there are objects with no alignment assigned.\n" +
                                    $"To fix enter main alignment name in BranchesOffToAlignment field.");
                            }

                            var polylines = allPipes
                                            //.GetFjvPipes(tx, true)
                                            //.HashSetOfType<Polyline>(tx, true)
                                            .Where(x => psmPipeline.FilterPropetyString
                                                       (x, driPipelineData.BelongsToAlignment, branchAlName));
                            //.ToHashSet();

                            foreach (Polyline polyline in polylines)
                            {
                                Point3d nearest = polyline.GetClosestPointTo(wPt, false);
                                if (nearest.DistanceHorizontalTo(wPt) < 0.01)
                                {
                                    POIs.Add(new POI(polyline, nearest.To2D(), EndType.Branch, PSM, DriGraph));
                                    break;
                                }
                            }
                        }
                    }
                    POIs.Add(new POI(br, wPt.To2D(), endType, PSM, DriGraph));
                }
                break;

            default:
                throw new System.Exception("Wrong type of object supplied!");
            }
        }