Пример #1
0
    def keyPressEvent(self, evt):
        keycode = evt.key()

        jog_keys = {
            QtCore.Qt.Key_Left: Vec2(-1, 0),
            QtCore.Qt.Key_Right: Vec2(1, 0),
            QtCore.Qt.Key_Up: Vec2(0, 1),
            QtCore.Qt.Key_Down: Vec2(0, -1)
        }

        if keycode == QtCore.Qt.Key_Escape:
            self.abort_entry()
        elif keycode in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return):
            if self.__point_active:
                self.commit_entry(evt.modifiers() & QtCore.Qt.ShiftModifier)
            else:
                self.__done = DONE_REASON.ACCEPT

        elif keycode in jog_keys:
            self.do_jog(jog_keys[keycode])
        elif keycode == QtCore.Qt.Key_Q:
            self.prev_point()
        elif keycode == QtCore.Qt.Key_W:
            self.next_point()
        elif keycode == QtCore.Qt.Key_E:
            self.make_active()
        elif keycode == QtCore.Qt.Key_R:
            self.next_option()
        else:
            return False

        return True
Пример #2
0
    def __init__(self, view, project, text_renderer):
        self.__text = text_renderer
        self.__project = project
        self.__view = view

        self.__top_side_labels = TextBatch(text_renderer)
        self.__top_side_pads = TextBatch(text_renderer)
        self.__bottom_side_labels = TextBatch(text_renderer)
        self.__bottom_side_pads = TextBatch(text_renderer)

        self.__last_generation = None

        self.__up_vector = Vec2(0, 1)
        self.__ltor_vector = Vec2(1, 0)
Пример #3
0
Файл: dip.py Проект: pcbre/pcbre
    def __init__(self, view, model, cmodel):
        self._model = model
        self._cmodel = cmodel

        self.p1_point = EditablePoint(Point2(0, 0))

        rmat = rotate(self._cmodel.theta)

        dy = -(model.pin_count / 2 - 1) * model.pin_space

        v_aligned = Vec2(0, dy)

        v_delta = project_point(rmat, v_aligned)

        # the pin on the end of the same row as P1
        self.p_bottom_corner = OffsetDefaultPoint(self.p1_point, v_delta)

        # Opposite corner point
        self.p_opposite = WidthProjectedPoint(self)

        points = [self.p1_point, self.p_bottom_corner, self.p_opposite]

        super(DIPEditFlow, self).__init__(view, points, True)

        self.update_matrix()
Пример #4
0
def passive_border_va(va: 'VA_xy', cmp: 'Passive2Component') -> None:
    """
    :type cmp: pcbre.model.passivecomponent.Passive2Component
    :type va: pcbre.accel.vert_array.VA_xy
    :param cmp:
    :return:
    """

    if cmp.body_type == Passive2BodyType.CHIP:
        bx = cmp.body_corner_vec.x
        by = cmp.body_corner_vec.y
        va.add_box(cmp.center.x, cmp.center.y, bx * 2, by * 2, cmp.theta)

    elif cmp.body_type == Passive2BodyType.TH_AXIAL:
        bx = cmp.body_corner_vec.x
        by = cmp.body_corner_vec.y
        va.add_box(cmp.center.x, cmp.center.y, bx * 2, by * 2, cmp.theta)

        vec = Vec2(math.cos(cmp.theta), math.sin(cmp.theta))

        # Add legs
        pa = cmp.pin_d * vec
        pb = cmp.body_corner_vec.x * vec
        va.add_line(pa.x + cmp.center.x, pa.y + cmp.center.y, pb.x + cmp.center.x, pb.y + cmp.center.y)
        va.add_line(-pa.x + cmp.center.x, -pa.y + cmp.center.y, -pb.x + cmp.center.x, -pb.y + cmp.center.y)

    elif cmp.body_type == Passive2BodyType.TH_RADIAL:
        raise NotImplementedError()
    else:
        raise NotImplementedError()
