Ejemplo n.º 1
0
def cutOffFaces(figure, ratio, faces):
	hyperplanes=[]
	innerPoint=algebra.vectAvg(*[v.position for v in figure if v.dim==0])
	for f in faces:
		points=[v.position for v in f if v.dim==0]
		basis=algebra.orthonormalBasisFromPoints(points)
		normal=algebra.orthogonalizeVect(algebra.vectDiff(points[0], innerPoint), basis)
		if algebra.vectLen(normal)<0.0001:
			raise RuntimeError("Cannot cut faces")
		hyperplanes.append(Hyperplane(normal, (1-ratio+algebra.dotProduct(normal, innerPoint)/algebra.vectLen(normal)**2)))
	return cutOffConvex(figure, hyperplanes, innerPoint)
Ejemplo n.º 2
0
def cutFigure(wholeFigure, hyperplane):

	facesAscending=[]
	queue=[wholeFigure]
	mark=object()
	while queue:
		figure=queue.pop(0)
		if figure.mark==mark: continue
		figure.mark=mark
		facesAscending.insert(0,figure)
		queue.extend(figure.boundary)

	for figure in facesAscending:
		figure.usedInSection=False
		figure.sectionFacets=[]
		if figure.dim == 0: # Vertex
			dist=hyperplane.orientedDistance(figure.position)
			if abs(dist)<0.0001:
				figure.cuttingCache=([], [figure], [])
			elif dist>0:
				figure.cuttingCache=([], [], [figure])
			else:
				figure.cuttingCache=([figure], [], [])
			continue;

		# Edge, face, ...

		left,middle,right = \
				zip(*map(lambda f: f.cuttingCache, 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
			figure.cuttingCache=([], [figure], [])
			continue


		if not right or not left:
			for f in middle:
				if f.dim==figure.dim-1:
					for f2 in f.boundary:
						f2.usedInSection=True
					figure.sectionFacets.append(f)

		middle2=[]
		for f in middle:
			if not f.usedInSection or f.dim == figure.dim-2:
				middle2.append(f)
		middle=middle2


		if not right:            # Nothing right
			figure.cuttingCache=([figure], middle, [])
			continue
		if not left:             # Nothing left
			figure.cuttingCache=([], middle, [figure])
			continue

		section=[]
		middle2=set()
		for f in middle:
			if f.dim == figure.dim-2:
				middle2.add(f)
			elif f.dim != figure.dim-1:
				section.append(f)
		middle=middle2

		if 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)))
			vert.usedInSection=True
			leftEdge=Figure([left[0], vert])
			rightEdge=Figure([right[0], vert])
			leftEdge.sectionFacets=[vert]
			rightEdge.sectionFacets=[vert]
			figure.cuttingCache=([leftEdge], [vert], [rightEdge])
			continue

		# Cutting face (at least 2-dimensional)

		leftComp=check.findComponents(left, middle)
		rightComp=check.findComponents(right, middle)
		leftComp=[Figure(c) for c in leftComp]
		rightComp=[Figure(c) for c in rightComp]

		for rightFigure in rightComp:
			rightFigure.sectionFacets=[]
			rightFigure.sectionRidges=set()
			for f in rightFigure.boundary:
				rightFigure.sectionRidges.update(f.sectionFacets)
		for leftFigure in leftComp:
			leftFigure.sectionFacets=[]
			leftRidges=set()
			for f in leftFigure.boundary:
				leftRidges.update(f.sectionFacets)
			for rightFigure in rightComp:
				rightRidges=rightFigure.sectionRidges
				commonRidges=leftRidges | rightRidges
				if commonRidges:
					f=Figure(commonRidges)
					f.usedInSection=True
					leftFigure.sectionFacets.append(f)
					rightFigure.sectionFacets.append(f)
					leftFigure.boundary.add(f)
					rightFigure.boundary.add(f)
					section.append(f)


		for f in middle:
			if not f.usedInSection:
				section.append(f)


		figure.cuttingCache=(leftComp, section, rightComp)

	ret=wholeFigure.cuttingCache;
	for figure in wholeFigure:
		del figure.cuttingCache
		del figure.usedInSection

	return ret;
