(3 + .1, 0)) #pylab.plot(*zip(*poly)); pylab.xlim(xmin=0); pylab.grid(); pylab.title('Meridian of the revolution surface\n(close to continue)'); pylab.gca().set_aspect(aspect='equal',adjustable='box'); pylab.show() thetas = arange(0, pi / 8, pi / 24) pts = pack.revolutionSurfaceMeridians([poly for theta in thetas], thetas, origin=Vector3(-4, 0, -1), orientation=Quaternion.Identity) surf = pack.sweptPolylines2gtsSurface(pts, capStart=True, capEnd=True, threshold=1e-4) O.bodies.append(pack.gtsSurface2Facets(surf, color=(1, 0, 1))) # fill this solid with triaxial packing; it will compute minimum-volume oriented bounding box # to minimize the number of throw-away spheres. # It does away with about 3k spheres for radius 3e-2 O.bodies.append( pack.randomDensePack(pack.inGtsSurface(surf), radius=3e-2, rRelFuzz=1e-1, memoizeDb='/tmp/gts-triax-packings.sqlite')) # translate the surface away and pack it again with sphere, but without the oriented bounding box (useOBB=False) # Here, we need 20k spheres (with more or less the same result) surf.translate(0, 0, 1) O.bodies.append(pack.gtsSurface2Facets(surf, color=(1, 0, 0))) O.bodies.append( pack.randomDensePack(pack.inGtsSurface(surf), radius=3e-2, rRelFuzz=1e-1, memoizeDb='/tmp/gts-triax-packings.sqlite', useOBB=False))
import gts s1 = gts.read(open('horse.coarse.gts')) s2 = gts.Surface() s2.copy(s1) s2.translate(0.04, 0, 0) O.bodies.append( pack.gtsSurface2Facets(s1, color=(0, 1, 0)) + pack.gtsSurface2Facets(s2, color=(1, 0, 0))) s12 = gts.Surface() s12.copy(s1.union(s2)) s12.translate(0, 0, .1) radius = 0.002 O.bodies.append(pack.gtsSurface2Facets(s12, color=(0, 0, 1))) qt.View() from time import time t0 = time() O.bodies.append( pack.regularHexa(pack.inGtsSurface(s1) | pack.inGtsSurface(s2), radius, gap=0, color=(0, 1, 0))) t1 = time() print 'Using predicate union: %gs' % (t1 - t0) O.bodies.append( pack.regularHexa(pack.inGtsSurface(s12), radius, gap=0., color=(1, 0, 0))) t2 = time() print 'Using surface union: %gs' % (t2 - t1)
# pts=pack.revolutionSurfaceMeridians([[(pt[0],pt[1]+2e-3*theta) for pt in poly] for theta in thetas],thetas # pts=pack.revolutionSurfaceMeridians([[(pt[0],pt[1]+1e-2*theta) for pt in poly] for theta in thetas],thetas,origin=Vector3(0,-.05,.1),orientation=Quaternion((1,1,0),pi/4)) # connect meridians to make surfaces # caps will close it at the beginning and the end # threshold will merge points closer than 1e-4; this is important: we want it to be closed for filling surf=pack.sweptPolylines2gtsSurface(pts,capStart=True,capEnd=True,threshold=1e-4) # add the surface as facets to the simulation, to make it visible O.bodies.append(pack.gtsSurface2Facets(surf,color=(1,0,1))) # now fill the inGtsSurface predicate constructed form the same surface with sphere packing generated by TriaxialTest # with given radius and standard deviation (see documentation of pack.randomDensePack) # # The memoizeDb will save resulting packing into given file and next time, if you run with the same # parameters (or parameters that can be scaled to the same one), # it will load the packing instead of running the triaxial compaction again. # Try running for the second time to see the speed difference! memoizeDb='/tmp/gts-triax-packings.sqlite' O.bodies.append(pack.randomDensePack(pack.inGtsSurface(surf),radius=5e-3,rRelFuzz=1e-4,memoizeDb=memoizeDb)) # We could also fill the horse with triaxial packing, but have nice approximation, the triaxial would run terribly long, # since horse discard most volume of its bounding box # Here, we would use a very crude one, however if 1: import gts horse=gts.read(open('horse.coarse.gts')) #; horse.scale(.25,.25,.25) O.bodies.append(pack.gtsSurface2Facets(horse)) O.bodies.append(pack.randomDensePack(pack.inGtsSurface(horse),radius=5e-3,memoizeDb=memoizeDb)) horse.translate(.07,0,0) O.bodies.append(pack.gtsSurface2Facets(horse)) # specifying spheresInCell makes the packing periodic, with the given number of spheres, proportions being equal to that of the predicate O.bodies.append(pack.randomDensePack(pack.inGtsSurface(horse),radius=1e-3,spheresInCell=2000,memoizeDb=memoizeDb))
Note that GTS only moves references to surfaces around, therefore e.g. translating surface that is part of the union will move also the part of the united surface. Therefore, we use the copy() method for deep copy here. """ from __future__ import print_function from woo import pack, qt import gts s1 = gts.read(open("horse.coarse.gts")) s2 = gts.Surface() s2.copy(s1) s2.translate(0.04, 0, 0) O.bodies.append(pack.gtsSurface2Facets(s1, color=(0, 1, 0)) + pack.gtsSurface2Facets(s2, color=(1, 0, 0))) s12 = gts.Surface() s12.copy(s1.union(s2)) s12.translate(0, 0, 0.1) radius = 0.002 O.bodies.append(pack.gtsSurface2Facets(s12, color=(0, 0, 1))) qt.View() from time import time t0 = time() O.bodies.append(pack.regularHexa(pack.inGtsSurface(s1) | pack.inGtsSurface(s2), radius, gap=0, color=(0, 1, 0))) t1 = time() print("Using predicate union: %gs" % (t1 - t0)) O.bodies.append(pack.regularHexa(pack.inGtsSurface(s12), radius, gap=0.0, color=(1, 0, 0))) t2 = time() print("Using surface union: %gs" % (t2 - t1))
isGtsSurface as predicate with the united surface. The disadvantage of the predicate union | is that each sphere must fit whole in one surface or another: with padding, several points on the sphere are tested. Therefore, areas near both surfaces' boundary will not be filled at all. Note that GTS only moves references to surfaces around, therefore e.g. translating surface that is part of the union will move also the part of the united surface. Therefore, we use the copy() method for deep copy here. """ from woo import pack,qt import gts s1=gts.read(open('horse.coarse.gts')) s2=gts.Surface(); s2.copy(s1); s2.translate(0.04,0,0) O.bodies.append(pack.gtsSurface2Facets(s1,color=(0,1,0))+pack.gtsSurface2Facets(s2,color=(1,0,0))) s12=gts.Surface(); s12.copy(s1.union(s2)); s12.translate(0,0,.1) radius=0.002 O.bodies.append(pack.gtsSurface2Facets(s12,color=(0,0,1))) qt.View() from time import time t0=time() O.bodies.append(pack.regularHexa(pack.inGtsSurface(s1) | pack.inGtsSurface(s2),radius,gap=0,color=(0,1,0))) t1=time() print('Using predicate union: %gs'%(t1-t0)) O.bodies.append(pack.regularHexa(pack.inGtsSurface(s12),radius,gap=0.,color=(1,0,0))) t2=time() print('Using surface union: %gs'%(t2-t1))
# -*- coding: utf-8 -*- from numpy import arange from woo import pack import pylab # define the section shape as polygon in 2d; repeat first point at the end to close the polygon sq2=sqrt(2) poly=((3+.1,0),(3+0,.1),(3+sq2,.1+sq2),(3+.1+sq2,sq2),(3+.1,0)) #pylab.plot(*zip(*poly)); pylab.xlim(xmin=0); pylab.grid(); pylab.title('Meridian of the revolution surface\n(close to continue)'); pylab.gca().set_aspect(aspect='equal',adjustable='box'); pylab.show() thetas=arange(0,pi/8,pi/24) pts=pack.revolutionSurfaceMeridians([poly for theta in thetas],thetas,origin=Vector3(-4,0,-1),orientation=Quaternion.Identity) surf=pack.sweptPolylines2gtsSurface(pts,capStart=True,capEnd=True,threshold=1e-4) O.bodies.append(pack.gtsSurface2Facets(surf,color=(1,0,1))) # fill this solid with triaxial packing; it will compute minimum-volume oriented bounding box # to minimize the number of throw-away spheres. # It does away with about 3k spheres for radius 3e-2 O.bodies.append(pack.randomDensePack(pack.inGtsSurface(surf),radius=3e-2,rRelFuzz=1e-1,memoizeDb='/tmp/gts-triax-packings.sqlite')) # translate the surface away and pack it again with sphere, but without the oriented bounding box (useOBB=False) # Here, we need 20k spheres (with more or less the same result) surf.translate(0,0,1); O.bodies.append(pack.gtsSurface2Facets(surf,color=(1,0,0))) O.bodies.append(pack.randomDensePack(pack.inGtsSurface(surf),radius=3e-2,rRelFuzz=1e-1,memoizeDb='/tmp/gts-triax-packings.sqlite',useOBB=False))