예제 #1
0
    def addRevArcSeg(self, x1, y1, x2, y2, cx, cy, arcDir):  
        """Add a 360 degree revolved arc to this Patch.      
                                                             
        x1, y1 -- start vertex
        x2, y2 -- end vertex
        cx, cy -- center point
        arcDir -- 'cclw' or 'clw'

        It is assumes the points are in the XZ plane and the axis of
        revolution is parallel to the vector (0, 0, 1), and passes through the
        point (0, 0, 0).
        """
        a = x1 - cx
        b = y1 - cy
        r = sqrt(a*a + b*b)
        arc = Arc.fromVectors(QVector2D(a, b),
                              QVector2D(x2 - cx, y2 - cy),
                              r,
                              arcDir == 'cclw')
        # TODO: By halving the mesh segs ( * 0.5), fewer triangles are
        #       created. Shading is ok but arc edges look blocky.
        # angstep = 360.0 / (self._mesh.segs * 0.5)
        angstep = 360.0 / self._mesh.segs
        # minimum 2 segments in the arc
        segs = max(int(abs(arc.span()) / angstep), 3)
        step = arc.span() / segs
        sa = arc.startAngle()
        a1 = radians(sa)
        sa1 = sin(a1)
        ca1 = cos(a1)
        for i in range(1, segs):
            a2 = radians(sa + step * i)
            sa2 = sin(a2)
            ca2 = cos(a2)
            x1 = cx + r * ca1
            y1 = cy + r * sa1
            x2 = cx + r * ca2
            y2 = cy + r * sa2
            self.addRevLineSeg(x1, y1, x2, y2)
            a1 = a2
            sa1 = sa2
            ca1 = ca2
            if i == 1:
                # only blend the first strip
                self._mesh.blendTangent(False)
        # last strip
        else:
            a2 = radians(arc.endAngle())
            x1 = cx + r * ca1
            y1 = cy + r * sa1
            x2 = cx + r * cos(a2)
            y2 = cy + r * sin(a2)
            self.addRevLineSeg(x1, y1, x2, y2)
