Skip to content

Instantly share code, notes, and snippets.

@yig
Created April 11, 2024 16:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yig/d571c855b6ae1e61b8eeaa52c9776172 to your computer and use it in GitHub Desktop.
Save yig/d571c855b6ae1e61b8eeaa52c9776172 to your computer and use it in GitHub Desktop.
A port of "Retrieval on Parametric Shape Collections" [Schulz et al. 2017]'s public code release to Python.
# A port of "Retrieval on Parametric Shape Collections" [Schulz et al. 2017]'s public code release to Python.
# Project website: <https://people.csail.mit.edu/aschulz/paramShapeRetrieval/index.html>
# This code was created by manually correcting the output of ChatGPT.
import numpy as np
class ParametricShape:
EPSILON_CONST = 1e-7
def __init__(self, filename=None, nParameters=None, defaultParameters=None, triangles=None,
verticesMatrix=None, verticesVector=None, constraintsMatrix=None,
constraintsVector=None):
if filename:
self.read_from_file(filename)
else:
self.nParameters = nParameters
self.defaultParameters = np.array(defaultParameters)
self.triangles = np.array(triangles)
self.verticesMatrix = np.array(verticesMatrix)
self.verticesVector = np.array(verticesVector)
self.constraintsMatrix = np.array(constraintsMatrix)
self.constraintsVector = np.array(constraintsVector)
def eval_shape(self, params):
if self.constraintsMatrix.shape[0] > 0:
if ( self.constraintsMatrix @ params - self.constraintsVector ).max() > self.EPSILON_CONST:
print("Parameters are not valid")
raise ValueError( "Parameters are not valid" )
vertex_positions = self.verticesMatrix @ params + self.verticesVector
vertices = vertex_positions.reshape( -1, 3 )
return vertices, self.triangles
def output_to_file(self, filename):
with open(filename, 'wb') as outFile:
print( outFile.tell() )
outFile.write( self.nParameters.to_bytes( length = 4, byteorder='little' ) )
outFile.write( self.verticesVector.shape[0].to_bytes( length = 4, byteorder='little' ) )
outFile.write( self.triangles.shape[0].to_bytes( length = 4, byteorder='little' ) )
outFile.write( self.constraintsVector.shape[0].to_bytes( length = 4, byteorder='little' ) )
outFile.write( self.defaultParameters.astype( '<f8' ).tobytes( order='F' ) )
outFile.write( self.verticesMatrix.astype( '<f8' ).tobytes( order='F' ) )
outFile.write( self.verticesVector.astype( '<f8' ).tobytes( order='F' ) )
outFile.write( self.triangles.astype( '<i4' ).tobytes() )
outFile.write( self.constraintsMatrix.astype( '<f8' ).tobytes( order='F' ) )
outFile.write( self.constraintsVector.astype( '<f8' ).tobytes( order='F' ) )
def read_from_file(self, filename):
with open(filename, 'rb') as inFile:
self.nParameters = int.from_bytes(inFile.read(4), byteorder='little')
nVertices = int.from_bytes(inFile.read(4), byteorder='little')
nTriangles = int.from_bytes(inFile.read(4), byteorder='little')
nConstraints = int.from_bytes(inFile.read(4), byteorder='little')
self.defaultParameters = np.frombuffer( inFile.read( self.nParameters * 8 ), dtype = '<f8' ).astype( 'f8' )
self.verticesMatrix = np.frombuffer( inFile.read( nVertices * self.nParameters * 8 ), dtype = '<f8' ).astype( 'f8' ).reshape( ( nVertices, self.nParameters ), order = 'F' )
self.verticesVector = np.frombuffer( inFile.read(nVertices * 8), dtype = '<f8' ).astype( 'f8' )
self.triangles = np.frombuffer( inFile.read( nTriangles * 3 * 4 ), dtype = '<i4' ).astype( 'i4' ).reshape( ( nTriangles, 3 ) )
self.constraintsMatrix = np.frombuffer( inFile.read( nConstraints * self.nParameters * 8 ), dtype = '<f8' ).astype( 'f8' ).reshape( ( nConstraints, self.nParameters ), order = 'F' )
self.constraintsVector = np.frombuffer( inFile.read( nConstraints * 8 ), dtype = '<f8' ).astype( 'f8' )
if __name__ == '__main__':
import argparse
import trimesh
parser = argparse.ArgumentParser()
parser.add_argument( 'inpath', type=str, help='One of the parametric shapes' )
parser.add_argument( 'outpath', type=str, help='Where to save the output' )
args = parser.parse_args()
shape = ParametricShape( args.inpath )
shape.output_to_file( args.inpath + '.verify' )
vertices, triangles = shape.eval_shape( shape.defaultParameters )
trimesh.Trimesh( vertices = vertices, faces = triangles ).export( args.outpath )
print( "Saved:", args.outpath )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment