Example #1
0
        // Update top-left and bottom-right points, which define drawing shape
        private void UpdateReferencePoints(DrawnVertex p1, DrawnVertex p2)
        {
            if (!p1.pos.IsFinite() || !p2.pos.IsFinite())
            {
                return;
            }

            // Make sure start always stays at left and up from the end
            if (p1.pos.x < p2.pos.x)
            {
                start.x = p1.pos.x;
                end.x   = p2.pos.x;
            }
            else
            {
                start.x = p2.pos.x;
                end.x   = p1.pos.x;
            }

            if (p1.pos.y < p2.pos.y)
            {
                start.y = p1.pos.y;
                end.y   = p2.pos.y;
            }
            else
            {
                start.y = p2.pos.y;
                end.y   = p1.pos.y;
            }

            // Update size
            width  = (int)(end.x - start.x);
            height = (int)(end.y - start.y);
        }
Example #2
0
        // Update bottom-left and top-right points, which define drawing shape
        private void UpdateReferencePoints(DrawnVertex p1, DrawnVertex p2)
        {
            if (!p1.pos.IsFinite() || !p2.pos.IsFinite())
            {
                return;
            }

            if (p1.pos.x < p2.pos.x)
            {
                start.x = p1.pos.x;
                end.x   = p2.pos.x;
            }
            else
            {
                start.x = p2.pos.x;
                end.x   = p1.pos.x;
            }

            if (p1.pos.y < p2.pos.y)
            {
                start.y = p1.pos.y;
                end.y   = p2.pos.y;
            }
            else
            {
                start.y = p2.pos.y;
                end.y   = p1.pos.y;
            }

            width  = (int)(end.x - start.x);
            height = (int)(end.y - start.y);
        }
            //draws an edge to an adjacent vertex given some drawing parameters.
            private void drawEdgeTo(DrawnVertex the_other, double the_edge_cost,
                                    Graphics the_g, Pen the_edge_pen, Pen the_arrow_pen, bool the_draw_arrow)
            {
                //draw edge
                Point xy1_offset = getEdgeTarget(x, y, the_other.x, the_other.y);
                Point xy2_offset = getEdgeTarget(the_other.x, the_other.y, x, y);
                float x1         = x + xy2_offset.X;
                float y1         = y + xy2_offset.Y;
                float x2         = the_other.x + xy1_offset.X;
                float y2         = the_other.y + xy1_offset.Y;

                the_g.DrawLine(the_edge_pen, x1, y1, x2, y2);

                //draw weight
                float mid_x = (float)((x + the_other.x) / 2.0);
                float mid_y = (float)((y + the_other.y) / 2.0);

                //draw arrow
                if (the_draw_arrow)
                {
                    drawArrows(x1, y1, x2, y2, the_g, the_arrow_pen);
                }

                //backdrop
                the_g.FillRectangle(my_edge_brush, new RectangleF(mid_x,
                                                                  mid_y - LABEL_OFFSET,
                                                                  BACKDROP_WIDTH,
                                                                  BACKDROP_HEIGHT));
                //edge cost
                the_g.DrawString(the_edge_cost.ToString("F2"), my_font,
                                 my_text_brush, new PointF(mid_x, mid_y - LABEL_OFFSET));
            }
Example #4
0
        // This draws a point at a specific location
        override public bool DrawPointAt(Vector2D pos, bool stitch, bool stitchline)
        {
            if (pos.x < General.Map.Config.LeftBoundary || pos.x > General.Map.Config.RightBoundary ||
                pos.y > General.Map.Config.TopBoundary || pos.y < General.Map.Config.BottomBoundary)
            {
                return(false);
            }

            DrawnVertex newpoint = new DrawnVertex {
                pos = pos, stitch = true, stitchline = stitchline
            };

            points.Add(newpoint);

            if (points.Count == 1)
            {
                // Add labels
                labels.AddRange(new[] { new LineLengthLabel(false, true), new LineLengthLabel(false, true), new LineLengthLabel(false, true), new LineLengthLabel(false, true) });
                hintlabel = new HintLabel(General.Colors.InfoLine);
                Update();
            }
            else if (points[0].pos == points[1].pos)
            {
                // Nothing is drawn
                FinishDraw();
            }
            else
            {
                // Handle the case when start point is not on current grid.
                Vector2D gridoffset = General.Map.Grid.SnappedToGrid(points[0].pos) - points[0].pos;
                newpoint = GetCurrentPosition(mousemappos + gridoffset, snaptonearest, snaptogrid, snaptocardinaldirection, usefourcardinaldirections, renderer, new List <DrawnVertex> {
                    points[0]
                });
                newpoint.pos -= gridoffset;

                // Create vertices for final shape.
                UpdateReferencePoints(points[0], newpoint);
                List <Vector2D[]> shapes = GetShapes(start, end);

                foreach (Vector2D[] shape in shapes)
                {
                    DrawnVertex[] verts = new DrawnVertex[shape.Length];
                    for (int i = 0; i < shape.Length; i++)
                    {
                        newpoint = new DrawnVertex {
                            pos = shape[i], stitch = true, stitchline = stitchline
                        };
                        verts[i] = newpoint;
                    }

                    gridpoints.Add(verts);
                }

                FinishDraw();
            }
            return(true);
        }
