コード例 #1
0
def path_segments_hv(start, end, max_bend, adj):
	# j-shaped path 'horizontal' to 'vertical' 
	dx = end.real - start.real
	dy = end.imag - start.imag
	dv = adj[0] * dy/abs(dy)
	dh = adj[1] * dx/abs(dx)

	h = Line(start, complex(start.real+dh, start.imag))
	v = Line(complex(end.real, end.imag-dv), end)

	p1 = h.end + complex(0.75*(dx-dh), 0)
	p2 = h.end + complex(dx-dh, 0.25*(dy-dv))
	p3 = h.end + complex(dx-dh, dy-dv)

	if abs(dx) > max_bend:
		dh = dx - max_bend*dx/abs(dx)
		h = Line(start, complex(start.real+dh, start.imag))
		p1 = complex(h.end.real + 0.75*max_bend*dx/abs(dx), p1.imag)
		p2 = complex(h.end.real + max_bend*dx/abs(dx), p2.imag)
		p3 = complex(h.end.real + max_bend*dx/abs(dx), p3.imag)
	if abs(dy) > max_bend:
		dv = dy - max_bend*dy/abs(dy)
		v = Line(complex(end.real, end.imag-dv), end)
		p2 = complex(p2.real, h.end.imag + 0.25*max_bend*dy/abs(dy))
		p3 = complex(p3.real, h.end.imag + max_bend*dy/abs(dy))

	c = CubicBezier(complex(start.real+dh, start.imag), p1, p2, p3)

	segs = [h,c,v]
	if v.start == v.end:
		segs.remove(v)
	if h.start == h.end:
		segs.remove(h)

	return segs
コード例 #2
0
ファイル: svg_converter.py プロジェクト: daisieh/TreeFig
def path_to_polygon(path):
    polygon = []
    global max_x, max_y, min_x, min_y
    new_path = Path()
    for segment in parse_path(path):
        new_path.append(Line(segment.start, segment.end))
    new_path.closed = True
    raw_path = new_path.d()

    # search for compound path bits and remove them
    path_bits = re.findall('M.+?[ZM]', raw_path)
    if len(path_bits) > 0:
        raw_path = path_bits[0]
        raw_path_size = len(re.findall(',', raw_path))
        for bit in path_bits:
            bit_size = len(re.findall(',', bit))
            if bit_size > raw_path_size:
                raw_path = bit
                raw_path_size = bit_size

    # convert to simple list of nodes
    nodes = re.findall('[ML]\s*(\d+\.*\d*,\d+\.*\d*)\s*', raw_path)
    for n in nodes:
        coords = n.split(',')
        if max_x < int(coords[0]):
            max_x = int(coords[0])
        if max_y < int(coords[1]):
            max_y = int(coords[1])
        if min_x > int(coords[0]):
            min_x = int(coords[0])
        if min_y > int(coords[1]):
            min_y = int(coords[1])
        polygon.append([int(coords[0]), int(coords[1])])
    polygon.pop()
    return polygon
コード例 #3
0
def mkLine(x1, y1, x2, y2):
    x1 = round(x1, 4)
    y1 = round(y1, 4)
    x2 = round(x2, 4)
    y2 = round(y2, 4)
    if (x1 == x2) and (y1 == y2):
        return None
    return Line(complex(x1, y1), complex(x2, y2))
コード例 #4
0
    def test_path_is_homogeneously_sampled(self):
        test_path = Path(Line(start=(0 + 0j), end=(5 + 0j)))
        expected_result = [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0)]

        traj = Trajectory()
        traj.paths.append(test_path)
        result = traj.get_path(0, 0, 1)

        for (x1, y1), (x2, y2) in zip(result, expected_result):
            self.assertAlmostEqual(x1, x2, delta=0.01)
            self.assertAlmostEqual(y1, y2, delta=0.01)