예제 #2
0
    def config(self, specMap={}):
        if not super(AngleDim, self).config(specMap):
            return
        pp = QPainterPath()
        labelP = self.specMap['pos']
        tb = self.dimText.sceneBoundingRect()
        l1 = self.specMap['line1']
        l2 = self.specMap['line2']
        outside = self.specMap['outside']
        if l1.isNull() or l2.isNull():
            raise AngleDimException("refrenced line has zero length")
        # line intersection point
        xsectP = QPointF()
        xsectType = l1.intersect(l2, xsectP)
        if xsectType == QLineF.NoIntersection:
            raise AngleDimException("reference lines are parallel")
        # radius of arc leaders that pass through the label's center point
        labelV = QVector2D(labelP - xsectP)
        dp = labelV.dotProduct
        radius = labelV.length()
        # find fixed leader span angle
        chordLen = self.scene().pixelsToScene(self.leaderLen)
        rsq = radius * radius
        res = (rsq + rsq - chordLen * chordLen) / (2 * rsq)
        fixedLeaderSpan = degrees(acos(clamp(res, 0.0, 1.0)))
        # guess the line vectors
        v1 = QVector2D(l1.p2() - l1.p1()).normalized()
        v2 = QVector2D(l2.p2() - l2.p1()).normalized()
        # maybe reverse the line vectors so they point towards the quadrant
        # specified
        quadV = self.specMap['quadV'].normalized()
        if dp(v1, quadV) <= 0:
            v1 = -v1
        if dp(v2, quadV) <= 0:
            v2 = -v2
        # angle bisector
        bisectV = (v1 + v2).normalized()
        # angle bisector rotated 90 degrees cclw
        bisectV90 = QVector2D(-bisectV.y(), bisectV.x())
        # determine which side of the bisector the arrow tips lay
        lL = l1
        rL = l2
        lV = v1
        rV = v2
        lAp = xsectP + (lV * radius).toPointF()
        rAp = xsectP + (rV * radius).toPointF()
        if dp(bisectV90, v1) <= 0.0:
            lL, rL, lV, rV, lAp, rAp = rL, lL, rV, lV, rAp, lAp
        # find where the label lays
        lableV = labelV.normalized()
        lVperp = QVector2D(-lV.y(), lV.x())
        rVperp = QVector2D(rV.y(), -rV.x())
        # leader arc rectangle
        rect = QRectF(xsectP.x() - radius,
                      xsectP.y() + radius,
                      radius * 2, -radius * 2)

        # When left and right are mentioned, they are relative to the
        # intersection point of the two reference lines, looking in the
        # direction of the angle bisector.
        
        # label left of quad
        if dp(labelV, lVperp) > 0.0:
            if outside:
                # leader from lable to left arrow
                arc = Arc.fromVectors(labelV, lV, radius, False)
                arc.center(xsectP)
                clipP = xsectArcRect1(arc, tb)
                if clipP:
                    arc = Arc.fromVectors(QVector2D(clipP - xsectP), lV,
                                         radius, False)
                    arc.center(xsectP)
                    pp.arcMoveTo(rect, arc.start())
                    pp.arcTo(rect, arc.start(), arc.span())
                # fixed leader from right arrow
                sa = vectorToAbsAngle(rV)
                pp.arcMoveTo(rect, sa)
                pp.arcTo(rect, sa, -fixedLeaderSpan)
            else:
                # leader from label, through left arrow, to right arrow
                arc = Arc.fromVectors(labelV, rV, radius, False)
                arc.center(xsectP)
                clipP = xsectArcRect1(arc, tb)
                if clipP:
                    arc = Arc.fromVectors(QVector2D(clipP - xsectP), rV,
                                         radius, False)
                    arc.center(xsectP)
                    pp.arcMoveTo(rect, arc.start())
                    pp.arcTo(rect, arc.start(), arc.span())
        # label right of quad
        elif dp(labelV, rVperp) > 0.0:
            if outside:
                # leader from label to right arrow
                arc = Arc.fromVectors(labelV, rV, radius)
                arc.center(xsectP)
                clipP = xsectArcRect1(arc, tb)
                if clipP:
                    arc = Arc.fromVectors(QVector2D(clipP - xsectP), rV,
                                         radius)
                    arc.center(xsectP)
                    pp.arcMoveTo(rect, arc.start())
                    pp.arcTo(rect, arc.start(), arc.span())
                # fixed length leader from left arrow
                sa = vectorToAbsAngle(lV)
                pp.arcMoveTo(rect, sa)
                pp.arcTo(rect, sa, fixedLeaderSpan)
            else:
                # leader from label, through right arrow, to left arrow
                arc = Arc.fromVectors(labelV, lV, radius)
                arc.center(xsectP)
                clipP = xsectArcRect1(arc, tb)
                if clipP:
                    arc = Arc.fromVectors(QVector2D(clipP - xsectP), lV,
                                         radius)
                    arc.center(xsectP)
                    pp.arcMoveTo(rect, arc.start())
                    pp.arcTo(rect, arc.start(), arc.span())
        # label inside quad
        else:
            if outside:
                # fixed length leader from right arrow
                sa = vectorToAbsAngle(rV)
                pp.arcMoveTo(rect, sa)
                pp.arcTo(rect, sa, -fixedLeaderSpan)
                # from left arrow
                sa = vectorToAbsAngle(lV)
                pp.arcMoveTo(rect, sa)
                pp.arcTo(rect, sa, fixedLeaderSpan)
            else:
                # leader from label to left arrow
                clipP = xsectArcRect1(Arc.fromVectors(labelV, lV, radius), tb)
                if clipP:
                    arc = Arc.fromVectors(QVector2D(clipP - xsectP), lV,
                                          radius)
                    pp.arcMoveTo(rect, arc.start())
                    pp.arcTo(rect, arc.start(), arc.span())
                # to right arrow
                clipP = xsectArcRect1(Arc.fromVectors(labelV, rV, radius,
                                                      False), tb)
                if clipP:
                    arc = Arc.fromVectors(QVector2D(clipP - xsectP), rV,
                                          radius, False)
                    pp.arcMoveTo(rect, arc.start())
                    pp.arcTo(rect, arc.start(), arc.span())
        # arrow tips
        if outside:
            self.arrow1.config({'pos': lAp,
                                'dir': -QVector2D(-lV.y(), lV.x())})
            self.arrow2.config({'pos': rAp,
                                'dir': -QVector2D(rV.y(), -rV.x())})
        else:
            self.arrow1.config({'pos': lAp,
                                'dir': QVector2D(-lV.y(), lV.x())})
            self.arrow2.config({'pos': rAp,
                                'dir': QVector2D(rV.y(), -rV.x())})
        # Find the end points closest to their arrow tips for extension lines
        # Don't render the extension if the arrow tip is on its line.
        p1 = None
        if not isPointOnLineSeg(lAp, lL):
            p1 = lL.p1()
            if QVector2D(lAp - lL.p2()).length() \
                    < QVector2D(lAp - p1).length():
                p1 = lL.p2()
        p2 = None
        if not isPointOnLineSeg(rAp, rL):
            p2 = rL.p1()
            if QVector2D(rAp - rL.p2()).length() \
                    < QVector2D(rAp - p2).length():
                p2 = rL.p2()
        self._addExtensionLines(p1, p2, lAp, rAp, pp)
        self.setPath(pp)
