[Python][SOP] Getting the number x elements in a geometry?

   2454   17   1
User Avatar
Member
339 posts
Joined: June 2013
Online
I'm trying to find the number of edges in a geometry object [www.sidefx.com].

Just like VEX and HScript I don't see an nedges. With SOPs I can mitigate this by making a dummy edge group and then using VEX's nedgesgroup()(which doesn't support adhoc group patterns or I would put "*").


With points, prims and vertices I honestly didn't also also find a straight answer in Python. Doing len(geo.points())is quite wasteful given that pointsneeds to build an object for each point, and I just want to know how many there are. That said I was able to circumvent this by using the detail intrinsics, geometry.intrinsicValue("pointcount")but alas, there is no "edgecount"

Is there maybe some procedure that is escaping me or is it RFE time?

Thanks
prb
User Avatar
Member
143 posts
Joined: May 2017
Offline
Hey,

>>> obj = hou.node('/obj/geo1/box1')
>>> geo = obj.geometry()

# count by attribute class...
>>> len(geo.globEdges("*"))
12
>>> len(geo.globPoints("*"))
8

# edge object
>>> geo.point(2)
<hou.Point #2 of geometry in /obj/geo1/box1 read-only>
>>> p1 = geo.point(0)
>>> p2 = geo.point(1)
>>> edg = geo.findEdge(p1, p2)  # you can also look for edge groups
<hou.Edge #0 - 1 of geometry in /obj/geo1/box1 read-only>

>>> edg.edgeId()
'p0-1'
>>> edg.length()
1.0

There are a few more edge methods:
Edge [www.sidefx.com]

There is only one intristisic that relates to edges; which contains the edge groups .

An example of how to get the edge count in vex:
string edg_grp[] = detailintrinsic(0, "edgegroups");
printf("%s \n", edg_grp); // {group1, group2}

for(string grp : edg_grp)
{
    int n = nedgesgroup(0, grp);
    printf("%s: %i  \n", grp, n);
    // group1: 12 - the first group contains all cube edges 
    // group2: 4 -  the second only the bottom
}

Create a new edge group in vex:
// int  setedgegroup(int geohandle, string name, int pt0, int pt1, int value)
setedgegroup(0, "new_edg_grp", 0, 1, 1);

Find the new edge group in python:
>>> grp = geo.findEdgeGroup("new_edg_grp")
>>> len(grp.edges())
1
Edited by viklc - Oct. 6, 2022 00:26:28
User Avatar
Member
900 posts
Joined: Feb. 2016
Offline
probiner
With points, prims and vertices I honestly didn't also also find a straight answer in Python. Doing len(geo.points())is quite wasteful given that pointsneeds to build an object for each point, and I just want to know how many there are. That said I was able to circumvent this by using the detail intrinsics, geometry.intrinsicValue("pointcount")but alas, there is no "edgecount"

Is there maybe some procedure that is escaping me or is it RFE time?

Thanks
prb


Since version 19.5.331, we have new methods to know the number of elements in a group:
EdgeGroup.edgeCount(), PointGroup.pointCount(), PrimGroup.primCount(), and VertexGroup.vertexCount()

Devs were super fast to implement these methods after I submitted the RFE (I had your very same concerns about performance of using len(geo.points()) )
I guess they could be as much fast if you RFE for the more general methods.
Edited by Andr - Oct. 6, 2022 08:55:27
User Avatar
Member
339 posts
Joined: June 2013
Online
vik_lc
Hey,

>>> obj = hou.node('/obj/geo1/box1')
>>> geo = obj.geometry()

# count by attribute class...
>>> len(geo.globEdges("*"))
12
>>> len(geo.globPoints("*"))
8

# edge object
>>> geo.point(2)
<hou.Point #2 of geometry in /obj/geo1/box1 read-only>
>>> p1 = geo.point(0)
>>> p2 = geo.point(1)
>>> edg = geo.findEdge(p1, p2)  # you can also look for edge groups
<hou.Edge #0 - 1 of geometry in /obj/geo1/box1 read-only>

>>> edg.edgeId()
'p0-1'
>>> edg.length()
1.0

There are a few more edge methods:
Edge [www.sidefx.com]

There is only one intristisic that relates to edges; which contains the edge groups .

An example of how to get the edge count in vex:
string edg_grp[] = detailintrinsic(0, "edgegroups");
printf("%s \n", edg_grp); // {group1, group2}

for(string grp : edg_grp)
{
    int n = nedgesgroup(0, grp);
    printf("%s: %i  \n", grp, n);
    // group1: 12 - the first group contains all cube edges 
    // group2: 4 -  the second only the bottom
}

Create a new edge group in vex:
// int  setedgegroup(int geohandle, string name, int pt0, int pt1, int value)
setedgegroup(0, "new_edg_grp", 0, 1, 1);

Find the new edge group in python:
>>> grp = geo.findEdgeGroup("new_edg_grp")
>>> len(grp.edges())
1

Hi

The idea was to get the geometry element counts in Python, not do edge operations. I've done before calculations in VEX and then fed to a Python SOP, but this Python is not to go on a SOP or HDA based but a script.

The example at a bottom is useful to account for edges meeting at a point not to count the edges on a geo.

Cheers
Edited by probiner - Oct. 6, 2022 10:02:13
User Avatar
Member
339 posts
Joined: June 2013
Online
Andr
probiner
With points, prims and vertices I honestly didn't also also find a straight answer in Python. Doing len(geo.points())is quite wasteful given that pointsneeds to build an object for each point, and I just want to know how many there are. That said I was able to circumvent this by using the detail intrinsics, geometry.intrinsicValue("pointcount")but alas, there is no "edgecount"

Is there maybe some procedure that is escaping me or is it RFE time?

Thanks
prb


Since version 19.5.331, we have new methods to know the number of elements in a group:
EdgeGroup.edgeCount(), PointGroup.pointCount(), PrimGroup.primCount(), and VertexGroup.vertexCount()

Devs were super fast to implement these methods after I submitted the RFE (I had your very same concerns about performance of using len(geo.points()) )
I guess they could be as much fast if you RFE for the more general methods.
That method is exactly the one I use in VEX in SOPs, I create a group beforehand and then nedgesgroup(). Unfortunately that requires to create the group beforehand.

Therefore I went ahead and filed the RFE for "edgecount" detailintrinsic.

Thanks
Edited by probiner - Oct. 6, 2022 10:02:57
User Avatar
Member
4516 posts
Joined: Feb. 2012
Offline
probiner
With points, prims and vertices I honestly didn't also also find a straight answer in Python. Doing len(geo.points())is quite wasteful given that pointsneeds to build an object for each point, and I just want to know how many there are.
prb

Andr
Since version 19.5.331, we have new methods to know the number of elements in a group:
EdgeGroup.edgeCount(), PointGroup.pointCount(), PrimGroup.primCount(), and VertexGroup.vertexCount()

Devs were super fast to implement these methods after I submitted the RFE (I had your very same concerns about performance of using len(geo.points()) )
I guess they could be as much fast if you RFE for the more general methods.

I submitted it over 7 years ago. Feel free to revive my RFE: #26541 The current ticket is closed.

If I had to do this in Python, I would use this Python function:
https://www.sidefx.com/docs/houdini/hom/hou/hscriptExpression.html [www.sidefx.com]

Because it's still a limitation in Python HOM that needs to be addressed.

Getting the edge count will be tricky. Your best bet is probably to use VEX for this. I would just use neighbours or half edges and sum the edge count.

Point Wrangle:

int edgecount = 0;
int pts [ ] = neighbours ( 0, @ptnum );
foreach ( int pt; pts )
    if ( @ptnum < pt )
        edgecount += 1;
        
i@edgecount = edgecount;

Then Attribute Promote. For 4M polygons, it takes 0.5s to cook.
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]