Example #5
0
        // Turns a position into a DrawnVertex and returns it
        private DrawnVertex SectorVertex(float x, float y)
        {
            DrawnVertex v = new DrawnVertex();

            v.stitch     = true;
            v.stitchline = true;
            v.pos        = new Vector2D((float)Math.Round(x, General.Map.FormatInterface.VertexDecimals), (float)Math.Round(y, General.Map.FormatInterface.VertexDecimals));

            return(v);
        }
        public bool DrawPoint()
        {
            DrawnVertex vertex = mode.GetVertexAt(cursor,
                                                  snaptonearest, snaptogrid,
                                                  stitchrange, scaletorenderer,
                                                  points);

            Logger.WriteLogLine("write point @ " + vertex.pos);
            return(DrawPointAt(vertex));
        }
Example #7
0
        public bool FinishDrawingPoints(List <PenVertex> points)
        {
            List <DrawnVertex> d = new List <DrawnVertex>(points.Count);

            // convert and also remove consecutive duplicates
            int   previndex = -1;
            float vrange    = General.Map.FormatInterface.MinLineLength * 0.9f;

            vrange = vrange * vrange;
            foreach (PenVertex p in points)
            {
                DrawnVertex nd = new DrawnVertex();
                nd.pos = p.pos.vec;
                if (!nd.pos.IsFinite())
                {
                    throw new ScriptRuntimeException("Error during finishing pen drawing, position ("
                                                     + nd.pos
                                                     + ") with index "
                                                     + (previndex + 1)
                                                     + " is not a valid vector. (You might have divided by 0 somewhere?)");
                }
                nd.stitch     = p.stitch;
                nd.stitchline = p.stitchline;
                if (previndex == -1 || Vector2D.DistanceSq(nd.pos, d[previndex].pos) > 0.001f)
                {
                    d.Add(nd);
                    previndex++;
                }
            }

            // Make the drawing
            if (!Tools.DrawLines(d))
            {
                // ano - i really wish i could give a better error than this, the whole plugin api thing
                // is a bit annoying.
                throw new ScriptRuntimeException("Unknown failure drawing pen vertices!");
            }

            // Snap to map format accuracy
            General.Map.Map.SnapAllToAccuracy();

            // Clear selection
            General.Map.Map.ClearSelectedLinedefs();
            General.Map.Map.ClearSelectedVertices();
            General.Map.Map.ClearSelectedSectors();

            // Update cached values
            General.Map.Map.Update();

            // Update the used textures
            General.Map.Data.UpdateUsedTextures();

            return(true);
        }
 public void DrawPoint()
 {
     // Mouse inside window?
     if (General.Interface.MouseInDisplay)
     {
         DrawnVertex newpoint = GetCurrentPosition();
         if (!DrawPointAt(newpoint))
         {
             General.Interface.DisplayStatus(StatusType.Warning, "Failed to draw point: outside of map boundaries.");
         }
     }
 }
