예제 #1
0
 public PlanktonMesh(PlanktonMesh source)
 {
     foreach (var v in source.Vertices)
     {
         this.Vertices.Add(new PlanktonVertex() {
                               OutgoingHalfedge = v.OutgoingHalfedge,
                               X = v.X,
                               Y = v.Y,
                               Z = v.Z
                           });
     }
     foreach (var f in source.Faces)
     {
         this.Faces.Add(new PlanktonFace() { FirstHalfedge = f.FirstHalfedge });
     }
     foreach (var h in source.Halfedges)
     {
         this.Halfedges.Add(new PlanktonHalfedge() {
                                StartVertex = h.StartVertex,
                                AdjacentFace = h.AdjacentFace,
                                NextHalfedge = h.NextHalfedge,
                                PrevHalfedge = h.PrevHalfedge,
                            });
     }
 }
예제 #2
0
        /// <summary>
        /// Creates a Rhino mesh from a Plankton halfedge mesh.
        /// Uses the face-vertex information available in the halfedge data structure.
        /// </summary>
        /// <returns>A <see cref="Mesh"/> which represents the source mesh (as best it can).</returns>
        /// <param name="source">A Plankton mesh to convert from.</param>
        /// <remarks>Any faces with five sides or more will be triangulated.</remarks>
        public static Mesh ToRhinoMesh(this PlanktonMesh source)
        {
            // could add different options for triangulating ngons later
            Mesh rMesh = new Mesh();

            foreach (PlanktonVertex v in source.Vertices)
            {
                rMesh.Vertices.Add(v.X, v.Y, v.Z);
            }
            for (int i = 0; i < source.Faces.Count; i++)
            {
                int[] fvs = source.Faces.GetFaceVertices(i);
                if (fvs.Length == 3)
                {
                    rMesh.Faces.AddFace(fvs[0], fvs[1], fvs[2]);
                }
                else if (fvs.Length == 4)
                {
                    rMesh.Faces.AddFace(fvs[0], fvs[1], fvs[2], fvs[3]);
                }
                else if (fvs.Length > 4)
                {
                    // triangulate about face center (fan)
                    var fc = source.Faces.GetFaceCenter(i);
                    rMesh.Vertices.Add(fc.X, fc.Y, fc.Z);
                    for (int j = 0; j < fvs.Length; j++)
                    {
                        rMesh.Faces.AddFace(fvs[j], fvs[(j + 1) % fvs.Length], rMesh.Vertices.Count - 1);
                    }
                }
            }
            rMesh.Normals.ComputeNormals();
            return(rMesh);
        }
예제 #3
0
 public PlanktonMesh(PlanktonMesh source)
 {
     foreach (var v in source.Vertices)
     {
         this.Vertices.Add(new PlanktonVertex()
         {
             OutgoingHalfedge = v.OutgoingHalfedge,
             X = v.X,
             Y = v.Y,
             Z = v.Z
         });
     }
     foreach (var f in source.Faces)
     {
         this.Faces.Add(new PlanktonFace()
         {
             FirstHalfedge = f.FirstHalfedge
         });
     }
     foreach (var h in source.Halfedges)
     {
         this.Halfedges.Add(new PlanktonHalfedge()
         {
             StartVertex  = h.StartVertex,
             AdjacentFace = h.AdjacentFace,
             NextHalfedge = h.NextHalfedge,
             PrevHalfedge = h.PrevHalfedge,
         });
     }
 }
예제 #4
0
        /// <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 P = new PlanktonMesh();
            List<Point3d> Points = new List<Point3d>();
            if ((!DA.GetData<PlanktonMesh>(0, ref P)) || (!DA.GetDataList(1, Points))) return;
            PlanktonMesh pMesh = P.ReplaceVertices(Points);           
            DA.SetData(0, pMesh);
        }
예제 #5
0
        /// <summary>
        /// Replaces the vertices of a PlanktonMesh with a new list of points
        /// </summary>
        /// <returns>A list of closed polylines representing the boundary edges of each face.</returns>
        /// <param name="source">A Plankton mesh.</param>
        /// <param name="points">A list of points.</param>
        public static PlanktonMesh ReplaceVertices(this PlanktonMesh source, List <Point3d> points)
        {
            PlanktonMesh pMesh = source;

            for (int i = 0; i < points.Count; i++)
            {
                pMesh.Vertices.SetVertex(i, points[i]);
            }
            return(pMesh);
        }
예제 #6
0
 public static List<string> PrintVertices(PlanktonMesh mesh)
 {
     List<string> output = new List<string>();
     for (int i = 0; i < mesh.Vertices.Count; i++)
     {
         string str = "Vertices[" + i.ToString() + "]=";
         str += mesh.Vertices[i].X.ToString() +
             "," + mesh.Vertices[i].Y.ToString() +
             "," + mesh.Vertices[i].Z.ToString();
         output.Add(str);
     }
     return output;
 }
예제 #7
0
 public static List<string> PrintHalfedges(PlanktonMesh mesh)
 {
     List<string> output = new List<string>();
     output.Add("Format: StartVertex,AdjacentFace,NextHalfedge,PrevHalfedge");
     for (int i = 0; i < mesh.Halfedges.Count; i++)
     {
         string str = "Halfedges[" + i.ToString() + "]=";
         str += mesh.Halfedges[i].StartVertex.ToString() + "," +
              mesh.Halfedges[i].AdjacentFace.ToString() + "," +
               mesh.Halfedges[i].NextHalfedge.ToString() + "," +
                mesh.Halfedges[i].PrevHalfedge.ToString();
         output.Add(str);
     }
     return output;
 }
예제 #8
0
 public static List<string> PrintFaces(PlanktonMesh mesh)
 {
     List<string> output = new List<string>();
     for (int i = 0; i < mesh.Faces.Count; i++)
     {
         string str = "Faces[" + i.ToString() + "]=";
         int[] findex = mesh.Faces.GetFaceVertices(i);
         for (int j = 0; j < findex.Length; j++)
         {
             if (j > 0) str += ",";
             str += findex[j].ToString();
         }
         output.Add(str);
     }
     return output;
 }
예제 #9
0
        /// <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)
        {
            PlanktonMesh P = new PlanktonMesh();
            if (!DA.GetData<PlanktonMesh>(0, ref P)) return;

            List<Point3d> Positions = new List<Point3d>();
            List<int> OutHEdge = new List<int>();

            foreach (PlanktonVertex v in P.Vertices)
            {
                Positions.Add(new Point3f(v.X, v.Y, v.Z));
                OutHEdge.Add(v.OutgoingHalfedge);
            }

            List<int> StartV = new List<int>();
            List<int> AdjF = new List<int>();
            List<int> Next = new List<int>();
            List<int> Prev = new List<int>();
            List<int> Pair = new List<int>();

            for (int i = 0; i < P.Halfedges.Count; i++)
            {
                StartV.Add(P.Halfedges[i].StartVertex);
                AdjF.Add(P.Halfedges[i].AdjacentFace);
                Next.Add(P.Halfedges[i].NextHalfedge);
                Prev.Add(P.Halfedges[i].PrevHalfedge);
                Pair.Add(P.Halfedges.GetPairHalfedge(i));
            }

            List<int> FaceEdge = new List<int>();
            for (int i = 0; i < P.Faces.Count; i++)
            {
                FaceEdge.Add(P.Faces[i].FirstHalfedge);
            }

            DA.SetDataList(0, Positions);
            DA.SetDataList(1, OutHEdge);

            DA.SetDataList(2, StartV);
            DA.SetDataList(3, AdjF);
            DA.SetDataList(4, Next);
            DA.SetDataList(5, Prev);
            DA.SetDataList(6, Pair);

            DA.SetDataList(7, FaceEdge);
        }
예제 #10
0
        /// <summary>
        /// Converts each face to a closed polyline.
        /// </summary>
        /// <returns>A list of closed polylines representing the boundary edges of each face.</returns>
        /// <param name="source">A Plankton mesh.</param>
        public static Polyline[] ToPolylines(this PlanktonMesh source)
        {
            int n = source.Faces.Count;

            Polyline[] polylines = new Polyline[n];
            for (int i = 0; i < n; i++)
            {
                Polyline facePoly = new Polyline();
                int[]    vs       = source.Faces.GetFaceVertices(i);
                for (int j = 0; j <= vs.Length; j++)
                {
                    var v = source.Vertices[vs[j % vs.Length]];
                    facePoly.Add(v.X, v.Y, v.Z);
                }
                polylines[i] = facePoly;
            }

            return(polylines);
        }
예제 #11
0
 public PlanktonMesh MeshFromPoints(List<PlanktonXYZ> pl, int u, int v)
 {
     if (u * v > pl.Count || u < 2 || v < 2) return null;
     PlanktonMesh mesh = new PlanktonMesh();
     for (int i = 0; i < pl.Count; i++)
     {
         mesh.Vertices.Add(pl[i]);
     }
     for (int i = 1; i < u; i++)
     {
         for (int j = 1; j < v; j++)
         {
             mesh.Faces.AddFace(
             (j - 1) * u + i - 1,
             (j - 1) * u + i,
             (j) * u + i,
             (j) * u + i - 1);
         }
     }
     return mesh;
 }
예제 #12
0
        /// <summary>
        /// Truncates the vertices of a mesh.
        /// </summary>
        /// <param name="t">Optional parameter for the normalised distance along each edge to control the amount of truncation.</param>
        /// <returns>A new mesh, the result of the truncation.</returns>
        public PlanktonMesh TruncateVertices(float t = 1f / 3)
        {
            // TODO: handle special cases (t = 0.0, t = 0.5, t > 0.5)
            var tMesh = new PlanktonMesh(this);

            var         vxyz = tMesh.Vertices.Select(v => v.ToXYZ()).ToArray();
            PlanktonXYZ v0, v1, v2;

            int[] oh;
            for (int i = 0; i < this.Vertices.Count; i++)
            {
                oh = this.Vertices.GetHalfedges(i);
                tMesh.Vertices.TruncateVertex(i);
                foreach (var h in oh)
                {
                    v0 = vxyz[this.Halfedges[h].StartVertex];
                    v1 = vxyz[this.Halfedges.EndVertex(h)];
                    v2 = v0 + (v1 - v0) * t;
                    tMesh.Vertices.SetVertex(tMesh.Halfedges[h].StartVertex, v2.X, v2.Y, v2.Z);
                }
            }

            return(tMesh);
        }
