公告:本站正式转型为非交互式静态网站!
转型:本站将通过笔记和博客的形式继续为大家服务,关于 Mathematica 问答服务请移步至QQ群:365716997
联系:如有问题请联系QQ群管理员,或发送邮件至:lixuan.xyz@qq.com。
感谢:最后非常感谢大家多年来的支持与帮助!
参考《互联网跟帖评论服务管理规定》《中华人民共和国网络安全法》《网络信息内容生态治理规定》《互联网用户账号信息管理规定》

—— 2022-11-27

欢迎来到 Mathematica 问答社区

提问时请贴上文本代码

语法高亮:在编辑器中点击

被禁止的话题:广告破解

请阅读:《提问的智慧》

备用域名:mma.ooo

支持LaTex数学公式
行内公式标识符:\$ 或“$\backslash ($”+“$\backslash )$”,
行间公式标识符:\$\$ 或 “$\backslash [$”+“$\backslash ]$”

社区建议QQ群:365716997

分类

+1 投票
2.8k 浏览

我想在一个矩形区域生成若干互不相交 位置半径随机分布(位置均匀分布,半径正态分布)的圆,参考了永的代码,效果很不错

(disk = Reap[
       region = 
        BoundaryDiscretizeGraphics[Rectangle[{0, 0}, {10, 10}]];
       Do[p = RandomPoint[region];
        rad = 
         If[(tem = Abs[SignedRegionDistance[region, p]]) < .4, tem, 
          RandomReal[{.2, 
            Min[{tem, Min@(Subtract @@ RegionBounds@region)/40}]}]];
        region = 
         RegionDifference[region, DiscretizeRegion@Sow[Disk[p, rad]]],
         200]][[-1, -1]];) // AbsoluteTiming;
Graphics[Transpose[{RandomColor[
    Hue[1/3, NormalDistribution[.6, .2], NormalDistribution[.6, .07]],
     disk // Length], disk}]]

但是目前有一个问题,图中的圆发生了粘连,如何修改可以添加一个参数 调节 所有圆间的最小距离

分类:绘图 | 用户: mma-2-2-2 (1.3k 分)

2 个回答

+3 投票
 
已采纳

下面的代码可以满足要求,但效率不高。

(*绘制不重叠的圆盘*)

n = 500;(*圆的个数*)
r = 1./Sqrt[n];(*每个圆的最大半径,此值越小,计算越快,但此值较大时有意思*)
minD = 0;(*允许的圆之前的最小距离*)
fRandomD := {RandomReal[1, 2], 
  Abs[RandomVariate[
    NormalDistribution[0, r]]]};(*在[0,1]\[Times][0,1]上取圆心*)
fMinDis[disks_, disk_] := 
 Min[EuclideanDistance[disk[[1]], #[[1]]] - #[[2]] & /@ disks] - 
  disk[[2]];

Dynamic[Column[{k, NumberForm[100.0 k/n, {4, 2}], 
   ProgressIndicator[k/n]}], Initialization -> (k = n)](*计算进度*)
Dynamic[Graphics[{Hue[n #[[2]]], Disk @@ #} & /@ disks]](*当前的圆盘*)

disks = {fRandomD};(*初始化圆盘集*)
Do[
 minDis = fMinDis[disks, disk = fRandomD];
 While[minDis < minD, 
  minDis = fMinDis[disks, disk = fRandomD]];(*直到计算出允许的圆盘后*)
 AppendTo[disks, disk];(*保留数据*)
, {k, n}]

修改了一下代码,半径改为正态分布的绝对值了。

用户: 野鹤 (5.1k 分)
采纳于 用户:mma-2-2-2
+3 投票
getRandomCircle = 
  Compile[{{xMin, _Real}, {xMax, _Real}, {yMin, _Real}, {yMax, \
_Real}, {n, _Integer}, {d, _Real}, {u, _Real}, {sigma, _Real}},
   Module[{data, num = 0, i, x = 0., y = 0., r = 0., flag = True},
    data = Table[{0., 0., 0.}, {n}];
    (*第一个圆*)
    data[[1, 3]] = Abs@RandomVariate[NormalDistribution[u, sigma]];
    data[[1, 1]] = 
     RandomReal[{xMin + data[[1, 3]], xMax - data[[1, 3]]}];
    data[[1, 2]] = 
     RandomReal[{yMin + data[[1, 3]], yMax - data[[1, 3]]}];
    num++;
    (*后面的圆*)
    While[num <= n - 1,
     While[True,
      x = RandomReal[{xMin, xMax}]; y = RandomReal[{yMin, yMax}];
      r = Abs@RandomVariate[NormalDistribution[u, sigma]];
      If[xMin <= x - r && xMax >= x + r && yMin <= y - r && 
        yMax >= y + r, Break[]];
      ];
     flag = True;
     For[i = 1, i <= num, i++,
      If[Sqrt[(x - data[[i, 1]])^2 + (y - data[[i, 2]])^2] < 
        data[[i, 3]] + r + d, flag = False; Break[]]
      ];
     If[flag, num++; data[[num, 1]] = x; data[[num, 2]] = y; 
      data[[num, 3]] = r];
     ];
    data
    ], CompilationTarget -> "C", RuntimeOptions -> "Speed"
   ];

输入参数:前四个是矩形的范围,生成n个圆,每两个圆之间的距离需要大于等于d,圆的半径生成按照Abs[满足参数u和sigma的正态分布的随机数]。

问题1:需要输入合适的参数,不合适的参数,例如圆的半径平均值很大,那么越到后来越难产生满足条件的圆。以下面例子给的参数为例,{0, 10, 0, 10, 1000, 0.1, 0.5, 0.3} 看上去产生1000个圆只要产生1000个半径就可以了,实际上产生了212330个半径才找到1000个能满足要求放在一起的圆。如果此时改成d=0.15,那么程序运行时间从0.2s增加到8s,d=0.16的运行时间是81s。当然也可以缩小u和sigma来缩短时间。

问题2:实际输出的圆的半径并不满足正态分布,因为到后期按照正态分布产生的较大数值的半径(例如半径为1)是几乎不可能距离已经产生的圆都大于d的,此时这个半径被抛弃。所以可以看到最终的结果半径数值小的比例被人为提高了。可以联想一下,你往杯子里扔大小随机变化的石头,扔到后来其实就不是大小随机了,因为大的石头塞不进去了,只能塞小的石头。

使用举例:

Graphics[Circle[{#1, #2}, #3] & @@@ 
  getRandomCircle[0, 10, 0, 10, 1000, 0.1, 0.5, 0.3]]

用户: 苹果 (2.2k 分)
谢谢 苹果,还有我想生成一个任意四边形,四边形为凸四边形,四个角最小角度为30度最大角度不超过150度,四条边最长边和最短边长度之比不超过3,设置一个参数S调节矩形区域允许出现的任意四边形的最长边的长度...且要求生成的四边形不相交不包含,这样吧,我再开个新帖
我已经开了新帖,我先按照您的代码 自己摸索一下尝试自己解决受约束的随机四边形问题,十分谢谢
...