예제 #3
0
 def config(self, specMap={}):
     if not super(RadiusDim, self).config(specMap):
         return
     arcRadius = self.specMap['arc'].radius()
     pos = self.specMap['pos']
     pp = QPainterPath()
     arcCenter = self.specMap['arc'].center()
     # is the label outside the arc
     labelOutside = QVector2D(pos - arcCenter).length() > arcRadius
     # is the label to the right of the arc's y axis?
     labelRight = pos.x() > arcCenter.x()
     br = self.dimText.sceneBoundingRect().normalized()
     # arrow pointing toward arc center point
     if self.specMap['outside']:
         if labelOutside:
             jogLen = self.scene().pixelsToScene(self.jogLineLen)
             if labelRight:
                 jogV = QVector2D(-1, 0).normalized()
                 jogSp = QPointF(br.left(), br.center().y())
             else:
                 jogV = QVector2D(1, 0).normalized()
                 jogSp = QPointF(br.right(), br.center().y())
             jogEp = jogSp + (jogV * jogLen).toPointF()
             ap = pointOnArc(jogEp, arcCenter, arcRadius)
             av = QVector2D(arcCenter - jogEp)
             self.arrow.config({'pos': ap, 'dir': av})
             pp.moveTo(jogSp)
             pp.lineTo(jogEp)
             pp.lineTo(ap)
         # label inside arc
         else:
             leaderLen = self.scene().pixelsToScene(self.leaderLen)
             ap = pointOnArc(pos, arcCenter, arcRadius)
             av = QVector2D(arcCenter - ap).normalized()
             self.arrow.config({'pos': ap, 'dir': av})
             # fixed len arrow leader
             ep = ap + (av * -1 * leaderLen).toPointF()
             pp.moveTo(ap)
             pp.lineTo(ep)
     # arrow pointing away from arc center
     else:
         if labelOutside:
             jogLen = self.scene().pixelsToScene(self.jogLineLen)
             if labelRight:
                 jogV = QVector2D(-1, 0).normalized()
                 jogSp = QPointF(br.left(), br.center().y())
             else:
                 jogV = QVector2D(1, 0).normalized()
                 jogSp = QPointF(br.right(), br.center().y())
             jogEp = jogSp + (jogV * jogLen).toPointF()
             ap = pointOnArc(jogEp, arcCenter, arcRadius)
             av = QVector2D(ap - arcCenter)
             self.arrow.config({'pos': ap, 'dir': av})
             pp.moveTo(arcCenter)
             pp.lineTo(ap)
             pp.lineTo(jogEp)
             pp.lineTo(jogSp)
         # label inside the arc
         else:
             ap = pointOnArc(pos, arcCenter, arcRadius)
             av = QVector2D(ap - arcCenter)
             self.arrow.config({'pos': ap, 'dir': av})
             # label to arc center leader
             xp1 = xsectLineRect1(QLineF(pos, arcCenter), br)
             if xp1:
                 pp.moveTo(xp1)
                 pp.lineTo(arcCenter)
             # label to arrow leader
             xp2 = xsectLineRect1(QLineF(pos, ap), br)
             if xp2:
                 pp.moveTo(xp2)
                 pp.lineTo(ap)
     # extension arc
     arc = self.specMap['arc']
     arcStart = arc.start()
     arcSpan = arc.span()
     if not isPointOnArc(ap, arcCenter, arcStart, arcSpan):
         # arc rect
         p = QPointF(arcRadius, arcRadius)
         r = QRectF(arcCenter - p, arcCenter + p)
         bisV = arc.bisector()
         # arc center to arrow tip vector
         apV = QVector2D(ap - arcCenter).normalized()
         # bisector rotated 90
         bis90V = QVector2D(-bisV.y(), bisV.x())
         spV = arc.startAngleVector()
         spLeftOfBisector = spV.dotProduct(spV, bis90V) >= 0.0
         epV = arc.endAngleVector()
         # is the arrow tip to the left of the bisector?
         if bis90V.dotProduct(apV, bis90V) >= 0.0:
             # is the start point left of the bisector?
             if spLeftOfBisector:
                 extensionArc = Arc.fromVectors(spV, apV, arcRadius, True)
             else:
                 extensionArc = Arc.fromVectors(epV, apV, arcRadius, True)
             pp.arcMoveTo(r, -extensionArc.start() - self.gapAngle)
             pp.arcTo(r, -extensionArc.start() - self.gapAngle,
                      -extensionArc.span() - self.extAngle)
         # arrow tip to right of bisector
         else:
             # is the start point left of the bisector?
             if spLeftOfBisector:
                 extensionArc = Arc.fromVectors(epV, apV, arcRadius, False)
             else:
                 extensionArc = Arc.fromVectors(spV, apV, arcRadius, False)
             pp.arcMoveTo(r, -extensionArc.start() + self.gapAngle)
             pp.arcTo(r, -extensionArc.start() + self.gapAngle,
                      -extensionArc.span() + self.extAngle)
     self.setPath(pp)
