コード例 #1
0
pt10B = pt("10B", pt10A[0] - abs(pt10A[0] - np.real(seg_10A_11.point(t)) / cm),
           (np.imag(seg_10A_11.point(t)) / cm))
#t = seg_10A_11.ilength(1.0*cm)
#pt10C = pt("10C", np.real(seg.point(t))/cm, np.imag(seg.point(t))/cm)

path1 = svgwrite.path.Path('%s' % sp_10A_11, fill="none",
                           stroke=col_sew)  # (pt2ph(pt10B),

# only curve 0.25, not 0.5
hipline_curve = 0.2  # not 0.5
seg_11_8 = Line(complex(pt11[0] * cm, pt11[1] * cm),
                complex(pt8[0] * cm, pt8[1] * cm))
seg_length = seg_11_8.length()
t_mid = seg_11_8.ilength(seg_length / 2)
geo_mid = seg_11_8.point(t_mid)
n = seg_11_8.normal(t_mid)
normal_line = Line(seg_11_8.point(t_mid),
                   seg_11_8.point(t_mid) + hipline_curve * cm * n)
ctrl_pt = (np.real(normal_line.point(1)), np.imag(normal_line.point(1)))
ctrl_pt_str = str(np.real(normal_line.point(1))) + ", " + str(
    np.imag(normal_line.point(1)))

p_11_8 = (pt2cm(pt11), ctrl_pt, pt2cm(pt8))
pf_11_8 = fitpath(p_11_8, 10e-1)
sp_11_8 = pathtosvg(pf_11_8).replace('M', 'L')[17:]

