def _GetLineCenterPoint(self, sp1, sp2): x = sp1.x / 2.0 + sp2.x / 2.0 y = sp1.y / 2.0 + sp2.y / 2.0 z = sp1.z / 2.0 + sp2.z / 2.0 sp = SurfacePoint(x, y, z) sp.SetRadius(1.0) return sp
def GetPickIntersectionPoint(x=None, y=None): """ Returns the point on the planet at (x, y) screen coordinates. This is done by casting a ray based on the screen coordinates (x, y) and the viewport and then finally calculating the intersection of that ray and a sphere (the planet). Method defaults to the current mouse coordinates if x and y arguments are None Returns None if the planet was not clicked. Arguments: x - the x coordinates in screen space y - the y coordinares in screen space """ if None in (x, y): x, y = int(uicore.uilib.x * uicore.desktop.dpiScaling), int( uicore.uilib.y * uicore.desktop.dpiScaling) device = trinity.device proj, view, vp = uix.GetFullscreenProjectionViewAndViewport() ray, start = device.GetPickRayFromViewport(x, y, vp, view.transform, proj.transform) lineVec = trinity.TriVector(*ray) lineP0 = trinity.TriVector(*start) sphereP0 = trinity.TriVector(0.0, 0.0, 0.0) sphereRad = 1000.0 pInt = GetSphereLineIntersectionPoint(lineP0, lineVec, sphereP0, sphereRad) if not pInt: return ret = SurfacePoint(pInt.x, pInt.y, pInt.z) ret.SetRadius(1.0) return ret
def ValidateMoveExtractorHead(self, pinID, headID, latitude, longitude): if self.colonyData is None: raise RuntimeError( 'Unable to validate extractor head movement - no colony data') if latitude < 0 or latitude > math.pi: raise RuntimeError( 'Invalid value for latitude - must be between 0..pi') if longitude < 0 or longitude > 2 * math.pi: raise RuntimeError( 'Invalid value for longitude - must be between 0..2pi') self.PreValidateMoveExtractorHead(pinID, headID, latitude, longitude) pin = self.GetPin(pinID) if not pin: raise UserError('PinDoesNotExist') if not pin.IsExtractor(): raise UserError('PinDoesNotHaveHeads') if pin.FindHead(headID) is None: raise UserError('CannotMoveHeadNotPresent') spA = SurfacePoint(theta=pin.longitude, phi=pin.latitude) spB = SurfacePoint(theta=longitude, phi=latitude) angleBetween = spA.GetAngleBetween(spB) areaOfInfluence = pin.GetAreaOfInfluence() if angleBetween > areaOfInfluence: raise UserError( 'CannotPlaceHeadTooFarAway', {'maxDist': util.FmtDist(angleBetween * self.planet.radius)}) self.PostValidateMoveExtractorHead(pinID, headID, latitude, longitude)
def _GetTriangleCenterPoint(self, sp1, sp2, sp3): x = sp1.x / 3.0 + sp2.x / 3.0 + sp3.x / 3.0 y = sp1.y / 3.0 + sp2.y / 3.0 + sp3.y / 3.0 z = sp1.z / 3.0 + sp2.z / 3.0 + sp3.z / 3.0 sp = SurfacePoint(x, y, z) sp.SetRadius(1.0) return sp
def ValidateAddExtractorHead(self, pinID, headID, latitude, longitude): if self.colonyData is None: raise RuntimeError('Unable to validate new extractor head - no colony data') if latitude < 0 or latitude > math.pi: raise RuntimeError('Invalid value for latitude - must be between 0..pi') if longitude < 0 or longitude > 2 * math.pi: raise RuntimeError('Invalid value for longitude - must be between 0..2pi') self.PreValidateAddExtractorHead(pinID, latitude, longitude) pin = self.GetPin(pinID) if not pin: raise UserError('PinDoesNotExist') if not pin.IsExtractor(): raise UserError('PinDoesNotHaveHeads') if pin.FindHead(headID) is not None: raise UserError('CannotAddHeadAlreadyExists') if len(pin.heads) >= ECU_MAX_HEADS: raise UserError('CannotPlaceHeadLimitReached') cpuDelta = pin.GetCpuUsage(numHeads=len(pin.heads) + 1) - pin.GetCpuUsage() powerDelta = pin.GetPowerUsage(numHeads=len(pin.heads) + 1) - pin.GetPowerUsage() if cpuDelta + self.colonyData.GetColonyCpuUsage() > self.colonyData.GetColonyCpuSupply(): raise UserError('CannotAddToColonyCPUUsageExceeded', {'typeName': (const.UE_LOC, 'UI/PI/Common/ExtractorHead')}) if powerDelta + self.colonyData.GetColonyPowerUsage() > self.colonyData.GetColonyPowerSupply(): raise UserError('CannotAddToColonyPowerUsageExceeded', {'typeName': (const.UE_LOC, 'UI/PI/Common/ExtractorHead')}) spA = SurfacePoint(radius=self.GetPlanetRadius(), theta=pin.longitude, phi=pin.latitude) spB = SurfacePoint(radius=self.GetPlanetRadius(), theta=longitude, phi=latitude) angleBetween = spA.GetAngleBetween(spB) areaOfInfluence = pin.GetAreaOfInfluence() if angleBetween > areaOfInfluence: raise UserError('CannotPlaceHeadTooFarAway', {'maxDist': util.FmtDist(areaOfInfluence * self.planet.radius)}) self.PostValidateAddExtractorHead(pinID, latitude, longitude)
def GetDistanceBetweenPins(pinA, pinB, planetRadius): spA = SurfacePoint(radius=planetRadius, theta=pinA.longitude, phi=pinA.latitude) spB = SurfacePoint(radius=planetRadius, theta=pinB.longitude, phi=pinB.latitude) return spA.GetDistanceToOther(spB)
def _GetLinkWeight(self, link, pinA, pinB): """ Right now, it uses the spherical distance between two points as its weight metric. """ spA = SurfacePoint(radius=1.0, theta=pinA.longitude, phi=pinA.latitude) spB = SurfacePoint(radius=1.0, theta=pinB.longitude, phi=pinB.latitude) return spA.GetDistanceToOther(spB)
def RenderPin(self, pin): if pin.id in self.pinsByID: self.pinsByID[pin.id].Remove() surfacePoint = SurfacePoint(phi=pin.latitude, theta=pin.longitude) pinClass = self.GetPinGraphicsClassForType(pin.typeID) UIpin = pinClass(surfacePoint, pin, self.planetUISvc.pinTransform) self.pinsByID[pin.id] = UIpin return UIpin
def GetPickIntersectionPoint(x=None, y=None): if None in (x, y): x, y = int(uicore.uilib.x * uicore.desktop.dpiScaling), int( uicore.uilib.y * uicore.desktop.dpiScaling) device = trinity.device proj, view, vp = uix.GetFullscreenProjectionViewAndViewport() ray, start = device.GetPickRayFromViewport(x, y, vp, view.transform, proj.transform) lineVec = trinity.TriVector(*ray) lineP0 = trinity.TriVector(*start) sphereP0 = trinity.TriVector(0.0, 0.0, 0.0) sphereRad = 1000.0 pInt = GetSphereLineIntersectionPoint(lineP0, lineVec, sphereP0, sphereRad) if not pInt: return ret = SurfacePoint(pInt.x, pInt.y, pInt.z) ret.SetRadius(1.0) return ret
def PlacePinOnNextClick(self, pinTypeID): self.eventManager.SetStateBuildPin() self._RemoveBuildIndicatorPin() self.newPinType = pinTypeID typeObj = cfg.invtypes.Get(pinTypeID) self.buildIndicatorPin = BuildIndicatorPin( SurfacePoint(), pinTypeID, typeObj.groupID, self.planetUISvc.pinOthersTransform) if typeObj.groupID == const.groupExtractionControlUnitPins: self.DisplayECUExtractionAreas(show=True)
def OnPlanetViewOpened(self): self.planetUISvc = sm.GetService('planetUI') self.eventManager = self.planetUISvc.eventManager sp = SurfacePoint() rubberColor = (1.0, 1.0, 1.0, 1.0) self.rubberLink = self.planetUISvc.curveLineDrawer.DrawArc( 'rubberLink', sp, sp, 2.0, rubberColor, rubberColor) self.InitRubberLinkLabels() self.ReRender() self.depletionPoints = [] self.bracketCurveSet.Play()
def AddLink(self, parentID, childID, linkTypeID): colony = self.planetUISvc.planet.GetColony(session.charid) if colony is None: log.LogError('Unable to render link for planet without a colony') return par = colony.GetPin(parentID) child = colony.GetPin(childID) if par is None or child is None: log.LogWarn('Trying to render link for non-existing pin', parentID, childID) return p1 = SurfacePoint(theta=par.longitude, phi=par.latitude) p2 = SurfacePoint(theta=child.longitude, phi=child.latitude) planetLink = colony.colonyData.GetLink(parentID, childID) link = Link(p1, p2, parentID, childID, linkTypeID, planetLink) self.linksByPinIDs[parentID, childID] = link self.linksByPinIDs[childID, parentID] = link self.links.append(link) linkGraphicID1, linkGraphicID2 = link.GetGraphicIDs() self.linksByGraphicID[linkGraphicID1] = link self.linksByGraphicID[linkGraphicID2] = link
def _SplitTriangle(self, v0, v1, v2, lines, cLines, hLines, sps, level): level -= 1 lc0 = self._GetLineCenterPoint(v0, v1) lc1 = self._GetLineCenterPoint(v1, v2) lc2 = self._GetLineCenterPoint(v2, v0) tc = self._GetTriangleCenterPoint(v0, v1, v2) if level > 0: self._SplitTriangle(v0, lc0, lc2, lines, cLines, hLines, sps, level) self._SplitTriangle(v1, lc1, lc0, lines, cLines, hLines, sps, level) self._SplitTriangle(v2, lc2, lc1, lines, cLines, hLines, sps, level) self._SplitTriangle(lc0, lc1, lc2, lines, cLines, hLines, sps, level) else: v = geo2.Vector vecC = v(*tc.GetAsXYZTuple()) vec0 = v(*v0.GetAsXYZTuple()) vec1 = v(*v0.GetAsXYZTuple()) vec2 = v(*v0.GetAsXYZTuple()) vec01 = v(*(v1.x - v0.x, v1.y - v0.y, v1.z - v0.z)) n0 = v(*geo2.Vec3Cross(vecC, vec01)) vec12 = v(*(v2.x - v1.x, v2.y - v1.y, v2.z - v1.z)) n1 = v(*geo2.Vec3Cross(vecC, vec12)) vec20 = v(*(v0.x - v2.x, v0.y - v2.y, v0.z - v2.z)) n2 = v(*geo2.Vec3Cross(vecC, vec20)) s = 0.16 sGap = 0.1 n0 = v(*(s * n0)) n1 = v(*(s * n1)) n2 = v(*(s * n2)) lp0 = SurfacePoint(*(vecC - n0)) lp1 = SurfacePoint(*(vecC - n1)) lp2 = SurfacePoint(*(vecC - n2)) lr0 = SurfacePoint(*(vecC - v(*(sGap * n0)))) lr1 = SurfacePoint(*(vecC - v(*(sGap * n1)))) lr2 = SurfacePoint(*(vecC - v(*(sGap * n2)))) lp0.SetRadius(1.0) lp1.SetRadius(1.0) lp2.SetRadius(1.0) lr0.SetRadius(1.0) lr1.SetRadius(1.0) lr2.SetRadius(1.0) lines.add((lr0, lp0)) lines.add((lr1, lp1)) lines.add((lr2, lp2))
def _DrawMesh(self, lsName, numPhi=30, numTheta=60, phiSkip=0, lineWidth=2.0, col=(1.0, 1.0, 1.0, 0.01)): col = (0.8, 0.8, 1.0, 0.3) colAnim = (1.0, 1.0, 1.0, 1.0) speedAnim = 0.06 scaleAnim = 2.0 phi0 = math.pi / 90 phiStep = (math.pi - 2 * phi0) / numPhi phiInit = phi0 + phiStep * phiSkip ls = self.GetLineSet(lsName) for p in xrange(numPhi + 1): if p <= phiSkip - 1 or p > numPhi - phiSkip: continue phi = phi0 + float(p) * phiStep for quarter in xrange(0, 4): th0 = math.pi / 2 * quarter p1 = SurfacePoint(theta=th0, phi=phi) p2 = SurfacePoint(theta=th0 + math.pi / 2, phi=phi) pC = SurfacePoint(0.0, p1.y, 0.0) lineID = ls.AddSpheredLineCrt(p1.GetAsXYZTuple(), col, p2.GetAsXYZTuple(), col, pC.GetAsXYZTuple(), lineWidth) ls.ChangeLineAnimation(lineID, colAnim, speedAnim, scaleAnim) for t in xrange(numTheta): th = float(t) / numTheta * math.pi * 2 p1 = SurfacePoint(theta=th, phi=math.pi / 2.0) p2 = SurfacePoint(theta=th, phi=phiInit) lineID = ls.AddSpheredLineCrt(p1.GetAsXYZTuple(), col, p2.GetAsXYZTuple(), col, self.p0, lineWidth) ls.ChangeLineAnimation(lineID, colAnim, speedAnim, scaleAnim) p2 = SurfacePoint(theta=th, phi=math.pi - phiInit) lineID = ls.AddSpheredLineCrt(p1.GetAsXYZTuple(), col, p2.GetAsXYZTuple(), col, self.p0, lineWidth) ls.ChangeLineAnimation(lineID, colAnim, speedAnim, scaleAnim) ls.SubmitChanges()
def CreateOrbitCircle(self, orbitem, parent, lineSet, points=256): orbitPos = geo2.Vector(*orbitem.translation) parentPos = geo2.Vector(*parent.translation) dirVec = orbitPos - parentPos radius = geo2.Vec3Length(dirVec) if radius == 0: return lineColor = (1, 1, 1, 0.1) dx, dy, dz = dirVec fromPoint = SurfacePoint(dx, dy, dz) radius, theta, phi = fromPoint.GetAsRadThPhiTuple() toPoint = SurfacePoint(theta=theta + math.pi * 0.5, phi=phi) x, y, z = toPoint.GetAsXYZTuple() line1 = lineSet.AddSpheredLineCrt(fromPoint.GetAsXYZTuple(), lineColor, (x, y, z), lineColor, parentPos, 3.0) line2 = lineSet.AddSpheredLineCrt(fromPoint.GetAsXYZTuple(), lineColor, (-x, -y, -z), lineColor, parentPos, 3.0) fromPoint = SurfacePoint(-dx, -dy, -dz) radius, theta, phi = fromPoint.GetAsRadThPhiTuple() toPoint = SurfacePoint(theta=theta + math.pi * 0.5, phi=phi) x, y, z = toPoint.GetAsXYZTuple() line3 = lineSet.AddSpheredLineCrt(fromPoint.GetAsXYZTuple(), lineColor, (x, y, z), lineColor, parentPos, 3.0) line4 = lineSet.AddSpheredLineCrt(fromPoint.GetAsXYZTuple(), lineColor, (-x, -y, -z), lineColor, parentPos, 3.0) lineSet.ChangeLineSegmentation(line1, 25) lineSet.ChangeLineSegmentation(line2, 25) lineSet.ChangeLineSegmentation(line3, 25) lineSet.ChangeLineSegmentation(line4, 25) animationColor = (0, 0, 0, 0.5) lineSet.ChangeLineAnimation(line1, animationColor, 0.1, 0.5) lineSet.ChangeLineAnimation(line2, animationColor, -0.1, 0.5) lineSet.ChangeLineAnimation(line3, animationColor, 0.1, 0.5) lineSet.ChangeLineAnimation(line4, animationColor, -0.1, 0.5)
def CreateProgram(self, harmonic, ecuPinID, resourceTypeID, points=None, headRadius=None): ecuPin = self.GetPin(ecuPinID) if points is None: points = ecuPin.heads if headRadius is None: headRadius = ecuPin.GetExtractorHeadRadius() overlapFactor = self.GetTypeAttribute(ecuPin.typeID, const.attributeEcuOverlapFactor) maxVolume = self.GetTypeAttribute(ecuPin.typeID, const.attributeEcuMaxVolume) overlapModifiers = {} heads = [] for index, longitude, latitude in points: heads.append((index, SurfacePoint(theta=latitude, phi=longitude))) overlapModifiers[index] = 1.0 distance = {} valueByIndex = {} for index, surfacePoint in heads: theta = 2.0 * math.pi - surfacePoint.theta phi = surfacePoint.phi valueByIndex[index] = max(builder.GetValueAt(harmonic, theta, phi), 0) for index2, surfacePoint2 in heads: if index == index2: continue key = tuple(sorted([index, index2])) if key not in distance: distance[key] = surfacePoint.GetDistanceToOther( surfacePoint2) with bluepy.TimerPush('OverlapOwnHeads'): for (head1, head2), dist in distance.iteritems(): if dist < headRadius * 2: radiusSquared = headRadius**2 overlap = ( 2 * radiusSquared * math.acos(0.5 * (dist / headRadius)) - 0.5 * dist * math.sqrt(4 * radiusSquared - dist**2) ) / (math.pi * radiusSquared) modifier = min(1, max(0, 1 - overlap * overlapFactor)) valueByIndex[head1] *= modifier valueByIndex[head2] *= modifier overlapModifiers[head1] *= modifier overlapModifiers[head2] *= modifier with bluepy.TimerPush('OverlapOthersHeads'): otherHeadsInfo = [] for pin in self.colonyData.GetECUs(ecuPinID): if pin.programType != resourceTypeID: continue otherHeadsInfo.append( (pin.GetExtractorHeadRadius(), pin.heads)) headArea = math.pi * headRadius**2 for index, surfacePoint1 in heads: modifier = 1 for otherHeadRadius, otherHeads in otherHeadsInfo: if modifier == 0: break for index2, longitude2, latitude2 in otherHeads: surfacePoint2 = SurfacePoint(theta=latitude2, phi=longitude2) d, R, r = surfacePoint1.GetDistanceToOther( surfacePoint2), headRadius, otherHeadRadius if d > R + r: continue r2, R2, d2 = r**2, R**2, d**2 alpha = (d2 + r2 - R2) / (2 * d * r) if alpha < -1: overlap = math.pi * r2 / headArea elif alpha > 1: overlap = 1 else: f1 = r**2 * math.acos(alpha) f2 = R**2 * math.acos( (d**2 + R**2 - r**2) / (2 * d * R)) f3 = 0.5 * math.sqrt((-d + r + R) * (d + r - R) * (d - r + R) * (d + r + R)) A = f1 + f2 - f3 overlap = A / headArea modifier *= min( 1, max(0, 1 - overlap * 2 * overlapFactor)) valueByIndex[index] *= modifier overlapModifiers[index] *= modifier for index, modifier in overlapModifiers.iteritems(): overlapModifiers[index] = 1.0 - modifier maxValue = maxVolume * sum(valueByIndex.values()) programLength = GetProgramLengthFromHeadRadius(headRadius) cycleTime = GetCycleTimeFromProgramLength(programLength) numCycles = int(programLength / cycleTime) cycleTime = int(cycleTime * const.HOUR) return (int(maxValue), cycleTime, numCycles, overlapModifiers)
def _GetLinkWeight(self, link, pinA, pinB): spA = SurfacePoint(radius=1.0, theta=pinA.longitude, phi=pinA.latitude) spB = SurfacePoint(radius=1.0, theta=pinB.longitude, phi=pinB.latitude) return spA.GetDistanceToOther(spB)