def drawD2(self): if self.vtkViewer.reader == None: return num = self.inputD2.text() try: num = list(map(int, num.split(' '))) except Exception: return if len(num) != 2 or num[0] <= 1 or num[1] <= 1: return self.clear() histogram, scale = self.vtkViewer.d2Sample(num[0], num[1]) d2Chart = QChart() d2Chart.legend().hide() polyline = QPolygonF(num[0]) pointer = polyline.data() dtype, tinfo = np.float, np.finfo pointer.setsize(2*polyline.size()*tinfo(dtype).dtype.itemsize) memory = np.frombuffer(pointer, dtype) memory[:(num[0]-1)*2+1:2] = scale memory[1:(num[0]-1)*2+2:2] = histogram curve = QLineSeries() curve.append(polyline) d2Chart.addSeries(curve) d2Chart.createDefaultAxes() ChartView = QChartView(d2Chart) self.d2ChartLayout.addWidget(ChartView)
class SideRoi: support: List[QRectF] polygon: QPolygonF def __init__(self): self.support = list() self.polygon = QPolygonF() def in_support(self, point: QPointF) -> bool: for s in self.support: if s.contains(point): return True return False def contains(self, point: QPointF) -> bool: return (self.polygon.size() >= 3) and \ self.polygon.containsPoint(point, Qt.OddEvenFill) def to_dict(self): o = dict() o['support'] = list() for s in self.support: r = dict() r['x'] = s.x() r['y'] = s.y() r['width'] = s.width() r['height'] = s.height() o['support'].append(r) o['polygon'] = list() for point in self.polygon: p = dict() p['x'] = point.x() p['y'] = point.y() o['polygon'].append(p) return o def from_dict(self, o: dict): self.support = list() self.polygon = QPolygonF() for r in o['support']: x = r['x'] y = r['y'] w = r['width'] h = r['height'] s = QRectF(x, y, w, h) self.support.append(s) for p in o['polygon']: x = p['x'] y = p['y'] point = QPointF(x, y) self.polygon.append(point) return self
def series_to_polyline(xdata, ydata): size = len(xdata) polyline = QPolygonF(size) pointer = polyline.data() dtype, tinfo = np.float, np.finfo # integers: = np.int, np.iinfo pointer.setsize(2 * polyline.size() * tinfo(dtype).dtype.itemsize) memory = np.frombuffer(pointer, dtype) memory[:(size - 1) * 2 + 1:2] = xdata memory[1:(size - 1) * 2 + 2:2] = ydata return polyline
def series_to_polyline(xdata, ydata): #inspired from https://github.com/PierreRaybaut/plotpy/wiki/Using-Qt-Charts-(PyQtChart)-to-plot-curves-efficiently-in-Python! size = len(xdata) polyline = QPolygonF(size) pointer = polyline.data() dtype, tinfo = np.float, np.finfo # integers: = np.int, np.iinfo pointer.setsize(2 * polyline.size() * tinfo(dtype).dtype.itemsize) memory = np.frombuffer(pointer, dtype) memory[:(size - 1) * 2 + 1:2] = xdata memory[1:(size - 1) * 2 + 2:2] = ydata return polyline
def series_to_polyline(xdata, ydata): """Convert series data to QPolygon(F) polyline This code is derived from PythonQwt's function named `qwt.plot_curve.series_to_polyline`""" size = len(xdata) polyline = QPolygonF(size) pointer = polyline.data() dtype, tinfo = np.float, np.finfo # integers: = np.int, np.iinfo pointer.setsize(2 * polyline.size() * tinfo(dtype).dtype.itemsize) memory = np.frombuffer(pointer, dtype) memory[:(size - 1) * 2 + 1:2] = xdata memory[1:(size - 1) * 2 + 2:2] = ydata return polyline
def rotatePolygonClockWiseRad(self, p: QPolygonF, angle, origin): ''' Rotate a polygon around a point :param p: polygon to rotate :param origin: the rotation center :param angle: rotation angle, in radians :return p: Polygon p rotated by angle around the origin point ''' for i in range(p.size()): curr = p.at(i) x = curr.x() y = curr.y() curr.setX(((cos(angle) * (x-origin.x())) + (-sin(angle) * (y-origin.y()))) + origin.x()) curr.setY(((sin(angle) * (x-origin.x())) + (cos(angle) * (y-origin.y()))) + origin.y()) p.replace(i, curr)
def series_to_polyline(self, xdata, ydata): #convert plot data for Qt """Convert series data to QPolygon(F) polyline This code is derived from PythonQwt's function named `qwt.plot_curve.series_to_polyline`""" xsize = len(xdata) ysize = len(ydata) if xsize != ysize: root = Tk() root.withdraw() messagebox.showinfo("Live Plot Error!", "Check force file/video file\n" + \ "Exception: x axis and y axis array sizes don't match") root.destroy() self.playStatus = False polyline = QPolygonF(xsize) pointer = polyline.data() dtype, tinfo = np.float, np.finfo # integers: = np.int, np.iinfo pointer.setsize(2*polyline.size()*tinfo(dtype).dtype.itemsize) memory = np.frombuffer(pointer, dtype) memory[:(xsize-1)*2+1:2] = xdata memory[1:(ysize-1)*2+2:2] = ydata return polyline
def series_to_polyline(xdata, ydata): """Convert series data to QPolygon(F) polyline This code is derived from PythonQwt's function named `qwt.plot_curve.series_to_polyline`""" size = len(xdata) dtype = np.float tinfo = np.finfo dtypesize = tinfo(dtype).dtype.itemsize polyline = QPolygonF(size) polyline_size = polyline.size() pointer = polyline.data() pointer_size = 2 * polyline_size * dtypesize pointer.setsize(pointer_size) memory = np.frombuffer(pointer, dtype) memory[:(size - 1) * 2 + 1:2] = xdata.T memory[1:(size - 1) * 2 + 2:2] = ydata.T return polyline
class Triangluation(CoordWidget): def __init__(self): super(Triangluation, self).__init__() self.setGeometry(300, 300, 800, 600) self.setWindowTitle('Triangluation ') self.points = [] # screen pos self.polygon = QPolygonF() self.holePoints = [] # screen pos self.holePolygon = QPolygonF() self.lineSeg = [] self.indenpandentPoints = [] # screen def mouseMoveEvent(self, e): newPos = e.pos() if (self.lastPos - newPos).manhattanLength() < 1: self.lastPos = newPos return if e.buttons() & Qt.RightButton: translation = self.screenToWorld(newPos) - self.screenToWorld( self.lastPos) self.scene_translation_ = self.scene_translation_ + translation elif e.buttons() & Qt.LeftButton: pass self.lastPos = e.pos() self.update() def mousePressEvent(self, qMousePressEvent): e = qMousePressEvent modifiers = QtWidgets.QApplication.keyboardModifiers() if e.buttons() & Qt.LeftButton: self.take_screenshot() if modifiers == QtCore.Qt.ControlModifier: # record a hole self.holePoints.append(e.pos()) self.makeConvexHull(self.holePoints, self.holePolygon) elif modifiers == QtCore.Qt.ShiftModifier: # record a line seg if len(self.lineSeg) < 3: self.lineSeg.append(self.screenToWorld(e.pos())) elif modifiers == QtCore.Qt.AltModifier: self.indenpandentPoints.append(e.pos()) else: self.points.append(e.pos()) self.makeConvexHull(self.points, self.polygon) self.lastPos = e.pos() self.update() def isRightTurn(self, p0, p1, p2): v1x = p1.x() - p0.x() v1y = p1.y() - p0.y() v2x = p2.x() - p1.x() v2y = p2.y() - p1.y() if v1x * v2y - v1y * v2x > 0.0: return False else: return True def makeConvexHull(self, points, polygon): verticesIter = map(lambda p: self.screenToWorld(p), points) vertices = list(verticesIter) vertices.sort(key=lambda p: (p.x(), p.y())) if len(vertices) < 3: return upper = [vertices[0], vertices[1]] for v in vertices[2:len(vertices)]: upper.append(v) while len(upper) > 2 and self.isRightTurn(upper[-3], upper[-2], upper[-1]): del upper[-2] lower = [vertices[-1], vertices[-2]] for v in reversed(vertices[0:-3]): lower.append(v) while len(lower) > 2 and self.isRightTurn(lower[-3], lower[-2], lower[-1]): del lower[-2] del lower[0] upper.extend(lower) polygon.clear() for v in upper: polygon.append(v) # http://www.cs.cmu.edu/~quake/triangle.html def triangulate(self): vertices = [] segments = [] outBoundarySegments = [] for i in range(self.polygon.size() - 1): v = self.polygon.at(i) vertices.append((v.x(), v.y())) if i == (self.polygon.size() - 2): outBoundarySegments.append((i, 0)) else: outBoundarySegments.append((i, i + 1)) outVertexNum = len(vertices) for i in range(self.holePolygon.size() - 1): v = self.holePolygon.at(i) vertices.append((v.x(), v.y())) n = i + outVertexNum if i == (self.holePolygon.size() - 2): segments.append((n, outVertexNum)) else: segments.append((n, n + 1)) v = self.lineSeg[0] vertices.append((v.x(), v.y())) v = self.lineSeg[1] vertices.append((v.x(), v.y())) segments.append((len(vertices) - 2, len(vertices) - 1)) for p in self.indenpandentPoints: v = self.screenToWorld(p) vertices.append((v.x(), v.y())) holeMarkerPos = [] center = self.holePolygon.boundingRect().center() holeMarkerPos.append((center.x(), center.y())) segments = segments + outBoundarySegments # A1 = triangle.get_data('face.1') A = dict(vertices=np.array(vertices), segments=np.array(segments), holes=np.array(holeMarkerPos)) B = triangle.triangulate(A, 'pqa0.01c') triangle.plot.compare(plt, A, B) # plt.show() def keyPressEvent(self, keyEvent): e = keyEvent if e.key() == Qt.Key_C: self.makeConvexHull(self.vertexs, self.polygon) self.makeConvexHull(self.holeVertexs, self.holePolygon) elif e.key() == Qt.Key_S: self.saveGIF() elif e.key() == Qt.Key_T: self.triangulate() super(Triangluation, self).keyPressEvent(keyEvent) def drawInWorld(self, qPainter): pen = qPainter.pen() pen.setColor(QColor.fromRgb(255, 0, 0)) qPainter.setPen(pen) if None is not self.polygon: qPainter.drawPolyline(self.polygon) pen.setColor(QColor.fromRgb(0, 255, 0)) qPainter.setPen(pen) if None is not self.holePolygon: qPainter.drawPolyline(self.holePolygon) if len(self.lineSeg) == 2: qPainter.drawLine(QLineF(self.lineSeg[0], self.lineSeg[1])) pen.setColor(QColor.fromRgb(0, 0, 255)) qPainter.setPen(pen) def drawInScreen(self, qPainter): pen = qPainter.pen() pen.setWidth(5) pen.setColor(QColor.fromRgb(0, 0, 0)) qPainter.setPen(pen) qPainter.resetTransform() # draw selected points in screen for v in self.points: qPainter.drawPoint(v) for v in self.indenpandentPoints: qPainter.drawPoint(v) for i in range(self.polygon.size() - 1): qPainter.drawText(self.worldToScreen(self.polygon.at(i)), str(i)) for i in range(self.holePolygon.size() - 1): n = self.polygon.size() + i - 1 qPainter.drawText(self.worldToScreen(self.holePolygon.at(i)), str(n))
class MapObject(Object): ## # Enumerates the different object shapes. Rectangle is the default shape. # When a polygon is set, the shape determines whether it should be # interpreted as a filled polygon or a line. ## Rectangle, Polygon, Polyline, Ellipse = range(4) def __init__(self, *args): super().__init__(Object.MapObjectType) self.mPolygon = QPolygonF() self.mName = QString() self.mPos = QPointF() self.mCell = Cell() self.mType = QString() self.mId = 0 self.mShape = MapObject.Rectangle self.mObjectGroup = None self.mRotation = 0.0 self.mVisible = True l = len(args) if l==0: self.mSize = QSizeF(0, 0) elif l==4: name, _type, pos, size = args self.mName = name self.mType = _type self.mPos = pos self.mSize = QSizeF(size) ## # Returns the id of this object. Each object gets an id assigned that is # unique for the map the object is on. ## def id(self): return self.mId ## # Sets the id of this object. ## def setId(self, id): self.mId = id ## # Returns the name of this object. The name is usually just used for # identification of the object in the editor. ## def name(self): return self.mName ## # Sets the name of this object. ## def setName(self, name): self.mName = name ## # Returns the type of this object. The type usually says something about # how the object is meant to be interpreted by the engine. ## def type(self): return self.mType ## # Sets the type of this object. ## def setType(self, type): self.mType = type ## # Returns the position of this object. ## def position(self): return QPointF(self.mPos) ## # Sets the position of this object. ## def setPosition(self, pos): self.mPos = pos ## # Returns the x position of this object. ## def x(self): return self.mPos.x() ## # Sets the x position of this object. ## def setX(self, x): self.mPos.setX(x) ## # Returns the y position of this object. ## def y(self): return self.mPos.y() ## # Sets the x position of this object. ## def setY(self, y): self.mPos.setY(y) ## # Returns the size of this object. ## def size(self): return self.mSize ## # Sets the size of this object. ## def setSize(self, *args): l = len(args) if l==1: size = args[0] self.mSize = QSizeF(size) elif l==2: width, height = args self.setSize(QSizeF(width, height)) ## # Returns the width of this object. ## def width(self): return self.mSize.width() ## # Sets the width of this object. ## def setWidth(self, width): self.mSize.setWidth(width) ## # Returns the height of this object. ## def height(self): return self.mSize.height() ## # Sets the height of this object. ## def setHeight(self, height): self.mSize.setHeight(height) ## # Sets the polygon associated with this object. The polygon is only used # when the object shape is set to either Polygon or Polyline. # # \sa setShape() ## def setPolygon(self, polygon): self.mPolygon = polygon ## # Returns the polygon associated with this object. Returns an empty # polygon when no polygon is associated with this object. ## def polygon(self): return QPolygonF(self.mPolygon) ## # Sets the shape of the object. ## def setShape(self, shape): self.mShape = shape ## # Returns the shape of the object. ## def shape(self): return self.mShape ## # Shortcut to getting a QRectF from position() and size(). ## def bounds(self): return QRectF(self.mPos, self.mSize) ## # Shortcut to getting a QRectF from position() and size() that uses cell tile if present. ## def boundsUseTile(self): if (self.mCell.isEmpty()): # No tile so just use regular bounds return self.bounds() # Using the tile for determing boundary # Note the position given is the bottom-left corner so correct for that return QRectF(QPointF(self.mPos.x(), self.mPos.y() - self.mCell.tile.height()), self.mCell.tile.size()) ## # Sets the tile that is associated with this object. The object will # display as the tile image. # # \warning The object shape is ignored for tile objects! ## def setCell(self, cell): self.mCell = cell ## # Returns the tile associated with this object. ## def cell(self): return self.mCell ## # Returns the object group this object belongs to. ## def objectGroup(self): return self.mObjectGroup ## # Sets the object group this object belongs to. Should only be called # from the ObjectGroup class. ## def setObjectGroup(self, objectGroup): self.mObjectGroup = objectGroup ## # Returns the rotation of the object in degrees. ## def rotation(self): return self.mRotation ## # Sets the rotation of the object in degrees. ## def setRotation(self, rotation): self.mRotation = rotation ## # This is somewhat of a workaround for dealing with the ways different objects # align. # # Traditional rectangle objects have top-left alignment. # Tile objects have bottom-left alignment on orthogonal maps, but # bottom-center alignment on isometric maps. # # Eventually, the object alignment should probably be configurable. For # backwards compatibility, it will need to be configurable on a per-object # level. ## def alignment(self): if (self.mCell.isEmpty()): return Alignment.TopLeft elif (self.mObjectGroup): map = self.mObjectGroup.map() if map: if (map.orientation() == Map.Orientation.Isometric): return Alignment.Bottom return Alignment.BottomLeft def isVisible(self): return self.mVisible def setVisible(self, visible): self.mVisible = visible ## # Flip this object in the given \a direction. This doesn't change the size # of the object. ## def flip(self, direction): if (not self.mCell.isEmpty()): if (direction == FlipDirection.FlipHorizontally): self.mCell.flippedHorizontally = not self.mCell.flippedHorizontally elif (direction == FlipDirection.FlipVertically): self.mCell.flippedVertically = not self.mCell.flippedVertically if (not self.mPolygon.isEmpty()): center2 = self.mPolygon.boundingRect().center() * 2 if (direction == FlipDirection.FlipHorizontally): for i in range(self.mPolygon.size()): # oh, QPointF mPolygon returned is a copy of internal object self.mPolygon[i] = QPointF(center2.x() - self.mPolygon[i].x(), self.mPolygon[i].y()) elif (direction == FlipDirection.FlipVertically): for i in range(self.mPolygon.size()): self.mPolygon[i] = QPointF(self.mPolygon[i].x(), center2.y() - self.mPolygon[i].y()) ## # Returns a duplicate of this object. The caller is responsible for the # ownership of this newly created object. ## def clone(self): o = MapObject(self.mName, self.mType, self.mPos, self.mSize) o.setProperties(self.properties()) o.setPolygon(self.mPolygon) o.setShape(self.mShape) o.setCell(self.mCell) o.setRotation(self.mRotation) return o
class MapObject(Object): ## # Enumerates the different object shapes. Rectangle is the default shape. # When a polygon is set, the shape determines whether it should be # interpreted as a filled polygon or a line. ## Rectangle, Polygon, Polyline, Ellipse = range(4) def __init__(self, *args): super().__init__(Object.MapObjectType) self.mPolygon = QPolygonF() self.mName = QString() self.mPos = QPointF() self.mCell = Cell() self.mType = QString() self.mId = 0 self.mShape = MapObject.Rectangle self.mObjectGroup = None self.mRotation = 0.0 self.mVisible = True l = len(args) if l == 0: self.mSize = QSizeF(0, 0) elif l == 4: name, _type, pos, size = args self.mName = name self.mType = _type self.mPos = pos self.mSize = QSizeF(size) ## # Returns the id of this object. Each object gets an id assigned that is # unique for the map the object is on. ## def id(self): return self.mId ## # Sets the id of this object. ## def setId(self, id): self.mId = id ## # Returns the name of this object. The name is usually just used for # identification of the object in the editor. ## def name(self): return self.mName ## # Sets the name of this object. ## def setName(self, name): self.mName = name ## # Returns the type of this object. The type usually says something about # how the object is meant to be interpreted by the engine. ## def type(self): return self.mType ## # Sets the type of this object. ## def setType(self, type): self.mType = type ## # Returns the position of this object. ## def position(self): return QPointF(self.mPos) ## # Sets the position of this object. ## def setPosition(self, pos): self.mPos = pos ## # Returns the x position of this object. ## def x(self): return self.mPos.x() ## # Sets the x position of this object. ## def setX(self, x): self.mPos.setX(x) ## # Returns the y position of this object. ## def y(self): return self.mPos.y() ## # Sets the x position of this object. ## def setY(self, y): self.mPos.setY(y) ## # Returns the size of this object. ## def size(self): return self.mSize ## # Sets the size of this object. ## def setSize(self, *args): l = len(args) if l == 1: size = args[0] self.mSize = QSizeF(size) elif l == 2: width, height = args self.setSize(QSizeF(width, height)) ## # Returns the width of this object. ## def width(self): return self.mSize.width() ## # Sets the width of this object. ## def setWidth(self, width): self.mSize.setWidth(width) ## # Returns the height of this object. ## def height(self): return self.mSize.height() ## # Sets the height of this object. ## def setHeight(self, height): self.mSize.setHeight(height) ## # Sets the polygon associated with this object. The polygon is only used # when the object shape is set to either Polygon or Polyline. # # \sa setShape() ## def setPolygon(self, polygon): self.mPolygon = polygon ## # Returns the polygon associated with this object. Returns an empty # polygon when no polygon is associated with this object. ## def polygon(self): return QPolygonF(self.mPolygon) ## # Sets the shape of the object. ## def setShape(self, shape): self.mShape = shape ## # Returns the shape of the object. ## def shape(self): return self.mShape ## # Shortcut to getting a QRectF from position() and size(). ## def bounds(self): return QRectF(self.mPos, self.mSize) ## # Shortcut to getting a QRectF from position() and size() that uses cell tile if present. ## def boundsUseTile(self): if (self.mCell.isEmpty()): # No tile so just use regular bounds return self.bounds() # Using the tile for determing boundary # Note the position given is the bottom-left corner so correct for that return QRectF( QPointF(self.mPos.x(), self.mPos.y() - self.mCell.tile.height()), self.mCell.tile.size()) ## # Sets the tile that is associated with this object. The object will # display as the tile image. # # \warning The object shape is ignored for tile objects! ## def setCell(self, cell): self.mCell = cell ## # Returns the tile associated with this object. ## def cell(self): return self.mCell ## # Returns the object group this object belongs to. ## def objectGroup(self): return self.mObjectGroup ## # Sets the object group this object belongs to. Should only be called # from the ObjectGroup class. ## def setObjectGroup(self, objectGroup): self.mObjectGroup = objectGroup ## # Returns the rotation of the object in degrees. ## def rotation(self): return self.mRotation ## # Sets the rotation of the object in degrees. ## def setRotation(self, rotation): self.mRotation = rotation ## # This is somewhat of a workaround for dealing with the ways different objects # align. # # Traditional rectangle objects have top-left alignment. # Tile objects have bottom-left alignment on orthogonal maps, but # bottom-center alignment on isometric maps. # # Eventually, the object alignment should probably be configurable. For # backwards compatibility, it will need to be configurable on a per-object # level. ## def alignment(self): if (self.mCell.isEmpty()): return Alignment.TopLeft elif (self.mObjectGroup): map = self.mObjectGroup.map() if map: if (map.orientation() == Map.Orientation.Isometric): return Alignment.Bottom return Alignment.BottomLeft def isVisible(self): return self.mVisible def setVisible(self, visible): self.mVisible = visible ## # Flip this object in the given \a direction. This doesn't change the size # of the object. ## def flip(self, direction): if (not self.mCell.isEmpty()): if (direction == FlipDirection.FlipHorizontally): self.mCell.flippedHorizontally = not self.mCell.flippedHorizontally elif (direction == FlipDirection.FlipVertically): self.mCell.flippedVertically = not self.mCell.flippedVertically if (not self.mPolygon.isEmpty()): center2 = self.mPolygon.boundingRect().center() * 2 if (direction == FlipDirection.FlipHorizontally): for i in range(self.mPolygon.size()): # oh, QPointF mPolygon returned is a copy of internal object self.mPolygon[i] = QPointF( center2.x() - self.mPolygon[i].x(), self.mPolygon[i].y()) elif (direction == FlipDirection.FlipVertically): for i in range(self.mPolygon.size()): self.mPolygon[i] = QPointF( self.mPolygon[i].x(), center2.y() - self.mPolygon[i].y()) ## # Returns a duplicate of this object. The caller is responsible for the # ownership of this newly created object. ## def clone(self): o = MapObject(self.mName, self.mType, self.mPos, self.mSize) o.setProperties(self.properties()) o.setPolygon(self.mPolygon) o.setShape(self.mShape) o.setCell(self.mCell) o.setRotation(self.mRotation) return o