- @classmethod
- def _sort_polygon_3d(cls, points):
- if len(points) <= 3:
- return points
- o = cls._polygon_inner_point(points)
- a = points[0]
- oa = Vector(o, a)
- norm_oa = oa.norm()
- for b in points[1:]:
- ob = Vector(o, b)
- u = oa.cross(ob)
- if not u.isnull():
- u = u.asunit()
- break
- else:
- raise ValueError('degenerate polygon')
- angles = {a: 0.}
- for m in points[1:]:
- om = Vector(o, m)
- normprod = norm_oa * om.norm()
- cosinus = max(oa.dot(om) / normprod, -1.)
- sinus = u.dot(oa.cross(om)) / normprod
- angle = math.acos(cosinus)
- angle = math.copysign(angle, sinus)
- angles[m] = angle
- return sorted(points, key=angles.get)
-
- def faces(self):
- vertices = self.vertices()
- faces = []
- for constraint in self.constraints:
- face = []
- for vertex in vertices:
- if constraint.subs(vertex.coordinates()) == 0:
- face.append(vertex)
- faces.append(face)
- return faces
-
- def plot(self):
- """
- Display 3D plot of set.
- """
- import matplotlib.pyplot as plt
- import matplotlib.patches as patches
-
- if len(self.symbols)> 3:
- raise TypeError
-
- elif len(self.symbols) == 2:
- import pylab
- points = []
- for verts in self.vertices():
- pairs=()
- for coordinate, point in verts.coordinates():
- pairs = pairs + (float(point),)
- points.append(pairs)
- cent=(sum([p[0] for p in points])/len(points),sum([p[1] for p in points])/len(points))
- points.sort(key=lambda p: math.atan2(p[1]-cent[1],p[0]-cent[0]))
- pylab.scatter([p[0] for p in points],[p[1] for p in points])
- pylab.gca().add_patch(patches.Polygon(points,closed=True,fill=True))
- pylab.grid()
- pylab.show()
-
- elif len(self.symbols)==3:
- from mpl_toolkits.mplot3d import Axes3D
- from mpl_toolkits.mplot3d.art3d import Poly3DCollection
- faces = self.faces()
- fig = plt.figure()
- ax = Axes3D(fig)
- for face in faces:
- points = []
- vertices = Polyhedron._sort_polygon_3d(face)
- for verts in vertices:
- pairs=()
- for coordinate, point in verts.coordinates():
- pairs = pairs + (float(point),)
- points.append(pairs)
- collection = Poly3DCollection([points], alpha=0.7)
- face_color = [0.5, 0.5, 1] # alternative: matplotlib.colors.rgb2hex([0.5, 0.5, 1])
- collection.set_facecolor(face_color)
- ax.add_collection3d(collection)
- ax.set_xlabel('X')
- ax.set_xlim(0, 5)
- ax.set_ylabel('Y')
- ax.set_ylim(0, 5)
- ax.set_zlabel('Z')
- ax.set_zlim(0, 5)
- plt.grid()
- plt.show()
- return points
-
- @classmethod
- def limit(cls, faces, variable, lim):
- sym = []
- if variable is 'x':
- n = 0
- elif variable is 'y':
- n = 1
- elif variable is 'z':
- n = 2
- for face in faces:
- for vert in face:
- coordinates = vert.coordinates()
- for point in enumerate(coordinates):
- coordinates.get(n)
- sym.append(points)
- if lim == 0:
- value = min(sym)
- else:
- value = max(sym)
- return value