text:
Draw the ☣ (Biohazard Symbol)
Draw the Biohazard symbol in an arbitrary colour on a distinctly coloured background. The specific proportions were published in the June 27th 1974 issue of the Federal Register of the US Government.
Details

As output, writing to a file (raster and vector formats are permitted) or displaying on the screen are both allowed.
You can draw just the border or the filled shape.
If you use raster images, you should take a parameter (or two) as input that lets you adjust the resolution of the output (e.g. width/height).
The background must at least have the size of the bounding box of the symbol but may be larger.
Outputting the unicode symbol ☣ is not sufficient.
The exact ratios of the used distances are given in following diagram (which was originally from here):

I also tried to make an additional diagram with the same measurements that is hopefully a little bit easier to read:

(Inspired by a post on 99%invisible)

Loophole: can we just put a 1x1 pixel image inside a variable sized background?

I don't think it is, if you set the resolution large enough the symbol should still appear. And in any case I hope people here have enough common sense to understand what we mean:)

If I had time to spare I would give it a try with PostScript or turtle graphics.

Hmmm, I wonder what a Racket solution would look like. Or a Processing or Compressed Turtle solution.

Since you want the points to be blunted can you put that in your question?  Currently it doesn't provide the information such as how long the bluntings should be only how wide apart.

@SriotchilismO'Zaic The length is determined by the two circles: They each have a given center and radius, so the length is determined by the size of the gap.

@flawr What is the center of the larger circle then?  I don't see it indicated on the diagram.

That is "E" in the original diagram (the crosses represent the circle centers), and $11$ in the one I added below (where the radius meets the axis of symmetry).

Ah I see thanks the diagram makes it look like E has only to do with the central annulus.  I will fix my answer to center it correctly and then it should blunt properly.

T-SQL, 442 441 426 355 349 344 bytes
DECLARE @ VARCHAR(MAX)=REPLACE(REPLACE(REPLACE('DECLARE @a5MULTIPOINT((0 31),(19 -2),(-19 -2))'',@b5MULTIPOINT((0 39),(26 -6),(-26 -6))'',@5POINT(0 9)'',@d5LINESTRING(0 9,0 99,90 -43,0 9,-90 -43)''SELECT @a830%b821)%86)%d81)%d84%819))).STUnion(@827%820)).STIntersection(@b819)))'
,8,'.STBuffer('),5,' GEOMETRY='''),'%',').STDifference(@')EXEC(@)

Saved 70+ bytes by using REPLACE() for long keywords and executing as dynamic SQL. See the post-replacement code in the screenshot below.
I doubled the coordinate values from the sample illustration and moved up 9 units, to reduce the number of decimals displayed.
This was done in SQL 2017, using geo-spatial features introduced in SQL 2008. Lots of useful built-in geometry functions, including STBuffer, which gives me a simple way to define circles of different sizes around a point.
Visual of output, with annotated code:

For more T-SQL drawing, see my Easter Bunny.
For more practical applications of this tech in SQL, read this article or watch this video. SE even has a related site, gis.stackexchange.com.
Edits:

Saved 1 byte by changing a coordinate from 104 to 99.
Saved 15 bytes by taking the STDifference of a STUnion of objects, instead of each individually.
Saved 71 bytes by using REPLACE() on repeated keywords, then executing as dynamic SQL. Reverted Edit 2, to leave more replacements of STDifference.
Saved 4 bytes by moving the center up 9 units, which changed a few coordinates to single (negative) digits. This also freed up the numeral 5 to use as a replacement character instead of '#', saving 2 more bytes on the quotes.
Saved 5 bytes by moving ) into the STDifference replacement string; thanks, @Nicholas!

Why... does this exist?

@Alexander For databases that contain or use geographic data, like population census, or scientific studies, or even just customer sales by geographic region. Or just for drawing bunnies and biohazard symbols.

SQL is bad enough for the one thing it's meant for, who in their right mind would want to go beyond that. Imagine GUIs written in SQL. I need annotations, aspects, and a unit testing framework. We need to go deeeeeper.

@Alexander As you wish: TSQLT

@FreeMan Oh for f...'s sake.

Legitimately the funniest thread I've read in a while. Thanks guys.

You can save 4 more by including ) in your STDiff replace. ').STDifference(@'

@Nicholas 5 bytes, actually, thanks!

Tex + Tikz, 232 bytes
43 bytes saved by switching to tex. Thanks to Phelype Oleinik
Some bytes saved thanks to Skillmon
\input tikz \tikz[x=1,y=1,white]{\def\f{\foreach\1in{90:,210:,330:}}\def\u{\draw[line width=}\def~{circle(}\f\fill[red](\122)~30);\f{\u2](0,)--(\111);\u8](\130)--(\160);\fill(\130)~21);}\fill~6);\u7,red]~23.5);\f\u2](\130)~20);}\bye

With line breaks and without \def:
\input tikz
\tikz[x=1,y=1,white]{
\foreach\1in{90,210,330}\fill[red](\1:22)circle(30);
\foreach\1in{90,210,330}{
\draw[line width=2](0,0)--(\1:11);
\fill(\1:30)circle(21);
\draw[line width=8](\1:30)--(\1:60);
}
\fill(0,0)circle(6);
\draw[line width=7,red](0,0)circle(23.5);
\foreach\1in{90,210,330}\draw[line width=2](\1:30)circle(20);
}
\bye

Explanation
This is a little outdated I will fix it when I can figure out how to make the images not enourmous
Here I am going to explain how the uncompressed answer solves the problem.  I may at some point explain how the compression works.  First we draw the big black circles:
\foreach\x in{90,210,330}\fill(\x:21)circle(30);

Then we draw some white lines:
\foreach\x in{90,210,330}\draw[white,line width=2cm](0,0)--(\x:11);

Then we draw white circles:
\foreach\x in{90,210,330}\fill[white](\x:30)circle(21);

Then we add a central white circle:
\fill[white](0,0)circle(6);

Then we add a black annulus:
\draw[line width=7cm](0,0)circle(25.5);

Then we remove parts of the black annulus
\foreach\x in{90,210,330}\draw[white,line width=2cm](\x:30)circle(20);

You haven't blunted the six outer points. There should be 4 units of white space between each pair.

@LevelRiverSt The six outer points are now 4 units away from their partner.

Those "claw tips" are too pointy, they should consist of straight line segments parallel to the segments coming from the center circle.  Also the 20.88 looks quite suspicious.

You can save another byte by using \1 instead of \x, as you can then use \def\f{\foreach\1in{90,210,330}}.

@flawr well... they're now literally quite a bit smaller than 5000x5000... only 90x90 now... barely can make out the details :D

@flawr The explanation has not changed.  I need to figure out how to make the images the right size before I update them.

@SriotchilismO'Zaic rasterize them at 300dpi, this should give good results (see my answer).

C, 8010 bytes
Way back, before SVG or EMF, you had to deal with raster, and if you wanted something to load right away, say before the O/S was ready, like a Windows startup screen, you had to use RLE, or run-length-encoding. This monster outputs a PBM file using RLE as the data. Build like usual and run like this ./biohazard > biohazard.pbm.
If you were to include all the frameworks required to generate, e.g. the SVG engine in HTML, the Java libraries, etc. this would likely be the smallest self-contained solution, because puts is the only external function, and it's typically one of the smallest stdio.h functions.
Regarding this detail:

If you use raster images, you should take a parameter (or two) as input that lets you adjust the resolution of the output (e.g. width/height).

