def transformedCornerCoordinates(self, center, rotation, xScale, yScale):
        # scale
        topLeft = QgsPointXY(-self.image.width() / 2.0 * xScale,
                             self.image.height() / 2.0 * yScale)
        topRight = QgsPointXY(self.image.width() / 2.0 * xScale,
                              self.image.height() / 2.0 * yScale)
        bottomLeft = QgsPointXY(-self.image.width() / 2.0 * xScale,
                                - self.image.height() / 2.0 * yScale)
        bottomRight = QgsPointXY(self.image.width() / 2.0 * xScale,
                                 - self.image.height() / 2.0 * yScale)

        # rotate
        # minus sign because rotation is CW in this class and Qt)
        rotationRad = -rotation * math.pi / 180
        cosRot = math.cos(rotationRad)
        sinRot = math.sin(rotationRad)

        topLeft = self._rotate(topLeft, cosRot, sinRot)
        topRight = self._rotate(topRight, cosRot, sinRot)
        bottomRight = self._rotate(bottomRight, cosRot, sinRot)
        bottomLeft = self._rotate(bottomLeft, cosRot, sinRot)

        topLeft.set(topLeft.x() + center.x(), topLeft.y() + center.y())
        topRight.set(topRight.x() + center.x(), topRight.y() + center.y())
        bottomRight.set(bottomRight.x() + center.x(),
                        bottomRight.y() + center.y())
        bottomLeft.set(bottomLeft.x() + center.x(),
                       bottomLeft.y() + center.y())

        return (topLeft, topRight, bottomRight, bottomLeft)
Ejemplo n.º 2
0
class QadGRIPMIRRORCommandClass(QadCommandClass):
    def instantiateNewCmd(self):
        """ istanzia un nuovo comando dello stesso tipo """
        return QadMIRRORCommandClass(self.plugIn)

    def __init__(self, plugIn):
        QadCommandClass.__init__(self, plugIn)
        self.cacheEntitySet = QadCacheEntitySet()
        self.basePt = QgsPointXY()
        self.secondMirrorPt = QgsPointXY()
        self.skipToNextGripCommand = False
        self.copyEntities = False
        self.nOperationsToUndo = 0

    def __del__(self):
        QadCommandClass.__del__(self)

    def getPointMapTool(self, drawMode=QadGetPointDrawModeEnum.NONE):
        if (self.plugIn is not None):
            if self.PointMapTool is None:
                self.PointMapTool = Qad_mirror_maptool(self.plugIn)
            return self.PointMapTool
        else:
            return None

    #============================================================================
    # setSelectedEntityGripPoints
    #============================================================================
    def setSelectedEntityGripPoints(self, entitySetGripPoints):
        # lista delle entityGripPoint con dei grip point selezionati
        self.cacheEntitySet.clear()

        for entityGripPoints in entitySetGripPoints.entityGripPoints:
            self.cacheEntitySet.appendEntity(entityGripPoints.entity)

        self.getPointMapTool().cacheEntitySet = self.cacheEntitySet

    #============================================================================
    # mirror
    #============================================================================
    def mirror(self, entity, mirrorPt, angle):
        # entity = entità da specchiare
        # pt1 e pt2 = linea di simmetria
        # rotFldName = campo della tabella che memorizza la rotazione
        # verifico se l'entità appartiene ad uno stile di quotatura
        if entity.whatIs() == "ENTITY":
            # specchio la geometria dell'entità
            qadGeom = entity.getQadGeom().copy()  # la copio
            qadGeom.mirror(mirrorPt, angle)
            f = entity.getFeature()
            f.setGeometry(fromQadGeomToQgsGeom(qadGeom, entity.crs()))

            if len(entity.rotFldName) > 0 is not None:
                rotValue = f.attribute(entity.rotFldName)
                rotValue = 0 if rotValue is None or rotValue == NULL else qad_utils.toRadians(
                    rotValue
                )  # la rotazione é in gradi nel campo della feature
                ptDummy = qad_utils.getPolarPointByPtAngle(
                    mirrorPt, rotValue, 1)
                ptDummy = qad_utils.mirrorPoint(ptDummy, mirrorPt, angle)
                rotValue = qad_utils.getAngleBy2Pts(mirrorPt, ptDummy)
                f.setAttribute(
                    entity.rotFldName,
                    qad_utils.toDegrees(qad_utils.normalizeAngle(rotValue)))

            if self.copyEntities == False:
                # plugIn, layer, feature, refresh, check_validity
                if qad_layer.updateFeatureToLayer(self.plugIn, entity.layer, f,
                                                  False, False) == False:
                    return False
            else:
                # plugIn, layer, features, coordTransform, refresh, check_validity
                if qad_layer.addFeatureToLayer(self.plugIn, entity.layer, f,
                                               None, False, False) == False:
                    return False
        elif entity.whatIs() == "DIMENTITY":
            # specchio la quota
            if self.copyEntities == False:
                if entity.deleteToLayers(self.plugIn) == False:
                    return False
            newDimEntity = QadDimEntity(entity)  # la copio
            newDimEntity.mirror(mirrorPt, angle)
            if newDimEntity.addToLayers(self.plugIn) == False:
                return False

        return True

    #============================================================================
    # mirrorGeoms
    #============================================================================
    def mirrorGeoms(self):
        self.plugIn.beginEditCommand("Feature mirrored",
                                     self.cacheEntitySet.getLayerList())

        angle = qad_utils.getAngleBy2Pts(self.firstMirrorPt,
                                         self.secondMirrorPt)

        dimElaboratedList = []  # lista delle quotature già elaborate
        entityIterator = QadCacheEntitySetIterator(self.cacheEntitySet)
        for entity in entityIterator:
            qadGeom = entity.getQadGeom()  # così inizializzo le info qad
            # verifico se l'entità appartiene ad uno stile di quotatura
            dimEntity = QadDimStyles.getDimEntity(entity)
            if dimEntity is not None:
                if appendDimEntityIfNotExisting(
                        dimElaboratedList,
                        dimEntity) == False:  # quota già elaborata
                    continue
                entity = dimEntity

            if self.mirror(entity, self.firstMirrorPt, angle) == False:
                self.plugIn.destroyEditCommand()
                return

        self.plugIn.endEditCommand()
        self.nOperationsToUndo = self.nOperationsToUndo + 1

    #============================================================================
    # waitForMirrorPoint
    #============================================================================
    def waitForMirrorPoint(self):
        self.step = 1
        self.plugIn.setLastPoint(self.basePt)
        # imposto il map tool
        self.getPointMapTool().firstMirrorPt = self.basePt
        self.getPointMapTool().setMode(
            Qad_mirror_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_PT)

        keyWords = QadMsg.translate("Command_GRIPMIRROR", "Base point") + "/" + \
                   QadMsg.translate("Command_GRIPMIRROR", "Copy") + "/" + \
                   QadMsg.translate("Command_GRIPMIRROR", "Undo") + "/" + \
                   QadMsg.translate("Command_GRIPMIRROR", "eXit")

        prompt = QadMsg.translate(
            "Command_GRIPMIRROR",
            "Specify second point or [{0}]: ").format(keyWords)

        englishKeyWords = "Base point" + "/" + "Copy" + "/" + "Undo" + "/" + "eXit"
        keyWords += "_" + englishKeyWords
        # si appresta ad attendere un punto, un numero reale o enter o una parola chiave
        # msg, inputType, default, keyWords, nessun controllo
        self.waitFor(prompt, QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                     None, \
                     keyWords, QadInputModeEnum.NONE)

    #============================================================================
    # waitForBasePt
    #============================================================================
    def waitForBasePt(self):
        self.step = 2
        # imposto il map tool
        self.getPointMapTool().setMode(
            Qad_mirror_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_FIRST_PT)
        # si appresta ad attendere un punto
        self.waitForPoint(
            QadMsg.translate("Command_GRIPROTATE", "Specify base point: "))

    def run(self, msgMapTool=False, msg=None):
        if self.plugIn.canvas.mapSettings().destinationCrs().isGeographic():
            self.showMsg(
                QadMsg.translate(
                    "QAD",
                    "\nThe coordinate reference system of the project must be a projected coordinate system.\n"
                ))
            return True  # fine comando

        #=========================================================================
        # RICHIESTA SELEZIONE OGGETTI
        if self.step == 0:  # inizio del comando
            if self.cacheEntitySet.isEmpty():  # non ci sono oggetti da ruotare
                return True
            self.showMsg(
                QadMsg.translate("Command_GRIPMIRROR", "\n** MIRROR **\n"))
            # si appresta ad attendere il secondo punto di specchio
            self.waitForMirrorPoint()

        #=========================================================================
        # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER SPECCHIO
        elif self.step == 1:  # dopo aver atteso un punto si riavvia il comando
            ctrlKey = False
            if msgMapTool == True:  # il punto arriva da una selezione grafica
                # la condizione seguente si verifica se durante la selezione di un punto
                # é stato attivato un altro plugin che ha disattivato Qad
                # quindi stato riattivato il comando che torna qui senza che il maptool
                # abbia selezionato un punto
                if self.getPointMapTool(
                ).point is None:  # il maptool é stato attivato senza un punto
                    if self.getPointMapTool(
                    ).rightButton == True:  # se usato il tasto destro del mouse
                        value = None
                    else:
                        self.setMapTool(
                            self.getPointMapTool())  # riattivo il maptool
                        return False

                ctrlKey = self.getPointMapTool().ctrlKey
                value = self.getPointMapTool().point
            else:  # il punto arriva come parametro della funzione
                value = msg

            if type(value) == unicode:
                if value == QadMsg.translate(
                        "Command_GRIPMIRROR",
                        "Base point") or value == "Base point":
                    # si appresta ad attendere il punto base
                    self.waitForBasePt()
                elif value == QadMsg.translate("Command_GRIPMIRROR",
                                               "Copy") or value == "Copy":
                    # Copia entità lasciando inalterate le originali
                    self.copyEntities = True
                    # si appresta ad attendere il secondo punto di specchio
                    self.waitForMirrorPoint()
                elif value == QadMsg.translate("Command_GRIPMIRROR",
                                               "Undo") or value == "Undo":
                    if self.nOperationsToUndo > 0:
                        self.nOperationsToUndo = self.nOperationsToUndo - 1
                        self.plugIn.undoEditCommand()
                    else:
                        self.showMsg(
                            QadMsg.translate(
                                "QAD", "\nThe command has been canceled."))
                    # si appresta ad attendere il secondo punto di specchio
                    self.waitForMirrorPoint()
                elif value == QadMsg.translate("Command_GRIPMIRROR",
                                               "eXit") or value == "eXit":
                    return True  # fine comando
            elif type(value
                      ) == QgsPointXY:  # se é stato inserito il secondo punto
                if qad_utils.ptNear(self.basePt, value):
                    self.showMsg(
                        QadMsg.translate("Command_GRIPMIRROR",
                                         "\nThe points must be different."))
                    # si appresta ad attendere il secondo punto di specchio
                    self.waitForMirrorPoint()
                    return False

                self.secondMirrorPt.set(value.x(), value.y())

                if ctrlKey:
                    self.copyEntities = True

                self.mirrorGeoms()

                if self.copyEntities == False:
                    return True

                # si appresta ad attendere il secondo punto di specchio
                self.waitForMirrorPoint()

            else:
                if self.copyEntities == False:
                    self.skipToNextGripCommand = True
                return True  # fine comando

            return False

        #=========================================================================
        # RISPOSTA ALLA RICHIESTA PUNTO BASE (da step = 1)
        elif self.step == 2:  # dopo aver atteso un punto
            if msgMapTool == True:  # il punto arriva da una selezione grafica
                # la condizione seguente si verifica se durante la selezione di un punto
                # é stato attivato un altro plugin che ha disattivato Qad
                # quindi stato riattivato il comando che torna qui senza che il maptool
                # abbia selezionato un punto
                if self.getPointMapTool(
                ).point is None:  # il maptool é stato attivato senza un punto
                    if self.getPointMapTool(
                    ).rightButton == True:  # se usato il tasto destro del mouse
                        pass  # opzione di default "spostamento"
                    else:
                        self.setMapTool(
                            self.getPointMapTool())  # riattivo il maptool
                        return False

                value = self.getPointMapTool().point
            else:  # il punto arriva come parametro della funzione
                value = msg

            if type(value) == QgsPointXY:  # se é stato inserito il punto base
                self.basePt.set(value.x(), value.y())

            # si appresta ad attendere il secondo punto di specchio
            self.waitForMirrorPoint()

            return False