예제 #13
0
        /// <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)
        {
            //------------------INPUT--------------------//
            PlanktonMesh pMesh = new PlanktonMesh();
            DA.GetData(0, ref pMesh);

            bool projXY = false;
            DA.GetData(1, ref projXY);



            //------------------CALCULATE--------------------//
            PMeshExt pMeshE = new PMeshExt(pMesh);

            if (!pMeshE.isMeshTriangulated())
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "The mesh has to be triangulated");
            }

            //Extract vertices from initial 3d pMesh
            Point3d[] verticesXYZ = pMeshE.convertVerticesToXYZ();

            //If projected then create new pMesh
            if (projXY)
            {
                pMeshE = pMeshE.projectMeshToXY();
            }

            Vector3d[] vertexAreas = pMeshE.calcVertexVoronoiAreas(projXY);



            //------------------OUTPUT--------------------//
            DA.SetDataList(0, verticesXYZ);
            DA.SetDataList(1, vertexAreas);
        }
예제 #14
0
        public PlanktonMesh TriangleMeshFromPoints(List<PlanktonXYZ> pl, int t1, int t2)
        {
            PlanktonMesh mesh = new PlanktonMesh();
            if (t1 < 1) return mesh;
            if (t2 <= t1) return mesh;
            int n = ((t1 + t2) * (t2 - t1 + 1)) / 2;
            if (n > pl.Count) return mesh;
            mesh.Vertices.AddVertices(pl);
            List<int> layer1; List<int> layer2 = new List<int>();
            for (int i = 0; i < t1; i++)
            {
                layer2.Add(i);
            }
            for (int i = t1 - 1; i < t2; i++)
            {
                layer1 = new List<int>(layer2);
                for (int j = 0; j < layer2.Count; j++)
                {
                    layer2[j] += i + 1;
                }
                layer2.Add(layer2[layer2.Count - 1] + 1);

                if (layer1.Count > 1)
                {
                    for (int j = 0; j < layer1.Count - 1; j++)
                    {
                        mesh.Faces.AddFace(layer1[j], layer1[j + 1], layer2[j + 1]);
                    }
                }
                for (int j = 0; j < layer1.Count; j++)
                {
                    mesh.Faces.AddFace(layer2[j], layer1[j], layer2[j + 1]);
                }
            }
            return mesh;
        }
예제 #15
0
        /// <summary>
        /// Truncates the vertices of a mesh.
        /// </summary>
        /// <param name="t">Optional parameter for the normalised distance along each edge to control the amount of truncation.</param>
        /// <returns>A new mesh, the result of the truncation.</returns>
        public PlanktonMesh TruncateVertices(float t = 1f/3)
        {
            // TODO: handle special cases (t = 0.0, t = 0.5, t > 0.5)
            var tMesh = new PlanktonMesh(this);

            var vxyz = tMesh.Vertices.Select(v => v.ToXYZ()).ToArray();
            PlanktonXYZ v0, v1, v2;
            int[] oh;
            for (int i = 0; i < this.Vertices.Count; i++)
            {
                oh = this.Vertices.GetHalfedges(i);
                tMesh.Vertices.TruncateVertex(i);
                foreach (var h in oh)
                {
                    v0 = vxyz[this.Halfedges[h].StartVertex];
                    v1 = vxyz[this.Halfedges.EndVertex(h)];
                    v2 = v0 + (v1 - v0) * t;
                    tMesh.Vertices.SetVertex(tMesh.Halfedges[h].StartVertex, v2.X, v2.Y, v2.Z);
                }
            }

            return tMesh;
        }
예제 #16
0
        public PlanktonMesh Dual()
        {
            // can later add options for other ways of defining face centres (barycenter/circumcenter etc)
            // won't work yet with naked boundaries

            PlanktonMesh P = this;
            PlanktonMesh D = new PlanktonMesh();

            //for every primal face, add the barycenter to the dual's vertex list
            //dual vertex outgoing HE is primal face's start HE
            //for every vertex of the primal, add a face to the dual
            //dual face's startHE is primal vertex's outgoing's pair

            for (int i = 0; i < P.Faces.Count; i++)
            {
                var fc = P.Faces.GetFaceCenter(i);
                D.Vertices.Add(new PlanktonVertex(fc.X, fc.Y, fc.Z));
                int[] FaceHalfedges = P.Faces.GetHalfedges(i);
                for (int j = 0; j < FaceHalfedges.Length; j++)
                {
                    if (P.Halfedges[P.Halfedges.GetPairHalfedge(FaceHalfedges[j])].AdjacentFace != -1)
                    {
                        // D.Vertices[i].OutgoingHalfedge = FaceHalfedges[j];
                        D.Vertices[D.Vertices.Count-1].OutgoingHalfedge = P.Halfedges.GetPairHalfedge(FaceHalfedges[j]);
                        break;
                    }
                }
            }

            for (int i = 0; i < P.Vertices.Count; i++)
            {
                if (P.Vertices.NakedEdgeCount(i) == 0)
                {
                    int df = D.Faces.Add(PlanktonFace.Unset);
                    // D.Faces[i].FirstHalfedge = P.PairHalfedge(P.Vertices[i].OutgoingHalfedge);
                    D.Faces[df].FirstHalfedge = P.Vertices[i].OutgoingHalfedge;
                }
            }

            // dual halfedge start V is primal AdjacentFace
            // dual halfedge AdjacentFace is primal end V
            // dual nextHE is primal's pair's prev
            // dual prevHE is primal's next's pair

            // halfedge pairs stay the same

            for (int i = 0; i < P.Halfedges.Count; i++)
            {
                if ((P.Halfedges[i].AdjacentFace != -1) & (P.Halfedges[P.Halfedges.GetPairHalfedge(i)].AdjacentFace != -1))
                {
                    PlanktonHalfedge DualHE = PlanktonHalfedge.Unset;
                    PlanktonHalfedge PrimalHE = P.Halfedges[i];
                    //DualHE.StartVertex = PrimalHE.AdjacentFace;
                    DualHE.StartVertex = P.Halfedges[P.Halfedges.GetPairHalfedge(i)].AdjacentFace;

                    if (P.Vertices.NakedEdgeCount(PrimalHE.StartVertex) == 0)
                    {
                        //DualHE.AdjacentFace = P.Halfedges[P.PairHalfedge(i)].StartVertex;
                        DualHE.AdjacentFace = PrimalHE.StartVertex;
                    }
                    else { DualHE.AdjacentFace = -1; }

                    //This will currently fail with open meshes...
                    //one option could be to build the dual with all halfedges, but mark some as dead
                    //if they connect to vertex -1
                    //mark the 'external' faces all as -1 (the ones that are dual to boundary verts)
                    //then go through and if any next or prevs are dead hes then replace them with the next one around
                    //this needs to be done repeatedly until no further change

                    //DualHE.NextHalfedge = P.Halfedges[P.PairHalfedge(i)].PrevHalfedge;
                    DualHE.NextHalfedge = P.Halfedges.GetPairHalfedge(PrimalHE.PrevHalfedge);

                    //DualHE.PrevHalfedge = P.PairHalfedge(PrimalHE.NextHalfedge);
                    DualHE.PrevHalfedge = P.Halfedges[P.Halfedges.GetPairHalfedge(i)].NextHalfedge;

                    D.Halfedges.Add(DualHE);
                }
            }
            return D;
        }
예제 #17
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PlanktonHalfedgeList"/> class.
 /// Should be called from the mesh constructor.
 /// </summary>
 /// <param name="ownerMesh">The mesh to which this list of halfedges belongs.</param>
 internal PlanktonHalfEdgeList(PlanktonMesh owner)
 {
     this._list = new List <PlanktonHalfedge>();
     this._mesh = owner;
 }
예제 #18
0
 public PlanktonMesh MeshFromPoints(PlanktonXYZ p1, PlanktonXYZ p2, PlanktonXYZ p3)
 {
     PlanktonMesh mesh = new PlanktonMesh();
     mesh.Vertices.Add(p1);
     mesh.Vertices.Add(p2);
     mesh.Vertices.Add(p3);
     mesh.Faces.AddFace(0, 1, 2);
     return mesh;
 }
