// 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); }
// 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)); }
// 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); }
// 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)); }
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."); } } }
// 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(); }
// 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); } }
// 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); }
// 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); } }
// 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; }
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(); }
// 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(); }
// This draws a point at a specific location public bool DrawPointAt(DrawnVertex p) { return(DrawPointAt(p.pos, p.stitch, p.stitchline)); }
// 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); } }
// 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(); }
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); }