コード例 #5
0
    def clean(points: List, new_path: svg.path.Path, height):
        count = len(points)
        i = 0

        while i < count:
            x1, y1 = points[i]

            while count >= 3:
                x2, y2 = points[(i + 1) % count]
                x3, y3 = points[(i + 2) % count]

                a = atan2(y2 - y1, x2 - x1)
                b = atan2(y3 - y2, x3 - x2)
                test = abs(a - b) <= ANGLE_TOLERANCE
                if not test:
                    break

                points.pop((i + 1) % count)
                if i + 1 >= count:
                    i -= 1

                count -= 1

            i += 1

        prev_point = complex(
            points[0][0] * INPUT_SCALE + INPUT_TRANSLATE_X,
            points[0][1] * INPUT_SCALE + INPUT_TRANSLATE_Y + height)
        start_point = prev_point
        new_path.append(Move(to=prev_point))

        for point in points[1:]:
            new_point = complex(
                point[0] * INPUT_SCALE + INPUT_TRANSLATE_X,
                point[1] * INPUT_SCALE + INPUT_TRANSLATE_Y + height)
            new_path.append(Line(start=prev_point, end=new_point))
            prev_point = new_point
            pass

        new_path.append(Close(start=prev_point, end=start_point))
        pass
コード例 #6
0
    def test_get_path_not_starting_at_0(self):
        test_path = Path(Line(start=(0 + 0j), end=(2 + 2j)),
                         Line(start=(2 + 2j), end=(7 + 1j)),
                         Line(start=(7 + 1j), end=(0 + 0j)))

        expected_result = Trajectory.discretize(
            Path(Line(start=(2 + 2j), end=(7 + 1j)),
                 Line(start=(7 + 1j), end=(0 + 0j)),
                 Line(start=(0 + 0j), end=(2 + 2j))), 1)

        traj = Trajectory()
        traj.paths.append(test_path)
        result = traj.get_path(0, 1, 1)

        self.assertEqual(result, expected_result)
コード例 #7
0
    def test_get_normalized_path(self):
        traj = Trajectory()

        test_path = Path(Line(start=(0 + 0j), end=(2 + 2j)),
                         Line(start=(2 + 2j), end=(7 + 1j)),
                         Line(start=(7 + 1j), end=(0 + 0j)))

        expected_path = Trajectory.scale(
            Trajectory.discretize(
                Path(Line(start=(0 + 0j), end=(2 + 2j)),
                     Line(start=(2 + 2j), end=(7 + 1j)),
                     Line(start=(7 + 1j), end=(0 + 0j))), 1), 1 / 7.0, 1 / 2.0)

        traj.paths.append(test_path)
        normalized_trajectory = traj.get_normalized_path(0)

        self.assertGreater(len(normalized_trajectory), 3)

        for (x1, y1), (x2, y2) in zip(normalized_trajectory, expected_path):
            self.assertAlmostEqual(x1, x2, delta=0.01)
            self.assertAlmostEqual(y1, y2, delta=0.01)
コード例 #8
0
def get_path_segments(start, end, start_direction, end_direction, max_bend= 40, adjust= None):
	"""get an svg.Path() object from 'start' to 'end'. 
	directionality is 'v' (vertical) or 'h' (horizontal).
	resulting path type is something like:
	R------------S (l-shaped)

	R-----
		  \
		   \
			-----S (s-shaped)
	or 
	R-------
			\
			 |
			 |
			 S (j-shaped)
	depending on given path directionality of reaction and species. """

	start_direction = start_direction[0].lower()
	end_direction = end_direction[0].lower()
	shape = start_direction + end_direction
	dx = end.real - start.real
	dy = end.imag - start.imag

	if start.real==end.real or start.imag==end.imag:
		segs = [Line(start, end)]

	elif shape == 'vh':
		# j-shaped
		if adjust == None:
			adjust = [0,0]
		segs = path_segments_vh(start, end, max_bend, adjust)
	
	elif shape == 'hv':
		# j-shaped
		if adjust == None:
			adjust = [0,0]
		segs = path_segments_hv(start, end, max_bend, adjust)

	elif shape == 'vv':
		# s-shaped
		if adjust == None:
			adjust = [0, 0]
			midpoint = [start.real + 0.5*dx, start.imag + 0.5*dy]
		elif len(adjust) == 2:
			midpoint = [start.real + 0.5*dx, start.imag + 0.5*dy + adjust[0]*dy/abs(dy)]
		else:
			midpoint = [start.real + 0.5*dx, start.imag + (adjust[2] + adjust[0])*dy/abs(dy)]
		# same as vh -- hv
		seg1 = path_segments_vh(
			start,
			complex(*midpoint),
			max_bend, 
			adj = [adjust[0], 0])
		seg2 = path_segments_hv(
			complex(*midpoint),
			end,
			max_bend,
			adj = [0, adjust[1]])
		segs = seg1+seg2

	elif shape == 'hh':
		# s-shaped
		if adjust == None:
			adjust = [0, 0]
			midpoint = [start.real + 0.5*dx, start.imag + 0.5*dy]
		elif len(adjust) == 2:
			midpoint = [start.real + 0.5*dx + adjust[0]*dx/abs(dx), start.imag + 0.5*dy]
		else:
			midpoint = [start.real + (adjust[2] + adjust[0])*dx/abs(dx), start.imag + 0.5*dy]
		# same as hv -- vh
		seg1 = path_segments_hv(
			start,
			complex(*midpoint),
			max_bend,
			adj = [adjust[0], 0])
		seg2 = path_segments_vh(
			complex(*midpoint),
			end,
			max_bend,
			adj = [0, adjust[1]])
		segs = seg1+seg2

	return segs
