def test_ray2d_angle(self):
     ray = ConstructionRay((10, 10), angle=HALF_PI)
     assert ray._is_vertical is True
     ray = ConstructionRay((10, 10), angle=0)
     assert ray._is_horizontal is True
     ray = ConstructionRay((10, 10), angle=math.pi / 4)
     assert math.isclose(ray._slope, 1.)
    def test_ray2d_intersect(self):
        ray1 = ConstructionRay((10, 1), (20, 10))
        ray2 = ConstructionRay((17, -7), (-10, 3))

        point = ray1.intersect(ray2)
        assert point.isclose(Vector(5.7434, -2.8309), abs_tol=1e-4)
        assert ray1.is_parallel(ray2) is False
Exemple #3
0
 def test_ray2d_intersect_with_vertical(self):
     ray1 = ConstructionRay((10, 1), (10, -7))
     ray2 = ConstructionRay((-10, 3), (17, -7))
     point = ray1.intersect(ray2)
     assert point.isclose(Vector(10., -4.4074), abs_tol=1e-4)
     with pytest.raises(ArithmeticError):
         _ = ray1.yof(1)
 def test_ray2d_intersect_with_vertical_and_horizontal(self):
     ray1 = ConstructionRay((-10, 10), (10, 10))
     ray2 = ConstructionRay((5, 0), (5, 20))
     point = ray1.intersect(ray2)
     assert point.y == 10
     assert point.x == 5
     assert point.isclose(Vector(5.0, 10.0), abs_tol=1e-4)
Exemple #5
0
def offset_vertices_2d(vertices: Iterable['Vertex'],
                       offset: float,
                       closed: bool = False) -> Iterable['Vec2']:
    """
    Yields vertices of the offset line to the shape defined by `vertices`. The source shape consist
    of straight segments and is located in the xy-plane, the z-axis of input vertices is ignored.
    Takes closed shapes into account if argument `closed` is ``True``, which yields intersection of first and last
    offset segment as first vertex for a closed shape. For closed shapes the first and last vertex can be equal,
    else an implicit closing segment from last to first vertex is added.
    A shape  with equal first and last vertex is not handled automatically as closed shape.

    .. warning::

        Adjacent collinear segments in `opposite` directions, same as a turn by 180 degree (U-turn), leads to
        unexpected results.

    Args:
        vertices: source shape defined by vertices
        offset: line offset perpendicular to direction of shape segments defined by vertices order, offset > ``0`` is
                'left' of line segment, offset < ``0`` is 'right' of line segment
        closed: ``True`` to handle as closed shape

    """
    vertices = Vec2.list(vertices)
    if len(vertices) < 2:
        raise ValueError('2 or more vertices required.')

    if closed and not vertices[0].isclose(vertices[-1]):
        # append first vertex as last vertex to close shape
        vertices.append(vertices[0])

    # create offset segments
    offset_segments = list()
    for start, end in zip(vertices[:-1], vertices[1:]):
        offset_vec = (end - start).orthogonal().normalize(offset)
        offset_segments.append((start + offset_vec, end + offset_vec))

    if closed:  # insert last segment also as first segment
        offset_segments.insert(0, offset_segments[-1])

    # first offset vertex = start point of first segment for open shapes
    if not closed:
        yield offset_segments[0][0]

    # yield intersection points of offset_segments
    if len(offset_segments) > 1:
        for (start1, end1), (start2, end2) in zip(offset_segments[:-1],
                                                  offset_segments[1:]):
            try:  # the usual case
                yield ConstructionRay(start1, end1).intersect(
                    ConstructionRay(start2, end2))
            except ParallelRaysError:  # collinear segments
                yield end1
                if not end1.isclose(start2):  # it's an U-turn (180 deg)
                    # creates an additional vertex!
                    yield start2

    # last offset vertex = end point of last segment for open shapes
    if not closed:
        yield offset_segments[-1][1]
 def test_init_with_angle(self):
     point = (10, 10)
     ray = ConstructionRay(point, angle=0)
     ray_normal = ray.orthogonal(point)
     assert ray_normal._is_vertical is True
     ray = ConstructionRay(point, angle=-HALF_PI)
     assert ray._is_horizontal is False
     assert ray._is_vertical is True
 def test_intersect_ray_pass(self):
     circle = ConstructionCircle((10., 10.), 3)
     ray1_hor = ConstructionRay((10., 15.), angle=0)
     ray2_hor = ConstructionRay((10., 5.), angle=0)
     ray1_vert = ConstructionRay((5., 10.), angle=HALF_PI)
     ray2_vert = ConstructionRay((15., 10.), angle=-HALF_PI)
     ray3 = ConstructionRay((13.24, 14.95), angle=0.3992)
     self.assertFalse(circle.intersect_ray(ray1_hor))
     self.assertFalse(circle.intersect_ray(ray2_hor))
     self.assertFalse(circle.intersect_ray(ray1_vert))
     self.assertFalse(circle.intersect_ray(ray2_vert))
     self.assertFalse(circle.intersect_ray(ray3))
    def test_two_close_horizontal_rays(self):
        p1 = (39340.75302672016, 32489.73349764998)
        p2 = (39037.75302672119, 32489.73349764978)
        p3 = (38490.75302672015, 32489.73349764997)

        ray1 = ConstructionRay(p1, p2)
        ray2 = ConstructionRay(p2, p3)
        assert ray1.is_horizontal is True
        assert ray2.is_horizontal is True
        assert ray1.is_parallel(ray2) is True
        assert math.isclose(
            ray1.slope,
            ray2.slope) is False, 'Only slope testing is not sufficient'
 def test_ray2d_parallel(self):
     ray1 = ConstructionRay((17, -8), (-10, 2))
     ray2 = ConstructionRay((-10, 3), (17, -7))
     ray3 = ConstructionRay((-10, 4), (17, -6))
     assert ray2.is_parallel(ray3) is True
     assert ray1.is_parallel(ray3) is True
     with pytest.raises(ParallelRaysError):
         _ = ray2.intersect(ray3)
