Example #1
0
    def save(self,
             path,
             filetype=None,
             title=None,
             description=None,
             svg_dpi=SVG_INKSCAPE):
        if path is None or not isinstance(path, str):
            logger.error('please provide a valide path to save the image "' +
                         str(path) + '"')
            return
        if filetype is None:
            if path.lower().endswith('.svg'):
                filetype = 'svg'
            else:
                filetype = 'raster'
        dpi = 72  # 300 # inkscape 96 ? check for illustrator --> check

        if filetype == 'svg':
            generator = QSvgGenerator()
            generator.setFileName(path)
            if svg_dpi == self.SVG_ILLUSTRATOR:
                generator.setSize(QSize(595, 842))
                generator.setViewBox(QRect(0, 0, 595, 842))
            else:
                generator.setSize(QSize(794, 1123))
                generator.setViewBox(QRect(0, 0, 794, 1123))

            if title is not None and isinstance(title, str):
                generator.setTitle(title)
            if description is not None and isinstance(description, str):
                generator.setDescription(description)
            generator.setResolution(
                svg_dpi
            )  # fixes issues in inkscape of pt size --> 72 pr illustrator and 96 pr inkscape but need change size

            painter = QPainter(generator)

            print(generator.title(), generator.heightMM(), generator.height(),
                  generator.widthMM(), generator.resolution(),
                  generator.description(), generator.logicalDpiX())
        else:
            scaling_factor_dpi = 1
            scaling_factor_dpi = self.scaling_factor_to_achieve_DPI(300)
            image = QtGui.QImage(
                QSize(
                    self.cm_to_inch(21) * dpi * scaling_factor_dpi,
                    self.cm_to_inch(29.7) * dpi * scaling_factor_dpi),
                QtGui.QImage.Format_RGB32)
            painter = QPainter(
                image)  # see what happens in case of rounding of pixels
            painter.scale(scaling_factor_dpi, scaling_factor_dpi)
        painter.setRenderHint(
            QPainter.HighQualityAntialiasing
        )  # to improve rendering #Antialiasing otherwise or nothing
        self.paint(painter)
        painter.end()
        if filetype != 'svg':
            image.save(path)
