Example #1
0
 def path(self, centerradius=None, bezierradius=None, beziersoftness=None):
     pathitems = []
     if centerradius is not None and self.center is not None:
         r = unit.topt(centerradius)
         pathitems.append(path.arc_pt(self.center[0], self.center[1], r, 0, 360))
         pathitems.append(path.closepath())
     if bezierradius is not None or beziersoftness is not None:
         raise ValueError("smooth functionality removed; apply smooth deformer on path")
     pathitems.append(path.moveto_pt(self.corners[0][0], self.corners[0][1]))
     for x, y in self.corners[1:]:
         pathitems.append(path.lineto_pt(x, y))
     pathitems.append(path.closepath())
     return path.path(*pathitems)
Example #2
0
 def path(self, centerradius=None, bezierradius=None, beziersoftness=None):
     pathitems = []
     if centerradius is not None and self.center is not None:
         r = unit.topt(centerradius)
         pathitems.append(
             path.arc_pt(self.center[0], self.center[1], r, 0, 360))
         pathitems.append(path.closepath())
     if bezierradius is not None or beziersoftness is not None:
         raise ValueError(
             "smooth functionality removed; apply smooth deformer on path")
     pathitems.append(path.moveto_pt(self.corners[0][0],
                                     self.corners[0][1]))
     for x, y in self.corners[1:]:
         pathitems.append(path.lineto_pt(x, y))
     pathitems.append(path.closepath())
     return path.path(*pathitems)
Example #3
0
    def __init__(self, box1, box2,
                 absangle1=None, absangle2=None,
                 relangle1=None, relangle2=None, relangleM=None,
                 length1=None, length2=None,
                 bezierradius=None, beziersoftness=1,
                 arcradius=None,
                 boxdists=[0,0]):

        # The connection with two lines can be done in the following ways:
        # 1. an angle at each box-center
        # 2. two armlengths (if they are long enough)
        # 3. angle and armlength at the same box
        # 4. angle and armlength at different boxes
        # 5. one armlength and the angle between the arms
        #
        # Angles at the box-centers can be relative or absolute
        # The angle in the middle is always relative
        # lengths are always absolute

        self.box1 = box1
        self.box2 = box2

        begin = self.box1.center
        end = self.box2.center
        rel = (self.box2.center[0] - self.box1.center[0],
               self.box2.center[1] - self.box1.center[1])
        distance = hypot(*rel)
        dangle = atan2(rel[1], rel[0])

        # find out what arguments are given:
        if relangle1 is not None: relangle1 = radians(relangle1)
        if relangle2 is not None: relangle2 = radians(relangle2)
        if relangleM is not None: relangleM = radians(relangleM)
        # absangle has priority over relangle:
        if absangle1 is not None: relangle1 = dangle - radians(absangle1)
        if absangle2 is not None: relangle2 = math.pi - dangle + radians(absangle2)

        # check integrity of arguments
        no_angles, no_lengths=0,0
        for anangle in (relangle1, relangle2, relangleM):
            if anangle is not None: no_angles += 1
        for alength in (length1, length2):
            if alength is not None: no_lengths += 1

        if no_angles + no_lengths != 2:
            raise NotImplementedError, "Please specify exactly two angles or lengths"

        # calculate necessary angles and armlengths
        # always length1 and relangle1

        # the case with two given angles
        # use the "sine-theorem" for calculating length1
        if no_angles == 2:
            if relangle1 is None: relangle1 = math.pi - relangle2 - relangleM
            elif relangle2 is None: relangle2 = math.pi - relangle1 - relangleM
            elif relangleM is None: relangleM = math.pi - relangle1 - relangle2
            length1 = distance * abs(sin(relangle2)/sin(relangleM))
            middle = self._middle_a(begin, dangle, length1, relangle1)
        # the case with two given lengths
        # uses the "cosine-theorem" for calculating length1
        elif no_lengths == 2:
            relangle1 = acos((distance**2 + length1**2 - length2**2) / (2.0*distance*length1))
            middle = self._middle_a(begin, dangle, length1, relangle1)
        # the case with one length and one angle
        else:
            if relangle1 is not None:
                if length1 is not None:
                    middle = self._middle_a(begin, dangle, length1, relangle1)
                elif length2 is not None:
                    length1 = self._missinglength(length2, distance, relangle1)
                    middle = self._middle_a(begin, dangle, length1, relangle1)
            elif relangle2 is not None:
                if length1 is not None:
                    length2 = self._missinglength(length1, distance, relangle2)
                    middle = self._middle_b(end, dangle, length2, relangle2)
                elif length2 is not None:
                    middle = self._middle_b(end, dangle, length2, relangle2)
            elif relangleM is not None:
                if length1 is not None:
                    length2 = self._missinglength(distance, length1, relangleM)
                    relangle1 = acos((distance**2 + length1**2 - length2**2) / (2.0*distance*length1))
                    middle = self._middle_a(begin, dangle, length1, relangle1)
                elif length2 is not None:
                    length1 = self._missinglength(distance, length2, relangleM)
                    relangle1 = acos((distance**2 + length1**2 - length2**2) / (2.0*distance*length1))
                    middle = self._middle_a(begin, dangle, length1, relangle1)
            else:
                raise NotImplementedError, "I found a strange combination of arguments"

        connectorpath = path.path(path.moveto_pt(*self.box1.center),
                                  path.lineto_pt(*middle),
                                  path.lineto_pt(*self.box2.center))
        connector_pt.__init__(self, connectorpath.normpath().normsubpaths)

        self.omitends(box1, box2)
        self.shortenpath(boxdists)