Exemple #10
0
 def _setup(self) -> None:
     """
     Calc setup values and determines the point order of the dimension line points.
     """
     self.measure_points = [Vector(point) for point in self.measure_points]  # type: List[Vector]
     dimlineray = ConstructionRay(self.dimlinepos, angle=radians(self.angle))  # Type: ConstructionRay
     self.dimline_points = [self._get_point_on_dimline(point, dimlineray) for point in
                            self.measure_points]  # type: List[Vector]
     self.point_order = self._indices_of_sorted_points(self.dimline_points)  # type: List[int]
     self._build_vectors()
 def test_touch(testnum, x, y, _angle, abs_tol=1e-6):
     result = True
     ray = ConstructionRay((x, y), angle=_angle)
     points = circle.intersect_ray(ray, abs_tol=abs_tol)
     if len(points) != 1:
         result = False
     else:
         point = points[0]
         # print ("{0}: x= {1:.{places}f} y= {2:.{places}f} : x'= {3:.{places}f} y' = {4:.{places}f}".format(testnum, x, y, point[0], point[1], places=places))
         if not isclose(point[0], x, abs_tol=abs_tol):
             result = False
         if not isclose(point[1], y, abs_tol=abs_tol):
             result = False
     return result
 def test_bisectrix(self):
     ray1 = ConstructionRay((10, 10), angle=math.pi / 3)
     ray2 = ConstructionRay((3, -5), angle=math.pi / 2)
     ray3 = ConstructionRay((1, 1), angle=math.pi / 3)
     a = ray1.bisectrix(ray2)
     assert math.isclose(a._angle, 1.309, abs_tol=1e-4)
     assert math.isclose(a.yof(7), 12.80385, abs_tol=1e-4)
     with pytest.raises(ParallelRaysError):
         _ = ray1.bisectrix(ray3)
    def test_intersect_ray_intersect(self):
        circle = ConstructionCircle((10., 10.), 3)
        ray_vert = ConstructionRay((8.5, 10.), angle=HALF_PI)
        cross_points = circle.intersect_ray(ray_vert)
        self.assertEqual(len(cross_points), 2)
        p1, p2 = cross_points
        if p1[1] > p2[1]: p1, p2 = p2, p1
        self.assertTrue(is_close_points(p1, (8.5, 7.4019), abs_tol=1e-4))
        self.assertTrue(is_close_points(p2, (8.5, 12.5981), abs_tol=1e-4))

        ray_hor = ConstructionRay((10, 8.5), angle=0.)
        cross_points = circle.intersect_ray(ray_hor)
        self.assertEqual(len(cross_points), 2)
        p1, p2 = cross_points
        if p1[0] > p2[0]: p1, p2 = p2, p1
        self.assertTrue(is_close_points(p1, (7.4019, 8.5), abs_tol=1e-4))
        self.assertTrue(is_close_points(p2, (12.5981, 8.5), abs_tol=1e-4))

        ray_slope = ConstructionRay((5, 5), (16, 12))
        cross_points = circle.intersect_ray(ray_slope)
        self.assertEqual(len(cross_points), 2)
        p1, p2 = cross_points
        if p1[0] > p2[0]: p1, p2 = p2, p1
        self.assertTrue(is_close_points(p1, (8.64840, 7.3217), abs_tol=1e-4))
        self.assertTrue(is_close_points(p2, (12.9986, 10.0900), abs_tol=1e-4))

        # ray with slope through midpoint
        ray_slope = ConstructionRay((10, 10), angle=HALF_PI / 2)
        cross_points = circle.intersect_ray(ray_slope)
        self.assertEqual(len(cross_points), 2)
        p1, p2 = cross_points
        if p1[0] > p2[0]: p1, p2 = p2, p1
        # print (p1[0], p1[1], p2[0], p2[1])
        self.assertTrue(is_close_points(p1, (7.8787, 7.8787), abs_tol=1e-4))
        self.assertTrue(is_close_points(p2, (12.1213, 12.1213), abs_tol=1e-4))

        # horizontal ray through midpoint
        ray_hor = ConstructionRay((10, 10), angle=0)
        cross_points = circle.intersect_ray(ray_hor)
        self.assertEqual(len(cross_points), 2)
        p1, p2 = cross_points
        if p1[0] > p2[0]: p1, p2 = p2, p1
        # print (p1[0], p1[1], p2[0], p2[1])
        self.assertTrue(is_close_points(p1, (7, 10), abs_tol=1e-5))
        self.assertTrue(is_close_points(p2, (13, 10), abs_tol=1e-5))

        # vertical ray through midpoint
        ray_vert = ConstructionRay((10, 10), angle=HALF_PI)
        cross_points = circle.intersect_ray(ray_vert)
        self.assertEqual(len(cross_points), 2)
        p1, p2 = cross_points
        if p1[1] > p2[1]: p1, p2 = p2, p1
        # print (p1[0], p1[1], p2[0], p2[1])
        self.assertTrue(is_close_points(p1, (10, 7), abs_tol=1e-5))
        self.assertTrue(is_close_points(p2, (10, 13), abs_tol=1e-5))
