public void DrawNetwork(Objects.Network nw)
        {
            Transaction t = null;

            if (_uiDoc.Document.IsModifiable == false)
            {
                t = new Transaction(_uiDoc.Document, "DrawNetwork");
                t.Start();
            }

            // draw all nodes and edges.

            foreach (var node in nw.Nodes)
            {
                // draw a circle...
                // Utilities.GeometryCreationUtils.DrawCircle(_uiDoc.Document, Plane.CreateByNormalAndOrigin( XYZ.BasisZ, node.Location), _uiDoc.ActiveGraphicalView.SketchPlane, 1.0);
            }

            List <Line> lines = new List <Line>();

            foreach (var edge in nw.Edges)
            {
                Objects.Node n1 = nw.Nodes.Single(n => n.Id == edge.Node1);
                Objects.Node n2 = nw.Nodes.Single(n => n.Id == edge.Node2);


                double dist = n1.Location.DistanceTo(n2.Location);
                if (dist < _uiDoc.Application.Application.ShortCurveTolerance)
                {
                    string stop = "";
                }
                else
                {
                    Line line = Line.CreateBound(n1.Location, n2.Location);
                    lines.Add(line);
                }
            }
            Utilities.GeometryCreationUtils.DrawLines(_uiDoc.Document, lines);

            if (t != null)
            {
                t.Commit();
            }
        }
        public Objects.Network BuildNetwork(IList <Objects.Space> spaces, IList <FamilyInstance> VAVs, IList <FamilyInstance> shafts, IList <Line> corridorLines, bool biDirectional = false)
        {
            // here we want to start with a node for every VAV, linked to the appropriate space.
            // then project the VAV onto the corridor lines.
            // then build the edges...

            Objects.Network     network = new Objects.Network();
            List <Objects.Node> nodes   = new List <Objects.Node>();
            List <Objects.Edge> edges   = new List <Objects.Edge>();

            network.Edges  = edges;
            network.Nodes  = nodes;
            network.Spaces = spaces.ToList();



            _ductWorkElevation = (VAVs.First().Location as LocationPoint).Point.Z;
            corridorLines      = resetLines(corridorLines);


            // figure out the current phase.
            Phase phase = _uiDoc.Document.GetElement(_uiDoc.ActiveGraphicalView.get_Parameter(BuiltInParameter.VIEW_PHASE).AsElementId()) as Phase;

            foreach (var vav in VAVs)
            {
                XYZ       location = (vav.Location as LocationPoint).Point;
                Connector c        = MEPController.GetProperConnector(vav, FlowDirectionType.In, DuctSystemType.SupplyAir);
                if (c != null)
                {
                    location = c.Origin;
                }
                location = normalizeZ(location);

                Objects.Node n = new Objects.Node()
                {
                    Location = location, Name = "VAV-" + vav.Id.IntegerValue, NodeType = Objects.Node.NodeTypeEnum.Vav
                };


                // determine the related space.
                var relatedSpace = vav.get_Space(phase);
                if (relatedSpace != null)
                {
                    n.SpaceId = relatedSpace.UniqueId;
                }

                // while we are at it, get the connection point to the corridor
                XYZ connection = getClosest(location, corridorLines, true);

                // does this node already exist?
                Objects.Node connNode = lookupExisting(location, nodes);

                if (connNode == null)
                {
                    // make a new one.
                    connNode = new Objects.Node()
                    {
                        NodeType = Objects.Node.NodeTypeEnum.Other, Name = "Corridor", Location = connection
                    };
                    nodes.Add(connNode);
                }

                // adding this later.
                nodes.Add(n);

                // make an edge from VAV to corridor.
                Objects.Edge edge = new Objects.Edge()
                {
                    Node1 = n.Id, Node2 = connNode.Id, Distance = n.Location.DistanceTo(connNode.Location)
                };
                log("Made edge from " + n.Name + " to " + connNode.Name);
                edges.Add(edge);
            }

            // now let's do the same thing with the shaft.
            foreach (var shaft in shafts)
            {
                XYZ location = (shaft.Location as LocationPoint).Point;
                location = normalizeZ(location);

                // shaft name is based on the mark
                Parameter    mark = shaft.get_Parameter(BuiltInParameter.ALL_MODEL_MARK);
                string       name = (String.IsNullOrEmpty(mark.AsString()) ? shaft.Id.IntegerValue.ToString() : mark.AsString());
                Objects.Node n    = new Objects.Node()
                {
                    Location = location, Name = "Shaft-" + name, NodeType = Objects.Node.NodeTypeEnum.Shaft
                };


                // now we need to find where this connects to the

                //CURRENT SIMPLIFICATION: NO SHAFT WILL BE ON TOP OF A CENTERLINE.
                // COME BACK AND FIX THIS  LATER!

                XYZ connection = getClosest(location, corridorLines, true);

                Objects.Node connNode = lookupExisting(connection, nodes);
                if (connNode == null)
                {
                    // make a new node
                    connNode = new Objects.Node()
                    {
                        NodeType = Objects.Node.NodeTypeEnum.Other, Name = "Corridor-To-Shaft", Location = connection
                    };
                    nodes.Add(connNode);
                }
                // add this later.
                nodes.Add(n);

                // make an edge that connects
                Objects.Edge edge = new Objects.Edge()
                {
                    Node1 = connNode.Id, Node2 = n.Id, Distance = (connNode.Location.DistanceTo(n.Location))
                };
                log("Made edge from " + connNode.Name + " to " + n.Name);
                edges.Add(edge);
            }

            // see if we have any corridor line intersects/overlaps
            for (int i = 0; i < corridorLines.Count; i++)
            {
                for (int j = i + 1; j < corridorLines.Count; j++)
                {
                    log("Checking Corrdor Lines " + i + " vs. " + j);

                    IntersectionResultArray outInts = null;
                    var result = corridorLines[i].Intersect(corridorLines[j], out outInts);
                    log("  => result: " + result);
                    switch (result)
                    {
                    case SetComparisonResult.Overlap:
                        foreach (IntersectionResult res in outInts)
                        {
                            XYZ tmp = normalizeZ(res.XYZPoint);

                            Objects.Node n1 = lookupExisting(tmp, nodes);
                            if (n1 == null)
                            {
                                n1 = new Objects.Node()
                                {
                                    Location = res.XYZPoint, NodeType = Objects.Node.NodeTypeEnum.Other, Name = "CorridorOverlap"
                                };
                                nodes.Add(n1);
                            }
                        }
                        break;
                    }
                }
            }

            // then we need to connect the corridor nodes
            foreach (var cl in corridorLines)
            {
                // for each centerline, we want the endpoints of the centerline, and an ordered list of edges that cover it (including all of the midpoints from nodes).

                IList <Objects.Node> onLine = getNodesOnLine(cl, nodes);

                // see if we have to add the endpoints, or if they're already there.
                Objects.Node n1 = lookupExisting(cl.GetEndPoint(0), nodes);
                Objects.Node n2 = lookupExisting(cl.GetEndPoint(1), nodes);
                if (n1 == null)
                {
                    n1 = new Objects.Node()
                    {
                        Location = cl.GetEndPoint(0), NodeType = Objects.Node.NodeTypeEnum.Other, Name = "CorridorEnd"
                    };
                    onLine.Add(n1);
                    nodes.Add(n1);
                }
                if (n2 == null)
                {
                    n2 = new Objects.Node()
                    {
                        Location = cl.GetEndPoint(1), NodeType = Objects.Node.NodeTypeEnum.Other, Name = "CorridorEnd"
                    };
                    onLine.Add(n2);
                    nodes.Add(n2);
                }

                // now we want to sort these things based on the distance from n1.
                onLine = onLine.OrderBy(n => n.Location.DistanceTo(n1.Location)).ToList();

                // make edges between each thing.
                for (int i = 1; i < onLine.Count; i++)
                {
                    Objects.Edge corrEdge = new Objects.Edge()
                    {
                        Node1 = onLine[i - 1].Id, Node2 = onLine[i].Id, Distance = onLine[i - 1].Location.DistanceTo(onLine[i].Location)
                    };
                    log("Made corridor edge from " + onLine[i - 1].Name + " to " + onLine[i].Name);
                    edges.Add(corrEdge);

                    if (biDirectional)
                    {
                        Objects.Edge c2 = new Objects.Edge()
                        {
                            Node2 = onLine[i - 1].Id, Node1 = onLine[i].Id, Distance = onLine[i - 1].Location.DistanceTo(onLine[i].Location)
                        };
                        log("Made corridor edge from " + onLine[i].Name + " to " + onLine[i - 1].Name);
                        edges.Add(c2);
                    }
                }
            }



            return(network);
        }
        public void Serialize(Objects.Network nw, string filename)
        {
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(nw);

            System.IO.File.WriteAllText(filename, json);
        }