public void Drag(Vector2d pt)
        {
            edPt = pt;
            edVec = MapToSphere(pt);

            double epsilon = 1.0e-5;
            Vector3d prep = stVec.Cross(edVec);

            if (prep.Length() > epsilon)
                quat = new Vector4d(prep, stVec.Dot(edVec));
            else
                quat = new Vector4d();
        }
        public Quaternion(Matrix3d m)
        {
            double T = 1.0 + m.Trace();
            double S, W, X, Y, Z;

            if (T > eps)
            {
                S = Math.Sqrt(T) * 2.0;
                X = (m[5] - m[7]) / S;
                Y = (m[6] - m[2]) / S;
                Z = (m[1] - m[3]) / S;
                W = 0.25 * S;
            }
            else if (m[0] > m[4] && m[0] > m[8])
            {
                S = Math.Sqrt(1.0 + m[0] - m[4] - m[8]) * 2.0;
                X = 0.25 * S;
                Y = (m[1] + m[3]) / S;
                Z = (m[6] + m[2]) / S;
                W = (m[5] - m[7]) / S;
            }
            else if (m[4] > m[8])
            {
                S = Math.Sqrt(1.0 + m[4] - m[0] - m[8]) * 2;
                X = (m[1] + m[3]) / S;
                Y = 0.25 * S;
                Z = (m[5] + m[7]) / S;
                W = (m[6] - m[2]) / S;
            }
            else
            {
                S = Math.Sqrt(1.0 + m[8] - m[0] - m[4]) * 2;
                X = (m[6] + m[2]) / S;
                Y = (m[5] + m[7]) / S;
                Z = 0.25 * S;
                W = (m[1] - m[3]) / S;
            }

            this.s = W;
            this.v = new Vector3d(X, Y, Z);
        }
 public double Dot(Vector3d v)
 {
     return x*v.x + y*v.y + z*v.z;
 }
 public double AverageFaceArea()
 {
     double tot = 0;
     for (int i = 0, j = 0; i < faceCount; i++, j += 3)
     {
         Vector3d v1 = new Vector3d(VertexPos, faceIndex[j] * 3);
         Vector3d v2 = new Vector3d(VertexPos, faceIndex[j + 1] * 3);
         Vector3d v3 = new Vector3d(VertexPos, faceIndex[j + 2] * 3);
         tot += ((v2 - v1).Cross(v3 - v1)).Length() / 2.0;
     }
     return (tot / faceCount);
 }
 public Vector3d Cross(Vector3d v)
 {
     return new Vector3d(
         y * v.z - v.y * z,
         z * v.x - v.z * x,
         x * v.y - v.x * y
         );
 }
 private double Face_wij(int i, int j)
 {
     double[] normal = this.new_normals == null ? mesh.FaceNormal : this.new_normals;
     int b = i * 3, c = j * 3;
     Vector3d ni = new Vector3d(normal, b);
     Vector3d nj = new Vector3d(normal, c);
     Vector3d vi = new Vector3d(mesh.DualVertexPos, b);
     Vector3d vj = new Vector3d(mesh.DualVertexPos, c);
     Vector3d eij = (vj - vi).Normalize();
     double d = (nj - ni).Length();
     double e = Math.Abs((ni).Dot(eij));
     return (1+e)*d;
 }
 /*s is the \sigma*/
 private void FilterFaceNormals(double s, int iterations)
 {
     // -- precompute normals based on NII, as a smoothing step --
     int n = mesh.FaceCount; double denominator  = s*s*2;
     old_normals = mesh.FaceNormal.Clone() as double[];
     new_normals = new double[n*3];
     for (int k = 0; k < iterations; ++k)
     {
         for (int i = 0; i < n; ++i)
         {
             // -- get two-ring neighbors
             Set<int> nbrs = this.neighbors[i]; nbrs.Remove(i);
             int count = nbrs.Count, b = i * 3;
             Vector3d ni = new Vector3d(mesh.FaceNormal, b);
             Vector3d nn = new Vector3d();
             foreach (int f in nbrs)
             {
                 Vector3d nj = new Vector3d(mesh.FaceNormal, f * 3);
                 double d = (ni - nj).Length();
                 double w = Math.Exp(-d * d / denominator);
                 nn = nn + w * nj;
             }
             nn = nn.Normalize();
             new_normals[b] = nn.x;
             new_normals[b + 1] = nn.y;
             new_normals[b + 2] = nn.z;
         }
         //mesh.FaceNormal = new_normals.Clone() as double[];
     }
 }
 public void ComputeFaceNormal()
 {
     for (int i=0,j=0; i<faceCount; i++,j+=3)
     {
         int c1 = faceIndex[j] * 3;
         int c2 = faceIndex[j+1] * 3;
         int c3 = faceIndex[j+2] * 3;
         Vector3d v1 = new Vector3d(vertexPos, c1);
         Vector3d v2 = new Vector3d(vertexPos, c2);
         Vector3d v3 = new Vector3d(vertexPos, c3);
         Vector3d normal = (v2-v1).Cross(v3-v1).Normalize();
         faceNormal[j] = normal.x;
         faceNormal[j+1] = normal.y;
         faceNormal[j+2] = normal.z;
     }
 }
        private void ApplyHarmonicSolver_Cholmod()
        {
            // --- build up lefthand side matrix A
            int vn = mesh.VertexCount;
            int fn = mesh.FaceCount;
            int bn = this.sourceVertices.Count + this.sinkVertices.Count;
            int m = vn+bn;

            if (this.sparseSolver != null) this.sparseSolver.Release();
            this.sparseSolver = new CholmodSolver();

            this.sparseSolver.InitializeMatrixA(m, vn);
            for (int i = 0, j = 0; i < fn; i++, j += 3)
            {
                int c1 = mesh.FaceIndex[j];
                int c2 = mesh.FaceIndex[j + 1];
                int c3 = mesh.FaceIndex[j + 2];
                Vector3d v1 = new Vector3d(mesh.VertexPos, c1 * 3);
                Vector3d v2 = new Vector3d(mesh.VertexPos, c2 * 3);
                Vector3d v3 = new Vector3d(mesh.VertexPos, c3 * 3);
                double cot1 = (v2 - v1).Dot(v3 - v1) / (v2 - v1).Cross(v3 - v1).Length();
                double cot2 = (v3 - v2).Dot(v1 - v2) / (v3 - v2).Cross(v1 - v2).Length();
                double cot3 = (v1 - v3).Dot(v2 - v3) / (v1 - v3).Cross(v2 - v3).Length();
                sparseSolver.Add_Coef(c2, c2, -cot1); sparseSolver.Add_Coef(c2, c3, cot1);
                sparseSolver.Add_Coef(c3, c3, -cot1); sparseSolver.Add_Coef(c3, c2, cot1);
                sparseSolver.Add_Coef(c3, c3, -cot2); sparseSolver.Add_Coef(c3, c1, cot2);
                sparseSolver.Add_Coef(c1, c1, -cot2); sparseSolver.Add_Coef(c1, c3, cot2);
                sparseSolver.Add_Coef(c1, c1, -cot3); sparseSolver.Add_Coef(c1, c2, cot3);
                sparseSolver.Add_Coef(c2, c2, -cot3); sparseSolver.Add_Coef(c2, c1, cot3);
            }

            // add positional weights
            int index = 0;
            foreach (int v in sourceVertices)
            {
                sparseSolver.Add_Coef(vn + index, v, 1.0 * ConstantWeight);
                ++index;
            }
            foreach (int v in sinkVertices)
            {
                sparseSolver.Add_Coef(vn + index, v, 1.0 * ConstantWeight);
                ++index;
            }

            if (!opt.UseAtb) m = vn;

            double[] b = new double[m];
            double[] x = new double[vn];

            // -- assign values to the right hand side b,-- Ax=b
            if (opt.UseAtb)
            {
                for (int j = 0; j < b.Length; j++) b[j] = 0;
                int count = 0;
                for (int j = 0; j < sourceVertices.Count; ++j, ++count)
                    b[vn + j] = 1.0 * ConstantWeight;
                for (int j = 0; j < sinkVertices.Count; ++j)
                    b[vn + count + j] = 0.0;
            }
            else // set by user..
            {
                foreach (int v in this.sourceVertices)
                    b[v] = 1.0 * ConstantWeight * ConstantWeight;
            }

            fixed (double* _b = b)
            {
                sparseSolver.InitializeMatrixB(_b, m, 1);
            }
            sparseSolver.InitializeSolver();
            sparseSolver.SetFinalPack(0);
            sparseSolver.Factorize();

            fixed (double* _x = x)
            {
                sparseSolver.Linear_Solve(_x, !opt.UseAtb);
            }

            this.harmonicField = x;
        }
 public void Click(Vector2d pt, MotionType type)
 {
     this.stPt = pt;
     this.stVec = MapToSphere(pt);
     this.type = type;
 }
 public Vector4d(Vector3d v)
 {
     this.x = v.x;
     this.y = v.y;
     this.z = v.z;
     this.w = 0;
 }
 public Vector3d MinCoord()
 {
     Vector3d minCoord = new Vector3d(double.MaxValue, double.MaxValue, double.MaxValue);
     for (int i=0,j=0; i<vertexCount; i++,j+=3)
     {
         Vector3d v = new Vector3d(vertexPos, j);
         minCoord = Vector3d.Min(minCoord, v);
     }
     return minCoord;
 }
 public double Volume()
 {
     double totVolume = 0;
     for (int i = 0, j = 0; i < faceCount; i++, j += 3)
     {
         int c1 = faceIndex[j] * 3;
         int c2 = faceIndex[j + 1] * 3;
         int c3 = faceIndex[j + 2] * 3;
         Vector3d a = new Vector3d(vertexPos, c1);
         Vector3d b = new Vector3d(vertexPos, c2);
         Vector3d c = new Vector3d(vertexPos, c3);
         totVolume +=
             a.x * b.y * c.z -
             a.x * b.z * c.y -
             a.y * b.x * c.z +
             a.y * b.z * c.x +
             a.z * b.x * c.y -
             a.z * b.y * c.x;
     }
     return totVolume;
 }
 public void ComputeVertexNormal()
 {
     Array.Clear(vertexNormal, 0, vertexNormal.Length);
     for (int i=0,j=0; i<faceCount; i++,j+=3)
     {
         int c1 = faceIndex[j] * 3;
         int c2 = faceIndex[j+1] * 3;
         int c3 = faceIndex[j+2] * 3;
         vertexNormal[c1] += faceNormal[j];
         vertexNormal[c2] += faceNormal[j];
         vertexNormal[c3] += faceNormal[j];
         vertexNormal[c1+1] += faceNormal[j+1];
         vertexNormal[c2+1] += faceNormal[j+1];
         vertexNormal[c3+1] += faceNormal[j+1];
         vertexNormal[c1+2] += faceNormal[j+2];
         vertexNormal[c2+2] += faceNormal[j+2];
         vertexNormal[c3+2] += faceNormal[j+2];
     }
     for (int i=0,j=0; i<vertexCount; i++,j+=3)
     {
         Vector3d n = new Vector3d(vertexNormal, j);
         n = n.Normalize();
         vertexNormal[j] = n.x;
         vertexNormal[j+1] = n.y;
         vertexNormal[j+2] = n.z;
     }
 }
        public void ComputeNormals2Ring()
        {
            int nf = faceCount;
            Vector3d[] vnormals = new Vector3d[VertexCount];
            for (int i = 0, j = 0; i < nf; i++, j += 3)
            {
                int v0 = faceIndex[j];
                int v1 = faceIndex[j + 1];
                int v2 = faceIndex[j + 2];
                Vector3d p0 = new Vector3d(vertexPos, v0 * 3);
                Vector3d p1 = new Vector3d(vertexPos, v1 * 3);
                Vector3d p2 = new Vector3d(vertexPos, v2 * 3);
                Vector3d a = p0 - p1, b = p1 - p2, c = p2 - p0;
                double l2a = a.Dot(a), l2b = b.Dot(b), l2c = c.Dot(c);
                Vector3d facenormal = a.Cross(b);

                // assign face normals
                facenormal = facenormal.Normalize();
                faceNormal[j] = facenormal.x;
                faceNormal[j + 1] = facenormal.y;
                faceNormal[j + 2] = facenormal.z;
            }
            for (int i = 0, j = 0; i < vertexCount; ++i, j += 3)
            {
                Set<int> fset = new Set<int>();
                foreach (int adj in adjVV[i])
                {
                    foreach (int f in adjVF[adj])
                    {
                        fset.Add(f);
                    }
                }
                vnormals[i] = new Vector3d();
                foreach (int f in fset)
                {
                    Vector3d fnormal = new Vector3d(faceNormal, f * 3);
                    double s = ComputeFaceArea(f);
                    vnormals[i] = vnormals[i] + s*fnormal;
                }
                vnormals[i] = vnormals[i].Normalize();
                vertexNormal[j] = vnormals[i].x;
                vertexNormal[j + 1] = vnormals[i].y;
                vertexNormal[j + 2] = vnormals[i].z;
            }
        }
        // compute both face normals and vertex normals, from trimesh2.
        public void ComputeNormals()
        {
            int nf = faceCount;
            Vector3d[] vnormals = new Vector3d[VertexCount];
            for (int i = 0, j = 0; i < nf; i++, j+=3) {
                int v0 = faceIndex[j];
                int v1 = faceIndex[j+1];
                int v2 = faceIndex[j+2];
                Vector3d p0 = new Vector3d(vertexPos, v0*3);
                Vector3d p1 = new Vector3d(vertexPos, v1*3);
                Vector3d p2 = new Vector3d(vertexPos, v2*3);
                Vector3d a = p0-p1, b = p1-p2, c = p2-p0;
                double l2a = a.Dot(a), l2b = b.Dot(b), l2c = c.Dot(c);
                Vector3d facenormal = a.Cross(b);

                // assign vertex normals
                vnormals[v0] = vnormals[v0] + facenormal * (1.0 / (l2a * l2c));
                vnormals[v1] = vnormals[v1] + facenormal * (1.0 / (l2b * l2a));
                vnormals[v2] = vnormals[v2] + facenormal * (1.0 / (l2c * l2b));

                // assign face normals
                facenormal = facenormal.Normalize();
                faceNormal[j] = facenormal.x;
                faceNormal[j+1] = facenormal.y;
                faceNormal[j+2] = facenormal.z;
            }
            for (int i = 0, j = 0; i < vertexCount; ++i, j += 3) {
                vnormals[i] = vnormals[i].Normalize();
                vertexNormal[j] = vnormals[i].x;
                vertexNormal[j+1] = vnormals[i].y;
                vertexNormal[j+2] = vnormals[i].z;
            }
        }
 public Matrix3d OuterCross(Vector3d v)
 {
     Matrix3d m = new Matrix3d();
     m[0, 0] = x * v.x;
     m[0, 1] = x * v.y;
     m[0, 2] = x * v.z;
     m[1, 0] = y * v.x;
     m[1, 1] = y * v.y;
     m[1, 2] = y * v.z;
     m[2, 0] = z * v.x;
     m[2, 1] = z * v.y;
     m[2, 2] = z * v.z;
     return m;
 }
        private void LocateFacesIsoPosition(double[] f, double[] isovals)
        {
            if (f == null) throw new ArgumentException();

            // initialize isofaces
            this.isofaces = new IsoFaceRec[mesh.FaceCount];
            for (int i = 0; i < mesh.FaceCount; ++i)
                this.isofaces[i] = new IsoFaceRec();
            for (int i = 0; i < isovalues.Length; ++i)
            {
                double v = isovals[i];
                for (int k = 0, m = 0; k < this.mesh.FaceCount; ++k, m += 3)
                {
                    int c1 = this.mesh.FaceIndex[m];
                    int c2 = this.mesh.FaceIndex[m + 1];
                    int c3 = this.mesh.FaceIndex[m + 2];
                    PQPairs r = null;
                    if ((f[c1] <= v && f[c2] >= v) || (f[c2] <= v && f[c1] >= v))
                    {
                        if (r == null) { r = new PQPairs(); r.findex = k; }
                        if (r.e1 == -1)
                        {
                            r.e1 = 0; r.ratio1 = (v - f[c1]) / (f[c2] - f[c1]);
                        }
                        else
                        {
                            r.e2 = 0; r.ratio2 = (v - f[c1]) / (f[c2] - f[c1]);
                        }
                    }
                    if ((f[c2] <= v && f[c3] >= v) || (f[c3] <= v && f[c2] >= v))
                    {
                        if (r == null) { r = new PQPairs(); r.findex = k; }
                        if (r.e1 == -1)
                        {
                            r.e1 = 1; r.ratio1 = (v - f[c2]) / (f[c3] - f[c2]);
                        }
                        else
                        {
                            r.e2 = 1; r.ratio2 = (v - f[c2]) / (f[c3] - f[c2]);
                        }
                    }
                    if ((f[c3] <= v && f[c1] >= v) || (f[c1] <= v && f[c3] >= v))
                    {
                        if (r == null) { r = new PQPairs(); r.findex = k; }
                        if (r.e1 == -1)
                        {
                            r.e1 = 2; r.ratio1 = (v - f[c3]) / (f[c1] - f[c3]);
                        }
                        else
                        {
                            r.e2 = 2; r.ratio2 = (v - f[c3]) / (f[c1] - f[c3]);
                        }
                    }
                    if (r == null) continue;
                    if (r.e1 == -1 || r.e2 == -1) continue;

                    r.isovalue = v;
                    r.lindex = i;

                    Vector3d v1 = new Vector3d(mesh.VertexPos, c1 * 3);
                    Vector3d v2 = new Vector3d(mesh.VertexPos, c2 * 3);
                    Vector3d v3 = new Vector3d(mesh.VertexPos, c3 * 3);
                    Vector3d n1 = new Vector3d(mesh.FaceNormal, k * 3);
                    Vector3d p = new Vector3d(), q = new Vector3d();
                    switch (r.e1)
                    {
                        case 0: p = v2 * r.ratio1 + v1 * (1.0 - r.ratio1); break;
                        case 1: p = v3 * r.ratio1 + v2 * (1.0 - r.ratio1); break;
                        case 2: p = v1 * r.ratio1 + v3 * (1.0 - r.ratio1); break;
                    }
                    switch (r.e2)
                    {
                        case 0: q = v2 * r.ratio2 + v1 * (1.0 - r.ratio2); break;
                        case 1: q = v3 * r.ratio2 + v2 * (1.0 - r.ratio2); break;
                        case 2: q = v1 * r.ratio2 + v3 * (1.0 - r.ratio2); break;
                    }
                    r.n = n1; r.p = p; r.q = q;
                    isofaces[k].pqPairs.Add(r);
                    isofaces[k].index = k;
                    isofaces[k].valid = true;
                }
            }
        }
 public Vector3d Rotate(Vector3d axis, double cos, double sin)
 {
     return this * cos + (axis.Cross(this)) * sin +
         axis * ((1.0 - cos) * (axis.Dot(this)));
 }
 public double ComputeFaceArea(int fIndex)
 {
     int b = fIndex * 3;
     Vector3d v1 = new Vector3d(VertexPos, faceIndex[b] * 3);
     Vector3d v2 = new Vector3d(VertexPos, faceIndex[b+1] * 3);
     Vector3d v3 = new Vector3d(VertexPos, faceIndex[b+2] * 3);
     return ((v2-v1).Cross(v3-v1)).Length() / 2.0;
 }
 public Vector4d(Vector3d v, double w)
 {
     this.x = v.x;
     this.y = v.y;
     this.z = v.z;
     this.w = w;
 }
 public static void Print3DText(Vector3d pos, string s)
 {
     FormMain f = FormMain.ActiveForm as FormMain;
     if (f != null)
         f.Print3DText(pos, s);
 }
 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;
 }
 public Quaternion(double s, Vector3d v)
 {
     this.s = s;
     this.v = v;
 }
 private double Face_dij(int i, int j)
 {
     Vector3d ci = new Vector3d(mesh.DualVertexPos, i * 3);
     Vector3d cj = new Vector3d(mesh.DualVertexPos, j * 3);
     double d = (cj - ci).Length();
     return d;
 }
 public static Vector3d Max(Vector3d v1, Vector3d v2)
 {
     return new Vector3d( (v1.x > v2.x) ? v1.x : v2.x,
         (v1.y > v2.y) ? v1.y : v2.y,
         (v1.z > v2.z) ? v1.z : v2.z );
 }
 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 static Vector3d Min(Vector3d v1, Vector3d v2)
 {
     return new Vector3d( (v1.x < v2.x) ? v1.x : v2.x,
         (v1.y < v2.y) ? v1.y : v2.y,
         (v1.z < v2.z) ? v1.z : v2.z );
 }
 private bool IsTheSamePosition(Vector3d s, Vector3d t)
 {
     if ((s - t).Length() < 1e-08)
         return true;
     return false;
 }
 public void Print3DText(Vector3d pos, string s)
 {
     GL.glRasterPos3d(pos.x, pos.y, pos.z);
     GL.glPushAttrib(GL.GL_LIST_BIT);					// Pushes The Display List Bits
     GL.glListBase(this.meshView1.fontBase);				// Sets The Base Character to 32
     GL.glCallLists(s.Length, GL.GL_UNSIGNED_SHORT, s);	// Draws The Display List Text
     GL.glPopAttrib();									// Pops The Display List Bits
 }