Jump to content

Help with a cmiVFX tutorial - Houdini XML Based Procedural Cities


moth0027

Recommended Posts

Hello ODFORCE community!

I've started one of the cmiVFX tutorials and I've run into an error I can't figure out! I should mention that I am fairly new to Python scripting which is why I wanted to try out this amazing looking tutorial.

Essentially the tutorial is guiding you through the process of taking XML map data and creating a cityscape. Using Python, coordinates are extracted from the XML file to create the map and then variables such as 'highway' and 'building' are extracted to be used to customise how the data is translated into geometry.

Everything worked fine until I had to create a local variable to group all the roads together to apply a polywire to them without effecting the other geometry (buildings etc...).

The code I used to do this was:

if geo.findGlobalAttrib("varmap") is None:

geo.addAttrib(hou.attribType.Global,"varmap","")

followed by:

type_attrib = geo.addAttrib(hou.attribType.Prim,"Type",0)

map_attrib = type_attrib.name()+' -> ' +type_attrib.name().upper()

geo.setGlobalAttribValue("varmap",map_attrib)

The error I'm getting is this:

Error: Python error: Traceback (most recent call last):

File "<stdin>", line 155, in <module>

File "<stdin>", line 152, in createCity

File "<stdin>", line 63, in handleWays

File "/Library/Frameworks/Houdini.framework/Versions/12.1.33/Resources/houdini/python2.6libs/hou.py", line 16371, in setGlobalAttribValue

return_hou.Geometry_setGlobalAttribValue(*args)

OperationFailed: The attempted operation failed.

No attribute with this name, type, and size 1 exists

I originally thought I must have typed something wrong and searched for any mistakes. Eventually I decided the best thing to do was try comparing the completed project files that came with the tutorial however when I loaded the OTL and .hip file I had the same error.

I have no idea if the tutorial was created on an older version of Houdini. Is it possible that the code in the tutorial is out of date? If so how would I need to change it to make this work?

If anyone could shed some light on this it would be amazing!

Thank you all in advance,

Best,

Moth

post-8290-0-09635800-1354227008_thumb.pn

Link to comment
Share on other sites

Houdini 12 now longer allows you to set varmap attributes like you once could. SESI also made hou.Geometry.addAttrib properly create the local variable for an attribute, which is what this code that is erroring is attempting to do. Most likely you can now omit anything that has to do with creating/setting the varmap global attribute.

  • Like 1
Link to comment
Share on other sites

Thank you Graham for your really quick response!

Oh dear... that's good news... sort of. At least I haven't done anything wrong. I shall attempt to do what you recommend by omitting the creating and setting the global attribute 'varmap' and tell you how it goes.

Thanks again!

Link to comment
Share on other sites

Hello again Graham,

I just wanted to thank you again. I did what you recommended and it has worked. I didn't have to create the Global Variable - one was created for me allowing me to use it in the polywire node.

I shall post an image of the city tomorrow when I complete the tutorial.

Thanks again and all the best!

Link to comment
Share on other sites

  • 9 months later...

It works with the following code:



----------------------------------------------------------------------------------------------

# This code is called when instances of this SOP cook.
geo = hou.pwd().geometry()

# Add code to modify the contents of geo.

