Algorithm Design
Computational Geometry
Performance Optimization
Graphics Programming
Overlapping Rectangles

Optimising the drawing of overlapping rectangles

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

Optimizing overlapping rectangle drawing is usually about reducing wasted work rather than drawing rectangles faster one by one. The best strategy depends on whether you are building a software renderer, a UI invalidation system, or a GPU-backed scene, but the recurring idea is the same: avoid redrawing pixels or issuing draw operations that do not change the final image.

Start by asking what is actually expensive

Different systems pay for different things:

  • in a software renderer, pixel writes and overdraw are expensive
  • in a UI toolkit, too many invalidation regions and paint callbacks are expensive
  • on the GPU, state changes and draw-call overhead may matter more than rectangle math itself

So before optimizing, decide whether your bottleneck is pixel fill, geometry management, or CPU-side dispatch.

Merge dirty rectangles when possible

If the rectangles represent regions that need repainting, a common optimization is to merge overlapping invalidation rectangles into a smaller set of larger repaint regions.

python
1from dataclasses import dataclass
2
3@dataclass
4class Rect:
5    x1: int
6    y1: int
7    x2: int
8    y2: int
9
10    def overlaps(self, other: "Rect") -> bool:
11        return not (self.x2 < other.x1 or other.x2 < self.x1 or self.y2 < other.y1 or other.y2 < self.y1)
12
13    def union(self, other: "Rect") -> "Rect":
14        return Rect(
15            min(self.x1, other.x1),
16            min(self.y1, other.y1),
17            max(self.x2, other.x2),
18            max(self.y2, other.y2),
19        )
20
21
22def merge_rects(rects):
23    merged = []
24    for rect in rects:
25        placed = False
26        for i, existing in enumerate(merged):
27            if rect.overlaps(existing):
28                merged[i] = existing.union(rect)
29                placed = True
30                break
31        if not placed:
32            merged.append(rect)
33    return merged

This trades some overdraw for fewer paint operations, which is often a good bargain in UI systems.

Use clipping to avoid drawing hidden areas

If rectangles are layered front to back, earlier rectangles may be fully or partially hidden by later ones. In that case, clip drawing to the visible portions instead of painting every full rectangle blindly.

This matters most in software rendering, where every pixel write costs CPU time. A simple painter's algorithm with clipping can reduce large amounts of wasted fill work when overlap is heavy.

Spatial indexing helps when there are many rectangles

For large dynamic sets of rectangles, use a spatial index so you do not compare every rectangle with every other one. Common choices include:

  • quadtrees
  • interval trees
  • uniform spatial grids

These structures help answer questions like "which rectangles overlap this region" or "which rectangles need merging" much faster than a naive all-pairs scan.

The right choice depends on how often rectangles move and how evenly they are distributed.

Batch draws when the backend supports it

If the rectangles share style or paint state, batch them. On modern graphics backends, reducing draw-call count can matter more than shaving a few arithmetic operations off the overlap tests.

This is especially true when rectangles differ only in position and size but use the same fill color, shader, or blend mode.

Do not over-merge if fill cost dominates

Merging all overlapping rectangles into one big union is not always optimal. A unioned region may be much larger than the true changed area, causing extra repaint cost.

So there is a tradeoff:

  • fewer regions reduce management overhead
  • larger merged regions may increase overdraw

Good systems often use heuristics, merging only when the bookkeeping savings outweigh the added repaint area.

Profile with realistic overlap patterns

Optimizations that look elegant on paper can fail in real workloads. For example, a quadtree may help only when the data is large and spatially diverse. If you have a small number of rectangles or highly clustered updates, a simple merge pass may outperform a more sophisticated structure.

So measure with the overlap patterns your application actually produces, not only with random synthetic data.

Common Pitfalls

  • Optimizing rectangle intersection math before identifying the real rendering bottleneck.
  • Merging repaint regions so aggressively that total redrawn area becomes much larger.
  • Using all-pairs overlap checks for large dynamic rectangle sets without spatial indexing.
  • Ignoring draw-call overhead on GPU-backed pipelines.
  • Benchmarking unrealistic rectangle distributions and drawing the wrong conclusions.

Summary

  • Optimize overlapping rectangle drawing by reducing wasted redraw work, not by focusing only on rectangle arithmetic.
  • Merge invalidation rectangles when that lowers overall repaint overhead.
  • Use clipping to avoid drawing pixels that will be hidden anyway.
  • Introduce spatial indexing only when the rectangle set is large enough to justify it.
  • Profile on realistic workloads because the right strategy depends on where the actual cost sits.

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.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.