1

I am generating a number of circles on a PowerPoint slide. Their placement is fixed (i.e. they cannot be moved around). I then connect them to call-out rectangles that I align on the right hand side of the slide. Pseudo code is as follows:

  1. Generate an circle(1 to x, 1 to 3) array for the circles, where dimension '1' is the circle, .Name, dimension '2' is the circle .Top and dimension '3' is the circle .Left
  2. Re-order the circle(1 to x, 1 to 3) array by dimension 2 (i.e. sorting the circle by .Top)
  3. Loop through the array and generate an associated rectangle for each circle and I lay them out programmatically to desired height and position on the RH side of the slide.
  4. Connect the circles to their corresponding rectangle with an msoConnectorElbow. Where there is only a small shape.Top differential between the rectangle and the circle then I connect them with msoConnectorStraight.

The result is relatively pleasing. Please see image pasted below. enter image description here

Problem. As you shall see, some of the msoConnectorElbow collide (e.g. first three circles). My question is as follows: how should I sort the circles such that the msoConnectorElbow no longer collide? Clearly I would need an optimization algorithm. My initial idea was to partition the array into two (e.g. identify the 'median' circle) and then iterate through each bit of the array again and again such that the elbows do not collide.

Pseudo code for the first 'half' of the array would look something like this (apologies, it's a bit hacky and relies on a helper array):

Pivot = UBound(countries) / 2

For i = 1 To Pivot - 1
    For z = i + 1 To Pivot

    If (circles(i, 2) - circles(z, 2)) < 0 And (circles(i, 3) - circles(z, 3)) > 0 Then

    'switch the two circles in a 'helper array'
    final_array(z, 1) = circles(i, 1)
    final_array(z, 2) = circles(i, 2)
    final_array(z, 3) = circles(i, 3)
    final_array(i, 1) = circles(z, 1)
    final_array(i, 2) = circles(z, 2)
    final_array(i, 3) = circles(z, 3)

    'amend the original array
    circles(z, 1) = final_array(i, 1)
    circles(z, 2) = final_array(i, 2)
    circles(z, 3) = final_array(i, 3)
    circles(i, 1) = final_array(z, 1)
    circles(i, 2) = final_array(z, 2)
    circles(i, 3) = final_array(z, 3)

    End If

    Next
Next

What ultimately happens when I run this to completion is a complete reordering of the circles by horizontal dimension... Which in the end creates perhaps even more colliding elbow connectors, etc.

What would be the appropriate algorithm to address my issue and properly order my array to optimize the placement of the rectangles?

ZygD
  • 22,092
  • 39
  • 79
  • 102
Noobster
  • 1,024
  • 1
  • 13
  • 28

1 Answers1

1

I think you could essentially avoid collision if you're allowed to change the order that the lines are connected to the dots.

Keep searching for the farthest right dot and connect it to the box center that it is closest to (in terms of absolute up/down distance) and repeat.

enter image description here

Sorry about the diagram being messy, I had to do it in paint!

Marcucciboy2
  • 3,156
  • 3
  • 20
  • 38