Demo build: items marked [TO FILL] and “Field test pending” are intentional gaps for the operator to complete with real information. See our editorial policy.

Design & Tolerances

Why Vertical and Horizontal 3D-Printed Holes Print Undersized

Key takeaways

  • STL triangulation inscribes an N-sided polygon inside the nominal circle, shrinking the inscribed radius to the apothem r_i = r * cos(pi / N).
  • Viscoelastic corner cutting (die swell and melt tension pulling inward around curved paths) and arc track compression dominate vertical hole shrinkage below 10 mm diameter.
  • Horizontal bores lose vertical clearance due to unsupported bridge sag and steep overhang curling at the top 45° crown, which can be eliminated with a 45° teardrop or flat-top diamond profile.

Even when a desktop FDM printer produces an external 20.00 mm calibration cube within 0.02 mm of its nominal dimensions, cylindrical holes in the same print routinely measure 0.15 mm to 0.40 mm (0.006 to 0.016 in) undersized. Vertical bores shrink because STL polygon chords cut inside the true circle, inward radial tension pulls molten filament toward the center of curvature, and curved extrusion tracks compress excess polymer onto the inner wall. Horizontal bores suffer from staircase Z-quantization, overhang curling near the upper arch, and unsupported bridge droop at the crown. You can calculate compensated CAD diameters or slicer offset values for both orientations with the Fit & Tolerance Calculator.

Cause 1: STL Polygon Chord Error (The Apothem Formula)

When a CAD program exports a cylindrical hole of radius r (diameter D = 2r) to an STL or 3MF mesh, it approximates the circular boundary as an N-sided regular polygon whose vertices lie on the nominal circumference. Because every straight chord between adjacent vertices passes inside the circle, the largest cylindrical pin that can pass through the polygonal prism is governed not by the circumradius r, but by the inscribed radius (apothem) r_i:

Inscribed radius (apothem):   r_i = r * cos(pi / N)
Inscribed diameter:           D_i = D * cos(pi / N)
Diametral chord shrinkage:    Delta_D = D * (1 - cos(pi / N))

As Chris Palmer (Nophead) demonstrated in HydraRaptor: Polyholes, low vertex counts in coarse CAD exports or default OpenSCAD $fn settings introduce substantial geometric shrinkage before the slicer generates G-code:

Polygon Sides (N) cos(pi / N) Factor Inscribed Diameter for D = 6.00 mm Diametral Error (Delta_D)
6 (Hexagon) 0.8660 5.20 mm (0.2046 in) -0.80 mm (-13.4%)
8 (Octagon) 0.9239 5.54 mm (0.2182 in) -0.46 mm (-7.6%)
12 (Dodecagon) 0.9659 5.80 mm (0.2282 in) -0.20 mm (-3.4%)
16 0.9808 5.88 mm (0.2317 in) -0.12 mm (-1.9%)
24 0.9914 5.95 mm (0.2342 in) -0.05 mm (-0.9%)
32 0.9952 5.97 mm (0.2351 in) -0.03 mm (-0.5%)
64 0.9988 5.99 mm (0.2359 in) -0.01 mm (-0.12%)

To make the flat sides of an N-sided polygon tangent to (circumscribed around) the desired hole diameter D, scale the CAD circumradius r_cad by the reciprocal of cos(pi / N):

Circumscribed CAD radius:     r_cad = r / cos(pi / N)
Circumscribed CAD diameter:   D_cad = D / cos(pi / N)

For example, modeling an octagonal hole (N = 8) to clear a 6.00 mm shaft requires setting the vertex-to-vertex diameter to 6.00 / cos(pi / 8) = 6.00 / 0.92388 = 6.49 mm so the flat faces sit 6.00 mm apart. Exporting native STEP files into modern slicers (or setting CAD chordal tolerance below 0.01 mm) eliminates STL faceting error, yet high-resolution circular holes still print undersized due to physical extrusion mechanics.

Cause 2: Viscoelastic Corner Pulling and Melt Tension

When a polymer melt exits a narrow nozzle orifice of diameter d_n (see Nozzle Diameter vs. Layer Height, Line Width, and Overhangs), the compressed macromolecular chains relax and expand radially—a phenomenon known as die swell. As the nozzle translates across the print bed, it drags a molten strand of plastic that has not yet solidified or bonded fully to the layer below.

Along a straight wall, axial tension in the extruded strand acts strictly along the toolpath vector, leaving the wall position unchanged. Around a circular bore, however, the nozzle continuously changes direction toward the center of the hole. Axial tension T in the stretched viscoelastic strand produces an inward centripetal force component f_r per unit arc length inversely proportional to the path radius r:

Inward radial force per unit length:  f_r = T / r

Because f_r scales as 1 / r, smaller holes experience a much stronger inward pull than larger holes. For a 2.5 mm or 3.0 mm screw hole, the molten strand acts like a taut rubber band dragged around a cylinder: before the plastic cools below its glass transition temperature and bonds to the previous layer, it pulls inward across the curve chord, constricting the bore by 0.15 to 0.30 mm. Higher speeds and lower nozzle temperatures increase melt elasticity, whereas tuned pressure advance and moderate perimeter speeds reduce strand tension (see Retraction, Stringing, and Pressure Advance).

Cause 3: Arc Track Compression and Extrusion Geometry

A third geometric error arises from bending a finite-width extrusion track into a tight circle. As derived by Adrian Bowyer in the RepRap Wiki on ArcCompensation, a slicer normally offsets the nozzle centerline by half the extrusion width (r_path = R + 0.5 * t) so the inner edge of a track of thickness t lands on a hole of radius R.