Example #9
0
        // This draws a point at a specific location
        override public bool DrawPointAt(Vector2D pos, bool stitch, bool stitchline)
        {
            if (pos.x < General.Map.Config.LeftBoundary || pos.x > General.Map.Config.RightBoundary ||
                pos.y > General.Map.Config.TopBoundary || pos.y < General.Map.Config.BottomBoundary)
            {
                return(false);
            }

            DrawnVertex newpoint = new DrawnVertex();

            newpoint.pos        = pos.GetRotated(-General.Map.Grid.GridRotate);
            newpoint.stitch     = true;         //stitch
            newpoint.stitchline = stitchline;
            points.Add(newpoint);

            if (points.Count == 1)
            {
                // Add labels
                labels.AddRange(new[] { new LineLengthLabel(false, true), new LineLengthLabel(false, true), new LineLengthLabel(false, true), new LineLengthLabel(false, true) });
                hintlabel = new HintLabel(General.Colors.InfoLine);
                Update();
            }
            else if (points[0].pos == points[1].pos)
            {
                // Nothing is drawn
                FinishDraw();
            }
            else
            {
                // Create vertices for final shape.
                UpdateReferencePoints(points[0], newpoint);
                List <Vector2D[]> shapes = GetShapes(start, end);

                foreach (Vector2D[] shape in shapes)
                {
                    DrawnVertex[] verts = new DrawnVertex[shape.Length];
                    for (int i = 0; i < shape.Length; i++)
                    {
                        newpoint = new DrawnVertex {
                            pos        = shape[i].GetRotated(General.Map.Grid.GridRotate),                      // Take grid rotation into account
                            stitch     = true,
                            stitchline = stitchline
                        };
                        verts[i] = newpoint;
                    }

                    gridpoints.Add(verts);
                }

                FinishDraw();
            }
            return(true);
        }
        // This draws a point at a specific location
        public bool DrawPointAt(DrawnVertex vertex)
        {
            if (vertex.pos.x < General.Map.Config.LeftBoundary || vertex.pos.x > General.Map.Config.RightBoundary ||
                vertex.pos.y > General.Map.Config.TopBoundary || vertex.pos.y < General.Map.Config.BottomBoundary)
            {
                return(false);
            }

            points.Add(vertex);

            return(true);
        }
        // This draws a point at a specific location
        override public bool DrawPointAt(Vector2D pos, bool stitch, bool stitchline)
        {
            if (pos.x < General.Map.Config.LeftBoundary || pos.x > General.Map.Config.RightBoundary ||
                pos.y > General.Map.Config.TopBoundary || pos.y < General.Map.Config.BottomBoundary)
            {
                return(false);
            }

            DrawnVertex newpoint = new DrawnVertex();

            newpoint.pos        = pos.GetRotated(-General.Map.Grid.GridRotate);
            newpoint.stitch     = true;         //stitch
            newpoint.stitchline = stitchline;
            points.Add(newpoint);

            if (points.Count == 1)             //add point and labels
            {
                labels.AddRange(new[] { new LineLengthLabel(false, true), new LineLengthLabel(false, true), new LineLengthLabel(false, true), new LineLengthLabel(false, true) });
                hintlabel = new HintLabel(General.Colors.InfoLine);
                Update();
            }
            else if (points[0].pos == points[1].pos)            //nothing is drawn
            {
                points = new List <DrawnVertex>();
                FinishDraw();
            }
            else
            {
                //create vertices for final shape.
                UpdateReferencePoints(points[0], newpoint);
                points = new List <DrawnVertex>();                //clear points
                Vector2D[] shape = GetShape(start, end);

                // Rotate the shape to fit the grid rotation
                for (int i = 0; i < shape.Length; i++)
                {
                    shape[i] = shape[i].GetRotated(General.Map.Grid.GridRotate);
                }

                // We don't want base.DrawPointAt to call Update() here, because it will mess labels[]
                // and trigger shape.Count number of display redraws...
                blockupdate = true;
                foreach (Vector2D t in shape)
                {
                    base.DrawPointAt(t, true, true);
                }
                blockupdate = false;

                FinishDraw();
            }
            return(true);
        }
        public virtual void InsertVertexAction()
        {
            // Start drawing mode
            DrawLinesMode drawmode = new DrawLinesMode();

            if (mouseinside)
            {
                bool        snaptogrid    = General.Interface.ShiftState ^ General.Interface.SnapToGrid;
                bool        snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge;
                DrawnVertex v             = DrawLinesMode.GetCurrentPosition(mousemappos, snaptonearest, snaptogrid, renderer, new List <DrawnVertex>());
                drawmode.DrawPointAt(v);
            }
            General.Editing.ChangeMode(drawmode);
        }
        //updates all vertex headings after the shortest path algorithms are run.
        private void updateAfterShortestPath()
        {
            //go through each vertex
            DirectedGraph <DSInteger> graph = getCurrentGraph();
            Iterator <DrawnVertex>    it    = my_drawables.values().iterator();

            while (it.hasNext())
            {
                DrawnVertex dv = it.next();
                dv.draw_heading = true; //make them show their headings

                bool   found           = false;
                double total_edge_cost = 0.0;

                //make sure the source vertex is found
                if (dv.label.Equals(my_last_highlighted))
                {
                    found = true;
                }

                //get the shortest path
                Iterator <DSInteger> it_vertices = graph.getShortestPath(dv.label).iterator();
                if (it_vertices.hasNext())
                {
                    //add up the shortest path
                    DSInteger last = it_vertices.next();
                    while (it_vertices.hasNext())
                    {
                        found = true;
                        DSInteger next = it_vertices.next();
                        total_edge_cost += graph.getEdgeCost(last, next);
                        last             = next;
                    }
                }

                //check for no shortest path
                if (!found)
                {
                    dv.heading = "Inf";
                }
                else
                {
                    dv.heading = total_edge_cost.ToString();
                }
            }

            //redraw the visual
            pnlDraw.Refresh();
        }
 //replaces the current graph with a scaled version of the same graph.
 private void replaceGraph(double the_width_ratio, double the_height_ratio)
 {
     //if there is something to draw
     if (my_generated)
     {
         //scale each vertex
         Iterator <DrawnVertex> it = my_drawables.values().iterator();
         while (it.hasNext())
         {
             DrawnVertex dv = it.next();
             dv.x = (float)(dv.x * the_width_ratio);
             dv.y = (float)(dv.y * the_height_ratio);
         }
     }
 }
        // Start editing
        protected override void OnEditBegin()
        {
            // Item highlighted?
            if ((highlighted != null) && !highlighted.IsDisposed)
            {
                // Edit pressed in this mode
                editpressed = true;

                // Highlighted item not selected?
                if (!highlighted.Selected && (BuilderPlug.Me.AutoClearSelection || (General.Map.Map.SelectedLinedefsCount == 0)))
                {
                    // Make this the only selection
                    General.Map.Map.ClearSelectedLinedefs();
                    highlighted.Selected = true;
                    General.Interface.RedrawDisplay();
                }

                // Update display
                if (renderer.StartPlotter(false))
                {
                    // Redraw highlight to show selection
                    renderer.PlotLinedef(highlighted, renderer.DetermineLinedefColor(highlighted));
                    renderer.PlotVertex(highlighted.Start, renderer.DetermineVertexColor(highlighted.Start));
                    renderer.PlotVertex(highlighted.End, renderer.DetermineVertexColor(highlighted.End));
                    renderer.Finish();
                    renderer.Present();
                }
            }
            else
            {
                // Start drawing mode
                DrawLinesMode drawmode      = new DrawLinesMode();
                bool          snaptogrid    = General.Interface.ShiftState ^ General.Interface.SnapToGrid;
                bool          snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge;
                DrawnVertex   v             = DrawLinesMode.GetCurrentPosition(mousemappos, snaptonearest, snaptogrid, renderer, new List <DrawnVertex>());

                if (drawmode.DrawPointAt(v))
                {
                    General.Editing.ChangeMode(drawmode);
                }
                else
                {
                    General.Interface.DisplayStatus(StatusType.Warning, "Failed to draw point: outside of map boundaries.");
                }
            }

            base.OnEditBegin();
        }