path1.push('%s' % sp_11_8)  # curve
# path1.push('L %s' % (pt2ph(pt8))) # curve
path1.push('L %s' % (pt2ph(pt14)))
path1.push('L %s' % (pt2ph(pt12)))
path1.push('L %s' % (pt2ph(pt13)))
コード例 #2
0
def offset_curve(path, offset_distance, steps=200):
    """Takes in a Path object, `path`, and a distance,
    `offset_distance`, and outputs an piecewise-linear approximation
    of the 'parallel' offset curve."""
    nls = []
    if 'intersect' in locals():
        del intersect
    '''    
    for n, segX in enumerate(path):

        u1 = segX.unit_tangent(0.0)
        u2 = segX.unit_tangent(1.0)
        mag = 1.0*cm
        tan1 = Line(segX.point(0.0), segX.point(0.0) + mag*u1*-1).reversed()
        tan2 = Line(segX.point(1.0), segX.point(1.0) + mag*u2)
        for seg in tan1, segX, tan2:
            for k in range(steps):
                t = k / float(steps)
                offset_vector = offset_distance * seg.normal(t)
                nl = Line(seg.point(t), seg.point(t) + offset_vector)
                nls.append(nl)
    '''

    for n, segX in enumerate(path):
        if n == len(path) - 1:
            n = -1
        if 'intersect' in locals():
            segX = segX.cropped(intersect[1], 1)
            del intersect
        segXN9 = segX.normal(0.9) * offset_distance
        segXN1 = segX.normal(1.0) * offset_distance
        segYN0 = path[n + 1].normal(0.0) * offset_distance
        segYN1 = path[n + 1].normal(0.1) * offset_distance
        nlX = Line(segX.point(0.9) + segXN9, segX.point(1) + segXN1)
        nlY = Line(path[n + 1].point(0) + segYN0,
                   path[n + 1].point(0.1) + segYN1)

        #print nlX.intersect(nlY)
        if nlX.intersect(nlY):
            intersect = nlX.intersect(nlY)[0]
            seg = segX.cropped(0, intersect[0])
            for k in range(steps):
                t = k / float(steps)
                offset_vector = offset_distance * seg.normal(t)
                nl = Line(seg.point(t), seg.point(t) + offset_vector)
                nls.append(nl)
        else:
            nls_X = []
            nls_Y = []
            for k in range(50):
                t = k / float(50)
                offset_vector_X = offset_distance * segX.normal(t)
                nl = Line(segX.point(t), segX.point(t) + offset_vector_X)
                nls_X.append(nl)

                offset_vector_Y = offset_distance * path[n + 1].normal(t)
                nl = Line(path[n + 1].point(t),
                          path[n + 1].point(t) + offset_vector_Y)
                nls_Y.append(nl)

            connect_the_dots_X = [
                Line(nls_X[k].end, nls_X[k + 1].end)
                for k in range(len(nls_X) - 1)
            ]
            connect_the_dots_Y = [
                Line(nls_Y[k].end, nls_Y[k + 1].end)
                for k in range(len(nls_Y) - 1)
            ]

            for n1, x in enumerate(connect_the_dots_X):
                for m, y in enumerate(connect_the_dots_Y):
                    if x.intersect(y):
                        intersect = [n1 / 50., m / 50.]  #x.intersect(y)

            if 'intersect' in locals():
                seg = segX.cropped(0, intersect[0])
                for k in range(steps):
                    t = k / float(steps)
                    offset_vector = offset_distance * seg.normal(t)
                    nl = Line(seg.point(t), seg.point(t) + offset_vector)
                    nls.append(nl)

            else:
                u1 = segX.unit_tangent(1.0)
                u2 = path[n + 1].unit_tangent(0.0)
                mag = 3.0 * cm  # to ensure it will intersect
                tan1 = Line(segX.point(1.0), segX.point(1.0) + mag * u1)
                tan2 = Line(path[n + 1].point(0.0),
                            path[n + 1].point(0.0) + mag * u2 * -1).reversed()
                tan1N0 = tan1.normal(0) * offset_distance
                tan1N1 = tan1.normal(1.0) * offset_distance
                tan2N1 = tan2.normal(1) * offset_distance
                tan2N0 = tan2.normal(0) * offset_distance
                nlX = Line(tan1.point(0) + tan1N0, tan1.point(1) + tan1N1)
                nlY = Line(tan2.point(0) + tan2N0, tan2.point(1) + tan2N1)

                # calc angle
                a = np.array([np.real(tan1[1]), np.imag(tan1[1])])
                b = np.array([np.real(tan1[0]), np.imag(tan1[0])])
                c = np.array([np.real(tan2[0]), np.imag(tan2[0])])  # tan2[0]

                ba = a - b
                bc = c - b

                from math import acos
                from math import sqrt
                from math import pi

                def length(v):
                    return sqrt(v[0]**2 + v[1]**2)

                def dot_product(v, w):
                    return v[0] * w[0] + v[1] * w[1]

                def determinant(v, w):
                    return v[0] * w[1] - v[1] * w[0]

                def inner_angle(v, w):
                    cosx = dot_product(v, w) / (length(v) * length(w))
                    rad = acos(cosx)  # in radians
                    return rad * 180 / pi  # returns degrees

                def angle_clockwise(A, B):
                    inner = inner_angle(A, B)
                    det = determinant(A, B)
                    if det < 0:  #this is a property of the det. If the det < 0 then B is clockwise of A
                        return inner
                    else:  # if the det > 0 then A is immediately clockwise of B
                        return 360 - inner

                #cosine_angle = np.dot(bc, ba) / (np.linalg.norm(ba) * np.linalg.norm(bc))
                #angle = np.arccos(cosine_angle)
                # print angle_clockwise(bc, ba)
                if angle_clockwise(bc, ba) < 90.0:
                    seg = segX
                    for k in range(steps):
                        t = k / float(steps)
                        offset_vector = offset_distance * seg.normal(t)
                        nl = Line(seg.point(t), seg.point(t) + offset_vector)
                        nls.append(nl)

                elif len(nlX.intersect(nlY)) > 0:

                    intersectT = nlX.intersect(nlY)
                    #print intersectT
                    tan1 = tan1.cropped(0, intersectT[0][0])
                    tan2 = tan2.cropped(intersectT[0][1], 1)
                    #print intersectT

                    for seg in segX, tan1, tan2:
                        for k in range(steps):
                            t = k / float(steps)
                            offset_vector = offset_distance * seg.normal(t)
                            nl = Line(seg.point(t),
                                      seg.point(t) + offset_vector)
                            nls.append(nl)
                else:
                    seg = segX
                    for k in range(steps):
                        t = k / float(steps)
                        offset_vector = offset_distance * seg.normal(t)
                        nl = Line(seg.point(t), seg.point(t) + offset_vector)
                        nls.append(nl)

    connect_the_dots = [
        Line(nls[k].end, nls[k + 1].end) for k in range(len(nls) - 1)
    ]
    if path.isclosed():
        connect_the_dots.append(Line(nls[-1].end, nls[0].end))
    offset_path = Path(*connect_the_dots)
    return offset_path