I'd like to ask if it is possible to use LINQ to draw rectangles saved in list with a condition of drawing a specific rectangle inside that list. This is a newbie question, so please bear with me.
As the name says, LINQ is for querying any kind of data. As long as you see objets as data carriers you can use LINQ to query them. But it can't do any drawing or any kind of code execution. If you divide your problem into two parts; first selecting the appropriate shapes and then drawing them, the code could be something like this:
public void QueryShapes(IEnumerable<Shape> shapes)
{
var rectangles =
from shape in shapes
where shape is Rectangle
let rect = (Rectangle)shape
where rect.Width > 100 // conditions...
select shape as Rectangle;
rectangles.ToList().ForEach(Draw);
}
public void Draw(Rectangle rectangle)
{
// drawing
}
Related
I am working with GoogleMap and I am trying to focus my map on a region that displayed my list of locations. The list gets "included" into the builder one by one, but when I actually call this method a lot of my locations are cropped out. Seems to me like the zoom level on the NewLatLngBounds is too high.
I thought about getting the Northeast and Southwest Corners and then centering the map but that doesn't work either. Not sure what else to try.
public void DisplayRegion(List<Position> positions, int padding = 0)
{
if (_googleMap == null) throw new InvalidOperationException("Map is not ready");
LatLngBounds.Builder builder = new LatLngBounds.Builder();
foreach(var p in positions)
{
builder.Include(new LatLng(p.Latitude, p.Longitude);
}
LatLngBounds bounds = builder.Build();
//var ne = bounds.Northeast;
// var se = bounds.Southwest;
_googleMap.AnimateCamera(CameraUpdateFactory.NewLatLngBounds(bounds, padding));
}
This does work but like I said above a good chunk of the locations passed in are cropped off screen. I also tried factoring in the width and height of the and basing padding on that but it's like I didn't do anything. All I want is for every item in my List of Positions to display on screen at an appropriate zoom level. Any suggestions?
First , select a location as the center of the map,just get the midpoint from Northeast and Southwest Corners , let's say we get a point ,it has centerLatitude and centerLongitude .
Calculate how far are the positions between the center location , and get the farthest distance , call it farthestDistance.
Use map.MoveToRegion (MapSpan.FromCenterAndRadius (new Position (centerLatitude,centerLongitude), Distance.FromKilometers (farthestDistance)));
Then the map will display including all the positions and use a proper zoom level .
Refer to https://stackoverflow.com/a/53735393/8187800 .
The problem is, for an IEnumerable of rectangles I need to know for each rectangle whether it intersects any of the others. So the output would be a sequence with the same count containing one boolean value for every rectangle.
So it is kind of a nested loop problem but it should not compare the element with itself and if rect A intersects rect B there is no need to check rect B again.
Is this possible with LINQ?
//for every rectangle in your list.
//search the list, eliminating the same one,
//and find if any of the others intersect with it.
var intersectingRectangles = rectangles
.Where(rect => rectangles
.Where(r => r != rect)
.Any(r => DoIntersect(rect, r)));
This assumes that you have a function DoIntersect taking two rectangles and telling you if they intersect.
There are MANY improvements that could be made to this if it is not effecient enough for your needs. you could potentially sort based on coordinates and be able to eliminate a lot of comparisons. But, that all depends on what your data looks like and how fast this needs to be.
If you want to have the output contain each of the original IEnumerable along with a status about whether is intersects any others than switch to using a Select() as below.
var allWithIntersectionStatus = rectangles.Select(rect => new
{
Value = rect,
DoesIntersect = rectangles
.Where(rectWhere => rectWhere != rect)
.Any(rectAnt => DoIntersect(rect, rectAnt))
});
var random = new Random();
Canvas.SetLeft(rectangle, random.Next((int)(ImageCanvas.Width - 100)));
Canvas.SetTop(rectangle, random.Next((int)(ImageCanvas.Height - 100)));
return rectangle;
So the above code just randomly sets the Top and Left positions of a rectangle that will appear on the canvas. I can easily reuse this code if I want multiple rectangles to appear on the screen, however what I was having trouble doing is tweaking the code so that each rectangle is never overlapping each other.
I thought of maybe doing a while loop that keeps running random.Next((int)(ImageCanvas.Height - 100)) continuously until it is not equal to the previous random... But that isn't perfect. The shapes are quite big, so having slightly different X or Y coordinates doesn't prevent a overlap. They would somehow need to be at least 50 pixels distance between each other or something for this to prevent any overlap between other rectangles.
Assuming your Canvas is reasonably large, i.e. the rectangles will not occupy a large amount of the area, it most likely suffices to simply generate rectangles at random (as in your example code), and then check to make sure they don't overlap with any of the previously selected rectangles.
Note that "overlaps with another rectangle" is really the same as "has a non-empty intersection with another rectangle". And .NET provides that functionality; for WPF, you should use the System.Windows.Rect struct. It even has an IntersectsWith() method, giving the information you need in a single call (otherwise you'd have to get the intersection as one step, and then check to see if the result is empty in a second step).
The whole thing might look something like this:
List<Rectangle> GenerateRectangles(Canvas canvas, int count, Size size)
{
Random random = new Random();
List<Rect> rectangles = new List<Rect>(count);
while (count-- > 0)
{
Rect rect;
do
{
rect = new Rect(random.Next((int)(canvas.Width - size.Width),
(int)(canvas.Height - size.Height), size.Width, size.Height);
} while (rectangles.Any(r => r.IntersectsWith(rect));
rectangles.Add(rect);
}
return rectangles.Select(r =>
{
Rectangle rectangle = new Rectangle();
rectangle.Width = r.Width;
rectangle.Height = r.Height;
canvas.SetLeft(rectangle, r.Left);
canvas.SetTop(rectangle, r.Top);
return rectangle;
}).ToList();
}
You would want something more sophisticated if you were dealing with a more constrained area and/or a larger number of rectangles. The above won't scale well for large numbers of rectangles, especially if the probability of a collision is high. But for your stated goals, it should work fine.
Hello I have 2d matrix data saved in the ILArray < double >. This matrix represents the weights of the neural network from one neuron and i want to see how the weights looks with ilnumerics. Any idea how can i do this? I find many examples for 3d plotting but nothing for plotting 2d image data representation.
Image data are currently best (simplest) visualized by utilizing ILSurface. Since this is a 3D plot, you may not get the optimal performance for large image data. Fortunately, ILNumerics' scene graph makes it easy to improve this with your own implementation.
The most simple attempt would take an ILPoints shape, arrange the needed number of points in a grid and let every point visualize the value of the corresponding element within the input matrix - let's say by color (or size).
private void ilPanel1_Load(object sender, EventArgs e) {
using (ILScope.Enter()) {
// some 'input matrix'
ILArray<float> Z = ILSpecialData.sincf(40, 50);
// do some reordering: prepare vertices
ILArray<float> Y = 1, X = ILMath.meshgrid(
ILMath.vec<float>(1, Z.S[1]),
ILMath.vec<float>(1,Z.S[0]),
Y);
// reallocate the vertex positions matrix
ILArray<float> pos = ILMath.zeros<float>(3, X.S.NumberOfElements);
// fill in values
pos["0;:"] = X[":"];
pos["1;:"] = Y[":"];
pos["2;:"] = Z[":"];
// colormap used to map the values to colors
ILColormap cmap = new ILColormap(Colormaps.Hot);
// setup the scene
ilPanel1.Scene.Add(new ILPlotCube {
new ILPoints() {
Positions = pos,
Colors = cmap.Map(Z).T,
Color = null
}
});
}
}
Obviously, the resulting points do not scale with the form. So the 'image' suffers from larger gaps between the points when the form size is increased. So, for a better implementation you may adapt the approach to utilize ILTriangles instead of ILPoints, in order to assemble adjacent rectangles.
I have decided to have a go at making a dungeon crawler game with the Xna framework. I am a computer science student and am quite familiar with c# and .net framework. I have some questions about different parts of the development for my engine.
Loading Maps
I have a tile class that stores the vector2 position, 2dtexture and dimensions of the tile. I have another class called tilemap that has a list of tiles that are indexed by position. I am reading from a text file which is in the number format above that matches the number to the index in the tile list and creates a new tile with the correct texture and position, storing it into another list of tiles.
public List<Tile> tiles = new List<Tile>(); // List of tiles that I have added to the game
public List<TileRow> testTiles = new List<TileRow>(); // Tilerow contains a list of tiles along the x axis along with there vector2 position.
Reading and storing the map tiles.
using (StreamReader stream = new StreamReader("TextFile1.txt"))
{
while (stream.EndOfStream != true)
{
line = stream.ReadLine().Trim(' ');
lineArray = line.Split(' ');
TileRow tileRow = new TileRow();
for (int x = 0; x < lineArray.Length; x++)
{
tileXCo = x * tiles[int.Parse(lineArray[x])].width;
tileYCo = yCo * tiles[int.Parse(lineArray[x])].height;
tileRow.tileList.Add(new Tile(tiles[int.Parse(lineArray[x])].titleTexture, new Vector2(tileXCo,tileYCo)));
}
testTiles.Add(tileRow);
yCo++;
}
}
For drawing the map.
public void Draw(SpriteBatch spriteBatch, GameTime gameTime)
{
foreach (TileRow tes in testTiles)
{
foreach (Tile t in tes.tileList)
{
spriteBatch.Draw(t.titleTexture, t.position, Color.White);
}
}
}
Questions:
Is this the correct way I should be doing it, or should I just be storing a list referencing my tiles list?
How would I deal with Multi Layered Maps?
Collision Detection
At the moment I have a method that is looping through every tile that is stored in my testTiles list and checking to see if its dimensions are intersecting with the players dimensions and then return a list of all the tiles that are. I have a derived class of my tile class called CollisionTile that triggers a collision when the player and that rectangle intersect. (public class CollisionTile : Tile)
public List<Tile> playerArrayPosition(TileMap tileMap)
{
List<Tile> list = new List<Tile>();
foreach (TileRow test in tileMap.testTiles)
{
foreach (Tile t in test.tileList)
{
Rectangle rectangle = new Rectangle((int)tempPosition.X, (int)tempPosition.Y, (int)playerImage.Width / 4, (int)playerImage.Height / 4);
Rectangle rectangle2 = new Rectangle((int)t.position.X, (int)t.position.Y, t.width, t.height);
if (rectangle.Intersects(rectangle2))
{
list.Add(t);
}
}
}
return list;
}
Yeah, I am pretty sure this is not the right way to check for tile collision. Any help would be great.
Sorry for the long post, any help would be much appreciated.
You are right. This is a very inefficient way to draw and check for collision on your tiles. What you should be looking into is a Quadtree data structure.
A quadtree will store your tiles in a manner that will allow you to query your world using a Rectangle, and your quadtree will return all tiles that are contained inside of that Rectangle.
List<Tiles> tiles = Quadtree.GetObjects(rectangle);
This allows you to select only the tiles that need to be processed. For example, when drawing your tiles, you could specify a Rectangle the size of your viewport, and only those tiles would be drawn (culling).
Another example, is you can query the world with your player's Rectangle and only check for collisions on the tiles that are returned for that portion of your world.
For loading your tiles, you may want to consider loading into a two dimensional array, instead of a List. This would allow you to fetch a tile based on its position, instead of cross referencing it between two lists.
Tile[,] tiles = new Tile[,]
Tile tile = tiles[x,y];
Also, in this case, an array data structure would be a lot more efficient than using a List.
For uniform sets of tiles with standard widths and heights, it is quite easy to calculate which tiles are visible on the screen, and to determine which tile(s) your character is overlapping with. Even though I wrote the QuadTree in Jon's answer, I think it's overkill for this. Generally, the formula is:
tileX = someXCoordinate % tileWidth;
tileY = someYCoordinate % tileHeight;
Then you can just look that up in a 2D array tiles[tileX, tileY]. For drawing, this can be used to figure out which tile is in the upper left corner of the screen, then either do the same again for the bottom right (+1), or add tiles to the upper left to fill the screen. Then your loop will look more like:
leftmostTile = screenX % tileWidth; // screenX is the left edge of the screen in world coords
topmostTile = screenY % tileHeight;
rightmostTile = (screenX + screenWidth) % tileWidth;
bottommostTile = (screenY + screenHeight) % tileHeight;
for(int tileX = leftmostTile; tileX <= rightmostTile; tileX++)
{
for(int tileY = topmostTile; tileY <= bottommostTile; tileY++)
{
Tile t = tiles[tileX][tileY];
// ... more stuff
}
}
The same simple formula can be used to quickly figure out which tile(s) are under rectangular areas.
IF however, your tiles are non-uniform, or you have an isometric view, or you want the additional functionality that a QuadTree provides, I would consider Jon's answer and make use of a QuadTree. I would try to keep tiles out of the QuadTree if you can though.