protected override void Algorithm(ref Cl3DModel p_Model)
        {
            Cl3DModel.Cl3DModelPointIterator NoseTip = null;

            if (!p_Model.GetSpecificPoint(Cl3DModel.eSpecificPoints.NoseTip, ref NoseTip))
            {
                throw new Exception("Cannot find specific point NoseTip");
            }

            Cl3DModel.Cl3DModelPointIterator iter = p_Model.GetIterator();
            float MaxZ = float.MinValue;
            float MinZ = float.MaxValue;

            do
            {
                if (MaxZ < iter.Z)
                {
                    MaxZ = iter.Z;
                }
                if (MinZ > iter.Z)
                {
                    MinZ = iter.Z;
                }
            }while(iter.MoveToNext());

            float step = 1f;
            int   name = (int)step;
            List <Cl3DModel.Cl3DModelPointIterator> PointsToRemove = new List <Cl3DModel.Cl3DModelPointIterator>();

            for (float Threshold = NoseTip.Z - step; Threshold > MinZ; Threshold -= step)
            {
                List <Cl3DModel.Cl3DModelPointIterator> PointsToCheck   = new List <Cl3DModel.Cl3DModelPointIterator>();
                List <Cl3DModel.Cl3DModelPointIterator> NewPoinsToCheck = new List <Cl3DModel.Cl3DModelPointIterator>();
                List <Cl3DModel.Cl3DModelPointIterator> VisitedPoints   = new List <Cl3DModel.Cl3DModelPointIterator>();
                PointsToCheck.Add(NoseTip.CopyIterator());
                while (PointsToCheck.Count != 0)
                {
                    foreach (Cl3DModel.Cl3DModelPointIterator point in PointsToCheck)
                    {
                        if (point.IsSpecificValueCalculated("ToRemove"))
                        {
                            continue;
                        }

                        point.AlreadyVisited = true;
                        VisitedPoints.Add(point.CopyIterator());

                        List <Cl3DModel.Cl3DModelPointIterator> Neighbors = point.GetListOfNeighbors();
                        foreach (Cl3DModel.Cl3DModelPointIterator Neighb in Neighbors)
                        {
                            if (Neighb.IsSpecificValueCalculated("ToRemove"))
                            {
                                continue;
                            }
                            if (Neighb.Z > Threshold && !Neighb.AlreadyVisited)
                            {
                                Neighb.AlreadyVisited = true;
                                NewPoinsToCheck.Add(Neighb.CopyIterator());
                            }
                        }
                    }
                    PointsToCheck   = NewPoinsToCheck;
                    NewPoinsToCheck = new List <Cl3DModel.Cl3DModelPointIterator>();
                }
                Cl3DModel.Cl3DModelPointIterator unconnected = p_Model.GetIterator();
                do
                {
                    if (!unconnected.AlreadyVisited && unconnected.Z > Threshold && !unconnected.IsSpecificValueCalculated("ToRemove"))
                    {
                        if (m_SaveScreenShots)
                        {
                            unconnected.Color = Color.Red;
                        }
                        unconnected.AddSpecificValue("ToRemove", 1.0f);
                        PointsToRemove.Add(unconnected.CopyIterator());
                    }
                } while (unconnected.MoveToNext());

                foreach (Cl3DModel.Cl3DModelPointIterator pts in VisitedPoints)
                {
                    if (m_SaveScreenShots)
                    {
                        pts.Color = Color.Green;
                    }
                    pts.AlreadyVisited = false;
                }
                if (m_SaveScreenShots)
                {
                    Bitmap mapa;
                    p_Model.GetBMPImage(out mapa, 1.0f);
                    mapa.Save(p_Model.ModelFilePath + name.ToString() + ".bmp");
                    name += (int)step;
                }
            }
            List <Cl3DModel.Cl3DModelPointIterator> RemPointsVisited = new List <Cl3DModel.Cl3DModelPointIterator>();

            foreach (Cl3DModel.Cl3DModelPointIterator RemPoint in PointsToRemove)
            {
                if (!RemPoint.IsValid() || RemPoint.AlreadyVisited)
                {
                    continue;
                }

                List <Cl3DModel.Cl3DModelPointIterator> PointsToCheck = new List <Cl3DModel.Cl3DModelPointIterator>();

                PointsToCheck.Add(RemPoint);
                bool remove = false;
                while (PointsToCheck.Count != 0)
                {
                    List <Cl3DModel.Cl3DModelPointIterator> NewPtsToCheck = new List <Cl3DModel.Cl3DModelPointIterator>();
                    foreach (Cl3DModel.Cl3DModelPointIterator pt in PointsToCheck)
                    {
                        if (!pt.IsValid() || pt.AlreadyVisited)
                        {
                            continue;
                        }
                        pt.AlreadyVisited = true;

                        RemPointsVisited.Add(pt);

                        List <Cl3DModel.Cl3DModelPointIterator> Neighbors = pt.GetListOfNeighbors();
                        if (Neighbors.Count != 8)
                        {
                            remove = true;
                        }
                        else
                        {
                            foreach (Cl3DModel.Cl3DModelPointIterator ne in Neighbors)
                            {
                                if (ne.IsSpecificValueCalculated("ToRemove") && !ne.AlreadyVisited)
                                {
                                    NewPtsToCheck.Add(ne);
                                }
                            }
                        }
                    }
                    PointsToCheck = NewPtsToCheck;
                }
                if (remove)
                {
                    foreach (Cl3DModel.Cl3DModelPointIterator ppt in RemPointsVisited)
                    {
                        p_Model.RemovePointFromModel(ppt);
                    }
                }
                RemPointsVisited = new List <Cl3DModel.Cl3DModelPointIterator>();
            }
        }
        protected override void Algorithm(ref Cl3DModel p_Model)
        {
            MarkHighCurvEdges(ref p_Model);

            p_Model.ResetVisitedPoints();
            //-------------------------------- Cropping
            Cl3DModel.Cl3DModelPointIterator NoseTip  = p_Model.GetSpecificPoint(Cl3DModel.eSpecificPoints.NoseTip);
            Cl3DModel.Cl3DModelPointIterator LeftEye  = p_Model.GetSpecificPoint(Cl3DModel.eSpecificPoints.LeftEyeRightCorner);
            Cl3DModel.Cl3DModelPointIterator RightEye = p_Model.GetSpecificPoint(Cl3DModel.eSpecificPoints.RightEyeLeftCorner);

            float distanceBetweenEyes = LeftEye - RightEye;
            float ossfest             = distanceBetweenEyes * 0.4f; //20% of distance between eyes will be taken as a stripe down to search for the mouth hole

            Cl3DModel.Cl3DModelPointIterator iter = p_Model.GetIterator();
            Dictionary <uint, Cl3DModel.Cl3DModelPointIterator> pointsToRemove = new Dictionary <uint, Cl3DModel.Cl3DModelPointIterator>();

            do
            {
                if (iter.X > LeftEye.X + ossfest && iter.X < RightEye.X - ossfest && iter.Y < NoseTip.Y - 20 && iter.Y > NoseTip.Y - 43)
                {
                    // iter.Color = Color.LightBlue;
                    if (iter.IsSpecificValueCalculated("ToRemove_HighCurvature"))
                    {
                        pointsToRemove.Add(iter.PointID, iter.CopyIterator());
                    }
                }
            } while (iter.MoveToNext());

            List <List <Cl3DModel.Cl3DModelPointIterator> > ListOfRegions = new List <List <Cl3DModel.Cl3DModelPointIterator> >();

            while (pointsToRemove.Count != 0)
            {
                Cl3DModel.Cl3DModelPointIterator test = new List <Cl3DModel.Cl3DModelPointIterator>(pointsToRemove.Values)[0];
                pointsToRemove.Remove(test.PointID);

                bool toRemove = false;
                List <Cl3DModel.Cl3DModelPointIterator> CurrentList = new List <Cl3DModel.Cl3DModelPointIterator>();
                ListOfRegions.Add(CurrentList);

                List <Cl3DModel.Cl3DModelPointIterator> ToCheck = new List <Cl3DModel.Cl3DModelPointIterator>();
                ToCheck.Add(test);
                test.AlreadyVisited = true;
                do
                {
                    List <Cl3DModel.Cl3DModelPointIterator> NewToCheck = new List <Cl3DModel.Cl3DModelPointIterator>();
                    foreach (Cl3DModel.Cl3DModelPointIterator pt in ToCheck)
                    {
                        CurrentList.Add(pt.CopyIterator());

                        foreach (Cl3DModel.Cl3DModelPointIterator ptNb in pt.GetListOfNeighbors())
                        {
                            if (ptNb.IsSpecificValueCalculated("ToRemove_HighCurvature") && ptNb.AlreadyVisited == false)
                            {
                                ptNb.AlreadyVisited = true;
                                NewToCheck.Add(ptNb.CopyIterator());
                                pointsToRemove.Remove(ptNb.PointID);
                                List <Cl3DModel.Cl3DModelPointIterator> Neighbors = ptNb.GetListOfNeighbors();

                                //   if (Neighbors.Count < 8) // that means the points from marked region went to the end of the model very rare happens that the open mouth region is the externatl region
                                //       toRemove = true;
                            }
                        }
                    }
                    ToCheck    = NewToCheck;
                    NewToCheck = new List <Cl3DModel.Cl3DModelPointIterator>();
                } while (ToCheck.Count != 0);
                if (toRemove)
                {
                    ListOfRegions.Remove(CurrentList);
                }
            }

            List <Cl3DModel.Cl3DModelPointIterator> BiggestRegion = null;
            int SizeOfTheBiggest = int.MinValue;

            for (int i = 0; i < ListOfRegions.Count; i++)
            {
                if (ListOfRegions[i].Count > SizeOfTheBiggest)
                {
                    SizeOfTheBiggest = ListOfRegions[i].Count;
                    BiggestRegion    = ListOfRegions[i];
                }
            }

            //------------------- Creating image of localized mouth part

            /*   int NoseX = NoseTip.RangeImageX;
             * int NoseY = NoseTip.RangeImageY;
             * //BiggestRegion
             * int[,] FMap = null;
             * if (!FaceMaps.TryGetValue(p_Model.m_sExpression, out FMap))
             * {
             *     FMap = new int[200, 200];
             *     FaceMaps.Add(p_Model.m_sExpression, FMap);
             * }
             * Cl3DModel.Cl3DModelPointIterator its = p_Model.GetIterator();
             * do
             * {
             *     int currX = its.RangeImageX;
             *     int currY = its.RangeImageY;
             *
             *
             *     int x = currX - NoseX + 100;
             *     int y = currY - NoseY + 100;
             *
             *     FMap[x, y]++;
             * } while (its.MoveToNext());
             *
             * int MaxF = int.MinValue;
             * for (int i = 0; i < 200; i++)
             *     for(int j=0; j< 200; j++)
             *         if (FMap[i, j] > MaxF)
             *             MaxF = FMap[i, j];
             *
             *
             * //-
             * int[,] FRem = null;
             * if (!RemovedMaps.TryGetValue(p_Model.m_sExpression, out FRem))
             * {
             *     FRem = new int[200, 200];
             *     RemovedMaps.Add(p_Model.m_sExpression, FRem);
             * }
             *
             * if (BiggestRegion != null)
             * {
             *     foreach (Cl3DModel.Cl3DModelPointIterator pp in BiggestRegion)
             *     {
             *         int currX = pp.RangeImageX;
             *         int currY = pp.RangeImageY;
             *
             *
             *         int x = currX - NoseX + 100;
             *         int y = currY - NoseY + 100;
             *
             *         FRem[x, y]++;
             *     }
             * }
             *
             * FRem[NoseTip.RangeImageX - NoseX + 100, NoseTip.RangeImageY - NoseY + 100]++;
             * //  FRem[LeftEye.RangeImageX - NoseX + 100, LeftEye.RangeImageY - NoseY + 100]++;
             * //  FRem[RightEye.RangeImageX - NoseX + 100, RightEye.RangeImageY - NoseY + 100]++;
             *
             *
             * int MaxR = int.MinValue;
             * for (int i = 0; i < 200; i++)
             *     for (int j = 0; j < 200; j++)
             *         if (FRem[i, j] > MaxR)
             *             MaxR = FRem[i, j];
             *
             *
             *
             *
             *
             *
             *
             *
             *
             * Bitmap map = new Bitmap(200, 200);
             * for (int i = 0; i < 200; i++)
             * {
             *     for (int j = 0; j < 200; j++)
             *     {
             *         map.SetPixel(i, j, ClTools.GetColorGray(((float)FMap[i, j]) / MaxF, 1.0f));
             *         if(FRem[i, j] != 0)
             *             map.SetPixel(i, j, ClTools.GetColorGray( 1 - ((float)FRem[i, j]) / MaxR, 1.0f));
             *     }
             * }
             * map.Save("d:\\" + p_Model.m_sExpression + ".bmp");
             * return;
             */
            //------------------------------------------------------------

            /*  TextWriter tw = new StreamWriter("d:\\MouthSizeBosphorus2.txt", false);
             *
             *
             * int ssize = 0;
             * if (BiggestRegion != null)
             *    ssize = BiggestRegion.Count;
             *
             * int[] OldSize;
             * if(!mouthSize.TryGetValue(p_Model.m_sExpression, out OldSize))
             * {
             *    OldSize = new int[2];
             *    mouthSize.Add(p_Model.m_sExpression, OldSize);
             * }
             * OldSize[0] += ssize;
             * OldSize[1]++;
             *
             * foreach(KeyValuePair<string, int[]> val in mouthSize)
             *    tw.WriteLine(val.Key+" "+ val.Value[0].ToString()+ " " + val.Value[1].ToString());
             *
             * tw.Close();
             *
             * return;
             */
            //----------------------------------------------------------------

            //---------------------- NO mouth REGION LOCALIZED
            if (BiggestRegion == null)
            {
                ClInformationSender.SendInformation("No mouth localized, normal Geodesic distance calculation", ClInformationSender.eInformationType.eDebugText);
                if (m_bRemoveRegions) // still there can be vertexes with high curvature (edges between hair and the face)
                {
                    Cl3DModel.Cl3DModelPointIterator remover = p_Model.GetIterator();
                    while (remover.IsValid())
                    {
                        if (remover.IsSpecificValueCalculated("ToRemove_HighCurvature"))
                        {
                            remover = p_Model.RemovePointFromModel(remover);
                        }
                        else
                        {
                            remover.MoveToNext();
                        }
                    }
                }

                ClTools.CalculateGeodesicDistanceFromSourcePointToAllPoints(NoseTip, Cl3DModel.Cl3DModelPointIterator.eSpecificValues.GeodesicDistanceToNoseTip.ToString());

                if (!m_bCrop)
                {
                    return;
                }

                iter = p_Model.GetIterator();
                while (iter.IsValid())
                {
                    if (!iter.IsSpecificValueCalculated(Cl3DModel.Cl3DModelPointIterator.eSpecificValues.GeodesicDistanceToNoseTip))
                    {
                        iter = p_Model.RemovePointFromModel(iter);
                    }
                    else
                    {
                        double distance = iter.GetSpecificValue(Cl3DModel.Cl3DModelPointIterator.eSpecificValues.GeodesicDistanceToNoseTip);
                        if (distance > m_fDistence)
                        {
                            iter = p_Model.RemovePointFromModel(iter);
                        }
                        else
                        {
                            iter.MoveToNext();
                        }
                    }
                }
                return;
            }

            //------------------------- Mouth REGION LOCALiZED
            p_Model.ResetVisitedPoints();
            List <Cl3DModel.Cl3DModelPointIterator> BorderOfTheBigestRegion = new List <Cl3DModel.Cl3DModelPointIterator>();

            foreach (Cl3DModel.Cl3DModelPointIterator pts in BiggestRegion)
            {
                if (m_bMarkRegion)
                {
                    pts.Color = Color.Red;
                }

                List <Cl3DModel.Cl3DModelPointIterator> neighb = pts.GetListOfNeighbors();
                foreach (Cl3DModel.Cl3DModelPointIterator ppt in neighb)
                {
                    if (!ppt.AlreadyVisited && !ppt.IsSpecificValueCalculated("ToRemove_HighCurvature"))
                    {
                        BorderOfTheBigestRegion.Add(ppt);
                        ppt.AlreadyVisited = true;
                    }
                }
            }

            if (m_bRemoveRegions) // After we have border of the mouth region we can remove them
            {
                Cl3DModel.Cl3DModelPointIterator remover = p_Model.GetIterator();
                while (remover.IsValid())
                {
                    if (remover.IsSpecificValueCalculated("ToRemove_HighCurvature"))
                    {
                        remover = p_Model.RemovePointFromModel(remover);
                    }
                    else
                    {
                        remover.MoveToNext();
                    }
                }
            }

            Cl3DModel.Cl3DModelPointIterator MaxLeft  = BorderOfTheBigestRegion[0];
            Cl3DModel.Cl3DModelPointIterator MaxRight = BorderOfTheBigestRegion[0];
            foreach (Cl3DModel.Cl3DModelPointIterator pt in BorderOfTheBigestRegion)
            {
                if (pt.X < MaxLeft.X)
                {
                    MaxLeft = pt;
                }
                if (pt.X > MaxRight.X)
                {
                    MaxRight = pt;
                }
            }

            int size = (int)Math.Abs(MaxLeft.X - MaxRight.X) + 1;

            List <Cl3DModel.Cl3DModelPointIterator>[] histogram = new List <Cl3DModel.Cl3DModelPointIterator> [size];

            foreach (Cl3DModel.Cl3DModelPointIterator pt in BorderOfTheBigestRegion)
            {
                int pos = (int)(pt.X - MaxLeft.X);
                if (histogram[pos] == null)
                {
                    histogram[pos] = new List <Cl3DModel.Cl3DModelPointIterator>();
                }

                histogram[pos].Add(pt);
            }

            Dictionary <uint, uint> movingPoints = new Dictionary <uint, uint>();

            for (int i = 0; i < size; i++)
            {
                if (histogram[i] != null && histogram[i].Count != 0)
                {
                    //Color cl = ClTools.GetColorRGB(((float)i) / size, 1.0f);
                    Cl3DModel.Cl3DModelPointIterator UpperPoint = histogram[i][0];
                    Cl3DModel.Cl3DModelPointIterator LowerPoint = histogram[i][0];
                    foreach (Cl3DModel.Cl3DModelPointIterator pts in histogram[i])
                    {
                        //  pts.Color = cl;
                        if (UpperPoint.Y < pts.Y)
                        {
                            UpperPoint = pts;
                        }
                        if (LowerPoint.Y > pts.Y)
                        {
                            LowerPoint = pts;
                        }
                    }
                    //UpperPoint from this one
                    if (UpperPoint.PointID != LowerPoint.PointID)
                    {
                        float distance = Math.Min(LowerPoint - MaxLeft, LowerPoint - MaxRight);
                        List <Cl3DModel.Cl3DModelPointIterator> neighborhood = null;
                        ClTools.GetNeighborhoodWithGeodesicDistance(out neighborhood, LowerPoint, distance);
                        Cl3DModel.Cl3DModelPointIterator ClosestPoint = LowerPoint;
                        float MinDistance = LowerPoint - UpperPoint;
                        foreach (Cl3DModel.Cl3DModelPointIterator ptNeighb in neighborhood)
                        {
                            // ptNeighb.Color = Color.Pink;
                            float newDistance = ptNeighb - UpperPoint;
                            if (newDistance < MinDistance)
                            {
                                MinDistance  = newDistance;
                                ClosestPoint = ptNeighb;
                            }
                        }
                        Color cl = ClTools.GetColorRGB(((float)i) / size, 1.0f);
                        //    ClosestPoint.Color = cl;
                        //    UpperPoint.Color = cl;
                        movingPoints.Add(UpperPoint.PointID, ClosestPoint.PointID);
                    }
                }
            }

            //-------------------------------- Calculation of the geodesic using movement points
            p_Model.ResetVisitedPoints();
            ClTools.CalculateGeodesicDistanceFromSourcePointToAllPointsWithMovement(NoseTip, Cl3DModel.Cl3DModelPointIterator.eSpecificValues.GeodesicDistanceToNoseTip.ToString(), movingPoints);

            if (!m_bCrop)
            {
                return;
            }

            iter = p_Model.GetIterator();
            while (iter.IsValid())
            {
                if (!iter.IsSpecificValueCalculated(Cl3DModel.Cl3DModelPointIterator.eSpecificValues.GeodesicDistanceToNoseTip))
                {
                    iter = p_Model.RemovePointFromModel(iter);
                }
                else
                {
                    double distance = iter.GetSpecificValue(Cl3DModel.Cl3DModelPointIterator.eSpecificValues.GeodesicDistanceToNoseTip);
                    if (distance > m_fDistence)
                    {
                        iter = p_Model.RemovePointFromModel(iter);
                    }
                    else
                    {
                        iter.MoveToNext();
                    }
                }
            }
        }
        protected override void Algorithm(ref Cl3DModel p_Model)
        {
            Cl3DModel.Cl3DModelPointIterator iter = p_Model.GetIterator();

            uint   current          = 0;
            string NeighborhoodSize = m_fNeighborhoodSize.ToString();

            if (m_bFirstNeighbor)
            {
                NeighborhoodSize = "1Neighb";
            }
            string ShapeIndexString = "ShapeIndex_" + NeighborhoodSize;

            if (iter.IsValid())
            {
                do
                {
                    double A = 0;
                    double B = 0;
                    double C = 0;
                    double D = 0;
                    double E = 0;
                    double F = 0;

                    double H               = 0;
                    double K               = 0;
                    double k1              = 0;
                    double k2              = 0;
                    double ShapeIndex      = 0;
                    double CurvednessIndex = 0;
                    List <Cl3DModel.Cl3DModelPointIterator> ListOfneighborhood;
                    double dx;
                    double dy;
                    double dxy;
                    double dxx;
                    double dyy;

                    //------------------------- Neighborhood Custom --------------------------------------------------
                    if (!iter.IsSpecificValueCalculated(ShapeIndexString) || m_bRecalculateCurvature)
                    {
                        if (!m_bFirstNeighbor)
                        {
                            ClTools.GetNeighborhoodWithGeodesicDistance(out ListOfneighborhood, iter, m_fNeighborhoodSize);
                        }
                        else
                        {
                            ListOfneighborhood = iter.GetListOfNeighbors();
                        }

                        if (m_bNeighborhoodRotation)
                        {
                            Matrix Rotation = ClTools.CalculateRotationMatrix(iter.NormalVector, new Vector(new double[] { iter.NormalVector[0], iter.NormalVector[1], 1 }));
                            List <ClTools.MainPoint3D> Neighbors = new List <ClTools.MainPoint3D>();
                            foreach (Cl3DModel.Cl3DModelPointIterator Neighb in ListOfneighborhood)
                            {
                                Matrix after = Rotation * Neighb;
                                Neighbors.Add(new ClTools.MainPoint3D((float)after[0, 0], (float)after[1, 0], (float)after[2, 0], ""));
                            }

                            if (!ClTools.CountSurfaceCoefficients(Neighbors, ref A, ref B, ref C, ref D, ref E, ref F))
                            {
                                iter.RemoveSpecificValue("Gaussian_" + NeighborhoodSize);
                                iter.RemoveSpecificValue("Mean_" + NeighborhoodSize);
                                iter.RemoveSpecificValue("K1_" + NeighborhoodSize);
                                iter.RemoveSpecificValue("K2_" + NeighborhoodSize);
                                iter.RemoveSpecificValue("ShapeIndex_" + NeighborhoodSize);
                                iter.RemoveSpecificValue("CurvednessIndex_" + NeighborhoodSize);
                                continue;
                            }
                        }
                        else
                        {
                            if (!ClTools.CountSurfaceCoefficients(ListOfneighborhood, ref A, ref B, ref C, ref D, ref E, ref F))
                            {
                                iter.RemoveSpecificValue("Gaussian_" + NeighborhoodSize);
                                iter.RemoveSpecificValue("Mean_" + NeighborhoodSize);
                                iter.RemoveSpecificValue("K1_" + NeighborhoodSize);
                                iter.RemoveSpecificValue("K2_" + NeighborhoodSize);
                                iter.RemoveSpecificValue("ShapeIndex_" + NeighborhoodSize);
                                iter.RemoveSpecificValue("CurvednessIndex_" + NeighborhoodSize);
                                continue;
                            }
                        }


                        dx  = B + 2 * D * iter.X + E * iter.Y;
                        dy  = C + E * iter.X + 2 * F * iter.Y;
                        dxy = E;
                        dxx = 2 * D;
                        dyy = 2 * F;
                        //Mean
                        H = ((((1 + Math.Pow(dy, 2)) * dxx) - (2 * dx * dy * dxy) + ((1 + Math.Pow(dx, 2)) * dyy)) / (2 * Math.Pow((1 + Math.Pow(dx, 2) + Math.Pow(dy, 2)), 3.0d / 2.0d)));
                        //Gaussian
                        K               = (((dxx * dyy) - Math.Pow(dxy, 2)) / Math.Pow((1 + Math.Pow(dx, 2) + Math.Pow(dy, 2)), 2));
                        k1              = H + Math.Sqrt(Math.Pow(H, 2) - K);
                        k2              = H - Math.Sqrt(Math.Pow(H, 2) - K);
                        ShapeIndex      = 0.5d - (1 / Math.PI) * Math.Atan((k1 + k2) / (k1 - k2));
                        CurvednessIndex = Math.Sqrt(Math.Pow(k1, 2) + Math.Pow(k2, 2)) / 2;

                        iter.AddSpecificValue("Gaussian_" + NeighborhoodSize, K);
                        iter.AddSpecificValue("Mean_" + NeighborhoodSize, H);
                        iter.AddSpecificValue("K1_" + NeighborhoodSize, k1);
                        iter.AddSpecificValue("K2_" + NeighborhoodSize, k2);
                        iter.AddSpecificValue("ShapeIndex_" + NeighborhoodSize, ShapeIndex);
                        iter.AddSpecificValue("CurvednessIndex_" + NeighborhoodSize, CurvednessIndex);
                    }

                    ClInformationSender.SendInformation((current * 100 / p_Model.ModelPointsCount).ToString(System.Globalization.CultureInfo.InvariantCulture), ClInformationSender.eInformationType.eProgress);
                    current++;
                } while (iter.MoveToNext());
            }
        }
        protected override void Algorithm(ref Cl3DModel p_Model)
        {
            // Looking for a hole and connecting points ---- Later should be removed
            Cl3DModel.Cl3DModelPointIterator NoseTip  = p_Model.GetSpecificPoint(Cl3DModel.eSpecificPoints.NoseTip);
            Cl3DModel.Cl3DModelPointIterator LeftEye  = p_Model.GetSpecificPoint(Cl3DModel.eSpecificPoints.LeftEyeRightCorner);
            Cl3DModel.Cl3DModelPointIterator RightEye = p_Model.GetSpecificPoint(Cl3DModel.eSpecificPoints.RightEyeLeftCorner);

            float distanceBetweenEyes = LeftEye - RightEye;
            float ossfest             = distanceBetweenEyes * 0.4f; //20% of distance between eyes will be taken as a stripe down to search for the mouth hole

            Cl3DModel.Cl3DModelPointIterator iter = p_Model.GetIterator();
            Dictionary <uint, Cl3DModel.Cl3DModelPointIterator> pointsLowerBoundary = new Dictionary <uint, Cl3DModel.Cl3DModelPointIterator>();

            do
            {
                if (iter.X > LeftEye.X + ossfest && iter.X < RightEye.X - ossfest && iter.Y < NoseTip.Y - 20 && iter.Y > NoseTip.Y - 40)
                {
                    // iter.Color = Color.LightGreen;
                    if (iter.GetListOfNeighbors().Count != 8)
                    {
                        // iter.Color = Color.LightBlue;
                        pointsLowerBoundary.Add(iter.PointID, iter.CopyIterator());
                    }
                }
            } while (iter.MoveToNext());

            List <List <Cl3DModel.Cl3DModelPointIterator> > ListOfBoundarie = new List <List <Cl3DModel.Cl3DModelPointIterator> >();

            while (pointsLowerBoundary.Count != 0)
            {
                Cl3DModel.Cl3DModelPointIterator test = new List <Cl3DModel.Cl3DModelPointIterator>(pointsLowerBoundary.Values)[0];
                pointsLowerBoundary.Remove(test.PointID);

                bool toRemove = false;
                List <Cl3DModel.Cl3DModelPointIterator> CurrentList = new List <Cl3DModel.Cl3DModelPointIterator>();
                ListOfBoundarie.Add(CurrentList);

                List <Cl3DModel.Cl3DModelPointIterator> ToCheck = new List <Cl3DModel.Cl3DModelPointIterator>();
                ToCheck.Add(test);
                test.AlreadyVisited = true;
                do
                {
                    List <Cl3DModel.Cl3DModelPointIterator> NewToCheck = new List <Cl3DModel.Cl3DModelPointIterator>();
                    foreach (Cl3DModel.Cl3DModelPointIterator pt in ToCheck)
                    {
                        CurrentList.Add(pt.CopyIterator());
                        if (pt.Y > NoseTip.Y)
                        {
                            toRemove = true;
                        }

                        foreach (Cl3DModel.Cl3DModelPointIterator ptNb in pt.GetListOfNeighbors())
                        {
                            if (ptNb.GetListOfNeighbors().Count != 8 && ptNb.AlreadyVisited == false)
                            {
                                ptNb.AlreadyVisited = true;
                                NewToCheck.Add(ptNb.CopyIterator());
                                pointsLowerBoundary.Remove(ptNb.PointID);
                            }
                        }
                    }
                    ToCheck    = NewToCheck;
                    NewToCheck = new List <Cl3DModel.Cl3DModelPointIterator>();
                } while (ToCheck.Count != 0);
                if (toRemove)
                {
                    ListOfBoundarie.Remove(CurrentList);
                }
            }

            List <Cl3DModel.Cl3DModelPointIterator> BiggestBoundary = null;
            int SizeOfTheBiggest = int.MinValue;

            for (int i = 0; i < ListOfBoundarie.Count; i++)
            {
                if (ListOfBoundarie[i].Count > SizeOfTheBiggest)
                {
                    SizeOfTheBiggest = ListOfBoundarie[i].Count;
                    BiggestBoundary  = ListOfBoundarie[i];
                }
            }

            if (BiggestBoundary == null)
            {
                ClTools.CalculateGeodesicDistanceFromSourcePointToAllPoints(NoseTip, Cl3DModel.Cl3DModelPointIterator.eSpecificValues.GeodesicDistanceToNoseTip.ToString());
                iter = p_Model.GetIterator();
                while (iter.IsValid())
                {
                    if (!iter.IsSpecificValueCalculated(Cl3DModel.Cl3DModelPointIterator.eSpecificValues.GeodesicDistanceToNoseTip))
                    {
                        iter = p_Model.RemovePointFromModel(iter);
                    }
                    else
                    {
                        double distance = iter.GetSpecificValue(Cl3DModel.Cl3DModelPointIterator.eSpecificValues.GeodesicDistanceToNoseTip);
                        if (distance > m_fDistence)
                        {
                            iter = p_Model.RemovePointFromModel(iter);
                        }
                        else
                        {
                            iter.MoveToNext();
                        }
                    }
                }
                return;
            }

            Cl3DModel.Cl3DModelPointIterator MaxLeft  = BiggestBoundary[0];
            Cl3DModel.Cl3DModelPointIterator MaxRight = BiggestBoundary[0];
            foreach (Cl3DModel.Cl3DModelPointIterator pt in BiggestBoundary)
            {
                if (pt.X < MaxLeft.X)
                {
                    MaxLeft = pt;
                }
                if (pt.X > MaxRight.X)
                {
                    MaxRight = pt;
                }
            }

            int size = (int)Math.Abs(MaxLeft.X - MaxRight.X) + 1;

            List <Cl3DModel.Cl3DModelPointIterator>[] histogram = new List <Cl3DModel.Cl3DModelPointIterator> [size];

            foreach (Cl3DModel.Cl3DModelPointIterator pt in BiggestBoundary)
            {
                int pos = (int)(pt.X - MaxLeft.X);
                if (histogram[pos] == null)
                {
                    histogram[pos] = new List <Cl3DModel.Cl3DModelPointIterator>();
                }

                histogram[pos].Add(pt);
            }

            Dictionary <uint, uint> movingPoints = new Dictionary <uint, uint>();

            for (int i = 0; i < size; i++)
            {
                if (histogram[i] != null && histogram[i].Count != 0)
                {
                    //Color cl = ClTools.GetColorRGB(((float)i) / size, 1.0f);
                    Cl3DModel.Cl3DModelPointIterator UpperPoint = histogram[i][0];
                    Cl3DModel.Cl3DModelPointIterator LowerPoint = histogram[i][0];
                    foreach (Cl3DModel.Cl3DModelPointIterator pts in histogram[i])
                    {
                        //  pts.Color = cl;
                        if (UpperPoint.Y < pts.Y)
                        {
                            UpperPoint = pts;
                        }
                        if (LowerPoint.Y > pts.Y)
                        {
                            LowerPoint = pts;
                        }
                    }
                    //UpperPoint from this one
                    if (UpperPoint.PointID != LowerPoint.PointID)
                    {
                        float distance = Math.Min(LowerPoint - MaxLeft, LowerPoint - MaxRight);
                        List <Cl3DModel.Cl3DModelPointIterator> neighborhood = null;
                        ClTools.GetNeighborhoodWithGeodesicDistance(out neighborhood, LowerPoint, distance);
                        Cl3DModel.Cl3DModelPointIterator ClosestPoint = LowerPoint;
                        float MinDistance = LowerPoint - UpperPoint;
                        foreach (Cl3DModel.Cl3DModelPointIterator ptNeighb in neighborhood)
                        {
                            // ptNeighb.Color = Color.Pink;
                            float newDistance = ptNeighb - UpperPoint;
                            if (newDistance < MinDistance)
                            {
                                MinDistance  = newDistance;
                                ClosestPoint = ptNeighb;
                            }
                        }
                        Color cl = ClTools.GetColorRGB(((float)i) / size, 1.0f);
                        ClosestPoint.Color = cl;
                        UpperPoint.Color   = cl;
                        movingPoints.Add(UpperPoint.PointID, ClosestPoint.PointID);
                    }
                }
            }
            p_Model.ResetVisitedPoints();
            ClTools.CalculateGeodesicDistanceFromSourcePointToAllPointsWithMovement(NoseTip, Cl3DModel.Cl3DModelPointIterator.eSpecificValues.GeodesicDistanceToNoseTip.ToString(), movingPoints);

            iter = p_Model.GetIterator();
            while (iter.IsValid())
            {
                if (!iter.IsSpecificValueCalculated(Cl3DModel.Cl3DModelPointIterator.eSpecificValues.GeodesicDistanceToNoseTip))
                {
                    iter = p_Model.RemovePointFromModel(iter);
                }
                else
                {
                    double distance = iter.GetSpecificValue(Cl3DModel.Cl3DModelPointIterator.eSpecificValues.GeodesicDistanceToNoseTip);
                    if (distance > m_fDistence)
                    {
                        iter = p_Model.RemovePointFromModel(iter);
                    }
                    else
                    {
                        iter.MoveToNext();
                    }
                }
            }
            return;

            //------------------------ PCA ----------------------

            /*
             * float MeanX = 0;
             * float MeanY = 0;
             * float MeanZ = 0;
             * Matrix xy = new Matrix(3, BiggestBoundary.Count);
             * for (int i = 0; i < BiggestBoundary.Count; i++)
             * {
             *  xy[0,i] = BiggestBoundary[i].X;
             *  xy[1,i] = BiggestBoundary[i].Y
             *  xy[2, i] = BiggestBoundary[i].Z;
             *
             *  MeanX += BiggestBoundary[i].X;
             *  MeanY += BiggestBoundary[i].Y;
             *  MeanZ += BiggestBoundary[i].Z;
             *
             *  BiggestBoundary[i].Color = Color.Red;
             * }
             * MeanX /= BiggestBoundary.Count;
             * MeanY /= BiggestBoundary.Count;
             * MeanZ /= BiggestBoundary.Count;
             *
             * for (int i = 0; i < BiggestBoundary.Count; i++)
             * {
             *  xy[0, i] -= MeanX;
             *  xy[1, i] -= MeanY;
             *  xy[2, i] -= MeanZ;
             * }
             *
             *
             * Matrix Transpose = xy.Clone();
             * Transpose.Transpose();
             * Matrix Corelation = xy * Transpose;
             *
             * SingularValueDecomposition SVD = new SingularValueDecomposition(Corelation);
             *
             * Cl3DModel.Cl3DModelPointIterator point = p_Model.AddPointToModel(MeanX, MeanY, MeanZ);
             * Cl3DModel.Cl3DModelPointIterator point2 = p_Model.AddPointToModel(MeanX + (float)SVD.LeftSingularVectors[0, 0] * 10, MeanY + (float)SVD.LeftSingularVectors[1, 0] * 10, MeanZ + (float)SVD.LeftSingularVectors[2, 0] * 10);
             * Cl3DModel.Cl3DModelPointIterator point3 = p_Model.AddPointToModel(MeanX + (float)SVD.LeftSingularVectors[0, 1] * 10, MeanY + (float)SVD.LeftSingularVectors[1, 1] * 10, MeanZ + (float)SVD.LeftSingularVectors[2, 1] * 10);
             * Cl3DModel.Cl3DModelPointIterator point4 = p_Model.AddPointToModel(MeanX + (float)SVD.LeftSingularVectors[0, 2] * 10, MeanY + (float)SVD.LeftSingularVectors[1, 2] * 10, MeanZ + (float)SVD.LeftSingularVectors[2, 2] * 10);
             * point2.Color = Color.Red;
             * point3.Color = Color.Green;
             * point4.Color = Color.Blue;
             * point.AddNeighbor(point2);
             * point.AddNeighbor(point3);
             * point.AddNeighbor(point4);
             */
            //---------------------------------------------------------------------------
        }