Clear["Global`*"];
bezierFunction[pts_][t_] := Module[{nd, p, n, a, b},
nd = 3;
n = Length@p;
p = Partition[pts, UpTo[nd + 1], nd];
n = Length@p;
a = ListConvolve[{-1, 1},
Prepend[UnitStep[n t - Range[n - 1]], 1], -1, 0];
b = MapIndexed[
BernsteinBasis[Length@#1 - 1, Range[0, Length@#1 - 1],
n t + 1 - #2[[1]]] . #1 &, p];
PiecewiseExpand[a . b]]
pts1 = {{0, 0}, {1, 1}, {2, -1}, {3, 0}, {5, 2}, {6, -1}, {7, 3}};
pts2 = {{5, -2}, {0, 0}, {1, 2}, {5, 1}, {2, 2}, {4, 3}, {5, 4}};
pts3 = {{4, 2}, {3, 2}, {2, 3}, {-1, -3}};
curves = {curve1, curve2, curve3} =
BezierCurve /@ {pts1, pts2, pts3};
g = Graphics[{Arrowheads[.02], Arrow /@ curves}];
fs1 = bezierFunction[pts1];
fs2 = bezierFunction[pts2];
fs3 = bezierFunction[pts3];
intersectionPosition[f_, g_] :=
{s, t} /.
Last@NMinimize[{Norm[f@s - g@t]^2, 0 < s < 1, 0 < t < 1}, {s, t},
Method -> "SimulatedAnnealing"];
{{t12, t21}, {t22, t31}, {t32, t11}} =
intersectionPosition @@@ {{fs1, fs2}, {fs2, fs3}, {fs3, fs1}};
{{t11, t12}, {t21, t22}, {t31, t32}}
plots = {ParametricPlot[fs1@t // Evaluate, {t, t11, t12},
PlotStyle -> Red],
ParametricPlot[fs2@t // Evaluate, {t, t21, t22},
PlotStyle -> Green],
ParametricPlot[fs3@t // Evaluate, {t, t31, t32},
PlotStyle -> Blue]}; reg =
Cases[Show[plots, PlotRange -> All], Line[pts_] :> pts, -1] //
Catenate // Polygon;
Graphics[{{HatchFilling[], reg}, curves, Arrowheads[{{Large, .5}}],
plots[[;; , 1]] /. Line -> Arrow}]
- We can test another points.
Clear["Global`*"];
bezierFunction[pts_][t_] := Module[{nd, p, n, a, b}, nd = 3;
n = Length@p;
p = Partition[pts, UpTo[nd + 1], nd];
n = Length@p;
a = ListConvolve[{-1, 1},
Prepend[UnitStep[n t - Range[n - 1]], 1], -1, 0];
b = MapIndexed[
BernsteinBasis[Length@#1 - 1, Range[0, Length@#1 - 1],
n t + 1 - #2[[1]]] . #1 &, p];
a . b]
SeedRandom[123456];
pts1 = SortBy[RandomPoint[StadiumShape[{{-15, 0}, {70, 0}}, 4], 23],
First];
pts2 = SortBy[RandomPoint[StadiumShape[{{40, -20}, {40, 60}}, 3], 24],
Last];
pts3 = ReverseSortBy[
RandomPoint[StadiumShape[{{-20, -20}, {50, 50}}, 3], 23], First];
curves = {curve1, curve2, curve3} =
BezierCurve /@ {pts1, pts2, pts3};
fs1 = bezierFunction[pts1];
fs2 = bezierFunction[pts2];
fs3 = bezierFunction[pts3];
intersectionPosition[f_, g_] := {s, t} /.
Last@NMinimize[{Norm[f@s - g@t]^2, 0 < s < 1, 0 < t < 1}, {s, t},
Method -> "SimulatedAnnealing"];
{{t12, t21}, {t22, t31}, {t32, t11}} =
intersectionPosition @@@ {{fs1, fs2}, {fs2, fs3}, {fs3, fs1}};
{{t11, t12}, {t21, t22}, {t31, t32}};
{plot1, plot2,
plot3} = {ParametricPlot[fs1@t // Evaluate, {t, t11, t12},
PlotStyle -> Red],
ParametricPlot[fs2@t // Evaluate, {t, t21, t22},
PlotStyle -> Green],
ParametricPlot[fs3@t // Evaluate, {t, t31, t32},
PlotStyle -> Blue]};
{lines1, lines2,
lines3} = {Catenate@Cases[plot1, Line[pts_] :> pts, -1],
Catenate@Cases[plot2, Line[pts_] :> pts, -1],
Catenate@Cases[plot3, Line[pts_] :> pts, -1]};
Graphics[{{HatchFilling[], Polygon@Catenate@{lines1, lines2, lines3}},
curves, AbsoluteThickness[2],
Arrowheads[{{Large, .5}}], {Red, Arrow@lines1}, {Green,
Arrow@lines2}, {Blue, Arrow@lines3}}]
BezierFunction
? It allows making the curve in the desired range. $\endgroup$