예제 #19
0
        public PlanktonMesh Dual()
        {
            // hack for open meshes
            // TODO: improve this ugly method
            if (this.IsClosed() == false)
            {
                var dual = new PlanktonMesh();

                // create vertices from face centers
                for (int i = 0; i < this.Faces.Count; i++)
                {
                    dual.Vertices.Add(this.Faces.GetFaceCenter(i));
                }

                // create faces from the adjacent face indices of non-boundary vertices
                for (int i = 0; i < this.Vertices.Count; i++)
                {
                    if (this.Vertices.IsBoundary(i))
                    {
                        continue;
                    }
                    dual.Faces.AddFace(this.Vertices.GetVertexFaces(i));
                }

                return(dual);
            }

            // can later add options for other ways of defining face centres (barycenter/circumcenter etc)
            // won't work yet with naked boundaries

            PlanktonMesh P = this;
            PlanktonMesh D = new PlanktonMesh();

            //for every primal face, add the barycenter to the dual's vertex list
            //dual vertex outgoing HE is primal face's start HE
            //for every vertex of the primal, add a face to the dual
            //dual face's startHE is primal vertex's outgoing's pair

            for (int i = 0; i < P.Faces.Count; i++)
            {
                var fc = P.Faces.GetFaceCenter(i);
                D.Vertices.Add(new PlanktonVertex(fc.X, fc.Y, fc.Z));
                int[] FaceHalfedges = P.Faces.GetHalfedges(i);
                for (int j = 0; j < FaceHalfedges.Length; j++)
                {
                    if (P.Halfedges[P.Halfedges.GetPairHalfedge(FaceHalfedges[j])].AdjacentFace != -1)
                    {
                        // D.Vertices[i].OutgoingHalfedge = FaceHalfedges[j];
                        D.Vertices[D.Vertices.Count - 1].OutgoingHalfedge = P.Halfedges.GetPairHalfedge(FaceHalfedges[j]);
                        break;
                    }
                }
            }

            for (int i = 0; i < P.Vertices.Count; i++)
            {
                if (P.Vertices.NakedEdgeCount(i) == 0)
                {
                    int df = D.Faces.Add(PlanktonFace.Unset);
                    // D.Faces[i].FirstHalfedge = P.PairHalfedge(P.Vertices[i].OutgoingHalfedge);
                    D.Faces[df].FirstHalfedge = P.Vertices[i].OutgoingHalfedge;
                }
            }

            // dual halfedge start V is primal AdjacentFace
            // dual halfedge AdjacentFace is primal end V
            // dual nextHE is primal's pair's prev
            // dual prevHE is primal's next's pair

            // halfedge pairs stay the same

            for (int i = 0; i < P.Halfedges.Count; i++)
            {
                if ((P.Halfedges[i].AdjacentFace != -1) & (P.Halfedges[P.Halfedges.GetPairHalfedge(i)].AdjacentFace != -1))
                {
                    PlanktonHalfedge DualHE   = PlanktonHalfedge.Unset;
                    PlanktonHalfedge PrimalHE = P.Halfedges[i];
                    //DualHE.StartVertex = PrimalHE.AdjacentFace;
                    DualHE.StartVertex = P.Halfedges[P.Halfedges.GetPairHalfedge(i)].AdjacentFace;

                    if (P.Vertices.NakedEdgeCount(PrimalHE.StartVertex) == 0)
                    {
                        //DualHE.AdjacentFace = P.Halfedges[P.PairHalfedge(i)].StartVertex;
                        DualHE.AdjacentFace = PrimalHE.StartVertex;
                    }
                    else
                    {
                        DualHE.AdjacentFace = -1;
                    }

                    //This will currently fail with open meshes...
                    //one option could be to build the dual with all halfedges, but mark some as dead
                    //if they connect to vertex -1
                    //mark the 'external' faces all as -1 (the ones that are dual to boundary verts)
                    //then go through and if any next or prevs are dead hes then replace them with the next one around
                    //this needs to be done repeatedly until no further change

                    //DualHE.NextHalfedge = P.Halfedges[P.PairHalfedge(i)].PrevHalfedge;
                    DualHE.NextHalfedge = P.Halfedges.GetPairHalfedge(PrimalHE.PrevHalfedge);

                    //DualHE.PrevHalfedge = P.PairHalfedge(PrimalHE.NextHalfedge);
                    DualHE.PrevHalfedge = P.Halfedges[P.Halfedges.GetPairHalfedge(i)].NextHalfedge;

                    D.Halfedges.Add(DualHE);
                }
            }
            return(D);
        }
예제 #20
0
 private Point3d MidPt(PlanktonMesh P, int E)
 {
     Point3d Pos1 = P.Vertices[P.Halfedges[2 * E].StartVertex].ToPoint3d();
     Point3d Pos2 = P.Vertices[P.Halfedges[2 * E + 1].StartVertex].ToPoint3d();
     return (Pos1 + Pos2) * 0.5;
 }
예제 #21
0
        private List<int> CompactByVertex(PlanktonMesh P, List<int> L)
        {
            List<int> L2 = new List<int>();

            for (int i = 0; i < P.Vertices.Count; i++)
            {
                if (P.Vertices[i].IsUnused == false)
                {
                    L2.Add(L[i]);
                }
            }
            return L2;
        }
예제 #22
0
        private static Vector3d[] LaplacianSmooth(PlanktonMesh P, int W, double Strength)
        {
            int VertCount = P.Vertices.Count;
            Vector3d[] Smooth = new Vector3d[VertCount];

            for (int i = 0; i < VertCount; i++)
            {
                if ((P.Vertices[i].IsUnused == false) && (P.Vertices.IsBoundary(i) == false))
                {
                    int[] Neighbours = P.Vertices.GetVertexNeighbours(i);
                    Point3d Vertex = P.Vertices[i].ToPoint3d();
                    Point3d Centroid = new Point3d();
                    if (W == 0)
                    {
                        for (int j = 0; j < Neighbours.Length; j++)
                        { Centroid = Centroid + P.Vertices[Neighbours[j]].ToPoint3d(); }
                        Smooth[i] = ((Centroid * (1.0 / P.Vertices.GetValence(i))) - Vertex) * Strength;
                    }
                    if (W == 1)
                    {
                        //get the radial vectors of the 1-ring
                        //get the vectors around the 1-ring
                        //get the cotangent weights for each edge

                        int valence = Neighbours.Length;

                        Point3d[] NeighbourPts = new Point3d[valence];
                        Vector3d[] Radial = new Vector3d[valence];
                        Vector3d[] Around = new Vector3d[valence];
                        double[] CotWeight = new double[valence];
                        double WeightSum = 0;

                        for (int j = 0; j < valence; j++)
                        {
                            NeighbourPts[j] = P.Vertices[Neighbours[j]].ToPoint3d();
                            Radial[j] = NeighbourPts[j] - Vertex;
                        }

                        for (int j = 0; j < valence; j++)
                        {
                            Around[j] = NeighbourPts[(j + 1) % valence] - NeighbourPts[j];
                        }

                        for (int j = 0; j < Neighbours.Length; j++)
                        {
                            //get the cotangent weights
                            int previous = (j + valence - 1) % valence;
                            Vector3d Cross1 = Vector3d.CrossProduct(Radial[previous], Around[previous]);
                            double Cross1Length = Cross1.Length;
                            double Dot1 = Radial[previous] * Around[previous];

                            int next = (j + 1) % valence;
                            Vector3d Cross2 = Vector3d.CrossProduct(Radial[next], Around[j]);
                            double Cross2Length = Cross2.Length;
                            double Dot2 = Radial[next] * Around[j];

                            CotWeight[j] = Math.Abs(Dot1 / Cross1Length) + Math.Abs(Dot2 / Cross2Length);
                            WeightSum += CotWeight[j];
                        }

                        double InvWeightSum = 1.0 / WeightSum;

                        Vector3d ThisSmooth = new Vector3d();

                        for (int j = 0; j < Neighbours.Length; j++)
                        {
                            ThisSmooth = ThisSmooth + Radial[j] * CotWeight[j];
                        }

                        Smooth[i] = ThisSmooth * InvWeightSum * Strength;
                    }

                }
            }
            return Smooth;
        }
예제 #23
0
        public PlanktonMesh TriangleMeshFromPoints(List<PlanktonXYZ> pl, int t)
        {
            //triangle MeshTopo Points From topo of the pyramid to the base
            PlanktonMesh mesh = new PlanktonMesh();
            if (t < 2) return mesh;
            int n = ((1 + t) * t) / 2;
            if (n > pl.Count) return mesh;

            mesh.Vertices.AddVertices(pl);
            List<int> layer1; List<int> layer2 = new List<int>();
            layer2.Add(0);
            for (int i = 0; i < t - 1; i++)
            {
                layer1 = new List<int>(layer2);
                for (int j = 0; j < layer2.Count; j++)
                {
                    layer2[j] += i + 1;
                }
                layer2.Add(layer2[layer2.Count - 1] + 1);

                if (layer1.Count > 1)
                {
                    for (int j = 0; j < layer1.Count - 1; j++)
                    {
                        mesh.Faces.AddFace(layer1[j], layer1[j + 1], layer2[j + 1]);
                    }
                }
                for (int j = 0; j < layer1.Count; j++)
                {
                    mesh.Faces.AddFace(layer2[j], layer1[j], layer2[j + 1]);
                }
            }
            return mesh;
        }
