Simplifying a set of shapes into a single shape - algorithm

Given you have a bunch of shapes, say like this:
Wondering if there is a real-time algorithm out there (or any suggestions would be helpful too) that can identify that you can approximate that with large circles sort of like this:
It doesn't have to be circles specifically, it can be parameterized to work in different ways. Just wondering how to basically:
Identify a chunk of shapes that can be approximated by a simpler shape.
Overlay that shape on top of the more complex/smaller shapes.
Thank you.

I think of an approach. I would call it Changing Contrast/Brightness as in image edit applications.
you get all the centers of your shapes.
get their volumes.
calculate the weight of each shape (function of distance and volume of each other shape. Wx = F(Di, Vi), where W (Weight), x: your current shape index, D (distance), Di the distance between x and i, V (Volume), Vi : the volume of i.
Have a variable (perhaps a value scroll bar) to change the Brightness.
repeat #4 for Contrast.
Calculate the average (or mean average) of Weight of all shapes.
Increasing the Brightness means decreasing the volume of far shapes (i.e. shapes with weight below the average "low weight").
Increasing the contrast means increase volume of shapes of high weight and decrease low weights.
By changing both contrast and brightness, some shapes will disappear, others will join as one shape, and you will get a simpler shape(s).

Related

Dividing the plane into regions of equal mass based on a density function

Given a "density" scalar field in the plane, how can I divide the plane into nice (low moment of inertia) regions so that each region contains a similar amount of "mass"?
That's not the best description of what my actual problem is, but it's the most concise phrasing I could think of.
I have a large map of a fictional world for use in a game. I have a pretty good idea of approximately how far one could walk in a day from any given point on this map, and this varies greatly based on the terrain etc. I would like to represent this information by dividing the map into regions, so that one day of walking could take you from any region to any of its neighboring regions. It doesn't have to be perfect, but it should be significantly better than simply dividing the map into a hexagonal grid (which is what many games do).
I had the idea that I could create a gray-scale image with the same dimensions as the map, where each pixel's color value represents how quickly one can travel through the pixel in the same place on the map. Well-maintained roads would be encoded as white pixels, and insurmountable cliffs would be encoded as black, or something like that.
My question is this: does anyone have an idea of how to use such a gray-scale image (the "density" scalar field) to generate my "grid" from the previous paragraph (regions of similar "mass")?
I've thought about using the gray-scale image as a discrete probability distribution, from which I can generate a bunch of coordinates, and then use some sort of clustering algorithm to create the regions, but a) the clustering algorithms would have to create clusters of a similar size, I think, for that idea to work, which I don't think they usually do, and b) I barely have any idea if any of that even makes sense, as I'm way out of my comfort zone here.
Sorry if this doesn't belong here, my idea has always been to solve it programatically somehow, so this seemed the most sensible place to ask.
UPDATE: Just thought I'd share the results I've gotten so far, trying out the second approach suggested by #samgak - recursively subdividing regions into boxes of similar mass, finding the center of mass of each region, and creating a voronoi diagram from those.
I'll keep tweaking, and maybe try to find a way to make it less grid-like (like in the upper right corner), but this worked way better than I expected!
Building upon #samgak's solution, if you don't want the grid-like structure, you can just add a small random perturbation to your centers. You can see below for example the difference I obtain:
without perturbation
adding some random perturbation
A couple of rough ideas:
You might be able to repurpose a color-quantization algorithm, which partitions color-space into regions with roughly the same number of pixels in them. You would have to do some kind of funny mapping where the darker the pixel in your map, the greater the number of pixels of a color corresponding to that pixel's location you create in a temporary image. Then you quantize that image into x number of colors and use their color values as co-ordinates for the centers of the regions in your map, and you could then create a voronoi diagram from these points to define your region boundaries.
Another approach (which is similar to how some color quantization algorithms work under the hood anyway) could be to recursively subdivide regions of your map into axis-aligned boxes by taking each rectangular region and choosing the optimal splitting line (x or y) and position to create 2 smaller rectangles of similar "mass". You would end up with a power of 2 count of rectangular regions, and you could get rid of the blockiness by taking the centre of mass of each rectangle (not simply the center of the bounding box) and creating a voronoi diagram from all the centre-points. This isn't guaranteed to create regions of exactly equal mass, but they should be roughly equal. The algorithm could be improved by allowing recursive splitting along lines of arbitrary orientation (or maybe a finite number of 8, 16, 32 etc possible orientations) but of course that makes it more complicated.

Fill polygon with smaller shapes (circles)

I'm just going to try and explain my problem with images:
The program receives an input (image):
There is a base polygon, but can be simplified into a circle in all situations:
Output should be something like:
There is no correct result, just good and bad ones.
To make things easier, an estimate how many circles there should be can be given based on the surface and extent of the polygon.
What I am searching is an algorithm that does something described above - cover as much as possible with the given shape, while minimizing the area of black pixels and overlapping areas.
I used k-means clustering to find circle centers. Number of clusters is calculated:
numberOfClusters = round(polygonArea / basePolygonArea).
Input data for k-means algorithm are points of white pixels.

Area divide algorithm