Example #16
0
        // Update bottom-left and top-right points, which define drawing shape
        private void UpdateReferencePoints(DrawnVertex p1, DrawnVertex p2)
        {
            if (!p1.pos.IsFinite() || !p2.pos.IsFinite())
            {
                return;
            }

            // If relative interpolation is enabled the interpolation will use the point where the drawing
            // started as the origin, not always the top left corner
            if (relativeinterpolation)
            {
                start.x = p1.pos.x;
                start.y = p1.pos.y;
                end.x   = p2.pos.x;
                end.y   = p2.pos.y;
            }
            else
            {
                if (p1.pos.x < p2.pos.x)
                {
                    start.x = p1.pos.x;
                    end.x   = p2.pos.x;
                }
                else
                {
                    start.x = p2.pos.x;
                    end.x   = p1.pos.x;
                }

                if (p1.pos.y < p2.pos.y)
                {
                    start.y = p1.pos.y;
                    end.y   = p2.pos.y;
                }
                else
                {
                    start.y = p2.pos.y;
                    end.y   = p1.pos.y;
                }
            }


            width  = (int)(end.x - start.x);
            height = (int)(end.y - start.y);
        }
        //mxd
        private static void DrawLine(Vector2D start, Vector2D end)
        {
            DrawnVertex dv1 = new DrawnVertex();
            DrawnVertex dv2 = new DrawnVertex();

            dv1.stitchline = true;
            dv2.stitchline = true;
            dv1.stitch     = true;
            dv2.stitch     = true;
            dv1.pos        = start;
            dv2.pos        = end;
            Tools.DrawLines(new List <DrawnVertex> {
                dv1, dv2
            }, false, false);

            // Update cache values
            General.Map.Map.Update();
            General.Map.IsChanged = true;
        }
        //draws the generated graph to the window.
        private void pnlDraw_Paint(object sender, PaintEventArgs e)
        {
            //if some drawing objects are ready
            if (my_generated)
            {
                //redo the buffer if necessary
                if (my_buffer == null)
                {
                    my_buffer = new Bitmap(pnlDraw.Width, pnlDraw.Height);

                    DirectedGraph <DSInteger> graph = getCurrentGraph();
                    Graphics g = Graphics.FromImage(my_buffer);

                    //draw edges
                    drawEdges(graph, g, false);

                    //draw mst if present
                    if (my_mst != null)
                    {
                        drawEdges(my_mst, g, true);
                    }

                    //draw vertices
                    Iterator <DrawnVertex> it_dv = my_drawables.values().iterator();
                    while (it_dv.hasNext())
                    {
                        DrawnVertex dv = it_dv.next();
                        dv.draw(g);
                    }

                    //draw highlight
                    if (my_last_highlighted != null)
                    {
                        my_drawables.get(my_last_highlighted).highlight(g);
                    }
                }

                //draw from the buffer
                e.Graphics.DrawImage(my_buffer, new Rectangle(0, 0, pnlDraw.Width, pnlDraw.Height),
                                     new Rectangle(0, 0, my_buffer.Width, my_buffer.Height), GraphicsUnit.Pixel);
            }
        }
Example #19
0
        // This draws a point at a specific location
        override public bool DrawPointAt(Vector2D pos, bool stitch, bool stitchline)
        {
            if (pos.x < General.Map.Config.LeftBoundary || pos.x > General.Map.Config.RightBoundary ||
                pos.y > General.Map.Config.TopBoundary || pos.y < General.Map.Config.BottomBoundary)
            {
                return(false);
            }

            DrawnVertex newpoint = new DrawnVertex();

            newpoint.pos        = pos;
            newpoint.stitch     = true;         //stitch
            newpoint.stitchline = stitchline;
            points.Add(newpoint);

            if (points.Count == 1)            //add point and labels
            {
                labels.AddRange(new[] { new LineLengthLabel(false, true), new LineLengthLabel(false, true), new LineLengthLabel(false, true), new LineLengthLabel(false, true) });
                hintlabel = new HintLabel(General.Colors.InfoLine);
                Update();
            }
            else if (points[0].pos == points[1].pos)            //nothing is drawn
            {
                points = new List <DrawnVertex>();
                FinishDraw();
            }
            else
            {
                //create vertices for final shape.
                UpdateReferencePoints(points[0], newpoint);
                points = new List <DrawnVertex>();                //clear points
                Vector2D[] shape = GetShape(start, end);

                foreach (Vector2D t in shape)
                {
                    base.DrawPointAt(t, true, true);
                }

                FinishDraw();
            }
            return(true);
        }
Example #20
0
        // This draws a point at a specific location
        public bool DrawPointAt(Vector2D pos, bool stitch, bool stitchline)
        {
            if (pos.x < General.Map.Config.LeftBoundary || pos.x > General.Map.Config.RightBoundary ||
                pos.y > General.Map.Config.TopBoundary || pos.y < General.Map.Config.BottomBoundary)
            {
                return(false);
            }

            if (points.Count > 0 && (points[points.Count - 1].pos - pos).GetLengthSq() < 0.001f)
            {
                return(true);
            }

            DrawnVertex newpoint = new DrawnVertex();

            newpoint.pos        = pos;
            newpoint.stitch     = stitch;
            newpoint.stitchline = stitchline;
            points.Add(newpoint);
            labels.Add(new LineLengthLabel());
            labels[labels.Count - 1].Start = newpoint.pos;
            if (labels.Count > 1)
            {
                labels[labels.Count - 2].End = newpoint.pos;
            }
            Update();

            // Check if point stitches with the first
            if ((points.Count > 1) && points[points.Count - 1].stitch)
            {
                Vector2D p1    = points[0].pos;
                Vector2D p2    = points[points.Count - 1].pos;
                Vector2D delta = p1 - p2;
                if ((Math.Abs(delta.x) <= 0.001f) && (Math.Abs(delta.y) <= 0.001f))
                {
                    // Finish drawing
                    FinishDraw();
                }
            }

            return(true);
        }
        //draws all edges on the window.
        private void drawEdges(DirectedGraph <DSInteger> the_graph, Graphics the_g, bool the_highlight)
        {
            //get all edges
            List <SimpleEdge <DSInteger> >     edges = the_graph.getEdges();
            Iterator <SimpleEdge <DSInteger> > it    = edges.iterator();

            while (it.hasNext())
            {
                //draw each edge
                SimpleEdge <DSInteger> edge = it.next();
                DrawnVertex            dv   = my_drawables.get(edge.first_label);

                //draw arrows or no arrows depending on the graph
                if (the_graph == my_d_graph)
                {
                    if (the_highlight)
                    {
                        dv.highlightDirectedEdgeTo(my_drawables.get(edge.second_label), edge.edge_cost, the_g);
                    }
                    else
                    {
                        dv.drawDirectedEdgeTo(my_drawables.get(edge.second_label), edge.edge_cost, the_g);
                    }
                }
                else
                {
                    if (the_highlight)
                    {
                        dv.highlightUndirectedEdgeTo(my_drawables.get(edge.second_label), edge.edge_cost, the_g);
                    }
                    else
                    {
                        dv.drawUndirectedEdgeTo(my_drawables.get(edge.second_label), edge.edge_cost, the_g);
                    }
                }
            }
        }
        // This draws a point at a specific location
        public bool DrawPointAt(Vector2D pos, bool stitch, bool stitchline)
        {
            if (pos.x < General.Map.Config.LeftBoundary || pos.x > General.Map.Config.RightBoundary ||
                pos.y > General.Map.Config.TopBoundary || pos.y < General.Map.Config.BottomBoundary)
            {
                return(false);
            }

            DrawnVertex newpoint = new DrawnVertex();

            newpoint.pos        = pos;
            newpoint.stitch     = stitch;
            newpoint.stitchline = stitchline;
            points.Add(newpoint);
            updateOverlaySurfaces();
            Update();

            if (points.Count == 3)
            {
                FinishDraw();
            }

            return(true);
        }
        // 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);
            }
        }
Example #24
0
		// Turns a position into a DrawnVertex and returns it
		private DrawnVertex SectorVertex(float x, float y)
		{
			DrawnVertex v = new DrawnVertex();

			v.stitch = true;
			v.stitchline = true;
			v.pos = new Vector2D((float)Math.Round(x, General.Map.FormatInterface.VertexDecimals), (float)Math.Round(y, General.Map.FormatInterface.VertexDecimals));

			return v;
		}