예제 #24
0
        /// <summary>
        /// Creates a Plankton halfedge mesh from a Rhino mesh.
        /// Uses the topology of the Rhino mesh directly.
        /// </summary>
        /// <returns>A <see cref="PlanktonMesh"/> which represents the topology and geometry of the source mesh.</returns>
        /// <param name="source">A Rhino mesh to convert from.</param>
        public static PlanktonMesh ToPlanktonMesh(this Mesh source)
        {
            PlanktonMesh pMesh = new PlanktonMesh();

            source.Vertices.CombineIdentical(true, true);
            source.Vertices.CullUnused();
            source.UnifyNormals();
            source.Weld(Math.PI);

            foreach (Point3f v in source.TopologyVertices)
            {
                pMesh.Vertices.Add(v.X, v.Y, v.Z);
            }

            for (int i = 0; i < source.Faces.Count; i++)
            {
                pMesh.Faces.Add(new PlanktonFace());
            }

            for (int i = 0; i < source.TopologyEdges.Count; i++)
            {
                PlanktonHalfedge HalfA = new PlanktonHalfedge();

                HalfA.StartVertex = source.TopologyEdges.GetTopologyVertices(i).I;

                if (pMesh.Vertices[HalfA.StartVertex].OutgoingHalfedge == -1)
                {
                    pMesh.Vertices[HalfA.StartVertex].OutgoingHalfedge = pMesh.Halfedges.Count;
                }

                PlanktonHalfedge HalfB = new PlanktonHalfedge();

                HalfB.StartVertex = source.TopologyEdges.GetTopologyVertices(i).J;

                if (pMesh.Vertices[HalfB.StartVertex].OutgoingHalfedge == -1)
                {
                    pMesh.Vertices[HalfB.StartVertex].OutgoingHalfedge = pMesh.Halfedges.Count + 1;
                }

                bool[] Match;
                int[]  ConnectedFaces = source.TopologyEdges.GetConnectedFaces(i, out Match);

                //Note for Steve Baer : This Match bool doesn't seem to work on triangulated meshes - it often returns true
                //for both faces, even for a properly oriented manifold mesh, which can't be right
                //So - making our own check for matching:
                //(I suspect the problem is related to C being the same as D for triangles, so best to
                //deal with them separately just to make sure)
                //loop through the vertices of the face until finding the one which is the same as the start of the edge
                //iff the next vertex around the face is the end of the edge then it matches.

                Match[0] = false;
                if (Match.Length > 1)
                {
                    Match[1] = true;
                }

                int VertA = source.TopologyVertices.TopologyVertexIndex(source.Faces[ConnectedFaces[0]].A);
                int VertB = source.TopologyVertices.TopologyVertexIndex(source.Faces[ConnectedFaces[0]].B);
                int VertC = source.TopologyVertices.TopologyVertexIndex(source.Faces[ConnectedFaces[0]].C);
                int VertD = source.TopologyVertices.TopologyVertexIndex(source.Faces[ConnectedFaces[0]].D);

                if ((VertA == source.TopologyEdges.GetTopologyVertices(i).I) &&
                    (VertB == source.TopologyEdges.GetTopologyVertices(i).J))
                {
                    Match[0] = true;
                }
                if ((VertB == source.TopologyEdges.GetTopologyVertices(i).I) &&
                    (VertC == source.TopologyEdges.GetTopologyVertices(i).J))
                {
                    Match[0] = true;
                }
                if ((VertC == source.TopologyEdges.GetTopologyVertices(i).I) &&
                    (VertD == source.TopologyEdges.GetTopologyVertices(i).J))
                {
                    Match[0] = true;
                }
                if ((VertD == source.TopologyEdges.GetTopologyVertices(i).I) &&
                    (VertA == source.TopologyEdges.GetTopologyVertices(i).J))
                {
                    Match[0] = true;
                }
                //I don't think these next 2 should ever be needed, but just in case:
                if ((VertC == source.TopologyEdges.GetTopologyVertices(i).I) &&
                    (VertA == source.TopologyEdges.GetTopologyVertices(i).J))
                {
                    Match[0] = true;
                }
                if ((VertB == source.TopologyEdges.GetTopologyVertices(i).I) &&
                    (VertD == source.TopologyEdges.GetTopologyVertices(i).J))
                {
                    Match[0] = true;
                }

                if (Match[0] == true)
                {
                    HalfA.AdjacentFace = ConnectedFaces[0];
                    if (pMesh.Faces[HalfA.AdjacentFace].FirstHalfedge == -1)
                    {
                        pMesh.Faces[HalfA.AdjacentFace].FirstHalfedge = pMesh.Halfedges.Count;
                    }
                    if (ConnectedFaces.Length > 1)
                    {
                        HalfB.AdjacentFace = ConnectedFaces[1];
                        if (pMesh.Faces[HalfB.AdjacentFace].FirstHalfedge == -1)
                        {
                            pMesh.Faces[HalfB.AdjacentFace].FirstHalfedge = pMesh.Halfedges.Count + 1;
                        }
                    }
                    else
                    {
                        HalfB.AdjacentFace = -1;
                        pMesh.Vertices[HalfB.StartVertex].OutgoingHalfedge = pMesh.Halfedges.Count + 1;
                    }
                }
                else
                {
                    HalfB.AdjacentFace = ConnectedFaces[0];

                    if (pMesh.Faces[HalfB.AdjacentFace].FirstHalfedge == -1)
                    {
                        pMesh.Faces[HalfB.AdjacentFace].FirstHalfedge = pMesh.Halfedges.Count + 1;
                    }

                    if (ConnectedFaces.Length > 1)
                    {
                        HalfA.AdjacentFace = ConnectedFaces[1];

                        if (pMesh.Faces[HalfA.AdjacentFace].FirstHalfedge == -1)
                        {
                            pMesh.Faces[HalfA.AdjacentFace].FirstHalfedge = pMesh.Halfedges.Count;
                        }
                    }
                    else
                    {
                        HalfA.AdjacentFace = -1;
                        pMesh.Vertices[HalfA.StartVertex].OutgoingHalfedge = pMesh.Halfedges.Count;
                    }
                }
                pMesh.Halfedges.Add(HalfA);
                pMesh.Halfedges.Add(HalfB);
            }

            for (int i = 0; i < (pMesh.Halfedges.Count); i += 2)
            {
                int[] EndNeighbours = source.TopologyVertices.ConnectedTopologyVertices(pMesh.Halfedges[i + 1].StartVertex, true);
                for (int j = 0; j < EndNeighbours.Length; j++)
                {
                    if (EndNeighbours[j] == pMesh.Halfedges[i].StartVertex)
                    {
                        int EndOfNextHalfedge         = EndNeighbours[(j - 1 + EndNeighbours.Length) % EndNeighbours.Length];
                        int StartOfPrevOfPairHalfedge = EndNeighbours[(j + 1) % EndNeighbours.Length];

                        int NextEdge     = source.TopologyEdges.GetEdgeIndex(pMesh.Halfedges[i + 1].StartVertex, EndOfNextHalfedge);
                        int PrevPairEdge = source.TopologyEdges.GetEdgeIndex(pMesh.Halfedges[i + 1].StartVertex, StartOfPrevOfPairHalfedge);

                        if (source.TopologyEdges.GetTopologyVertices(NextEdge).I == pMesh.Halfedges[i + 1].StartVertex)
                        {
                            pMesh.Halfedges[i].NextHalfedge = NextEdge * 2;
                        }
                        else
                        {
                            pMesh.Halfedges[i].NextHalfedge = NextEdge * 2 + 1;
                        }

                        if (source.TopologyEdges.GetTopologyVertices(PrevPairEdge).J == pMesh.Halfedges[i + 1].StartVertex)
                        {
                            pMesh.Halfedges[i + 1].PrevHalfedge = PrevPairEdge * 2;
                        }
                        else
                        {
                            pMesh.Halfedges[i + 1].PrevHalfedge = PrevPairEdge * 2 + 1;
                        }
                        break;
                    }
                }

                int[] StartNeighbours = source.TopologyVertices.ConnectedTopologyVertices(pMesh.Halfedges[i].StartVertex, true);
                for (int j = 0; j < StartNeighbours.Length; j++)
                {
                    if (StartNeighbours[j] == pMesh.Halfedges[i + 1].StartVertex)
                    {
                        int EndOfNextOfPairHalfedge = StartNeighbours[(j - 1 + StartNeighbours.Length) % StartNeighbours.Length];
                        int StartOfPrevHalfedge     = StartNeighbours[(j + 1) % StartNeighbours.Length];

                        int NextPairEdge = source.TopologyEdges.GetEdgeIndex(pMesh.Halfedges[i].StartVertex, EndOfNextOfPairHalfedge);
                        int PrevEdge     = source.TopologyEdges.GetEdgeIndex(pMesh.Halfedges[i].StartVertex, StartOfPrevHalfedge);

                        if (source.TopologyEdges.GetTopologyVertices(NextPairEdge).I == pMesh.Halfedges[i].StartVertex)
                        {
                            pMesh.Halfedges[i + 1].NextHalfedge = NextPairEdge * 2;
                        }
                        else
                        {
                            pMesh.Halfedges[i + 1].NextHalfedge = NextPairEdge * 2 + 1;
                        }

                        if (source.TopologyEdges.GetTopologyVertices(PrevEdge).J == pMesh.Halfedges[i].StartVertex)
                        {
                            pMesh.Halfedges[i].PrevHalfedge = PrevEdge * 2;
                        }
                        else
                        {
                            pMesh.Halfedges[i].PrevHalfedge = PrevEdge * 2 + 1;
                        }
                        break;
                    }
                }
            }

            return(pMesh);
        }
