Esempio n. 1
0
        private Vector2D GetCircumcenter(List <Vector3D> points)
        {
            float u_ray;

            Line2D line1 = new Line2D(points[0], points[1]);
            Line2D line2 = new Line2D(points[2], points[0]);

            // Perpendicular bisectors
            Line2D bisector1 = new Line2D(line1.GetCoordinatesAt(0.5f), line1.GetCoordinatesAt(0.5f) + line1.GetPerpendicular());
            Line2D bisector2 = new Line2D(line2.GetCoordinatesAt(0.5f), line2.GetCoordinatesAt(0.5f) + line2.GetPerpendicular());

            bisector1.GetIntersection(bisector2, out u_ray);

            return(bisector1.GetCoordinatesAt(u_ray));
        }
Esempio n. 2
0
        // returns true/false, u_line, u_ray
        public DynValue GetIntersection(float x3, float y3, float x4, float y4)
        {
            DynValue[] output = new DynValue[3];
            float      u_line = 0.0f;
            float      u_ray  = 0.0f;

            bool intersecting = l2d.GetIntersection(x3, y3, x4, y4, out u_ray, out u_line);

            if (float.IsInfinity(u_ray) || float.IsNaN(u_ray))
            {
                u_ray = -1f;
            }
            if (float.IsInfinity(u_line) || float.IsNaN(u_line))
            {
                u_line = -1f;
            }

            output[0] = DynValue.NewBoolean(intersecting);
            output[1] = DynValue.NewNumber(u_ray);
            output[2] = DynValue.NewNumber(u_line);

            return(DynValue.NewTuple(output));
        }
Esempio n. 3
0
        /// <summary>
        /// Crop a polygon by a split line
        /// </summary>
        private static void CropPolygon(List <Vector2D> poly, Split split)
        {
            if (poly.Count == 0)
            {
                return;
            }
            Vector2D prev = poly[poly.Count - 1];

            float           side1 = (prev.y - split.pos.y) * split.delta.x - (prev.x - split.pos.x) * split.delta.y;
            List <Vector2D> newp  = new List <Vector2D>(poly.Count);

            for (int i = 0; i < poly.Count; i++)
            {
                // Fetch vertex and determine side
                Vector2D cur   = poly[i];
                float    side2 = (cur.y - split.pos.y) * split.delta.x - (cur.x - split.pos.x) * split.delta.y;

                // Front?
                if (side2 < -EPSILON)
                {
                    if (side1 > EPSILON)
                    {
                        // Split line with plane and insert the vertex
                        float u;
                        Line2D.GetIntersection(split.pos, split.pos + split.delta, prev.x, prev.y, cur.x, cur.y, out u, false);
                        Vector2D newv = prev + (cur - prev) * u;
                        newp.Add(newv);
                    }

                    newp.Add(cur);
                }
                // Back?
                else if (side2 > EPSILON)
                {
                    if (side1 < -EPSILON)
                    {
                        // Split line with plane and insert the vertex
                        float u;
                        Line2D.GetIntersection(split.pos, split.pos + split.delta, prev.x, prev.y, cur.x, cur.y, out u, false);
                        Vector2D newv = prev + (cur - prev) * u;
                        newp.Add(newv);
                    }
                }
                else
                {
                    // On the plane
                    newp.Add(cur);
                }

                // Next
                prev  = cur;
                side1 = side2;
            }
            poly.Clear();
            poly.AddRange(newp);

            // The code below would be more efficient, because it modifies the polygon in place...
            // but it has a bug, some polygons are corrupted.

            /*
             * bool prevremoved = false;
             * float prevside = (prev.y - split.pos.y) * split.delta.x - (prev.x - split.pos.x) * split.delta.y;
             * int i = 0;
             * while(i < poly.Count)
             * {
             *      Vector2D cur = poly[i];
             *      float curside = (cur.y - split.pos.y) * split.delta.x - (cur.x - split.pos.x) * split.delta.y;
             *
             *      // Point is in FRONT of the split?
             *      if(curside < -EPSILON)
             *      {
             *              if(prevside > EPSILON)
             *              {
             *                      // Previous point was BEHIND the split
             *                      // Line crosses the split, we need to add the intersection point
             *                      float u;
             *                      Line2D.GetIntersection(split.pos, split.pos + split.delta, prev.x, prev.y, cur.x, cur.y, out u);
             *                      Vector2D newv = prev + (cur - prev) * u;
             *                      poly.Insert(i, newv);
             *                      i++;
             *              }
             *              else if(prevside < -EPSILON)
             *              {
             *                      // Previous point was also in FRONT of the split
             *                      // We don't need to do anything
             *              }
             *              else
             *              {
             *                      // Previous point was ON the split
             *                      // If the previous point was removed, we have to add it again
             *                      if(prevremoved)
             *                      {
             *                              poly.Insert(i, prev);
             *                              i++;
             *                      }
             *              }
             *
             *              i++;
             *              prevremoved = false;
             *      }
             *      // Point is BEHIND the split?
             *      else if(curside > EPSILON)
             *      {
             *              if(prevside < -EPSILON)
             *              {
             *                      // Previous point was in FRONT of the split
             *                      // Line crosses the split, so we must add the intersection point
             *                      float u;
             *                      Line2D.GetIntersection(split.pos, split.pos + split.delta, prev.x, prev.y, cur.x, cur.y, out u);
             *                      Vector2D newv = prev + (cur - prev) * u;
             *                      poly.Insert(i, newv);
             *                      i++;
             *              }
             *              else if(prevside > EPSILON)
             *              {
             *                      // Previous point was also BEHIND the split
             *                      // We don't need to do anything, this point will be removed
             *              }
             *              else
             *              {
             *                      // Previous point was ON the split
             *                      // We don't need to do anything, this point will be removed
             *              }
             *
             *              poly.RemoveAt(i);
             *              prevremoved = true;
             *      }
             *      // Point is ON the split?
             *      else
             *      {
             *              if(prevside > EPSILON)
             *              {
             *                      // Previous point was BEHIND the split
             *                      // Remove this point
             *                      poly.RemoveAt(i);
             *                      prevremoved = true;
             *              }
             *              else if(prevside < -EPSILON)
             *              {
             *                      // Previous point was in FRONT of the split
             *                      // We want to keep this point
             *                      prevremoved = false;
             *                      i++;
             *              }
             *              else
             *              {
             *                      // Previous point is ON the split
             *                      // Only if the previous point was also removed, we remove this one as well
             *                      if(prevremoved)
             *                              poly.RemoveAt(i);
             *                      else
             *                              i++;
             *              }
             *      }
             *
             *      prev = cur;
             *      prevside = curside;
             * }
             */
        }