Example #4
0
    def _halfbracepath_pt(self, length_pt, height_pt, ilength_pt, olength_pt, # <<<
    ithick_pt, othick_pt, bthick_pt, cos_iangle, sin_iangle, cos_oangle,
    sin_oangle, cos_slangle, sin_slangle):

        ismooth = self.innerstrokessmoothness
        osmooth = self.outerstrokessmoothness

        # these two parameters are not important enough to be seen outside
        inner_cap_param = 1.5
        outer_cap_param = 2.5
        outerextracurved = 0.6 # in (0, 1]
        # 1.0 will lead to F=G, the outer strokes will not be curved at their ends.
        # The smaller, the more curvature

        # build an orientation path (three straight lines)
        #
        #      \q1
        #    /  \
        #   /    \
        # _/      \______________________________________q5
        #         q2         q3              q4           \
        #                                                  \
        #                                                   \
        #                                                    \q6
        #
        # get the points for that:
        q1 = (0, height_pt - inner_cap_param * ithick_pt + 0.5*ithick_pt/sin_iangle)
        q2 = (q1[0] + ilength_pt * sin_iangle,
              q1[1] - ilength_pt * cos_iangle)
        q6 = (length_pt, 0)
        q5 = (q6[0] - olength_pt * sin_oangle,
              q6[1] + olength_pt * cos_oangle)
        bardir = (q5[0] - q2[0], q5[1] - q2[1])
        bardirnorm = math.hypot(*bardir)
        bardir = (bardir[0]/bardirnorm, bardir[1]/bardirnorm)
        ismoothlength_pt = ilength_pt * ismooth
        osmoothlength_pt = olength_pt * osmooth
        if bardirnorm < ismoothlength_pt + osmoothlength_pt:
            ismoothlength_pt = bardirnorm * ismoothlength_pt / (ismoothlength_pt + osmoothlength_pt)
            osmoothlength_pt = bardirnorm * osmoothlength_pt / (ismoothlength_pt + osmoothlength_pt)
        q3 = (q2[0] + ismoothlength_pt * bardir[0],
              q2[1] + ismoothlength_pt * bardir[1])
        q4 = (q5[0] - osmoothlength_pt * bardir[0],
              q5[1] - osmoothlength_pt * bardir[1])

        #
        #    P _O
        #   / | \A2
        #  / A1\ \
        #   /   \ B2C2________D2___________E2_______F2___G2
        #        \______________________________________  \
        #       B1,C1         D1           E1      F1  G1  \
        #                                                \  \
        #                                                 \  \H2
        #                                                H1\_/I2
        #                                                  I1
        #
        # the halfbraces meet in P and A1:
        P = (0, height_pt)
        A1 = (0, height_pt - inner_cap_param * ithick_pt)
        # A2 is A1, shifted by the inner thickness
        A2 = (A1[0] + ithick_pt * cos_iangle,
              A1[1] + ithick_pt * sin_iangle)
        s, t = deformer.intersection(P, A2, (cos_slangle, sin_slangle), (sin_iangle, -cos_iangle))
        O = (P[0] + s * cos_slangle,
             P[1] + s * sin_slangle)

        # from D1 to E1 is the straight part of the brace
        # also back from E2 to D1
        D1 = (q3[0] + bthick_pt * bardir[1],
              q3[1] - bthick_pt * bardir[0])
        D2 = (q3[0] - bthick_pt * bardir[1],
              q3[1] + bthick_pt * bardir[0])
        E1 = (q4[0] + bthick_pt * bardir[1],
              q4[1] - bthick_pt * bardir[0])
        E2 = (q4[0] - bthick_pt * bardir[1],
              q4[1] + bthick_pt * bardir[0])
        # I1, I2 are the control points at the outer stroke
        I1 = (q6[0] - 0.5 * othick_pt * cos_oangle,
              q6[1] - 0.5 * othick_pt * sin_oangle)
        I2 = (q6[0] + 0.5 * othick_pt * cos_oangle,
              q6[1] + 0.5 * othick_pt * sin_oangle)
        # get the control points for the curved parts of the brace
        s, t = deformer.intersection(A1, D1, (sin_iangle, -cos_iangle), bardir)
        B1 = (D1[0] + t * bardir[0],
              D1[1] + t * bardir[1])
        s, t = deformer.intersection(A2, D2, (sin_iangle, -cos_iangle), bardir)
        B2 = (D2[0] + t * bardir[0],
              D2[1] + t * bardir[1])
        s, t = deformer.intersection(E1, I1, bardir, (-sin_oangle, cos_oangle))
        G1 = (E1[0] + s * bardir[0],
              E1[1] + s * bardir[1])
        s, t = deformer.intersection(E2, I2, bardir, (-sin_oangle, cos_oangle))
        G2 = (E2[0] + s * bardir[0],
              E2[1] + s * bardir[1])
        # at the inner strokes: use curvature zero at both ends
        C1 = B1
        C2 = B2
        # at the outer strokes: use curvature zero only at the connection to
        # the straight part
        F1 = (outerextracurved * G1[0] + (1 - outerextracurved) * E1[0],
              outerextracurved * G1[1] + (1 - outerextracurved) * E1[1])
        F2 = (outerextracurved * G2[0] + (1 - outerextracurved) * E2[0],
              outerextracurved * G2[1] + (1 - outerextracurved) * E2[1])
        # the tip of the outer stroke, endpoints of the bezier curve
        H1 = (I1[0] - outer_cap_param * othick_pt * sin_oangle,
              I1[1] + outer_cap_param * othick_pt * cos_oangle)
        H2 = (I2[0] - outer_cap_param * othick_pt * sin_oangle,
              I2[1] + outer_cap_param * othick_pt * cos_oangle)

        #for qq in [A1,B1,C1,D1,E1,F1,G1,H1,I1,
        #           A2,B2,C2,D2,E2,F2,G2,H2,I2,
        #           O,P
        #           ]:
        #    cc.fill(path.circle(qq[0], qq[1], 0.5), [color.rgb.green])

        # now build the right halfbrace
        bracepath = path.path(path.moveto_pt(*A1))
        bracepath.append(path.curveto_pt(B1[0], B1[1], C1[0], C1[1], D1[0], D1[1]))
        bracepath.append(path.lineto_pt(E1[0], E1[1]))
        bracepath.append(path.curveto_pt(F1[0], F1[1], G1[0], G1[1], H1[0], H1[1]))
        # the tip of the right halfbrace
        bracepath.append(path.curveto_pt(I1[0], I1[1], I2[0], I2[1], H2[0], H2[1]))
        # the rest of the right halfbrace
        bracepath.append(path.curveto_pt(G2[0], G2[1], F2[0], F2[1], E2[0], E2[1]))
        bracepath.append(path.lineto_pt(D2[0], D2[1]))
        bracepath.append(path.curveto_pt(C2[0], C2[1], B2[0], B2[1], A2[0], A2[1]))
        # the tip in the middle of the brace
        bracepath.append(path.curveto_pt(O[0], O[1], O[0], O[1], P[0], P[1]))

        return bracepath