Пример #5
0
    def keyPressEvent(self, evt):
        disabled = not self.active or self.model_overall.view_mode
        if disabled:
            return False

        if evt.key() == QtCore.Qt.Key_Escape:
            self.idx_handle_sel = None

        elif self.idx_handle_sel is not None:

            if evt.key() in (QtCore.Qt.Key_Delete, QtCore.Qt.Key_Backspace) and IDX_IS_ANCHOR(self.idx_handle_sel):

                cmd = cmd_set_handle_position(self.model, self.idx_handle_sel, None)
                self._parent.undoStack.push(cmd)
                #self.model.set_handle(self.idx_handle_sel, None)
                self.idx_handle_sel = None

            # Basic 1-px nudging
            elif evt.key() in (QtCore.Qt.Key_Left, QtCore.Qt.Key_Right, QtCore.Qt.Key_Up, QtCore.Qt.Key_Down):
                nudge = {
                    QtCore.Qt.Key_Left:  (-1,  0),
                    QtCore.Qt.Key_Right: ( 1,  0),
                    QtCore.Qt.Key_Up:    ( 0, -1),
                    QtCore.Qt.Key_Down:  ( 0,  1),
                }[evt.key()]

                current = Vec2(self.im2V(self.model.align_handles[self.idx_handle_sel]))
                viewspace = self.V2im(current + nudge)
                cmd = cmd_set_handle_position(self.model, self.idx_handle_sel, viewspace)
                self._parent.undoStack.push(cmd)
                #self.model.set_handle(self.idx_handle_sel, viewspace)

                self.ghost_handle = None
Пример #6
0
    def updated(self, ep):
        if self.p1_point.is_set:
            if self.p_bottom_corner.is_set:
                v = (self.p_bottom_corner.get() - self.p1_point.get())
                mag = v.mag()
                v = v.norm()
                self._cmodel.theta = v.angle()

                self._model.pin_spacing = mag / (self._model.side1_pins - 1)

            self.v_base = Vec2.from_polar(self._cmodel.theta, 1)
            self.v_vert = Vec2(-self.v_base.y, self.v_base.x).norm()

            p_edge_center = self.v_base * self._model.pin_spacing * (
                self._model.side1_pins - 1) / 2

            if self.p_side_3_1.is_set:
                dv = self.p_side_3_1.get() - self.p1_point.get()

                v, _ = project_point_line(dv, Point2(0, 0), self.v_vert, False)
                self._model.dim_2_pincenter = v.mag()

            self._cmodel.center = self.v_vert * self._model.dim_2_pincenter / 2 + p_edge_center + self.p1_point.get(
            )

            if self.p_side_2_1.is_set:
                v, _ = project_point_line(
                    self.p_side_2_1.get() - self._cmodel.center, Point2(0, 0),
                    self.v_base, False)

                self._model.dim_1_pincenter = v.mag() * 2
Пример #7
0
    def __init__(self, view, model):
        self._model = model

        self.p1_point = EditablePoint(Point2(0, 0))

        self.__theta = 0
        self.__corner = Point2(0, 0)

        rmat = rotate(self.theta)

        dy = -(model.pin_count / 2 - 1) * model.pin_space

        v_aligned = Vec2(0, dy)

        v_delta = projectPoint(rmat, v_aligned)

        # the pin on the end of the same row as P1
        self.p_bottom_corner = OffsetDefaultPoint(self.p1_point, v_delta)

        # Opposite corner point
        self.p_opposite = WidthProjectedPoint(self)

        points = [self.p1_point, self.p_bottom_corner, self.p_opposite]

        super(DIPEditFlow, self).__init__(view, points, True)

        if self.view.viewState.current_layer is None:
            self.side = SIDE.Top

        else:
            self.side = self.view.viewState.current_layer.side

        self.update_matrix()
Пример #8
0
    def mouseMoveEvent(self, event):
        disabled = not self.active or self.model_overall.view_mode
        if disabled:
            return False

        needs_update = False
        idx = self.get_handle_for_mouse(event.pos())

        if self.ghost_handle is not None:
            self.ghost_handle = None

        if self.behave_mode == MODE_NONE:
            if idx is not None:
                self.idx_handle_hover = idx

            else:
                self.idx_handle_hover = None

            if event.modifiers() & ADD_MODIFIER:
                line_idx, pos = self.get_line_query_for_mouse(event.pos())

                if line_idx is not None:
                    self.ghost_handle = pos

        elif self.behave_mode == MODE_DRAGGING:
            w_pos = self.V2im(Vec2(event.pos()))

            cmd = cmd_set_handle_position(self.model, self.idx_handle_sel, w_pos, merge=True)
            self._parent.undoStack.push(cmd)
            #self.model.set_handle(self.idx_handle_sel, w_pos)


        return False