youtube.com/@pragmaticvfx | patreon.com/animatrix | animatrix2k7.gumroad.com
User Avatar
Member
339 posts
Joined: June 2013
Online
animatrix_
If I had to do this in Python, I would use this Python function:
https://www.sidefx.com/docs/houdini/hom/hou/hscriptExpression.html [www.sidefx.com]

Because it's still a limitation in Python HOM that needs to be addressed.
I assume you're mentioning this for getting the other counts and not edgecount? Because there's no nedges() (equivalent to npoints()). For those the geometry.intrinsicValue("pointcount")and alike are quite instantaneous.

animatrix_
Getting the edge count will be tricky. Your best bet is probably to use VEX for this. I would just use neighbours or half edges and sum the edge count.

Point Wrangle:

int edgecount = 0;
int pts [ ] = neighbours ( 0, @ptnum );
foreach ( int pt; pts )
    if ( @ptnum < pt )
        edgecount += 1;
        
i@edgecount = edgecount;

Then Attribute Promote. For 4M polygons, it takes 0.5s to cook.

Yes, this works better than what I've done before; adding all edges to an edge group and then using nedgesgroup() (since it doesn't support adhoc). For some reason the Create Group set to all edges is quite slow.
Thank you for this VEX method, although like I said, for this one I was looking for something without SOP/VEX dependencies, it would be just a script.

