A Flash Developer Resource Site

Results 1 to 9 of 9

Thread: [AS2] Point in Polygon (beginfill is not instant)

  1. #1
    Senior Member Alluvian's Avatar
    Join Date
    Jun 2006
    Posts
    967

    [AS2] Point in Polygon (beginfill is not instant)

    I figured Point in Polygon would be a SNAP in flash. Just draw the polygond with beginfill, moveto, lineto, endfill and then perform a shapeflag = true hittest!

    Drawing the shape and checking hittesting with mouse coordinate and onenterframe worked great. So I wasted a bunch of time making a polygon drawing function which I was going to use to draw a polygon, perform hittests against it, and then erase the polygon and associated movieclip.

    Unfortunately
    I don't know if it waits till the next frame or what, but you can't do a shapeflag = true hittest on movieclip in code that executes in the same frame. For instance:
    PHP Code:
    var square_mc:MovieClip this.createEmptyMovieClip("square_mc"1);
    square_mc.beginFill(0xFF0000);
    square_mc.moveTo(1010);
    square_mc.lineTo(10010);
    square_mc.lineTo(100100);
    square_mc.lineTo(10100);
    square_mc.lineTo(1010);
    square_mc.endFill();
    trace(square_mc.hitTest(50,50,true));  // returns false
    trace(square_mc.hitTest(50,50,false));  // returns true 
    I am trying to make a bunch of objects (to be rendered as bitmaps) in a bricklike grid pattern within polygonal shapes. Works fine for rectangles, and I was going to use the same rectangle row/column code but with an added "is point in polygon" check for each object, creating it if it is inside the polygon.

    Unfortunately the above issue prevents this from working right. I guess I could keep the movieclips with the polygons till the next frame, then check all the objects to see if they are THEN inside their appropriate polygons and THEN delete those extra movieclips, but that just seems like a very lame hack of a solution.

    Anyone now a decen point in poly function for flash as2? Right now I have the vertices as arrays of point objects, but I could be flexible.

  2. #2
    Senior Member rachil0's Avatar
    Join Date
    Jul 2007
    Location
    Columbus, OH.
    Posts
    465
    Use a sequence of cross products to sidetest against each edge of the polygon (assuming it's convex). You can also do dot products against the normals of the edges, in 2D these operators are exactly the same.

    If your points are sequenced in a counter clockwise fashion in a right handed coordinate system, do something like:

    Code:
      function testInside (testPoint: Vector2D, p : Polygon) : Boolean
         {
         for each Edge e of Polygon p
            {
            var point1 : Vector2D = start of Edge e
            var point2 : Vector2D = end of the Edge e
            var edge_displacement : Vector2D = point2 - point1
            var test_displacement : Vector2D = testPoint - point1
            var det : Number = cross(edge_displacement, test_displacement);
            if (det < 0) 
              return false;
            }
         return true;
         }
    
       function cross (v1, v2) : Number
          {
          return v1.x * v2.y - v2.x*v1.y;
          }
    If your polygon is not convex, tesselate it into a union of convex polygons, do a insideness test against each one, and "or" the result.
    Last edited by rachil0; 04-15-2008 at 05:47 PM.

  3. #3
    Senior Member Alluvian's Avatar
    Join Date
    Jun 2006
    Posts
    967
    Know of a way tesselate a concave poly into a series of convex ones?

    Seems like I am increasing my odds of having an edge case with more polygons (object on an edge will cause extra issues with most point in poly schemes).

    Anyone know of a ray casting solution for AS2?

  4. #4
    Senior Member Alluvian's Avatar
    Join Date
    Jun 2006
    Posts
    967
    An ugly solution I am kicking around is making all the objects, waiting 2 frames and using hittest to see which ones I should delete. Not a pleasant solution for me with the number of arrays I have them in for cross referencing purposes though. (region arrays for fast hittesting, all of type array for checking when game is won, and a third for seeing when I can turn of some displacement map effects to shave some cpu time)

  5. #5
    Senior Member Alluvian's Avatar
    Join Date
    Jun 2006
    Posts
    967
    FOUND IT!

    For others who want it, here is my AS2 rewrite of the C++ code found here: http://geometryalgorithms.com/Archiv...rithm_0103.htm

    This uses raycasting so it will work on concave or convex polys. It will even work with polys with holes in them. Anyway, I take very little credit since the C++ code practically ported itself.

    PHP Code:
    import flash.geom.Point;
    pointinpoly = function(P:PointV:Array){
        var 
    crossing:Number 0;
        var 
    n:Number V.length 1;
        for(var 
    0i<ni++){
            if (((
    V[i].<= P.y) and (V[i+1].P.y)) or ((V[i].P.y) and (V[i+1].<= P.y))) { 
                var 
    vt:Number = (P.V[i].y) / (V[i+1].V[i].y);
                if (
    P.V[i].vt * (V[i+1].V[i].x)) {crossing++;}
            }
        } 
    // next i
        
    if (crossing 2) {return true;} else {return false;}
    // end of pointinpoly 
    Where P is a point object and V is an array of vertices as point objects. The polygon should be closed, meaning the first and last points should be the same. v[0] = v[n]

  6. #6
    Senior Member rachil0's Avatar
    Join Date
    Jul 2007
    Location
    Columbus, OH.
    Posts
    465
    If you build in some fudge factor into that determinant test, you shouldn't have significant problems with edge cases. Maybe edges count as inside, maybe they don't, but you as a system designer can make that choice willfully and in a fault-tolerant way with that determinant test.

    Decomposition of complex polygons into convex sets has been a part of every constrained movement system I've tried to write, so it's always part of my content creation pipeline. You can always tesselate shapes by hand, that's what I do at least.

    If this is not an option, I do have an old solution to the tesselation problem programmed up. I think it works by corner lopping but I don't recall every detail. It's attached and there's a few pngs in there that shows the sample input and output. The catch is that it's written in matlab so you'd have a tedious amount of porting to do. It will not handle holes, intersecting polygons and is not thoroughly tested (bug reports welcome).


    EDIT: Whoops, too late. Glad you got it fixed.
    Attached Files Attached Files
    Last edited by rachil0; 04-15-2008 at 11:19 PM.

  7. #7
    Pumpkin Carving 2008 ImprisonedPride's Avatar
    Join Date
    Apr 2006
    Location
    Grand Rapids MI
    Posts
    2,377
    That's nifty stuff Alluvian. I've already got this idea in my head just from reading your description. Would be fun to play around with if I ever get the time (that whole college things disrupts my schedule yet again... ARGH).
    The 'Boose':
    ASUS Sabertooth P67 TUF
    Intel Core i7-2600K Quad-Core Sandy Bridge 3.4GHz Overclocked to 4.2GHz
    8GB G.Skill Ripjaws 1600 DDR3
    ASUS ENGTX550 TI DC/DI/1GD5 GeForce GTX 550 Ti (Fermi) 1GB 1GDDR5 (Overclocked to 1.1GHz)
    New addition: OCZ Vertex 240GB SATA III SSD
    WEI Score: 7.6

  8. #8
    Senior Member tonypa's Avatar
    Join Date
    Jul 2001
    Location
    Estonia
    Posts
    8,223
    Quote Originally Posted by Alluvian
    trace(square_mc.hitTest(50,50,true)); // returns false
    Depends on the version of Flash:
    *with F8 it returns false
    *with F9 (AS2) it returns true

  9. #9

    [AS2] Point in Polygon & Pick's Theorem for Geoboard

    I know it's a year and a half later, but I have a question on this topic. Although the code above does indeed work if a point is clearly inside a polygon, it is a bit flaky when it comes to points that are on the line. How could this code be adjusted to determine if a point is on the line or not? I could do the hitTest thing I suppose, but it would be cool to do it with math. The reason I'd like to do this is because I'm working on a Geoboard and I'd love to use Pick's Theorem to find the area of an irregular polygon.

    Here is the code modified for my purposes (not optimized yet). I don't think I mucked it up, but it's a possibility!

    Code:
    function pointInPolyCheck(thisBand, pointX, pointY){
    	
    	var myPoints = thisBand.pointsClip.myPoints;
    	var crossings = 0;
    	
    	// check point against all of the polygon's lines
    	for (var i=0; i<myPoints.length; i++){
    		var linePoint1 = thisBand.pointsClip["point"+myPoints[i]];
    		var linePoint2 = thisBand.pointsClip["point"+myPoints[(i+1)%(myPoints.length)]];
    		
    		if (((linePoint1._y <= pointY) && (linePoint2._y > pointY)) || ((linePoint1._y > pointY) && (linePoint2._y <= pointY))){ 
    			var vt:Number = (pointY - linePoint1._y) / (linePoint2._y - linePoint1._y);
    			if (pointX < linePoint1._x + vt * (linePoint2._x - linePoint1._x)) {
    				crossings++;
    			}
    		}
    	}
    	
    	//trace("crossings:"+crossings);
    	if (crossings % 2){
    		// point is in polygon
    		return true;
    	} else {
    		return false;
    	}
    }
    Any insight would be greatly appreciated.

    Update: I just found this, which is definitely an easier approach. It seems to work great even on complex polygons so I should be all good. Here are examples for a triangle and a square if anyone else is ever looking to figure out the area of a polygon.

    x1 = 0;
    y1 = 0;
    x2 = 10;
    y2 = 0;
    x3 = 10;
    y3 = 10;
    area = ((x1*y2 + x2*y3 + x3*y1) - (x2*y1 + x3*y2 + x1*y3))/2;
    trace(area);

    x1 = 0;
    y1 = 0;
    x2 = 10;
    y2 = 0;
    x3 = 10;
    y3 = 10;
    x4 = 0;
    y4 = 10;
    area = ((x1*y2 + x2*y3 + x3*y4 + x4*y1) - (x2*y1 + x3*y2 + x4*y3 + x1*y4))/2;
    trace(area);

    I suppose I should have started a new topic in the Math forum for this but I can't seem to figure out how to delete this. Sorry
    Last edited by sirzooass; 03-04-2009 at 08:20 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center