3

My goal is to take a point that is inside of a circle with a given radius and put it on the circumference.

Recently I have been normalizing the vector between the point and the center of the circle then multiplying that by the radius. However I need (if possible) a less computationally expensive method because the distance formula is expensive.

Another thought I had was to use "atan2" to get the angle between the two points and then use sine and cosine multiplied by the radius to get the point on the circumference.

Which method do you think would be faster for the computer to process? Can you think of a faster method.

Details about the simulation This is an ios application written in swift.

Basically there are a bunch of particles moving around randomly. And the user is putting down fingers. Each finger is a circle with a radius that grows as time goes on. The part that is inneficent is that if the dot is ever inside of any of the circles (attached to touchscreen touches) that it goes on the circumference of the circle.

J.Doe
  • 1,445
  • 12
  • 23
  • 1
    Normalizing is almost certainly faster than doing anything with trigonometry: a square root and a few adds and multiplies should be cheaper to evaluate than a sequence of trigonometric functions. I'm surprised to hear that normalizing is too expensive, as this should be quite fast on modern CPUs. Can you say more about the context of this problem? How have you determined that the normalization is causing a performance issue? – Nathan Reed Jun 26 '16 at 19:41
  • The problem is their are tons of points that this needs to be done for. Anywhere from 400-1500 points have this done about every frame – J.Doe Jun 26 '16 at 19:45
  • 1
    OK. 400-1500 points is a fair number, but not that many; it should only take microseconds to normalize them if it's coded efficiently in a native-compiling language like C++. What language/framework/engine/etc are you using? How are you implementing the normalization process? – Nathan Reed Jun 26 '16 at 20:07
  • Is the radius a variable or a constant? – trichoplax is on Codidact now Jun 26 '16 at 20:09
  • I added some details about the simulation above. – J.Doe Jun 26 '16 at 20:20
  • The radius is variable. Right now I first check if it's in the circle using the squared distance. Then after that I subtract the center from the point and decide that by the sqrt of the distance squared. That is then multiplied by the radius. – J.Doe Jun 26 '16 at 20:21
  • If you have existing code then it might help to edit it into the question so we can see it. There may be potential optimisations that are not obvious from the question wording. – trichoplax is on Codidact now Jun 26 '16 at 21:37
  • For example, from your last comment I would suggest storing the radius squared and comparing that to the distance squared if many points are compared against the same radius, but I wouldn't have thought to mention that just from the question wording. – trichoplax is on Codidact now Jun 26 '16 at 21:39
  • It would also help to know how often the point is inside the circle. If there are enough points that are outside the circle then it may be worth including a fast test that excludes points outside a bounding square. – trichoplax is on Codidact now Jun 26 '16 at 21:40
  • Does your current implementation use an acceleration structure such as a grid? If not that would be your answer (for a huge speed up). Let me know and I'll write something up if that's the case. – trichoplax is on Codidact now Jun 26 '16 at 22:27
  • 1
    BTW, although an acceleration structure may be helpful, I still think that even brute-force testing 1500 points against each of 10 circles (for instance) is not a huge amount of calculation, even on a mobile device. I would look into making sure it's coded efficiently, i.e. not having unnecessary function calls or pointer indirections, and possibly using SIMD for the calculations, before going to the trouble of implementing an acceleration structure. – Nathan Reed Jun 26 '16 at 23:04
  • @NathanReed so as of now I am using a static math library of my own design that has functions like add subtract and multiply. It creates a new point struct and returns it. Would it be faster to now use the static class? – J.Doe Jun 26 '16 at 23:30
  • 1
    @J.Doe Ideally you would look at the generated code (assembly language) to see how it's coming out. Compilers can often optimize away small function calls by inlining, and can keep small structs in registers, etc. I don't develop for Swift or iOS so I can't tell you in detail about that platform, but a quick google did turn up this article on viewing disassembly in Swift. – Nathan Reed Jun 26 '16 at 23:36
  • @NathanReed Looking at assembly code is a bit beyond my knowledge so far, I think I will just try and replace the static methods before the final build. Thanks! – J.Doe Jun 26 '16 at 23:43

1 Answers1

2

Before focusing on optimising the individual process of moving a point, consider how many points are being processed this way. This is likely to give a much more significant speed up if it hasn't yet been addressed.

For example, if every point on the screen is being tested against every circle, then most of the points are being checked needlessly.

If instead you divide the screen into a grid, with each grid cell keeping a list of all points currently within it, then each circle only needs to be checked against the points that appear in the grid cells which that circle overlaps. This allows checking a few tens of points, instead of hundreds or thousands.

This is a much bigger speed up than you can hope to achieve by optimising the circumference calculation, and after this you may find that further optimisation is not needed.

  • Is that even faster then doing a quick broad phase AABB check? – J.Doe Jun 26 '16 at 23:00
  • If you do a bounding box check on each point, then that fast check is still being done on all 1000 points, for each circle. With a grid acceleration structure, if a circle only overlaps grid cells containing 30 points, none of the points outside those grid cells get checked at all, as they are not relevant. – trichoplax is on Codidact now Jun 26 '16 at 23:10
  • You will see the best speed up from a grid if the points are evenly spread over the screen. If the circles force all the points into a small area of the screen then the speed up will be less significant, and then you might need to look for other optimisations. – trichoplax is on Codidact now Jun 26 '16 at 23:12
  • A rough guide to whether this is the right answer is to observe the change of speed in your current implementation. Does it slow down (1) in proportion to the total number of points, or (2) in proportion to the number of points needing to be moved? (1) suggests you need an acceleration structure (such as a grid), while (2) suggests you need to optimise the movement of the points to the circumference. This answer is a best guess without seeing the code or the app running, so it may not be what you need. – trichoplax is on Codidact now Jun 26 '16 at 23:16
  • Also see Nathan Reed's comment on the question. I trust Nathan's intuition far more than my own. – trichoplax is on Codidact now Jun 26 '16 at 23:19
  • 2
    Ok I tried out broad phase, and grid phase. Turns out the best one was doing a AABB check before anything else. Reading all of your comments (thankyou so much) has helped me make sense of why. The radius is growing, and points group up quickly. Thank much! – J.Doe Jun 26 '16 at 23:42