I've filed the "edgecount" intrinsic already and I guess I'll add the nedges() for VEX and Hscript to request.

Cheers
Edited by probiner - Oct. 6, 2022 10:51:01
User Avatar
Member
4516 posts
Joined: Feb. 2012
Offline
probiner
animatrix_
If I had to do this in Python, I would use this Python function:
https://www.sidefx.com/docs/houdini/hom/hou/hscriptExpression.html [www.sidefx.com]

Because it's still a limitation in Python HOM that needs to be addressed.
I assume you're mentioning this for getting the other counts and not edgecount? Because there's no nedges() (equivalent to npoints()). For those the geometry.intrinsicValue("pointcount")and alike are quite instantaneous.

Oh yes because that was what I filed an RFE for over 7 years ago. But I agree edge count would also be immensely useful.
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]

youtube.com/@pragmaticvfx | patreon.com/animatrix | animatrix2k7.gumroad.com
User Avatar
Member
339 posts
Joined: June 2013
Online
animatrix_
probiner
animatrix_
If I had to do this in Python, I would use this Python function:
https://www.sidefx.com/docs/houdini/hom/hou/hscriptExpression.html [www.sidefx.com]

Because it's still a limitation in Python HOM that needs to be addressed.
I assume you're mentioning this for getting the other counts and not edgecount? Because there's no nedges() (equivalent to npoints()). For those the geometry.intrinsicValue("pointcount")and alike are quite instantaneous.

Oh yes because that was what I filed an RFE for over 7 years ago. But I agree edge count would also be immensely useful.

Right, I've added those nedges() functions to the request.

Cheers
Edited by probiner - Oct. 6, 2022 12:11:10
User Avatar
Member
4516 posts
Joined: Feb. 2012
Offline
probiner
animatrix_
probiner
animatrix_
If I had to do this in Python, I would use this Python function:
https://www.sidefx.com/docs/houdini/hom/hou/hscriptExpression.html [www.sidefx.com]

Because it's still a limitation in Python HOM that needs to be addressed.
I assume you're mentioning this for getting the other counts and not edgecount? Because there's no nedges() (equivalent to npoints()). For those the geometry.intrinsicValue("pointcount")and alike are quite instantaneous.

Oh yes because that was what I filed an RFE for over 7 years ago. But I agree edge count would also be immensely useful.

Right, I've added those nedges() functions to the request.

Cheers

I don't know how SESI will implement this but AFAIK this info is not readily available anywhere in Houdini since edges are second class citizens, even MMB info tooltip doesn't show them. So I wouldn't expect them in intrinsics or another place. I also couldn't find them in the HDK, only the new edge count for edge groups.
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]

