def loadMap(self, mapLocation): with open(mapLocation) as file: mapObjList = json.load(file) for item in mapObjList["objects"]: if (item["type"] == "rect"): shape = QGraphicsRectItem(item["centerX"] - item["length"] / 2, -item["centerY"] - item["width"] / 2, item["length"], item["width"]) shape.setTransformOriginPoint( QPoint(item["centerX"], -item["centerY"])) shape.setPen(QPen(self.black)) shape.setBrush(QBrush(self.black, Qt.SolidPattern)) shape.setRotation(item["rotation"]) self.scene.addItem(shape) elif (item["type"] == "text"): label = QGraphicsTextItem(item["text"]) label.setX(item["centerX"] - item["length"] / 2) label.setY(-item["centerY"] - item["width"] / 2) font = QFont("Bavaria") font.setPointSize(24) font.setWeight(QFont.Bold) label.setFont(font) label.setRotation(item["rotation"]) self.RoomNameList.append(label) self.scene.addItem(label) elif (item["type"] == "obstacle"): shape = QGraphicsRectItem(item["centerX"] - item["length"] / 2, -item["centerY"] - item["width"] / 2, item["length"], item["width"]) shape.setTransformOriginPoint( QPoint(item["centerX"], -item["centerY"])) shape.setPen(QPen(self.gray)) shape.setBrush(QBrush(self.gray, Qt.SolidPattern)) shape.setRotation(item["rotation"]) self.ObstacleList.append(shape) elif (item["type"] == "plant"): shape = QGraphicsEllipseItem( item["centerX"] - item["length"] / 2, -item["centerY"] - item["width"] / 2, item["length"], item["width"]) shape.setTransformOriginPoint( QPoint(item["centerX"], -item["centerY"])) shape.setPen(QPen(self.green)) shape.setBrush(QBrush(self.green, Qt.SolidPattern)) shape.setRotation(item["rotation"]) self.ObstacleList.append(shape) self.SupervisorMap.scale(self.scaleFactor, self.scaleFactor)
class BlockItem(QGraphicsPixmapItem): def __init__(self, trnsysType, parent, **kwargs): super().__init__(None) self.logger = parent.logger self.w = 120 self.h = 120 self.parent = parent self.id = self.parent.parent().idGen.getID() self.propertyFile = [] if "displayName" in kwargs: self.displayName = kwargs["displayName"] else: self.displayName = trnsysType + "_" + str(self.id) if "loadedBlock" not in kwargs: self.parent.parent().trnsysObj.append(self) self.inputs = [] self.outputs = [] # Export related: self.name = trnsysType self.trnsysId = self.parent.parent().idGen.getTrnsysID() # Transform related self.flippedV = False self.flippedH = False self.rotationN = 0 self.flippedHInt = -1 self.flippedVInt = -1 pixmap = self._getPixmap() self.setPixmap(pixmap) # To set flags of this item self.setFlags(self.ItemIsSelectable | self.ItemIsMovable) self.setFlag(self.ItemSendsScenePositionChanges, True) self.setCursor(QCursor(QtCore.Qt.PointingHandCursor)) self.label = QGraphicsTextItem(self.displayName, self) self.label.setVisible(False) if self.name == "Bvi": self.inputs.append(_cspi.createSinglePipePortItem("i", 0, self)) self.outputs.append(_cspi.createSinglePipePortItem("o", 2, self)) if self.name == "StorageTank": # Inputs get appended in ConfigStorage pass self.logger.debug("Block name is " + str(self.name)) # Update size for generic block: if self.name == "Bvi": self.changeSize() # Experimental, used for detecting genereated blocks attached to storage ports self.inFirstRow = False # Undo framework related self.oldPos = None self.origOutputsPos = None self.origInputsPos = None def _getImageAccessor(self) -> _tp.Optional[_img.ImageAccessor]: if type(self) == BlockItem: raise AssertionError( "`BlockItem' cannot be instantiated directly.") currentClassName = BlockItem.__name__ currentMethodName = f"{currentClassName}.{BlockItem._getImageAccessor.__name__}" message = ( f"{currentMethodName} has been called. However, this method should not be called directly but must\n" f"implemented in a child class. This means that a) someone instantiated `{currentClassName}` directly\n" f"or b) a child class of it doesn't implement `{currentMethodName}`. Either way that's an\n" f"unrecoverable error and therefore the program will be terminated now. Please do get in touch with\n" f"the developers if you've encountered this error. Thanks.") exception = AssertionError(message) # I've seen exception messages mysteriously swallowed that's why we're logging the message here, too. self.logger.error(message, exc_info=exception, stack_info=True) raise exception def addTree(self): pass # Setter functions def setParent(self, p): self.parent = p if self not in self.parent.parent().trnsysObj: self.parent.parent().trnsysObj.append(self) # self.logger.debug("trnsysObj are " + str(self.parent.parent().trnsysObj)) def setId(self, newId): self.id = newId def setName(self, newName): self.displayName = newName self.label.setPlainText(newName) # Interaction related def contextMenuEvent(self, event): menu = QMenu() a1 = menu.addAction("Launch NotePad++") a1.triggered.connect(self.launchNotepadFile) rr = _img.ROTATE_TO_RIGHT_PNG.icon() a2 = menu.addAction(rr, "Rotate Block clockwise") a2.triggered.connect(self.rotateBlockCW) ll = _img.ROTATE_LEFT_PNG.icon() a3 = menu.addAction(ll, "Rotate Block counter-clockwise") a3.triggered.connect(self.rotateBlockCCW) a4 = menu.addAction("Reset Rotation") a4.triggered.connect(self.resetRotation) b1 = menu.addAction("Print Rotation") b1.triggered.connect(self.printRotation) c1 = menu.addAction("Delete this Block") c1.triggered.connect(self.deleteBlockCom) menu.exec_(event.screenPos()) def launchNotepadFile(self): self.logger.debug("Launching notpad") global FilePath os.system("start notepad++ " + FilePath) def mouseDoubleClickEvent(self, event): if hasattr(self, "isTempering"): self.parent.parent().showTVentilDlg(self) elif self.name == "Pump": self.parent.parent().showPumpDlg(self) elif self.name == "TeePiece" or self.name == "WTap_main": self.parent.parent().showBlockDlg(self) elif self.name in ["SPCnr", "DPCnr", "DPTee"]: self.parent.parent().showDoublePipeBlockDlg(self) else: self.parent.parent().showBlockDlg(self) if len(self.propertyFile) > 0: for files in self.propertyFile: os.startfile(files, "open") def mouseReleaseEvent(self, event): # self.logger.debug("Released mouse over block") if self.oldPos is None: self.logger.debug("For Undo Framework: oldPos is None") else: if self.scenePos() != self.oldPos: self.logger.debug("Block was dragged") self.logger.debug("Old pos is" + str(self.oldPos)) command = MoveCommand(self, self.oldPos, "Move BlockItem") self.parent.parent().parent().undoStack.push(command) self.oldPos = self.scenePos() super(BlockItem, self).mouseReleaseEvent(event) # Transform related def changeSize(self): self._positionLabel() w, h = self._getCappedWithAndHeight() if self.name == "Bvi": delta = 4 self.inputs[0].setPos( -2 * delta + 4 * self.flippedH * delta + self.flippedH * w, h / 3) self.outputs[0].setPos( -2 * delta + 4 * self.flippedH * delta + self.flippedH * w, 2 * h / 3) self.inputs[0].side = 0 + 2 * self.flippedH self.outputs[0].side = 0 + 2 * self.flippedH def _positionLabel(self): width, height = self._getCappedWithAndHeight() rect = self.label.boundingRect() labelWidth, lableHeight = rect.width(), rect.height() labelPosX = (height - labelWidth) / 2 self.label.setPos(labelPosX, width) def _getCappedWithAndHeight(self): width = self.w height = self.h if height < 20: height = 20 if width < 40: width = 40 return width, height def updateFlipStateH(self, state): self.flippedH = bool(state) pixmap = self._getPixmap() self.setPixmap(pixmap) self.flippedHInt = 1 if self.flippedH else -1 if self.flippedH: for i in range(0, len(self.inputs)): distanceToMirrorAxis = self.w / 2.0 - self.origInputsPos[i][0] self.inputs[i].setPos( self.origInputsPos[i][0] + 2.0 * distanceToMirrorAxis, self.inputs[i].pos().y(), ) for i in range(0, len(self.outputs)): distanceToMirrorAxis = self.w / 2.0 - self.origOutputsPos[i][0] self.outputs[i].setPos( self.origOutputsPos[i][0] + 2.0 * distanceToMirrorAxis, self.outputs[i].pos().y(), ) else: for i in range(0, len(self.inputs)): self.inputs[i].setPos(self.origInputsPos[i][0], self.inputs[i].pos().y()) for i in range(0, len(self.outputs)): self.outputs[i].setPos(self.origOutputsPos[i][0], self.outputs[i].pos().y()) def updateFlipStateV(self, state): self.flippedV = bool(state) pixmap = self._getPixmap() self.setPixmap(pixmap) self.flippedVInt = 1 if self.flippedV else -1 if self.flippedV: for i in range(0, len(self.inputs)): distanceToMirrorAxis = self.h / 2.0 - self.origInputsPos[i][1] self.inputs[i].setPos( self.inputs[i].pos().x(), self.origInputsPos[i][1] + 2.0 * distanceToMirrorAxis, ) for i in range(0, len(self.outputs)): distanceToMirrorAxis = self.h / 2.0 - self.origOutputsPos[i][1] self.outputs[i].setPos( self.outputs[i].pos().x(), self.origOutputsPos[i][1] + 2.0 * distanceToMirrorAxis, ) else: for i in range(0, len(self.inputs)): self.inputs[i].setPos(self.inputs[i].pos().x(), self.origInputsPos[i][1]) for i in range(0, len(self.outputs)): self.outputs[i].setPos(self.outputs[i].pos().x(), self.origOutputsPos[i][1]) def updateSidesFlippedH(self): if self.rotationN % 2 == 0: for p in self.inputs: if p.side == 0 or p.side == 2: self.updateSide(p, 2) for p in self.outputs: if p.side == 0 or p.side == 2: self.updateSide(p, 2) if self.rotationN % 2 == 1: for p in self.inputs: if p.side == 1 or p.side == 3: self.updateSide(p, 2) for p in self.outputs: if p.side == 1 or p.side == 3: self.updateSide(p, 2) def updateSidesFlippedV(self): if self.rotationN % 2 == 1: for p in self.inputs: if p.side == 0 or p.side == 2: self.updateSide(p, 2) for p in self.outputs: if p.side == 0 or p.side == 2: self.updateSide(p, 2) if self.rotationN % 2 == 0: for p in self.inputs: if p.side == 1 or p.side == 3: self.updateSide(p, 2) for p in self.outputs: if p.side == 1 or p.side == 3: self.updateSide(p, 2) def updateSide(self, port, n): port.side = (port.side + n) % 4 # self.logger.debug("Port side is " + str(port.side)) def rotateBlockCW(self): # Rotate block clockwise # self.setTransformOriginPoint(50, 50) # self.setTransformOriginPoint(self.w/2, self.h/2) self.setTransformOriginPoint(0, 0) self.setRotation((self.rotationN + 1) * 90) self.label.setRotation(-(self.rotationN + 1) * 90) self.rotationN += 1 self.logger.debug("rotated by " + str(self.rotationN)) for p in self.inputs: p.itemChange(27, p.scenePos()) self.updateSide(p, 1) for p in self.outputs: p.itemChange(27, p.scenePos()) self.updateSide(p, 1) pixmap = self._getPixmap() self.setPixmap(pixmap) def rotateBlockToN(self, n): if n > 0: while self.rotationN != n: self.rotateBlockCW() if n < 0: while self.rotationN != n: self.rotateBlockCCW() def rotateBlockCCW(self): # Rotate block clockwise # self.setTransformOriginPoint(50, 50) self.setTransformOriginPoint(0, 0) self.setRotation((self.rotationN - 1) * 90) self.label.setRotation(-(self.rotationN - 1) * 90) self.rotationN -= 1 self.logger.debug("rotated by " + str(self.rotationN)) for p in self.inputs: p.itemChange(27, p.scenePos()) self.updateSide(p, -1) for p in self.outputs: p.itemChange(27, p.scenePos()) self.updateSide(p, -1) pixmap = self._getPixmap() self.setPixmap(pixmap) def resetRotation(self): self.logger.debug("Resetting rotation...") self.setRotation(0) self.label.setRotation(0) for p in self.inputs: p.itemChange(27, p.scenePos()) self.updateSide(p, -self.rotationN) # self.logger.debug("Portside of port " + str(p) + " is " + str(p.portSide)) for p in self.outputs: p.itemChange(27, p.scenePos()) self.updateSide(p, -self.rotationN) # self.logger.debug("Portside of port " + str(p) + " is " + str(p.portSide)) self.rotationN = 0 pixmap = self._getPixmap() self.setPixmap(pixmap) def printRotation(self): self.logger.debug("Rotation is " + str(self.rotationN)) # Deletion related def deleteConns(self): for p in self.inputs: while len(p.connectionList) > 0: p.connectionList[0].deleteConn() for p in self.outputs: while len(p.connectionList) > 0: p.connectionList[0].deleteConn() def deleteBlock(self): self.parent.parent().trnsysObj.remove(self) self.parent.scene().removeItem(self) widgetToRemove = self.parent.parent().findChild( QTreeView, self.displayName + "Tree") if widgetToRemove: widgetToRemove.hide() def deleteBlockCom(self): self.parent.deleteBlockCom(self) def getConnections(self): """ Get the connections from inputs and outputs of this block. Returns ------- c : :obj:`List` of :obj:`BlockItem` """ c = [] for i in self.inputs: for cl in i.connectionList: c.append(cl) for o in self.outputs: for cl in o.connectionList: c.append(cl) return c # Scaling related def mousePressEvent(self, event): # create resizer """ Using try catch to avoid creating extra resizers. When an item is clicked on, it will check if a resizer already existed. If there exist a resizer, returns. else, creates one. Resizer will not be created for GenericBlock due to complications in the code. Resizer will not be created for storageTank as there's already a built in function for it in the storageTank dialog. Resizers are deleted inside mousePressEvent function inside GUI.py """ self.logger.debug("Inside Block Item mouse click") self.isSelected = True if self.name == "GenericBlock" or self.name == "StorageTank": return try: self.resizer except AttributeError: self.resizer = ResizerItem(self) self.resizer.setPos(self.w, self.h) self.resizer.itemChange(self.resizer.ItemPositionChange, self.resizer.pos()) else: return def setItemSize(self, w, h): self.logger.debug("Inside block item set item size") self.w, self.h = w, h # if h < 20: # self.h = 20 # if w < 40: # self.w = 40 def updateImage(self): self.logger.debug("Inside block item update image") pixmap = self._getPixmap() self.setPixmap(pixmap) if self.flippedH: self.updateFlipStateH(self.flippedH) if self.flippedV: self.updateFlipStateV(self.flippedV) def _getPixmap(self) -> QPixmap: imageAccessor = self._getImageAccessor() image = imageAccessor.image(width=self.w, height=self.h).mirrored( horizontal=self.flippedH, vertical=self.flippedV) pixmap = QPixmap(image) return pixmap def deleteResizer(self): try: self.resizer except AttributeError: self.logger.debug("No resizer") else: del self.resizer # AlignMode related def itemChange(self, change, value): # self.logger.debug(change, value) # Snap grid excludes alignment if change == self.ItemPositionChange: if self.parent.parent().snapGrid: snapSize = self.parent.parent().snapSize self.logger.debug("itemchange") self.logger.debug(type(value)) value = QPointF(value.x() - value.x() % snapSize, value.y() - value.y() % snapSize) return value else: # if self.hasElementsInYBand() and not self.elementInY() and not self.aligned: if self.parent.parent().alignMode: if self.hasElementsInYBand(): return self.alignBlock(value) else: # self.aligned = False return value else: return value else: return super(BlockItem, self).itemChange(change, value) def alignBlock(self, value): for t in self.parent.parent().trnsysObj: if isinstance(t, BlockItem) and t is not self: if self.elementInYBand(t): value = QPointF(self.pos().x(), t.pos().y()) self.parent.parent().alignYLineItem.setLine( self.pos().x() + self.w / 2, t.pos().y(), t.pos().x() + t.w / 2, t.pos().y()) self.parent.parent().alignYLineItem.setVisible(True) qtm = QTimer(self.parent.parent()) qtm.timeout.connect(self.timerfunc) qtm.setSingleShot(True) qtm.start(1000) e = QMouseEvent( QEvent.MouseButtonRelease, self.pos(), QtCore.Qt.NoButton, QtCore.Qt.NoButton, QtCore.Qt.NoModifier, ) self.parent.mouseReleaseEvent(e) self.parent.parent().alignMode = False # self.setPos(self.pos().x(), t.pos().y()) # self.aligned = True if self.elementInXBand(t): value = QPointF(t.pos().x(), self.pos().y()) self.parent.parent().alignXLineItem.setLine( t.pos().x(), t.pos().y() + self.w / 2, t.pos().x(), self.pos().y() + t.w / 2) self.parent.parent().alignXLineItem.setVisible(True) qtm = QTimer(self.parent.parent()) qtm.timeout.connect(self.timerfunc2) qtm.setSingleShot(True) qtm.start(1000) e = QMouseEvent( QEvent.MouseButtonRelease, self.pos(), QtCore.Qt.NoButton, QtCore.Qt.NoButton, QtCore.Qt.NoModifier, ) self.parent.mouseReleaseEvent(e) self.parent.parent().alignMode = False return value def timerfunc(self): self.parent.parent().alignYLineItem.setVisible(False) def timerfunc2(self): self.parent.parent().alignXLineItem.setVisible(False) def hasElementsInYBand(self): for t in self.parent.parent().trnsysObj: if isinstance(t, BlockItem): if self.elementInYBand(t): return True return False def hasElementsInXBand(self): for t in self.parent.parent().trnsysObj: if isinstance(t, BlockItem): if self.elementInXBand(t): return True return False def elementInYBand(self, t): eps = 50 return self.scenePos().y() - eps <= t.scenePos().y( ) <= self.scenePos().y() + eps def elementInXBand(self, t): eps = 50 return self.scenePos().x() - eps <= t.scenePos().x( ) <= self.scenePos().x() + eps def elementInY(self): for t in self.parent.parent().trnsysObj: if isinstance(t, BlockItem): if self.scenePos().y == t.scenePos().y(): return True return False def encode(self): portListInputs = [] portListOutputs = [] for inp in self.inputs: portListInputs.append(inp.id) for output in self.outputs: portListOutputs.append(output.id) blockPosition = (float(self.pos().x()), float(self.pos().y())) blockItemModel = BlockItemModel( self.name, self.displayName, blockPosition, self.id, self.trnsysId, portListInputs, portListOutputs, self.flippedH, self.flippedV, self.rotationN, ) dictName = "Block-" return dictName, blockItemModel.to_dict() def decode(self, i, resBlockList): model = BlockItemModel.from_dict(i) self.setName(model.BlockDisplayName) self.setPos(float(model.blockPosition[0]), float(model.blockPosition[1])) self.id = model.Id self.trnsysId = model.trnsysId if len(self.inputs) != len(model.portsIdsIn) or len( self.outputs) != len(model.portsIdsOut): temp = model.portsIdsIn model.portsIdsIn = model.portsIdsOut model.portsIdsOut = temp for index, inp in enumerate(self.inputs): inp.id = model.portsIdsIn[index] for index, out in enumerate(self.outputs): out.id = model.portsIdsOut[index] self.updateFlipStateH(model.flippedH) self.updateFlipStateV(model.flippedV) self.rotateBlockToN(model.rotationN) resBlockList.append(self) def decodePaste(self, i, offset_x, offset_y, resConnList, resBlockList, **kwargs): self.setPos( float(i["BlockPosition"][0] + offset_x), float(i["BlockPosition"][1] + offset_y), ) self.updateFlipStateH(i["FlippedH"]) self.updateFlipStateV(i["FlippedV"]) self.rotateBlockToN(i["RotationN"]) for x in range(len(self.inputs)): self.inputs[x].id = i["PortsIDIn"][x] for x in range(len(self.outputs)): self.outputs[x].id = i["PortsIDOut"][x] resBlockList.append(self) # Export related def exportBlackBox(self): equation = [] if (len(self.inputs + self.outputs) == 2 and self.isVisible() and not isinstance(self.outputs[0], DoublePipePortItem)): files = glob.glob(os.path.join(self.path, "**/*.ddck"), recursive=True) if not (files): status = "noDdckFile" else: status = "noDdckEntry" lines = [] for file in files: infile = open(file, "r") lines += infile.readlines() for i in range(len(lines)): if "output" in lines[i].lower() and "to" in lines[i].lower( ) and "hydraulic" in lines[i].lower(): for j in range(i, len(lines) - i): if lines[j][0] == "T": outputT = lines[j].split("=")[0].replace(" ", "") status = "success" break equation = ["T" + self.displayName + "=" + outputT] break else: status = "noBlackBoxOutput" if status == "noDdckFile" or status == "noDdckEntry": equation.append("T" + self.displayName + "=1") return status, equation def exportPumpOutlets(self): return "", 0 def exportMassFlows(self): return "", 0 def exportDivSetting1(self): return "", 0 def exportDivSetting2(self, nUnit): return "", nUnit def exportPipeAndTeeTypesForTemp(self, startingUnit): return "", startingUnit def getTemperatureVariableName(self, portItem: SinglePipePortItem) -> str: return f"T{self.displayName}" def getFlowSolverParametersId(self, portItem: SinglePipePortItem) -> int: return self.trnsysId def assignIDsToUninitializedValuesAfterJsonFormatMigration( self, generator: _id.IdGenerator) -> None: pass def deleteLoadedFile(self): for items in self.loadedFiles: try: self.parent.parent().fileList.remove(str(items)) except ValueError: self.logger.debug("File already deleted from file list.") self.logger.debug("filelist:", self.parent.parent().fileList)
def __init__(self, radius=200, parent=None, categories=[], loglevel=logging.DEBUG): super(WheelScene, self).__init__(parent) self.logger = logs.build_logger(__name__, loglevel) self.loglevel = loglevel #super(TestWheelScene, self).__init__(parent) families = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] if len(categories) == 0: sector_names = [ "freespin", "bankruptcy", "dogs", "cats", "PC", "OP", "loseturn", "colors", "numbers", "states", "countries", "people" ] else: sector_names = categories self.radius = radius total = 0 set_angle = 0 count1 = 0 colours = [] total = sum(families) for count in range(len(families)): number = [] for count in range(3): number.append(random.randrange(0, 255)) colours.append(QColor(number[0], number[1], number[2])) for i, family in enumerate(families): # Max span is 5760, so we have to calculate corresponding span angle angle = round(float(family * 5760) / total) subangle = round(float((family * 5760) / total / 2)) subangle += 120 # ellipse = QGraphicsEllipseItem(0,0,400,400) ellipse = QGraphicsEllipseItem(0, 0, self.radius * 2, self.radius * 2) #ellipse.setPos(QPointF(0, 0)) # ellipse.setPos(ellipse.boundingRect().center()) #print(ellipse.rect().center()) #ellipse.setTransformOriginPoint(200, 200) # ellipse.setRect(-200,200,400,400) ellipse.setStartAngle(set_angle) ellipse.setSpanAngle(angle) ellipse.setBrush(colours[count1]) # https://stackoverflow.com/questions/3312016/text-in-a-qgraphicsscene text = QGraphicsTextItem() #text.setFont(QFont("Helvetica", 65)) #text.setTextWidth(20) # print("angle=%s, set_angle=%s, sector_name=%s" % (angle, set_angle, sector_names[i])) document = QtGui.QTextDocument() document.setDocumentMargin(0) text.setDocument(document) self.font = QFont() self.default_font_size = 14 self.font.setPointSize(self.default_font_size) self.font.setBold(True) self.font.setFamily("Helvetica") self.font.setCapitalization(True) text.setPlainText(textwrap.fill(sector_names[i], width=1)) text.setFont(self.font) # print("render_piece label=%s, textangle=%s sub_angle=%s, set_angle=%s, angle=%s" % # (sector_names[i], # ((set_angle+subangle)/5760)*360, # subangle, # set_angle, # angle)) #print("textpos=%s" % ellipse.rect().center()) reduction_factor = 0 while text.boundingRect().height() > self.radius - (self.radius * .01): # print("category=%s, real_height=%s, radius=%s" % (sector_names[i], # text.boundingRect().height(), # self.radius)) # print("trying changing reduction factor from %s to %s" % (reduction_factor, # reduction_factor + 1)) reduction_factor += 1 self.font.setPointSize(self.default_font_size - reduction_factor) text.deleteLater() text = None text = QGraphicsTextItem() text.setDocument(document) #text.setFont(QFont("Helvetica", 65- reduction_factor)) text.setPlainText(textwrap.fill(sector_names[i], width=1)) text.setFont(self.font) text.setZValue(2) if sector_names[i] == False: #scrap this part for now until we can figure out how to safely offset titles. # print("ellipse center=%s" % ellipse.rect().center()) hypotenuse = self.radius * .01 degree_subangle = (((set_angle + subangle) / 5760) * 360) degree_subangle += 90 degree_subangle = degree_subangle % 360 doTranslate = True if doTranslate: #math.cos(degree_subangle) = adjacent/hypotenuse x = math.cos(degree_subangle) * hypotenuse y = math.sin(degree_subangle) * hypotenuse extra = True if extra: if degree_subangle > 0. and degree_subangle < 90.: pass elif degree_subangle > 90 and degree_subangle < 180: pass elif degree_subangle > 180 and degree_subangle < 270: pass #y = -y elif degree_subangle > 270: pass target = ellipse.rect().center() target.setX(x + target.x()) target.setY(y + target.y()) # print("target=%s" % target) print( "do_move_text_offset cat=%s, offset=%s degree_subangle=%s, x=%s, y=%s" % (sector_names[i], target, degree_subangle, x, y)) text.setPos(target) else: text.setPos(ellipse.rect().center()) text.setPos(ellipse.rect().center()) self.logger.debug("ellipse rect: %s" % ellipse.rect()) text.setRotation((((set_angle + subangle) / 5760) * 360)) #text.setRotation(30) # set_angle+=1 set_angle += angle count1 += 1 self.addItem(ellipse) self.addItem(text) self.setSceneRect(0, 0, self.radius * 2, self.radius * 2) self.logger.debug("scenesize= %s" % self.sceneRect())
def drawRobotCallback(self, result): for item in self.RobotShapes: self.scene.removeItem(item) self.RobotShapes.clear() self.RobotNames.clear() for item in self.robotMarkerShapes: self.augmentedRealityScene.removeItem(item) self.robotMarkerShapes.clear() frameRotation = 0 obSize = 70 controlledRobot = None for item in result.robots: shape = QGraphicsEllipseItem(int(item.pose.pose.pose.position.x*100 - obSize / 2), -int(item.pose.pose.pose.position.y*100 + obSize / 2), obSize, obSize) shape.setPen(QPen(self.black)) color = self.yellow if self.currentRobot is not None: if item.name == self.currentRobot.name: color = self.blue controlledRobot = item if self.helperRobot is not None: if self.helperRobot == item.name: color = self.purple shape.setBrush(QBrush(color, Qt.SolidPattern)) self.scene.addItem(shape) self.RobotShapes.append(shape) self.RobotNames.append(item.name) quat = item.pose.pose.pose.orientation siny_cosp = 2 * (quat.w * quat.z + quat.x * quat.y) cosy_cosp = 1 - 2 * (quat.y * quat.y + quat.z * quat.z) yaw = math.atan2(siny_cosp, cosy_cosp) #making the arrow startArrowX = int(item.pose.pose.pose.position.x*100-math.cos(yaw)*obSize/4) startArrowY = -int(item.pose.pose.pose.position.y*100-math.sin(yaw)*obSize/4) endArrowX =int(item.pose.pose.pose.position.x*100+math.cos(yaw)*obSize/2-math.cos(yaw)*obSize/4) endArrowY = -int(item.pose.pose.pose.position.y*100+math.sin(yaw)*obSize/2-math.sin(yaw)*obSize/4) line = QGraphicsLineItem(startArrowX, startArrowY, endArrowX, endArrowY) line.setPen(QPen(self.black, 5)) self.scene.addItem(line) self.RobotShapes.append(line) line = QGraphicsLineItem(endArrowX, endArrowY, endArrowX-math.cos(3.14/4+yaw)*obSize/4, endArrowY+math.sin(3.14/4+yaw)*obSize/4) line.setPen(QPen(self.black, 5)) self.scene.addItem(line) self.RobotShapes.append(line) line = QGraphicsLineItem(endArrowX, endArrowY, endArrowX- math.cos(3.14 / 4 - yaw) * obSize / 4, endArrowY- math.sin(3.14 / 4 - yaw) * obSize / 4) line.setPen(QPen(self.black, 5)) self.scene.addItem(line) self.RobotShapes.append(line) if self.currentRobot is not None: if item.name == self.currentRobot.name: self.OperatorMap.centerOn(int(item.pose.pose.pose.position.x * 100), -int(item.pose.pose.pose.position.y * 100)) deltaRotate = math.degrees(yaw)-90-self.previousMapRotation self.previousMapRotation = math.degrees(yaw)-90 self.OperatorMap.rotate(deltaRotate) frameRotation = math.degrees(yaw)-90 else: self.OperatorMap.rotate(-self.previousMapRotation) self.previousMapRotation = 0 frameRotation = 0 for item in result.robots: color = self.yellow if self.currentRobot is not None: if item.name == self.currentRobot.name: color = self.blue if self.helperRobot is not None: if self.helperRobot == item.name: color = self.purple label = QGraphicsTextItem(item.name) label.setX(int(item.pose.pose.pose.position.x * 100 + obSize * 1.1*math.cos(math.radians(-frameRotation-45)))) label.setY(int(-item.pose.pose.pose.position.y * 100 + obSize * 1.1*math.sin(math.radians(-frameRotation-45)))) label.setRotation(-frameRotation) font = QFont("Bavaria") font.setPointSize(18) font.setWeight(QFont.Bold) label.setDefaultTextColor(color) label.setFont(font) self.scene.addItem(label) self.RobotShapes.append(label) for item in self.RoomNames: item.setRotation(-frameRotation) if self.RobotWarningCB.isChecked(): for item in result.robots:#draw arrows to other bots if controlledRobot is not None: if item.name is not controlledRobot.name: deltaX = controlledRobot.pose.pose.pose.position.x - item.pose.pose.pose.position.x deltaY = controlledRobot.pose.pose.pose.position.y - item.pose.pose.pose.position.y robotDistance = math.sqrt( math.pow(deltaX, 2)+ math.pow(deltaY, 2)) if robotDistance<self.robotWarningDistance: color = self.yellow if self.helperRobot is not None: if self.helperRobot == item.name: color = self.purple quat = controlledRobot.pose.pose.pose.orientation siny_cosp = 2 * (quat.w * quat.z + quat.x * quat.y) cosy_cosp = 1 - 2 * (quat.y * quat.y + quat.z * quat.z) yaw = math.atan2(siny_cosp, cosy_cosp) difAngle = math.atan2(deltaY, deltaX) totalAngle = yaw-difAngle+math.pi/2 startArrowX = int(self.AugmentedRealityPanel.height()*math.cos(totalAngle)*0.45) startArrowY = int(self.AugmentedRealityPanel.height()*math.sin(totalAngle)*0.45) endArrowX = int(self.AugmentedRealityPanel.height()*math.cos(totalAngle)*0.49) endArrowY = int(self.AugmentedRealityPanel.height()*math.sin(totalAngle)*0.49) line = QGraphicsLineItem(startArrowX, startArrowY, endArrowX,endArrowY) line.setPen(QPen(color, 10)) self.augmentedRealityScene.addItem(line) self.robotMarkerShapes.append(line) line = QGraphicsLineItem(endArrowX, endArrowY, endArrowX - math.cos(3.14 / 4 + totalAngle) * self.AugmentedRealityPanel.height()*0.02, endArrowY - math.sin(3.14 / 4 + totalAngle) * self.AugmentedRealityPanel.height()*0.02) line.setPen(QPen(color, 10)) self.augmentedRealityScene.addItem(line) self.robotMarkerShapes.append(line) line = QGraphicsLineItem(endArrowX, endArrowY, endArrowX - math.cos(3.14 / 4 - totalAngle) * self.AugmentedRealityPanel.height()*0.02, endArrowY + math.sin(3.14 / 4 - totalAngle) * self.AugmentedRealityPanel.height()*0.02) line.setPen(QPen(color, 10)) self.augmentedRealityScene.addItem(line) self.robotMarkerShapes.append(line)
class TVentil(BlockItem, MassFlowNetworkContributorMixin): def __init__(self, trnsysType, parent, **kwargs): super(TVentil, self).__init__(trnsysType, parent, **kwargs) self.h = 40 self.w = 40 self.isTempering = False self.positionForMassFlowSolver = 1.0 self.posLabel = QGraphicsTextItem(str(self.positionForMassFlowSolver), self) self.posLabel.setVisible(False) self.inputs.append(_cspi.createSinglePipePortItem("i", 0, self)) self.inputs.append(_cspi.createSinglePipePortItem("i", 1, self)) self.outputs.append(_cspi.createSinglePipePortItem("o", 2, self)) self.changeSize() def _getImageAccessor(self) -> _tp.Optional[_img.ImageAccessor]: return _img.T_VENTIL_SVG def changeSize(self): w = self.w h = self.h delta = 20 # Limit the block size: if h < 20: h = 20 if w < 40: w = 40 # center label: rect = self.label.boundingRect() lw, lh = rect.width(), rect.height() lx = (w - lw) / 2 self.label.setPos(lx, h - self.flippedV * (h + h / 2)) self.posLabel.setPos(lx + 5, -15) self.origInputsPos = [[0, delta], [delta, 0]] self.origOutputsPos = [[w, delta]] self.inputs[0].setPos(self.origInputsPos[0][0], self.origInputsPos[0][1]) self.inputs[1].setPos(self.origInputsPos[1][0], self.origInputsPos[1][1]) self.outputs[0].setPos(self.origOutputsPos[0][0], self.origOutputsPos[0][1]) self.updateFlipStateH(self.flippedH) self.updateFlipStateV(self.flippedV) self.inputs[0].side = (self.rotationN + 2 * self.flippedH) % 4 self.inputs[1].side = (self.rotationN + 1 + 2 * self.flippedV) % 4 self.outputs[0].side = (self.rotationN + 2 - 2 * self.flippedH) % 4 return w, h def rotateBlockCW(self): super().rotateBlockCW() # Rotate valve position label back so it will always stay horizontal self._updateRotation() def rotateBlockCCW(self): super().rotateBlockCCW() # Rotate valve position label back so it will always stay horizontal self._updateRotation() def resetRotation(self): super().resetRotation() # Rotate valve position label back so it will always stay horizontal self._updateRotation() def _updateRotation(self): self.posLabel.setRotation(-self.rotationN * 90) def setComplexDiv(self, b): self.isTempering = bool(b) def setPositionForMassFlowSolver(self, f): self.positionForMassFlowSolver = f def encode(self): dictName, dct = super(TVentil, self).encode() dct["IsTempering"] = self.isTempering dct["PositionForMassFlowSolver"] = self.positionForMassFlowSolver return dictName, dct def decode(self, i, resBlockList): super().decode(i, resBlockList) if "IsTempering" not in i or "PositionForMassFlowSolver" not in i: self.logger.debug("Old version of diagram") self.positionForMassFlowSolver = 1.0 else: self.isTempering = i["IsTempering"] self.positionForMassFlowSolver = i["PositionForMassFlowSolver"] def decodePaste(self, i, offset_x, offset_y, resConnList, resBlockList, **kwargs): super(TVentil, self).decodePaste(i, offset_x, offset_y, resConnList, resBlockList, **kwargs) if "IsTempering" or "PositionForMassFlowSolver" not in i: self.logger.debug("Old version of diagram") self.positionForMassFlowSolver = 1.0 else: self.isTempering = i["IsTempering"] self.positionForMassFlowSolver = i["PositionForMassFlowSolver"] def exportMassFlows(self): if not self.isTempering: resStr = "xFrac" + self.displayName + " = " + str( self.positionForMassFlowSolver) + "\n" equationNr = 1 return resStr, equationNr else: return "", 0 def exportDivSetting1(self): if self.isTempering: constants = 1 f = "T_set_" + self.displayName + "=50\n" return f, constants else: return "", 0 def exportDivSetting2(self, nUnit): if self.isTempering: f = "" nUnit = nUnit + 1 f += "UNIT %d TYPE 811 ! Passive Divider for heating \n" % nUnit f += "PARAMETERS 1" + "\n" f += "5 !Nb.of iterations before fixing the value \n" f += "INPUTS 4 \n" if (self.outputs[0].pos().y() == self.inputs[0].pos().y() or self.outputs[0].pos().x() == self.inputs[0].pos().x()): first = self.inputs[0] second = self.inputs[1] f += "T" + first.connectionList[0].displayName + "\n" f += "T" + second.connectionList[0].displayName + "\n" f += "Mfr" + self.outputs[0].connectionList[0].displayName + "\n" f += "T_set_" + self.displayName + "\n" f += "*** INITIAL INPUT VALUES" + "\n" f += "35.0 21.0 800.0 T_set_" + self.displayName + "\n" f += "EQUATIONS 1\n" f += "xFrac" + self.displayName + " = 1.-[%d,5] \n\n" % nUnit return f, nUnit else: return "", nUnit def getInternalPiping(self) -> _mfs.InternalPiping: teePiece, modelPortItemsToGraphicalPortItem = self._getModelAndMapping( ) return _mfs.InternalPiping([teePiece], modelPortItemsToGraphicalPortItem) def _getModelAndMapping(self): input1 = _mfn.PortItem("TVentil Input 1", _mfn.PortItemType.INPUT) input2 = _mfn.PortItem("TVentil Input 2", _mfn.PortItemType.INPUT) output = _mfn.PortItem("TVentil Output", _mfn.PortItemType.OUTPUT) teePiece = _mfn.Diverter(self.displayName, self.trnsysId, output, input1, input2) modelPortItemsToGraphicalPortItem = { input1: self.inputs[0], input2: self.inputs[1], output: self.outputs[0] } return teePiece, modelPortItemsToGraphicalPortItem def exportPipeAndTeeTypesForTemp(self, startingUnit): if self.isVisible(): f = "" unitNumber = startingUnit tNr = 929 # Temperature calculation from a tee-piece unitText = "" ambientT = 20 equationConstant = 1 unitText += "UNIT " + str(unitNumber) + " TYPE " + str(tNr) + "\n" unitText += "!" + self.displayName + "\n" unitText += "PARAMETERS 0\n" unitText += "INPUTS 6\n" openLoops, nodesToIndices = self._getOpenLoopsAndNodeToIndices() assert len(openLoops) == 1 openLoop = openLoops[0] assert len(openLoop.realNodes) == 1 realNode = openLoop.realNodes[0] outputVariables = realNode.serialize( nodesToIndices).outputVariables for outputVariable in outputVariables: if not outputVariable: continue unitText += outputVariable.name + "\n" unitText += f"T{self.outputs[0].connectionList[0].displayName}\n" unitText += f"T{self.inputs[0].connectionList[0].displayName}\n" unitText += f"T{self.inputs[1].connectionList[0].displayName}\n" unitText += "***Initial values\n" unitText += 3 * "0 " + 3 * (str(ambientT) + " ") + "\n" unitText += "EQUATIONS 1\n" unitText += "T" + self.displayName + "= [" + str( unitNumber) + "," + str(equationConstant) + "]\n" unitNumber += 1 f += unitText + "\n" return f, unitNumber else: return "", startingUnit