1
\$\begingroup\$

So, I`d like to output a rounded equilateral triangle in Gerber format.

The first method I tried was to pick a large triangular aperture (%ADD11P,8X3*%, that is) and draw a small closed arc, a.k.a. circle, with it:

%FSLAX26Y26*%
%MOMM*%
G01*
%LPD*%
%ADD10C,1*%
%ADD11P,8X3*%
D11*
X00000000Y00000000D02*
G03*
G75*
I01000000J01000000D01*
M02*

However, the reference Gerber viewer throws a rather peculiar error while trying to interpret that file:

Arc with a non-circular aperture found. This is invalid.

Okay, I thought, but I can still approximate a circle with lines, right? Let`s try drawing a line:

%FSLAX26Y26*%
%MOMM*%
G01*
%LPD*%
%ADD10C,1*%
%ADD11P,8X3*%
D11*
X00000000Y00000000D02*
X11000000Y07000000D01*
M02*

And again, the reference app doesn`t seem to like what I`m trying to do:

Draw with an invalid aperture 11 emulated. Review resulting image.

And only if I correct my aperture definition to become a diamond instead of a triangle (%ADD11P,8X4*%) no errors get thrown.

Am I doing something wrong? Is drawing arcs or lines with triangular apertures documented as incorrect in the standard somewhere?

Naturally, I know I can compute 3 points and draw 3 segments between them using a circle and then fill the interior with a polygon, but I`d really like to avoid that. The task this one is a part of implies drawing multiple triangles with different orientations which can easily be set using the aperture angle parameter.

…Well, preliminary solution found:

%FSLAX26Y26*%
%MOMM*%
G01*
%LPD*%
%AM_my_own_triangle*
$5=$1*
$6=$2x$1*
$7=0.8660254x$5*
4,1,3,$5,0,-0.5x($5+$6),$7,-0.5x($5+$6),-$7,$5,0,$3+$4*
4,1,3,$5,0,-0.5x($5+$6),$7,-0.5x($5+$6),-$7,$5,0,$3+$4+120*
4,1,3,$5,0,-0.5x($5+$6),$7,-0.5x($5+$6),-$7,$5,0,$3+$4+240*
1,1,$6,$5,0,$3+$4*
1,1,$6,$5,0,$3+$4+120*
1,1,$6,$5,0,$3+$4+240*%
%ADD10_my_own_triangle,100x0.1x0x0*%
D10*X00000000Y00000000D03*
M02*

Here I make extensive use of the so-called Aperture Macro definitions. AMs can be rotated independently, see $3+$4+*, and support variables in arithmetic expressions.

This seems to be it, so if in a week`s time nothing less inelegant appears in answers, I`m going to answer the question myself.

\$\endgroup\$
3
  • \$\begingroup\$ It would be interesting if you receive an answer on here. Many of us contract 3rd party ODMs for providing schematics, board layouts, and gerbers so finding an answer on here might not happen. \$\endgroup\$
    – user103380
    Commented May 21, 2019 at 15:39
  • \$\begingroup\$ @KingDuken Just in case you`re interested: I`ve found a working, albeit a bit ugly, solution. \$\endgroup\$ Commented May 21, 2019 at 22:27
  • 1
    \$\begingroup\$ You're more than welcome to answer your own question. If you do that, you'll be helping any one in the future who would have the same question. \$\endgroup\$
    – user103380
    Commented May 22, 2019 at 5:42

1 Answer 1

1
\$\begingroup\$

Okay, here are the two solutions: the «short» and the «compatible» (for nobody except the official Gerber viewer seems to interpret the «short» one correctly).

Short

%FSLAX26Y26*%
%MOMM*%
G01*
%LPD*%
%AM_my_own_triangle*
$5=$1*
$6=$2x$1*
$7=0.8660254x$5*
4,1,3,$5,0,-0.5x($5+$6),$7,-0.5x($5+$6),-$7,$5,0,$3+$4*
4,1,3,$5,0,-0.5x($5+$6),$7,-0.5x($5+$6),-$7,$5,0,$3+$4+120*
4,1,3,$5,0,-0.5x($5+$6),$7,-0.5x($5+$6),-$7,$5,0,$3+$4+240*
1,1,$6,$5,0,$3+$4*
1,1,$6,$5,0,$3+$4+120*
1,1,$6,$5,0,$3+$4+240*%
%ADD10_my_own_triangle,100x0.1x0x0*%
D10*X00000000Y00000000D03*
M02*

Here, the so-called variable Aperture Macros are being used. Literally not a single third-party Gerber viewer I tried, be it online or installable, had support for AMs that contain variables.

Compatible

My suspicions have turned out to be true. For your Gerber files to be understood by third parties you need to compute triangles manually; there is no other way.

This is the C code I now use to generate rounded triangles:

void GenTri(char *retn, double xpos, double ypos, double scal, double angl) {
    double plus = M_PI * 2.0 / 3.0, dots[6] = {
        scal * cos(angl),              scal * sin(angl),
        scal * cos(angl + plus),       scal * sin(angl + plus),
        scal * cos(angl + plus * 2.0), scal * sin(angl + plus * 2.0)
    };
    sprintf(retn, "X%0.0fY%0.0fD02*\nX%0.0fY%0.0fD01*\n"
                  "X%0.0fY%0.0fD01*\nX%0.0fY%0.0fD01*\n",
            dots[0] + xpos, dots[1] + ypos, dots[2] + xpos, dots[3] + ypos,
            dots[4] + xpos, dots[5] + ypos, dots[0] + xpos, dots[1] + ypos);
}

...

GenTri(pstr, temp.x, -temp.y, data->scal * size, data->angl);
lptr += sprintf(bptr + lptr, "%sG36*\n%sG37*\n", pstr, pstr);

This is the corresponding Gerber output, unfortunately almost completely human-unreadable, unlike the «short» approach.

%FSLAX36Y36*%
%MOMM*%
G01*
%ADD10C,0.96000000*%
D10*
X72483601Y-39726784D02*
X57369097Y-32796289D01*
X58924363Y-49351081D01*
X72483601Y-39726784D01*
G36*
X72483601Y-39726784D02*
X57369097Y-32796289D01*
X58924363Y-49351081D01*
X72483601Y-39726784D01*
G37*
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.