Example #25
0
        override protected void Update()
        {
            PixelColor stitchcolor = General.Colors.Highlight;
            PixelColor losecolor   = General.Colors.Selection;

            // We WANT snaptogrid and DON'T WANT snaptonearest when lock to grid is enabled
            snaptocardinaldirection = General.Interface.ShiftState && General.Interface.AltState;             //mxd
            snaptogrid    = (snaptocardinaldirection || gridlockmode != GridLockMode.NONE || (General.Interface.ShiftState ^ General.Interface.SnapToGrid));
            snaptonearest = (gridlockmode == GridLockMode.NONE && (General.Interface.CtrlState ^ General.Interface.AutoMerge));

            DrawnVertex curp = GetCurrentPosition();

            Vector2D curvertexpos = curp.pos;
            float    vsize        = (renderer.VertexSize + 1.0f) / renderer.Scale;

            curp.pos = curp.pos.GetRotated(-General.Map.Grid.GridRotate);

            // Render drawing lines
            if (renderer.StartOverlay(true))
            {
                PixelColor color = snaptonearest ? stitchcolor : losecolor;

                if (points.Count == 1)
                {
                    UpdateReferencePoints(points[0], curp);
                    List <Vector2D[]> shapes = GetShapes(start, end);

                    Vector2D startrotated = start.GetRotated(General.Map.Grid.GridRotate);
                    Vector2D endrotated   = end.GetRotated(General.Map.Grid.GridRotate);

                    // Rotate the shape to fit the grid rotation
                    foreach (Vector2D[] shape in shapes)
                    {
                        for (int i = 0; i < shape.Length; i++)
                        {
                            shape[i] = shape[i].GetRotated(General.Map.Grid.GridRotate);
                        }
                    }

                    // Render guidelines
                    if (showguidelines)
                    {
                        RenderGuidelines(startrotated, endrotated, General.Colors.Guideline.WithAlpha(80), -General.Map.Grid.GridRotate);
                    }

                    //render shape
                    foreach (Vector2D[] shape in shapes)
                    {
                        for (int i = 1; i < shape.Length; i++)
                        {
                            renderer.RenderLine(shape[i - 1], shape[i], LINE_THICKNESS, color, true);
                        }
                    }

                    //vertices
                    foreach (Vector2D[] shape in shapes)
                    {
                        for (int i = 0; i < shape.Length; i++)
                        {
                            renderer.RenderRectangleFilled(new RectangleF((float)(shape[i].x - vsize), (float)(shape[i].y - vsize), vsize * 2.0f, vsize * 2.0f), color, true);
                        }
                    }

                    //and labels
                    if (width == 0 || height == 0)
                    {
                        // Render label for line
                        labels[0].Move(startrotated, endrotated);
                        renderer.RenderText(labels[0].TextLabel);
                    }
                    else
                    {
                        // Render labels for grid
                        Vector2D[] labelCoords = { startrotated, new Vector2D(end.x, start.y).GetRotated(General.Map.Grid.GridRotate), endrotated, new Vector2D(start.x, end.y).GetRotated(General.Map.Grid.GridRotate), startrotated };

                        for (int i = 1; i < 5; i++)
                        {
                            labels[i - 1].Move(labelCoords[i], labelCoords[i - 1]);
                            renderer.RenderText(labels[i - 1].TextLabel);
                        }
                    }

                    //render hint
                    if (horizontalslices > 1 || verticalslices > 1)
                    {
                        string text = "H: " + (slicesH - 1) + "; V: " + (slicesV - 1);
                        if (Math.Abs(width) > text.Length * vsize && Math.Abs(height) > 16 * vsize)
                        {
                            hintlabel.Text = text;
                            hintlabel.Move(startrotated, endrotated);
                            renderer.RenderText(hintlabel.TextLabel);
                        }
                    }
                }
                else
                {
                    // Render vertex at cursor
                    renderer.RenderRectangleFilled(new RectangleF((float)(curvertexpos.x - vsize), (float)(curvertexpos.y - vsize), vsize * 2.0f, vsize * 2.0f), color, true);
                }

                // Done
                renderer.Finish();
            }

            // Done
            renderer.Present();
        }
Example #26
0
        // Start editing
        protected override void OnEditBegin()
        {
            bool snaptogrid    = General.Interface.ShiftState ^ General.Interface.SnapToGrid;
            bool snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge;

            // Vertex highlighted?
            if ((highlighted != null) && !highlighted.IsDisposed)
            {
                // Edit pressed in this mode
                editpressed = true;

                // Highlighted item not selected?
                if (!highlighted.Selected && (BuilderPlug.Me.AutoClearSelection || (General.Map.Map.SelectedVerticessCount == 0)))
                {
                    // Make this the only selection
                    General.Map.Map.ClearSelectedVertices();
                    highlighted.Selected = true;
                    General.Interface.RedrawDisplay();
                }

                // Update display
                if (renderer.StartPlotter(false))
                {
                    // Redraw highlight to show selection
                    renderer.PlotVertex(highlighted, renderer.DetermineVertexColor(highlighted));
                    renderer.Finish();
                    renderer.Present();
                }
            }
            else
            {
                // Find the nearest linedef within highlight range
                Linedef l = General.Map.Map.NearestLinedefRange(mousemappos, BuilderPlug.Me.SplitLinedefsRange / renderer.Scale);
                if (l != null)
                {
                    // Create undo
                    General.Map.UndoRedo.CreateUndo("Split linedef");

                    Vector2D insertpos;

                    // Snip to grid also?
                    if (snaptogrid)
                    {
                        // Find all points where the grid intersects the line
                        List <Vector2D> points = l.GetGridIntersections();
                        insertpos = mousemappos;
                        float distance = float.MaxValue;
                        foreach (Vector2D p in points)
                        {
                            float pdist = Vector2D.DistanceSq(p, mousemappos);
                            if (pdist < distance)
                            {
                                insertpos = p;
                                distance  = pdist;
                            }
                        }
                    }
                    else
                    {
                        // Just use the nearest point on line
                        insertpos = l.NearestOnLine(mousemappos);
                    }

                    // Make the vertex
                    Vertex v = General.Map.Map.CreateVertex(insertpos);
                    if (v == null)
                    {
                        General.Map.UndoRedo.WithdrawUndo();
                        return;
                    }

                    // Snap to map format accuracy
                    v.SnapToAccuracy();

                    // Split the line with this vertex
                    Linedef sld = l.Split(v);
                    if (sld == null)
                    {
                        General.Map.UndoRedo.WithdrawUndo();
                        return;
                    }
                    BuilderPlug.Me.AdjustSplitCoordinates(l, sld);

                    // Update
                    General.Map.Map.Update();

                    // Highlight it
                    Highlight(v);

                    // Redraw display
                    General.Interface.RedrawDisplay();
                }
                else
                {
                    // Start drawing mode
                    DrawGeometryMode drawmode = new DrawGeometryMode();
                    DrawnVertex      v        = DrawGeometryMode.GetCurrentPosition(mousemappos, snaptonearest, snaptogrid, renderer, new List <DrawnVertex>());

                    if (drawmode.DrawPointAt(v))
                    {
                        General.Editing.ChangeMode(drawmode);
                    }
                    else
                    {
                        General.Interface.DisplayStatus(StatusType.Warning, "Failed to draw point: outside of map boundaries.");
                    }
                }
            }

            base.OnEditBegin();
        }
