# Filling between several parametric plots

I have several (four) parametric curves defining a closed loop in the plane, and I wish to fill it with some color. Now, I have seen several nice answers for the case of two curves, where the simplest solution is to shift between them as $$t \:\gamma_1+(1-t)\gamma_2$$, but this is easy only for two curves.

xs[u_, v_, λ_] := (-(1/4)+I/4) Sqrt[π]  λ(Erf[(1/2+I/2) u]-Erf[(1/2+I/2) (u-I v)]+Erfi[(1/2+I/2) u]-Erfi[(1/2+I/2) (u+I v)])+1/λ Sqrt[π]  FresnelC[u/Sqrt[π]]
ys[u_, v_, λ_] := (-(1/4)-I/4) Sqrt[π] λ(Erf[(1/2+I/2) u]-Erf[(1/2+I/2) (u-I v)]-Erfi[(1/2+I/2) u]+Erfi[(1/2+I/2) (u+I v)])+1/λ Sqrt[π]  FresnelS[u/Sqrt[π]]

loop[λ_] := {{xs[-1, t, λ], ys[-1, t, λ]}, {xs[2.2, t, λ], ys[2.2, t, λ]}, {xs[t, -1, λ], ys[t, -1, λ]}, {xs[t, 2.2, λ], ys[t, 2.2, λ]}}

ParametricPlot[{loop[0.6]}, {t, -1, 2.2} ]


• We can mapping the rectangle -1<=s<=2.2, -1<=t<=2.2 to such region.
xs[u_, v_, λ_] := (-(1/4) +
I/4) Sqrt[π] λ (Erf[(1/2 + I/2) u] -
Erf[(1/2 + I/2) (u - I v)] + Erfi[(1/2 + I/2) u] -
Erfi[(1/2 + I/2) (u + I v)]) +
1/λ Sqrt[π] FresnelC[u/Sqrt[π]]
ys[u_, v_, λ_] := (-(1/4) -
I/4) Sqrt[π] λ (Erf[(1/2 + I/2) u] -
Erf[(1/2 + I/2) (u - I v)] - Erfi[(1/2 + I/2) u] +
Erfi[(1/2 + I/2) (u + I v)]) +
1/λ Sqrt[π] FresnelS[u/Sqrt[π]]
ParametricPlot[{xs[s, t, .6], ys[s, t, .6]}, {s, -1, 2.2}, {t, -1,
2.2}, PlotStyle -> Cyan]


• We can compare with the mapping domain and the mapping range as below.
{ParametricPlot[{s, t}, {s, -1, 2.2}, {t, -1, 2.2}, PlotStyle -> Cyan,
Axes -> None, Mesh -> {10, 10},
MeshShading -> {{Red, Blue}, {Yellow, Green}}],
ParametricPlot[{xs[s, t, .6], ys[s, t, .6]}, {s, -1, 2.2}, {t, -1,
2.2}, PlotStyle -> Cyan, Axes -> None, Mesh -> {10, 10},
MeshShading -> {{Red, Blue}, {Yellow, Green}}]} // GraphicsRow


• Another way is take care of the orientation of paths.
xs[u_, v_, λ_] = (-(1/4) +
I/4) Sqrt[π] λ (Erf[(1/2 + I/2) u] -
Erf[(1/2 + I/2) (u - I v)] + Erfi[(1/2 + I/2) u] -
Erfi[(1/2 + I/2) (u + I v)]) +
1/λ Sqrt[π] FresnelC[u/Sqrt[π]];
ys[u_, v_, λ_] = (-(1/4) -
I/4) Sqrt[π] λ (Erf[(1/2 + I/2) u] -
Erf[(1/2 + I/2) (u - I v)] - Erfi[(1/2 + I/2) u] +
Erfi[(1/2 + I/2) (u + I v)]) +
1/λ Sqrt[π] FresnelS[u/Sqrt[π]];
loop[λ_] = {{xs[-1, t, λ],
ys[-1, t, λ]}, {xs[2.2, t, λ],
ys[2.2, t, λ]}, {xs[t, -1, λ],
ys[t, -1, λ]}, {xs[t, 2.2, λ],
ys[t, 2.2, λ]}};
{l1, l2, l3, l4} = ParametricPlot[#, {t, -1, 2.2}] & /@ loop[.6];
{pts1, pts2, pts3, pts4} =
Cases[#, Line[a_] :> a, Infinity] & /@ {l1, l2, l3, l4};
pts = Join[pts3[[1]], pts2[[1]], Reverse@pts4[[1]], Reverse@pts1[[1]]];
Graphics[{Green, FilledCurve[Line[pts]]}, Axes -> True]
(* Graphics[{Green, WindingPolygon[pts]}, Axes -> True] *)


•  BoundaryDiscretizeGraphics also work if we use JoinedCurve.
Clear[xs, ys, l1, l2, l3, l4];
xs[u_, v_, λ_] = (-(1/4) +
I/4) Sqrt[π] λ (Erf[(1/2 + I/2) u] -
Erf[(1/2 + I/2) (u - I v)] + Erfi[(1/2 + I/2) u] -
Erfi[(1/2 + I/2) (u + I v)]) +
1/λ Sqrt[π] FresnelC[u/Sqrt[π]] // Re;
ys[u_, v_, λ_] = (-(1/4) -
I/4) Sqrt[π] λ (Erf[(1/2 + I/2) u] -
Erf[(1/2 + I/2) (u - I v)] - Erfi[(1/2 + I/2) u] +
Erfi[(1/2 + I/2) (u + I v)]) +
1/λ Sqrt[π] FresnelS[u/Sqrt[π]] // Re;
l1 = Cases[
ParametricPlot[{xs[s, -1, .6], ys[s, -1, .6]}, {s, -1, 2.2}],
Line[a_] :> a, Infinity][[1]];
l2 = Cases[
ParametricPlot[{xs[2.2, t, .6], ys[2.2, t, .6]}, {t, -1, 2.2}],
Line[a_] :> a, Infinity][[1]];
l3 = Cases[
ParametricPlot[{xs[s, 2.2, .6], ys[s, 2.2, .6]}, {s, 2.2, -1}],
Line[a_] :> a, Infinity][[1]] // Reverse;
l4 = Cases[
ParametricPlot[{xs[-1, t, .6], ys[-1, t, .6]}, {t, 2.2, -1}],
Line[a_] :> a, Infinity][[1]] // Reverse;
Graphics[JoinedCurve[
Line[Join[l1, l2, l3, l4]]]] // BoundaryDiscretizeGraphics


• Some related.

https://mathematica.stackexchange.com/a/252935/72111

https://mathematica.stackexchange.com/a/262992/72111

• Excellent ! Thank you so much. Mar 2, 2022 at 22:56

An alternative approach: post-process one-parameter ParametricPlot output to order line coordinates and add a polygon.

ClearAll[addFilling]
addFilling[style_ : ColorData[97]@1] := Graphics[{Opacity[.3], style,
Polygon @ #[[Last@FindShortestTour[#]]] & @
MeshCoordinates @ DiscretizeGraphics @ #}] &;


Use addFilling[] with the option DisplayFunction:

ppA1 = ParametricPlot[loop[0.6], {t, -1, 2.2},
ImageSize -> 700, PlotStyle -> AbsoluteThickness[.5], Axes -> False, Frame -> True,
DisplayFunction -> (Show[#, addFilling[] @ #] &)]


Compare with the two-parameter ParametricPlot method from cvgmt's answer:

ppA2 = ParametricPlot[{xs[s, t, .6], ys[s, t, .6]}, {s, -1, 2.2}, {t, -1, 2.2},
Axes -> False, ImageSize -> 700]


Zoom in to see the artifacts in the second picture:

GraphicsColumn[{Show[ppA1, PlotRange -> {{.5, 2}, {.5, 1}}],
Show[ppA2, PlotRange -> {{.5, 2}, {.5, 1}}]}]


Using λ = .3:

ppB1 = ParametricPlot[loop[0.3], {t, -1, 2.2},
Axes -> False, PlotStyle -> AbsoluteThickness[.5], Frame -> True, ImageSize -> 700,
DisplayFunction -> (Show[#, addFilling[] @ #] &)]


ppB2 = ParametricPlot[{xs[s, t, .3], ys[s, t, .3]}, {s, -1, 2.2}, {t, -1,  2.2},
Axes -> False, ImageSize -> 700]


GraphicsColumn[{Show[ppB1, PlotRange -> {{-2, 2}, {-1, 1}}],
Show[ppB2, PlotRange -> {{-2, 2}, {-1, 1}}]}]


• (+1) The extra part come from other mesh line. ParametricPlot[{xs[s, t, .6], ys[s, t, .6]}, {s, -1, 2.2}, {t, -1, 2.2}, PlotStyle -> Yellow, Axes -> False, Frame -> False, Method -> {"BoundaryOffset" -> False}, MeshFunctions -> {#4 &}, Mesh -> {{{2.2, Red}, {2.1, Green}, {2.0, Blue}}}, MeshStyle -> Red, BoundaryStyle -> None] Mar 2, 2022 at 2:09
• Thank you so much. I hesitated about which answer to accept since both yours and cvgmt's are excellent. In the end I accepted the latter because I found it just slightly easier to implement. Mar 2, 2022 at 22:59