def createCity():
    import xml.dom.minidom

    sizeMultiplier = hou.pwd().parm('sizeMultiplier').evalAsFloat()
    MapFile = hou.pwd().parm('MapFile').evalAsString()
    if(MapFile==''):
        print('Please specify a file name')
        return
    if not(MapFile.endswith('.osm')) and not(MapFile.endswith('.xml')):
        print('Bad file type, please use only .osm or .xml data')
        return
    map = xml.dom.minidom.parse(MapFile)

    if(map.documentElement.tagName != "osm"):
        print ('Bad File Type')
        return
   
    pointsIDs = []
    points = []

    def handleNodes(xmlData):
        bounds = xmlData.getElementsByTagName("bounds")[0]
        minlat = float(bounds.getAttribute('minlat'))
        maxlat = float(bounds.getAttribute('maxlat'))
        minlon = float(bounds.getAttribute('minlon'))
        maxlon = float(bounds.getAttribute('maxlon'))

        normalizingFactor = sizeMultiplier / max((maxlon-minlon),(maxlat-minlat))

        nodes = xmlData.getElementsByTagName('node')
        for node in nodes:
            lat = float(node.getAttribute('lat'))
            lon = float(node.getAttribute('lon'))

            if lat<minlat or lat>maxlat or lon<minlon or lon>maxlon :
                continue

            normalizedLat = (lat-minlat) * normalizingFactor
            normalizedLon = (lon-minlon) * normalizingFactor

            centeredLat = normalizedLat - (maxlat-minlat)*normalizingFactor/2
            centeredLon = normalizedLon - (maxlon-minlon)*normalizingFactor/2

            point = geo.createPoint()
            point.setPosition((centeredLon,0,-centeredLat))

            pointsIDs.append(int(node.getAttribute('id')))
            points.append(point)

    def handleWays(xmlData):

#        if geo.findGlobalAttrib("varmap") is None:
#            geo.addAttrib(hou.attribType.Global,"varmap","")

        color_attrib = geo.addAttrib(hou.attribType.Prim,"Cd",(1.0,1.0,1.0))
        type_attrib = geo.addAttrib(hou.attribType.Prim,"Type",0)
        map_attrib = type_attrib.name()+' -> ' +type_attrib.name().upper()
#        geo.setGlobalAttribValue("varmap",map_attrib)

        width_attrib = geo.addAttrib(hou.attribType.Point,"width",0.02)
        map_attrib = width_attrib.name()+' -> ' +width_attrib.name().upper()
#        geo.setGlobalAttribValue("varmap",map_attrib)

        ways = xmlData.getElementsByTagName('way')
        for way in ways:
            wayPoints = []
            nodes = way.getElementsByTagName('nd')
            tags = way.getElementsByTagName('tag')

            isACarRoad = 0
            isABuilding = 0
            isAPark = 0
            isACoastline = 0
            width = 0.02
            layer = 0

            for tag in tags:
                tagType = str(tag.getAttribute('k'))
                if tagType == 'highway':
                    subType = str(tag.getAttribute('v'))
                    if not(subType =='pedestrian') and not(subType =='steps') and not(subType =='footway') and not(subType =='cycleway'):
                        isACarRoad = 1
                elif tagType == 'building':
                    temp = str(tag.getAttribute('v'))
                    if temp=='yes':
                        isABuilding = 1
                elif tagType == 'leisure':
                    temp = str(tag.getAttribute('v'))
                    if temp == 'park':
                        isAPark = 1
                elif tagType == 'natural':
                    temp = str(tag.getAttribute('v'))
                    if temp == 'coastline':
                        isACoastline = 1
                elif tagType == 'layer':
                    layer = int(tag.getAttribute('v'))

            for node in nodes:
                ref = int(node.getAttribute('ref'))
                try:
                    index = pointsIDs.index(ref)
                except ValueError:
                    index = -1

                if (index != -1):
                    wayPoints.append(points[index])
            if (isACarRoad == 1 or isABuilding ==1 or isAPark ==1 or isACoastline ==1):
                poly = geo.createPolygon()
   
                if(isABuilding == 1):
                    poly.setIsClosed(1)
                    poly.setAttribValue(color_attrib,(0.9,0.9,0.9))
                    poly.setAttribValue(type_attrib,1)
                elif(isAPark ==1):
                    poly.setIsClosed(1)
                    poly.setAttribValue(color_attrib,(0.3,1.0,0.3))
                    poly.setAttribValue(type_attrib,2)
                elif(isACoastline ==1):
                    poly.setIsClosed(1)
                    poly.setAttribValue(color_attrib,(0.6,0.6,0.6))
                    poly.setAttribValue(type_attrib,3)
                elif(isACarRoad ==1):
                    poly.setIsClosed(0)
                    poly.setAttribValue(type_attrib,4)
                    if(subType=='motorway' or subType =='motorway_link'):
                        poly.setAttribValue(color_attrib,(0.5,0.75,0.85))
                        width = 0.035
                    elif(subType=='primary' or subType =='primary_link'):
                        poly.setAttribValue(color_attrib,(1.0,0.5,0.5))
                        width = 0.035
                    elif(subType=='secondary' or subType =='secondary_link'):
                        poly.setAttribValue(color_attrib,(1.0,0.8,0.65))
                        width = 0.025
                    elif(subType=='trunk' or subType =='trunk_link'):
                        poly.setAttribValue(color_attrib,(0.7,0.85,0.7))
                        width = 0.025
                    else:
                        width = 0.03
       
                for point in wayPoints:
                    poly.addVertex(point)
                    point.setAttribValue(width_attrib,width)
