Использование только геометрии
Конечно, это можно победить, используя декартову геометрию.Единственная проблема заключается в том, что есть много дуг и пересечений для расчета.
Я сделал подход.Ограничение состоит в том, что он еще не обрабатывает «разветвленные» линии (например, деревья).
Некоторые примеры:
Расчет происходит мгновенно, но код является беспорядочным.
k[pp_] := Module[{ED(*TODO: make all symbols local*)}, (
(*follows some analytic geometry *)
(*Functions to calcu|late borderlines*)
linesIncrUpDown[{x0_, y0_}, {x1_, y1_}] :=
thk/2 {-(y1 - y0), (x1 - x0)}/ED[{x0, y0}, {x1, y1}];
lineUp[{{x0_, y0_}, {x1_, y1_}}] :=
Plus[linesIncrUpDown[{x0, y0}, {x1, y1}], #] & /@ {{x0, y0}, {x1,y1}};
lineDown[{{x0_, y0_}, {x1_, y1_}}] :=
Plus[-linesIncrUpDown[{x0, y0}, {x1, y1}], #] & /@ {{x0,y0}, {x1, y1}};
(*Distance from line to point*)
distanceLinePt[{{x1_, y1_}, {x2_, y2_}}, {x0_, y0_}] :=
Abs[(x2 - x1) (y1 - y0) - (x1 - x0) (y2 - y1)]/ED[{x1, y1}, {x2, y2}];
(*intersect between two lines without overflows for verticals*)
intersect[{{{x1_, y1_}, {x2_, y2_}}, {{x3_, y3_}, {x4_,
y4_}}}] := {((x3 - x4) (-x2 y1 + x1 y2) + (x1 - x2) (x4 y3 -
x3 y4))/(-(x3 - x4) (y1 - y2) + (x1 - x2) (y3 -
y4)), (-(x2 y1 - x1 y2) (y3 - y4) + (y1 - y2) (x4 y3 -
x3 y4))/(-(x3 - x4) (y1 - y2) + (x1 - x2) (y3 - y4))};
l2C := #[[1]] + I #[[2]] & ; (*list to complex for using Arg[]*);
ED = EuclideanDistance; (*shorthand*)
thk = Cases[pp, AbsoluteThickness[x_] -> x, Infinity][[1]];
lines = Cases[pp, Line[x_] -> x, Infinity][[1]];
isz = Cases[pp, Rule[ImageSize, x_] -> x, Infinity][[1]];
(*now get the scale *)
{minX, maxX} = {Min[#], Max[#]} &@Transpose[lines][[1]];
(*scale graphDiam +thk= isz *)
scale = (isz - thk)/(maxX - minX);
(*calculate absolute positions for lines*)
absL = (lines) scale + thk/2;
(*now we already got the centers for the circles*)
(*Calculate both lines Top Down*)
luT = Table[Line[lineUp[absL[[i ;; i + 1]]]], {i, Length[absL] - 1}];
luD = Table[Line[lineDown[absL[[i ;; i + 1]]]], {i, Length[absL] - 1}];
(*Calculate intersection points for Top and Down lines*)
iPuT =Table[intersect[{luT[[i, 1]], luT[[i + 1, 1]]}], {i,Length@luT - 1}];
iPuD =Table[intersect[{luD[[i, 1]], luD[[i + 1, 1]]}], {i,Length@luD - 1}];
(*beware drawArc has side effects as modifies luT and luD*)
drawArc[i_] := Module[{s},
Circle[absL[[i]], thk/2,
Switch[i,
1 , (*first point*)
If[ ED[absL[[i + 1]],absL[[i]] + {Cos[s = ((#[[2]] + #[[1]])/2)], Sin[s]}] <
ED[absL[[i + 1]],absL[[i]] + {Cos[s + Pi], Sin[s + Pi]}], # + Pi, #]
&@{Min@#, Max@#} &@
Mod[ {Arg[l2C @((luD[[i]])[[1, 1]] - absL[[i]])],
Arg[l2C @((luT[[i]])[[1, 1]] - absL[[i]])]}, 2 Pi],
Length@absL,(*last point*)
If[ED[absL[[i - 1]], absL[[i]] + {Cos[s = ((#[[2]] + #[[1]])/2)], Sin[s]}] <
ED[absL[[i - 1]], absL[[i]] + {Cos[s + Pi], Sin[s + Pi]}], # + Pi, #]
&@{Min@#, Max@#} &@
Mod[{Arg[l2C @((luD[[i - 1]])[[1, 2]] - absL[[i]])],
Arg[l2C@((luT[[i - 1]])[[1, 2]] - absL[[i]])]}, 2 Pi],
_,(*all middle points*)
(* here I must chose which lines to intersect luD or luT.
the correct answer is the line farthest to the previous point*)
If[
distanceLinePt[luD[[i, 1]], absL[[i - 1]]] >
distanceLinePt[luT[[i, 1]], absL[[i - 1]]],
(*shorten the other lines*)
luT[[i - 1, 1, 2]] = luT[[i, 1, 1]] = iPuT[[i - 1]]; lu = luD;
,
(*shorten the other lines*)
luD[[i - 1, 1, 2]] = luD[[i, 1, 1]] = iPuD[[i - 1]];
lu = luT;];
(If[ED[absL[[i - 1]], absL[[i]] + {Cos[s = ((#[[2]] + #[[1]])/2)], Sin[s]}] <
ED[absL[[i - 1]], absL[[i]] + {Cos[s + Pi], Sin[s + Pi]}], {#[[2]]-2 Pi, #[[1]]}, #])
&@{Min@#, Max@#} &@
{Arg[l2C @((lu[[i - 1]])[[1, 2]] - absL[[i]])],
Arg[l2C@((lu[[i]])[[1, 1]] - absL[[i]])]}
] ] ];
);
Graphics[{Black, Table[drawArc[i], {i, Length@absL}], Red, luT, Blue, luD},
ImageSize -> isz] ];
Тест-драйв
isz = 250;
pp[1] = Graphics[{AbsoluteThickness[50], JoinForm["Round"],
CapForm["Round"], Line[{{0, 0}, {1, 0}, {0, 1}, {1, 1}}]},
ImageSize -> isz];
pp[2] = Graphics[{AbsoluteThickness[50], JoinForm["Round"],
CapForm["Round"],
Line[{{0, 0}, {1, 0}, {0, -1}, {0.7, -1}, {0, -4}, {2, -3}}]},
ImageSize -> isz];
pp[3] = Graphics[{AbsoluteThickness[50], JoinForm["Round"],
CapForm["Round"],
Line[{{0, 0}, {0, 1}, {1, 1}, {2, 0}, {2, 3}, {5, 5}, {5, 1}, {4,
1}}]}, ImageSize -> isz];
pp[4] = Graphics[{AbsoluteThickness[50], JoinForm["Round"],
CapForm["Round"],
Line[{{0, 0}, {0, 1}, {1, 1}, {1, 0}, {1/2, 0}}]},
ImageSize -> isz];
GraphicsGrid[Table[{pp[i], k@pp[i]}, {i, 4}]]