예제 #1
0
 def test_pllp(self):
     """Test for pllp function."""
     c1 = Coord(-30, 0)
     c2 = Coord(30, 0)
     coord = pllp(c1, 50, 50, c2)
     self.assertAlmostEqual(0, coord.x)
     self.assertAlmostEqual(40, coord.y)
     coord = pllp(c1, 30, 30, c2)
     self.assertAlmostEqual(coord.x, 0)
     self.assertAlmostEqual(coord.y, 0)
     coord = pllp(c1, 90, 30, c2)
     self.assertAlmostEqual(60, coord.x)
     self.assertAlmostEqual(0, coord.y)
예제 #2
0
파일: part.py 프로젝트: s40723245/Pyslvs-UI
def boundary_loop(boundary: Sequence[_Coord],
                  radius: float) -> List[_CoordsPair]:
    """Create boundary edges by pairs of coordinates."""
    boundary_tmp = []
    for i in range(len(boundary)):
        p1 = Coord(*boundary[i])
        p2 = Coord(*boundary[i + 1 if i + 1 < len(boundary) else 0])
        alpha = atan2(p2.y - p1.y, p2.x - p1.x) - radians(90)
        offset_x = radius * cos(alpha)
        offset_y = radius * sin(alpha)
        boundary_tmp.append((
            Coord(p1.x + offset_x, p1.y + offset_y),
            Coord(p2.x + offset_x, p2.y + offset_y),
        ))
    return boundary_tmp
예제 #3
0
 def __is_ok(self) -> None:
     """Check and show the final position."""
     mode = self.tab_widget.currentIndex()
     if mode == 0:
         x = self.plap_p1x_box.value()
         y = self.plap_p1y_box.value()
         c = plap(Coord(x, y), self.plap_distance_box.value(),
                  radians(self.plap_angle_box.value()))
     elif mode == 1:
         x1 = self.pllp_p1x_box.value()
         y1 = self.pllp_p1y_box.value()
         x2 = self.pllp_p2x_box.value()
         y2 = self.pllp_p2y_box.value()
         c = pllp(Coord(x1, y1), self.pllp_distance1_box.value(),
                  self.pllp_distance2_box.value(), Coord(x2, y2),
                  self.pllp_inversed_box.isChecked())
     else:
         raise ValueError("invalid option")
     self.preview_label.setText(f"({c.x}, {c.y})")
     self.__x = c.x
     self.__y = c.y
     ok_button = self.button_box.button(QDialogButtonBox.Ok)
     ok_button.setEnabled(not (isnan(c.x) or isnan(c.y)))
예제 #4
0
 def test_palp(self):
     """Test for palp function."""
     coord = palp(Coord(0, 0), radians(15), 20, Coord(60, 10))
     self.assertAlmostEqual(42.253221, coord.x, 6)
     self.assertAlmostEqual(19.222356, coord.y, 6)
예제 #5
0
 def test_plpp(self):
     """Test for plpp function."""
     coord = plpp(Coord(0, 0), sqrt(5), Coord(0, -3), Coord(3 / 2, 0))
     self.assertAlmostEqual(2, coord.x)
     self.assertAlmostEqual(1, coord.y)
예제 #6
0
 def test_plap(self):
     """Test for plap function."""
     coord = plap(Coord(0, 0), 50 * sqrt(2), radians(45), Coord(50, 0))
     self.assertAlmostEqual(50, coord.x)
     self.assertAlmostEqual(50, coord.y)
예제 #7
0
 def test_ppp(self):
     """Test for ppp function."""
     coord = ppp(Coord(0, 0), Coord(0, 90), Coord(90, 0))
     self.assertAlmostEqual(90, coord.x)
     self.assertAlmostEqual(90, coord.y)
예제 #8
0
 def test_pxy(self):
     """Test for pxy function."""
     coord = pxy(Coord(80, 90), 40, -20)
     self.assertAlmostEqual(120, coord.x)
     self.assertAlmostEqual(70, coord.y)
