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)
def _configParallel(self, p1, p2, px, py, outside): """Define a parallel (diagonal) dimension. p1 -- first ref point p2 -- second ref point px, py -- dimension label center point outside -- True if arrows should point towards each other p1 and p2 have different x and y coordinates """ pp = QPainterPath() pos = QPointF(px, py) v = QVector2D(pos - p1) # from p1 to p2 u = QVector2D(p2 - p1).normalized() # point on line through p1 and p2 where pos is projected mp = (QVector2D(p1) + v.dotProduct(v, u) * u).toPointF() # perpendicular vector pointing towards pos sv = pos - mp # new arrow positions ap1 = p1 + sv ap2 = p2 + sv # vectors from label center point to arrow tips lv1 = QVector2D(ap1 - pos) lv2 = QVector2D(ap2 - pos) # dim label is outside extension lines if lv1 & 2 point in the same dir dimOutside = lv1.dotProduct(lv1.normalized(), lv2.normalized()) >= 0.0 br = self.dimText.sceneBoundingRect().normalized() # arrows pointing towards each other if outside: leaderLen = self.scene().pixelsToScene(self.leaderLen) self.arrow1.config({'pos': ap1, 'dir': u}) self.arrow2.config({'pos': ap2, 'dir': u * -1}) if dimOutside: if lv1.length() > lv2.length(): np = ap2 # ap2 is near point fp = ap1 npv = u else: np = ap1 fp = ap2 npv = u * -1 pp.moveTo(np) xp = xsectLineRect1(QLineF(pos, np), br) if not xp: ep = np + (npv * leaderLen).toPointF() pp.lineTo(ep) else: pp.lineTo(xp) ep = fp + (npv * -leaderLen).toPointF() pp.moveTo(fp) pp.lineTo(ep) else: ep = ap1 + (u * -leaderLen).toPointF() pp.moveTo(ap1) pp.lineTo(ep) ep = ap2 + (u * leaderLen).toPointF() pp.moveTo(ap2) pp.lineTo(ep) # arrows pointing away from each other else: self.arrow1.config({'pos': ap1, 'dir': u * -1}) self.arrow2.config({'pos': ap2, 'dir': u}) if dimOutside: if lv1.length() > lv2.length(): ep = ap1 else: ep = ap2 xp = xsectLineRect1(QLineF(pos, ep), br) pp.moveTo(xp) pp.lineTo(ep) else: xp1 = xsectLineRect1(QLineF(pos, ap1), br) if not xp1: pp.moveTo(ap2) else: pp.moveTo(xp1) pp.lineTo(ap1) xp2 = xsectLineRect1(QLineF(pos, ap2), br) if not xp2: pp.moveTo(ap1) else: pp.moveTo(xp2) pp.lineTo(ap2) # extension lines self._addExtensionLines(p1, p2, self.arrow1.pos(), self.arrow2.pos(), pp) self.setPath(pp)
def _configTwoLineSegs(self, line1, line2): """Dimension between two parallel lines. line1, line2 -- QLineF If the lines are not parallel, raise LinearDimException. """ # some checks first lv1 = QVector2D(line1.p1() - line1.p2()) lv2 = QVector2D(line2.p1() - line2.p2()) dp = lv1.dotProduct(lv1.normalized(), lv2.normalized()) # XXX: constant 0.001 if 1.0 - abs(dp) > 0.001: raise LinearDimException("Cannot dimension intersecting lines") if linesCollinear(line1, line2): raise LinearDimException("Cannot dimension collinear lines") pp = QPainterPath() pos = self.specMap['pos'] # arrow tip positions ap1 = pointOnLine(pos, line1.p1(), line1.p2()) ap2 = pointOnLine(pos, line2.p1(), line2.p2()) # vector from label center to arrow tips v1 = QVector2D(ap1 - pos) v2 = QVector2D(ap2 - pos) # find nearest line, arrow and vector to label l1, l2 = line1, line2 if v1.length() > v2.length(): v1, v2 = v2, v1 ap1, ap2 = ap2, ap1 l1, l2 = l2, l1 # for extension lines # label center is outside lines dimOutside = v1.dotProduct(v1.normalized(), v2.normalized()) >= 0.0 br = self.dimText.sceneBoundingRect().normalized() # arrows pointing in if self.specMap['outside']: leaderLen = self.scene().pixelsToScene(self.leaderLen) if dimOutside: self.arrow1.config({'pos': ap1, 'dir': v1}) self.arrow2.config({'pos': ap2, 'dir': v2 * -1}) xp = xsectLineRect1(QLineF(pos, ap1), br) if xp: pp.moveTo(xp) pp.lineTo(ap1) v = v2.normalized() ep = ap2 + (v2.normalized() * leaderLen).toPointF() pp.moveTo(ap2) pp.lineTo(ep) else: self.arrow1.config({'pos': ap1, 'dir': v1 * -1}) self.arrow2.config({'pos': ap2, 'dir': v2 * -1}) v = v2.normalized() ep = ap2 + (v2.normalized() * leaderLen).toPointF() pp.moveTo(ap2) pp.lineTo(ep) v = v1.normalized() ep = ap1 + (v1.normalized() * leaderLen).toPointF() pp.moveTo(ap1) pp.lineTo(ep) # arrows pointing out else: if dimOutside: self.arrow1.config({'pos': ap1, 'dir': v1 * -1}) self.arrow2.config({'pos': ap2, 'dir': v2}) xp = xsectLineRect1(QLineF(pos, ap2), br) if xp: pp.moveTo(xp) pp.lineTo(ap2) else: self.arrow1.config({'pos': ap1, 'dir': v1}) self.arrow2.config({'pos': ap2, 'dir': v2}) xp1 = xsectLineRect1(QLineF(pos, ap1), br) if xp1: pp.moveTo(xp1) pp.lineTo(ap1) xp2 = xsectLineRect1(QLineF(pos, ap2), br) if xp2: pp.moveTo(xp2) pp.lineTo(ap2) # extension lines # TODO: rethink this, it renders okay, but... p1 = ap1 # should I p2 = ap2 # copy apN here? # first v1 = QVector2D(l1.p1() - ap1) v2 = QVector2D(l1.p2() - ap1) offLine = v1.dotProduct(v1.normalized(), v2.normalized()) >= 0.0 # set v1 to closest end point if v1.length() > v2.length(): v1, v2 = v2, v1 if offLine: p1 = ap1 + v1.toPointF() # second v1 = QVector2D(l2.p1() - ap2) v2 = QVector2D(l2.p2() - ap2) offLine = v1.dotProduct(v1.normalized(), v2.normalized()) >= 0.0 # set v1 to closest end point if v1.length() > v2.length(): v1, v2 = v2, v1 if offLine: p2 = ap2 + v1.toPointF() self._addExtensionLines(p1, p2, ap1, ap2, pp) self.setPath(pp)