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).
Fracturing a grid with a number of open polygonal curves
5937 5 2- futnuh
- Member
- 56 posts
- Joined: March 2006
- Offline
- mattd
- Member
- 24 posts
- Joined: June 2006
- Offline
- anon_user_40689665
- Member
- 648 posts
- Joined: July 2005
- Offline
- Mario Marengo
- 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;
}
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;
}
- futnuh
- 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.
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.
- Mario Marengo
- Member
- 941 posts
- Joined: July 2005
- Offline
The FracturePrim() function satisfies your original request, which was:
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).
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).
-
- Quick Links