예제 #9
0
def slvs2_part(vpoints: List[VPoint], radius: float, file_name: str) -> None:
    """Generate a linkage sketch by specified radius."""
    # Translate
    min_x = min(vpoint.cx for vpoint in vpoints)
    min_y = min(vpoint.cy for vpoint in vpoints)
    centers = [(vpoint.cx - min_x, vpoint.cy - min_y) for vpoint in vpoints]
    # Synchronous the point coordinates after using convex hull
    centers_ch = convex_hull(centers)
    _boundary = centers_ch.copy()
    for x, y in centers:
        if (x, y) not in centers_ch:
            centers_ch.append((x, y))
    centers = centers_ch
    del vpoints, min_x, min_y

    # Frame (p1, p2, p3) -> ((p1, p2), (p3, p1), (p3, p2))
    frame: List[_CoordsPair] = [(
        Coord(centers[-2][0], centers[-2][1]),
        Coord(centers[-1][0], centers[-1][1]),
    )]
    for x, y in centers[2:]:
        frame.append((frame[0][0], Coord(x, y)))
        frame.append((frame[0][1], Coord(x, y)))

    # Boundary
    boundary = boundary_loop(_boundary, radius)
    del _boundary

    # Writer object
    writer = SlvsWriter2()
    writer.script_group.pop()
    writer.group_normal(0x3, "boundary")

    # Add "Param"
    def add_param(edges: Sequence[_CoordsPair]) -> None:
        """Add param by pair of coordinates."""
        for edge in edges:
            writer.param_num += 0x10
            for coord in edge:
                writer.param_val(writer.param_num, coord.x)
                writer.param_num += 1
                writer.param_val(writer.param_num, coord.y)
                writer.param_num += 2
            writer.param_shift16()

    def arc_coords(
        index: int,
        _cx: float,
        _cy: float
    ) -> Iterator[_Coord]:
        yield from (
            (_cx, _cy),
            (boundary[index - 1][1].x, boundary[index - 1][1].y),
            (boundary[index][0].x, boundary[index][0].y),
        )

    add_param(frame)
    add_param(boundary)
    # Circles
    for x, y in centers:
        writer.param_num += 0x10
        writer.param_val(writer.param_num, x)
        writer.param_num += 1
        writer.param_val(writer.param_num, y)
        # Shift to 0x40
        writer.param_num += 0x2f
        writer.param_val(writer.param_num, radius / 2)
        writer.param_shift16()
    # Arc
    for i in range(len(boundary)):
        cx, cy = centers[i]
        writer.param_num += 0x10
        for x, y in arc_coords(i, cx, cy):
            writer.param_val(writer.param_num, x)
            writer.param_num += 1
            writer.param_val(writer.param_num, y)
            writer.param_num += 2
        writer.param_shift16()

    # Group 2:
    point_count = len(centers)
    # The number of same points
    point_num: List[List[int]] = [[] for _ in range(point_count)]
    # The number of same lines
    line_num: List[List[int]] = [[] for _ in range(len(frame))]

    def segment_processing(edges: Sequence[_CoordsPair], *,
                           is_frame: bool = True) -> None:
        """Add edges to work plane. (No any constraint.)"""
        # Add "Request"
        for _ in range(len(edges)):
            writer.request_line(writer.request_num)
            writer.request_num += 1

        # Add "Entity"
        p_counter = _by_frame() if is_frame else _by_boundary(len(point_num))
        for index, edge in enumerate(edges):
            writer.entity_line(writer.entity_num)
            for j, coord in enumerate(edge):
                writer.entity_num += 1
                point_num[next(p_counter)].append(writer.entity_num)
                writer.entity_point_2d(writer.entity_num, coord.x, coord.y)
                line_num[index].append(writer.entity_num)
            writer.entity_shift16()

    segment_processing(frame, is_frame=True)
    center_num = [nums[0] for nums in point_num]
    # Add "Constraint"
    # Same point constraint
    for p in point_num:
        for p_ in p[1:]:
            writer.constraint_point(writer.constraint_num, p[0], p_)
            writer.constraint_num += 1
    for i, (n1, n2) in enumerate(line_num):
        p1, p2 = frame[i]
        writer.constraint_distance(writer.constraint_num, n1, n2,
                                   p1.distance(p2))
        writer.constraint_num += 1
    # Add "Constraint" of position
    for i, c in enumerate(frame[0]):
        writer.constraint_grounded(writer.constraint_num, point_num[i][0], c.x, c.y)
        if i == 1:
            writer.script_constraint.pop()
            writer.constraint_num += 1
        else:
            writer.constraint_num += 2

    # Group 3:
    writer.set_group(0x3)

    # The number of same points
    point_num = [[] for _ in range(len(boundary))]
    # The number of same lines
    line_num = [[] for _ in range(len(boundary))]
    segment_processing(boundary)
    # The number of circles
    circles = []

    def add_circle(index: int, _x: float, _y: float) -> None:
        """Add circle"""
        # Add "Request"
        writer.request_circle(writer.request_num)
        writer.request_num += 1
        # Add "Entity"
        writer.entity_circle(writer.entity_num)
        circles.append(writer.entity_num)
        writer.entity_num += 1
        writer.entity_point_2d(writer.entity_num, _x, _y)
        num = writer.entity_num
        # Shift to 0x20
        writer.entity_num += 0x1f
        writer.entity_normal_2d(writer.entity_num, num)
        # Shift to 0x40
        writer.entity_num += 0x20
        writer.entity_distance(writer.entity_num, radius / 2)
        writer.entity_shift16()
        # Add "Constraint" for centers
        writer.constraint_point(writer.constraint_num, num, center_num[index])
        writer.constraint_num += 1
        # Add "Constraint" for diameter
        if index == 0:
            writer.constraint_diameter(writer.constraint_num, circles[-1],
                                       radius)
        else:
            writer.constraint_equal_radius(writer.constraint_num, circles[-1],
                                           circles[0])
        writer.constraint_num += 1

    def add_arc(index: int, _cx: float, _cy: float) -> None:
        """Add arc"""
        # Add "Request"
        writer.request_arc(writer.request_num)
        writer.request_num += 1
        # Add "Entity"
        writer.entity_arc(writer.entity_num)
        circles.append(writer.entity_num)
        p3 = []
        for ax, ay in arc_coords(index, _cx, _cy):
            writer.entity_num += 1
            writer.entity_point_2d(writer.entity_num, ax, ay)
            p3.append(writer.entity_num)
        writer.entity_num += 0x3d
        writer.entity_normal_2d(writer.entity_num, p3[0])
        writer.entity_shift16()
        # Add "Constraint" for three points
        num1 = point_num[index][0]
        num2 = point_num[index][1]
        if num1 % 16 < num2 % 16:
            num1, num2 = num2, num1
        for j, num in enumerate([center_num[index], num1, num2]):
            writer.constraint_point(writer.constraint_num, p3[j], num)
            writer.constraint_num += 1
        # Add "Constraint" for diameter
        if index == 0:
            writer.constraint_diameter(writer.constraint_num, circles[-1],
                                       radius * 2)
        else:
            writer.constraint_equal_radius(writer.constraint_num, circles[-1],
                                           circles[0])
        writer.constraint_num += 1
        # Add "Constraint" for become tangent line
        for j, num in enumerate((num1 - num1 % 16, num2 - num2 % 16)):
            writer.constraint_arc_line_tangent(
                writer.constraint_num,
                circles[-1],
                num,
                reverse=(j == 1)
            )
            writer.constraint_num += 1

    for i, (x, y) in enumerate(centers):
        add_circle(i, x, y)
    circles.clear()
    for i in range(len(boundary)):
        x, y = centers[i]
        add_arc(i, x, y)
    # Write file
    writer.save(file_name)