Exemplo n.º 1
0
        public void Run()
        {
            foreach (Node n in Children)
            {
                n.Run();
            }

            if (Scene.NextStage("NodeCreate"))
            {
                Create();
                Scene.LastNode = this;
            }
        }
Exemplo n.º 2
0
        public override void Create()
        {
            if (!Scene.NextStage("Create SplitByRayNode"))
            {
                Shapes.AddRange(Children.SelectMany(a => a.Shapes).Select(a => a.Copy())); // if not doing this stage, just copy over the none split convexes
                return;
            }
            else if (Scene.IsCurrentStage())
            {
                Scene.AddDebugLine(RayStart - RayDir * 10, RayStart + RayDir * 10);
            }

            Shapes.AddRange(Children.SelectMany(a => a.Shapes).Select(a => a.Copy().Split2d(RayStart, RayDir, SplitMode))); //do full copy then split
        }
Exemplo n.º 3
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;
                }
            }
        }