Here is an example of constructing purely vector figure using Region
functionality.
Input:
data = Table[{x, BesselJ[k, x]}, {k, 0, 4}, {x, 0, 10, 0.5}];
aspectRatio = 1/2;
markers = {"Circle", "ThreePointedStar", "FourPointedStar",
"DiagonalFourPointedStar", "FivePointedStar"};
colors = {Blue, Red, Green, Yellow, Orange};
background = Darker@Gray;
Auxiliary functions:
Clear[padPlotRange, rescaleCoords, rescaleCoordsBack, putMarker, \
createLineWithMarkers]
padPlotRange[xPadding_ : .01,
yPadding_ : .02][{{xMin_, xMax_}, {yMin_, yMax_}}] :=
Module[{xd, yd},
xd = (xMax - xMin)*xPadding;
yd = (yMax - yMin)*yPadding;
{{xMin - xd, xMax + xd}, {yMin - yd, yMax + yd}}
]
rescaleCoords[paddedPlotRange_, aspectRatio_][pts_] :=
Module[{xCoords = pts[[All, 1]], yCoords = pts[[All, 2]], xResc,
yResc},
xResc = Rescale[#, paddedPlotRange[[1]], {0, 1}] & /@ xCoords;
yResc =
Rescale[#, paddedPlotRange[[2]], {0, aspectRatio}] & /@ yCoords;
Transpose[{xResc, yResc}]
]
rescaleCoordsBack[paddedPlotRange_, aspectRatio_][pts_] :=
Module[{xCoords = pts[[All, 1]], yCoords = pts[[All, 2]], xResc,
yResc},
xResc = Rescale[#, {0, 1}, paddedPlotRange[[1]]] & /@ xCoords;
yResc =
Rescale[#, {0, aspectRatio}, paddedPlotRange[[2]]] & /@ yCoords;
Transpose[{xResc, yResc}]
]
putMarker[marker_Polygon][pts_] :=
Polygon /@ Table[# + vect & /@ marker[[1]], {vect, pts}];
createLineWithMarkers[marker_String, pts_, size_ : .02] :=
Module[{markerPrims, linePrims},
markerPrims =
putMarker[ResourceFunction["PolygonMarker"][marker, size]][pts];
linePrims =
MeshPrimitives[
RegionDifference[Line[pts], RegionUnion @@ markerPrims], 1];
Join[{CapForm[None]}, linePrims, markerPrims]
]
Plotting:
dataRange = MinMax /@ Transpose[Flatten[data, 1]];
paddedPlotRange = padPlotRange[.004, .0001]@dataRange;
dataResc = rescaleCoords[paddedPlotRange, aspectRatio] /@ data;
primitivesResc =
Table[{colors[[i]], FaceForm[None],
EdgeForm[{colors[[i]], AbsoluteThickness[1.5],
JoinForm[{"Miter", 6}]}],
createLineWithMarkers[markers[[i]], dataResc[[i]], .02]}, {i,
Length[dataResc]}];
primitives =
primitivesResc /. (h : Line | Polygon)[pts_] :>
h@rescaleCoordsBack[paddedPlotRange, aspectRatio][pts];
pl = Graphics[primitives, AspectRatio -> aspectRatio, ImageSize -> 500,
Frame -> True, Background -> background, FrameStyle -> White,
ImagePadding -> {{30, 20}, {25, 20}}, GridLines -> Automatic]
Exporting to PDF and looking closer:
Export["plot.pdf", pl] // SystemOpen
Looks perfect.