Exemplo n.º 1
0
        public void CanGetIntersectionPoint()
        {
            var line       = new Line2D(2, 0);
            var secondLine = new Line2D(3, 1);

            Assert.AreEqual(new Point2D(-1, -2), line.GetIntersectionPoint(secondLine));
        }
Exemplo n.º 2
0
        public void CanFindIntersectionPoint()
        {
            // 0.5x - 1
            var firstLine = new Line2D(0.5, -1);
            // -2x - 6
            var secondLine = new Line2D(-2, -6);

            var intersectionPoint = firstLine.GetIntersectionPoint(secondLine);
            Assert.AreEqual(-2, intersectionPoint.X);
            Assert.AreEqual(-2, intersectionPoint.Y);
        }
Exemplo n.º 3
0
        public void CanFindIntersectionPoint()
        {
            // 0.5x - 1
            var firstLine = new Line2D(0.5, -1);
            // -2x - 6
            var secondLine = new Line2D(-2, -6);

            var intersectionPoint = firstLine.GetIntersectionPoint(secondLine);

            Assert.AreEqual(-2, intersectionPoint.X);
            Assert.AreEqual(-2, intersectionPoint.Y);
        }
        // This returns the aligned and snapped draw position
        public static DrawnVertex GetCurrentPosition(Vector2D mousemappos, bool snaptonearest, bool snaptogrid, bool snaptocardinal, bool usefourcardinaldirections, IRenderer2D renderer, List <DrawnVertex> points)
        {
            DrawnVertex p = new DrawnVertex();

            p.stitch       = true;                                 //mxd. Setting these to false seems to be a good way to create invalid geometry...
            p.stitchline   = true;                                 //mxd
            snaptocardinal = (snaptocardinal && points.Count > 0); //mxd. Don't snap to cardinal when there are no points

            //mxd. If snap to cardinal directions is enabled and we have points, modify mouse position
            Vector2D vm, gridoffset;

            if (snaptocardinal)
            {
                Vector2D offset = mousemappos - points[points.Count - 1].pos;

                float angle;
                if (usefourcardinaldirections)
                {
                    angle = Angle2D.DegToRad((General.ClampAngle((int)Angle2D.RadToDeg(offset.GetAngle()))) / 90 * 90 + 45);
                }
                else
                {
                    angle = Angle2D.DegToRad((General.ClampAngle((int)Angle2D.RadToDeg(offset.GetAngle()) + 22)) / 45 * 45);
                }

                offset = new Vector2D(0, -offset.GetLength()).GetRotated(angle);
                vm     = points[points.Count - 1].pos + offset;

                //mxd. We need to be snapped relative to initial position
                Vector2D prev = points[points.Count - 1].pos;
                gridoffset = prev - General.Map.Grid.SnappedToGrid(prev);
            }
            else
            {
                vm         = mousemappos;
                gridoffset = new Vector2D();
            }

            float vrange = BuilderPlug.Me.StitchRange / renderer.Scale;

            // Snap to nearest?
            if (snaptonearest)
            {
                // Go for all drawn points
                foreach (DrawnVertex v in points)
                {
                    if (Vector2D.DistanceSq(vm, v.pos) < (vrange * vrange))
                    {
                        p.pos = v.pos;
                        return(p);
                    }
                }

                // Try the nearest vertex
                Vertex nv = General.Map.Map.NearestVertexSquareRange(vm, vrange);
                if (nv != null)
                {
                    //mxd. Line angle must stay the same
                    if (snaptocardinal)
                    {
                        Line2D ourline = new Line2D(points[points.Count - 1].pos, vm);
                        if (Math.Round(ourline.GetSideOfLine(nv.Position), 1) == 0)
                        {
                            p.pos = nv.Position;
                            return(p);
                        }
                    }
                    else
                    {
                        p.pos = nv.Position;
                        return(p);
                    }
                }

                // Try the nearest linedef. mxd. We'll need much bigger stitch distance when snapping to cardinal directions
                Linedef nl = General.Map.Map.NearestLinedefRange(vm, BuilderPlug.Me.StitchRange / renderer.Scale);
                if (nl != null)
                {
                    //mxd. Line angle must stay the same
                    if (snaptocardinal)
                    {
                        Line2D   ourline      = new Line2D(points[points.Count - 1].pos, vm);
                        Line2D   nearestline  = new Line2D(nl.Start.Position, nl.End.Position);
                        Vector2D intersection = Line2D.GetIntersectionPoint(nearestline, ourline, false);
                        if (!float.IsNaN(intersection.x))
                        {
                            // Intersection is on nearestline?
                            float u = Line2D.GetNearestOnLine(nearestline.v1, nearestline.v2, intersection);

                            if (u < 0f || u > 1f)
                            {
                            }
                            else
                            {
                                p.pos = new Vector2D((float)Math.Round(intersection.x, General.Map.FormatInterface.VertexDecimals),
                                                     (float)Math.Round(intersection.y, General.Map.FormatInterface.VertexDecimals));
                                return(p);
                            }
                        }
                    }
                    // Snap to grid?
                    else if (snaptogrid)
                    {
                        // Get grid intersection coordinates
                        List <Vector2D> coords = nl.GetGridIntersections(General.Map.Grid.GridRotate,
                                                                         General.Map.Grid.GridOriginX, General.Map.Grid.GridOriginY);

                        // Find nearest grid intersection
                        bool     found          = false;
                        float    found_distance = float.MaxValue;
                        Vector2D found_coord    = new Vector2D();
                        foreach (Vector2D v in coords)
                        {
                            Vector2D delta = vm - v;
                            if (delta.GetLengthSq() < found_distance)
                            {
                                found_distance = delta.GetLengthSq();
                                found_coord    = v;
                                found          = true;
                            }
                        }

                        if (found)
                        {
                            // Align to the closest grid intersection
                            p.pos = found_coord;
                            return(p);
                        }
                    }
                    else
                    {
                        // Aligned to line
                        p.pos = nl.NearestOnLine(vm);
                        return(p);
                    }
                }
            }
            else
            {
                // Always snap to the first drawn vertex so that the user can finish a complete sector without stitching
                if (points.Count > 0)
                {
                    if (Vector2D.DistanceSq(vm, points[0].pos) < (vrange * vrange))
                    {
                        p.pos = points[0].pos;
                        return(p);
                    }
                }
            }

            // if the mouse cursor is outside the map bondaries check if the line between the last set point and the
            // mouse cursor intersect any of the boundary lines. If it does, set the position to this intersection
            if (points.Count > 0 &&
                (mousemappos.x < General.Map.Config.LeftBoundary || mousemappos.x > General.Map.Config.RightBoundary ||
                 mousemappos.y > General.Map.Config.TopBoundary || mousemappos.y < General.Map.Config.BottomBoundary))
            {
                Line2D        dline             = new Line2D(mousemappos, points[points.Count - 1].pos);
                bool          foundintersection = false;
                float         u      = 0.0f;
                List <Line2D> blines = new List <Line2D>();

                // lines for left, top, right and bottom boundaries
                blines.Add(new Line2D(General.Map.Config.LeftBoundary, General.Map.Config.BottomBoundary, General.Map.Config.LeftBoundary, General.Map.Config.TopBoundary));
                blines.Add(new Line2D(General.Map.Config.LeftBoundary, General.Map.Config.TopBoundary, General.Map.Config.RightBoundary, General.Map.Config.TopBoundary));
                blines.Add(new Line2D(General.Map.Config.RightBoundary, General.Map.Config.TopBoundary, General.Map.Config.RightBoundary, General.Map.Config.BottomBoundary));
                blines.Add(new Line2D(General.Map.Config.RightBoundary, General.Map.Config.BottomBoundary, General.Map.Config.LeftBoundary, General.Map.Config.BottomBoundary));

                // check for intersections with boundaries
                for (int i = 0; i < blines.Count; i++)
                {
                    if (!foundintersection)
                    {
                        // only check for intersection if the last set point is not on the
                        // line we are checking against
                        if (blines[i].GetSideOfLine(points[points.Count - 1].pos) != 0.0f)
                        {
                            foundintersection = blines[i].GetIntersection(dline, out u);
                        }
                    }
                }

                // if there was no intersection set the position to the last set point
                if (!foundintersection)
                {
                    vm = points[points.Count - 1].pos;
                }
                else
                {
                    vm = dline.GetCoordinatesAt(u);
                }
            }

            // Snap to grid?
            if (snaptogrid)
            {
                // Aligned to grid
                p.pos = General.Map.Grid.SnappedToGrid(vm - gridoffset) + gridoffset;

                // special handling
                if (p.pos.x > General.Map.Config.RightBoundary)
                {
                    p.pos.x = General.Map.Config.RightBoundary;
                }
                if (p.pos.y < General.Map.Config.BottomBoundary)
                {
                    p.pos.y = General.Map.Config.BottomBoundary;
                }

                return(p);
            }
            else
            {
                // Normal position
                p.pos.x = (float)Math.Round(vm.x);                 //mxd
                p.pos.y = (float)Math.Round(vm.y);                 //mxd

                return(p);
            }
        }
        //mxd
        protected void RenderGuidelines(Vector2D start, Vector2D end, PixelColor c)
        {
            if (end.x != start.x && end.y != start.y)
            {
                Vector2D tr = new Vector2D(Math.Max(end.x, start.x), Math.Max(end.y, start.y));
                Vector2D bl = new Vector2D(Math.Min(end.x, start.x), Math.Min(end.y, start.y));

                // Create guidelines
                Line3D[] lines = new Line3D[5];
                lines[0] = new Line3D(new Vector2D(tr.x, General.Map.Config.TopBoundary), new Vector2D(tr.x, General.Map.Config.BottomBoundary), c, false);
                lines[1] = new Line3D(new Vector2D(bl.x, General.Map.Config.TopBoundary), new Vector2D(bl.x, General.Map.Config.BottomBoundary), c, false);
                lines[2] = new Line3D(new Vector2D(General.Map.Config.LeftBoundary, tr.y), new Vector2D(General.Map.Config.RightBoundary, tr.y), c, false);
                lines[3] = new Line3D(new Vector2D(General.Map.Config.LeftBoundary, bl.y), new Vector2D(General.Map.Config.RightBoundary, bl.y), c, false);

                // Create current line extent. Make sure v1 is to the left of v2
                Line2D current = (end.x < start.x ? new Line2D(end, start) : new Line2D(start, end));

                Vector2D extentstart, extentend;
                if (current.v1.y < current.v2.y)                // Start is lower
                {
                    // Start point can hit left or bottom boundaries
                    extentstart = Line2D.GetIntersectionPoint(left, current, false);
                    if (extentstart.y < General.Map.Config.BottomBoundary)
                    {
                        extentstart = Line2D.GetIntersectionPoint(bottom, current, false);
                    }

                    // End point can hit right or top boundaries
                    extentend = Line2D.GetIntersectionPoint(right, current, false);
                    if (extentend.y > General.Map.Config.TopBoundary)
                    {
                        extentend = Line2D.GetIntersectionPoint(top, current, false);
                    }
                }
                else                 // Start is higher
                {
                    // Start point can hit left or top boundaries
                    extentstart = Line2D.GetIntersectionPoint(left, current, false);
                    if (extentstart.y > General.Map.Config.TopBoundary)
                    {
                        extentstart = Line2D.GetIntersectionPoint(top, current, false);
                    }

                    // End point can hit right or bottom boundaries
                    extentend = Line2D.GetIntersectionPoint(right, current, false);
                    if (extentend.y < General.Map.Config.BottomBoundary)
                    {
                        extentend = Line2D.GetIntersectionPoint(bottom, current, false);
                    }
                }

                lines[4] = new Line3D(extentstart, extentend, c, false);

                // Render them
                renderer.RenderArrows(lines);

                // Update horiz/vert length labels
                if (guidelabels != null)
                {
                    guidelabels[0].Move(tr, new Vector2D(tr.x, bl.y));
                    guidelabels[1].Move(new Vector2D(bl.x, tr.y), tr);
                    guidelabels[2].Move(new Vector2D(tr.x, bl.y), bl);
                    guidelabels[3].Move(bl, new Vector2D(bl.x, tr.y));
                }
            }
            // Render horizontal line + 2 vertical guidelines
            else if (end.x != start.x)
            {
                Line3D l  = new Line3D(new Vector2D(General.Map.Config.LeftBoundary, end.y), new Vector2D(General.Map.Config.RightBoundary, end.y), c, false);
                Line3D gs = new Line3D(new Vector2D(start.x, General.Map.Config.TopBoundary), new Vector2D(start.x, General.Map.Config.BottomBoundary), c, false);
                Line3D ge = new Line3D(new Vector2D(end.x, General.Map.Config.TopBoundary), new Vector2D(end.x, General.Map.Config.BottomBoundary), c, false);
                renderer.RenderArrows(new List <Line3D> {
                    l, gs, ge
                });
            }
            // Render vertical line + 2 horizontal guidelines
            else if (end.y != start.y)
            {
                Line3D l  = new Line3D(new Vector2D(end.x, General.Map.Config.TopBoundary), new Vector2D(end.x, General.Map.Config.BottomBoundary), c, false);
                Line3D gs = new Line3D(new Vector2D(General.Map.Config.LeftBoundary, start.y), new Vector2D(General.Map.Config.RightBoundary, start.y), c, false);
                Line3D ge = new Line3D(new Vector2D(General.Map.Config.LeftBoundary, end.y), new Vector2D(General.Map.Config.RightBoundary, end.y), c, false);
                renderer.RenderArrows(new List <Line3D> {
                    l, gs, ge
                });
            }
            // Start and end match. Render a cross
            else
            {
                Line3D gs = new Line3D(new Vector2D(General.Map.Config.LeftBoundary, start.y), new Vector2D(General.Map.Config.RightBoundary, start.y), c, false);
                Line3D ge = new Line3D(new Vector2D(start.x, General.Map.Config.TopBoundary), new Vector2D(start.x, General.Map.Config.BottomBoundary), c, false);
                renderer.RenderArrows(new List <Line3D> {
                    gs, ge
                });
            }
        }
