Hey Chris, I quickly (read - some things may not work!) refactored my old
.PLY importer for you. should work...

Just rename as .py and run in the script editor.

Like Alan suggested though, it's just point data so it just makes a
pointcloud.

Hope it helps.

DAN



On Mon, Jan 7, 2013 at 5:09 PM, Chris Marshall <[email protected]>wrote:

> Hi,
> Sorry for the slow reply on this. We have an xyz file, which is just a
> grid of points, like this:-
>
> -105.2500000000,39.7500000000,1757.129
> -105.2500000000,39.7499583333,1758.791
> -105.2500000000,39.7499166667,1760.882
> -105.2500000000,39.7498750000,1763.025
> -105.2500000000,39.7498333333,1765.183
> -105.2500000000,39.7497916667,1767.467
> -105.2500000000,39.7497500000,1768.741
> -105.2500000000,39.7497083333,1771.766
> -105.2500000000,39.7496666667,1773.832
> -105.2500000000,39.7496250000,1775.873
> -105.2500000000,39.7495833333,1777.84
> -105.2500000000,39.7495416667,1779.369
> -105.2500000000,39.7495000000,1781.255
> -105.2500000000,39.7494583333,1783.423
> -105.2500000000,39.7494166667,1785.815
> -105.2500000000,39.7493750000,1788.552
> -105.2500000000,39.7493333333,1791.749
> -105.2500000000,39.7492916667,1795.332
> -105.2500000000,39.7492500000,1800.269
> -105.2500000000,39.7492083333,1804.516
> -105.2500000000,39.7491666667,1808.3
>
> So it must be relatively easy to convert this into a grid? Anyone got any
> ideas or can supply a simple script we can modify that'll read this data
> and generate a new grid or adjust the height of an existing grid?
>
> Thanks
>
> Chris
>
>
>
>
> On 14 December 2012 19:12, Matt Lind <[email protected]> wrote:
>
>> If it’s ASCII, an importer can probably be written fairly easily.****
>>
>> ** **
>>
>> Do you have a sample file?****
>>
>> ** **
>>
>> ** **
>>
>> Matt****
>>
>> ** **
>>
>> ** **
>>
>> ** **
>>
>> *From:* [email protected] [mailto:
>> [email protected]] *On Behalf Of *Chris Marshall
>> *Sent:* Friday, December 14, 2012 5:19 AM
>> *To:* [email protected]
>> *Subject:* terrain ascii xyz import****
>>
>> ** **
>>
>> Hello,****
>>
>> Anyone know how to get these into soft?****
>>
>> ** **
>>
>> Cheers****
>>
>> ** **
>>
>> Chris****
>>
>> ** **
>>
>
>
>
> --
>
> Chris Marshall
> Mint Motion Limited
> 029 20 37 27 57
> 07730 533 115
> www.mintmotion.co.uk
>
>
import sys
import random
import gzip
import os
import re
from struct import pack
import win32com.client
from win32com.client import constants

## Globals
null = None
false = 0
true = 1
xsi = Application
pr = xsi.LogMessage

def main():
        # Browse for the .XYZ file
        xyzFilePath = GetXYZfilePath()
        if xyzFilePath:
                # Retreive the point data from the .XYZ file
                pointsList = GetPointsList(xyzFilePath)
                nbPoints = len(pointsList)
                if nbPoints > 0:
                        # Get user input
                        oPset = GetInputValues(nbPoints)
                        if oPset:
                                pointsPerc = oPset.pPointsPerc.value
                                
                                # Take the list of point data and rework it for 
softimage - Use user input to filter/modify the data.
                                pointDataList = ParsePoints(pointsList, 
pointsPerc)
                                nbPoints = len(pointDataList)
                                
                                # Write the icecache
                                cachePath = WriteIceCache(xyzFilePath, 
pointDataList, oPset.pPointSize.value)
                                
                                # Create an empty pointcloud under a model
                                cloudModel = 
xsi.ActiveSceneRoot.AddModel("",xyzfileName + "_model")
                                pointCloud = 
