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
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)
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()
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()
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
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
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()
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
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
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
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
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)
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
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
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()
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)
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)
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
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)
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)
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
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))
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
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))
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))
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)
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
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
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)
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