예제 #1
0
 def setDateEnd( self, date, ignoreDuration = False ):
     """
     Sets the date start value for this item.
     
     :param      dateStart | <QDate>
     """
     date = QDate(date)
     
     delta = self._dateEnd.daysTo(date)
     if ( not delta ):
         return
     
     if ( self.itemStyle() != self.ItemStyle.Group ):
         self._dateEnd = date
     else:
         duration        = self.duration()
         if ignoreDuration is False:
             self._dateStart = date.addDays(-duration)
         self._dateEnd   = date
         
     self.adjustChildren(delta)
     self.adjustRange()
     
     # sync the tree
     self.sync()
예제 #2
0
    def setDateEnd(self, date, ignoreDuration=False):
        """
        Sets the date start value for this item.
        
        :param      dateStart | <QDate>
        """
        date = QDate(date)

        delta = self._dateEnd.daysTo(date)
        if (not delta):
            return

        if (self.itemStyle() != self.ItemStyle.Group):
            self._dateEnd = date
        else:
            duration = self.duration()
            if ignoreDuration is False:
                self._dateStart = date.addDays(-duration)
            self._dateEnd = date

        self.adjustChildren(delta)
        self.adjustRange()

        # sync the tree
        self.sync()
예제 #3
0
    def setDateStart(self, dateStart):
        """
        Sets the start date for this item.  This will automatically push the
        end date to match the duration for this item.  So if the item starts
        on 1/1/12 and ends on 1/2/12, and the start date is changed to 2/1/12,
        the end date will change to 2/2/12.  To affect the duration of the 
        item, use either setDuration, or setDateEnd.
        
        :param      dateStart | <QDate>
        """
        dateStart = QDate(dateStart)

        duration = self.duration()
        self._dateStart = dateStart
        self._dateEnd = dateStart.addDays(duration - 1)
        self.markForRebuild()
예제 #4
0
 def setDateStart( self, dateStart ):
     """
     Sets the start date for this item.  This will automatically push the
     end date to match the duration for this item.  So if the item starts
     on 1/1/12 and ends on 1/2/12, and the start date is changed to 2/1/12,
     the end date will change to 2/2/12.  To affect the duration of the 
     item, use either setDuration, or setDateEnd.
     
     :param      dateStart | <QDate>
     """
     dateStart = QDate(dateStart)
     
     duration = self.duration()
     self._dateStart = dateStart
     self._dateEnd   = dateStart.addDays(duration - 1)
     self.markForRebuild()
예제 #5
0
    def test__years_QDate(self):
        """
		Überprüft, daß die Funktion der Berechnung der Jahre auch Ergebnisse im zu erwartenden Rahmen zurückgibt.
		"""

        DATE_STEP = 1
        DATE_YEAR = {
            "min": -1,
            "max": 2,
        }

        ## Eine Liste mit Daten anlegen
        dates_all = []

        ## Von ...
        year_min = DATE_YEAR["min"]
        ## ... bis
        year_max = DATE_YEAR["max"]

        ## Startdatum
        date_store = QDate(year_min, 1, 1)
        date_max = QDate(year_max, 1, 1)

        ## Die Listen tatsächlich anlegen
        while date_store < date_max:
            dates_all.append(date_store)
            date_store = date_store.addDays(DATE_STEP)

        ## Kopie erstellen
        dates_to_compare = dates_all[:]
        results_expected = tuple(range(year_max - year_min + 1))

        for date_1 in dates_all:
            dates_to_compare.remove(date_1)
            for date_2 in dates_to_compare:
                self.assertIn(Calc.years(date_1, date_2), results_expected)
예제 #6
0
	def test__years_QDate(self):
		"""
		Überprüft, daß die Funktion der Berechnung der Jahre auch Ergebnisse im zu erwartenden Rahmen zurückgibt.
		"""
		
		DATE_STEP = 1
		DATE_YEAR = {
			"min": -1,
			"max": 2,
		}

		## Eine Liste mit Daten anlegen
		dates_all = []

		## Von ...
		year_min = DATE_YEAR["min"]
		## ... bis
		year_max = DATE_YEAR["max"]

		## Startdatum
		date_store = QDate(year_min, 1, 1)
		date_max = QDate(year_max, 1, 1)

		## Die Listen tatsächlich anlegen
		while date_store < date_max:
			dates_all.append( date_store )
			date_store = date_store.addDays( DATE_STEP )

		## Kopie erstellen
		dates_to_compare = dates_all[:]
		results_expected = tuple( range( year_max - year_min + 1 ) )

		for date_1 in dates_all:
			dates_to_compare.remove( date_1 )
			for date_2 in dates_to_compare:
				self.assertIn( Calc.years(date_1, date_2), results_expected )
