INDX
INDEX_SECTION ¥LÔ>Ô Sop/primitivecentroid ¥ *3LÔ>Ô primitivecentroid PrimitiveCentroid 2oplib:/Sop/primitivecentroid?Sop/primitivecentroid MISC_python Sop LÔ>Ô INDX
DialogScript ™LÔ>Ô
PythonCook ™ LÔ>Ô TypePropertiesOptions ° ìLÔ>Ô Help œ SLÔ>Ô Tools.shelf ï LÔ={ CreateScript Œ .LÔ5¡ Version º LÔ3Þ PythonModule Á ÅLÔ>Ô ExtraFileOptions '† ÜLÔ>Ô Credits (b ±LÔ4Í# Dialog script for primitivecentroid automatically generated 11/05/10 10:28:52
{
name primitivecentroid
script primitivecentroid
label PrimitiveCentroid
help {
""
}
parm {
name "method"
label "Method"
type ordinal
default { "0" }
menu {
"bary" "Bary Center"
"bbox" "BoundingBox"
}
range { 0 1 }
export none
}
parm {
name "use_groups"
label "Process Groups"
type toggle
default { "0" }
range { 0 1 }
export none
}
parm {
name "group"
label "Primtive Groups"
type string
default { "" }
disablewhen "{ use_groups == 0 }"
menutoggle {
[ "sopnode = hou.pwd()" ]
[ "if len(sopnode.inputs()) > 0:" ]
[ " input_geo = sopnode.inputs()[0].geometry()" ]
[ "" ]
[ " menu_list = []" ]
[ " for group in input_geo.primGroups():" ]
[ " menu_list.append(group.name())" ]
[ " menu_list.append(group.name())" ]
[ " return menu_list" ]
[ "else:" ]
[ " return []" ]
language python
}
range { 0 1 }
export none
}
parm {
name "keep"
label "Keep Geometry"
type toggle
default { "off" }
range { 0 1 }
export none
}
}
#
# Produced by:
# Graham Thompson
# captainhammy@gmail.com
# www.captainhammy.com
#
# Description:
# PythonCook section for PrimitiveCentroid SOP.
#
sopnode = hou.pwd()
geo = sopnode.geometry()
# Get the frozen geometry since we are going to be doing a lot of iteration
# and this can help increase speed.
frozen_geo = geo.freeze()
# If we aren't going to keep the geometry then create a list of points to destroy.
if not sopnode.evalParm("keep"):
points_to_destroy = geo.points()
# Get the centroid calculation method.
method = sopnode.parm("method").evalAsString()
# See if we are using groups.
use_groups = sopnode.evalParm("use_groups")
# Try and grab the Normal point attribute.
normal_attr = geo.findPointAttrib("N")
# If the Normal attribute doesn't exist, create it.
if normal_attr is None:
normal_attr = geo.addAttrib(hou.attribType.Point, "N", (0.0, 0.0, 0.0), True)
# We are using groups.
if use_groups:
# Get the group pattern.
group_pattern = sopnode.parm("group").evalAsString()
# Filter the list of primitive groups with our pattern using the custom function
# in the PythonModule.
groups = [group for group in frozen_geo.primGroups()
if sopnode.hm().matchesPattern(group.name(), group_pattern)]
if method == "bbox":
for group in groups:
# Get the primitives in this group.
prim_list = group.prims()
# Build a bounding box from these primitives.
bbox = sopnode.hm().buildBBoxFromPrims(prim_list)
# Get the sum of the normal vectors for each primitive.
normal= sum([prim.normal() for prim in prim_list], hou.Vector3())
# Create a new point.
point = geo.createPoint()
# Position it in the center of the bounding box.
point.setPosition(bbox.center())
# Set the normal value to be the normalized sum of the normals.
point.setAttribValue(normal_attr, normal.normalized())
else:
# Create a point for each primitive group.
for group in groups:
group_prims = group.prims()
# The new normal vector.
normal = hou.Vector3()
# Point numbers we will need to glob for.
point_nums = []
for prim in group_prims:
# Get all the points from the primitives vertices as strings.
point_nums += [str(vert.point().number()) for vert in prim.vertices()]
# Sum up the primitives normal value.
normal += prim.normal()
# Get the actual hou.Point objects. Luckily globPoints doesn't care
# about duplicates.
points = frozen_geo.globPoints(" ".join(point_nums))
# Calculate the sum of all the point positions.
center = sum(map(hou.Point.position, points), hou.Vector3())
# Create the new points.
point = geo.createPoint()
# Position the point at the center of the group of primitives. We do this
# by diving the sum of positions by the number of prims.
point.setPosition(center * (1.0 / len(points)))
# Set the normal vector to be the normalized sum of the individual primitive
# normals.
point.setAttribValue(normal_attr, normal.normalized())
else:
if method == "bbox":
for prim in frozen_geo.prims():
# Create a bounding box for this primitive.
bbox = sopnode.hm().buildBBoxFromPrims([prim])
# Create a new point.
point = geo.createPoint()
# Position it in the center of the bounding box.
point.setPosition(bbox.center())
# Set the normal value to the normal value of this primitive.
point.setAttribValue(normal_attr, prim.normal())
else:
# Create a point for each primitive in the geometry.
for prim in frozen_geo.prims():
# Get the center of the primtive.
center = sum((vert.point().position() for vert in prim.vertices()),
hou.Vector3()) * (1.0 / prim.numVertices())
# Create a new point.
point = geo.createPoint()
# Position it in the center of the bounding box.
point.setPosition(center)
# Set the normal value to the normal value of this primitive.
point.setAttribValue(normal_attr, prim.normal())
# Delete the prims.
if not sopnode.evalParm("keep"):
geo.deletePoints(points_to_destroy)
ParmsFromVfl := 0;
PrefixDroppedParmName := 1;
UseDSParms := 1;
ForbidOutsideParms := 1;
LockContents := 1;
SaveSpareParms := 0;
CheckExternal := 1;
GzipContents := 1;
MakeDefault := 0;
PrefixDroppedParmLabel := 1;
UnlockOnCreate := 0;
#type: node
#context: sop
#internal: primitivecentroid
#icon: MISC/python
= PrimitiveCentroid =
"""Create points at the centers of primitives or primitive groups."""
This node creates points at the centers of primitives or groups of primitives.
These points have their normal value set to the normal of the primitive they are
at the center of. In the case of groups, the normal is the average normal value.
@parameters
Method:
The type of calculation to use when computing the centroid.
Bary Center:
Use the average point position of each point in the primitive or group of
primitives to find the center.
Bounding Box:
Use the bouding box of the primitive or group of primitives to find the center.
Process Groups:
Create points at the center of the specified primitive groups.
Primitive Groups:
The primitive groups to create centroid points for.
Keep Geometry:
Keep the original geometry. If this is disabled, all points and primitives that existed
before will be destroyed.
operator:Sop/primitivecentroid
SOP
SOP
$HDA_TABLE/$HDA_NAME
Utility
# Automatically generated script: Friday November 05, 09:49 2010
\set noalias = 1
#
# Creation script for primitivecentroid operator
#
if ( "$arg1" == "" ) then
echo This script is intended as a creation script
exit
endif
# Node $arg1 (Sop/primitivecentroid)
opexprlanguage -s hscript $arg1
1.0#
# Produced by:
# Graham Thompson
# captainhammy@gmail.com
# www.captainhammy.com
#
# Description:
# PythonModule section for PrimitiveCentroid SOP.
#
import inlinecpp
# Given a list of hou.Prim objects we can construct a hou.BoundingBox object
# by finding all the points for each primitive and then by enlarging the box
# so that it contains all the points corresponding to the primitives.
# To create a bounding box for a list of points we need to create a new
# hou.BoundingBox object centered around the first point in the list. We do
# this because since we are enlarging, the default center, (0,0,0) might not
# be in the bounds of those points. We then enlarge the box so that it contains
# the positions of the remaining points.
def buildBBoxFromPrims(prims):
""" Get a hou.BoundingBox object that encompasses a list of primitivevs. """
# Get all points attached to the primitives.
points = [vert.point() for prim in prims
for vert in prim.vertices()]
# Get the initial position.
init_pos = points[0].position()
# Construct a bbox around that position.
bbox = hou.BoundingBox(init_pos[0], init_pos[1], init_pos[2], init_pos[0], init_pos[1], init_pos[2])
# For the remaining points, enlarge the box to contain that position.
for point in points[1:]:
bbox.enlargeToContain(point.position())
return bbox
op_utils = inlinecpp.createLibrary(
name="%s_utils" % kwargs["type"].name(),
includes="""
#include
""",
function_sources=[
"""bool matchesPattern(const char *str, const char *pattern)
{
return UT_String(str).multiMatch(pattern);
}
""",
])
matchesPattern = op_utils.matchesPattern Credits/IsExpr Credits/IsPython Credits/IsScript Credits/Source PythonModule/IsExpr PythonModule/IsPython PythonModule/IsScript PythonModule/Source Produced by:
Graham Thompson
captainhammy@gmail.com
www.captainhammy.com
Name: sop_primitivecentroid.otl
Version: 1.0
Compatibility: Houdini 11.0