public void Render(Graphics g, WorldTransform t) { Coordinates wll = t.WorldLowerLeft; Coordinates wur = t.WorldUpperRight; PointF ll = new PointF((float)wll.X, (float)wll.Y); PointF ur = new PointF((float)wur.X, (float)wur.Y); float startX = (float)Math.Floor(wll.X / spacing) * spacing; float endX = (float)Math.Ceiling(wur.X / spacing) * spacing; float startY = (float)Math.Floor(wll.Y / spacing) * spacing; float endY = (float)Math.Ceiling(wur.Y / spacing) * spacing; using (Pen p = new Pen(color, 1 / t.Scale)) { if (endX - startX / spacing < 400 && endY - startY / spacing < 400) { for (float x = startX; x <= endX; x += spacing) { g.DrawLine(p, x, ll.Y, x, ur.Y); } for (float y = startY; y <= endY; y += spacing) { g.DrawLine(p, ll.X, y, ur.X, y); } } } }
public DragScreenHelper(IDrawingSurface drawingSurface, Coordinates worldPoint) { this.drawingSurface = drawingSurface; this.originalTransform = drawingSurface.Transform.Clone(); this.originalCenter = originalTransform.CenterPoint; this.moveOrigin = worldPoint + originalCenter; }
public void SetupTransform(WorldTransform transform) { // figure out if the height or width is more constraining Coordinates lowerLeft = transform.WorldLowerLeft; Coordinates upperRight = transform.WorldUpperRight; double width = Math.Abs(upperRight.X - lowerLeft.X); double height = Math.Abs(upperRight.Y - lowerLeft.Y); double rad; if (width < height) { rad = width / 2; } else { rad = height / 2; } // get the heading double heading = Services.VehicleStateService.Heading; // calculate the offset vector Coordinates offsetVector = Coordinates.FromAngle(heading)*rad*offsetFrac; // calculate the vehicle center position transform.CenterPoint = Services.VehicleStateService.Location - offsetVector; }
/// <summary> /// Constructor /// </summary> public RoadDisplay() { // initialize the tranform before calling InitializeComponent so the OnResize method works properly transform = new WorldTransform(); // initialize the form InitializeComponent(); // set our style base.SetStyle(ControlStyles.UserPaint, true); base.SetStyle(ControlStyles.AllPaintingInWmPaint, true); base.SetStyle(ControlStyles.Opaque, true); base.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); base.SetStyle(ControlStyles.ResizeRedraw, true); base.SetStyle(ControlStyles.Selectable, true); // list of object to display displayObjects = new List<IDisplayObject>(); // don't draw things in design mode if (!this.DesignMode) { // initialize the grid this.AddDisplayObject(new DisplayGrid()); } }
public HitBase GetHit(Vector position, ICamera camera, WorldTransform worldTransform) { var newTransform = worldTransform.Compose(this.Offset, this.ParallaxScrollingVector); return this.Sprites.OfType<IHitTarget>() .Select(sprite => sprite.GetHit(position, camera, newTransform)) .FirstOrDefault(spriteHit => spriteHit != null); }
public void Render(System.Drawing.Graphics g, WorldTransform t) { if(Current != null && rndf != null && DrawingUtility.DisplayCurrentGoal) { // draw goal DrawingUtility.DrawControlPoint(rndf.Waypoints[Current].Position, DrawingUtility.CurrentGoalColor, "Goal", System.Drawing.ContentAlignment.TopCenter, ControlPointStyle.SmallCircle, g, t); } }
public WorldTransform Compose(Vector newOffset, Vector newParallaxScrollingVector) { var newTransform = new WorldTransform(this) { offset = newOffset, parallaxScrollingVector = newParallaxScrollingVector }; return newTransform; }
public static void DrawControlLine(IGraphics g, Color c, DashStyle style, Coordinates loc1, Coordinates loc2, WorldTransform wt) { float pw = 1.25f / wt.Scale; using (IPen p = g.CreatePen()) { p.Color = c; p.Width = pw; p.DashStyle = style; g.DrawLine(p, Utility.ToPointF(loc1), Utility.ToPointF(loc2)); } }
public void Render(Graphics g, WorldTransform t) { if (DrawingUtility.DrawArbiterLanePath && arbiterState != null && this.path is Path) { this.RenderRelativePath(arbiterState, (Path)this.path, g, t, true); } if (DrawingUtility.DrawOperationalLanePath && updatedState != null && this.path is Path) { this.RenderRelativePath(updatedState, (Path)this.path, g, t, false); } }
public void Render(System.Drawing.Graphics g, WorldTransform t) { if (DrawingUtility.DisplayFullRoute) { for (int i = 0; i < route.RouteNodes.Count - 1; i++) { RndfWayPoint initial = rndf.Waypoints[route.RouteNodes[i]]; RndfWayPoint final = rndf.Waypoints[route.RouteNodes[i + 1]]; DrawingUtility.DrawControlLine(initial.Position, final.Position, DrawingUtility.RouteColor, g, t); } } }
public void Render(System.Drawing.Graphics g, WorldTransform t) { for (int i = 0; i < Poly.points.Count; i++) { if (i == Poly.points.Count - 1) { DrawingUtility.DrawColoredControlLine(Color.Orange, Poly.points[i], Poly.points[0], g, t); } else { DrawingUtility.DrawColoredControlLine(Color.Orange, Poly.points[i], Poly.points[i + 1], g, t); } } }
public HitBase GetHit(Vector position, ICamera camera, WorldTransform worldTransform) { var rectangle = new Rectangle( worldTransform.Offset.X + this.x, worldTransform.Offset.Y + this.y, this.width, this.height) .Scale(camera.ZoomFactor) .Translate(camera.GetSceneTranslationVector(worldTransform.ParallaxScrollingVector)); return rectangle.Intercept(position) ? new RectangleHit(this) : null; }
private void RenderRelativePath(VehicleState vs, Path transPath, Graphics g, WorldTransform t, bool isArbiterPath) { if((isArbiterPath && DrawingUtility.DrawArbiterLanePath) || (!isArbiterPath && DrawingUtility.DrawOperationalLanePath)) { // compute the rotation matrix to add in our vehicles rotation /*Matrix3 rotMatrix = new Matrix3( Math.Cos(vs.heading.ArcTan), -Math.Sin(vs.heading.ArcTan), 0, Math.Sin(vs.heading.ArcTan), Math.Cos(vs.heading.ArcTan), 0, 0, 0, 1); // compute the translation matrix to move our vehicle's location Matrix3 transMatrix = new Matrix3( 1, 0, vs.xyPosition.X, 0, 1, vs.xyPosition.Y, 0, 0, 1); // compute the combined transformation matrix Matrix3 m = rotMatrix * transMatrix; // clone, transform and add each segment to our path transPath.Transform(m);*/ float nomPixelWidth = 2.0f; float penWidth = nomPixelWidth / t.Scale; Pen arbiterPen = new Pen(Color.FromArgb(100, DrawingUtility.ArbiterLanePath), penWidth); Pen operationalPen = new Pen(Color.FromArgb(100, DrawingUtility.OperationalLanePath), penWidth); // display path foreach (IPathSegment ps in transPath) { if (ps is BezierPathSegment) { BezierPathSegment seg = (BezierPathSegment)ps; CubicBezier cb = seg.cb; if (isArbiterPath) { g.DrawBezier(arbiterPen, DrawingUtility.ToPointF(cb.P0), DrawingUtility.ToPointF(cb.P1), DrawingUtility.ToPointF(cb.P2), DrawingUtility.ToPointF(cb.P3)); } else { g.DrawBezier(operationalPen, DrawingUtility.ToPointF(cb.P0), DrawingUtility.ToPointF(cb.P1), DrawingUtility.ToPointF(cb.P2), DrawingUtility.ToPointF(cb.P3)); } } } } }
public void Render(System.Drawing.Graphics g, WorldTransform t) { Coordinates[] coordArray = log.ToArray(); Coordinates wll = t.WorldLowerLeft; Coordinates wur = t.WorldUpperRight; if (DrawingUtility.DisplayPoseLog) { if (log.Count > 1) { for (int i = 0; i < coordArray.Length - 1; i++) { if(wll.X < coordArray[i].X && wll.Y < coordArray[i].Y && wur.X > coordArray[i].X && wur.Y > coordArray[i].Y) DrawingUtility.DrawControlLine(coordArray[i], coordArray[i + 1], Color.OrangeRed, g, t); } } } }
public static void DrawArrow(IGraphics g, Coordinates startingLoc, Coordinates direction, double len, double headSize, Color lineColor, WorldTransform wt) { Coordinates endingLoc = startingLoc + direction.Normalize(len); Coordinates headPt0 = endingLoc + direction.Rotate(135*Math.PI/180.0).Normalize(headSize); Coordinates headPt1 = endingLoc + direction.Rotate(-135*Math.PI/180.0).Normalize(headSize); IPen pen = g.CreatePen(); pen.Width = 3/wt.Scale; pen.Color = Color.White; PointF ptfStart = Utility.ToPointF(startingLoc); PointF ptfEnd = Utility.ToPointF(endingLoc); PointF ptfHeadPt0 = Utility.ToPointF(headPt0); PointF ptfHeadPt1 = Utility.ToPointF(headPt1); PointF[] headPts = new PointF[] { ptfHeadPt0, ptfEnd, ptfHeadPt1 }; g.DrawLine(pen, ptfStart, ptfEnd); g.DrawLines(pen, headPts); pen.Width = 1/wt.Scale; pen.Color = lineColor; g.DrawLine(pen, ptfStart, ptfEnd); g.DrawLines(pen, headPts); }
public void OnPreRender(UrbanChallenge.OperationalUI.Common.GraphicsWrapper.IGraphics g, WorldTransform transform) { }
public void InitScene(WorldTransform wt, Color background) { this.transform = wt; Coordinates ll = transform.WorldLowerLeft; Coordinates ur = transform.WorldUpperRight; Gl.glViewport(0, 0, (int)transform.ScreenSize.Width, (int)transform.ScreenSize.Height); Gl.glLoadIdentity(); Gl.glOrtho(ll.X, ur.X, ll.Y, ur.Y, 1.0, -1.0); Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT); }
public void CompleteMove(Coordinates orig, Coordinates offset, WorldTransform t) { throw new Exception("The method or operation is not implemented."); }
public HitTestResult HitTest(UrbanChallenge.Common.Coordinates loc, float tol, WorldTransform wt, DisplayObjectFilter filter) { // check filter if (filter.Target == null || filter.Target is ArbiterPerimeterWaypoint) { // get bounding box dependent on tolerance RectangleF bounding = this.GetBoundingBox(wt); bounding.Inflate(tol, tol); // check if contains point if (bounding.Contains(DrawingUtility.ToPointF(loc))) { return(new HitTestResult(this, true, (float)loc.DistanceTo(this.Position))); } } return(new HitTestResult(this, false, float.MaxValue)); }
public abstract void CompleteMove(Coordinates orig, Coordinates offset, WorldTransform t);
public void CancelMove(UrbanChallenge.Common.Coordinates orig, WorldTransform t) { this.position = orig; }
public HitTestResult HitTest(UrbanChallenge.Common.Coordinates loc, float tol, WorldTransform wt, DisplayObjectFilter filter) { if (filter(this)) { Coordinates closest = this.GetClosest(loc); if ((float)loc.DistanceTo(closest) < 5 + tol) { return(new HitTestResult(this, true, (float)loc.DistanceTo(closest))); } } return(new HitTestResult(this, false, float.MaxValue)); }
public System.Drawing.RectangleF GetBoundingBox(WorldTransform wt) { throw new Exception("The method or operation is not implemented."); }
public RulerTool(bool snap, ArbiterRoadNetwork arn, WorldTransform wt) { this.snapToWaypoints = snap; this.roadNetwork = arn; this.wt = wt; }
public void Render(System.Drawing.Graphics g, WorldTransform t) { throw new Exception("The method or operation is not implemented."); }
public void Render(System.Drawing.Graphics g, WorldTransform t) { if (!this.snapToWaypoints || this.roadNetwork == null) { if (this.Current != null) { LLACoord lla = GpsTools.XyToLlaDegrees(Current, projection); string locString = Current.X.ToString("F6") + ", " + Current.Y.ToString("F6") + "\n" + lla.lat.ToString("F6") + ", " + lla.lon.ToString("F6") + "\n" + GpsTools.LlaDegreesToArcMinSecs(lla); DrawingUtility.DrawControlPoint(this.Current, DrawingUtility.ColorToolPointAnalysis, locString, ContentAlignment.BottomCenter, ControlPointStyle.SmallCircle, g, t); } if (Save != null && Save.Count > 0) { foreach (Coordinates tmp in Save) { LLACoord lla = GpsTools.XyToLlaDegrees(tmp, projection); string locString = tmp.X.ToString("F6") + ", " + tmp.Y.ToString("F6") + "\n" + lla.lat.ToString("F6") + ", " + lla.lon.ToString("F6") + "\n" + GpsTools.LlaDegreesToArcMinSecs(lla); DrawingUtility.DrawControlPoint(tmp, DrawingUtility.ColorToolPointAnalysis, locString, ContentAlignment.BottomCenter, ControlPointStyle.SmallCircle, g, t); } } } else { if (this.Current != null) { Coordinates c = this.Current; double minDist = Double.MaxValue; Coordinates?closest = null; foreach (IArbiterWaypoint iaw in this.roadNetwork.ArbiterWaypoints.Values) { double d = iaw.Position.DistanceTo(c); if (d < minDist && ((IDisplayObject)iaw).HitTest(c, (float)0.2, wt, DrawingUtility.DefaultFilter).Hit) { minDist = d; closest = iaw.Position; } } if (closest != null) { c = closest.Value; } LLACoord lla = GpsTools.XyToLlaDegrees(c, projection); string locString = c.X.ToString("F6") + ", " + c.Y.ToString("F6") + "\n" + lla.lat.ToString("F6") + ", " + lla.lon.ToString("F6") + "\n" + GpsTools.LlaDegreesToArcMinSecs(lla); DrawingUtility.DrawControlPoint(c, DrawingUtility.ColorToolPointAnalysis, locString, ContentAlignment.BottomCenter, ControlPointStyle.SmallCircle, g, t); } } }
public PointAnalysisTool(PlanarProjection projection, bool snap, ArbiterRoadNetwork arn, WorldTransform wt) { this.projection = projection; this.snapToWaypoints = snap; this.roadNetwork = arn; this.wt = wt; }
public void CancelMove(Coordinates orig, WorldTransform t) { throw new NotSupportedException(); }
public void Render(Graphics g, WorldTransform t) { Coordinates wll = t.WorldLowerLeft; Coordinates wup = t.WorldUpperRight; if ((position.X < wll.X || position.X > wup.X || position.Y < wll.Y || position.Y > wup.Y)) { return; } Matrix bodyTrans = new Matrix(); bodyTrans.Rotate((float)(this.Heading) * 180 / (float)Math.PI - 90); bodyTrans.Translate((float)position.X, (float)position.Y, MatrixOrder.Append); Matrix origTrans = g.Transform.Clone(); bodyTrans.Multiply(g.Transform, MatrixOrder.Append); g.Transform = bodyTrans; float penWidth = nomPixelWidth / t.Scale; using (Pen p = new Pen(color, penWidth)) { DrawRectangle(g, p, bodyRect); // build the transform for the rear wheels // do the left wheel Matrix wheelTransform = bodyTrans.Clone(); wheelTransform.Translate(-wheelOffset, 0, MatrixOrder.Prepend); try { g.Transform = wheelTransform; g.FillRectangle(Brushes.White, wheelRectL); DrawRectangle(g, p, wheelRectL); } catch (Exception) { } // do the right wheel wheelTransform = bodyTrans.Clone(); wheelTransform.Translate(wheelOffset, 0, MatrixOrder.Prepend); try { g.Transform = wheelTransform; g.FillRectangle(Brushes.White, wheelRectR); DrawRectangle(g, p, wheelRectR); } catch (Exception) { } // do the front wheels // do the left wheel wheelTransform = bodyTrans.Clone(); wheelTransform.Translate(-wheelOffset, wheelbase, MatrixOrder.Prepend); wheelTransform.Rotate(steeringAngle * 180 / (float)Math.PI, MatrixOrder.Prepend); try { g.Transform = wheelTransform; g.FillRectangle(Brushes.White, wheelRectL); DrawRectangle(g, p, wheelRectL); } catch (Exception) { } // do the right wheel wheelTransform = bodyTrans.Clone(); wheelTransform.Translate(wheelOffset, wheelbase, MatrixOrder.Prepend); wheelTransform.Rotate(steeringAngle * 180 / (float)Math.PI, MatrixOrder.Prepend); try { g.Transform = wheelTransform; g.FillRectangle(Brushes.White, wheelRectR); DrawRectangle(g, p, wheelRectR); } catch (Exception) { } } g.Transform = origTrans; // draw Position DrawingUtility.DrawControlPoint(this.position, color, null, ContentAlignment.MiddleCenter, ControlPointStyle.LargeX, g, t); }
public static void DrawArrow(IGraphics g, Coordinates startingLoc, Coordinates direction, double len, double headSize, Color lineColor, WorldTransform wt) { Coordinates endingLoc = startingLoc + direction.Normalize(len); Coordinates headPt0 = endingLoc + direction.Rotate(135 * Math.PI / 180.0).Normalize(headSize); Coordinates headPt1 = endingLoc + direction.Rotate(-135 * Math.PI / 180.0).Normalize(headSize); IPen pen = g.CreatePen(); pen.Width = 3 / wt.Scale; pen.Color = Color.White; PointF ptfStart = Utility.ToPointF(startingLoc); PointF ptfEnd = Utility.ToPointF(endingLoc); PointF ptfHeadPt0 = Utility.ToPointF(headPt0); PointF ptfHeadPt1 = Utility.ToPointF(headPt1); PointF[] headPts = new PointF[] { ptfHeadPt0, ptfEnd, ptfHeadPt1 }; g.DrawLine(pen, ptfStart, ptfEnd); g.DrawLines(pen, headPts); pen.Width = 1 / wt.Scale; pen.Color = lineColor; g.DrawLine(pen, ptfStart, ptfEnd); g.DrawLines(pen, headPts); }
public abstract void BeginMove(Coordinates orig, WorldTransform t);
public abstract void CancelMove(Coordinates orig, WorldTransform t);
public static void DrawControlPoint(IGraphics g, Coordinates loc, Color color, string label, ContentAlignment align, ControlPointStyle style, WorldTransform wt) { DrawControlPoint(g, loc, color, label, align, style, true, wt); }
public static void DrawControlPoint(IGraphics g, Coordinates loc, Color color, string label, ContentAlignment align, ControlPointStyle style, bool drawTextBox, WorldTransform wt) { // figure out the size the control box needs to be in world coordinates to make it // show up as appropriate in view coordinates // invert the scale float scaled_size = 0; if (style == ControlPointStyle.LargeBox || style == ControlPointStyle.LargeCircle || style == ControlPointStyle.LargeX) { scaled_size = cp_large_size / wt.Scale; } else { scaled_size = cp_small_size / wt.Scale; } float scaled_offset = 1 / wt.Scale; // assume that the world transform is currently applied correctly to the graphics RectangleF rect = new RectangleF(-scaled_size / 2, -scaled_size / 2, scaled_size, scaled_size); rect.Offset(Utility.ToPointF(loc)); if (style == ControlPointStyle.LargeBox) { g.FillRectangle(Color.White, rect); // shrink the rect down a little (nominally 1 pixel) rect.Inflate(-scaled_offset, -scaled_offset); g.FillRectangle(color, rect); } else if (style == ControlPointStyle.LargeCircle) { g.FillEllipse(Color.White, rect); // shrink the rect down a little (nominally 1 pixel) rect.Inflate(-scaled_offset, -scaled_offset); g.FillEllipse(color, rect); } else if (style == ControlPointStyle.LargeX) { using (IPen p = g.CreatePen()) { p.Width = 3 / wt.Scale; p.Color = Color.White; g.DrawLine(p, new PointF(rect.Left, rect.Top), new PointF(rect.Right, rect.Bottom)); g.DrawLine(p, new PointF(rect.Left, rect.Bottom), new PointF(rect.Right, rect.Top)); p.Width = scaled_offset; p.Color = color; g.DrawLine(p, new PointF(rect.Left, rect.Top), new PointF(rect.Right, rect.Bottom)); g.DrawLine(p, new PointF(rect.Left, rect.Bottom), new PointF(rect.Right, rect.Top)); } } else if (style == ControlPointStyle.SmallBox) { g.FillRectangle(color, rect); } else if (style == ControlPointStyle.SmallCircle) { g.FillEllipse(color, rect); } else if (style == ControlPointStyle.SmallX) { using (IPen p = g.CreatePen()) { p.Width = 3 / wt.Scale; p.Color = color; g.DrawLine(p, new PointF(rect.Left, rect.Top), new PointF(rect.Right, rect.Bottom)); g.DrawLine(p, new PointF(rect.Left, rect.Bottom), new PointF(rect.Right, rect.Top)); } } if (!string.IsNullOrEmpty(label)) { SizeF strSize = g.MeasureString(label, label_font); float x = 0, y = 0; if (align == ContentAlignment.BottomRight || align == ContentAlignment.MiddleRight || align == ContentAlignment.TopRight) { x = (float)loc.X + cp_label_space / wt.Scale; } else if (align == ContentAlignment.BottomCenter || align == ContentAlignment.MiddleCenter || align == ContentAlignment.TopCenter) { x = (float)loc.X - strSize.Width / (2 * wt.Scale); } else if (align == ContentAlignment.BottomLeft || align == ContentAlignment.MiddleLeft || align == ContentAlignment.TopLeft) { x = (float)loc.X - (strSize.Width + cp_label_space) / wt.Scale; } if (align == ContentAlignment.BottomCenter || align == ContentAlignment.BottomLeft || align == ContentAlignment.BottomRight) { y = (float)loc.Y - cp_label_space / wt.Scale; } else if (align == ContentAlignment.MiddleCenter || align == ContentAlignment.MiddleLeft || align == ContentAlignment.MiddleRight) { y = (float)loc.Y + strSize.Height / (2 * wt.Scale); } else if (align == ContentAlignment.TopCenter || align == ContentAlignment.TopLeft || align == ContentAlignment.TopRight) { y = (float)loc.Y + (strSize.Height + cp_label_space) / wt.Scale; } PointF text_loc = new PointF(x, y); if (drawTextBox) { RectangleF text_rect = new RectangleF(text_loc.X - 4 / wt.Scale, text_loc.Y - 4 / wt.Scale, strSize.Width / wt.Scale, strSize.Height / wt.Scale); g.FillRectangle(Color.FromArgb(127, Color.White), text_rect); } g.DrawString(label, label_font, color, text_loc); } }
public void OnPreRender(IGraphics g, WorldTransform transform) { }
public void Render(Graphics g, WorldTransform t) { if (this.observedVehicle.ObservationState != ObservedVehicleState.Deleted || (this.observedVehicle.ObservationState == ObservedVehicleState.Deleted && DrawingUtility.DisplayDeletedVehicles)) { Coordinates wll = t.WorldLowerLeft; Coordinates wup = t.WorldUpperRight; if ((Position.X < wll.X || Position.X > wup.X || Position.Y < wll.Y || Position.Y > wup.Y)) { return; } Matrix bodyTrans = new Matrix(); bodyTrans.Rotate((float)(this.Heading) * 180 / (float)Math.PI - 90); bodyTrans.Translate((float)Position.X, (float)Position.Y, MatrixOrder.Append); Matrix origTrans = g.Transform.Clone(); bodyTrans.Multiply(g.Transform, MatrixOrder.Append); g.Transform = bodyTrans; float penWidth = nomPixelWidth / t.Scale; using (Pen p = new Pen(color, penWidth)) { DrawRectangle(g, p, bodyRect); // build the transform for the rear wheels // do the left wheel Matrix wheelTransform = bodyTrans.Clone(); wheelTransform.Translate(-WheelOffset, 0, MatrixOrder.Prepend); try { g.Transform = wheelTransform; g.FillRectangle(Brushes.White, wheelRectL); DrawRectangle(g, p, wheelRectL); } catch (Exception) { } // do the right wheel wheelTransform = bodyTrans.Clone(); wheelTransform.Translate(WheelOffset, 0, MatrixOrder.Prepend); try { g.Transform = wheelTransform; g.FillRectangle(Brushes.White, wheelRectR); DrawRectangle(g, p, wheelRectR); } catch (Exception) { } // do the front wheels // do the left wheel wheelTransform = bodyTrans.Clone(); wheelTransform.Translate(-WheelOffset, WheelBase, MatrixOrder.Prepend); wheelTransform.Rotate(steeringAngle * 180 / (float)Math.PI, MatrixOrder.Prepend); try { g.Transform = wheelTransform; g.FillRectangle(Brushes.White, wheelRectL); DrawRectangle(g, p, wheelRectL); } catch (Exception) { } // do the right wheel wheelTransform = bodyTrans.Clone(); wheelTransform.Translate(WheelOffset, WheelBase, MatrixOrder.Prepend); wheelTransform.Rotate(steeringAngle * 180 / (float)Math.PI, MatrixOrder.Prepend); try { g.Transform = wheelTransform; g.FillRectangle(Brushes.White, wheelRectR); DrawRectangle(g, p, wheelRectR); } catch (Exception) { } } g.Transform = origTrans; // draw Position DrawingUtility.DrawControlPoint(this.Position, color, this.observedVehicle.Id.ToString(), ContentAlignment.MiddleCenter, ControlPointStyle.LargeBox, g, t); Coordinates head = this.Position + this.observedVehicle.Heading.Normalize(this.observedVehicle.Length / 2.0); DrawingUtility.DrawControlLine(this.Position, head, color, g, t); } }
public HitBase GetHit(Vector position, ICamera camera, WorldTransform worldTransform, Sprite sprite) { var source = this.definitions[sprite.SpriteName]; var spriteRectangle = new Rectangle( worldTransform.Offset.X + sprite.Position.X, worldTransform.Offset.X + sprite.Position.Y, source.Rectangle.Width, source.Rectangle.Height) .Scale(camera.ZoomFactor) .Translate(camera.GetSceneTranslationVector(worldTransform.ParallaxScrollingVector)); return spriteRectangle.Intercept(position) ? new SpriteHit(sprite) : null; }
public HitBase GetHit(Vector position, ICamera camera, WorldTransform worldTransform) { return this.SpriteSheet.GetHit(position, camera, worldTransform, this); }
public void SetupTransform(WorldTransform transform) { }
// Compute contact points for edge versus circle. // This accounts for edge connectivity. public static bool CollideEdgeAndCircle( Fixture fixtureA, WorldTransform xfA, Fixture fixtureB, WorldTransform xfB, out Manifold manifold) { manifold = new Manifold(); var edgeA = fixtureA as EdgeFixture; var circleB = fixtureB as CircleFixture; System.Diagnostics.Debug.Assert(edgeA != null); System.Diagnostics.Debug.Assert(circleB != null); // Compute circle in frame of edge var q = xfA.ToLocal(xfB.ToGlobal(circleB.Center)); var a = edgeA.Vertex1; var b = edgeA.Vertex2; var e = b - a; // Barycentric coordinates var u = Vector2Util.Dot(e, b - q); var v = Vector2Util.Dot(e, q - a); var radius = edgeA.Radius + circleB.Radius; ContactFeature cf; cf.IndexB = 0; cf.TypeB = (byte)ContactFeature.FeatureType.Vertex; // Region A if (v <= 0.0f) { var p = a; var d = q - p; var dd = Vector2Util.Dot(ref d, ref d); if (dd > radius * radius) { return(false); } // Is there an edge connected to A? if (edgeA.HasVertex0) { var a1 = edgeA.Vertex0; var b1 = a; var e1 = b1 - a1; var u1 = Vector2Util.Dot(e1, b1 - q); // Is the circle in Region AB of the previous edge? if (u1 > 0.0f) { return(false); } } cf.IndexA = 0; cf.TypeA = (byte)ContactFeature.FeatureType.Vertex; manifold.Type = Manifold.ManifoldType.Circles; manifold.LocalPoint = p; manifold.LocalNormal = Vector2.Zero; manifold.PointCount = 1; manifold.Points.Item1.Id.Key = 0; manifold.Points.Item1.Id.Feature = cf; manifold.Points.Item1.LocalPoint = circleB.Center; return(true); } // Region B if (u <= 0.0f) { var p = b; var d = q - p; var dd = Vector2Util.Dot(ref d, ref d); if (dd > radius * radius) { return(false); } // Is there an edge connected to B? if (edgeA.HasVertex3) { var a2 = b; var b2 = edgeA.Vertex3; var e2 = b2 - a2; var v2 = Vector2Util.Dot(e2, q - a2); // Is the circle in Region AB of the next edge? if (v2 > 0.0f) { return(false); } } cf.IndexA = 1; cf.TypeA = (byte)ContactFeature.FeatureType.Vertex; manifold.Type = Manifold.ManifoldType.Circles; manifold.LocalPoint = p; manifold.LocalNormal = Vector2.Zero; manifold.PointCount = 1; manifold.Points.Item1.Id.Key = 0; manifold.Points.Item1.Id.Feature = cf; manifold.Points.Item1.LocalPoint = circleB.Center; return(true); } // Region AB var den = Vector2Util.Dot(ref e, ref e); System.Diagnostics.Debug.Assert(den > 0.0f); { var p = (1.0f / den) * (u * a + v * b); var d = q - p; var dd = Vector2Util.Dot(ref d, ref d); if (dd > radius * radius) { return(false); } } Vector2 n; n.X = -e.Y; n.Y = e.X; if (Vector2Util.Dot(n, q - a) < 0.0f) { n = -n; } n.Normalize(); cf.IndexA = 0; cf.TypeA = (byte)ContactFeature.FeatureType.Face; manifold.Type = Manifold.ManifoldType.FaceA; manifold.LocalPoint = a; manifold.LocalNormal = n; manifold.PointCount = 1; manifold.Points.Item1.Id.Key = 0; manifold.Points.Item1.Id.Feature = cf; manifold.Points.Item1.LocalPoint = circleB.Center; return(true); }
// This function collides and edge and a polygon. // This takes into account edge adjacency. // Algorithm: // 1. Classify v1 and v2 // 2. Classify polygon centroid as front or back // 3. Flip normal if necessary // 4. Initialize normal range to [-pi, pi] about face normal // 5. Adjust normal range according to adjacent edges // 6. Visit each separating axes, only accept axes within the range // 7. Return if _any_ axis indicates separation // 8. Clip public static bool CollideEdgeAndPolygon( Fixture fixtureA, WorldTransform xfA, Fixture fixtureB, WorldTransform xfB, out Manifold manifold) { manifold = new Manifold(); var edgeA = fixtureA as EdgeFixture; var polygonB = fixtureB as PolygonFixture; System.Diagnostics.Debug.Assert(edgeA != null); System.Diagnostics.Debug.Assert(polygonB != null); // This holds polygon B expressed in frame A. var tpv = new Vector2[Settings.MaxPolygonVertices]; var tpn = new Vector2[Settings.MaxPolygonVertices]; Vector2 normal0 = Vector2.Zero, normal1, normal2 = Vector2.Zero; var xf = xfA.MulT(xfB); var centroidB = xf.ToOther(polygonB.Centroid); var v0 = edgeA.Vertex0; var v1 = edgeA.Vertex1; var v2 = edgeA.Vertex2; var v3 = edgeA.Vertex3; var hasVertex0 = edgeA.HasVertex0; var hasVertex3 = edgeA.HasVertex3; var edge1 = v2 - v1; edge1.Normalize(); normal1.X = edge1.Y; normal1.Y = -edge1.X; var offset1 = Vector2Util.Dot(normal1, centroidB - v1); var offset0 = 0.0f; var offset2 = 0.0f; var convex1 = false; var convex2 = false; // Is there a preceding edge? if (hasVertex0) { var edge0 = v1 - v0; edge0.Normalize(); normal0.X = edge0.Y; normal0.Y = -edge0.X; convex1 = Vector2Util.Cross(ref edge0, ref edge1) >= 0.0f; offset0 = Vector2Util.Dot(normal0, centroidB - v0); } // Is there a following edge? if (hasVertex3) { var edge2 = v3 - v2; edge2.Normalize(); normal2.X = edge2.Y; normal2.Y = -edge2.X; convex2 = Vector2Util.Cross(ref edge1, ref edge2) > 0.0f; offset2 = Vector2Util.Dot(normal2, centroidB - v2); } // Determine front or back collision. Determine collision normal limits. bool front; Vector2 normal, lowerLimit, upperLimit; if (hasVertex0 && hasVertex3) { if (convex1 && convex2) { front = offset0 >= 0.0f || offset1 >= 0.0f || offset2 >= 0.0f; if (front) { normal = normal1; lowerLimit = normal0; upperLimit = normal2; } else { normal = -normal1; lowerLimit = -normal1; upperLimit = -normal1; } } else if (convex1) { front = offset0 >= 0.0f || (offset1 >= 0.0f && offset2 >= 0.0f); if (front) { normal = normal1; lowerLimit = normal0; upperLimit = normal1; } else { normal = -normal1; lowerLimit = -normal2; upperLimit = -normal1; } } else if (convex2) { front = offset2 >= 0.0f || (offset0 >= 0.0f && offset1 >= 0.0f); if (front) { normal = normal1; lowerLimit = normal1; upperLimit = normal2; } else { normal = -normal1; lowerLimit = -normal1; upperLimit = -normal0; } } else { front = offset0 >= 0.0f && offset1 >= 0.0f && offset2 >= 0.0f; if (front) { normal = normal1; lowerLimit = normal1; upperLimit = normal1; } else { normal = -normal1; lowerLimit = -normal2; upperLimit = -normal0; } } } else if (hasVertex0) { if (convex1) { front = offset0 >= 0.0f || offset1 >= 0.0f; if (front) { normal = normal1; lowerLimit = normal0; upperLimit = -normal1; } else { normal = -normal1; lowerLimit = normal1; upperLimit = -normal1; } } else { front = offset0 >= 0.0f && offset1 >= 0.0f; if (front) { normal = normal1; lowerLimit = normal1; upperLimit = -normal1; } else { normal = -normal1; lowerLimit = normal1; upperLimit = -normal0; } } } else if (hasVertex3) { if (convex2) { front = offset1 >= 0.0f || offset2 >= 0.0f; if (front) { normal = normal1; lowerLimit = -normal1; upperLimit = normal2; } else { normal = -normal1; lowerLimit = -normal1; upperLimit = normal1; } } else { front = offset1 >= 0.0f && offset2 >= 0.0f; if (front) { normal = normal1; lowerLimit = -normal1; upperLimit = normal1; } else { normal = -normal1; lowerLimit = -normal2; upperLimit = normal1; } } } else { front = offset1 >= 0.0f; if (front) { normal = normal1; lowerLimit = -normal1; upperLimit = -normal1; } else { normal = -normal1; lowerLimit = normal1; upperLimit = normal1; } } // Get polygonB in frameA. var tpc = polygonB.Count; for (var i = 0; i < tpc; ++i) { tpv[i] = xf.ToOther(polygonB.Vertices[i]); tpn[i] = xf.Rotation * polygonB.Normals[i]; } const float radius = 2.0f * Settings.PolygonRadius; Axis edgeAxis; edgeAxis.Type = Axis.AxisType.EdgeA; edgeAxis.Index = front ? 0 : 1; edgeAxis.Separation = float.MaxValue; for (var i = 0; i < tpc; ++i) { var s = Vector2Util.Dot(normal, tpv[i] - v1); if (s < edgeAxis.Separation) { edgeAxis.Separation = s; } } // If no valid normal can be found than this edge should not collide. if (edgeAxis.Type == Axis.AxisType.None) { return(false); } if (edgeAxis.Separation > radius) { return(false); } Axis polygonAxis; polygonAxis.Type = Axis.AxisType.None; polygonAxis.Index = -1; polygonAxis.Separation = float.MinValue; Vector2 perp; perp.X = -normal.Y; perp.Y = normal.X; for (var i = 0; i < tpc; ++i) { var n = -tpn[i]; var s1 = Vector2Util.Dot(n, tpv[i] - v1); var s2 = Vector2Util.Dot(n, tpv[i] - v2); var s = System.Math.Min(s1, s2); if (s > radius) { // No collision polygonAxis.Type = Axis.AxisType.EdgeB; polygonAxis.Index = i; polygonAxis.Separation = s; break; } // Adjacency if (Vector2Util.Dot(ref n, ref perp) >= 0.0f) { if (Vector2Util.Dot(n - upperLimit, normal) < -Settings.AngularSlop) { continue; } } else { if (Vector2Util.Dot(n - lowerLimit, normal) < -Settings.AngularSlop) { continue; } } if (s > polygonAxis.Separation) { polygonAxis.Type = Axis.AxisType.EdgeB; polygonAxis.Index = i; polygonAxis.Separation = s; } } if (polygonAxis.Type != Axis.AxisType.None && polygonAxis.Separation > radius) { return(false); } // Use hysteresis for jitter reduction. const float relativeTol = 0.98f; const float absoluteTol = 0.001f; Axis primaryAxis; if (polygonAxis.Type == Axis.AxisType.None) { primaryAxis = edgeAxis; } else if (polygonAxis.Separation > relativeTol * edgeAxis.Separation + absoluteTol) { primaryAxis = polygonAxis; } else { primaryAxis = edgeAxis; } FixedArray2 <ClipVertex> incidentEdge; // Reference face used for clipping int rfi1, rfi2; Vector2 rfv1, rfv2; Vector2 rfnormal; Vector2 rfsideNormal1; if (primaryAxis.Type == Axis.AxisType.EdgeA) { manifold.Type = Manifold.ManifoldType.FaceA; // Search for the polygon normal that is most anti-parallel to the edge normal. var bestIndex = 0; var bestValue = Vector2Util.Dot(ref normal, ref tpn[0]); for (var i = 1; i < tpc; ++i) { var value = Vector2Util.Dot(ref normal, ref tpn[i]); if (value < bestValue) { bestValue = value; bestIndex = i; } } var i1 = bestIndex; var i2 = i1 + 1 < tpc ? i1 + 1 : 0; incidentEdge = new FixedArray2 <ClipVertex> { Item1 = new ClipVertex { Vertex = tpv[i1], Id = { Feature = { IndexA = 0, IndexB = (byte)i1, TypeA = (byte)ContactFeature.FeatureType.Face, TypeB = (byte)ContactFeature.FeatureType.Vertex } } }, Item2 = new ClipVertex { Vertex = tpv[i2], Id = { Feature = { IndexA = 0, IndexB = (byte)i2, TypeA = (byte)ContactFeature.FeatureType.Face, TypeB = (byte)ContactFeature.FeatureType.Vertex } } } }; if (front) { rfi1 = 0; rfi2 = 1; rfv1 = v1; rfv2 = v2; rfnormal = normal1; } else { rfi1 = 1; rfi2 = 0; rfv1 = v2; rfv2 = v1; rfnormal = -normal1; } } else { manifold.Type = Manifold.ManifoldType.FaceB; incidentEdge = new FixedArray2 <ClipVertex> { Item1 = new ClipVertex { Vertex = v1, Id = { Feature = { IndexA = 0, IndexB = (byte)primaryAxis.Index, TypeA = (byte)ContactFeature.FeatureType.Vertex, TypeB = (byte)ContactFeature.FeatureType.Face } } }, Item2 = new ClipVertex { Vertex = v2, Id = { Feature = { IndexA = 0, IndexB = (byte)primaryAxis.Index, TypeA = (byte)ContactFeature.FeatureType.Vertex, TypeB = (byte)ContactFeature.FeatureType.Face } } } }; rfi1 = primaryAxis.Index; rfi2 = rfi1 + 1 < tpc ? rfi1 + 1 : 0; rfv1 = tpv[rfi1]; rfv2 = tpv[rfi2]; rfnormal = tpn[rfi1]; } rfsideNormal1.X = rfnormal.Y; rfsideNormal1.Y = -rfnormal.X; var rfsideNormal2 = -rfsideNormal1; var rfsideOffset1 = Vector2Util.Dot(ref rfsideNormal1, ref rfv1); var rfsideOffset2 = Vector2Util.Dot(ref rfsideNormal2, ref rfv2); // Clip incident edge against extruded edge1 side edges. FixedArray2 <ClipVertex> clipPoints1, clipPoints2; // Clip to box side 1 var np = ClipSegmentToLine( out clipPoints1, incidentEdge, rfsideNormal1, rfsideOffset1, rfi1); if (np < 2) { return(false); } // Clip to negative box side 1 np = ClipSegmentToLine( out clipPoints2, clipPoints1, rfsideNormal2, rfsideOffset2, rfi2); if (np < 2) { return(false); } // Now clipPoints2 contains the clipped points. if (primaryAxis.Type == Axis.AxisType.EdgeA) { manifold.LocalPoint = rfv1; manifold.LocalNormal = rfnormal; } else { manifold.LocalPoint = polygonB.Vertices[rfi1]; manifold.LocalNormal = polygonB.Normals[rfi1]; } var pointCount = 0; for (var i = 0; i < 2; ++i) { if (Vector2Util.Dot(rfnormal, clipPoints2[i].Vertex - rfv1) <= radius) { var cp = manifold.Points[pointCount]; if (primaryAxis.Type == Axis.AxisType.EdgeA) { cp.LocalPoint = xf.FromOther(clipPoints2[i].Vertex); cp.Id = clipPoints2[i].Id; } else { cp.LocalPoint = clipPoints2[i].Vertex; cp.Id.Feature.TypeA = clipPoints2[i].Id.Feature.TypeB; cp.Id.Feature.TypeB = clipPoints2[i].Id.Feature.TypeA; cp.Id.Feature.IndexA = clipPoints2[i].Id.Feature.IndexB; cp.Id.Feature.IndexB = clipPoints2[i].Id.Feature.IndexA; } manifold.Points[pointCount] = cp; ++pointCount; } } manifold.PointCount = pointCount; return(pointCount > 0); }
public void BeginMove(UrbanChallenge.Common.Coordinates orig, WorldTransform t) { }
public void InMove(Coordinates orig, Coordinates offset, WorldTransform t) { throw new NotSupportedException(); }
public Transform(Entity parent) : base(parent) { Grid = new GridTransform(this); World = new WorldTransform(this); }
private void DrawZoomBox(IGraphics g, WorldTransform transform, Coordinates start, Coordinates end) { float x, y; float width, height; if (start.X < end.X) { x = (float)start.X; width = (float)(end.X - start.X); } else { x = (float)end.X; width = (float)(start.X - end.X); } if (start.Y < end.Y) { y = (float)start.Y; height = (float)(end.Y - start.Y); } else { y = (float)end.Y; height = (float)(start.Y - end.Y); } // create the rectangle RectangleF rect = new RectangleF(x, y, width, height); // draw the transparent background g.FillRectangle(Color.FromArgb(50, Color.Purple), rect); IPen pen = g.CreatePen(); pen.Width = 1.0f/transform.Scale; pen.Color = Color.Purple; g.DrawRectangle(pen, rect); pen.Dispose(); }
public void CompleteMove(UrbanChallenge.Common.Coordinates orig, UrbanChallenge.Common.Coordinates offset, WorldTransform t) { this.position = orig + offset;; }
public HitBase GetHit(Vector position, ICamera camera, WorldTransform worldTransform) { for (var i = 0; i < this.MapSize.Width; i++) for (var j = 0; j < this.MapSize.Height; j++) { var tileRectangle = new Rectangle( this.Offset.X + i * this.TileSize.Width, this.Offset.Y + j * this.TileSize.Height, this.TileSize.Width, this.TileSize.Height) .Scale(camera.ZoomFactor) .Translate(camera.GetSceneTranslationVector(this.ParallaxScrollingVector)); if (tileRectangle.Intercept(position)) return new TileHit(new Point(i, j)); } return null; }
public HitTestResult HitTest(Coordinates loc, float tol, WorldTransform wt, DisplayObjectFilter filter) { throw new Exception("The method or operation is not implemented."); }
public void OnPostRender(IGraphics g, WorldTransform transform) { if (inZoom) { DrawZoomBox(g, transform, startPoint, endPoint); } }
public System.Drawing.RectangleF GetBoundingBox(WorldTransform wt) { return(new System.Drawing.RectangleF()); }
public HitTestResult HitTest(UrbanChallenge.Common.Coordinates loc, float tol, WorldTransform wt, DisplayObjectFilter filter) { return(new HitTestResult(this, false, float.MaxValue)); }
public void Render(System.Drawing.Graphics g, WorldTransform t) { }
public HitBase GetHit(Vector position, ICamera camera, WorldTransform worldTransform) { for (var i = 0; i < this.MapSize.Width; i++) for (var j = 0; j < this.MapSize.Height; j++) { var hexDistance = this.HexSize.Width - (this.HexSize.Width - this.TopEdgeLength) / 2; var halfHeight = this.HexSize.Height / 2; var rectangle = new Rectangle( this.Offset.X + i * hexDistance, this.Offset.Y + j * this.HexSize.Height + (i % 2 == 1 ? halfHeight : 0), this.HexSize.Width, this.HexSize.Height); var mapPosition = position .Translate(-camera.GetSceneTranslationVector(this.ParallaxScrollingVector)) .Scale(1.0f / camera.ZoomFactor); var x1 = (this.HexSize.Width - this.TopEdgeLength) / 2; var x2 = x1 + this.TopEdgeLength; var polygone = new[] { new Vector(rectangle.X + x1, rectangle.Y), new Vector(rectangle.X + x2, rectangle.Y), new Vector(rectangle.X + this.HexSize.Width, rectangle.Y + halfHeight), new Vector(rectangle.X + x2, rectangle.Y + this.HexSize.Height), new Vector(rectangle.X + x1, rectangle.Y + this.HexSize.Height), new Vector(rectangle.X, rectangle.Y + halfHeight) }; if (MathUtil.IsHitPolygone(polygone, mapPosition)) return new HexHit(new Point(i, j)); } return null; }
public void CancelMove(UrbanChallenge.Common.Coordinates orig, WorldTransform t) { throw new Exception("The method or operation is not implemented."); }
public void Render(System.Drawing.Graphics g, WorldTransform t) { // width of drawing float penWidth = nomPixelWidth / t.Scale; // body rectangle RectangleF bodyRect = new RectangleF((float)(-this.Width / 2), -rearOffset, (float)Width, (float)Length); // body transformation matrix Matrix bodyTrans = new Matrix(); bodyTrans.Rotate((float)(this.Heading.ToDegrees() - 90)); bodyTrans.Translate((float)Position.X, (float)Position.Y, MatrixOrder.Append); // save original world transformation matrix Matrix origTrans = g.Transform.Clone(); bodyTrans.Multiply(g.Transform, MatrixOrder.Append); // set the new transform g.Transform = bodyTrans; // make a new pen and draw wheels using (Pen p = new Pen(color, penWidth)) { DrawRectangle(g, p, bodyRect); // build the transform for the rear wheels // do the left wheel Matrix wheelTransform = bodyTrans.Clone(); wheelTransform.Translate(-wheelOffset, 0, MatrixOrder.Prepend); g.Transform = wheelTransform; g.FillRectangle(Brushes.White, wheelRectL); DrawRectangle(g, p, wheelRectL); // do the right wheel wheelTransform = bodyTrans.Clone(); wheelTransform.Translate(wheelOffset, 0, MatrixOrder.Prepend); g.Transform = wheelTransform; g.FillRectangle(Brushes.White, wheelRectR); DrawRectangle(g, p, wheelRectR); // do the front wheels // do the left wheel wheelTransform = bodyTrans.Clone(); wheelTransform.Translate(-wheelOffset, wheelbase, MatrixOrder.Prepend); wheelTransform.Rotate(steeringAngle * 180 / (float)Math.PI, MatrixOrder.Prepend); g.Transform = wheelTransform; g.FillRectangle(Brushes.White, wheelRectL); DrawRectangle(g, p, wheelRectL); // do the right wheel wheelTransform = bodyTrans.Clone(); wheelTransform.Translate(wheelOffset, wheelbase, MatrixOrder.Prepend); wheelTransform.Rotate(steeringAngle * 180 / (float)Math.PI, MatrixOrder.Prepend); g.Transform = wheelTransform; g.FillRectangle(Brushes.White, wheelRectR); DrawRectangle(g, p, wheelRectR); } // return to normal transformation g.Transform = origTrans; // draw car center point DrawingUtility.DrawControlPoint(this.Position, this.color, null, ContentAlignment.MiddleCenter, ControlPointStyle.LargeX, g, t); // check if should draw id if (DrawingUtility.DrawSimCarId) { // get length double idOffset = this.Length / 2; if (this.RearAxleType == RearAxleType.Center) { idOffset = this.Length / 3; } // get label position Coordinates labelPosition = this.Position + this.Heading.Normalize(idOffset); // draw label DrawingUtility.DrawControlLabel(labelPosition, this.color, this.Id, ContentAlignment.MiddleCenter, ControlPointStyle.None, g, t); } }
public void Render(IGraphics g, WorldTransform wt) { Coordinates wll = wt.WorldLowerLeft; Coordinates wur = wt.WorldUpperRight; PointF ll = new PointF((float)wll.X, (float)wll.Y); PointF ur = new PointF((float)wur.X, (float)wur.Y); float startX = (float)Math.Floor(wll.X / spacing) * spacing; float endX = (float)Math.Ceiling(wur.X / spacing) * spacing; float startY = (float)Math.Floor(wll.Y / spacing) * spacing; float endY = (float)Math.Ceiling(wur.Y / spacing) * spacing; IPen p = g.CreatePen(); p.Color = color; p.Width = nominal_pixel_width / wt.Scale; string formatString; if (spacing >= 1) { formatString = "F0"; } else if (spacing >= 0.1) { formatString = "F1"; } else if (spacing >= 0.01) { formatString = "F2"; } else { formatString = "F4"; } // find the largest value (in magnitude) that we'll need to draw, assuming this will be the max length string float testVal = Math.Max(Math.Max(Math.Abs(startX), Math.Abs(endX)), Math.Max(Math.Abs(startY), Math.Abs(endY))); string testString = testVal.ToString(formatString); SizeF nomStringSize = g.MeasureString(testString, labelFont); SizeF unitStringSize = g.MeasureString(testString + " m", labelFont); float pixelSpacing = spacing * wt.Scale; bool drawLabels = showLabels && pixelSpacing >= (nomStringSize.Width + nominal_label_spacing * 2); bool drawUnits = pixelSpacing >= (unitStringSize.Width + nominal_label_spacing * 2); float labelSpacing = nominal_label_spacing / wt.Scale; // don't draw if there are too many lines if ((endX - startX) / spacing <= max_lines && (endY - startY) / spacing <= max_lines && pixelSpacing >= min_pixel_spacing) { for (float x = startX; x <= endX; x += spacing) { g.DrawLine(p, new PointF(x, ll.Y), new PointF(x, ur.Y)); } for (float y = startY; y <= endY; y += spacing) { g.DrawLine(p, new PointF(ll.X, y), new PointF(ur.X, y)); } if (drawLabels) { float minX = ll.X + unitStringSize.Width / wt.Scale + 2 * labelSpacing; for (float x = startX; x <= endX; x += spacing) { if (x > minX) { g.DrawString(x.ToString(formatString) + (drawUnits ? " m" : ""), labelFont, Color.Black, new PointF(x + labelSpacing, ll.Y + labelSpacing + nomStringSize.Height / wt.Scale)); } } for (float y = startY; y <= endY; y += spacing) { g.DrawString(y.ToString(formatString) + (drawUnits ? " m" : ""), labelFont, Color.Black, new PointF(ll.X + labelSpacing, y + labelSpacing)); } } } }