Example #5
0
    def _halfbracepath_pt(
            self,
            length_pt,
            height_pt,
            ilength_pt,
            olength_pt,  # <<<
            ithick_pt,
            othick_pt,
            bthick_pt,
            cos_iangle,
            sin_iangle,
            cos_oangle,
            sin_oangle,
            cos_slangle,
            sin_slangle):

        ismooth = self.innerstrokessmoothness
        osmooth = self.outerstrokessmoothness

        # these two parameters are not important enough to be seen outside
        inner_cap_param = 1.5
        outer_cap_param = 2.5
        outerextracurved = 0.6  # in (0, 1]
        # 1.0 will lead to F=G, the outer strokes will not be curved at their ends.
        # The smaller, the more curvature

        # build an orientation path (three straight lines)
        #
        #      \q1
        #    /  \
        #   /    \
        # _/      \______________________________________q5
        #         q2         q3              q4           \
        #                                                  \
        #                                                   \
        #                                                    \q6
        #
        # get the points for that:
        q1 = (0, height_pt - inner_cap_param * ithick_pt +
              0.5 * ithick_pt / sin_iangle)
        q2 = (q1[0] + ilength_pt * sin_iangle, q1[1] - ilength_pt * cos_iangle)
        q6 = (length_pt, 0)
        q5 = (q6[0] - olength_pt * sin_oangle, q6[1] + olength_pt * cos_oangle)
        bardir = (q5[0] - q2[0], q5[1] - q2[1])
        bardirnorm = math.hypot(*bardir)
        bardir = (bardir[0] / bardirnorm, bardir[1] / bardirnorm)
        ismoothlength_pt = ilength_pt * ismooth
        osmoothlength_pt = olength_pt * osmooth
        if bardirnorm < ismoothlength_pt + osmoothlength_pt:
            ismoothlength_pt = bardirnorm * ismoothlength_pt / (
                ismoothlength_pt + osmoothlength_pt)
            osmoothlength_pt = bardirnorm * osmoothlength_pt / (
                ismoothlength_pt + osmoothlength_pt)
        q3 = (q2[0] + ismoothlength_pt * bardir[0],
              q2[1] + ismoothlength_pt * bardir[1])
        q4 = (q5[0] - osmoothlength_pt * bardir[0],
              q5[1] - osmoothlength_pt * bardir[1])

        #
        #    P _O
        #   / | \A2
        #  / A1\ \
        #   /   \ B2C2________D2___________E2_______F2___G2
        #        \______________________________________  \
        #       B1,C1         D1           E1      F1  G1  \
        #                                                \  \
        #                                                 \  \H2
        #                                                H1\_/I2
        #                                                  I1
        #
        # the halfbraces meet in P and A1:
        P = (0, height_pt)
        A1 = (0, height_pt - inner_cap_param * ithick_pt)
        # A2 is A1, shifted by the inner thickness
        A2 = (A1[0] + ithick_pt * cos_iangle, A1[1] + ithick_pt * sin_iangle)
        s, t = deformer.intersection(P, A2, (cos_slangle, sin_slangle),
                                     (sin_iangle, -cos_iangle))
        O = (P[0] + s * cos_slangle, P[1] + s * sin_slangle)

        # from D1 to E1 is the straight part of the brace
        # also back from E2 to D1
        D1 = (q3[0] + bthick_pt * bardir[1], q3[1] - bthick_pt * bardir[0])
        D2 = (q3[0] - bthick_pt * bardir[1], q3[1] + bthick_pt * bardir[0])
        E1 = (q4[0] + bthick_pt * bardir[1], q4[1] - bthick_pt * bardir[0])
        E2 = (q4[0] - bthick_pt * bardir[1], q4[1] + bthick_pt * bardir[0])
        # I1, I2 are the control points at the outer stroke
        I1 = (q6[0] - 0.5 * othick_pt * cos_oangle,
              q6[1] - 0.5 * othick_pt * sin_oangle)
        I2 = (q6[0] + 0.5 * othick_pt * cos_oangle,
              q6[1] + 0.5 * othick_pt * sin_oangle)
        # get the control points for the curved parts of the brace
        s, t = deformer.intersection(A1, D1, (sin_iangle, -cos_iangle), bardir)
        B1 = (D1[0] + t * bardir[0], D1[1] + t * bardir[1])
        s, t = deformer.intersection(A2, D2, (sin_iangle, -cos_iangle), bardir)
        B2 = (D2[0] + t * bardir[0], D2[1] + t * bardir[1])
        s, t = deformer.intersection(E1, I1, bardir, (-sin_oangle, cos_oangle))
        G1 = (E1[0] + s * bardir[0], E1[1] + s * bardir[1])
        s, t = deformer.intersection(E2, I2, bardir, (-sin_oangle, cos_oangle))
        G2 = (E2[0] + s * bardir[0], E2[1] + s * bardir[1])
        # at the inner strokes: use curvature zero at both ends
        C1 = B1
        C2 = B2
        # at the outer strokes: use curvature zero only at the connection to
        # the straight part
        F1 = (outerextracurved * G1[0] + (1 - outerextracurved) * E1[0],
              outerextracurved * G1[1] + (1 - outerextracurved) * E1[1])
        F2 = (outerextracurved * G2[0] + (1 - outerextracurved) * E2[0],
              outerextracurved * G2[1] + (1 - outerextracurved) * E2[1])
        # the tip of the outer stroke, endpoints of the bezier curve
        H1 = (I1[0] - outer_cap_param * othick_pt * sin_oangle,
              I1[1] + outer_cap_param * othick_pt * cos_oangle)
        H2 = (I2[0] - outer_cap_param * othick_pt * sin_oangle,
              I2[1] + outer_cap_param * othick_pt * cos_oangle)

        #for qq in [A1,B1,C1,D1,E1,F1,G1,H1,I1,
        #           A2,B2,C2,D2,E2,F2,G2,H2,I2,
        #           O,P
        #           ]:
        #    cc.fill(path.circle(qq[0], qq[1], 0.5), [color.rgb.green])

        # now build the right halfbrace
        bracepath = path.path(path.moveto_pt(*A1))
        bracepath.append(
            path.curveto_pt(B1[0], B1[1], C1[0], C1[1], D1[0], D1[1]))
        bracepath.append(path.lineto_pt(E1[0], E1[1]))
        bracepath.append(
            path.curveto_pt(F1[0], F1[1], G1[0], G1[1], H1[0], H1[1]))
        # the tip of the right halfbrace
        bracepath.append(
            path.curveto_pt(I1[0], I1[1], I2[0], I2[1], H2[0], H2[1]))
        # the rest of the right halfbrace
        bracepath.append(
            path.curveto_pt(G2[0], G2[1], F2[0], F2[1], E2[0], E2[1]))
        bracepath.append(path.lineto_pt(D2[0], D2[1]))
        bracepath.append(
            path.curveto_pt(C2[0], C2[1], B2[0], B2[1], A2[0], A2[1]))
        # the tip in the middle of the brace
        bracepath.append(path.curveto_pt(O[0], O[1], O[0], O[1], P[0], P[1]))

        return bracepath