Exemple #14
0
def center_of_3points_arc(point1: 'Vertex', point2: 'Vertex', point3: 'Vertex') -> Vector:
    """
    Calc center point of 3 point arc. ConstructionCircle is defined by 3 points on the circle: point1, point2 and point3.
    """
    ray1 = ConstructionRay(point1, point2)
    ray2 = ConstructionRay(point1, point3)
    midpoint1 = lerp(point1, point2)
    midpoint2 = lerp(point1, point3)
    center_ray1 = ray1.orthogonal(midpoint1)
    center_ray2 = ray2.orthogonal(midpoint2)
    return center_ray1.intersect(center_ray2)
 def test_ray2d_normal(self):
     ray = ConstructionRay((-10, 3), (17, -7))
     ortho = ray.orthogonal((3, 3))
     point = ray.intersect(ortho)
     assert point.isclose(Vector(1.4318, -1.234), abs_tol=1e-4)
 def test_ray2d_normal_vertical(self):
     ray = ConstructionRay((10, 1), (10, -7))  # vertical line
     ortho = ray.orthogonal((3, 3))
     point = ray.intersect(ortho)
     assert point.isclose(Vector(10, 3))
 def test_ray2d_parallel_vertical(self):
     ray1 = ConstructionRay((10, 1), (10, -7))
     ray2 = ConstructionRay((11, 0), angle=HALF_PI)
     ray3 = ConstructionRay((12, -10), (12, 7))
     ray4 = ConstructionRay((0, 0), (1, 1))
     ray5 = ConstructionRay((0, 0), angle=0)
     with pytest.raises(ParallelRaysError):
         _ = ray1.intersect(ray3)
     assert ray1.is_parallel(ray3) is True
     assert ray1.is_parallel(ray2) is True
     assert ray2.is_parallel(ray2) is True
     assert ray1.is_parallel(ray4) is False
     assert ray2.is_parallel(ray4) is False
     assert ray3.is_parallel(ray4) is False
     assert ray1.is_parallel(ray5) is False
     assert ray2.is_parallel(ray5) is False
     assert ray3.is_parallel(ray5) is False
     # vertical rays can't calc a y-value
     with pytest.raises(ArithmeticError):
         _ = ray1.yof(-1.)
 def test_Ray2D_get_x_y(self):
     ray1 = ConstructionRay((10, 1), (20, 10))
     y = ray1.yof(15)
     assert math.isclose(y, 5.5)
     assert math.isclose(ray1.xof(y), 15.)
 def test_ray2d_normal_horizontal(self):
     ray = ConstructionRay((10, 10), (20, 10))  # horizontal line
     ortho = ray.orthogonal((3, 3))
     point = ray.intersect(ortho)
     assert point.isclose(Vector(3, 10))
Exemple #20
0
 def _get_point_on_dimline(point: 'Vertex',
                           dimray: ConstructionRay) -> Vector:
     """ get the measure target point projection on the dimension line """
     return dimray.intersect(dimray.orthogonal(point))