Example #27
0
 // This draws a point at a specific location
 public bool DrawPointAt(DrawnVertex p)
 {
     return(DrawPointAt(p.pos, p.stitch, p.stitchline));
 }
Example #28
0
        // This returns the aligned and snapped draw position
        public static DrawnVertex GetCurrentPosition(Vector2D mousemappos, bool snaptonearest, bool snaptogrid, IRenderer2D renderer, List <DrawnVertex> points)
        {
            DrawnVertex p      = new DrawnVertex();
            Vector2D    vm     = mousemappos;
            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(mousemappos, v.pos) < (vrange * vrange))
                    {
                        p.pos        = v.pos;
                        p.stitch     = true;
                        p.stitchline = true;
                        return(p);
                    }
                }

                // Try the nearest vertex
                Vertex nv = General.Map.Map.NearestVertexSquareRange(mousemappos, vrange);
                if (nv != null)
                {
                    p.pos        = nv.Position;
                    p.stitch     = true;
                    p.stitchline = true;
                    return(p);
                }

                // Try the nearest linedef
                Linedef nl = General.Map.Map.NearestLinedefRange(mousemappos, BuilderPlug.Me.StitchRange / renderer.Scale);
                if (nl != null)
                {
                    // Snap to grid?
                    if (snaptogrid)
                    {
                        // Get grid intersection coordinates
                        List <Vector2D> coords = nl.GetGridIntersections();

                        // Find nearest grid intersection
                        bool     found          = false;
                        float    found_distance = float.MaxValue;
                        Vector2D found_coord    = new Vector2D();
                        foreach (Vector2D v in coords)
                        {
                            Vector2D delta = mousemappos - 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;
                            p.stitch     = true;
                            p.stitchline = true;
                            return(p);
                        }
                    }
                    else
                    {
                        // Aligned to line
                        p.pos        = nl.NearestOnLine(mousemappos);
                        p.stitch     = true;
                        p.stitchline = true;
                        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(mousemappos, points[0].pos) < (vrange * vrange))
                    {
                        p.pos        = points[0].pos;
                        p.stitch     = true;
                        p.stitchline = false;
                        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 bondaries
                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);

                // 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;
                }
                p.stitch     = snaptonearest;
                p.stitchline = snaptonearest;
                return(p);
            }
            else
            {
                // Normal position
                p.pos        = vm;
                p.stitch     = snaptonearest;
                p.stitchline = snaptonearest;
                return(p);
            }
        }
Example #29
0
        // This updates the dragging
        private void Update()
        {
            PixelColor stitchcolor = General.Colors.Highlight;
            PixelColor losecolor   = General.Colors.Selection;
            PixelColor color;

            snaptogrid    = General.Interface.ShiftState ^ General.Interface.SnapToGrid;
            snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge;

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

            // The last label's end must go to the mouse cursor
            if (labels.Count > 0)
            {
                labels[labels.Count - 1].End = curp.pos;
            }

            // Render drawing lines
            if (renderer.StartOverlay(true))
            {
                // Go for all points to draw lines
                if (points.Count > 0)
                {
                    // Render lines
                    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);
                        lastp = points[i];
                    }

                    // Determine line color
                    if (lastp.stitchline && snaptonearest)
                    {
                        color = stitchcolor;
                    }
                    else
                    {
                        color = losecolor;
                    }

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

                    // Render vertices
                    for (int i = 0; i < points.Count; i++)
                    {
                        // Determine vertex color
                        if (points[i].stitch)
                        {
                            color = stitchcolor;
                        }
                        else
                        {
                            color = 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);
                    }
                }

                // Determine point color
                if (snaptonearest)
                {
                    color = stitchcolor;
                }
                else
                {
                    color = 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);

                // Go for all labels
                foreach (LineLengthLabel l in labels)
                {
                    renderer.RenderText(l.TextLabel);
                }

                // Done
                renderer.Finish();
            }

            // Done
            renderer.Present();
        }