Example #2
0
    def __save(self):
        """If AerialWare has been used as a module, emits signal 'done'. Saves user results into SVG and makes report otherwise.
		"""
        # Variables for report
        self.pointsMeridian = ""
        self.pointsHorizontal = ""

        # Total lengths of paths. Used in report and methods.
        self.lenMeridian = 0
        self.lenMeridianWithTurns = 0
        self.lenHorizontal = 0
        self.lenHorizontalWithTurns = 0

        # Fields for methods
        self.pathMeridianPointsPx = []
        self.pathMeridianPointsDeg = []
        self.pathMeridianLinesPx = []
        self.pathMeridianLinesWithTurnsPx = []
        self.pathMeridianLinesDeg = []
        self.pathMeridianLinesWithTurnsDeg = []

        self.pathHorizontalPointsPx = []
        self.pathHorizontalPointsDeg = []
        self.pathHorizontalLinesPx = []
        self.pathHorizontalLinesWithTurnsPx = []
        self.pathHorizontalLinesDeg = []
        self.pathHorizontalLinesWithTurnsDeg = []

        # Process each line
        def processLines(lines, isMeridian=False):
            i = 2  # Counter for report
            isEven = False  # If current line is even we must swap it's points.
            for line in lines:
                linePx = line.line()
                p1 = linePx.p1()
                p2 = linePx.p2()
                p1Deg = self.pxToDeg(p1.x(), p1.y())
                p2Deg = self.pxToDeg(p2.x(), p2.y())
                lineDeg = QLineF(p1Deg, p2Deg)
                lineLength = self.__lenMeters(p1Deg, p2Deg)

                if isMeridian:
                    self.pathMeridianLinesWithTurnsPx.append(linePx)
                    self.pathMeridianLinesWithTurnsDeg.append(lineDeg)
                    self.lenMeridianWithTurns += lineLength
                else:
                    self.pathHorizontalLinesWithTurnsPx.append(linePx)
                    self.pathHorizontalLinesWithTurnsDeg.append(lineDeg)
                    self.lenHorizontalWithTurns += lineLength

                if line.pen().style(
                ) == Qt.SolidLine:  # Check if current line doesn't represent turn
                    if isEven:
                        p1, p2, p1Deg, p2Deg = p2, p1, p2Deg, p1Deg

                    point = f'"{i - 1}","{p1Deg.x()}","{p1Deg.y()}"\n' + f'"{i}","{p2Deg.x()}","{p2Deg.y()}"\n'
                    if isMeridian:
                        self.pointsMeridian += point
                        self.pathMeridianPointsPx.extend([p1, p2])
                        self.pathMeridianPointsDeg.extend([p1Deg, p2Deg])
                        self.pathMeridianLinesPx.append(linePx)
                        self.pathMeridianLinesDeg.append(lineDeg)
                        self.lenMeridian += lineLength
                    else:
                        self.pointsHorizontal += point
                        self.pathHorizontalPointsPx.extend([p1, p2])
                        self.pathHorizontalPointsDeg.extend([p1Deg, p2Deg])
                        self.pathHorizontalLinesPx.append(linePx)
                        self.pathHorizontalLinesDeg.append(lineDeg)
                        self.lenHorizontal += lineLength
                    isEven = not isEven
                    i += 2

        processLines(self.scene.getMeridianLines(), True)
        processLines(self.scene.getHorizontalLines())

        if self.getResultsAfterCompletion:
            self.done.emit()
            return

        self.__disableItems()

        # Make report
        pointHeader = f'"{self.lang.repPoint}","{self.lang.lblLatitude}","{self.lang.lblLongitude}"\n'

        if self.lenHorizontalWithTurns > self.lenMeridianWithTurns:
            directionWithTurns = self.lang.repFlyMeridians
        elif self.lenHorizontalWithTurns < self.lenMeridianWithTurns:
            directionWithTurns = self.lang.repFlyHorizontals
        else:
            directionWithTurns = self.lang.repFlyEqual

        if self.lenHorizontal > self.lenMeridian:
            directionWithoutTurns = self.lang.repFlyMeridians
        elif self.lenHorizontal < self.lenMeridian:
            directionWithoutTurns = self.lang.repFlyHorizontals
        else:
            directionWithoutTurns = self.lang.repFlyEqual

        report = (
            f'"{self.lang.repCornersDescription}"\n'
            f'"{self.lang.lblCorner}","{self.lang.lblLongitude}","{self.lang.lblLatitude}"\n'
            f'"{self.lang.lblTopLeft}","{self.xTL}","{self.yTL}"\n'
            f'"{self.lang.lblTopRight}","{self.xTR}","{self.yTR}"\n'
            f'"{self.lang.lblBottomLeft}","{self.xBL}","{self.yBL}"\n'
            f'"{self.lang.lblBottomRight}","{self.xBR}","{self.yBR}"\n'
            f'"{self.lang.lblDelimiters}","{self.xD}","{self.yD}"\n\n'
            f'"{self.lang.repTotalWithTurns}"\n'
            f'"{self.lang.repByMeridians}","{self.lenMeridianWithTurns}"\n'
            f'"{self.lang.repByHorizontals}","{self.lenHorizontalWithTurns}"\n'
            f'"{self.lang.repBetterFlyBy}","{directionWithTurns}"\n\n'
            f'"{self.lang.repTotalWithoutTurns}"\n'
            f'"{self.lang.repByMeridians}","{self.lenMeridian}"\n'
            f'"{self.lang.repByHorizontals}","{self.lenHorizontal}"\n'
            f'"{self.lang.repBetterFlyBy}","{directionWithoutTurns}"\n\n'
            f'"{self.lang.repAerialParams}"\n'
            f'"{self.lang.repArea}","{self.maxHorizontal}","x","{self.maxVertical}"\n'
            f'"{self.lang.lblDesiredRes}","{self.camRatio}"\n'
            f'"{self.lang.lblRes}","{self.camWidth}","x","{self.camHeight}"\n'
            f'"{self.lang.lblHeight}","{self.flightHeight}"\n'
            f'"{self.lang.lblFocal}","{self.focalLength}"\n\n'
            f'"{self.lang.repMeridianPoints}"\n' + pointHeader +
            self.pointsMeridian + f'\n"{self.lang.repHorizontalPoints}"\n' +
            pointHeader + self.pointsHorizontal)

        # Save image
        self.__disableItems()
        file = QFileDialog.getSaveFileName(self, self.lang.saveFile, "",
                                           self.lang.vectorImage +
                                           " (*.svg)")[0]
        if file == "":
            self.__enableItems()
            return

        # And choose where to save report
        reportName = ""
        while reportName == "":
            reportName = QFileDialog.getSaveFileName(
                self, self.lang.saveFile, "", self.lang.table + " (*.csv)")[0]
            if reportName == "":
                msg = QMessageBox()
                msg.setIcon(QMessageBox.Warning)
                msg.setText(self.lang.errSaveBoth)
                msg.exec_()

        rect = self.scene.sceneRect()
        gen = QSvgGenerator()
        gen.setFileName(file)
        gen.setSize(rect.size().toSize())
        gen.setViewBox(rect)
        gen.setTitle("Flight paths generated by AerialWare")
        gen.setDescription(gen.title())

        # Notice: painting will temporarily freeze application because QGraphicsScene::render is not thread safe.
        # Don't try putting this into python's threads and QThread, doesn't work, I've tried, trust me XD
        painter = QPainter(gen)
        self.scene.render(painter)
        painter.end()

        # Save report
        reportFile = open(reportName, "w")
        reportFile.write(report)
        reportFile.close()

        self.__enableItems()