Fracturing a grid with a number of open polygonal curves

   5894   5   2
User Avatar
Member
56 posts
Joined: March 2006
Offline
Any ideas on the following

0) In the viewport, go into Top view.
1) Lay down a Grid SOP.
2) Lay down a Curve SOP. Draw an open polygonal curve that snakes across the grid. Endpoints of the curve cannot lie inside the grid.
3) Repeat step 2) any number of times.
4) Merge the curves.
5) Lay down an Add SOP with a single point that lies within the grid.

The aim is to procedurally extract from the grid the unique polygon clipped by the various curves (4) that contains the point (5).
User Avatar
Member
24 posts
Joined: June 2006
Offline
I got frustrated by trying the ray sop and lots of fuse, it worked at times but would fail if the conditions were not perfect. I arrived at a solution, render the lines as an image, and use the trace sop to build the fractured mesh, then conncetivity should get your piece isolated
MD
User Avatar
Member
648 posts
Joined: July 2005
Offline
this file should work, but the attrib transfer is screwy,
even with a heavily divided source. hava a look and
see if you can fix.
b.t.w the subdivide sop doesn't propagate the class attribute,
bug or feature?

-cpb

Attachments:
deleteFrag.hipnc (324.0 KB)

User Avatar
Member
941 posts
Joined: July 2005
Offline
I got curious, so I did a quick implementation of the pseudo-code that I posted to the mailing list, and it seems to work pretty nicely. And with the exception of one additional call to unituv(), it's almost identical to what I posted – which surprised the heck outta me, I tell'ya.

Because of the way the algorithm works, you also get some cool features for free:
* The slicing curves can be closed.
* They can intersect.
* They extend implicitly along the tangents at each endpoint.
* Their endpoints are not restricted to be outside the grid.
* Each curve sets its own polarity (KeepInside/KeepOutside) via a primitive attribute named “KeepInside”.
* Even though it is currently hard-coded to a boolean AND, the internal test can be turned into any boolean op – in fact, this could be a per-curve attribute.
* Because it's implemented as a single custom function, there's no need to get into any weird loops in SOPs or anything like that (the looping is done inside the function).

I'm attaching a test with two flavours of the function: FracturePrim() has the functionality that Darran was after, and FracturePoints() is a variation that returns a list of all the points in the valid region (which you can use in a group sop).


##############################################################################
# Calc the grid primitive that is both closest to the reference point AND
# a member of the valid group defined by the slicing curves
##############################################################################
float FracturePrim(string grid_sop, string curves_sop, string add_sop) {
float gridprim = nprims(grid_sop);
float ncurves = nprims(curves_sop);
vector X = vector3(point(add_sop,0,“P”,0),0,point(add_sop,0,“P”,2));
float passed = 0;
for(c=0; c<ncurves; c++) {
float KeepInside = prim(curves_sop,c,“KeepInside”,0);
float Pu = unituv(curves_sop,c,pointdist(add_sop,0,curves_sop,c,1),D_U);
vector Pnear = vector3( primuv(curves_sop,c,“P”,0,Pu,0), 0,
primuv(curves_sop,c,“P”,2,Pu,0) );
vector Ptan = vector3( primduv(curves_sop,c,“P”,0,Pu,0,1,0), 0,
primduv(curves_sop,c,“P”,2,Pu,0,1,0) );
vector Pperp = vector3(-Ptan,0,Ptan);
if(!KeepInside) Pperp = -Pperp;
float Dot = dot(X-Pnear,Pperp);
if(Dot<0) { passed=0; break; }
passed += 1;
}
if(passed) {
gridprim = pointdist(add_sop,0,grid_sop,-1,3);
}

return gridprim;
}


##############################################################################
# Calc the list of points that belong to the valid region as defined by the
# slicing curves
##############################################################################
string FracturePoints(string grid_sop, string curves_sop) {
string pts = “”; # the selected point list
float npts = npoints(grid_sop);
float ncurves = nprims(curves_sop);
for(p=0; p<npts; p++) {
vector X = vector3(point(grid_sop,p,“P”,0),0,point(grid_sop,p,“P”,2));
float passed = 0;
for(c=0; c<ncurves; c++) {
float KeepInside = prim(curves_sop,c,“KeepInside”,0);
float Pu = unituv(curves_sop,c,pointdist(grid_sop,p,curves_sop,c,1),D_U);
vector Pnear = vector3( primuv(curves_sop,c,“P”,0,Pu,0), 0,
primuv(curves_sop,c,“P”,2,Pu,0) );
vector Ptan = vector3( primduv(curves_sop,c,“P”,0,Pu,0,1,0), 0,
primduv(curves_sop,c,“P”,2,Pu,0,1,0) );
vector Pperp = vector3(-Ptan,0,Ptan);
if(!KeepInside) Pperp = -Pperp;
float Dot = dot(X-Pnear,Pperp);
if(Dot<0) { passed=0; break; }
passed += 1;
}
if(passed) {
pts = pts + “ ” + p;
}
}

return pts;
}

Attachments:
happy.jpg (19.5 KB)
TestFracture.tar.gz (15.9 KB)

Mario Marengo
Senior Developer at Folks VFX [folksvfx.com] in Toronto, Canada.
User Avatar
Member
56 posts
Joined: March 2006
Offline
Hi Mario,

Perhaps I'm missing something … does your code actually fracture test object or simply return those constituent primitives lying inside the region enclosed by the bounding curves? It's the former that I was trying to do - and have mostly accomplished via the Cookie SOP (a la Francois' suggestion). Or did you envision using the Cookie approach to do the fracture and then this code snippet to identify the primitive of interest?

Cheers,
Darran.
User Avatar
Member
941 posts
Joined: July 2005
Offline
The FracturePrim() function satisfies your original request, which was:
futnuh
The aim is to procedurally extract from the grid the unique polygon clipped by the various curves (4) that contains the point (5).

It doesn't create new primitives by slicing existing ones, no (but then, you never asked for that ). What it *does* do is “extract from the grid the unique polygon clipped by the various curves (4) that contains the point (5)”.

The FracturePoints() function currently returns the region defined by a boolean AND of all the half-spaces defined by the curves, but it could be changed to return any other combination of these spaces. But again, this was not intended to *create* new polygons, but rather “fracture” existing polygons into different groups (i.e: an extension to your original request).
Mario Marengo
Senior Developer at Folks VFX [folksvfx.com] in Toronto, Canada.
  • Quick Links