2

I've encountered this problem, and I'd like to know how is possible to solve it in Mathematica:

There's a bar that has a room with a very irregular shape. From every point inside the room it must be possible to see a no smoking sign, so people inside the bar can be always aware of it. Find the minimum number of signs that are needed and place them in room walls in order to satisfy the condition.

For example, I've this room/polygon:

corners = 
  {{0, 0}, {200, 0}, {200, 30}, {160, 50}, {200, 70}, {200, 200}, {100, 200}, 
   {100, 150}, {150, 170}, {140, 80}, {90, 80}, {90, 130}, {40, 130}, {40, 20}}; 
Graphics[{FaceForm[White], EdgeForm[Black], Polygon[corners]}]

Room example

I need to select a list of points of the perimeter of the polygon such that at least one of them is visible from every interior polygon point. How can I achieve this using Mathematica?

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
Jepessen
  • 950
  • 6
  • 16

1 Answers1

0

The following gives an answer to the question although I do not claim it to be a formal answer to the mathematical problem. We start with the corners defining the room:

corners = {{0, 0}, {200, 0}, {200, 30}, {160, 50}, {200, 70}, 
{200, 200}, {100, 200}, {100, 150}, {150, 170}, {140, 80}, 
{90, 80}, {90, 130}, {40, 130}, {40, 20}};

We add {0,0} in order to create a closed line which represents the room walls:

roomwalls = Line[Join[corners, {{0, 0}}]];
RegionPlot@roomwalls;

We add some padding to our region:

paddedbounds = RegionBounds@roomwalls + {{-5, 5}, {-5, 5}};

Next, we create a polygon to represent the bar room and add people inside:

barroom = Polygon@corners;
peopleintheroom = RandomPoint[barroom, 16];

To find the position of the signs we create a Voronoi mesh from the position of each person in such a way that it covers the room:

p1 = Graphics[{Point /@ peopleintheroom, Thick, roomwalls}];
p2 = Graphics[{Red, 
MeshPrimitives[VoronoiMesh[peopleintheroom, paddedbounds], 1]}];
Show[p1, p2]

enter image description here

The position of the no-smoking signs are given by the intersection of the lines of the Voronoi mesh with the room walls:

signs = Rest@
Union@Table[
 RegionIntersection[
  Part[MeshPrimitives[VoronoiMesh[peopleintheroom, paddedbounds], 
    1], i], roomwalls], {i, 1, numberoflines}];

In this case this yields 17 signs:

In[]:=Length@signs
Out[]= 17

We display the walls with the signs:

Show[Graphics@roomwalls, Graphics@Append[{Red, PointSize[.03]}, signs]]

enter image description here

As I said at the beginning I do not claim this to be the optimal solution but I think that at least it can give some idea. The points of the Voronoi mesh are chosen at random, so different choices might give better answers.

Alfonso
  • 64
  • 1
  • It's a nice try, but there are two problems: 1) solution is randomic, not deterministic, so you can have a set or random points that don't cover all the room 2) the number of signs is not minimized. – Jepessen Jun 22 '17 at 08:54
  • 1
    This doesn't solve the problem at all. For instance, Fisk proved the optimal (in this case) has 5 points, but this solution here gives 18! You might as well just place points randomly against the walls. Or at least every vertex. – David G. Stork Jun 22 '17 at 23:58