Ejemplo n.º 3
0
class QadGRIPSTRETCHCommandClass(QadCommandClass):
    def instantiateNewCmd(self):
        """ istanzia un nuovo comando dello stesso tipo """
        return QadGRIPSTRETCHCommandClass(self.plugIn)

    def __init__(self, plugIn):
        QadCommandClass.__init__(self, plugIn)
        self.selectedEntityGripPoints = [
        ]  # lista in cui ogni elemento è una entità + una lista di punti da stirare
        self.basePt = QgsPointXY()
        self.skipToNextGripCommand = False
        self.copyEntities = False
        self.nOperationsToUndo = 0

    def __del__(self):
        QadCommandClass.__del__(self)

    def getPointMapTool(self, drawMode=QadGetPointDrawModeEnum.NONE):
        if (self.plugIn is not None):
            if self.PointMapTool is None:
                self.PointMapTool = Qad_gripStretch_maptool(self.plugIn)
            return self.PointMapTool
        else:
            return None

    #============================================================================
    # addToSelectedEntityGripPoints
    #============================================================================
    def addToSelectedEntityGripPoints(self, entityGripPoints):
        # entità con lista dei grip point
        i = 0
        gripPoints = entityGripPoints.gripPoints
        gripPointsLen = len(gripPoints)
        ptList = []
        while i < gripPointsLen:
            gripPoint = gripPoints[i]
            # grip point selezionato
            if gripPoint.getStatus() == qad_grip.QadGripStatusEnum.SELECTED:
                if gripPoint.gripType == qad_grip.QadGripPointTypeEnum.CENTER:
                    ptList.append(gripPoint.getPoint())
                elif gripPoint.gripType == qad_grip.QadGripPointTypeEnum.LINE_MID_POINT:
                    # aggiungo il vertice precedente e successivo di quello intermedio
                    if i > 0:
                        ptList.append(gripPoints[i - 1].getPoint())
                    if i < gripPointsLen - 1:
                        ptList.append(gripPoints[i + 1].getPoint())
                elif gripPoint.gripType == qad_grip.QadGripPointTypeEnum.QUA_POINT:
                    ptList.append(gripPoint.getPoint())
                elif gripPoint.gripType == qad_grip.QadGripPointTypeEnum.VERTEX or \
                     gripPoint.gripType == qad_grip.QadGripPointTypeEnum.END_VERTEX:
                    ptList.append(gripPoint.getPoint())
                elif gripPoint.gripType == qad_grip.QadGripPointTypeEnum.ARC_MID_POINT:
                    ptList.append(gripPoint.getPoint())
            i = i + 1

        if len(ptList) > 0:
            self.selectedEntityGripPoints.append(
                [entityGripPoints.entity, ptList])

    #============================================================================
    # setSelectedEntityGripPoints
    #============================================================================
    def setSelectedEntityGripPoints(self, entitySetGripPoints):
        # lista delle entityGripPoint con dei grip point selezionati
        # ritorna una lista in cui ogni elemento è una entità + una lista di punti da stirare
        del self.selectedEntityGripPoints[:]  # svuoto la lista

        for entityGripPoints in entitySetGripPoints.entityGripPoints:
            self.addToSelectedEntityGripPoints(entityGripPoints)
        self.getPointMapTool().setSelectedEntityGripPoints(
            self.selectedEntityGripPoints)

        # input : self.basePt e entitySetGripPoints
        # cerco in entitySetGripPoints l'entità che ha un solo grip selezionato corrispondente a basePt
        entityGripPoints, entityGripPoint = entitySetGripPoints.isIntersecting(
            self.basePt)
        if entityGripPoint.getStatus() == qad_grip.QadGripStatusEnum.SELECTED and \
           len(entityGripPoints.getSelectedGripPoints()) == 1:

            entity = entityGripPoints.entity
            # verifico se l'entità appartiene ad uno stile di quotatura
            if QadDimStyles.isDimEntity(entity):
                pass
            else:
                qadGeom = entity.getQadGeom(entityGripPoint.atGeom,
                                            entityGripPoint.atSubGeom)
                qadGeomType = qadGeom.whatIs()
                if qadGeomType == "POLYLINE":
                    self.getPointMapTool().prevPart, self.getPointMapTool(
                    ).nextPart = qadGeom.getPrevNextLinearObjectsAtVertex(
                        entityGripPoint.nVertex)
                elif qadGeomType == "CIRCLE":
                    if qadGeom.isPtOnCircle(entityGripPoint.getPoint()):
                        line = QadLine()
                        line.set(qadGeom.center, entityGripPoint.getPoint())
                        self.getPointMapTool().prevPart = line
                elif qadGeomType == "ELLIPSE":
                    if qadGeom.containsPt(entityGripPoint.getPoint()):
                        line = QadLine()
                        line.set(qadGeom.center, entityGripPoint.getPoint())
                        self.getPointMapTool().prevPart = line

    #============================================================================
    # getSelectedEntityGripPointNdx
    #============================================================================
    def getSelectedEntityGripPointNdx(self, entity):
        # lista delle entityGripPoint con dei grip point selezionati
        # cerca la posizione di un'entità nella lista in cui ogni elemento è una entità + una lista di punti da stirare
        i = 0
        tot = len(self.selectedEntityGripPoints)
        while i < tot:
            selectedEntityGripPoint = self.selectedEntityGripPoints[i]
            if selectedEntityGripPoint[0] == entity:
                return i
            i = i + 1
        return -1

    #============================================================================
    # stretch
    #============================================================================
    def stretch(self, entity, ptList, offsetX, offsetY, tolerance2ApproxCurve):
        # entity = entità da stirare
        # ptList = lista dei punti da stirare
        # offsetX, offsetY = spostamento da applicare
        # tolerance2ApproxCurve = tolleranza per ricreare le curve

        if entity.whatIs() == "DIMENTITY":
            dimEntity = entity
        else:
            # verifico se l'entità appartiene ad uno stile di quotatura
            dimEntity = QadDimStyles.getDimEntity(entity)

        if dimEntity is None:
            stretchedGeom = entity.getQadGeom()
            # controllo inserito perchè con le quote, questa viene cancellata e ricreata quindi alcuni oggetti potrebbero non esistere più
            if stretchedGeom is None:  # se non c'è lo salto senza errore
                return True

            # stiro la feature
            stretchedGeom = qad_stretch_fun.stretchQadGeometry(stretchedGeom, ptList, \
                                                               offsetX, offsetY)

            if stretchedGeom is not None:
                # trasformo la geometria QAD in geometria GSIS nel crs del layer
                f = entity.getFeature()
                f.setGeometry(fromQadGeomToQgsGeom(stretchedGeom,
                                                   entity.crs()))
                if self.copyEntities == False:
                    # plugIn, layer, feature, refresh, check_validity
                    if qad_layer.updateFeatureToLayer(self.plugIn,
                                                      entity.layer, f, False,
                                                      False) == False:
                        return False
                else:
                    # plugIn, layer, features, coordTransform, refresh, check_validity
                    if qad_layer.addFeatureToLayer(self.plugIn, entity.layer,
                                                   f, None, False,
                                                   False) == False:
                        return False

        else:
            # stiro la quota
            if self.copyEntities == False:
                if dimEntity.deleteToLayers(self.plugIn) == False:
                    return False
            newDimEntity = QadDimEntity(dimEntity)  # la copio
            newDimEntity.stretch(ptList, offsetX, offsetY)
            if newDimEntity.addToLayers(self.plugIn) == False:
                return False
            # non so per quale motivo a volte non si aggiorna la mappa quindi forzo l'aggiornamento
            self.plugIn.canvas.refresh()

        return True

    #============================================================================
    # stretchFeatures
    #============================================================================
    def stretchFeatures(self, newPt):
        # mi ricavo un unico QadEntitySet con le entità selezionate
        entitySet = QadEntitySet()
        for selectedEntity in self.selectedEntityGripPoints:
            entitySet.addEntity(selectedEntity[0])
        self.plugIn.beginEditCommand("Feature stretched",
                                     entitySet.getLayerList())

        dimElaboratedList = []  # lista delle quotature già elaborate

        for selectedEntity in self.selectedEntityGripPoints:
            entity = selectedEntity[0]
            ptList = selectedEntity[1]
            layer = entity.layer

            tolerance2ApproxCurve = QadVariables.get(
                QadMsg.translate("Environment variables",
                                 "TOLERANCE2APPROXCURVE"))
            offsetX = newPt.x() - self.basePt.x()
            offsetY = newPt.y() - self.basePt.y()

            # verifico se l'entità appartiene ad uno stile di quotatura
            dimEntity = QadDimStyles.getDimEntity(entity)
            if dimEntity is None:
                if self.stretch(entity, ptList, offsetX, offsetY,
                                tolerance2ApproxCurve) == False:
                    self.plugIn.destroyEditCommand()
                    return
            else:
                found = False
                for dimElaborated in dimElaboratedList:
                    if dimElaborated == dimEntity:
                        found = True

                if found == False:  # quota non ancora elaborata
                    # aggiungo i layer dei componenti della quota
                    self.plugIn.addLayerListToLastEditCommand(
                        "Feature stretched", [
                            dimEntity.getSymbolLayer(),
                            dimEntity.getLinearLayer(),
                            dimEntity.getTextualLayer()
                        ])

                    dimEntitySet = dimEntity.getEntitySet()
                    # creo un'unica lista contenente i grip points di tutti i componenti della quota
                    dimPtlist = []
                    for layerEntitySet in dimEntitySet.layerEntitySetList:
                        for featureId in layerEntitySet.featureIds:
                            componentDim = QadEntity()
                            componentDim.set(layerEntitySet.layer, featureId)
                            i = self.getSelectedEntityGripPointNdx(
                                componentDim)
                            if i >= 0:
                                dimPtlist.extend(
                                    self.selectedEntityGripPoints[i][1])

                    dimElaboratedList.append(dimEntity)
                    if self.stretch(dimEntity, dimPtlist, offsetX, offsetY,
                                    tolerance2ApproxCurve) == False:
                        self.plugIn.destroyEditCommand()
                        return

        self.plugIn.endEditCommand()
        self.nOperationsToUndo = self.nOperationsToUndo + 1

    #============================================================================
    # waitForStretchPoint
    #============================================================================
    def waitForStretchPoint(self):
        self.step = 1
        self.plugIn.setLastPoint(self.basePt)
        # imposto il map tool
        self.getPointMapTool().basePt = self.basePt
        self.getPointMapTool().setMode(
            Qad_stretch_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_MOVE_PT)

        keyWords = QadMsg.translate("Command_GRIP", "Base point") + "/" + \
                   QadMsg.translate("Command_GRIP", "Copy") + "/" + \
                   QadMsg.translate("Command_GRIP", "Undo") + "/" + \
                   QadMsg.translate("Command_GRIP", "eXit")

        prompt = QadMsg.translate(
            "Command_GRIPSTRETCH",
            "Specify stretch point or [{0}]: ").format(keyWords)

        englishKeyWords = "Base point" + "/" + "Copy" + "/" + "Undo" + "/" + "eXit"
        keyWords += "_" + englishKeyWords
        # si appresta ad attendere un punto o enter o una parola chiave
        # msg, inputType, default, keyWords, nessun controllo
        self.waitFor(prompt, QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                     None, \
                     keyWords, QadInputModeEnum.NONE)

    #============================================================================
    # waitForBasePt
    #============================================================================
    def waitForBasePt(self):
        self.step = 2
        # imposto il map tool
        self.getPointMapTool().setMode(
            Qad_stretch_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_BASE_PT)

        # si appresta ad attendere un punto
        self.waitForPoint(
            QadMsg.translate("Command_GRIPSTRETCH", "Specify base point: "))

    #============================================================================
    # run
    #============================================================================
    def run(self, msgMapTool=False, msg=None):
        if self.plugIn.canvas.mapSettings().destinationCrs().isGeographic():
            self.showMsg(
                QadMsg.translate(
                    "QAD",
                    "\nThe coordinate reference system of the project must be a projected coordinate system.\n"
                ))
            return True  # fine comando

        #=========================================================================
        # RICHIESTA SELEZIONE OGGETTI
        if self.step == 0:  # inizio del comando
            if len(self.selectedEntityGripPoints
                   ) == 0:  # non ci sono oggetti da stirare
                return True
            self.showMsg(
                QadMsg.translate("Command_GRIPSTRETCH", "\n** STRETCH **\n"))
            # si appresta ad attendere un punto di stiramento
            self.waitForStretchPoint()
            return False

        #=========================================================================
        # RISPOSTA ALLA RICHIESTA DI UN PUNTO DI STIRAMENTO
        elif self.step == 1:
            ctrlKey = False
            if msgMapTool == True:  # il punto arriva da una selezione grafica
                # la condizione seguente si verifica se durante la selezione di un punto
                # é stato attivato un altro plugin che ha disattivato Qad
                # quindi stato riattivato il comando che torna qui senza che il maptool
                # abbia selezionato un punto
                if self.getPointMapTool(
                ).point is None:  # il maptool é stato attivato senza un punto
                    if self.getPointMapTool(
                    ).rightButton == True:  # se usato il tasto destro del mouse
                        value = None
                    else:
                        self.setMapTool(
                            self.getPointMapTool())  # riattivo il maptool
                        return False
                else:
                    value = self.getPointMapTool().point

                ctrlKey = self.getPointMapTool().ctrlKey
            else:  # il punto arriva come parametro della funzione
                value = msg

            if type(value) == unicode:
                if value == QadMsg.translate(
                        "Command_GRIP", "Base point") or value == "Base point":
                    # si appresta ad attendere il punto base
                    self.waitForBasePt()
                elif value == QadMsg.translate("Command_GRIP",
                                               "Copy") or value == "Copy":
                    # Copia entità lasciando inalterate le originali
                    self.copyEntities = True
                    # si appresta ad attendere un punto di stiramento
                    self.waitForStretchPoint()
                elif value == QadMsg.translate("Command_GRIP",
                                               "Undo") or value == "Undo":
                    if self.nOperationsToUndo > 0:
                        self.nOperationsToUndo = self.nOperationsToUndo - 1
                        self.plugIn.undoEditCommand()
                    else:
                        self.showMsg(
                            QadMsg.translate(
                                "QAD", "\nThe command has been canceled."))
                    # si appresta ad attendere un punto di stiramento
                    self.waitForStretchPoint()
                elif value == QadMsg.translate("Command_GRIP",
                                               "eXit") or value == "eXit":
                    return True  # fine comando
            elif type(value) == QgsPointXY:  # se é stato selezionato un punto
                if ctrlKey:
                    self.copyEntities = True

                self.stretchFeatures(value)

                if self.copyEntities == False:
                    return True
                # si appresta ad attendere un punto di stiramento
                self.waitForStretchPoint()

            else:
                if self.copyEntities == False:
                    self.skipToNextGripCommand = True
                return True  # fine comando

            return False

        #=========================================================================
        # RISPOSTA ALLA RICHIESTA PUNTO BASE (da step = 1)
        elif self.step == 2:  # dopo aver atteso un punto
            if msgMapTool == True:  # il punto arriva da una selezione grafica
                # la condizione seguente si verifica se durante la selezione di un punto
                # é stato attivato un altro plugin che ha disattivato Qad
                # quindi stato riattivato il comando che torna qui senza che il maptool
                # abbia selezionato un punto
                if self.getPointMapTool(
                ).point is None:  # il maptool é stato attivato senza un punto
                    if self.getPointMapTool(
                    ).rightButton == True:  # se usato il tasto destro del mouse
                        pass  # opzione di default "spostamento"
                    else:
                        self.setMapTool(
                            self.getPointMapTool())  # riattivo il maptool
                        return False

                value = self.getPointMapTool().point
            else:  # il punto arriva come parametro della funzione
                value = msg

            if type(value) == QgsPointXY:  # se é stato inserito il punto base
                self.basePt.set(value.x(), value.y())
                # imposto il map tool
                self.getPointMapTool().basePt = self.basePt

            # si appresta ad attendere un punto di stiramento
            self.waitForStretchPoint()

            return False