Пример #9
0
    def gen_dim(self, idx, always_above = True):
        """
        Generate rendering data for the dimension-lines
        :param idx:
        :return:
        """
        a = self.im2V(self.model.dim_handles[0 + idx])
        b = self.im2V(self.model.dim_handles[1 + idx])

        d = b-a

        delta = (b-a).norm()

        normal = Point2(rotate(math.pi / 2)[:2,:2].dot(delta))

        if always_above:
            if numpy.cross(Vec2(1,0), normal) > 0:
                normal = -normal

        res = numpy.array([
            a + normal * 8,
            a + normal * 20,
            a + normal * 15,
            b + normal * 15,
            b + normal * 8,
            b + normal * 20,
            ])

        return res
Пример #10
0
    def move(self, cur: Point2) -> None:
        lx, ly = project_point(self.vs.revMatrix, self.last)
        nx, ny = project_point(self.vs.revMatrix, cur)

        self.vs.translate(Vec2(nx - lx, ny - ly))

        self.last = cur
Пример #11
0
    def gen_dim(self, idx: int, always_above: bool = True) -> 'npt.NDArray[numpy.float64]':
        """
        Generate rendering data for the dimension-lines
        :param idx:
        :return:
        """
        a = self.im2V(self.model.dim_handles[0 + idx])
        b = self.im2V(self.model.dim_handles[1 + idx])

        d = b - a

        delta = (b - a).norm()

        normal = Vec2.from_mat(rotate(math.pi / 2)[:2, :2].dot(delta))

        if always_above:
            if numpy.cross(Vec2(1, 0), normal) > 0:
                normal = -normal

        res = numpy.array([
            a + normal * 8,
            a + normal * 20,
            a + normal * 15,
            b + normal * 15,
            b + normal * 8,
            b + normal * 20,
        ], dtype=numpy.float64)

        return res
Пример #12
0
    def __init__(self,
            view: "BoardViewWidget",
            project: "Project",
            text_renderer: "TextRender") -> None:

        self.__text = text_renderer
        self.__project = project
        self.__view = view

        self.__top_side_labels = TextBatch(text_renderer)
        self.__top_side_pads = TextBatch(text_renderer)
        self.__bottom_side_labels = TextBatch(text_renderer)
        self.__bottom_side_pads = TextBatch(text_renderer)

        self.__last_generation : Optional[int] = None

        self.__up_vector = Vec2(0, 1)
        self.__ltor_vector = Vec2(1, 0)
Пример #13
0
    def __init__(self, is_new: bool = True) -> None:
        # World-space coordinates of the keypoint
        self.world = Vec2(0, 0)

        # Current align-layer-space coordinates of the keypoint (in pixels, not in normalized image coords)
        self.layer = Vec2(0, 0)

        # Keypoint created for this layer or existing?
        # if existing, keypoint should not be moved in worldspace or deleted
        # since the alignment solution for other layers may rely on it
        # AlignKeypoint.is_new may also be true if it existed before, but no other layer
        # ever used it for alignment (since then it may be safely moved or deleted)
        self.is_new = is_new

        # Use this keypoint for the alignment solution
        self.use = False

        self._orig_kp: Optional[KeyPoint] = None
Пример #14
0
    def __update(self):
        if self.__pins_cache:
            return

        w = self.dim_1_body
        h = self.dim_2_body

        pads = []

        d_2_pc = self.dim_2_pincenter / 2
        d_1_pc = self.dim_1_pincenter / 2
        overall_pin_no = 0

        for i, side_pin_count in enumerate(self.side_pins):
            offset = (side_pin_count - 1) / 2 * self.pin_spacing
            pad_theta = math.pi / 2 * i
            if i == 0:
                start = Point2(-d_2_pc, offset)
                step = Vec2(0, -self.pin_spacing)
            elif i == 1:
                start = Point2(-offset, -d_1_pc)
                step = Vec2(self.pin_spacing, 0)
            elif i == 2:
                start = Point2(d_2_pc, -offset)
                step = Vec2(0, self.pin_spacing)
            elif i == 3:
                start = Point2(offset, d_1_pc)
                step = Vec2(-self.pin_spacing, 0)

            for pin_no in range(side_pin_count):
                pin_center = start + step * pin_no
                pads.append(
                    Pad(self,
                        "%s" % (overall_pin_no + 1),
                        pin_center,
                        pad_theta,
                        self.pin_spacing / 2,
                        self.pin_contact_length,
                        side=self.side))
                overall_pin_no += 1

        self.__pins_cache = pads