youtube.com/@pragmaticvfx | patreon.com/animatrix | animatrix2k7.gumroad.com
User Avatar
Member
122 posts
Joined: June 2019
Offline
I guess it is like that because there is no edges actually in geo. So you still need to count them manually.
Also currently it's not that difficult to create your own geometry functions based on verbs and graph invokation.

Here's the example of such function based on animatrix approach (I think it's the fastest one).

The function in the session module and can be used in any script on geometry.

Attachments:
py_nedges.hiplc (96.0 KB)

User Avatar
Member
339 posts
Joined: June 2013
Online
elovikov
Also currently it's not that difficult to create your own geometry functions based on verbs and graph invokation.

Here's the example of such function based on animatrix approach (I think it's the fastest one).

The function in the session module and can be used in any script on geometry.

Thanks for the demo! May not be difficult but it's not quite clear for my yet

I've checked the docs [www.sidefx.com] and there's no mention, for example, of being able to set one's own verbs or set them in custom SOP HDAs. Is it possible? Also from testing not all sops have verbs, "polypath" and "convertline" didn't work for me. "'NoneType' object has no attribute 'execute'". hou.sopNodeTypeCategory().nodeVerbs()will state the existing ones.


I checked your scene and the session module has a long binary string describing a houdini file or a single subnet network? I've only seen binary data like HDA section "Contents.gz" .binaryContents().
How did you generate the binary string? This is what I tried with a subnet with animatrix setup inside:

subnet = hou.node('/obj/geo1/subnet1')
path = hou.text.expandString("$HOME/subnet")
subnet.parent().saveItemsToFile([subnet], path)
f = open(path, 'rb')
f.read()
but what comes out of f.read() is invalid in load(). I looked into .geometry().data() but that's binary data of the geometry not a graph.

If there's any documentation I should check to be able to replicate what you've did for other things?
Thanks
Edited by probiner - Oct. 7, 2022 00:52:40
User Avatar
Member
122 posts
Joined: June 2019
Offline
Currently verbs (as python sop verbs) are available only for certain atomic nodes. There is no obvious way to "verbify" hdas.
Basically sop compilation is the way of creating custom verbs.

Sorry, I've deleted the part where I created this string. I just put it back in the example so it's a bit more clear. Just look at the attached hip.

I'm only using one verb: Invoke Graph https://www.sidefx.com/docs/houdini/nodes/sop/invokegraph.html [www.sidefx.com]
It's a tool that can invoke a graph stored in geometry. Basically you can create any sop graph (even procedurally so it's also a metaprogramming feature which is really cool) and invoke it on any other geometry.

Unfortunately creating such graphs is rather cumbersome. Currently, if you want to dump any subnetwork to geometry you use Attribute From Parameters SOP which isn't very intuitive suggested by its name.
I've also mentioned how to do it in detail here: https://www.sidefx.com/forum/topic/84322/#post-364485 [www.sidefx.com]

Attachments:
py_nedges.hiplc (122.1 KB)

User Avatar
Member
900 posts
Joined: Feb. 2016
Offline
animatrix_
probiner
With points, prims and vertices I honestly didn't also also find a straight answer in Python. Doing len(geo.points())is quite wasteful given that pointsneeds to build an object for each point, and I just want to know how many there are.
prb

Andr
Since version 19.5.331, we have new methods to know the number of elements in a group:
EdgeGroup.edgeCount(), PointGroup.pointCount(), PrimGroup.primCount(), and VertexGroup.vertexCount()

Devs were super fast to implement these methods after I submitted the RFE (I had your very same concerns about performance of using len(geo.points()) )
I guess they could be as much fast if you RFE for the more general methods.

I submitted it over 7 years ago. Feel free to revive my RFE: #26541 The current ticket is closed.

If I had to do this in Python, I would use this Python function:
https://www.sidefx.com/docs/houdini/hom/hou/hscriptExpression.html [www.sidefx.com]

Because it's still a limitation in Python HOM that needs to be addressed.

