Esempio n. 1
0
 public Face[] CreateFaces(int count)
 {
     Face[] buff = new Face[count];
     for (int i = 0; i < count; i++)
         buff[i] = CreateFace();
     return buff;
 }
Esempio n. 2
0
 public Face CreateFace()
 {
     Face f = new Face();
     Faces.Add(f);
     f.OwnerMesh = this;
     return f;
 }
Esempio n. 3
0
 public void Clip2d(Face face_a, Face face_b, out List<Face> a_only, out Face overlap)
 {
     a_only = new List<Face>();
     overlap = null;
 }
Esempio n. 4
0
        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]);
            }
        }
Esempio n. 5
0
        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;
            }
        }