I interpreted "should" as different from "must", e.g. as in RFC 2119, so I didn't include scaling, because for this code it would only be feasible to do multiples of the original, e.g. ./biohazard 2 and that would introduce atoi, printf and other complications which would detract from the main focus of the submission.
int o,i,x[]=
{4946,3,33,2,389,8,33,8,378,13,33,13,369,17,33,16,363,20,33,20,356,19,41,19,350,18,49,18,344,18,55,18,339,17,61,17,334,
17,66,17,330,17,71,17,325,17,75,17,321,17,79,17,317,17,83,17,313,17,87,16,311,16,90,17,307,17,93,17,303,17,97,17,300,
17,99,17,297,17,102,18,293,18,105,17,291,18,107,18,288,17,110,18,285,18,113,17,283,18,115,18,280,18,117,18,277,19,119,
18,275,19,121,19,272,19,123,19,270,19,125,19,268,19,127,19,266,19,129,19,263,20,131,19,261,20,133,19,259,20,134,20,257,
20,136,20,255,21,137,20,253,21,139,20,251,21,141,20,249,21,142,21,248,21,143,21,246,21,145,21,244,21,146,22,242,22,147,
22,240,22,149,22,238,22,150,22,238,22,151,22,236,22,152,23,234,23,153,23,232,23,155,22,232,23,155,23,230,23,157,23,228,
24,157,24,226,24,159,23,226,24,159,24,224,24,160,25,222,25,161,24,222,24,162,25,220,25,163,25,219,25,163,25,218,25,164,
26,216,26,165,25,216,26,165,26,214,26,166,26,214,26,167,26,212,27,167,26,212,26,168,27,210,27,169,27,209,27,169,27,208,
27,170,28,207,27,170,28,206,28,171,27,206,28,171,28,204,29,171,28,204,28,172,29,202,29,172,29,202,29,173,29,201,29,173,
29,200,30,173,29,200,30,173,30,198,31,173,30,198,30,174,31,197,30,174,31,196,31,174,31,196,31,175,31,195,31,175,31,194,
32,175,31,194,32,175,32,193,32,175,32,193,32,175,32,192,33,175,32,192,33,175,33,191,33,175,33,190,34,175,33,190,34,175,
33,190,34,175,34,189,34,174,35,189,34,174,35,188,35,174,35,188,35,174,36,187,36,173,36,187,36,173,36,187,36,173,36,186,
37,74,25,74,36,186,37,67,39,67,36,186,37,62,49,61,38,185,37,58,57,57,38,185,38,53,64,54,38,185,38,50,71,50,38,185,38,
47,76,48,38,185,38,45,81,44,39,184,40,41,87,41,39,184,40,39,91,39,39,184,40,37,95,37,39,184,40,35,99,34,41,183,41,32,
103,32,41,183,41,30,107,30,41,183,41,28,111,27,42,183,42,25,115,25,42,183,42,24,117,24,42,183,42,22,121,21,43,183,43,
19,124,20,43,183,43,18,127,18,43,183,43,17,129,16,44,183,44,14,133,14,44,183,44,13,135,12,45,183,45,11,137,11,45,183,
45,10,139,9,46,183,46,9,138,10,46,183,46,10,137,9,47,183,47,9,136,10,47,183,47,10,135,9,48,183,48,10,56,20,57,10,48,
183,49,9,50,33,49,10,48,184,49,10,45,41,45,10,48,184,50,10,40,49,40,10,49,184,50,10,37,55,36,10,50,185,50,10,33,60,34,
10,50,185,51,10,30,65,30,10,51,185,51,11,27,69,27,10,52,185,52,10,25,73,24,11,52,185,53,10,22,77,21,11,53,185,53,11,19,
81,19,10,53,186,54,11,16,85,16,10,54,185,56,11,13,88,14,11,56,181,59,11,11,91,11,11,59,176,63,11,8,94,9,11,63,171,66,
11,6,97,6,11,66,167,68,12,4,99,4,11,69,163,71,12,1,102,2,11,72,159,74,126,75,155,77,124,78,151,80,123,79,149,82,120,83,
145,85,118,86,141,88,116,88,139,90,114,91,135,93,112,93,133,96,109,96,130,98,107,98,127,101,104,102,124,104,101,104,
122,106,99,106,119,110,95,109,117,112,93,112,114,115,89,115,112,118,85,118,110,120,82,121,107,124,78,124,105,127,74,
127,103,131,69,130,101,134,65,133,99,137,60,137,97,141,54,141,95,146,47,145,93,151,39,150,91,157,29,156,89,166,13,165,
88,168,9,168,86,169,9,169,84,170,9,170,82,171,9,171,80,172,9,171,79,173,9,172,78,173,9,173,76,174,9,174,74,175,9,175,
72,176,9,175,72,176,9,176,70,177,9,177,68,64,20,93,10,94,20,63,68,57,34,83,17,83,33,58,66,54,42,77,21,76,43,54,64,51,
50,71,25,71,49,51,64,48,57,65,29,65,56,49,62,46,63,61,31,61,62,47,60,45,67,58,33,58,67,44,60,43,71,55,35,54,72,43,58,
41,36,8,32,52,37,51,33,8,35,41,58,40,36,17,26,49,39,48,27,16,37,40,56,39,38,22,23,46,41,45,24,21,39,39,55,37,40,26,21,
43,42,44,21,26,40,37,54,36,42,29,20,41,43,41,20,29,42,36,53,35,43,29,21,39,44,39,22,29,43,35,52,34,45,29,23,37,45,37,
23,29,45,34,51,33,46,29,24,35,46,35,25,29,46,33,50,32,48,29,26,33,47,33,26,29,47,33,49,31,49,29,27,32,47,32,27,29,49,
31,48,31,49,30,28,30,48,30,29,29,50,31,47,29,51,30,30,28,49,28,30,29,51,30,46,29,52,29,32,27,49,27,31,29,53,28,46,28,
53,29,33,26,49,26,32,29,54,28,44,28,54,29,34,25,49,25,33,29,55,27,44,27,55,29,35,24,49,23,35,29,56,27,43,26,56,29,36,
22,50,22,36,29,57,26,42,26,57,29,37,21,50,21,37,29,58,26,41,25,58,29,38,21,49,20,38,29,59,25,40,25,59,29,39,20,49,19,
39,29,60,24,40,24,60,29,40,19,49,19,39,29,61,24,39,23,61,29,41,18,49,18,40,29,62,23,38,23,62,30,41,17,49,17,41,29,63,
22,38,22,63,30,42,16,48,17,42,29,63,23,37,21,65,29,43,16,47,16,43,29,64,22,36,22,65,29,43,16,47,15,44,29,65,21,36,21,
66,29,44,13,50,14,44,29,66,21,35,20,67,29,45,11,53,11,45,29,67,20,34,20,68,29,46,8,57,8,46,29,67,20,34,20,68,29,46,6,
61,5,46,30,68,19,34,19,69,29,47,4,63,4,46,30,69,19,33,18,70,30,47,1,67,1,47,29,70,19,32,19,70,30,163,29,71,18,32,18,71,
30,61,2,37,2,61,29,72,18,31,17,73,29,59,5,35,5,58,30,72,18,31,17,73,29,58,7,33,7,57,30,73,17,30,17,74,30,55,10,31,10,
55,30,73,17,30,17,74,30,53,13,28,14,53,30,74,16,30,16,75,30,51,17,25,16,52,29,75,17,29,16,76,29,50,20,21,19,50,30,76,
16,29,15,77,30,50,21,16,22,50,30,77,15,29,15,77,30,50,26,7,25,51,30,77,15,28,15,78,30,51,57,50,30,78,15,28,15,78,31,50,
56,51,30,79,15,27,14,80,30,51,55,51,30,79,15,27,14,80,30,51,55,50,31,80,14,27,13,81,31,51,53,51,30,81,14,27,13,82,30,
51,53,51,30,82,13,27,13,82,31,50,52,51,31,82,13,26,13,83,31,51,51,51,31,82,13,26,13,83,31,51,51,50,31,84,12,26,13,84,
31,50,50,51,31,84,12,26,12,85,31,51,49,50,32,84,13,25,12,85,32,50,49,50,31,86,12,25,12,86,31,50,48,50,32,86,12,25,11,
87,32,50,47,50,32,86,12,25,11,87,32,50,47,49,32,88,11,25,11,88,32,49,47,49,32,88,11,25,11,88,32,49,46,49,32,89,11,25,
10,90,32,49,45,49,32,89,11,25,10,90,33,48,45,48,33,90,10,25,10,91,32,48,45,47,33,91,10,25,10,91,33,47,44,48,33,91,10,
25,10,91,34,46,44,47,33,92,10,25,9,93,33,47,43,46,34,92,10,25,9,93,34,46,43,46,33,93,10,25,9,94,34,45,43,45,34,94,9,25,
9,94,35,44,43,44,34,95,9,25,9,95,34,44,42,44,35,95,9,25,9,95,35,43,42,44,34,96,9,25,9,96,35,42,42,43,35,96,9,25,8,97,
36,42,41,42,35,97,9,25,8,98,36,41,41,41,36,97,9,25,8,99,36,40,41,40,36,98,8,26,8,99,37,39,41,39,36,99,8,26,8,100,37,38,
41,38,37,99,8,27,7,100,38,37,41,37,37,101,7,27,7,101,38,36,41,36,38,101,7,27,7,102,38,35,41,35,38,102,7,27,7,102,39,34,
41,34,38,103,7,27,7,103,39,33,41,33,39,103,7,27,7,104,39,32,41,32,39,104,7,27,7,104,41,30,41,30,40,104,7,29,6,105,41,
29,41,29,40,105,7,29,6,106,41,28,41,28,41,105,7,29,6,107,42,26,41,26,42,106,7,29,6,108,42,25,41,25,42,107,7,29,7,107,
44,22,42,23,43,108,6,30,7,108,44,21,42,21,45,108,6,31,6,109,45,19,42,20,45,109,6,31,6,110,46,17,43,17,46,110,6,31,6,
111,47,15,43,15,47,111,6,31,6,112,48,13,43,13,48,112,5,33,5,113,49,11,43,10,50,112,6,33,5,114,50,9,43,9,50,113,6,33,6,
113,50,8,44,9,49,114,6,33,6,114,48,9,45,8,48,115,5,35,5,115,47,9,45,8,47,116,5,35,5,117,45,8,46,9,45,116,6,35,6,117,44,
8,46,9,44,117,5,37,5,118,42,9,47,8,43,118,5,37,5,119,41,9,47,9,41,119,5,37,5,120,40,8,48,9,40,119,5,39,5,120,39,8,48,9,
38,121,5,39,5,121,37,9,49,8,37,122,5,39,5,123,35,9,49,9,35,123,4,41,5,123,34,8,50,9,34,123,5,41,5,124,32,9,51,9,31,125,
5,42,3,127,30,9,51,9,30,127,3,43,1,130,28,9,52,9,29,130,1,176,26,9,53,9,26,310,24,9,54,9,24,314,22,9,55,9,22,317,20,9,
55,9,20,320,18,9,56,10,17,324,15,10,57,9,16,327,13,9,58,10,13,331,10,10,59,9,11,335,8,9,60,10,8,339,5,10,61,9,6,344,2,
9,62,10,2,358,63,368,65,367,65,366,67,365,67,364,69,362,70,362,71,360,73,358,75,356,76,356,77,354,79,352,81,350,82,349,
84,215,2,130,86,130,3,79,5,129,87,128,6,77,6,127,89,126,6,79,6,125,91,124,7,80,6,123,93,122,7,82,6,121,95,120,7,84,6,
119,97,118,7,86,7,115,100,116,7,87,8,113,102,114,7,89,8,111,105,111,7,91,8,109,107,109,7,93,8,107,109,106,9,94,9,103,
112,104,9,96,9,101,115,101,9,98,10,97,118,98,10,100,10,95,121,95,10,102,11,91,124,92,11,104,11,89,127,88,11,107,12,85,
131,85,11,110,12,81,135,81,12,112,13,77,138,78,13,114,14,73,143,73,14,116,15,69,72,2,73,69,15,118,17,63,74,5,73,64,16,
122,17,59,75,7,75,58,18,124,19,53,77,9,77,53,19,126,22,45,79,13,78,46,21,130,24,37,82,15,81,38,24,132,28,27,85,18,86,
27,28,135,37,5,95,21,95,5,37,138,134,24,135,141,131,27,131,144,128,31,127,148,124,34,125,151,121,37,121,155,117,41,117,
159,113,45,113,163,109,49,109,167,105,53,105,171,101,57,101,175,96,62,96,181,91,67,91,185,86,72,86,191,80,78,81,196,74,
84,74,204,67,91,67,211,59,99,59,219,51,107,51,228,40,119,39,242,25,133,25,5311,0};
main(){for(puts("P1\n432 408");x[i];++i,o=!o)while(x[i]--)puts(o?"0":"1");}

Would be nice to explain how you generated the code.

The code outputs a newline after every character; I think you need putchar() or similar.

@marcelm - PBM P1 format is okay with that!

@YiminRong Oh right, the output was PBM; I didn't quite pay attention to that!

I'm pretty sure that should does mean must for this question, but that would probably be worth taking up with the OP.

@SriotchilismO'Zaic -  Note that "must" is used in the detail following (regarding backgrounds) so there is a distinction with the OP.

I don't think that using must necessarily means that there is a distinction.  This is really a question you should (or perhaps must) ask the OP.

TeX + TikZ, 234 230 226 224 bytes
Originally 5 bytes longer than Sriotchilism O'Zaic's answer, but this one should be correct. It is similar to his answer but saves a few bytes more here and there, it needs one \draw[line width=8] more (in the code below this is done by \28](~30)to(~55);, that's 17 bytes added only for this) to get the tips of the symbol right, hence the 5 bytes more overall code length.

thanks to Sriotchilism O'Zaic I reread some specifications of the question and realized I can change the colour to red, so that saves a few bytes again.
another two bytes were stripped thanks to Joe85AC's comment

\input tikz\let~\def~\1{circle(}~\2{~\draw[line width=}~~{\foreach~in{90:,210:,330:}}\tikz[x=1,y=1,white]{~\fill[red](~22)\130);~\fill(~30)\121);\28](~30)to(~55);\22](~0)to(~10);\fill\16);\27,red]\123.5);\22](~30)\120);}\bye

TeX-g + TikZ, 195 Bytes
Just if someone cares, the following uses a TeX-based code golf dialect that I'm working on (don't consider the code stable). The byte count includes EOL characters and the EOF character, as those are semantically used (EOL delimits arguments of loops). The dialect is pretty small up until now and only features shorthands for definitions and a for-loop syntax, however it is not specifically written for this answer, so it shouldn't break the rules of code golfing. Repository for the -g.tex-package/file: https://github.com/Skillmon/TeX-g
\input-g <tikz>~"{\:~{90:,210:,330:}}~'{circle(}~_{\draw[line width=}!f\fill\tikz[x=1,y=1,white]{"f[red](~22)'30);
"f(~30)'21);_8](~30)to(~55);_2](~0)to(~10);
f'6);_7,red]'23.5);"_2](~30)'20);
}

Output of both code snippets looks identical:

(too lazy to update the image, just imagine it being red)

My answer is now correct and 2 bytes shorter than yours.  I'm sure someone could probably combine some of my answer with some of yours to make a shorter one, but I don't quite understand your answer.

@SriotchilismO'Zaic if I change the colour to red (overread the rule that the colour can be arbitrary), I get it to 230 bytes.

@SriotchilismO'Zaic and obviously you saved more than just one byte by in your answer by looking at mine (just saying).

Ok, I looked at your answer and did not understand what it was doing so I don't think I could have really taken very much from your answer. But I changed the message to remove a exact number anyway, since maybe I picked up some stuff from your answer without realizing it.

@SriotchilismO'Zaic it's ok. My code is influenced by yours after all, I currently try to write a code golfing package to turn TeX into a code golfing language of some sort. When I finally published it my answer will be shorter :) (This is no language specifically crafted for this question, so it doesn't break the rules)

With the current version of my TeX code golfing language I get it down to 199 bytes (+EOF byte).

It seems that you can leave out \let~\def without having to add an additional byte. This doesn't save a byte either but makes the code more readable, I guess.

Took me quite a while but I managed to improve your result by another two bytes: \input tikz\def\c{circle(}\def\d{~\draw[line width=}\def~{\foreach~in{90:,210:,330:}}\tikz[x=1,y=1,white]{~\fill[red](~22)\c30);~\fill(~30)\c21);\d8](~30)to(~55);\d2](~0)to(~10);\fill\c6);\d7,red]\c23.5);\d2](~30)\c20);}\bye
This was a very hard challenge for myself as you've done a near perfect job, IMHO.

SVG(HTML5), 434 410 321 306 bytes

<svg viewbox=-60,-60,120,120><circle r=23.5 stroke-width=7 fill=#fff stroke=#000 /><use href=#g transform=scale(-1,1) /><g id=g><use href=#p transform=rotate(120) /><use href=#p transform=rotate(240) /><path id=p stroke=#fff stroke-width=2 d=M5,0A5,5,0,0,0,0,-5V-10A20,20,0,0,0,2,-50V-53A31,31,0,0,1,31,-17

Now based on @LevelRiverSt's SVG. Edit: Saved 12 bytes thanks to @G0BLiN.

I believe that omitting <defs> is safe. This works for me on Firefox, Chrome and Edge.

@Arnauld Thanks, that means I can get rid of the first <use> as well!

You can shorten this by drawing the symbol centered on x=0,y=0. Try this <svg viewbox=-60,-60,120,120><circle r=23.5 stroke-width=7 fill=#fff stroke=#000 /><use href=#g transform=scale(-1,1) /><g id=g><use href=#p transform=rotate(120) /><use href=#p transform=rotate(240) /><path id=p stroke=#fff stroke-width=2 d=M-5,0A5,5,0,0,1,0,-5V-10A20,20,0,0,1,-2,-50V-53A31,31,0,0,0,-31,-17 - should shorten this to 309 bytes. :)