예제 #7
0
 def rebuildMonth( self ):
     """
     Rebuilds the month for this scene.
     """
     # make sure we start at 0 for sunday vs. 7 for sunday
     day_map     = dict([(i+1, i+1) for i in range(7)])
     day_map[7]  = 0
     
     today   = QDate.currentDate()
     curr    = self.currentDate()
     first   = QDate(curr.year(), curr.month(), 1)
     last    = QDate(curr.year(), curr.month(), curr.daysInMonth())
     first   = first.addDays(-day_map[first.dayOfWeek()])
     last    = last.addDays(6-day_map[last.dayOfWeek()])
     
     cols    = 7
     rows    = (first.daysTo(last) + 1) / cols
     
     hlines  = []
     vlines  = []
     
     padx    = 6
     pady    = 6
     header  = 24
     
     w       = self.width() - (2 * padx)
     h       = self.height() - (2 * pady)
     
     dw      = (w / cols) - 1
     dh      = ((h - header) / rows) - 1
     
     x0      = padx
     y0      = pady + header
     
     x       = x0
     y       = y0
     
     for row in range(rows + 1):
         hlines.append(QLine(x0, y, w, y))
         y += dh
     
     for col in range(cols + 1):
         vlines.append(QLine(x, y0, x, h))
         x += dw
     
     self._buildData['grid'] = hlines + vlines
     
     # draw the date fields
     date = first
     row  = 0
     col  = 0
     
     # draw the headers
     x = x0
     y = pady
     
     regular_text = []
     mid_text     = []
     self._buildData['regular_text'] = regular_text
     self._buildData['mid_text']     = mid_text
     
     for day in ('Sun', 'Mon','Tue','Wed','Thu','Fri','Sat'):
         regular_text.append((x + 5,
                              y,
                              dw,
                              y0,
                              Qt.AlignLeft | Qt.AlignVCenter,
                              day))
         x += dw
     
     for i in range(first.daysTo(last) + 1):
         top    = (y0 + (row * dh))
         left   = (x0 + (col * dw))
         rect   = QRectF(left - 1, top, dw, dh)
         
         # mark the current date on the calendar
         if ( date == curr ):
             self._buildData['curr_date'] = rect
         
         # mark today's date on the calendar
         elif ( date == today ):
             self._buildData['today'] = rect
         
         # determine how to draw the calendar
         format = 'd'
         if ( date.day() == 1 ):
             format = 'MMM d'
         
         # determine the color to draw the text
         if ( date.month() == curr.month() ):
             text = regular_text
         else:
             text = mid_text
         
         # draw the text
         text.append((left + 2,
                      top + 2,
                      dw - 4,
                      dh - 4,
                      Qt.AlignTop | Qt.AlignLeft,
                      date.toString(format)))
         
         # update the limits
         if ( not i ):
             self._minimumDate = date
         self._maximumDate = date
         
         self._dateGrid[date.toJulianDay()] = ((row, col), rect)
         if ( col == (cols - 1) ):
             row += 1
             col = 0
         else:
             col += 1
             
         date = date.addDays(1)
