protected void ProduceResponse(HttpContext context, string title, RenderContext ctx, Size tileSize, AbstractMatrix transform, bool transparent = false) { ProduceResponse(context, this, title, ctx, tileSize, transform, transparent, (context.Items["RouteData"] as System.Web.Routing.RouteData).Values); }
public bool Equals(AbstractMatrix <T> x, AbstractMatrix <T> y) { if (ReferenceEquals(x, null)) { return(false); } if (ReferenceEquals(y, null)) { return(false); } if (ReferenceEquals(x, y)) { return(true); } if (x.Size != y.Size) { return(false); } for (int i = 1; i <= x.Size; i++) { for (int j = 1; j <= x.Size; j++) { if (!x[i, j].Equals(y[i, j])) { return(false); } } } return(true); }
public void Sum_SquarePlusSquareEqualsDiagonal_PositiveTest() { AbstractMatrix <int> matr = new SquareMatrix <int>(2, new int[] { 1, 2, 3, 4 }); AbstractMatrix <int> smatr = new SquareMatrix <int>(2, new int[] { 1, -2, -3, 4 }); AbstractMatrix <int> actualResult = matr.Sum <int>(smatr); Assert.IsTrue(actualResult.GetType().ToString() == "Logic.DiagonalMatrix`1[System.Int32]"); }
public void Sum_IntInputValues_PositiveTest() { AbstractMatrix <int> matr = new SquareMatrix <int>(2, new int[] { 1, 2, 3, 4 }); AbstractMatrix <int> smatr = new SymmetricMatrix <int>(2, new int[] { 1, 1 }); AbstractMatrix <int> actualResult = matr.Sum <int>(smatr); AbstractMatrix <int> expectedResult = new SquareMatrix <int>(2, new int[] { 2, 3, 4, 4 }); Assert.IsTrue((new MatrixComparer <int>()).Equals(actualResult, expectedResult)); }
public void SymByExpressionMatrix <T>(AbstractMatrix <T> abstractMatrix1, AbstractMatrix <T> abstractMatrix2, AbstractMatrix <T> result) { var matrix3 = abstractMatrix1.SymByExpression(abstractMatrix2); for (int i = 0; i < abstractMatrix1.Lenght; i++) { for (int j = 0; j < abstractMatrix1.Lenght; j++) { Assert.AreEqual(result[i, j], matrix3[i, j]); } } }
private static void ShowMatrix <T>(AbstractMatrix <T> a, string message) { Console.WriteLine(message); for (int i = 0; i < a.Size; i++) { for (int j = 0; j < a.Size; j++) { Console.Write(a[i, j] + "\t"); } Console.WriteLine(); } }
public static AbstractMatrix <T> SumMatrix <T>(this AbstractMatrix <T> matrix, AbstractMatrix <T> otherMatrix) { AbstractMatrix <T> newMatrix = new SquareMatrix <T>(matrix.Size); Func <T, T, T> addMethod = CreateAdd <T>(); for (int i = 0; i < matrix.Size; i++) { for (int j = 0; j < matrix.Size; j++) { newMatrix[i, j] = addMethod(matrix[i, j], otherMatrix[i, j]); } } return(newMatrix); }
static void Main(string[] args) { AbstractMatrix <int> matrix = new SquareMatrix <int>(3); ListenersChangeMatrix <int> listener = new ListenersChangeMatrix <int>(matrix); matrix[0, 0] = 1; matrix[0, 1] = 2; matrix[0, 2] = 3; matrix[1, 0] = 4; matrix[1, 1] = 5; matrix[1, 2] = 6; matrix[2, 0] = 7; matrix[2, 1] = 8; matrix[2, 2] = 9; AbstractMatrix <int> matrix2 = new TriangularMatrix <int>(3); ListenersChangeMatrix <int> listener2 = new ListenersChangeMatrix <int>(matrix2); matrix2[0, 0] = 1; matrix2[1, 0] = 2; matrix2[1, 1] = 3; matrix2[2, 0] = 4; matrix2[2, 1] = 5; matrix2[2, 2] = 6; AbstractMatrix <int> matrix4 = new DiagonalMatrix <int>(3); ListenersChangeMatrix <int> listener3 = new ListenersChangeMatrix <int>(matrix4); matrix4[0, 0] = 1; matrix4[1, 1] = 2; matrix4[2, 2] = 3; AbstractMatrix <int> matrix3 = matrix4.SumMatrix(matrix4); for (int i = 0; i < matrix3.Size; i++) { for (int j = 0; j < matrix3.Size; j++) { Console.Write(" " + matrix3[i, j] + " "); } Console.WriteLine(); } }
private static void RenderToGraphics(RenderContext ctx, int rot, float translateX, float translateY, AbstractGraphics graphics) { graphics.TranslateTransform(translateX, translateY); graphics.RotateTransform(rot * 90); if (ctx.DrawBorder && ctx.ClipPath != null) { using (graphics.Save()) { // Render border in world space AbstractMatrix m = ctx.ImageSpaceToWorldSpace; graphics.MultiplyTransform(m); AbstractPen pen = new AbstractPen(ctx.Styles.imageBorderColor, 0.2f); // SVG/PdfSharp can't ExcludeClip so we take advantage of the fact that we know // the path starts on the left edge and proceeds clockwise. We extend the // path with a counterclockwise border around it, then use that to exclude // the original path's region for rendering the border. RectangleF bounds = PathUtil.Bounds(ctx.ClipPath); bounds.Inflate(2 * (float)pen.Width, 2 * (float)pen.Width); List <byte> types = new List <byte>(ctx.ClipPath.Types); List <PointF> points = new List <PointF>(ctx.ClipPath.Points); PointF key = points[0]; points.Add(new PointF(bounds.Left, key.Y)); types.Add(1); points.Add(new PointF(bounds.Left, bounds.Bottom)); types.Add(1); points.Add(new PointF(bounds.Right, bounds.Bottom)); types.Add(1); points.Add(new PointF(bounds.Right, bounds.Top)); types.Add(1); points.Add(new PointF(bounds.Left, bounds.Top)); types.Add(1); points.Add(new PointF(bounds.Left, key.Y)); types.Add(1); points.Add(new PointF(key.X, key.Y)); types.Add(1); graphics.IntersectClip(new AbstractPath(points.ToArray(), types.ToArray())); graphics.DrawPath(pen, ctx.ClipPath); } } using (graphics.Save()) { ctx.Render(graphics); } }
public static AbstractMatrix <T> SumByDynamic <T>(this AbstractMatrix <T> matrix1, AbstractMatrix <T> matrix2) { if (matrix1.Lenght != matrix2.Lenght) { throw new ArgumentException("Matrixs must have same lenght"); } var resultMatrix = new T[matrix1.Lenght, matrix1.Lenght]; for (int i = 0; i < matrix1.Lenght; i++) { for (int j = 0; j < matrix1.Lenght; j++) { T result; try { result = (T)((dynamic)matrix1[i, j] + matrix2[i, j]); } catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex) { throw new NotSupportedException(nameof(T), ex); } resultMatrix[i, j] = result; } } int maxCount = matrix1.Count > matrix2.Count ? matrix1.Count : matrix2.Count; if (maxCount == matrix1.Lenght * matrix1.Lenght) { return(new SquareMatrix <T>(resultMatrix)); } else if (maxCount == matrix1.Lenght) { return(new DiagonalMatrix <T>(resultMatrix)); } else { return(new SymmetricMatrix <T>(resultMatrix)); } }
public static AbstractMatrix <T> SymByExpression <T>(this AbstractMatrix <T> matrix1, AbstractMatrix <T> matrix2) { if (matrix1.Lenght != matrix2.Lenght) { throw new ArgumentException("Matrixs must have same lenght"); } var resultMatrix = new T[matrix1.Lenght, matrix1.Lenght]; for (int i = 0; i < matrix1.Lenght; i++) { for (int j = 0; j < matrix1.Lenght; j++) { T result; try { result = Add <T>()(matrix1[i, j], matrix2[i, j]); } catch (InvalidOperationException ex) { throw new NotSupportedException("", ex);; } resultMatrix[i, j] = result; } } int maxCount = matrix1.Count > matrix2.Count ? matrix1.Count : matrix2.Count; if (maxCount == matrix1.Lenght * matrix1.Lenght) { return(new SquareMatrix <T>(resultMatrix)); } else if (maxCount == matrix1.Lenght) { return(new DiagonalMatrix <T>(resultMatrix)); } else { return(new SymmetricMatrix <T>(resultMatrix)); } }
public void AddTest() { SymmetricMatrix <int> firstMatrix = new SymmetricMatrix <int>(new int[, ] { { 1, 1, 1 }, { 1, 2, 1 }, { 1, 1, 3 } }); DiagonalMatrix <int> secondMatrix = new DiagonalMatrix <int>(new int[, ] { { 1, 0, 0 }, { 0, 2, 0 }, { 0, 0, 3 } }); SquareMatrix <int> expectedMatrix = new SquareMatrix <int>(new int[, ] { { 2, 1, 1 }, { 1, 4, 1 }, { 1, 1, 6 } }); AbstractMatrix <int> resultMatrix = firstMatrix.AddMatrix(secondMatrix); for (int i = 0; i < firstMatrix.Dimension; i++) { for (int j = 0; j < firstMatrix.Dimension; j++) { Assert.AreEqual(expectedMatrix[i, j], resultMatrix[i, j]); } } }
/// <summary> /// Add matrix /// </summary> /// <typeparam name="T">type parameter</typeparam> /// <param name="matrix">matrix first term</param> /// <param name="matrixForAdd">matrix second term</param> /// <returns>matrix which is the sum of two matrix</returns> public static AbstractMatrix <T> AddMatrix <T>(this AbstractMatrix <T> matrix, AbstractMatrix <T> matrixForAdd) { if (matrix == null || matrixForAdd == null) { throw new ArgumentNullException("Matrix must be not null"); } if (matrix.Dimension != matrixForAdd.Dimension) { throw new ArgumentException("The matrix dimension must match"); } SquareMatrix <T> result = new SquareMatrix <T>(matrix.Dimension); for (int i = 0; i < matrix.Dimension; i++) { for (int j = 0; j < matrix.Dimension; j++) { result[i, j] = (dynamic)matrix[i, j] + (dynamic)matrixForAdd[i, j]; } } return(result); }
public override void Process(ResourceManager resourceManager) { // // Jump // int jump = GetIntOption("jump", 6).Clamp(0, 20); // // Content & Coordinates // Selector selector; Location loc; if (Context.Request.HttpMethod == "POST") { Sector sector; bool lint = GetBoolOption("lint", defaultValue: false); Func <ErrorLogger.Record, bool> filter = null; if (lint) { bool hide_uwp = GetBoolOption("hide-uwp", defaultValue: false); bool hide_tl = GetBoolOption("hide-tl", defaultValue: false); filter = (ErrorLogger.Record record) => { if (hide_uwp && record.message.StartsWith("UWP")) { return(false); } if (hide_tl && record.message.StartsWith("UWP: TL")) { return(false); } return(true); }; } ErrorLogger errors = new ErrorLogger(filter); sector = GetPostedSector(Context.Request, errors) ?? throw new HttpError(400, "Bad Request", "Either file or data must be supplied in the POST data."); if (lint && !errors.Empty) { throw new HttpError(400, "Bad Request", errors.ToString()); } int hex = GetIntOption("hex", Astrometrics.SectorCentralHex); loc = new Location(new Point(0, 0), hex); selector = new HexSectorSelector(resourceManager, sector, loc.Hex, jump); } else { // NOTE: This (re)initializes a static data structure used for // resolving names into sector locations, so needs to be run // before any other objects (e.g. Worlds) are loaded. SectorMap.Milieu map = SectorMap.ForMilieu(resourceManager, GetStringOption("milieu")); if (HasOption("sector") && HasOption("hex")) { string sectorName = GetStringOption("sector"); int hex = GetIntOption("hex", 0); Sector sector = map.FromName(sectorName) ?? throw new HttpError(404, "Not Found", $"The specified sector '{sectorName}' was not found."); loc = new Location(sector.Location, hex); } else if (HasLocation()) { loc = GetLocation(); } else { loc = Location.Empty; } selector = new HexSelector(map, resourceManager, loc, jump); } // // Scale // double scale = GetDoubleOption("scale", 64).Clamp(MinScale, MaxScale); // // Options & Style // MapOptions options = MapOptions.BordersMajor | MapOptions.BordersMinor | MapOptions.ForceHexes; Style style = Style.Poster; ParseOptions(ref options, ref style); // // Border // bool border = GetBoolOption("border", defaultValue: true); // // Clip // bool clip = GetBoolOption("clip", defaultValue: true); // Hex Rotation int hrot = GetIntOption("hrotation", defaultValue: 0); // // What to render // RectangleF tileRect = new RectangleF(); Point coords = Astrometrics.LocationToCoordinates(loc); tileRect.X = coords.X - jump - 1; tileRect.Width = jump + 1 + jump; tileRect.Y = coords.Y - jump - 1; tileRect.Height = jump + 1 + jump; // Account for jagged hexes tileRect.Y += (coords.X % 2 == 0) ? 0 : 0.5f; tileRect.Inflate(0.35f, 0.15f); Size tileSize = new Size((int)Math.Floor(tileRect.Width * scale * Astrometrics.ParsecScaleX), (int)Math.Floor(tileRect.Height * scale * Astrometrics.ParsecScaleY)); // Construct clipping path List <Point> clipPath = new List <Point>(jump * 6 + 1); Point cur = coords; for (int i = 0; i < jump; ++i) { // Move J parsecs to the upper-left (start of border path logic) cur = Astrometrics.HexNeighbor(cur, 1); } clipPath.Add(cur); for (int dir = 0; dir < 6; ++dir) { for (int i = 0; i < jump; ++i) { cur = Astrometrics.HexNeighbor(cur, (dir + 3) % 6); // Clockwise from upper left clipPath.Add(cur); } } Stylesheet styles = new Stylesheet(scale, options, style); // If any names are showing, show them all if (styles.worldDetails.HasFlag(WorldDetails.KeyNames)) { styles.worldDetails |= WorldDetails.AllNames; } // Compute path RenderUtil.HexEdges(styles.hexStyle == HexStyle.Square ? PathUtil.PathType.Square : PathUtil.PathType.Hex, out float[] edgeX, out float[] edgeY); PathUtil.ComputeBorderPath(clipPath, edgeX, edgeY, out PointF[] boundingPathCoords, out byte[] boundingPathTypes); AbstractMatrix transform = AbstractMatrix.Identity; if (hrot != 0) { ApplyHexRotation(hrot, styles, ref tileSize, ref transform); } RenderContext ctx = new RenderContext(resourceManager, selector, tileRect, scale, options, styles, tileSize) { DrawBorder = border, ClipOutsectorBorders = true, // TODO: Widen path to allow for single-pixel border ClipPath = clip ? new AbstractPath(boundingPathCoords, boundingPathTypes) : null }; ProduceResponse(Context, "Jump Map", ctx, tileSize, transform, transparent: clip); }
public ListenersChangeMatrix(AbstractMatrix <T> matrix) { matrix.Change += ListenerMsg; }
protected static void ApplyHexRotation(int hrot, Stylesheet stylesheet, ref Size bitmapSize, ref AbstractMatrix transform) { float degrees = -hrot; double radians = degrees * Math.PI / 180f; double newWidth = Math.Abs(Math.Sin(radians)) * bitmapSize.Height + Math.Abs(Math.Cos(radians)) * bitmapSize.Width; double newHeight = Math.Abs(Math.Sin(radians)) * bitmapSize.Width + Math.Abs(Math.Cos(radians)) * bitmapSize.Height; transform.TranslatePrepend((float)newWidth / 2, (float)newHeight / 2); transform.RotatePrepend(-degrees); transform.TranslatePrepend(-bitmapSize.Width / 2, -bitmapSize.Height / 2); bitmapSize.Width = (int)Math.Ceiling(newWidth); bitmapSize.Height = (int)Math.Ceiling(newHeight); stylesheet.hexRotation = (float)degrees; stylesheet.microBorders.textStyle.Rotation = degrees; }
protected void ProduceResponse(HttpContext context, ITypeAccepter accepter, string title, RenderContext ctx, Size tileSize, AbstractMatrix transform, bool transparent = false, IDictionary <string, object> queryDefaults = null) { // New-style Options #region URL Parameters // TODO: move to ParseOptions (maybe - requires options to be parsed after stylesheet creation?) if (GetBoolOption("sscoords", queryDefaults: queryDefaults, defaultValue: false)) { ctx.Styles.hexCoordinateStyle = HexCoordinateStyle.Subsector; } if (GetBoolOption("allhexes", queryDefaults: queryDefaults, defaultValue: false)) { ctx.Styles.numberAllHexes = true; } if (GetBoolOption("nogrid", queryDefaults: queryDefaults, defaultValue: false)) { ctx.Styles.parsecGrid.visible = false; } if (!GetBoolOption("routes", queryDefaults: queryDefaults, defaultValue: true)) { ctx.Styles.macroRoutes.visible = false; ctx.Styles.microRoutes.visible = false; } if (!GetBoolOption("rifts", queryDefaults: queryDefaults, defaultValue: true)) { ctx.Styles.showRiftOverlay = false; } if (GetBoolOption("po", queryDefaults: queryDefaults, defaultValue: false)) { ctx.Styles.populationOverlay.visible = true; } if (GetBoolOption("im", queryDefaults: queryDefaults, defaultValue: false)) { ctx.Styles.importanceOverlay.visible = true; } if (GetBoolOption("cp", queryDefaults: queryDefaults, defaultValue: false)) { ctx.Styles.capitalOverlay.visible = true; } if (GetBoolOption("stellar", queryDefaults: queryDefaults, defaultValue: false)) { ctx.Styles.showStellarOverlay = true; } ctx.Styles.dimUnofficialSectors = GetBoolOption("dimunofficial", queryDefaults: queryDefaults, defaultValue: false); ctx.Styles.colorCodeSectorStatus = GetBoolOption("review", queryDefaults: queryDefaults, defaultValue: false); ctx.Styles.droyneWorlds.visible = GetBoolOption("dw", queryDefaults: queryDefaults, defaultValue: false); ctx.Styles.minorHomeWorlds.visible = GetBoolOption("mh", queryDefaults: queryDefaults, defaultValue: false); ctx.Styles.ancientsWorlds.visible = GetBoolOption("an", queryDefaults: queryDefaults, defaultValue: false); // TODO: Return an error if pattern is invalid? ctx.Styles.highlightWorldsPattern = HighlightWorldPattern.Parse( GetStringOption("hw", queryDefaults: queryDefaults, defaultValue: String.Empty).Replace(' ', '+')); ctx.Styles.highlightWorlds.visible = ctx.Styles.highlightWorldsPattern != null; double devicePixelRatio = GetDoubleOption("dpr", defaultValue: 1, queryDefaults: queryDefaults); devicePixelRatio = Math.Round(devicePixelRatio, 1); if (devicePixelRatio <= 0) { devicePixelRatio = 1; } if (devicePixelRatio > 2) { devicePixelRatio = 2; } bool dataURI = GetBoolOption("datauri", queryDefaults: queryDefaults, defaultValue: false); if (GetStringOption("milieu", SectorMap.DEFAULT_MILIEU) != SectorMap.DEFAULT_MILIEU) { // TODO: Make this declarative in resource files. if (ctx.Styles.macroBorders.visible) { ctx.Styles.macroBorders.visible = false; ctx.Styles.microBorders.visible = true; } ctx.Styles.macroNames.visible = false; ctx.Styles.macroRoutes.visible = false; } #endregion MemoryStream ms = null; if (dataURI) { ms = new MemoryStream(); } Stream outputStream = ms ?? Context.Response.OutputStream; if (accepter.Accepts(context, ContentTypes.Image.Svg, ignoreHeaderFallbacks: true)) { #region SVG Generation using (var svg = new SVGGraphics(tileSize.Width, tileSize.Height)) { RenderToGraphics(ctx, transform, svg); using (var stream = new MemoryStream()) { svg.Serialize(new StreamWriter(stream)); context.Response.ContentType = ContentTypes.Image.Svg; if (!dataURI) { context.Response.AddHeader("content-length", stream.Length.ToString()); context.Response.AddHeader("content-disposition", $"inline;filename=\"{Util.SanitizeFilename(title)}.svg\""); } stream.WriteTo(outputStream); } } #endregion } else if (accepter.Accepts(context, ContentTypes.Application.Pdf, ignoreHeaderFallbacks: true)) { #region PDF Generation using (var document = new PdfDocument()) { document.Version = 14; // 1.4 for opacity document.Info.Title = title; document.Info.Author = "Joshua Bell"; document.Info.Creator = "TravellerMap.com"; document.Info.Subject = DateTime.Now.ToString("F", CultureInfo.InvariantCulture); document.Info.Keywords = "The Traveller game in all forms is owned by Far Future Enterprises. Copyright (C) 1977 - 2019 Far Future Enterprises. Traveller is a registered trademark of Far Future Enterprises."; // TODO: Credits/Copyright // This is close, but doesn't define the namespace correctly: // document.Info.Elements.Add( new KeyValuePair<string, PdfItem>( "/photoshop/Copyright", new PdfString( "HelloWorld" ) ) ); PdfPage page = document.AddPage(); // NOTE: only PageUnit currently supported in MGraphics is Points page.Width = XUnit.FromPoint(tileSize.Width); page.Height = XUnit.FromPoint(tileSize.Height); using (var gfx = new PdfSharpGraphics(XGraphics.FromPdfPage(page))) { RenderToGraphics(ctx, transform, gfx); using (var stream = new MemoryStream()) { document.Save(stream, closeStream: false); context.Response.ContentType = ContentTypes.Application.Pdf; if (!dataURI) { context.Response.AddHeader("content-length", stream.Length.ToString()); context.Response.AddHeader("content-disposition", $"inline;filename=\"{Util.SanitizeFilename(title)}.pdf\""); } stream.WriteTo(outputStream); } } } #endregion } else { #region Bitmap Generation int width = (int)Math.Floor(tileSize.Width * devicePixelRatio); int height = (int)Math.Floor(tileSize.Height * devicePixelRatio); using (var bitmap = TryConstructBitmap(width, height, PixelFormat.Format32bppArgb)) { if (bitmap == null) { throw new HttpError(500, "Internal Server Error", $"Failed to allocate bitmap ({width}x{height}). Insufficient memory?"); } if (transparent) { bitmap.MakeTransparent(); } using (var g = System.Drawing.Graphics.FromImage(bitmap)) { g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; using (var graphics = new BitmapGraphics(g)) { graphics.ScaleTransform((float)devicePixelRatio); RenderToGraphics(ctx, transform, graphics); } } BitmapResponse(context.Response, outputStream, ctx.Styles, bitmap, transparent ? ContentTypes.Image.Png : null); } #endregion } if (dataURI) { string contentType = context.Response.ContentType; context.Response.ContentType = ContentTypes.Text.Plain; ms.Seek(0, SeekOrigin.Begin); context.Response.Output.Write("data:"); context.Response.Output.Write(contentType); context.Response.Output.Write(";base64,"); context.Response.Output.Flush(); System.Security.Cryptography.ICryptoTransform encoder = new System.Security.Cryptography.ToBase64Transform(); using (System.Security.Cryptography.CryptoStream cs = new System.Security.Cryptography.CryptoStream(context.Response.OutputStream, encoder, System.Security.Cryptography.CryptoStreamMode.Write)) { ms.WriteTo(cs); cs.FlushFinalBlock(); } } context.Response.Flush(); context.Response.Close(); return; }
public override void Process(ResourceManager resourceManager) { Selector selector; RectangleF tileRect; MapOptions options = MapOptions.SectorGrid | MapOptions.SubsectorGrid | MapOptions.BordersMajor | MapOptions.BordersMinor | MapOptions.NamesMajor | MapOptions.NamesMinor | MapOptions.WorldsCapitals | MapOptions.WorldsHomeworlds; Style style = Style.Poster; ParseOptions(ref options, ref style); string title; bool clipOutsectorBorders; if (HasOption("x1") && HasOption("x2") && HasOption("y1") && HasOption("y2")) { // Arbitrary rectangle int x1 = GetIntOption("x1", 0); int x2 = GetIntOption("x2", 0); int y1 = GetIntOption("y1", 0); int y2 = GetIntOption("y2", 0); tileRect = new RectangleF() { X = Math.Min(x1, x2), Y = Math.Min(y1, y2) }; tileRect.Width = Math.Max(x1, x2) - tileRect.X; tileRect.Height = Math.Max(y1, y2) - tileRect.Y; // NOTE: This (re)initializes a static data structure used for // resolving names into sector locations, so needs to be run // before any other objects (e.g. Worlds) are loaded. SectorMap.Milieu map = SectorMap.ForMilieu(resourceManager, GetStringOption("milieu")); selector = new RectSelector(map, resourceManager, tileRect, slop: false); // Include specified hexes tileRect.Offset(-1, -1); tileRect.Width += 1; tileRect.Height += 1; title = $"Poster ({x1},{y1}) - ({x2},{y2})"; clipOutsectorBorders = true; } else if (HasOption("domain")) { string domain = GetStringOption("domain"); double x, y, w = 2, h = 2; switch (domain.ToLowerInvariant()) { case "deneb": x = -4; y = -1; title = "Domain of Deneb"; break; case "vland": x = -2; y = -1; title = "Domain of Vland"; break; case "ilelish": x = -2; y = 1; title = "Domain of Ilelish"; break; case "antares": x = 0; y = -2; title = "Domain of Antares"; break; case "sylea": x = 0; y = 0; title = "Domain of Sylea"; break; case "sol": x = 0; y = 2; title = "Domain of Sol"; break; case "gateway": x = 2; y = 0; title = "Domain of Gateway"; break; // And these aren't domains, but... case "foreven": x = -6; y = -1; title = "Land Grant / Foreven"; break; case "imperium": x = -4; y = -1; w = 7; h = 5; title = "Third Imperium"; break; case "solomani": x = -1.5; y = 2.75; w = 4; h = 2.25; title = "Solomani Confederacy"; break; case "zhodani": x = -8; y = -3; w = 5; h = 3; title = "Zhodani Consulate"; break; case "hive": case "hiver": x = 2; y = 1; w = 6; h = 4; title = "Hiver Federation"; break; case "aslan": x = -8; y = 1; w = 7; h = 4; title = "Aslan Hierate"; break; case "vargr": x = -4; y = -4; w = 8; h = 3; title = "Vargr Extents"; break; case "kkree": x = 4; y = -2; w = 4; h = 4; title = "Two Thousand Worlds"; break; case "jp": x = 0; y = -3; w = 4; h = 3; title = "Julian Protectorate"; break; // TODO: Zhodani provinces case "chartedspace": x = -8; y = -3; w = 16; h = 8; title = "Charted Space"; break; case "jg": x = 160; y = 0; w = 2; h = 2; title = "Judges Guild"; break; default: throw new HttpError(404, "Not Found", $"Unknown domain: {domain}"); } int x1 = (int)Math.Round(x * Astrometrics.SectorWidth - Astrometrics.ReferenceHex.X + 1); int y1 = (int)Math.Round(y * Astrometrics.SectorHeight - Astrometrics.ReferenceHex.Y + 1); int x2 = (int)Math.Round(x1 + w * Astrometrics.SectorWidth - 1); int y2 = (int)Math.Round(y1 + h * Astrometrics.SectorHeight - 1); tileRect = new RectangleF() { X = Math.Min(x1, x2), Y = Math.Min(y1, y2) }; tileRect.Width = Math.Max(x1, x2) - tileRect.X; tileRect.Height = Math.Max(y1, y2) - tileRect.Y; // NOTE: This (re)initializes a static data structure used for // resolving names into sector locations, so needs to be run // before any other objects (e.g. Worlds) are loaded. SectorMap.Milieu map = SectorMap.ForMilieu(resourceManager, GetStringOption("milieu")); selector = new RectSelector(map, resourceManager, tileRect, slop: false); // Include selected hexes tileRect.Offset(-1, -1); tileRect.Width += 1; tileRect.Height += 1; // Account for jagged hexes tileRect.Height += 0.5f; tileRect.Inflate(0.25f, 0.10f); if (style == Style.Candy) { tileRect.Width += 0.75f; } clipOutsectorBorders = true; } else { // Sector - either POSTed or specified by name Sector sector = null; options &= ~MapOptions.SectorGrid; if (Context.Request.HttpMethod == "POST") { bool lint = GetBoolOption("lint", defaultValue: false); Func <ErrorLogger.Record, bool> filter = null; if (lint) { bool hide_uwp = GetBoolOption("hide-uwp", defaultValue: false); bool hide_tl = GetBoolOption("hide-tl", defaultValue: false); filter = (ErrorLogger.Record record) => { if (hide_uwp && record.message.StartsWith("UWP")) { return(false); } if (hide_tl && record.message.StartsWith("UWP: TL")) { return(false); } return(true); }; } ErrorLogger errors = new ErrorLogger(filter); sector = GetPostedSector(Context.Request, errors) ?? throw new HttpError(400, "Bad Request", "Either file or data must be supplied in the POST data."); if (lint && !errors.Empty) { throw new HttpError(400, "Bad Request", errors.ToString()); } title = "User Data"; // TODO: Suppress all OTU rendering. options &= ~(MapOptions.WorldsHomeworlds | MapOptions.WorldsCapitals); } else { string sectorName = GetStringOption("sector") ?? throw new HttpError(400, "Bad Request", "No sector specified."); SectorMap.Milieu map = SectorMap.ForMilieu(resourceManager, GetStringOption("milieu")); sector = map.FromName(sectorName) ?? throw new HttpError(404, "Not Found", $"The specified sector '{sectorName}' was not found."); title = sector.Names[0].Text; } if (sector != null && HasOption("subsector") && GetStringOption("subsector").Length > 0) { string subsector = GetStringOption("subsector"); int index = sector.SubsectorIndexFor(subsector); if (index == -1) { throw new HttpError(404, "Not Found", $"The specified subsector '{subsector}' was not found."); } selector = new SubsectorSelector(resourceManager, sector, index); tileRect = sector.SubsectorBounds(index); options &= ~(MapOptions.SectorGrid | MapOptions.SubsectorGrid); title = $"{title} - Subsector {'A' + index}"; } else if (sector != null && HasOption("quadrant") && GetStringOption("quadrant").Length > 0) { string quadrant = GetStringOption("quadrant"); int index; switch (quadrant.ToLowerInvariant()) { case "alpha": index = 0; quadrant = "Alpha"; break; case "beta": index = 1; quadrant = "Beta"; break; case "gamma": index = 2; quadrant = "Gamma"; break; case "delta": index = 3; quadrant = "Delta"; break; default: throw new HttpError(400, "Bad Request", $"The specified quadrant '{quadrant}' is invalid."); } selector = new QuadrantSelector(resourceManager, sector, index); tileRect = sector.QuadrantBounds(index); options &= ~(MapOptions.SectorGrid | MapOptions.SubsectorGrid | MapOptions.SectorsMask); title = $"{title} - {quadrant} Quadrant"; } else { selector = new SectorSelector(resourceManager, sector); tileRect = sector.Bounds; options &= ~(MapOptions.SectorGrid); } // Account for jagged hexes tileRect.Height += 0.5f; tileRect.Inflate(0.25f, 0.10f); if (style == Style.Candy) { tileRect.Width += 0.75f; } clipOutsectorBorders = false; } const double NormalScale = 64; // pixels/parsec - standard subsector-rendering scale double scale = GetDoubleOption("scale", NormalScale).Clamp(MinScale, MaxScale); int rot = GetIntOption("rotation", 0) % 4; int hrot = GetIntOption("hrotation", 0); bool thumb = GetBoolOption("thumb", false); Stylesheet stylesheet = new Stylesheet(scale, options, style); Size tileSize = new Size((int)Math.Floor(tileRect.Width * scale * Astrometrics.ParsecScaleX), (int)Math.Floor(tileRect.Height * scale * Astrometrics.ParsecScaleY)); if (thumb) { tileSize.Width = (int)Math.Floor(16 * tileSize.Width / scale); tileSize.Height = (int)Math.Floor(16 * tileSize.Height / scale); scale = 16; } int bitmapWidth = tileSize.Width, bitmapHeight = tileSize.Height; AbstractMatrix transform = AbstractMatrix.Identity; switch (rot) { case 1: // 90 degrees clockwise transform.RotatePrepend(90); transform.TranslatePrepend(0, -bitmapHeight); Util.Swap(ref bitmapWidth, ref bitmapHeight); break; case 2: // 180 degrees transform.RotatePrepend(180); transform.TranslatePrepend(-bitmapWidth, -bitmapHeight); break; case 3: // 270 degrees clockwise transform.RotatePrepend(270); transform.TranslatePrepend(-bitmapWidth, 0); Util.Swap(ref bitmapWidth, ref bitmapHeight); break; } // TODO: Figure out how to compose rot and hrot properly. Size bitmapSize = new Size(bitmapWidth, bitmapHeight); if (hrot != 0) { ApplyHexRotation(hrot, stylesheet, ref bitmapSize, ref transform); } if (GetBoolOption("clampar", defaultValue: false)) { // Landscape: 1.91:1 (1.91) // Portrait: 4:5 (0.8) const double MIN_ASPECT_RATIO = 0.8; const double MAX_ASPECT_RATIO = 1.91; double aspectRatio = (double)bitmapSize.Width / (double)bitmapSize.Height; Size newSize = bitmapSize; if (aspectRatio < MIN_ASPECT_RATIO) { newSize.Width = (int)Math.Floor(bitmapSize.Height * MIN_ASPECT_RATIO); } else if (aspectRatio > MAX_ASPECT_RATIO) { newSize.Height = (int)Math.Floor(bitmapSize.Width / MAX_ASPECT_RATIO); } if (newSize != bitmapSize) { transform.TranslatePrepend( (newSize.Width - bitmapSize.Width) / 2f, (newSize.Height - bitmapSize.Height) / 2f); bitmapSize = newSize; } } RenderContext ctx = new RenderContext(resourceManager, selector, tileRect, scale, options, stylesheet, tileSize) { ClipOutsectorBorders = clipOutsectorBorders }; ProduceResponse(Context, title, ctx, bitmapSize, transform); }
public void Unregister(AbstractMatrix <T> matrix) { matrix.Change -= ListenerMsg; }
private static void SumMatrix <T, U>(AbstractMatrix <T> a, AbstractMatrix <U> b, string message) { ShowMatrix(a.Sum(b), message); }
public void Unregister <T>(AbstractMatrix <T> matrix) where T : struct { matrix.PropertyChanged -= Message; }
public int GetHashCode(AbstractMatrix <T> obj) { throw new NotImplementedException(); }