def figuresMaxRadius(figures):
	maxRadius=0
	for f in figuresIterator(figures):
		if f.dim==0:
			r=algebra.vectLen(f.position)
			if r>maxRadius:
				maxRadius=r
	return maxRadius
def figuresScale(figures, factor):
	for f in figuresIterator(figures):
		if f.dim==0:
			f.position=algebra.vectMult(factor, f.position)
Example #3
0
def cutFigure(figure, hyperplane, reuseCache=False):
	if not reuseCache:
		for f in figure:
			f.cuttingCache=None

	if figure.cuttingCache: # Already computed
		return figure.cuttingCache
	def cache(left, section, right): # Caching before returning
		if reuseCache:
			figure.cuttingCache=left,section,right
		else: # Remove cache
			for f in figure:
				del f.cuttingCache
		return left, section, right

	if figure.dim == 0: # Vertex
		dist=hyperplane.orientedDistance(figure.position)
		if abs(dist)<0.00001:
			return cache([], [figure], [])
		elif dist<0:
			return cache([figure], [], [])
		else:
			return cache([], [], [figure])

	else: # Edge, face, ...
		left,middle,right = \
				zip(*map(lambda f: cutFigure(f, hyperplane, True), figure.boundary))
		left,middle,right = (reduce(lambda a,b: a+b, l) for l in (left,middle,right))

		if not right and not left: # All in the hyperplane
			return cache([], [figure], [])
		elif not right:            # Nothing right
			return cache([figure], middle, [])
		elif not left:             # Nothing left
			return cache([], middle, [figure])

		elif figure.dim == 1:      # Cutting edge
			diff=algebra.vectDiff(right[0].position, left[0].position)
			prod=algebra.dotProduct(diff, hyperplane.normal)
			dist=hyperplane.orientedDistance(left[0].position)
			vert=Vertex(algebra.vectSum(left[0].position, algebra.vectMult(-dist/prod, diff)))
			leftEdge=Figure([left[0], vert])
			rightEdge=Figure([right[0], vert])
			return cache([leftEdge], [vert], [rightEdge])

		else:                      # Cutting face (at least 2-dimensional)
			middle.sort(key=attrgetter('dim'), reverse=True)
			for f in figuresIterator(middle):
				f.used=False
			section=[]
			middle2=set()
			for f in middle:
				if not f.used:
					if f.dim == figure.dim-2:
						middle2.add(f)
					else:
						section.append(f)
					for f2 in f:
						f2.used=True
			for f in figuresIterator(middle):
				del f.used

			if True: # General case

				def findComponents(figures, exclude):
					for f in figures:
						f.group=None
						f.groupIndex=None
						f.groupRank=0
						for f2 in f.boundary:
							f2.groupRank=0
							f2.group=None
					def find(f):
						f2=f
						while f.group:
							f=f.group
						while f2.group:
							f3=f2.group
							f2.group=f
							f2=f3
						return f
					def union(parent, child):
						parent=find(parent)
						child=find(child)
						if child == parent:
							return
						if parent.groupRank>child.groupRank:
							child.group=parent
						elif parent.groupRank == child.groupRank:
							child.group=parent
							parent.groupRank+=1
						else:
							parent.group=child
						return
					for f in figures:
						for f2 in f.boundary:
							if not f2 in exclude:
								union(f, f2)
					groups=[]
					for f in figures:
						g=find(f)
						if g.groupIndex == None:
							g.groupIndex=len(groups)
							groups.append([])
						groups[g.groupIndex].append(f)
					for f in figures:
						del f.group
						del f.groupIndex
						del f.groupRank
						for f2 in f.boundary:
							f2.group=None
							del f2.group
							f2.groupRank=None
							del f2.groupRank
					return groups

				leftComp=findComponents(left, middle2)
				rightComp=findComponents(right, middle2)
				leftComp=[Figure(c) for c in leftComp]
				rightComp=[Figure(c) for c in rightComp]

				sectComp=[]
				for f in leftComp:
					comp=[set()]
					for f2 in f.boundary:
						comp[0] |= f2.boundary & middle2
					sectComp.append(comp)
					f.sect=comp
				# sectComp=[ [set(vertices)] ]
				for f in rightComp:
					f.sect=[]
				for c in sectComp:
					m=c.pop()
					for f in rightComp:
						comp=[set()]
						for f2 in f.boundary:
							comp[0] |= f2.boundary & m
						c.append(comp)
						f.sect.append(comp)
				# sectComp=[ [[set(vertices)]] ]
				for l in sectComp:
					for m in l:
						m.append(Figure(m.pop()))
						section.append(m[0])
				for f in leftComp+rightComp:
					for f2 in f.sect:
						f.addToBoundary(f2[0])
					del f.sect

			else: # Convex only

				newSect=Figure(middle2)
				leftComp=[Figure(left + [newSect])]
				rightComp=[Figure(right + [newSect])]
				section.append(newSect)

			return cache(leftComp, section, rightComp)