コード例 #9
0
 def test_eq(self, element):
     Elements.test_eq(self, element)
     assert not (element['obj'] == Line(0, 1 + 1j))
コード例 #10
0
 def test_eq(self, element):
     Elements.test_eq(self, element)
     assert not element['obj'] == QuadraticBezier(0, 1 + 1j, 2)
     assert not element['obj'] == SymbolicLine(Line(0 + 0j, 10 + 0j))
コード例 #11
0
 def element(self, request):
     element_ = Line(*request.param)
     obj = SymbolicLine(element_)
     return {'obj': obj, 'base': element_}
コード例 #12
0
ファイル: segments_svg.py プロジェクト: RodrigoD27avila/TCC2
SVG2 = '''  </g>
</svg>
'''

svgpath1 = '''<path
       style="fill:none;fill-rule:evenodd;stroke:#{0:02x}{1:02x}{2:02x};stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
       d="'''
svgpath2 = ''' Z"/>
'''

print(SVG1)
for p in paths:
	path     = parse_path(p.attrib["d"])
	start    = None
	myrange  = list(frange(0, 1, decimal.Decimal('0.01')))
	mycolors = list(red.range_to(blue, len(myrange)))
	
	for i, px in enumerate(myrange):
		new_path = Path()
		if start is None:
			start = path.point(float(px))
		else:
			end   = path.point(float(px))
			new_path.append(Line(start, end))
			start = end
			color = mycolors[i]
			r = int(color.red * 255)
			g = int(color.green * 255)
			b = int(color.blue * 255)
			print((svgpath1 + new_path.d() + svgpath2).format(clamp(r), clamp(g), clamp(b)))
print(SVG2)
コード例 #13
0
def createLineSegment(currentPoint, previousPoint):
    lineSegment = Line(previousPoint, currentPoint)
    # print(lineSegment)
    return lineSegment
コード例 #14
0
ファイル: parse_svg.py プロジェクト: RodrigoD27avila/TCC2
       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
       d="'''
svgpath2 = ''' Z"/>
'''

print(SVG1)
for p in paths:
    new_path = Path()
    path = parse_path(p.attrib["d"])
    start = None
    for command in path:
        if type(command) == Line:
            new_path.append(command)
            start = command.end
            ##print(command)
        else:
            not_line_path = Path(command)
            for px in list(frange(0, 1, decimal.Decimal(factor))):
                if start is None:
                    start = not_line_path.point(float(px))
                else:
                    end = not_line_path.point(float(px))
                    new_command = Line(start, end)
                    new_path.append(new_command)
                    ##print(new_command)
                    start = end

    new_path_str = new_path.d()
    start = None
    print(svgpath1 + new_path_str + svgpath2)
