Shading in squares crossed by a diagonal
You could do something like this
Manipulate[
DynamicModule[{ptlst, height, length},
{length, height} = Round[pt];
ptlst =
Floor[1 + {height, length} #] & /@
MovingAverage[
Union@Join[Range[0, 1, 1/length], Range[0, 1, 1/height]], 2];
Show[ArrayPlot[SparseArray[Thread[ptlst -> 1]], Mesh -> True,
MeshStyle -> Gray, DataReversed -> True],
Graphics[{Red, Line[{{0, height}, {length, 0}}]}],
PlotRange -> {{-1, 21}, {-1, 21}},
GridLines -> {Range[0, 21], Range[0, 21]},
GridLinesStyle -> LightGray]],
{{pt, {10, 10}}, {1, 1}, {20, 20}, {1, 1}, Locator}
]
Explanation of the code
We're representing the squares in the rectangle by an array of 0's and 1's. We're assuming that the rectangle has dimensions {length, height}
and is aligned with the origin. The array is such that the unit square with lower left corner {k,l}
corresponds to the element at index {l + 1, k + 1}
in the array (the reversal of indices is because ArrayPlot
plots an m
by n
array as a n
by m
rectangle).
The diagonal from {0,0}
to {length, height}
can be parameterized by {length, height} t
where 0<=t<=1
. To find all squares that are intersected by this diagonal, we first calculate the intersection points of the diagonal with the grid, i.e. we find a list of values for t
such that either length t
or height t
is an integer. For two consecutive elements in this list, t0
and t1
, the line segment from {length, height} t0
to {length, height} t1
will lie completely within one unit square. The coordinates of the lower left corner of this square are equal to Floor[{height, length} (t0+t1)/2]
which corresponds to the element at index 1 + Floor[{length, height} (t0+t1)/2]
in the array.
I was trying to answer this question, and i came up with the following related thing.
I was in doubt to post it, but I think is a "curious" way to count the squares that have been split by the diagonal by using image processing:
c[x_, y_] :=
Module[{d = .03},
MorphologicalComponents@ColorNegate@Rasterize@
Graphics[{Black, Table[Rectangle[(1 + d) {i,j}],{i, 0, x - 1}, {j, 0, y - 1}],
White, Thickness[d/4], Line[{{0, 0}, {x + (x - 1) d, y + (y - 1) d}}]}]]
So
c[4, 5] // Colorize
hence you can define:
countDividedSquares[x_, y_] := Max@
Module[{d = .03},
MorphologicalComponents@ColorNegate@Rasterize@
Graphics[{Black, Table[Rectangle[(1 + d) {i,j}], {i, 0, x - 1}, {j, 0, y - 1}],
White, Thickness[d/4], Line[{{0, 0}, {x + (x - 1) d, y + (y - 1) d}}]}]
- x y];
countDividedSquares[4, 5]
(*
-> 8
*)
ListPlot
with Filling
and InterpolationOrder
options:
Manipulate[{length, width} = Round[p];
lctr = Graphics[{Green, PointSize -> .025, Point[{length, width}]}];
rectangle ={Green,Thick,Line[{{0, 0}, {0, width}, {length, width}, {length, 0}, {0, 0}}]};
lst = Transpose[{#, (width/length) #} &@Range[0, length, 1]];
data = {lst, lst /. {x_, y_} :> {x,Floor[y]},
((lst /. {x_Integer, y_} :> {Max[0, x - 1], Ceiling[y]}) // Append[#, Last@lst] &)};
ListPlot[data, InterpolationOrder -> {1, 0, 0},
Joined -> True, AspectRatio -> 1, Axes -> False,
PlotStyle -> {{Thick, Red}, White, White},
Filling -> {3 -> {{1}, {Black, Black}}, 1 -> {{2}, {Black, Black}}},
GridLines -> {Table[i, {i, 0, 20}], Table[i, {i, 0, 20}]},
Method -> {"GridLinesInFront" -> True},
Epilog -> rectangle, PlotRange -> {{0, 20}, {0, 20}},
PlotRangePadding -> .2],
{{p, {2, 3}}, {1, 1}, {20, 20}, {1, 1}, Locator, Appearance -> lctr}]
Snapshots: