# How to define space inside a closed curve as a Region

Let's say I have some closed curve, which could be given by a parametric representation, or by a closed spline as in:

pts = {{-1, 0}, {-1, 1}, {0, 0}, {1, 1}, {1, 0}};


which looks like so:

Graphics[{Thick, BSplineCurve[pts, SplineClosed -> True]}]


My question is, is there an efficient way to convert the space inside the boundary to a Region (which could then be postprocessed by any of Mathematica's functions that act on such objects)? I don't see any built-in functionality that would achieve this. Do I have to define a Boolean function that tests whether a point lies within the area enclosed by the curve, and plug that into ImplicitRegion? If so, what would be a good approach to do this?

Of course, extending this idea to the 3D case (a parametric closed surface defining a 3D region) would be of interest as well.

## 4 Answers

In principle this should work:

pts = {{-1, 0}, {-1, 1}, {0, 0}, {1, 1}, {1, 0}};

g = Graphics[{FilledCurve@BSplineCurve[pts, SplineClosed -> True]}]


DiscretizeGraphics[g]


But as you can see, the result is wrong.

This may be the same bug as described here:

You may want to report it to Wolfram again in the hope that more reports equal a higher likelihood of fixing it ...

• Bummer! I'll report it, but I won't get my hopes up. Someone else recently commented about Region-associated functionality being incomplete, and that seems to be the case. One would think that what I want to do corresponds to functionality that is required frequently. So, I'll have to figure out how to define my own Boolean function that I can plug into ImplicitRegion? That might end up being very slow, certainly if I use contour integrals. Are there any good (=fast) algorithms for this that I should use?
– Pirx
Commented Sep 5, 2016 at 14:21
• @Pirx You could approximate your curve with a polygon. Do you really need a BSplineCurve or is this question more general? A polygon is already a region as it is and it is fast to work with. Commented Sep 5, 2016 at 14:24
• The question is intended to be more general. Yes, you are correct, certainly in 2D I could just convert whatever curve I have into a polygon. I wonder if there is perhaps a pre-defined function in Mma that does this faster than code I could come up with on my own? I realize this is simple enough to code, but perhaps there's already a better way. More generally, however, being able to just feed curves or surfaces into some function that converts them into regions in a smart way would be desirable. Also, the extension of the polynomial idea into 3D would be less trivial, I think...
– Pirx
Commented Sep 5, 2016 at 16:32

The problem mentionned by @Szabolcs in his answer is solved on Mathematica version 12.2 (the problem is present on Mathematica 12.1)

\$Version

pts = {{-1, 0}, {-1, 1}, {0, 0}, {1, 1}, {1, 0}};
g = Graphics[{FilledCurve@BSplineCurve[pts, SplineClosed -> True]}]
DiscretizeGraphics[g]


It seems that the DiscretizeGraphics code doesn't know how to handle the SplineClosed->True option of the BSplineCurve object. As a workaround, you can use my FullBSplineCurve function to convert the SplineClosed->True option into an equivalent SplineKnots specification, and then perform the discretization:

DiscretizeGraphics @ FilledCurve @ FullBSplineCurve @ BSplineCurve[
{{-1, 0}, {-1, 1}, {0, 0}, {1, 1}, {1, 0}},
SplineClosed->True
]


• FullBSplineCurve seems to fail with numeric SplineWeights and either SplineClosed -> True or SplineKnots -> "Unclamped". Example: BSplineCurve[{{50, 70}, {70, 50}, {50, 30}, {30, 50}}, SplineWeights -> {1, 1, 1, 1}, SplineClosed -> True]. The result is renderer differently both by Graphics and DiscretizeGraphics. Commented Dec 3, 2021 at 15:35

A clean solution is to 1) use BSplineFunction, 2) calculate points along the closed curve, 3) call these points a Polygon. See below

poly = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
weights = {7.8, 9.1, 4.8, 7.8};

bSplineFunction =
BSplineFunction[poly, SplineClosed -> True, SplineDegree -> 3,
SplineWeights -> weights];
bsPolygonPts = Table[bSplineFunction[i], {i, 0, 1, .01}];

bSplinePts = Graphics[Point[bsPolygonPts]];

bSplineCurve =
Graphics[{Red,
BSplineCurve[poly, SplineClosed -> True, SplineDegree -> 3,
SplineWeights -> weights]}];

bSplinePolygon = Graphics[{Red, Polygon[bsPolygonPts]}];

Show[ply, bSplineCurve, bSplinePts]
Show[ply, bSplinePolygon]

• What's ply in the last two lines of code? Commented Jul 11, 2022 at 19:01