#                    pointPos = point.position()
#                    point.setPosition((pointPos[0],layer,pointPos[2]))

    handleNodes(map)
    handleWays(map)
    map.unlink()

createCity()

Edited by lubitel
Link to comment
Share on other sites

  • 1 year later...


Posting in Code Block for Easier Reading


# This code is called when instances of this SOP cook.

geo = hou.pwd().geometry()

# Add code to modify the contents of geo.

def createCity():

    import xml.dom.minidom

    sizeMultiplier = hou.pwd().parm('sizeMultiplier').evalAsFloat()

    MapFile = hou.pwd().parm('MapFile').evalAsString()

    if(MapFile==''):

        print('Please specify a file name')

        return

    if not(MapFile.endswith('.osm')) and not(MapFile.endswith('.xml')):

        print('Bad file type, please use only .osm or .xml data')

        return

    map = xml.dom.minidom.parse(MapFile)

    if(map.documentElement.tagName != "osm"):

        print ('Bad File Type')

        return

   

    pointsIDs = []

    points = []

    def handleNodes(xmlData):

        bounds = xmlData.getElementsByTagName("bounds")[0]

        minlat = float(bounds.getAttribute('minlat'))

        maxlat = float(bounds.getAttribute('maxlat'))

        minlon = float(bounds.getAttribute('minlon'))

        maxlon = float(bounds.getAttribute('maxlon'))

        normalizingFactor = sizeMultiplier / max((maxlon-minlon),(maxlat-minlat))

        nodes = xmlData.getElementsByTagName('node')

        for node in nodes:

            lat = float(node.getAttribute('lat'))

            lon = float(node.getAttribute('lon'))

            if lat<minlat or lat>maxlat or lon<minlon or lon>maxlon :

                continue

            normalizedLat = (lat-minlat) * normalizingFactor

            normalizedLon = (lon-minlon) * normalizingFactor

            centeredLat = normalizedLat - (maxlat-minlat)*normalizingFactor/2

            centeredLon = normalizedLon - (maxlon-minlon)*normalizingFactor/2

            point = geo.createPoint()

            point.setPosition((centeredLon,0,-centeredLat))

            pointsIDs.append(int(node.getAttribute('id')))

            points.append(point)

    def handleWays(xmlData):

#        if geo.findGlobalAttrib("varmap") is None:

#            geo.addAttrib(hou.attribType.Global,"varmap","")

        color_attrib = geo.addAttrib(hou.attribType.Prim,"Cd",(1.0,1.0,1.0))

        type_attrib = geo.addAttrib(hou.attribType.Prim,"Type",0)

        map_attrib = type_attrib.name()+' -> ' +type_attrib.name().upper()

#        geo.setGlobalAttribValue("varmap",map_attrib)

        width_attrib = geo.addAttrib(hou.attribType.Point,"width",0.02)

        map_attrib = width_attrib.name()+' -> ' +width_attrib.name().upper()