Esempio n. 4
0
        // This runs the check
        public override void Run()
        {
            BlockMap <BlockEntry> blockmap = BuilderPlug.Me.ErrorCheckForm.BlockMap;
            int   progress     = 0;
            int   stepprogress = 0;
            float maxradius    = 0;
            Dictionary <int, HashSet <int> > processedthingpairs = new Dictionary <int, HashSet <int> >();       //mxd

            foreach (ThingTypeInfo tti in General.Map.Data.ThingTypes)
            {
                if (tti.Radius > maxradius)
                {
                    maxradius = tti.Radius;
                }
            }

            // Go for all the things
            foreach (Thing t in General.Map.Map.Things)
            {
                ThingTypeInfo info  = General.Map.Data.GetThingInfo(t.Type);
                bool          stuck = false;

                // Check this thing for getting stuck?
                if ((info.ErrorCheck == ThingTypeInfo.THING_ERROR_INSIDE_STUCK) &&
                    (info.Blocking > ThingTypeInfo.THING_BLOCKING_NONE))
                {
                    // Make square coordinates from thing
                    float    blockingsize = t.Size - ALLOWED_STUCK_DISTANCE;
                    Vector2D lt           = new Vector2D(t.Position.x - blockingsize, t.Position.y - blockingsize);
                    Vector2D rb           = new Vector2D(t.Position.x + blockingsize, t.Position.y + blockingsize);
                    Vector2D bmlt         = new Vector2D(t.Position.x - maxradius, t.Position.y - maxradius);
                    Vector2D bmrb         = new Vector2D(t.Position.x + maxradius, t.Position.y + maxradius);

                    // Go for all the lines to see if this thing is stuck
                    List <BlockEntry>             blocks         = blockmap.GetSquareRange(new RectangleF(bmlt.x, bmlt.y, (bmrb.x - bmlt.x), (bmrb.y - bmlt.y)));
                    Dictionary <Linedef, Linedef> doneblocklines = new Dictionary <Linedef, Linedef>(blocks.Count * 3);

                    foreach (BlockEntry b in blocks)
                    {
                        foreach (Linedef l in b.Lines)
                        {
                            // Only test when sinlge-sided, two-sided + impassable and not already checked
                            if (((l.Back == null) || l.IsFlagSet(General.Map.Config.ImpassableFlag)) && !doneblocklines.ContainsKey(l))
                            {
                                // Test if line ends are inside the thing
                                if (PointInRect(lt, rb, l.Start.Position) || PointInRect(lt, rb, l.End.Position))
                                {
                                    // Thing stuck in line!
                                    stuck = true;
                                    SubmitResult(new ResultStuckThingInLine(t, l));
                                }
                                // Test if the line intersects the square
                                else if (Line2D.GetIntersection(l.Start.Position, l.End.Position, lt.x, lt.y, rb.x, lt.y) ||
                                         Line2D.GetIntersection(l.Start.Position, l.End.Position, rb.x, lt.y, rb.x, rb.y) ||
                                         Line2D.GetIntersection(l.Start.Position, l.End.Position, rb.x, rb.y, lt.x, rb.y) ||
                                         Line2D.GetIntersection(l.Start.Position, l.End.Position, lt.x, rb.y, lt.x, lt.y))
                                {
                                    // Thing stuck in line!
                                    stuck = true;
                                    SubmitResult(new ResultStuckThingInLine(t, l));
                                }

                                // Checked
                                doneblocklines.Add(l, l);
                            }
                        }

                        // Check if thing is stuck in other things
                        if (info.Blocking != ThingTypeInfo.THING_BLOCKING_NONE)
                        {
                            foreach (Thing ot in b.Things)
                            {
                                // Don't compare the thing with itself
                                if (t.Index == ot.Index)
                                {
                                    continue;
                                }

                                // mxd. Don't compare already processed stuff
                                if (processedthingpairs.ContainsKey(t.Index) && processedthingpairs[t.Index].Contains(ot.Index))
                                {
                                    continue;
                                }

                                // Only check of items that can block
                                if (General.Map.Data.GetThingInfo(ot.Type).Blocking == ThingTypeInfo.THING_BLOCKING_NONE)
                                {
                                    continue;
                                }

                                // need to compare the flags
                                if (FlagsOverlap(t, ot) && ThingsOverlap(t, ot))
                                {
                                    stuck = true;
                                    SubmitResult(new ResultStuckThingInThing(t, ot));
                                }

                                //mxd. Prepare collections
                                if (!processedthingpairs.ContainsKey(t.Index))
                                {
                                    processedthingpairs.Add(t.Index, new HashSet <int>());
                                }
                                if (!processedthingpairs.ContainsKey(ot.Index))
                                {
                                    processedthingpairs.Add(ot.Index, new HashSet <int>());
                                }

                                //mxd. Add both ways
                                processedthingpairs[t.Index].Add(ot.Index);
                                processedthingpairs[ot.Index].Add(t.Index);
                            }
                        }
                    }
                }

                // Check this thing for being outside the map?
                if (!stuck && info.ErrorCheck >= ThingTypeInfo.THING_ERROR_INSIDE)
                {
                    // Get the nearest line to see if the thing is outside the map
                    bool    outside;
                    Linedef l = General.Map.Map.NearestLinedef(t.Position);
                    if (l.SideOfLine(t.Position) <= 0)
                    {
                        outside = (l.Front == null);
                    }
                    else
                    {
                        outside = (l.Back == null);
                    }

                    // Outside the map?
                    if (outside)
                    {
                        // Make result
                        SubmitResult(new ResultThingOutside(t));
                    }
                }

                // Handle thread interruption
                try { Thread.Sleep(0); }
                catch (ThreadInterruptedException) { return; }

                // We are making progress!
                if ((++progress / PROGRESS_STEP) > stepprogress)
                {
                    stepprogress = (progress / PROGRESS_STEP);
                    AddProgress(1);
                }
            }
        }
        // This runs the check
        public override void Run()
        {
            BlockMap <BlockEntry> blockmap = BuilderPlug.Me.ErrorCheckForm.BlockMap;
            int progress     = 0;
            int stepprogress = 0;

            // Go for all the things
            foreach (Thing t in General.Map.Map.Things)
            {
                ThingTypeInfo info    = General.Map.Data.GetThingInfo(t.Type);
                bool          stucked = false;

                // Check this thing for getting stucked?
                if ((info.ErrorCheck == ThingTypeInfo.THING_ERROR_INSIDE_STUCKED) &&
                    (info.Blocking > ThingTypeInfo.THING_BLOCKING_NONE))
                {
                    // Make square coordinates from thing
                    float    blockingsize = t.Size - ALLOWED_STUCK_DISTANCE;
                    Vector2D lt           = new Vector2D(t.Position.x - blockingsize, t.Position.y - blockingsize);
                    Vector2D rb           = new Vector2D(t.Position.x + blockingsize, t.Position.y + blockingsize);

                    // Go for all the lines to see if this thing is stucked
                    List <BlockEntry>             blocks         = blockmap.GetSquareRange(new RectangleF(lt.x, lt.y, (rb.x - lt.x), (rb.y - lt.y)));
                    Dictionary <Linedef, Linedef> doneblocklines = new Dictionary <Linedef, Linedef>(blocks.Count * 3);
                    foreach (BlockEntry b in blocks)
                    {
                        foreach (Linedef l in b.Lines)
                        {
                            // Only test when sinlge-sided and not already checked
                            if ((l.Back == null) && !doneblocklines.ContainsKey(l))
                            {
                                // Test if line ends are inside the thing
                                if (PointInRect(lt, rb, l.Start.Position) ||
                                    PointInRect(lt, rb, l.End.Position))
                                {
                                    // Thing stucked in line!
                                    stucked = true;
                                }
                                // Test if the line intersects the square
                                else if (Line2D.GetIntersection(l.Start.Position, l.End.Position, lt.x, lt.y, rb.x, lt.y) ||
                                         Line2D.GetIntersection(l.Start.Position, l.End.Position, rb.x, lt.y, rb.x, rb.y) ||
                                         Line2D.GetIntersection(l.Start.Position, l.End.Position, rb.x, rb.y, lt.x, rb.y) ||
                                         Line2D.GetIntersection(l.Start.Position, l.End.Position, lt.x, rb.y, lt.x, lt.y))
                                {
                                    // Thing stucked in line!
                                    stucked = true;
                                }

                                // Checked
                                doneblocklines.Add(l, l);
                            }
                        }
                    }
                }

                // Stucked?
                if (stucked)
                {
                    // Make result
                    SubmitResult(new ResultStuckedThing(t));
                }
                else
                {
                    // Check this thing for being outside the map?
                    if (info.ErrorCheck >= ThingTypeInfo.THING_ERROR_INSIDE)
                    {
                        // Get the nearest line to see if the thing is outside the map
                        bool    outside = false;
                        Linedef l       = General.Map.Map.NearestLinedef(t.Position);
                        if (l.SideOfLine(t.Position) <= 0)
                        {
                            outside = (l.Front == null);
                        }
                        else
                        {
                            outside = (l.Back == null);
                        }

                        // Outside the map?
                        if (outside)
                        {
                            // Make result
                            SubmitResult(new ResultThingOutside(t));
                        }
                    }
                }

                // Handle thread interruption
                try { Thread.Sleep(0); }
                catch (ThreadInterruptedException) { return; }

                // We are making progress!
                if ((++progress / PROGRESS_STEP) > stepprogress)
                {
                    stepprogress = (progress / PROGRESS_STEP);
                    AddProgress(1);
                }
            }
        }
 public bool GetIntersection(Line2D ray, out float u_ray, out float u_line)
 {
     return(Line2D.GetIntersection(v1, v2, ray.v1.x, ray.v1.y, ray.v2.x, ray.v2.y, out u_ray, out u_line));
 }
 public bool GetIntersection(Line2D ray)
 {
     return(Line2D.GetIntersection(v1, v2, ray.v1.x, ray.v1.y, ray.v2.x, ray.v2.y));
 }
 public bool GetIntersection(float x3, float y3, float x4, float y4, out float u_ray, out float u_line)
 {
     return(Line2D.GetIntersection(v1, v2, x3, y3, x4, y4, out u_ray, out u_line));
 }
 public bool GetIntersection(float x3, float y3, float x4, float y4)
 {
     return(Line2D.GetIntersection(v1, v2, x3, y3, x4, y4));
 }
