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 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.__theta = v.angle() self._model.pin_spacing = mag / (self._model.side1_pins - 1) self.v_base = Vec2.fromPolar(self.__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.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.center, Point2(0,0), self.v_base, False) self._model.dim_1_pincenter = v.mag() * 2
def dist_pt_line_seg(pt, s_pt1, s_pt2): """ :param pt: :param seg: :return: """ pt, dist = project_point_line(pt, s_pt1, s_pt2, True, True) return dist
def get_line_query_for_mouse(self, pos: Vec2) -> Tuple[Optional[int], Optional[Vec2]]: for n, (p1, p2) in enumerate(self.model.lines()): p1_v = self.im2V(p1) p2_v = self.im2V(p2) p, d = project_point_line(pos, p1_v, p2_v) if d is not None and d < HANDLE_HALF_SIZE: return n, p return None, None
def get_line_query_for_mouse(self, pos): for n, (p1, p2) in enumerate(self.model.line_iter()): p1_v = self.im2V(p1) p2_v = self.im2V(p2) p, d = project_point_line(pos, p1_v, p2_v) if p is not None and d < HANDLE_HALF_SIZE: return n, p return None, None
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 __update_line_pos(self, h_idx, pos): """ :param h_idx: index of the moved handle :param pos: point it was moved to :return: """ if pos is None: self.align_handles[h_idx] = None return pos = Vec2(pos) # 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.line_iter()[(h_idx + 1) % 4] pt_ahead_2 = None line_behind_2 = self.line_iter()[(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) 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.align_handles[ahead_idx_2] = pt_ahead_2 if pt_behind_2 is not None: self.align_handles[behind_idx_2] = pt_behind_2 self.align_handles[h_idx] = pos else: line_idx = (h_idx - 4) // 2 o_idx = (h_idx & ~1) | (h_idx ^ 1) this_anchor = Vec2(self.align_handles[h_idx]) other_anchor = self.align_handles[o_idx] lines = list(self.line_iter()) 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 = Vec2(this_line[0]) + delta pt_b = Vec2(this_line[1]) + delta else: pt_a = pos pt_b = Vec2(other_anchor) # 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.align_handles[line_idx] = pt_prev self.align_handles[(line_idx + 1) % 4] = pt_next # We can always move an anchor self.align_handles[h_idx] = pos