@G0BLiN Thanks, and I was able to save a further 3 bytes by drawing the mirrored version of the path (since it's reflected anyway).

Processing, 371 368 bytes
translate(width/2,width/2);scale(width/99);int i=0,b=204;float t=TAU/3;noStroke();for(;i<3;i++){fill(0);ellipse(0,-22,60,60);rotate(t);}for(;i<6;i++){fill(b);rect(-4,-60,8,16);ellipse(0,-30,42,42);rotate(t);}ellipse(0,0,12,12);stroke(0);strokeWeight(7);noFill();ellipse(0,0,47,47);for(;i<9;i++){strokeWeight(2);stroke(b);ellipse(0,-30,40,40);line(0,0,0,-9);rotate(t);}

I wasn't sure if Processing should count as rasterized or not for the purpose of this challenge. If it counts as rasterized, the translate and scale is necessary to make the symbol legible and on-screen for a given window size. But, because all of the drawing commands are vectorized, it works at any given scale; so if we assume drawing at the relative origin to be about 200 units wide is fine, the first 43 bytes can be dropped.
This assumes the background color is 204, 204, 204, which is the default background color in processing. It also assumes a rectMode of CORNER and an ellipseMode of CENTER (the defaults)
With an initial size(640, 640), the resulting sketch looks like this:

By doubling the scale, I saved 3 bytes, because .5s are eliminated (though several numbers do flow from 1 digit to 2 digit).
The construction is similar to the TeX solution, drawing black and then gray on top to "erase" the gaps between the shape.
Explanation:
translate(width/2,width/2); // Move to the middle of the canvas
scale(width/99);            // Scale up to fill the canvas

int i=0,b=204;              // Initialize i, and `b` to the background color
float t=TAU/3;              // Save a rotation of one third, in radians

noStroke();
for(;i<3;i++){ // Draw the three big black circles
  fill(0);
  ellipse(0,-22,60,60);
  rotate(t);
}
for(;i<6;i++){
  fill(b);
  rect(-4,-60,8,16);     // "Blunt" the corners on the sharp outer rings
  ellipse(0,-30,42,42); // Cut out the middle of the big circles
  rotate(t);
}
ellipse(0,0,12,12); // Cut out the small circle in the middle
stroke(0);
strokeWeight(7);
noFill();
ellipse(0,0,47,47); // Draw the thick band that goes through all three big circles
for(;i<9;i++){
  strokeWeight(2);
  stroke(b);
  ellipse(0,-30,40,40); // Cut the "gap" between the three big rings
                        //and the band passing through them
  line(0,0,0,-16);      // Cut the lines coming out of the small middle circle
  rotate(t);
}

Looks nice:) I think if you double all the measurements you can avoid the .5!

Yes, but that'd also change some of the single digit number to double digit, so I'm not sure how it balances out. If I counted right, it looks like that would save 2 bytes. I was also thinking about using a scale to change it for only part of the code, but wasn't sure where to best put it

oh you're right, I did not consider that.

Doubling the measurements to remove decimals saved almost 10 bytes in my answer, even though a few coords went from single to double digits. Worth a try, anyway.

@CurtisFenner -.- I made a mistake and downvoted your answer (when I was trying to upvote it). Since I've downvoted a few days ago, the vote is locked and I can't upvote until an edit is made. Could you please edit something so I can give you the well-deserved upvote?

I saved 3 bytes by doubling the scale it's drawn at. @IsmaelMiguel

@CurtisFenner Awesome! And upvoted! Thank you. By the way, does Processing allow to, say, do (a=fill)(0); and then do a(b); instead of fill(b);? Or similar? You repeat a lot of functions.

Not like that (Processing is basically just Java). It's possible that adding methods could help a little, though

Yeah, Java is a mess regarding these things :/

GLSL, 700 629 564 545 499 bytes
#define v vec2
#define j(x,r)length(x-g)<r
#define k(x,r,q)j(x,q)!=j(x,r)
#define l(b)length(g-b)<1.&&length(g-dot(g,b)*b)<(length(g)<S?A*S:A/S)
float C=.86,S=.5,F=.3,E=.22,A=.02,G=.21;void mainImage(out vec4 o,in v p){v r=iResolution.xy;v g=(p/S-r)/r.y;o.g=(k(v(0,F),G,G-A)||k(v(F*C,-F*S),G,G-A)||k(v(-F*C,-F*S),G,G-A))?o.g=0.:k(v(0),F,G)?C:l(v(0,1))||l(v(C,-S))||l(v(-C,-S))||j(v(0),.06)||j(v(0,F),G)||j(v(F*C,-F*S),G)||j(v(-F*C,-F*S),G)?0.:j(v(0,E),F)||j(v(E*C,-E*S),F)||j(v(-E*C,-E*S),F)?C:0.;}

I was playing around with Shadertoy, so I tried the GLSL shading language. The code just rasterizes circles and lines by testing each fragment, and assigns them a value of one or zero. The size was cut down from >1000 bytes by heavy use of macros.
Shadertoy program

Welcome to the site! Neat first answer!

I don't know the language, but can the && and || be golfed to & and | at some or all parts?

@KevinCruijssen It's a subset of C, so those would be bitwise operations. For me the compiler complains about type though

@Roninkoi I indeed saw that it was based on C. In C it is possible to use |/& instead of ||/&& for bools, isn't it? Haven't done anything in C in a long time, so not sure. I know it works in Java/C# .NET in most cases. But I only now notice the Shadertoy link you've added, and it doesn't seem to work there as you've already stated. Ah well. Nice first answer btw! Welcome to CGCC.

I cut -30 bytes on posted code but Header sais 566 bytes, and posted code is 628?

@PrincePolka Oh, sorry only the Shadertoy was 566. Now posted code is 564

PostScript, 367 359 328 271 bytes
Code (compressed version):
5 5 scale 36 24 translate <</c{0 360 arc closepath}/r{120 rotate}/R{repeat}/L{setlinewidth}/g{setgray}/F{fill}>>begin 3{0 11 15 c F r}R 1 g 3{0 15 10.5 c F r}R 0 0 3 c F 3{[-.5 2 1 3 -2 25 4 3]rectfill r}R 0 g 4 L 0 0 11.5 c stroke 1 g 1 L 3{0 15 10 c stroke r}R showpage

Code (uncompressed version):
5 5 scale                  % over-all scale
36 24 translate            % over-all shift

% define some short-named procedures for later use
<<
  /c { 0 360 arc closepath }  % append circle (x, y, radius are taken from stack)
  /r { 120 rotate }           % rotate by 120°
  /R { repeat }
  /L { setlinewidth }
  /g { setgray }
  /F { fill }
>> begin

3 {
    0 11 15 c F       % black circle
    r                 % rotate by 120°
} R
1 g                   % set white color
3 {
    0 15 10.5 c F     % white circle
    r                 % rotate by 120°
} R
0 0 3 c F             % small white circle
3 {
    [ -.5 2 1 3       % white gap near center
      -2 25 4 3       % white gap on edge
    ] rectfill
    r                 % rotate by 120°
} R
0 g                   % set black color
4 L                   % set linewidth 4
0 0 11.5 c stroke     % black ring
1 g                   % set white color
1 L                   % set linewidth 1
3 {
    0 15 10 c stroke  % white ring
    r                 % rotate by 120°
} R
showpage

Result (as animation to see how it is drawn):

Great animation.

