/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object can be used to retrieve data from input parameters and /// to store data in output parameters.</param> protected override void SolveInstance(IGH_DataAccess DA) { PlanktonMesh mesh = null; DA.GetData(0, ref mesh); DA.SetData(0, mesh.Dual()); }
public void CanDualCube() { // Create a simple cube PlanktonMesh pMesh = new PlanktonMesh(); pMesh.Vertices.Add(-0.5, -0.5, 0.5); pMesh.Vertices.Add(-0.5, -0.5, -0.5); pMesh.Vertices.Add(-0.5, 0.5, -0.5); pMesh.Vertices.Add(-0.5, 0.5, 0.5); pMesh.Vertices.Add(0.5, -0.5, 0.5); pMesh.Vertices.Add(0.5, -0.5, -0.5); pMesh.Vertices.Add(0.5, 0.5, -0.5); pMesh.Vertices.Add(0.5, 0.5, 0.5); pMesh.Faces.AddFace(3, 2, 1, 0); pMesh.Faces.AddFace(1, 5, 4, 0); pMesh.Faces.AddFace(2, 6, 5, 1); pMesh.Faces.AddFace(7, 6, 2, 3); pMesh.Faces.AddFace(4, 7, 3, 0); pMesh.Faces.AddFace(5, 6, 7, 4); var dual = pMesh.Dual(); Assert.AreEqual(new int[] { 2, 3, 0, 1 }, dual.Vertices.GetVertexFaces(0)); }
private void _applyOperation(Token token) { switch (token.Operation) { case Operation.kis: _pMesh = _pMesh.Kis(); break; case Operation.ambo: _pMesh = _pMesh.Ambo(); break; case Operation.gyro: break; case Operation.dual: _pMesh = _pMesh.Dual(); break; case Operation.reflect: break; case Operation.expand: _pMesh = _pMesh.Expand(); break; case Operation.bevel: _pMesh = _pMesh.Bevel(); break; case Operation.ortho: _pMesh = _pMesh.Ortho(); break; case Operation.meta: _pMesh = _pMesh.Meta(); break; case Operation.truncate: _pMesh = _pMesh.Truncate(); break; case Operation.@join: _pMesh = _pMesh.Join(); break; case Operation.split: break; case Operation.propeller: _pMesh = _pMesh.Propeller(); break; case Operation.flatten: break; case Operation.loft: _pMesh = _pMesh.Loft(); break; case Operation.needle: _pMesh = _pMesh.Needle(); break; case Operation.zip: _pMesh = _pMesh.Zip(); break; case Operation.quinto: _pMesh = _pMesh.Quinto(); break; case Operation.none: break; default: throw new ArgumentOutOfRangeException(); } }
public static PlanktonMesh Needle(this PlanktonMesh pMesh) { return(pMesh.Dual().Kis()); }
protected override void SolveInstance(IGH_DataAccess DA) { PlanktonMesh P1 = null; if (!DA.GetData(0, ref P1)) { return; } List <double> RL = new List <double>(); if (!DA.GetDataList(1, RL)) { return; } bool D = false; if (!DA.GetData(2, ref D)) { return; } if (D) { P1 = P1.Dual(); } PlanktonMesh P2 = new PlanktonMesh(); int vcount = P1.Vertices.Count; List <Vector3d> Normals = new List <Vector3d>(); List <int> Outer = new List <int>(); List <int> Inner = new List <int>(); List <int> Elbow = new List <int>(); for (int i = 0; i < vcount; i++) { Point3d Vertex = P1.Vertices[i].ToPoint3d(); Vector3d Normal = new Vector3d(); double AvgAngle = 0; double R = 0; if (RL.Count == 1) { R = RL[0]; } else { R = RL[i]; } int[] OutEdges = P1.Vertices.GetHalfedges(i); int[] Neighbours = P1.Vertices.GetVertexNeighbours(i); Vector3d[] OutVectors = new Vector3d[Neighbours.Length]; int Valence = P1.Vertices.GetValence(i); for (int j = 0; j < Valence; j++) { Vector3d OutVector = P1.Vertices[Neighbours[j]].ToPoint3d() - Vertex; OutVector.Unitize(); OutVectors[j] = OutVector; } for (int j = 0; j < Valence; j++) { if (P1.Halfedges[OutEdges[(j + 1) % Valence]].AdjacentFace != -1) { Normal += (Vector3d.CrossProduct(OutVectors[(j + 1) % Valence], OutVectors[j])); } } Normal.Unitize(); Normals.Add(Normal); for (int j = 0; j < Valence; j++) { AvgAngle += Vector3d.VectorAngle(Normal, OutVectors[j]); } AvgAngle = AvgAngle * (1.0 / Valence); double Offset = R / (Math.Sin(AvgAngle)); Outer.Add(P2.Vertices.Add(Vertex + (Normal * Offset))); //this adds the actual point to the mesh, as well as its index to Outer Inner.Add(P2.Vertices.Add(Vertex - (Normal * Offset))); } for (int i = 0; i < P1.Halfedges.Count; i++) { //get the 3 points of the angle int Prev = P1.Halfedges[i].PrevHalfedge; int Next = P1.Halfedges[i].NextHalfedge; int PrevV = P1.Halfedges[Prev].StartVertex; int NextV = P1.Halfedges[Next].StartVertex; int ThisV = P1.Halfedges[i].StartVertex; double R = 0; if (RL.Count == 1) { R = RL[0]; } else { R = RL[ThisV]; } Point3d PrevPt = P1.Vertices[PrevV].ToPoint3d(); Point3d NextPt = P1.Vertices[NextV].ToPoint3d(); Point3d ThisPt = P1.Vertices[ThisV].ToPoint3d(); //construct the point at the inside of the 'elbow' Vector3d Arm1 = PrevPt - ThisPt; Vector3d Arm2 = NextPt - ThisPt; Arm1.Unitize(); Arm2.Unitize(); double alpha = Vector3d.VectorAngle(Arm1, Arm2); Point3d ThisElbow; Vector3d Bisect = new Vector3d(); if (P1.Halfedges[i].AdjacentFace == -1) { Bisect = Vector3d.CrossProduct(Normals[ThisV], -1.0 * Arm1) + Vector3d.CrossProduct(Normals[ThisV], Arm2); } else { Bisect = Arm1 + Arm2; } Bisect.Unitize(); ThisElbow = ThisPt + Bisect * (R / Math.Sin(alpha * 0.5)); Elbow.Add(P2.Vertices.Add(ThisElbow)); } for (int i = 0; i < P1.Halfedges.Count; i++) { int Next = P1.Halfedges[i].NextHalfedge; int NextV = P1.Halfedges[Next].StartVertex; int ThisV = P1.Halfedges[i].StartVertex; P2.Faces.AddFace(Outer[ThisV], Outer[NextV], Elbow[Next], Elbow[i]); P2.Faces.AddFace(Elbow[i], Elbow[Next], Inner[NextV], Inner[ThisV]); } Mesh OutputMesh = P2.ToRhinoMesh(); DA.SetData(0, OutputMesh); }
/// <summary> /// Same as `Dual`, but returns a PlanktonMesh, useful for chaining operators /// </summary> /// <param name="pMesh"></param> /// <returns></returns> public static PlanktonMesh Dual(this PlanktonMesh pMesh) { return(pMesh.Dual()); }