kstreet13 / mazing

Utilities for making and plotting mazes
Other
4 stars 1 forks source link

Add start and end visual indicators - enhancement #2

Closed dmoul closed 3 years ago

dmoul commented 3 years ago

Fun package!

It would be helpful if there were a way to indicate to the person solving the maze where they should start and end.

For example, the following plots a nice maze and solution, however the start and end point are not obvious without showing the path:

m <- maze(35,100)
p <- solve_maze(m, start = 'left', end = 'right')
plot(m, lwd = 1, walls = TRUE)
lines(p, lwd = 3, col = 2)

This enhancement could be implemented in a number of ways. I can think of two:

  1. Make a break in the wall at the start and end points
  2. Plot user-defined symbols for start and end outside the maze in the right locations (along with (1) if walls are drawn)

To do this with existing functionality I would need to save the maze as an image and then post-process it in an image editor to do (1) and/or (2).

The above is based on mazing version 1.0.2.

kstreet13 commented 3 years ago

Thanks! I agree that this would be helpful! I think your solution (1) would be my preferred method, but I haven't yet found an elegant way to implement it. My best idea so far is to add an argument to the plot method that takes location indicators (like "topleft" and "bottomright") and adds openings in those locations, but there may be more than one wall there, for example if it's a corner, so there's some ambiguity. Any thoughts on how you'd like to have it work?

That said, I think (2) is possible with the current functionality. Would something like this work?

m <- maze(10,10)
p <- find_maze_refpoint(c('bottomleft','topright'), m)

plot(m, walls = TRUE)
points(p, col = 3:2, pch = 16:15)

image

It would take a little adjusting to get them outside the maze, like you describe, but that's also possible:

m <- maze(10,10)
p <- find_maze_refpoint(c('bottomleft','topright'), m)
p[1,] <- p[1,] - c(1,0)
p[2,] <- p[2,] + c(1,0)

plot(m, walls = TRUE)
points(p, col = 3:2, pch = 16:15)

image

Best, Kelly

dmoul commented 3 years ago

Nice solution for (2).

For (1) you could do something like openings and openings_direction:

m <- maze(10,10)
p <- find_maze_refpoint(c('bottomleft','topright'), m)

plot(m, 
  walls = TRUE,
  openings = p, # location inside maze of start and end points
  openings_direction = c("bottom", "top") # direction of opening for start and end points, respectively
                                          # if not specified; default is to create openings at closest point on left and right walls
)

If the user specifies one of the following for openings_direction, you could open both edges of the corner:

The above may be too much investment of your time. Perhaps simpler for you would be to NOT provide default directions and instead require the user to specify the directions when they want openings. That way you don't have to calculate the direction of the nearest walls. IMO this would not be a hardship for users.

--Daniel

kstreet13 commented 3 years ago

Hey @dmoul,

Thanks for the suggestion! I've implemented it almost exactly as you described. The only difference is a shortcut I took for the default openings_direction, when the user doesn't specify one. Rather than calculating directions, it just removes the first available wall out of c("left","right","top","bottom"). Hopefully that's not a very frequent use-case, though, as it can be a little counter-intuitive (ie. deleting interior walls rather than exterior).

I'll submit the new version (1.0.3) to CRAN in a bit, but feel free to check it out and please let me know if anything isn't working! Kelly

dmoul commented 3 years ago

looking good @kstreet13 ! Here are two working examples:

# remotes::install_github("kstreet13/mazing") to get version 1.0.3
library(mazing) 

# Example 1: Rectangular
m3 <- maze(30,50)
s3 <- solve_maze(m3)
p <- find_maze_refpoint(c('bottomleft','topright'), m3)
plot(m3, lwd = 1, walls = TRUE,
     openings = p,
     openings_direction = c("bottom", "top"))
lines(s3, lwd = 3, col = 2)


# Example 2: Circular
mat <- matrix(1, 20, 20)
for(i in 1:nrow(mat)){
  for(j in 1:ncol(mat)){
    if((i-10.5)^2+(j-10.5)^2 > 100){
      mat[i,j] <- 0
    }
  }
}
m4 <- as.maze(mat)
s4 <- solve_maze(m4)
p4 <- s4[c(1, nrow(s4)), ] # first and last points of solution
plot(m4, lwd = 1, walls = TRUE,
     openings = p4)
lines(s4, lwd = 3, col = 2)

Created on 2021-08-29 by the reprex package (v2.0.1)

dmoul commented 3 years ago

Feel free to close this issue, and thanks for implementing this feature.

kstreet13 commented 3 years ago

Awesome, glad it works for you! I've just been leaving it open as a reminder to update the CRAN version (there was an issue with the sysfonts package and now there is a freeze on incoming packages/updates that has delayed that).