Jump to content


Is there a way to get primitives using a point?


  • Please log in to reply
27 replies to this topic

#1 magneto

magneto

    Grand Master

  • Members
  • PipPipPipPipPip
  • 2,021 posts
  • Joined: 04-October 11
  • Location:Canada
  • Name:Ryan K

Posted 23 June 2012 - 08:32 PM

I am wondering if this is possible to do in a python SOP? Basically something that would return the primitives that uses a particular point.

I looked at the help and in the forums but couldn't find anything.

If there is an hscript expression that would work too.

Thanks :)

#2 rdg

rdg

    Houdini Master

  • Members
  • PipPipPipPip
  • 731 posts
  • Joined: 21-August 05
  • Location:weta
  • Name:Georg Duemlein

Posted 23 June 2012 - 11:34 PM

Basically something that would return the primitives that uses a particular point.



You could build a tree for the bounding boxes of the primitives and find the prims that intersect the location of the point.
Might be faster than iterating over all primitives to see if they use a point.

Or use hou.Geometry.nearestPrim if you only need one prim.
The Industrial Parametrization of the World
http://rdg.preset.de/

#3 magneto

magneto

    Grand Master

  • Members
  • PipPipPipPipPip
  • 2,021 posts
  • Joined: 04-October 11
  • Location:Canada
  • Name:Ryan K

Posted 23 June 2012 - 11:38 PM

Thanks rdg. How do you build a tree for the bounding boxes of primitives? Actually I also don't know how to get the bounding box of a primitive :)

Is there an expression for that? My geometry is a single connected polygon mesh, not sure if that matters.

#4 rdg

rdg

    Houdini Master

  • Members
  • PipPipPipPip
  • 731 posts
  • Joined: 21-August 05
  • Location:weta
  • Name:Georg Duemlein

Posted 23 June 2012 - 11:55 PM

Thanks rdg. How do you build a tree for the bounding boxes of primitives? Actually I also don't know how to get the bounding box of a primitive :)

Is there an expression for that? My geometry is a single connected polygon mesh, not sure if that matters.


Good question, don't know. Probably would end up using hou.Geometry.nearestPrim, if I had to use python.
Or put the point into a group. Put $PR onto all prims, convert the point group into a prim group and look at the stored attribute?
That sounds pretty Houdini.
The Industrial Parametrization of the World
http://rdg.preset.de/

#5 magneto

magneto

    Grand Master

  • Members
  • PipPipPipPipPip
  • 2,021 posts
  • Joined: 04-October 11
  • Location:Canada
  • Name:Ryan K

Posted 24 June 2012 - 12:00 AM

Thanks, that's a cool trick. I guess I could use a Group SOP to convert each point to prims and then read the group contents in python. I was trying to keep everything in python.

Interestingly there is a way to get the points of a primitive in python, but not the other way around :)

#6 mantragora

mantragora

    Houdini Master

  • Members
  • PipPipPipPip
  • 636 posts
  • Joined: 08-December 11
  • Location:here
  • Name:Real Time

Posted 24 June 2012 - 12:35 AM

Sorry. My CTRL+C/CTRL+V wasn't working as it should.

Interestingly there is a way to get the points of a primitive in python, but not the other way around :)


Yes, there is:
# This code is called when instances of this SOP cook.
node = hou.pwd()
geo = node.geometry()

# Add code to modify the contents of geo.
pointnumber = node.evalParm('val')

def GetAllPoints():
    """ use it to get points of each primitive """
    dict = {}
    for prim in geo.prims():
        points = []
        for verticle in prim.vertices():
            points.append(verticle.point().number())
        dict[prim.number()] = points
    return dict
    

def GetPointPrimitives(dict, pointnumber):
    """ use it to get primitives that uses this point """
    prims = []
    for k, v in dict.items():
        if pointnumber in v:
            prims.append(k)
    return prims

# MAIN()        
print(GetPointPrimitives(GetAllPoints(), pointnumber))

Edited by mantragora, 24 June 2012 - 04:06 AM.

magic happens here... sometimes

Vimeo
Twitter
 
 
 "If it's not real-time, it's a piece of shit not a state of the art technology" - me


#7 magneto

magneto

    Grand Master

  • Members
  • PipPipPipPipPip
  • 2,021 posts
  • Joined: 04-October 11
  • Location:Canada
  • Name:Ryan K

Posted 24 June 2012 - 01:46 AM

Thanks mantragora, that's the method I was talking about. But looking up the prims from the points would be slow. You could make another dictionary from yours where point numbers would be the keys but that would be even slower to construct :)

These are the kinds of solutions I don't like implementing because they are not scalable. If I had 10 points in a mesh with 100 points, and it takes 1 ms for cooking my SOP, having the same 10 points in a mesh with 1 million points will be 10000 slower, which would be 10 seconds (just an example), but it shouldn't be. I shouldn't pay that price because I am not modifying the whole mesh.

Reminds me Edit Poly limitations in Max (not Editable Poly), where even setting the position of a vertex/point would be an epic undertaking :)

#8 mantragora

mantragora

    Houdini Master

  • Members
  • PipPipPipPip
  • 636 posts
  • Joined: 08-December 11
  • Location:here
  • Name:Real Time

Posted 24 June 2012 - 01:53 AM