Ejemplo n.º 4
0
class QadGRIPROTATECommandClass(QadCommandClass):
    def instantiateNewCmd(self):
        """ istanzia un nuovo comando dello stesso tipo """
        return QadGRIPROTATECommandClass(self.plugIn)

    def __init__(self, plugIn):
        QadCommandClass.__init__(self, plugIn)
        self.cacheEntitySet = QadCacheEntitySet()
        self.basePt = QgsPointXY()
        self.skipToNextGripCommand = False
        self.copyEntities = False
        self.nOperationsToUndo = 0
        self.Pt1ReferenceAng = None
        self.ReferenceAng = 0

    def __del__(self):
        QadCommandClass.__del__(self)

    def getPointMapTool(self, drawMode=QadGetPointDrawModeEnum.NONE):
        if (self.plugIn is not None):
            if self.PointMapTool is None:
                self.PointMapTool = Qad_rotate_maptool(self.plugIn)
            return self.PointMapTool
        else:
            return None

    #============================================================================
    # setSelectedEntityGripPoints
    #============================================================================
    def setSelectedEntityGripPoints(self, entitySetGripPoints):
        # lista delle entityGripPoint con dei grip point selezionati
        self.cacheEntitySet.clear()

        for entityGripPoints in entitySetGripPoints.entityGripPoints:
            self.cacheEntitySet.appendEntity(entityGripPoints.entity)

        self.getPointMapTool().cacheEntitySet = self.cacheEntitySet

    #============================================================================
    # rotate
    #============================================================================
    def rotate(self, entity, basePt, angle, rotFldName):
        # entity = entità da ruotare
        # basePt = punto base
        # angle = angolo di rotazione in gradi
        # verifico se l'entità appartiene ad uno stile di quotatura
        if entity.whatIs() == "ENTITY":
            # ruoto la geometria dell'entità
            qadGeom = entity.getQadGeom().copy()  # la copio
            qadGeom.rotate(basePt, angle)
            f = entity.getFeature()
            f.setGeometry(fromQadGeomToQgsGeom(qadGeom, entity.crs()))

            if entity.rotFldName is not None:
                rotValue = f.attribute(entity.rotFldName)
                # a volte vale None e a volte null (vai a capire...)
                rotValue = 0 if rotValue is None or isinstance(
                    rotValue, QPyNullVariant) else qad_utils.toRadians(
                        rotValue
                    )  # la rotazione é in gradi nel campo della feature
                rotValue = rotValue + angle
                f.setAttribute(
                    entity.rotFldName,
                    qad_utils.toDegrees(qad_utils.normalizeAngle(rotValue)))

            if self.copyEntities == False:
                # plugIn, layer, feature, refresh, check_validity
                if qad_layer.updateFeatureToLayer(self.plugIn, entity.layer, f,
                                                  False, False) == False:
                    return False
            else:
                # plugIn, layer, features, coordTransform, refresh, check_validity
                if qad_layer.addFeatureToLayer(self.plugIn, entity.layer, f,
                                               None, False, False) == False:
                    return False

        elif entity.whatIs() == "DIMENTITY":
            # stiro la quota
            if self.copyEntities == False:
                if entity.deleteToLayers(self.plugIn) == False:
                    return False
            newDimEntity = QadDimEntity(entity)  # la copio
            newDimEntity.rotate(basePt, angle)
            if newDimEntity.addToLayers(self.plugIn) == False:
                return False

        return True

    #============================================================================
    # rotateFeatures
    #============================================================================
    def rotateFeatures(self, angle):
        self.plugIn.beginEditCommand("Feature rotated",
                                     self.cacheEntitySet.getLayerList())

        entityIterator = QadCacheEntitySetIterator(self.cacheEntitySet)
        for entity in entityIterator:
            qadGeom = entity.getQadGeom()  # così inizializzo le info qad
            # verifico se l'entità appartiene ad uno stile di quotatura
            dimEntity = QadDimStyles.getDimEntity(entity)
            if dimEntity is not None:
                if appendDimEntityIfNotExisting(
                        dimElaboratedList,
                        dimEntity) == False:  # quota già elaborata
                    continue
                entity = dimEntity

            if self.rotate(entity, self.basePt, angle) == False:
                self.plugIn.destroyEditCommand()
                return

        self.plugIn.endEditCommand()
        self.nOperationsToUndo = self.nOperationsToUndo + 1

    #============================================================================
    # waitForRotatePoint
    #============================================================================
    def waitForRotatePoint(self):
        self.step = 1
        self.plugIn.setLastPoint(self.basePt)
        # imposto il map tool
        self.getPointMapTool().basePt = self.basePt
        self.getPointMapTool().setMode(
            Qad_rotate_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_NEW_ROTATION_PT)

        keyWords = QadMsg.translate("Command_GRIPROTATE", "Base point") + "/" + \
                   QadMsg.translate("Command_GRIPROTATE", "Copy") + "/" + \
                   QadMsg.translate("Command_GRIPROTATE", "Undo") + "/" + \
                   QadMsg.translate("Command_GRIPROTATE", "Reference") + "/" + \
                   QadMsg.translate("Command_GRIPROTATE", "eXit")

        prompt = QadMsg.translate(
            "Command_GRIPROTATE",
            "Specify rotation angle or [{0}]: ").format(keyWords)

        englishKeyWords = "Base point" + "/" + "Copy" + "/" + "Undo" + "/" + "Reference" + "/" + "eXit"
        keyWords += "_" + englishKeyWords
        # si appresta ad attendere un punto, un numero reale o enter o una parola chiave
        # msg, inputType, default, keyWords, nessun controllo
        self.waitFor(prompt, QadInputTypeEnum.POINT2D | QadInputTypeEnum.ANGLE | QadInputTypeEnum.KEYWORDS, \
                     None, \
                     keyWords, QadInputModeEnum.NONE)

    #============================================================================
    # waitForBasePt
    #============================================================================
    def waitForBasePt(self):
        self.step = 2
        # imposto il map tool
        self.getPointMapTool().setMode(
            Qad_rotate_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_BASE_PT)

        # si appresta ad attendere un punto
        self.waitForPoint(
            QadMsg.translate("Command_GRIPROTATE", "Specify base point: "))

    def waitForReferenceRot(self):
        # imposto il map tool
        self.getPointMapTool().setMode(
            Qad_rotate_maptool_ModeEnum.ASK_FOR_FIRST_PT_REFERENCE_ANG)

        msg = QadMsg.translate("Command_GRIPROTATE",
                               "Specify reference angle <{0}>: ")
        # si appresta ad attendere un punto o enter o una parola chiave
        # msg, inputType, default, keyWords, nessun controllo
        self.waitFor(msg.format(str(qad_utils.toDegrees(self.plugIn.lastReferenceRot))), \
                     QadInputTypeEnum.POINT2D | QadInputTypeEnum.ANGLE, \
                     self.plugIn.lastReferenceRot, \
                     "")
        self.step = 3

    #============================================================================
    # run
    #============================================================================
    def run(self, msgMapTool=False, msg=None):
        if self.plugIn.canvas.mapSettings().destinationCrs().isGeographic():
            self.showMsg(
                QadMsg.translate(
                    "QAD",
                    "\nThe coordinate reference system of the project must be a projected coordinate system.\n"
                ))
            return True  # fine comando

        #=========================================================================
        # RICHIESTA SELEZIONE OGGETTI
        if self.step == 0:  # inizio del comando
            if self.cacheEntitySet.isEmpty():  # non ci sono oggetti da ruotare
                return True
            self.showMsg(
                QadMsg.translate("Command_GRIPROTATE", "\n** ROTATE **\n"))
            # si appresta ad attendere un punto di rotazione
            self.waitForRotatePoint()
            return False

        #=========================================================================
        # RISPOSTA ALLA RICHIESTA DI UN PUNTO DI ROTAZIONE
        elif self.step == 1:
            ctrlKey = False
            if msgMapTool == True:  # il punto arriva da una selezione grafica
                # la condizione seguente si verifica se durante la selezione di un punto
                # é stato attivato un altro plugin che ha disattivato Qad
                # quindi stato riattivato il comando che torna qui senza che il maptool
                # abbia selezionato un punto
                if self.getPointMapTool(
                ).point is None:  # il maptool é stato attivato senza un punto
                    if self.getPointMapTool(
                    ).rightButton == True:  # se usato il tasto destro del mouse
                        value = None
                    else:
                        self.setMapTool(
                            self.getPointMapTool())  # riattivo il maptool
                        return False
                else:
                    value = self.getPointMapTool().point

                ctrlKey = self.getPointMapTool().ctrlKey
            else:  # il punto arriva come parametro della funzione
                value = msg

            if type(value) == unicode:
                if value == QadMsg.translate(
                        "Command_GRIPROTATE",
                        "Base point") or value == "Base point":
                    # si appresta ad attendere il punto base
                    self.waitForBasePt()
                elif value == QadMsg.translate("Command_GRIPROTATE",
                                               "Copy") or value == "Copy":
                    # Copia entità lasciando inalterate le originali
                    self.copyEntities = True
                    # si appresta ad attendere un punto di rotazione
                    self.waitForRotatePoint()
                elif value == QadMsg.translate("Command_GRIPROTATE",
                                               "Undo") or value == "Undo":
                    if self.nOperationsToUndo > 0:
                        self.nOperationsToUndo = self.nOperationsToUndo - 1
                        self.plugIn.undoEditCommand()
                    else:
                        self.showMsg(
                            QadMsg.translate(
                                "QAD", "\nThe command has been canceled."))
                    # si appresta ad attendere un punto di rotazione
                    self.waitForRotatePoint()
                elif value == QadMsg.translate(
                        "Command_GRIPROTATE",
                        "Reference") or value == "Reference":
                    # si appresta ad attendere l'angolo di riferimento
                    self.waitForReferenceRot()
                elif value == QadMsg.translate("Command_GRIPROTATE",
                                               "eXit") or value == "eXit":
                    return True  # fine comando
            elif type(value) == QgsPointXY or type(
                    value
            ) == float:  # se é stato inserito l'angolo di rotazione
                if type(
                        value
                ) == QgsPointXY:  # se é stato inserito l'angolo di rotazione con un punto
                    angle = qad_utils.getAngleBy2Pts(self.basePt, value)
                else:
                    angle = qad_utils.toRadians(value)
                angle = angle - self.ReferenceAng
                self.plugIn.setLastRot(angle)

                if ctrlKey:
                    self.copyEntities = True

                self.rotateFeatures(angle)

                if self.copyEntities == False:
                    return True

                # si appresta ad attendere un punto di rotazione
                self.waitForRotatePoint()

            else:
                if self.copyEntities == False:
                    self.skipToNextGripCommand = True
                return True  # fine comando

            return False

        #=========================================================================
        # RISPOSTA ALLA RICHIESTA PUNTO BASE (da step = 1)
        elif self.step == 2:  # dopo aver atteso un punto
            if msgMapTool == True:  # il punto arriva da una selezione grafica
                # la condizione seguente si verifica se durante la selezione di un punto
                # é stato attivato un altro plugin che ha disattivato Qad
                # quindi stato riattivato il comando che torna qui senza che il maptool
                # abbia selezionato un punto
                if self.getPointMapTool(
                ).point is None:  # il maptool é stato attivato senza un punto
                    if self.getPointMapTool(
                    ).rightButton == True:  # se usato il tasto destro del mouse
                        pass  # opzione di default "spostamento"
                    else:
                        self.setMapTool(
                            self.getPointMapTool())  # riattivo il maptool
                        return False

                value = self.getPointMapTool().point
            else:  # il punto arriva come parametro della funzione
                value = msg

            if type(value) == QgsPointXY:  # se é stato inserito il punto base
                self.basePt.set(value.x(), value.y())
                # imposto il map tool
                self.getPointMapTool().basePt = self.basePt

            # si appresta ad attendere un punto di rotazione
            self.waitForRotatePoint()

            return False

        #=========================================================================
        # RISPOSTA ALLA RICHIESTA PRIMO PUNTO PER ANGOLO ROTAZIONE DI RIFERIMENTO (da step = 1)
        elif self.step == 3:  # dopo aver atteso un punto o un numero reale si riavvia il comando
            if msgMapTool == True:  # il punto arriva da una selezione grafica
                # la condizione seguente si verifica se durante la selezione di un punto
                # é stato attivato un altro plugin che ha disattivato Qad
                # quindi stato riattivato il comando che torna qui senza che il maptool
                # abbia selezionato un punto
                if self.getPointMapTool(
                ).point is None:  # il maptool é stato attivato senza un punto
                    if self.getPointMapTool(
                    ).rightButton == True:  # se usato il tasto destro del mouse
                        return True  # fine comando
                    else:
                        self.setMapTool(
                            self.getPointMapTool())  # riattivo il maptool
                        return False

                value = self.getPointMapTool().point
            else:  # il punto arriva come parametro della funzione
                value = msg

            if type(value
                    ) == float:  # se é stato inserito l'angolo di rotazione
                self.ReferenceAng = qad_utils.toRadians(value)
                self.getPointMapTool().ReferenceAng = self.ReferenceAng
                # si appresta ad attendere un punto di rotazione
                self.waitForRotatePoint()

            elif type(
                    value
            ) == QgsPointXY:  # se é stato inserito l'angolo di rotazione con un punto
                self.Pt1ReferenceAng = QgsPointXY(value)
                self.getPointMapTool().Pt1ReferenceAng = self.Pt1ReferenceAng
                # imposto il map tool
                self.getPointMapTool().setMode(
                    Qad_rotate_maptool_ModeEnum.
                    FIRST_PT_KNOWN_ASK_FOR_SECOND_PT_REFERENCE_ANG)
                # si appresta ad attendere un punto
                self.waitForPoint(
                    QadMsg.translate("Command_GRIPROTATE",
                                     "Specify second point: "))
                self.step = 4

            return False

        #=========================================================================
        # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER NUOVO ANGOLO ROTAZIONE (da step = 3)
        elif self.step == 4:  # dopo aver atteso un punto o un numero reale si riavvia il comando
            if msgMapTool == True:  # il punto arriva da una selezione grafica
                # la condizione seguente si verifica se durante la selezione di un punto
                # é stato attivato un altro plugin che ha disattivato Qad
                # quindi stato riattivato il comando che torna qui senza che il maptool
                # abbia selezionato un punto
                if self.getPointMapTool(
                ).point is None:  # il maptool é stato attivato senza un punto
                    if self.getPointMapTool(
                    ).rightButton == True:  # se usato il tasto destro del mouse
                        return True  # fine comando
                    else:
                        self.setMapTool(
                            self.getPointMapTool())  # riattivo il maptool
                        return False

                value = self.getPointMapTool().point
            else:  # il punto arriva come parametro della funzione
                value = msg

            if type(value) == QgsPointXY or type(
                    value
            ) == float:  # se é stato inserito l'angolo di rotazione
                if type(
                        value
                ) == QgsPointXY:  # se é stato inserito l'angolo di rotazione con un punto
                    self.ReferenceAng = qad_utils.getAngleBy2Pts(
                        self.Pt1ReferenceAng, value)
                else:
                    self.ReferenceAng = qad_utils.toRadians(value)
                self.getPointMapTool().ReferenceAng = self.ReferenceAng

            # si appresta ad attendere un punto di rotazione
            self.waitForRotatePoint()

            return False
