def addCircleOverlay(self, circleOverlay, container=True, **attr): """Adds and returns fig.Circle for all circles of the given overlay, using the overlays' color and width.""" if container == True: container = self.f circles = circleOverlay.originalCircles attr = dict(attr) self._setOverlayColor(circleOverlay, "penColor", attr) o = self.offset + attr.get('offset', (0, 0)) if self.roi: o = o - self.roi.begin() # don't modify in-place! result = fig.Compound(container) for center, radius in circles: if self.roi and not self.roi.contains(center + o): continue p = intPos(((center[0], center[1]) + o) * self.scale) dc = fig.Circle(p, radius * self.scale) for a in attr: setattr(dc, a, attr[a]) result.append(dc) return result
def addPointCircles(self, points, radius, returnIndices=False, container=True, **attr): """fe.addPointCircles(points, radius, returnIndices = False,...) Marks each point in points with a circle of the given radius (in pixels) if it is within the clipping rect. The list of fig.Circle objects is returned. Again, note the possibility of setting properties (depth, penColor, lineStyle, lineWidth, ...) on all resulting objects via keyword arguments (cf. documentation of the FigExporter class). By default, circles will be filled, but have lineWidth=0. To draw a transparent circle, call: fi.addPointCircles([(5.2,5.3)], 2, penColor=fig.Color.Cyan,fillStyle=fig.FillStyle.None,lineWidth=1) If returnIndices is set to True (default: False), a list of (i, c) pairs is returned instead, where c is the fig.Circle object, and i is the index of the corresponding position in points.""" if container == True: container = self.f attr = dict(attr) if "fillStyle" not in attr: attr["fillStyle"] = fig.FillStyle.Solid if "lineWidth" not in attr and attr["fillStyle"] != fig.FillStyle.None: attr["lineWidth"] = 0 compound = fig.Compound(container) if returnIndices: result = [] else: result = compound o = self.offset + attr.get('offset', (0, 0)) o2 = self.roi and o - self.roi.begin() or o for i, point in enumerate(points): if self.roi: radiusOff = (radius, radius) circleBounds = BoundingBox(o + point - radiusOff, o + point + radiusOff) if not self.roi.contains(circleBounds): continue # FIXME: add arcs if intersects p = intPos((numpy.array((point[0], point[1])) + o2) * self.scale) dc = fig.Circle(p, radius * self.scale) for a in attr: if a != "offset": setattr(dc, a, attr[a]) if returnIndices: result.append((i, dc)) compound.append(dc) return result
def addPixelRaster(self, rect=None, labels=None, fill=None, container=True, labelType=int, **attr): """The default label size looks good with 1cm^2 pixels (scale = 450).""" assert rect or labels or fill if rect is None: rect = Rect2D((labels or fill).size()) elif not hasattr(rect, "upperLeft"): w, h = rect rect = Rect2D((w, h)) if container == True: container = self.f result = fig.Compound(container) for x, y in meshIter(rect): boxX1 = (x - rect.left()) * self.scale boxY1 = (y - rect.top()) * self.scale boxX2 = boxX1 + self.scale boxY2 = boxY1 + self.scale pixelRect = fig.PolyBox(boxX1, boxY1, boxX2, boxY2) for a in attr: setattr(pixelRect, a, attr[a]) if labels: textX = (boxX1 + boxX2) / 2 textY = (boxY1 + boxY2) / 2 label = fig.Text(fig.Vector(textX, textY), str(labelType(labels[x, y])), alignment=fig.Alignment.Centered) label.pos += (0, label.height / 2) label.depth = pixelRect.depth - 10 label.font = fig.Font.Helvetica result.append(label) if fill: pixelRect.fillStyle = fig.FillStyle.Solid pixelRect.fillColor = self.f.getColor(int(fill[x, y])) result.append(pixelRect) return result
def addEdgels(self, edgels, length=0.65, container=True, **attr): if container == True: container = self.f result = fig.Compound(container) for edgel in edgels: pos = numpy.array((edgel.x, edgel.y)) c = math.cos(edgel.orientation) * length / 2 s = -math.sin(edgel.orientation) * length / 2 self.addClippedPoly([pos + (c, s), pos - (c, s)], container=result, **attr) return result
def addEdgeOverlay(self, edgeOverlay, container=True, **attr): """Adds and returns fig.Polygon for all edges (or -parts, see addClippedPoly) of the given overlay, using the overlays' color.""" if container == True: container = self.f edges = edgeOverlay.originalEdges attr = dict(attr) self._setOverlayColor(edgeOverlay, "penColor", attr) attr["offset"] = (edgeOverlay.offset[0] - 0.5, edgeOverlay.offset[1] - 0.5) result = fig.Compound(container) for edge in edges: parts = self.addClippedPoly(edge, container=result, **attr) return result
def addMapEdges(self, map, skipBorder=False, returnEdges=False, container=True, **attr): """Adds and returns fig.Polygons for all map edges (or -parts, see addClippedPoly). If no penColor is given, only edges with a valid 'color' attribute are exported (can be either a fig or a Qt color). For example, to draw only a subregion, and shift the upper left of the region to the origin, call fi.addMapEdges(map, penColor=fig.Color.Green, \ offset=(-13,-13), roi=BoundingBox((13,13), (24,24))) """ if container == True: container = self.f compound = fig.Compound(container) if returnEdges: result = [] else: result = compound for edge in map.edgeIter(): if skipBorder and edge.flag(flag_constants.BORDER_PROTECTION): continue parts = self.addClippedPoly(edge, container=compound, **attr) if returnEdges: result.extend([(edge, part) for part in parts]) return result
def addMapFaces(self, geomap, faceMeans=None, similarity=None, returnFaces=False, container=True, **attr): """fe.addMapFaces(geomap, faceMeans, ...) Adds and returns fig.Polygons for all map faces (or -parts, see addClippedPoly). Clipping closed polygons should work nowadays, too.""" import maputils def getGray(face): faceColor = faceMeans[face.label()] return self.f.gray(int(faceColor)) def getRGB(face): faceColor = faceMeans[face.label()] return self.f.getColor(map(int, tuple(faceColor)), similarity) if not faceMeans: if not hasattr(geomap, "faceMeans"): raise ValueError( "addMapFaces: need faceMeans for proper coloring") faceMeans = geomap.faceMeans if hasattr(faceMeans, "bands"): getFaceColor = getGray if faceMeans.bands() == 3: getFaceColor = getRGB else: getFaceColor = lambda face: faceMeans[face.label()] if container == True: container = self.f attr = dict(attr) attr["lineWidth"] = attr.get("lineWidth", 0) attr["fillStyle"] = attr.get("fillStyle", fig.FillStyle.Solid) compound = fig.Compound(container) if returnFaces: result = [] else: result = compound todo = [geomap.face(0)] # +1 because the first iteration will not add any objects: currentDepth = attr.get("depth", 100) + 1 while todo: thisLayer = todo todo = [] for face in thisLayer: if face.area() > 0: color = getFaceColor(face) if color is not None: thisattr = dict(attr) thisattr["fillColor"] = getFaceColor(face) thisattr["depth"] = currentDepth parts = self.addClippedPoly(contourPoly( face.contour()), container=compound, **thisattr) if returnFaces: result.extend([(face, part) for part in parts]) for anchor in face.holeContours(): todo.extend(maputils.holeComponent(anchor)) currentDepth -= 1 return result
def addMapOverlay(fe, overlay, skipBorder=False, **attr): qtColor2figColor = figexport.qtColor2figColor # FIXME: str(type(overlay)).contains(...) instead? if isinstance(overlay, ROISelector): color = qtColor2figColor(overlay.color, fe.f) return fe.addROIRect(overlay.roi, penColor=color, **attr) elif isinstance(overlay, (MapNodes, MapEdges, MapFaces)): oldScale, oldOffset, oldROI = fe.scale, fe.offset, fe.roi if isinstance(overlay, MapFaces): zoom = overlay.edgeOverlay._zoom else: zoom = overlay._zoom extraZoom = float(zoom) / overlay.viewer.zoomFactor() fe.scale *= extraZoom fe.roi = BoundingBox(fe.roi.begin() / extraZoom, fe.roi.end() / extraZoom) map = overlay._map() if isinstance(overlay, MapNodes): radius = overlay.origRadius if not overlay.relativeRadius: radius /= float(overlay._zoom) color = qtColor2figColor(overlay.color, fe.f) result = fe.addMapNodes(map, radius, fillColor=color, lineWidth=0, **attr) elif isinstance(overlay, MapEdges): attr = dict(attr) if overlay.width: attr["lineWidth"] = overlay.width if overlay.colors: result = fig.Compound(fe.f) for edge in map.edgeIter(): edgeColor = overlay.colors[edge.label()] if edgeColor: fe.addClippedPoly(edge, penColor=qtColor2figColor( edgeColor, fe.f), container=result, **attr) elif overlay.color: result = fe.addMapEdges(map, skipBorder=skipBorder, penColor=qtColor2figColor( overlay.color, fe.f), **attr) else: result = fig.Compound(fe.f) if overlay.protectedColor: attr["penColor"] = \ qtColor2figColor(overlay.protectedColor, fe.f) attr["lineWidth"] = overlay.protectedWidth or overlay.width it = skipBorder and maputils.nonBorderEdges(map) \ or map.edgeIter() for edge in it: if edge.flag(flag_constants.ALL_PROTECTION): fe.addClippedPoly(edge, container=result, **attr) else: # isinstance(overlay, MapFaces) attr = dict(attr) if overlay.color: if overlay.width: attr["lineWidth"] = overlay.width attr["penColor"] = qtColor2figColor(overlay.color, fe.f) if overlay.fillColor: attr["fillColor"] = qtColor2figColor(overlay.fillColor, fe.f) attr["fillStyle"] = fig.FillStyle.Solid result = fig.Compound(fe.f) for face in map.faceIter(): if face.flag(overlay.flags): if face.holeCount: assert not overlay.fillColor or not overlay.color, "FIXME: cannot currently export filled+stroked polygons with holes" if not overlay.color: wholePoly = list(contourPoly(face.contour())) back = wholePoly[0] assert wholePoly[-1] == back for dart in face.holeContours(): wholePoly.extend(contourPoly(dart)) wholePoly.append(back) fe.addClippedPoly(wholePoly, container=result, **attr) else: for dart in face.contours(): fe.addClippedPoly(contourPoly(dart), container=result, **attr) fe.scale, fe.offset, fe.roi = oldScale, oldOffset, oldROI return result else: return figexport.addStandardOverlay(fe, overlay, **attr)