コード例 #1
0
 def bulge_stop_point(self):
     if self._stop_bulge_point is None:
         angle = self.half_bulge_angle
         offset = self.direction * self._radius / math.tan(
             self.half_bulge_angle)
         self._stop_bulge_point = self.start_point + sign(angle) * offset
     return self._stop_bulge_point
コード例 #2
0
ファイル: Vector.py プロジェクト: maaaash/Patro
    def angle_with(self, direction):
        """Return the angle of self on direction"""

        angle = math.acos(self.cos_with(direction))
        angle_sign = sign(self.sin_with(direction))

        return angle_sign * math.degrees(angle)
コード例 #3
0
    def _test_is_convex(self):

        # https://en.wikipedia.org/wiki/Convex_polygon
        # http://mathworld.wolfram.com/ConvexPolygon.html

        if not self.is_simple:
            return False

        edges = list(self.edges)
        # a polygon is convex if all turns from one edge vector to the next have the same sense
        # sign = edges[-1].perp_dot(edges[0])
        sign0 = sign(edges[-1].cross(edges[0]))
        for i in range(len(edges)):
            if sign(edges[i].cross(edges[i+1])) != sign0:
                return False
        return True
コード例 #4
0
 def bulge_start_point(self):
     if self._start_bulge_point is None:
         angle = self.half_bulge_angle
         offset = self.prev_part.direction * self._radius / math.tan(angle)
         self._start_bulge_point = self.start_point - sign(angle) * offset
         # Note: -offset create internal loop
     return self._start_bulge_point
コード例 #5
0
    def geometry(self):

        items = []
        for vertex1, vertex2 in self.iter_on_segment():
            segment = Segment2D(vertex1.point, vertex2.point)
            if vertex1.bulge:
                segment_center = segment.center
                direction = vertex1.segment_vector.normalise()
                normal = direction.normal
                # offset = vertex1.bulge_radius - vertex1.sagitta
                offset = vertex1.sagitta_dual
                center = segment_center + normal * sign(vertex1.bulge) * offset
                arc = Circle2D(center, vertex1.bulge_radius)
                start_angle, stop_angle = [
                    arc.angle_for_point(vertex.point)
                    for vertex in (vertex1, vertex2)
                ]
                if start_angle < 0:
                    start_angle += 360
                if stop_angle < 0:
                    stop_angle += 360
                if vertex1.bulge < 0:
                    start_angle, stop_angle = stop_angle, start_angle
                # print('bulb', vertex1, vertex2, vertex1.bulge, start_angle, stop_angle)
                arc.domain = AngularDomain(start_angle, stop_angle)
                # arc = Circle2D(center, vertex1.bulge_radius, domain=AngularDomain(start_angle, stop_angle))
                items.append(arc)
            else:
                items.append(segment)
        return items
コード例 #6
0
    def distance_to_point(self, point, return_point=False, is_inside=False):

        # Fixme: can be transform the problem to a circle using transformation ???

        point_in_frame = self.point_in_ellipse_frame(point)
        point_in_frame_abs = self.__vector_cls__(abs(point_in_frame.x),
                                                 abs(point_in_frame.y))
        distance, point_in_ellipse = self._eberly_distance(point_in_frame_abs)

        if is_inside:
            # Fixme: right ???
            return ((point_in_frame_abs - self._center).magnitude_square <=
                    (point_in_ellipse - self._center).magnitude_square)
        elif return_point:
            point_in_ellipse = self.__vector_cls__(
                sign(point_in_frame.x) * (point_in_ellipse.x),
                sign(point_in_frame.y) * (point_in_ellipse.y),
            )
            point_in_ellipse = self.point_from_ellipse_frame(point_in_ellipse)
            return distance, point_in_ellipse
        else:
            return distance
コード例 #7
0
    def intersect_circle(self, circle):

        # Fixme: check domain !!!

        v = circle.center - self.center
        d = sign(v.x) * v.magnitude

        x = (d**2 - circle.radius**2 + self.radius**2) / (2 * d)
        y2 = self.radius**2 - x**2

        if y2 < 0:
            return None
        else:
            p = self.center + v.normalise() * x
            if y2 == 0:
                return p
            else:
                n = v.normal() * sqrt(y2)
                return p - n, p - n
コード例 #8
0
    def intersect_segment(self, segment):
        """Compute the intersection of a circle and a segment."""

        # Fixme: check domain !!!

        dx = segment.vector.x
        dy = segment.vector.y
        dr2 = dx**2 + dy**2

        p0 = segment.p0 - self.center
        p1 = segment.p1 - self.center
        D = p0.cross(p1)  # Fixme: fixed typo _product ??

        # from sympy import *
        # x, y, dx, dy, D, r = symbols('x y dx dy D r')
        # system = [x**2 + y**2 - r**2, dx*y - dy*x + D]
        # vars = [x, y]
        # solution = nonlinsolve(system, vars)
        # solution.subs(dx**2 + dy**2, dr**2)

        Vector2D = self.__vector_cls__
        discriminant = self.radius**2 * dr2 - D**2
        if discriminant < 0:
            return None
        elif discriminant == 0:  # tangent line
            x = (D * dy) / dr2
            y = (-D * dx) / dr2
            return Vector2D(x, y) + self.center
        else:  # intersection
            x_a = D * dy
            y_a = -D * dx
            x_b = sign(dy) * dx * sqrt(discriminant)
            y_b = fabs(dy) * sqrt(discriminant)
            x0 = (x_a - x_b) / dr2
            y0 = (y_a - y_b) / dr2
            x1 = (x_a + x_b) / dr2
            y1 = (y_a + y_b) / dr2
            p0 = Vector2D(x0, y0) + self.center
            p1 = Vector2D(x1, y1) + self.center
            return p0, p1
コード例 #9
0
    def _compute_area_barycenter(self):
        """Compute polygon area and barycenter."""

        if not self.is_simple:
            return None

        # area = self._points[-1].cross(self._points[0])
        # for i in range(self.number_of_points):
        #     area *= self._points[i].cross(self._points[i+1])

        # P0, P1, Pn-1, P0
        points = self.closed_point_array

        # from 0 to n-1 : P0, ..., Pn-1
        xi = points[0, :-1]
        yi = points[1, :-1]
        # from 1 to n : P1, ..., Pn-1, P0
        xi1 = points[0, 1:]
        yi1 = points[1, 1:]

        # Fixme: np.cross ???
        cross = xi * yi1 - xi1 * yi
        self._cross = cross

        area = .5 * np.sum(cross)

        if area == 0:
            # print('Null area')
            self._area = 0
            self._barycenter = self.start_point
        else:
            factor = 1 / (6 * area)
            x = factor * np.sum((xi + xi1) * cross)
            y = factor * np.sum((yi + yi1) * cross)

            # area of a convex polygon is defined to be positive if the points are arranged in a
            # counterclockwise order, and negative if they are in clockwise order (Beyer 1987).
            self._area = abs(area)
            self._area_sign = sign(area)
            self._barycenter = self.__vector_cls__(x, y)