예제 #8
0
    def run(self):
        """Run method that performs all the real work"""
        self.dlg.show()  # show the dialog
        result = self.dlg.exec_()  # Run the dialog event loop

        if result:  # The user pressed OK, and this is what happened next!

            survex3dfile = self.dlg.selectedFile.text()
            gpkg_file = self.dlg.selectedGPKG.text()

            include_legs = self.dlg.Legs.isChecked()
            include_stations = self.dlg.Stations.isChecked()
            include_polygons = self.dlg.Polygons.isChecked()
            include_walls = self.dlg.Walls.isChecked()
            include_xsections = self.dlg.XSections.isChecked()
            include_traverses = self.dlg.Traverses.isChecked()

            exclude_surface_legs = not self.dlg.LegsSurface.isChecked()
            exclude_splay_legs = not self.dlg.LegsSplay.isChecked()
            exclude_duplicate_legs = not self.dlg.LegsDuplicate.isChecked()

            exclude_surface_stations = not self.dlg.StationsSurface.isChecked()

            use_clino_wgt = self.dlg.UseClinoWeights.isChecked()
            include_up_down = self.dlg.IncludeUpDown.isChecked()

            discard_features = not self.dlg.KeepFeatures.isChecked()

            get_crs_from_file = self.dlg.CRSFromFile.isChecked()
            get_crs_from_project = self.dlg.CRSFromProject.isChecked()

            if not os.path.exists(survex3dfile):
                raise Exception("File '%s' doesn't exist" % survex3dfile)

            if discard_features:
                self.leg_list = []
                self.station_list = []
                self.station_xyz = {}
                self.xsect_list = []

            # Read .3d file as binary, parse, and save data structures

            with open(survex3dfile, 'rb') as fp:

                line = fp.readline().rstrip()  # File ID check

                if not line.startswith(b'Survex 3D Image File'):
                    raise IOError('Not a survex .3d file: ' + survex3dfile)

                line = fp.readline().rstrip()  # File format version

                if not line.startswith(b'v'):
                    raise IOError('Unrecognised survex .3d version in ' +
                                  survex3dfile)

                version = int(line[1:])
                if version < 8:
                    raise IOError('Survex .3d version >= 8 required in ' +
                                  survex3dfile)

                line = fp.readline().rstrip(
                )  # Metadata (title and coordinate system)
                fields = line.split(b'\x00')

                previous_title = '' if discard_features else self.title

                if previous_title:
                    self.title = previous_title + ' + ' + fields[0]
                else:
                    self.title = fields[0]

                # Try to work out EPSG number from second field if available.
                # The project_crs should end up as a lowercase string like 'epsg:27700'

                if get_crs_from_project:
                    project_crs = self.iface.mapCanvas().mapRenderer(
                    ).destinationCrs()
                    self.extract_epsg(project_crs.authid().lower())
                elif get_crs_from_file and len(fields) > 1:
                    self.extract_epsg(fields[1])
                else:
                    self.epsg = None

                line = fp.readline().rstrip(
                )  # Timestamp, unused in present application

                if not line.startswith(b'@'):
                    raise IOError('Unrecognised timestamp in ' + survex3dfile)

                # timestamp = int(line[1:])

                flag = ord(fp.read(1))  # file-wide flag

                if flag & 0x80:  # abort if extended elevation
                    raise IOError("Can't deal with extended elevation in " +
                                  survex3dfile)

                # All front-end data read in, now read byte-wise
                # according to .3d spec.  Note that all elements must
                # be processed, in order, otherwise we get out of sync.

                # We first define some baseline dates

                date0 = QDate(1900, 1, 1)
                date1 = QDate(1900, 1, 1)
                date2 = QDate(1900, 1, 1)

                label, style = '', 0xff  # initialise label and style

                legs = []  # will be used to capture leg data between MOVEs
                xsect = []  # will be used to capture XSECT data
                nlehv = None  # .. remains None if there isn't any error data...

                while True:  # start of byte-gobbling while loop

                    char = fp.read(1)

                    if not char:  # End of file (reached prematurely?)
                        raise IOError('Premature end of file in ' +
                                      survex3dfile)

                    byte = ord(char)

                    if byte <= 0x05:  # STYLE
                        if byte == 0x00 and style == 0x00:  # this signals end of data
                            if legs:  # there may be a pending list of legs to save
                                self.leg_list.append((legs, nlehv))
                            break  # escape from byte-gobbling while loop
                        else:
                            style = byte

                    elif byte <= 0x0e:  # Reserved
                        continue

                    elif byte == 0x0f:  # MOVE
                        xyz = self.read_xyz(fp)
                        if legs:
                            self.leg_list.append((legs, nlehv))
                            legs = []

                    elif byte == 0x10:  # DATE (none)
                        date1 = date2 = date0

                    elif byte == 0x11:  # DATE (single date)
                        days = unpack('<H', fp.read(2))[0]
                        date1 = date2 = date0.addDays(days)

                    elif byte == 0x12:  # DATE (date range, short format)
                        days, extra = unpack('<HB', fp.read(3))
                        date1 = date0.addDays(days)
                        date2 = date0.addDays(days + extra + 1)

                    elif byte == 0x13:  # DATE (date range, long format)
                        days1, days2 = unpack('<HH', fp.read(4))
                        date1 = date0.addDays(days1)
                        date2 = date0.addDays(days2)

                    elif byte <= 0x1e:  # Reserved
                        continue

                    elif byte == 0x1f:  # Error info
                        nlehv = unpack('<iiiii', fp.read(20))

                    elif byte <= 0x2f:  # Reserved
                        continue

                    elif byte <= 0x33:  # XSECT
                        label = self.read_label(fp, label)
                        if byte & 0x02:
                            lrud = unpack('<iiii', fp.read(16))
                        else:
                            lrud = unpack('<hhhh', fp.read(8))
                        xsect.append((label, lrud))
                        if byte & 0x01:  # XSECT_END
                            self.xsect_list.append(xsect)
                            xsect = []

                    elif byte <= 0x3f:  # Reserved
                        continue

                    elif byte <= 0x7f:  # LINE
                        flag = byte & 0x3f
                        if not (flag & 0x20):
                            label = self.read_label(fp, label)
                        xyz_prev = xyz
                        xyz = self.read_xyz(fp)
                        while (True):  # code pattern to implement logic
                            if exclude_surface_legs and flag & 0x01: break
                            if exclude_duplicate_legs and flag & 0x02: break
                            if exclude_splay_legs and flag & 0x04: break
                            legs.append(((xyz_prev, xyz), label, style, date1,
                                         date2, flag))
                            break

                    elif byte <= 0xff:  # LABEL (or NODE)
                        flag = byte & 0x7f
                        label = self.read_label(fp, label)
                        xyz = self.read_xyz(fp)
                        while (True):  # code pattern to implement logic
                            if exclude_surface_stations and flag & 0x01 and not flag & 0x02:
                                break
                            self.station_list.append((xyz, label, flag))
                            break
                        self.station_xyz[label] = xyz

                # End of byte-gobbling while loop

            # file closes automatically, with open(survex3dfile, 'rb') as fp:

            # Now create the layers in QGIS.  Attributes are inserted
            # like pushing onto a stack, so in reverse order.  Layers
            # are created only if required and data is available.
            # If nlehv is still None, then no error data has been provided.

            layers = []  # used to keep a list of the created layers

            if include_stations and self.station_list:  # station layer

                station_layer = self.add_layer('stations', 'Point')

                attrs = [
                    QgsField(self.station_attr[k], QVariant.Int)
                    for k in self.station_flags
                ]
                attrs.insert(0, QgsField('ELEVATION', QVariant.Double))
                attrs.insert(0, QgsField('NAME', QVariant.String))
                station_layer.dataProvider().addAttributes(attrs)
                station_layer.updateFields()

                features = []

                for (xyz, label, flag) in self.station_list:
                    xyz = [0.01 * v for v in xyz]
                    attrs = [1 if flag & k else 0 for k in self.station_flags]
                    attrs.insert(0, round(xyz[2], 2))  # elevation
                    attrs.insert(0, label)
                    feat = QgsFeature()
                    geom = QgsGeometry(QgsPointV2(QgsWKBTypes.PointZ, *xyz))
                    feat.setGeometry(geom)
                    feat.setAttributes(attrs)
                    features.append(feat)

                station_layer.dataProvider().addFeatures(features)
                layers.append(station_layer)

            if include_legs and self.leg_list:  # leg layer

                leg_layer = self.add_layer('legs', 'LineString')

                attrs = [
                    QgsField(self.leg_attr[k], QVariant.Int)
                    for k in self.leg_flags
                ]
                if nlehv:
                    [
                        attrs.insert(0, QgsField(s, QVariant.Double))
                        for s in self.error_fields
                    ]
                    attrs.insert(0, QgsField('NLEGS', QVariant.Int))
                attrs.insert(0, QgsField('DATE2', QVariant.Date))
                attrs.insert(0, QgsField('DATE1', QVariant.Date))
                attrs.insert(0, QgsField('STYLE', QVariant.String))
                attrs.insert(0, QgsField('ELEVATION', QVariant.Double))
                attrs.insert(0, QgsField('NAME', QVariant.String))
                leg_layer.dataProvider().addAttributes(attrs)
                leg_layer.updateFields()

                features = []

                for legs, nlehv in self.leg_list:
                    for (xyz_pair, label, style, from_date, to_date,
                         flag) in legs:
                        elev = 0.5 * sum([0.01 * xyz[2] for xyz in xyz_pair])
                        points = []
                        for xyz in xyz_pair:
                            xyz = [0.01 * v for v in xyz]
                            points.append(QgsPointV2(QgsWKBTypes.PointZ, *xyz))
                        attrs = [1 if flag & k else 0 for k in self.leg_flags]
                        if nlehv:
                            [
                                attrs.insert(0, 0.01 * v)
                                for v in reversed(nlehv[1:5])
                            ]
                            attrs.insert(0, nlehv[0])
                        attrs.insert(0, to_date)
                        attrs.insert(0, from_date)
                        attrs.insert(0, self.style_type[style])
                        attrs.insert(0, round(elev, 2))
                        attrs.insert(0, label)
                        linestring = QgsLineStringV2()
                        linestring.setPoints(points)
                        feat = QgsFeature()
                        geom = QgsGeometry(linestring)
                        feat.setGeometry(geom)
                        feat.setAttributes(attrs)
                        features.append(feat)

                leg_layer.dataProvider().addFeatures(features)
                layers.append(leg_layer)

            # Now do wall features if asked

            if (include_traverses or include_xsections or include_walls
                    or include_polygons) and self.xsect_list:

                trav_features = []
                wall_features = []
                xsect_features = []
                quad_features = []

                for xsect in self.xsect_list:

                    if len(xsect) < 2:  # if there's only one station ..
                        continue  # .. give up as we don't know which way to face

                    centerline = [
                    ]  # will contain the station position and LRUD data

                    for label, lrud in xsect:
                        xyz = self.station_xyz[
                            label]  # look up coordinates from label
                        lrud_or_zero = tuple([max(0, v) for v in lrud
                                              ])  # deal with missing data
                        centerline.append(
                            xyz + lrud_or_zero)  # and collect as 7-uple

                    direction = [
                    ]  # will contain the corresponding direction vectors

                    # The calculations below use integers for xyz and lrud, and
                    # conversion to metres is left to the end.  Then dh2 is an
                    # integer and the test for a plumb is safely dh2 = 0.

                    # The directions are unit vectors optionally weighted by
                    # cos(inclination) = dh/dl where dh^2 = dx^2 + dy^2 + dz^2
                    # and dl^2 = dh^2 + dz^2.  The normalisation is correspondingly
                    # either 1/dh, or 1/dh * dh/dl = 1/dl.

                    for i, xyzlrud in enumerate(centerline):
                        x, y, z = xyzlrud[0:3]
                        if i > 0:
                            dx, dy, dz = x - xp, y - yp, z - zp
                            dh2 = dx * dx + dy * dy  # integer horizontal displacement (mm^2)
                            norm = sqrt(dh2 + dz *
                                        dz) if use_clino_wgt else sqrt(dh2)
                            dx, dy = (dx / norm, dy /
                                      norm) if dh2 > 0 and norm > 0 else (0, 0)
                            direction.append((dx, dy))
                        xp, yp, zp = x, y, z

                    left_wall = []
                    right_wall = []
                    up_down = []

                    # We build the walls by walking through the list
                    # of stations and directions, with simple defaults
                    # for the start and end stations

                    for i, (x, y, z, l, r, u, d) in enumerate(centerline):
                        d1x, d1y = direction[i - 1] if i > 0 else (0, 0)
                        d2x, d2y = direction[i] if i + 1 < len(
                            centerline) else (0, 0)
                        dx, dy = d1x + d2x, d1y + d2y  # mean (sum of) direction vectors
                        norm = sqrt(dx * dx +
                                    dy * dy)  # normalise to unit vector
                        ex, ey = (dx / norm, dy / norm) if norm > 0 else (0, 0)
                        # Convert to metres when saving the points
                        left_wall.append((0.01 * (x - l * ey),
                                          0.01 * (y + l * ex), 0.01 * z))
                        right_wall.append((0.01 * (x + r * ey),
                                           0.01 * (y - r * ex), 0.01 * z))
                        up_down.append((0.01 * u, 0.01 * d))

                    # Mean elevation of centerline, used for elevation attribute

                    elev = 0.01 * sum([xyzlrud[2] for xyzlrud in centerline
                                       ]) / len(centerline)
                    attrs = [round(elev, 2)]

                    # Now create the feature sets - first the centerline traverse

                    points = []

                    for xyzlrud in centerline:
                        xyz = [0.01 * v for v in xyzlrud[0:3]
                               ]  # These were mm, convert to metres
                        points.append(QgsPointV2(QgsWKBTypes.PointZ, *xyz))

                    linestring = QgsLineStringV2()
                    linestring.setPoints(points)
                    feat = QgsFeature()
                    geom = QgsGeometry(linestring)
                    feat.setGeometry(geom)
                    feat.setAttributes(attrs)
                    trav_features.append(feat)

                    # The walls as line strings

                    for wall in (left_wall, right_wall):

                        points = [
                            QgsPointV2(QgsWKBTypes.PointZ, *xyz)
                            for xyz in wall
                        ]
                        linestring = QgsLineStringV2()
                        linestring.setPoints(points)
                        feat = QgsFeature()
                        geom = QgsGeometry(linestring)
                        feat.setGeometry(geom)
                        feat.setAttributes(attrs)
                        wall_features.append(feat)

                    # Slightly more elaborate, pair up points on left
                    # and right walls, and build a cross section as a
                    # 2-point line string, and a quadrilateral polygon
                    # with a closed 5-point line string for the
                    # exterior ring.  Note that QGIS polygons are
                    # supposed to have their points ordered clockwise.

                    for i, xyz_pair in enumerate(zip(left_wall, right_wall)):

                        elev = 0.01 * centerline[i][
                            2]  # elevation of station in centerline
                        attrs = [round(elev, 2)]
                        points = [
                            QgsPointV2(QgsWKBTypes.PointZ, *xyz)
                            for xyz in xyz_pair
                        ]
                        linestring = QgsLineStringV2()
                        linestring.setPoints(points)
                        feat = QgsFeature()
                        geom = QgsGeometry(linestring)
                        feat.setGeometry(geom)
                        feat.setAttributes(attrs)
                        xsect_features.append(feat)

                        if i > 0:
                            elev = 0.5 * (prev_xyz_pair[0][2] + xyz_pair[0][2]
                                          )  # average elevation
                            attrs = [round(elev, 2)]
                            if include_up_down:  # average up / down
                                attrs += [
                                    0.5 * (v1 + v2)
                                    for (v1,
                                         v2) in zip(up_down[i - 1], up_down[i])
                                ]
                            points = [
                            ]  # will contain the exterior 5-point ring, as follows...
                            for xyz in tuple(
                                    reversed(prev_xyz_pair)) + xyz_pair + (
                                        prev_xyz_pair[1], ):
                                points.append(
                                    QgsPointV2(QgsWKBTypes.PointZ, *xyz))
                            linestring = QgsLineStringV2()
                            linestring.setPoints(points)
                            polygon = QgsPolygonV2()
                            polygon.setExteriorRing(linestring)
                            feat = QgsFeature()
                            geom = QgsGeometry(polygon)
                            feat.setGeometry(geom)
                            feat.setAttributes(attrs)
                            quad_features.append(feat)

                        prev_xyz_pair = xyz_pair

                # End of processing xsect_list - now add features to requested layers

                attrs = [QgsField('ELEVATION',
                                  QVariant.Double)]  # common to all

                if include_traverses and trav_features:  # traverse layer
                    travs_layer = self.add_layer('traverses', 'LineString')
                    travs_layer.dataProvider().addAttributes(attrs)
                    travs_layer.updateFields()
                    travs_layer.dataProvider().addFeatures(trav_features)
                    layers.append(travs_layer)

                if include_xsections and xsect_features:  # xsection layer
                    xsects_layer = self.add_layer('xsections', 'LineString')
                    xsects_layer.dataProvider().addAttributes(attrs)
                    xsects_layer.updateFields()
                    xsects_layer.dataProvider().addFeatures(xsect_features)
                    layers.append(xsects_layer)

                if include_walls and wall_features:  # wall layer
                    walls_layer = self.add_layer('walls', 'LineString')
                    walls_layer.dataProvider().addAttributes(attrs)
                    walls_layer.updateFields()
                    walls_layer.dataProvider().addFeatures(wall_features)
                    layers.append(walls_layer)

                if include_up_down:  # add fields if requested for polygons
                    attrs += [
                        QgsField(s, QVariant.Double)
                        for s in ('MEAN_UP', 'MEAN_DOWN')
                    ]

                if include_polygons and quad_features:  # polygon layer
                    quads_layer = self.add_layer('polygons', 'Polygon')
                    quads_layer.dataProvider().addAttributes(attrs)
                    quads_layer.updateFields()
                    quads_layer.dataProvider().addFeatures(quad_features)
                    layers.append(quads_layer)

            # All layers have been created, now update extents and add to QGIS registry

            if layers:
                [layer.updateExtents() for layer in layers]
                QgsMapLayerRegistry.instance().addMapLayers(layers)

            # Save layers to a GeoPackage if selected.

            # QgsVectorFileWriter would be ideal but it can only write
            # single layers (afaik!), so the GeoPackage layers,
            # fields, and attributes are created using OGR calls,
            # translating the corresponding QGIS objects on the fly.

            # It's possible this could be done faster by iterating
            # numerically over the attributes but I'm not sure the OGR
            # features would be visited in the right order, so here
            # use the field names as indices.  Meanwhile, the user is
            # appraised of progress by a progress bar.

            if gpkg_file:

                nfeatures = 0  # how many features in total
                for layer in layers:
                    nfeatures += layer.featureCount()

                if nfeatures > 100:  # create a progress bar
                    progress_bar = QProgressBar()
                    progress_bar.setMaximum(nfeatures)
                    progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
                    msg = 'Saving ' + QFileInfo(gpkg_file).fileName()
                    progressMessageBar = self.iface.messageBar().createMessage(
                        msg)
                    progressMessageBar.layout().addWidget(progress_bar)
                    self.iface.messageBar().pushWidget(
                        progressMessageBar,
                        self.iface.messageBar().INFO)
                    ntrack = int(10**(floor(log10(nfeatures)) -
                                      1))  # update frequency
                else:
                    progress_bar = None

                gpkg_driver = ogr.GetDriverByName('GPKG')

                if os.path.exists(gpkg_file):
                    gpkg_driver.DeleteDataSource(gpkg_file)

                ogr_dataset = gpkg_driver.CreateDataSource(gpkg_file)

                if self.epsg:  # figure out the spatial reference system in OGR terms
                    ogr_srs = osr.SpatialReference()
                    ogr_srs.ImportFromEPSG(self.epsg)
                else:
                    ogr_srs = None

                ncount = 0  # to keep track of number of features processed

                for layer in layers:  # go through all the layers

                    qgis_name = layer.name()
                    match = search(' - ([a-z]*)', qgis_name)
                    ogr_name = str(match.group(
                        1)) if match else qgis_name  # ie, legs, stations, etc
                    ogr_type = self.ogr_vec_type[layer.wkbType()]
                    ogr_layer = ogr_dataset.CreateLayer(ogr_name,
                                                        srs=ogr_srs,
                                                        geom_type=ogr_type)

                    qgis_fields = layer.pendingFields()
                    names = [str(field.name()) for field in qgis_fields]
                    types = [
                        self.ogr_type[field.type()] for field in qgis_fields
                    ]
                    ogr_type_of_ = dict(zip(
                        names, types))  # map field names to OGR field types

                    [
                        ogr_layer.CreateField(
                            ogr.FieldDefn(name, ogr_type_of_[name]))
                        for name in names
                    ]

                    ogr_schema = ogr_layer.GetLayerDefn(
                    )  # for creating features in the OGR layer

                    for qgis_feat in layer.getFeatures(
                    ):  # go through all the features

                        ncount += 1  # update feature count

                        if progress_bar and ncount % ntrack:  # update progress bar
                            progress_bar.setValue(ncount)

                        ogr_feat = ogr.Feature(ogr_schema)

                        ogr_wkt = qgis_feat.geometry().exportToWkt().replace(
                            *self.wkt_replace[ogr_type])
                        ogr_feat.SetGeometry(
                            ogr.CreateGeometryFromWkt(ogr_wkt))

                        qgis_attrs = qgis_feat.attributes()

                        for name, qgis_attr in zip(names, qgis_attrs):
                            if ogr_type_of_[
                                    name] == ogr.OFTString:  # fix for strings
                                ogr_feat.SetField(name, str(qgis_attr))
                            elif ogr_type_of_[
                                    name] == ogr.OFTDate:  # translate dates
                                ogr_feat.SetField(
                                    name, str(qgis_attr.toString(Qt.ISODate)))
                            else:  # everything else just passes through
                                ogr_feat.SetField(name, qgis_attr)

                        ogr_layer.CreateFeature(ogr_feat)

                ogr_dataset = None  # all done, flush to disk

                if progress_bar:  # clean up and free resources
                    self.iface.messageBar().clearWidgets()
                    progress_bar = None

                msg = QFileInfo(gpkg_file).fileName() + ' to ' + QFileInfo(
                    gpkg_file).path()
                QgsMessageLog.logMessage('Saved ' + msg,
                                         tag='Import .3d',
                                         level=QgsMessageLog.INFO)
                self.iface.messageBar().pushMessage('Saved',
                                                    msg,
                                                    level=QgsMessageBar.INFO,
                                                    duration=5)
