What is the logic behind calculating diagonals on a chessboard? - logic

Given the position of a Bishop on an 8 * 8 chessboard, the task is to count the total number of squares that can be visited by the Bishop in one move. The position of the Bishop is denoted using row and column number of the chessboard.
Examples:
Input: Row = 4, Column = 4
Output: 13
Input: Row = 1, Column = 1
Output: 7
Approach: In the game of chess, a Bishop can only move diagonally and there is no restriction in distance for each move.
So, We can also say that Bishop can move in four ways i.e. diagonally top left, top right, bottom left and bottom right from current position.
We can calculate the numbers of squares visited in each move by:
Total squares visited in Top Left move = Math.min(r, c) – 1
Total squares visited in Top Right move = Math.min(r, 9 – c) – 1
Total squares visited in Bottom Left move = 8 – Math.max(r, 9 – c)
Total squares visited in Bottom Right move = 8 – Math.max(r, c)
where, r and c are the coordinates of the current position of the Bishop on the chessboard.
Guys I cannot figure out the logic behind the above diagonal calculations. Please help me find out that by what logic the diagonals are calculated above ??? I JUST NEED THE LOGIC. No code required.
( Also If you can help with the basic behind logic of similar kinds of chess problems or matrix it would be fantastic)
Chessboard image for reference

The top-left distance to the edge of the board is indeed min(r, c) - 1. Given that the bishop starts on rank r, it can move up no more than r - 1 ranks before landing on the first rank. It may hit the first file before that if c < r, in which case it will only be able to move c - 1 squares. For example if the bishop starts at r = 5 and c = 4, it will be able to move three squares, not four. Thus the top-left formula is min(r - 1, c - 1), which can be refactored to min(r, c) - 1.
Similarly, when heading towards the bottom-left corner, the rank increases while the file decreases. The bishop can move at most 8 - r ranks and at most c - 1 files, so the bottom-left formula is min(8 - r, c - 1). That can be refactored to 8 – max(r, 9 – c), although this expression seems more convoluted.

To count elements in the left-top and right-bottom sides of the diagonal (in which Bishop is placed), the following formula is enough:
n-abs(r-c)-1, where n is the size of the board e.g. n=8 in the above case.
So three (instead of four) formulae can give all the cells that Bishop can visit diagonally:
[8-abs(r-c)-1] + [Math.min(r, 9 – c) – 1] + [8 – Math.max(r, 9 – c)]

simply apply this formula for any directions: distance = max(abs(x1 - x2), abs(y1 - y2))

Related

Maximum possible number of rectangles that can be crossed with a single straight line

