InterviewDB Question · Los Angeles

Implement 2D Canvas: Build a Drawing Surface with Shape Rendering and Hit Testing

Question Details

Round 1 Coding

Problem

Implement a 2D canvas abstraction that manages a collection of shapes and handles rendering and hit-testing:

  • add_shape(shape) — add a shape (Circle, Rect, or Line) with id, position, color.
  • move_shape(id, dx, dy) — translate shape by offset.
  • hit_test(x, y) -> str | None —

return the id of the topmost shape at point (x,y), or None.
- render() -> list[str] —

return a list of draw commands in z-order (e.g. ["draw_rect(0,0,10,10,red)", ...]).

python
class Canvas:
    def add_shape(self, shape: Shape) -> None: ...
    def move_shape(self, shape_id: str, dx: int, dy: int) -> None: ...
    def hit_test(self, x: int, y: int) -> str | None: ...
    def render(self) -> list[str]: ...

class Rect(Shape):
    def contains(self, x, y) -> bool:

**return** self.x <= x <= self.x+self.w and self.y <= y <= self.y+self.h
canvas.add_shape(Rect("r1", 0, 0, 10, 10, "red"))
canvas.add_shape(Circle("c1", 5, 5, 4, "blue"))  # overlaps r1 at center
canvas.hit_test(5, 5) -> "c1"   # topmost
canvas.move_shape("c1", 20, 0)
canvas.hit_test(5, 5) -> "r1"

Follow-ups

  1. How do you determine "topmost" — insertion order, z-index property, or both?
  2. Your hit_test is O(n). For a canvas with 10,000 shapes, how do you speed this up (spatial index)?
  3. How would you implement undo/redo for move_shape and add_shape?
  4. Describe how you would serialize the canvas state to JSON and restore it.

Full Details

Round 1 Coding

Problem

Implement a 2D canvas abstraction that manages a collection of shapes and handles rendering and hit-testing:

  • add_shape(shape) — add a shape (Circle, Rect, or Line) with id, position, color.
  • move_shape(id, dx, dy) — translate shape by offset.
  • hit_test(x, y) -> str | None —

return the id of the topmost shape at point (x,y), or None.
- render() -> list[str] —

return a list of draw commands in z-order (e.g. ["draw_rect(0,0,10,10,red)", ...]).

python
class Canvas:
    def add_shape(self, shape: Shape) -> None: ...
    def move_shape(self, shape_id: str, dx: int, dy: int) -> None: ...
    def hit_test(self, x: int, y: int) -> str | None: ...
    def render(self) -> list[str]: ...

class Rect(Shape):
    def contains(self, x, y) -> bool:

**return** self.x <= x <= self.x+self.w and self.y <= y <= self.y+self.h
canvas.add_shape(Rect("r1", 0, 0, 10, 10, "red"))
canvas.add_shape(Circle("c1", 5, 5, 4, "blue"))  # overlaps r1 at center
canvas.hit_test(5, 5) -> "c1"   # topmost
canvas.move_shape("c1", 20, 0)
canvas.hit_test(5, 5) -> "r1"

Follow-ups

  1. How do you determine "topmost" — insertion order, z-index property, or both?
  2. Your hit_test is O(n). For a canvas with 10,000 shapes, how do you speed this up (spatial index)?
  3. How would you implement undo/redo for move_shape and add_shape?
  4. Describe how you would serialize the canvas state to JSON and restore it.

About This Question

This is a reported interview question from a figma interview during the phone round.

It covers the following topics: Coding, Onsite, Phone .