예제 #25
0
        public PlanktonMesh CatmullClark(int iteration, List <int> fixVertices, List <int> fixEdges, List <int> fixFaces)
        {
            // Gene added catmull clark subdivision function, function written for Leopard.
            // maybe change this function to static, so can be easier.

            PlanktonMesh cMesh = new PlanktonMesh(this); //  this iteration

            List <bool> isBoundaryVertices = new List <bool>();

            // assign boundary vertices
            for (int i = 0; i < cMesh.Vertices.Count; i++)
            {
                if (cMesh.Vertices.IsBoundary(i))
                {
                    isBoundaryVertices.Add(true);
                }
                else
                {
                    isBoundaryVertices.Add(false);
                }
            }

            // set vertices
            foreach (int v in fixVertices)
            {
                isBoundaryVertices[v] = true;
            }

            // set edges
            foreach (int e in fixEdges)
            {
                int id = e * 2;
                //int[] pEndsIndices = cMesh.Halfedges.GetVertices(edge);

                int pairIndex = cMesh.Halfedges.GetPairHalfedge(id);
                if (pairIndex < id)
                {
                    int temp = id; id = pairIndex; pairIndex = temp;
                }
                int[] vts = cMesh.Halfedges.GetVertices(id);

                isBoundaryVertices[vts[0]] = true;
                isBoundaryVertices[vts[1]] = true;
            }

            // set face
            foreach (int f in fixFaces)
            {
                foreach (int v in cMesh.Faces.GetFaceVertices(f))
                {
                    isBoundaryVertices[v] = true;
                }
            }


            for (int iter = 0; iter < iteration; iter++)
            {
                PlanktonMesh subdMesh = new PlanktonMesh(); // current mesh for each iteration

                // add the original vertices
                for (int i = 0; i < cMesh.Vertices.Count; i++)
                {
                    subdMesh.Vertices.Add(cMesh.Vertices[i].ToXYZ());
                }

                // face centers
                #region face centers
                PlanktonXYZ[] faceCenter = new PlanktonXYZ[cMesh.Faces.Count];
                for (int i = 0; i < cMesh.Faces.Count; i++)
                {
                    faceCenter[i] = cMesh.Faces.GetFaceCenter(i);
                    isBoundaryVertices.Add(false);
                    subdMesh.Vertices.Add(cMesh.Faces.GetFaceCenter(i));
                }
                #endregion

                // new edge points
                #region new edge points
                PlanktonXYZ[] newEdgePoints = new PlanktonXYZ[cMesh.Halfedges.Count / 2]; // pair half edges belong to one.
                for (int i = 0; i < cMesh.Halfedges.Count; i++)
                {
                    if (i % 2 == 1)
                    {
                        continue;
                    }

                    int pairIndex = cMesh.Halfedges.GetPairHalfedge(i);

                    int[] pEndsIndices = cMesh.Halfedges.GetVertices(i);
                    int   fA           = cMesh.Halfedges[i].AdjacentFace;
                    int   fB           = cMesh.Halfedges[pairIndex].AdjacentFace;

                    PlanktonXYZ pStart, pEnd, fAC, fBC;

                    // not boudary condition
                    if (pEndsIndices[0] >= 0 && pEndsIndices[1] >= 0 &&
                        fA != -1 && fB != -1)
                    {
                        pStart = cMesh.Vertices[pEndsIndices[0]].ToXYZ();
                        pEnd   = cMesh.Vertices[pEndsIndices[1]].ToXYZ();

                        fAC = faceCenter[fA];
                        fBC = faceCenter[fB];

                        if (isBoundaryVertices[pEndsIndices[0]] && isBoundaryVertices[pEndsIndices[1]])
                        {
                            newEdgePoints[(int)i / 2] = (cMesh.Vertices[pEndsIndices[0]].ToXYZ() + cMesh.Vertices[pEndsIndices[1]].ToXYZ()) * 0.5f;
                            isBoundaryVertices.Add(true);
                            subdMesh.Vertices.Add(newEdgePoints[(int)i / 2]);
                        }
                        else if ((!isBoundaryVertices[pEndsIndices[0]] && isBoundaryVertices[pEndsIndices[1]]) ||
                                 (isBoundaryVertices[pEndsIndices[0]] && !isBoundaryVertices[pEndsIndices[1]]))
                        {
                            newEdgePoints[(int)i / 2] =
                                (cMesh.Vertices[pEndsIndices[0]].ToXYZ() + cMesh.Vertices[pEndsIndices[1]].ToXYZ()) * 0.5f * 0.5f +
                                (pStart + pEnd + fAC + fBC) * 0.25f * 0.5f;
                            isBoundaryVertices.Add(false);
                            subdMesh.Vertices.Add(newEdgePoints[(int)i / 2]);
                        }
                        else
                        {
                            newEdgePoints[(int)i / 2] = (pStart + pEnd + fAC + fBC) * 0.25f;
                            isBoundaryVertices.Add(false);
                            subdMesh.Vertices.Add(newEdgePoints[(int)i / 2]);
                        }
                    }
                    // boudary condition
                    else
                    {
                        newEdgePoints[(int)i / 2] = (cMesh.Vertices[pEndsIndices[0]].ToXYZ() + cMesh.Vertices[pEndsIndices[1]].ToXYZ()) * 0.5f;
                        isBoundaryVertices.Add(true);
                        subdMesh.Vertices.Add(newEdgePoints[(int)i / 2]);
                    }
                }
                #endregion

                // new vertex points
                #region new vertex points
                PlanktonXYZ[] newVertexPoints = new PlanktonXYZ[cMesh.Vertices.Count];
                for (int i = 0; i < cMesh.Vertices.Count; i++)
                {
                    int n = cMesh.Vertices.GetValence(i);

                    // F
                    int[]       fIndices = cMesh.Vertices.GetVertexFaces(i);
                    PlanktonXYZ fn       = new PlanktonXYZ();
                    foreach (int f in fIndices)
                    {
                        if (f != -1)
                        {
                            fn += faceCenter[f];
                        }
                    }
                    fn *= (float)(1.0f / (n * n));

                    // E
                    int[]       vnIndices = cMesh.Vertices.GetVertexNeighbours(i);
                    PlanktonXYZ vn        = new PlanktonXYZ();
                    foreach (int e in vnIndices)
                    {
                        if (e != -1)
                        {
                            vn += cMesh.Vertices[e].ToXYZ();
                        }
                    }
                    vn *= (float)(1.0f / (n * n));

                    // V
                    PlanktonXYZ v = cMesh.Vertices[i].ToXYZ() * (n - 2) * (1.0f / n);
                    if (!isBoundaryVertices[i])
                    {
                        newVertexPoints[i] = fn + vn + v;
                        subdMesh.Vertices.SetVertex(i, newVertexPoints[i].X, newVertexPoints[i].Y, newVertexPoints[i].Z);
                    }
                    else
                    {
                        newVertexPoints[i] = cMesh.Vertices[i].ToXYZ();
                        subdMesh.Vertices.SetVertex(i, newVertexPoints[i].X, newVertexPoints[i].Y, newVertexPoints[i].Z);
                    }
                }
                #endregion

                // add mesh face
                #region construct mesh
                for (int i = 0; i < cMesh.Faces.Count; i++)
                {
                    int pMVC   = cMesh.Vertices.Count;
                    int fNewID = i + pMVC;

                    int[] fVertices = cMesh.Faces.GetFaceVertices(i);
                    int[] fEdgePts  = cMesh.Faces.GetHalfedges(i);

                    int fNum = cMesh.Faces.Count;
                    int eNum = cMesh.Halfedges.Count / 2;

                    if (fVertices.Length == 3)
                    {
                        subdMesh.Faces.AddFace(fNewID, fNum + fEdgePts[0] / 2 + pMVC, fVertices[1], fNum + fEdgePts[1] / 2 + pMVC);
                        subdMesh.Faces.AddFace(fNewID, fNum + fEdgePts[1] / 2 + pMVC, fVertices[2], fNum + fEdgePts[2] / 2 + pMVC);
                        subdMesh.Faces.AddFace(fNewID, fNum + fEdgePts[2] / 2 + pMVC, fVertices[0], fNum + fEdgePts[0] / 2 + pMVC);
                    }
                    else
                    {
                        subdMesh.Faces.AddFace(fNewID, fNum + fEdgePts[0] / 2 + pMVC, fVertices[1], fNum + fEdgePts[1] / 2 + pMVC);
                        subdMesh.Faces.AddFace(fNewID, fNum + fEdgePts[1] / 2 + pMVC, fVertices[2], fNum + fEdgePts[2] / 2 + pMVC);
                        subdMesh.Faces.AddFace(fNewID, fNum + fEdgePts[2] / 2 + pMVC, fVertices[3], fNum + fEdgePts[3] / 2 + pMVC);
                        subdMesh.Faces.AddFace(fNewID, fNum + fEdgePts[3] / 2 + pMVC, fVertices[0], fNum + fEdgePts[0] / 2 + pMVC);
                    }
                }
                #endregion

                cMesh = subdMesh;
            }

            return(cMesh);
        }
예제 #26
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PlanktonVertexList"/> class.
 /// Should be called from the mesh constructor.
 /// </summary>
 /// <param name="ownerMesh">The mesh to which this list of vertices belongs.</param>
 internal PlanktonVertexList(PlanktonMesh owner)
 {
     this._list = new List <PlanktonVertex>();
     this._mesh = owner;
 }
예제 #27
0
        public PMeshExt(PlanktonMesh source): base(source)
        {

        }
예제 #28
0
 /// <summary>
 /// Clone the data structure without trigging a costly rebuild operation and garbage collection.
 /// </summary>
 public void CopyInto(PlanktonMesh clone)
 {
     this.Vertices.CopyInto(clone._vertices);
     this.Halfedges.CopyInto(clone._halfedges);
     this.Faces.CopyInto(clone._faces);
 }
예제 #29
0
        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);
        }
