Operations “intra” & “inter” lists

2019-04-27 13:20发布

问题:

Please Consider the following :

lesDisques={{14.2065, 10.609, 0.974938}, {19.5653, 6.92721, 0.974938}, 
            {30.4607,17.4802, 0.974938}, {27.4621, 10.0393, 0.974938}, 
            {15.915, 20.4278,0.974938}, {28.6921, 5.2132, 1.53205}, 
            {27.0317, 24.8346,1.53205}, {20.8853, 18.8588, 1.53205}}

 where lesDisques[[#]] is {X,Y,R}

 frmCorner = {{6.5946, 1.5946`}, {6.5946, 28.4054`}, 
              {60.2162`,28.4054`}, {33.4054`, 28.4054`}}

 cog = {23.91871026577044`, 15.010499627383863`}

 scrCenter = {20, 15}

 frmXY={{6.5946, 1.5946}, {33.4054, 28.4054}}

 Graphics[{
           White, EdgeForm[Thick],
           Rectangle @@ frmXY,
           Red, PointSize[.04],
           Point@cog,
           Black, Disk @@@ (lesDisques /. {a_, b_, c_} :> {{a, b}, c})},
           ImageSize -> 600]

For each of the 8 disks,

I would like to compute the minimum distance between its edge and :

-The edge of every other disks (7 values) -Each frame corner {4 values},

I would then obtain 8 lists of 11 values.

The following enables me to "pointize" the disks perimeter :

 pointize[{{x_,y_},r_},size_:12]:=Table[{x+r Cos[i ((2\[Pi])/size)],
                                  y+r Sin[i ((2\[Pi])/size)]},{i,0,size}]

With this I could find the 2 closest points for 2 disks and compute de distance, but I feel this might not be the right way to do it.

回答1:

Try this,

Outer[ Norm[#1[[;;2]] - #2[[;;2]]] - #1[[3]] - #2[[3]]&, #, #, 1]& @ lesDisques

It works by computing the distance between the centers of the discs, Norm[#1[[;;2]] - #2[[;;2]]], and then subtracting off their radii for all pairs of discs. For a large list, though, this may not be the speediest as it computes all the values twice, but it is straightforward.

For a speed up, first we need to determine what the pairs we want to calculate are. A straightforward way is to determine all unique pairs with

Subsets[Range[Length@lesDisques], {2}]  

which returns

{{1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}, {1, 7}, {1, 8}, {2, 3}, 
 {2, 4}, {2, 5}, {2, 6}, {2, 7}, {2, 8}, {3, 4}, {3, 5}, {3, 6}, 
 {3, 7}, {3, 8}, {4, 5}, {4, 6}, {4, 7}, {4, 8}, {5, 6}, {5, 7}, 
 {5, 8}, {6, 7}, {6, 8}, {7, 8}}

Also, it doesn't pair up the discs with themselves, unlike Outer. I'd use it like this

With[{ps = lesDisques[[ # ]]},
  Norm[#1[[;;2]] - #2[[;;2]]] - #1[[3]] - #2[[3]]& @@ ps ]& /@ 
Subsets[Range[Length@lesDisques], {2}]

Edit: I have a pathological dislike for using variables like lesDisques in more than one place as it makes it more difficult to change later. So, here's a rewrite:

With[{ps = #},
  Norm[Subtract @@ ps[[#1,;;2]]] - Plus @@ ps[[#1,3]]& /@ 
  Subsets[Range[Length@ps], {2}]
]& @ lesDisques

Edit: The Subsets version has a flaw that the Outer version does not, as written you can't tell which pair of disks are being compared. Here's a rewritten version,

With[{ps = #},
  Rule[#1,Norm[Subtract @@ ps[[#1,;;2]]] - Plus @@ ps[[#1,3]]]& /@ 
  Subsets[Range[Length@ps], {2}]
]& @ lesDisques

which returns

{{1, 2} -> 4.55184, {1, 3} -> 15.697, {1, 4} -> 11.318, 
 {1, 5} -> 8.01646, {1, 6} -> 12.9509, {1, 7} -> 16.6464, 
 {1, 8} -> 8.10742, {2, 3} -> 13.2184, {2, 4} -> 6.53803, 
 {2, 5} -> 12.0355, {2, 6} -> 6.77936, {2, 7} -> 16.8946, 
 {2, 8} -> 9.4974, {3, 4} -> 6.0725, {3, 5} -> 12.8915, 
 {3, 6} -> 9.88685, {3, 7} -> 5.60752, {3, 8} -> 7.16714, 
 {4, 5} -> 13.5826, {4, 6} -> 2.47339, {4, 7} -> 12.2946, 
 {4, 8} -> 8.49473, {5, 6} -> 17.361, {5, 7} -> 9.45131, 
 {5, 8} -> 2.70508, {6, 7} -> 16.6274, {6, 8} -> 12.6569, 
 {7, 8} -> 5.50844}

It occurs to me that I never answered the second part of your question, find the minimum distances between the discs and the corners of the frame. This task is best done using Outer as there aren't any redundant calculations. So, this is what I'd do

Outer[ Norm[#1 - #2[[;;2]]]- #2[[3]]&, #1, #2, 1]& @@ {frmCorner, lesDisques}

which is only a slight modification of the original code. Note, in the matrix generated by Outer, the rows correspond to the first input (frmCorner in this case) and the columns to the second input, as follows

{{10.8234, 13.0492, 27.6946, 21.5365, 20.0384, 20.8598, 29.4159, 20.8795}, 
 {18.381, 24.1159, 25.2729, 26.8237, 11.2934, 30.502, 19.2147, 15.654}, 
 {48.3566, 45.0012, 30.7229, 36.577, 44.0388, 37.6042, 31.844, 38.9409}, 
 {25.2035, 24.5762, 10.3402, 18.3289, 18.2489, 22.1342, 5.77375, 14.2125}}


回答2:

dist[{d1_, d2_}] :=EuclideanDistance[d1[[1 ;; 2]], d2[[1 ;; 2]]]-d1[[3]]-d2[[3]];
l = Subsets[lesDisques, {2}];
(*Nearest disks*)
nD = l[[Ordering[dist /@ l]]][[1]]
(*minmum distance*)
minD = dist[nD]

Graphics[{White, EdgeForm[Thick], Rectangle @@ frmXY, Red, 
  PointSize[.04], Point@cog, Black, 
  Disk @@@ (lesDisques /. {a_, b_, c_} :> {{a, b}, c}),
  Line[{nD[[1, 1 ;; 2]], nD[[2, 1 ;; 2]]}]}, ImageSize -> 600]