plotting algorithm
data visualization
algorithm development
computer graphics
coding techniques

Outline plotting algorithm

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

An outline plotting algorithm turns a filled region into just its boundary. That boundary is what you want when drawing vector edges, simplifying tile maps, or extracting the visible contour of binary data without rendering the interior.

The exact algorithm depends on the source data, but the core idea is stable: inspect each filled element, find where it touches empty space, and emit only those exposed edges. That gives you a clean outline that can be plotted, stroked, or simplified later.

Turning Filled Cells Into Boundary Segments

For grid data, a practical approach is to examine each filled cell and test its four neighbors. If the neighbor on one side is empty or outside the grid, that side belongs to the outline.

This method is easy to reason about and works well for occupancy maps, bitmap masks, and level editors:

python
1from typing import List, Tuple
2
3Segment = Tuple[Tuple[int, int], Tuple[int, int]]
4
5
6def outline_segments(grid: List[List[int]]) -> List[Segment]:
7    rows = len(grid)
8    cols = len(grid[0]) if rows else 0
9    segments: List[Segment] = []
10
11    for r in range(rows):
12        for c in range(cols):
13            if grid[r][c] != 1:
14                continue
15
16            if r == 0 or grid[r - 1][c] == 0:
17                segments.append(((c, r), (c + 1, r)))
18            if c == cols - 1 or grid[r][c + 1] == 0:
19                segments.append(((c + 1, r), (c + 1, r + 1)))
20            if r == rows - 1 or grid[r + 1][c] == 0:
21                segments.append(((c, r + 1), (c + 1, r + 1)))
22            if c == 0 or grid[r][c - 1] == 0:
23                segments.append(((c, r), (c, r + 1)))
24
25    return segments
26
27
28grid = [
29    [0, 1, 1, 0],
30    [1, 1, 1, 0],
31    [0, 1, 0, 0],
32]
33
34for segment in outline_segments(grid):
35    print(segment)

The output is a set of line segments. That is usually enough for plotting, but many applications want connected polylines rather than many independent edges.

Joining Segments Into Paths

Once you have boundary segments, the next step is stitching them into ordered paths. Build an adjacency map from segment endpoints, then walk from one endpoint to the next until the loop closes.

This separation of concerns keeps the implementation understandable. Boundary detection decides which edges are exposed. Path assembly decides how those edges connect. An optional simplification pass removes redundant collinear points before rendering.

If the source data is a continuous scalar field instead of a binary grid, use a contouring algorithm such as marching squares. Marching squares handles thresholded data and produces smoother-looking isolines than direct cell-edge extraction.

Plotting The Result

After extracting boundary segments, you can draw them with any plotting library. The example below uses matplotlib to render the outline:

python
1import matplotlib.pyplot as plt
2
3
4def plot_segments(segments):
5    for (x1, y1), (x2, y2) in segments:
6        plt.plot([x1, x2], [y1, y2], color="black", linewidth=2)
7
8    plt.gca().set_aspect("equal")
9    plt.gca().invert_yaxis()
10    plt.show()
11
12
13segments = outline_segments(grid)
14plot_segments(segments)

The inverted y-axis matches common grid indexing, where row zero is at the top. If your plotting space is Cartesian instead, leave the axis in its default orientation.

Improving Quality

Raw outlines are often jagged because the source grid is discrete. You can improve the result in several ways. Merge collinear edges to reduce path size. Preserve inner loops separately so holes remain holes. If you need a softer visual result, smooth the polyline after extraction rather than during boundary detection.

Those steps matter because outline extraction is often the first stage in a larger graphics pipeline. Once the boundary is stable, you can simplify, fill, offset, or export it as vector geometry.

Common Pitfalls

One common mistake is treating diagonal contact as connected outline data. In a four-neighbor grid, two cells touching only at a corner do not share an edge, so merging them can create false boundaries.

Another issue is duplicate segments. If you emit edges without checking whether the opposite side is occupied, interior edges remain in the result and the outline looks doubled. The neighbor tests in the first example prevent that.

A third problem is mixing coordinate conventions. Grid indices usually refer to cell positions, while plotting libraries render points in geometric space. Decide early whether a coordinate describes a cell center, a cell corner, or a vertex on the outline. Inconsistent choices cause shifted or self-intersecting paths.

Summary

  • Outline plotting means extracting only the exposed boundary of filled data.
  • For binary grids, checking each cell against its four neighbors is a reliable starting algorithm.
  • The raw output is usually a list of segments that can be stitched into closed paths.
  • Marching squares is a better fit when the input is a continuous field rather than a simple mask.
  • Most rendering bugs come from duplicate edges, wrong connectivity assumptions, or inconsistent coordinates.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.