def stroke_path(path, pen): """Create a QPainterPath stroke from the `path` drawn with `pen`. """ stroker = QPainterPathStroker() stroker.setCapStyle(pen.capStyle()) stroker.setJoinStyle(pen.joinStyle()) stroker.setMiterLimit(pen.miterLimit()) stroker.setWidth(max(pen.widthF(), 1e-9)) return stroker.createStroke(path)
def buildPath(self): srcPos, tarPos = self.getNodePos() if self.pathPnt and (self.pathPnt[0] - srcPos).manhattanLength( ) < 0.05 and (self.pathPnt[1] - tarPos).manhattanLength() < 0.05: return self.path self.pathPnt = (srcPos, tarPos) path = QtGui.QPainterPath() path.moveTo(srcPos) dx = tarPos.x() - srcPos.x() p1 = srcPos + QtCore.QPointF(dx * 0.3, 0) p2 = tarPos + QtCore.QPointF(-dx * 0.7, 0) path.cubicTo(p1, p2, tarPos) self.curve = QtGui.QPainterPath(path) self.path = path from PyQt4.QtGui import QPainterPathStroker stroker = QPainterPathStroker() stroker.setWidth(10.0) self.pathShape = stroker.createStroke(self.path) return path
def arrow_path_plain(line, width): """ Return an :class:`QPainterPath` of a plain looking arrow. """ path = QPainterPath() p1, p2 = line.p1(), line.p2() if p1 == p2: return path baseline = QLineF(line) # Require some minimum length. baseline.setLength(max(line.length() - width * 3, width * 3)) path.moveTo(baseline.p1()) path.lineTo(baseline.p2()) stroker = QPainterPathStroker() stroker.setWidth(width) path = stroker.createStroke(path) arrow_head_len = width * 4 arrow_head_angle = 50 line_angle = line.angle() - 180 angle_1 = line_angle - arrow_head_angle / 2.0 angle_2 = line_angle + arrow_head_angle / 2.0 points = [ p2, p2 + QLineF.fromPolar(arrow_head_len, angle_1).p2(), p2 + QLineF.fromPolar(arrow_head_len, angle_2).p2(), p2, ] poly = QPolygonF(points) path_head = QPainterPath() path_head.addPolygon(poly) path = path.united(path_head) return path
def arrow_path_plain(line, width): """ Return an :class:`QPainterPath` of a plain looking arrow. """ path = QPainterPath() p1, p2 = line.p1(), line.p2() if p1 == p2: return path baseline = QLineF(line) # Require some minimum length. baseline.setLength(max(line.length() - width * 3, width * 3)) path.moveTo(baseline.p1()) path.lineTo(baseline.p2()) stroker = QPainterPathStroker() stroker.setWidth(width) path = stroker.createStroke(path) arrow_head_len = width * 4 arrow_head_angle = 50 line_angle = line.angle() - 180 angle_1 = line_angle - arrow_head_angle / 2.0 angle_2 = line_angle + arrow_head_angle / 2.0 points = [ p2, p2 + QLineF.fromPolar(arrow_head_len, angle_1).p2(), p2 + QLineF.fromPolar(arrow_head_len, angle_2).p2(), p2 ] poly = QPolygonF(points) path_head = QPainterPath() path_head.addPolygon(poly) path = path.united(path_head) return path
def setAnchorPath(self, path): """ Set the anchor's curve path as a :class:`QPainterPath`. """ self.__anchorPath = path # Create a stroke of the path. stroke_path = QPainterPathStroker() stroke_path.setCapStyle(Qt.RoundCap) # Shape is wider (bigger mouse hit area - should be settable) stroke_path.setWidth(9) self.__shape = stroke_path.createStroke(path) # The full stroke stroke_path.setWidth(3) self.__fullStroke = stroke_path.createStroke(path) # The dotted stroke (when not connected to anything) stroke_path.setDashPattern(Qt.DotLine) self.__dottedStroke = stroke_path.createStroke(path) if self.anchored: self.setPath(self.__fullStroke) self.setBrush(self.connectedBrush) else: self.setPath(self.__dottedStroke) self.setBrush(self.normalBrush)
def setAnchorPath(self, path): """ Set the anchor's curve path as a :class:`QPainterPath`. """ self.__anchorPath = path # Create a stroke of the path. stroke_path = QPainterPathStroker() stroke_path.setCapStyle(Qt.RoundCap) # Shape is wider (bigger mouse hit area - should be settable) stroke_path.setWidth(12) self.__shape = stroke_path.createStroke(path) # The full stroke stroke_path.setWidth(3) self.__fullStroke = stroke_path.createStroke(path) # The dotted stroke (when not connected to anything) stroke_path.setDashPattern(Qt.DotLine) self.__dottedStroke = stroke_path.createStroke(path) if self.anchored: self.setPath(self.__fullStroke) self.setBrush(self.connectedBrush) else: self.setPath(self.__dottedStroke) self.setBrush(self.normalBrush)
def path_stroke(path, width=1, join_style=Qt.MiterJoin): stroke = QPainterPathStroker() stroke.setWidth(width) stroke.setJoinStyle(join_style) return stroke.createStroke(path)
def shapeFromPath(path, pen): """Create a QPainterPath shape from the `path` drawn with `pen`. """ stroker = QPainterPathStroker() stroker.setCapStyle(pen.capStyle()) stroker.setJoinStyle(pen.joinStyle()) stroker.setMiterLimit(pen.miterLimit()) stroker.setWidth(max(pen.widthF(), 1e-9)) shape = stroker.createStroke(path) shape.addPath(path) return shape
def setGeometry(self): """ Read the parameters that define the geometry of the point """ params = parameters.instance self.setEditable(params.is_cell_editable) points = self.points polygon_id = self.polygon_id polygon = [ points[pt].pos() if pt in points else None for pt in polygon_id ] non_none_cnt = len([p for p in polygon if p is not None]) if non_none_cnt == 0: self.rect = QRectF() self.bounding_rect = QRectF() self.setVisible(False) return self.setVisible(True) # First, check if this is a "simple" cell walls = self.walls real_polygon = [pid for pid in polygon_id if pid in points] #sides = [ walls[real_polygon[i], real_polygon[(i+1)%len(real_polygon)]] for i in range(len(real_polygon)) ] sides = [None] * len(polygon) self.sides = sides real_scale_x = self.scale[0] / self.glob_scale real_scale_y = self.scale[1] / self.glob_scale for i in range(len(polygon)): if polygon[i] is not None: # Find the next j = (i + 1) % len(polygon) while polygon[j] is None: j = (j + 1) % len(polygon) w = [ QPointF(p.x() * real_scale_x, p.y() * real_scale_y) for p in walls[polygon_id[i], polygon_id[j]] ] sides[i] = [polygon[i]] + w + [polygon[j]] prev = real_polygon[-1] polygon_shape = [] for i in range(len(polygon)): if polygon[i]: polygon_shape.append(polygon[i]) polygon_shape.extend(sides[i]) # Now add the dummy points .. starts at the first non-None point if non_none_cnt > 2: start = None for i in range(len(polygon)): if polygon[i] is not None: start = i break prev = start cur = start + 1 if start + 1 < len(polygon) else 0 log_debug("Polygon before: [%s]" % ",".join("(%f,%f)" % (p.x(), p.y()) if p is not None else "None" for p in polygon)) while cur != start: if polygon[cur] is None: cnt = 1 next = cur + 1 if cur + 1 < len(polygon) else 0 while True: if polygon[next] is None: cnt += 1 else: break next += 1 if next == len(polygon): next = 0 #print "%d points missing" % cnt # First, find total length of wall length = 0.0 side = sides[prev] for i in range(len(side) - 1): length += dist(side[i], side[i + 1]) diff = length / (cnt + 1) # Distance between two points i = cur p = side[0] for j in range(cnt): l = 0.0 found = False for k in range(len(side) - 1): dl = dist(side[k], side[k + 1]) l += dl if l > diff * ( 1 + 1e-5 ): # Account for accumulation of small errors c = (i + j) % len(polygon) delta = diff - l + dl p = side[k] + (side[k + 1] - side[k]) * delta / dl s1 = side[:k + 1] + [p] s2 = [p] + side[k + 1:] sides[c - 1] = s1 sides[c] = s2 side = s2 polygon[c] = p found = True break assert found, "Could not find point in polygon for position %d" % ( j + i, ) #p = p + diff #c = (i+j)%len(polygon) #polygon[c] = QPointF(p) cur = next else: prev = cur cur += 1 if cur >= len(polygon): cur = 0 assert None not in polygon, "Error, some dummy points were not added" else: polygon = [p for p in polygon if p is not None] center = sum(polygon, QPointF(0, 0)) / float(len(polygon)) self.center = center if len(polygon) > 2: polygon = QPolygonF(polygon + [polygon[0]]) polygon.translate(-center) polygon_shape = QPolygonF(polygon_shape + [polygon_shape[0]]) self.polygon_shape = polygon_shape polygon_shape.translate(-center) # Translate the sides too sides = [[p - center for p in s] for s in sides] self.sides = sides assert len(sides) == len(polygon) - 1 elif len(polygon) == 2: polygon = QLineF(polygon[0], polygon[1]) polygon.translate(-center) else: polygon = None self.polygon = polygon self.setPos(center) params = parameters.instance self.prepareGeometryChange() size = params.cell_size scale = self.scale height = size * cos(pi / 6) * scale[1] width = size * scale[0] pos_x = size * cos(pi / 3) * scale[0] self.sel_rect = QRectF(-width, -height, 2 * width, 2 * height) if isinstance(polygon, QPolygonF): self.rect = self.polygon_shape.boundingRect() | self.sel_rect elif isinstance(polygon, QLineF): self.rect = QRectF(polygon.p1(), polygon.p2()).normalized() | self.sel_rect else: self.rect = self.sel_rect self.bounding_rect = QRectF(self.rect) if self.p1 in points and self.p2 in points: self.division_line = QLineF(points[self.p1].pos() - center, points[self.p2].pos() - center) else: self.division_line = None self.hexagon = QPolygonF([ QPointF(-width, 0), QPointF(-pos_x, height), QPointF(pos_x, height), QPointF(width, 0), QPointF(pos_x, -height), QPointF(-pos_x, -height) ]) self.hexagon_path = QPainterPath() self.hexagon_path.addPolygon(self.hexagon) s1 = QPainterPath() if isinstance(self.polygon, QPolygonF): s1.addPolygon(polygon_shape) elif isinstance(self.polygon, QLineF): s1.moveTo(self.polygon.p1()) s1.lineTo(self.polygon.p2()) stroke = QPainterPathStroker() sel_thick = 3 * params.cell_thickness if sel_thick == 0: sel_thick = 3 stroke.setWidth(sel_thick) self.stroke = stroke.createStroke(s1)
def setGeometry(self): """ Read the parameters that define the geometry of the point """ params = parameters.instance self.setEditable(params.is_cell_editable) points = self.points polygon_id = self.polygon_id polygon = [points[pt].pos() if pt in points else None for pt in polygon_id] non_none_cnt = len([p for p in polygon if p is not None]) if non_none_cnt == 0: self.rect = QRectF() self.bounding_rect = QRectF() self.setVisible(False) return self.setVisible(True) # First, check if this is a "simple" cell walls = self.walls real_polygon = [pid for pid in polygon_id if pid in points] #sides = [ walls[real_polygon[i], real_polygon[(i+1)%len(real_polygon)]] for i in range(len(real_polygon)) ] sides = [None] * len(polygon) self.sides = sides real_scale_x = self.scale[0]/self.glob_scale real_scale_y = self.scale[1]/self.glob_scale for i in range(len(polygon)): if polygon[i] is not None: # Find the next j = (i+1) % len(polygon) while polygon[j] is None: j = (j+1) % len(polygon) w = [QPointF(p.x()*real_scale_x, p.y()*real_scale_y) for p in walls[polygon_id[i], polygon_id[j]]] sides[i] = [polygon[i]] + w + [polygon[j]] prev = real_polygon[-1] polygon_shape = [] for i in range(len(polygon)): if polygon[i]: polygon_shape.append(polygon[i]) polygon_shape.extend(sides[i]) # Now add the dummy points .. starts at the first non-None point if non_none_cnt > 2: start = None for i in range(len(polygon)): if polygon[i] is not None: start = i break prev = start cur = start+1 if start+1 < len(polygon) else 0 log_debug("Polygon before: [%s]" % ",".join("(%f,%f)" % (p.x(), p.y()) if p is not None else "None" for p in polygon)) while cur != start: if polygon[cur] is None: cnt = 1 next = cur+1 if cur+1 < len(polygon) else 0 while True: if polygon[next] is None: cnt += 1 else: break next += 1 if next == len(polygon): next = 0 #print "%d points missing" % cnt # First, find total length of wall length = 0.0 side = sides[prev] for i in range(len(side)-1): length += dist(side[i], side[i+1]) diff = length/(cnt+1) # Distance between two points i = cur p = side[0] for j in range(cnt): l = 0.0 found = False for k in range(len(side)-1): dl = dist(side[k], side[k+1]) l += dl if l > diff*(1+1e-5): # Account for accumulation of small errors c = (i + j) % len(polygon) delta = diff-l+dl p = side[k] + (side[k+1]-side[k])*delta/dl s1 = side[:k+1] + [p] s2 = [p] + side[k+1:] sides[c-1] = s1 sides[c] = s2 side = s2 polygon[c] = p found = True break assert found, "Could not find point in polygon for position %d" % (j+i,) #p = p + diff #c = (i+j)%len(polygon) #polygon[c] = QPointF(p) cur = next else: prev = cur cur += 1 if cur >= len(polygon): cur = 0 assert None not in polygon, "Error, some dummy points were not added" else: polygon = [p for p in polygon if p is not None] center = sum(polygon, QPointF(0, 0)) / float(len(polygon)) self.center = center if len(polygon) > 2: polygon = QPolygonF(polygon+[polygon[0]]) polygon.translate(-center) polygon_shape = QPolygonF(polygon_shape + [polygon_shape[0]]) self.polygon_shape = polygon_shape polygon_shape.translate(-center) # Translate the sides too sides = [[p-center for p in s] for s in sides] self.sides = sides assert len(sides) == len(polygon)-1 elif len(polygon) == 2: polygon = QLineF(polygon[0], polygon[1]) polygon.translate(-center) else: polygon = None self.polygon = polygon self.setPos(center) params = parameters.instance self.prepareGeometryChange() size = params.cell_size scale = self.scale height = size*cos(pi/6)*scale[1] width = size*scale[0] pos_x = size*cos(pi/3)*scale[0] self.sel_rect = QRectF(-width, -height, 2*width, 2*height) if isinstance(polygon, QPolygonF): self.rect = self.polygon_shape.boundingRect() | self.sel_rect elif isinstance(polygon, QLineF): self.rect = QRectF(polygon.p1(), polygon.p2()).normalized() | self.sel_rect else: self.rect = self.sel_rect self.bounding_rect = QRectF(self.rect) if self.p1 in points and self.p2 in points: self.division_line = QLineF(points[self.p1].pos()-center, points[self.p2].pos()-center) else: self.division_line = None self.hexagon = QPolygonF([QPointF(-width, 0), QPointF(-pos_x, height), QPointF(pos_x, height), QPointF(width, 0), QPointF(pos_x, -height), QPointF(-pos_x, -height)]) self.hexagon_path = QPainterPath() self.hexagon_path.addPolygon(self.hexagon) s1 = QPainterPath() if isinstance(self.polygon, QPolygonF): s1.addPolygon(polygon_shape) elif isinstance(self.polygon, QLineF): s1.moveTo(self.polygon.p1()) s1.lineTo(self.polygon.p2()) stroke = QPainterPathStroker() sel_thick = 3*params.cell_thickness if sel_thick == 0: sel_thick = 3 stroke.setWidth(sel_thick) self.stroke = stroke.createStroke(s1)