Example #1
0
        internal MeshGeometry3D AutoSnake(MeshGeometry3D mesh, ref MeshBuilder newmbP)
        {
            //Dictionary<Int32, SmileEdge> neighbours = SmileVisual3D.findNeighbours(mesh);

            Point3DCollection positions       = mesh.Positions;
            Int32Collection   triangleIndices = mesh.TriangleIndices;
            Mesh3D            m3d             = new Mesh3D(positions, triangleIndices);

            Vector3DCollection t          = new Vector3DCollection(positions.Count);
            Vector3DCollection b          = new Vector3DCollection(positions.Count);
            Vector3DCollection n          = new Vector3DCollection(positions.Count);
            double             eThreshold = -0.5;
            double             nThreshold = 0.8;
            double             minEnergy  = 10;
            double             alpha      = 1;
            double             betha      = 1;
            double             ballon     = 1;
            double             lambda     = 1;
            Vector3DCollection e          = new Vector3DCollection(positions.Count);
            Vector3DCollection eInt       = new Vector3DCollection(positions.Count);
            Vector3DCollection eExt       = new Vector3DCollection(positions.Count);

            Vector3DCollection delta = new Vector3DCollection(positions.Count);
            Vector3DCollection f     = new Vector3DCollection(positions.Count);
            Vector3DCollection tETF  = new Vector3DCollection(positions.Count);

            //Vector3DCollection k = new Vector3DCollection();
            //DoubleCollection kH = new DoubleCollection();
            Dictionary <int, Double> kH = new Dictionary <int, double>();
            MeshBuilder newmbD          = new MeshBuilder(false, false);

            for (int i = 0; i < triangleIndices.Count; i += 3)
            {
                for (int a = 0; a < 3; a++)
                {
                    int vi = triangleIndices[i + a];

                    if (!kH.ContainsKey(vi))
                    {
                        double kHi = _MeanCurvature(m3d, vi);
                        kH.Add(vi, kHi);
                    }
                    //Console.WriteLine("start mean");
                    //kH.Add(kHi);
                    //Console.WriteLine("end mean");
                    if (a == 2)
                    {
                        int    vi1 = triangleIndices[i + a - 1];
                        int    vi2 = triangleIndices[i + a - 2];
                        double kH3 = 0;
                        kH.TryGetValue(vi, out kH3);
                        double kH2 = 0;
                        kH.TryGetValue(vi1, out kH2);
                        double kH1 = 0;
                        kH.TryGetValue(vi2, out kH1);

                        if ((kH3 < eThreshold || kH2 < eThreshold || kH1 < eThreshold))
                        {
                            newmbD.Positions.Add(positions[vi]);
                            newmbD.Positions.Add(positions[vi1]);
                            newmbD.Positions.Add(positions[vi2]);
                            newmbD.TriangleIndices.Add(i + a);
                            newmbD.TriangleIndices.Add(i + a - 1);
                            newmbD.TriangleIndices.Add(i + a - 2);
                        }
                        if ((kH3 > nThreshold || kH2 > nThreshold || kH1 > nThreshold))
                        {
                            newmbP.Positions.Add(positions[vi]);
                            newmbP.Positions.Add(positions[vi1]);
                            newmbP.Positions.Add(positions[vi2]);
                            newmbP.TriangleIndices.Add(i + a);
                            newmbP.TriangleIndices.Add(i + a - 1);
                            newmbP.TriangleIndices.Add(i + a - 2);
                        }
                    }

                    int[] nbrs            = m3d.GetNeighbourVertices(vi);
                    Vector3DCollection N  = new Vector3DCollection(positions.Count);
                    Point3D            pi = positions[vi];
                    int i0 = triangleIndices[i + a];
                    if (i + a - 1 >= 0)
                    {
                        i0 = triangleIndices[i + a - 1];
                    }
                    Point3D pi0 = positions[i0];
                    int     i1  = vi;
                    if (i + a + i < triangleIndices.Count)
                    {
                        i1 = triangleIndices[i + a + 1];
                    }
                    Point3D pi1 = positions[i1];

                    t.Insert(vi, (pi1 - pi0) / (Point3D.Subtract(pi1, pi0).Length));
                    //t[i] = (pi1 - pi0) / Math.Sqrt((Point3D.Subtract(pi1, pi0).Length));
                    n.Insert(vi, SmileVisual3D.CalculateNormal(pi0, pi, pi1));
                    b.Insert(vi, Vector3D.CrossProduct(t[vi], n[vi]));

                    Vector3D eIntV        = new Vector3D(); //eInt[vi];
                    Vector3D eExtV        = new Vector3D(); //eExt[vi];
                    Vector3D eV           = new Vector3D(); //e[vi];
                    Vector3D sumDeltaNbrs = new Vector3D();
                    Vector3D sumFNbrs     = new Vector3D();
                    int      maxNbrs      = (nbrs.Length > 2 ? 2 : nbrs.Length);
                    for (int j = 0; j < maxNbrs; j++)
                    {
                        Point3D nbj = positions[nbrs[j]];
                        N.Add(nbj.ToVector3D());
                    }
                    double determinantVi = determinant(N);
                    double kv            = 0;
                    kH.TryGetValue(vi, out kv);
                    double  jminEnergy = minEnergy;
                    Point3D tempNbj    = pi;
                    for (int j = 0; j < maxNbrs; j++)
                    {
                        Point3D nbj = positions[nbrs[j]];

                        double ku = 0;
                        kH.TryGetValue(nbrs[j], out ku);
                        sumDeltaNbrs += Vector3D.Multiply((kv - ku), Vector3D.Divide(Point3D.Subtract(nbj, pi), (Point3D.Subtract(nbj, pi).Length)));
                        delta.Insert(vi, (1 / determinantVi) * sumDeltaNbrs);
                        f.Insert(vi, Vector3D.Multiply((1 - lambda), Vector3D.Multiply((1 / determinantVi), new Vector3D())) + Vector3D.Multiply(lambda, delta[vi]));
                        double eIntj   = alpha * (Point3D.Subtract(pi0, nbj).Length) + betha * (Point3D.Subtract(pi0, Point3D.Add(pi1, (Vector3D)nbj)).Length);                    //TODO: crosscheck
                        double eFaej   = ballon * (-(f[vi].Length) - Vector3D.DotProduct((f[vi] / f[vi].Length), (Point3D.Subtract(nbj, pi) / Point3D.Subtract(nbj, pi).Length))); //TODO: crosscheck
                        double ePressj = ballon * Vector3D.DotProduct(b[vi], (Point3D.Subtract(pi0, nbj) / Point3D.Subtract(pi0, nbj).Length));
                        double eExtj   = eFaej + ePressj;
                        double ej      = eIntj + eExtj;

                        if (j == 0)
                        {
                            eIntV.X = eIntj;
                            eExtV.X = eExtj;
                            eV.X    = ej;
                        }
                        if (j == 1)
                        {
                            eIntV.Y = eIntj;
                            eExtV.Y = eExtj;
                            eV.Y    = ej;
                        }
                        if (j == 2)
                        {
                            eIntV.Z = eIntj;
                            eExtV.Z = eExtj;
                            eV.Z    = ej;
                        }

                        if (ej < jminEnergy)
                        {
                            jminEnergy = ej;
                            tempNbj    = nbj;
                            //TODO: snake movement
                            //AddSnakeElement(nbj);
                        }
                    }
                    AddSnakeElement(tempNbj);

                    eInt.Insert(vi, eIntV);
                    eExt.Insert(vi, eExtV);
                    e.Insert(vi, eV);

                    //delta.Insert(vi,  (1 / determinant(N[vi])) * sumDeltaNbrs); //TODO:implemenet
                    //f.Insert(vi, n[vi]);// (1 - lambda) * (1 / (Math.Abs(nbrs.Count))) + lambda *delta[i]; //TODO:implemenet

                    tETF.Insert(vi, Vector3D.CrossProduct(delta[vi], n[vi]));
                }
            }
            return(newmbD.ToMesh());

/*
 *          for (int i = 0; i < positions.Count; i++)
 *          {
 *              Int32Collection nbrs = neighbours[i].neighbours;
 *
 *              Point3D pi = positions[i];
 *              int i0 = i;
 *              if (i - 1 >= 0) i0 = i - 1;
 *              Point3D pi0 = positions[i0];
 *              int i1 = i;
 *              if (i + i < triangleIndices.Count) i = i + 1;
 *              Point3D pi1 = positions[i1];
 *
 *              t[i] = (pi1 - pi0) / (Point3D.Subtract(pi1, pi0).Length);
 *              //t[i] = (pi1 - pi0) / Math.Sqrt((Point3D.Subtract(pi1, pi0).Length));
 *              n[i] = SmileVisual3D.CalculateNormal(pi0, pi, pi1);
 *              b[i] = Vector3D.CrossProduct(t[i], n[i]);
 *
 *
 *              Vector3D eIntV = eInt[i];
 *              Vector3D eExtV = eExt[i];
 *              Vector3D eV = e[i];
 *              int maxNbrs = (nbrs.Count > 2 ? 2 : nbrs.Count);
 *              for (int j = 0; j < maxNbrs; j++)
 *              {
 *                  Point3D nbj = positions[nbrs[j]];
 *                  double eIntj = alpha * (Point3D.Subtract(pi0, nbj).Length) + betha * (Point3D.Subtract(pi0, Point3D.Add(pi1, (Vector3D)nbj)).Length); //TODO: crosscheck
 *
 *
 *                  delta[i] = n[i];// 1 / determinant(N[i]); //TODO:implemenet
 *                  f[i] = n[i];// (1 - lambda) * (1 / (Math.Abs(nbrs.Count))) + lambda *delta[i]; //TODO:implemenet
 *
 *
 *                  double eFaej = ballon * (-(f[i].Length) - Vector3D.DotProduct((f[i] / f[i].Length), (Point3D.Subtract(nbj, pi) / Point3D.Subtract(nbj, pi).Length))); //TODO: crosscheck
 *                  double ePressj = ballon * Vector3D.DotProduct(b[i], (Point3D.Subtract(pi0, nbj) / Point3D.Subtract(pi0, nbj).Length));
 *                  double eExtj = eFaej + ePressj;
 *                  double ej = eIntj + eExtj;
 *
 *                  if (j == 0)
 *                  {
 *                      eIntV.X = eIntj;
 *                      eExtV.X = eExtj;
 *                      eV.X = ej;
 *                  }
 *                  if (j == 1)
 *                  {
 *                      eIntV.Y = eIntj;
 *                      eExtV.Y = eExtj;
 *                      eV.Y = ej;
 *                  }
 *                  if (j == 2)
 *                  {
 *                      eIntV.Z = eIntj;
 *                      eExtV.Z = eExtj;
 *                      eV.Z = ej;
 *                  }
 *
 *                  if (ej < minEnergy)
 *                  {
 *                      minEnergy = ej;
 *                      //TODO: snake movement
 *                      AddSnakeElement(nbj);
 *                  }
 *
 *                  eInt[i] = eIntV;
 *                  eExt[i] = eExtV;
 *                  e[i] = eV;
 *              }
 *
 *              tETF[i] = Vector3D.CrossProduct(delta[i], n[i]);
 *
 *          }
 * */
        }
