4 Replies Latest reply on Sep 2, 2010 1:36 AM by excessdenied

    Why is Flash's Rectangle.intersection() slow?

    Robotacid Level 1

      For some reason I can't fathom, I have long been able to get faster intersection tests for my own version of the Rectangle object. This is silly. Why should my code be any faster than the Flash player team's code - who have had 10 iterations of the Flash player to get it right?

       

      example:

       

      package {
           import flash.display.Sprite;
           import flash.events.Event;
           import flash.geom.Rectangle;
           import flash.utils.getTimer;
           
           /**
            * ...
            * @author Aaron Steed, robotacid.com
            */
           public class Main extends Sprite {
                
                public function Main():void {
                     if (stage) init();
                     else addEventListener(Event.ADDED_TO_STAGE, init);
                }
                
                private function init(e:Event = null):void {
                     removeEventListener(Event.ADDED_TO_STAGE, init);
                     // entry point
                     
                     var t:int, i:int;
                     
                     var flashRect:Rectangle = new Rectangle();
                     var myRect:Rect = new Rect();
                     
                     
                     t = getTimer();
                     for(i = 0; i < 1000000; i++){
                          flashRect.intersects(flashRect);
                     }
                     trace(getTimer() - t);
                     
                     t = getTimer();
                     for(i = 0; i < 1000000; i++){
                          myRect.intersects(myRect);
                     }
                     trace(getTimer() - t);
                }
                
           }
           
      }
      class Rect{
           
           public var x:Number;
           public var y:Number;
           public var width:Number;
           public var height:Number;
                
           public function Rect(x:Number = 0, y:Number = 0, width:Number = 0, height:Number = 0){
                this.x = x;
                this.y = y;
                this.width = width;
                this.height = height;
           }
           /* Do two Rects intersect? */
           public function intersects(b:Rect):Boolean{
                return !(this.x > b.x + (b.width - 1) || this.x + (this.width - 1) < b.x || this.y > b.y + (b.height - 1) || this.y + (this.height - 1) < b.y);
           }
      }

       

      Hell, even if I write a separate method and use

       

      return !(this.x > b.x + (b.width - 1) || this.x + (this.width - 1) < b.x || this.y > b.y + (b.height - 1) || this.y + (this.height - 1) < b.y);

       

      with a flash Rectangle it's still faster than using crappy old Rectangle.intersects()

       

      Why?

       

      Is there anyone at Adobe that could fix this, as I'm a bit fed up of up of having to write my own versions of Flash's geometry objects.

        • 1. Re: Why is Flash's Rectangle.intersection() slow?
          Ned Murphy Adobe Community Professional & MVP

          You won't find Adobe folks here very often...

           

          Adobe - Wishlist & Bug Report
          -----------------------------

          http://www.adobe.com/cfusion/mmform/index.cfm?name=wishform

          1 person found this helpful
          • 2. Re: Why is Flash's Rectangle.intersection() slow?
            Robotacid Level 1

            Cheers mate, I'll forward this to the bug report thingamajig. Seems to be where the site directs me from there.

            • 3. Re: Why is Flash's Rectangle.intersection() slow?
              excessdenied Level 1

              Hi. Nice work on the custom intersects(). It's about 2x as fast as Rectangle.intersects() too, on my computer. Can I ask why you use

              (b.width - 1), (this.width - 1), etc. instead of just b.width, this.width, etc.? Why the minus 1? And, why (won't) the minus 1 affect its accuracy when x,y,width,height are decimals?

              • 4. Flash's Rectangle.intersects() is not only slow, but buggy...
                excessdenied Level 1

                Hi, I tried running a benchmark to test the speed, and accuracy of your intersects(), and I discovered that yours is not only 2x faster on my computer, it is also more accurate/robust than Flash's Rectangle.intersects()!

                Below is my benchmarking code, just copy into the first frame of a new Flash document and run.

                I have no idea why your suggestion (http://bugs.adobe.com/jira/browse/ASL-65) is marked resolved, when it is clearly not,

                but I have filed/cloned a bug report (http://bugs.adobe.com/jira/browse/FP-5350) regarding the issue, and also listing your version of intersects() as a workaround.

                 

                Thanks, and cheerio XD.

                 

                import flash.geom.Rectangle;
                import flash.utils.getTimer;
                import flash.text.TextField;

                function normal(i1:int, i2:int):int {
                    var totalTime:int = 0;
                    for (var i:int=0; i<i1; i++) {
                        var rect1:Rectangle = new Rectangle(Math.random()*200-100, Math.random()*200-100, Math.random()*200-100, Math.random()*200-100);
                        var rect2:Rectangle = new Rectangle(Math.random()*200-100, Math.random()*200-100, Math.random()*200-100, Math.random()*200-100);
                       
                        var startTime:int = getTimer();
                        for (var j:int=0; j<i2; j++) {
                            rect1.intersects(rect2);
                        }
                        totalTime += getTimer() - startTime;
                    }
                    return totalTime;
                }
                function custom(i1:int, i2:int):int {
                    var totalTime:int = 0;
                    for (var i:int=0; i<i1; i++) {
                        var rect1:Rectangle = new Rectangle(Math.random()*200-100, Math.random()*200-100, Math.random()*200-100, Math.random()*200-100);
                        var rect2:Rectangle = new Rectangle(Math.random()*200-100, Math.random()*200-100, Math.random()*200-100, Math.random()*200-100);
                       
                        var startTime:int = getTimer();
                        for (var j:int=0; j<i2; j++) {
                            intersects(rect1, rect2);
                        }
                        totalTime += getTimer() - startTime;
                    }
                    return totalTime;
                }
                function intersects(a:Rectangle, b:Rectangle):Boolean {
                    return !(a.x > b.x + (b.width - 1) || a.x + (a.width - 1) < b.x || a.y > b.y + (b.height - 1) || a.y + (a.height - 1) < b.y);
                }
                function test(i1:int, i2:int):int {
                    var totalTime:int = 0;
                    for (var i:int=0; i<i1; i++) {
                        var rect1:Rectangle = new Rectangle(Math.random()*200-100, Math.random()*200-100, Math.random()*200-100, Math.random()*200-100);
                        var rect2:Rectangle = new Rectangle(Math.random()*200-100, Math.random()*200-100, Math.random()*200-100, Math.random()*200-100);
                       
                        var startTime:int = getTimer();
                        for (var j:int=0; j<i2; j++) {
                            try {
                                assert(intersects(rect1, rect2) == rect1.intersects(rect2));
                            }
                            catch (e:Error) {
                                this.x = 100;
                                this.y = 100;
                                graphics.clear();
                                graphics.beginFill(0xff0000, 0.5);
                                graphics.drawRect(rect1.x,rect1.y,rect1.width,rect1.height);
                                graphics.endFill();
                                graphics.beginFill(0x00ff00, 0.5);
                                graphics.drawRect(rect2.x,rect2.y,rect2.width,rect2.height);
                                graphics.endFill();
                                trace(rect1, rect2, intersects(rect1, rect2), rect1.intersects(rect2));
                                throw new Error("Assertion failed!");
                            }
                        }
                        totalTime += getTimer() - startTime;
                    }
                    return totalTime;
                }
                function assert(expression:Boolean):void {
                    if (!expression) throw new Error("Assertion failed!");
                }
                trace('Rectangle.intersects():', normal(1000, 1000));
                trace('custom intersects():', custom(1000, 1000));
                trace('test accuracy of custom intersects():', test(1000, 1000));