← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-pkg/yade/git-trunk] Rev 3968: added pack.inHalfSpace and pack.inConvexPolygon + example script

 

------------------------------------------------------------
revno: 3968
committer: Jan Stránský <jan.stransky@xxxxxxxxxxx>
timestamp: Thu 2016-11-10 15:38:54 +0100
message:
  added pack.inHalfSpace and pack.inConvexPolygon + example script
added:
  examples/test/pack-inConvexPolyhedron.py
modified:
  py/pack/pack.py


--
lp:yade
https://code.launchpad.net/~yade-pkg/yade/git-trunk

Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-pkg/yade/git-trunk/+edit-subscription
=== added file 'examples/test/pack-inConvexPolyhedron.py'
--- examples/test/pack-inConvexPolyhedron.py	1970-01-01 00:00:00 +0000
+++ examples/test/pack-inConvexPolyhedron.py	2016-11-10 14:38:54 +0000
@@ -0,0 +1,62 @@
+from yade import pack
+import random
+random.seed(1)
+
+# a cube
+p1 = Vector3(-9,-2,-2)
+p2 = p1 + (1,1,1)
+pred1 = pack.inConvexPolyhedron((
+	(p1, (+1, 0, 0)),
+	(p1, ( 0,+1, 0)),
+	(p1, ( 0, 0,+1)),
+	(p2, (-1, 0, 0)),
+	(p2, ( 0,-1, 0)),
+	(p2, ( 0, 0,-1)),
+))
+
+# a tetrahedron
+p1 = Vector3(-7,-2,-2)
+p2 = p1 + (1,1,1)
+pred2 = pack.inConvexPolyhedron((
+	(p1, (+1, 0, 0)),
+	(p1, ( 0,+1, 0)),
+	(p1, ( 0, 0,+1)),
+	(p2, (-1,-1,-1)),
+))
+
+# random polyhedron
+center = Vector3(-2,-2,-2)
+dMin = 1
+dMax = 1.2
+n = 20
+planes = []
+for i in xrange(n):
+	d = random.random()*(dMax-dMin) + dMin # distance of plane from center, random number in range (dMin,dMax)
+	# http://mathworld.wolfram.com/HyperspherePointPicking.html
+	normal = Vector3([random.gauss(0,10) for _ in xrange(3)]) # random normal vector
+	normal.normalize()
+	planes.append((center-d*normal,normal))
+pred3 = pack.inConvexPolyhedron(planes)
+
+try: # should be ValueError, since the 3 planes does not form closed polyhedron and finding its bounds should fail
+	pred4 = pack.inConvexPolyhedron((
+		((0,0,0), (+1, 0, 0)),
+		((0,0,0), ( 0,+1, 0)),
+		((0,0,0), ( 0, 0,+1)),
+	))
+except ValueError:
+	print 'ValueError successfully detected'
+else:
+	raise RuntimeError, "ValueError should have been detected..."
+
+r = .05
+for p in (pred1,pred2,pred3):
+	O.bodies.append(pack.regularHexa(p,r,0,color=randomColor()))
+
+
+try:
+	from yade import qt
+	v = qt.View()
+	v.axes = True
+except:
+	pass

=== modified file 'py/pack/pack.py'
--- py/pack/pack.py	2015-12-09 00:13:58 +0000
+++ py/pack/pack.py	2016-11-10 14:38:54 +0000
@@ -174,6 +174,78 @@
       inf=float('inf'); return Vector3(inf,inf,inf)
     def __call__(self,pt,pad): return True
 
+  class inHalfSpace(Predicate):
+    """Predicate returning True  any points, with infinite bounding box."""
+    def __init__(self, _center=Vector3().Zero, _dir=Vector3(1,0,0)):
+      self._center = Vector3(_center)
+      self._dir = Vector3(_dir)
+      assert self._dir.norm() > 0., "Direction has to be nonzero vector"
+      self._dir.normalize()
+      self._d = -self._dir.dot(self._center)
+    def aabb(self):
+      d,c = self._dir, self._center
+      inf=float('inf')
+      min = Vector3(-inf,-inf,-inf)
+      max = Vector3(+inf,+inf,+inf)
+      for i in xrange(3):
+        j = (i+1)%3
+        k = (i+2)%3
+        if d[i]==0 and d[j]==0:
+          if d[k] > 0: min[k] = c[k]
+          else: max[k] = c[k]
+      return min,max
+    def center(self):
+      return self._center
+    def dim(self):
+      inf=float('inf')
+      return Vector3(inf,inf,inf)
+    def __call__(self,pt,pad):
+      v = self._dir.dot(pt) + self._d
+      return v > pad
+
+  class inConvexPolyhedron(Predicate):
+    def __init__(self,planes):
+      self._inHalfSpaces = [inHalfSpace(c,d) for c,d in planes]
+      self._min, self._max = self._computeAabb()
+    def _computeAabb(self):
+      try:
+        import scipy.optimize
+      except ImportError:
+        raise ImportError, "scipy (package python-scipy) needed for pack.inConvexPolyhedron"
+      min,max = Vector3.Zero, Vector3.Zero
+      A,b = [],[]
+      for h in self._inHalfSpaces:
+        A.append(tuple(-h._dir))
+        b.append(h._d)
+      inf = float('inf')
+      for i in xrange(3):
+        c = Vector3.Zero
+        #
+        c[i] = 1
+        opt = scipy.optimize.linprog(c,A_ub=A,b_ub=b,bounds=(-inf,inf))
+        errmsg = "Something wrong in pack.inConvexPolyhedron defining planes.\nThe scipy.optimize.linprog output:\n{}\n"
+        if not opt.success:
+          raise ValueError, errmsg.format(opt)
+        min[i] = opt.x[i]
+        #
+        c[i] = -1
+        opt = scipy.optimize.linprog(c,A_ub=A,b_ub=b,bounds=(-inf,inf))
+        if not opt.success:
+          raise ValueError, errmsg.format(opt)
+        max[i] = opt.x[i]
+      return min,max
+    def aabb(self):
+      return Vector3(self._min), Vector3(self._max)
+    def center(self):
+      return .5*(self._min + self._max)
+    def dim(self):
+      return self._max - self._min
+    def __call__(self,pt,pad):
+      for p in self._inHalfSpaces:
+        if not p(pt,pad):
+          return False
+      return True
+
 #####
 ## surface construction and manipulation
 #####