On a straight wall, half of the extruded cross-sectional area lies on each side of the nozzle centerline. On a circular path of radius r_path, the inner circumference is shorter than the outer circumference. Equating the inner extruded area (A_i = pi * r_path * t) to the annular space pi * (r_path^2 - R^2) yields:

r_path^2 - r_path * t - R^2 = 0
r_path = (t + sqrt(t^2 + 4 * R^2)) / 2

For a hole radius of R = 1.50 mm (D = 3.00 mm) and an extrusion width of t = 0.50 mm:

  • Naive centerline offset: r_naive = 1.50 + 0.25 = 1.750 mm
  • Area-compensated centerline radius: r_path = (0.50 + sqrt(0.25 + 9.00)) / 2 = 1.771 mm

Pure geometric area crowding accounts for 0.042 mm of diametral shrinkage on a 3 mm hole (2 * (1.771 - 1.750)), which combines with semicircular track rounding (h / 2 side profile documented in the Slic3r Flow Math manual) and viscoelastic pulling to make sub-5 mm bores consistently tighter than large bores.

Nophead’s Polyhole Solution

In HydraRaptor: Polyholes, Nophead observed that low-vertex polygons do not suffer from continuous centripetal corner pulling along their straight segments—only their discrete vertices get rounded inward. Choosing a vertex count N so that vertex rounding never encroaches past the inscribed circle, and circumscribing the polygon via D_cad = D / cos(pi / N), produces accurate holes across different printers:

Optimal polyhole vertex count:  N = max(round(2 * D), 3)
Compensated vertex diameter:    D_cad = D / cos(pi / N)

For a D = 3.0 mm hole, N = 6 (hexagon) with vertex diameter 3.0 / cos(pi / 6) = 3.464 mm; for a D = 5.0 mm hole, N = 10 (decagon) with vertex diameter 5.0 / cos(pi / 10) = 5.257 mm.

Why Horizontal Holes Print Oval and Undersized

Orienting a bore horizontally (axis parallel to the X or Y bed axis) eliminates continuous circular corner pulling in the XY plane, but introduces three Z-axis distortions that flatten the bore into a vertically compressed oval:

  1. Z-Layer Staircase Quantization: A horizontal cylinder is sliced at discrete vertical intervals equal to the layer height h (see Stepper Angles, GT2 Belts, Lead Screws, and Z Layer Heights). Near the bottom and top crowns, the tangent approaches horizontal, creating steps that quantize the vertical diameter to an integer multiple of h.
  2. Steep Overhang Curling (Upper 45° to 75° Arch): As the bore walls curve inward past 45° from vertical, each new perimeter bead steps inward over empty air by more than half its width. Cooling contraction curls the overhanging edge upward, and the next nozzle pass pushes that curled lip inward into the bore.
  3. Crown Bridge Sag: At the top of the horizontal hole, the closing layers bridge across the gap. Gravity and low melt tension cause unsupported bridging strands to droop downward by 0.15 to 0.40 mm, directly reducing vertical clear height.

CAD Geometry Fixes for Horizontal Bores

Modify horizontal bore cross-sections in CAD using one of three self-supporting profiles:

  • Teardrop Profile (45° Pointed Crown): Replace the top arc above the 45° tangent points with two straight lines meeting at a 90° apex (45° from vertical on each side). For a hole of radius r, the apex sits at r * sqrt(2) = 1.414 * r above the center (1.24 mm above the crown of a 6.0 mm bore), eliminating overhangs steeper than 45° and bridge sag.
  • Truncated Teardrop (Flat-Top Bridge): Truncate the 45° teardrop walls with a short horizontal bridge (0.8 to 1.5 mm wide) positioned 0.20 mm (one layer height) above the nominal circle crown so a single short bridge spans the top without sagging into the pin envelope.
  • Diamond / Octagonal Bore: For pins under 5 mm, a square rotated 45° or an unequal octagon with 45° top and bottom facets prints cleanly without overhangs or first-layer squish.

Slicer XY Hole Compensation vs. Contour Compensation

Modern slicers provide two separate dimensional offset settings (see Slic3r Dimension Errors):

  • XY Hole Compensation (Horizontal Hole Expansion): Offsets only closed internal perimeter loops radially outward when set to a positive value, leaving outer walls unchanged.
  • XY Contour / Size Compensation (Horizontal Expansion): Offsets the outer 2D slice contour.

Because X-Y Hole Compensation is a radial (per-side) offset in PrusaSlicer, OrcaSlicer, Bambu Studio, and Cura:

Measured bore diameter:    D_measured = 5.76 mm
Target bore diameter:      D_target   = 6.00 mm
Diametral shortfall:       Delta_D    = 6.00 - 5.76 = +0.24 mm
Required XY Hole Comp:     c_hole     = +Delta_D / 2 = +0.12 mm (radial offset)

Entering +0.12 mm moves the inner hole wall outward by 0.12 mm on all sides, expanding the bore diameter by 2 * 0.12 mm = +0.24 mm. Always complete Flow Rate and Extrusion Multiplier Calibration first and apply functional joint gaps from Designing 3D-Printed Parts That Fit.

Run the numbers

Fit, Clearance & Shrinkage Calculator (+ STL Gauge)

Compute CAD dimensions for press, sliding, loose and print-in-place joints after polymer shrinkage and nozzle geometry, and download a printable STL test gauge.

Sources and further reading

  1. HydraRaptor – Polyholes
  2. RepRap Wiki – ArcCompensation
  3. Slic3r Manual – Flow Math
  4. Slic3r Manual – Dimension Errors

3D printing guidance on this page is general. Printers, hotends, slicers and filament batches vary, so verify dimensions and settings with test prints and calipers. Always observe thermal, electrical and ventilation safety around heated components and melted polymers. Spotted an error? Tell us and we will review it under our corrections policy.