#        geo.setGlobalAttribValue("varmap",map_attrib)

        ways = xmlData.getElementsByTagName('way')

        for way in ways:

            wayPoints = []

            nodes = way.getElementsByTagName('nd')

            tags = way.getElementsByTagName('tag')

            isACarRoad = 0

            isABuilding = 0

            isAPark = 0

            isACoastline = 0

            width = 0.02

            layer = 0

            for tag in tags:

                tagType = str(tag.getAttribute('k'))

                if tagType == 'highway':

                    subType = str(tag.getAttribute('v'))

                    if not(subType =='pedestrian') and not(subType =='steps') and not(subType =='footway') and not(subType =='cycleway'):

                        isACarRoad = 1

                elif tagType == 'building':

                    temp = str(tag.getAttribute('v'))

                    if temp=='yes':

                        isABuilding = 1

                elif tagType == 'leisure':

                    temp = str(tag.getAttribute('v'))

                    if temp == 'park':

                        isAPark = 1

                elif tagType == 'natural':

                    temp = str(tag.getAttribute('v'))

                    if temp == 'coastline':

                        isACoastline = 1

                elif tagType == 'layer':

                    layer = int(tag.getAttribute('v'))

            for node in nodes:

                ref = int(node.getAttribute('ref'))

                try:

                    index = pointsIDs.index(ref)

                except ValueError:

                    index = -1

                if (index != -1):

                    wayPoints.append(points[index])

            if (isACarRoad == 1 or isABuilding ==1 or isAPark ==1 or isACoastline ==1):

                poly = geo.createPolygon()

   

                if(isABuilding == 1):

                    poly.setIsClosed(1)

                    poly.setAttribValue(color_attrib,(0.9,0.9,0.9))

                    poly.setAttribValue(type_attrib,1)

                elif(isAPark ==1):

                    poly.setIsClosed(1)

                    poly.setAttribValue(color_attrib,(0.3,1.0,0.3))

                    poly.setAttribValue(type_attrib,2)

                elif(isACoastline ==1):

                    poly.setIsClosed(1)

                    poly.setAttribValue(color_attrib,(0.6,0.6,0.6))

                    poly.setAttribValue(type_attrib,3)

                elif(isACarRoad ==1):

                    poly.setIsClosed(0)

                    poly.setAttribValue(type_attrib,4)

                    if(subType=='motorway' or subType =='motorway_link'):

                        poly.setAttribValue(color_attrib,(0.5,0.75,0.85))

                        width = 0.035

                    elif(subType=='primary' or subType =='primary_link'):

                        poly.setAttribValue(color_attrib,(1.0,0.5,0.5))

                        width = 0.035

                    elif(subType=='secondary' or subType =='secondary_link'):

                        poly.setAttribValue(color_attrib,(1.0,0.8,0.65))

                        width = 0.025

                    elif(subType=='trunk' or subType =='trunk_link'):

                        poly.setAttribValue(color_attrib,(0.7,0.85,0.7))

                        width = 0.025

                    else:

                        width = 0.03

       

                for point in wayPoints:

                    poly.addVertex(point)

                    point.setAttribValue(width_attrib,width)

#                    pointPos = point.position()

#                    point.setPosition((pointPos[0],layer,pointPos[2]))

    handleNodes(map)

    handleWays(map)

    map.unlink()

createCity()

Edited by paxsonsa
  • Like 1
Link to comment
Share on other sites

  • 10 months later...

Hey guys. I am trying to get this working in Houdini 15. I get a few errors after pasting this code above.

 

The node errors out and when I middle click to check info I get this.

 

 

Error: python error: Traceback ( most recent call last):

File "<stdin>", line 132 in <module>

File "<stdin>", line 6, in createCity

AttributeError: 'NoneType' object has no attribute 'EvalAsFloat'

 

anyone know whats going wrong?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...