예제 #30
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            ITargetLength TargetLength = null;
            bool reset = false;
            int Flip = 0;
            List<Curve> FC = new List<Curve>();
            List<Point3d> FV = new List<Point3d>();
            double FixT = 0.01;
            double PullStrength = 0.8;
            double SmoothStrength = 0.8;
            double LengthTol = 0.15;
            bool Minim = false;
            int Iters = 1;

            GH_ObjectWrapper Surf = new GH_ObjectWrapper();
            DA.GetData<GH_ObjectWrapper>(0, ref Surf);

            GH_ObjectWrapper Obj = null;
            DA.GetData<GH_ObjectWrapper>(1, ref Obj);
            TargetLength = Obj.Value as ITargetLength;

            DA.GetDataList<Curve>(2, FC);
            DA.GetDataList<Point3d>(3, FV);
            DA.GetData<int>(4, ref Flip);

            DA.GetData<double>(5, ref PullStrength);

            DA.GetData<int>(6, ref Iters);
            DA.GetData<bool>(7, ref reset);

            if (PullStrength == 0) { Minim = true; }

            if (Surf.Value is GH_Mesh)
            {
                DA.GetData<Mesh>(0, ref M);
                M.Faces.ConvertQuadsToTriangles();
            }
            else
            {
                double L = 1.0;
                MeshingParameters MeshParams = new MeshingParameters();
                MeshParams.MaximumEdgeLength = 3 * L;
                MeshParams.MinimumEdgeLength = L;
                MeshParams.JaggedSeams = false;
                MeshParams.SimplePlanes = false;
                Brep SB = null;
                DA.GetData<Brep>(0, ref SB);
                Mesh[] BrepMeshes = Mesh.CreateFromBrep(SB, MeshParams);
                M = new Mesh();
                foreach (var mesh in BrepMeshes)
                    M.Append(mesh);
            }

            if (reset || initialized == false)
            {
                #region reset
                M.Faces.ConvertQuadsToTriangles();
                P = M.ToPlanktonMesh();

                initialized = true;

                AnchorV.Clear();
                FeatureV.Clear();
                FeatureE.Clear();

                //Mark any vertices or edges lying on features
                for (int i = 0; i < P.Vertices.Count; i++)
                {
                    Point3d Pt = P.Vertices[i].ToPoint3d();
                    AnchorV.Add(-1);
                    for (int j = 0; j < FV.Count; j++)
                    {
                        if (Pt.DistanceTo(FV[j]) < FixT)
                        { AnchorV[AnchorV.Count - 1] = j; }
                    }

                    FeatureV.Add(-1);
                    for (int j = 0; j < FC.Count; j++)
                    {
                        double param = new double();
                        FC[j].ClosestPoint(Pt, out param);
                        if (Pt.DistanceTo(FC[j].PointAt(param)) < FixT)
                        { FeatureV[FeatureV.Count - 1] = j; }
                    }
                }

                int EdgeCount = P.Halfedges.Count / 2;
                for (int i = 0; i < EdgeCount; i++)
                {
                    FeatureE.Add(-1);
                    int vStart = P.Halfedges[2 * i].StartVertex;
                    int vEnd = P.Halfedges[2 * i + 1].StartVertex;

                    Point3d PStart = P.Vertices[vStart].ToPoint3d();
                    Point3d PEnd = P.Vertices[vEnd].ToPoint3d();

                    for (int j = 0; j < FC.Count; j++)
                    {
                        double paramS = new double();
                        double paramE = new double();
                        Curve thisFC = FC[j];
                        thisFC.ClosestPoint(PStart, out paramS);
                        thisFC.ClosestPoint(PEnd, out paramE);
                        if ((PStart.DistanceTo(thisFC.PointAt(paramS)) < FixT) &&
                          (PEnd.DistanceTo(thisFC.PointAt(paramE)) < FixT))
                        {
                            FeatureE[FeatureE.Count - 1] = j;
                        }
                    }
                }
                #endregion
            }

            else
            {
                for (int iter = 0; iter < Iters; iter++)
                {
                    int EdgeCount = P.Halfedges.Count / 2;
                    double[] EdgeLength = P.Halfedges.GetLengths();
                    List<bool> Visited = new List<bool>();
                    Vector3d[] Normals = new Vector3d[P.Vertices.Count];

                    for (int i = 0; i < P.Vertices.Count; i++)
                    {
                        Visited.Add(false);
                        Normals[i] = Normal(P, i);
                    }

                    double t = LengthTol;     //a tolerance for when to split/collapse edges
                    double smooth = SmoothStrength;  //smoothing strength
                    double pull = PullStrength;  //pull to target mesh strength

                    // Split the edges that are too long
                    for (int i = 0; i < EdgeCount; i++)
                    {
                        if (P.Halfedges[2 * i].IsUnused == false)
                        {
                            int vStart = P.Halfedges[2 * i].StartVertex;
                            int vEnd = P.Halfedges[2 * i + 1].StartVertex;

                            if ((Visited[vStart] == false)
                              && (Visited[vEnd] == false))
                            {

                                double L2 = TargetLength.Calculate(P, 2 * i);

                                if (EdgeLength[2 * i] > (1 + t) * (4f / 3f) * L2)
                                {

                                    int SplitHEdge = P.Halfedges.TriangleSplitEdge(2 * i);
                                    if (SplitHEdge != -1)
                                    {
                                        int SplitCenter = P.Halfedges[SplitHEdge].StartVertex;
                                        P.Vertices.SetVertex(SplitCenter, MidPt(P, i));

                                        //update the feature information
                                        FeatureE.Add(FeatureE[i]);
                                        FeatureV.Add(FeatureE[i]);
                                        AnchorV.Add(-1);

                                        //2 additional new edges have also been created (or 1 if split was on a boundary)
                                        //mark these as non-features
                                        int CEdgeCount = P.Halfedges.Count / 2;
                                        while (FeatureE.Count < CEdgeCount)
                                        { FeatureE.Add(-1); }

                                        Visited.Add(true);
                                        int[] Neighbours = P.Vertices.GetVertexNeighbours(SplitCenter);
                                        foreach (int n in Neighbours)
                                        { Visited[n] = true; }
                                    }
                                }

                            }
                        }
                    }

                    //Collapse the edges that are too short
                    for (int i = 0; i < EdgeCount; i++)
                    {
                        if (P.Halfedges[2 * i].IsUnused == false)
                        {
                            int vStart = P.Halfedges[2 * i].StartVertex;
                            int vEnd = P.Halfedges[2 * i + 1].StartVertex;
                            if ((Visited[vStart] == false)
                              && (Visited[vEnd] == false))
                            {
                                if (!(AnchorV[vStart] != -1 && AnchorV[vEnd] != -1)) // if both ends are anchored, don't collapse
                                {
                                    int Collapse_option = 0; //0 for none, 1 for collapse to midpt, 2 for towards start, 3 for towards end
                                    //if neither are anchorV
                                    if (AnchorV[vStart] == -1 && AnchorV[vEnd] == -1)
                                    {
                                        // if both on same feature (or neither on a feature)
                                        if (FeatureV[vStart] == FeatureV[vEnd])
                                        { Collapse_option = 1; }
                                        // if start is on a feature and end isn't
                                        if ((FeatureV[vStart] != -1) && (FeatureV[vEnd] == -1))
                                        { Collapse_option = 2; }
                                        // if end is on a feature and start isn't
                                        if ((FeatureV[vStart] == -1) && (FeatureV[vEnd] != -1))
                                        { Collapse_option = 3; }
                                    }
                                    else // so one end must be an anchor
                                    {
                                        // if start is an anchor
                                        if (AnchorV[vStart] != -1)
                                        {
                                            // if both are on same feature, or if the end is not a feature
                                            if ((FeatureE[i] != -1) || (FeatureV[vEnd] == -1))
                                            { Collapse_option = 2; }
                                        }
                                        // if end is an anchor
                                        if (AnchorV[vEnd] != -1)
                                        {
                                            // if both are on same feature, or if the start is not a feature
                                            if ((FeatureE[i] != -1) || (FeatureV[vStart] == -1))
                                            { Collapse_option = 3; }
                                        }
                                    }

                                    Point3d Mid = MidPt(P, i);

                                    double L2 = TargetLength.Calculate(P, 2 * i);

                                    if ((Collapse_option != 0) && (EdgeLength[2 * i] < (1 - t) * 4f / 5f * L2))
                                    {
                                        int Collapsed = -1;
                                        int CollapseRtn = -1;
                                        if (Collapse_option == 1)
                                        {
                                            Collapsed = P.Halfedges[2 * i].StartVertex;
                                            P.Vertices.SetVertex(Collapsed, MidPt(P, i));
                                            CollapseRtn = P.Halfedges.CollapseEdge(2 * i);
                                        }
                                        if (Collapse_option == 2)
                                        {
                                            Collapsed = P.Halfedges[2 * i].StartVertex;
                                            CollapseRtn = P.Halfedges.CollapseEdge(2 * i);
                                        }
                                        if (Collapse_option == 3)
                                        {
                                            Collapsed = P.Halfedges[2 * i + 1].StartVertex;
                                            CollapseRtn = P.Halfedges.CollapseEdge(2 * i + 1);
                                        }
                                        if (CollapseRtn != -1)
                                        {
                                            int[] Neighbours = P.Vertices.GetVertexNeighbours(Collapsed);
                                            foreach (int n in Neighbours)
                                            { Visited[n] = true; }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    EdgeCount = P.Halfedges.Count / 2;

                    if ((Flip == 0) && (PullStrength > 0))
                    {
                        //Flip edges to reduce valence error
                        for (int i = 0; i < EdgeCount; i++)
                        {
                            if (!P.Halfedges[2 * i].IsUnused
                              && (P.Halfedges[2 * i].AdjacentFace != -1)
                              && (P.Halfedges[2 * i + 1].AdjacentFace != -1)
                              && (FeatureE[i] == -1)  // don't flip feature edges
                              )
                            {
                                int Vert1 = P.Halfedges[2 * i].StartVertex;
                                int Vert2 = P.Halfedges[2 * i + 1].StartVertex;
                                int Vert3 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i].NextHalfedge].NextHalfedge].StartVertex;
                                int Vert4 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i + 1].NextHalfedge].NextHalfedge].StartVertex;

                                int Valence1 = P.Vertices.GetValence(Vert1);
                                int Valence2 = P.Vertices.GetValence(Vert2);
                                int Valence3 = P.Vertices.GetValence(Vert3);
                                int Valence4 = P.Vertices.GetValence(Vert4);

                                if (P.Vertices.NakedEdgeCount(Vert1) > 0) { Valence1 += 2; }
                                if (P.Vertices.NakedEdgeCount(Vert2) > 0) { Valence2 += 2; }
                                if (P.Vertices.NakedEdgeCount(Vert3) > 0) { Valence3 += 2; }
                                if (P.Vertices.NakedEdgeCount(Vert4) > 0) { Valence4 += 2; }

                                int CurrentError =
                                  Math.Abs(Valence1 - 6) +
                                  Math.Abs(Valence2 - 6) +
                                  Math.Abs(Valence3 - 6) +
                                  Math.Abs(Valence4 - 6);
                                int FlippedError =
                                  Math.Abs(Valence1 - 7) +
                                  Math.Abs(Valence2 - 7) +
                                  Math.Abs(Valence3 - 5) +
                                  Math.Abs(Valence4 - 5);
                                if (CurrentError > FlippedError)
                                {
                                    P.Halfedges.FlipEdge(2 * i);
                                }
                            }
                        }
                    }
                    else
                    {
                        //Flip edges based on angle
                        for (int i = 0; i < EdgeCount; i++)
                        {
                            if (!P.Halfedges[2 * i].IsUnused
                              && (P.Halfedges[2 * i].AdjacentFace != -1)
                              && (P.Halfedges[2 * i + 1].AdjacentFace != -1)
                              && (FeatureE[i] == -1) // don't flip feature edges
                              )
                            {
                                int Vert1 = P.Halfedges[2 * i].StartVertex;
                                int Vert2 = P.Halfedges[2 * i + 1].StartVertex;
                                int Vert3 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i].NextHalfedge].NextHalfedge].StartVertex;
                                int Vert4 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i + 1].NextHalfedge].NextHalfedge].StartVertex;

                                Point3d P1 = P.Vertices[Vert1].ToPoint3d();
                                Point3d P2 = P.Vertices[Vert2].ToPoint3d();
                                Point3d P3 = P.Vertices[Vert3].ToPoint3d();
                                Point3d P4 = P.Vertices[Vert4].ToPoint3d();

                                double A1 = Vector3d.VectorAngle(new Vector3d(P3 - P1), new Vector3d(P4 - P1))
                                  + Vector3d.VectorAngle(new Vector3d(P4 - P2), new Vector3d(P3 - P2));

                                double A2 = Vector3d.VectorAngle(new Vector3d(P1 - P4), new Vector3d(P2 - P4))
                                  + Vector3d.VectorAngle(new Vector3d(P2 - P3), new Vector3d(P1 - P3));

                                if (A2 > A1)
                                {
                                    P.Halfedges.FlipEdge(2 * i);
                                }
                            }
                        }
                    }

                    if (Minim)
                    {
                        Vector3d[] SmoothC = LaplacianSmooth(P, 1, smooth);

                        for (int i = 0; i < P.Vertices.Count; i++)
                        {
                            if (AnchorV[i] == -1) // don't smooth feature vertices
                            {
                                P.Vertices.MoveVertex(i, 0.5 * SmoothC[i]);
                            }
                        }
                    }

                    Vector3d[] Smooth = LaplacianSmooth(P, 0, smooth);

                    for (int i = 0; i < P.Vertices.Count; i++)
                    {
                        if (AnchorV[i] == -1) // don't smooth feature vertices
                        {
                            // make it tangential only
                            Vector3d VNormal = Normal(P, i);
                            double ProjLength = Smooth[i] * VNormal;
                            Smooth[i] = Smooth[i] - (VNormal * ProjLength);

                            P.Vertices.MoveVertex(i, Smooth[i]);

                            if (P.Vertices.NakedEdgeCount(i) != 0)//special smoothing for feature edges
                            {
                                int[] Neighbours = P.Vertices.GetVertexNeighbours(i);
                                int ncount = 0;
                                Point3d Avg = new Point3d();

                                for (int j = 0; j < Neighbours.Length; j++)
                                {
                                    if (P.Vertices.NakedEdgeCount(Neighbours[j]) != 0)
                                    {
                                        ncount++;
                                        Avg = Avg + P.Vertices[Neighbours[j]].ToPoint3d();
                                    }
                                }
                                Avg = Avg * (1.0 / ncount);
                                Vector3d move = Avg - P.Vertices[i].ToPoint3d();
                                move = move * smooth;
                                P.Vertices.MoveVertex(i, move);
                            }

                            if (FeatureV[i] != -1)//special smoothing for feature edges
                            {
                                int[] Neighbours = P.Vertices.GetVertexNeighbours(i);
                                int ncount = 0;
                                Point3d Avg = new Point3d();

                                for (int j = 0; j < Neighbours.Length; j++)
                                {
                                    if ((FeatureV[Neighbours[j]] == FeatureV[i]) || (AnchorV[Neighbours[j]] != -1))
                                    {
                                        ncount++;
                                        Avg = Avg + P.Vertices[Neighbours[j]].ToPoint3d();
                                    }
                                }
                                Avg = Avg * (1.0 / ncount);
                                Vector3d move = Avg - P.Vertices[i].ToPoint3d();
                                move = move * smooth;
                                P.Vertices.MoveVertex(i, move);
                            }

                            //projecting points onto the target along their normals

                            if (pull > 0)
                            {
                                Point3d Point = P.Vertices[i].ToPoint3d();
                                Vector3d normal = Normal(P, i);
                                Ray3d Ray1 = new Ray3d(Point, normal);
                                Ray3d Ray2 = new Ray3d(Point, -normal);
                                double RayPt1 = Rhino.Geometry.Intersect.Intersection.MeshRay(M, Ray1);
                                double RayPt2 = Rhino.Geometry.Intersect.Intersection.MeshRay(M, Ray2);
                                Point3d ProjectedPt;

                                if ((RayPt1 < RayPt2) && (RayPt1 > 0) && (RayPt1 < 1.0))
                                {
                                    ProjectedPt = Point * (1 - pull) + pull * Ray1.PointAt(RayPt1);
                                }
                                else if ((RayPt2 < RayPt1) && (RayPt2 > 0) && (RayPt2 < 1.0))
                                {
                                    ProjectedPt = Point * (1 - pull) + pull * Ray2.PointAt(RayPt2);
                                }
                                else
                                {
                                    ProjectedPt = Point * (1 - pull) + pull * M.ClosestPoint(Point);
                                }

                                P.Vertices.SetVertex(i, ProjectedPt);
                            }

                            if (FeatureV[i] != -1) //pull feature vertices onto feature curves
                            {
                                Point3d Point = P.Vertices[i].ToPoint3d();
                                Curve CF = FC[FeatureV[i]];
                                double param1 = 0.0;
                                Point3d onFeature = new Point3d();
                                CF.ClosestPoint(Point, out param1);
                                onFeature = CF.PointAt(param1);
                                P.Vertices.SetVertex(i, onFeature);
                            }
                        }
                        else
                        {
                            P.Vertices.SetVertex(i, FV[AnchorV[i]]); //pull anchor vertices onto their points
                        }
                    }

                    //end new

                    AnchorV = CompactByVertex(P, AnchorV); //compact the fixed points along with the vertices
                    FeatureV = CompactByVertex(P, FeatureV);
                    FeatureE = CompactByEdge(P, FeatureE);

                    P.Compact(); //this cleans the mesh data structure of unused elements
                }

            }

            DA.SetData(0, P);
        }
