For what should be obvious reasons, we armored Mary’s “kitchen garden” with buried concrete blocks and deer fence. I secured the fence to 7 foot plastic-coated steel-core posts strapped to shorter stakes supporting the lower wire fence, using cable ties we both knew wouldn’t survive exposure to the sun.
As part of the spring garden prep, I summoned proper supports from the vasty digital deep:

The general idea is to plunk one atop each post and tangle wrap the netting through the hooks, thusly:

The garden looks like we killed an entire chess set and impaled their carcasses as a warning to others of their kind, but the fence now hangs neatly from the top of the posts rather than drooping sadly.
Each one of those things takes nigh onto two hours to emerge from the M2, so I printed them one by one over the course of a few days while making continuous product improvements.
The “natural” PETG isn’t UV stabilized, either, but it ought to last longer than those little bitty nylon cable ties. We shall see.
The OpenSCAD source code as a GitHub Gist:
| // Deer Fence Hangers | |
| // Ed Nisley KE4ZNU May 2021 | |
| Layout = "Show"; // [Build, Show, Cap, Hook] | |
| // net grid spacing | |
| NetOC = 55.0; // [40.0:5.0:70.0] | |
| // stake OD | |
| PoleDia = 23.0; // [20.0:30.0] | |
| //- Extrusion parameters must match reality! | |
| /* [Hidden] */ | |
| ThreadThick = 0.25; | |
| ThreadWidth = 0.40; | |
| HoleWindage = 0.2; | |
| Protrusion = 0.1; // make holes end cleanly | |
| inch = 25.4; | |
| ID = 0; | |
| OD = 1; | |
| LENGTH = 2; | |
| function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit); | |
| //———————- | |
| // Dimensions | |
| Notch = 5.0; // hook engagement | |
| WallThick = 3.0; // min wall and end thickness | |
| Shell = [PoleDia,PoleDia + 2*WallThick,NetOC + 2*Notch]; | |
| HookBlock = [10.0,Shell.y/4,2*Notch]; // hanger inside length | |
| LegendBlock = [0.7*Shell.z,Shell.y/2,2*ThreadThick]; // legend size | |
| //———————- | |
| // Useful routines | |
| module PolyCyl(Dia,Height,ForceSides=0) { // based on nophead's polyholes | |
| Sides = (ForceSides != 0) ? ForceSides : (ceil(Dia) + 2); | |
| FixDia = Dia / cos(180/Sides); | |
| cylinder(r=(FixDia + HoleWindage)/2, | |
| h=Height, | |
| $fn=Sides); | |
| } | |
| //———————- | |
| // Pieces | |
| module Hook() { | |
| //%Cap(); | |
| translate([Shell[OD]/2 – Protrusion,HookBlock.y/2,0]) | |
| rotate([90,0,0]) | |
| linear_extrude(height=HookBlock.y) | |
| difference() { | |
| scale([1,2]) | |
| intersection() { | |
| circle(r=HookBlock.x); | |
| square(HookBlock.x,center=false); | |
| } | |
| square(Notch,center=false); | |
| } | |
| } | |
| module Cap() { | |
| difference() { | |
| rotate(180/6) | |
| PolyCyl(Shell[OD],Shell[LENGTH],6); | |
| translate([0,0,-WallThick]) | |
| rotate(180/24) | |
| PolyCyl(Shell[ID],Shell[LENGTH],24); | |
| translate([-Shell[OD]/2,0,Shell[LENGTH]/2]) | |
| rotate([0,90,0]) | |
| cube(LegendBlock,center=true); | |
| } | |
| translate([-(Shell[OD]/2 – LegendBlock.z/2),0,Shell[LENGTH]/2]) | |
| rotate([0,-90,0]) | |
| resize(0.8*LegendBlock,auto=[true,true,false]) | |
| linear_extrude(height=LegendBlock.z) | |
| text(text=str(NetOC," ",PoleDia), | |
| size=6,spacing=1.00,font="Bitstream Vera Sans:style=Bold", | |
| halign="center",valign="center"); | |
| } | |
| module Hanger() { | |
| Cap(); | |
| for (k=[0,1]) | |
| translate([0,0,k*Shell.z]) | |
| for (a=[-1:1]) | |
| rotate([k*180,0,a*60]) | |
| Hook(); | |
| } | |
| //———————- | |
| // Build it | |
| if (Layout == "Cap") | |
| Cap(); | |
| if (Layout == "Hook") | |
| Hook(); | |
| if (Layout == "Show") | |
| Hanger(); | |
| if (Layout == "Build") | |
| translate([0,0,Shell[LENGTH]]) | |
| rotate([180,0,0]) | |
| Hanger(); |

