Exemplo n.º 6
0
        // This checks if the view offset/zoom changed and updates the check (never used. mxd)

        /*protected bool CheckViewChanged()
         * {
         *      // View changed?
         *      bool viewchanged = (renderer.OffsetX != lastoffsetx || renderer.OffsetY != lastoffsety || renderer.Scale != lastscale);
         *
         *      // Keep view information
         *      lastoffsetx = renderer.OffsetX;
         *      lastoffsety = renderer.OffsetY;
         *      lastscale = renderer.Scale;
         *
         *      // Return result
         *      return viewchanged;
         * }*/

        // This updates the dragging
        protected virtual void Update()
        {
            PixelColor stitchcolor = General.Colors.Highlight;
            PixelColor losecolor   = General.Colors.Selection;

            snaptocardinaldirection = General.Interface.ShiftState && General.Interface.AltState;             //mxd
            snaptogrid    = (snaptocardinaldirection || General.Interface.ShiftState ^ General.Interface.SnapToGrid);
            snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge;

            DrawnVertex curp  = GetCurrentPosition();
            float       vsize = (renderer.VertexSize + 1.0f) / renderer.Scale;

            // Update label positions (mxd)
            if (labels.Count > 0)
            {
                // Update labels for already drawn lines
                for (int i = 0; i < labels.Count - 1; i++)
                {
                    labels[i].ShowAngle = showguidelines;
                    labels[i].Move(points[i].pos, points[i + 1].pos);
                }

                // Update label for active line
                labels[labels.Count - 1].ShowAngle = showguidelines;
                labels[labels.Count - 1].Move(points[points.Count - 1].pos, curp.pos);
            }

            // Render drawing lines
            if (renderer.StartOverlay(true))
            {
                // Go for all points to draw lines
                PixelColor color;
                if (points.Count > 0)
                {
                    //mxd
                    bool renderguidelabels = false;
                    if (showguidelines)
                    {
                        Vector2D   prevp = points[points.Count - 1].pos;
                        PixelColor c     = General.Colors.InfoLine.WithAlpha(80);
                        if (curp.pos.x != prevp.x && curp.pos.y != prevp.y)
                        {
                            renderguidelabels = true;

                            Vector2D tr = new Vector2D(Math.Max(curp.pos.x, prevp.x), Math.Max(curp.pos.y, prevp.y));
                            Vector2D bl = new Vector2D(Math.Min(curp.pos.x, prevp.x), Math.Min(curp.pos.y, prevp.y));

                            // Create guidelines
                            Line3D[] lines = new Line3D[5];
                            lines[0] = new Line3D(new Vector2D(tr.x, General.Map.Config.TopBoundary), new Vector2D(tr.x, General.Map.Config.BottomBoundary), c, false);
                            lines[1] = new Line3D(new Vector2D(bl.x, General.Map.Config.TopBoundary), new Vector2D(bl.x, General.Map.Config.BottomBoundary), c, false);
                            lines[2] = new Line3D(new Vector2D(General.Map.Config.LeftBoundary, tr.y), new Vector2D(General.Map.Config.RightBoundary, tr.y), c, false);
                            lines[3] = new Line3D(new Vector2D(General.Map.Config.LeftBoundary, bl.y), new Vector2D(General.Map.Config.RightBoundary, bl.y), c, false);

                            // Create current line extent. Make sure v1 is to the left of v2
                            Line2D current = (curp.pos.x < prevp.x ? new Line2D(curp.pos, prevp) : new Line2D(prevp, curp.pos));

                            Vector2D extentstart, extentend;
                            if (current.v1.y < current.v2.y)                            // Start is lower
                            {
                                // Start point can hit left or bottom boundaries
                                extentstart = Line2D.GetIntersectionPoint(left, current, false);
                                if (extentstart.y < General.Map.Config.BottomBoundary)
                                {
                                    extentstart = Line2D.GetIntersectionPoint(bottom, current, false);
                                }

                                // End point can hit right or top boundaries
                                extentend = Line2D.GetIntersectionPoint(right, current, false);
                                if (extentend.y > General.Map.Config.TopBoundary)
                                {
                                    extentend = Line2D.GetIntersectionPoint(top, current, false);
                                }
                            }
                            else                             // Start is higher
                            {
                                // Start point can hit left or top boundaries
                                extentstart = Line2D.GetIntersectionPoint(left, current, false);
                                if (extentstart.y > General.Map.Config.TopBoundary)
                                {
                                    extentstart = Line2D.GetIntersectionPoint(top, current, false);
                                }

                                // End point can hit right or bottom boundaries
                                extentend = Line2D.GetIntersectionPoint(right, current, false);
                                if (extentend.y < General.Map.Config.BottomBoundary)
                                {
                                    extentend = Line2D.GetIntersectionPoint(bottom, current, false);
                                }
                            }

                            lines[4] = new Line3D(extentstart, extentend, c, false);

                            // Render them
                            renderer.RenderArrows(lines);

                            // Update horiz/vert length labels
                            guidelabels[0].Move(tr, new Vector2D(tr.x, bl.y));
                            guidelabels[1].Move(new Vector2D(bl.x, tr.y), tr);
                            guidelabels[2].Move(new Vector2D(tr.x, bl.y), bl);
                            guidelabels[3].Move(bl, new Vector2D(bl.x, tr.y));
                        }
                        // Render horizontal line
                        else if (curp.pos.x != prevp.x)
                        {
                            Line3D l = new Line3D(new Vector2D(General.Map.Config.LeftBoundary, curp.pos.y), new Vector2D(General.Map.Config.RightBoundary, curp.pos.y), c, false);
                            renderer.RenderArrows(new List <Line3D> {
                                l
                            });
                        }
                        // Render vertical line
                        else if (curp.pos.y != prevp.y)
                        {
                            Line3D l = new Line3D(new Vector2D(curp.pos.x, General.Map.Config.TopBoundary), new Vector2D(curp.pos.x, General.Map.Config.BottomBoundary), c, false);
                            renderer.RenderArrows(new List <Line3D> {
                                l
                            });
                        }
                    }

                    // Render lines
                    DrawnVertex lastp = points[0];
                    for (int i = 1; i < points.Count; i++)
                    {
                        // Determine line color
                        if (lastp.stitchline && points[i].stitchline)
                        {
                            color = stitchcolor;
                        }
                        else
                        {
                            color = losecolor;
                        }

                        // Render line
                        renderer.RenderLine(lastp.pos, points[i].pos, LINE_THICKNESS, color, true);
                        RenderLinedefDirectionIndicator(lastp.pos, points[i].pos, color);                         //mxd
                        lastp = points[i];
                    }

                    // Determine line color
                    color = (lastp.stitchline && snaptonearest ? stitchcolor : losecolor);

                    // Render line to cursor
                    renderer.RenderLine(lastp.pos, curp.pos, LINE_THICKNESS, color, true);
                    RenderLinedefDirectionIndicator(lastp.pos, curp.pos, color);                     //mxd

                    // Render vertices
                    for (int i = 0; i < points.Count; i++)
                    {
                        // Determine vertex color
                        color = points[i].stitch ? stitchcolor : losecolor;

                        // Render vertex
                        renderer.RenderRectangleFilled(new RectangleF(points[i].pos.x - vsize, points[i].pos.y - vsize, vsize * 2.0f, vsize * 2.0f), color, true);
                    }

                    //mxd. Render guide labels?
                    if (renderguidelabels)
                    {
                        renderer.RenderText(guidelabels);
                    }

                    // Render labels
                    renderer.RenderText(labels.ToArray());
                }

                // Determine point color
                color = snaptonearest ? stitchcolor : losecolor;

                // Render vertex at cursor
                renderer.RenderRectangleFilled(new RectangleF(curp.pos.x - vsize, curp.pos.y - vsize, vsize * 2.0f, vsize * 2.0f), color, true);

                // Done
                renderer.Finish();
            }

            // Done
            renderer.Present();
        }
Exemplo n.º 7
0
 public void CanGetIntersectionPoint()
 {
     var line = new Line2D(2, 0);
     var secondLine = new Line2D(3, 1);
     Assert.AreEqual(new Point2D(-1, -2), line.GetIntersectionPoint(secondLine));
 }