예제 #31
0
        /// <summary>
        /// Creates a Plankton halfedge mesh from a Rhino mesh.
        /// Uses the topology of the Rhino mesh directly.
        /// </summary>
        /// <returns>A <see cref="PlanktonMesh"/> which represents the topology and geometry of the source mesh.</returns>
        /// <param name="source">A Rhino mesh to convert from.</param>
        public static PlanktonMesh ToPlanktonMesh(this Mesh source)
        {
            PlanktonMesh pMesh = new PlanktonMesh();

            source.Vertices.CombineIdentical(true, true);
            source.Vertices.CullUnused();
            source.UnifyNormals();
            source.Weld(Math.PI);

            foreach (Point3f v in source.TopologyVertices)
            {
                pMesh.Vertices.Add(v.X, v.Y, v.Z);
            }

            for (int i = 0; i < source.Faces.Count; i++)
            {
                pMesh.Faces.Add(new PlanktonFace());
            }

            for (int i = 0; i < source.TopologyEdges.Count; i++)
            {
                PlanktonHalfedge HalfA = new PlanktonHalfedge();

                HalfA.StartVertex = source.TopologyEdges.GetTopologyVertices(i).I;

                if (pMesh.Vertices [HalfA.StartVertex].OutgoingHalfedge == -1) {
                    pMesh.Vertices [HalfA.StartVertex].OutgoingHalfedge = pMesh.Halfedges.Count;
                }

                PlanktonHalfedge HalfB = new PlanktonHalfedge();

                HalfB.StartVertex = source.TopologyEdges.GetTopologyVertices(i).J;

                if (pMesh.Vertices [HalfB.StartVertex].OutgoingHalfedge == -1) {
                    pMesh.Vertices [HalfB.StartVertex].OutgoingHalfedge = pMesh.Halfedges.Count + 1;
                }

                bool[] Match;
                int[] ConnectedFaces = source.TopologyEdges.GetConnectedFaces(i, out Match);

                //Note for Steve Baer : This Match bool doesn't seem to work on triangulated meshes - it often returns true
                //for both faces, even for a properly oriented manifold mesh, which can't be right
                //So - making our own check for matching:
                //(I suspect the problem is related to C being the same as D for triangles, so best to
                //deal with them separately just to make sure)
                //loop through the vertices of the face until finding the one which is the same as the start of the edge
                //iff the next vertex around the face is the end of the edge then it matches.

                Match[0] = false;
                if (Match.Length > 1)
                {Match[1] = true;}

                int VertA = source.TopologyVertices.TopologyVertexIndex(source.Faces[ConnectedFaces[0]].A);
                int VertB = source.TopologyVertices.TopologyVertexIndex(source.Faces[ConnectedFaces[0]].B);
                int VertC = source.TopologyVertices.TopologyVertexIndex(source.Faces[ConnectedFaces[0]].C);
                int VertD = source.TopologyVertices.TopologyVertexIndex(source.Faces[ConnectedFaces[0]].D);

                if ((VertA == source.TopologyEdges.GetTopologyVertices(i).I)
                    && (VertB == source.TopologyEdges.GetTopologyVertices(i).J))
                { Match[0] = true;
                }
                if ((VertB == source.TopologyEdges.GetTopologyVertices(i).I)
                    && (VertC == source.TopologyEdges.GetTopologyVertices(i).J))
                {
                    Match[0] = true;
                }
                if ((VertC == source.TopologyEdges.GetTopologyVertices(i).I)
                    && (VertD == source.TopologyEdges.GetTopologyVertices(i).J))
                {
                    Match[0] = true;
                }
                if ((VertD == source.TopologyEdges.GetTopologyVertices(i).I)
                    && (VertA == source.TopologyEdges.GetTopologyVertices(i).J))
                {
                    Match[0] = true;
                }
                //I don't think these next 2 should ever be needed, but just in case:
                if ((VertC == source.TopologyEdges.GetTopologyVertices(i).I)
                    && (VertA == source.TopologyEdges.GetTopologyVertices(i).J))
                {
                    Match[0] = true;
                }
                if ((VertB == source.TopologyEdges.GetTopologyVertices(i).I)
                    && (VertD == source.TopologyEdges.GetTopologyVertices(i).J))
                {
                    Match[0] = true;
                }

                if (Match[0] == true)
                {
                    HalfA.AdjacentFace = ConnectedFaces[0];
                    if (pMesh.Faces[HalfA.AdjacentFace].FirstHalfedge == -1) {
                        pMesh.Faces[HalfA.AdjacentFace].FirstHalfedge = pMesh.Halfedges.Count;
                    }
                    if (ConnectedFaces.Length > 1)
                    {
                        HalfB.AdjacentFace = ConnectedFaces[1];
                        if (pMesh.Faces[HalfB.AdjacentFace].FirstHalfedge == -1) {
                            pMesh.Faces[HalfB.AdjacentFace].FirstHalfedge = pMesh.Halfedges.Count + 1;
                        }
                    }
                    else
                    {
                        HalfB.AdjacentFace = -1;
                        pMesh.Vertices[HalfB.StartVertex].OutgoingHalfedge = pMesh.Halfedges.Count + 1;
                    }
                }
                else
                {
                    HalfB.AdjacentFace = ConnectedFaces[0];

                    if (pMesh.Faces[HalfB.AdjacentFace].FirstHalfedge == -1) {
                        pMesh.Faces[HalfB.AdjacentFace].FirstHalfedge = pMesh.Halfedges.Count + 1;
                    }

                    if (ConnectedFaces.Length > 1)
                    {
                        HalfA.AdjacentFace = ConnectedFaces[1];

                        if (pMesh.Faces[HalfA.AdjacentFace].FirstHalfedge == -1) {
                            pMesh.Faces[HalfA.AdjacentFace].FirstHalfedge = pMesh.Halfedges.Count;
                        }
                    }
                    else
                    {
                        HalfA.AdjacentFace = -1;
                        pMesh.Vertices[HalfA.StartVertex].OutgoingHalfedge = pMesh.Halfedges.Count;
                    }
                }
                pMesh.Halfedges.Add(HalfA);
                pMesh.Halfedges.Add(HalfB);
            }

            for (int i = 0; i < (pMesh.Halfedges.Count); i += 2)
            {
                int[] EndNeighbours = source.TopologyVertices.ConnectedTopologyVertices(pMesh.Halfedges[i + 1].StartVertex, true);
                for (int j = 0; j < EndNeighbours.Length; j++)
                {
                    if(EndNeighbours[j] == pMesh.Halfedges[i].StartVertex)
                    {
                        int EndOfNextHalfedge = EndNeighbours[(j - 1 + EndNeighbours.Length) % EndNeighbours.Length];
                        int StartOfPrevOfPairHalfedge = EndNeighbours[(j + 1) % EndNeighbours.Length];

                        int NextEdge = source.TopologyEdges.GetEdgeIndex(pMesh.Halfedges[i + 1].StartVertex,EndOfNextHalfedge);
                        int PrevPairEdge = source.TopologyEdges.GetEdgeIndex(pMesh.Halfedges[i + 1].StartVertex,StartOfPrevOfPairHalfedge);

                        if (source.TopologyEdges.GetTopologyVertices(NextEdge).I == pMesh.Halfedges[i + 1].StartVertex) {
                            pMesh.Halfedges[i].NextHalfedge = NextEdge * 2;
                        } else {
                            pMesh.Halfedges[i].NextHalfedge = NextEdge * 2 + 1;
                        }

                        if (source.TopologyEdges.GetTopologyVertices(PrevPairEdge).J == pMesh.Halfedges[i + 1].StartVertex) {
                            pMesh.Halfedges[i + 1].PrevHalfedge = PrevPairEdge * 2;
                        } else {
                            pMesh.Halfedges[i + 1].PrevHalfedge = PrevPairEdge * 2+1;
                        }
                        break;
                    }
                }

                int[] StartNeighbours = source.TopologyVertices.ConnectedTopologyVertices(pMesh.Halfedges[i].StartVertex, true);
                for (int j = 0; j < StartNeighbours.Length; j++)
                {
                    if (StartNeighbours[j] == pMesh.Halfedges[i+1].StartVertex)
                    {
                        int EndOfNextOfPairHalfedge = StartNeighbours[(j - 1 + StartNeighbours.Length) % StartNeighbours.Length];
                        int StartOfPrevHalfedge = StartNeighbours[(j + 1) % StartNeighbours.Length];

                        int NextPairEdge = source.TopologyEdges.GetEdgeIndex(pMesh.Halfedges[i].StartVertex, EndOfNextOfPairHalfedge);
                        int PrevEdge = source.TopologyEdges.GetEdgeIndex(pMesh.Halfedges[i].StartVertex, StartOfPrevHalfedge);

                        if (source.TopologyEdges.GetTopologyVertices(NextPairEdge).I == pMesh.Halfedges[i].StartVertex) {
                            pMesh.Halfedges[i + 1].NextHalfedge = NextPairEdge * 2;
                        } else {
                            pMesh.Halfedges[i + 1].NextHalfedge = NextPairEdge * 2 + 1;
                        }

                        if (source.TopologyEdges.GetTopologyVertices(PrevEdge).J == pMesh.Halfedges[i].StartVertex) {
                            pMesh.Halfedges[i].PrevHalfedge = PrevEdge * 2;
                        } else {
                            pMesh.Halfedges[i].PrevHalfedge = PrevEdge * 2 + 1;
                        }
                        break;
                    }
                }
            }

            return pMesh;
        }