Is there any algorithm to find a distribution of area into n sub-regions, where each sub-region might have different area.
To formally put the problem statement: Suppose you have a rectangular plot. How will you divide the region into n rectangles. The sum of area of these sub-rectangles will be equal to original rectangular plot(So there wouldn't be any overlaps between the rectangles)
And the area of each of these smaller n rectangles is given before hand.
Restriction is on width of each sub-rectangle.
This subdivision has to be displayed on may be a computer screen which is divided into pixels. So I don't want any areas any dimension to be smaller than a pixel(or maybe 10), which might be of no use to display as such.
I was looking at a rectangle packing algorithm here but this seems to be wasting space which I don't want. Does there exist any algorithm to solve this problem.
Backtracking doesn't seem to be a good solution in this case as the sub-rectangles area is only specified, not the dimensions, or is it?
Example 1:
Example 2:
The integral of a function is the area bound by the limits, the curve of the function, and the x-axis. Define one side of the rectangle as the x-axis, then find the boundaries for the others. There are plenty of numerical integration libraries around in the language of your choice.
EDIT: some difficulties in trying to illustrate in words...
Assuming, at least, that the containing rectangle has an area larger than the sum of the areas of the sub-regions; and there is no requirement of a certain order of containment:
Contain the largest sub-region first with edges on the axes.
Pick the next smaller sub-region.
Create the function (integral) to calculate the free area as seen from each axes.
With windows/limits equal to the length on the sub-region's sides (facing the axes), slide these windows along the axes away from the origin.
Create the function for finding the free space bounded by the outside arms of the cross formed by the windows as they slide along the axes. Efficiency in the use of space is found in the region where free space is minimal (differentiation).
Rotate the sub-region by 90 degrees and repeat from step 3.
Place the sub-region in the orientation and location where most efficient.
Repeat step 2. Stop when sliding windows report negative
free space for the entire domain (allocated space overlaps the placeholder made by the windows).
In theory, this will systematically try to squeeze in sub-regions. Sketch and pseudocode to follow if time permits.

What sort of fuzzy flood fill algorithms are there?

I'm implementing a flood fill algorithm for the project I'm currently working on. I'm using it for the normal purpose, image editing. I have no problem with the basic algorithm, but I'd like a better looking fill.
In many cases areas of my image will have regions that are mostly one color, but which are bordered by pixels which are slightly lighter or darker. I'd like to know an algorithm for a "fuzzy" flood fill that won't leave these border pixels. I've tried to fill all pixels withn two different, simple, distance metrics of the origin pixel:
a Manhattan Distance on all 3 color components: red, green, and blue
the maximum of the distance between the color components.
Neither of these do the trick, often leaving borders and occasionally filling adjacent regions of a visually distinct but "close" color.
I don't think there is a magic bullet to solve my problem, but I'd be interested in knowing any algorithms which I might try to get a better result, or even where I might usefully look to find such algorithms. Looking around the net I've found reference to something called the "fuzzy flood fill mean shift algorihm", but I'm not sure that's even the same thing.
Using the actual distance seems natural: D = Sqrt(R^2 + G^2 + B^2)
Then define a tolerance parameter that specifies the maximum distance from the original pixel (in colorspace) that the test pixel can be. If it is greater than that value, do not flood outward from that pixel.
Tweak the tolerance from 0 to Sqrt(255^2 + 255^2 + 255^2) until you see the desired effect.
Maybe you could try using the qualities of the local pixels rather than the origin pixels. You could do an effect much like an anisotropic diffusion filter. Enqueue a neighbor if the gradient between the current pixel (in the fill) and the neighbor pixel is low enough.
You should set tolerance not with a single number but rather with a range. Say, from 20% to 50% would mean that when color difference is 20% you change the color of this pixel completely. When it's greater then 50% you don't fill this pixel. And when the difference lays in a range from 20% to 50% you blend the old color with the new color with ratio of (d-t_min)/(t_max-t_min) where d is color difference and t_max and t_min is your tolerance range (expressed in 0...1).
I never seen such an algorithm ever implemented; maybe I just invented it.

How can I fill an outline with predefined tangram shapes?

I am interested in using shapes like these:
Usually a tangram is made of 7 shapes(5 triangles, 1 square and 1 parallelogram).
What I want to do is fill a shape only with tangram shapes, so at this point,
the size and repetition of shapes shouldn't matter.
Here's something I manually tried:
I am a bit lost on how to approach this.
Assuming I have a path (an ordered list/array of points of the outline),
I imagine I should try to do some sort of triangulation.
Is there such a thing as Deulanay triangulation with triangles constrained to 45 degrees
right angled triangles ?
A more 'brute' approach would be to add a bunch of triangles(45 degrees) and use SAT
for collision detection to 'fix' overlaps, and hopefully gaps will be avoided.
Since the square and parallelogram can be made of triangles(45 degrees) too, I imagine there
would be a nice clean geometric solution, right ?
How do I pack triangles(45 degrees) inside an arbitrary shape ?
Any ideas are welcome.
A few random thoughts (maybe they help you find a better solution) if you're using only the original sizes of the shapes:
as you point out, all shapes in the tangram can be made composed of e.g. the yellow or pink triangle (d-g-c), so try also thinking of a bottom-up approach such as first trying to place as many yellow triangles into your shape and then combine them into larger shapes if possible. In the worst case, you'll end up with a set of these smallest triangles.
any kind triangulation of non-polygons (such as the half-moon in your example) probably does not work very well...
It looks like you require that the shapes can only have a few discrete orientations. To find the best fit of these triangles into the given shape, I'd propose the following approximate solution: draw a grid of triangles (i.e. a square grid with diagonal lines) across the shape and take those triangles which are fully contained. This most likely will not give you the optimal coverage but then you could repeatedly shift the grid by a tenth of the grid size in horizontal and vertical direction and see whether you'll find something which covers a larger fraction of the original shape (or you could go in steps of 1/2 then 1/4 etc. of the original grid size in the spirit of a binary search).
If you allow any arbitrary scaling of the shapes you could approximate any (reasonably smooth ?) shape to arbitrary precision by adding smaller and smaller shapes. E.g. if you have a raster image, you can e.g. choose the size of the yellow triangle such that two of them make a pixel on the image and then you can represent any such raster image.

Resources