Results 1 to 8 of 8

Thread: Fix Polygon Vertexorder

  1. #1
    Sergeant serthy's Avatar
    Join Date
    Nov 2012
    Posts
    450
    Thanks
    96
    Thanked 296 Times in 188 Posts

    Fix Polygon Vertexorder

    Sanibonani =)

    I have an array of n unsorted points (x,y,z).
    These vertices will create a !convex! polygon.
    Now I need your help to create an indexlist of these vertices in a sorted way:

    Example:

    5 points in 3d space: ( A , B , D , C )
    Code:
    	A      B
    
    
    
    
    
    
    	C      D
    connect them in the unsorted order as they are:
    Code:
    	A------B
    	 \    /
    	  \  /
    	   \/
    	   /\
    	  /  \
    	 /    \
    	C------D
    now sort them (counter-)clock wise:
    Code:
    	A      B
    
    
    
    
    
    
    	D      C
    and connect them again: ( A , B , C , D )
    Code:
    	A------B
    	|      |
    	|      |
    	|      |
    	|      |
    	|      |
    	|      |
    	C------D
    I am currently going over a dotProduct from the center of the polygon, but stucked there...
    Maybe arcTan( x / y ) works!?

    PHP Code:
    sortVertsOnPolyverts center )
    {
        
    dots = [];
        
    idx = [];

        for( 
    verts.size i++ )
        {
            
    v1 verts[i];                //catch current vert
            
    v2 verts[( ) % verts.size];    //catch next vert to compare to

            
    v1 -= center;    //calculate current directions
            
    v2 -= center;

            
    dots[i] = ( v1[0] * v2[1] - v1[1] * v2[0] ); //calculate the dot(2D)
            
    idx[i] = i;    //store the index-information in a different array
        
    }

        
    //sort them by their dot-value
        
    for( dots.size i-- )
        {
            for( 
    j++ )
            {
                if( 
    dots[i] > dots[1] )    
                {
                    
    dots[i];    //swap
                    
    dots[i] = dots[1];
                    
    dots[1] = t;

                    
    idx[i];        //also swap the index array
                    
    idx[i] = idx[1];
                    
    idx[1] = t;
                }
            }
        }

        return 
    idx;    //return sorted index array

    EDIT:

    or just get vertex #1 as reference and calculate all other angles and compare them:
    guess this woll work also... geez, why i didnt get this in my first toughts?!

    PHP Code:
        dirs = [];
        
    dirs[0] = 0;
        
    dir vectorNormalizeverts[0] - center );

        for( 
    verts.size i++ )
        {
            
    dirs[i] = aCosvectorDotdir vectorNormalizeverts[i] - center ) ) );
            
    idx[i] = i;
        } 
    EDIT: dont mind, im confused, the dot is the almost angle ~.~
    Last edited by serthy; 27th January 2013 at 18:18.

  2. The Following User Says Thank You to serthy For This Useful Post:

    kung foo man (27th January 2013)

  3. #2
    Assadministrator kung foo man's Avatar
    Join Date
    Jun 2012
    Location
    trailerpark
    Posts
    2,011
    Thanks
    2,102
    Thanked 1,084 Times in 753 Posts
    Sanibonani

    Could you provide a full example to test with?
    timescale 0.01

  4. #3
    Sergeant serthy's Avatar
    Join Date
    Nov 2012
    Posts
    450
    Thanks
    96
    Thanked 296 Times in 188 Posts
    Code:
    init()
    {
    	count = 6;
    	radius = 100;
    	verts = [];
    
    	//create a convex poly 
    	for( i = 0 ; i < count ; i++ )
    	{
    		angle = 360 / count * i;
    		verts[i] = ( radius * cos( angle ) , radius * sin( angle ) , 0 );
    	}
    
    	order = [];
    
    	//assign the order
    	for( i = 0 ; i < verts.size ; i++ )
    	{
    		order[i] = i;
    	}
    
    	//shuffle them
    	for( i = 0 ; i < order.size ; i++ )
    	{
    		j = randomInt( order.size );
    		t = order[i];
    		order[i] = order[j];
    		order[j] = t;
    	}
    
    	//show unsortedorder
    	s = "\n";
    
    	for( i = 0 ; i < order.size ; i++ )
    	{
    		s += ( "order[" + i + "] = " + order[i] + "\n" );
    	}
    
    	debug( s );
    
    	//get the center
    	center = calculatePolyCenter( verts );
    	//sort the vertices
    	order = sortVertsOnPoly( verts , center );
    
    	//show sorted order
    	s = "\n";
    
    	for( i = 0 ; i < verts.size ; i++ )
    	{
    		s += ( "sorted order[" + i + "] = " + order[i] + "\n" );
    	}
    
    	debug( s );
    }
    
    sortVertsOnPoly( verts , center )
    {
    	idx = [];
    	idx[0] = 0;
    	dirs = [];
    	dirs[0] = 0;
    	dir = vectorNormalize( verts[0] - center );
    
    	for( i = 1 ; i < verts.size ; i++ )//i should use arctan(y/x) instead here... need abit time to think about it...
    	{
    		dot = vectorDot( dir , vectorNormalize( verts[i] - center ) );
    
    		if( dot < 0 )
    			dirs[i] = 360 - aCos( dot );
    		else
    			dirs[i] = aCos( dot );
    
    		idx[i] = i;
    	}
    
    	swapped = true;
    
          for( j = 1 ; swapped ; j++ )
    	{
                swapped = false;
    
                for( i = 0 ; i < dirs.size - j ; i++ )
    		{
    			if( dirs[i] > dirs[i + 1] )	
    			{
    				t = dirs[i];
    				dirs[i] = dirs[i + 1];
    				dirs[i + 1] = t;
    
    				t = idx[i];
    				idx[i] = idx[i + 1];
    				idx[i + 1] = t;
    
                            swapped = true;
                      }
                }
          }
    
    	return idx;
    } 
    
    calculatePolyCenter( verts )
    {
    	center = ( 0 , 0 , 0 );	
    	
    	for( i = 0 ; i < verts.size ; i++ )
    	{
    		center += verts[i];
    	}
    
    	return vectorScale( center , 1 / verts.size );
    }
    
    vectorScale( v , s )
    {
    	return ( v[0] * s , v[1] * s , v[2] * s );
    }
    
    debug( x )
    {
    iPrintLn( "debug: " + x );
    }
    Last edited by serthy; 27th January 2013 at 19:37.

  5. #4
    Sergeant serthy's Avatar
    Join Date
    Nov 2012
    Posts
    450
    Thanks
    96
    Thanked 296 Times in 188 Posts
    solved:

    instead of the dotproduct you should use the arcus tangenz to calculate the angle for comparison:

    PHP Code:
        t aTan( ( verts[i][0] - verts[0][0] ) / ( verts[i][1] - verts[0][1] ) );

        if( 
    )
            
    += 180;

        
    dirs[i] = t

  6. The Following User Says Thank You to serthy For This Useful Post:

    kung foo man (27th January 2013)

  7. #5
    Assadministrator IzNoGoD's Avatar
    Join Date
    Aug 2012
    Posts
    1,718
    Thanks
    17
    Thanked 1,068 Times in 674 Posts
    Dont use tangens. Use vectorproduct, not dotproduct.

    Same hack I used in navmesh, use it with 2d-inputs.


    Code:
    ispointinsidenode(point,node)
    {
    	//DONT CHECK HEIGHT OF POINT. IMPORTANT!
    	//now, for each child of [node] find another connected child of [node]
    	first=undefined;
    	previous=undefined;
    	posneg=0;
    	inside=true;
    	child=level.child[node.child[0]];
    	for(iterations=0;iterations<node.child.size&&(!isdefined(first)||first.num!=child.num);iterations++)
    	{
    		for(i=0;i<child.conn.size;i++)
    		{
    			if(isinarray(child.conn[i],node.child))
    			{
    				//this connection is one of the node ones
    				if(!isdefined(first))
    					first=child;
    				if(!isdefined(previous)||previous.num!=child.conn[i])
    				{
    					//not one that has already been checked
    					previous=child;
    					child=level.child[child.conn[i]];
    					ans=vectorprod2d(point-previous.origin,child.origin-previous.origin);
    					if(posneg==0)
    					{
    						if(ans<0)
    							posneg=-1;
    						else if(ans>0)
    							posneg=1;
    					}
    					else if(ans*posneg<0)
    						return false;
    				}
    			}
    		}
    	}
    	return true;
    }
    with
    Code:
    
    vectorprod2d(vec1,vec2) 
    {
    	num=vec1[0]*vec2[1]-vec1[1]*vec2[0];
    	return num;
    }
    If you have 2 lines and do a vectorprod2d on them, it will become positive if the second line is going "more right" than the first. Negative if "more left" (directions might be flipped though, but always same result)
    This should be lighter than tangens.

  8. The Following User Says Thank You to IzNoGoD For This Useful Post:

    kung foo man (27th January 2013)

  9. #6
    Sergeant serthy's Avatar
    Join Date
    Nov 2012
    Posts
    450
    Thanks
    96
    Thanked 296 Times in 188 Posts
    okay, does vectorprod2d returns values which are sortable?
    didnt tested it right now, but seems to work on the first view

  10. #7
    Assadministrator IzNoGoD's Avatar
    Join Date
    Aug 2012
    Posts
    1,718
    Thanks
    17
    Thanked 1,068 Times in 674 Posts
    Pick 3 random points
    Make a triangle out of them.

    Get another point
    for all 3 points you already had:
    draw vector from point to newpoint
    draw 2 vectors from point to other 2 points
    vectorprod2d each of those 2 lines with the line to newpoint
    If one of them is positive and one of them is neg, ignore
    Other 2 points will have both positive or both negative outcome
    create new triangle with those 2 and newpoint

    get another new point
    look to which of the triangles it is closest (average coordinates of all points of all triangles)

    repeat above procedure

    If at some point above statements become false, its not a convex polygon.

    At the end youll be left with a shitload of triangles. You need to sort those then (linkedlist i suppose to create the triangles)

    Just pick a random start point, add to list and remove from original list (to prevent duplicates)
    get rightmost connected point (multiple triangles can be connected to one point, thus multiple points connected to it), add to list, remove from original
    repeat until original list is empty.

    return list.

    Good luck

    Edit: method only works for 2d stuff, not 3d.

  11. The Following User Says Thank You to IzNoGoD For This Useful Post:

    kung foo man (28th January 2013)

  12. #8
    Sergeant serthy's Avatar
    Join Date
    Nov 2012
    Posts
    450
    Thanks
    96
    Thanked 296 Times in 188 Posts

    [solved]

    made something here, used only while navmesh creation, so it doesnt need to have a good performance.
    works also for randomly added verteices, no need to keep the order
    PHP Code:
    sortVertsOnNodenode )
    {
        if( 
    node.verts.size <= //sort a line/point genious?
            
    return node.verts//sure not!

        
    ids = [];
        
    srt = [];
        
    ids[0] = 0;
        
    srt[0] = 0;

        
    dir vectorNormalizelevel.verts[node.verts[0]].origin node.origin ); 
             
        for( 
    node.verts.size i++ )
        {
            
    vectorNormalizelevel.verts[node.verts[i]].origin node.origin ); 
                    
    dot vectorDotdir );

            
    57.2957795 aCosdot ); //1 rad = 57.2957795 deg

            
    if( ( dir[0] * d[1] ) - ( d[0] * dir[1] ) < 
                
    360 a;

            
    ids[i] = i;
            
    srt[i] = a;
        }         

            
    //sort the shit out of them
        
    for( node.verts.size i++ )
        {
            for( 
    node.verts.size j++ )
            {
                if( 
    srt[j] > srt[1] )
                {
                    
    ids[j];
                    
    ids[j] = ids[1];
                    
    ids[1] = t;

                    
    srt[j];
                    
    srt[j] = srt[1];
                    
    srt[1] = t;
                }
            }
        }

        
    verts = [];

        for( 
    ids.size i++ )
        {
            
    verts[i] = node.verts[ids[i]];
        }

        return 
    verts//gotta catch 'em all!

    just to mark this as solved

  13. The Following User Says Thank You to serthy For This Useful Post:

    kung foo man (30th March 2013)

Posting Permissions

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