예제 #4
0
    def config(self, specMap={}):
        if not super(AngleDim, self).config(specMap):
            return
        pp = QPainterPath()
        labelP = self.specMap['pos']
        tb = self.dimText.sceneBoundingRect()
        l1 = self.specMap['line1']
        l2 = self.specMap['line2']
        outside = self.specMap['outside']
        if l1.isNull() or l2.isNull():
            raise AngleDimException("refrenced line has zero length")
        # line intersection point
        xsectP = QPointF()
        xsectType = l1.intersect(l2, xsectP)
        if xsectType == QLineF.NoIntersection:
            raise AngleDimException("reference lines are parallel")
        # radius of arc leaders that pass through the label's center point
        labelV = QVector2D(labelP - xsectP)
        dp = labelV.dotProduct
        radius = labelV.length()
        # find fixed leader span angle
        chordLen = self.scene().pixelsToScene(self.leaderLen)
        rsq = radius * radius
        res = (rsq + rsq - chordLen * chordLen) / (2 * rsq)
        fixedLeaderSpan = degrees(acos(clamp(res, 0.0, 1.0)))
        # guess the line vectors
        v1 = QVector2D(l1.p2() - l1.p1()).normalized()
        v2 = QVector2D(l2.p2() - l2.p1()).normalized()
        # maybe reverse the line vectors so they point towards the quadrant
        # specified
        quadV = self.specMap['quadV'].normalized()
        if dp(v1, quadV) <= 0:
            v1 = -v1
        if dp(v2, quadV) <= 0:
            v2 = -v2
        # angle bisector
        bisectV = (v1 + v2).normalized()
        # angle bisector rotated 90 degrees cclw
        bisectV90 = QVector2D(-bisectV.y(), bisectV.x())
        # determine which side of the bisector the arrow tips lay
        lL = l1
        rL = l2
        lV = v1
        rV = v2
        lAp = xsectP + (lV * radius).toPointF()
        rAp = xsectP + (rV * radius).toPointF()
        if dp(bisectV90, v1) <= 0.0:
            lL, rL, lV, rV, lAp, rAp = rL, lL, rV, lV, rAp, lAp
        # find where the label lays
        lableV = labelV.normalized()
        lVperp = QVector2D(-lV.y(), lV.x())
        rVperp = QVector2D(rV.y(), -rV.x())
        # leader arc rectangle
        rect = QRectF(xsectP.x() - radius,
                      xsectP.y() + radius, radius * 2, -radius * 2)

        # When left and right are mentioned, they are relative to the
        # intersection point of the two reference lines, looking in the
        # direction of the angle bisector.

        # label left of quad
        if dp(labelV, lVperp) > 0.0:
            if outside:
                # leader from lable to left arrow
                arc = Arc.fromVectors(labelV, lV, radius, False)
                arc.center(xsectP)
                clipP = xsectArcRect1(arc, tb)
                if clipP:
                    arc = Arc.fromVectors(QVector2D(clipP - xsectP), lV,
                                          radius, False)
                    arc.center(xsectP)
                    pp.arcMoveTo(rect, arc.start())
                    pp.arcTo(rect, arc.start(), arc.span())
                # fixed leader from right arrow
                sa = vectorToAbsAngle(rV)
                pp.arcMoveTo(rect, sa)
                pp.arcTo(rect, sa, -fixedLeaderSpan)
            else:
                # leader from label, through left arrow, to right arrow
                arc = Arc.fromVectors(labelV, rV, radius, False)
                arc.center(xsectP)
                clipP = xsectArcRect1(arc, tb)
                if clipP:
                    arc = Arc.fromVectors(QVector2D(clipP - xsectP), rV,
                                          radius, False)
                    arc.center(xsectP)
                    pp.arcMoveTo(rect, arc.start())
                    pp.arcTo(rect, arc.start(), arc.span())
        # label right of quad
        elif dp(labelV, rVperp) > 0.0:
            if outside:
                # leader from label to right arrow
                arc = Arc.fromVectors(labelV, rV, radius)
                arc.center(xsectP)
                clipP = xsectArcRect1(arc, tb)
                if clipP:
                    arc = Arc.fromVectors(QVector2D(clipP - xsectP), rV,
                                          radius)
                    arc.center(xsectP)
                    pp.arcMoveTo(rect, arc.start())
                    pp.arcTo(rect, arc.start(), arc.span())
                # fixed length leader from left arrow
                sa = vectorToAbsAngle(lV)
                pp.arcMoveTo(rect, sa)
                pp.arcTo(rect, sa, fixedLeaderSpan)
            else:
                # leader from label, through right arrow, to left arrow
                arc = Arc.fromVectors(labelV, lV, radius)
                arc.center(xsectP)
                clipP = xsectArcRect1(arc, tb)
                if clipP:
                    arc = Arc.fromVectors(QVector2D(clipP - xsectP), lV,
                                          radius)
                    arc.center(xsectP)
                    pp.arcMoveTo(rect, arc.start())
                    pp.arcTo(rect, arc.start(), arc.span())
        # label inside quad
        else:
            if outside:
                # fixed length leader from right arrow
                sa = vectorToAbsAngle(rV)
                pp.arcMoveTo(rect, sa)
                pp.arcTo(rect, sa, -fixedLeaderSpan)
                # from left arrow
                sa = vectorToAbsAngle(lV)
                pp.arcMoveTo(rect, sa)
                pp.arcTo(rect, sa, fixedLeaderSpan)
            else:
                # leader from label to left arrow
                clipP = xsectArcRect1(Arc.fromVectors(labelV, lV, radius), tb)
                if clipP:
                    arc = Arc.fromVectors(QVector2D(clipP - xsectP), lV,
                                          radius)
                    pp.arcMoveTo(rect, arc.start())
                    pp.arcTo(rect, arc.start(), arc.span())
                # to right arrow
                clipP = xsectArcRect1(
                    Arc.fromVectors(labelV, rV, radius, False), tb)
                if clipP:
                    arc = Arc.fromVectors(QVector2D(clipP - xsectP), rV,
                                          radius, False)
                    pp.arcMoveTo(rect, arc.start())
                    pp.arcTo(rect, arc.start(), arc.span())
        # arrow tips
        if outside:
            self.arrow1.config({
                'pos': lAp,
                'dir': -QVector2D(-lV.y(), lV.x())
            })
            self.arrow2.config({
                'pos': rAp,
                'dir': -QVector2D(rV.y(), -rV.x())
            })
        else:
            self.arrow1.config({'pos': lAp, 'dir': QVector2D(-lV.y(), lV.x())})
            self.arrow2.config({'pos': rAp, 'dir': QVector2D(rV.y(), -rV.x())})
        # Find the end points closest to their arrow tips for extension lines
        # Don't render the extension if the arrow tip is on its line.
        p1 = None
        if not isPointOnLineSeg(lAp, lL):
            p1 = lL.p1()
            if QVector2D(lAp - lL.p2()).length() \
                    < QVector2D(lAp - p1).length():
                p1 = lL.p2()
        p2 = None
        if not isPointOnLineSeg(rAp, rL):
            p2 = rL.p1()
            if QVector2D(rAp - rL.p2()).length() \
                    < QVector2D(rAp - p2).length():
                p2 = rL.p2()
        self._addExtensionLines(p1, p2, lAp, rAp, pp)
        self.setPath(pp)