Ejemplo n.º 5
0
class QadSTRETCHCommandClass(QadCommandClass):
    def instantiateNewCmd(self):
        """ istanzia un nuovo comando dello stesso tipo """
        return QadSTRETCHCommandClass(self.plugIn)

    def getName(self):
        return QadMsg.translate("Command_list", "STRETCH")

    def getEnglishName(self):
        return "STRETCH"

    def connectQAction(self, action):
        action.triggered.connect(self.plugIn.runSTRETCHCommand)

    def getIcon(self):
        return QIcon(":/plugins/qad/icons/stretch.png")

    def getNote(self):
        # impostare le note esplicative del comando
        return QadMsg.translate("Command_STRETCH", "Stretches objects.")

    def __init__(self, plugIn):
        QadCommandClass.__init__(self, plugIn)
        self.AddOnSelection = True  # se = False significa remove
        self.points = []
        self.MPOLYGONCommand = None
        self.SSGeomList = [
        ]  # lista di entità da stirare con geom di selezione
        self.basePt = QgsPointXY()

    def __del__(self):
        QadCommandClass.__del__(self)
        if self.MPOLYGONCommand is not None:
            del self.MPOLYGONCommand
        for SSGeom in self.SSGeomList:
            SSGeom[0].deselectOnLayer()

    def getPointMapTool(self, drawMode=QadGetPointDrawModeEnum.NONE):
        if self.step == 2:  # quando si é in fase di disegno linea
            return self.MPOLYGONCommand.getPointMapTool(drawMode)
        else:
            if (self.plugIn is not None):
                if self.PointMapTool is None:
                    self.PointMapTool = Qad_stretch_maptool(self.plugIn)
                return self.PointMapTool
            else:
                return None

    def getCurrentContextualMenu(self):
        if self.step == 2:  # quando si é in fase di disegno linea
            return self.MPOLYGONCommand.getCurrentContextualMenu()
        else:
            return self.contextualMenu

    def stretch(self, entity, containerGeom, offsetX, offsetY,
                tolerance2ApproxCurve):
        # entity = entità da stirare
        # ptList = lista dei punti da stirare
        # offsetX, offsetY = spostamento da applicare
        # tolerance2ApproxCurve = tolleranza per ricreare le curve

        if entity.whatIs() == "DIMENTITY":
            dimEntity = entity
        else:
            # verifico se l'entità appartiene ad uno stile di quotatura
            dimEntity = QadDimStyles.getDimEntity(entity)

        if dimEntity is None:
            stretchedGeom = entity.getQadGeom()
            # controllo inserito perchè con le quote, questa viene cancellata e ricreata quindi alcuni oggetti potrebbero non esistere più
            if stretchedGeom is None:  # se non c'è lo salto senza errore
                return True
            # stiro la feature
            stretchedGeom = qad_stretch_fun.stretchQadGeometry(stretchedGeom, containerGeom, \
                                                               offsetX, offsetY)

            if stretchedGeom is not None:
                # trasformo la geometria nel crs del layer
                f = entity.getFeature()
                f.setGeometry(fromQadGeomToQgsGeom(stretchedGeom,
                                                   entity.crs()))
                # plugIn, layer, feature, refresh, check_validity
                if qad_layer.updateFeatureToLayer(self.plugIn, entity.layer, f,
                                                  False, False) == False:
                    return False

        else:
            # stiro la quota
            if dimEntity.deleteToLayers(self.plugIn) == False:
                return False
            newDimEntity = QadDimEntity(dimEntity)  # la copio
            newDimEntity.stretch(containerGeom, offsetX, offsetY)
            if newDimEntity.addToLayers(self.plugIn) == False:
                return False

        return True

    #============================================================================
    # stretchFeatures
    #============================================================================
    def stretchFeatures(self, newPt):
        # mi ricavo un unico QadEntitySet con le entità selezionate
        entitySet = QadEntitySet()
        for SSGeom in self.SSGeomList:
            entitySet.unite(SSGeom[0])
        self.plugIn.beginEditCommand("Feature stretched",
                                     entitySet.getLayerList())

        dimElaboratedList = []  # lista delle quotature già elaborate

        tolerance2ApproxCurve = QadVariables.get(
            QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
        offsetX = newPt.x() - self.basePt.x()
        offsetY = newPt.y() - self.basePt.y()

        entity = QadEntity()
        for SSGeom in self.SSGeomList:
            # copio entitySet
            entitySet = QadEntitySet(SSGeom[0])
            geomSel = SSGeom[1]

            for layerEntitySet in entitySet.layerEntitySetList:
                layer = layerEntitySet.layer

                for featureId in layerEntitySet.featureIds:
                    entity.set(layer, featureId)

                    # verifico se l'entità appartiene ad uno stile di quotatura
                    dimEntity = QadDimStyles.getDimEntity(entity)
                    if dimEntity is None:
                        if self.stretch(entity, geomSel, offsetX, offsetY,
                                        tolerance2ApproxCurve) == False:
                            self.plugIn.destroyEditCommand()
                            return
                    else:
                        found = False
                        for dimElaborated in dimElaboratedList:
                            if dimElaborated == dimEntity:
                                found = True

                        if found == False:  # quota non ancora elaborata
                            # aggiungo i layer dei componenti della quota
                            self.plugIn.addLayerListToLastEditCommand(
                                "Feature stretched", [
                                    dimEntity.getSymbolLayer(),
                                    dimEntity.getLinearLayer(),
                                    dimEntity.getTextualLayer()
                                ])

                            dimElaboratedList.append(dimEntity)
                            if self.stretch(dimEntity, geomSel, offsetX,
                                            offsetY,
                                            tolerance2ApproxCurve) == False:
                                self.plugIn.destroyEditCommand()
                                return

        self.plugIn.endEditCommand()

    #============================================================================
    # setEntitySetGeom
    #============================================================================
    def setEntitySetGeom(self, entitySet, selGeom):
        for SSGeom in self.SSGeomList:
            SSGeom[0].deselectOnLayer()
        del self.SSGeomList[:]  # svuoto la lista
        # aggiuge il gruppo di selezione con la geometria usata per la selezione
        self.SSGeomList.append([entitySet, selGeom])
        entitySet.selectOnLayer(False)  # incremental = False

    #============================================================================
    # addEntitySetGeom
    #============================================================================
    def addEntitySetGeom(self, entitySet, selGeom):
        # elimino dai gruppi precedenti gli oggetti presenti in entitySet
        self.removeEntitySet(entitySet)
        # aggiuge il gruppo di selezione con la geometria usata per la selezione
        self.SSGeomList.append([entitySet, selGeom])
        entitySet.selectOnLayer(True)  # incremental = True

    #============================================================================
    # removeEntitySet
    #============================================================================
    def removeEntitySet(self, entitySet):
        # elimino dai gruppi precedenti gli oggetti presenti in entitySet
        for SSGeom in self.SSGeomList:
            SSGeom[0].subtract(entitySet)
        for SSGeom in self.SSGeomList:
            SSGeom[0].selectOnLayer(False)  # incremental = False

    #============================================================================
    # SSGeomListIsEmpty
    #============================================================================
    def SSGeomListIsEmpty(self):
        if len(self.SSGeomList) == 0:
            return True
        for SSGeom in self.SSGeomList:
            if SSGeom[0].isEmpty() == False:
                return False
        return True

    #============================================================================
    # waitForObjectSel
    #============================================================================
    def waitForObjectSel(self):
        self.step = 1
        # imposto il map tool
        self.getPointMapTool().setMode(
            Qad_stretch_maptool_ModeEnum.ASK_FOR_FIRST_PT_RECTANGLE)

        keyWords = QadMsg.translate("Command_STRETCH", "Polygon") + "/" + \
                   QadMsg.translate("Command_STRETCH", "Add") + "/" + \
                   QadMsg.translate("Command_STRETCH", "Remove")

        if self.AddOnSelection == True:
            prompt = QadMsg.translate("Command_STRETCH", "Select vertices")
        else:
            prompt = QadMsg.translate("Command_STRETCH", "Remove vertices")
        prompt = prompt + QadMsg.translate(
            "Command_STRETCH",
            " to stretch crossed by a selection window or [{0}]: ").format(
                keyWords)

        englishKeyWords = "Polygon" + "/" + "Add" + "/" + "Remove"
        keyWords += "_" + englishKeyWords
        # si appresta ad attendere un punto o enter o una parola chiave
        # msg, inputType, default, keyWords, nessun controllo
        self.waitFor(prompt, QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                     None, \
                     keyWords, QadInputModeEnum.NONE)

    #============================================================================
    # waitForBasePt
    #============================================================================
    def waitForBasePt(self):
        self.step = 4
        # imposto il map tool
        self.getPointMapTool().setMode(
            Qad_stretch_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_BASE_PT)

        keyWords = QadMsg.translate("Command_STRETCH", "Displacement")
        prompt = QadMsg.translate(
            "Command_STRETCH",
            "Specify base point or [{0}] <{0}>: ").format(keyWords)

        englishKeyWords = "Displacement"
        keyWords += "_" + englishKeyWords
        # si appresta ad attendere un punto o enter o una parola chiave
        # msg, inputType, default, keyWords, nessun controllo
        self.waitFor(prompt, \
                     QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                     None, \
                     keyWords, QadInputModeEnum.NONE)

    #============================================================================
    # run
    #============================================================================
    def run(self, msgMapTool=False, msg=None):
        if self.plugIn.canvas.mapSettings().destinationCrs().isGeographic():
            self.showMsg(
                QadMsg.translate(
                    "QAD",
                    "\nThe coordinate reference system of the project must be a projected coordinate system.\n"
                ))
            return True  # fine comando

        #=========================================================================
        # RICHIESTA SELEZIONE OGGETTI
        if self.step == 0:  # inizio del comando
            # si appresta ad attendere la selezione degli oggetti da stirare
            self.waitForObjectSel()
            return False

        #=========================================================================
        # RISPOSTA ALLA SELEZIONE OGGETTI DA STIRARE
        elif self.step == 1:
            if msgMapTool == True:  # il punto arriva da una selezione grafica
                # la condizione seguente si verifica se durante la selezione di un punto
                # é stato attivato un altro plugin che ha disattivato Qad
                # quindi stato riattivato il comando che torna qui senza che il maptool
                # abbia selezionato un punto
                if self.getPointMapTool(
                ).point is None:  # il maptool é stato attivato senza un punto
                    if self.getPointMapTool(
                    ).rightButton == True:  # se usato il tasto destro del mouse
                        value = None
                    else:
                        self.setMapTool(
                            self.getPointMapTool())  # riattivo il maptool
                        return False
                else:
                    value = self.getPointMapTool().point
            else:  # il punto arriva come parametro della funzione
                value = msg

            if type(value) == unicode:
                if value == QadMsg.translate("Command_STRETCH",
                                             "Polygon") or value == "Polygon":
                    # Seleziona tutti gli oggetti che sono interni al poligono
                    self.MPOLYGONCommand = QadMPOLYGONCommandClass(self.plugIn)
                    # se questo flag = True il comando serve all'interno di un altro comando per disegnare una linea
                    # che non verrà salvata su un layer
                    self.MPOLYGONCommand.virtualCmd = True
                    self.MPOLYGONCommand.run(msgMapTool, msg)
                    self.step = 2
                    return False
                elif value == QadMsg.translate("Command_SSGET",
                                               "Add") or value == "Add":
                    # Passa al metodo Aggiungi: gli oggetti selezionati possono essere aggiunti al gruppo di selezione
                    self.AddOnSelection = True
                elif value == QadMsg.translate("Command_SSGET",
                                               "Remove") or value == "Remove":
                    # Passa al metodo Rimuovi: gli oggetti possono essere rimossi dal gruppo di selezione
                    self.AddOnSelection = False
            elif type(value) == QgsPointXY:  # se é stato selezionato un punto
                del self.points[:]  # svuoto la lista
                self.points.append(value)
                # imposto il map tool
                self.getPointMapTool().setMode(
                    Qad_stretch_maptool_ModeEnum.
                    FIRST_PT_KNOWN_ASK_FOR_SECOND_PT_RECTANGLE)
                self.getPointMapTool().setStartPoint(value)

                # si appresta ad attendere un punto
                self.waitForPoint(
                    QadMsg.translate("Command_STRETCH",
                                     "Specify opposite corner: "))
                self.step = 3
                return False
            else:
                if self.SSGeomListIsEmpty():
                    return True
                # si appresta ad attendere il punto base o lo spostamento
                self.waitForBasePt()
                return False

            # si appresta ad attendere la selezione degli oggetti da stirare
            self.waitForObjectSel()

            return False

        #=========================================================================
        # RISPOSTA ALLA RICHIESTA PUNTO PER MODALITA' POLIGONO (da step = 1)
        elif self.step == 2:  # dopo aver atteso un punto si riavvia il comando
            if self.MPOLYGONCommand.run(msgMapTool, msg) == True:
                if self.MPOLYGONCommand.polyline.qty() > 0:
                    # cerco tutte le geometrie intersecanti il poligono
                    # e considerando solo layer editabili
                    selSet = getSelSet("CP", self.getPointMapTool(), self.MPOLYGONCommand.PLINECommand.polyline.asPolyline(), \
                                       None, True, True, True, \
                                       True)
                    # se la selezione é avvenuta con shift premuto o se si deve rimuovere il gruppo selSet dal gruppo
                    if self.AddOnSelection == False:
                        self.removeEntitySet(selSet)
                    else:
                        self.setEntitySetGeom(
                            selSet,
                            QgsGeometry.fromPolygonXY([
                                self.MPOLYGONCommand.PLINECommand.polyline.
                                asPolyline()
                            ]))

                del self.MPOLYGONCommand
                self.MPOLYGONCommand = None

                # si appresta ad attendere la selezione degli oggetti da stirare
                self.waitForObjectSel()
                self.getPointMapTool().refreshSnapType(
                )  # aggiorno lo snapType che può essere variato dal maptool di mpolygon
            return False

        #=========================================================================
        # RISPOSTA ALLA RICHIESTA PUNTO PER MODALITA' FINESTRA (da step = 1)
        elif self.step == 3:  # dopo aver atteso un punto si riavvia il comando
            if msgMapTool == True:  # il punto arriva da una selezione grafica
                # la condizione seguente si verifica se durante la selezione di un punto
                # é stato attivato un altro plugin che ha disattivato Qad
                # quindi stato riattivato il comando che torna qui senza che il maptool
                # abbia selezionato un punto
                if self.getPointMapTool(
                ).point is None:  # il maptool é stato attivato senza un punto
                    if self.getPointMapTool(
                    ).rightButton == True:  # se usato il tasto destro del mouse
                        self.showMsg(
                            QadMsg.translate("Command_STRETCH",
                                             "Window not correct."))
                        # si appresta ad attendere un punto
                        self.waitForPoint(
                            QadMsg.translate("Command_STRETCH",
                                             "Specify opposite corner: "))
                        return False
                    else:
                        self.setMapTool(
                            self.getPointMapTool())  # riattivo il maptool
                        return False

                shiftKey = self.getPointMapTool().shiftKey
                value = self.getPointMapTool().point
            else:  # il punto arriva come parametro della funzione
                shiftKey = False
                value = msg

            if type(value) == QgsPointXY:
                self.points.append(value)
                # cerco tutte le geometrie intersecanti il rettangolo
                # e considerando solo layer editabili
                selSet = getSelSet("C", self.getPointMapTool(), self.points, \
                                   None, True, True, True, \
                                   True)
                # se si deve rimuovere il gruppo entitySet dal gruppo
                if self.AddOnSelection == False:
                    self.removeEntitySet(selSet)
                else:
                    if shiftKey:  # se la selezione é avvenuta con shift premuto
                        self.addEntitySetGeom(
                            selSet,
                            QgsGeometry.fromRect(
                                QgsRectangle(self.points[0], self.points[1])))
                    else:
                        self.setEntitySetGeom(
                            selSet,
                            QgsGeometry.fromRect(
                                QgsRectangle(self.points[0], self.points[1])))
                # si appresta ad attendere la selezione degli oggetti da stirare
                self.waitForObjectSel()
            return False

        #=========================================================================
        # RISPOSTA ALLA RICHIESTA PUNTO BASE (da step = 1)
        elif self.step == 4:  # dopo aver atteso un punto o un numero reale si riavvia il comando
            if msgMapTool == True:  # il punto arriva da una selezione grafica
                # la condizione seguente si verifica se durante la selezione di un punto
                # é stato attivato un altro plugin che ha disattivato Qad
                # quindi stato riattivato il comando che torna qui senza che il maptool
                # abbia selezionato un punto
                if self.getPointMapTool(
                ).point is None:  # il maptool é stato attivato senza un punto
                    if self.getPointMapTool(
                    ).rightButton == True:  # se usato il tasto destro del mouse
                        pass  # opzione di default "spostamento"
                    else:
                        self.setMapTool(
                            self.getPointMapTool())  # riattivo il maptool
                        return False

                value = self.getPointMapTool().point
            else:  # il punto arriva come parametro della funzione
                value = msg

            # imposto il map tool
            self.getPointMapTool().SSGeomList = self.SSGeomList

            if value is None or type(value) == unicode:
                self.basePt.set(0, 0)
                self.getPointMapTool().basePt = self.basePt
                self.getPointMapTool().setMode(
                    Qad_stretch_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_MOVE_PT)
                # si appresta ad attendere un punto
                msg = QadMsg.translate(
                    "Command_STRETCH",
                    "Specify the displacement from the origin point 0,0 <{0}, {1}>: "
                )
                # msg, inputType, default, keyWords, nessun controllo
                self.waitFor(msg.format(str(self.plugIn.lastOffsetPt.x()), str(self.plugIn.lastOffsetPt.y())), \
                             QadInputTypeEnum.POINT2D, \
                             self.plugIn.lastOffsetPt, \
                             "", QadInputModeEnum.NONE)
                self.step = 5
            elif type(
                    value) == QgsPointXY:  # se é stato inserito il punto base
                self.basePt.set(value.x(), value.y())

                # imposto il map tool
                self.getPointMapTool().basePt = self.basePt
                self.getPointMapTool().setMode(
                    Qad_stretch_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_MOVE_PT)

                # si appresta ad attendere un punto o enter o una parola chiave
                # msg, inputType, default, keyWords, nessun controllo
                self.waitFor(QadMsg.translate("Command_STRETCH", "Specify second point or <use first point as displacement from origin point 0,0>: "), \
                             QadInputTypeEnum.POINT2D, \
                             None, \
                             "", QadInputModeEnum.NONE)
                self.step = 6

            return False

        #=========================================================================
        # RISPOSTA ALLA RICHIESTA DEL PUNTO DI SPOSTAMENTO (da step = 2)
        elif self.step == 5:  # dopo aver atteso un punto o un numero reale si riavvia il comando
            if msgMapTool == True:  # il punto arriva da una selezione grafica
                # la condizione seguente si verifica se durante la selezione di un punto
                # é stato attivato un altro plugin che ha disattivato Qad
                # quindi stato riattivato il comando che torna qui senza che il maptool
                # abbia selezionato un punto
                if self.getPointMapTool(
                ).point is None:  # il maptool é stato attivato senza un punto
                    if self.getPointMapTool(
                    ).rightButton == True:  # se usato il tasto destro del mouse
                        return True  # fine comando
                    else:
                        self.setMapTool(
                            self.getPointMapTool())  # riattivo il maptool
                        return False

                value = self.getPointMapTool().point
            else:  # il punto arriva come parametro della funzione
                value = msg

            self.plugIn.setLastOffsetPt(value)
            self.stretchFeatures(value)
            return True  # fine comando

        #=========================================================================
        # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER SPOSTAMENTO (da step = 2)
        elif self.step == 6:  # dopo aver atteso un punto o un numero reale si riavvia il comando
            if msgMapTool == True:  # il punto arriva da una selezione grafica
                # la condizione seguente si verifica se durante la selezione di un punto
                # é stato attivato un altro plugin che ha disattivato Qad
                # quindi stato riattivato il comando che torna qui senza che il maptool
                # abbia selezionato un punto
                if self.getPointMapTool(
                ).point is None:  # il maptool é stato attivato senza un punto
                    if self.getPointMapTool(
                    ).rightButton == True:  # se usato il tasto destro del mouse
                        return True  # fine comando
                    else:
                        self.setMapTool(
                            self.getPointMapTool())  # riattivo il maptool
                        return False

                value = self.getPointMapTool().point
            else:  # il punto arriva come parametro della funzione
                value = msg

            if value is None:
                newPt = QgsPointXY(self.basePt.x() * 2, self.basePt.y() * 2)
                self.stretchFeatures(newPt)
            elif type(
                    value
            ) == QgsPointXY:  # se é stato inserito lo spostamento con un punto
                self.stretchFeatures(value)

            return True  # fine comando