Ejemplo n.º 3
0
def stellateFigure(figure):
	for f in figure.boundary:
		for f2 in f:
			f2.bounds=[]
	for f in figure.boundary:
		for f2 in f:
			f2.bounds.append(f)
	vertsPos=[v.position for v in figure if v.dim == 0]
	innerPoint=algebra.vectMult(1.0/len(vertsPos), algebra.vectSum(*vertsPos))
	figByBoundary=dict()
	for f in sorted(figure, key=attrgetter("dim")):
		if f.dim == 0:
			pass
		else:
			figByBoundary[frozenset(f.boundary)]=f

	newFacets=[]
	for f in figure.boundary:
		facets=set()
		for f2 in f.boundary:
			facets=facets.union(f2.bounds) # to be in-place
		facets.remove(f)
		hyperplanes=[spaceCuts.hyperplaneOfFacet(f2, innerPoint) for f2 in facets]
		hyperplane=spaceCuts.hyperplaneOfFacet(f, innerPoint).inverse()
		fv=[v.position for v in f if v.dim==0]
		apexPoint=algebra.vectMult(1.0/len(fv), algebra.vectSum(*fv))
		dist=float('inf')
		for h in hyperplanes:
			p=algebra.dotProduct(hyperplane.normal, h.normal)
			if p<-0.0001:
				d=-h.orientedDistance(apexPoint)/p
				if d<0.0001:
					raise RuntimeError("The figure is not convex")
				elif d<dist:
					dist=d
		if dist == float('inf'):
			raise RuntimeError("Infinite stellations are not supported")

		hyperplanes.append(hyperplane)
		apexInnerPoint=algebra.vectSum(apexPoint, algebra.vectMult(dist/2.0, hyperplane.normal))
		apexFigure=spaceCuts.figureFromArea(hyperplanes, apexInnerPoint)
		vertices=[v for v in f if v.dim == 0]
		apexVertices=[v for v in apexFigure if v.dim == 0]
		for f2 in sorted(apexFigure, key=attrgetter('dim')):
			f2.copy=None
			if f2.dim==0:
				for v in vertices: # slow, can be improved
					if algebra.pointsDist(v.position, f2.position) < 0.0001:
						f2.copy = v
						break
			else:
				boundary=set()
				shared=True
				for f3 in f2.boundary:
					boundary.add(f3.copy or f3)
					shared = shared and f3.copy
				f2.boundary=boundary
				if shared:
					f2.copy=figByBoundary[frozenset(boundary)]
				elif f2.dim==f.dim:
					newFacets.append(f2)
	return objFigure.Figure(newFacets)
Ejemplo n.º 4
0
def stellateFigure(figure):
	objFigure.updateVerticesLists(figure)
	objFigure.updateParentsLists(figure)
	innerPoint=algebra.vectAvg(*[v.position for v in figure.vertices])

	for f in figure.boundary:
		f.hyperplane=spaceCuts.hyperplaneOfFacet(f, innerPoint);
		f.hyperplane.origFacet=f

	newFacets=[]
	for f in figure.boundary:
		facets=set()
		for f2 in f.boundary:
			facets.update(f2.parents)
		facets.remove(f)
		hyperplanes=[f2.hyperplane for f2 in facets]
		hyperplane=f.hyperplane.inverse()
		hyperplane.origFacet=f
		apexPoint=algebra.vectAvg(*[v.position for v in f.vertices])
		dist=float('inf')
		for h in hyperplanes:
			p=algebra.dotProduct(hyperplane.normal, h.normal)
			if p<-0.0001:
				d=-h.orientedDistance(apexPoint)/p
				if d<0.0001:
					raise RuntimeError("The figure is not convex")
				elif d<dist:
					dist=d
		if dist == float('inf'):
			raise RuntimeError("Infinite stellations are not supported")

		hyperplanes.append(hyperplane)
		apexInnerPoint=algebra.vectSum(apexPoint, algebra.vectMult(dist/2.0, hyperplane.normal))
		apexFigure=spaceCuts.figureFromArea(hyperplanes, apexInnerPoint)

		apexBaseFacet=[f3 for f3 in apexFigure.boundary if f3.origHypp.origFacet==f][0]
		for f3 in apexFigure:
			f3.origFace=None
		apexFigure.rmFromBoundary(apexBaseFacet)
		for apexFacet in apexFigure.boundary:
			apexRidge=(apexFacet.boundary & apexBaseFacet.boundary).pop()
			apexRidge.origFace=(apexFacet.origHypp.origFacet.boundary & f.boundary).pop()
		objFigure.updateParentsLists(apexBaseFacet)
		queue=[]
		for apexRidge in apexBaseFacet.boundary:
			queue.extend(apexRidge.boundary)
		while queue:
			apexFace=queue.pop(0)
			if apexFace.origFace: continue
			origP1=apexFace.parents[0].origFace
			origP2=apexFace.parents[1].origFace
			apexFace.origFace=(origP1.boundary & origP2.boundary).pop()
			queue.extend(apexFace.boundary)
		for f3 in apexBaseFacet:
			del f3.parents
		queue=[apexFigure]
		apexFigure.mark=True
		while queue:
			apexFace=queue.pop(0)
			if not apexFace.mark: continue
			apexFace.mark=None
			for apexFace2 in list(apexFace.boundary):
				if apexFace2.origFace:
					apexFace.boundary.remove(apexFace2)
					apexFace.boundary.add(apexFace2.origFace)
				else:
					apexFace2.mark=True
					queue.append(apexFace2)
		newFacets.extend(apexFigure.boundary)

	return objFigure.Figure(newFacets)
Ejemplo n.º 5
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)