Shorter but uglier: ```[/t 30/d{c fill r}/e{c stroke}/c{0 360 arc}/r{120 rotate}/R{repeat}/L{setlinewidth}/g{setgray}>>begin
72 48 translate
3{9{0}R 22 t d}R
3{1 g 6 d t 21 d[-1 4 2 6 -4 50 8 6]rectfill g 8 L 23 e}R
3{1 g 2 L t 20 e r}R

Java 10, 860 841 bytes
import java.awt.*;v->new Frame(){Color C;public void paint(Graphics g){var G=(Graphics2D)g;int t=300;G.fillOval(150,40,t,t);G.fillOval(55,205,t,t);G.fillOval(245,205,t,t);G.setColor(C.WHITE);G.fillOval(195,45,t=210,t);G.fillOval(65,270,t,t);G.fillOval(325,270,t,t);G.fillOval(270,270,60,60);G.fillRect(295,240,10,60);G.fillPolygon(new int[]{246,251,303,298},new int[]{326,334,304,296},4);G.fillPolygon(new int[]{298,349,354,303},new int[]{304,334,326,296},4);G.fillRect(280,0,40,80);G.fillPolygon(new int[]{30,50,119,99},new int[]{433,467,427,393},4);G.fillPolygon(new int[]{550,570,501,481},new int[]{467,433,393,427},4);G.setColor(C.BLACK);G.setStroke(new BasicStroke(35));G.drawOval(183,183,235,235);G.setColor(C.WHITE);G.setStroke(new BasicStroke(10));G.drawOval(200,50,t=205,t);G.drawOval(70,275,t,t);G.drawOval(330,275,t,t);}{show();}}

Output:

And here with each part colored differently to see what is actually being drawn:

Explanation:
Unlike all other answers, rotating and drawing would be even longer in Java, so instead I'm using default draw methods. This unfortunately came with one big disadvantage: I need to know the \$x,y\$-coordinate of the top-left corner of the square surrounding the circle, and its width/height. As well as some more \$x,y\$-coordinates for rotated rectangles. This took A LOT of calculations to finally finish with this code and output.
The sizes are based on a center point at coordinate \$[300,300]\$, with 10 times the units mentioned in the picture of the challenge description as sizes for all shapes. Why 10 times as large? All the Java AWT methods require integers as pixel-coordinates, so using the default small units would become way to inaccurate when rounding to integers. By using a 10 times as large value it's still easy to calculate with, and the rounding errors are minimal (although still slightly noticeable to the naked eye - note: all decimals are rounded 'half up').
Code explanation:
// Import for Frame, Panel, Graphics, Graphics2D, Color, and BasicStroke:
import java.awt.*;
// Method with empty unused parameter and Frame return-type
v->
  // Create a Frame (window for graphical output)
  new Frame(){
    // Color null-object on class-level to use for static calls and save bytes
    Color C;
    // Override its default paint method
    public void paint(Graphics g){
      // Cast the Graphics to a Graphics2D-object, for the setStroke() method
      var G=(Graphics2D)g;
      // Temp integer to save bytes
      int t=300;
      // Draw the three large black circles (default color is black)
      G.fillOval(150,40,t,t);
      G.fillOval(55,205,t,t);
      G.fillOval(245,205,t,t);
      // Then change the color to white
      G.setColor(C.WHITE);
      // Draw the two smaller inner circles
      G.fillOval(195,45,t=210,t);
      G.fillOval(65,270,t,t);
      G.fillOval(325,270,t,t);
      // As well as the small circle at the center of the bio-hazard symbol
      G.fillOval(270,270,60,60);
      // Draw the three openings next to the middle circle
      G.fillRect(295,240,10,60);
      G.fillPolygon(new int[]{246,251,303,298},new int[]{326,334,304,296},4);
      G.fillPolygon(new int[]{298,349,354,303},new int[]{304,334,326,296},4);
      // Create the three openings for the outer circles
      G.fillRect(280,0,40,80);
      G.fillPolygon(new int[]{30,50,119,99},new int[]{433,467,427,393},4);
      G.fillPolygon(new int[]{550,570,501,481},new int[]{467,433,393,427},4);
      // Change the color back to black
      G.setColor(C.BLACK);
      // Set the line thickness to 35 pixels
      G.setStroke(new BasicStroke(35));
      // Draw the circle that would form the arcs in the bio-hazard symbol
      G.drawOval(183,183,235,235);
      // Change the color to white again
      G.setColor(C.WHITE);
      // Set the line thickness to 10 pixels
      G.setStroke(new BasicStroke(10));
      // And draw the three rings alongside the earlier inner circles we drew,
      // to create gaps in the ring to form the arcs
      G.drawOval(200,50,t=200,t);
      G.drawOval(70,275,t,t);
      G.drawOval(330,275,t,t);}
    // Start an initialized block for this Frame
    {
     // And finally show the Frame
     show();}}

Calculations:
And now comes the long part: how are all these magic numbers in the code calculated?
As I mentioned earlier, I've used 10 times the units of the picture in the challenge description, so those sizes are: \$A=10, B=35, C=40, D=60, E=110, F=150, G=210, H=300\$. I've also assumed the very center is at coordinate \$[300,300]\$. Using just this information, I had to calculate all the magic numbers you see in the code, which I will go over down below:
1a) Top black circle:
Width/height: this is mentioned in the diagram: \$H=300\$.
\$x,y\$-coordinate top-left square corner: line \$E\$ goes from the center of the bio-hazard symbol (\$[300,300]\$) to the center of the black circle. So the coordinate at the center of this circle is therefore \$[300, 300-E]\$. From there, we can subtract halve the width/height from both the \$x\$ and \$y\$ coordinate of this center to get the coordinate of the top-left corner of the square surrounding the circle: \$[300-\frac{H}{2}, 300-E-\frac{H}{2}] → [150, 40]\$.
1b) Bottom-left black circle:
Width/height: again \$H=300\$.
\$x,y\$-coordinate top-left square corner: we again know the length of line \$E\$. We also know that the angle is at 330°. If we draw a triangle with \$E\$ as long side, and with the three corners as angles \$90,60,30\$, we can calculate the other two sides:

Here \$a=\frac{E}{2}\$ and \$c=\frac{E}{2}\sqrt{3}\$. So the center coordinates of this black circle is therefore \$[300-\frac{E}{2}\sqrt{3}, 300+\frac{E}{2}]\$. From there, we can again subtract halve the width/height from both to get the coordinate of the top-left corner of the square surrounding the circle: \$[300-\frac{E}{2}\sqrt{3}-\frac{H}{2}, 300+\frac{E}{2}-\frac{H}{2}] → [54.737, 205]\$
1c) Bottom-right black circle:
Width/height: again \$H=300\$.
\$x,y\$-coordinate top-left square corner: we do something similar as above, but in the other direction: \$[300+\frac{E}{2}\sqrt{3}-\frac{H}{2}, 300+\frac{E}{2}-\frac{H}{2}] → [245.262, 205]\$
2a) Top inner white circle:
Width/height: this is mentioned in the diagram: \$G=210\$.
\$x,y\$-coordinate top-left square corner: line \$F\$ goes from the center of the bio-hazard symbol (\$[300,300]\$) to the center of the inner white circle. So the coordinate at the center of this circle is therefore \$[300, 300-F]\$. From there, we can subtract halve the width/height from both the \$x\$ and \$y\$ coordinate of this center to get the coordinate of the top-left corner of the square surrounding the circle: \$[300-\frac{G}{2}, 300-F-\frac{G}{2}] → [195, 45]\$.
2b) Bottom-left inner white circle:
Width/height: again \$G=210\$.
\$x,y\$-coordinate top-left square corner: similar as what we did in step 1b: \$[300-\frac{F}{2}\sqrt{3}-\frac{G}{2}, 300+\frac{F}{2}-\frac{G}{2}] → [65.096, 270]\$
2c) Bottom-right inner white circle:
Width/height: again \$G=210\$.
\$x,y\$-coordinate top-left square corner: similar as what we did in step 1c: \$[300+\frac{F}{2}\sqrt{3}-\frac{G}{2}, 300+\frac{F}{2}-\frac{G}{2}] → [324.903, 270]\$
3) Center white circle:
Width/height: this is mentioned in the diagram: \$D=60\$.
\$x,y\$-coordinate top-left square corner: subtracting halve this width/height from the center coordinate is enough: \$[300-\frac{D}{2}, 300-\frac{D}{2}] → [270, 270]\$
4a) Top white rectangle gap at the center of the bio-hazard symbol:
Width: this is mentioned in the diagram: \$A=10\$.
Height: Not too irrelevant, as long as it's large enough to create the gap, and not too large to go over other thing that should remain black. So I've just used \$D=60\$ here.
\$x,y\$-coordinate top-left corner: \$[300-\frac{A}{2}, 300-D] → [295, 240]\$
4b) Bottom-left rectangle gap at the center of the bio-hazard symbol:
Single the rectangle is angled, the Java method fillPolygon(int[] xPoints, int[] yPoint, int amountOfPoints) doesn't need the width/height, but instead needs the four individual coordinates of the corners of this rectangle. By again creating multiple triangles with corner-angles at 90, 60, and 30 degrees with the long side known, we can calculate the other sides. The calculations of the four points in the order I've used them in the Java method are:
\$[300-\frac{D}{2}\sqrt{3}-\frac{A}{4}, 300+\frac{D}{2}-\frac{A}{4}\sqrt(3)] → [245.528, 325.669]\$
\$[300-\frac{D}{2}\sqrt{3}+\frac{A}{4}, 300+\frac{D}{2}+\frac{A}{4}\sqrt(3)] → [250.538, 334.330]\$
\$[300+\frac{A}{4}, 300+\frac{A}{4}\sqrt{3}] → [302.5, 304.330]\$
\$[300-\frac{A}{4}, 300-\frac{A}{4}\sqrt{3}] → [297.5, 295.669]\$
4c) Bottom-right rectangle gap at the center of the bio-hazard symbol:
Likewise as step 4b:
\$[300-\frac{A}{4}, 300+\frac{A}{4}\sqrt{3}] → [297.5, 304.220]\$
\$[300+\frac{D}{2}\sqrt{3}-\frac{A}{4}, 300+\frac{D}{2}+\frac{A}{4}\sqrt{3}] → [349.461, 334.330]\$
\$[300+\frac{D}{2}\sqrt{3}+\frac{A}{4}, 300+\frac{D}{2}-\frac{A}{4}\sqrt{3}] → [354.461, 325.669]\$
\$[300+\frac{A}{4}, 300-\frac{A}{4}\sqrt{3}] → [302.5, 295.669]\$
5a) Top big white gap:
Width: this is mentioned in the diagram: \$C=40\$.
Height: Not too irrelevant, as long as it's large enough to create the gap, and not too large to go over other thing that should remain black. So I've just used \$2\times\text{1a.}y=80\$ here.
\$x,y\$-coordinate top-left corner: \$[300-\frac{C}{2}, 0] → [280, 0]\$ The \$0\$ isn't calculated, it was just easier to use (as mentioned earlier, the height is mostly irrelevant).
5b) Bottom-left big rectangle gap:
Similar as step 4b for the first two points:
\$[300-\frac{H}{2}\sqrt{3}-\frac{C}{4}, 300+\frac{H}{2}-\frac{C}{4}\sqrt{3}] → [30.192, 432.679]\$
\$[300-\frac{H}{2}\sqrt{3}+\frac{C}{4}, 300+\frac{H}{2}+\frac{C}{4}\sqrt{3}] → [50.192, 467.320]\$
For the other two we can't base it on the center of the screen like we did in step 4b, but instead we'll calculate it based on the two points we've just calculated:
\$[300-\frac{H}{2}\sqrt{3}+\frac{C}{4}+\frac{80}{2}\sqrt{3}, 300+\frac{H}{2}+\frac{C}{4}\sqrt{3}-\frac{80}{2}] → [119.474, 427.320]\$
\$[300-\frac{H}{2}\sqrt{3}-\frac{C}{4}+\frac{80}{2}\sqrt{3}, 300+\frac{H}{2}-\frac{C}{4}\sqrt{3}-\frac{80}{2}] → [99.474, 392.679]\$
(where the \$80\$ is the \$2\times\text{1a.}y\$ mentioned in step 5a)
5c) Bottom-right big rectangle gap:
Likewise as step 5b:
\$[300+\frac{H}{2}\sqrt{3}-\frac{C}{4}, 300+\frac{H}{2}+\frac{C}{4}\sqrt{3}] → [549.807, 467.320]\$
\$[300+\frac{H}{2}\sqrt{3}+\frac{C}{4}, 300+\frac{H}{2}-\frac{C}{4}\sqrt{3}] → [569.807, 432,679]\$
\$[300+\frac{H}{2}\sqrt{3}+\frac{C}{4}-\frac{80}{2}\sqrt{3}, 300+\frac{H}{2}-\frac{C}{4}\sqrt{3}-\frac{80}{2}] → [500.525, 392.679]\$
\$[300+\frac{H}{2}\sqrt{3}-\frac{C}{4}-\frac{80}{2}\sqrt{3}, 300+\frac{H}{2}+\frac{C}{4}\sqrt{3}-\frac{80}{2}] → [480.525, 427.320]\$
6) Black ring that will form the arcs:
Thickness: this is mentioned in the diagram: \$B=35\$.
Width/height: this can be calculated with the units in the diagram: \$2(E-A+B) → 270\$, after which we'll remove the thickness: \$2(E-A+B)-B → 235\$ (halve the thickness at both sides)
\$x,y\$-coordinate top-left corner: we simply subtract halve the width/height from the center coordinate: \$[300-\frac{2(E-A+B)-B}{2}, 300-\frac{2(E-A+B)-B}{2}] → [182.5, 182.5]\$
7) White ring inside the inner circles to form the arcs:
Thickness: this is mentioned in the diagram: \$A=10\$.
Width/height: this is the same as step 2a: \$G=210\$, but with this thickness removed: \$G-A → 200\$
\$x,y\$-coordinate top-left corner: these are the same calculations as in step 2a, but with the adjusted width/height \$G-A\$ instead of \$G\$:
\$[300-\frac{G-A}{2}, 300-F-\frac{G-A}{2}] → [200, 50]\$
\$[300-\frac{F}{2}\sqrt{3}-\frac{G-A}{2}, 300+\frac{F}{2}-\frac{G-A}{2}] → [65.096, 270] → [70.096, 275]\$
\$[300+\frac{F}{2}\sqrt{3}-\frac{G-A}{2}, 300+\frac{F}{2}-\frac{G-A}{2}] → [324.903, 270] → [329.903, 275]\$
And rounding all those values we've calculated to integers we get the code and output above.

Can g.fillOval be assigned to a variable in Java? I think it occurs enough times for that to save bytes.

@someone Ah yeah, I did that in the rabbit challenge earlier and planned on doing it here after I was done, but forgot.. Thanks, will fix it right away and see how much it saves. :)

I have the impressions the proportions are somehow off. The bottom one of those three parts crossing the central "ring" looks a thinner than the other two. And I have the impression that those "claws" don't quite look right, unfortunately I cannot exactly say what seems off.

@flawr You're right, it's off. I left a note about that at the bottom. But I might have also made some mistakes somewhere to make it more off than the rounding errors and drawing things from a top-left position. Just not entirely sure where the error margin is at..

@someone Apparently it's 10 byte longer instead of shorter.. I guess I'm not using fillOval enough.. >.>

Why is the ring missing pixels?

@mbomb007 Because overlapping curved line are buggy I guess.. I draw 20 partially overlapping arc-lines next to each other for that part. In theory, since they're all using the same curve and are partially overlapping due to the i/2 (integer-division), there shouldn't have been any empty pixels.. But since they're still loose lines instead of a solid polygon, I guess those empty pixels tend to happen.. :( I could mark it as non-competing for now, and try to fix it later when I have time. I think I could remove the loop, and give the arc-lines a thickness to draw single thick arc-lines.

@mbomb007 Should be fixed now, at the cost of 24 bytes.

This answer is still wrong. The edges of the ring sections are supposed to be curved to match the circles they are within. Also, the gaps at the outside look too wide. I understand you're trying to be golfy, but compromises that change the output from what it's supposed to be aren't really allowed.

@mbomb007 Hmm, you're indeed right. I will delete for now and see if I have some time to fix it later on, since I currently don't have the time.

@flawr It's been a while (a year and 3 days I now notice xD), but I've just fixed the code. It required A LOT of calculations, but I'm glad everything is correct now.

GLSL, 319 310 bytes
#define F float
#define H(y)sqrt(x*x+(y)*(y))
void mainImage(out vec4 D,in vec2 u){vec2 U=u*.003-.5;F x=abs(U.x),y=U.y;if(y<.577*x){F t=.5*x+.866*y;y=.866*x-.5*y;x=abs(t);}F c=F(H(y-.11)<.15);F R=H(y);F S=H(y-.15);if(S<.105)c=0.;if(R<.03)c=0.;if(x<(R<.1?.005:.02))c=0.;if(R>.10&&R<.135&&S<.095)c=1.;D=vec4(c);}

This can be rendered on Shadertoy.

You can use the symmetry in the image to draw it with a smaller amount of separate shapes.
Here is a somewhat inflated version:
#define F float
#define H(y) sqrt(x*x+(y)*(y))

void mainImage(out vec4 D,in vec2 u)
{
    // normalized UV
    vec2 U = u*.003 - .5;

    // fold the 6 identical sections to the same UV coordinates
    F x = abs(U.x), y = U.y;
    if (y < .577*x)
    {
        F t = .5*x + .866*y;
        y = .866*x - .5*y;
        x = abs(t);
    }

    // circles and lines
    F c = F(H(y-.11) < .15);
    F R = H(y);
    F S = H(y-.15);
    if (S < .105) c = 0.;
    if (R < .03) c = 0.;
    if (x < (R < .1 ? .005 : .02)) c = 0.;
    if (R > .10 && R < .135 && S < .095) c = 1.;

    // output
    D = vec4(c);
}

(thanks to @Kevin Cruijssen for removing some unnecessary whitespace)

You can remove some of the spaces. The one in your define: H(y) sqrt→H(y)sqrt; all the spaces at your if-statements: if (→if(; and those in your last if-statement surrounding the ANDs: if (R>.10 && R<.135 && S<.095)c=1.;→if(R>.10&&R<.135&&S<.095)c=1.;.

Haskell, 530 491 436 435 430 420 bytes
f=fromIntegral
c(a,b)r(x,y)=(x-a)^2+(y-b)^2<r^2
(m#w)t(x,y)|c<-cos(-t),s<-sin(-t)=x*c-y*s>m&&abs(x*s+y*c)<w/2
u a p=any($p)a
i a p=all($p)a
v=(*(pi/6))<$>[9,5,1]
o=c(0,0)
h?r=[c(h*cos a,h*sin a)r|a<-v]
(h%y)x|u[i[u$11?15,(not.)$u$o 3:map(0#1)v++map(9#4)v++15?10.5],i[o 13.5,not.(o 10),u$15?9.5]](60*f x/h-30,60*f y/h-30)="0 "|0<1="1 "
g h|s<-show h,n<-[0..h-1]=writeFile"a.pbm"$unlines$"P1":(s++' ':s):[n>>=(f h%)y|y<-n]

Outputs a PBM file.
This was a lot of fun!

(I had to convert this to PNG to upload to imgur)
Basically we create our own vector graphics functions which render onto an image pixel by pixel by detecting whether the pixel is part of the shape. The shape is constructed as a bunch of circles and lines (radiating from the origin) held together with basic set operations: union, intersection, and not. The circles are composed of their center and a radius, and the lines have a minimum radius, a width, and an angle in that order. Detecting membership in a circle is easy: I just subtract the center coords and compare the magnitude to the radius. The line is slightly more complicated: I rotate the point by the opposite of the angle to bring it (to nullify the rotation) then I just check whether the x and y coordinates fall within the expected range. The minimum radius is to ensure the larger gap at the far ends of the large circles does not overrule the small gaps near the center. After that it's a simple matter of boolean logic to do set math.
EDIT: Thanks a lot to @flawr for taking off 39 bytes!
EDIT2: Thanks a lot to @Christian Sievers for taking off 55 bytes! Good idea making them into functions
EDIT3: Thanks again to @Christian Sievers for shaving off another byte!
EDIT4: Took off 7 bytes thanks to @H.PWiz and @Angs!
EDIT5: Just noticed a bug! I was rendering the lines twice as thick as they were supposed to be! Cost me 2 bytes to fix it (had to divide width by 2; could've adjusted the constant values but changing 1 to 0.5 would also cost 2).
EDIT6: Thanks @Angs for taking off another 10 bytes!

Wow, this is so cool. It is rare to see someone defining their own types in [tag:code-golf] here:) Two questions: Is it necessary to have negative angles [-90,-210,-330]? And would it be possible to change the <= to <?

@flawr The negatives were to get the orientation right, as the circles were out of sync with the lines (I think). I did a lot of fiddling around and at this point I'm scared to mess with it any more, lol. I erred on the side of caution with <= I wasn't sure if < would really count because it might make the proportions slightly off in places or cause weird artifacts

So I tried it and managed to shave a few bytes off

Mainly some unnecessary perenthesis, then using just on size parameter as well as compressing the three angles.

Oh, in case you didn't know, we have a haskell chat as well as some tips for golfing in haskell.

Another small tweak

Nice! It's possible without data type

Oh, and (not.)$... can be written as not.(...), where ... ends with 10.5 before the next  ].

You should be able to save bytes by renaming l to #

Using NetPBM saves a whopping two bytes!.

Some refactoring for 10 bytes

HTML / JS,  448 435 433  387 bytes
Saved many bytes by using @Neil's pre-minimized version of the SVG
Saved 2 bytes thanks to @Shaggy
A compressed version of this SVG file from Wikimedia Commons.
<body onload="_=`<svg~12y~24y><path id=p d=m28.8117,27.046a3,3}0qb3117q4.004v-1w539|1wq20.7959v-w583a1jxb7975x7.3228xj,8.6032x9.7443l-.4835q.2792|-18.7598q9.0989zm3.4148q8.871a10x0}0q1b453,c9w,9w{-kx3wx3w}1x6.8042,0x0x0{k>~><use href=#p transform=rotate(},cc|a10wx0w}c{}1qb1756,yc26,26) /x,1w.5q,-kb7417j5x5}1c0,b2.`;for(i of`bcjkqwxy{|}~`)with(_.split(i))_=b.innerHTML=join(pop())"id=b>

Try it online! (just outputs the decompressed string)
Demo snippet

setTimeout(_ => document.getElementsByTagName('svg')[0].setAttribute("viewBox", "0 0 100 100"), 0)
<body onload="_=`<svg~12y~24y><path id=p d=m28.8117,27.046a3,3}0qb3117q4.004v-1w539|1wq20.7959v-w583a1jxb7975x7.3228xj,8.6032x9.7443l-.4835q.2792|-18.7598q9.0989zm3.4148q8.871a10x0}0q1b453,c9w,9w{-kx3wx3w}1x6.8042,0x0x0{k>~><use href=#p transform=rotate(},cc|a10wx0w}c{}1qb1756,yc26,26) /x,1w.5q,-kb7417j5x5}1c0,b2.`;for(i of`bcjkqwxy{|}~`)with(_.split(i))_=b.innerHTML=join(pop())"id=b>

This works, on CodePen in Chrome Android, for 392.

@Arnauld I have inverted my answer, although it cost 5 bytes (I found another unnecessary byte though so overall my score only went up by 4).

@Neil Updated accordingly. ;)

