2

I am implementing a map-like interface for a personal project, in Javascript with HTML5 canvas, and I am mostly looking for ideas on how I could properly tessellate all 2D polygon sides with equal-length rectangles per side. Before explaining further, here are two actual screenshots of the existing interface:

Screenshot
(source: mavrosxristoforos.com)

As you can see, there are "n" rectangles on each of the polygon sides, with length equal to "side's length" divided by "n", and width their length divided by 2. The number of rectangles is user-set. The actual data I have is: the polygon corner coordinates and the number of rectangles. The sides are always populated clockwise.

At the moment, the pseudocode for how they are drawn, looks like this:

RECT_LENGTH = polygon_side_length / count_of_rectangles;
i = first_corner_of_the_polygon_side;
for ( j = 0; j < count_of_rectangles; j++) {
    move pen to i;
    point1 = i + RECT_LENGTH * right_angle_on_polygon_side_slope;
    line to point1;
    point2 = point1 - RECT_LENGTH * polygon_side_slope;
    line to point2;
    i += RECT_LENGTH * polygon_side_slope;
    line to i;
}

It is pretty obvious from the code, that it doesn't take into consideration anything other than the polygon side slope, which is the angle from the horizontal axis, measured in -π (pi) to +π, calculated from the two corner coordinates. There are mainly three appearance problems in these screenshots:

  1. In the upper screenshot, on the left, the big rectangle goes out of the polygon side.
  2. In the upper screenshot, on the bottom right, the rectangles overlap (also on other corners, but that particular one looks completely unnatural).
  3. In the lower screenshot, on the top corner, both sides' rectangles get out of the original polygon.

As a solution, I thought that I could search for a line segment intersection between the current line being drawn and the polygon sides, as well as the previous rectangle, but that doesn't feel right, and it would perform quite slow.

As already mentioned, any idea is welcome. I am not a native English speaker, so please feel free to correct me on my English.

Thank you for your time!

EDIT: I wouldn't mind it if the last rectangle became a trapezoid, just to completely cover the polygon side.

Community
  • 1
  • 1
mavrosxristoforos
  • 3,573
  • 2
  • 25
  • 40
  • May I ask if you have an working demo of this? – jonathancardoso Mar 31 '13 at 23:33
  • You mean with the fixed suggestion below? As mentioned in my question, these are real screenshots. So, I do have it working, although it's on localhost. – mavrosxristoforos Apr 01 '13 at 07:22
  • Well, while I did appreciate the answer below, I couldn't implement it, because I understood after this that what I want is to turn the last rectangle to a trapezoid, to be able to cover as much space of the polygon as possible. But I believe that saastn's suggestion is easy to implement. – mavrosxristoforos Apr 02 '13 at 09:13

1 Answers1

1

Since you're using rectangles you just can cover right-angled areas. So you have to leave some area of polygons uncovered. You have to reduce the actual length of edges like this:

enter image description here

In this solution you can reduce length of edges just form heads which meet an acute angle. With Alpha as the inner angle of corner, the reduction amount would be Rectangle.Width / Tan(Alpha). It keeps rectangles inside polygon but wont solve the overlap problem.

To prevent rectangles from overlapping you have to leave more area uncovered:

enter image description here

To do this you have to reduce the length of edge form both heads by Rectangle.Width / Tan(Alpha / 2) (Alpha may differ at each corner).

But all of these wont help since width of rectangle is unknown. In fact width of rectangle is calculated by length of edge itself, and we are using it to calculate the length of edge!!

So we have a mathematical problem here:

Known:

L1: actual length of edge
N: number of divisions
Alpha & Beta: half of inner angle of head corners

Unknown:

L2: reduced length of edge
W: width of rectangles

We can form two equations:

(1): L2 = 2 * N * W
(2): L2 = L1 - (W / Tan(Alpha) - (W / Tan(Beta)

By solving them we can find W:

W = L1 / (2 * N + Cot(Alpha) + Cot(Beta))

All these are true in convex polygons. If either head corners of edge are concave you can replace their inner angle with Pi / 2 to prevent reduction from those corners. Please recheck everything! Considering your lovely UI, I suppose you can handle trigonometric calculations for finding start and end point of rectangles.

saastn
  • 5,717
  • 8
  • 47
  • 78
  • Thanks for your good words and good answer, with images. You are right on everything you mentioned, and that would probably solve the rectangles going out of the polygon area. I guess it would need some pre-calculated math to be quick enough on real-time, but it is a good idea. I'm going to wait a little to see if anyone comes up with an idea to solve overlapping, because that is a big problem, too, but if no-one appears, I will give you your reputation for a good answer. Thanks again. – mavrosxristoforos Feb 24 '13 at 19:42
  • @mavrosxristoforos: Apparently I wasn't clear enough, but using bisectors solves overlapping problem. By the way, if you want to edit polygon real-time, no pre-calculation could be done. Because all of calculations are based on geometry of polygon. – saastn Feb 24 '13 at 20:28
  • Thanks for writing again. Well, I'm probably the one not being clear enough. For the record, the polygons are not editable on real-time. They are constant. The user input is the number of the rectangles per polygon side. By using bisectors I can solve the overlapping problem. But I am mostly looking for a way to cover the whole area, rather than leaving bigger spaces from the edges. To get a better idea, think of how a block of streets is covered by houses. The difference with that is that I don't want to cover the whole polygon, rather than just the sides. Thanks again for the help. – mavrosxristoforos Feb 24 '13 at 21:45
  • Your answer is correct, if I want to always use rectangles to fill the polygon side. Although, your answer gave me the idea to actually find what I would like to see, which is a trapezoid as the first and last shape in each polygon side. The idea hit me when I was thinking the bisectors you mentioned. So, I'm going to turn the first and last rectangle in each side a trapezoid, which will touch each other on the bisector of the angle. THANKS!! – mavrosxristoforos Feb 25 '13 at 01:08