I didn't find a previous question that seemed to suit what I am asking, but I may not be asking the right thing either.
I have two rectangles, one larger and one smaller. The smaller one can be moved and resized, but I need it contained inside the larger one. But I am having a hard time keeping it inside of the larger one. I can detect when it moves outside of the larger rectangle, but I cannot figure out the method needed to keep it contained without moving outside of the bounding box.
I am currently working python/pyqt4 in a qgraphicsview/scene.
For a working example: In the program gimp, the cropping tool box cannot move outside of the image that is displayed. But it can be moved and resized up to the image's size. That's what I'm aiming for.
Related
As part of my current pygame project (I am very new to pygame), I have created multiple rectangles that move at random around the screen. As one of the features of this game, I want to make it so if one rectangle is close enough to another one, it moves towards it. Another feature I want to add is that rectangles cannot collide with each other, but I don't want to just do the regular
if rectangle1.colliderect(rectangle2):
rectange.x -= 10 # That is, it's previous position
because it will make the animations look odd.
The main way I can see to solve these problems is to use some sort of function that could check if a rectangle.x - 30 is another rectangle (or something similar), but I am unaware of one that exists.
I have attempted to look through google, but I haven't found anything as all the posts are different problems that aren't quite the same.
Thank you for any responses!
Use inflate to create a rectangle that is larger than the original one and surrounds it. Use this rectangle to find other rectangles in range:
test_rect = rect1.inflate(dist, dist)
if test_rect.colliderect(rect2):
# [...]
I'd like to ask if there's a better or faster alternative way to get the largest rectangle inside an almost rectangular contour.
The rectangle should be aligned to both x and y axis and should be completely inside the rectangular contour. That means it would not contain any external white pixels, yet occupy the largest area in the contour.
Test image is here:
I've tried these two but I'm looking if there's a faster and neater way to go around this.
I also tried going through the points of a contour and getting the minimum and maximum points like in here but of course, it just shows similar results to what cv2.boundingRect already does.
Maybe this is a bit of lateral thinking, but looking at your examples and spec when not fill out white pikels contiguouys with the outside bounding box instead. (Like a 'paint pot' brush in Paint-type application).
E.g. (red pixels being the ones you would turn black from white):
You could probably even limit the process to the outer N pixels.
============================
So how might one implement this? It is essentially a version of the "flood fill" algorithm used in pixel graphics programmes, except that you start not from a single seed pixel but checking every point on the edge of the outside bounding rectangle. You start filling in and build a stack of points you need to come back to because you can't necessarily follow every area at once and may need to go back on your self.
You can look that algorithm up, but a 'pure' version will be very stack-heavy if you push every point you can't follow right now, particularly starting with the whole boundary of the shape.
I haven't implemented it this way, but my first thought would be a scan from a boundary inwards, taking a whole line of pixels at a time and mark all the 'white' pixels with a new 3rd colour, then on the next row you fill all the white pixels touching the previously marked pixels and so on. (doesn't matter whether you mark the changed pixels as a 3rd colour, a mask, or alpha-channel or whatever - but you must be able to tell newly filled in pixels from the old black ones.
As you go, you need to check for any 'stranded' areas where you need to work backwards to fill in white areas that are not directly connected to the outside:
Start filling from the edge...
Watch out for stranded areas - if you find one, scan backwards to fill before going to where you were before, to carry one (you may need to recurse if you stranded area turns back on itself again, though in your particular application this shouldn't be a huge issue, unlike some graphics applications)
And continue, not forgetting to fill in from the other edges if required (see note below) until you come to a row with no further pixels to fill and no more back-filling to do. Then restart at the far side of the image as you need to start a backward pass from the far side to catch anything else on that side.
For a practical implementation there is some thinking to do. Your examples will have a lot of filling at the edge but not much by way of complex internal shapes to follow, which keeps things simple. But you need to work from all 4 sides to do it efficiently - perhaps working in as a series of concentric rectangles rather than one side at a time. More complexity working through the design but massively more efficient in this example.
Food for thought anyhow.
I'm creating GUI using python tkinter to visualize Road Scenarios (the main vehicle & close by vehicles). I draw in the canvas lines to give road top view (as the Picture below).
The user can insert a rectangle (vehicle) then move it freely on the canvas.
What I want is: after the user moves the rectangle to where ever he wants, the y coordination of the rectangle will relocate to the nearest lane, to have a nice looking png at the end.
My thought about it:
Divide the canvas to regions (each Region represent a lane)
Create a function which knows when the rectangle finished moving, then modify the y coordination of it to the nearest Region (lane).
Not sure how to apply this in Code though. Any useful canvas functions or another approach are much appreciated.
The approach I mentioned at the question worked for me.
A list identifing the y-axis sides of each Region was created.
After creating the items needed, they all share a common Tag.
Choose which part of the items you want to consider the original Point (which will be used later as the item's current location). Canvas.bboc(CURRENT) can be sufficient to do that.
Detect when does the item enter a Region, by comparing if the item's current Location is within the boundaries of a Region.
Use Canvas.coords() or Cancas.move() methods to move the items at the middle of the regoin they have entered.
I'm coding a game where the viewport follows the player's ship in a finite game world, and I am trying to make it so that the background "wraps" around in all directions (you could think of it as a 2D surface wrapped around a sphere - no matter what direction you travel in, you will end up back where you started).
I have no trouble getting the ship and objects to wrap, but the background doesn't show up until the viewport itself passes an edge of the gameworld. Is it possible to make the background surface "wrap" around?
I'm sorry if I'm not being very articulate. It seems like a simple problem and tons of games do it, but I haven't had any luck finding an answer. I have some idea about how to do it by tiling the background, but it would be nice if I could just tell the surface to wrap.
I don't think so, I have an idea though. I'm guessing your background wraps horizontally and always to the right, then you could attach part of the beginning to the end of the background.
Example, if you have a 10,000px background and your viewport is 1000px, attach the first 1000px to the end of the background, so you'll have a 11,000px background. Then when the vieport reaches the end of the background, you just move it to the 0px position and continue moving right.
I was monkeying around with something similar to what you described that may be of use. I decided to try using a single map class which contained all of my Tiles, and I wanted only part of it loaded into memory at once so I broke it up into Sectors (32x32 tiles). I limited it to only having 3x3 Sectors loaded at once. As my map scrolled to an edge, it would unload the Sectors on the other side and load in new ones.
My Map class would have a Rect of all loaded Sectors, and my camera would have a Rect of where it was located. Each tick I would use those two Rects to find what part of the Map I should blit, and if I should load in new Sectors. Once you start to change what Sectors are loaded, you have to shift
Each sector had the following attributes:
1. Its Coordinate, with (0, 0) being the topleft most possible Sector in the world.
2. Its Relative Sector Coordinate, with (0, 0) being the topleft most loaded sector, and (2,2) the bottom right most if 3x3 were loaded.
3. A Rect that held the area of the Sector
4. A bool to indicate of the Sector was fully loaded
Each game tick would check if the bool to see if Sector was fully loaded, and if not, call next on a generator that would blit X tiles onto the Map surface. I
The entire Surface
Each update would unload, load, or update and existing Sector
When an existing Sector was updated, it would shift
It would unload Sectors on update, and then create the new ones required. After being created, each Sector would start a generator that would blit X amount of tiles per update
Thanks everyone for the suggestions. I ended up doing something a little different from the answers provided. Essentially, I made subsurfaces of the main surface and used them as buffers, displaying them as appropriate whenever the viewport included coordinates outside the world. Because the scrolling is omnidirectional, I needed to use 8 buffers, one for each side and all four corners. My solution may not be the most elegant, but it seems to work well, with no noticeable performance drop.
I'm tinkering around with tkinter, and have used it to make some dynamic graphics based on a dataset.
I started of with an arbitrary sized canvas of 1000x1000 pixels, and now I have my images made, I wondered if there is was anyway to crop the canvas around the unoccupied parts of the edges.
I think of a couple of ways to achieve this, one would be to trim each edge until an object is hit, however, I think this wouldn't work because as far as I can tell the objects are directly addressed onto the canvas location, so any changes to the canvas in the top RHS would just result in objects moving in concert, another would be to (somehow) group all the objects into a single named object, get the borders and a somehow redraw the lot on a newly sized canvas.
I wondered if anyone had any ideas or done this before?
The bbox method of the canvas gives you the bounding box (opposite corners) of an object or objects on the canvas. So, my_canvas.bbox("all") will return you a rectangle that encompasses all of the items on the canvas. According to the official Tk documentation, this method "may overestimate the actual bounding box by a few pixels"
I'm not sure exactly what you mean by "crop" in the context of this question, but since you know the x/y of the upper left corner of the objects, you can use the move method to move all objects by -x1/-y1 pixels to move everything to the upper left corner.