def __init__(self, methodName): """Run once on class initialization.""" unittest.TestCase.__init__(self, methodName) # create composition self.mComposition = QgsComposition(QgsProject.instance()) self.mComposition.setPaperSize(297, 210) self.mComposerShape = QgsComposerShape(20, 20, 150, 100, self.mComposition) self.mComposerShape.setBackgroundColor(QColor.fromRgb(255, 150, 0)) self.mComposition.addComposerShape(self.mComposerShape)
def __init__(self, methodName): """Run once on class initialisation.""" unittest.TestCase.__init__(self, methodName) self.mapSettings = QgsMapSettings() # create composition self.mComposition = QgsComposition(self.mapSettings) self.mComposition.setPaperSize(297, 210) self.mComposerShape = QgsComposerShape(20, 20, 150, 100, self.mComposition) self.mComposerShape.setBackgroundColor(QColor.fromRgb(255, 150, 0)) self.mComposition.addComposerShape(self.mComposerShape)
def __init__(self, methodName): """Run once on class initialisation.""" unittest.TestCase.__init__(self, methodName) # create composition self.mMapRenderer = QgsMapRenderer() self.mComposition = QgsComposition(self.mMapRenderer) self.mComposition.setPaperSize(297, 210) self.mComposerRect1 = QgsComposerShape(20, 20, 150, 100, self.mComposition) self.mComposerRect1.setShapeType(QgsComposerShape.Rectangle) self.mComposerRect1.setBackgroundColor(QColor.fromRgb(255, 150, 0)) self.mComposition.addComposerShape(self.mComposerRect1) self.mComposerRect2 = QgsComposerShape(50, 50, 150, 100, self.mComposition) self.mComposerRect2.setShapeType(QgsComposerShape.Rectangle) self.mComposerRect2.setBackgroundColor(QColor.fromRgb(0, 100, 150)) self.mComposition.addComposerShape(self.mComposerRect2)
def __init__(self, methodName): """Run once on class initialization.""" unittest.TestCase.__init__(self, methodName) # create composition self.mMapSettings = QgsMapSettings() self.mComposition = QgsComposition(self.mMapSettings, QgsProject.instance()) self.mComposition.setPaperSize(297, 210) self.mComposerRect1 = QgsComposerShape(20, 20, 150, 100, self.mComposition) self.mComposerRect1.setShapeType(QgsComposerShape.Rectangle) self.mComposerRect1.setBackgroundColor(QColor.fromRgb(255, 150, 0)) self.mComposition.addComposerShape(self.mComposerRect1) self.mComposerRect2 = QgsComposerShape(50, 50, 150, 100, self.mComposition) self.mComposerRect2.setShapeType(QgsComposerShape.Rectangle) self.mComposerRect2.setBackgroundColor(QColor.fromRgb(0, 100, 150)) self.mComposition.addComposerShape(self.mComposerRect2)
class TestQgsComposerEffects(TestCase): def __init__(self, methodName): """Run once on class initialisation.""" unittest.TestCase.__init__(self, methodName) # create composition self.mMapRenderer = QgsMapRenderer() self.mComposition = QgsComposition(self.mMapRenderer) self.mComposition.setPaperSize(297, 210) self.mComposerRect1 = QgsComposerShape(20, 20, 150, 100, self.mComposition) self.mComposerRect1.setShapeType(QgsComposerShape.Rectangle) self.mComposerRect1.setBackgroundColor(QColor.fromRgb(255, 150, 0)) self.mComposition.addComposerShape(self.mComposerRect1) self.mComposerRect2 = QgsComposerShape(50, 50, 150, 100, self.mComposition) self.mComposerRect2.setShapeType(QgsComposerShape.Rectangle) self.mComposerRect2.setBackgroundColor(QColor.fromRgb(0, 100, 150)) self.mComposition.addComposerShape(self.mComposerRect2) def testBlendModes(self): """Test that blend modes work for composer items.""" self.mComposerRect2.setBlendMode(QPainter.CompositionMode_Multiply) checker = QgsCompositionChecker() myPath = os.path.join(TEST_DATA_DIR, "control_images", "expected_composereffects", "composereffect_blend.png") myTestResult, myMessage = checker.testComposition("Composer effects blending", self.mComposition, myPath) self.mComposerRect2.setBlendMode(QPainter.CompositionMode_SourceOver) assert myTestResult == True, myMessage def testTransparency(self): """Test that transparency works for composer items.""" self.mComposerRect2.setTransparency(50) checker = QgsCompositionChecker() myPath = os.path.join( TEST_DATA_DIR, "control_images", "expected_composereffects", "composereffect_transparency.png" ) myTestResult, myMessage = checker.testComposition("Composer effects transparency", self.mComposition, myPath) self.mComposerRect2.setTransparency(100) assert myTestResult == True, myMessage
class TestQgsComposerEffects(unittest.TestCase): def __init__(self, methodName): """Run once on class initialization.""" unittest.TestCase.__init__(self, methodName) # create composition self.mMapSettings = QgsMapSettings() self.mComposition = QgsComposition(self.mMapSettings, QgsProject.instance()) self.mComposition.setPaperSize(297, 210) self.mComposerRect1 = QgsComposerShape(20, 20, 150, 100, self.mComposition) self.mComposerRect1.setShapeType(QgsComposerShape.Rectangle) self.mComposerRect1.setBackgroundColor(QColor.fromRgb(255, 150, 0)) self.mComposition.addComposerShape(self.mComposerRect1) self.mComposerRect2 = QgsComposerShape(50, 50, 150, 100, self.mComposition) self.mComposerRect2.setShapeType(QgsComposerShape.Rectangle) self.mComposerRect2.setBackgroundColor(QColor.fromRgb(0, 100, 150)) self.mComposition.addComposerShape(self.mComposerRect2) def testBlendModes(self): """Test that blend modes work for composer items.""" self.mComposerRect2.setBlendMode(QPainter.CompositionMode_Multiply) checker = QgsCompositionChecker('composereffects_blend', self.mComposition) checker.setControlPathPrefix("composer_effects") myTestResult, myMessage = checker.testComposition() self.mComposerRect2.setBlendMode(QPainter.CompositionMode_SourceOver) assert myTestResult, myMessage def testTransparency(self): """Test that transparency works for composer items.""" self.mComposerRect2.setTransparency(50) checker = QgsCompositionChecker('composereffects_transparency', self.mComposition) checker.setControlPathPrefix("composer_effects") myTestResult, myMessage = checker.testComposition() self.mComposerRect2.setTransparency(100) assert myTestResult, myMessage
def draw_scalebar(self, composer_map, top_offset): """Add a numeric scale to the bottom left of the map. We draw the scale bar manually because QGIS does not yet support rendering a scale bar for a geographic map in km. .. seealso:: :meth:`drawNativeScaleBar` :param composer_map: Composer map on which to draw the scalebar. :type composer_map: QgsComposerMap :param top_offset: Vertical offset at which the logo should be drawn. :type top_offset: int """ LOGGER.debug('InaSAFE Map drawScaleBar called') myCanvas = self.iface.mapCanvas() myRenderer = myCanvas.mapRenderer() # # Add a linear map scale # myDistanceArea = QgsDistanceArea() myDistanceArea.setSourceCrs(myRenderer.destinationCrs().srsid()) myDistanceArea.setEllipsoidalMode(True) # Determine how wide our map is in km/m # Starting point at BL corner myComposerExtent = composer_map.extent() myStartPoint = QgsPoint(myComposerExtent.xMinimum(), myComposerExtent.yMinimum()) # Ending point at BR corner myEndPoint = QgsPoint(myComposerExtent.xMaximum(), myComposerExtent.yMinimum()) myGroundDistance = myDistanceArea.measureLine(myStartPoint, myEndPoint) # Get the equivalent map distance per page mm myMapWidth = self.mapWidth # How far is 1mm on map on the ground in meters? myMMToGroundDistance = myGroundDistance / myMapWidth #print 'MM:', myMMDistance # How long we want the scale bar to be in relation to the map myScaleBarToMapRatio = 0.5 # How many divisions the scale bar should have myTickCount = 5 myScaleBarWidthMM = myMapWidth * myScaleBarToMapRatio myPrintSegmentWidthMM = myScaleBarWidthMM / myTickCount # Segment width in real world (m) # We apply some logic here so that segments are displayed in meters # if each segment is less that 1000m otherwise km. Also the segment # lengths are rounded down to human looking numbers e.g. 1km not 1.1km myUnits = '' myGroundSegmentWidth = myPrintSegmentWidthMM * myMMToGroundDistance if myGroundSegmentWidth < 1000: myUnits = 'm' myGroundSegmentWidth = round(myGroundSegmentWidth) # adjust the segment width now to account for rounding myPrintSegmentWidthMM = myGroundSegmentWidth / myMMToGroundDistance else: myUnits = 'km' # Segment with in real world (km) myGroundSegmentWidth = round(myGroundSegmentWidth / 1000) myPrintSegmentWidthMM = ((myGroundSegmentWidth * 1000) / myMMToGroundDistance) # Now adjust the scalebar width to account for rounding myScaleBarWidthMM = myTickCount * myPrintSegmentWidthMM #print "SBWMM:", myScaleBarWidthMM #print "SWMM:", myPrintSegmentWidthMM #print "SWM:", myGroundSegmentWidthM #print "SWKM:", myGroundSegmentWidthKM # start drawing in line segments myScaleBarHeight = 5 # mm myLineWidth = 0.3 # mm myInsetDistance = 7 # how much to inset the scalebar into the map by myScaleBarX = self.pageMargin + myInsetDistance myScaleBarY = ( top_offset + self.mapHeight - myInsetDistance - myScaleBarHeight) # mm # Draw an outer background box - shamelessly hardcoded buffer myRect = QgsComposerShape(myScaleBarX - 4, # left edge myScaleBarY - 3, # top edge myScaleBarWidthMM + 13, # right edge myScaleBarHeight + 6, # bottom edge self.composition) myRect.setShapeType(QgsComposerShape.Rectangle) myPen = QtGui.QPen() myPen.setColor(QtGui.QColor(255, 255, 255)) myPen.setWidthF(myLineWidth) myRect.setPen(myPen) #myRect.setLineWidth(myLineWidth) myRect.setFrameEnabled(False) myBrush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) # workaround for missing setTransparentFill missing from python api myRect.setBrush(myBrush) self.composition.addItem(myRect) # Set up the tick label font myFontWeight = QtGui.QFont.Normal myFontSize = 6 myItalicsFlag = False myFont = QtGui.QFont('verdana', myFontSize, myFontWeight, myItalicsFlag) # Draw the bottom line myUpshift = 0.3 # shift the bottom line up for better rendering myRect = QgsComposerShape(myScaleBarX, myScaleBarY + myScaleBarHeight - myUpshift, myScaleBarWidthMM, 0.1, self.composition) myRect.setShapeType(QgsComposerShape.Rectangle) myPen = QtGui.QPen() myPen.setColor(QtGui.QColor(255, 255, 255)) myPen.setWidthF(myLineWidth) myRect.setPen(myPen) #myRect.setLineWidth(myLineWidth) myRect.setFrameEnabled(False) self.composition.addItem(myRect) # Now draw the scalebar ticks for myTickCountIterator in range(0, myTickCount + 1): myDistanceSuffix = '' if myTickCountIterator == myTickCount: myDistanceSuffix = ' ' + myUnits myRealWorldDistance = ('%.0f%s' % (myTickCountIterator * myGroundSegmentWidth, myDistanceSuffix)) #print 'RW:', myRealWorldDistance myMMOffset = myScaleBarX + (myTickCountIterator * myPrintSegmentWidthMM) #print 'MM:', myMMOffset myTickHeight = myScaleBarHeight / 2 # Lines are not exposed by the api yet so we # bodge drawing lines using rectangles with 1px height or width myTickWidth = 0.1 # width or rectangle to be drawn myUpTickLine = QgsComposerShape( myMMOffset, myScaleBarY + myScaleBarHeight - myTickHeight, myTickWidth, myTickHeight, self.composition) myUpTickLine.setShapeType(QgsComposerShape.Rectangle) myPen = QtGui.QPen() myPen.setWidthF(myLineWidth) myUpTickLine.setPen(myPen) #myUpTickLine.setLineWidth(myLineWidth) myUpTickLine.setFrameEnabled(False) self.composition.addItem(myUpTickLine) # # Add a tick label # myLabel = QgsComposerLabel(self.composition) myLabel.setFont(myFont) myLabel.setText(myRealWorldDistance) myLabel.adjustSizeToText() myLabel.setItemPosition( myMMOffset - 3, myScaleBarY - myTickHeight) myLabel.setFrameEnabled(self.showFramesFlag) self.composition.addItem(myLabel)
def draw_graticule_mask(self, top_offset): """A helper function to mask out graticule labels. It will hide labels on the right side by over painting a white rectangle with white border on them. **kludge** :param top_offset: Vertical offset at which the logo should be drawn. :type top_offset: int """ LOGGER.debug('InaSAFE Map drawGraticuleMask called') myLeftOffset = self.pageMargin + self.mapWidth myRect = QgsComposerShape(myLeftOffset + 0.5, top_offset, self.pageWidth - myLeftOffset, self.mapHeight + 1, self.composition) myRect.setShapeType(QgsComposerShape.Rectangle) myPen = QtGui.QPen() myPen.setColor(QtGui.QColor(0, 0, 0)) myPen.setWidthF(0.1) myRect.setPen(myPen) myRect.setBackgroundColor(QtGui.QColor(255, 255, 255)) myRect.setTransparency(100) #myRect.setLineWidth(0.1) #myRect.setFrameEnabled(False) #myRect.setOutlineColor(QtGui.QColor(255, 255, 255)) #myRect.setFillColor(QtGui.QColor(255, 255, 255)) #myRect.setOpacity(100) # These two lines seem superfluous but are needed myBrush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) myRect.setBrush(myBrush) self.composition.addItem(myRect)
def draw_scalebar(self, composer_map, top_offset): """Add a numeric scale to the bottom left of the map. We draw the scale bar manually because QGIS does not yet support rendering a scale bar for a geographic map in km. .. seealso:: :meth:`drawNativeScaleBar` :param composer_map: Composer map on which to draw the scalebar. :type composer_map: QgsComposerMap :param top_offset: Vertical offset at which the logo should be drawn. :type top_offset: int """ LOGGER.debug('InaSAFE Map drawScaleBar called') canvas = self.iface.mapCanvas() renderer = canvas.mapRenderer() # # Add a linear map scale # distance_area = QgsDistanceArea() distance_area.setSourceCrs(renderer.destinationCrs().srsid()) distance_area.setEllipsoidalMode(True) # Determine how wide our map is in km/m # Starting point at BL corner composer_extent = composer_map.extent() start_point = QgsPoint(composer_extent.xMinimum(), composer_extent.yMinimum()) # Ending point at BR corner end_point = QgsPoint(composer_extent.xMaximum(), composer_extent.yMinimum()) ground_distance = distance_area.measureLine(start_point, end_point) # Get the equivalent map distance per page mm map_width = self.mapWidth # How far is 1mm on map on the ground in meters? mm_to_ground = ground_distance / map_width #print 'MM:', myMMDistance # How long we want the scale bar to be in relation to the map scalebar_to_map_ratio = 0.5 # How many divisions the scale bar should have tick_count = 5 scale_bar_width_mm = map_width * scalebar_to_map_ratio print_segment_width_mm = scale_bar_width_mm / tick_count # Segment width in real world (m) # We apply some logic here so that segments are displayed in meters # if each segment is less that 1000m otherwise km. Also the segment # lengths are rounded down to human looking numbers e.g. 1km not 1.1km units = '' ground_segment_width = print_segment_width_mm * mm_to_ground if ground_segment_width < 1000: units = 'm' ground_segment_width = round(ground_segment_width) # adjust the segment width now to account for rounding print_segment_width_mm = ground_segment_width / mm_to_ground else: units = 'km' # Segment with in real world (km) ground_segment_width = round(ground_segment_width / 1000) print_segment_width_mm = ((ground_segment_width * 1000) / mm_to_ground) # Now adjust the scalebar width to account for rounding scale_bar_width_mm = tick_count * print_segment_width_mm #print "SBWMM:", scale_bar_width_mm #print "SWMM:", print_segment_width_mm #print "SWM:", myGroundSegmentWidthM #print "SWKM:", myGroundSegmentWidthKM # start drawing in line segments scalebar_height = 5 # mm line_width = 0.3 # mm inset_distance = 7 # how much to inset the scalebar into the map by scalebar_x = self.page_margin + inset_distance scalebar_y = (top_offset + self.map_height - inset_distance - scalebar_height) # mm # Draw an outer background box - shamelessly hardcoded buffer rectangle = QgsComposerShape( scalebar_x - 4, # left edge scalebar_y - 3, # top edge scale_bar_width_mm + 13, # right edge scalebar_height + 6, # bottom edge self.composition) rectangle.setShapeType(QgsComposerShape.Rectangle) pen = QtGui.QPen() pen.setColor(QtGui.QColor(255, 255, 255)) pen.setWidthF(line_width) rectangle.setPen(pen) #rectangle.setLineWidth(line_width) rectangle.setFrameEnabled(False) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) # workaround for missing setTransparentFill missing from python api rectangle.setBrush(brush) self.composition.addItem(rectangle) # Set up the tick label font font_weight = QtGui.QFont.Normal font_size = 6 italics_flag = False font = QtGui.QFont('verdana', font_size, font_weight, italics_flag) # Draw the bottom line up_shift = 0.3 # shift the bottom line up for better rendering rectangle = QgsComposerShape(scalebar_x, scalebar_y + scalebar_height - up_shift, scale_bar_width_mm, 0.1, self.composition) rectangle.setShapeType(QgsComposerShape.Rectangle) pen = QtGui.QPen() pen.setColor(QtGui.QColor(255, 255, 255)) pen.setWidthF(line_width) rectangle.setPen(pen) #rectangle.setLineWidth(line_width) rectangle.setFrameEnabled(False) self.composition.addItem(rectangle) # Now draw the scalebar ticks for tick_counter in range(0, tick_count + 1): distance_suffix = '' if tick_counter == tick_count: distance_suffix = ' ' + units real_world_distance = ( '%.0f%s' % (tick_counter * ground_segment_width, distance_suffix)) #print 'RW:', myRealWorldDistance mm_offset = scalebar_x + (tick_counter * print_segment_width_mm) #print 'MM:', mm_offset tick_height = scalebar_height / 2 # Lines are not exposed by the api yet so we # bodge drawing lines using rectangles with 1px height or width tick_width = 0.1 # width or rectangle to be drawn uptick_line = QgsComposerShape( mm_offset, scalebar_y + scalebar_height - tick_height, tick_width, tick_height, self.composition) uptick_line.setShapeType(QgsComposerShape.Rectangle) pen = QtGui.QPen() pen.setWidthF(line_width) uptick_line.setPen(pen) #uptick_line.setLineWidth(line_width) uptick_line.setFrameEnabled(False) self.composition.addItem(uptick_line) # # Add a tick label # label = QgsComposerLabel(self.composition) label.setFont(font) label.setText(real_world_distance) label.adjustSizeToText() label.setItemPosition(mm_offset - 3, scalebar_y - tick_height) label.setFrameEnabled(self.show_frames) self.composition.addItem(label)
class TestQgsComposerShapes(unittest.TestCase): def __init__(self, methodName): """Run once on class initialization.""" unittest.TestCase.__init__(self, methodName) # create composition self.mComposition = QgsComposition(QgsProject.instance()) self.mComposition.setPaperSize(297, 210) self.mComposerShape = QgsComposerShape(20, 20, 150, 100, self.mComposition) self.mComposerShape.setBackgroundColor(QColor.fromRgb(255, 150, 0)) self.mComposition.addComposerShape(self.mComposerShape) def testRectangle(self): """Test rectangle composer shape""" self.mComposerShape.setShapeType(QgsComposerShape.Rectangle) checker = QgsCompositionChecker('composershapes_rectangle', self.mComposition) checker.setControlPathPrefix("composer_shapes") myTestResult, myMessage = checker.testComposition() assert myTestResult, myMessage def testEllipse(self): """Test ellipse composer shape""" self.mComposerShape.setShapeType(QgsComposerShape.Ellipse) checker = QgsCompositionChecker('composershapes_ellipse', self.mComposition) checker.setControlPathPrefix("composer_shapes") myTestResult, myMessage = checker.testComposition() assert myTestResult, myMessage def testTriangle(self): """Test triangle composer shape""" self.mComposerShape.setShapeType(QgsComposerShape.Triangle) checker = QgsCompositionChecker('composershapes_triangle', self.mComposition) checker.setControlPathPrefix("composer_shapes") myTestResult, myMessage = checker.testComposition() assert myTestResult, myMessage def testRoundedRectangle(self): """Test rounded rectangle composer shape""" self.mComposerShape.setShapeType(QgsComposerShape.Rectangle) self.mComposerShape.setCornerRadius(30) checker = QgsCompositionChecker('composershapes_roundedrect', self.mComposition) checker.setControlPathPrefix("composer_shapes") myTestResult, myMessage = checker.testComposition() self.mComposerShape.setCornerRadius(0) assert myTestResult, myMessage
def drawGraticuleMask(self, theTopOffset): """A helper function to mask out graticule labels on the right side by over painting a white rectangle with white border on them. Args: theTopOffset - vertical offset at which the map should be drawn Returns: None Raises: None """ LOGGER.debug('InaSAFE Map drawGraticuleMask called') myLeftOffset = self.pageMargin + self.mapWidth myRect = QgsComposerShape(myLeftOffset + 0.5, theTopOffset, self.pageWidth - myLeftOffset, self.mapHeight + 1, self.composition) myRect.setShapeType(QgsComposerShape.Rectangle) myRect.setLineWidth(0.1) myRect.setFrame(False) myRect.setOutlineColor(QtGui.QColor(255, 255, 255)) myRect.setFillColor(QtGui.QColor(255, 255, 255)) myRect.setOpacity(100) # These two lines seem superfluous but are needed myBrush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) myRect.setBrush(myBrush) self.composition.addItem(myRect)
def drawScaleBar(self, theComposerMap, theTopOffset): """Add a numeric scale to the bottom left of the map We draw the scale bar manually because QGIS does not yet support rendering a scalebar for a geographic map in km. .. seealso:: :meth:`drawNativeScaleBar` Args: * theComposerMap - QgsComposerMap instance used as the basis scale calculations. * theTopOffset - vertical offset at which the map should be drawn Returns: None Raises: Any exceptions raised by the InaSAFE library will be propagated. """ LOGGER.debug('InaSAFE Map drawScaleBar called') myCanvas = self.iface.mapCanvas() myRenderer = myCanvas.mapRenderer() # # Add a linear map scale # myDistanceArea = QgsDistanceArea() myDistanceArea.setSourceCrs(myRenderer.destinationCrs().srsid()) myDistanceArea.setProjectionsEnabled(True) # Determine how wide our map is in km/m # Starting point at BL corner myComposerExtent = theComposerMap.extent() myStartPoint = QgsPoint(myComposerExtent.xMinimum(), myComposerExtent.yMinimum()) # Ending point at BR corner myEndPoint = QgsPoint(myComposerExtent.xMaximum(), myComposerExtent.yMinimum()) myGroundDistance = myDistanceArea.measureLine(myStartPoint, myEndPoint) # Get the equivalent map distance per page mm myMapWidth = self.mapWidth # How far is 1mm on map on the ground in meters? myMMToGroundDistance = myGroundDistance / myMapWidth #print 'MM:', myMMDistance # How long we want the scale bar to be in relation to the map myScaleBarToMapRatio = 0.5 # How many divisions the scale bar should have myTickCount = 5 myScaleBarWidthMM = myMapWidth * myScaleBarToMapRatio myPrintSegmentWidthMM = myScaleBarWidthMM / myTickCount # Segment width in real world (m) # We apply some logic here so that segments are displayed in meters # if each segment is less that 1000m otherwise km. Also the segment # lengths are rounded down to human looking numbers e.g. 1km not 1.1km myUnits = '' myGroundSegmentWidth = myPrintSegmentWidthMM * myMMToGroundDistance if myGroundSegmentWidth < 1000: myUnits = 'm' myGroundSegmentWidth = round(myGroundSegmentWidth) # adjust the segment width now to account for rounding myPrintSegmentWidthMM = myGroundSegmentWidth / myMMToGroundDistance else: myUnits = 'km' # Segment with in real world (km) myGroundSegmentWidth = round(myGroundSegmentWidth / 1000) myPrintSegmentWidthMM = ((myGroundSegmentWidth * 1000) / myMMToGroundDistance) # Now adjust the scalebar width to account for rounding myScaleBarWidthMM = myTickCount * myPrintSegmentWidthMM #print "SBWMM:", myScaleBarWidthMM #print "SWMM:", myPrintSegmentWidthMM #print "SWM:", myGroundSegmentWidthM #print "SWKM:", myGroundSegmentWidthKM # start drawing in line segments myScaleBarHeight = 5 # mm myLineWidth = 0.3 # mm myInsetDistance = 7 # how much to inset the scalebar into the map by myScaleBarX = self.pageMargin + myInsetDistance myScaleBarY = (theTopOffset + self.mapHeight - myInsetDistance - myScaleBarHeight) # mm # Draw an outer background box - shamelessly hardcoded buffer myRect = QgsComposerShape( myScaleBarX - 4, # left edge myScaleBarY - 3, # top edge myScaleBarWidthMM + 13, # right edge myScaleBarHeight + 6, # bottom edge self.composition) myRect.setShapeType(QgsComposerShape.Rectangle) myRect.setLineWidth(myLineWidth) myRect.setFrame(False) myBrush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) # workaround for missing setTransparentFill missing from python api myRect.setBrush(myBrush) self.composition.addItem(myRect) # Set up the tick label font myFontWeight = QtGui.QFont.Normal myFontSize = 6 myItalicsFlag = False myFont = QtGui.QFont('verdana', myFontSize, myFontWeight, myItalicsFlag) # Draw the bottom line myUpshift = 0.3 # shift the bottom line up for better rendering myRect = QgsComposerShape(myScaleBarX, myScaleBarY + myScaleBarHeight - myUpshift, myScaleBarWidthMM, 0.1, self.composition) myRect.setShapeType(QgsComposerShape.Rectangle) myRect.setLineWidth(myLineWidth) myRect.setFrame(False) self.composition.addItem(myRect) # Now draw the scalebar ticks for myTickCountIterator in range(0, myTickCount + 1): myDistanceSuffix = '' if myTickCountIterator == myTickCount: myDistanceSuffix = ' ' + myUnits myRealWorldDistance = ( '%.0f%s' % (myTickCountIterator * myGroundSegmentWidth, myDistanceSuffix)) #print 'RW:', myRealWorldDistance myMMOffset = myScaleBarX + (myTickCountIterator * myPrintSegmentWidthMM) #print 'MM:', myMMOffset myTickHeight = myScaleBarHeight / 2 # Lines are not exposed by the api yet so we # bodge drawing lines using rectangles with 1px height or width myTickWidth = 0.1 # width or rectangle to be drawn myUpTickLine = QgsComposerShape( myMMOffset, myScaleBarY + myScaleBarHeight - myTickHeight, myTickWidth, myTickHeight, self.composition) myUpTickLine.setShapeType(QgsComposerShape.Rectangle) myUpTickLine.setLineWidth(myLineWidth) myUpTickLine.setFrame(False) self.composition.addItem(myUpTickLine) # # Add a tick label # myLabel = QgsComposerLabel(self.composition) myLabel.setFont(myFont) myLabel.setText(myRealWorldDistance) myLabel.adjustSizeToText() myLabel.setItemPosition(myMMOffset - 3, myScaleBarY - myTickHeight) myLabel.setFrame(self.showFramesFlag) self.composition.addItem(myLabel)
def draw_graticule_mask(self, top_offset): """A helper function to mask out graticule labels. It will hide labels on the right side by over painting a white rectangle with white border on them. **kludge** :param top_offset: Vertical offset at which the logo should be drawn. :type top_offset: int """ LOGGER.debug('InaSAFE Map drawGraticuleMask called') left_offset = self.page_margin + self.mapWidth rect = QgsComposerShape(left_offset + 0.5, top_offset, self.page_width - left_offset, self.map_height + 1, self.composition) rect.setShapeType(QgsComposerShape.Rectangle) pen = QtGui.QPen() pen.setColor(QtGui.QColor(0, 0, 0)) pen.setWidthF(0.1) rect.setPen(pen) rect.setBackgroundColor(QtGui.QColor(255, 255, 255)) rect.setTransparency(100) #rect.setLineWidth(0.1) #rect.setFrameEnabled(False) #rect.setOutlineColor(QtGui.QColor(255, 255, 255)) #rect.setFillColor(QtGui.QColor(255, 255, 255)) #rect.setOpacity(100) # These two lines seem superfluous but are needed brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) rect.setBrush(brush) self.composition.addItem(rect)
class TestQgsComposerEffects(unittest.TestCase): def __init__(self, methodName): """Run once on class initialization.""" unittest.TestCase.__init__(self, methodName) # create composition self.mMapSettings = QgsMapSettings() self.mComposition = QgsComposition(QgsProject.instance()) self.mComposition.setPaperSize(297, 210) self.mComposerRect1 = QgsComposerShape(20, 20, 150, 100, self.mComposition) self.mComposerRect1.setShapeType(QgsComposerShape.Rectangle) self.mComposerRect1.setBackgroundColor(QColor.fromRgb(255, 150, 0)) self.mComposition.addComposerShape(self.mComposerRect1) self.mComposerRect2 = QgsComposerShape(50, 50, 150, 100, self.mComposition) self.mComposerRect2.setShapeType(QgsComposerShape.Rectangle) self.mComposerRect2.setBackgroundColor(QColor.fromRgb(0, 100, 150)) self.mComposition.addComposerShape(self.mComposerRect2) def testBlendModes(self): """Test that blend modes work for composer items.""" self.mComposerRect2.setBlendMode(QPainter.CompositionMode_Multiply) checker = QgsCompositionChecker('composereffects_blend', self.mComposition) checker.setControlPathPrefix("composer_effects") myTestResult, myMessage = checker.testComposition() self.mComposerRect2.setBlendMode(QPainter.CompositionMode_SourceOver) assert myTestResult, myMessage def testTransparency(self): """Test that transparency works for composer items.""" self.mComposerRect2.setTransparency(50) checker = QgsCompositionChecker('composereffects_transparency', self.mComposition) checker.setControlPathPrefix("composer_effects") myTestResult, myMessage = checker.testComposition() self.mComposerRect2.setTransparency(100) assert myTestResult, myMessage
def drawGraticuleMask(self, theTopOffset): """A helper function to mask out graticule labels on the right side by over painting a white rectangle with white border on them. Args: theTopOffset - vertical offset at which the map should be drawn Returns: None Raises: None """ LOGGER.debug("InaSAFE Map drawGraticuleMask called") myLeftOffset = self.pageMargin + self.mapWidth myRect = QgsComposerShape( myLeftOffset + 0.5, theTopOffset, self.pageWidth - myLeftOffset, self.mapHeight + 1, self.composition ) myRect.setShapeType(QgsComposerShape.Rectangle) myRect.setLineWidth(0.1) myRect.setFrame(False) myRect.setOutlineColor(QtGui.QColor(255, 255, 255)) myRect.setFillColor(QtGui.QColor(255, 255, 255)) myRect.setOpacity(100) # These two lines seem superfluous but are needed myBrush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) myRect.setBrush(myBrush) self.composition.addItem(myRect)
def draw_scalebar(self, composer_map, top_offset): """Add a numeric scale to the bottom left of the map. We draw the scale bar manually because QGIS does not yet support rendering a scale bar for a geographic map in km. .. seealso:: :meth:`drawNativeScaleBar` :param composer_map: Composer map on which to draw the scalebar. :type composer_map: QgsComposerMap :param top_offset: Vertical offset at which the logo should be drawn. :type top_offset: int """ LOGGER.debug('InaSAFE Map drawScaleBar called') canvas = self.iface.mapCanvas() renderer = canvas.mapRenderer() # # Add a linear map scale # distance_area = QgsDistanceArea() distance_area.setSourceCrs(renderer.destinationCrs().srsid()) distance_area.setEllipsoidalMode(True) # Determine how wide our map is in km/m # Starting point at BL corner composer_extent = composer_map.extent() start_point = QgsPoint( composer_extent.xMinimum(), composer_extent.yMinimum()) # Ending point at BR corner end_point = QgsPoint( composer_extent.xMaximum(), composer_extent.yMinimum()) ground_distance = distance_area.measureLine(start_point, end_point) # Get the equivalent map distance per page mm map_width = self.mapWidth # How far is 1mm on map on the ground in meters? mm_to_ground = ground_distance / map_width #print 'MM:', myMMDistance # How long we want the scale bar to be in relation to the map scalebar_to_map_ratio = 0.5 # How many divisions the scale bar should have tick_count = 5 scale_bar_width_mm = map_width * scalebar_to_map_ratio print_segment_width_mm = scale_bar_width_mm / tick_count # Segment width in real world (m) # We apply some logic here so that segments are displayed in meters # if each segment is less that 1000m otherwise km. Also the segment # lengths are rounded down to human looking numbers e.g. 1km not 1.1km units = '' ground_segment_width = print_segment_width_mm * mm_to_ground if ground_segment_width < 1000: units = 'm' ground_segment_width = round(ground_segment_width) # adjust the segment width now to account for rounding print_segment_width_mm = ground_segment_width / mm_to_ground else: units = 'km' # Segment with in real world (km) ground_segment_width = round(ground_segment_width / 1000) print_segment_width_mm = ( (ground_segment_width * 1000) / mm_to_ground) # Now adjust the scalebar width to account for rounding scale_bar_width_mm = tick_count * print_segment_width_mm #print "SBWMM:", scale_bar_width_mm #print "SWMM:", print_segment_width_mm #print "SWM:", myGroundSegmentWidthM #print "SWKM:", myGroundSegmentWidthKM # start drawing in line segments scalebar_height = 5 # mm line_width = 0.3 # mm inset_distance = 7 # how much to inset the scalebar into the map by scalebar_x = self.page_margin + inset_distance scalebar_y = ( top_offset + self.map_height - inset_distance - scalebar_height) # mm # Draw an outer background box - shamelessly hardcoded buffer rectangle = QgsComposerShape( scalebar_x - 4, # left edge scalebar_y - 3, # top edge scale_bar_width_mm + 13, # right edge scalebar_height + 6, # bottom edge self.composition) rectangle.setShapeType(QgsComposerShape.Rectangle) pen = QtGui.QPen() pen.setColor(QtGui.QColor(255, 255, 255)) pen.setWidthF(line_width) rectangle.setPen(pen) #rectangle.setLineWidth(line_width) rectangle.setFrameEnabled(False) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) # workaround for missing setTransparentFill missing from python api rectangle.setBrush(brush) self.composition.addItem(rectangle) # Set up the tick label font font_weight = QtGui.QFont.Normal font_size = 6 italics_flag = False font = QtGui.QFont( 'verdana', font_size, font_weight, italics_flag) # Draw the bottom line up_shift = 0.3 # shift the bottom line up for better rendering rectangle = QgsComposerShape( scalebar_x, scalebar_y + scalebar_height - up_shift, scale_bar_width_mm, 0.1, self.composition) rectangle.setShapeType(QgsComposerShape.Rectangle) pen = QtGui.QPen() pen.setColor(QtGui.QColor(255, 255, 255)) pen.setWidthF(line_width) rectangle.setPen(pen) #rectangle.setLineWidth(line_width) rectangle.setFrameEnabled(False) self.composition.addItem(rectangle) # Now draw the scalebar ticks for tick_counter in range(0, tick_count + 1): distance_suffix = '' if tick_counter == tick_count: distance_suffix = ' ' + units real_world_distance = ( '%.0f%s' % (tick_counter * ground_segment_width, distance_suffix)) #print 'RW:', myRealWorldDistance mm_offset = scalebar_x + ( tick_counter * print_segment_width_mm) #print 'MM:', mm_offset tick_height = scalebar_height / 2 # Lines are not exposed by the api yet so we # bodge drawing lines using rectangles with 1px height or width tick_width = 0.1 # width or rectangle to be drawn uptick_line = QgsComposerShape( mm_offset, scalebar_y + scalebar_height - tick_height, tick_width, tick_height, self.composition) uptick_line.setShapeType(QgsComposerShape.Rectangle) pen = QtGui.QPen() pen.setWidthF(line_width) uptick_line.setPen(pen) #uptick_line.setLineWidth(line_width) uptick_line.setFrameEnabled(False) self.composition.addItem(uptick_line) # # Add a tick label # label = QgsComposerLabel(self.composition) label.setFont(font) label.setText(real_world_distance) label.adjustSizeToText() label.setItemPosition( mm_offset - 3, scalebar_y - tick_height) label.setFrameEnabled(self.show_frames) self.composition.addItem(label)
class TestQgsComposerEffects(TestCase): def __init__(self, methodName): """Run once on class initialisation.""" unittest.TestCase.__init__(self, methodName) # create composition self.mMapRenderer = QgsMapRenderer() self.mComposition = QgsComposition(self.mMapRenderer) self.mComposition.setPaperSize(297, 210) self.mComposerRect1 = QgsComposerShape(20, 20, 150, 100, self.mComposition) self.mComposerRect1.setShapeType(QgsComposerShape.Rectangle) self.mComposerRect1.setBackgroundColor(QColor.fromRgb(255, 150, 0)) self.mComposition.addComposerShape(self.mComposerRect1) self.mComposerRect2 = QgsComposerShape(50, 50, 150, 100, self.mComposition) self.mComposerRect2.setShapeType(QgsComposerShape.Rectangle) self.mComposerRect2.setBackgroundColor(QColor.fromRgb(0, 100, 150)) self.mComposition.addComposerShape(self.mComposerRect2) def testBlendModes(self): """Test that blend modes work for composer items.""" self.mComposerRect2.setBlendMode(QPainter.CompositionMode_Multiply) checker = QgsCompositionChecker() myPath = os.path.join(TEST_DATA_DIR, 'control_images', 'expected_composereffects', 'composereffect_blend.png') myTestResult, myMessage = checker.testComposition( 'Composer effects blending', self.mComposition, myPath) self.mComposerRect2.setBlendMode(QPainter.CompositionMode_SourceOver) assert myTestResult == True, myMessage def testTransparency(self): """Test that transparency works for composer items.""" self.mComposerRect2.setTransparency(50) checker = QgsCompositionChecker() myPath = os.path.join(TEST_DATA_DIR, 'control_images', 'expected_composereffects', 'composereffect_transparency.png') myTestResult, myMessage = checker.testComposition( 'Composer effects transparency', self.mComposition, myPath) self.mComposerRect2.setTransparency(100) assert myTestResult == True, myMessage
class TestQgsComposerShapes(TestCase): def __init__(self, methodName): """Run once on class initialisation.""" unittest.TestCase.__init__(self, methodName) # create composition self.mComposition = QgsComposition(None) self.mComposition.setPaperSize(297, 210) self.mComposerShape = QgsComposerShape(20, 20, 150, 100, self.mComposition) self.mComposerShape.setBackgroundColor(QColor.fromRgb(255, 150, 0)) self.mComposition.addComposerShape(self.mComposerShape) def testRectangle(self): """Test rectangle composer shape""" self.mComposerShape.setShapeType(QgsComposerShape.Rectangle) checker = QgsCompositionChecker() myPath = os.path.join(TEST_DATA_DIR, 'control_images', 'expected_composershapes', 'composershape_rectangle.png') myTestResult, myMessage = checker.testComposition( 'Composer shapes rectangle', self.mComposition, myPath) assert myTestResult == True, myMessage def testEllipse(self): """Test ellipse composer shape""" self.mComposerShape.setShapeType(QgsComposerShape.Ellipse) checker = QgsCompositionChecker() myPath = os.path.join(TEST_DATA_DIR, 'control_images', 'expected_composershapes', 'composershape_ellipse.png') myTestResult, myMessage = checker.testComposition( 'Composer shapes ellipse', self.mComposition, myPath) assert myTestResult == True, myMessage def testTriangle(self): """Test triangle composer shape""" self.mComposerShape.setShapeType(QgsComposerShape.Triangle) checker = QgsCompositionChecker() myPath = os.path.join(TEST_DATA_DIR, 'control_images', 'expected_composershapes', 'composershape_triangle.png') myTestResult, myMessage = checker.testComposition( 'Composer shapes triangle', self.mComposition, myPath) assert myTestResult == True, myMessage def testRoundedRectangle(self): """Test rounded rectangle composer shape""" self.mComposerShape.setShapeType(QgsComposerShape.Rectangle) self.mComposerShape.setCornerRadius(30) checker = QgsCompositionChecker() myPath = os.path.join(TEST_DATA_DIR, 'control_images', 'expected_composershapes', 'composershape_roundedrectangle.png') myTestResult, myMessage = checker.testComposition( 'Composer shapes rounded rectangle', self.mComposition, myPath) self.mComposerShape.setCornerRadius(0) assert myTestResult == True, myMessage
class TestQgsComposerShapes(unittest.TestCase): def __init__(self, methodName): """Run once on class initialization.""" unittest.TestCase.__init__(self, methodName) self.mapSettings = QgsMapSettings() # create composition self.mComposition = QgsComposition(self.mapSettings) self.mComposition.setPaperSize(297, 210) self.mComposerShape = QgsComposerShape(20, 20, 150, 100, self.mComposition) self.mComposerShape.setBackgroundColor(QColor.fromRgb(255, 150, 0)) self.mComposition.addComposerShape(self.mComposerShape) def testRectangle(self): """Test rectangle composer shape""" self.mComposerShape.setShapeType(QgsComposerShape.Rectangle) checker = QgsCompositionChecker('composershapes_rectangle', self.mComposition) checker.setControlPathPrefix("composer_shapes") myTestResult, myMessage = checker.testComposition() assert myTestResult, myMessage def testEllipse(self): """Test ellipse composer shape""" self.mComposerShape.setShapeType(QgsComposerShape.Ellipse) checker = QgsCompositionChecker('composershapes_ellipse', self.mComposition) checker.setControlPathPrefix("composer_shapes") myTestResult, myMessage = checker.testComposition() assert myTestResult, myMessage def testTriangle(self): """Test triangle composer shape""" self.mComposerShape.setShapeType(QgsComposerShape.Triangle) checker = QgsCompositionChecker('composershapes_triangle', self.mComposition) checker.setControlPathPrefix("composer_shapes") myTestResult, myMessage = checker.testComposition() assert myTestResult, myMessage def testRoundedRectangle(self): """Test rounded rectangle composer shape""" self.mComposerShape.setShapeType(QgsComposerShape.Rectangle) self.mComposerShape.setCornerRadius(30) checker = QgsCompositionChecker('composershapes_roundedrect', self.mComposition) checker.setControlPathPrefix("composer_shapes") myTestResult, myMessage = checker.testComposition() self.mComposerShape.setCornerRadius(0) assert myTestResult, myMessage
class TestQgsComposerShapes(TestCase): def __init__(self, methodName): """Run once on class initialisation.""" unittest.TestCase.__init__(self, methodName) # create composition self.mComposition = QgsComposition(None) self.mComposition.setPaperSize(297, 210) self.mComposerShape = QgsComposerShape(20, 20, 150, 100, self.mComposition) self.mComposerShape.setBackgroundColor(QColor.fromRgb(255, 150, 0)) self.mComposition.addComposerShape(self.mComposerShape) def testRectangle(self): """Test rectangle composer shape""" self.mComposerShape.setShapeType(QgsComposerShape.Rectangle) checker = QgsCompositionChecker() myPath = os.path.join(TEST_DATA_DIR, 'control_images', 'expected_composershapes', 'composershape_rectangle.png') myTestResult, myMessage = checker.testComposition('Composer shapes rectangle', self.mComposition, myPath) assert myTestResult == True, myMessage def testEllipse(self): """Test ellipse composer shape""" self.mComposerShape.setShapeType(QgsComposerShape.Ellipse) checker = QgsCompositionChecker() myPath = os.path.join(TEST_DATA_DIR, 'control_images', 'expected_composershapes', 'composershape_ellipse.png') myTestResult, myMessage = checker.testComposition('Composer shapes ellipse', self.mComposition, myPath) assert myTestResult == True, myMessage def testTriangle(self): """Test triangle composer shape""" self.mComposerShape.setShapeType(QgsComposerShape.Triangle) checker = QgsCompositionChecker() myPath = os.path.join(TEST_DATA_DIR, 'control_images', 'expected_composershapes', 'composershape_triangle.png') myTestResult, myMessage = checker.testComposition('Composer shapes triangle', self.mComposition, myPath) assert myTestResult == True, myMessage def testRoundedRectangle(self): """Test rounded rectangle composer shape""" self.mComposerShape.setShapeType(QgsComposerShape.Rectangle) self.mComposerShape.setCornerRadius(30) checker = QgsCompositionChecker() myPath = os.path.join(TEST_DATA_DIR, 'control_images', 'expected_composershapes', 'composershape_roundedrectangle.png') myTestResult, myMessage = checker.testComposition('Composer shapes rounded rectangle', self.mComposition, myPath) self.mComposerShape.setCornerRadius(0) assert myTestResult == True, myMessage