Example #2
0
        //ref: Snake-Based Segmentation of Teeth from Virtual Dental Casts
        //pLane located manually, set of verteks D and P from manual cutting plane
        //the plan is: teeth and gum separated then teeth segmented using snake below
        public static void snake(MeshGeometry3D mesh)
        {
            Dictionary <Int32, SmileEdge> neighbours = SmileVisual3D.findNeighbours(mesh);
            Point3DCollection             pos        = mesh.Positions;
            Int32Collection    ind        = mesh.TriangleIndices;
            Vector3DCollection t          = new Vector3DCollection();
            Vector3DCollection b          = new Vector3DCollection();
            Vector3DCollection n          = new Vector3DCollection();
            double             eThreshold = -0.3;
            double             nThreshold = 0.8;
            double             minEnergy  = 10;
            double             alpha      = 1;
            double             betha      = 1;
            double             ballon     = 1;
            double             lambda     = 1;
            Vector3DCollection e          = new Vector3DCollection();
            Vector3DCollection eInt       = new Vector3DCollection();
            Vector3DCollection eExt       = new Vector3DCollection();

            Vector3DCollection        delta = new Vector3DCollection();
            List <Vector3DCollection> N     = new List <Vector3DCollection>();
            Vector3DCollection        f     = new Vector3DCollection();
            Vector3DCollection        tETF  = new Vector3DCollection();

            Vector3DCollection k    = new Vector3DCollection();
            Vector3DCollection kH   = new Vector3DCollection();
            Vector3DCollection kMin = new Vector3DCollection();
            Vector3DCollection kMax = new Vector3DCollection();

            for (int i = 0; i < ind.Count; i++)
            {
                Point3D pi = pos[i];
                //kij =  2ni ยท (pi - pj)/|pi- pj |2
                kH[i] = (kMin[i] + kMax[i]) / 2;
            }

            for (int i = 0; i < ind.Count; i++)
            {
                Int32Collection nbrs = neighbours[i].neighbours;

                Point3D pi = pos[i];
                int     i0 = i;
                if (i - 1 >= 0)
                {
                    i0 = i - 1;
                }
                Point3D pi0 = pos[i0];
                int     i1  = i;
                if (i + i < ind.Count)
                {
                    i = i + 1;
                }
                Point3D pi1 = pos[i1];

                t[i] = (pi1 - pi0) / (Point3D.Subtract(pi1, pi0).Length);
                //t[i] = (pi1 - pi0) / Math.Sqrt((Point3D.Subtract(pi1, pi0).Length));
                n[i] = SmileVisual3D.CalculateNormal(pi0, pi, pi1);
                b[i] = Vector3D.CrossProduct(t[i], n[i]);


                Vector3D eIntV   = eInt[i];
                Vector3D eExtV   = eExt[i];
                Vector3D eV      = e[i];
                int      maxNbrs = (nbrs.Count > 2 ? 2 : nbrs.Count);
                for (int j = 0; j < maxNbrs; j++)
                {
                    Point3D nbj   = pos[nbrs[j]];
                    double  eIntj = alpha * (Point3D.Subtract(pi0, nbj).Length) + betha * (Point3D.Subtract(pi0, Point3D.Add(pi1, (Vector3D)nbj)).Length); //TODO: crosscheck


                    delta[i] = n[i]; // 1 / determinant(N[i]); //TODO:implemenet
                    f[i]     = n[i]; // (1 - lambda) * (1 / (Math.Abs(nbrs.Count))) + lambda *delta[i]; //TODO:implemenet


                    double eFaej   = ballon * (-(f[i].Length) - Vector3D.DotProduct((f[i] / f[i].Length), (Point3D.Subtract(nbj, pi) / Point3D.Subtract(nbj, pi).Length))); //TODO: crosscheck
                    double ePressj = ballon * Vector3D.DotProduct(b[i], (Point3D.Subtract(pi0, nbj) / Point3D.Subtract(pi0, nbj).Length));
                    double eExtj   = eFaej + ePressj;
                    double ej      = eIntj + eExtj;

                    if (j == 0)
                    {
                        eIntV.X = eIntj;
                        eExtV.X = eExtj;
                        eV.X    = ej;
                    }
                    if (j == 1)
                    {
                        eIntV.Y = eIntj;
                        eExtV.Y = eExtj;
                        eV.Y    = ej;
                    }
                    if (j == 2)
                    {
                        eIntV.Z = eIntj;
                        eExtV.Z = eExtj;
                        eV.Z    = ej;
                    }

                    if (ej < minEnergy)
                    {
                        minEnergy = ej;
                        //TODO: snake movement
                        AddSnakeElement(nbj);
                    }

                    eInt[i] = eIntV;
                    eExt[i] = eExtV;
                    e[i]    = eV;
                }

                tETF[i] = Vector3D.CrossProduct(delta[i], n[i]);
            }
        }