cloudModel.AddPrimitive("pointcloud", xyzfileName)
                                
                                # Load in out newly created icecache
                                xsi.AddFileCacheSource(pointCloud, cachePath)
                                
                                # Cleanup...
                                xsi.FreezeObj(pointCloud)
                                xsi.DeleteObj(cloudModel.Fullname + ".Mixer")
                                # I figure one more command isn't gonna hurt 
after the 3 above this... ;)
                                xsi.SetValue(pointCloud.Fullname + 
".particledisplay.displaytype", 1, "")
                        else:
                                pr("Aborting!!!")
                        xsi.DeleteObj(oPset)
                else:
                        pr("Error - no points found or not a valid XYZ file!!!")
        else:
                pr("Error - no XYZ file!!!")
        return

def GetInputValues(nbPoints):
        # Setup the Custom Pset and inspect Modally - Define the Pset as a 
global
        global oPset
        oPset = xsi.ActiveSceneRoot.AddCustomProperty("XYZ_ImportOptions")
        pImportPerc = oPset.AddParameter2("pPointsPerc", constants.siInt2, 100, 
0, 100, 0, 100) 

        pSpatialScale = oPset.AddParameter2("pSpatialScale", constants.siFloat, 
1, 0, 1000, 0, 1)
        pNullScale = oPset.AddParameter2("pPointSize", constants.siFloat, 0.1, 
0, 1000, 0, 1)

        pBoundsFilter = oPset.AddParameter2("pFilterByBounds", 
constants.siBool, 0, 0, 1, 0, 1)
        
        pBoundMinX = oPset.AddParameter2("pBoundMinX", constants.siFloat, 
-1000, -1000, 1000, -1000, 1000)
        pBoundMinY = oPset.AddParameter2("pBoundMinY", constants.siFloat, 
-1000, -1000, 1000, -1000, 1000)
        pBoundMinZ = oPset.AddParameter2("pBoundMinZ", constants.siFloat, 
-1000, -1000, 1000, -1000, 1000)
        
        pBoundMaxX = oPset.AddParameter2("pBoundMaxX", constants.siFloat, 1000, 
-1000, 1000, -1000, 1000)
        pBoundMaxY = oPset.AddParameter2("pBoundMaxY", constants.siFloat, 1000, 
-1000, 1000, -1000, 1000)
        pBoundMaxZ = oPset.AddParameter2("pBoundMaxZ", constants.siFloat, 1000, 
-1000, 1000, -1000, 1000)

        oLayout = oPset.PPGLayout
        oLayout.Clear()
        
        oLayout.AddGroup("Import Options")
        oLayout.AddStaticText( "\n" + str(nbPoints) + " Points were found in 
.XYZ file '" + xyzfileName + "'\n" )
        iImportPerc = oLayout.AddItem("pPointsPerc", "Approximate Percentage of 
Points to Import", constants.siControlNumber )
        iImportPerc.LabelMinPixels = 160
        oLayout.EndGroup()
        
        oLayout.AddGroup("Scaling Options")
        oLayout.AddItem("pSpatialScale", "Scale Dataset", 
constants.siControlNumber )
        oLayout.AddItem("pPointSize", "Size of Points", 
constants.siControlNumber )
        oLayout.EndGroup()
        
        oLayout.AddGroup("Pointcloud Bounds")
        oLayout.AddItem("pFilterByBounds", "Filter points by bounding volume", 
constants.siControlBoolean )
        oLayout.AddRow()
        oLayout.AddItem("pBoundMinX", "Min X", constants.siControlNumber )
        oLayout.AddItem("pBoundMaxX", "Max X", constants.siControlNumber )
        oLayout.EndRow()
        oLayout.AddRow()
        oLayout.AddItem("pBoundMinY", "Min Y", constants.siControlNumber )
        oLayout.AddItem("pBoundMaxY", "Max Y", constants.siControlNumber )
        oLayout.EndRow()
        oLayout.AddRow()
        oLayout.AddItem("pBoundMinZ", "Min Z", constants.siControlNumber )
        oLayout.AddItem("pBoundMaxZ", "Max Z", constants.siControlNumber )
        oLayout.EndRow()
        oLayout.EndGroup()
        
        rtn = xsi.InspectObj(oPset, 0, 0, constants.siModal, False)
        if not rtn:
                return oPset
        else:
                return


def GetXYZfilePath():
        # Setup a simple file browser session to pick .XYZ file
        global xyzfileName
        global xyzfilePath
        
        initDir = xsi.ActiveProject2.Path
        
        oFilebrowser = XSIUIToolkit.FileBrowser
        oFilebrowser.DialogTitle = "Please pick a .xyz file to import..."
        oFilebrowser.InitialDirectory = initDir
        oFilebrowser.Filter = "XYZ Files(*.xyz)|*.xyz|All Files (*.*)|*.*||"
        oFilebrowser.ShowOpen()
        
        xyzfilePath = oFilebrowser.FilePathName
        xyzfileName = oFilebrowser.FileBaseName
        
        
        if xyzfilePath <> "":
                return xyzfilePath
        else:
                return

def GetPointsList(xyzFilePath):
        # Open the .XYZ file and read-in all the data.
        xyzFile = open(xyzfilePath,"rU")
        dataStr = xyzFile.read()
        
        # Setup progress bar for point data parsing in case file is huge
        oProgressBar = XSIUIToolkit.ProgressBar
        oProgressBar.Maximum = 100
        oProgressBar.Caption = "Retrieving Points from .xyz File..."
        oProgressBar.Visible = 1
        oProgressBar.Value = 100
                
        # Massive regular expression retrieves all vaid point data from the file
        pointsList = 
re.findall(r"(-*\d+\.\d+|-*\d+\.\d+[Ee]-\d+)\,(-*\d+\.\d+|-*\d+\.\d+[Ee]-\d+)\,(-*\d+\.\d+|-*\d+\.\d+[Ee]-\d+)",
 dataStr)
        
        xyzFile.close()
        return pointsList

def ParsePoints(pointsList, pointsPerc):
        pointDataList = []
        
        nbPoints = len(pointsList)
        nbPointsFloat = float(nbPoints)

        lineStep = 
int(nbPointsFloat/((nbPointsFloat/100)*float(pointsPerc))+0.001)
        
        if lineStep >= 1 and lineStep <= nbPoints:
                # Setup progress bar for point data parsing
                oProgressBar = XSIUIToolkit.ProgressBar
                oProgressBar.Maximum = nbPoints
                oProgressBar.Step = lineStep
                oProgressBar.Caption = "Parsing Points List..."
                oProgressBar.CancelEnabled = 1
                oProgressBar.Visible = 1
                
                while oProgressBar.Value < oProgressBar.Maximum and not 
oProgressBar.CancelPressed:
                        lineNo = int(oProgressBar.Value)
                        
                        # Extract point data from points list
                        pointTuple = pointsList[lineNo]
                        
                        # Convert the point position tuple of string data to a 
list of floats that have been scaled according to user input
                        tmpPosition = [v*oPset.pSpatialScale.value for v in 
map(float, pointTuple[:3])]
                        # reorder as XYZ
                        pointPosition = 
[tmpPosition[0],tmpPosition[1],tmpPosition[2]]
                        
                        filterPoint = oPset.pFilterByBounds.value
                        # Check if point lies within the user defined bounding 
volume
                        inBounds = CheckWithinBounds(pointPosition)
                        
                        # Decide whether or not to skip the point if it lies 
outside the user defined bounding volume                   
                        if ((not filterPoint) or (filterPoint and inBounds)):
                                # Convert the color tuple of string data to a 
list of floats representing the color as Softimage RGB
                                pointColor = [0,0,0]
                                # Add a value of 1 as Alpha
                                pointAlphaValue = float(1)
                                pointColor.append(pointAlphaValue)
                                
                                # Append point position and color to 
pointDataList
                                pointDataList.append(pointColor+pointPosition)

                        oProgressBar.Increment()
                
        else:
                pr("Percentage too low!!! No points will be created!!!")
                pr("Aborting!!!")
        
        return pointDataList

def CheckWithinBounds(pointPosition):
        isWithinBounds = 1
        for i in range(0,2):
                if pointPosition[0] > oPset.pBoundMaxX.value or 
pointPosition[1] > oPset.pBoundMaxY.value or pointPosition[2] > 
oPset.pBoundMaxZ.value:
                        isWithinBounds = 0
                if pointPosition[0] < oPset.pBoundMinX.value or 
pointPosition[1] < oPset.pBoundMinY.value or pointPosition[2] < 
oPset.pBoundMinZ.value:
                        isWithinBounds = 0
        return isWithinBounds

####################################################################################################################################
# ICE CACHE STUFF
####################################################################################################################################

def WriteIceCache(xyzFilePath, pointDataList, pointSize):
        fileName, ext = os.path.splitext( xyzFilePath )

        icePath1 = fileName + ".1.icecache"
        icePath2 = fileName + ".2.icecache"
        returnPath = fileName + ".[1..2].icecache"
        
        cachefile1 = gzip.open( icePath1, "wb" )
        cachefile2 = gzip.open( icePath2, "wb" )
        
        nbPoints = len(pointDataList)
        
        data = WriteHeader( nbPoints, 3 )
        data += WriteAttrDefs()
        
        chunks = GetChunks(nbPoints)
        
        # Colors
        for chunk in chunks:
                data += pack("I", 0)    #is constant?
                for i in chunk:
                        r = pointDataList[i][0]
                        g = pointDataList[i][1]
                        b = pointDataList[i][2]
                        a = pointDataList[i][3]
                        
                        #pr(str(i) + ": " + str(r) + " --- " + str(g) + " --- " 
+ str(b) + " --- " + str(a))
                        data += pack("4f",r, g, b, a)
                        
        # Point positions
        data += pack("I", 0)    #is constant?
        for chunk in chunks:    
                for i in chunk:
                        x = pointDataList[i][4]
                        y = pointDataList[i][5]
                        z = pointDataList[i][6]
                        
                        #pr(str(i) + ": " + str(x) + " --- " + str(y) + " --- " 
+ str(z))
                        data += pack("3f",x, y, z)
                        
        # Sizes
        for chunk in chunks:
                data += pack("I", 0)    #is constant?
                for i in chunk:
                        data += pack("1f",pointSize)

        # Write two cache files.
        cachefile1.write( data )
        cachefile1.close()
        cachefile2.write( data )
        cachefile2.close()
        
        return returnPath

