Final
pnts = {{0.3, 0}, {4, 2}, {4, -2}};
rotpnts = Table[RotationTransform[2*Pi/3*i][pnts], {i, 0, 2}];
polys = BoundaryMeshRegion[#, Line[{1, 2, 3, 1}]] & /@ rotpnts;
reg = RegionUnion[polys]
regnp=ImplicitRegion[RegionDistance[reg,{x,y}]<2,{x,y}]
regn=NDSolve`FEM`ToElementMesh[regnp, MaxCellMeasure -> {"Length" -> .1}, "MaxBoundaryCellMeasure" -> .001]
-SignedRegionDistance[regn,{0,0}]
The following code can generate you a correct result, but at a low speed:
pnts = {{0.3, 0}, {4, 2}, {4, -2}};
rotpnts = Table[RotationTransform[2*Pi/3*i][pnts], {i, 0, 2}];
polys = BoundaryMeshRegion[#, Line[{1, 2, 3, 1}]] & /@ rotpnts;
reg = RegionUnion[polys]
c[r_?NumericQ] :=
NMaximize[
RegionDistance[reg, {x, y}], {x, y} \[Element] Circle[{0, 0}, r],
Method -> "NelderMead", PrecisionGoal -> 6, WorkingPrecision -> 10][[1]]
NMinimize[{r, c[r] > 2, 2<=r<=5}, r,Method -> "SimulatedAnnealing", PrecisionGoal -> 4, WorkingPrecision -> 10]
(*3.5439*)
The constraint is written in c[r]>2
, you can customize the function to make it wider applicable.
The main idea of the code is quite simple, for each curve with coefficient r
, in this case a circle with radius r
, we can find out the largest distance we can get by moving the point on the curve by RegionDistance
and NMaximize
.
I strongly suggest adding Method->"NelderMead"
as sometimes other method like "DifferentialEvolution"
will find the distance always 0
(the searching point keeps in the region and never get out.) and stop evaluation.
Then we can find out the shortest r
we need by NMinimize
.
There's still one problem left, If we use StepMonitor
to track the process, we can find out that no matter which method we choose, the process will not be ideal, so I think maybe we can create a simple form of NMaximize
or so specially designed for this problem. Also, we can find out that sometimes the value has already reached the most optimized value but it still won't generate an output.
Edit1
The second problem can be solved by ConnectedMeshComponents
and RegionNearest
.
res=NMaximize[ RegionDistance[reg, {x, y}], {x, y} \[Element] Circle[{0, 0}, 3.5439(*the result*)], Method -> "NelderMead", PrecisionGoal -> 6, WorkingPrecision -> 10]
pt={x,y}/.res[[2]];
dis=res[[1]];
near=RegionNearest[#,pt]&/@ConnectedMeshComponents@DiscretizeRegion@RegionIntersection[Disk[pt,dis+.1],reg]
Show[RegionPlot[reg],Graphics[{Line[{pt,#}]&/@near,Red,Point@pt,Blue,Point/@near}]]

Edit2
I think you've got an answer by yourself already. This code can do the job you want:
pt = {3, 3};
n = 2;
near = RegionNearest[#, pt] & /@ ConnectedMeshComponents@reg
sel = TakeSmallestBy[near, EuclideanDistance[pt, #] &, n]
Show[RegionPlot[reg],
Graphics[{Line[{pt, #}] & /@ sel, Red, Point@pt, Blue,
Point /@ sel}]]

Edit3
Here gives a faster code optimized for this occasion:
pnts = {{0.3, 0}, {4, 2}, {4, -2}};
rotpnts = Table[RotationTransform[2*Pi/3*i][pnts], {i, 0, 2}];
polys = BoundaryMeshRegion[#, Line[{1, 2, 3, 1}]] & /@ rotpnts;
reg = RegionUnion[polys]
c[r_?NumericQ] :=
NMaximize[
SignedRegionDistance[reg, {x, y}], {x, y} \[Element]
Circle[{0, 0}, r], Method -> "NelderMead", PrecisionGoal -> 6,
WorkingPrecision -> 10][[1]]
find[tar_, range : {min_, max_}, prec_: .0001] :=
Round[NestWhile[
If[c@Mean@# > tar, Most, Rest][Subdivide[#[[1]], #[[2]], 2]] &,
N@range, #[[2]] - #[[1]] >= prec &][[1]], prec]
find[2, {2, 5}]
(*3.5439*)
Use simple and violent method to find out the smallest r in a given range, but this method can only apply when c[r] is monotony in the given range.
In this case, this is correct, so it can generate a correct result in a short amout of time.
Will this help?
Edit4
A totally new method: inflation and calculate the minimum distance.
regn=Quiet@DiscretizeRegion[ImplicitRegion[RegionDistance[reg,{x,y}]<2,{x,y}],MaxCellMeasure->0.001]
-SignedRegionDistance[regn,{0,0}]
This method is widely applicable as long as your precision goal is not that high. Firstly, we create a new region to include every point in a distance to the region, then we find out at which distance finally there's a point not satisfying that, then this distance is just what you want!
Or maybe this will be even better in performance?
regnp=ImplicitRegion[RegionDistance[reg,{x,y}]<2,{x,y}]
regn=NDSolve`FEM`ToElementMesh[regnp, MaxCellMeasure -> {"Length" -> .1}, "MaxBoundaryCellMeasure" -> .001]
dmax
of any inner points of the circle. The resulting circle may be smaller than the extents of the polygons... $\endgroup$