Jump to content
anicg

remove primitives that are not perfect rectangles

Recommended Posts

I need to get rid of all primitives that:

  • have more or less than 4 points,
  • and of those that have 4 points, I need to delete the primitives that are not perfect rectangles (they don't need to be squares, I just need to get rid of the "distorted" rectangles

 

Edited by anicg

Share this post


Link to post
Share on other sites

Hi, you can do something like this inside a Primitive Wrangle and use the deviation parameter (from 0 to 1) to remove quad primitives based on how much one of its edges can deviate from the average edge length:

float deviation = ch("deviation");

int count = primvertexcount ( 0, @primnum );
if ( count != 4 )
    removeprim ( geoself ( ), @primnum, 1 );
else
{
    int isclosed = primintrinsic ( geoself ( ), "closed", @primnum );
    if ( isclosed )
    {
        int pts [ ] = primpoints ( geoself ( ), @primnum );
        float edgelen [ ] = { };
        for ( int i = 0; i < len ( pts ) - 1; ++i )
        {
            vector p0 = point ( geoself ( ), "P", pts [ i ] );
            vector p1 = point ( geoself ( ), "P", pts [ i + 1 ] );
            
            append ( edgelen, distance2 ( p0, p1 ) );
        }
        
        float perim = primintrinsic ( geoself ( ), "measuredperimeter", @primnum );
        perim *= perim;
        
        float avgperim = perim / count;
        foreach ( float elen; edgelen )
        {
            if ( abs ( elen - avgperim ) / avgperim < deviation )
            {
                removeprim ( geoself ( ), @primnum, 1 );
                break;
            }
        }
    }
}

 

  • Like 1

Share this post


Link to post
Share on other sites

Hi Mani,

a rectangle is defined by having four corners with rectangular angles. So first get rid of non-quads in a primitive wrangle:

if(primvertexcount(0, i@primnum) != 4){
    removeprim(0, i@primnum, 1);
}

Then create vertex attributes with the direction from one vertex to the next (and the number of the next vertex):

int num_vtx = primvertexcount(0, i@primnum);
int index_curr = vertexprimindex(0, i@vtxnum);
int index_next = (index_curr + 1) % num_vtx;
int vtx_next = primvertex(0, i@primnum, index_next);

int pt_curr = vertexpoint(0, i@vtxnum);
int pt_next = vertexpoint(0, vtx_next);
vector pos_curr = point(0, 'P', pt_curr);
vector pos_next = point(0, 'P', pt_next);
vector dir = normalize(pos_next - pos_curr);

v@dir = dir;
i@vtx_next = vtx_next;

Lastly you would filter out primitives by their inner angle between consecutive vertices:

float tol = chf('tolerance');

int vtx[] = primvertices(0, i@primnum);
foreach(int vt; vtx){
    int vtx_next = vertex(0, 'vtx_next', vt);
    vector dir_0 = vertex(0, 'dir', vt);
    vector dir_1 = vertex(0, 'dir', vtx_next);
    float angle = dot(dir_0, dir_1);
    if(abs(angle) > tol){
        removeprim(0, i@primnum, 1);
        break;
    }
}

 

keep_rect_quads.hipnc

  • Like 1

Share this post


Link to post
Share on other sites

and what about, after removing non-quads, just testing (in loop per prim) whether the perimeter of a primitive (using measure SOP) is equal to a distance between any two points multiplied by 4? does it make sense?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×