Esempio n. 1
0
 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)
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))