It turns out that @LevelRiverSt's SVG is much smaller!

Ruby, 278 bytes
puts"<svg viewBox='-60-60 120 120'><circle cx='0'cy='0'r='23.5'stroke-width='7'fill='white'stroke='red'/>",(-3..5).map{|i|"<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(#{i/3},-1)rotate(#{i*120})'/>"}

Try it online!
Generates the SVG code below, with the symbol being at 200% of the scale in the OP.
It consists of a circle at the back, and the prongs in the foreground. The prong is scaled -1,0,1 in the X axis and rotated through multiples of 120 degrees. The cases where the X scaling is zero produce no output, while the -1 and +1. provide the two sides of each pair of prongs.
Use is made of a 2-unit wide white border around the prong to cut the back circle, using the stroke and stroke-width attributes. In order for the internal shape to be per the OP, the coordinates are moved by 1 unit (half the width of the border.) Note that the path is deliberately not closed, to suppress the drawing of the final line of the border. This ensures the two halves of each pair of prongs join together.
90 degrees of the inner circle are drawn rather than the expected 60, for golfing reasons. This means there is some overlap between the bases of each pair of prongs, but this does not affect the appearance of the output shape.

<svg viewBox='-60-60 120 120'><circle cx='0'cy='0'r='23.5'stroke-width='7'fill='white'stroke='red'/>
<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(-1,-1)rotate(-360)'/>
<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(-1,-1)rotate(-240)'/>
<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(-1,-1)rotate(-120)'/>
<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(0,-1)rotate(0)'/>
<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(0,-1)rotate(120)'/>
<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(0,-1)rotate(240)'/>
<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(1,-1)rotate(360)'/>
<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(1,-1)rotate(480)'/>
<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(1,-1)rotate(600)'/>

Desmos, 126 125 bytes
s=\sqrt3x
Y=max(2y,s-y,-s-y)/2
S=xx+yy

S-6Y+6.39<\{4<S<7.29\}

0>(S-6Y+4.59)(S-.36)(S-4.4Y-4.16)\{Y<2,S-YY>.16\}\{S-YY>.01\}

The empty lines are included to paste in piecewises properly.
Try it on Desmos!
-1 byte thanks to @KevinCruijssen (inline S-YY)
This translates nicely to the following 159-byte one-liner:

[\{xx+yy-6Y+6.39<\{4<xx+yy<7.29\},(xx+yy-6Y+4.59)(.36-xx-yy)(xx+yy-4.4Y-4.16)\{Y<2,xx+yy-YY>.16\}\{xx+yy-YY>.01\}\}\for Y=[\max(2y,\sqrt3x-y,-\sqrt3x-y)/2]]>0

Try it on Desmos!

Wow. I actually doubted this was possible, but you proved me wrong. I am blown away.

Wow, you beat all the other answers too!

