def mouseMoveEvent(self, event): if self.lastPoint is None: self.lastPoint = event.pos() return delta_px = event.pos() - self.lastPoint lastpoint_real = self.viewState.tfV2P(Point2(self.lastPoint)) newpoint_real = self.viewState.tfV2P(Point2(event.pos())) lx,ly = lastpoint_real nx,ny = newpoint_real delta = nx-lx, ny-ly self.lastPoint = event.pos() needs_update = False if (event.buttons() & MOVE_MOUSE_BUTTON) and self.move_dragging: self.move_dragged = True self.viewState.transform = M.translate(*delta).dot(self.viewState.transform) needs_update = True elif (event.buttons() & QtCore.Qt.MiddleButton): delta = -10 * delta_px.y() self.wheelEvent(QtGui.QWheelEvent(event.pos(),delta, event.buttons(), event.modifiers())) needs_update = True elif not self.move_dragging and not self.mwemu: if self.interactionDelegate is not None: self.interactionDelegate.mouseMoveEvent(event) needs_update = True if needs_update: self.update()
def __update_matrix(self): rot = rotate(self.__theta) if self.side == SIDE.Top: sign = -1 else: sign = 1 self.matrix = translate(self.center.x, self.center.y).dot(rotate(self.__theta))
def render_handle(self, position, color, diagonal=False, filled=False): if diagonal: r = rotate(math.pi/4) else: r = numpy.identity(3) m = self.viewState.glWMatrix.dot(translate(*position).dot(r)) GL.glUniformMatrix3fv(self.mat_loc, 1, True, m.astype(numpy.float32)) GL.glUniform4f(self.col_loc, *color) GL.glDrawArrays(GL.GL_TRIANGLE_FAN if filled else GL.GL_LINE_LOOP, 0, 4)
def render(self, vs): self.vs = vs # Standard alpha-blending. We emit alpha=1 or alpha=0 (no real blending), # but the text rendering needs transparency for font rendering GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA) # transform from center of keypoint to edge-of-text tmove = translate(-self.d1 + 2, -self.d1 - 3).dot(scale(14, -14)) count = len(self.model.kp.keypoints) for n, kp in enumerate(self.model.kp.keypoints): # In unaligned view mode we don't need to show any keypoints that aren't in use if self.model.view_mode == 0 and not kp.use: continue # Generate a number of colors, separated by as far in hue-space as possible color = colorsys.hsv_to_rgb(float(n) / count, 1,0.8) + (1,) # use colors based on current selection selected = n == self.model.kp.selected_idx frame_color = [1,1,1,1] if selected else color text_color = [0,0,0,1] if selected else [1,1,1,1] p = self.get_keypoint_viewport_center(kp) # Coordinates in view-space center_point = vs.glWMatrix.dot(translate(p.x, p.y)) text_point = center_point.dot(tmove) with self.prog, self.handle_vao: GL.glUniformMatrix3fv(self.prog.uniforms.mat, 1, True, center_point.astype(numpy.float32)) GL.glUniform4f(self.prog.uniforms.color, *frame_color) # Render the frame GL.glDrawArrays(GL.GL_LINES, 0, 12) # and the text flag background GL.glDrawArrays(GL.GL_TRIANGLE_STRIP, 12, 4) # Render the text for the flag s = self._parent.view.text_batch.get_string("%d" % (n+1)) self._parent.view.text_batch.submit(s, text_point, text_color)
def get_render_to_mat(self, rect): hscale = rect.width / self.__rect.width vscale = rect.height / self.__rect.height actual_scale = min(hscale, vscale) cx = self.__rect.center cx *= actual_scale return translate(rect.center.x - cx.x, rect.center.y - cx.y).dot(scale(actual_scale))
def fixed_center_dot(viewState, m, view_center=None): if view_center is None: view_center = Point2(viewState.width/2, viewState.height/2) world_center = viewState.tfV2W(view_center) proj_orig_center = projectPoint(viewState.transform, world_center) viewState.transform = viewState.transform.dot(m) proj_new_center = projectPoint(viewState.transform, world_center) dx = proj_new_center[0] - proj_orig_center[0] dy = proj_new_center[1] - proj_orig_center[1] viewState.transform = M.translate(-dx, -dy).dot(viewState.transform)
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 __init__(self, project): BaseViewWidget.__init__(self) self.project = project self.image_view_cache = { } self.pad_renderer = PadRender(self) self.dip_renderer = DIPRender(self) self.smd_renderer = SMDRender(self) self.trace_renderer = TraceRender(self) self.via_renderer = THRenderer(self) self.text_batch = TextBatcher(self.gls.text) self.poly_renderer = CachedPolygonRenderer(self) self.hairline_renderer = HairlineRenderer(self) self.passive_renderer = PassiveRender(self) # Initial view is a normalized 1-1-1 area. # Shift to be 10cm max self.viewState.transform = translate(-0.9, -0.9).dot(scale(1./100000))
def __init__(self, parent, pad_no, rel_center, theta, w, l, th_diam=0, side=None): """ :param parent: Parent :param rel_center: :type rel_center: Point2 :param theta: :param w: :param l: :param r: :return: """ self.parent = parent self.__rel_center = rel_center # Cached translation-only location matrix self.__translate_mat = translate(self.__rel_center.x, self.__rel_center.y) self.__theta = theta self.w = w self.l = l self.side = side # Throughhole diameter, 0 if not T/H self.th_diam = th_diam self.pad_no = pad_no if self.parent is not None: pmat = self.parent.matrix else: pmat = numpy.identity(3, dtype=numpy.float32) self.__pmat = pmat self.center = projectPoint(pmat, self.__rel_center) self.layer = self.parent._side_layer_oracle.stackup.layer_for_side(self.side)
def translate_matrix(self): pt = self.scale_matrix.dot(self.persp_matrix.dot(self.align_handles[self.origin_idx].homol())) pt /= pt[2] return translate(self.translate_x - pt[0], self.translate_y - pt[1])
def _image_transform_info(self): """ Calculate the constraint level and the transform (if possible) :return: constraint_level, transform_matrix """ relevant_keypoints = [i for i in self.keypoints if i.use] # Num keypoints = 0 - can't compute a transform if len(relevant_keypoints) == 0: return CONS_UNCONSTRAINED, numpy.identity(3) # Num keypoints = 1, just do a simple translate elif len(relevant_keypoints) == 1: kp = relevant_keypoints[0] # Pixel in worldspace layer_world = self.__image.p2n(kp.layer) # Just basic translation in worldspace vec = kp.world - layer_world return CONS_TRANSLATION, translate(vec.x, vec.y) # Calculate either translate-rotate, or translate-rotate-scale transforms elif len(relevant_keypoints) in (2,3): # Construct a system of equations to solve the positioning # Basic Ax = b, where x is the non-homologous terms of the translation matrix # 'A' is made from "rows" rows = [] b = [] # Add all of the keypoints as constraints for kp in relevant_keypoints: # normalized image / world coordinates for the keypoint lw = self.__image.p2n(kp.layer) w = kp.world # a b c d e f # rows.append([lw.x, lw.y, 1, 0, 0, 0, ]) rows.append([0, 0, 0, lw.x, lw.y, 1, ]) b.append(w.x) b.append(w.y) # If we only have two keypoints, constrain scale to equal on both axes if len(relevant_keypoints) == 2: rows.append([1, 0, 0, 0, -1, 0 ]) rows.append([0, 1, 0, 1, 0, 0 ]) b.extend((0, 0)) # Try to solve the system of equations a = numpy.vstack(rows) try: x = numpy.linalg.solve(a, b) except numpy.linalg.linalg.LinAlgError: # Cant solve, constructed matrix is singular return CONS_SINGULAR, numpy.identity(3) # Depending on the number of keypoints, we're either constrainted to translate/rotate/equal-scale # or full Orthogonal projection constraint = CONS_ORTHOGONAL if len(relevant_keypoints) == 2: constraint = CONS_ROTATE_SCALE return constraint, numpy.vstack((x.reshape(2, 3), (0,0,1))) elif len(relevant_keypoints) == 4: # Perspective transform # TODO: replace this with a LMS solver for overconstrained cases # plus provide error estimations and visualize src = numpy.ones((4,2), dtype=numpy.float32) dst = numpy.ones((4,2), dtype=numpy.float32) src[:, :2] = [self.__image.p2n(kp.layer) for kp in relevant_keypoints] dst[:, :2] = [kp.world for kp in relevant_keypoints] return CONS_PERSPECTIVE, cv2.getPerspectiveTransform(src, dst) else: # Temporarily refuse to solve overconstrained alignments return CONS_OVERCONSTRAINED, numpy.identity(3)
def __inv_p2p_mat(self): return translate(self.rel_center.x, self.rel_center.y).dot(rotate(self.theta))
def __p2p_mat(self): return rotate(-self.theta).dot(translate(-self.rel_center.x, -self.rel_center.y))
def matrix(self): return translate(self.center.x, self.center.y).dot(rotate(self.theta).dot(cflip(self.side == SIDE.Bottom)))