Thanks for the RFE number, I will ask to add my name to it!

I agree it should be implemented in python, also because one issue with using hscript expression in the python script is that it's not dynamic.
So if you update the group in the python script, you must implement your own counter, because hscript expression would always return the element count of the (non-updated) input geometry.
User Avatar
Member
339 posts
Joined: June 2013
Online
elovikov
Currently verbs (as python sop verbs) are available only for certain atomic nodes. There is no obvious way to "verbify" hdas.
Basically sop compilation is the way of creating custom verbs.

Sorry, I've deleted the part where I created this string. I just put it back in the example so it's a bit more clear. Just look at the attached hip.

I'm only using one verb: Invoke Graph https://www.sidefx.com/docs/houdini/nodes/sop/invokegraph.html [www.sidefx.com]
It's a tool that can invoke a graph stored in geometry. Basically you can create any sop graph (even procedurally so it's also a metaprogramming feature which is really cool) and invoke it on any other geometry.

Unfortunately creating such graphs is rather cumbersome. Currently, if you want to dump any subnetwork to geometry you use Attribute From Parameters SOP which isn't very intuitive suggested by its name.
I've also mentioned how to do it in detail here: https://www.sidefx.com/forum/topic/84322/#post-364485 [www.sidefx.com]

Thank you very much, Igor, that made it quite understandable. This should be an example file under both Invoke Graph and Attribute from Parameters help pages

I got a bit thrown off for a moment there with the Python3 function __annotations__in the definition, eheh.

I've added a speed comparison with globEdges(), and added extra demo methods to source the geo graph, since it wasn't clear to me a method to get the string from data(); printing it Houdini's terminal adds linebreaks and hou.ui.copyTextToClipboard(text) didn't work for me.

Really appreciate the the extra clarification!! It's niche but can be VERY useful.

Edited by probiner - Oct. 7, 2022 19:15:55

Attachments:
PRB_py_nedges.hip (291.4 KB)

User Avatar
Member
339 posts
Joined: June 2013
Online
Since this got me looking into the Invoke Compile Graph SOP, I tried its first method in the menu "Invoke Compile Block", while Attributes from Parameters SOP method was set to "Points From Compiled Block", but this was without success. I renamed the input like one would for an Invoke Compile Block SOP, as the image shows. The Attribute from Parameters SOP seems to generate the points without issue but nothing comes out of Invoke Graph.

Regardless of Invoke Graph method, just like usual Compiled Blocks there shouldn't be any non-compliable SOPs in the graph. So no Python SOP itself.


Cheers
Edited by probiner - Oct. 8, 2022 06:58:39

Attachments:
PRB_InvokeGraph_Compiled.hip (266.3 KB)

User Avatar
Member
900 posts
Joined: Feb. 2016
Offline
probiner
With points, prims and vertices I honestly didn't also also find a straight answer in Python. Doing len(geo.points())is quite wasteful given that pointsneeds to build an object for each point, and I just want to know how many there are. That said I was able to circumvent this by using the detail intrinsics, geometry.intrinsicValue("pointcount")but alas, there is no "edgecount"
len(geo.iterPoints()) is much faster.

I've always assumed iterPoints() was an iterator and so you couldn't ask for its len(). It's actually a generator.
User Avatar
Member
339 posts
Joined: June 2013
Online
Andr
probiner
With points, prims and vertices I honestly didn't also also find a straight answer in Python. Doing len(geo.points())is quite wasteful given that pointsneeds to build an object for each point, and I just want to know how many there are. That said I was able to circumvent this by using the detail intrinsics, geometry.intrinsicValue("pointcount")but alas, there is no "edgecount"
len(geo.iterPoints()) is much faster.

I've always assumed iterPoints() was an iterator and so you couldn't ask for its len(). It's actually a generator.

Thanks for the follow up.
Unfortunately doesn't exist for vertices and edges.

Cheers
Edited by probiner - Oct. 17, 2022 14:12:58
  • Quick Links