Пример #15
0
    def __init__(self, image):
        GenModel.__init__(self)

        self.__image = image
        # 4 corner handles, 2 (potential) anchor handles per line
        ini_shape = image.decoded_image.shape
        max_dim = float(max(ini_shape))
        x = ini_shape[1] / max_dim
        y = ini_shape[0] / max_dim

        self.__align_handles = [Vec2(-x, -y), Vec2(x, -y), Vec2(x, y), Vec2(-x, y)] + [None] * 8

        self.__dim_handles = [self.__align_handles[0],
                              self.__align_handles[1],
                              self.align_handles[1],
                              self.align_handles[2]]

        self.__placeholder_dim_values = [100, 100]
        self.__dim_values = [None, None]
        self.update_matricies()
Пример #16
0
    def update_layer(self) -> None:
        idx = self.kpts_sel.currentIndex()
        vx = self.px.getValue()
        vy = self.py.getValue()
        if vx is None or vy is None:
            # TODO - flash bad box?
            return

        p = Vec2(vx, vy)
        cmd = cmd_set_keypoint_px(self.model, idx, p)
        self._parent.undoStack.push(cmd)
Пример #17
0
    def __init__(self, view, points, can_shortcut=False):
        self.view = view
        self.__points = points
        self.__current_point_index = 0
        self.__point_active = False
        self.is_initial_active = True
        self.simple_entry = True
        self.can_shortcut = can_shortcut

        self.__done = DONE_REASON.NOT_DONE

        self.__grab_delta = Vec2(0, 0)
Пример #18
0
    def deserialize(project: 'Project', msg: ser.Component.Reader) -> Component:
        t = msg.smd4
        cmp = SMD4Component(
                project,
                Vec2(0,0), 0,  SIDE.Top,   # Placeholder values
                project,
                t.side1Pins, t.side2Pins, t.side3Pins, t.side4Pins,
                t.dim1Body, t.dim1PinEdge, t.dim2Body, t.dim2PinEdge,
                t.pinContactLength, t.pinContactWidth, t.pinSpacing)

        Component.deserializeTo(project, msg.common, cmp)
        return cmp
Пример #19
0
def pt_inside_pad(pad, pt):
    """

    :param pt:
    :return:
    """
    point_padspace = pad.world_to_pad(pt)
    delta = Vec2(point_padspace)

    if pad.w == pad.l:
        return delta.mag() < pad.l / 2
    else:
        return pt_inside_trace(pad.trace_repr, pt)
Пример #20
0
    def V2im(self, pt):
        """
        Translate viewport coordinates to image coordinates
        :param pt:
        :return:
        """
        world = self.viewState.tfV2W(pt)

        if self.model_overall.view_mode:
            inv = numpy.linalg.inv(self.model.image_matrix)
            return projectPoint(inv, world)
        else:
            return Vec2(world)
Пример #21
0
    def __init__(self, image: 'ImageLayer'):
        self.__image = image
        # 4 corner handles, 2 (potential) anchor handles per line
        ini_shape = image.decoded_image.shape
        max_dim = float(max(ini_shape))
        x = ini_shape[1] / max_dim
        y = ini_shape[0] / max_dim

        # print("Initial shape:", x, y)

        # Expressed in a way that mypy static type checking likes
        self.__corner_handles: CornerHandleType = (
            Vec2(-x, -y), Vec2(x, -y), Vec2(x, y), Vec2(-x, y),
        )
        self.__line_handles: LineHandleType = (None, None, None, None, None, None, None, None)

        self.__dim_handles = (self.__corner_handles[0],
                              self.__corner_handles[1],
                              self.__corner_handles[1],
                              self.__corner_handles[2])

        self.__dims_locked = True

        self.__placeholder_dim_values: List[float] = [100, 100]
        self.__dim_values: List[Optional[float]] = [None, None]

        self.update_matricies()

        self.translate_x : float = 0
        self.translate_y : float = 0
        self.origin_idx : int = 0

        self.persp_matrix = numpy.identity(3)
        self.scale_matrix = numpy.identity(3)
        self.rotate_theta = 0.0
        self.flip_x = False
        self.flip_y = False
