Skip to content

Commit 4c1bdfb

Browse files
committed
[sextante] improved modeler appearance with Bezier curves
1 parent 41932df commit 4c1bdfb

File tree

2 files changed

+77
-90
lines changed

2 files changed

+77
-90
lines changed

python/plugins/sextante/modeler/ModelerArrowItem.py

+73-86
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
##
4646
#############################################################################
4747

48-
class ModelerArrowItem(QtGui.QGraphicsLineItem):
48+
class ModelerArrowItem(QtGui.QGraphicsPathItem):
4949

5050
def __init__(self, startItem, outputIndex, endItem, paramIndex ,parent=None, scene=None):
5151
super(ModelerArrowItem, self).__init__(parent, scene)
@@ -59,8 +59,35 @@ def __init__(self, startItem, outputIndex, endItem, paramIndex ,parent=None, sce
5959
self.setPen(QtGui.QPen(self.myColor, 1, QtCore.Qt.SolidLine,
6060
QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
6161
self.setZValue(0)
62-
63-
62+
63+
64+
65+
def contains_point(self, x, y, epsilon):
66+
p = (x, y)
67+
min_distance = float(0x7fffffff)
68+
t = 0.0
69+
while t < 1.0:
70+
point = self.path.pointAtPercent(t)
71+
spline_point = (point.x(), point.y())
72+
print p, spline_point
73+
distance = self.distance(p, spline_point)
74+
if distance < min_distance:
75+
min_distance = distance
76+
t += 0.1
77+
print min_distance, epsilon
78+
return (min_distance <= epsilon)
79+
80+
#===========================================================================
81+
# def boundingRect(self):
82+
# return self.path.boundingRect()
83+
#===========================================================================
84+
85+
86+
def distance(self, p0, p1):
87+
a = p1[0] - p0[0]
88+
b = p1[1] - p0[1]
89+
return math.sqrt(a * a + b * b)
90+
6491
def startItem(self):
6592
return self.myStartItem
6693

@@ -71,95 +98,55 @@ def boundingRect(self):
7198
#this is a quick fix to avoid arrows not being drawn
7299
return QtCore.QRectF(0, 0, 4000,4000)
73100

74-
def shape(self):
75-
path = super(ModelerArrowItem, self).shape()
76-
path.addPolygon(self.arrowHead)
77-
return path
78-
79-
def updatePosition(self):
80-
line = QtCore.QLineF(self.mapFromItem(self.myStartItem, 0, 0), self.mapFromItem(self.myEndItem, 0, 0))
81-
self.setLine(line)
101+
#===============================================================================
102+
# def shape(self):
103+
# path = super(ModelerArrowItem, self).shape()
104+
# path.addPolygon(self.arrowHead)
105+
# return path
106+
#
107+
# def updatePosition(self):
108+
# line = QtCore.QLineF(self.mapFromItem(self.myStartItem, 0, 0), self.mapFromItem(self.myEndItem, 0, 0))
109+
# self.setLine(line)
110+
#===============================================================================
82111

83112
def paint(self, painter, option, widget=None):
84-
myStartItem = self.myStartItem
85-
myEndItem = self.myEndItem
113+
startItem = self.myStartItem
114+
endItem = self.myEndItem
86115
myPen = self.pen()
87116
myPen.setColor(self.myColor)
88-
arrowSize = 6.0
89117
painter.setPen(myPen)
90118
painter.setBrush(self.myColor)
91119

92-
if isinstance(self.startItem().element, GeoAlgorithm):
93-
if self.startItem().element.outputs:
94-
endPt = self.endItem().getLinkPointForParameter(self.paramIndex)
95-
startPt = self.startItem().getLinkPointForOutput(self.outputIndex)
96-
arrowLine = QtCore.QLineF(myEndItem.pos() + endPt - QtCore.QPointF(endPt.x() + ModelerGraphicItem.BOX_WIDTH /2, 0), myEndItem.pos() + endPt)
97-
painter.drawLine(arrowLine)
98-
tailLine = QtCore.QLineF(myStartItem.pos() + startPt + QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH /2 - startPt.x(),0), myStartItem.pos() + startPt)
99-
painter.drawLine(tailLine)
100-
pt = QtCore.QPointF(myStartItem.pos() + startPt + QtCore.QPointF(- 2, -2))
101-
rect = QtCore.QRectF(pt.x(), pt.y(), 4, 4)
102-
painter.fillRect(rect, QtCore.Qt.gray)
103-
line = QtCore.QLineF(myStartItem.pos() + startPt + QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH /2 - startPt.x(),0),
104-
myEndItem.pos() + endPt - QtCore.QPointF(endPt.x() + ModelerGraphicItem.BOX_WIDTH /2, 0))
120+
controlPoints = []
121+
endPt = self.endItem().getLinkPointForParameter(self.paramIndex)
122+
startPt = self.startItem().getLinkPointForOutput(self.outputIndex)
123+
if isinstance(self.startItem().element, GeoAlgorithm):
124+
if self.startItem().element.outputs:
125+
controlPoints.append(startItem.pos() + startPt)
126+
controlPoints.append(startItem.pos() + startPt + QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH /2,0))
127+
controlPoints.append(endItem.pos() + endPt - QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH /2, 0))
128+
controlPoints.append(endItem.pos() + endPt)
129+
pt = QtCore.QPointF(startItem.pos() + startPt + QtCore.QPointF(-3, -3))
130+
painter.drawEllipse(pt.x(), pt.y(), 6, 6)
131+
pt = QtCore.QPointF(endItem.pos() + endPt + QtCore.QPointF(-3, -3))
132+
painter.drawEllipse(pt.x(), pt.y(), 6, 6)
105133
else: # case where there is a dependency on an algorithm not on an output
106-
endPolygon = myEndItem.polygon()
107-
p1 = endPolygon.first() + myEndItem.pos()
108-
line = QtCore.QLineF(myStartItem.pos(), myEndItem.pos())
109-
intersectPoint = QtCore.QPointF()
110-
for i in endPolygon:
111-
p2 = i + myEndItem.pos()
112-
polyLine = QtCore.QLineF(p1, p2)
113-
intersectType = polyLine.intersect(line, intersectPoint)
114-
if intersectType == QtCore.QLineF.BoundedIntersection:
115-
break
116-
p1 = p2
117-
118-
self.setLine(QtCore.QLineF(intersectPoint, myStartItem.pos()))
119-
line = self.line()
120-
if line.length() == 0: #division by zero might occur if arrow has no length
121-
return
122-
angle = math.acos(line.dx() / line.length())
123-
if line.dy() >= 0:
124-
angle = (math.pi * 2.0) - angle
125-
126-
arrowP1 = line.p1() + QtCore.QPointF(math.sin(angle + math.pi / 3.0) * arrowSize,
127-
math.cos(angle + math.pi / 3) * arrowSize)
128-
arrowP2 = line.p1() + QtCore.QPointF(math.sin(angle + math.pi - math.pi / 3.0) * arrowSize,
129-
math.cos(angle + math.pi - math.pi / 3.0) * arrowSize)
130-
131-
self.arrowHead.clear()
132-
for point in [line.p1(), arrowP1, arrowP2]:
133-
self.arrowHead.append(point)
134-
135-
painter.drawLine(line)
136-
painter.drawPolygon(self.arrowHead)
137-
return;
138-
else:
139-
endPt = self.endItem().getLinkPointForParameter(self.paramIndex)
140-
arrowLine = QtCore.QLineF(myEndItem.pos() + endPt - QtCore.QPointF(endPt.x() + ModelerGraphicItem.BOX_WIDTH /2, 0), myEndItem.pos() + endPt)
141-
painter.drawLine(arrowLine)
142-
line = QtCore.QLineF(myStartItem.pos(),
143-
myEndItem.pos() + endPt - QtCore.QPointF(endPt.x() + ModelerGraphicItem.BOX_WIDTH /2, 0))
144-
145-
self.setLine(line);
146-
147-
if line.length() == 0: #division by zero might occur if arrow has no length
148-
return
149-
150-
angle = math.acos(line.dx() / line.length())
151-
if line.dy() >= 0:
152-
angle = (math.pi * 2.0) - angle
153-
154-
arrowP1 = arrowLine.p2() + QtCore.QPointF(-math.cos(math.pi / 9.0) * arrowSize,
155-
math.sin(math.pi / 9.0) * arrowSize)
156-
arrowP2 = arrowLine.p2() + QtCore.QPointF(-math.cos(math.pi / 9.0) * arrowSize,
157-
-math.sin(math.pi / 9.0) * arrowSize)
158-
159-
self.arrowHead.clear()
160-
for point in [arrowLine.p2(), arrowP1, arrowP2]:
161-
self.arrowHead.append(point)
162-
163-
painter.drawLine(line)
164-
painter.drawPolygon(self.arrowHead)
134+
controlPoints.append(startItem.pos() + startPt)
135+
controlPoints.append(startItem.pos() + startPt + QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH /2,0))
136+
controlPoints.append(endItem.pos() + endPt - QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH /2, 0))
137+
controlPoints.append(endItem.pos() + endPt)
138+
else:
139+
controlPoints.append(startItem.pos())
140+
controlPoints.append(startItem.pos() + QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH /2,0))
141+
controlPoints.append(endItem.pos() + endPt - QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH /2, 0))
142+
controlPoints.append(endItem.pos() + endPt)
143+
pt = QtCore.QPointF(endItem.pos() + endPt + QtCore.QPointF(-3, -3))
144+
painter.drawEllipse(pt.x(), pt.y(), 6, 6)
145+
146+
path = QtGui.QPainterPath()
147+
path.moveTo(controlPoints[0])
148+
path.cubicTo(*controlPoints[1:])
149+
painter.strokePath(path, painter.pen())
150+
self.setPath(path)
151+
165152

