public Face[] CreateFaces(int count) { Face[] buff = new Face[count]; for (int i = 0; i < count; i++) buff[i] = CreateFace(); return buff; }
public Face CreateFace() { Face f = new Face(); Faces.Add(f); f.OwnerMesh = this; return f; }
public void Clip2d(Face face_a, Face face_b, out List<Face> a_only, out Face overlap) { a_only = new List<Face>(); overlap = null; }
public void TransferFaceTo(Face f, Mesh mesh) { if (mesh.Shape != Shape) throw new System.ApplicationException("Can not transfer faces between shapes"); //transfer the face Faces.Remove(f); mesh.Faces.Add(f); f.OwnerMesh = mesh; //go over each edge in the face and copy it over for(int edgeidx = 0; edgeidx < f.Edges.Count; edgeidx++) { //get the edge and remove the face from it Edge e = f.Edges[edgeidx]; e.OwnerFaces.Remove(f); //create a new edge and replace it Edge newedge = mesh.CreateEdge(); newedge.OwnerFaces.Add(f); f.Edges[edgeidx] = newedge; //set the 2 vertex references newedge.SetVertex(0, e.Vertices[0]); newedge.SetVertex(1, e.Vertices[1]); } }
public void SplitByRay(Point3D raystart, Vector3D raydir, out Face inside_face, out Face outside_face) { //default to just returning this as inside and outside inside_face = this; outside_face = null; raydir.Normalize(); if (!Scene.NextStage("SplitByRay")) return; else if (Scene.IsCurrentStage()) Scene.AddDebugLine(raystart-raydir*10,raystart+raydir*10); //get the edges, feature info and params that describe how the ray intersects the face Edge edge0, edge1; double param0, param1; MathUtils.RayLineResult res0, res1; GetRaySplitParams(raystart, raydir, out edge0, out param0, out res0, out edge1, out param1, out res1); //debug draw the results if (Scene.IsCurrentStage()) { if(res0 == MathUtils.RayLineResult.INTERSECTING_LINE) Scene.AddDebugLine(edge0.Vertices[0].Pos,edge0.Vertices[1].Pos); else if(res0 == MathUtils.RayLineResult.INTERSECTING_POS0) Scene.AddDebugCross(edge0.Vertices[0].Pos, 0.5); else if (res0 == MathUtils.RayLineResult.PARALLEL_OVERLAPPING) { Scene.AddDebugCross(edge0.Vertices[0].Pos, 0.5); Scene.AddDebugCross(edge0.Vertices[1].Pos, 0.5); } if (res1 == MathUtils.RayLineResult.INTERSECTING_LINE) Scene.AddDebugLine(edge1.Vertices[0].Pos, edge1.Vertices[1].Pos); else if (res1 == MathUtils.RayLineResult.INTERSECTING_POS0) Scene.AddDebugCross(edge1.Vertices[0].Pos, 0.5); else if (res1 == MathUtils.RayLineResult.PARALLEL_OVERLAPPING) { Scene.AddDebugCross(edge1.Vertices[1].Pos, 0.5); Scene.AddDebugCross(edge1.Vertices[1].Pos, 0.5); } } //check if centre is initially inside ray Vector3D centre_offset = Centre - raystart; double centre_cp = MathUtils.CrossXY(centre_offset, raydir); //valid results for closed, convex, clockwise polygon are: // res0 == no intersection res1 == no intersection //when res0 is parallel: // res0 == parallel overlapping res1 == intersecting pos0 of next edge (this is treated as no intersection as there is no split required) // res0 == parallel overlapping res1 == parallel overlapping next edge IF next edge is colinear //when res0 is vertex cases // res0 == intersecting pos0 of first edge res1 == parallel overlapping last edge (note: in any other scenario res0 would detect the parallel line, and res1 will be the vertex) // res0 == intersecting pos0 of any edge res1 == no intersection (i.e. we just touched 1 vertex) // res0 == intersecting pos0 of any edge res1 == intersecting pos0 of any none-neighour edge // res0 == intersecting pos0 of any edge res1 == intersecting line of any edge other than previous neighbour //when res0 is line cases // res0 == intersecting line of any edge res1 == intersecting pos0 of any edge other than next neighbour // res0 == intersecting line of any edge res1 == intersecting line of any edge //check intersection results for each valid combination of res0 and res1 if (res0 == MathUtils.RayLineResult.PARALLEL_OVERLAPPING) { //first edge is both parallel and overlapping the ray, so just return this face as left or right if (edge1 != NextEdge(edge0)) throw new System.ApplicationException("If res0 is parallel, expected res1 to be the next edge"); if (res1 == MathUtils.RayLineResult.PARALLEL_OVERLAPPING) { if(Math.Abs(1-Vector3D.DotProduct(edge0.Direction,edge1.Direction)) > MathUtils.EPSILON) throw new System.ApplicationException("If res0 is parallel and res1 is parallel, res1 must be colinear"); //pick side and return if (centre_cp <= 0) inside_face = this; } else if (res1 == MathUtils.RayLineResult.INTERSECTING_POS0) { //pick side and return if (centre_cp <= 0) inside_face = this; } else { throw new System.ApplicationException("If res0 is parallel, expected res1 must be overlapping (if colinear) or pos0"); } } else if (res0 == MathUtils.RayLineResult.INTERSECTING_POS0) { //first edge overlaps its starting vertex if (res1 == MathUtils.RayLineResult.UNKOWN) { //no intersection (we just clipped the first vertex of edge0) - still pick side and return? if (centre_cp <= 0) inside_face = this; } else if(res1 == MathUtils.RayLineResult.INTERSECTING_POS0) { if(edge1 == NextEdge(edge0) || edge1 == PrevEdge(edge0)) throw new System.ApplicationException("If res0 is pos0 and res1 is pos0, edge1 must not be neighbour of edge0"); //got intersection - need to do vertex-vertex split Face newface = Split(edge0, edge1); Vector3D new_centre_offset = Centre - raystart; double new_centre_cp = MathUtils.CrossXY(new_centre_offset, raydir); if (new_centre_cp <= 0) { inside_face = this; outside_face = newface; } else { outside_face = this; inside_face = newface; } } else if (res1 == MathUtils.RayLineResult.INTERSECTING_LINE) { if (edge1 == PrevEdge(edge0)) throw new System.ApplicationException("If res0 is pos0 and res1 is line, edge1 must not be neighbour of edge0"); //got intersection - need to do vertex-edge split Face newface = Split(edge0, edge1, param1); Vector3D new_centre_offset = Centre - raystart; double new_centre_cp = MathUtils.CrossXY(new_centre_offset, raydir); if (new_centre_cp <= 0) { inside_face = this; outside_face = newface; } else { outside_face = this; inside_face = newface; } } else if (res1 == MathUtils.RayLineResult.PARALLEL_OVERLAPPING) { if (edge1 != Edges.Last()) throw new System.ApplicationException("If res1 is parallel, expected it to be the last edge"); if (edge0 != Edges.First()) throw new System.ApplicationException("If res1 is parallel, expected res0 to be the first edge"); //pick side and return if (centre_cp <= 0) inside_face = this; } else { throw new System.ApplicationException("If res0 is pos0, res1 must be none, pos0 or line"); } } else if (res0 == MathUtils.RayLineResult.INTERSECTING_LINE) { //first edge is overlaps the line if (res1 == MathUtils.RayLineResult.INTERSECTING_POS0) { if (edge1 == NextEdge(edge0)) throw new System.ApplicationException("If res0 is line, edge1 must not be next neighbour of edge0"); //got intersection - need to do edge-vertex split Face newface = Split(edge0, param0, edge1); Vector3D new_centre_offset = Centre - raystart; double new_centre_cp = MathUtils.CrossXY(new_centre_offset, raydir); if (new_centre_cp <= 0) { inside_face = this; outside_face = newface; } else { outside_face = this; inside_face = newface; } } else if (res1 == MathUtils.RayLineResult.INTERSECTING_LINE) { //got intersection - need to do edge-edge split Face newface = Split(edge0, param0, edge1, param1); Vector3D new_centre_offset = Centre - raystart; double new_centre_cp = MathUtils.CrossXY(new_centre_offset, raydir); if (new_centre_cp <= 0) { inside_face = this; outside_face = newface; } else { outside_face = this; inside_face = newface; } } else { throw new System.ApplicationException("If res0 is line, res1 must be pos or line"); } } else { if (res1 != MathUtils.RayLineResult.UNKOWN) throw new System.ApplicationException("If res0 is no intersection, res1 should also be no intersection"); //no intersection at all - still pick side and return? if (centre_cp <= 0) inside_face = this; } }