Skip to main content
1 of 14
Alexey Popkov
  • 62.3k
  • 7
  • 154
  • 375

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]

output

Exporting to PDF and looking closer:

Export["plot.pdf", pl] // SystemOpen

screenshot

Looks perfect.

Alexey Popkov
  • 62.3k
  • 7
  • 154
  • 375