예제 #32
0
        private List<int> CompactByEdge(PlanktonMesh P, List<int> L1)
        {
            List<int> L2 = new List<int>();

            int EdgeCount = P.Halfedges.Count / 2;

            for (int i = 0; i < EdgeCount; i++)
            {
                if (P.Halfedges[2 * i].IsUnused == false)
                {
                    L2.Add(L1[i]);
                }
            }
            return L2;
        }
예제 #33
0
 /// <summary>
 /// Gets positions of vertices
 /// </summary>
 /// <returns>A list of Point3d</returns>
 /// <param name="source">A Plankton mesh.</param>
 public static IEnumerable <Point3d> GetPositions(this PlanktonMesh source)
 {
     return(Enumerable.Range(0, source.Vertices.Count).Select(i => source.Vertices[i].ToPoint3d()));
 }
예제 #34
0
        private double CreaseAngle(PlanktonMesh P, int HE)
        {
            if (P.Halfedges[HE].IsUnused)
            { return -1; }
            else
            {
                int Pair = P.Halfedges.GetPairHalfedge(HE);
                if (P.Halfedges[HE].AdjacentFace == -1 || P.Halfedges[Pair].AdjacentFace == -1)
                { return 0; }
                else
                {
                    int Vert1 = P.Halfedges[HE].StartVertex;
                    int Vert2 = P.Halfedges[Pair].StartVertex;
                    int Vert3 = P.Halfedges[P.Halfedges[P.Halfedges[HE].NextHalfedge].NextHalfedge].StartVertex;
                    int Vert4 = P.Halfedges[P.Halfedges[P.Halfedges[Pair].NextHalfedge].NextHalfedge].StartVertex;

                    Point3d P1 = P.Vertices[Vert1].ToPoint3d();
                    Point3d P2 = P.Vertices[Vert2].ToPoint3d();
                    Point3d P3 = P.Vertices[Vert3].ToPoint3d();
                    Point3d P4 = P.Vertices[Vert4].ToPoint3d();

                    Vector3d ThisEdge = P2 - P1;
                    Vector3d Edge1 = P3 - P1;
                    Vector3d Edge2 = P4 - P1;

                    Vector3d Normal1 = Vector3d.CrossProduct(ThisEdge, Edge1);
                    Vector3d Normal2 = Vector3d.CrossProduct(Edge2, ThisEdge);

                    return (Vector3d.VectorAngle(Normal1, Normal2));
                }
            }
        }
예제 #35
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PlanktonFaceList"/> class.
 /// Should be called from the mesh constructor.
 /// </summary>
 /// <param name="owner">The mesh to which this list of half-edges belongs.</param>
 internal PlanktonFaceList(PlanktonMesh owner)
 {
     this._list = new List <PlanktonFace>();
     this._mesh = owner;
 }
예제 #36
0
        private Vector3d Normal(PlanktonMesh P, int V)
        {
            Point3d Vertex = P.Vertices[V].ToPoint3d();
            Vector3d Norm = new Vector3d();

            int[] OutEdges = P.Vertices.GetHalfedges(V);
            int[] Neighbours = P.Vertices.GetVertexNeighbours(V);
            Vector3d[] OutVectors = new Vector3d[Neighbours.Length];
            int Valence = P.Vertices.GetValence(V);

            for (int j = 0; j < Valence; j++)
            {
                OutVectors[j] = P.Vertices[Neighbours[j]].ToPoint3d() - Vertex;
            }

            for (int j = 0; j < Valence; j++)
            {
                if (P.Halfedges[OutEdges[(j + 1) % Valence]].AdjacentFace != -1)
                {
                    Norm += (Vector3d.CrossProduct(OutVectors[(j + 1) % Valence], OutVectors[j]));
                }
            }

            Norm.Unitize();
            return Norm;
        }
예제 #37
0
		public PolyMesh()
		{
			geometry = new PlanktonMesh();
		}