/// <summary> /// Defines the supplied pen with this pattern /// </summary> /// <param name="pen">The pen to define</param> /// <param name="draw">The definition of the draw</param> /// <param name="logWidth">The width of the pen, in logical units</param> /// <param name="b">The brush defining the pen colour</param> internal void DefinePen(Pen pen, ISpatialDisplay draw, float logWidth, Brush b) { float[] style = new float[m_Pattern.Length]; for (int i = 0; i < m_Pattern.Length; i++) { style[i] = draw.LengthToDisplay((double)m_Pattern[i]); // Ensure dashes are at least one pixel in size style[i] = Math.Max(style[i], 1.0F); } // The default is PS_ENDCAP_ROUND, but if the line is thick, the dashes bleed into // each other. I also tried PS_ENDCAP_SQUARE, which seems to bleed even more. // Using PS_ENDCAP_FLAT means you can have really thin dashes along with thick lines, // which looks fine for simple line segments (it might be a poor choice for // convoluted lines however). pen.DashPattern = style; pen.EndCap = LineCap.Flat; pen.Brush = b; pen.Width = logWidth; //pen.CreatePen(PS_GEOMETRIC | PS_USERSTYLE | PS_ENDCAP_FLAT // , logWidth // , &b // , m_NumElement // , style); }
/// <summary> /// Draws a circle /// </summary> /// <param name="display">The display to draw to</param> /// <param name="center">The position of the center of the circle</param> /// <param name="radius">The radius of the circle, in meters on the ground</param> public void Render(ISpatialDisplay display, IPosition center, double radius) { float xc = display.EastingToDisplay(center.X); float yc = display.NorthingToDisplay(center.Y); float r = display.LengthToDisplay(radius); float sz = r + r; display.Graphics.DrawEllipse(m_Pen, xc - r, yc - r, sz, sz); }
/// <summary> /// Calculates the line width in pixels on a display. /// </summary> /// <param name="display">The display where a line will be drawn</param> /// <returns>The pen width, in pixels</returns> internal float LineWidth(ISpatialDisplay display) { if (m_Weight <= 0.0) { return(1.0F); } else { return(display.LengthToDisplay(m_Weight)); } }
/// <summary> /// Draws a circular arc /// </summary> /// <param name="display">The display to draw to</param> /// <param name="arc">The circular arc</param> public void Render(ISpatialDisplay display, IClockwiseCircularArcGeometry arc) { ICircleGeometry circle = arc.Circle; IWindow extent = CircleGeometry.GetExtent(circle); float topLeftX = display.EastingToDisplay(extent.Min.X); float topLeftY = display.NorthingToDisplay(extent.Max.Y); float size = 2.0f * display.LengthToDisplay(circle.Radius); float startAngle = (float)(arc.StartBearingInRadians * MathConstants.RADTODEG - 90.0); float sweepAngle = (float)(arc.SweepAngleInRadians * MathConstants.RADTODEG); display.Graphics.DrawArc(m_Pen, topLeftX, topLeftY, size, size, startAngle, sweepAngle); }
/// <summary> /// Draws a point as a plus sign. /// </summary> /// <param name="display">The display to draw to</param> /// <param name="position">The position of the center of the point</param> public void RenderPlus(ISpatialDisplay display, IPosition position) { float size = display.LengthToDisplay(m_PointHeight.Meters); if (size > 1.0F) { PointF p = CreatePoint(display, position); float d = size * 0.5F; display.Graphics.DrawLine(m_Pen, p.X - d, p.Y, p.X + d, p.Y); display.Graphics.DrawLine(m_Pen, p.X, p.Y - d, p.X, p.Y + d); } }
public Font CreateFont(ISpatialDisplay display) { double ght = (double)m_Height; float dht = display.LengthToDisplay(ght); int ht = (int)dht; if (ht <= 0) { return(null); } return(CreateFont(ht, 0.0)); }
/// <summary> /// Draws a point as a triangle. /// </summary> /// <param name="display">The display to draw to</param> /// <param name="position">The position of the center of the point</param> public void RenderTriangle(ISpatialDisplay display, IPosition position) { float size = display.LengthToDisplay(m_PointHeight.Meters); if (size > 1.0F) { PointF p = CreatePoint(display, position); float d = size * 0.5F; PointF[] outline = new PointF[4]; outline[0] = new PointF(p.X - d, p.Y + d); outline[1] = new PointF(p.X + d, p.Y + d); outline[2] = new PointF(p.X, p.Y - d); outline[3] = outline[0]; display.Graphics.FillPolygon(m_Fill.Brush, outline); } }
/// <summary> /// Highlights a line. /// </summary> /// <param name="line">The line to highlight</param> void Highlight(LineFeature line) { ISpatialDisplay display = ActiveDisplay; // Create thick pen (we want a line that is 1mm wide, corresponding // to the pick aperture). DrawStyle style = new HighlightStyle(); style.LineColor = m_LineColor; double scale = display.MapScale; float pxwid = display.LengthToDisplay(scale * 0.001); style.Pen.Width = pxwid; // Do the draw line.Render(display, style); }
/// <summary> /// Draws a point /// </summary> /// <param name="display">The display to draw to</param> /// <param name="position">The position of the center of the point</param> public virtual void Render(ISpatialDisplay display, IPosition position) { float size = display.LengthToDisplay(m_PointHeight.Meters); if (size > 1.0F) { PointF p = CreatePoint(display, position); float d = size * 0.5F; if (FillColor == Color.Transparent) { display.Graphics.DrawRectangle(m_Pen, p.X - d, p.Y - d, size, size); } else { display.Graphics.FillRectangle(Brush, p.X - d, p.Y - d, size, size); } } }
/// <summary> /// Defines the supplied pen with this style /// </summary> /// <param name="pen">The pen to define</param> /// <param name="draw">The definition of the draw</param> internal override void DefinePen(ScaleSpecificPen pen, ISpatialDisplay draw) { float fwt = (m_Weight > 0.0 ? draw.LengthToDisplay(m_Weight) : 0.0F); if (m_Pattern != null) { m_Pattern.DefinePen(pen.Pen, draw, fwt, new SolidBrush(this.Color)); } // MUST be solid for anything that has non-zero weight //else if ((int)fwt != 0) // pen.CreateSolidPen(fwt, this.Color); else { pen.CreateSolidPen(0.0F, this.Color); Pen p = pen.Pen; p.DashStyle = m_Style; p.Width = fwt; p.StartCap = LineCap.Round; p.EndCap = LineCap.Round; } }
public Font CreateFont(ISpatialDisplay display) { double ght = (double)m_Height; float dht = display.LengthToDisplay(ght); int ht = (int)dht; if (ht<=0) return null; return CreateFont(ht, 0.0); }
/// <summary> /// Creates the font used to present the string. /// </summary> /// <param name="display">The display on which the string will be displayed</param> /// <returns> /// The corresponding font (may be null if the font is too small to be drawn) /// </returns> public Font CreateFont(ISpatialDisplay display) { float heightInPixels = display.LengthToDisplay(m_Height); return(new Font("Arial", heightInPixels, m_FontStyle, GraphicsUnit.Pixel)); }
/// <summary> /// Draws a point as a triangle. /// </summary> /// <param name="display">The display to draw to</param> /// <param name="position">The position of the center of the point</param> public void RenderTriangle(ISpatialDisplay display, IPosition position) { float size = display.LengthToDisplay(m_PointHeight.Meters); if (size>1.0F) { PointF p = CreatePoint(display, position); float d = size * 0.5F; PointF[] outline = new PointF[4]; outline[0] = new PointF(p.X-d, p.Y+d); outline[1] = new PointF(p.X+d, p.Y+d); outline[2] = new PointF(p.X, p.Y-d); outline[3] = outline[0]; display.Graphics.FillPolygon(m_Fill.Brush, outline); } }
/// <summary> /// Draws a point as a plus sign. /// </summary> /// <param name="display">The display to draw to</param> /// <param name="position">The position of the center of the point</param> public void RenderPlus(ISpatialDisplay display, IPosition position) { float size = display.LengthToDisplay(m_PointHeight.Meters); if (size>1.0F) { PointF p = CreatePoint(display, position); float d = size * 0.5F; display.Graphics.DrawLine(m_Pen, p.X-d, p.Y, p.X+d, p.Y); display.Graphics.DrawLine(m_Pen, p.X, p.Y-d, p.X, p.Y+d); } }
/// <summary> /// Draws a circle /// </summary> /// <param name="display">The display to draw to</param> /// <param name="center">The position of the center of the circle</param> /// <param name="radius">The radius of the circle, in meters on the ground</param> public void Render(ISpatialDisplay display, IPosition center, double radius) { float xc = display.EastingToDisplay(center.X); float yc = display.NorthingToDisplay(center.Y); float r = display.LengthToDisplay(radius); float sz = r+r; display.Graphics.DrawEllipse(m_Pen, xc-r, yc-r, sz, sz); }
/// <summary> /// Draws a text string (annotation) /// </summary> /// <param name="display">The display to draw to</param> /// <param name="text">The item of text</param> public void Render(ISpatialDisplay display, IString text) { // Draw the outline if it's too small Font f = text.CreateFont(display); IPosition[] outline = text.Outline; if (outline == null) { // This is a bit of a hack that covers the Backsight.Editor.Annotation class... if (f == null) return; // Note that the order you apply the transforms is significant... IPointGeometry pg = text.Position; PointF p = CreatePoint(display, pg); display.Graphics.TranslateTransform(p.X, p.Y); double rotation = text.Rotation.Degrees; display.Graphics.RotateTransform((float)rotation); StringFormat sf = text.Format; if (sf == null) sf = StringFormat.GenericTypographic; string s = text.Text; display.Graphics.DrawString(s, f, Brush, 0, 0, sf); display.Graphics.ResetTransform(); // TEST -- draw rotated 180 to see if that's all we need to do flip... looks good /* display.Graphics.TranslateTransform(p.X, p.Y); display.Graphics.RotateTransform((float)rotation+180); display.Graphics.DrawString(s, f, Brush, 0, 0, sf); display.Graphics.ResetTransform(); */ } else { if (f == null) { Render(display, outline); } else { string s = text.Text; // Note that the order you apply the transforms is significant... PointF p = CreatePoint(display, outline[0]); display.Graphics.TranslateTransform(p.X, p.Y); double rotation = text.Rotation.Degrees; display.Graphics.RotateTransform((float)rotation); Size size = TextRenderer.MeasureText(s, f); double groundWidth = BasicGeom.Distance(outline[0], outline[1]); float xScale = display.LengthToDisplay(groundWidth) / (float)size.Width; float yScale = f.Size / (float)size.Height; // ScaleTransform doesn't like values of 0 (single character names lead to outline with no width, // should really see if proper character width can be determined in that case). if (xScale < Single.Epsilon) xScale = yScale; display.Graphics.ScaleTransform(xScale, yScale); // I tried StringFormat.GenericDefault, but that seems to leave too much // leading space. display.Graphics.DrawString(s, f, Brush, 0, 0, StringFormat.GenericTypographic); display.Graphics.ResetTransform(); } } }
/// <summary> /// Draws a circular arc /// </summary> /// <param name="display">The display to draw to</param> /// <param name="arc">The circular arc</param> public void Render(ISpatialDisplay display, IClockwiseCircularArcGeometry arc) { ICircleGeometry circle = arc.Circle; IWindow extent = CircleGeometry.GetExtent(circle); float topLeftX = display.EastingToDisplay(extent.Min.X); float topLeftY = display.NorthingToDisplay(extent.Max.Y); float size = 2.0f * display.LengthToDisplay(circle.Radius); float startAngle = (float)(arc.StartBearingInRadians * MathConstants.RADTODEG - 90.0); float sweepAngle = (float)(arc.SweepAngleInRadians * MathConstants.RADTODEG); display.Graphics.DrawArc(m_Pen, topLeftX, topLeftY, size, size, startAngle, sweepAngle); }
/// <summary> /// Draws a point /// </summary> /// <param name="display">The display to draw to</param> /// <param name="position">The position of the center of the point</param> public virtual void Render(ISpatialDisplay display, IPosition position) { float size = display.LengthToDisplay(m_PointHeight.Meters); if (size>1.0F) { PointF p = CreatePoint(display, position); float d = size * 0.5F; if (FillColor == Color.Transparent) display.Graphics.DrawRectangle(m_Pen, p.X-d, p.Y-d, size, size); else display.Graphics.FillRectangle(Brush, p.X-d, p.Y-d, size, size); } }
/// <summary> /// Draws a text string (annotation) /// </summary> /// <param name="display">The display to draw to</param> /// <param name="text">The item of text</param> public void Render(ISpatialDisplay display, IString text) { // Draw the outline if it's too small Font f = text.CreateFont(display); IPosition[] outline = text.Outline; if (outline == null) { // This is a bit of a hack that covers the Backsight.Editor.Annotation class... if (f == null) { return; } // Note that the order you apply the transforms is significant... IPointGeometry pg = text.Position; PointF p = CreatePoint(display, pg); display.Graphics.TranslateTransform(p.X, p.Y); double rotation = text.Rotation.Degrees; display.Graphics.RotateTransform((float)rotation); StringFormat sf = text.Format; if (sf == null) { sf = StringFormat.GenericTypographic; } string s = text.Text; display.Graphics.DrawString(s, f, Brush, 0, 0, sf); display.Graphics.ResetTransform(); // TEST -- draw rotated 180 to see if that's all we need to do flip... looks good /* * display.Graphics.TranslateTransform(p.X, p.Y); * display.Graphics.RotateTransform((float)rotation+180); * display.Graphics.DrawString(s, f, Brush, 0, 0, sf); * display.Graphics.ResetTransform(); */ } else { if (f == null) { Render(display, outline); } else { string s = text.Text; // Note that the order you apply the transforms is significant... PointF p = CreatePoint(display, outline[0]); display.Graphics.TranslateTransform(p.X, p.Y); double rotation = text.Rotation.Degrees; display.Graphics.RotateTransform((float)rotation); Size size = TextRenderer.MeasureText(s, f); double groundWidth = BasicGeom.Distance(outline[0], outline[1]); float xScale = display.LengthToDisplay(groundWidth) / (float)size.Width; float yScale = f.Size / (float)size.Height; // ScaleTransform doesn't like values of 0 (single character names lead to outline with no width, // should really see if proper character width can be determined in that case). if (xScale < Single.Epsilon) { xScale = yScale; } display.Graphics.ScaleTransform(xScale, yScale); // I tried StringFormat.GenericDefault, but that seems to leave too much // leading space. display.Graphics.DrawString(s, f, Brush, 0, 0, StringFormat.GenericTypographic); display.Graphics.ResetTransform(); } } }
/// <summary> /// Defines the supplied pen with this pattern /// </summary> /// <param name="pen">The pen to define</param> /// <param name="draw">The definition of the draw</param> /// <param name="logWidth">The width of the pen, in logical units</param> /// <param name="b">The brush defining the pen colour</param> internal void DefinePen(Pen pen, ISpatialDisplay draw, float logWidth, Brush b) { float[] style = new float[m_Pattern.Length]; for (int i=0; i<m_Pattern.Length; i++) { style[i] = draw.LengthToDisplay((double)m_Pattern[i]); // Ensure dashes are at least one pixel in size style[i] = Math.Max(style[i], 1.0F); } // The default is PS_ENDCAP_ROUND, but if the line is thick, the dashes bleed into // each other. I also tried PS_ENDCAP_SQUARE, which seems to bleed even more. // Using PS_ENDCAP_FLAT means you can have really thin dashes along with thick lines, // which looks fine for simple line segments (it might be a poor choice for // convoluted lines however). pen.DashPattern = style; pen.EndCap = LineCap.Flat; pen.Brush = b; pen.Width = logWidth; //pen.CreatePen(PS_GEOMETRIC | PS_USERSTYLE | PS_ENDCAP_FLAT // , logWidth // , &b // , m_NumElement // , style); }
/// <summary> /// Defines the supplied pen with this style /// </summary> /// <param name="pen">The pen to define</param> /// <param name="draw">The definition of the draw</param> internal override void DefinePen(ScaleSpecificPen pen, ISpatialDisplay draw) { float fwt = (m_Weight > 0.0 ? draw.LengthToDisplay(m_Weight) : 0.0F); if (m_Pattern != null) m_Pattern.DefinePen(pen.Pen, draw, fwt, new SolidBrush(this.Color)); // MUST be solid for anything that has non-zero weight //else if ((int)fwt != 0) // pen.CreateSolidPen(fwt, this.Color); else { pen.CreateSolidPen(0.0F, this.Color); Pen p = pen.Pen; p.DashStyle = m_Style; p.Width = fwt; p.StartCap = LineCap.Round; p.EndCap = LineCap.Round; } }
/// <summary> /// Creates the font used to present the string. /// </summary> /// <param name="display">The display on which the string will be displayed</param> /// <returns> /// The corresponding font (may be null if the font is too small to be drawn) /// </returns> public Font CreateFont(ISpatialDisplay display) { float heightInPixels = display.LengthToDisplay(m_Height); return new Font("Arial", heightInPixels, m_FontStyle, GraphicsUnit.Pixel); }
/// <summary> /// Calculates the line width in pixels on a display. /// </summary> /// <param name="display">The display where a line will be drawn</param> /// <returns>The pen width, in pixels</returns> internal float LineWidth(ISpatialDisplay display) { if (m_Weight<=0.0) return 1.0F; else return display.LengthToDisplay(m_Weight); }