This is an interview question.
We are given dimensions of various rectangles, we have to find out the area(minimum) of rectangle that can enclose all of them? rectangles can be rotated also .
test case:-
input:
3 //number of rectangles
8 8
4 3
3 4
output:
88
11x8:
+ - - - - - - + + - +
| | | |
| | | |
| | + - +
| | + - +
| | | |
| | | |
+ - - - - - - + + - +
i looked at a similar question asked before fitting rectangles in the smallest possible area
the above approach looks at all possibilities ,rotations, and determine the minimum over all such possibilities in all layout cases.
can't we base an algorithm in which we find the sum of area of rectangles first and then look for max length ,width?
There is no absolute solution to this problem, but there are several approximate solutions, you can read about some of them here.
Optimal Rectangle Packing on Non-Square Benchmarks:
Given a set of rectangles, our problem is to find all enclosing
rectangles of minimum area that will contain them without overlap. We
refer to an enclosing rectangle as a bounding box. The optimization
problem is NP-hard, while the problem of deciding whether a set of
rectangles can be packed in a given bounding box is NP-complete, via a
reduction from bin-packing (Korf 2003).
New Improvements in Optimal Rectangle Packing:
Korf [2003] divided the rectangle packing problem into two
subproblems: the minimal bounding box problem and the containment
problem. The former finds a bounding box of least area that can
contain a given set of rectangles, while the latter tries to pack the
given rectangles in a given bounding box. The algorithm that solves
the minimal bounding box problem calls the algorithm that solves the
containment problem as a subroutine.
Minimal Bounding Box Problem
A simple way to solve the minimal bounding box problem is to find the
minimum and maximum areas that describe the set of feasible and
potentially optimal bounding boxes. Bounding boxes of all dimensions
can be generated with areas within this range, and then tested in
non-decreasing order of area until all feasible solutions of smallest
area are found. The minimum area is the sum of the areas of the given
rectangles. The maximum area is determined by the bounding box of a
greedy solution found by setting the bounding box height to that of
the tallest rectangle, and then placing the rectangles in the first
available position when scanning from left to right, and for each
column scanning from bottom to top.
See also Optimal Rectangle Packing: New Results.
First of all you should check, could be enclosing rectangle be rotated or no?
Anyway, you could ignore "rectangles" condition and resolve task in points.
You have array of points (which are vertexes of rectangles). Your task is to find encosing rectangle with minimum area.
If enclosing rectangle could not be rotated then solution is silly and has complexity O(n).
Generated array of rectangles and make array of points, which are vertexes of rectangles.
Next is simple:
long n; // Number of vertexes
point arr[SIZE]; //Array of vertexes
long minX = MAXNUMBER, minY = MAXNUMBER, maxX = -MAXNUMER, maxY = -MAXNUMBER;
for (long i = 0; i < 4 * n; i++)
{
minX = MIN(minX, arr[i].x);
minY = MIN(minY, arr[i].y);
maxX = MIN(maxX, arr[i].x);
maxY = MIN(maxY, arr[i].y);
}
long width = maxX - minX, height = maxY - minY;
printf("%ddX%ld", width, height);
Another task if rectangle could be rotated. Then you should first:
Build minimum convex polygon of all the points in rectangle. You can
use any of existing algorythms. Complexity O(n log n). As exmaple "Graham's Scan" : http://en.wikipedia.org/wiki/Graham%27s_scan
Use simple algorithm for convex polygon. Link: http://cgm.cs.mcgill.ca/~orm/maer.html
Link for your task in wiki: http://en.wikipedia.org/wiki/Minimum_bounding_rectangle
Related
I have a set of data which contains a list of array. Each array contains 4 value of coordinates which forms a rectangle.
i.e. the start and end point(Xs, Xe) on X-axis; and the start and end point(Ys, Ye) on y-axis.
Xs|Xe|Ys|Ye
--------------
[[10,15,5,8],
[9,12,5,8],
[1,20,1,20]]
, for example.
And now I had a point(x,y).
To get all the rectangles that will cover the point, I simply loop through all array and compare one by one.
related_rectangles = []
for rectangle in dataset:
if x > rectangle[0] and x < rectangle[1] and y > rectangle[2] and y < rectangle[3]:
related_rectangles.append(rectangle)
The complexity should be O(n).
The question is, is there any algorithm or data structure that could reduce the complexity of searching? Especially for the case that all rectangles are squares.
Thanks.
I am working with a biological model of the distribution of microbial biomass (b1) on a 2D grid. From the biomass a protein (p1) is produced. The biomass diffuses over the grid, while the protein does not. Only if a certain amount of protein is produced (p > p_lim), the biomass is supposed to diffuse.
I try to implement this by using a dummy cell variable z multiplied with the diffusion coefficient and setting it from 0 to 1 only in cells where p > p_lim.
The condition works fine and when the critical amount of p is reached in a cell, z is set to 1, and diffusion happens. However, the diffusion still does not work with the rate I would like, because to calculate diffusion, the face variable, not the value of the cell itself is used. The faces of z are always a mean of the cell with z=1 and its neighboring cells with z=0. I I, however, would like the diffusion to work at its original rate even if the neighbouring cell is still at p < p_lim.
So, my question is: Can i somehow access a faceVariable and change it? For example, set a face to 1 if any neigboring cell has reached p1 > p_lim? I guess this is not a proper mathematical thing to do, but I couldn't think of another way to simulate this problem.
I will show a very reduced form of my model below. In any case, I thank you very much for your time!
##### produce mesh
nx= 5.
ny= nx
dx = 1.
dy = dx
L = nx*dx
mesh = Grid2D(nx=nx,ny=ny,dx=dx,dy=dy)
#parameters
h1 = 0.5 # production rate of p
Db = 10. # diffusion coeff of b
p_lim=0.1
# cell variables
z = CellVariable(name="z",mesh=mesh,value=0.)
b1 = CellVariable(name="b1",mesh=mesh,hasOld=True,value=0.)
p1= CellVariable(name="p1",mesh=mesh,hasOld=True,value=0.)
# equations
eqb1 = (TransientTerm(var=b1)== DiffusionTerm(var=b1,coeff=Db*z.arithmeticFaceValue)-ImplicitSourceTerm(var=b1,coeff=h1))
eqp1 = (TransientTerm(var=p1)==ImplicitSourceTerm(var=b1,coeff=h1))
# set b1 to 10. in the center of the grid
b1.setValue(10.,where=((x>2.)&(x<3.)&(y>2.)&(y<3.)))
vi=Viewer(vars=(b1,p1),FIPY_VIEWER="matplotlib")
eq = eqb1 & eqp1
from builtins import range
for t in range(10):
b1.updateOld()
p1.updateOld()
z.setValue(z + 0.1,where=((p1>=p_lim) & (z < 1.)))
eq.solve(dt=0.1)
vi.plot()
In addition to .arithmeticFaceValue, FiPy provides other interpolators between cell and face values, such as .harmonicFaceValue and .minmodFaceValue.
These properties are implemented using subclasses of _CellToFaceVariable, specifically _ArithmeticCellToFaceVariable, _HarmonicCellToFaceVariable, and _MinmodCellToFaceVariable.
You can also make a custom interpolator by subclassing _CellToFaceVariable. Two such examples are _LevelSetDiffusionVariable and ScharfetterGummelFaceVariable (neither is well documented, I'm afraid).
You need to override the _calc_() method to provide your custom calculation. This method takes three arguments:
alpha: an array of the ratio (0-1) of the distance from the face to the cell on one side, relative to the distance from distance from the cell on the other side to the cell on the first side
id1: an array of indices of the cells on one side of the face
id2: an array of indices of the cells on the other side of the face
Note: You can ignore any clause if inline.doInline: and look at the _calc_() method defined under the else: clause.
I have an sparse matrix array in which i need to find highest empty region around an element. Region should be in rectangle or square form. In that region, no other element should present. Algorithm is enough to develop code. Is there any algorithm available to achieve this?
Since you mentioned no requirements as to the efficiency of a solution, here's a brute force approach.
Let M denote the matrix
Let n be the number of rows
Let m be the number of columns
Let maxRowSize be 0, initially
Let maxColSize be 0, initially
Let maxRowStart be 0, initially
Let maxColStart be 0, initially
for top from 0 to n:
for left from 0 to m:
numNonEmptyElements = 0
if M[top][left] is non-empty:
numNonEmptyElements = 1
for bottom from i to n:
if M[bottom][left] is non-empty AND numNonEmptyElements == 1:
break
for right from 0 to m:
if M[bottom][right] is non-empty:
numNonEmptyElements += 1
if numNonEmptyElements > 1:
break
if (right - left + 1) * (bottom - top + 1) > maxRowSize * maxColSize:
maxRowSize = bottom - top + 1
maxColSize = right - left + 1
maxRowStart = top
maxColStart = left
return any of the maxRowSize, maxColSize, maxRowStart, maxColStart you need
As you can observe from the loops, the time complexity for the pseudocode is O(N2M2), N and M being row and column size of the matrix, and is really inefficient.
Here is an algorithm to solve this problem.First you have to calculate size of the maximum rectangle possible in all the four directions: top-left , top-right ,bottom-left,bottom-right.See the figure all rectangle are indicated in different colors.
For example we want to calculate for the index(3,4),which is 5 in the matrix below.Then calculate the dimensions of all rectangles(top-left , top-right ,bottom-left,bottom-right).I have shown These rectangles in the figure with different colors(red,green,yellow & blue).
After finding dimensions of all the rectangles we can find the dimensions of the highest empty region(Shaded region in figure) by:
Length:
Min((Top-Left_Length+Top-right_Length),(Bottom-Left_Length+Bottom-right_Length));
Width:
Min((Top-Left_Breadth+Top-right_Breadth),(Bottom-Left_Breadth+Bottom-right_Breadth));
This looks like a very good application for a modified flood-fill algorithm.
Considering a NxM matrix and the postion of your element (i,j); 0<=i
getLargestArea(i,j)
a0 = floodFill_markArea(i+1,j)
a1 = floodFill_markArea(i-1,j)
a2 = floodFill_markArea(i,j+1)
a3 = floodFill_markArea(i,j-1)
return max(a0,a1,a2,a3)
As for floodFill_markArea, it starts from a corned and fills a rectangular area keping track of surface area; if should be easy to add a few constraints to the classic flood-fill algorithm to achieve this.
I posted this on twitter a while ago but seeing how none of my followers appears to be a math/programming genius, I'll try my luck here as well. I got here because I found this which might contain part of my solution.
I described my problem in the following pdf document, containing a picture of what I'm trying to achieve.
To give some more details, I divided the pentagon's of a dodecahedron (12 pentagons) into triangles (5/pentagon, 60 triangles in total), then collected a set of data points relative to each of these triangles.
The idea is to generate terrain meshes for each individual triangle.
To do so, the data must be represented flat, in a 32K x 32K square (idTech4 Megatexture)
I have vaguely heard of transformation matrices, which when set up properly, could do the trick of passing all the data points trough them to have them show up in the right place.
I looked at this source code here but I don't understand how I'm supposed to get the points in and/or out of there, not to mention how to do the setup so I can present each point in turn and get the result point back.
I got as fas as identifying the point that belongs in the back right corner. All my 3D points are originally stored in latitude / longitude pairs. I retrieve the 3D vectors this way:
coord getcoord(point* p)
{
coord c;
c.x=cos(p->lat*pi/180.l) * cos(p->lon*pi/180.l);
c.y=cos(p->lat*pi/180.l) * sin(p->lon*pi/180.l);
c.z=sin(p->lat*pi/180.l);
return c;
};
My thought is that if I can find the center of my triangle, and discover how to offset my angles so the vector from the center of my sphere to the middle of the triangle moves to 90N then my points would already be in the right plane if I rotated them all along the same angles. If I then convert them all to 3d and subtracti the radius from y, they'll be at the correct y position as well.
Then all I'd need to do is the rotation, the scaling, and the moving to the final position.
There are several kinds of 'centers' for a triangle, I think the one I need is the one that is equidistant to the corners of the triangle (Circumcenter?)
But then there might be an easier approach to the whole problem so while I continue my own research, perhaps some of you can help pointing me in the right direction.
It appears as if some sample data is in order, here are a few of these triangles in obj file format:
v 0.000000 0.000000 3396.000000
v 2061.582356 0.000000 2698.646733
v 637.063983 1960.681333 2698.646733
f 1 2 3
And another:
v -938.631230 2888.810129 1518.737455
v 637.063983 1960.681333 2698.646733
v 1030.791271 3172.449325 637.064076
f 1 2 3
You will notice that each point is at a distance of 3396 from 0,0,0
I mentioned 'on the sphere' meaning that the face away from the center of the sphere is the face that needs to become the 'top' when translated into the square.
Theoretically all these triangles should in fact have identical sizes, but due to rounding errors in the math that generated them, this might not be entirely true.
If I'm not mistaken I already took measures to ensure that the first point you see here is always the one opposite the longest border, so it's the one that should go in the far left corner (testing the above 2 samples confirms this, but I'm measuring anyway just to be sure)
Both legs leading away from this point should theoretically have the same length as well, but again rounding errors might slightly offset that.
If I've done it correctly then the longer side is 1,113587 times longer than the 2 shorter sides. Assuming those are identical, then doing some goal seeking in excel, I can deduct that the final points, assuming I was just translating this triangle, should look like:
v 16384.000000 0.000000 16384.000000
v -16384.000000 0.000000 9916.165306
v 9916.165306 0.000000 -16384.000000
f 1 2 3
So I need to setup the matrix to do this transformation, preferably using the 4x4 matrix as explained below.
I would recommend using transform matrices. The 3d transform matrix is a 4x4 data structure which describes a translation and rotation (and possibly a scale). Once you have a matrix you can transform a point like so
result.x = (tmp->pt.x * m->element[0][0]) +
(tmp->pt.y * m->element[1][0]) +
(tmp->pt.z * m->element[2][0]) +
m->element[3][0];
result.y = (tmp->pt.x * m->element[0][1]) +
(tmp->pt.y * m->element[1][1]) +
(tmp->pt.z * m->element[2][1]) +
m->element[3][1];
result.z = (tmp->pt.x * m->element[0][2]) +
(tmp->pt.y * m->element[1][2]) +
(tmp->pt.z * m->element[2][2]) +
m->element[3][2];
int w = (tmp->pt.x * m->element[0][3]) + (tmp->pt.y * m->element[1][3])
+ (tmp->pt.z * m->element[2][3]) + m->element[3][3];
if (w!=0 || w!=1)
result.x/=w; result.y/=w; result.z/=w;
This will transform the 3D point pt by the matrix m. If you now a little matrix math you'll see i'm just multiplying my origin point as a vector against the matrix (and doing a little normalization if it is a skew matrix.) Matrices can be multiplied together to form complicated transformations so they are very useful.
For details on making matrices suggest reading this link.
http://en.wikipedia.org/wiki/Transformation_matrix
With reference to this programming game I am currently building.
alt text http://img12.imageshack.us/img12/2089/shapetransformationf.jpg
To translate a Canvas in WPF, I am using two Forms: TranslateTransform (to move it), and RotateTransform (to rotate it) [children of the same TransformationGroup]
I can easily get the top left x,y coordinates of a canvas when its not rotated (or rotated at 90deg, since it will be the same), but the problem I am facing is getting the top left (and the other 3 points) coordinates.
This is because when a RotateTransform is applied, the TranslateTransform's X and Y properties are not changed (and thus still indicate that the top-left of the square is like the dotted-square (from the image)
The Canvas is being rotated from its center, so that is its origin.
So how can I get the "new" x and y coordinates of the 4 points after a rotation?
[UPDATE]
alt text http://img25.imageshack.us/img25/8676/shaperotationaltransfor.jpg
I have found a way to find the top-left coordinates after a rotation (as you can see from the new image) by adding the OffsetX and OffsetY from the rotation to the starting X and Y coordinates.
But I'm now having trouble figuring out the rest of the coordinates (the other 3).
With this rotated shape, how can I figure out the x and y coordinates of the remaining 3 corners?
[EDIT]
The points in the 2nd image ARE NOT ACCURATE AND EXACT POINTS. I made the points up with estimates in my head.
[UPDATE] Solution:
First of all, I would like to thank Jason S for that lengthy and Very informative post in which he describes the mathematics behind the whole process; I certainly learned a lot by reading your post and trying out the values.
But I have now found a code snippet (thanks to EugeneZ's mention of TransformBounds) that does exactly what I want:
public Rect GetBounds(FrameworkElement of, FrameworkElement from)
{
// Might throw an exception if of and from are not in the same visual tree
GeneralTransform transform = of.TransformToVisual(from);
return transform.TransformBounds(new Rect(0, 0, of.ActualWidth, of.ActualHeight));
}
Reference: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/86350f19-6457-470e-bde9-66e8970f7059/
If I understand your question right:
given:
shape has corner (x1,y1), center (xc,yc)
rotated shape has corner (x1',y1') after being rotated about center
desired:
how to map any point of the shape (x,y) -> (x',y') by that same rotation
Here's the relevant equations:
(x'-xc) = Kc*(x-xc) - Ks*(y-yc)
(y'-yc) = Ks*(x-xc) + Kc*(y-yc)
where Kc=cos(theta) and Ks=sin(theta) and theta is the angle of counterclockwise rotation. (to verify: if theta=0 this leaves the coordinates unchanged, otherwise if xc=yc=0, it maps (1,0) to (cos(theta),sin(theta)) and (0,1) to (-sin(theta), cos(theta)) . Caveat: this is for coordinate systems where (x,y)=(1,1) is in the upper right quadrant. For yours where it's in the lower right quadrant, theta would be the angle of clockwise rotation rather than counterclockwise rotation.)
If you know the coordinates of your rectangle aligned with the x-y axes, xc would just be the average of the two x-coordinates and yc would just be the average of the two y-coordinates. (in your situation, it's xc=75,yc=85.)
If you know theta, you now have enough information to calculate the new coordinates.
If you don't know theta, you can solve for Kc, Ks. Here's the relevant calculations for your example:
(62-75) = Kc*(50-75) - Ks*(50-85)
(40-85) = Ks*(50-75) + Kc*(50-85)
-13 = -25*Kc + 35*Ks = -25*Kc + 35*Ks
-45 = -25*Ks - 35*Kc = -35*Kc - 25*Ks
which is a system of linear equations that can be solved (exercise for the reader: in MATLAB it's:
[-25 35;-35 -25]\[-13;-45]
to yield, in this case, Kc=1.027, Ks=0.3622 which does NOT make sense (K2 = Kc2 + Ks2 is supposed to equal 1 for a pure rotation; in this case it's K = 1.089) so it's not a pure rotation about the rectangle center, which is what your drawing indicates. Nor does it seem to be a pure rotation about the origin. To check, compare distances from the center of rotation before and after the rotation using the Pythagorean theorem, d2 = deltax2 + deltay2. (for rotation about xc=75,yc=85, distance before is 43.01, distance after is 46.84, the ratio is K=1.089; for rotation about the origin, distance before is 70.71, distance after is 73.78, ratio is 1.043. I could believe ratios of 1.01 or less would arise from coordinate rounding to integers, but this is clearly larger than a roundoff error)
So there's some missing information here. How did you get the numbers (62,40)?
That's the basic gist of the math behind rotations, however.
edit: aha, I didn't realize they were estimates. (pretty close to being realistic, though!)
I use this method:
Point newPoint = rotateTransform.Transform(new Point(oldX, oldY));
where rotateTransform is the instance on which I work and set Angle...etc.
Look at GeneralTransform.TransformBounds() method.
I'm not sure, but is this what you're looking for - rotation of a point in Cartesian coordinate system:
link
You can use Transform.Transform() method on your Point with the same transformations to get a new point to which these transformations were applied.