예제 #9
0
    def rebuildMonth(self):
        """
        Rebuilds the month for this scene.
        """
        # make sure we start at 0 for sunday vs. 7 for sunday
        day_map = dict([(i + 1, i + 1) for i in range(7)])
        day_map[7] = 0

        today = QDate.currentDate()
        curr = self.currentDate()
        first = QDate(curr.year(), curr.month(), 1)
        last = QDate(curr.year(), curr.month(), curr.daysInMonth())
        first = first.addDays(-day_map[first.dayOfWeek()])
        last = last.addDays(6 - day_map[last.dayOfWeek()])

        cols = 7
        rows = (first.daysTo(last) + 1) / cols

        hlines = []
        vlines = []

        padx = 6
        pady = 6
        header = 24

        w = self.width() - (2 * padx)
        h = self.height() - (2 * pady)

        dw = (w / cols) - 1
        dh = ((h - header) / rows) - 1

        x0 = padx
        y0 = pady + header

        x = x0
        y = y0

        for row in range(rows + 1):
            hlines.append(QLine(x0, y, w, y))
            y += dh

        for col in range(cols + 1):
            vlines.append(QLine(x, y0, x, h))
            x += dw

        self._buildData['grid'] = hlines + vlines

        # draw the date fields
        date = first
        row = 0
        col = 0

        # draw the headers
        x = x0
        y = pady

        regular_text = []
        mid_text = []
        self._buildData['regular_text'] = regular_text
        self._buildData['mid_text'] = mid_text

        for day in ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'):
            regular_text.append(
                (x + 5, y, dw, y0, Qt.AlignLeft | Qt.AlignVCenter, day))
            x += dw

        for i in range(first.daysTo(last) + 1):
            top = (y0 + (row * dh))
            left = (x0 + (col * dw))
            rect = QRectF(left - 1, top, dw, dh)

            # mark the current date on the calendar
            if (date == curr):
                self._buildData['curr_date'] = rect

            # mark today's date on the calendar
            elif (date == today):
                self._buildData['today'] = rect

            # determine how to draw the calendar
            format = 'd'
            if (date.day() == 1):
                format = 'MMM d'

            # determine the color to draw the text
            if (date.month() == curr.month()):
                text = regular_text
            else:
                text = mid_text

            # draw the text
            text.append(
                (left + 2, top + 2, dw - 4, dh - 4, Qt.AlignTop | Qt.AlignLeft,
                 date.toString(format)))

            # update the limits
            if (not i):
                self._minimumDate = date
            self._maximumDate = date

            self._dateGrid[date.toJulianDay()] = ((row, col), rect)
            if (col == (cols - 1)):
                row += 1
                col = 0
            else:
                col += 1

            date = date.addDays(1)