Circular Layout

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • JosAH
    Recognized Expert MVP
    • Mar 2007
    • 11453

    #16
    For a fast upperbound you can do this; an icon at 45 degrees takes up most of the space, i.e. sqrt(2)*48 == W pixels (its diagonal). For n icons in a 'circular' layout you need a circumpherence of n*W pixels. That basically solves it; note that not all icons will 'touch' eachother because this estimation is a minimal upperbound.

    kind regards,

    Jos

    Comment

    • Dormilich
      Recognized Expert Expert
      • Aug 2008
      • 8694

      #17
      Originally posted by Dormilich
      Code:
      r(min) = n · icon.width / ( sqroot(2) · pi )
      @JosAH: like that one? (only put in a formula)

      note: this solution does not work for n = 4, you'll see the overlap in some cases (the minimum radius is calculated 10% too small)

      Comment

      • JosAH
        Recognized Expert MVP
        • Mar 2007
        • 11453

        #18
        Originally posted by Dormilich
        @JosAH: like that one? (only put in a formula)

        note: this solution does not work for n = 4, you'll see the overlap in some cases (the minimum radius is calculated 10% too small)
        No not like that one; I reread my reply and noticed that my description was extremely sloppy. When you chop up a circle in equal angle wedges, those wedges are all isosecles triangles. The sides opposite to the centre of the circle should equal sqrt(2)*W, not that part of the circumpherence of the circle.

        kind regards,

        Jos

        Comment

        • Dormilich
          Recognized Expert Expert
          • Aug 2008
          • 8694

          #19
          ok, you can exactly calculate the r(min) for every n by using the Law of Cosines, nevertheless, for n > 4 the approximation by circle segments is good enough and far easier to compute.

          Alas, I see our discussion is interesting, but pointless, because RedSon said 5 or more icons would be too much for his application.

          Comment

          • YarrOfDoom
            Recognized Expert Top Contributor
            • Aug 2007
            • 1243

            #20
            This has caught my interest. I didn't see this solution anywhere, but wouldn't the perfect formula for for calculating the minimum radius be:
            Code:
            (sqrt(2) * 24) / sin(pi / n)
            I've tried this on my graphical calculator and it seems to work for every n>1.
            Here's how I got to it:

            Comment

            • RedSon
              Recognized Expert Expert
              • Jan 2007
              • 4980

              #21
              I'm assuming 24 to be dependent on the dimension of the icon? How would your formula change if the icons could have an arbitrary height and width (but still be square)?

              Comment

              • Dormilich
                Recognized Expert Expert
                • Aug 2008
                • 8694

                #22
                Originally posted by YarrOfDoom
                I didn't see this solution anywhere, but wouldn't the perfect formula for for calculating the minimum radius be:
                Code:
                (sqrt(2) * 24) / sin(pi / n)
                well, I was not aiming for the perfect formula (since this would involve sines or cosines), just one easy and fast to compute. and, put in another way, you have to round it anyways in the end (to get the pixels).

                EDIT: using the Law of Cosines I get:
                Code:
                r = w / sqrt(1 – cos(2pi/n))

                Comment

                • YarrOfDoom
                  Recognized Expert Top Contributor
                  • Aug 2007
                  • 1243

                  #23
                  Originally posted by RedSon
                  I'm assuming 24 to be dependent on the dimension of the icon? How would your formula change if the icons could have an arbitrary height and width (but still be square)?
                  It would become (sqrt(2) * x) / (2 * sin(pi / n))

                  Originally posted by Dormilich
                  well, I was not aiming for the perfect formula (since this would involve sines or cosines), just one easy and fast to compute. and, put in another way, you have to round it anyways in the end (to get the pixels).
                  I guess it all depends on the situation, but it's always handy to have a more general solution standby, in case you come across a similar situation.

                  Comment

                  • RedSon
                    Recognized Expert Expert
                    • Jan 2007
                    • 4980

                    #24
                    Originally posted by YarrOfDoom
                    It would become (sqrt(2) * x) / (2 * sin(pi / n))
                    Yes I know but my question was, what is x defined as? Is it half the width of the icon if the icon is square?

                    Comment

                    • YarrOfDoom
                      Recognized Expert Top Contributor
                      • Aug 2007
                      • 1243

                      #25
                      Originally posted by RedSon
                      Yes I know but my question was, what is x defined as? Is it half the width of the icon if the icon is square?
                      Oops, lost a line there, x represents the width (and height, since it's a square) of the icon, and also note that the sine is multiplied by 2 now. (So the 24 is indeed meant as one half of 48).

                      Comment

                      • bvdet
                        Recognized Expert Specialist
                        • Oct 2006
                        • 2851

                        #26
                        RedSon,

                        I found this thread by accident since I don't get over here often. For the exercise, I worked up a general solution in Python using code from one of my modules.
                        Code:
                        from math import pi, sin
                        
                        from macrolib.PointPlane3D import *
                        
                        def icon_layout(origin, size, n):
                        
                            # calculate radius
                            minChord = size*2**0.5
                            angleBetween = 2*pi/n
                            minRadius = (minChord/2)/sin(angleBetween/2)
                            
                            startPoint = Point(origin.x+minRadius, origin.y, 0)
                            '''
                            Three counter-clockwise points define a plane with the plane normal
                            vector pointing out of the screen. First point is the center of
                            rotation. Second point defines the X axis and radius of circle.
                            '''
                            A = Plane3D(origin, startPoint, 
                                        Point(origin.x, origin.y+minRadius, 0))
                        
                            return [A.PointRotate3D(startPoint, angleBetween*i) \
                                    for i in range(numberIcons)]
                        
                        origin = Point(120, 160, 0)
                        iconSize = 48
                        numberIcons = 12
                        pointList = icon_layout(origin, iconSize, numberIcons)
                        for pt in pointList:
                            print repr(pt)
                        Output:
                        Code:
                        >>> Point(251.138439, 160.000000, 0.000000)
                        Point(233.569219, 225.569219, 0.000000)
                        Point(185.569219, 273.569219, 0.000000)
                        Point(120.000000, 291.138439, 0.000000)
                        Point(54.430781, 273.569219, 0.000000)
                        Point(6.430781, 225.569219, 0.000000)
                        Point(-11.138439, 160.000000, 0.000000)
                        Point(6.430781, 94.430781, 0.000000)
                        Point(54.430781, 46.430781, 0.000000)
                        Point(120.000000, 28.861561, 0.000000)
                        Point(185.569219, 46.430781, 0.000000)
                        Point(233.569219, 94.430781, 0.000000)
                        >>>
                        If you are interested in the source code for PointPlane3D: link

                        Here's a graphical solution:
                        Attached Files

                        Comment

                        • gtoal
                          New Member
                          • Oct 2011
                          • 2

                          #27
                          I don't think any of these solutions are taking into account a visually pleasing layout where the amount of white space between each icon is roughly similar. in 'circular_layou t.jpg' above where the icons are regularly spaced, you can see where the icons at 45 degrees almost touch but the vertically or horizontally adjacent ones have a gap. A smarter algorithm that takes the shortest distance between the nearest points of adjacent icons into account may be needed.

                          Comment

                          • Dormilich
                            Recognized Expert Expert
                            • Aug 2008
                            • 8694

                            #28
                            a smarter algorithm would just add padding to the icon width.

                            Comment

                            • franknagy
                              New Member
                              • Oct 2011
                              • 27

                              #29
                              Let your icons be squares of sides a. Define a regular polygon of n sides with side d=a*sqrt(2). You can count from d and n the radius of the circle around the polygon:
                              r=(d/2)/sin(2*pi/n).
                              Place the center points of your icons on the vertices of this polygon.
                              x(k)= C(x)+r*cos(k/(2*pi),
                              y(k)= C(y)+r*sin(k/(2*pi), k=0,1,2,...,n-1.

                              Comment

                              Working...