Do you need the X=S-YY? You're only using X two times, so using 0>(S-6Y+4.59)(S-.36)(S-4.4Y-4.16)\{Y<2,S-YY>.16\}\{S-YY>.01\} without the \nX=S-YY is one byte shorter (125 bytes), isn't it? (I didn't know how to modify the tio-link to verify my assumption..)

@KevinCruijssen yep, that saves a byte
Documentation on sharing the tio link

@fireflame241 Sharing the link wasn't the issue, I know how to do that. ;) It's how to replace those checks of the last two lines, with the togglable circles in front of them. Maybe I need to be logged in to modify those? :/

@KevinCruijssen you don't need to be logged in. Are you referring to comparing with the reference? Clicking inside the circle should work

@fireflame241 No, I mean how to modify the comparisons. I know the ones at the top are just a comment, but I couldn't really find how to modify the 0>(S-6Y+4.59)(S-.36)(S-4.4Y-4.16)\{Y<2,X>.16\}\{X>.01\} to 0>(S-6Y+4.59)(S-.36)(S-4.4Y-4.16)\{Y<2,S-YY>.16\}\{S-YY>.01\} when I made my suggestion earlier. Here a gif of what I see from my end, and how I can't find a way to edit that value (ignore that it's in Dutch instead of English).

@KevinCruijssen oh! You need to copy-paste into there: make sure to include the leading newline for the last two expressions, and copy only one line at a time. It's normally editable; abusing the syntax messed up the renderer (but not the evaluator). The renderer expects \left\{\right\} instead of \{\}

@fireflame241 Ahhh. The leading newline did the trick. I did copy-paste the lines, but without leading newline. Ok, good to know. :)

Because I'm really running out of bounty space right now, I'm just gonna give you a +300 bounty on one of your Desmos LoTM answers.

Wolfram Language (Mathematica), 211 209 191 182 175 168 166 164 163 162 bytes
{a,b}=AbsArg[I*x-y];z=Exp[Mod[b,2Pi/3]I-Pi/3I]a-22;u=Abs@Im@z;n=Abs[z-8];RegionPlot[20<a<27&&n<19||a>6&&Abs[z]<30&&n>21&&u>1&&(u>4||Re@z<-2),{x,s=52,-s},{y,-s,s}]

Here exported with the additional option PlotPoints -> 100 to make it look more accurate:

how it works:

a = Sqrt[x^2+y^2] is the distance from the center.
z+22 = I*x-y is the complex representation of the point (x,y) but mapped into the first 120° wedge, so that its complex argument is always in the range [-π/3,+π/3] and we only need to deal with one third of the symbol
u = Abs[Im[z]] is the magnitude of the x-coordinate in the first 120° wedge
The RegionPlot plots for each point in the x-y plane whether or not it satisfies a given condition. This condition is satisfied for points that belong to the symbol, magnified by a factor of 2 to avoid fractions.
n is the distance to the point (0,30), which is the center of the outward-going arcs (2F=30)
20 < a < 27 && n < 19 is the ring around the center: 2(E-A) < a < 2(E-A+B) and n < G-2A
a > 6 && Abs[z] < 30 && n > 21 && u > 1 && (u > 4 || Re@z < -2) is the main structure of the symbol:

a > D clears out the central hole
Abs[z+22 - 2E] < H clears out anything beyond the outer edge of the arcs
n > G clears out the holes surrounded by the arcs
u > A clears the gaps in the symbol around the central hole
u > C || Re[z+22] < 20 cuts a gap into the tips of the arcs

Python 3 with pygame, 327 314 287 278 bytes
(Applied various nasty hacks to save 13 bytes; most notably no longer storing the color but calculating it on the fly with -(r>25))
(Refactored to function, losing sys; hacked out math in favour of coordinate constants; small tweaks; saved 27 bytes)
(Rewrote coordinate constants to complex math tricks to get (co)sine, saving 9 bytes)
Function that takes a single integer argument representing half the width/height of the resulting image.
E.g. f(500) will create a 1000x1000 pixel window, and draw a biohazard symbol in there.
from pygame import*;D=display
def f(S):
 u=D.set_mode([S*2]*2);b=S>>6
 for p,r,w in(22,30,0),(30,20,0),(0,27,7),(30,21,2),(0,6,0),(51,4,0):
  for l in 0,4/3,8/3:Z=1j**l*p*b;q=S+int(Z.imag),S-int(Z.real);draw.circle(u,-(r>25),q,r*b,w*b);r-20or draw.line(u,0,(S,S),q,b*2);D.flip()

Unshortened version:
import pygame
import math
import sys

size = int(sys.argv[1])
basic = size // 55

screen = pygame.display.set_mode((size * 2, size * 2))

circles = [
    (22, 30, 0, -1),  # basic shape
    (30, 20, 0, 0),   # large cutouts
    (0, 27, 7, -1),   # "background circle"
    (30, 21, 2, 0),   # "background circle" clearance
    (0, 6, 0, 0),     # center disc
    (51, 4, 0, 0),    # blunt the points
]

for pos, radius, width, color in circles:
    for lobe in [0, math.pi * 2 / 3, math.pi * 4 / 3]:
        x = int(math.sin(lobe) * pos * basic) + size
        y = size - int(pos * basic * math.cos(lobe))
        pygame.draw.circle(screen, color, (x, y), radius * basic, width * basic)
        # Hack to draw the small slots in the center
        if radius == 20:
            pygame.draw.line(screen, 0, (size, size), (x, y), basic * 2)

pygame.display.flip()

The key to this program is mostly exploiting the 3-way point symmetry of the symbol, and expressing the drawing operations as sparsely as possible.
The heart of it all is circles, which is a list of circle definitions, consisting just of:

position: how far outwards from the origin in half basic units
radius: the radius of the circle in half basic units
width: the border width of the circle (inwards from the outer circle, 0 = fill)
color: exploiting the fact that pygame interprets 0 as black and -1 as white

Every drawing operation is repeated three times, rotated 120°.
The blunting of the "claws" is done with another circle.
The inside "line cuts" are special-cased because I couldn't think of a more efficient way to get them in there.
The "basic unit" defined in the specification is doubled here so I didn't have to use .5 in circles and int() all over the place to satisfy pygame.
Result for python3 -c 'from biohazard import *; f(500)':

Good job and welcome to CGCC! The description should say "Python 3 + pygame" when a non-builtin library is used. The input can be taken from standard input or as a function argument to avoid importing the sys module, which shortens the code (see rules). Also, this trick can be applied to avoid the need of importing math.

@Joel Thanks for the feedback! I included pygame in the header, and converted the code to a function. As for math, I refactored that to a list of coordinates; it was only 3 of them anyway. No (co)sine necessary.

Applying the above-mentioned trick actually saves more bytes than putting all the numbers into the source code.

@Joel Thanks for the reminder; earlier I discarded that option because it seemed longer but it looks like I was wrong. It also allowed some more optimizations.

C (gcc) (MinGW), 557 530 524 522 bytes
-27 -6 bytes thanks to ceilingcat
Added compiler option -lm on TiO strictly to be able to show how it runs. Under MinGW this is not necessary.
Takes width of image as a command line argument. Outputs a 3-shade greyscale PGM file to STDOUT. The circle drawing function is slightly longer than it could be, to avoid dreadful runtime on even moderately sized images, the positioning/scaling of the symbol is not perfect, and I suspect shuffling the draw order somewhat might squeeze some more out of this, so there is room for improvement for sure.
Everything is drawn as circles. The rectangular cutouts are painted using the circle drawing function as a moving brush.
char*I;q,j=5,r,c;N(n){n="F=**(..*(C/)F<<*>FF)"[j*4+n]-40;}float d,b,m,x,y,V=2.0944;C(x,y,R,t,z)float x,y,R,t;{for(r=y<R?0:y-R;r<=y+R;r++)for(c=x-R;c<=x+R;c++)d=hypot(c-x,r-y),d<R&d>=R-t?I[r*q+c]=z:0;}main(i,v)int**v;{q=atoi(v[1]);b=q/104.;m=q/2.;for(I=memset(calloc(q,q+1),2,q*q);i=j--;)for(x=0;x<7;x+=V)C(m+cos(x)-N(0)*b*sin(x),m-N(0)*b*cos(x)+sin(x),N(1)*b,N(2)*b,N(3));for(;i<3;i++)for(j=m;j--;C(m-x,m-y,d,d=d>4*b&d<10*b?b:d>50*b?b*4:0,2))d=hypot(x=j*sin(x)-cos(x),y=j*cos(x=i*V)-sin(x));printf("P5 %d %d 2 %s",q,q,I);}

Try it online!

@ceilingcat Quite the improvement!

Tcl/Tk - 557 bytes
set F #000
set B #F50
pack [canvas .c -bg $B]
rename expr e
rename foreach f
rename proc p
p R r {list [e $r*cos($::a)] [e $r*sin($::a)]}
p D {d r} {lassign [R $d] x y;list [e $x-$r] [e $y-$r] [e $x+$r] [e $y+$r]}
p C {d r c} {.c cr o {*}[D $d $r] -f $c -outline $c}
p L {p q w} {.c cr l {*}[R $p] {*}[R $q] -w [e $w] -f $::B}
p A {d r w c} {.c cr a {*}[D $d $r] -w [e $w] -star 0 -ex 359.9 -sty arc -outline $c}
f x {{C 11 15 $F} {C 15 10.5 $B} {L 0 5 1} {L 20 40 4} {C 0 3 $B} {A 0 11.75 3.5 $F} {A 15 10 1 $B}} {f a {2.62 4.72 6.81} $x}
.c move all 99 99

That version, however, is boring, since you get the same small-sized image no matter what.
It does satisfy the OP conditions for displaying on-screen, however.
Here is the uncompressed version with commentary and the ability to specify a size added in:
# Input: command line argument is the pixel width (same as the height) of the window to create
# For example:
#   wish a.tcl 500
set window_size $argv

set foreground_color #000
set background_color #F50
pack [canvas .c -bg $background_color -width $window_size -height $window_size]

# Helper procs to generate x,y coordinates
proc radius->x,y r {
  list [expr {$r*cos($::angle)}] [expr {$r*sin($::angle)}]
}

proc center_offset,radius->rectangle {offset r} {
  lassign [radius->x,y $offset] x y
  list [expr {$x-$r}] [expr {$y-$r}] [expr {$x+$r}] [expr {$y+$r}]
}

# Tk's canvas does not scale line widths, so we have to do that manually
# The $scale is a global variable for compressing the code text above
set scale [expr {$window_size*.016}]

# These three procs draw items in the canvas
proc circle {offset r color} {
  .c create oval {*}[center_offset,radius->rectangle $offset $r] -fill $color -outline $color
}
proc line {p q w} {
  .c create line {*}[radius->x,y $p] {*}[radius->x,y $q] -width [expr {$::scale*$w}] -fill $::background_color
}
proc annulus {offset r w color} {
  .c create arc {*}[center_offset,radius->rectangle $offset $r] -width [expr {$::scale*$w}] -start 0 -extent 359.9 -style arc -outline $color
}

# Our list of shapes to draw
#  circle  center_offset, radius,                   color
#  line    end_offset_1,  end_offset_2, line_width
#  annulus center_offset, radius,       line_width, color
foreach command {
  {circle  11 15        $foreground_color}
  {circle  15 10.5      $background_color}
  {line     0  5    1}
  {line    20 40    4}
  {circle   0  3        $background_color}
  {annulus  0 11.75 3.5 $foreground_color}
  {annulus 15 10    1   $background_color}
} {
  # Each command gets applied thrice, rotated $angle radians each time
  foreach angle {2.62 4.72 6.81} $command
}

.c scale all 0 0 $scale $scale
.c move all [expr {$window_size/2}] [expr {$window_size/2}]

# Some random convenience stuff for playing with it
bind . <Escape> exit
after 500 {focus -force .}

Sorry, no pictures (working off my phone today). Produces a black symbol on a biohazard orange background.

Scratch, 423 bytes
Try it online!
Surprisingly, Scratch beats more than 0 other langauges! Alternatively, 46 blocks.
define T(o
turn cw(o)degrees
define P(s
set pen size to(s
define (d)(r)(t)(c
set pen color to(c
P(1
repeat(3
move(d)steps
repeat(360
move(r)steps
pen down
move(t)steps
pen up
move(()-((r)+(t)))steps
T(1
end
move(()-(d))steps
T(120
when gf clicked
repeat(2
point in direction(0
erase all
(22)()(30)(
(30)()(19)(#fff
repeat(3
P(2
pen down
move(52)steps
P(8
pen down
pen up
go to x()y(
T(120
()(20)(7)(
()()(6)(#fff
(30)(19)(2)(#fff

Explanation
Definitions
define T(o                Obligatory hat block
turn cw(o)degrees         Rotate clockwise a specified amount of degrees

define P(s                Obligatory hat block
set pen size to(s         Sets pen size to a specified amount

define (d)(r)(t)(c        d=distance, r=radius, t=thickness (of ring), c=color
set pen color to(c        Sets pen to a specified color
P(1                       Sets pen size to be 1 pixel in diameter
repeat(3                  Loops code for each circle
move(d)steps              Moves a specified distance away from the center
repeat(360                Loops code for each ray being drawn in a circle
move(r)steps              Moves to the inner edge of the ring, without applying pen
pen down                  Begins to apply pen
move(t)steps              Applies pen for the specified thickness of the ring
pen up                    Stops applying the pen
move(()-((r)+(t)))steps   Moves back to the center of the circle being drawn
T(1                       Rotates 1 degree clockwise
end                       Ends code to be  looped
go to x()y(               Moves to the center
T(120                     Rotates in preparation of next circle

Construction
when gf clicked        Initiates code
repeat(2               Loops code twice, skipping the need to move to the origin.
point in direction(0   Resets angle
erase all              Clears stage
(22)()(30)(            Draws 3 black circles 22 pixels from the center, with a radius of 30
(30)()(19)(#fff        Draws 3 white circles 30 pixels from the center, with a radius of 19
repeat(3               Loops code for each break to be made
P(2                    Sets pen size to 2 pixels in diameter
pen down               Applies pen
move(52)steps          Draws a white line from the center
P(8                    Sets pen size to 8 pixels in diameter
pen down               Applies pen, creating the gap in the outer rings
pen up                 Removes pen
go to x()y(            Moves to the origin
T(120                  Rotates 120 degrees clockwise
()(20)(7)(             Draws a black ring 7 pixels thick with an internal radius of 20 pixels
()()(6)(#fff           Draws a white circle with a 6 pixel radius
(30)(19)(2)(#fff       Draws 3 white rings 30 pixels from the center, 2 pixels thick, and an internal radius of 29 pixels

C (GCC), 319 bytes
#define q(i)x*x+(y-i)*(y-i)main(k,w,i,j,z){scanf("%d",&k);i=w=65*k;float x,y,s;for(printf("P5\n%d %d\n1\n",2*w,2*w);i-->-w;)for(j=-w;j++<w;putchar((q(22)>900|q(30)<441|q(0)<36|(s=labs(x))<1|s<4&y>30)&(q(0)<400|q(0)>729)|q(30)<441&q(30)>400))s=sqrt(3),z=i<0|abs(j)>s*i,s/=j>0?2:-2,x=(z?i*s+j/2.:j)/k,y=(z?j*s-i/2.:i)/k;}
Attempt This Online!
Takes the scale factor (a positive integer) from stdin, and outputs on stdout a binary (black and white) PGM image.
Formatted version:
// q(i) == x^2 + (y-i)^2
// used to draw circles of center (x,y-i)
#define q(i)x*x+(y-i)*(y-i)

main(k,w,i,j,z){
    scanf("%d",&k);
    i=w=65*k;
    float x,y,s;

    // PPM header
    printf("P5\n%d %d\n1\n",2*w,2*w);

    for(;i-->-w;)
        for(j=-w;j++<w;)

            // rotates the points of the bottom part by +120 or -120 degrees
            s=sqrt(3),
            z=i<0|abs(j)>s*i,
            s/=j>0?2:-2,
            x=(z?i*s+j/2.:j)/k,
            y=(z?j*s-i/2.:i)/k,

            putchar((q(22)>900|q(30)<441|q(0)<36|(s=labs(x))<1|s<4&y>30)&(q(0)<400|q(0)>729)|q(30)<441&q(30)>400);
}

PostScript, 198 106 bytes
00000000: 3520 3592 8b88 3c36 3092 ad32 7b33 7b39  5 5...<60..2{3{9
00000010: 7b30 7d92 8333 3088 1532 3735 2e35 884f  {0}..30..275.5.O
00000020: 9205 3232 881e 3832 2e33 8754 0192 0636  ..22..82.3.T...6
00000030: 8800 3730 2e35 9205 9242 924e 3330 8813  ..70.5...B.N30..
00000040: 3088 ff92 0592 1492 6f88 1b30 885a 9205  0.......o..0.Z..
00000050: 3230 885a 3092 0692 4292 4d88 7892 887d  20.Z0...B.M.x..}
00000060: 9283 88ff 3192 8b7d 9283                 ....1..}..

Before tokenization:
5 5 scale 60 60 translate
2{3{9{0}repeat 30 21 275.5 79 arc 22 30 82.3 340 arcn
6 0 70.5 arc fill gsave 30 19 0 -1 arc clip newpath
27 0 90 arc 20 90 0 arcn fill
grestore 120 rotate}repeat -1 1 scale}repeat

This draws 1/6 of the shape at a time:
Final output:

JavaScript, 193 189 183 bytes
(x,y,t=(r,c=0)=>(R=(u,v=y-c/2)=>u*u+v*v<r*r)(x,y+c)|R(x+(X=c*.75**.5))|R(x-X))=>t(15,11)&!(t(10.5,15)|t(3)|((y<0?4*x*x:((x*x)**.5-y*3**.5)**2)<(y*y>36?16:1)))|t(13.5)&!t(10)&t(9.5,15)

A pixel shader taking x and y centred around [0, 0] to the scale of the spec. Outputs truthy or falsey depending on whether to draw the pixel.
Ungolfed and explained:
(x, y, // the current pixel
  t = ( // define a func 't' to check if pixel is in any of 3 circles around centre
      r,    // radius of circle
      c = 0 // distance from centre
    ) => ( // define a func 'R' to check if pixel inside a circle
        R = (u, v = y - c / 2) => u ** 2 + v ** 2 < r ** 2
    )(x, y + c) | // call 'R' on each circle centre
    R(x + (X = c * Math.sqrt(3) / 2)) | // use default y
    R(x - X) // use default y
) =>
  t(15, 11) & // 3 largest circles
  !(
    t(10.5, 15) | // large circle cutouts
    t(3) |        // tiny centre circle
    ((y < 0 ? // remove gaps
      4 * x ** 2 : // top half
      (Math.abs(x) - y * Math.sqrt(3)) ** 2) < // bottom half
    (y ** 2 > 36 ? 16 : 1))) | // a bit of pythagoras
  t(13.5) &  // pixel inside ring
  !t(10) &   // (ring inner)
  t(9.5, 15) // (ring cut-away)

shader =
  (x,y,t=(r,c=0)=>(R=(u,v=y-c/2)=>u*u+v*v<r*r)(x,y+c)|R(x+(X=c*.75**.5))|R(x-X))=>t(15,11)&!(t(10.5,15)|t(3)|((y<0?4*x*x:((x*x)**.5-y*3**.5)**2)<(y*y>36?16:1)))|t(13.5)&!t(10)&t(9.5,15)

const size = 400;
const scale = 60;
const ratio = scale / size;

const canvas = document.getElementById('canvas');
canvas.width = canvas.height = size;
const ctx = canvas.getContext('2d');

let x, y;
for (x = 0; x < size; x++) for (y = 0; y < size; y++) {
  ctx.fillStyle = shader((x - size / 2) * ratio, (y - size / 2) * ratio) ? 'black' : 'orangered';
  ctx.fillRect(x, y, 1, 1);
}
<canvas id="canvas"/>


text:
What's this constructed number's starter?
A number of programming languages construct large integers through 'concatenating' the digit to the end of the existing number. For example, Labyrinth, or Adapt. By concatenating the digit to the end, I mean that, if the existing number is \$45\$, and the digit is \$7\$, the result number is \$457\:(45 \times 10 + 7)\$.
A constructed number is a number that can be built this way through the use of the multiples of single digit numbers: \$1, 2, 3, 4, 5, 6, 7, 8, 9\$ A.K.A an element in one of these 9 sequences:
$$1, 12, 123, 1234, 12345, \: \dots$$
$$2, 24, 246, 2468, 24690, \: \dots$$
$$3, 36, 369, 3702, 37035, \: \dots$$
$$4, 48, 492, 4936, 49380, \: \dots$$
$$5, 60, 615, 6170, 61725, \: \dots$$
$$6, 72, 738, 7404, 74070, \: \dots$$
$$7, 84, 861, 8638, 86415, \: \dots$$
$$8, 96, 984, 9872, 98760, \: \dots$$
$$9, 108, 1107, 11106, 111105, \: \dots$$
To provide an example of how the sequences are constructed, here's how the sequence for \$a = 3\$ in constructed:
$$\begin{align}
u_1 = && a = && 3 & = 3\\
u_2 = && 10 \times u_1 + 2 \times a = && 30 + 6 & = 36 \\
u_3 = && 10 \times u_2 + 3 \times a = && 360 + 9 & = 369 \\
u_4 = && 10 \times u_3 + 4 \times a = && 3690 + 12 & = 3702 \\
u_5 = && 10 \times u_4 + 5 \times a = && 37020 + 15 & = 37035 \\
u_6 = && 10 \times u_5 + 6 \times a = && 370350 + 18 & = 370368 \\
\end{align}$$
$$\vdots$$
$$\begin{align}
u_{33} = && 10 \times u_{32} + 33 \times a = && 37\dots260 + 99 & = 37\dots359 \\
u_{34} = && 10 \times u_{33} + 34 \times a = && 37\dots359 + 102 & = 37\dots3692
\end{align}$$
$$\vdots$$
\$u_{33}\$ and \$u_{34}\$ included to demonstrate when \$n \times a \ge 100\$. A lot of digits dotted out for space.
It may still not be clear how these sequences are constructed, so here are two different ways to understand them:

Each sequence starts from the single digit. The next term is found by taking the next multiple of that digit, multiplying the previous term by \$10\$ and adding the multiple. In sequence terms:
$$u_n = 10 \times u_{n-1} + n \times a,  \: \: u_1 = a$$
where \$a\$ is a single digit (\$1\$ through \$9\$)

Each of the \$9\$ elements at any point in the sequence (take \$n = 3\$ for instance) are the multiples of \$123\dots\$ from \$1\$ to \$9\$, where \$123\dots\$ is constructed by \$u_{n+1} = 10 \times u_n + n\$ \$(1, 12, 123, \dots, 123456789, 1234567900, 12345679011, \dots)\$
So the first values are \$1 \times 1, 2, 3, \dots, 8, 9\$, the second are \$12 \times 1, 2, 3, \dots, 8, 9\$, the third \$123 \times 1, 2, 3, \dots, 8, 9\$, etc.

Your task is to take a constructed number as input and to output the initial digit used to construct it. You can assume the input will always be a constructed number, and will be greater than \$0\$. It may be a single digit, which maps back to itself.
You may take input in any reasonable manner, including as a list of digits, as a string etc. It is acceptable (though not recommended) to take input in unary, or any other base of your choosing.
This is a code-golf so the shortest code wins!
Test cases
       u_n        => a
 37035            => 3
 6172839506165    => 5
 5                => 5
 246913580244     => 2
 987654312        => 8
 61728395061720   => 5
 1111104          => 9
 11111103         => 9
 111111102        => 9
 2469134          => 2
 98760            => 8
 8641975308641962 => 7

or as two lists:
[37035, 6172839506165, 5, 246913580244, 987654312, 61728395061720, 1111104, 11111103, 111111102, 2469134, 98760, 8641975308641962]
[3, 5, 5, 2, 8, 5, 9, 9, 9, 2, 8, 7]

When I posted this challenge, I didn't realise it could be simplified so much by the method used in Grimmy's answer, and so therefore would be very interested in answers that take a more mathematical approach to solving this, rather than a 'digit' trick (Obviously all valid answers are equally valid, just what I'd be interested in seeing).

Sandbox post. I have a 9 byte solution in Jelly, if anyone wants to challenge that.

05AB1E, 7 5 4 bytes
>9*н

Try it online!
>            # input + 1
 9*          # * 9
   н         # take the first digit

The \$(n-1)^{th}\$ term of the sequence starting with \$a\$ is \$\sum _{i=1}^{n-1} a \times i \times 10^{i-1} = a \times \frac{(10^n - 1) / 9 - n}{9}\$. Multiply that by \$9\$ and add \$a\times n\$, and you get \$a \times \frac{10^n - 1}{9}\$, aka the digit \$a\$ repeated \$n\$ times. Turns out adding \$9\$ instead of \$a\times n\$ works for \$n=1\$, and for bigger \$n\$ the linear difference is negligible next to the exponential growth.

Hmm, that doesn't bode well for this challenge if it can be simplified that easily

You have approximately 1 byte of code for 800 bytes of challenge explanation. :p

How do you come up with the solution and why is it correct?

@Joel the (n-1)th term of the sequence starting with a is a * (((10**n - 1) / 9 - n) / 9). Multiply that by 9 and add a*n, and you get  a * ((10**n - 1) / 9), aka the digit a repeated n times. Turns out adding 9 instead of a*n works for n=1, and for bigger n the constant difference is negligible next to the exponential growth.

@Grimy Thanks a lot for the explanation. Maybe you can put it into your post.

Candidate for the best mathematical insight 2019? ;)

Nominated as promised :)

@KevinCruijssen thanks! i’m a MathJax noob.

@Grimmy I was the same first, but creating challenges like this and this improved that quite a bit, haha. xD Also, here is a great cheat-sheet I use pretty often.

Python 3, 22 bytes
lambda i:str(-~i*9)[0]

Try it online!
Port of Grimy's 05AB1E answer

Python 3, 72 bytes
f=lambda i,j=1,l=1,k=2:l*(i==j)or f(i,*(10*j+k*l,l+1,l,l+1,k+1)[i<j::2])

Try it online!
Explanation
Recursive function. Iterates over the sequence for each digit l, starting at 1. If the input i is equal to the current iteration j, the corresponding digit l is returned. Else, if the current value j in the sequence exceeds the input value i, it will increment the digit l and start over. Argument k is used to increment the multiplication factor.

Stax, 5 bytes
^9*Eh

Run and debug it

Labyrinth,  28 22  20 bytes
9 10/;!@
? _ :
)*"""

Applies the digit-based method described by Grimy by repeated integer division by ten until zero is found.
Try it online!

Charcoal, 7 bytes
§Ｉ×⁹⊕Ｎ⁰

Try it online! Link is to verbose version of code. @Grimy's method of course. Here's a 27 byte mathematical approach:
ＮθＷ¬№Ｅχ×κ↨υχθ⊞υＬυＩ⌕Ｅχ×ι↨υχθ

Try it online! Link is to verbose version of code. Crashes on invalid inputs. Explanation:
Ｎθ

Input the constructed number.
Ｗ¬№Ｅχ×κ↨υχθ

Interpret the list as a number in base 10, multiply by all numbers from 0 to 9, and see whether the constructed number appears.
⊞υＬυ

Push the list's length to itself. The list therefore becomes of the form [0, 1, 2, ..., n].
Ｉ⌕Ｅχ×ι↨υχθ

Recreate the constructed numbers but this time find and output the index at which the input number appeared.

MathGolf, 6 bytes
)9*▒├Þ

Try it online!
Unfortunately, there's no head operation in MathGolf, so I have to make do with ▒├Þ to convert to string, pop from the left and discard all but the top of stack.

Japt -g, 7 6 5 bytes
-1 byte thanks to Shaggy
Takes input as a string
i°U*9

Try it | Test multiple inputs

5 bytes, taking input as a string.

Jelly, 5 bytes
‘×9DḢ

Try it online!
Using Grimy's approach.

Java 8, 23 bytes
n->(n*9+9+"").charAt(0)

Port of @Grimy's 05AB1E answer, so make sure to upvote him!
Try it online.
But because I kinda feel bad for @cairdCoinheringaahing, here a brute-force approach with a bit more afford (83 bytes):
n->{long r=n,a=0,u,k;for(;++a<10;r=u>n?r:a)for(k=2,u=a;u<n;)u=u*10+k++*a;return r;}

Try it online.
Explanation:
n->{                 // Method with long as both parameter and return-type
  long r=n,          //  Result, starting at the input in case it's already a single digit
       a=0,          //  The digit to start the sequence with
       u,            //  The last number of the sequence we're building for digit a
       k;            //  Multiplier which increments each iteration
  for(;++a<10;       //  Loop in the range [1,9] (over each digit):
      r=u>n?         //    After ever iteration: if `u` is larger than the input:
            r        //     Keep the result the same
           :         //    Else:
            a)       //     Change the result to `a`
    for(k=2,         //   Reset `k` to 2
        u=a;         //   Reset `u` to the current digit `a`
        u<n;)        //   Inner loop as long as `u` is smaller than the input
      u=             //    Change `u` to:
        u*10         //     10 times the current `u`
            +k++*a;  //     With `k` multiplied by `a` added
                     //     (after which `k` increases by 1 with `k++`)
  return r;}         //  And after we iterated over each digit, return the result

Whitespace, 108 bytes
[S S S N
_Push_0][S N
S _Duplicate_0][T   N
T   T   _Read_STDIN_as_integer][T   T   T   _Retrieve_input][S S S T    N
_Push_1][T  S S S _Add][S S S T S S T   N
_Push_9][T  S S N
_Multiply][S S S T  N
_Push_1][N
S S N
_Create_Label_LOOP][S S S T S T S N
_Push_10][T S S N
_Multiply][S N
S _Duplicate][S T   S S S T S N
_Copy_0-based_2nd]S N
T   Swap_top_two][T S S T   _Subtract][N
T   T   S N
_If_neg_jump_to_Label_PRINT][N
S N
N
_Jump_to_Label_LOOP][N
S S S N
_Create_Label_PRINT][S S S T    S T S N
_Push_10][T S T S _Integer_divide][T    S T S _Integer_divide][T    N
S T _Output_top_as_number]

Letters S (space), T (tab), and N (new-line) added as highlighting only.
[..._some_action] added as explanation only.
Port of @Grimy's 05AB1E answer, except that I don't have a builtin to get the first digit. ;)
Try it online (with raw spaces, tabs and new-lines only).
Explanation in pseudo-code:
Integer i = STDIN as integer
i = i + 1
i = i * 9
Integer t = 1
Start LOOP:
  t = t * 10
  If(i - t < 0):
    Call function PRINT
  Go to next iteration of LOOP

function PRINT:
  t = t / 10
  i = i / t    (NOTE: Whitespace only has integer-division)
  Print i as integer to STDOUT

Hy, 44 bytes
(defn a[p](print(get(str(*(+(int p)1)9))0)))

Uses Grimy's method
Try it online!

JavaScript (ES6),  16  15 bytes
Thanks to @Grimy for lifting the 32-bit constraint I had with the previous version.
Using Grimy's magical incantation. Takes input as a string.
n=>(n*9+9+n)[0]

Try it online!

JavaScript (ES6), 53 bytes
Naive brute force approach.
n=>(g=(k,x=i=0)=>x>n?g(k+1):x<n?g(k,++i*k+10*x):k)(1)

Try it online!

-~n*9 can be n*9+9, which is the same bytecount but should get rid of the 32-bit limitation if I understood correctly.

the brute force works for a>=10, like 14808

@NahuelFouilleul if we consider a>=10, the answer is no longer unique (14808 could be either the 4th term of a=12, or the first term of a=14808). If outputting any of those is allowed, n=>n works for all inputs.

PHP, 20 bytes
<?=(_.++$argn*9)[1];

Try it online!
Yet another Grimy's answer port!

Jelly, 8 bytes
RRḌ÷@fⱮ9

Try it online!
A full program that takes an integer and prints the starter digit. Doesn’t use Grimy’s clever method! Terribly inefficient for larger input. The following version handles all of the test cases but is a byte longer:
Jelly, 9 bytes
DJRḌ÷@fⱮ9

Try it online!

Keg -rr, 4 bytes
⑨9*÷

Try it online!
Of course, uses the same approach as the 05AB1E answer. Also uses the new -rr (reverse and print raw) flag.
Transpiles to:
from KegLib import *
from Stackd import Stack
stack = Stack()
printed = False
increment(stack)
integer(stack, 9)
maths(stack, '*')
item_split(stack)
if not printed:
    reverse(stack)
    raw(stack)

Wren, 30 bytes
Just a port of most answers.
Fn.new{|i|(i*9+9).toString[0]}

Try it online!

W h, 3 bytes
)9*

Explanation
)   % Increment by 1
 9* % Multiply by 9

Flag:h % Take the first item of the result
```

cQuents, 10 bytes
D9*_+$)[0]

Try it online!
Just another port of Grimmy's answer.
     $     # Index
   _+      # +1
 9*        # *9
D     )[0] # First digit

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Infinitely many primes
Since Euclid, we have known that there are infinitely many primes. The argument is by contradiction: If there are only finitely many, let's say \$p_1,p_2,...,p_n\$, then surely \$m:=p_1\cdot p_2\cdot...\cdot p_n+1\$ is not divisible by any of these primes, so its prime factorization must yield a new prime that was not in the list. So the assumption that only finitely primes exist is false.
Now let's assume that \$2\$ is the only prime. The method from above yields \$2+1=3\$ as a new (possible) prime. Applying the method again yields \$2\cdot 3+1=7\$, and then \$2\cdot 3\cdot 7+1=43\$, then \$2\cdot 3\cdot 7\cdot 43+1=13\cdot 139\$, so both \$13\$ and \$139\$ are new primes, etc. In the case where we get a composite number, we just take the least new prime. This results in A000945.
Challenge
Given a prime \$p_1\$ and an integer \$n\$ calculate the \$n\$-th term \$p_n\$ of the sequence defined as follows:
$$p_n := \min(\operatorname{primefactors}(p_1\cdot p_2\cdot ... \cdot p_{n-1} + 1))$$
These sequences are known as Euclid-Mullin-sequences.
Examples
For \$p_1 = 2\$:
1 2
2 3
3 7
4 43
5 13
6 53
7 5
8 6221671
9 38709183810571

For \$p_1 = 5\$ (A051308):
1 5
2 2
3 11
4 3
5 331
6 19
7 199
8 53
9 21888927391

For \$p_1 = 97\$  (A051330)
1 97
2 2
3 3
4 11
5 19
6 7
7 461
8 719
9 5

JavaScript (ES6),  45  44 bytes
Takes input as (n)(p1), where \$n\$ is 0-indexed.
n=>g=(p,d=2)=>n?~p%d?g(p,d+1):--n?g(p*d):d:p

Try it online!
Commented
n =>                // n = 0-based index of the requested term
  g = (             // g is a recursive function taking:
    p,              //   p = current prime product
    d = 2           //   d = current divisor
  ) =>              //
    n ?             // if n is not equal to 0:
      ~p % d ?      //   if d is not a divisor of ~p (i.e. not a divisor of p + 1):
        g(p, d + 1) //     increment d until it is
      :             //   else:
        --n ?       //     decrement n; if it's still not equal to 0:
          g(p * d)  //       do a recursive call with the updated prime product
        :           //     else:
          d         //       stop recursion and return d
    :               // else:
      p             //   don't do any recursion and return p right away

05AB1E, 6 bytes
This produces and infinite output stream.
λλP>fW

Try it online! (link includes a slightly modified version, λ£λP>fW, which instead outputs the first \$n\$ terms)
Explanation
Very straightforward. Given \$p_1\$ and \$n\$, the program does the following:

Starts with \$p_1\$ as an initial parameter for the infinite stream (which is generated using the first λ) and begins a recursive environment which generates a new term after each interation and appends it to the stream.
The second λ, now being used inside the recursive environment, changes its functionality: Now, it retrieves all previously generated elements (i.e. the list \$[\lambda_0, \lambda_1, \lambda_2, \ldots, \lambda_{n-1}]\$), where \$n\$ represents the current iteration number.
The rest is trivial: P takes the product (\$\lambda_0\lambda_1\lambda_2 \cdots \lambda_{n-1}\$), > adds one to this product, and fW retrieves the minimum prime factor.

J, 15 bytes
-10 bytes thanks to miles!
Returning the sequence up to n (zero-indexed) – thanks to @miles
(,0({q:)1+*/)^:

Try it online!
J, 25 bytes
Returns the n th item
_2{((],0{[:q:1+*/@])^:[])

Try it online!

(,0({q:)1+*/)^: for 15 bytes, returning the sequence up to n (zero-indexed)

Very nice.  @miles what exactly is happening there grammatically? we put a verb and a conjunction together and get a dyadic verb back.  I thought verb conj produced an adverb.

@Jonah it's a trick I learned from golfing. I think it's one of the older parsing rules that's still valid

@miles I just realized it is an adverb (or adnoun).  It modifies the noun to its left, which "attaches" to the right of the ^:, and then that becomes a verb that applies to the right arg.  I think that's what's happening grammatically.

Python 2, 56 bytes
i=input();k=1
while 1:
 k*=i;print i;i=2
 while~k%i:i+=1

Try it online!

Commented
i=input() # the initial prime
k=1       # the product of all previous primes
while 1:  # infinite loop
 k*=i     # update the product of primes
 print i  # output the last prime
 i=2      # starting at two ...
 while~k%i: # find the lowest number that divides k+1
  i+=1
            # this our new prime

Try it online!

I just started with Python, but do you need int(input()) otherwise i is a str?

In Python 3 this would be true as input() always returns strings. In Python 2 input() tries to evaluate the input. I'm using Python 2 in this case because the resulting code is slightly shorter. For real code you should try to use Python 3 as it is the newer and more supported version of Python.

How does this terminate after n steps?

@sintax it outputs the sequence for a given p1 indefinitely, as allowed by the default sequence rules.

Jelly, 8 bytes
P‘ÆfṂṭµ¡

A full program (using zero indexing) accepting \$P_0\$ and \$n\$ which prints a Jelly representation of the list of \$P_0\$ to \$P_n\$ inclusive. (As a dyadic Link, with n=0 we'll be given back an integer, not a list.)
Try it online!
How?
P‘ÆfṂṭµ¡ - Link: integer, p0; integer n
      µ¡ - repeat the monadic chain to the left n times, starting with x=p0:
P        -   product of x (p0->p0 or [p0,...,pm]->pm*...*p0)
 ‘       -   increment
  Æf     -   prime factors
    Ṃ    -   minimum
     ṭ   -   tack
         - implicit print

05AB1E, 8 bytes
GDˆ¯P>fß

First input is \$n\$, second is prime \$p\$.
Try it online or very some more test cases (test suite lacks the test cases for \$n\geq9\$, because for \$p=2\$ and \$p=5\$ the builtin f takes too long).
Explanation:
G         # Loop (implicit input) n-1 amount of times:
 Dˆ       #  Add a copy of the number at the top of the stack to the global array
          #  (which will take the second input p implicitly the first iteration)
   ¯      #  Push the entire global array
    P     #  Take the product of this list
     >    #  Increase it by 1
      f   #  Get the prime factors of this number (without counting duplicates)
       ß  #  Pop and only leave the smallest prime factor
          # (after the loop: implicitly output the top of the stack as result)

I had λλP>fW (6 bytes) with output as an infinite list and λ£λP>fW (7 bytes) for the first $n$ terms. However getting the $n^{\text{th}}$ should be 9 bytes... If only we had a flag like £ but for the last element!

@Mr.Xcoder "If only we had a flag like £ but for the last element!", like .£? ;) EDIT: Actually, it doesn't work exactly like £ for lists.. using a list like [1,2] with .£ results in two loose items with the last 1 and 2 items (i.e. 12345 becomes [5,45] instead of [45,3] or [3,45], with 12S.£)..

Umm, no, I don't see how λ.£ should work. I used flag as in additional function associated with λ (see this conversation with Adnan). I basically want some flag è such that when running λè...} it would generate the n-th element rather than the the infinite stream (just like λ£ would work for generating the first n elements).

@Mr.Xcoder Ah sorry, you've used the £ for the recursive environment. Yeah, then λ.£ is indeed not gonna work, my bad. Nice 6-byter regardless. Now you just have to wait for @flawr's response whether it's allowed or not (it probably is).

Japt, 12 11 bytes
Struggled to get this one right so may have missed something that can be golfed.
Takes n as the first input and p1, as a singleton array, as the second. Returns the first n terms. Change h to g to return the nth 0-indexed term instead.
@Z×Ä k Î}hV

Try it
@Z×Ä k Î}hV     :Implicit input of integer U=n & array V=[p1]
@               :Function taking an array as an argument via parameter Z
 Z×             :  Reduce Z by multiplication
   Ä            :  Add 1
     k          :  Prime factors
       Î        :  First element
        }       :End function
         hV     :Run that function, passing V as Z, and
                : push the result to V.
                : Repeat until V is of length U

Retina, 56 bytes
,|$
$*
"$&"{~`.+¶
$$¶_
)`\b(__+?)\1*$
$.1$*
1A`
.$

\*
,

Try it online! Takes input as the number of new terms to add on the first line and the seed term(s) on the second line. Note: Gets very slow since it uses unary factorisation so it needs to create a string of the relevant length. Explanation:
,|$
$*

Replace the commas in the seed terms with *s and append a *. This creates a Retina expression for a string of length of the product of the values.
"$&"{
)`

Repeat the loop the number of times given by the first input.
~`.+¶
$$¶_

Temporarily replace the number on the first line with a $ and prepend a _ to the second line, then evaluate the result as a Retina program, thus appending a string of _s of length 1 more than the product of the values.
\b(__+?)\1*$
$.1$*

Find the smallest nontrivial factor of the number in decimal and append a * ready for the next loop.
1A`

Delete the iteration input.
.$

Delete the last *.
\*
,

Replace the remaining *s with ,s.

APL (Dyalog Extended), 15 bytes
This is a fairly simple implementation of the algorithm which uses Extended's very helpful prime factors builtin, ⍭. Try it online!
{⍵,⊃⍭1+×/⍵}⍣⎕⊢⎕

Explanation
{⍵,⊃⍭1+×/⍵}⍣⎕⊢⎕

             ⊢⎕  First get the first prime of the sequence S from input.
{         }⍣⎕    Then we repeat the code another input number of times.
     1+×/⍵       We take the product of S and add 1.
    ⍭            Get the prime factors of product(S)+1.
   ⊃             Get the first element, the smallest prime factor of prod(S)+1.
 ⍵,              And append it to S.

JavaScript (Node.js), 54 bytes
f=(p,n,P=p,F=n=>-~P%n?F(n+1):n)=>--n?f(p=F(2),n,P*p):p

Try it online!
Ungolfed
F=(p,n=2)=>            // Helper function F for finding the smallest prime factor
  p%n                  //   If n (starting at 2) doesn't divide p:
    ?F(n+1)            //     Test n+1 instead
    :n                 //   Otherwise, return n
f=(p,n,P=p)=>          // Main function f:
  --n                  //   Repeat n - 1 times:
    ?f(p=F(P+1),n,P*p) //     Find the next prime factor and update the product
    :p                 //   Return the last prime

bash +GNU coreutils, 89 bytes
IFS=\*;n=$1;shift;for((;++i<n;));{ set $@ `factor $["$*+1"]|cut -d\  -f2`;};echo ${@: -1}

TIO

Ruby 2.6, 51 bytes
f=->s,n{[s,l=(2..).find{|d|~s%d<1}][n]||f[l*s,n-1]}

(2..), the infinite range starting from 2, isn't supported on TIO yet.
This is a recursive function that takes a starting value s (can be a prime or composite), returns it when n=0 (edit: note that this means it's zero-indexed), returns the least number l that's greater than 1 and divides -(s+1) when n=1, and otherwise recurses with s=l*s and n=n-1.

You should probably mention that you're doing zero-indexed; I replaced (2..) with 2.step (just 1 byte longer) to allow it to work on TIO and everything was off by one. Try it online!

C (gcc), 54 53 bytes
p;f(x,n){for(p=x;--n;p*=x)for(x=1;~p%++x;);return x;}

Try it online!
-1 byte thanks to ceilingcat

Pari/GP, 45 bytes
(p,n)->s=p;for(i=2,n,s*=p=divisors(s+1)[2]);p

Try it online!

Stax, 9 bytes
é|G╝╓c£¼_

Run and debug it
Takes p0 and (zero-indexed) n for input.  Produces pn.

Perl 6, 33 32 bytes
-1 byte thanks to nwellnhof
{$_,{1+(2...-+^[*](@_)%%*)}...*}

Try it online!
Anonymous code block that takes a number and returns a lazy list.
Explanation:
{                              }  # Anonymous codeblock
                           ...*   # That returns an infinite list
 $_,                              # Starting with the input
    {                     }       # Where each element is
     1+(2...             )          # The first number above 2
                      %%*           # That cleanly divides
               [*](@_)                # The product of all numbers so far
            -+^                       # Plus one

Haskell, 49 bytes
g 1
g a b=b:g(a*b)([c|c<-[2..],1>mod(a*b+1)c]!!0)

Try it online!
Returns the infinite sequence as a lazy list.
Explanation:
g 1                                            -- Initialise the product as 1
g a b=                                         -- Given the product and the current number
       b:                                      -- Return the current number, followed by
         g                                     -- Recursively calliong the function with
          (a*b)                                -- The new product
               (                             ) -- And get the next number as
                [c|c<-[2..],             ]!!0  -- The first number above 2
                            1>mod       c      -- That cleanly divides
                                 (a*b+1)       -- The product plus one

Husk, 8 bytes
!¡ö←p→Π;

Try it online!
For input m,n outputs the n-th term in the sequence starting with m.
Drop the initial ! (for 7 bytes) to output the entire infinite sequence (this link selects the first 10 elements from the infinite list).
If both input & output are flexible enough (input: list of just the first term, output: infinite sequence) we could get down to 6 bytes.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/