import math, time scaler = 100 step = 0.001 maxcoord = 150 class Calculator: def __init__(self, sliders, tools, affordances, positions): self.sliders = sliders self.tools = tools self.affordances = affordances self.positions = positions def _prepare(self): """ r = {'aff1': toolAffVal*sliderVal} r = {'tool1': {'aff1': toolAffVal*sliderVal} } """ r = {} for tool in self.tools: r[tool.id] = {} for a in self.affordances: slider_val = self.sliders.get(a, 0) r[tool.id][a] = (tool.getAffordanceData(a)/6) * (slider_val/6) self._cached_ontovectors = r return def _cache_ontodistance(self): r = {} for t1 in self.tools: r[t1.id] = {} for t2 in self.tools: aloc = self._ontovector(t1.id) bloc = self._ontovector(t2.id) dcum = 0 for a in self.affordances: ad = aloc.get(a) bd = bloc.get(a) dcum += math.pow(ad-bd, 2) res = math.sqrt(dcum) r[t1.id][t2.id] = scaler * res self._cached_onto_distance = r def _finalize(self): self.tools = [ t.id for t in self.tools ] def calculate(self): #for iCount in [1,]: ovr = time.time() for iCount in range(1, 100): #print ">>", iCount #st = time.time() for t1 in self.tools: for t2 in self.tools: targetdistance = self._ontodistance(t1, t2) delta = self._ddistance(t1, t2) - targetdistance; newloc = self._approach(t1, t2, delta*step) self.positions[t1] = newloc #print time.time()-st self._normalize() self._rotateBiggestToCorner() self._normalize() print time.time()-ovr return self.positions def _ontodistance(self, t1, t2): return self._cached_onto_distance.get(t1).get(t2) def _ontovector(self, tool): return self._cached_ontovectors[tool] def _ddistance(self, t1, t2): aloc = self.positions.get(t1) bloc = self.positions.get(t2) dcum = 0 # X ad = aloc[0] bd = bloc[0] #dcum += math.pow(abs(ad-bd), 2); dcum += (ad-bd)*(ad-bd) # Y ad = aloc[1] bd = bloc[1] #dcum += math.pow(abs(ad-bd), 2) dcum += (ad-bd)*(ad-bd) return math.sqrt(dcum); def _approach(self, t1, t2, ste): aloc = self.positions.get(t1) bloc = self.positions.get(t2) newloc = [0,0] # X ad = aloc[0] bd = bloc[0] ddist = ad-bd newd = ad-ddist*ste newloc[0] = newd # Y ad = aloc[1] bd = bloc[1] ddist = ad-bd newd = ad-ddist*ste newloc[1] = newd return newloc; def _normalize(self): gminx = 10000 gmaxx = -10000 gminy = 10000 gmaxy = -10000 for cords in self.positions.values(): if cords[0] < gminx: gminx = cords[0] if cords[0] > gmaxx: gmaxx = cords[0] if cords[1] < gminy: gminy = cords[1] if cords[1] > gmaxy: gmaxy = cords[1] koefx = 2*maxcoord/(gmaxx-gminx) koefy = 2*maxcoord/(gmaxy-gminy) centrx = (gmaxx+gminx)/2 centry = (gmaxy+gminy)/2 for k in self.positions.keys(): cords = self.positions.get(k) self.positions[k] = [(cords[0]-centrx)*koefx, (cords[1]-centry)*koefy] def _rotateBiggestToCorner(self): tool = self._biggestontovector() print "best tool:", tool p = self.positions.get(tool) angle = math.atan2(p[1], p[0]) cornerangle = math.pi*0.7 #print "rotating:", cornerangle-angle, math.degrees(cornerangle-angle), math.degrees(angle) self._rotateCoordinates(cornerangle-angle) def _biggestontovector(self): bignr = -1 toolid = "" for t in self._cached_ontovectors.keys(): afs = sum(self._cached_ontovectors[t].values()) if afs > bignr: bignr = afs toolid = t return toolid def _rotateCoordinates(self, angle): s = math.sin(angle) c = math.cos(angle) for k in self.positions.keys(): cords = self.positions.get(k) self.positions[k] = [c*cords[0]+s*cords[1], c*cords[1]-s*cords[0]]