private void LowerFaces() { cFace f = Faces.head; /*int z;*/ int Flower = 0; /* Total number of lower faces. */ do { /*z = Normz( f ); * if ( z < 0 ) {*/ if (Normz(f) < 0) { Flower++; f.lower = true; System.Diagnostics.Debug.WriteLine("lower face indices: " + f.Vertices[0].IndexInModel + ", " + f.Vertices[1].IndexInModel + ", " + f.Vertices[2].IndexInModel); } else { f.lower = false; } f = f.next; } while (f != Faces.head); System.Diagnostics.Debug.WriteLine("A total of " + Flower + " lower faces identified."); }
public void InitHead(cFace h) { head = new cFace(); head = h; head.next = head.prev = head; n = 1; }
public cFace MakeNullFace() { cFace f = new cFace(); InsertBeforeHead(f); return(f); }
/*--------------------------------------------------------------------- * MakeFace creates a new face structure from three vertices (in ccw * order). It returns a pointer to the face. * ---------------------------------------------------------------------*/ protected cFace MakeFace(cVertex v0, cVertex v1, cVertex v2, cFace fold) { cFace f; cEdge e0, e1, e2; /* Create edges of the initial triangle. */ if (fold == null) { e0 = Edges.MakeNullEdge(); e1 = Edges.MakeNullEdge(); e2 = Edges.MakeNullEdge(); } else { /* Copy from fold, in reverse order. */ e0 = fold.Edges[2]; e1 = fold.Edges[1]; e2 = fold.Edges[0]; } e0.Endpts[0] = v0; e0.Endpts[1] = v1; e1.Endpts[0] = v1; e1.Endpts[1] = v2; e2.Endpts[0] = v2; e2.Endpts[1] = v0; /* Create face for triangle. */ f = Faces.MakeNullFace(); f.Edges[0] = e0; f.Edges[1] = e1; f.Edges[2] = e2; f.Vertices[0] = v0; f.Vertices[1] = v1; f.Vertices[2] = v2; /* Link edges to face. */ e0.Adjface[0] = e1.Adjface[0] = e2.Adjface[0] = f; return(f); }
/*--------------------------------------------------------------------- * Volumed is the same as VolumeSign but computed with doubles. For * protection against overflow. * ---------------------------------------------------------------------*/ protected double Volumed(cFace f, cVertex p) { double vol; double ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz; double bxdx, bydy, bzdz, cxdx, cydy, czdz; ax = f.Vertices[0].Point.X; ay = f.Vertices[0].Point.Y; az = f.Vertices[0].Point.Z; bx = f.Vertices[1].Point.X; by = f.Vertices[1].Point.Y; bz = f.Vertices[1].Point.Z; cx = f.Vertices[2].Point.X; cy = f.Vertices[2].Point.Y; cz = f.Vertices[2].Point.Z; dx = p.Point.X; dy = p.Point.Y; dz = p.Point.Z; bxdx = bx - dx; bydy = by - dy; bzdz = bz - dz; cxdx = cx - dx; cydy = cy - dy; czdz = cz - dz; vol = (az - dz) * (bxdx * cydy - bydy * cxdx) + (ay - dy) * (bzdz * cxdx - bxdx * czdz) + (ax - dx) * (bydy * czdz - bzdz * cydy); return(vol); }
/*--------------------------------------------------------------------- * Computes the z-coordinate of the vector normal to face f. * ---------------------------------------------------------------------*/ protected double Normz(cFace f) { cVertex a, b, c; /*double ba0, ca1, ba1, ca0,z;*/ a = f.Vertices[0]; b = f.Vertices[1]; c = f.Vertices[2]; /* * ba0 = ( b.v.x - a.v.x ); * ca1 = ( c.v.y - a.v.y ); * ba1 = ( b.v.y - a.v.y ); * ca0 = ( c.v.x - a.v.x ); * * z = ba0 * ca1 - ba1 * ca0; * System.Diagnostics.Debug.WriteLine("Normz = %lf=%g\n", z,z); * if ( z > 0.0 ) return 1; * else if ( z < 0.0 ) return -1; * else return 0; */ return ((b.Point.X - a.Point.X) * (c.Point.Y - a.Point.Y) - (b.Point.Y - a.Point.Y) * (c.Point.X - a.Point.X)); }
public void ClearFaceList() { if (head != null) { head = null; } n = 0; }
public cFace() { Edges = new cEdge[3]; Edges[0] = Edges[1] = Edges[2] = null; Vertices = new cVertex[3]; Vertices[0] = Vertices[1] = Vertices[2] = null; visible = lower = false; next = prev = null; }
/*--------------------------------------------------------------------- * doubleTriangle builds the initial double triangle. It first finds 3 * noncollinear points and makes two faces out of them, in opposite order. * It then finds a fourth point that is not coplanar with that face. The * pointCloud are stored in the face structure in counterclockwise order so * that the volume between the face and the point is negative. Lastly, the * 3 newfaces to the fourth point are constructed and the data structures * are cleaned up. * ---------------------------------------------------------------------*/ private bool doubleTriangle() { cVertex v0, v1, v2, v3;//;, t; cFace f0, f1 = null; double vol; /* Find 3 non-Collinear points. */ v0 = Vertices.head; while (Collinear(v0, v0.NextVertex, v0.NextVertex.NextVertex)) { if ((v0 = v0.NextVertex) == Vertices.head) { System.Diagnostics.Debug.WriteLine("doubleTriangle: All points are Collinear!"); return(false); } } v1 = v0.NextVertex; v2 = v1.NextVertex; /* Mark the pointCloud as processed. */ v0.IsProcessed = PROCESSED; v1.IsProcessed = PROCESSED; v2.IsProcessed = PROCESSED; /* Create the two "twin" faces. */ f0 = MakeFace(v0, v1, v2, f1); f1 = MakeFace(v2, v1, v0, f0); /* Link adjacent face fields. */ f0.Edges[0].Adjface[1] = f1; f0.Edges[1].Adjface[1] = f1; f0.Edges[2].Adjface[1] = f1; f1.Edges[0].Adjface[1] = f0; f1.Edges[1].Adjface[1] = f0; f1.Edges[2].Adjface[1] = f0; /* Find a fourth, non-coplanar point to form tetrahedron. */ v3 = v2.NextVertex; vol = VolumeSign(f0, v3); while (vol == 0) { if ((v3 = v3.NextVertex) == v0) { System.Diagnostics.Debug.WriteLine("doubleTriangle: All points are coplanar!"); return(false); } vol = VolumeSign(f0, v3); } /* Insure that v3 will be the first added. */ Vertices.head = v3; return(true); }
public cEdge next, prev; /* pointers to neighbours in cEdgeList */ public cEdge() { Adjface = new cFace[2]; Adjface[0] = Adjface[1] = null; Endpts = new cVertex[2]; Endpts[0] = Endpts[1] = null; newface = null; delete = false; next = prev = null; }
/*Inserts newF before oldF */ public void InsertBeforeHead(cFace e) { if (head == null) { InitHead(e); } else { InsertBefore(e, head); } }
public void PrintFaces() { cFace temp = head; int i = 1; if (head != null) { do { temp.PrintFace(i); temp = temp.next; i++; } while (temp != head); } }
public void InsertBefore(cFace newF, cFace oldF) { if (head == null) { InitHead(newF); } else { oldF.prev.next = newF; newF.prev = oldF.prev; newF.next = oldF; oldF.prev = newF; n++; } }
public void Delete(cFace e) { if (head == head.next) { head = null; } else if (e == head) { head = head.next; } e.prev.next = e.next; e.next.prev = e.prev; n--; }
public bool Voronoi(List <Vector3d> myListVectors) { if (Delaunay(myListVectors)) { for (int i = 0; i < this.Faces.ListFaces.Count; i++) { cFace face = this.Faces.ListFaces[i]; for (int j = 0; j < face.Edges.Length; j++) { cEdge edge = face.Edges[j]; for (int k = 0; k < edge.Adjface.Length; k++) { cFace adjFace = edge.Adjface[k]; cEdge newEdge = new cEdge(); //Kante m durch Verbindung der Umkreismittelpunkte von k und k+1 } } } return(true); } return(false); //var t = DelaunayTriangulation<TCell>.Create(data); //var myCells = t.Cells; //var edges = new HashSet<TEdge>(new EdgeComparer()); //foreach (var c in myCells) //{ // for (int i = 0; i < c.Adjacency.Length; i++) // { // var af = c.Adjacency[i]; // if (af != null) // edges.Add(new TEdge { Source = c, Target = af }); // } //} //return new VoronoiMesh<TCell, TEdge> //{ // Cells = myCells, // Edges = edges.ToList() //}; }
/*--------------------------------------------------------------------- * MakeCcw puts the vertices in the face structure in counterclock wise * order. We want to store the vertices in the same * order as in the visible face. The third vertex is always p. * ---------------------------------------------------------------------*/ protected void MakeCcw(cFace f, cEdge e, cVertex p) { cFace fv; /* The visible face adjacent to e */ int i; /* Index of e.endpoint[0] in fv. */ cEdge s = new cEdge(); /* Temporary, for swapping */ if (e.Adjface[0].visible) { fv = e.Adjface[0]; } else { fv = e.Adjface[1]; } /* Set vertex[0] & [1] of f to have the same orientation * as do the corresponding vertices of fv. */ for (i = 0; fv.Vertices[i] != e.Endpts[0]; ++i) { ; } /* Orient f the same as fv. */ if (fv.Vertices[(i + 1) % 3] != e.Endpts[1]) { f.Vertices[0] = e.Endpts[1]; f.Vertices[1] = e.Endpts[0]; } else { f.Vertices[0] = e.Endpts[0]; f.Vertices[1] = e.Endpts[1]; Swap(s, f.Edges[1], f.Edges[2]); } /* This swap is tricky. e is edge[0]. edge[1] is based on endpt[0], * edge[2] on endpt[1]. So if e is oriented "forwards," we * need to move edge[1] to follow [0], because it precedes. */ f.Vertices[2] = p; }
/*--------------------------------------------------------------------- * VolumeSign returns the sign of the volume of the tetrahedron determined * by f and p. VolumeSign is +1 iff p is on the negative side of f, * where the positive side is determined by the rh-rule. So the volume * is positive if the ccw normal to f points outside the tetrahedron. * The fewer-multiplications form is due to Robert Fraczkiewicz. * ---------------------------------------------------------------------*/ private double VolumeSign(cFace f, cVertex p) { double vol; //double voli = 0; double ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz; double bxdx, bydy, bzdz, cxdx, cydy, czdz; ax = f.Vertices[0].Point.X; ay = f.Vertices[0].Point.Y; az = f.Vertices[0].Point.Z; bx = f.Vertices[1].Point.X; by = f.Vertices[1].Point.Y; bz = f.Vertices[1].Point.Z; cx = f.Vertices[2].Point.X; cy = f.Vertices[2].Point.Y; cz = f.Vertices[2].Point.Z; dx = p.Point.X; dy = p.Point.Y; dz = p.Point.Z; bxdx = bx - dx; bydy = by - dy; bzdz = bz - dz; cxdx = cx - dx; cydy = cy - dy; czdz = cz - dz; vol = (az - dz) * (bxdx * cydy - bydy * cxdx) + (ay - dy) * (bzdz * cxdx - bxdx * czdz) + (ax - dx) * (bydy * czdz - bzdz * cydy); return(vol); ///* The volume should be an integer. */ //if (vol > 0) return 1; //else if (vol < 0) return -1; //else return 0; }
public cFaceList() { head = null; n = 0; }