Esempio n. 10
0
    // This checks if a line is inside a triangle (touching the triangle is allowed)
    // NOTE: We already know p1 is on an edge segment of the triangle
    private static bool LineInsideTriangle(EarClipVertex[] t, Vector2D p1, Vector2D p2)
    {
        float s01             = Line2D.GetSideOfLine(t[0].Position, t[1].Position, p2);
        float s12             = Line2D.GetSideOfLine(t[1].Position, t[2].Position, p2);
        float s20             = Line2D.GetSideOfLine(t[2].Position, t[0].Position, p2);
        float p2_on_edge      = 2.0f;   // somewhere outside the 0 .. 1 range
        float p1_on_same_edge = 2.0f;

        // Test if p2 is inside the triangle
        if ((s01 < 0.0f) && (s12 < 0.0f) && (s20 < 0.0f))
        {
            // Line is inside triangle, because p2 is
            return(true);
        }

        // Test if p2 is on an edge of the triangle and if it is we would
        // like to know where on the edge segment p2 is
        if (s01 == 0.0f)
        {
            p2_on_edge      = Line2D.GetNearestOnLine(t[0].Position, t[1].Position, p2);
            p1_on_same_edge = Line2D.GetSideOfLine(t[0].Position, t[1].Position, p1);
        }
        else if (s12 == 0.0f)
        {
            p2_on_edge      = Line2D.GetNearestOnLine(t[1].Position, t[2].Position, p2);
            p1_on_same_edge = Line2D.GetSideOfLine(t[1].Position, t[2].Position, p1);
        }
        else if (s20 == 0.0f)
        {
            p2_on_edge      = Line2D.GetNearestOnLine(t[2].Position, t[0].Position, p2);
            p1_on_same_edge = Line2D.GetSideOfLine(t[2].Position, t[0].Position, p1);
        }

        // Is p2 actually on the edge segment?
        if ((p2_on_edge >= 0.0f) && (p2_on_edge <= 1.0f))
        {
            // If p1 is on the same edge (or the unlimited line of that edge)
            // then the line is not inside this triangle.
            if (p1_on_same_edge == 0.0f)
            {
                return(false);
            }
        }

        // Do a complete line-triangle intersection test
        // We already know p1 is not inside the triangle (possibly on an edge)
        Line2D p = new Line2D(p1, p2);
        Line2D t01 = new Line2D(t[0].Position, t[1].Position);
        Line2D t12 = new Line2D(t[1].Position, t[2].Position);
        Line2D t20 = new Line2D(t[2].Position, t[0].Position);
        float  pu, pt;

        //mxd. Test intersections
        if (t01.GetIntersection(p, out pu, out pt))
        {
            return(true);
        }
        if (t12.GetIntersection(p, out pu, out pt))
        {
            return(true);
        }
        if (t20.GetIntersection(p, out pu, out pt))
        {
            return(true);
        }

        return(false);
    }