Thanks mantragora, that's the method I was talking about. But looking up the prims from the points would be slow. You could make another dictionary from yours where point numbers would be the keys but that would be even slower to construct :)

These are the kinds of solutions I don't like implementing because they are not scalable. If I had 10 points in a mesh with 100 points, and it takes 1 ms for cooking my SOP, having the same 10 points in a mesh with 1 million points will be 10000 slower, which would be 10 seconds (just an example), but it shouldn't be. I shouldn't pay that price because I am not modifying the whole mesh.

Reminds me Edit Poly limitations in Max (not Editable Poly), where even setting the position of a vertex/point would be an epic undertaking :)



Use InlineCPP.

magic happens here... sometimes

Vimeo
Twitter
 
 
 "If it's not real-time, it's a piece of shit not a state of the art technology" - me


#9 magneto

magneto

    Grand Master

  • Members
  • PipPipPipPipPip
  • 2,021 posts
  • Joined: 04-October 11
  • Location:Canada
  • Name:Ryan K

Posted 24 June 2012 - 02:00 AM

Use InlineCPP.


I want to, but don't want to take a huge detour from the task at hand :)

Do you know which functions would be of interest for this? Although if I use the HDK, I would want to solve this using edges. Not sure if they exist there but this primitive thing I am trying is some sort of a dirty way for me to construct edge loops :D

#10 mantragora

mantragora

    Houdini Master

  • Members
  • PipPipPipPip
  • 636 posts
  • Joined: 08-December 11
  • Location:here
  • Name:Real Time

Posted 24 June 2012 - 02:47 AM

There is an old documentation example in inlineCpp section called "point_ref_utils" that looks like it may guide you a little:

The following example shows how to return an array of array of structures, where each structure contains two integers named prim_id and vertex_id. It creates a function that receives a hou.Geometry object and, for each point in it, returns the vertices (as primitive and vertex ids) that reference that point.


but it uses deprecated GB library so it doesn't work in H12. And it's not for edges. Just messing with vertex, point, primitive.

I haven't poked new GA stuff yet so can't help with it.

Edited by mantragora, 24 June 2012 - 04:59 AM.

magic happens here... sometimes

Vimeo
Twitter
 
 
 "If it's not real-time, it's a piece of shit not a state of the art technology" - me


#11 magneto

magneto

    Grand Master

  • Members
  • PipPipPipPipPip
  • 2,021 posts
  • Joined: 04-October 11
  • Location:Canada
  • Name:Ryan K

Posted 24 June 2012 - 02:48 AM

Thanks man, I will check it out :)

#12 graham

graham

    Houdini Master

  • Moderator
  • 782 posts
  • Joined: 13-September 06
  • Location:Santa Monica, CA
  • Name:Graham Thompson

Posted 24 June 2012 - 07:02 AM

Given the realities of production and available technology, quite often there is no way to go about things other than doing them the 'slow' way. In this case, doing what you want using inlinecpp is quite trivial, if you have access to it. However, if you can't use that then you are forced to go with a pure Python way which can indeed be slow for large meshes. Depending on the situation and how you need the information, the slow method might not be so bad. For example, to do this with just Python I'd use something like the following:

def buildPointPrimRefMap(geo):
    """ Build a dictionary whose keys are hou.Point objects and values
        are a list of hou.Primitive objects that reference the point.
    """
    point_map = {}

    for prim in geo.prims():
        for vert in prim.vertices():
            pt = vert.point()

            if not pt in point_map:
                point_map[pt] = []

            point_map[pt].append(prim)

    return point_map
This results in a dictionary where I can use a hou.Point to get any prims that reference it.

Now if the geometry has a huge number of points and/or primitives, it would definitely be slow to calculate. However, if I could create my system so that it only ever had to calculate once per use then perhaps it wouldn't be so bad. I could do this if I had a Python SOP that only needed to cook once in my session. If the node needed to be time dependent due to deforming but not changing topology then perhaps on its first cook it could stash the resulting structure into the cached user data and reuse it. If the topology was going to be constantly changing, or I needed this as a one off query then there's really not a lot you can actually do other than to suffer through the slowness of processing huge amounts of geometry data with Python.

Using inlinecpp:

cpp_geo_methods = inlinecpp.createLibrary("cpp_geo_methods",
includes="""#include <GU/GU_Detail.h>""",
structs=[("IntArray", "*i"),],
function_sources=[
"""
IntArray connectedPrims(const GU_Detail *gdp, int idx)
{
    std::vector<int>    ids;

    GA_Offset           ptOff, primOff;
    GA_OffsetArray      prims;

    GA_OffsetArray::const_iterator prims_it;

    ptOff = gdp->pointOffset(idx);

    gdp->getPrimitivesReferencingPoint(prims, ptOff);

    for (prims_it = prims.begin(); !prims_it.atEnd(); ++prims_it)
    {
        ids.push_back(gdp->primitiveIndex(*prims_it));
    }

    return ids;
}
""",])

def connectedPrims(point):
    """ Returns a tuple of primitives connected to the point. """
    geo = point.geometry()

    result = cpp_geo_methods.connectedPrims(geo, point.number())

    return geo.globPrims(' '.join([str(i) for i in result]))

Edited by graham, 24 June 2012 - 07:05 AM.

I write python and break things.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users