/// <summary>
        /// <para>Identification is specified unambiguously by volume id, label/level,</para>
        /// <para>index within the level / label and id of the lower defining polygon of a wall.</para>
        /// </summary>
        /// <param name="_volume_id"></param>
        /// <param name="_is_wall"></param>
        /// <param name="_level_or_label"></param>
        /// <param name="_label_for_openings"></param>
        /// <param name="_wall_lower_poly"></param>
        /// <returns></returns>
        public ZonedVolume GetOtherSideOf(long _volume_id, bool _is_wall, int _level_or_label, int _label_for_openings, long _wall_lower_poly)
        {
            // find the volume
            if (this.nodes == null)
            {
                return(null);
            }
            if (this.nodes.Count < 1)
            {
                return(null);
            }

            NeighbNode n = this.nodes.FirstOrDefault(x => x.IsValid && x.Volume.ID == _volume_id);

            if (n == null)
            {
                return(null);
            }
            if (n.Edges.Count == 0)
            {
                return(null);
            }

            foreach (NeighbEdge e in n.Edges)
            {
                if (!e.IsValid)
                {
                    continue;
                }

                if ((e.Match.Match01.VolumeID == _volume_id &&
                     e.Match.Match01.IsWall == _is_wall &&
                     e.Match.Match01.LevelOrLabel == _level_or_label &&
                     e.Match.Match01.LabelForOpenings == _label_for_openings &&
                     e.Match.Match01.Wall_LowerPoly == _wall_lower_poly) ||
                    (e.Match.Match02.VolumeID == _volume_id &&
                     e.Match.Match02.IsWall == _is_wall &&
                     e.Match.Match02.LevelOrLabel == _level_or_label &&
                     e.Match.Match02.LabelForOpenings == _label_for_openings &&
                     e.Match.Match02.Wall_LowerPoly == _wall_lower_poly))
                {
                    if (e.Node1.Volume.ID == _volume_id)
                    {
                        return(e.Node2.Volume);
                    }
                    else if (e.Node2.Volume.ID == _volume_id)
                    {
                        return(e.Node1.Volume);
                    }
                }
            }
            return(null);
        }
        private void AddToGraph(List <SurfaceMatch> _matches)
        {
            if (_matches == null || _matches.Count == 0)
            {
                return;
            }

            if (this.nodes == null)
            {
                this.nodes = new List <NeighbNode>();
            }
            if (this.edges == null)
            {
                this.edges = new List <NeighbEdge>();
            }

            foreach (SurfaceMatch match in _matches)
            {
                if (!match.IsContainment)
                {
                    continue;
                }

                // look for the nodes
                NeighbNode n1 = this.nodes.FirstOrDefault(x => x.IsValid && x.Volume.ID == match.Match01.VolumeID);
                if (n1 == null)
                {
                    ZonedVolume v1 = this.volumes_tested.Where(x => x.Key.ID == match.Match01.VolumeID).Select(x => x.Key).FirstOrDefault();
                    if (v1 != null)
                    {
                        n1 = new NeighbNode(v1);
                        this.nodes.Add(n1);
                    }
                }

                NeighbNode n2 = this.nodes.FirstOrDefault(x => x.IsValid && x.Volume.ID == match.Match02.VolumeID);
                if (n2 == null)
                {
                    ZonedVolume v2 = this.volumes_tested.Where(x => x.Key.ID == match.Match02.VolumeID).Select(x => x.Key).FirstOrDefault();
                    if (v2 != null)
                    {
                        n2 = new NeighbNode(v2);
                        this.nodes.Add(n2);
                    }
                }

                // create the edge
                if (n1 != null && n2 != null)
                {
                    this.edges.Add(new NeighbEdge(n1, n2, match));
                }
            }
        }
 public NeighbEdge(NeighbNode _n1, NeighbNode _n2, SurfaceMatch _match)
 {
     this.Node1 = _n1;
     this.Node2 = _n2;
     this.Match = _match;
     this.SetValidity();
     // set navigation
     if (this.IsValid)
     {
         _n1.AddEdge(this);
         _n2.AddEdge(this);
     }
 }
        public List <ZonedVolume> GetNeighborsOf(ZonedVolume _zv)
        {
            List <ZonedVolume> neighbors = new List <ZonedVolume>();

            if (this.nodes == null)
            {
                return(neighbors);
            }
            if (this.nodes.Count < 1)
            {
                return(neighbors);
            }
            if (_zv == null)
            {
                return(neighbors);
            }

            NeighbNode n = this.nodes.FirstOrDefault(x => x.IsValid && x.Volume.ID == _zv.ID);

            if (n == null)
            {
                return(neighbors);
            }
            if (n.Edges.Count == 0)
            {
                return(neighbors);
            }

            foreach (NeighbEdge e in n.Edges)
            {
                if (!e.IsValid)
                {
                    continue;
                }

                if (e.Node1.Volume.ID == _zv.ID)
                {
                    neighbors.Add(e.Node2.Volume);
                }
                else if (e.Node2.Volume.ID == _zv.ID)
                {
                    neighbors.Add(e.Node1.Volume);
                }
            }

            return(neighbors);
        }