public Vector3 CalcMidpoint() { Vector3 accum = Vector3.zero; int ct = 0; if (edges.Count >= 3) // Sanity check { WEdge eStart = this.edges[0]; accum += eStart.GetEdgeVert(this).position; ++ct; for ( WEdge eIt = eStart.GetConnectingEdge(this); eIt != eStart; eIt = eIt.GetConnectingEdge(this)) { accum += eIt.GetEdgeVert(this).position; ++ct; } } if (ct == 0) { return(Vector3.zero); } return(accum / (float)ct); }
public WGraph <T, TOp, WGraphNode <T, WEdge <T> >, WEdge <T> > ToGraph() { var res = new WGraphNode <T, WEdge <T> > [edgeContainer.Length]; var csr = edgeContainer.ToCSR(); var counter = new int[res.Length]; var rootCounter = edgeContainer.IsDirected ? new int[res.Length] : counter; var children = new WEdge <T> [res.Length][]; var roots = edgeContainer.IsDirected ? new WEdge <T> [res.Length][] : children; for (int i = 0; i < res.Length; i++) { if (children[i] == null) { children[i] = new WEdge <T> [edgeContainer.sizes[i]]; } if (roots[i] == null) { roots[i] = new WEdge <T> [edgeContainer.rootSizes[i]]; } res[i] = new WGraphNode <T, WEdge <T> >(i, roots[i], children[i]); foreach (ref var e in csr.EList.AsSpan(csr.Start[i], csr.Start[i + 1] - csr.Start[i])) { var to = e.To; if (roots[to] == null) { roots[to] = new WEdge <T> [edgeContainer.rootSizes[to]]; } children[i][counter[i]++] = e; roots[to][rootCounter[to]++] = e.Reversed(i); } } return(new WGraph <T, TOp, WGraphNode <T, WEdge <T> >, WEdge <T> >(res, csr)); }
public WEdge AddBlankEdge() { WEdge e = new WEdge(); e.selfNode = this.edges.AddLast(e); return(e); }
public bool SetEdgeFromFace(WEdge e, Face f) { if (this.conA.face == f) { this.conA.edge = e; return(true); } if (this.conB.face == f) { this.conB.edge = e; return(true); } return(false); }
void SimpleTriangulate() { List <Face> origFaces = new List <Face>(this.faces); foreach (Face f in origFaces) { if (f.edges.Count <= 3) { break; } List <WEdge> origEdges = new List <WEdge>(f.edges); // Created edges that will be used as part of the next triangle in the fan WEdge sE = null; // Processing the first triangle of the fan is a bit different // than the rest. // TODO: } }
public void Clear() { while (this.edges.Count != 0) { WEdge e = this.edges.First.Value; e.conA.edge = null; e.conA.face = null; e.conA.vert = null; e.conB.edge = null; e.conB.face = null; e.conB.vert = null; e.selfNode = null; this.edges.RemoveFirst(); } while (this.vertices.Count != 0) { Vert v = this.vertices.First.Value; v.edges.Clear(); v.selfNode = null; this.vertices.RemoveFirst(); } while (this.faces.Count != 0) { Face f = this.faces.First.Value; f.edges.Clear(); f.selfNode = null; f.edges.Clear(); } }
public Face CreateFace(params Vector3 [] rv3s) { List <Vert> verts = new List <Vert>(); foreach (Vector3 v in rv3s) { verts.Add(this.GetVert(v)); } Face f = this.shape.AddBlankFace(); for (int i = 0; i < verts.Count; ++i) { WEdge we; Vert vCur = verts[i]; Vert vNxt = verts[(i + 1) % verts.Count]; if (this.knownEdgeFromVerts.TryGetValue(new TwoVert(vCur, vNxt), out we) == true) { if (we.conA.face == null || we.conB.face != null) { } // Throw error we.conB.face = f; } else { we = this.shape.AddBlankEdge(); this.knownEdgeFromVerts.Add(new TwoVert(vCur, vNxt), we); vCur.edges.Add(we); vNxt.edges.Add(we); we.conA.vert = vCur; we.conB.vert = vNxt; we.conA.face = f; } f.edges.Add(we); } // Define the faceloop for (int i = 0; i < f.edges.Count; ++i) { // At this point, the size of edges and verts should be the same size, // with WEdge we = f.edges[i]; Vert v = verts[i]; WEdge weNext = f.edges[(i + 1) % f.edges.Count]; if (we.conA.face == f) { we.conA.edge = weNext; } else if (we.conB.face == f) { we.conB.edge = weNext; } else { // Throw error } } return(f); }
public VertEdgeCon(Vert vert, WEdge edge, Face face) { this.vert = vert; this.edge = edge; this.face = face; }
public Shape Clone() { Shape sret = new Shape(); // Create a map, where we can reference an old element and know what the // equivalent is in the new clone. Dictionary <Vert, Vert> oldToNewVert = new Dictionary <Vert, Vert>(); Dictionary <WEdge, WEdge> oldToNewEdge = new Dictionary <WEdge, WEdge>(); Dictionary <Face, Face> oldToNewFace = new Dictionary <Face, Face>(); // Start copying elements to fill the maps. foreach (Vert v in this.vertices) { oldToNewVert.Add(v, sret.AddVertice(v.position)); } foreach (WEdge e in this.edges) { oldToNewEdge.Add(e, sret.AddBlankEdge()); } foreach (Face f in this.faces) { oldToNewFace.Add(f, sret.AddBlankFace()); } // Now that we have everything that could be referenced when constructing // the clone, start making the equivalent cloned connections. foreach (KeyValuePair <Vert, Vert> kvpv in oldToNewVert) { Vert oldV = kvpv.Key; Vert newV = kvpv.Value; foreach (WEdge e in oldV.edges) { newV.edges.Add(oldToNewEdge[e]); } } foreach (KeyValuePair <WEdge, WEdge> kvpe in oldToNewEdge) { WEdge oldE = kvpe.Key; WEdge newE = kvpe.Value; // Transfer mapped conA stuff if (oldE.conA.edge != null) { newE.conA.edge = oldToNewEdge[oldE.conA.edge]; } if (oldE.conA.face != null) { newE.conA.face = oldToNewFace[oldE.conA.face]; } if (oldE.conA.vert != null) { newE.conA.vert = oldToNewVert[oldE.conA.vert]; } // Transfer mapped conB stuff if (oldE.conB.edge != null) { newE.conB.edge = oldToNewEdge[oldE.conB.edge]; } if (oldE.conB.face != null) { newE.conB.face = oldToNewFace[oldE.conB.face]; } if (oldE.conB.vert != null) { newE.conB.vert = oldToNewVert[oldE.conB.vert]; } } foreach (KeyValuePair <Face, Face> kvpf in oldToNewFace) { Face oldF = kvpf.Key; Face newF = kvpf.Value; foreach (WEdge e in oldF.edges) { newF.edges.Add(oldToNewEdge[e]); } } return(sret); }
public Mesh GenerateMesh() { // Convert unique verts to an array of Vector3 that can be // int indexable. List <Vector3> mverts = new List <Vector3>(); Dictionary <Vert, int> vlookup = new Dictionary <Vert, int>(); foreach (Vert v in this.vertices) { vlookup.Add(v, mverts.Count); mverts.Add(v.position); } // Convert the polygons into faces List <int> tris = new List <int>(); foreach (Face f in this.faces) { List <int> facevertidxs = new List <int>(); // An edge can have two faces comming off if it, so an edge // has two faces assigned to it. Which edge and edge loop do we // trace to create the face? WEdge startingEdge = null; for (WEdge wit = f.edges[0]; wit != startingEdge; /*adv done in loop*/) { WEdge next = null; if (wit.conA.face == f) { facevertidxs.Add(vlookup[wit.conA.vert]); next = wit.conA.edge; } else if (wit.conB.face == f) { facevertidxs.Add(vlookup[wit.conB.vert]); next = wit.conB.edge; } else { } // TODO: Throw error if (startingEdge == null) { startingEdge = wit; } wit = next; } // This shouldn't happen unless we're in a degenerate state if (facevertidxs.Count < 3) { continue; } else if (facevertidxs.Count == 3) { // Just append them in directly - no need for extra complicated code. tris.AddRange(facevertidxs); } else { // For else we need to tesselate the polygon into triangles. For now we're just going // to be simple and direct, do a triangle fan tesselation, using the first point as a pivot. int pivot = facevertidxs[0]; for ( int i = 1; // The first point is already accounted for in pivot i < facevertidxs.Count - 1; // We can only process points that aren't the last one. ++i) { tris.Add(pivot); tris.Add(facevertidxs[i + 0]); tris.Add(facevertidxs[i + 1]); } } } Mesh m = new Mesh(); if (mverts.Count != 0 && tris.Count != 0) { m.subMeshCount = 1; m.vertices = mverts.ToArray(); m.SetIndices(tris.ToArray(), MeshTopology.Triangles, 0); //m.RecalculateNormals(); m.RecalculateBounds(); } return(m); }
public bool CollapseSingleEdge(WEdge e) { return(false); // !TODO }
public void SimpleSubdivide() { Dictionary <WEdge, Vert> midEdge = new Dictionary <WEdge, Vert>(); Dictionary <Face, Vert> midFace = new Dictionary <Face, Vert>(); // We need to record what we're starting out with, because as we subdivide, // it's going to change those containers List <WEdge> startingEdges = new List <WEdge>(this.edges); List <Face> startingFaces = new List <Face>(this.faces); // Edge centroids foreach (WEdge e in startingEdges) { this.edges.Remove(e.selfNode); if (e.conA.vert != null) { e.conA.vert.edges.Remove(e); } if (e.conB.vert != null) { e.conB.vert.edges.Remove(e); } // Centroid Vert v = this.AddVertice(e.CalcMidpoint()); midEdge[e] = v; WEdge e1 = this.AddBlankEdge(); WEdge e2 = this.AddBlankEdge(); // Subdivision v.edges.Add(e1); v.edges.Add(e2); // Set them to the old faces (new faces don't exist yet) // we do this, so later on we can identify them. e1.conA.face = e.conA.face; e2.conA.face = e.conA.face; e1.conB.face = e.conB.face; e2.conB.face = e.conB.face; // Define the verts for the edges e1.conA.vert = e.conA.vert; e1.conB.vert = v; // Define the verts for the edges e2.conA.vert = v; e2.conB.vert = e.conB.vert; } // Face centroids foreach (Face f in startingFaces) { this.faces.Remove(f.selfNode); // Create subdivided centroid vert. Vert v = this.AddVertice(f.CalcMidpoint()); midFace[f] = v; foreach (WEdge e in f.edges) { WEdge enew = this.AddBlankEdge(); enew.conA.vert = v; enew.conB.vert = midEdge[e]; v.edges.Add(enew); midEdge[e].edges.Add(enew); } } foreach (Face f in startingFaces) { // The edges in a vertice aren't in a certain order, but // there's a property we can leverage Vert v = midFace[f]; for (int i = 0; i < v.edges.Count; ++i) { int nextIdx = (i + 1) % v.edges.Count; WEdge oldEdge = f.edges[i]; WEdge oldEdgeNext = f.edges[nextIdx]; // the subdividing vert for oldEdge Vert subdivVert = midEdge[oldEdge]; Vert subdivVertNext = midEdge[oldEdgeNext]; // New edge from centroid vert to subdivVert WEdge e0 = v.edges[i]; WEdge e1 = subdivVert.EdgeWithFaceAndNotVert(f, oldEdge.GetEdgeVert(f)); WEdge e2 = subdivVertNext.EdgeWithFaceAndVert(f, oldEdgeNext.GetEdgeVert(f)); WEdge e3 = v.edges[nextIdx]; Face fnew = this.AddBlankFace(); // Add edges fnew.edges.Add(e0); fnew.edges.Add(e1); fnew.edges.Add(e2); fnew.edges.Add(e3); // Assemble the edge loop e0.conA.edge = e1; e0.conA.face = fnew; // e1.ReplaceFace(f, fnew); e1.SetEdgeFromFace(e2, fnew); // e2.ReplaceFace(f, fnew); e2.SetEdgeFromFace(e3, fnew); // e3.conB.edge = e0; e3.conB.face = fnew; } } }