def __init__(self, inputData, solutionData, routeAttribute, attributeName=None, styleSheet=None): wx.Frame.__init__(self, None, wx.ID_ANY, title='Grid view') if attributeName is None: attributeName = routeAttribute gridStyle = stylesheet.StyleSheet() if styleSheet is None\ else styleSheet # step 1: count and sort the occurrences of the grid attribute attributeValues = set( [route[routeAttribute] for route in solutionData.routes]) gridSize = len(attributeValues) # old version gridWidth = int(math.ceil(math.sqrt(gridSize))) # new version colsPerRow = 4.0 / 3.0 * inputData.heightOverWidth gridWidth = int(colsPerRow * gridWidth) # gridHeight = 1 + gridSize / gridWidth gridSizer = wx.GridSizer(gridHeight, gridWidth, vgap=5, hgap=5) # # step 2: fill the grid ffs! vSizers = [wx.BoxSizer(wx.VERTICAL) for i in range(gridSize)] labels = [ attributeName + ' ' + str(value) for value in attributeValues ] predicates = [ util.makeRoutePredicate(routeAttribute, value) for value in attributeValues ] self.panels = [ VrpPanel(self, inputData=inputData, solutionData=solutionData, routePredicate=pred, styleSheet=gridStyle) for pred in predicates ] # add all our panels to our grid for vSizer, label, panel, count in zip(vSizers, labels, self.panels, range(len(attributeValues))): vSizer.Add(wx.StaticText(self, label=label), proportion=0, flag=wx.ALIGN_CENTER | wx.ALL, border=3) vSizer.Add(panel, 1, wx.EXPAND) # add the whole box in our grid gridSizer.Add(vSizer, 1, wx.EXPAND) w = inputData.width / gridWidth h = w * inputData.heightOverWidth panel.SetSize((w, h)) # display the grid! self.SetSizerAndFit(gridSizer) self.Show()
def __init__(self, inputData, solutionData, routeAttribute, attributeName=None, styleSheet=None): wx.Frame.__init__(self, None, wx.ID_ANY, title='Grid view') if attributeName is None: attributeName = routeAttribute gridStyle = stylesheet.StyleSheet() if styleSheet is None\ else styleSheet # step 1: count and sort the occurrences of the grid attribute attributeValues = set([ route[routeAttribute] for route in solutionData.routes ]) gridSize = len(attributeValues) # old version gridWidth = int(math.ceil(math.sqrt(gridSize))) # new version colsPerRow = 4.0/3.0 * inputData.heightOverWidth gridWidth = int(colsPerRow * gridWidth) # gridHeight = 1 + gridSize / gridWidth gridSizer = wx.GridSizer(gridHeight, gridWidth, vgap = 5, hgap = 5) # # step 2: fill the grid ffs! vSizers = [ wx.BoxSizer(wx.VERTICAL) for i in range(gridSize) ] labels = [ attributeName + ' ' + str(value) for value in attributeValues ] predicates = [ util.makeRoutePredicate(routeAttribute, value) for value in attributeValues ] self.panels = [ VrpPanel(self, inputData = inputData, solutionData = solutionData, routePredicate = pred, styleSheet = gridStyle ) for pred in predicates ] # add all our panels to our grid for vSizer, label, panel, count in zip(vSizers, labels, self.panels, range(len(attributeValues))): vSizer.Add(wx.StaticText(self, label=label), proportion=0, flag=wx.ALIGN_CENTER | wx.ALL, border=3) vSizer.Add(panel, 1, wx.EXPAND) # add the whole box in our grid gridSizer.Add(vSizer, 1, wx.EXPAND) w = inputData.width / gridWidth h = w * inputData.heightOverWidth panel.SetSize((w, h)) # display the grid! self.SetSizerAndFit(gridSizer) self.Show()
def paint( self, inputData, solutionData, canvas, nodePredicate=None, # lambda(x): True, routePredicate=None, # lambda(x): True, arcPredicate=None, # lambda(x): True, thumbnail=False, ): """ Paint inputData and solutionData on canvas. The predicates are used to filter out some nodes, routes and arcs if required. They are passed to each style's individual paint() call. The style is supposed to paint only the entities that satisfy the predicate. """ canvas.blank() # case where we want to paint a thumbnail: smaller padding and a border if thumbnail: margin = 2 canvas.drawBorder() else: margin = padding # compute bounding box for drawing width, height = canvas.getSize() # start grid code here! if not self.gridRouteAttribute and solutionData.routeAttributes: self.gridRouteAttribute = solutionData.routeAttributes[0] # only use a grid if the solution isn't empty if self.grid and solutionData.routes: # count and sort the occurrences of the grid attribute attributeValues = set([route[self.gridRouteAttribute] for route in solutionData.routes]) gridSize = len(attributeValues) # if we must use a grid but haven't specified dimensions for it yet if not self.nColumnsInGrid: # approximate a square grid wPrime = 1.0 / inputData.heightOverWidth self.nColumnsInGrid = int(ceil(sqrt(gridSize * wPrime) / wPrime)) self.nRowsInGrid = 1 + (gridSize - 1) / self.nColumnsInGrid # compute number of rows from number of columns nColumns = self.nColumnsInGrid nRows = self.nRowsInGrid # case where we don't use a grid else: # in case grid is set to True but the solution is empty self.grid = False nColumns = 1 nRows = 1 attributeValues = set([None]) cellWidth = float(width + gridCellPadding) / nColumns cellHeight = float(height + gridCellPadding) / nRows # for each cell in the grid, compute its bounding box # draw a grid if needed # (do it before displaying the cell's title) if self.drawGridLines and self.grid: self.drawGrid(canvas, nColumns, nRows) for i, cell in enumerate(attributeValues): # grid coordinates for the cell cellX = i % nColumns cellY = i / nColumns # real coordinates of the cell cellXmin = cellX * cellWidth cellXmax = cellXmin + cellWidth - gridCellPadding cellYmax = height - cellY * cellHeight cellYmin = cellYmax - cellHeight + gridCellPadding # In case grid decoration is required if self.grid and self.displayCellTitle: titleText = self.cellTitleFormat.replace("%a", str(self.gridRouteAttribute)).replace("%v", str(cell)) canvas.drawFancyText( titleText, cellXmin + (cellXmax - cellXmin) / 2.0, cellYmax - cellTitleFontSize / 2.0, gridDecorationFont, colours.black, colours.white, referencePoint="centre", ) cellYmax -= cellTitleFontSize # self.drawCellBorder(canvas, # cellXmin, cellXmax, cellYmin, cellYmax) # only draw in this cell canvas.restrictDrawing(cellXmin, cellYmin, cellXmax, cellYmax) # next steps: xmin, xmax, ymin, ymax = self.computeOuterBoundingBox( cellXmin, cellXmax, cellYmin, cellYmax, inputData, margin ) revX, revY = self.getReverseCoordMapping(canvas, inputData) convertX, convertY = self.getTransformations(cellXmin, cellXmax, cellYmin, cellYmax, inputData, margin) # predicate if required for grid tmpNodePredicate = lambda (x): True if not self.grid: newRoutePredicate = routePredicate else: tmpPredicate = util.makeRoutePredicate(self.gridRouteAttribute, cell) newRoutePredicate = lambda (route): tmpPredicate(route) and ( routePredicate is None or routePredicate(route) ) # in case we also need to filter nodes if self.filterNodesInGrid: tmpNodePredicate = util.makeNodeInRoutePredicate(solutionData, newRoutePredicate) newNodePredicate = lambda (node): tmpNodePredicate(node) and (nodePredicate is None or nodePredicate(node)) # display all styles sequentially for style in self.styles: style.paintData( inputData, solutionData, canvas, convertX, convertY, newNodePredicate, newRoutePredicate, arcPredicate, ( revX(xmin - padding + 2), revY(ymin - padding + 2), revX(xmax + padding - 2), revY(ymax + padding - 2), ), ) # allow to draw everywhere again canvas.unrestrictDrawing()
def paint(self, inputData, solutionData, canvas, nodePredicate=None, #lambda(x): True, routePredicate=None, #lambda(x): True, arcPredicate=None, #lambda(x): True, thumbnail=False): """ Paint inputData and solutionData on canvas. The predicates are used to filter out some nodes, routes and arcs if required. They are passed to each style's individual paint() call. The style is supposed to paint only the entities that satisfy the predicate. """ canvas.blank() # case where we want to paint a thumbnail: smaller padding and a border if thumbnail: margin = 2 canvas.drawBorder() else: margin = padding # compute bounding box for drawing width, height = canvas.getSize() # start grid code here! if not self.gridRouteAttribute and solutionData.routeAttributes: self.gridRouteAttribute = solutionData.routeAttributes[0] # case where a grid is defined but the grid attribute does not exist in # the routes for route in solutionData.routes: if not self.gridRouteAttribute in route: self.gridRouteAttribute = solutionData.routeAttributes[0] break # only use a grid if the solution isn't empty if self.grid and solutionData.routes: # count and sort the occurrences of the grid attribute attributeValues = set([ route[self.gridRouteAttribute] for route in solutionData.routes ]) gridSize = len(attributeValues) # if we must use a grid but haven't specified dimensions for it yet if not self.nColumnsInGrid: # approximate a square grid wPrime = 1.0 / inputData.heightOverWidth self.nColumnsInGrid = \ int(ceil(sqrt(gridSize * wPrime) / wPrime)) self.nRowsInGrid = 1 + (gridSize-1) / self.nColumnsInGrid # compute number of rows from number of columns nColumns = self.nColumnsInGrid nRows = self.nRowsInGrid # case where we don't use a grid else: # in case grid is set to True but the solution is empty self.grid = False nColumns = 1 nRows = 1 attributeValues = set([None]) cellWidth = float(width + gridCellPadding) / nColumns cellHeight = float(height + gridCellPadding) / nRows # for each cell in the grid, compute its bounding box # draw a grid if needed # (do it before displaying the cell's title) if self.drawGridLines and self.grid: self.drawGrid(canvas, nColumns, nRows) for i, cell in enumerate(attributeValues): # grid coordinates for the cell cellX = i % nColumns cellY = i / nColumns # real coordinates of the cell cellXmin = cellX * cellWidth cellXmax = cellXmin + cellWidth - gridCellPadding cellYmax = height - cellY * cellHeight cellYmin = cellYmax - cellHeight + gridCellPadding # In case grid decoration is required if self.grid and self.displayCellTitle: titleText = \ self.cellTitleFormat.replace('%a', str(self.gridRouteAttribute))\ .replace('%v', str(cell)) canvas.drawFancyText(titleText, cellXmin + (cellXmax - cellXmin) / 2.0, cellYmax - cellTitleFontSize / 2.0, gridDecorationFont, colours.black, colours.white, referencePoint='centre') cellYmax -= cellTitleFontSize # self.drawCellBorder(canvas, # cellXmin, cellXmax, cellYmin, cellYmax) # only draw in this cell canvas.restrictDrawing(cellXmin, cellYmin, cellXmax, cellYmax) # next steps: xmin, xmax, ymin, ymax = \ self.computeOuterBoundingBox(cellXmin, cellXmax, cellYmin, cellYmax, inputData, margin) revX, revY = self.getReverseCoordMapping(canvas, inputData) convertX, convertY = self.getTransformations(cellXmin, cellXmax, cellYmin, cellYmax, inputData, margin) # predicate if required for grid tmpNodePredicate = lambda(x): True if not self.grid: newRoutePredicate = routePredicate else: tmpPredicate = util.makeRoutePredicate(self.gridRouteAttribute, cell) newRoutePredicate = \ lambda(route): tmpPredicate(route) and \ (routePredicate is None or routePredicate(route)) # in case we also need to filter nodes if self.filterNodesInGrid: tmpNodePredicate = \ util.makeNodeInRoutePredicate(solutionData, newRoutePredicate) newNodePredicate = lambda(node): tmpNodePredicate(node) and\ (nodePredicate is None or nodePredicate(node)) # display all styles sequentially for style in self.styles: if i == 0 or not style.oncePerGrid: style.paintData(inputData, solutionData, canvas, convertX, convertY, newNodePredicate, newRoutePredicate, arcPredicate, (revX(xmin-padding+2), revY(ymin-padding+2), revX(xmax+padding-2), revY(ymax+padding-2)) ) # allow to draw everywhere again canvas.unrestrictDrawing()