-
Sticky Trap Screen Frames
The objective being to reduce the number of onion maggots in Mary’s Vassar Farm plot without chemical agents, I conjured sticky trap screen frames from the vasty digital deep:

Sticky Trap – first production run Each one contains half a sheet of yellow sticky plastic, which is easy enough to cut before peeling off the protective covering sheets. The cage is half-inch galvanized hardware cloth snipped with hardened diagonal cutters. A bead of acrylic adhesive around the base holds the cage in place
Although you can deploy sticky sheets without cages, they tend to attract and affix beneficial critters: butterflies, small birds, furry critters, toads, gardeners, and the like. We don’t know how effective the cages will be, but they seemed better than nothing.
They mount on ski poles cut in half:

Sticky Trap – ski pole installed And on fence posts around the perimeter:

Sticky Trap – angle bracket installed To my untrained eye, some of those doomed critters are, indeed, onion maggot flies. The rest seem to be gnats and other nuisances, so IMO we’re applying population pressure in the right direction.
Each base-and-cap frame takes about three hours to print, so I did them one at a time over the course of a few days while applying continuous product improvement.
The sheets rest on small V blocks intended to keep them centered within the cage:

Sticky Sheet Cage – angle bracket – solid model The ski pole attachment must build with the cap on top, but it bridges well enough for the purpose:

Sticky Sheet Cage – ski pole – solid model The overhanging hooks on the blocks (just barely) engage the grid to keep the lid in place, while remaining short enough to not droop too badly. You could probably delete the hooks from the bottom plate, but they align the cage while the adhesive cures.
The sheets tend to bend in the middle, so I’ll stick a thin slat or two vertically to keep them straight.
The OpenSCAD source code as a GitHub Gist:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters// Sticky Sheet Cage // Ed Nisley KE4ZNU May 2021 Layout = "Build"; // [Build, Show, Cap, Attachment] Bracket = "Ski"; // [Angle, Ski, Post] //- 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 Sheet = [1,100,150]; // sticky sheet Grid = 0.5*inch; Cage = [2*Grid + 5.0, 8*Grid + 5.0, 12*Grid + 2.0]; // grid wire cage bent around sheet CageRad = 2.5; // wire bending radius CageThick = 2.0; // grid thickness WallThick = 3.0; // min wall and bottom thickness Recess = 5.0; // inset to capture cage edge Plate = [Cage.x,Cage.y,Recess] + [2*WallThick,2*WallThick,WallThick]; PlateRad = 5.0; SkiPole = [20.0,20.0 + 2*WallThick,50]; AnglePlate = [30,30,50]; ScrewClear = 5.0; BuildGap = 5.0; //———————- // 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 Cap() { union() { difference() { hull() for (i=[-1,1], j=[-1,1]) translate([i*(Plate.x/2 – PlateRad),j*(Plate.y/2 – PlateRad),0]) cylinder(r=PlateRad,h=Plate.z,$fn=12); translate([0,0,Plate.z – Recess]) hull() for (i=[-1,1], j=[-1,1]) translate([i*(Cage.x/2 – CageRad),j*(Cage.y/2 – CageRad),0]) cylinder(r=CageRad,h=Plate.z,$fn=12); } difference() { Strut = Cage.x – 2*CageThick; Latch = [Cage.x,WallThick,0.75*Plate.z]; union() { for (j=[-1,1]) translate([0,j*2.5*Grid,Plate.z]) cube([Strut,WallThick,2*Plate.z],center=true); for (j=[-1,1]) translate([0,j*2.5*Grid,2*Plate.z – Latch.z/2]) cube(Latch,center=true); } translate([0,0,2*Plate.z + (Cage.z – Sheet.z)/4]) rotate([0,45,0]) cube([Strut/sqrt(2),Plate.y,Strut/sqrt(2)],center=true); } } } module Attachment() { if (Bracket == "Angle") { translate([0,Plate.y/2,0]) rotate(45) difference() { union() { cube(AnglePlate,center=false); rotate(-45) translate([0,WallThick,Plate.z/2]) cube([Plate.x – 2*PlateRad,4*WallThick,Plate.z],center=true); } translate([WallThick,WallThick,-Protrusion]) cube(AnglePlate + [0,0,2*Protrusion],center=false); translate([AnglePlate.x/2,-Protrusion,2*AnglePlate.z/3]) rotate([-90,0,0]) PolyCyl(ScrewClear,2*AnglePlate.x,6); translate([-Protrusion,AnglePlate.x/2,1*AnglePlate.z/3]) rotate([90,0,90]) PolyCyl(ScrewClear,2*AnglePlate.x,6); } } else if (Bracket == "Ski") { translate([0,Plate.y/2 + SkiPole[OD]/2,0]) difference() { union() { PolyCyl(SkiPole[OD],SkiPole[LENGTH],24); translate([0,-3*WallThick,Plate.z/2]) cube([Plate.x – 2*PlateRad,4*WallThick,Plate.z],center=true); } translate([0,0,-2*WallThick]) PolyCyl(SkiPole[ID],SkiPole[LENGTH],24); } } } //———————- // Build it if (Layout == "Cap") Cap(); if (Layout == "Attachment") { Attachment(); } if (Layout == "Show") { translate([0,0,Sheet.z/2 + Plate.z]) color("Yellow") cube(Sheet,center=true); Cap(); Attachment(); translate([0,0,Sheet.z + 2*Plate.z]) rotate([180,0,0]) Cap(); } if (Layout == "Build") { translate([-(Plate.x/2 + BuildGap),0,0]) { Cap(); Attachment(); } translate([(Plate.x/2 + BuildGap),0,0]) Cap(); }