/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param> protected override void SolveInstance(IGH_DataAccess DA) { HeGraph3d graph = null; double layerHeigth = 0; double length = 0; if (!DA.GetData(0, ref graph)) { return; } if (!DA.GetData(1, ref layerHeigth)) { return; } if (!DA.GetData(2, ref length)) { return; } var f = new DataTree <Plane>(); var tparams = new DataTree <double>(); List <GH_Path> branches = new List <GH_Path>(); for (int i = 0; i < graph.Edges.Count; i++) { branches.Add(new GH_Path(i)); } for (int i = 0; i < graph.Vertices.Count; i++) { for (int j = 0; j < graph.Vertices[i].ConnectedVertices.ToList().Count; j++) { var v0 = graph.Vertices[i].Position; var v1 = graph.Vertices[i].ConnectedVertices.ToList()[j].Position; var eVec = (v0 - v1).Unit; var dist = v0.DistanceTo(v1); var zUnit = new Vec3d(1, 0, 0); var n = Vec3d.Cross(eVec, zUnit).Unit; var bn = Vec3d.Cross(eVec, n).Unit; var bbn = Vec3d.Cross(eVec, bn).Unit; var frames = new List <Rhino.Geometry.Plane>(); var edgeId = graph.Vertices[i].FindHalfedgeTo(graph.Vertices[i].ConnectedVertices.ToList()[j]).Index >> 1; var branch = new GH_Path(edgeId); int cnt = 0; double l = 0; do { Point3d pt = v0 - eVec * cnt * layerHeigth; l += v0.DistanceTo((Vec3d)pt); var frame = new Rhino.Geometry.Plane((Point3d)pt, (Vector3d)bn, (Vector3d)bbn); frames.Add(frame); cnt++; }while (length > l); f.AddRange(frames, branch); } } for (int i = 0; i < graph.Edges.Count; i++) { var count = f.Branch(i).Count; var t0 = 1.0 / (double)count; for (int j = 0; j < count; j++) { tparams.Add((j * t0), new GH_Path(i)); } } DA.SetDataTree(0, f); DA.SetDataTree(1, tparams); }
/// <summary> /// Applies this rotation to the given vector. /// </summary> /// <param name="vector"></param> /// <returns></returns> public Vector3d Apply(Vector3d vector) { return(_cosAngle * vector + _sinAngle * Vector3d.Cross(_axis, vector) + Vector3d.Dot(_axis, vector) * (1.0 - _cosAngle) * _axis); }
/// <summary> /// Performs a singular value decomposition of the given matrix A. /// Returns the rank of A. /// Note that this implementation ensures that U and V are proper rotations (i.e. no reflections). /// </summary> public static int SingularValue(ref Matrix3d A, out Matrix3d U, out Vector3d sigma, out Matrix3d V, double epsilon = D.ZeroTolerance) { // U -> proper rotation (no reflection) // sigma -> singular values // V -> proper rotation (no reflection) // impl ref // https://www.math.ucla.edu/~jteran/papers/ITF04.pdf var AtA = A.ApplyTranspose(ref A); EigenSymmetricPSD(AtA, out V, out sigma, epsilon); // handle reflection in V if (V.Determinant < 0.0) { V.Column2 *= -1.0; } // U = A V inv(sigma) // must handle cases where singular values are zero if (sigma.X < epsilon) { // all zero singular values // | 0 - - | // Σ = | - 0 - | // | - - 0 | sigma.X = sigma.Y = sigma.Z = 0.0; U = Identity; return(0); } else if (sigma.Y < epsilon) { // one non-zero singular value // | x - - | // Σ = | - 0 - | // | - - 0 | sigma.X = Math.Sqrt(sigma.X); sigma.Y = sigma.Z = 0.0; var u0 = A.Apply(V.Column0 / sigma.X); var u1 = u0.Y > 0.0 ? u0.CrossX : u0.CrossY; u1.Unitize(); U = new Matrix3d(u0, u1, Vector3d.Cross(u0, u1)); return(1); } else if (sigma.Z < epsilon) { // two non-zero singular values // | x - - | // Σ = | - y - | // | - - 0 | sigma.X = Math.Sqrt(sigma.X); sigma.Y = Math.Sqrt(sigma.Y); sigma.Z = 0.0; var u0 = A.Apply(V.Column0 / sigma.X); var u1 = A.Apply(V.Column1 / sigma.Y); U = new Matrix3d(u0, u1, Vector3d.Cross(u0, u1)); return(2); } // all non-zero singular values // | x - - | // Σ = | - y - | // | - - z | sigma.X = Math.Sqrt(sigma.X); sigma.Y = Math.Sqrt(sigma.Y); sigma.Z = Math.Sqrt(sigma.Z); U = new Matrix3d( A.Apply(V.Column0 / sigma.X), A.Apply(V.Column1 / sigma.Y), A.Apply(V.Column2 / sigma.Z)); // handle reflection in U if (U.Determinant < 0.0) { U.Column2 *= -1.0; sigma.Z *= -1.0; } return(3); }
/// <summary> /// Assumes the given vectors are orthonormal. /// </summary> /// <param name="z"></param> /// <param name="x"></param> private void SetOrthoZX(Vector3d z, Vector3d x) { _x = x; _y = Vector3d.Cross(z, x); _z = z; }
/// <summary> /// Assumes the given vectors are orthonormal. /// </summary> /// <param name="y"></param> /// <param name="z"></param> private void SetOrthoYZ(Vector3d y, Vector3d z) { _x = Vector3d.Cross(y, z); _y = y; _z = z; }
/// <summary> /// Assumes the given vectors are orthonormal. /// </summary> /// <param name="x"></param> /// <param name="y"></param> private void SetOrthoXY(Vector3d x, Vector3d y) { _x = x; _y = y; _z = Vector3d.Cross(x, y); }