<commit_before># Copyright (c) 2020, <NAME>
# License: MIT License
# Created: 2020-07-10
from typing import TYPE_CHECKING, List, Tuple, Iterable, Sequence
from collections import abc
from enum import Enum
import math
from ezdxf.math import Vector, NULLVEC, Bezier4P, Matrix44, bulge_to_arc, cubic_bezier_from_arc

if TYPE_CHECKING:
    from ezdxf.eztypes import LWPolyline, Polyline, Vertex
    from ezdxf.entities.hatch import PolylinePath, EdgePath

__all__ = ['Path', 'Command']


class Command(Enum):
    LINE = 1
    CUBIC = 2


class Path(abc.Sequence):
    def __init__(self, start: 'Vertex' = NULLVEC):
        self._start = Vector(start)
        self._commands: List[Tuple] = []

    def __len__(self):
        return len(self._commands)

    def __getitem__(self, item):
        return self._commands[item]

    def __iter__(self):
        return iter(self._commands)

    @property
    def start(self) -> Vector:
        """ Path start point. """
        return self._start

    @start.setter
    def start(self, location: 'Vertex') -> None:
        self._start = Vector(location)

    @property
    def end(self) -> Vector:
        """ Path end point. """
        if self._commands:
            return self._commands[-1][1]
        else:
            return self._start

    @classmethod
    def from_lwpolyline(cls, lwpolyline: 'LWPolyline') -> 'Path':
        assert lwpolyline.dxftype() == 'LWPOLYLINE'
        path = cls()
        path._setup_polyline(lwpolyline.points('xyb'), close=lwpolyline.closed)
        return path

    @classmethod
    def from_polyline(cls, polyline: 'Polyline') -> 'Path':
        assert polyline.dxftype() == 'POLYLINE'
        points = [vertex.format('xyb') for vertex in polyline.vertices]
        path = cls()
        path._setup_polyline(points, close=polyline.is_closed)
        return path

    def _setup_polyline(self, points: Iterable[Sequence[float]], close: bool) -> None:
        def bulge_to(p1: Vector, p2: Vector, bulge: float):
            center, start_angle, end_angle, radius = bulge_to_arc(p1, p2, bulge)
            curves = list(
                cubic_bezier_from_arc(Vector(center), radius, math.degrees(start_angle), math.degrees(end_angle)))

            if not curves[0].control_points[0].isclose(p1):
                # reverse all curves
                curves = list(c.reverse() for c in curves)
                curves.reverse()

            for curve in curves:
                pts = curve.control_points
                self.cubic_to(pts[3], pts[1], pts[2])

        prev_point = None
        prev_bulge = 0
        for x, y, bulge in points:
            point = Vector(x, y)
            if prev_point is None:
                self.start = point
                prev_point = point
                prev_bulge = bulge
                continue

            if prev_bulge:
                bulge_to(prev_point, point, prev_bulge)
            else:
                self.line_to(point)
            prev_point = point
            prev_bulge = bulge

        if close and not self.start.isclose(self.end):
            if prev_bulge:
                bulge_to(self.end, self.start, prev_bulge)
            else:
                self.line_to(self.start)

    @classmethod<commit_msg>minor edit<commit_after># Copyright (c) 2020, <NAME>
# License: MIT License
# Created: 2020-07-10
from typing import TYPE_CHECKING, List, Tuple, Iterable, Sequence
from collections import abc
from enum import Enum
import math
from ezdxf.math import Vector, NULLVEC, Bezier4P, Matrix44, bulge_to_arc, cubic_bezier_from_arc

if TYPE_CHECKING:
    from ezdxf.eztypes import LWPolyline, Polyline, Vertex
    from ezdxf.entities.hatch import PolylinePath, EdgePath

__all__ = ['Path', 'Command']


class Command(Enum):
    LINE = 1
    CUBIC = 2


class Path(abc.Sequence):
    def __init__(self, start: 'Vertex' = NULLVEC):
        self._start = Vector(start)
        self._commands: List[Tuple] = []

    def __len__(self):
        return len(self._commands)

    def __getitem__(self, item):
        return self._commands[item]

    def __iter__(self):
        return iter(self._commands)

    @property
    def start(self) -> Vector:
        """ Path start point. """
        return self._start

    @start.setter
    def start(self, location: 'Vertex') -> None:
        self._start = Vector(location)

    @property
    def end(self) -> Vector:
        """ Path end point. """
        if self._commands:
            return self._commands[-1][1]
        else:
            return self._start

    @classmethod
    def from_lwpolyline(cls, lwpolyline: 'LWPolyline') -> 'Path':
        assert lwpolyline.dxftype() == 'LWPOLYLINE'
        path = cls()
        path._setup_polyline(lwpolyline.points('xyb'), close=lwpolyline.closed)
        return path

    @classmethod
    def from_polyline(cls, polyline: 'Polyline') -> 'Path':
        assert polyline.dxftype() == 'POLYLINE'
        points = [vertex.format('xyb') for vertex in polyline.vertices]
        path = cls()
        path._setup_polyline(points, close=polyline.is_closed)
        return path

    def _setup_polyline(self, points: Iterable[Sequence[float]], close: bool) -> None:
        def bulge_to(p1: Vector, p2: Vector, bulge: float):
            center, start_angle, end_angle, radius = bulge_to_arc(p1, p2, bulge)
            curves = list(
                cubic_bezier_from_arc(Vector(center), radius, math.degrees(start_angle), math.degrees(end_angle)))

            # Curves from p1 to p2?
            if not curves[0].control_points[0].isclose(p1):
                # reverse all curves
                curves = list(c.reverse() for c in curves)
                curves.reverse()

            for curve in curves:
                _, ctrl1, ctrl2, end = curve.control_points
                self.cubic_to(end, ctrl1, ctrl2)

        prev_point = None
        prev_bulge = 0
        for x, y, bulge in points:
            point = Vector(x, y)
            if prev_point is None:
                self.start = point
                prev_point = point
                prev_bulge = bulge
                continue

            if prev_bulge:
                bulge_to(prev_point, point, prev_bulge)
            else:
                self.line_to(point)
            prev_point = point
            prev_bulge = bulge

        if close and not self.start.isclose(self.end):
            if prev_bulge:
                bulge_to(self.end, self.start, prev_bulge)
            else:
                self.line_to(self.start)

    @classmethod
{'fraction_non_alphanumeric': 0.10114766641162969, 'fraction_numerical': 0.009640397857689364, 'mean_word_length': 2.1377820451272203, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6926337', 'n_tokens_mistral': 2067, 'n_tokens_neox': 1970, 'n_words': 501}