As Henrik Schumacher correctly points out in the comments, the stars on the plot produced by the naive application of the undocumented MeshFunctions -> {"ArcLength"}
option
do not look equidistantly spaced with respect to arclength
It took me a while to figure out what happens. The reason is that scales in the vertical and horizontal directions of the plot differ by an order of magnitude. I tried other plotting functions like ListPlot
, Plot
, ParametricPlot
and found that all of them also suffer from this issue.
The following approach solves the problem almost exactly. Small inaccuracy comes from the fact that I use AspectRatio
of the whole graphics instead of the actual aspect ratio of the plotting range with PlotRangePadding
included. But visually it is hardly noticeable. From the other hand, it isn't too difficult to improve this approach for obtaining exact result.
We start by defining our data1
:
b1={1.8743,1.8784,1.88248,1.89049,1.89828,1.90587,1.91327,1.96335,2.03035,2.12536,2.23701,2.30098,2.34255,2.37175,2.3934,2.42334,2.44307,2.48725,2.51208,2.5173,2.52799,2.53164,2.53348,2.53533,2.53625,2.53745,2.53793,2.53894,2.53909,2.53543};
ks1={0.01,1.,2.,4.,6.,8.,10.,25.,50.,100.,200.,300.,400.,500.,600.,800.,1000.,2000.,4000.,5000.,10000.,15000.,20000.,30000.,40000.,70000.,100000.,1.*10^6,1.*10^8,1.*10^12};
data1 = Transpose[{ks1, b1}];
Now define future AspectRatio
of the plot and log-transformed data1
(the Graphics
produced by ListLogLinearPlot
contains log-transformed data: it is just Ticks
what creates the illusion of logarithmic plot):
aspectRatio = 1./GoldenRatio;
data1Log = {Log@#1, #2} & @@@ data1;
Now create rescaling function and its inverse:
t = RescalingTransform[
MinMax /@ Transpose[data1Log], {{0, 1}, {0, aspectRatio}}];
tInv = InverseFunction[t];
This function makes vertical and horizontal scales almost equal (if necessary one can improve it for obtaining exact result).
Then we use MeshFunctions -> {"ArcLength"}
for generating the equidistantly spaced points with respect to arclength:
s2 = ListLinePlot[t[data1Log], PlotRange -> All,
MeshFunctions -> {"ArcLength"}, Mesh -> True];
Extracting the equidistant points and performing the inverse coordinate transform:
pts = tInv @@@ Cases[Normal[s2], _Point, -1];
Now we can use these coordinates for placing the stars in Epilog
:
ListLogLinearPlot[data1, Joined -> True,
PlotStyle -> {Black, Thickness[0.01]}, AxesStyle -> Black, PlotRange -> All,
Epilog -> {Red, Translate[Inset[Style["☆", 15, Bold], {0, 0}], pts]},
AspectRatio -> aspectRatio]
Voila! :)
UPDATE: I just accidentally found that I knew about this feature of MeshFunctions -> {"ArcLength"}
already several years ago but completely forgot due to non-use of this functionality. I can add to that old post that now we have the wonderful GraphicsInformation
function by Carl Woll which simplifies things considerably.