private double Vrt_wij(int i, int j)
 {
     int b = i * 3, c = j * 3;
     Vector3d s = new Vector3d(mesh.VertexPos, b);
     Vector3d t = new Vector3d(mesh.VertexPos, c);
     Vector3d e = t-s;
     Vector3d ns = new Vector3d(mesh.VertexNormal, b);
     Vector3d nt = new Vector3d(mesh.VertexNormal, c);
     double w = (1 + ns.Dot(e) / e.Length()) * (1 + ns.Cross(nt).Length());
     return w;
 }
 private double Face_wij1(int i, int j)
 {
     Vector3d ns = new Vector3d(mesh.FaceNormal, i * 3);
     Vector3d nt = new Vector3d(mesh.FaceNormal, j * 3);
     return -ns.Dot(nt);
 }
 public Vector3d Rotate(Vector3d axis, double cos, double sin)
 {
     return this * cos + (axis.Cross(this)) * sin +
         axis * ((1.0 - cos) * (axis.Dot(this)));
 }
        // Compute the principle curvatures and directions, i.e. k1, k2, e1, e2.
        public void ObtainPerVertexPCurAndDirs()
        {
            // initialize areas.
            ComputePointAreas();
            int nf = mesh.FaceCount, nv = mesh.VertexCount;

            // Set up an initial coordinate system per vertex
            localvu = new Vector3d[nv];
            localvv = new Vector3d[nv];
            for (int i = 0; i < nf; i++)
            {
                int      b  = i * 3;
                int      c0 = mesh.FaceIndex[b];
                int      c1 = mesh.FaceIndex[b + 1];
                int      c2 = mesh.FaceIndex[b + 2];
                Vector3d v0 = new Vector3d(mesh.VertexPos, c0 * 3);
                Vector3d v1 = new Vector3d(mesh.VertexPos, c1 * 3);
                Vector3d v2 = new Vector3d(mesh.VertexPos, c2 * 3);
                localvu[c0] = v1 - v0;
                localvu[c1] = v2 - v1;
                localvu[c2] = v0 - v2;
            }
            for (int i = 0; i < nv; i++)
            {
                Vector3d normali = new Vector3d(mesh.VertexNormal, i * 3);
                localvu[i] = (localvu[i].Cross(normali)).Normalize();
                localvv[i] = normali.Cross(localvu[i]);
            }
            // Compute curvature per-face
            for (int i = 0; i < nf; i++)
            {
                // Edges
                int        c  = i * 3;
                int        d0 = mesh.FaceIndex[c] * 3;
                int        d1 = mesh.FaceIndex[c + 1] * 3;
                int        d2 = mesh.FaceIndex[c + 2] * 3;
                Vector3d[] e  = new Vector3d[3] {
                    new Vector3d(mesh.VertexPos, d2) - new Vector3d(mesh.VertexPos, d1),
                    new Vector3d(mesh.VertexPos, d0) - new Vector3d(mesh.VertexPos, d2),
                    new Vector3d(mesh.VertexPos, d1) - new Vector3d(mesh.VertexPos, d0)
                };
                Vector3d[] normals = new Vector3d[3] {
                    new Vector3d(mesh.VertexNormal, d0),
                    new Vector3d(mesh.VertexNormal, d1),
                    new Vector3d(mesh.VertexNormal, d2)
                };

                // N-T-B coordinate system per face
                Vector3d t = e[0].Normalize();
                Vector3d n = e[0].Cross(e[1]);
                Vector3d b = n.Cross(t).Normalize();

                // Estimate curvature based on variation of normals
                // along edges
                double[] m = new double[3] {
                    0, 0, 0
                };
                double[][] w = new double[3][];
                for (int j = 0; j < 3; ++j)
                {
                    w[j] = new double[3];
                }
                for (int j = 0; j < 3; ++j)
                {
                    double u = e[j].Dot(t);
                    double v = e[j].Dot(b);
                    w[0][0] += u * u;
                    w[0][1] += u * v;
                    w[2][2] += v * v;
                    Vector3d dn  = normals[(j + 2) % 3] - normals[(j + 1) % 3];
                    double   dnu = dn.Dot(t);
                    double   dnv = dn.Dot(b);
                    m[0] += dnu * u;
                    m[1] += dnu * v + dnv * u;
                    m[2] += dnv * v;
                }
                w[1][1] = w[0][0] + w[2][2];
                w[1][2] = w[0][1];

                // Least squares solution
                double[] diag = new double[3];
                if (!ldltdc(w, diag, 3))
                {
                    System.Console.WriteLine("ldltdc failed!\n");
                    continue;
                }
                ldltsl(w, diag, m, ref m, 3);

                // Push it back out to the vertices
                for (int j = 0; j < 3; j++)
                {
                    int    vj = mesh.FaceIndex[c + j];
                    double c1 = 0, c12 = 0, c2 = 0;
                    proj_curv(t, b, m[0], m[1], m[2],
                              localvu[vj], localvv[vj],
                              ref c1, ref c12, ref c2);
                    double wt = cornerareas[i][j] / pointareas[vj];
                    curva[vj] += wt * c1;
                    curvb[vj] += wt * c12;
                    curvc[vj] += wt * c2;
                }
            }

            // Compute principal directions and curvatures at each vertex
            for (int i = 0; i < nv; i++)
            {
                Vector3d ni = new Vector3d(mesh.VertexNormal, i * 3);
                DiagonalizeCurvature(localvu[i], localvv[i],
                                     curva[i], curvb[i], curvc[i],
                                     ni, ref pDir1[i], ref pDir2[i],
                                     ref curv1[i], ref curv2[i]);
            }
            System.Console.WriteLine("Done.\n");
        }
        public void ObtainDualPCurAndDirs()
        {
            ComputeDualPointAreas();
            // Compute curvature per-face
            int nf = mesh.FaceCount, nv = mesh.VertexCount;

            for (int i = 0; i < nf; i++)
            {
                // compute local uv coordinates for face i
                int        cc = i * 3;
                int        c0 = mesh.FaceIndex[cc] * 3;
                int        c1 = mesh.FaceIndex[cc + 1] * 3;
                int        c2 = mesh.FaceIndex[cc + 2] * 3;
                Vector3d[] eg = new Vector3d[3] {
                    new Vector3d(mesh.VertexPos, c2) - new Vector3d(mesh.VertexPos, c1),
                    new Vector3d(mesh.VertexPos, c0) - new Vector3d(mesh.VertexPos, c2),
                    new Vector3d(mesh.VertexPos, c1) - new Vector3d(mesh.VertexPos, c0)
                };
                // local coordinate system per face
                Vector3d uu = eg[0].Normalize();
                Vector3d nn = new Vector3d(mesh.FaceNormal, cc);
                Vector3d vv = nn.Cross(uu).Normalize();

                // Edges
                int[] c = new int[3];
                for (int j = 0; j < 3; ++j)
                {
                    c[j] = -1;
                }
                for (int j = 0; j < mesh.AdjFF[i].Length; ++j)
                {
                    c[j] = mesh.AdjFF[i][j] * 3;
                }
                for (int j = 0; j < 3; ++j)
                {
                    int d0 = cc;
                    int d1 = c[j];
                    int d2 = c[(j + 1) % 3];
                    if (d1 < 0 || d2 < 0)
                    {
                        continue;
                    }

                    Vector3d[] e = new Vector3d[3] {
                        new Vector3d(mesh.DualVertexPos, d2) -
                        new Vector3d(mesh.DualVertexPos, d1),
                        new Vector3d(mesh.DualVertexPos, d0) -
                        new Vector3d(mesh.DualVertexPos, d2),
                        new Vector3d(mesh.DualVertexPos, d1) -
                        new Vector3d(mesh.DualVertexPos, d0)
                    };
                    Vector3d[] normals = new Vector3d[3] {
                        new Vector3d(mesh.FaceNormal, d0),
                        new Vector3d(mesh.FaceNormal, d1),
                        new Vector3d(mesh.FaceNormal, d2)
                    };

                    // N-T-B coordinate system per face
                    Vector3d t = e[0].Normalize();
                    Vector3d n = e[0].Cross(e[1]).Normalize();
                    Vector3d b = n.Cross(t).Normalize();

                    // Estimate curvature based on variation of normals
                    // along edges
                    double[] m = new double[3] {
                        0, 0, 0
                    };
                    double[][] w = new double[3][];
                    for (int k = 0; k < 3; ++k)
                    {
                        w[k] = new double[3];
                    }
                    for (int k = 0; k < 3; ++k)
                    {
                        double u = e[k].Dot(t);
                        double v = e[k].Dot(b);
                        w[0][0] += u * u;
                        w[0][1] += u * v;
                        w[2][2] += v * v;
                        Vector3d dn  = normals[(k + 2) % 3] - normals[(k + 1) % 3];
                        double   dnu = dn.Dot(t);
                        double   dnv = dn.Dot(b);
                        m[0] += dnu * u;
                        m[1] += dnu * v + dnv * u;
                        m[2] += dnv * v;
                    }
                    w[1][1] = w[0][0] + w[2][2];
                    w[1][2] = w[0][1];

                    // Least squares solution
                    double[] diag = new double[3];
                    if (!ldltdc(w, diag, 3))
                    {
                        System.Console.WriteLine("ldltdc failed!\n");
                        continue;
                    }
                    ldltsl(w, diag, m, ref m, 3);

                    // Push it back out to the dual vertices
                    double g1 = 0, g12 = 0, g2 = 0;
                    proj_curv(t, b, m[0], m[1], m[2],
                              uu, vv, ref g1, ref g12, ref g2);
                    double wt = dual_cornerareas[i][j] / dual_pointareas[i];
                    dual_curva[i] += wt * g1;
                    dual_curvb[i] += wt * g12;
                    dual_curvc[i] += wt * g2;
                }

                // Compute principal directions and curvatures at each dual vertex
                DiagonalizeCurvature(uu, vv,
                                     dual_curva[i], dual_curvb[i], dual_curvc[i],
                                     nn, ref fpDir1[i], ref fpDir2[i],
                                     ref fcurv1[i], ref fcurv2[i]);
            }
            System.Console.WriteLine("Done.\n");
        }
        // Compute the principle curvatures and directions for a specific face.
        public void ObtainPerFacePCurAndDirs()
        {
            // Compute curvature per-face
            int nf = mesh.FaceCount, nv = mesh.VertexCount;

            for (int i = 0; i < nf; i++)
            {
                // Edges
                int        c  = i * 3;
                int        d0 = mesh.FaceIndex[c] * 3;
                int        d1 = mesh.FaceIndex[c + 1] * 3;
                int        d2 = mesh.FaceIndex[c + 2] * 3;
                Vector3d[] e  = new Vector3d[3] {
                    new Vector3d(mesh.VertexPos, d2) - new Vector3d(mesh.VertexPos, d1),
                    new Vector3d(mesh.VertexPos, d0) - new Vector3d(mesh.VertexPos, d2),
                    new Vector3d(mesh.VertexPos, d1) - new Vector3d(mesh.VertexPos, d0)
                };
                Vector3d[] normals = new Vector3d[3] {
                    new Vector3d(mesh.VertexNormal, d0),
                    new Vector3d(mesh.VertexNormal, d1),
                    new Vector3d(mesh.VertexNormal, d2)
                };

                // N-T-B coordinate system per face
                Vector3d t = e[0].Normalize();
                Vector3d n = e[0].Cross(e[1]);
                Vector3d b = n.Cross(t).Normalize();

                // Estimate curvature based on variation of normals
                // along edges
                double[] m = new double[3] {
                    0, 0, 0
                };
                double[][] w = new double[3][];
                for (int j = 0; j < 3; ++j)
                {
                    w[j] = new double[3];
                }
                for (int j = 0; j < 3; ++j)
                {
                    double u = e[j].Dot(t);
                    double v = e[j].Dot(b);
                    w[0][0] += u * u;
                    w[0][1] += u * v;
                    w[2][2] += v * v;
                    Vector3d dn  = normals[(j + 2) % 3] - normals[(j + 1) % 3];
                    double   dnu = dn.Dot(t);
                    double   dnv = dn.Dot(b);
                    m[0] += dnu * u;
                    m[1] += dnu * v + dnv * u;
                    m[2] += dnv * v;
                }
                w[1][1] = w[0][0] + w[2][2];
                w[1][2] = w[0][1];

                // Least squares solution
                double[] diag = new double[3];
                if (!ldltdc(w, diag, 3))
                {
                    System.Console.WriteLine("ldltdc failed!\n");
                    continue;
                }
                ldltsl(w, diag, m, ref m, 3);

                // compute the principle curvatures on face i.
                Vector3d fn = new Vector3d(mesh.FaceNormal, i * 3);
                DiagonalizeCurvature(t, b,
                                     m[0], m[1], m[2],
                                     fn, ref fpDir1[i], ref fpDir2[i],
                                     ref fcurv1[i], ref fcurv2[i]);
            }
            System.Console.WriteLine("Done.\n");
        }
        // Compute the principle curvatures and directions for a specific vertex
        // this is due to the sence that the vertex position may be changed on
        // the fly for some geometry filtering algorithms.
        public void ObtainCurvDirAt(int index, ref Vector3d e1, ref Vector3d e2, ref double k1, ref double k2)
        {
            // Initialize curvature tensor matrix elements.
            double aa = 0;
            double bb = 0;
            double cc = 0;

            Vector3d ni    = new Vector3d(mesh.VertexNormal, index * 3);
            Vector3d pdir1 = localvu[index];
            Vector3d pdir2 = localvv[index];

            // Compute curvature per-face
            foreach (int f in mesh.AdjVF[index])
            {
                // Edges
                int        c  = f * 3;
                int        d0 = mesh.FaceIndex[c] * 3;
                int        d1 = mesh.FaceIndex[c + 1] * 3;
                int        d2 = mesh.FaceIndex[c + 2] * 3;
                Vector3d[] e  = new Vector3d[3] {
                    new Vector3d(mesh.VertexPos, d2) - new Vector3d(mesh.VertexPos, d1),
                    new Vector3d(mesh.VertexPos, d0) - new Vector3d(mesh.VertexPos, d2),
                    new Vector3d(mesh.VertexPos, d1) - new Vector3d(mesh.VertexPos, d0)
                };
                Vector3d[] normals = new Vector3d[3] {
                    new Vector3d(mesh.VertexNormal, d0),
                    new Vector3d(mesh.VertexNormal, d1),
                    new Vector3d(mesh.VertexNormal, d2)
                };

                // N-T-B coordinate system per face
                Vector3d t = e[0].Normalize();
                Vector3d n = e[0].Cross(e[1]);
                Vector3d b = n.Cross(t).Normalize();

                // Estimate curvature based on variation of normals
                // along edges
                double[] m = new double[3] {
                    0, 0, 0
                };
                double[][] w = new double[3][];
                for (int jj = 0; jj < 3; ++jj)
                {
                    w[jj] = new double[3];
                }
                for (int jj = 0; jj < 3; ++jj)
                {
                    double u = e[jj].Dot(t);
                    double v = e[jj].Dot(b);
                    w[0][0] += u * u;
                    w[0][1] += u * v;
                    w[2][2] += v * v;
                    Vector3d dn  = normals[(jj + 2) % 3] - normals[(jj + 1) % 3];
                    double   dnu = dn.Dot(t);
                    double   dnv = dn.Dot(b);
                    m[0] += dnu * u;
                    m[1] += dnu * v + dnv * u;
                    m[2] += dnv * v;
                }
                w[1][1] = w[0][0] + w[2][2];
                w[1][2] = w[0][1];

                // Least squares solution
                double[] diag = new double[3];
                if (!ldltdc(w, diag, 3))
                {
                    System.Console.WriteLine("ldltdc failed!\n");
                    continue;
                }
                ldltsl(w, diag, m, ref m, 3);

                // Push it back out to the vertices
                for (int jj = 0; jj < 3; jj++)
                {
                    int pj = mesh.FaceIndex[c + jj];

                    if (pj != index)
                    {
                        continue;
                    }

                    double c1 = 0, c12 = 0, c2 = 0;
                    proj_curv(t, b, m[0], m[1], m[2],
                              pdir1, pdir2,
                              ref c1, ref c12, ref c2);
                    double wt = cornerareas[f][jj] / pointareas[pj];
                    aa += wt * c1;
                    bb += wt * c12;
                    cc += wt * c2;
                }
            }

            // Compute principal directions and curvatures at each vertex
            DiagonalizeCurvature(pdir1, pdir2,
                                 aa, bb, cc,
                                 ni, ref e1, ref e2, ref k1, ref k2
                                 );

            System.Console.WriteLine("Done.\n");
        }