public void DrawPeriodicPoint(LocalCS cs, Geometry.Point point, Geometry.Box box, Geometry.Unit unit, bool drawDots) { PointF p = cs.Convert(point); DrawPoint(p); double pi2 = 2 * Geometry.HalfAngle(unit); Pen pen = drawDots ? this.penDot : this.pen; // draw points on the west double x_tmp = point[0] - pi2; while (x_tmp >= box.Min[0]) { p.X = cs.ConvertX(x_tmp); DrawPoint(p, pen); x_tmp -= pi2; } // draw points on the east x_tmp = point[0] + pi2; while (x_tmp <= box.Max[0]) { p.X = cs.ConvertX(x_tmp); DrawPoint(p, pen); x_tmp += pi2; } }
public PeriodicDrawableBox(LocalCS cs, Geometry.IRandomAccessRange <Geometry.Point> points, Geometry.Unit unit) : base(true) { int count = points.Count + 1; xs_orig = new float[count]; points_rel = new PointF[count]; xs_orig[0] = cs.ConvertX(points[0][0]); points_rel[0] = cs.Convert(points[0]); for (int i = 1; i < points.Count; ++i) { xs_orig[i] = cs.ConvertX(points[i][0]); // always relative to p0 double distNorm = Geometry.NormalizedAngleUnsigned(points[i][0] - points[0][0], unit); // [0, 2pi] - min is always lesser than max double x_curr = points[0][0] + distNorm; // always relative to p0 points_rel[i] = new PointF(cs.ConvertX(x_curr), cs.ConvertY(points[i][1])); } // close xs_orig[points.Count] = xs_orig[0]; points_rel[points.Count] = points_rel[0]; }
public void DrawPeriodicPoint(LocalCS cs, Geometry.Point point, Geometry.Box box, Geometry.Unit unit) { PointF p = cs.Convert(point); DrawPoint(p); Pen penDot = (Pen)pen.Clone(); penDot.DashStyle = DashStyle.Dot; double pi2 = 2 * Geometry.HalfAngle(unit); // draw points on the west double x_tmp = point[0] - pi2; while (x_tmp >= box.Min[0]) { p.X = cs.ConvertX(x_tmp); DrawPoint(p, penDot); x_tmp -= pi2; } // draw points on the east x_tmp = point[0] + pi2; while (x_tmp <= box.Max[0]) { p.X = cs.ConvertX(x_tmp); DrawPoint(p, penDot); x_tmp += pi2; } }
void DrawLines(Geometry.Box box, Graphics graphics, Settings settings, Geometry.Traits traits, double diffX) { // NOTE: traits == null bool fill = true; LocalCS cs = new LocalCS(box, graphics, fill); //float dx = cs.ConvertDimensionX(diffX); //float s = Math.Min(Math.Max(dx, 1.0f), 2.0f); Drawer drawer = new Drawer(graphics, settings.color); if (points.Count == 1) { float x = cs.ConvertX(points[0][0]); float y = cs.ConvertY(points[0][1]); drawer.DrawLine(x, y - 0.5f, x, y + 0.5f); } else if (points.Count > 1) { float xp = cs.ConvertX(points[0][0]); float yp = cs.ConvertY(points[0][1]); for (int i = 1; i < points.Count; ++i) { float x = cs.ConvertX(points[i][0]); float y = cs.ConvertY(points[i][1]); drawer.DrawLine(xp, yp, x, y); xp = x; yp = y; } } }
public PeriodicDrawableRange(LocalCS cs, Geometry.IRandomAccessRange <Geometry.Point> points, Geometry.Box box, Geometry.Unit unit) { if (points.Count < 2) { return; } double pi = Geometry.HalfAngle(unit); periodf = cs.ConvertDimension(2 * pi); xs_orig = new float[points.Count]; points_rel = new PointF[points.Count]; xs_orig[0] = cs.ConvertX(points[0][0]); points_rel[0] = cs.Convert(points[0]); minf = points_rel[0].X; maxf = points_rel[0].X; double x0 = Geometry.NormalizedAngle(points[0][0], unit); double x0_prev = points[0][0]; for (int i = 1; i < points.Count; ++i) { xs_orig[i] = cs.ConvertX(points[i][0]); double x1 = Geometry.NormalizedAngle(points[i][0], unit); double dist = x1 - x0; // [-2pi, 2pi] double distNorm = Geometry.NormalizedAngle(dist, unit); // [-pi, pi] double x0_curr = x0_prev + distNorm; points_rel[i] = new PointF(cs.ConvertX(x0_curr), cs.ConvertY(points[i][1])); // expand relative box X if (points_rel[i].X < minf) { minf = points_rel[i].X; } if (points_rel[i].X > maxf) { maxf = points_rel[i].X; } x0_prev = x0_curr; x0 = x1; } box_minf = cs.ConvertX(box.Min[0]); box_maxf = cs.ConvertX(box.Max[0]); }
void DrawBars(Geometry.Box box, Graphics graphics, Settings settings, Geometry.Traits traits) { // NOTE: traits == null bool fill = true; LocalCS cs = new LocalCS(box, graphics, fill); float y0 = cs.ConvertY(0); float x0 = cs.ConvertX(0); float x1 = cs.ConvertX(1); float dx = Math.Abs(x1 - x0); bool drawLines = dx < 4; double i = 0; if (drawLines) { float penWidth = dx < 2 ? 1 : 2; Pen pen = new Pen(settings.color, penWidth); foreach (double v in values) { float x = cs.ConvertX(i); float y = cs.ConvertY(v); graphics.DrawLine(pen, x, y0, x, y); i += 1; } } else { Drawer drawer = new Drawer(graphics, settings.color); foreach (double v in values) { float x = cs.ConvertX(i); float y = cs.ConvertY(v); float t = Math.Min(y0, y); float h = Math.Abs(y - y0); float xl = dx / 3.0f; float xw = dx * 2.0f / 3.0f; if (h >= 2) { drawer.DrawRectangle(x - xl, t, xw, h); drawer.FillRectangle(x - xl, t, xw, h); } else { drawer.DrawLine(x - xl, t, x + xl, t); } i += 1; } } }
public void DrawPeriodic(LocalCS cs, Geometry.Box box, Geometry.Interval interval, Geometry.Unit unit, IPeriodicDrawable drawer, bool fill, bool drawDirs, bool drawDots) { double twoPi = Geometry.FullAngle(unit); float periodf = cs.ConvertDimensionX(twoPi); float box_minf = cs.ConvertX(box.Min[0]); float box_maxf = cs.ConvertX(box.Max[0]); float minf = cs.ConvertX(interval.Min); float maxf = cs.ConvertX(interval.Max); if (maxf >= box_minf && minf <= box_maxf) { drawer.DrawOne(this, 0, fill, drawDirs, drawDots); } // west float minf_i = minf; float maxf_i = maxf; float translationf = 0; while (maxf_i >= box_minf && Util.Assign(ref maxf_i, maxf_i - periodf)) { translationf -= periodf; minf_i -= periodf; //maxf_i -= periodf; // subtracted above if (maxf_i >= box_minf && minf_i <= box_maxf) { drawer.DrawOne(this, translationf, fill, drawDirs, drawDots); } } // east minf_i = minf; maxf_i = maxf; translationf = 0; while (minf_i <= box_maxf && Util.Assign(ref minf_i, minf_i + periodf)) { translationf += periodf; //minf_i += periodf; // added above maxf_i += periodf; if (maxf_i >= box_minf && minf_i <= box_maxf) { drawer.DrawOne(this, translationf, fill, drawDirs, drawDots); } } }
public PeriodicDrawableNSphere(LocalCS cs, Geometry.NSphere nsphere, Geometry.Box box, Geometry.Unit unit) { double pi = Geometry.HalfAngle(unit); periodf = cs.ConvertDimension(2 * pi); c_rel = cs.Convert(nsphere.Center); r = cs.ConvertDimension(nsphere.Radius); minf = c_rel.X - r; maxf = c_rel.X + r; box_minf = cs.ConvertX(box.Min[0]); box_maxf = cs.ConvertX(box.Max[0]); }
public void DrawPeriodic(LocalCS cs, Geometry.Box box, Geometry.Interval interval, Geometry.Unit unit, IPeriodicDrawable drawer, bool fill, bool drawDirs, bool drawDots) { double pi = Geometry.HalfAngle(unit); float periodf = cs.ConvertDimensionX(2 * pi); float box_minf = cs.ConvertX(box.Min[0]); float box_maxf = cs.ConvertX(box.Max[0]); float minf = cs.ConvertX(interval.Min); float maxf = cs.ConvertX(interval.Max); if (maxf >= box_minf && minf <= box_maxf) { drawer.DrawOne(this, 0, fill, drawDirs, drawDots); } // west float minf_i = minf; float maxf_i = maxf; float translationf = 0; while (maxf_i >= box_minf) { translationf -= periodf; minf_i -= periodf; maxf_i -= periodf; if (maxf_i >= box_minf && minf_i <= box_maxf) { drawer.DrawOne(this, translationf, fill, drawDirs, drawDots); } } // east minf_i = minf; maxf_i = maxf; translationf = 0; while (minf_i <= box_maxf) { translationf += periodf; minf_i += periodf; maxf_i += periodf; if (maxf_i >= box_minf && minf_i <= box_maxf) { drawer.DrawOne(this, translationf, fill, drawDirs, drawDots); } } }
public PeriodicDrawableBox(LocalCS cs, Geometry.IRandomAccessRange <Geometry.Point> points, Geometry.Box box, Geometry.Unit unit) { double pi = Geometry.HalfAngle(unit); periodf = cs.ConvertDimension(2 * pi); xs_orig = new float[points.Count]; points_rel = new PointF[points.Count]; xs_orig[0] = cs.ConvertX(points[0][0]); points_rel[0] = cs.Convert(points[0]); minf = points_rel[0].X; maxf = points_rel[0].X; double x0 = Geometry.NormalizedAngle(points[0][0], unit); for (int i = 1; i < points.Count; ++i) { xs_orig[i] = cs.ConvertX(points[i][0]); double x1 = Geometry.NormalizedAngle(points[i][0], unit); double dist = x1 - x0; // [-2pi, 2pi] double distNorm = Geometry.NormalizedAngle(dist, unit); // [-pi, pi] while (distNorm < 0) { distNorm += 2 * Geometry.HalfAngle(unit); // [0, 2pi] - min is always lesser than max } double x0_curr = points[0][0] + distNorm; // always relative to p0 points_rel[i] = new PointF(cs.ConvertX(x0_curr), cs.ConvertY(points[i][1])); // expand relative box X if (points_rel[i].X < minf) { minf = points_rel[i].X; } if (points_rel[i].X > maxf) { maxf = points_rel[i].X; } } box_minf = cs.ConvertX(box.Min[0]); box_maxf = cs.ConvertX(box.Max[0]); }
private static PointF[] DensifyAndConvert(LocalCS cs, Geometry.Point p0, Geometry.Point p1, double length, Geometry.Unit unit) { double distNorm = Geometry.NormalizedAngleSigned(p1[0] - p0[0], unit); bool intersPole = IsAntipodal(distNorm, unit); double halfPi = Geometry.HalfAngle(unit) / 2; double poleLat = p1[1] - p0[1] >= 0 ? halfPi : -halfPi; int intersPoleIndex = -1; Geometry.Point[] densPoints = Geometry.SphericalDensify(p0, p1, length, unit); PointF[] result = new PointF[densPoints.Length + (intersPole ? 2 : 0)]; int k = 0; for (int j = 0; j < densPoints.Length; ++j, ++k) { double densDistNorm = Geometry.NormalizedAngleSigned(densPoints[j][0] - p0[0], unit); densPoints[j][0] = p0[0] + densDistNorm; if (intersPole && intersPoleIndex == -1 && Math.Abs(densDistNorm) > halfPi) { intersPoleIndex = j; Geometry.Point p = j == 0 ? p0 : densPoints[j - 1]; float poleF = cs.ConvertY(poleLat); result[k++] = new PointF(cs.ConvertX(p[0]), poleF); result[k++] = new PointF(cs.ConvertX(densPoints[j][0]), poleF); } result[k] = cs.Convert(densPoints[j]); } // last segment if (intersPole && intersPoleIndex == -1) { int j = densPoints.Length; intersPoleIndex = j; float poleF = cs.ConvertY(poleLat); result[j] = new PointF(cs.ConvertX(densPoints[j - 1][0]), poleF); result[j + 1] = new PointF(cs.ConvertX(p1[0]), poleF); } return(result); }
public void DrawPeriodicPoint(LocalCS cs, Geometry.Point point, Geometry.Box box, Geometry.Unit unit, bool drawDots) { PointF p = cs.Convert(point); DrawPoint(p); double twoPi = Geometry.FullAngle(unit); Pen pen = drawDots ? this.penDot : this.pen; // NOTE: Use AssignChanged becasue for big coordinates subtracting/adding // twoPi doesn't change the value of x_tmp which causes infinite loop float x = Math.Min(Math.Max(p.X, 0.0f), cs.Width); double nPeriodsWest = (point[0] - box.Min[0]) / twoPi; float pixelsWest = x; double nPeriodsEast = (box.Max[0] - point[0]) / twoPi; float pixelsEast = cs.Width - x; if (nPeriodsWest <= pixelsWest / 5) { // draw points on the west double x_tmp = point[0]; while (Util.Assign(ref x_tmp, x_tmp - twoPi) && x_tmp >= box.Min[0]) { p.X = cs.ConvertX(x_tmp); DrawPoint(p, pen); } } if (nPeriodsEast <= pixelsEast / 5) { // draw points on the east double x_tmp = point[0]; while (Util.Assign(ref x_tmp, x_tmp + twoPi) && x_tmp <= box.Max[0]) { p.X = cs.ConvertX(x_tmp); DrawPoint(p, pen); } } }
void DrawPoints(Geometry.Box box, Graphics graphics, Settings settings, Geometry.Traits traits) { // NOTE: traits == null bool fill = true; LocalCS cs = new LocalCS(box, graphics, fill); float x0 = cs.ConvertX(0); float x1 = cs.ConvertX(1); float dx = Math.Abs(x1 - x0); float s = Math.Min(Math.Max(dx * 2.0f, 2.0f), 5.0f); double i = 0; Drawer drawer = new Drawer(graphics, settings.color); foreach (double v in values) { float x = cs.ConvertX(i); float y = cs.ConvertY(v); drawer.DrawPoint(x, y, s); i += 1; } }
void DrawLines(Geometry.Box box, Graphics graphics, Settings settings, Geometry.Traits traits) { // NOTE: traits == null bool fill = true; LocalCS cs = new LocalCS(box, graphics, fill); //float x0 = cs.ConvertX(0); //float x1 = cs.ConvertX(1); //float dx = Math.Abs(x1 - x0); //float s = Math.Min(Math.Max(dx, 1.0f), 2.0f); Drawer drawer = new Drawer(graphics, settings.color); if (values.Count == 1) { float x = cs.ConvertX(0); float y = cs.ConvertY(values[0]); drawer.DrawLine(x, y - 0.5f, x, y + 0.5f); } else if (values.Count > 1) { double d = 0; float xp = cs.ConvertX(d); float yp = cs.ConvertY(values[0]); d += 1; for (int i = 1; i < values.Count; ++i) { float x = cs.ConvertX(d); float y = cs.ConvertY(values[i]); drawer.DrawLine(xp, yp, x, y); d += 1; xp = x; yp = y; } } }
void DrawPoints(Geometry.Box box, Graphics graphics, Settings settings, Geometry.Traits traits, double diffX) { // NOTE: traits == null bool fill = true; LocalCS cs = new LocalCS(box, graphics, fill); float dx = cs.ConvertDimensionX(diffX); float s = Math.Min(Math.Max(dx * 2.0f, 2.0f), 5.0f); bool drawPts = dx < 1; Drawer drawer = new Drawer(graphics, settings.color); for (int i = 0; i < points.Count; ++i) { float x = cs.ConvertX(points[i][0]); float y = cs.ConvertY(points[i][1]); drawer.DrawPoint(x, y, s); } }
public static bool DrawScales(Graphics graphics, Geometry.Box box, Colors colors, bool fill) { if (!box.IsValid()) { return(false); } LocalCS cs = new LocalCS(box, graphics, fill); // Aabb float min_x = cs.ConvertX(box.Min[0]); float min_y = cs.ConvertY(box.Min[1]); float max_x = cs.ConvertX(box.Max[0]); float max_y = cs.ConvertY(box.Max[1]); // pen for lines Pen penAabb = new Pen(colors.AabbColor, 1); float maxHeight = 20.0f; // font and brush for text Font font = new Font(new FontFamily(System.Drawing.Text.GenericFontFamilies.SansSerif), maxHeight / 2.0f); SolidBrush brushText = new SolidBrush(colors.TextColor); // Scales { float wWidth = graphics.VisibleClipBounds.Width; float wHeight = graphics.VisibleClipBounds.Height; // In CS coordinates double mi_x = cs.InverseConvertX(0); double mi_y = cs.InverseConvertY(wHeight); double ma_x = cs.InverseConvertX(wWidth); double ma_y = cs.InverseConvertY(0); double mima_x = ma_x - mi_x; double mima_y = ma_y - mi_y; // Esstimate numbers of strings for both axes double esst_x = Math.Abs(mima_x) < 10 ? mima_x / 10 : mima_x; float wStrNumX = wWidth / StringWidth(graphics, font, esst_x) / 1.25f; float wStrNumH = wHeight / StringWidth(graphics, font, 1.0) / 2.0f; // Find closest power of 10 lesser than the width and height double pd_x = AbsOuterPow10(mima_x / wStrNumX); double pd_y = AbsOuterPow10(mima_y / wStrNumH); // Find starting x and y values being the first lesser whole // values of the same magnitude, per axis double x = ScaleStart(mi_x, pd_x); double y = ScaleStart(mi_y, pd_y); // Make sure the scale starts outside the view if (x > mi_x) { x -= pd_x; } if (y > mi_y) { y -= pd_y; } // Create the string output pattern, e.g. 0.00 for previously calculated step string xStrFormat = StringFormat(pd_x); string yStrFormat = StringFormat(pd_y); float wd_x = cs.ConvertDimensionX(pd_x); int smallScaleX = SmallScaleSegments(wd_x, 10); float wd_x_step = wd_x / smallScaleX; float wd_x_limit = wd_x - wd_x_step / 2; float wd_y = cs.ConvertDimensionY(pd_y); int smallScaleY = SmallScaleSegments(wd_y, 10); float wd_y_step = wd_y / smallScaleY; float wd_y_limit = wd_y - wd_y_step / 2; // Draw horizontal scale double limit_x = ma_x + pd_x * 1.001; for (; x < limit_x; x += pd_x) { float wx = cs.ConvertX(x); // scale graphics.DrawLine(penAabb, wx, wHeight, wx, wHeight - 5); // value string xStr = Util.ToString(x, xStrFormat); SizeF xStrSize = graphics.MeasureString(xStr, font); float xStrLeft = wx - xStrSize.Width / 2; float xStrTop = wHeight - 5 - xStrSize.Height; graphics.DrawString(xStr, font, brushText, xStrLeft, xStrTop); // small scale for (float wsx = wx + wd_x_step; wsx < wx + wd_x_limit; wsx += wd_x_step) { graphics.DrawLine(penAabb, wsx, wHeight, wsx, wHeight - 3); } } // Draw vertical scale double limit_y = ma_y + pd_y * 1.001; for (; y < limit_y; y += pd_y) { float wy = cs.ConvertY(y); // scale graphics.DrawLine(penAabb, wWidth, wy, wWidth - 5, wy); // value string yStr = Util.ToString(y, yStrFormat); SizeF yStrSize = graphics.MeasureString(yStr, font); float yStrLeft = wWidth - 5 - yStrSize.Width; float yStrTop = wy - yStrSize.Height / 2; graphics.DrawString(yStr, font, brushText, yStrLeft, yStrTop); // small scale for (float wsy = wy - wd_y_step; wsy > wy - wd_y_limit; wsy -= wd_y_step) { graphics.DrawLine(penAabb, wWidth, wsy, wWidth - 3, wsy); } } } return(true); }
public static bool DrawAxes(Graphics graphics, Geometry.Box box, Geometry.Unit unit, Colors colors, bool fill) { if (!box.IsValid()) { return(false); } LocalCS cs = new LocalCS(box, graphics, fill); //Geometry.Box viewBox = cs.ViewBox(); // Axes float h = graphics.VisibleClipBounds.Height; float w = graphics.VisibleClipBounds.Width; Pen prime_pen = new Pen(colors.AxisColor, 1); if (unit == Geometry.Unit.None) { // Y axis //if (Geometry.IntersectsX(viewBox, 0.0)) { float x0 = cs.ConvertX(0.0); graphics.DrawLine(prime_pen, x0, 0, x0, h); } // X axis //if (Geometry.IntersectsY(viewBox, 0.0)) { float y0 = cs.ConvertY(0.0); graphics.DrawLine(prime_pen, 0, y0, w, y0); } } else { Pen anti_pen = new Pen(colors.AxisColor, 1); anti_pen.DashStyle = DashStyle.Custom; anti_pen.DashPattern = new float[] { 5, 5 }; double pi = Geometry.HalfAngle(unit); double anti_mer = Geometry.NearestAntimeridian(box.Min[0], -1, unit); double prime_mer = anti_mer + pi; double next_anti_mer = anti_mer + 2 * pi; double next_prime_mer = prime_mer + 2 * pi; float anti_mer_f = cs.ConvertX(anti_mer); float anti_mer_step = cs.ConvertX(next_anti_mer) - anti_mer_f; float prime_mer_f = cs.ConvertX(prime_mer); float prime_mer_step = cs.ConvertX(next_prime_mer) - prime_mer_f; // Antimeridians for (; anti_mer_f <= w; anti_mer_f += anti_mer_step) { if (anti_mer_f >= 0) { graphics.DrawLine(anti_pen, anti_mer_f, 0, anti_mer_f, h); } } // Prime meridians for (; prime_mer_f <= w; prime_mer_f += prime_mer_step) { if (prime_mer_f >= 0) { graphics.DrawLine(prime_pen, prime_mer_f, 0, prime_mer_f, h); } } // Equator float e = cs.ConvertY(0.0); if (0 <= e && e <= h) { graphics.DrawLine(prime_pen, 0, e, w, e); } // North pole float n = cs.ConvertY(pi / 2); if (0 <= n && n <= h) { graphics.DrawLine(anti_pen, 0, n, w, n); } // South pole float s = cs.ConvertY(-pi / 2); if (0 <= s && s <= h) { graphics.DrawLine(anti_pen, 0, s, w, s); } } return(true); }
public static bool DrawAxes(Graphics graphics, Geometry.Box box, Geometry.Unit unit, Colors colors, bool fill) { if (!box.IsValid()) { return(false); } LocalCS cs = new LocalCS(box, graphics, fill); // NOTE: the coordinates limit of MS GDI+ is 1073741951 so below // avoid passing such coordinates. But instead of checking this // value or similar one check whether or not an axis is range // of an image. // Axes float h = graphics.VisibleClipBounds.Height; float w = graphics.VisibleClipBounds.Width; Pen prime_pen = new Pen(colors.AxisColor, 1); if (unit == Geometry.Unit.None) { // Y axis float x0 = cs.ConvertX(0.0); if (0 <= x0 && x0 <= w) { graphics.DrawLine(prime_pen, x0, 0, x0, h); } // X axis float y0 = cs.ConvertY(0.0); if (0 <= y0 && y0 <= h) { graphics.DrawLine(prime_pen, 0, y0, w, y0); } } else { Pen anti_pen = new Pen(colors.AxisColor, 1); anti_pen.DashStyle = DashStyle.Custom; anti_pen.DashPattern = new float[] { 5, 5 }; double pi = Geometry.StraightAngle(unit); double anti_mer = Geometry.NearestAntimeridian(box.Min[0], -1, unit); double prime_mer = anti_mer + pi; double next_anti_mer = anti_mer + 2 * pi; double next_prime_mer = prime_mer + 2 * pi; float anti_mer_f = cs.ConvertX(anti_mer); float anti_mer_step = cs.ConvertX(next_anti_mer) - anti_mer_f; float prime_mer_f = cs.ConvertX(prime_mer); float prime_mer_step = cs.ConvertX(next_prime_mer) - prime_mer_f; // Antimeridians while (anti_mer_f <= w // NOTE: For bug coordinates anti_mer_step may be 0 which results in infinite loop && Util.Assign(ref anti_mer_f, anti_mer_f + anti_mer_step)) { if (anti_mer_f >= 0) { graphics.DrawLine(anti_pen, anti_mer_f, 0, anti_mer_f, h); } } // Prime meridians bool primeMeridiansDrawn = false; while (prime_mer_f <= w // NOTE: For bug coordinates anti_mer_step may be 0 which results in infinite loop && Util.Assign(ref prime_mer_f, prime_mer_f += prime_mer_step)) { if (prime_mer_f >= 0) { graphics.DrawLine(prime_pen, prime_mer_f, 0, prime_mer_f, h); primeMeridiansDrawn = true; } } // Prime meridian float p = cs.ConvertX(0.0); if (!primeMeridiansDrawn && 0 <= p && p <= w) { graphics.DrawLine(prime_pen, p, 0, p, h); } // Equator float e = cs.ConvertY(0.0); if (0 <= e && e <= h) { graphics.DrawLine(prime_pen, 0, e, w, e); } // North pole float n = cs.ConvertY(pi / 2); if (0 <= n && n <= h) { graphics.DrawLine(anti_pen, 0, n, w, n); } // South pole float s = cs.ConvertY(-pi / 2); if (0 <= s && s <= h) { graphics.DrawLine(anti_pen, 0, s, w, s); } } return(true); }
public static bool DrawAabb(Graphics graphics, Geometry.Box box, Geometry.Traits traits, Colors colors) { if (!box.IsValid()) { return(false); } LocalCS cs = new LocalCS(box, graphics); // Axes float h = graphics.VisibleClipBounds.Height; float w = graphics.VisibleClipBounds.Width; Pen prime_pen = new Pen(colors.AxisColor, 1); if (traits.Unit == Geometry.Unit.None) { // Y axis float x0 = cs.ConvertX(0.0); graphics.DrawLine(prime_pen, x0, 0, x0, h); // X axis float y0 = cs.ConvertY(0.0); graphics.DrawLine(prime_pen, 0, y0, w, y0); } else { Pen anti_pen = new Pen(colors.AxisColor, 1); anti_pen.DashStyle = DashStyle.Custom; anti_pen.DashPattern = new float[] { 5, 5 }; double pi = Geometry.HalfAngle(traits.Unit); double anti_mer = Geometry.NearestAntimeridian(box.Min[0], -1, traits.Unit); double prime_mer = anti_mer + pi; double next_anti_mer = anti_mer + 2 * pi; double next_prime_mer = prime_mer + 2 * pi; float anti_mer_f = cs.ConvertX(anti_mer); float anti_mer_step = cs.ConvertX(next_anti_mer) - anti_mer_f; float prime_mer_f = cs.ConvertX(prime_mer); float prime_mer_step = cs.ConvertX(next_prime_mer) - prime_mer_f; // Antimeridians for (; anti_mer_f <= w; anti_mer_f += anti_mer_step) { if (anti_mer_f >= 0) { graphics.DrawLine(anti_pen, anti_mer_f, 0, anti_mer_f, h); } } // Prime meridians for (; prime_mer_f <= w; prime_mer_f += prime_mer_step) { if (prime_mer_f >= 0) { graphics.DrawLine(prime_pen, prime_mer_f, 0, prime_mer_f, h); } } // Equator float e = cs.ConvertY(0.0); if (0 <= e && e <= h) { graphics.DrawLine(prime_pen, 0, e, w, e); } // North pole float n = cs.ConvertY(pi / 2); if (0 <= n && n <= h) { graphics.DrawLine(anti_pen, 0, n, w, n); } // South pole float s = cs.ConvertY(-pi / 2); if (0 <= s && s <= h) { graphics.DrawLine(anti_pen, 0, s, w, s); } } // Aabb float min_x = cs.ConvertX(box.Min[0]); float min_y = cs.ConvertY(box.Min[1]); float max_x = cs.ConvertX(box.Max[0]); float max_y = cs.ConvertY(box.Max[1]); Pen penAabb = new Pen(colors.AabbColor, 1); graphics.DrawLine(penAabb, min_x - 1, min_y, min_x + 5, min_y); graphics.DrawLine(penAabb, min_x, min_y - 5, min_x, min_y + 1); graphics.DrawLine(penAabb, max_x - 5, max_y, max_x + 1, max_y); graphics.DrawLine(penAabb, max_x, max_y - 1, max_x, max_y + 5); // Aabb's coordinates float maxHeight = 20.0f;// Math.Min(Math.Max(graphics.VisibleClipBounds.Height - min_y, 0.0f), 20.0f); if (maxHeight > 1) { string min_x_str = box.Min[0].ToString("0.00", System.Globalization.CultureInfo.InvariantCulture); string min_y_str = box.Min[1].ToString("0.00", System.Globalization.CultureInfo.InvariantCulture); string max_x_str = box.Max[0].ToString("0.00", System.Globalization.CultureInfo.InvariantCulture); string max_y_str = box.Max[1].ToString("0.00", System.Globalization.CultureInfo.InvariantCulture); Font font = new Font(new FontFamily(System.Drawing.Text.GenericFontFamilies.SansSerif), maxHeight / 2.0f); StringFormat drawFormat = new StringFormat(); drawFormat.Alignment = StringAlignment.Center; string minStr = "(" + min_x_str + " " + min_y_str + ")"; string maxStr = "(" + max_x_str + " " + max_y_str + ")"; SizeF minSize = graphics.MeasureString(minStr, font); SizeF maxSize = graphics.MeasureString(maxStr, font); RectangleF drawRectMin = new RectangleF(Math.Max(min_x - minSize.Width, 0.0f), Math.Min(min_y + 2, graphics.VisibleClipBounds.Height - maxSize.Height), minSize.Width, minSize.Height); RectangleF drawRectMax = new RectangleF(Math.Min(max_x, graphics.VisibleClipBounds.Width - maxSize.Width), Math.Max(max_y - maxHeight, 0.0f), maxSize.Width, maxSize.Height); SolidBrush brushText = new SolidBrush(colors.TextColor); graphics.DrawString(minStr, font, brushText, drawRectMin, drawFormat); graphics.DrawString(maxStr, font, brushText, drawRectMax, drawFormat); } return(true); }
public void Draw(Geometry.Box box, Graphics graphics, Settings settings, Geometry.Traits traits) { LocalCS cs = new LocalCS(box, graphics); Drawer drawer = new Drawer(graphics, settings.color); double width = Dim(0); double height = Dim(1); float rw = cs.ConvertDimensionX(Math.Abs(width)); float rh = cs.ConvertDimensionY(Math.Abs(height)); if (traits.Unit == Geometry.Unit.None) { float rx = cs.ConvertX(Math.Min(Min[0], Max[0])); float ry = cs.ConvertY(Math.Max(Min[1], Max[1])); if (rw == 0 && rh == 0) { drawer.DrawPoint(rx, ry); } else if (rw == 0 || rh == 0) { drawer.DrawLine(rx, ry, rx + rw, ry + rh); } else { drawer.DrawRectangle(rx, ry, rw, rh); bool isInvalid = width < 0 || height < 0; if (!isInvalid) { drawer.FillRectangle(rx, ry, rw, rh); } else { drawer.DrawLine(rx, ry, rx + rw, ry + rh); drawer.DrawLine(rx + rw, ry, rx, ry + rh); } } } else // Radian, Degree { if (rw == 0 && rh == 0) { drawer.DrawPeriodicPoint(cs, Min, box, traits.Unit, settings.showDots); } else if (rw == 0 || rh == 0) { Geometry.Segment seg = new Geometry.Segment(Min, Max); Drawer.PeriodicDrawableBox pd = new Drawer.PeriodicDrawableBox(cs, seg, traits.Unit); Geometry.Interval interval = RelativeEnvelopeLon(seg, false, traits.Unit); drawer.DrawPeriodic(cs, box, interval, traits.Unit, pd, false, false, settings.showDots); } else { Geometry.Ring ring = new Geometry.Ring(); ring.Add(new Geometry.Point(Min[0], Min[1])); ring.Add(new Geometry.Point(Max[0], Min[1])); ring.Add(new Geometry.Point(Max[0], Max[1])); ring.Add(new Geometry.Point(Min[0], Max[1])); Drawer.PeriodicDrawableBox pd = new Drawer.PeriodicDrawableBox(cs, ring, traits.Unit); Geometry.Interval interval = RelativeEnvelopeLon(ring, true, traits.Unit); drawer.DrawPeriodic(cs, box, interval, traits.Unit, pd, true, false, settings.showDots); } } }
public PeriodicDrawableRange(LocalCS cs, Geometry.IRandomAccessRange <Geometry.Point> points, bool closed, Geometry.Unit unit, bool densify) { this.closed = closed; this.containsPole = ContainsPole.No; if (points.Count < 2) { return; } // approx. length of densified segments /*double densLength = Math.Min(cs.InverseConvertDimensionX(20), * cs.InverseConvertDimensionY(20));*/ double densLength = Geometry.FromDegree(5, unit); int count = points.Count + (closed ? 1 : 0); xs_orig = new float[count]; points_rel = new PointF[count]; if (densify) { dens_points_rel = new PointF[points.Count][]; } xs_orig[0] = cs.ConvertX(points[0][0]); points_rel[0] = cs.Convert(points[0]); Geometry.Point p0 = points[0].Clone(); for (int i = 1; i < count; ++i) { Geometry.Point p1 = points[i % points.Count].Clone(); xs_orig[i] = cs.ConvertX(p1[0]); double distNorm = Geometry.NormalizedAngleSigned(p1[0] - p0[0], unit); // [-pi, pi] p1[0] = p0[0] + distNorm; points_rel[i] = cs.Convert(p1); if (dens_points_rel != null) { dens_points_rel[i - 1] = DensifyAndConvert(cs, p0, p1, densLength, unit); } p0 = p1; } if (closed && Math.Abs(points_rel[0].X - points_rel[points.Count].X) > 0.1) { // Check which pole double area = 0; p0 = points[0].Clone(); for (int i = 1; i < count; ++i) { Geometry.Point p1 = points[i % points.Count].Clone(); double distNorm = Geometry.NormalizedAngleSigned(p1[0] - p0[0], unit); // [-pi, pi] p1[0] = p0[0] + distNorm; area += Geometry.SphericalTrapezoidArea(p0, p1, unit); p0 = p1; } int areaSign = Math.Sign(area); int dirSign = Math.Sign(points_rel[points.Count].X - points_rel[0].X); this.containsPole = (areaSign * dirSign >= 0) ? ContainsPole.North : ContainsPole.South; } }