public static GraphManager <PointI> CreatePolygonGridManager( GraphDialog dialog, RegularPolygon polygon) { int width = 20, height = 20; PolygonGrid grid = new PolygonGrid(polygon); grid.Size = new SizeI(width, height); // shrink grid until it fits in output box double outputWidth = dialog.OutputBox.Width - 16; double outputHeight = dialog.OutputBox.Height - 16; while (grid.DisplayBounds.Width > outputWidth) { grid.Size = new SizeI(--width, height); } while (grid.DisplayBounds.Height > outputHeight) { grid.Size = new SizeI(width, --height); } var manager = new GraphManager <PointI>(dialog, 4); manager.Graph = grid; manager.Renderer = new GraphRenderer <PointI>(manager); return(manager); }
private void OnGridChanged(object sender, EventArgs args) { RoutedEventArgs routedArgs = args as RoutedEventArgs; if (routedArgs != null) { routedArgs.Handled = true; } if (_ignoreControls) { return; } Grid = new PolygonGrid(Element, GridShift); // determine number of columns and rows int width = (int)ColumnsUpDown.Value; int height = (int)RowsUpDown.Value; Grid.Size = new SizeI(width, height); // show resulting output size RectD bounds = Grid.DisplayBounds; WidthBox.Text = bounds.Width.ToString("N0"); HeightBox.Text = bounds.Height.ToString("N0"); }
/// <summary> /// Draws the specified <see cref="PolygonGrid"/> to the specified <see /// cref="StreamGeometry"/>, with optimization to remove duplicate lines.</summary> /// <param name="grid"> /// The <see cref="PolygonGrid"/> to draw.</param> /// <param name="context"> /// The <see cref="StreamGeometryContext"/> that receives <paramref name="grid"/>.</param> /// <param name="offset"> /// The offset by which to shift <paramref name="grid"/>.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="grid"/> or <paramref name="context"/> is a null reference.</exception> /// <remarks><para> /// <b>DrawOptimized</b> shifts the <see cref="RegularPolygon.Vertices"/> of each <see /// cref="PolygonGrid.Element"/> in the specified <paramref name="grid"/> by the /// corresponding <see cref="PolygonGrid.GridToDisplay"/> result plus the specified /// <paramref name="offset"/>. /// </para><para> /// <b>DrawOptimized</b> skips any <see cref="RegularPolygon"/> edges that coincide with an /// edge drawn for a previous <see cref="PolygonGrid.Element"/>. This optimization results /// in a total number of lines drawn to the specified <paramref name="context"/> that is /// about half that of the unoptimized <see cref="Draw"/> method. /// </para><para> /// There are two disadvantages. First, <b>DrawOptimized</b> requires more time and memory /// than <see cref="Draw"/> due to the additional vertex comparisons. Second, most polygons /// are not represented by closed figures within the specified <paramref name="context"/>, /// and so the area covered by the specified <paramref name="grid"/> is never considered /// filled for hit-testing, rendering, and clipping.</para></remarks> public static void DrawOptimized(this PolygonGrid grid, StreamGeometryContext context, PointD offset) { HashSet <LineI> lines = new HashSet <LineI>(); double epsilon = grid.Element.Length / 4.0; PointD[] vertices = grid.Element.Vertices; int width = grid.Size.Width, height = grid.Size.Height; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { PointD element = grid.GridToDisplay(x, y) + offset; // get & remember first element vertex PointD start = vertices[0] + element; PointD elementStart = start; bool lineSkipped = true; for (int i = 1; i <= vertices.Length; i++) { // close figure by returning to first vertex PointD next = (i == vertices.Length ? elementStart : vertices[i] + element); // reduce line to unique hash coordinates LineI line = new LineI( (int)(start.X / epsilon), (int)(start.Y / epsilon), (int)(next.X / epsilon), (int)(next.Y / epsilon)); // skip lines that were drawn (in either direction) if (lines.Contains(line) || lines.Contains(new LineI(line.End, line.Start))) { lineSkipped = true; } else { // restart figure after skipping lines if (lineSkipped) { context.BeginFigure(start.ToWpfPoint(), false, false); lineSkipped = false; } // draw & remember current line context.LineTo(next.ToWpfPoint(), true, true); lines.Add(line); } // prepare for next vertex start = next; } } } }
public bool Equals(FilterResult other) { if (ReferenceEquals(null, other)) { return(false); } if (ReferenceEquals(this, other)) { return(true); } return(Id.Equals(other.Id) && Uid.Equals(other.Uid) && string.Equals(Name, other.Name) && string.Equals(Description, other.Description) && StartUtc.Equals(other.StartUtc) && EndUtc.Equals(other.EndUtc) && OnMachineDesignId == other.OnMachineDesignId && OnMachineDesignName == other.OnMachineDesignName && AssetIDs.ScrambledEquals(other.AssetIDs) && VibeStateOn == other.VibeStateOn && CompactorDataOnly.Equals(other.CompactorDataOnly) && ElevationType == other.ElevationType && PolygonLL.ScrambledEquals(other.PolygonLL) && PolygonGrid.ScrambledEquals(other.PolygonGrid) && ForwardDirection == other.ForwardDirection && (AlignmentFile == null ? other.AlignmentFile == null : AlignmentFile.Equals(other.AlignmentFile)) && StartStation.Equals(other.StartStation) && EndStation.Equals(other.EndStation) && LeftOffset.Equals(other.LeftOffset) && RightOffset.Equals(other.RightOffset) && LayerType.Equals(other.LayerType) && (LayerDesignOrAlignmentFile == null ? other.LayerDesignOrAlignmentFile == null : LayerDesignOrAlignmentFile.Equals(other.LayerDesignOrAlignmentFile)) && BenchElevation.Equals(other.BenchElevation) && LayerNumber == other.LayerNumber && LayerThickness.Equals(other.LayerThickness) && ContributingMachines.ScrambledEquals(other.ContributingMachines) && SurveyedSurfaceExclusionList.ScrambledEquals(other.SurveyedSurfaceExclusionList) && ExcludedSurveyedSurfaceUids.ScrambledEquals(other.ExcludedSurveyedSurfaceUids) && ReturnEarliest.Equals(other.ReturnEarliest) && GpsAccuracy.Equals(other.GpsAccuracy) && GpsAccuracyIsInclusive.Equals(other.GpsAccuracyIsInclusive) && BladeOnGround.Equals(other.BladeOnGround) && TrackMapping.Equals(other.TrackMapping) && WheelTracking.Equals(other.WheelTracking) && (DesignFile == null ? other.DesignFile == null : DesignFile.Equals(other.DesignFile)) && AutomaticsType == other.AutomaticsType && TemperatureRangeMin.Equals(other.TemperatureRangeMin) && TemperatureRangeMax.Equals(other.TemperatureRangeMax) && PassCountRangeMin.Equals(other.PassCountRangeMin) && PassCountRangeMax.Equals(other.PassCountRangeMax)); }
/// <summary> /// Sets the <see cref="MapGrid"/> property.</summary> /// <param name="grid"> /// The new value for the <see cref="MapGrid"/> property.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="grid"/> is a null reference.</exception> /// <remarks><para> /// <b>SetMapGrid</b> assigns a copy of the specified <paramref name="grid"/> to the <see /// cref="MapGrid"/> property, so that both objects can be changed independently. /// </para><para> /// <b>SetMapGrid</b> also recreates the <see cref="TileCopyBuffer"/> and <see /// cref="TileDrawBuffer"/> bitmaps with the resulting <see cref="TileWidth"/> and <see /// cref="TileHeight"/>. Any existing bitmap contents are lost.</para></remarks> protected void SetMapGrid(PolygonGrid grid) { if (grid == null) { ThrowHelper.ThrowArgumentNullException("grid"); } this._mapGrid = new PolygonGrid(grid); // create tile buffers for one grid element TileCopyBuffer = CreateTileCopyBuffer(0, 0); TileDrawBuffer = CreateTileDrawBuffer(0, 0); }
/// <summary> /// Handles the <see cref="ToggleButton.Checked"/> event for the "Grid Shift" <see /// cref="RadioButton"/> controls on the <see cref="StructureTab"/> page.</summary> /// <param name="sender"> /// The <see cref="Object"/> where the event handler is attached.</param> /// <param name="args"> /// A <see cref="RoutedEventArgs"/> object containing event data.</param> /// <remarks> /// <b>OnShiftChecked</b> changes the <see cref="PolygonGrid.GridShift"/> value of the <see /// cref="MapGrid"/> to that indicated by the checked "Grid Shift" radio button, and sets /// the <see cref="DataChanged"/> flag if the value has changed.</remarks> private void OnShiftChecked(object sender, RoutedEventArgs args) { args.Handled = true; if (this._ignoreEvents) { return; } // get new grid shifting PolygonGridShift gridShift; if (ShiftNoneToggle.IsChecked == true) { gridShift = PolygonGridShift.None; } else if (ColumnUpToggle.IsChecked == true) { gridShift = PolygonGridShift.ColumnUp; } else if (ColumnDownToggle.IsChecked == true) { gridShift = PolygonGridShift.ColumnDown; } else if (RowLeftToggle.IsChecked == true) { gridShift = PolygonGridShift.RowLeft; } else if (RowRightToggle.IsChecked == true) { gridShift = PolygonGridShift.RowRight; } else { return; } // sanity check for element shape if (!PolygonGrid.AreCompatible(MapGrid.Element, gridShift)) { return; } // assign new grid shifting if (gridShift != MapGrid.GridShift) { this._mapGrid.GridShift = gridShift; // broadcast data changes DataChanged = true; } }
/// <summary> /// Draws the specified <see cref="PolygonGrid"/> to the specified <see /// cref="StreamGeometry"/>.</summary> /// <param name="grid"> /// The <see cref="PolygonGrid"/> to draw.</param> /// <param name="context"> /// The <see cref="StreamGeometryContext"/> that receives <paramref name="grid"/>.</param> /// <param name="isFilled"> /// <c>true</c> to use the area covered by <paramref name="grid"/> for hit-testing, /// rendering, and clipping; otherwise, <c>false</c>.</param> /// <param name="offset"> /// The offset by which to shift <paramref name="grid"/>.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="grid"/> is a null reference.</exception> /// <remarks><para> /// <b>Draw</b> invokes the <see cref="RegularPolygon"/> overload of <see cref="Draw"/> for /// each <see cref="PolygonGrid.Element"/> in the specified <paramref name="grid"/>, shifted /// by the corresponding <see cref="PolygonGrid.GridToDisplay"/> result. Each polygonal <see /// cref="PolygonGrid.Element"/> is therefore represented by one figure. /// </para><para> /// All coordinates are also shifted by the specified <paramref name="offset"/>. /// </para></remarks> public static void Draw(this PolygonGrid grid, StreamGeometryContext context, PointD offset, bool isFilled) { int width = grid.Size.Width, height = grid.Size.Height; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { PointD element = grid.GridToDisplay(x, y); grid.Element.Draw(context, element + offset, isFilled); } } }
/// <summary> /// Converts the specified <see cref="PolygonGrid"/> to a <see /// cref="PathFigureCollection"/>.</summary> /// <param name="grid"> /// The <see cref="PolygonGrid"/> to convert.</param> /// <returns> /// A frozen <see cref="PathFigureCollection"/> containing one <see cref="PathFigure"/> for /// each polygonal <see cref="PolygonGrid.Element"/> in the specified <paramref /// name="grid"/>.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="grid"/> is a null reference.</exception> /// <remarks> /// <b>ToFigures</b> returns the results of <see cref="ToFigure"/> for each <see /// cref="PolygonGrid.Element"/> in the specified <paramref name="grid"/>, shifted by the /// corresponding <see cref="PolygonGrid.GridToDisplay"/> result. Each polygonal <see /// cref="PolygonGrid.Element"/> is therefore represented by one <see cref="PathFigure"/>. /// </remarks> public static PathFigureCollection ToFigures(this PolygonGrid grid) { int width = grid.Size.Width, height = grid.Size.Height; var figures = new PathFigureCollection(width * height); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { PointD offset = grid.GridToDisplay(x, y); PathFigure figure = grid.Element.ToFigure(offset); figures.Add(figure); } } figures.Freeze(); return(figures); }
internal void UpdateGrid(Size layoutSize) { Grid = new PolygonGrid(StandardPolygon, GridShift); Grid.Size = _gridSize; // check for available space when using standard size double ratioX = layoutSize.Width / Grid.DisplayBounds.Width; double ratioY = layoutSize.Height / Grid.DisplayBounds.Height; // increase grid size accordingly if possible Grid.Size = new SizeI( (int)(_gridSize.Width * ratioX) - 1, (int)(_gridSize.Height * ratioY) - 1); // show resulting actual grid size ColumnsBox.Text = Grid.Size.Width.ToString(); RowsBox.Text = Grid.Size.Height.ToString(); }
public bool SetVertexNeighbors(bool value) { PolygonGrid grid = _graph as PolygonGrid; if (grid == null) { return(false); } RegularPolygon element = grid.Element; if (element.Sides != 4 || element.VertexNeighbors == value) { return(false); } grid.Element = new RegularPolygon(element.Length, 4, element.Orientation, value); return(true); }
private void DrawDecoration(DrawingContext dc) { if (_showElement == PolygonGrid.InvalidLocation) { return; } // always draw current element DrawElement(dc, _showElement, Brushes.Red, -1); PolygonGrid grid = PolygonGridTest.Instance.Grid; // show grid distances if desired if (_showDistances) { for (int x = 0; x < grid.Size.Width; x++) { for (int y = 0; y < grid.Size.Height; y++) { PointI target = new PointI(x, y); if (target != _showElement) { int distance = grid.GetStepDistance(_showElement, target); // use different brushes to highlight distances int index = (distance - 1) % _neighborBrushes.Length; DrawElement(dc, target, _neighborBrushes[index], distance); } } } } // highlight neighbors if desired if (_showNeighbors > 0) { IList <PointI> neighbors = grid.GetNeighbors(_showElement, _showNeighbors); foreach (PointI neighbor in neighbors) { DrawElement(dc, neighbor, Brushes.Yellow, -1); } } }
protected override void OnRender(DrawingContext dc) { base.OnRender(dc); // reserve border around centered polygon grid PolygonGrid grid = _manager.Graph as PolygonGrid; if (grid != null) { Canvas output = _manager.Dialog.OutputBox; double borderWidth = (output.Width - grid.DisplayBounds.Width) / 2; double borderHeight = (output.Height - grid.DisplayBounds.Height) / 2; dc.PushTransform(new TranslateTransform(borderWidth, borderHeight)); } DrawNodes(dc); // draw clipped Delaunay edges to indicate connections Subdivision division = _manager.Graph as Subdivision; if (division != null) { foreach (SubdivisionEdge edge in division.Edges.Values) { if (edge.Key > edge.Twin.Key) { continue; } PointD p = edge.Origin.Move(edge.Destination, 10); PointD q = edge.Destination.Move(edge.Origin, 10); dc.DrawLine(_edgePen, p.ToWpfPoint(), q.ToWpfPoint()); } } if (grid != null) { dc.Pop(); } }
public void PolygonGrid() { var polygon = new RegularPolygon(5, 4, PolygonOrientation.OnEdge); var grid = new PolygonGrid(polygon) { Size = new SizeI(10, 10) }; Subdivision division = grid.ToSubdivision(PointD.Empty).Source; CheckSearch(division); grid.Element = new RegularPolygon(5, 4, PolygonOrientation.OnVertex); division = grid.ToSubdivision(PointD.Empty).Source; CheckSearch(division); grid.Element = new RegularPolygon(5, 6, PolygonOrientation.OnEdge); division = grid.ToSubdivision(PointD.Empty).Source; CheckSearch(division); grid.Element = new RegularPolygon(5, 6, PolygonOrientation.OnVertex); division = grid.ToSubdivision(PointD.Empty).Source; CheckSearch(division); }
public void PolygonGrid() { var grid = new PolygonGrid(new RegularPolygon(10, 4, PolygonOrientation.OnEdge)); grid.Size = new SizeI(6, 4); var division = grid.ToSubdivision(PointD.Empty); CheckGridDivision(division); grid = new PolygonGrid(new RegularPolygon(10, 4, PolygonOrientation.OnVertex)); grid.Size = new SizeI(4, 6); division = grid.ToSubdivision(PointD.Empty); CheckGridDivision(division); grid = new PolygonGrid(new RegularPolygon(10, 6, PolygonOrientation.OnEdge)); grid.Size = new SizeI(6, 4); division = grid.ToSubdivision(PointD.Empty); CheckGridDivision(division); grid = new PolygonGrid(new RegularPolygon(10, 6, PolygonOrientation.OnVertex)); grid.Size = new SizeI(4, 6); division = grid.ToSubdivision(PointD.Empty); CheckGridDivision(division); }
public void SetUp() { grid = new PolygonGrid(element); readOnly = grid.AsReadOnly(); }
private void SubdivisionSearchTest(bool random) { Stopwatch timer = new Stopwatch(); var testCases = _subdivSearchTestCases; Output(String.Format("{0,6}", " ")); foreach (TestCase test in testCases) { Output(String.Format("{0,12}", test.Name)); } Output("\n"); const int outerLoop = 100, innerLoop = 200; const int iterations = outerLoop * innerLoop; PointD[] query = new PointD[innerLoop]; PolygonGrid grid = null; int sizeMin, sizeMax, sizeStep; if (random) { sizeMin = 100; sizeMax = 1200; sizeStep = 100; } else { sizeMin = 6; sizeMax = 30; sizeStep = 2; RegularPolygon polygon = new RegularPolygon(10, 4, PolygonOrientation.OnEdge); grid = new PolygonGrid(polygon); } for (int size = sizeMin; size <= sizeMax; size += sizeStep) { Subdivision division; if (random) { // create subdivision from random lines (few faces) division = CreateSubdivision(size, 1e-10); } else { // create subdivision from grid of diamonds (many faces) grid.Element = new RegularPolygon(900 / size, 4, PolygonOrientation.OnEdge); grid.Size = new SizeI(size, size); division = grid.ToSubdivision(PointD.Empty).Source; } var ordered = new SubdivisionSearch(division, true); var randomized = new SubdivisionSearch(division, false); // test cases: BruteForce, Ordered, Randomized testCases[0].FindSubdivision = (q) => division.Find(q, division.Epsilon); testCases[1].FindSubdivision = (q) => ordered.Find(q); testCases[2].FindSubdivision = (q) => randomized.Find(q); // trigger JIT compilation and reset ticks foreach (TestCase test in testCases) { test.FindSubdivision(PointD.Empty); test.Ticks = 0; } for (int j = 0; j < outerLoop; j++) { for (int k = 0; k < query.Length; k++) { query[k] = GeoAlgorithms.RandomPoint(0, 0, 1000, 1000); } foreach (TestCase test in testCases) { timer.Restart(); for (int k = 0; k < query.Length; k++) { test.FindSubdivision(query[k]); } timer.Stop(); test.Ticks += timer.ElapsedTicks; } } Output(String.Format("{0,6:N0}", division.Edges.Count / 2)); foreach (TestCase test in testCases) { Output(String.Format("{0,12:N2}", AverageMicrosecs(test.Ticks, iterations))); } Output("\n"); } Output("\nTimes are µsec averages for subdivisions of the indicated edge count,\n"); if (random) { Output("based on random line sets (few faces, completely random edges).\n"); } else { Output("based on grids of squares (many faces, strictly ordered edges).\n"); } }
/// <summary> /// Draws all arrows in the specified collection.</summary> /// <param name="arrows"> /// A <see cref="List{LineI}"/> containing the arrows to draw.</param> /// <param name="brush"> /// The <see cref="Brush"/> with which to draw all <paramref name="arrows"/>.</param> private void DrawArrows(List <LineI> arrows, LinearGradientBrush brush) { Debug.Assert(arrows != null); Debug.Assert(brush != null); Canvas canvas = this._mapView.Control.MapCanvas; PolygonGrid mapGrid = this._mapView.MapGrid; // draw all arrows defined by map view for (int i = 0; i < arrows.Count; i++) { PointI start = arrows[i].Start; PointI end = arrows[i].End; // skip arrows with zero length if (start == end) { continue; } // skip invalid map coordinates if (!mapGrid.Contains(start) || !mapGrid.Contains(end)) { continue; } // create arrow with specified brush Polygon arrow = new Polygon(); arrow.Stroke = Brushes.White; arrow.StrokeThickness = 1.0; arrow.Fill = brush; // convert map to display coordinates PointD viewStart = this._mapView.SiteToView(start); PointD viewEnd = this._mapView.SiteToView(end); LineD viewArrow = new LineD(viewStart, viewEnd); // scale arrow thickness to current polygon size double dx = Math.Max(2.0, this._mapView.MapGrid.Element.OuterRadius * 0.4); double length = viewArrow.Length; arrow.Points = new PointCollection { new Point(dx * 1.4, 0), new Point(dx * 0.8, dx * 0.8), new Point(length - dx * 1.4, dx * 0.4), new Point(length - dx * 1.6, dx), new Point(length - dx * 0.4, 0), new Point(length - dx * 1.6, -dx), new Point(length - dx * 1.4, -dx * 0.4), new Point(dx * 0.8, -dx * 0.8), }; // rotate into direction of arrow arrow.RenderTransform = new RotateTransform(viewArrow.Angle * Angle.RadiansToDegrees); // show arrow at display coordinates canvas.Children.Add(arrow); Canvas.SetLeft(arrow, viewStart.X); Canvas.SetTop(arrow, viewStart.Y); } }