Пример #22
0
    def update_matrix(self):

        rot = rotate(self._cmodel.theta)

        center_to_corner = Vec2(
            0,
            self._model.pin_space * (self._model.pin_count - 1) / 2)

        center_to_corner_w = project_point(rot, center_to_corner)

        self._cmodel.center = self.p1_point.get() - center_to_corner_w

        self.matrix = translate(self._cmodel.center.x,
                                self._cmodel.center.y).dot(
                                    rotate(self._cmodel.theta))
Пример #23
0
 def commit_entry(self, shift_pressed):
     if self.simple_entry and not shift_pressed:
         self.__done = DONE_REASON.ACCEPT
         self.__point_active = False
     else:
         self.simple_entry = False
         if self.__point_active:
             self.__point_active = False
             self.next_point()
             if not self.current_point.is_set:
                 if self.is_initial_active:
                     self.__grab_delta = Vec2(0, 0)
                     self.make_active()
             else:
                 self.is_initial_active = False
Пример #24
0
Файл: dip.py Проект: pcbre/pcbre
    def update_matrix(self):

        rot = rotate(self._cmodel.theta)

        sign = self.get_cur_sign()

        center_to_corner = Vec2(
            sign * self._model.pin_width / 2,
            self._model.pin_space * (self._model.pin_count / 2 - 1) / 2)

        center_to_corner_w = project_point(rot, center_to_corner)

        self._cmodel.center = self.p1_point.get() - center_to_corner_w

        self.matrix = translate(self._cmodel.center.x,
                                self._cmodel.center.y).dot(
                                    rotate(self._cmodel.theta))
Пример #25
0
    def update_matrix(self):

        rot = rotate(self.theta)

        if self.side == SIDE.Top:
            sign = -1
        else:
            sign = 1

        center_to_corner = Vec2(
            sign * self._model.pin_width / 2,
            self._model.pin_space * (self._model.pin_count / 2 - 1) / 2)

        center_to_corner_w = projectPoint(rot, center_to_corner)

        self.center = self.p1_point.get() - center_to_corner_w

        self.matrix = translate(self.center.x,
                                self.center.y).dot(rotate(self.theta))
Пример #26
0
    def __build_trace(self) -> None:
        # Update trace VBO
        self.working_array["vertex"][0] = (0, 0)
        self.working_array["ptid"][0] = 0
        self.working_array["vertex"][1] = (0, 0)
        self.working_array["ptid"][1] = 1

        end = Vec2(1, 0)
        for i in range(0, NUM_ENDCAP_SEGMENTS):
            theta = math.pi * i / (NUM_ENDCAP_SEGMENTS - 1) + math.pi / 2
            m = rotate(theta).dot(end.homol())
            self.working_array["vertex"][2 + i] = m[:2]
            self.working_array["ptid"][2 + i] = 0
            self.working_array["vertex"][2 + i + NUM_ENDCAP_SEGMENTS] = -m[:2]
            self.working_array["ptid"][2 + i + NUM_ENDCAP_SEGMENTS] = 1

        # Force data copy
        self.trace_vbo.bind()
        self.trace_vbo.set_array(self.working_array)
Пример #27
0
    def __init__(self, view: 'BoardViewWidget',
                 submit: 'Callable[[Any], None]', project: 'Project',
                 toolsettings: 'TraceToolSettings') -> None:
        """

        :type view: pcbre.ui.boardviewwidget.BoardViewWidget
        """
        super(TraceToolController, self).__init__()

        self.view = view
        self.submit = submit
        self.project = project

        self.toolsettings = toolsettings

        self.cur_pt = Vec2(0, 0)
        self.last_pt = None
        self.last_layer = None

        self.overlay = TraceToolOverlay(self)

        self.routing_mode = RoutingMode.STRAIGHT
        self.routing_dir = False
