private static void IncludeVolumesOnOFFLayersPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            NeighborhoodGraph instance = d as NeighborhoodGraph;

            if (instance == null)
            {
                return;
            }

            instance.ExtractVolumesToSort();
        }
        private static void VolumeManagerContentChangePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            NeighborhoodGraph instance = d as NeighborhoodGraph;

            if (instance == null)
            {
                return;
            }

            // exract volumes to sort
            instance.ExtractVolumesToSort();
        }
        private static void VolumeManagerPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            NeighborhoodGraph instance = d as NeighborhoodGraph;

            if (instance == null || instance.VolumeManager == null)
            {
                instance.volumes_tested = new Dictionary <ZonedVolume, bool>();
                return;
            }

            // exract volumes to sort
            instance.ExtractVolumesToSort();
        }
        private static void ClusterAccToAlignment(ref Dictionary <SurfaceBasicInfo, int> _processed, List <SurfaceBasicInfo> _surfaces)
        {
            if (_surfaces == null || _surfaces.Count == 0)
            {
                return;
            }
            if (_processed == null || _processed.Count == 0)
            {
                _processed = NeighborhoodGraph.ClusterAccToAlignment(_surfaces);
                return;
            }

            // initiate
            int cluster_counter = _processed.Select(x => x.Value).Max() + 1;

            foreach (SurfaceBasicInfo s in _surfaces)
            {
                _processed.Add(s, -1);
            }

            NeighborhoodGraph.ClusterAccToAlignmentAlgorithm(ref _processed, ref cluster_counter);
        }
        private static Dictionary <SurfaceBasicInfo, int> ClusterAccToAlignment(List <SurfaceBasicInfo> _surfaces)
        {
            Dictionary <SurfaceBasicInfo, int> processed = new Dictionary <SurfaceBasicInfo, int>();

            if (_surfaces == null || _surfaces.Count == 0)
            {
                return(processed);
            }

            foreach (SurfaceBasicInfo s in _surfaces)
            {
                processed.Add(s, -1);
            }

            SurfaceBasicInfo s1 = processed.ElementAt(0).Key;

            processed[s1] = 0;
            int cluster_counter = 1;

            NeighborhoodGraph.ClusterAccToAlignmentAlgorithm(ref processed, ref cluster_counter);
            return(processed);
        }
        private static void ShowNeighborsPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            NeighborhoodGraph instance = d as NeighborhoodGraph;

            if (instance == null)
            {
                return;
            }

            if (instance.nodes_vis == null || instance.edge_vis == null)
            {
                return;
            }
            if (instance.ShowNeighbors)
            {
                instance.nodes_vis.Visibility = Visibility.Visible;
                instance.edge_vis.Visibility  = Visibility.Visible;
            }
            else
            {
                instance.nodes_vis.Visibility = Visibility.Collapsed;
                instance.edge_vis.Visibility  = Visibility.Collapsed;
            }
        }
        private void FindNeighbors()
        {
            if (this.volumes_tested.Count < 2)
            {
                return;
            }

            // ---------------------------------------- ALIGNMENT ----------------------------------------------

            // extract the surfaces of the 'first' volume and set them as cluster initiators
            ZonedVolume v1 = this.volumes_tested.ElementAt(0).Key;

            this.volumes_tested[v1] = true;

            List <SurfaceBasicInfo>            v1_surf       = v1.ExportBasicInfoForNeighborhoodTest();
            Dictionary <SurfaceBasicInfo, int> surf_clusters = NeighborhoodGraph.ClusterAccToAlignment(v1_surf);

            for (int i = 1; i < this.volumes_tested.Count; i++)
            {
                // get the next volume
                ZonedVolume v_next = this.volumes_tested.ElementAt(i).Key;
                this.volumes_tested[v_next] = true;

                // extract its enclosing surfaces
                List <SurfaceBasicInfo> v_next_surf = v_next.ExportBasicInfoForNeighborhoodTest();
                // try to place them in a cluster
                NeighborhoodGraph.ClusterAccToAlignment(ref surf_clusters, v_next_surf);
            }

            // assemble the clusters
            List <List <SurfaceBasicInfo> > clusters_alignment = NeighborhoodGraph.AssembleClusters(surf_clusters);

            // debug
            string debug = string.Empty;

            foreach (List <SurfaceBasicInfo> cluster in clusters_alignment)
            {
                if (cluster.Count < 2)
                {
                    continue;
                }
                foreach (SurfaceBasicInfo sbi in cluster)
                {
                    debug += sbi.ToString() + "\n";
                }
                debug += "\n";
            }
            string test = debug;

            // --------------------------------------- OVERLAPPING ---------------------------------------------

            // start overlap testing in each cluster
            this.ClearGraph();
            List <SurfaceMatch> overlaps_all = new List <SurfaceMatch>();

            foreach (List <SurfaceBasicInfo> cluster in clusters_alignment)
            {
                if (cluster.Count < 2)
                {
                    continue;
                }

                List <SurfaceMatch> overlaps = NeighborhoodGraph.FindOverlaps(cluster, this.MaxOverlapError);
                overlaps_all.AddRange(overlaps);
            }
            this.AddToGraph(overlaps_all);
        }