print(SVG2)
コード例 #15
0
    def _pairwise_overlap_check(lines, to_update, to_remove):
        """Naive N^2 search for overlapping lines within a slope-intersect bucket.

        Adds lines to the to_remove dictionary when they are fully redundant, and adds updated line info to the
        to_update dictionary if a line needs to be lengthened to simplify partially overlapping lines.

        Returns True if a line update was produced (which means another pass of overlap-checking is required with the
        updated line info.
        """
        for i in range(len(lines)):
            if lines[i]['overall_index'] in to_remove:
                continue
            line1 = lines[i]['line']
            for j in range(i + 1, len(lines)):
                if lines[j]['overall_index'] in to_remove:
                    continue
                line2 = lines[j]['line']

                if _lines_are_collinear(line1, line2):
                    # Check for overlap using the min/max x and y values of the lines
                    l1x1 = min(line1.start.real, line1.end.real)
                    l1x2 = max(line1.start.real, line1.end.real)
                    l1y1 = min(line1.start.imag, line1.end.imag)
                    l1y2 = max(line1.start.imag, line1.end.imag)

                    l2x1 = min(line2.start.real, line2.end.real)
                    l2x2 = max(line2.start.real, line2.end.real)
                    l2y1 = min(line2.start.imag, line2.end.imag)
                    l2y2 = max(line2.start.imag, line2.end.imag)

                    if l1x1 <= l2x1 + eps and l1x2 + eps >= l2x2 and l1y1 <= l2y1 + eps and l1y2 + eps >= l2y2:
                        # Line 1 is bigger, fully contains line 2
                        assert line1.length() + eps >= line2.length()
                        to_remove[lines[j]['overall_index']] = (lines[j]['path_index'], lines[j]['line_index'], line2)
                    elif l1x1 + eps >= l2x1 and l1x2 <= l2x2 + eps and l1y1 + eps >= l2y1 and l1y2 <= l2y2 + eps:
                        # Line 2 is bigger, fully contains line 1
                        assert line2.length() + eps >= line1.length()
                        to_remove[lines[i]['overall_index']] = (lines[i]['path_index'], lines[i]['line_index'], line1)

                    # Check for partial overlap, i.e. one point of line 2 is between points of line 1 or vice versa
                    # To avoid cases with 2 line segments end-to-end, we check for point containment with either
                    # X inclusive OR Y inclusive, but not both (which would mean they share an endpoint and therefore
                    # must be end-to-end rather than overlapping since we already covered the fully-contained cases
                    # above)
                    elif (
                        (l1x1 <= l2x1 + eps and l2x1 <= l1x2 + eps and l1y1 + eps < l2y1 and l2y1 + eps < l1y2) or
                        (l1x1 + eps < l2x1 and l2x1 + eps < l1x2 and l1y1 <= l2y1 + eps and l2y1 <= l1y2 + eps) or
                        (l1x1 <= l2x2 + eps and l2x2 <= l1x2 + eps and l1y1 + eps < l2y2 and l2y2 + eps < l1y2) or
                        (l1x1 + eps < l2x2 and l2x2 + eps < l1x2 and l1y1 <= l2y2 + eps and l2y2 <= l1y2 + eps)
                    ):
                        print 'Partial overlap of these lines:\n  {!r}\n  {!r}'.format(line1, line2)

                        # Arbitrarily pick line1 to remove, and update line2 to cover the full length
                        to_remove[lines[i]['overall_index']] = (
                            lines[i]['path_index'],
                            lines[i]['line_index'],
                            line1,
                        )
                        if lines[i]['overall_index'] in to_update:
                            # In case we're now deleting a line that was previously updated, remove it from
                            # to_update to be safe
                            del to_update[lines[i]['overall_index']]

                        # To form a line that covers the full length, try all pairs of points and select the pair
                        # that produces the longest length.
                        #
                        # Simply sorting the points as x,y tuples and choosing the first/last wouldn't work because
                        # of possible floating point error: if the 2 lines have the exact same x coordinate then the
                        # sort will fall back to sorting on y and work as expected, but if the 2 lines have the
                        # "same" x coordinate but one is actually a miniscule amount smaller, that x difference will
                        # take precedence in the sort, potentially resulting in the wrong endpoints being selected.
                        points = [
                            line1.start,
                            line1.end,
                            line2.start,
                            line2.end,
                        ]

                        longest_line = line1
                        for x in range(len(points)):
                            for y in range(x + 1, len(points)):
                                new_line = Line(points[x], points[y])
                                if new_line.length() > longest_line.length():
                                    longest_line = new_line

                        # Update the original line's values (needed for subsequent comparisons of collinear lines)
                        # and log an entry in to_update for the final SVG path generation.
                        line2.start = longest_line.start
                        line2.end = longest_line.end
                        to_update[lines[j]['overall_index']] = (
                            lines[j]['path_index'],
                            lines[j]['line_index'],
                            line2,
                        )
                        print '  -- merged into a single line: {!r}'.format(line2)
                        return True
        return False
コード例 #16
0
def parse_polygon(points: str) -> Path:
    coordinates = [tuple(map(float, c.split(','))) for c in points.split()]
    path = Path()
    for a, b in pairwise(coordinates):
        path.append(Line(complex(*a), complex(*b)))
    return path
コード例 #17
0
 def StraightenCurve(self, data, samples):
     #todo: implement samples
     line = Line(data.point(0), data.point(1))
     return line