Esempio n. 11
0
    // This finds the cut coordinates and splits the other poly with inner vertices
    private static void SplitOuterWithInner(LinkedListNode <EarClipVertex> start, EarClipPolygon p)
    {
        LinkedListNode <EarClipVertex> insertbefore = null;
        float    foundu   = float.MaxValue;
        Vector2D foundpos = new Vector2D();

        // Create a line from start that goes beyond the right most vertex of p
        LinkedListNode <EarClipVertex> pr = FindRightMostVertex(p);
        float  startx       = start.Value.Position.x;
        float  endx         = pr.Value.Position.x + 10.0f;
        Line2D starttoright = new Line2D(start.Value.Position, new Vector2D(endx, start.Value.Position.y));

        // Calculate a small bonus (0.1 mappixel)
        float bonus = starttoright.GetNearestOnLine(new Vector2D(start.Value.Position.x + 0.1f, start.Value.Position.y));

        // Go for all lines in the outer polygon
        LinkedListNode <EarClipVertex> v1 = p.Last;
        LinkedListNode <EarClipVertex> v2 = p.First;

        while (v2 != null)
        {
            // Check if the line goes between startx and endx
            if ((v1.Value.Position.x > startx || v2.Value.Position.x > startx) &&
                (v1.Value.Position.x < endx || v2.Value.Position.x < endx))
            {
                // Find intersection
                Line2D pl = new Line2D(v1.Value.Position, v2.Value.Position);
                float  u, ul;
                pl.GetIntersection(starttoright, out u, out ul);
                if (float.IsNaN(u))
                {
                    // We have found a line that is perfectly horizontal
                    // (parallel to the cut scan line) Check if the line
                    // is overlapping the cut scan line.
                    if (v1.Value.Position.y == start.Value.Position.y)
                    {
                        // This is an exceptional situation which causes a bit of a problem, because
                        // this could be a previously made cut, which overlaps another line from the
                        // same cut and we have to determine which of the two we will join with. If we
                        // pick the wrong one, the polygon is no longer valid and triangulation will fail.

                        // Calculate distance of each vertex in units
                        u  = starttoright.GetNearestOnLine(v1.Value.Position);
                        ul = starttoright.GetNearestOnLine(v2.Value.Position);

                        // Rule out vertices before the scan line
                        if (u < 0.0f)
                        {
                            u = float.MaxValue;
                        }
                        if (ul < 0.0f)
                        {
                            ul = float.MaxValue;
                        }

                        float    insert_u = Math.Min(u, ul);
                        Vector2D inserpos = starttoright.GetCoordinatesAt(insert_u);

                        // Check in which direction the line goes.
                        if (v1.Value.Position.x > v2.Value.Position.x)
                        {
                            // The line goes from right to left (towards our start point)
                            // so we must always insert our cut after this line.

                            // If the next line goes up, we consider this a better candidate than
                            // a horizontal line that goes from left to right (the other cut line)
                            // so we give it a small bonus.
                            LinkedListNode <EarClipVertex> v3 = v2.Next ?? v2.List.First;
                            if (v3.Value.Position.y < v2.Value.Position.y)
                            {
                                insert_u -= bonus;
                            }

                            // Remember this when it is a closer match
                            if (insert_u <= foundu)
                            {
                                insertbefore = v2.Next ?? v2.List.First;
                                foundu       = insert_u;
                                foundpos     = inserpos;
                            }
                        }
                        else
                        {
                            // The line goes from left to right (away from our start point)
                            // so we must always insert our cut before this line.

                            // If the previous line goes down, we consider this a better candidate than
                            // a horizontal line that goes from right to left (the other cut line)
                            // so we give it a small bonus.
                            LinkedListNode <EarClipVertex> v3 = v1.Previous ?? v1.List.Last;
                            if (v3.Value.Position.y > v1.Value.Position.y)
                            {
                                insert_u -= bonus;
                            }

                            // Remember this when it is a closer match
                            if (insert_u <= foundu)
                            {
                                insertbefore = v2;
                                foundu       = insert_u;
                                foundpos     = inserpos;
                            }
                        }
                    }
                }
                // Found a closer match?
                else if ((ul >= 0.0f) && (ul <= 1.0f) && (u > 0.0f) && (u <= foundu))
                {
                    // Found a closer intersection
                    insertbefore = v2;
                    foundu       = u;
                    foundpos     = starttoright.GetCoordinatesAt(u);
                }
            }

            // Next
            v1 = v2;
            v2 = v2.Next;
        }

        // Found anything?
        if (insertbefore != null)
        {
            Sidedef sd = (insertbefore.Previous == null) ? insertbefore.List.Last.Value.Sidedef : insertbefore.Previous.Value.Sidedef;

            // Find the position where we have to split the outer polygon
            EarClipVertex split = new EarClipVertex(foundpos, null);

            // Insert manual split vertices
            p.AddBefore(insertbefore, new EarClipVertex(split, sd));

            // Start inserting from the start (do I make sense this time?)
            v1 = start;
            do
            {
                // Insert inner polygon vertex
                p.AddBefore(insertbefore, new EarClipVertex(v1.Value));
                v1 = (v1.Next ?? v1.List.First);
            } while (v1 != start);

            // Insert manual split vertices
            p.AddBefore(insertbefore, new EarClipVertex(start.Value, sd));
            if (split.Position != insertbefore.Value.Position)
            {
                p.AddBefore(insertbefore, new EarClipVertex(split, sd));
            }
        }
    }