def WriteHeader( nbPoints, nbAttributes ):
        data  = pack( "8s", "ICECACHE" )    #header string
        data += pack( "I", 102 )     #version number
        data += pack( "I", 0 )     #object type, pointcloud
        data += pack( "I", nbPoints )     #point count
        data += pack( "I", 0 )    #edge count
        data += pack( "I", 0 )     #polygon count
        data += pack( "I", 0 )     #sample count
        data += pack( "I", 0 )     #don"t know this one
        data += pack( "I", nbAttributes )     #attribute count
        return data

def WriteAttrDefs():
        #particle color
        data  = pack( "L", 5 )    #attribute name length
        data += pack( "8s", "color___" )    #attribute name
        data += pack( "I", 512 )    #data type
        data += pack( "I", 1 )    #structure type
        data += pack( "I", 2 )    #context type
        data += pack( "I", 0 )    #database ID, obsolete
        data += pack( "I", 2 )    #category
                        
        #particle position
        data += pack( "L", 13 )    #attribute name length
        data += pack( "16s", "pointposition___" )    #attribute name
        data += pack( "I", 16 )    #data type
        data += pack( "I", 1 )    #structure type
        data += pack( "I", 2 )    #context type
        data += pack( "I", 0 )    #database ID, obsolete
        data += pack( "I", 2 )    #category

        #particle size
        data += pack( "L", 4 )    #attribute name length
        data += pack( "4s", "size" )    #attribute name
        data += pack( "I", 4 )    #data type
        data += pack( "I", 1 )    #structure type
        data += pack( "I", 2 )    #context type
        data += pack( "I", 0 )    #database ID, obsolete
        data += pack( "I", 2 )    #category

        return data
                

def GetChunks(num):
        if num < 4000:
                return [range(num)]
        
        outlist = []
        chunks = num / 4000
        for i in range(chunks):
                outlist.append(range((i)*4000, (i+1)*4000))
        outlist.append(range( (i+1)*4000, (i+1)*4000 + num%4000) )
                                
        return outlist

main()

Reply via email to