I found this challenge problem which states the following :
Suppose that there are n rectangles on the XY plane. Write a program to calculate the maximum possible number of rectangles that can be crossed with a single straight line drawn on this plane.
I have been brainstorming for quite a time but couldn't find any solution.
Maybe at some stage, we use dynamic programming steps but couldn't figure out how to start.
Here is a sketch of an O(n^2 log n) solution.
First, the preliminaries shared with other answers.
When we have a line passing through some rectangles, we can translate it to any of the two sides until it passes through a corner of some rectangle.
After that, we fix that corner as the center of rotation and rotate the line to any of the two sides until it passes through another corner.
During the whole process, all points of intersection between our line and rectangle sides stayed on these sides, so the number of intersections stayed the same, as did the number of rectangles crossed by the line.
As a result, we can consider only lines which pass through two rectangle corners, which is capped by O(n^2), and is a welcome improvement compared to the infinite space of arbitrary lines.
So, how do we efficiently check all these lines?
First, let us have an outer loop which fixes one point A and then considers all lines passing through A.
There are O(n) choices of A.
Now, we have one point A fixed, and want to consider all lines AB passing through all other corners B.
In order to do that, first sort all other corners B according to the polar angle of AB, or, in other words, angle between axis Ox and vector AB.
Angles are measured from -PI to +PI or from 0 to 2 PI or otherwise, the point in which we cut the circle to sort angles can be arbitrary.
The sorting is done in O(n log n).
Now, we have points B1, B2, ..., Bk sorted by the polar angle around point A (their number k is something like 4n-4, all corners of all rectangles except the one where point A is a corner).
First, look at the line AB1 and count the number of rectangles crossed by that line in O(n).
After that, consider rotating AB1 to AB2, then AB2 to AB3, all the way to ABk.
The events which happen during the rotation are as follows:
When we rotate to ABi, and Bi is the first corner of some rectangle in our order, the number of rectangles crossed increases by 1 as soon as the rotating line hits Bi.
When we rotate to ABj, and Bj is the last corner of some rectangle in our order, the number of rectangles crossed decreases by 1 as soon as the line rotates past Bj.
Which corners are first and last can be established with some O(n) preprocessing, after the sort, but before considering the ordered events.
In short, we can rotate to the next such event and update the number of rectangles crossed in O(1).
And there are k = O(n) events in total.
What's left to do is to track the global maximum of this quantity throughout the whole algorithm.
The answer is just this maximum.
The whole algorithm runs in O(n * (n log n + n + n)), which is O(n^2 log n), just as advertised.
Solution
In the space of all lines in the graph, the lines which pass by a corner are exactly the ones where the number or intersections is about to decrease. In other words, they each form a local maximum.
And for every line which passes by at least one corner, there exist an associated line that passes by two corners that has the same number of intersections.
The conclusion is that we only need to check the lines formed by two rectangle corners as they form a set that fully represents the local maxima of our problem. From those we pick the one which has the most intersections.
Time complexity
This solution first needs to recovers all lines that pass by two corners. The number of such line is O(n^2).
We then need to count the number of intersections between a given line and a rectangle. This can obviously be done in O(n) by comparing to each rectangles.
There might be a more efficient way to proceed, but we know that this algorithm is then at most O(n^3).
Python3 implementation
Here is a Python implementation of this algorithm. I oriented it more toward readability than efficiency, but it does exactly what the above defines.
def get_best_line(rectangles):
"""
Given a set of rectangles, return a line which intersects the most rectangles.
"""
# Recover all corners from all rectangles
corners = set()
for rectangle in rectangles:
corners |= set(rectangle.corners)
corners = list(corners)
# Recover all lines passing by two corners
lines = get_all_lines(corners)
# Return the one which has the highest number of intersections with rectangles
return max(
((line, count_intersections(rectangles, line)) for line in lines),
key=lambda x: x[1])
This implementation uses the following helpers.
def get_all_lines(points):
"""
Return a generator providing all lines generated
by a combination of two points out of 'points'
"""
for i in range(len(points)):
for j in range(i, len(points)):
yield Line(points[i], points[j])
def count_intersections(rectangles, line):
"""
Return the number of intersections with rectangles
"""
count = 0
for rectangle in rectangles:
if line in rectangle:
count += 1
return count
And here are the class definition that serve as data structure for rectangles and lines.
import itertools
from decimal import Decimal
class Rectangle:
def __init__(self, x_range, y_range):
"""
a rectangle is defined as a range in x and a range in y.
By example, the rectangle (0, 0), (0, 1), (1, 0), (1, 1) is given by
Rectangle((0, 1), (0, 1))
"""
self.x_range = sorted(x_range)
self.y_range = sorted(y_range)
def __contains__(self, line):
"""
Return whether 'line' intersects the rectangle.
To do so we check if the line intersects one of the diagonals of the rectangle
"""
c1, c2, c3, c4 = self.corners
x1 = line.intersect(Line(c1, c4))
x2 = line.intersect(Line(c2, c3))
if x1 is True or x2 is True \
or x1 is not None and self.x_range[0] <= x1 <= self.x_range[1] \
or x2 is not None and self.x_range[0] <= x2 <= self.x_range[1]:
return True
else:
return False
#property
def corners(self):
"""Return the corners of the rectangle sorted in dictionary order"""
return sorted(itertools.product(self.x_range, self.y_range))
class Line:
def __init__(self, point1, point2):
"""A line is defined by two points in the graph"""
x1, y1 = Decimal(point1[0]), Decimal(point1[1])
x2, y2 = Decimal(point2[0]), Decimal(point2[1])
self.point1 = (x1, y1)
self.point2 = (x2, y2)
def __str__(self):
"""Allows to print the equation of the line"""
if self.slope == float('inf'):
return "y = {}".format(self.point1[0])
else:
return "y = {} * x + {}".format(round(self.slope, 2), round(self.origin, 2))
#property
def slope(self):
"""Return the slope of the line, returning inf if it is a vertical line"""
x1, y1, x2, y2 = *self.point1, *self.point2
return (y2 - y1) / (x2 - x1) if x1 != x2 else float('inf')
#property
def origin(self):
"""Return the origin of the line, returning None if it is a vertical line"""
x, y = self.point1
return y - x * self.slope if self.slope != float('inf') else None
def intersect(self, other):
"""
Checks if two lines intersect.
Case where they intersect: return the x coordinate of the intersection
Case where they do not intersect: return None
Case where they are superposed: return True
"""
if self.slope == other.slope:
if self.origin != other.origin:
return None
else:
return True
elif self.slope == float('inf'):
return self.point1[0]
elif other.slope == float('inf'):
return other.point1[0]
elif self.slope == 0:
return other.slope * self.origin + other.origin
elif other.slope == 0:
return self.slope * other.origin + self.origin
else:
return (other.origin - self.origin) / (self.slope - other.slope)
Example
Here is a working example of the above code.
rectangles = [
Rectangle([0.5, 1], [0, 1]),
Rectangle([0, 1], [1, 2]),
Rectangle([0, 1], [2, 3]),
Rectangle([2, 4], [2, 3]),
]
# Which represents the following rectangles (not quite to scale)
#
# *
# *
#
# ** **
# ** **
#
# **
# **
We can clearly see that an optimal solution should find a line that passes by three rectangles and that is indeed what it outputs.
print('{} with {} intersections'.format(*get_best_line(rectangles)))
# prints: y = 0.50 * x + -5.00 with 3 intersections
(Edit of my earlier answer that considered rotating the plane.)
Here's sketch of the O(n^2) algorithm, which combines Gassa's idea with Evgeny Kluev's reference to dual line arrangements as sorted angular sequences.
We start out with a doubly connected edge list or similar structure, allowing us to split an edge in O(1) time, and a method to traverse the faces we create as we populate a 2-dimensional plane. For simplicity, let's use just three of the twelve corners on the rectangles below:
9| (5,9)___(7,9)
8| | |
7| (4,6)| |
6| ___C | |
5| | | | |
4| |___| | |
3| ___ |___|(7,3)
2| | | B (5,3)
1|A|___|(1,1)
|_ _ _ _ _ _ _ _
1 2 3 4 5 6 7
We insert the three points (corners) in the dual plane according to the following transformation:
point p => line p* as a*p_x - p_y
line l as ax + b => point l* as (a, -b)
Let's enter the points in order A, B, C. We first enter A => y = x - 1. Since there is only one edge so far, we insert B => y = 5x - 3, which creates the vertex, (1/2, -1/2) and splits our edge. (One elegant aspect of this solution is that each vertex (point) in the dual plane is actually the dual point of the line passing through the rectangles' corners. Observe 1 = 1/2*1 + 1/2 and 3 = 1/2*5 + 1/2, points (1,1) and (5,3).)
Entering the last point, C => y = 4x - 6, we now look for the leftmost face (could be an incomplete face) where it will intersect. This search is O(n) time since we have to try each face. We find and create the vertex (-3, -18), splitting the lower edge of 5x - 3 and traverse up the edges to split the right half of x - 1 at vertex (5/3, 2/3). Each insertion has O(n) time since we must first find the leftmost face, then traverse each face to split edges and mark the vertices (intersection points for the line).
In the dual plane we now have:
After constructing the line arrangement, we begin our iteration on our three example points (rectangle corners). Part of the magic in reconstructing a sorted angular sequence in relation to one point is partitioning the angles (each corresponding with an ordered line intersection in the dual plane) into those corresponding with a point on the right (with a greater x-coordinate) and those on the left and concatenating the two sequences to get an ordered sequence from -90 deg to -270 degrees. (The points on the right transform to lines with positive slopes in relation to the fixed point; the ones on left, with negative slopes. Rotate your sevice/screen clockwise until the line for (C*) 4x - 6 becomes horizontal and you'll see that B* now has a positive slope and A* negative.)
Why does it work? If a point p in the original plane is transformed into a line p* in the dual plane, then traversing that dual line from left to right corresponds with rotating a line around p in the original plane that also passes through p. The dual line marks all the slopes of this rotating line by the x-coordinate from negative infinity (vertical) to zero (horizontal) to infinity (vertical again).
(Let's summarize the rectangle-count-logic, updating the count_array for the current rectangle while iterating through the angular sequence: if it's 1, increment the current intersection count; if it's 4 and the line is not directly on a corner, set it to 0 and decrement the current intersection count.)
Pick A, lookup A*
=> x - 1.
Obtain the concatenated sequence by traversing the edges in O(n)
=> [(B*) 5x - 3, (C*) 4x - 6] ++ [No points left of A]
Initialise an empty counter array, count_array of length n-1
Initialise a pointer, ptr, to track rectangle corners passed in
the opposite direction of the current vector.
Iterate:
vertex (1/2, -1/2)
=> line y = 1/2x + 1/2 (AB)
perform rectangle-count-logic
if the slope is positive (1/2 is positive):
while the point at ptr is higher than the line:
perform rectangle-count-logic
else if the slope is negative:
while the point at ptr is lower than the line:
perform rectangle-count-logic
=> ptr passes through the rest of the points up to the corner
across from C, so intersection count is unchanged
vertex (5/3, 2/3)
=> line y = 5/3x - 2/3 (AC)
We can see that (5,9) is above the line through AC (y = 5/3x - 2/3), which means at this point we would have counted the intersection with the rightmost rectangle and not yet reset the count for it, totaling 3 rectangles for this line.
We can also see in the graph of the dual plane, the other angular sequences:
for point B => B* => 5x - 3: [No points right of B] ++ [(C*) 4x - 6, (A*) x - 1]
for point C => C* => 4x - 6: [(B*) 5x - 3] ++ [(A*) x - 1]
(note that we start at -90 deg up to -270 deg)
How about the following algorithm:
RES = 0 // maximum number of intersections
CORNERS[] // all rectangles corners listed as (x, y) points
for A in CORNERS
for B in CORNERS // optimization: starting from corner next to A
RES = max(RES, CountIntersectionsWithLine(A.x, A.y, B.x, B.y))
return RES
In other words, start drawing lines from each rectangle corner to each other rectangle corner and find the maximum number of intersections. As suggested by #weston, we can avoid calculating same line twice by starting inner loop from the corner next to A.
If you consider a rotating line at angle Θ and if you project all rectangles onto this line, you obtain N line segments. The maximum number of rectangles crossed by a perpendicular to this line is easily obtained by sorting the endpoints by increasing abscissa and keeping a count of the intervals met from left to right (keep a trace of whether an endpoint is a start or an end). This is shown in green.
Now two rectangles are intersected by all the lines at an angle comprised between the two internal tangents [example in red], so that all "event" angles to be considered (i.e. all angles for which a change of count can be observed) are these N(N-1) angles.
Then the brute force resolution scheme is
for all limit angles (O(N²) of them),
project the rectangles on the rotating line (O(N) operations),
count the overlaps and keep the largest (O(N Log N) to sort, then O(N) to count).
This takes in total O(N³Log N) operations.
Assuming that the sorts needn't be re-done in full for every angle if we can do them incrementally, we can hope for a complexity lowered to O(N³). This needs to be checked.
Note:
The solutions that restrict the lines to pass through the corner of one rectangle are wrong. If you draw wedges from the four corners of a rectangle to the whole extent of another, there will remain empty space in which can lie a whole rectangle that won't be touched, even though there exists a line through the three of them.
We can have an O(n^2 (log n + m)) dynamic-programming method by adapting Andriy Berestovskyy's idea of iterating over the corners slightly to insert the relationship of the current corner vis a vis all the other rectangles into an interval tree for each of our 4n iteration cycles.
A new tree will be created for the corner we are trying. For each rectangle's four corners we'll iterate over each of the other rectangles. What we'll insert will be the angles marking the arc the paired-rectangle's farthest corners create in relation to the current fixed corner.
In the example directly below, for the fixed lower rectangle's corner R when inserting the record for the middle rectangle, we would insert the angles marking the arc from p2 to p1 in relation to R (about (37 deg, 58 deg)). Then when we check the high rectangle in relation to R, we'll insert the interval of angles marking the arc from p4 to p3 in relation to R (about (50 deg, 62 deg)).
When we insert the next arc record, we'll check it against all intersecting intervals and keep a record of the most intersections.
(Note that because any arc on a 360 degree circle for our purpose has a counterpart rotated 180 degrees, we may need to make an arbitrary cutoff (any alternative insights would be welcome). For example, this means that an arc from 45 degrees to 315 degrees would split into two: [0, 45] and [135, 180]. Any non-split arc could only intersect with one or the other but either way, we may need an extra hash to make sure rectangles are not double-counted.)

Geometry matrix colinearity prove

Let's say I have this matrix with n=4 and m=5
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
Let's say I have a diagonal from the (1,2) point to the (4,5) point. And I have a point P(3,4). How can I check in my algorithm that P is on the diagonal?
TL;DR
Instead of an n-by-m matrix, think about it like a x-y grid. You can get the equation of a line on that grid, and once you have that equation, you put the x coordinate of the point you are interested in checking into your equation. If the y value you calculate from the equation matches the y coordinate of the point you are checking, the point lies on the line.
But How Do I Maths?
First some quick terminology. We have 3 points of interest in this case - the two points that define the line (or "diagonal", as the OP calls it), and the one point that we want to check. I'm going to designate the coordinates of the "diagonal" points with the numbers 1 and 2, and the point we want to check with the letter i. Additionally, for the math we need to do later, I need to treat the horizontal and vertical coordinates of the points separately, and I'll use your n-by-m convention to do so. So when I write n1 in an equation below, that is the n coordinate of the first point used to define the diagonal (so the 1 part of the point (1,2) that you give in your example).
What we are looking for is the equation of a line on our grid. This equation will have the form n = (slope) * m + (intercept).
Okay, now that we have the definitions taken care of, we can write the equations. The first step to solving the problem is finding the slope of your line. This will be the change in the vertical coordinate divided by the change in the horizontal component between the two points that define the line (so (n2 - n1) / (m2 - m1)). Using the values from your example, this will be (4 - 1) / (5 - 2) = 3 / 3 = 1. Note that since you are doing a division here, it is possible that your answer will not be a whole number, so make sure you keep that in mind when declaring your variables in whatever programming language you end up using - unintentional rounding in this step can really mess things up later.
Once we have our slope, the next step is calculating our intercept. We can do this by plugging our slope and the m and n coordinates into the equation for the line we are trying to get. So we start with the equation n1 = (slope) * m1 + (intercept). We can rearrange this equation to (intercept) = n1 - (slope) * m1. Plugging in the values from our example, we get (intercept) = 1 - (1 * 2) = -1.
So now we have the general equation of our line, which for our example is n = (1) * m + (-1).
Now that we have the (slope) and (intercept), we can plug in the coordinates of any point we want to check and see if the numbers match up. Our example point has a m coordinate of 4, so we can plug that into our equation.
n = (1) * (4) + (-1) = 3
Since the n coordinate we calculated using our equation matches the n coordinate of our point in our example, we can say that the sample point DOES fall on the line.
Suppose we wanted to also check to see if the point (2,5) was also on the line. When we plug that point's m coordinate into our equation, we get...
n = (1) * (5) + (-1) = 4
Since the n coordinate we calculated with our equation (4) doesn't match the n coordinate of the point we were checking (2), we know this point DOES NOT fall on the line.

What is the area covered by a Random walk in a 2D grid?

I am a biologist and applying for a job, for which I need to solve this question. It is an open book test, where the internet and any other resources are fair game. Here's the question - I'm stuck on how to approach it and would appreciate pointers. My intuition is posted underneath.
Background
Your neighbor is a farmer with two cows, Clarabelle and Bernadette. Each cow has its own square pen that is 11m on a side (see first figure). The farmer is heading out of town for a trip and plans to leave the cows in their respective pens, which are completely filled with grass to start. The cows begin in the center of the pen, and will slowly move around the pen eating the grass. They move around the pen very slowly, always pausing to eat or rest after every step. If you divide the pen into 1m squares, the cows can move one square in any direction each step (like a king on a chess board), as shown in the second figure.
After each move, the cow will spend 20 minutes in the new square eating grass, if it is available. Once the grass in a square is eaten, it is gone forever. If the cow moves to a square whose grass was already eaten, then the cow will spend 20 minutes resting in that square. After 20 minutes, whether resting or eating, the cow moves to another square. If a cow is in a square adjacent to the fence, she will never try to move in the direction of the fence. The cows never stay in the same square twice in a row -- they always move to a different one after resting or eating. The first figure shows an example of what a pen might look like after some hours, with the brown spots indicating squares that have been grazed.
The first cow, Clarabelle, has no preference for direction when she moves. She is equally likely to move in any direction at all times. Let p be the probability that she moves in a direction, as shown in the first figure below.
The second cow, Bernadette, prefers to move towards squares with grass. She is twice as likely to move towards a space that has grass as she is towards a space that she has already eaten, as shown in the second figure below.
Questions
If the farmer returns after 48 hours, what percentage of the grass in her pen do you expect Clarabelle to have eaten?
How long do you expect it will take for Bernadette to eat 50% of the grass in her pen?
Suppose that if either of the cows go 24 hours without eating any grass, she will die. Which cow is expected to survive longer?
My intuition
This appears to be modeling a random walk through a 2 dimensional grid. I can for instance figure out the probability of being at a particular node in the grid, after a given time. But I'm not sure how to think about the area covered by the cow as it walks through. Would appreciate any insights.
Edit: The final aim here would be for me to write some sort of a program for this. This isn't a purely mathematics question and thus the post here.
Here is a way of computing the probabilities (for Clarabelle):
Start with a grid of 0, except 1 on the (6, 6) cell, this is your probability grid for time t = 0.
At time t + 1, the probability p(x, y, t + 1) of being on cell (x, y) is given by: p(x, y, t + 1) = p1 * p(x + 1, y, t) + p2 * p(x + 1, y - 1, t) + ... (you have eight term in the sum).
Note that all the pi are not equals: the probability can be 1/3 (corner), 1/5 (edge), or 1/8 (any other cell).
You can dynamically update your grid by running this for each step t = 0 to t = 144 (48h).
If you want to know the probability for a cell already been eaten, it is simply 1 - Pn where Pn if the probability of the cell never been visited, which is:
(1 - p(x, y, 0)) * (1 - p(x, y, 1)) * (1 - p(x, y, 2)) * ...
Here is a code that compute these probability using numpy in Python (basically, this is considering a Markov Chain where the state X is the set of all cells |X| = 121, and the transition matrix T = {Tij} where Tij is the probability of moving from i to j):
GridSize = 11
TranSize = GridSize * GridSize
T_Matrix = np.zeros((TranSize, TranSize), dtype = float)
for u in range(T_Matrix.shape[0]):
for v in range(T_Matrix.shape[1]):
ux, uy = u % GridSize, u // GridSize
vx, vy = v % GridSize, v // GridSize
if u == v or abs(ux - vx) > 1 or abs(uy - vy) > 1:
p = 0
elif (ux == 0 or ux == 10) and (uy == 0 or uy == 10):
p = 1/3
elif ux == 0 or ux == 10 or uy == 10 or uy == 0:
p = 0.2
else:
p = 0.125
T_Matrix[u, v] = p
pxy = np.zeros((TranSize, ), dtype = float)
pxy[11 * 5 + 5] = 1
eat = 1 - pxy
for _ in range(144):
pxy = pxy.dot(T_Matrix)
eat *= (1 - pxy)
print((1 - eat).reshape((GridSize, GridSize)))
The algorithm for Bernadette is a bit more complex because your p1, p2, ... are probabilistic, so you get two terms for each adjacent cell.
Once you have all these probabilities, you can easily find what you want.
There are two ways to approach such problems: analytically or via simulation.
If you'll simulate the process using a Monte-Carlo based method, you can easily find the answers by averaging the results of many trails.
I would assume that this is what you're expected to do, unless you were guided otherwise.

Looking for a non "brute force" algorithm to remove intersecting areas of a collection of Rects

I have an n-sized collection of Rects, most of which intersect each other. I'd like to remove the intersections and reduce the intersecting Rects into smaller non-intersecting rects.
I could easily brute force a solution, but I'm looking for an efficient algorithm.
Here's a visualization:
Original:
Processed:
Ideally the method signature would look like this:
public static List<RectF> resolveIntersection(List<RectF> rects);
the output would be greater or equal to the input, where the output resolves the above visual representation.
Sweepline algoithms are good at processing intersections in 2D universes. I mean consider an horizontal line moving down from a rectangle edge to the next rectangle edge. The line hits a number of rectangles, forming the so-called active lists. The active list is kept updated at every move.
By studying the ranges of abscissas along the horizontal line, you can detect the overlaps.
A careful study of all configurations should allow you to split the rectangles the way you want in a single sweep, with lower complexity than brute force (closer to N^1.5 than to N^2).
this is a problem I solved in the past. The first thing it to sort the rectangles using the x or y value of one of the edges. Lets say you order in the y-direction and use the top edge. The topmost rectangle in your example is first in sorted order. For each rectangle you know its size in the y-direction.
Now, for each entry (call it the the current entry, it corresponds to a rectangle)in the sorted list you search forward through the list until you reach an entry greater than the current entry + the corresponding rectangle size. (call it the stopping entry)
Any entries in the sorted list between the current entry and this stopping entry will be potential intersections. Simply check if the rectangles x-ranges intersect.
When choosing to sort in the x or y direction, it will be better to choose the dimension that is larger as this will imply fewer intersection on average so less checking.
Here is an example. Rectangles are defined as R(x1,x2,y1,y2) where x1 is the left side, x2 is right side, y1 is top and y2 is bottom
rectangle 1 (1,5,0,4)
rectangle 2 (7,9,6,8)
rectangle 3 (2,4,2,3)
rectangle 4 (3,6,3,7)
rectangle 5 (3,6,9,15)
sort according to y1 to give
# y1 size
rectangle 1 0 4
rectangle 3 2 3
rectangle 4 3 4
rectangle 2 6 2
rectangle 5 9 6
so, rectangle 1 has y1 + size = 0 + 4 = 4 implying it will potentially intersect rectangle 3 (y1 value = 3 < 4) and rectangle 4 (y1 value = 3 < 4) but not rectangle 2 (y1 value = 6 > 4)...no need to check any rectangels in the list after 2
Rectangle 3 has y2 + size = 2 + 3 = 5 implying it will potentially intersect rectangle 4 (y1 value = 3 < 5) but not recatngle 2 (y1 value = 6 > 5) no need to check any rectangels in the list after 2
Rectangle 4 has y2 + size = 3 + 4 = 7 implying it will potentially intersect rectangle 2 (y1 value = 6 < 7) but not recatngle 5 (y1 value = 9 > 7)
Of course, with large numbers of rectangles you will generally only have to check a fraction of the possible pairs for intersection.
what you're descrbing is the packing problem, have a look at wikipedia
it refers to this article describing an algorithm for packing rectangles in rectangles
this is from the article:
This article describes a fast algorithm to pack a series of rectangles of varying widths and heights into a single enclosing rectangle, with no overlap and in a way that minimizes the amount of wasted space in the enclosing rectangle.

How to get the length of a segment crossing a square?

I have a line, defined by the parameters m, h, where
y = m*x + h
This line goes across a grid (i.e. pixels). For each square (a, b) of the grid (ie the square [a, a+1] x [b, b+1]), I want to determine if the given line crosses this square or not, and if so, what is the length of the segment in the square.
Eventually, I would like to be able to do this with multiple lines at once (ie m and h are vectors, matlab-style), but we can focus on the "simple" case for now.
I figured how to determine if the line crosses the square:
Compute the intersection of the line with the vertical lines x = a and x = a + 1, and the horizontal lines y = b and y = b + 1
Check if 2 of these 4 points are on the square boundaries (ie a <= x < a + 1 and b <= y < b + 1)
If two on these points are on the square, the line crosses it. Then, to compute the length, you simply subtract the two points, and use Pythagorean theorem.
My problem is more on the implementation side: how can I implement that nicely (especially when selecting which 2 points to subtract) ?
Let square be defined by corner points (a,b), (a+1,b), (a,b+1), (a+1,b+1).
Step 1: Check if the line intersects the square...
(a)Substitute each of the coordinates of the 4 corner points, in turn into y - mx - h. If the sign of this evaluation includes both positive and negative terms, go to step b. Otherwise, the line does not intersect the square.
(b)Now there are two sub-cases:
(b1)Case 1: In step (a) you had three points for which y - mx - h evaluated to one sign and the fourth point evaluated to the other sign. Let this 4th point be some (x*,y*). Then the points of intersection are (x*,mx*+h) and ((y*-h)/m,y*).
(b2)Case 2: In step (a) you had two points for which y - mx - h evaluate to one sign and the other two points evaluated to the other sign. Pick any two points that evaluated to the same sign, say (x*,y*) and (x*+1, y*). Then the intersection points are (x*, mx* + h) and (x*+1,m(x*+1) + h).
You would have to consider some degenerate cases where the line touches exactly one of the four corner points and the case where the line lies exactly on one side of the square.
Your proposed method may meet with problems in step (1) when m is 0 (when trying to compute the intersection with y = k).
if m is 0, then it's easy (the line segment length is either 1 or 0, depending on whether b <= h <= b+1).
Otherwise, you can find the intersections with x = a and a+1, say, y_a, y_{a+1} via a substitution. Then, clip y_a and y_{a+1} to between b and b+1 (say, y1 and y2, i.e. y1 = min(b+1, max(b, y_a)) and similarly for y2), and use the proportion abs((y1-y2)/m) * sqrt(m^2+1).
This makes use of the fact that the line segment between x=k and x=k+1 is sqrt(m^2+1), and the difference in y is m, and similarity.
You can do like this:
first find center of square and then find length of diagonal. If the distance from center of square to line is less than length of diagonal then the line will intersect the square. and once you know that line will intersect then you can easily find the intersected line segment. I think you are trying to make weight matrix for Algebraic reconstruction technique. I hope this is correct answer. This was my first answer in stack flow. :)

Resources