예제 #5
0
 def config(self, specMap={}):
     if not super(RadiusDim, self).config(specMap):
         return
     arcRadius = self.specMap['arc'].radius()
     pos = self.specMap['pos']
     pp = QPainterPath()
     arcCenter = self.specMap['arc'].center()
     # is the label outside the arc
     labelOutside = QVector2D(pos - arcCenter).length() > arcRadius
     # is the label to the right of the arc's y axis?
     labelRight = pos.x() > arcCenter.x()
     br = self.dimText.sceneBoundingRect().normalized()
     # arrow pointing toward arc center point
     if self.specMap['outside']:
         if labelOutside:
             jogLen = self.scene().pixelsToScene(self.jogLineLen)
             if labelRight:
                 jogV = QVector2D(-1, 0).normalized()
                 jogSp = QPointF(br.left(), br.center().y())
             else:
                 jogV = QVector2D(1, 0).normalized()
                 jogSp = QPointF(br.right(), br.center().y())
             jogEp = jogSp + (jogV * jogLen).toPointF()
             ap = pointOnArc(jogEp, arcCenter, arcRadius)
             av = QVector2D(arcCenter - jogEp)
             self.arrow.config({'pos': ap, 'dir': av})
             pp.moveTo(jogSp)
             pp.lineTo(jogEp)
             pp.lineTo(ap)
         # label inside arc
         else:
             leaderLen = self.scene().pixelsToScene(self.leaderLen)
             ap = pointOnArc(pos, arcCenter, arcRadius)
             av = QVector2D(arcCenter - ap).normalized()
             self.arrow.config({'pos': ap, 'dir': av})
             # fixed len arrow leader
             ep = ap + (av * -1 * leaderLen).toPointF()
             pp.moveTo(ap)
             pp.lineTo(ep)
     # arrow pointing away from arc center
     else:
         if labelOutside:
             jogLen = self.scene().pixelsToScene(self.jogLineLen)
             if labelRight:
                 jogV = QVector2D(-1, 0).normalized()
                 jogSp = QPointF(br.left(), br.center().y())
             else:
                 jogV = QVector2D(1, 0).normalized()
                 jogSp = QPointF(br.right(), br.center().y())
             jogEp = jogSp + (jogV * jogLen).toPointF()
             ap = pointOnArc(jogEp, arcCenter, arcRadius)
             av = QVector2D(ap - arcCenter)
             self.arrow.config({'pos': ap, 'dir': av})
             pp.moveTo(arcCenter)
             pp.lineTo(ap)
             pp.lineTo(jogEp)
             pp.lineTo(jogSp)
         # label inside the arc
         else:
             ap = pointOnArc(pos, arcCenter, arcRadius)
             av = QVector2D(ap - arcCenter)
             self.arrow.config({'pos': ap, 'dir': av})
             # label to arc center leader
             xp1 = xsectLineRect1(QLineF(pos, arcCenter), br)
             if xp1:
                 pp.moveTo(xp1)
                 pp.lineTo(arcCenter)
             # label to arrow leader
             xp2 = xsectLineRect1(QLineF(pos, ap), br)
             if xp2:
                 pp.moveTo(xp2)
                 pp.lineTo(ap)
     # extension arc
     arc = self.specMap['arc']
     arcStart = arc.start()
     arcSpan = arc.span()
     if not isPointOnArc(ap, arcCenter, arcStart, arcSpan):
         # arc rect
         p = QPointF(arcRadius, arcRadius)
         r = QRectF(arcCenter - p, arcCenter + p)
         bisV = arc.bisector()
         # arc center to arrow tip vector
         apV = QVector2D(ap - arcCenter).normalized()
         # bisector rotated 90
         bis90V = QVector2D(-bisV.y(), bisV.x())
         spV = arc.startAngleVector()
         spLeftOfBisector = spV.dotProduct(spV, bis90V) >= 0.0
         epV = arc.endAngleVector()
         # is the arrow tip to the left of the bisector?
         if bis90V.dotProduct(apV, bis90V) >= 0.0:
             # is the start point left of the bisector?
             if spLeftOfBisector:
                 extensionArc = Arc.fromVectors(spV, apV, arcRadius, True)
             else:
                 extensionArc = Arc.fromVectors(epV, apV, arcRadius, True)
             pp.arcMoveTo(r, -extensionArc.start() - self.gapAngle)
             pp.arcTo(r, -extensionArc.start() - self.gapAngle,
                      -extensionArc.span() - self.extAngle)
         # arrow tip to right of bisector
         else:
             # is the start point left of the bisector?
             if spLeftOfBisector:
                 extensionArc = Arc.fromVectors(epV, apV, arcRadius, False)
             else:
                 extensionArc = Arc.fromVectors(spV, apV, arcRadius, False)
             pp.arcMoveTo(r, -extensionArc.start() + self.gapAngle)
             pp.arcTo(r, -extensionArc.start() + self.gapAngle,
                      -extensionArc.span() + self.extAngle)
     self.setPath(pp)