Пример #28
0
    def get_corner_points(self) -> List[Vec2]:
        # Normalized_dims
        max_dim = float(max(self.__cached_decode.shape))
        x = self.__cached_decode.shape[1]/max_dim
        y = self.__cached_decode.shape[0]/max_dim

        corners = (
                (-1, -1),
                (-1, 1),
                (1, 1),
                (1, -1))

        # Rectangle in pixel space
        corners_pixspace = [
                Vec2(mx * x, my * y) for mx, my in corners
                ]

        # Possibly non-rectangular corner points
        corners_norm = [
                project_point(self.transform_matrix, p) for p in corners_pixspace
                ]

        return corners_norm
Пример #29
0
    def __update_line_pos(self, h_idx: int, _pos: Optional[Vec2]) -> None:
        """
        :param h_idx: index of the moved handle
        :param pos: point it was moved to
        :return:
        """
        if _pos is None:
            self.move_handle(h_idx, None)
            return

        pos = _pos.dup()

        # If we're moving an endpoint
        if h_idx < 4:
            anchors_ahead = self.get_anchors(h_idx)
            anchors_prev = self.get_anchors((h_idx - 1) % 4)

            ahead_idx_2 = (h_idx + 1) % 4
            line_ahead_2 = self.lines()[(h_idx + 1) % 4]
            pt_ahead_2 = None

            line_behind_2 = self.lines()[(h_idx - 2) % 4]
            behind_idx_2 = (h_idx - 1) % 4
            pt_behind_2 = None

            if len(anchors_ahead) == 2 and len(anchors_prev) == 2:
                # Our lines are anchored on both sides by double-anchors, so we can't move at all
                return

            # If the ahead of prev line constrain us, then project the point to the line for motion
            elif len(anchors_ahead) == 2:
                pos, _ = project_point_line(pos, anchors_ahead[0], anchors_ahead[1], False)
            elif len(anchors_prev) == 2:
                pos, _ = project_point_line(pos, anchors_prev[0], anchors_prev[1], False)

            assert pos is not None

            if len(anchors_ahead) == 1:
                itype, pt_ahead_2 = line_intersect(pos, anchors_ahead[0], line_ahead_2[0], line_ahead_2[1])
                if itype != Intersect.NORMAL:
                    return

            if len(anchors_prev) == 1:
                itype, pt_behind_2 = line_intersect(pos, anchors_prev[0], line_behind_2[0], line_behind_2[1])
                if itype != Intersect.NORMAL:
                    return

            if pt_ahead_2 is not None:
                self.move_handle(ahead_idx_2, pt_ahead_2)

            if pt_behind_2 is not None:
                self.move_handle(behind_idx_2, pt_behind_2)

            self.move_handle(h_idx, pos)

        else:
            line_idx = (h_idx - 4) // 2
            o_idx = (h_idx & ~1) | (h_idx ^ 1)

            this_anchor = self.align_handles[h_idx].dup()
            other_anchor = self.align_handles[o_idx]

            lines = list(self.lines())

            this_line = lines[line_idx]
            prev_line = lines[(line_idx - 1) % 4]
            next_line = lines[(line_idx + 1) % 4]

            if other_anchor is None:
                if this_anchor is None:
                    delta = Vec2(0, 0)
                else:
                    # One anchor, move the whole line by pos - this_anchor
                    delta = pos - this_anchor
                pt_a = this_line[0].dup() + delta
                pt_b = this_line[1].dup() + delta

            else:
                pt_a = pos
                pt_b = other_anchor.dup()

            # Recalculate the endpoints
            intersect_cond, pt_prev = line_intersect(pt_a, pt_b, prev_line[0], prev_line[1])

            if intersect_cond != Intersect.NORMAL:
                return

            intersect_cond, pt_next = line_intersect(pt_a, pt_b, next_line[0], next_line[1])

            if intersect_cond != Intersect.NORMAL:
                return

            self.move_handle(line_idx, pt_prev)
            self.move_handle((line_idx + 1) % 4, pt_next)

            # We can always move an anchor
            self.move_handle(h_idx, pos)
Пример #30
0
    def save(self, project: 'Project') -> None:
        align = RectAlignment(self.__corner_handles + self.__line_handles, self.__dim_handles, self.__active_dims(), self.dims_locked,
                              Vec2(self.translate_x, self.translate_y), self.origin_idx, self.flip_x, self.flip_y)
        self.__image.set_alignment(align)

        self.__image.transform_matrix = self.image_matrix