protected override void Algorithm(ref Cl3DModel p_Model)
        {
            Cl3DModel.Cl3DModelPointIterator iter = p_Model.GetIterator();
            do
            {
                double value = 0;
                if (!iter.GetSpecificValue(m_SpecificValue, out value))
                {
                    iter.MoveToNext();
                    continue;
                }

                if (value > m_ThresholdValue)
                {
                    iter = p_Model.RemovePointFromModel(iter);
                }
                else
                {
                    iter.MoveToNext();
                }

            } while (iter.IsValid());
        }
        protected override void Algorithm(ref Cl3DModel p_Model)
        {
            Cl3DModel.Cl3DModelPointIterator RightEye = p_Model.GetSpecificPoint(Cl3DModel.eSpecificPoints.RightEyeLeftCorner.ToString());
            Cl3DModel.Cl3DModelPointIterator LeftEye = p_Model.GetSpecificPoint(Cl3DModel.eSpecificPoints.LeftEyeRightCorner.ToString());

            Cl3DModel.Cl3DModelPointIterator[,] Map = null;
            int Width, Height, Xoffset, Yoffset;
            ClTools.CreateGridBasedOnRangeValues(p_Model, out Map, out Width, out Height, out Xoffset, out Yoffset);

            int RightEyeX = RightEye.RangeImageX - Xoffset;
            int RightEyeY = RightEye.RangeImageY - Yoffset;
            int LeftEyeX = LeftEye.RangeImageX - Xoffset;
            int LeftEyeY = LeftEye.RangeImageY - Yoffset;

            int MiddleX = (RightEyeX + LeftEyeX) / 2;
            int MiddleY = (RightEyeY + LeftEyeY) / 2;

            Cl3DModel.Cl3DModelPointIterator MiddlePoint = Map[MiddleX, MiddleY];
            p_Model.AddSpecificPoint(Cl3DModel.eSpecificPoints.UnspecifiedPoint, MiddlePoint);

            List<Cl3DModel.Cl3DModelPointIterator> Neighborhood = null;
            ClTools.GetNeighborhoodWithGeodesicDistance(out Neighborhood, MiddlePoint, m_fEyesPartRadious);
            foreach (Cl3DModel.Cl3DModelPointIterator point in Neighborhood)
                point.AlreadyVisited = true;

            MiddlePoint.AlreadyVisited = true;

            Cl3DModel.Cl3DModelPointIterator iter = p_Model.GetIterator();
            do
            {
                if (!iter.IsValid())
                    break;

                if (!iter.AlreadyVisited)
                    iter = p_Model.RemovePointFromModel(iter);
                else
                    if (!iter.MoveToNext())
                        break;

            } while (true);
        }
        private void SampleUVParametriztion(Cl3DModel p_Model, out Cl3DModel.Cl3DModelPointIterator[,] SampledModel, int MatrixWidth, int MatrixHeight)
        {
            Cl3DModel.Cl3DModelPointIterator iter = p_Model.GetIterator();
            float maxU = iter.U;
            float minU = iter.U;
            float maxV = iter.V;
            float minV = iter.V;

            do
            {
                if (maxU < iter.U)
                    maxU = iter.U;
                if (maxV < iter.V)
                    maxV = iter.V;

                if (minU > iter.U)
                    minU = iter.U;
                if (minV > iter.V)
                    minV = iter.V;
            } while (iter.MoveToNext());

            List<Cl3DModel.Cl3DModelPointIterator>[,] SampledModelList = new List<Cl3DModel.Cl3DModelPointIterator>[MatrixWidth,MatrixHeight];
            SampledModel = new Cl3DModel.Cl3DModelPointIterator[MatrixWidth, MatrixHeight];

            iter = p_Model.GetIterator();
            do
            {
                float U = iter.U - minU;
                float V = iter.V - minV;

                int RoundU = (int)((U / (maxU - minU)) * (MatrixWidth - 1));
                int RoundV = (int)((V / (maxV - minV)) * (MatrixHeight - 1));

                if(SampledModelList[RoundU, RoundV] == null)
                    SampledModelList[RoundU, RoundV] = new List<Cl3DModel.Cl3DModelPointIterator>();

                SampledModelList[RoundU, RoundV].Add(iter.CopyIterator());

               } while (iter.MoveToNext());

            for(int i=0; i< MatrixWidth; i++)
            {
                for(int j=0; j<MatrixHeight; j++)
                {
                    if(SampledModelList[i,j]!= null)
                    {
                        float x = 0;
                        float y = 0;
                        float z = 0;
                        float u = 0;
                        float v = 0;
                        int ColorR = 0;
                        int ColorG = 0;
                        int ColorB = 0;
                        string specPoint = Cl3DModel.eSpecificPoints.UnspecifiedPoint.ToString();
                        bool isSpecific = false;

                        Dictionary<string, double> SumOfSpecificValues = new Dictionary<string, double>();
                        foreach(Cl3DModel.Cl3DModelPointIterator pts in SampledModelList[i,j])
                        {
                            pts.AlreadyVisited = true;
                            if (!isSpecific)
                                isSpecific = p_Model.IsThisPointInSpecificPoints(pts, ref specPoint);

                            List<string> specValues = pts.GetListOfSpecificValues();
                            foreach (string valueName in specValues)
                            {
                                double currentVal = 0;
                                pts.GetSpecificValue(valueName, out currentVal);
                                double countedVal = 0;
                                SumOfSpecificValues.TryGetValue(valueName, out countedVal);

                                SumOfSpecificValues.Remove(valueName);
                                SumOfSpecificValues.Add(valueName, countedVal + currentVal);
                            }
                            x += pts.X;
                            y += pts.Y;
                            z += pts.Z;
                            u += pts.U;
                            v += pts.V;
                            ColorR += pts.ColorR;
                            ColorG += pts.ColorG;
                            ColorB += pts.ColorB;
                        }

                        int Count = SampledModelList[i, j].Count;

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

                        foreach (Cl3DModel.Cl3DModelPointIterator point in SampledModelList[i, j])
                            foreach (Cl3DModel.Cl3DModelPointIterator InnerPoint in point.GetListOfNeighbors())
                                if (InnerPoint.AlreadyVisited == false)
                                    connections.Add(InnerPoint);

                        Cl3DModel.Cl3DModelPointIterator pt = p_Model.AddPointToModel(x / Count,
                                                                                        y / Count,
                                                                                        z / Count);
                        pt.Color = Color.FromArgb(ColorR / Count,
                                                    ColorG / Count,
                                                    ColorB / Count);

                        pt.U = (int)((u / SampledModelList[i, j].Count) / maxU * MatrixWidth);
                        pt.V = (int)((v / SampledModelList[i, j].Count) / maxV * MatrixHeight);

                        foreach (KeyValuePair<string, double> SpecVal in SumOfSpecificValues)
                            pt.AddSpecificValue(SpecVal.Key, SpecVal.Value / Count);

                        SampledModel[i, j] = pt;

                        if (isSpecific)
                            p_Model.AddSpecificPoint(specPoint, pt);

                        foreach(Cl3DModel.Cl3DModelPointIterator point in SampledModelList[i, j])
                            p_Model.RemovePointFromModel(point);

                        foreach (Cl3DModel.Cl3DModelPointIterator point in connections)
                            pt.AddNeighbor(point);

                    }
                }
            }
        }
        protected override void Algorithm(ref Cl3DModel p_Model)
        {
            Cl3DModel.Cl3DModelPointIterator iter = p_Model.GetIterator();
            int maxX = (int)iter.X;
            int minX = (int)iter.X;
            int maxY = (int)iter.Y;
            int minY = (int)iter.Y;

            do
            {
                if (maxX < iter.X)
                    maxX = (int)iter.X;
                if (maxY < iter.Y)
                    maxY = (int)iter.Y;

                if (minX > iter.X)
                    minX = (int)iter.X;
                if (minY > iter.Y)
                    minY = (int)iter.Y;
            } while (iter.MoveToNext());

            int width = (maxX - minX) + 1;
            int height = (maxY - minY) + 1;

            List<Cl3DModel.Cl3DModelPointIterator>[,] map = new List<Cl3DModel.Cl3DModelPointIterator>[width, height];

            iter = p_Model.GetIterator();
            do
            {
                int x = (int)iter.X - minX;
                int y = (int)iter.Y - minY;
                if(map[x,y] == null)
                    map[x,y] = new List<Cl3DModel.Cl3DModelPointIterator>();

                map[x,y].Add(iter.CopyIterator());
            } while (iter.MoveToNext());

            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    if (map[x, y] != null)
                    {
                        int MeanR = 0;
                        int MeanG = 0;
                        int MeanB = 0;
                        float MeanX = 0;
                        float MeanY = 0;
                        float MeanZ = 0;

                        float MeanU = 0;
                        float MeanV = 0;

                        float MeanRangeX = 0;
                        float MeanRangeY = 0;

                        Dictionary<string, List<double>> MeanSpecificValues = new Dictionary<string, List<double>>();

                        Cl3DModel.Cl3DModelPointIterator MaxPoint = null;

                        string specPoint = Cl3DModel.eSpecificPoints.UnspecifiedPoint.ToString();
                        bool isSpecific = false;
                        foreach (Cl3DModel.Cl3DModelPointIterator point in map[x, y])
                        {
                            point.AlreadyVisited = true;
                            if(!isSpecific)
                                isSpecific = p_Model.IsThisPointInSpecificPoints(point, ref specPoint);

                            if (m_bMean)
                            {
                                MeanR += point.ColorR;
                                MeanG += point.ColorG;
                                MeanB += point.ColorB;
                                MeanX += point.X;
                                MeanY += point.Y;
                                MeanZ += point.Z;

                                MeanU += point.U;
                                MeanV += point.V;

                                MeanRangeX += point.RangeImageX;
                                MeanRangeY += point.RangeImageY;

                                List<string> listOfValuesNames = point.GetListOfSpecificValues();
                                foreach(string name in listOfValuesNames)
                                {
                                    List<double> listOfValues = null;
                                    if (!MeanSpecificValues.TryGetValue(name, out listOfValues))
                                    {
                                        listOfValues = new List<double>();
                                        MeanSpecificValues.Add(name, listOfValues);
                                    }
                                    double val = point.GetSpecificValue(name);
                                    listOfValues.Add(val);
                                }
                            }
                            else
                            {// search for max Z
                                if (MaxPoint == null)
                                    MaxPoint = point;
                                else if(MaxPoint.Z < point.Z)
                                    MaxPoint = point;
                            }
                        }

                        if (m_bMean)
                        {
                            MeanR /= map[x, y].Count;
                            MeanG /= map[x, y].Count;
                            MeanB /= map[x, y].Count;
                            MeanX /= map[x, y].Count;
                            MeanY /= map[x, y].Count;
                            MeanZ /= map[x, y].Count;

                            MeanU /= map[x, y].Count;
                            MeanV /= map[x, y].Count;

                            MeanRangeX /= map[x, y].Count;
                            MeanRangeY /= map[x, y].Count;
                        }
                        else
                        {
                            MeanR = MaxPoint.ColorR;
                            MeanG = MaxPoint.ColorG;
                            MeanB = MaxPoint.ColorB;
                            MeanX = MaxPoint.X;
                            MeanY = MaxPoint.Y;
                            MeanZ = MaxPoint.Z;

                            MeanU = MaxPoint.U;
                            MeanV = MaxPoint.V;

                            MeanRangeX = MaxPoint.RangeImageX;
                            MeanRangeY = MaxPoint.RangeImageY;
                        }

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

                        foreach (Cl3DModel.Cl3DModelPointIterator point in map[x, y])
                            foreach (Cl3DModel.Cl3DModelPointIterator InnerPoint in point.GetListOfNeighbors())
                                if(InnerPoint.AlreadyVisited == false)
                                    connections.Add(InnerPoint);

                        Cl3DModel.Cl3DModelPointIterator pt = p_Model.AddPointToModel((int)MeanX, (int)MeanY, MeanZ, x, width - y);
                        pt.Color = Color.FromArgb(MeanR, MeanG, MeanB);
                        pt.U = MeanU;
                        pt.V = MeanV;

                        foreach (KeyValuePair<string, List<double>> kvValues in MeanSpecificValues)
                        {
                            string valueName = kvValues.Key;
                            List<double> values = kvValues.Value;
                            double meanVal = 0;
                            foreach (double val in values)
                            {
                                meanVal += val;
                            }
                            meanVal /= values.Count;
                            pt.AddSpecificValue("Mean_" + valueName, meanVal);
                        }

                        if (isSpecific)
                            p_Model.AddSpecificPoint(specPoint, pt);

                        List<Cl3DModel.Cl3DModelPointIterator> lista =  map[x, y];
                        for (int i = 0; i < lista.Count; i++)
                        {
                            p_Model.RemovePointFromModel(lista[i]);
                        }

                        foreach (Cl3DModel.Cl3DModelPointIterator point in connections)
                            pt.AddNeighbor(point);
                    }
                }
            }
        }
        protected override void Algorithm(ref Cl3DModel p_Model)
        {
            Cl3DModel.Cl3DModelPointIterator NoseTip = null;

            if (!p_Model.GetSpecificPoint(m_NoseTipName, ref NoseTip))
                throw new Exception("Cannot find specific point NoseTip");

            Cl3DModel.Cl3DModelPointIterator iter = p_Model.GetIterator();

            while(iter.IsValid())
            {
                bool isOk = false;
                if (ClTools.IsItInsideSphere(iter.X, iter.Y, iter.Z, NoseTip.X, NoseTip.Y, NoseTip.Z + m_fBottomSphereNoseTipZoffset, m_fBottomSphereRadious))
                {
                    if (ClTools.IsItInsideSphere(iter.X, iter.Y, iter.Z, NoseTip.X, NoseTip.Y, NoseTip.Z + m_fUpperSphereNoseTipZoffset, m_fUpperSphereRadious))
                    {
                        isOk = true;
                    }
                }

                if (!isOk)
                {
                    iter = p_Model.RemovePointFromModel(iter);
                }
                else
                {
                    if (!iter.MoveToNext())
                        break;
                }
            }
        }
        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)
        {
            if (NormalsAdded.Count != 0)
            {
                foreach (Cl3DModel.Cl3DModelPointIterator pt in NormalsAdded)
                    p_Model.RemovePointFromModel(pt);

                NormalsAdded = new List<Cl3DModel.Cl3DModelPointIterator>();
            }

            Cl3DModel.Cl3DModelPointIterator iter = p_Model.GetIterator();
            do
            {
                Vector NormalVector = null;
                if (UsePCA)
                {
                    ClTools.CalculateNormalVectorInPointUsingPCA(iter.X, iter.Y, iter.Z, iter.GetListOfNeighbors(), out NormalVector);
                }
                else
                {
                    ClTools.CalculateNormalVectorInPoint(iter.X, iter.Y, iter.Z, iter.GetListOfNeighbors(), out NormalVector);
                }

                double norm = Math.Sqrt(Math.Pow(NormalVector[0], 2) + Math.Pow(NormalVector[1], 2) + Math.Pow(NormalVector[2], 2));
                if (norm != 0)
                {
                    NormalVector[0] /= (float)norm;
                    NormalVector[1] /= (float)norm;
                    NormalVector[2] /= (float)norm;
                }
                iter.NormalVector = NormalVector;

                if (ShowNormals)
                {
                    Cl3DModel.Cl3DModelPointIterator point = p_Model.AddPointToModel(iter.X - (float)NormalVector[0]*3, iter.Y - (float)NormalVector[1]*3, iter.Z - (float)NormalVector[2]*3);
                    iter.AddNeighbor(point);
                    NormalsAdded.Add(point);
                }

            } while (iter.MoveToNext());
        }
        protected override void Algorithm(ref Cl3DModel p_Model)
        {
            Cl3DModel.Cl3DModelPointIterator iter = p_Model.GetIterator();

            if(iter.IsValid())
            {
                do
                {
                    List<float> points = new List<float>();
                    List<Cl3DModel.Cl3DModelPointIterator> Neighbors = iter.GetListOfNeighbors();

                    foreach (Cl3DModel.Cl3DModelPointIterator neighbor in Neighbors)
                        points.Add(neighbor.Z);
                    points.Add(iter.Z);

                    points.Sort();

                    float result = 0;
                    if (points.Count % 2 == 0)// even
                    {
                        int first = (int)(points.Count / 2);
                        result = (points[first - 1] + points[first]) / 2;
                    }
                    else // odd
                    {
                        int element = (int)(points.Count / 2);
                        result = points[element];
                    }

                    if (m_bDecision)
                    {
                        float diff = Math.Abs(iter.Z - result);
                        if (diff >= m_SpikeThreshold)
                        {
                            iter = p_Model.RemovePointFromModel(iter);
                        }
                        else
                            if (!iter.MoveToNext())
                                break;
                    }
                    else
                    {
                        iter.Z = result;
                        if (!iter.MoveToNext())
                            break;
                    }
                } while (iter.IsValid());
            }
        }
        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();

            while(iter.IsValid())
            {
                bool isOk = false;
                if (iter.Z < NoseTip.X && iter.Z > NoseTip.Z - m_fPlaneDistanceZ)
                {
                    isOk = true;
                }

                if (!isOk)
                {
                    iter = p_Model.RemovePointFromModel(iter);
                }
                else
                {
                    if (!iter.MoveToNext())
                        break;
                }
            }
        }
        protected override void Algorithm(ref Cl3DModel p_Model)
        {
            Cl3DModel.Cl3DModelPointIterator iter = p_Model.GetIterator();

               // uint no = (uint)p_Model.ModelPointsCount / 2;

              //  if (!iter.MoveToPoint(no))
              //      throw new Exception("Cannot find point no: " + no.ToString());

            List<Cl3DModel.Cl3DModelPointIterator> PointNeighborhood;
            ClTools.GetNeighborhoodWithGeodesicDistance(out PointNeighborhood, iter, m_SphereSize);
            foreach (Cl3DModel.Cl3DModelPointIterator p in PointNeighborhood)
            {
                p_Model.RemovePointFromModel(p);
            }
            p_Model.RemovePointFromModel(iter);
        }
        protected override void Algorithm(ref Cl3DModel p_Model)
        {
            Cl3DModel.Cl3DModelPointIterator[,] Map;
            int width = 0;
            int height = 0;
            int offsetX = 0;
            int offsetY = 0;
            ClTools.CreateGridBasedOnRangeValues(p_Model, out Map, out width, out height, out offsetX, out offsetY);

            double SumOfKernelMatrix = 0;

            double[,] Mask = GetGaussianMatrix(MaskSize, 2.0f, out SumOfKernelMatrix);

            int pointsFromCenter = (MaskSize / 2);
            for (int centX = 0; centX < width; centX++)
            {
                for (int centY = 0; centY < height; centY++)
                {
                    if (Map[centX, centY] == null)
                        continue;

                    int XBeginning = centX - pointsFromCenter;
                    int YBeginning = centY - pointsFromCenter;

                    double value = 0;
                    bool didBreak = false;
                    for (int xi = 0; xi < MaskSize; xi++)
                    {
                        for (int yi = 0; yi < MaskSize; yi++)
                        {
                            if (XBeginning + xi >= 0 && XBeginning + xi < width && YBeginning + yi >= 0 && YBeginning + yi < height &&
                                Map[XBeginning + xi, YBeginning + yi] != null)
                                value += Mask[xi, yi] * Map[XBeginning + xi, YBeginning + yi].Z;
                            else
                            {
                                Map[centX, centY].AlreadyVisited = true;
                              //  Map[centX, centY].Color = Color.Red;
                                didBreak = true;
                                break;
                            }
                        }
                        if (didBreak)
                            break;
                    }
                    if(!didBreak)
                        Map[centX, centY].Z = (float)(value / SumOfKernelMatrix);
                }
            }
            Cl3DModel.Cl3DModelPointIterator iter = p_Model.GetIterator();
            do
            {
                if (iter.AlreadyVisited)
                    iter = p_Model.RemovePointFromModel(iter);
                else
                    iter.MoveToNext();
            } while (iter.IsValid());
        }
        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)
        {
            Cl3DModel.Cl3DModelPointIterator nose = p_Model.GetSpecificPoint(Cl3DModel.eSpecificPoints.NoseTip.ToString());

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

            Cl3DModel.Cl3DModelPointIterator iter = p_Model.GetIterator();
            do
            {
                double distance = 0;
                if (iter.GetSpecificValue(Cl3DModel.Cl3DModelPointIterator.eSpecificValues.GeodesicDistanceToNoseTip, out distance))
                {
                    if (distance > m_fDistence)
                        iter = p_Model.RemovePointFromModel(iter);
                    else
                    {
                        if (!iter.MoveToNext())
                            break;
                    }
                }
                else
                    iter = p_Model.RemovePointFromModel(iter);

            }while(iter.IsValid());
        }
        protected override void Algorithm(ref Cl3DModel p_Model)
        {
            Cl3DModel.Cl3DModelPointIterator NoseTip = null;
            if (!p_Model.GetSpecificPoint(m_point, ref NoseTip))
                throw new Exception("Cannot get point " + m_point);

             //   p_Model.RemoveAllSpecificPoints();
            p_Model.RemovePointFromModel(NoseTip);
        }
        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);
            */
            //---------------------------------------------------------------------------
        }
        protected override void Algorithm(ref Cl3DModel p_Model)
        {
            if (p_Model.ModelType != "abs")
                throw new Exception("Remove Half Of The Face works only for ABS files");

            Cl3DModel.Cl3DModelPointIterator iter = p_Model.GetIterator();
            if (!iter.IsValid())
                throw new Exception("Model iterator not Valid");

            int MinX;
            int MaxX;
            int MinY;
            int MaxY;

            MinX = iter.RangeImageX;
            MaxX = iter.RangeImageX;
            MinY = iter.RangeImageY;
            MaxY = iter.RangeImageY;

            do
            {
                if (MinX > iter.RangeImageX)
                    MinX = iter.RangeImageX;
                if (MaxX < iter.RangeImageX)
                    MaxX = iter.RangeImageX;

                if (MinY > iter.RangeImageY)
                    MinY = iter.RangeImageY;
                if (MaxY < iter.RangeImageY)
                    MaxY = iter.RangeImageY;

            } while (iter.MoveToNext());

            int Width = (MaxX - MinX) + 1;
            int Height = (MaxY - MinY) + 1;
            Cl3DModel.Cl3DModelPointIterator[,] map = new Cl3DModel.Cl3DModelPointIterator[Width, Height];

            iter = p_Model.GetIterator();
            do
            {
                map[iter.RangeImageX - MinX, iter.RangeImageY - MinY] = iter.CopyIterator();
            } while (iter.MoveToNext());

            int procent = (int)(Width * m_procentToRemove);

            for (int i = procent; i < Width; i++)
            {
                for (int j = 0; j < Height; j++)
                {
                    p_Model.RemovePointFromModel(map[i, j]);
                }
            }
        }
        protected override void Algorithm(ref Cl3DModel p_Model)
        {
            Cl3DModel.Cl3DModelPointIterator tmpIter = p_Model.GetIterator();

            while (tmpIter.IsValid())
            {
                if (tmpIter.GetListOfNeighbors().Count <= 1)
                    tmpIter = p_Model.RemovePointFromModel(tmpIter);
                else
                {
                    if (!tmpIter.MoveToNext())
                        break;
                }
            }

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

            List<Cl3DModel.Cl3DModelPointIterator> ListToCheck = new List<Cl3DModel.Cl3DModelPointIterator>();
            List<Cl3DModel.Cl3DModelPointIterator> newListToCheck = new List<Cl3DModel.Cl3DModelPointIterator>();
            Cl3DModel.Cl3DModelPointIterator iter = null;
            int listNo = 0;

            while ((iter = findNextUnseenElement(ref p_Model)) != null)
            {
                ListToCheck.Add(iter);
                listOfRegions.Add(new List<Cl3DModel.Cl3DModelPointIterator>());
                do
                {
                    foreach (Cl3DModel.Cl3DModelPointIterator ElementFromListToCheck in ListToCheck)
                    {
                        if (!ElementFromListToCheck.AlreadyVisited)
                        {
                            listOfRegions[listNo].Add(ElementFromListToCheck);
                            ElementFromListToCheck.AlreadyVisited = true;
                            foreach (Cl3DModel.Cl3DModelPointIterator it in ElementFromListToCheck.GetListOfNeighbors())
                            {
                                if(!it.AlreadyVisited)
                                    newListToCheck.Add(it);
                            }
                        }
                    }

                    ListToCheck.Clear();
                    foreach (Cl3DModel.Cl3DModelPointIterator it in newListToCheck)
                        ListToCheck.Add(it);
                    newListToCheck.Clear();

                } while (ListToCheck.Count != 0);
                ListToCheck.Clear();
                listNo++;
            }

            if (listOfRegions.Count <= 1)
                return;

            int maxCount = listOfRegions[0].Count; ;
            int maxI = 0;
            for (int i = 1; i < listOfRegions.Count; i++)
            {
                if (listOfRegions[i].Count > maxCount)
                {
                    maxI = i;
                    maxCount = listOfRegions[i].Count;
                }
            }

            if (m_bColorIt)
            {
                for (int i = 0; i < listOfRegions.Count; i++ )
                {
                    if (i == maxI)
                        continue;

                    for (int j = 0; j < listOfRegions[i].Count; j++)
                    {
                        listOfRegions[i][j].Color = ClTools.GetColorRGB(((float)i) / listOfRegions.Count, 1);
                    }
                }
            }
            else
            {
                for (int i = 0; i < listOfRegions.Count; i++)
                {
                    if (i == maxI)
                        continue;

                    for (int j = 0; j < listOfRegions[i].Count; j++)
                    {
                        p_Model.RemovePointFromModel(listOfRegions[i][j]);
                    }
                }
            }
        }