Example #30
0
        override protected 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;

            // Render drawing lines
            if (renderer.StartOverlay(true))
            {
                PixelColor color = snaptonearest ? stitchcolor : losecolor;

                if (points.Count == 1)
                {
                    UpdateReferencePoints(points[0], curp);
                    Vector2D[] shape = GetShape(start, end);

                    //render shape
                    for (int i = 1; i < shape.Length; i++)
                    {
                        renderer.RenderLine(shape[i - 1], shape[i], LINE_THICKNESS, color, true);
                    }

                    //vertices
                    for (int i = 0; i < shape.Length; i++)
                    {
                        renderer.RenderRectangleFilled(new RectangleF(shape[i].x - vsize, shape[i].y - vsize, vsize * 2.0f, vsize * 2.0f), color, true);
                    }

                    //and labels
                    Vector2D[] labelCoords = new[] { start, new Vector2D(end.x, start.y), end, new Vector2D(start.x, end.y), start };
                    for (int i = 1; i < 5; i++)
                    {
                        labels[i - 1].Move(labelCoords[i], labelCoords[i - 1]);
                        renderer.RenderText(labels[i - 1].TextLabel);
                    }

                    //got beveled corners?
                    if (alwaysrendershapehints || shape.Length > minpointscount + 1)
                    {
                        //render hint
                        if (width > 64 * vsize && height > 16 * vsize)
                        {
                            hintlabel.Move(start, end);
                            hintlabel.Text = GetHintText();
                            renderer.RenderText(hintlabel.TextLabel);
                        }

                        //and shape corners
                        for (int i = 0; i < 4; i++)
                        {
                            renderer.RenderRectangleFilled(new RectangleF(labelCoords[i].x - vsize, labelCoords[i].y - vsize, vsize * 2.0f, vsize * 2.0f), General.Colors.InfoLine, true);
                        }
                    }
                }
                else
                {
                    // 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();
        }
        // This draws a point at a specific location
        public virtual bool DrawPointAt(Vector2D pos, bool stitch, bool stitchline)
        {
            if (pos.x < General.Map.Config.LeftBoundary || pos.x > General.Map.Config.RightBoundary ||
                pos.y > General.Map.Config.TopBoundary || pos.y < General.Map.Config.BottomBoundary)
            {
                return(false);
            }

            //mxd. Avoid zero-length lines...
            if (points.Count > 0)
            {
                Vector2D delta = points[points.Count - 1].pos - pos;
                if ((Math.Abs(delta.x) <= 0.001f) && (Math.Abs(delta.y) <= 0.001f))
                {
                    return(true);
                }
            }

            DrawnVertex newpoint = new DrawnVertex();

            newpoint.pos        = pos;
            newpoint.stitch     = stitch;
            newpoint.stitchline = stitchline;
            points.Add(newpoint);
            labels.Add(new LineLengthLabel(labelshowangle, labeluseoffset));
            Update();

            if (points.Count > 1)
            {
                // Check if point stitches with the first
                if (points[points.Count - 1].stitch)
                {
                    Vector2D p1    = points[0].pos;
                    Vector2D p2    = points[points.Count - 1].pos;
                    Vector2D delta = p1 - p2;
                    if ((Math.Abs(delta.x) <= 0.001f) && (Math.Abs(delta.y) <= 0.001f))
                    {
                        //mxd. Seems... logical?
                        if (points.Count == 2)
                        {
                            OnCancel();
                            return(true);
                        }

                        // Finish drawing
                        FinishDraw();
                        return(true);
                    }
                }

                //mxd. Points and existing geometry form a closed shape?
                if (autoclosedrawing)
                {
                    // Determive center point
                    float minx = float.MaxValue;
                    float maxx = float.MinValue;
                    float miny = float.MaxValue;
                    float maxy = float.MinValue;

                    foreach (DrawnVertex v in points)
                    {
                        if (v.pos.x < minx)
                        {
                            minx = v.pos.x;
                        }
                        if (v.pos.x > maxx)
                        {
                            maxx = v.pos.x;
                        }
                        if (v.pos.y < miny)
                        {
                            miny = v.pos.y;
                        }
                        if (v.pos.y > maxy)
                        {
                            maxy = v.pos.y;
                        }
                    }

                    Vector2D shapecenter = new Vector2D(minx + (maxx - minx) / 2, miny + (maxy - miny) / 2);

                    // Determine center point between start and end points
                    minx = Math.Min(points[0].pos.x, points[points.Count - 1].pos.x);
                    maxx = Math.Max(points[0].pos.x, points[points.Count - 1].pos.x);
                    miny = Math.Min(points[0].pos.y, points[points.Count - 1].pos.y);
                    maxy = Math.Max(points[0].pos.y, points[points.Count - 1].pos.y);

                    Vector2D startendcenter = new Vector2D(minx + (maxx - minx) / 2, miny + (maxy - miny) / 2);

                    // Offset the center perpendicular to the start -> end line direction...
                    if (shapecenter == startendcenter)
                    {
                        shapecenter -= new Line2D(points[0].pos, points[points.Count - 1].pos).GetPerpendicular().GetNormal();
                    }

                    // Do the check
                    if (CanFinishDrawing(points[0].pos, points[points.Count - 1].pos, shapecenter))
                    {
                        drawingautoclosed = true;
                        FinishDraw();
                    }
                }
            }

            return(true);
        }