python/plugins/sextante/modeler/ModelerGraphicItem.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -238,14 +238,14 @@ def paint(self, painter, option, widget=None):
238238
painter.drawPixmap(-(ModelerGraphicItem.BOX_WIDTH / 2.0) + 3, -8, self.pixmap)
239239

240240
def getLinkPointForParameter(self, paramIndex):
241-
offsetX = 30
241+
offsetX = 25
242242
if self.inputFolded:
243243
paramIndex = -1
244-
offsetX = 22
244+
offsetX = 17
245245
font = QtGui.QFont("Verdana", 8)
246246
fm = QtGui.QFontMetricsF(font)
247247
if isinstance(self.element, GeoAlgorithm):
248-
h = (fm.height() * 1.2) * (paramIndex + 2) - fm.height() / 2.0
248+
h = (fm.height() * 1.2) * (paramIndex + 2) - fm.height() / 2.0 + 2
249249
h = h + ModelerGraphicItem.BOX_HEIGHT / 2.0
250250
else:
251251
h = 0
@@ -264,7 +264,7 @@ def getLinkPointForOutput(self, outputIndex):
264264
fm = QtGui.QFontMetricsF(font)
265265
w = fm.width(QtCore.QString(text))
266266
h = (fm.height() * 1.2) * (outputIndex + 3 + numParams) - fm.height() / 2.0
267-
y = h + ModelerGraphicItem.BOX_HEIGHT / 2.0
267+
y = h + ModelerGraphicItem.BOX_HEIGHT / 2.0 + 2
268268
x = -(ModelerGraphicItem.BOX_WIDTH)/2 + 33 + w + 5 if not self.outputFolded else 10
269269
return QtCore.QPointF(x, y)
270270
else:

0 commit comments

Comments
 (0)