def fixedPositonBySignet(srcImg): h, w = srcImg.shape[:2] img = cv2.cvtColor(srcImg, cv2.COLOR_RGB2HSV) img = cv2.inRange(img, np.array((90, 60, 50), dtype=np.uint8), np.array((140, 255, 255), dtype=np.uint8)) contours0, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours0: if len(cnt) < 5: continue ellipse = cv2.fitEllipse(cnt) center, r, ang = ellipse # 角度精确读不足,使用直线检测来确定偏转角度 chileIm = cv2.getRectSubPix(srcImg, (400, 100), center) new_img = cv2.cvtColor(chileIm, cv2.COLOR_RGB2GRAY) new_img = cv2.GaussianBlur(new_img, (3, 3), 0) edges = cv2.Canny(new_img, 50, 150, apertureSize=3) lines = cv2.HoughLines(edges, 1, np.pi / 180, 200) if lines is not None: for line in lines[0]: rho = line[0] # 第一个元素是距离rho theta = line[1] # 第二个元素是角度theta if (theta > (np.pi / 4.)) or (theta < (3.*np.pi / 4.0)): # 该直线与第一列的交点 pt1 = (0, int(rho / np.sin(theta))) # 该直线与最后一列的交点 pt2 = (chileIm.shape[1], int((rho - chileIm.shape[1] * np.cos(theta)) / np.sin(theta))) M = (pt2[1] - pt1[1]) * 1.0 / (pt2[0] - pt1[0]) pi_angle = math.atan(M) ang = pi_angle * 180 / np.pi break else : ang = ang - 270 if r[0] < 30 or r[1] < 50 or center[1] > h / 2: continue rate = r[1] / 175.8019256591797 return center, rate, ang
def _get_alpha(self): if abs(self.dec) + self.radius > 89.9: return 180 return math.degrees( abs( math.atan( math.sin(math.radians(self.radius)) / np.sqrt( abs( math.cos(math.radians(self.dec - self.radius)) * math.cos(math.radians(self.dec + self.radius)))))))
def get_alpha(radius, dec): if abs(dec) + radius > 89.9: return 180 return math.degrees( abs( math.atan( math.sin(math.radians(radius)) / np.sqrt( abs( math.cos(math.radians(dec - radius)) * math.cos(math.radians(dec + radius)))))))
def draw_line(self, pos): if self.viewer._ocr and self.x_clicked or self.y_clicked: img_line = cv.line(self.image.copy(), (self.x_clicked, self.y_clicked), (pos.x(), pos.y()), (0, 0, 0), 2) image_height, image_width, image_depth = img_line.shape QIm = cv.cvtColor(img_line, cv.COLOR_BGR2RGB) QIm = QImage(QIm.data, image_width, image_height, image_width * image_depth, QImage.Format_RGB888) self.viewer.setPhoto(QPixmap.fromImage(QIm)) # 终止画线 if self.x_released or self.y_released: self.choosePoints = [] # 初始化存储点组 inf = float("inf") if self.x_released or self.y_released: if (self.x_released - self.x_clicked) == 0: slope = inf else: slope = (self.y_released - self.y_clicked) / ( self.x_released - self.x_clicked) siteLenth = 0.5 * math.sqrt( square(self.y_released - self.y_clicked) + square(self.x_released - self.x_clicked)) mySiteLenth = 2 * siteLenth self.siteLenth = ("%.2f" % mySiteLenth) self.editSiteLenth.setText(self.siteLenth) radian = math.atan(slope) self.siteSlope = ("%.2f" % radian) self.editSiteSlope.setText(self.siteSlope) x_bas = math.ceil(math.fabs(0.5 * siteLenth * math.sin(radian))) y_bas = math.ceil(math.fabs(0.5 * siteLenth * math.cos(radian))) if slope <= 0: self.choosePoints.append([(self.x_clicked - x_bas), (self.y_clicked - y_bas)]) self.choosePoints.append([(self.x_clicked + x_bas), (self.y_clicked + y_bas)]) self.choosePoints.append([(self.x_released + x_bas), (self.y_released + y_bas)]) self.choosePoints.append([(self.x_released - x_bas), (self.y_released - y_bas)]) elif slope > 0: self.choosePoints.append([(self.x_clicked + x_bas), (self.y_clicked - y_bas)]) self.choosePoints.append([(self.x_clicked - x_bas), (self.y_clicked + y_bas)]) self.choosePoints.append([(self.x_released - x_bas), (self.y_released + y_bas)]) self.choosePoints.append([(self.x_released + x_bas), (self.y_released - y_bas)]) self.viewer._ocr = False
def XYZ2BL(x, y, z): blh = zeros(2) t = math.sqrt(x * x + y * y) eps = 1.0E-10 if math.fabs(t) < eps: if z > 0: blh[0] = 90.0 blh[1] = 0.0 elif z < 0: blh[0] = -90 blh[1] = 0.0 else: blh[0] = math.atan(z / t) * 180.0 / math.pi # -90 to 90 # 0-360 blh[1] = math.atan2(y, x) * 180.0 / math.pi if blh[1] < 0.0: blh[1] = blh[1] + 360.0 return blh
def fixedPositon(img): corners = findCorners(img) center = (sum(c[0] for c in corners) / 4, sum(c[1] for c in corners) / 4) p1 = np.float32((corners[0][0] + corners[3][0], corners[0][1] + corners[3][1])) p2 = np.float32((corners[1][0] + corners[2][0], corners[1][1] + corners[2][1])) p3 = np.float32((corners[0][0] + corners[1][0], corners[0][1] + corners[1][1])) p4 = np.float32((corners[2][0] + corners[3][0], corners[2][1] + corners[3][1])) width = math.sqrt((p2[0] - p1[0]) * (p2[0] - p1[0]) + (p2[1] - p1[1]) * (p2[1] - p1[1])) / 2 height = math.sqrt((p3[0] - p4[0]) * (p3[0] - p4[0]) + (p3[1] - p4[1]) * (p3[1] - p4[1])) / 2 # print corners # print signetCenter cv2.polylines(img, [np.array(corners, np.int32)], True, (0, 0, 0)) wRate = width / 1195 # (560, 1196) hRate = height / 560 # (560, 1196) h, w = img.shape[:2] M = ((corners[1][1] + corners[2][1]) - (corners[0][1] + corners[3][1])) / ((corners[1][0] + corners[2][0]) - (corners[0][0] + corners[3][0])) pi_angle = math.atan(M) ang = pi_angle * 180 / np.pi return center, wRate, hRate, ang raise Exception(_("无法定位发票"))
def odleglosc((x1,y1),(x2,y2)): dxKw = pow((x1-x2), 2) dyKw = pow((y1-y2), 2) return sqrt( dxKw + dyKw ) def ustalAlfa((x0,y0), (a,b)): dy = -(b-y0) dx = (a-x0) if dx == 0: if b > y0: alfa = 270 else: alfa = 90 else: alfa = math.atan( float(dy) / dx ) if a < x0: alfa += math.pi if alfa<0: alfa += 2*math.pi ''' if(dx!=0): print 'dy',dy,'dx',dx, 'dy/dx', float(dy)/dx alfa /= math.pi alfa *= 180 print 'alfa=',alfa ''' return alfa
def Evolvent(self): '''Расчет эвольвенты зуба ''' #Расчет эвольветы зуба # Читаем данные из полей формы # z = Количество зубьев z = self.doubleSpinBox_Z.value() # m = Модуль зуба m = self.doubleSpinBox_m.value() # a = Угол главного профиля a = self.doubleSpinBox_a.value() #b = Угол наклона зубьев b = self.doubleSpinBox_b.value() #ha = Коэффициент высоты головки ha = self.doubleSpinBox_ha.value() #pf = К-т радиуса кривизны переходной кривой pf = self.doubleSpinBox_pf.value() #c = Коэффициент радиального зазора c = self.doubleSpinBox_c.value() #x = К-т смещения исходного контура x = self.doubleSpinBox_x.value() #y =Коэффициент уравнительного смещения y = self.doubleSpinBox_y.value() # n= Количество точек (точность построения) #n=int(self.doubleSpinBox_n.value()) n=100 # заполня переменные # Делительный диаметр d = z * m # Высота зуба h= h = 2.25 * m # Высота головки ha = hav = m # Высота ножки hf= hf = 1.25 * m #Диаметр вершин зубьев #da = d + (2 * m)*(ha+x+y) da = d + 2 * (ha + x - y) * m #Диаметр впадин (справочно) #df = d -(2 * hf) df = d -2 * (ha + c - x) * m #Окружной шаг зубьев или Шаг зацепления по дуге делительной окружности: Pt или p pt = math.pi * m #Окружная толщина зуба или Толщина зуба по дуге делительной окружности: St или S #Суммарный коэффициент смещений: XΣ X = 0.60 + 0.12 # St = 0.5 * pf # St = 0.5 * pt St = 0.5 * pt + 2 * x * m * math.tan(math.radians(a)) #inv a inva=math.tan(math.radians(a))-math.radians(a) #Угол зацепления invαw invaw= (2 * X - math.tan(math.radians(a))) / (10+26) + inva #Угол профиля at = math.ceil(math.degrees(math.atan(math.tan(math.radians(a)) /math.cos( math.radians(b))))) # Диаметр основной окружности db = d * math.cos(math.radians(at)) #Диаметр начала выкружки зуба D = 2 * m * ( ( z/( 2 * math.cos(math.radians(b)) )-(1-x)) ** 2 + ((1-x)/math.tan(math.radians(at)))**2)**0.5 #Промежуточные данные yi = math.pi/2-math.radians(at) hy = yi/(n-1) x0 = math.pi/(4*math.cos(math.radians(b)) )+pf*math.cos(math.radians(at))+math.tan(math.radians(at)) y0 = 1-pf*math.sin(math.radians(at))-x C = (math.pi/2+2*x*math.tan(math.radians(a)) )/z+math.tan(math.radians(at))-math.radians(at) #Расчетный шаг точек эвольвенты hdy = (da-D)/(n-1) dyi = da fi = 2*math.cos(math.radians(b))/z*(x0+y0*math.tan(yi)) #Заполняем текстовые поля в форме # Делительный диаметр # self.lineEdit_d.setText(str(d)) # Высота зуба h= # self.lineEdit_h.setText(str(h)) # Высота головки ha = # self.lineEdit_ha.setText(str(hav)) # Высота ножки hf= # self.lineEdit_hf.setText(str(hf)) # Диаметр вершин зубьев # self.lineEdit_da.setText(str(da)) # Диаметр впадин (справочно) # self.lineEdit_df.setText(str(df)) # Окружной шаг зубьев Pt= # self.lineEdit_Pt.setText(str(math.ceil(pt))) # Окружная толщина зуба St= # self.lineEdit_St.setText(str(math.ceil(St))) # Угол профиля # self.lineEdit_at.setText(str(at)) # Диаметр основной окружности # self.lineEdit_db.setText(str(math.ceil(db))) # Создаем списки List_dyi=[] List_Di=[] List_Yei=[] List_Xei=[] List_Minus_Xei=[] List_Xdai=[] List_Ydai=[] List_yi=[] List_Ai=[] List_Bi=[] List_fi=[] List_Ypki=[] List_Xpki=[] List_Minus_Xpki=[] # Заполняем нуливой (первый )индекс списка значениями List_dyi.append(dyi) List_Di.append( math.acos( db/ List_dyi[0] ) - math.tan( math.acos( db / List_dyi[0] ) ) + C ) List_Yei.append(dyi / 2*math.cos( List_Di[0])) List_Xei.append(List_Yei[0]*math.tan(List_Di[0])) List_Minus_Xei.append(-List_Xei[0]) List_Xdai.append(-List_Xei[0]) List_Ydai.append(((da/2)**2-List_Xdai[0]**2)**0.5) hda=(List_Xei[0]-List_Minus_Xei[0])/(n-1) # Заполняем первый (второй по счету )индекс списка значениями List_dyi.append(dyi-hdy) List_Di.append( math.acos(db/List_dyi[1])-math.tan(math.acos(db/List_dyi[1]))+C) List_Yei.append( List_dyi[1]/2*math.cos(List_Di[1])) List_Xei.append( List_Yei[1]* math.tan(List_Di[1])) List_Minus_Xei.append(-List_Xei[1]) List_Xdai.append(List_Xdai[0]+hda) List_Ydai.append(((da/2)**2-List_Xdai[1]**2)**0.5) Xdai=List_Xdai[1] dyi=dyi-hdy # Начинаем заполнять списки в цикле i=0 while i < n-2: i=i+1 dyi=dyi-hdy List_Di.append(math.acos(db/dyi)-math.tan(math.acos(db/dyi))+C) Di=math.acos(db/dyi)-math.tan(math.acos(db/dyi))+C Yei=dyi/2*math.cos(Di) Xei=Yei*math.tan(Di) List_dyi.append(dyi) List_Yei.append(dyi/2*math.cos(Di)) List_Xei.append(Yei*math.tan(Di)) List_Minus_Xei.append(-Xei) Xdai=Xdai+hda List_Xdai.append(Xdai) List_Ydai.append(((da/2)**2-Xdai**2)**0.5) #Заполняем последний индекс списка List_dyi[n-1]=D # Заполняем нуливой (первый )индекс списка значениями List_yi.append(yi) List_Ai.append(z/(2*math.cos(math.radians(b)))-y0-pf*math.cos(List_yi[0]) ) List_Bi.append(y0*math.tan(List_yi[0])+pf*math.sin(List_yi[0])) List_fi.append(fi) List_Ypki.append((List_Ai[0] * math.cos(fi)+List_Bi[0] * math.sin(fi)) * m) List_Xpki.append((List_Ai[0] * math.sin(fi)-List_Bi[0] * math.cos(fi)) * m) List_Minus_Xpki.append(-List_Xpki[0]) # Начинаем заполнять списки в цикле i=0 while i < n-2: i=i+1 yi=yi-hy List_yi.append(yi) Ai = z / (2 * math.cos(math.radians(b)))-y0-pf*math.cos(yi) List_Ai.append( z / (2 * math.cos(math.radians(b)))-y0-pf*math.cos(yi)) Bi =y0*math.tan(yi)+pf*math.sin(yi) List_Bi.append(y0*math.tan(yi)+pf*math.sin(yi)) fi = 2*math.cos(math.radians(b))/z*(x0+y0*math.tan(yi)) List_fi.append(2*math.cos(math.radians(b))/z*(x0+y0*math.tan(yi))) List_Ypki.append((Ai*math.cos(fi)+Bi*math.sin(fi))*m) Ypki=(Ai*math.cos(fi)+Bi*math.sin(fi))*m Xpki=(Ai*math.sin(fi)-Bi*math.cos(fi))*m List_Xpki.append((Ai*math.sin(fi)-Bi*math.cos(fi))*m) List_Minus_Xpki.append(-Xpki) #Заполняем последний индекс списка List_yi.append(yi-yi) List_Ai.append(z/(2*math.cos(math.radians(b)))-y0-pf*math.cos(List_yi[n-1]) ) List_Bi.append(y0*math.tan(List_yi[n-1])+pf*math.sin(List_yi[n-1])) List_fi.append(2*math.cos(math.radians(b))/z*(x0+y0*math.tan(List_yi[n-1]))) List_Ypki.append((List_Ai[n-1] * math.cos(fi)+List_Bi[n-1] * math.sin(List_fi[n-1])) * m) List_Xpki.append((List_Ai[n-1] * math.sin(fi)-List_Bi[n-1] * math.cos(List_fi[n-1])) * m) List_Minus_Xpki.append(-List_Xpki[n-1]) # self.WiPfileZub(List_Yei,List_Xei,List_Minus_Xei,List_Ypki,List_Xpki,List_Minus_Xpki,List_Ydai,List_Xdai) self.GragEvolvent(List_Minus_Xei+List_Minus_Xpki,List_Yei+List_Ypki,n) DFreza = self.lineEditDFreza.text() VisotaYAxis = self.lineEditVisota.text() Diametr = self.lineEditDiametr.text() if DFreza and VisotaYAxis: E30 = (int(DFreza)/2) +float(VisotaYAxis) else: E30 = 0 angi_B=0 if ValkosZub: angie_A:float = 90# угол А треугольника по высоте детали angie_B:float = float(b) #угол B треугольника по высоте детали ( угол наклона зуба по чертежу) angie_Y:float = 180 - (angie_A + angie_B) # трерий уго треугольника по высоте детали side_c:float = float(E30)# высота детали первая сторона треугольника side_a = side_c * math.sin(math.radians(angie_A)) / math.sin(math.radians(angie_Y))# вторая сторона треугольника side_b = side_c * math.sin(math.radians(angie_B)) / math.sin(math.radians(angie_Y))# третия сторона треугольника ( ось Х) sid_a:float = float(Diametr)/2 # радиус детали первая и вторая тророны треугольника по торцу # sid_a:float = float(self.lineEdit_da.text())/2 # радиус детали первая и вторая тророны треугольника по торцу sid_c:float = sid_a if sid_c < 10 : sid_a:float = 10 sid_c:float = 10 angi_B = float('{:.3f}'.format(math.degrees(math.acos((sid_a**2+sid_c**2-side_b**2)/(2*sid_a*sid_c))))) QMessageBox.about (self, "Ошибка " , "Диаметр шестерни задан меньше 20 мм. \n Введите риальный диаметр шестерни " ) else: angi_B = float('{:.3f}'.format(math.degrees(math.acos((sid_a**2+sid_c**2-side_b**2)/(2*sid_a*sid_c)))))# результат угол поворота стола self.label_da.setText(str(round(da,1))) self.label_d.setText(str(round(d,1))) self.label_at.setText(str(round(at,1))) self.label_db.setText(str(round(db,1))) self.label_df.setText(str(round(df,1))) self.label_St.setText(str(round(St,1))) self.label_Pt.setText(str(round(pt,1))) self.label_hf.setText(str(round(hf,1))) self.label_ha.setText(str(round(ha,1))) self.label_h.setText(str(round(h,1))) self.lineEditDiametr.setText(str(da)) self.lineEditUgol.setText(str(angi_B))
def get_line_data(pixels, x1, y1, x2, y2, line_w=2, the_z=0, the_c=0, the_t=0): """ Grabs pixel data covering the specified line, and rotates it horizontally so that x1,y1 is to the left, Returning a numpy 2d array. Used by Kymograph.py script. Uses PIL to handle rotating and interpolating the data. Converts to numpy to PIL and back (may change dtype.) @param pixels: PixelsWrapper object @param x1, y1, x2, y2: Coordinates of line @param line_w: Width of the line we want @param the_z: Z index within pixels @param the_c: Channel index @param the_t: Time index """ size_x = pixels.getSizeX() size_y = pixels.getSizeY() line_x = x2 - x1 line_y = y2 - y1 rads = math.atan(float(line_x) / line_y) # How much extra Height do we need, top and bottom? extra_h = abs(math.sin(rads) * line_w) bottom = int(max(y1, y2) + extra_h / 2) top = int(min(y1, y2) - extra_h / 2) # How much extra width do we need, left and right? extra_w = abs(math.cos(rads) * line_w) left = int(min(x1, x2) - extra_w) right = int(max(x1, x2) + extra_w) # What's the larger area we need? - Are we outside the image? pad_left, pad_right, pad_top, pad_bottom = 0, 0, 0, 0 if left < 0: pad_left = abs(left) left = 0 x = left if top < 0: pad_top = abs(top) top = 0 y = top if right > size_x: pad_right = right - size_x right = size_x w = int(right - left) if bottom > size_y: pad_bottom = bottom - size_y bottom = size_y h = int(bottom - top) tile = (x, y, w, h) # get the Tile plane = pixels.getTile(the_z, the_c, the_t, tile) # pad if we wanted a bigger region if pad_left > 0: data_h, data_w = plane.shape pad_data = zeros((data_h, pad_left), dtype=plane.dtype) plane = hstack((pad_data, plane)) if pad_right > 0: data_h, data_w = plane.shape pad_data = zeros((data_h, pad_right), dtype=plane.dtype) plane = hstack((plane, pad_data)) if pad_top > 0: data_h, data_w = plane.shape pad_data = zeros((pad_top, data_w), dtype=plane.dtype) plane = vstack((pad_data, plane)) if pad_bottom > 0: data_h, data_w = plane.shape pad_data = zeros((pad_bottom, data_w), dtype=plane.dtype) plane = vstack((plane, pad_data)) pil = script_utils.numpy_to_image(plane, (plane.min(), plane.max()), int32) # Now need to rotate so that x1,y1 is horizontally to the left of x2,y2 to_rotate = 90 - math.degrees(rads) if x1 > x2: to_rotate += 180 # filter=Image.BICUBIC see # http://www.ncbi.nlm.nih.gov/pmc/articles/PMC2172449/ rotated = pil.rotate(to_rotate, expand=True) # rotated.show() # finally we need to crop to the length of the line length = int(math.sqrt(math.pow(line_x, 2) + math.pow(line_y, 2))) rot_w, rot_h = rotated.size crop_x = (rot_w - length) / 2 crop_x2 = crop_x + length crop_y = (rot_h - line_w) / 2 crop_y2 = crop_y + line_w cropped = rotated.crop((crop_x, crop_y, crop_x2, crop_y2)) return asarray(cropped)
def getLineData(pixels, x1, y1, x2, y2, lineW=2, theZ=0, theC=0, theT=0): """ Grabs pixel data covering the specified line, and rotates it horizontally so that x1,y1 is to the left, Returning a numpy 2d array. Used by Kymograph.py script. Uses PIL to handle rotating and interpolating the data. Converts to numpy to PIL and back (may change dtype.) @param pixels: PixelsWrapper object @param x1, y1, x2, y2: Coordinates of line @param lineW: Width of the line we want @param theZ: Z index within pixels @param theC: Channel index @param theT: Time index """ from numpy import asarray sizeX = pixels.getSizeX() sizeY = pixels.getSizeY() lineX = x2 - x1 lineY = y2 - y1 rads = math.atan(float(lineX) / lineY) # How much extra Height do we need, top and bottom? extraH = abs(math.sin(rads) * lineW) bottom = int(max(y1, y2) + extraH / 2) top = int(min(y1, y2) - extraH / 2) # How much extra width do we need, left and right? extraW = abs(math.cos(rads) * lineW) left = int(min(x1, x2) - extraW) right = int(max(x1, x2) + extraW) # What's the larger area we need? - Are we outside the image? pad_left, pad_right, pad_top, pad_bottom = 0, 0, 0, 0 if left < 0: pad_left = abs(left) left = 0 x = left if top < 0: pad_top = abs(top) top = 0 y = top if right > sizeX: pad_right = right - sizeX right = sizeX w = int(right - left) if bottom > sizeY: pad_bottom = bottom - sizeY bottom = sizeY h = int(bottom - top) tile = (x, y, w, h) # get the Tile plane = pixels.getTile(theZ, theC, theT, tile) # pad if we wanted a bigger region if pad_left > 0: data_h, data_w = plane.shape pad_data = zeros((data_h, pad_left), dtype=plane.dtype) plane = hstack((pad_data, plane)) if pad_right > 0: data_h, data_w = plane.shape pad_data = zeros((data_h, pad_right), dtype=plane.dtype) plane = hstack((plane, pad_data)) if pad_top > 0: data_h, data_w = plane.shape pad_data = zeros((pad_top, data_w), dtype=plane.dtype) plane = vstack((pad_data, plane)) if pad_bottom > 0: data_h, data_w = plane.shape pad_data = zeros((pad_bottom, data_w), dtype=plane.dtype) plane = vstack((plane, pad_data)) pil = numpyToImage(plane) #pil.show() # Now need to rotate so that x1,y1 is horizontally to the left of x2,y2 toRotate = 90 - math.degrees(rads) if x1 > x2: toRotate += 180 # filter=Image.BICUBIC see # http://www.ncbi.nlm.nih.gov/pmc/articles/PMC2172449/ rotated = pil.rotate(toRotate, expand=True) #rotated.show() # finally we need to crop to the length of the line length = int(math.sqrt(math.pow(lineX, 2) + math.pow(lineY, 2))) rotW, rotH = rotated.size cropX = (rotW - length) / 2 cropX2 = cropX + length cropY = (rotH - lineW) / 2 cropY2 = cropY + lineW cropped = rotated.crop((cropX, cropY, cropX2, cropY2)) #cropped.show() return asarray(cropped)
def getLineData(pixels, x1, y1, x2, y2, lineW=2, theZ=0, theC=0, theT=0): """ Grabs pixel data covering the specified line, and rotates it horizontally so that x1,y1 is to the left, Returning a numpy 2d array. Used by Kymograph.py script. Uses PIL to handle rotating and interpolating the data. Converts to numpy to PIL and back (may change dtype.) @param pixels: PixelsWrapper object @param x1, y1, x2, y2: Coordinates of line @param lineW: Width of the line we want @param theZ: Z index within pixels @param theC: Channel index @param theT: Time index """ from numpy import asarray sizeX = pixels.getSizeX() sizeY = pixels.getSizeY() lineX = x2-x1 lineY = 1 if y2-y1 == 0 else y2-y1 rads = math.atan(float(lineX) / lineY) # How much extra Height do we need, top and bottom? extraH = abs(math.sin(rads) * lineW) bottom = int(max(y1, y2) + extraH/2) top = int(min(y1, y2) - extraH/2) # How much extra width do we need, left and right? extraW = abs(math.cos(rads) * lineW) left = int(min(x1, x2) - extraW) right = int(max(x1, x2) + extraW) # What's the larger area we need? - Are we outside the image? pad_left, pad_right, pad_top, pad_bottom = 0, 0, 0, 0 if left < 0: pad_left = abs(left) left = 0 x = left if top < 0: pad_top = abs(top) top = 0 y = top if right > sizeX: pad_right = right - sizeX right = sizeX w = int(right - left) if bottom > sizeY: pad_bottom = bottom - sizeY bottom = sizeY h = int(bottom - top) tile = (x, y, w, h) # get the Tile plane = pixels.getTile(theZ, theC, theT, tile) # pad if we wanted a bigger region if pad_left > 0: data_h, data_w = plane.shape pad_data = zeros((data_h, pad_left), dtype=plane.dtype) plane = hstack((pad_data, plane)) if pad_right > 0: data_h, data_w = plane.shape pad_data = zeros((data_h, pad_right), dtype=plane.dtype) plane = hstack((plane, pad_data)) if pad_top > 0: data_h, data_w = plane.shape pad_data = zeros((pad_top, data_w), dtype=plane.dtype) plane = vstack((pad_data, plane)) if pad_bottom > 0: data_h, data_w = plane.shape pad_data = zeros((pad_bottom, data_w), dtype=plane.dtype) plane = vstack((plane, pad_data)) pil = numpyToImage(plane) # pil.show() # Now need to rotate so that x1,y1 is horizontally to the left of x2,y2 toRotate = 90 - math.degrees(rads) if x1 > x2: toRotate += 180 # filter=Image.BICUBIC see # http://www.ncbi.nlm.nih.gov/pmc/articles/PMC2172449/ rotated = pil.rotate(toRotate, expand=True) # rotated.show() # finally we need to crop to the length of the line length = int(math.sqrt(math.pow(lineX, 2) + math.pow(lineY, 2))) rotW, rotH = rotated.size cropX = (rotW - length)/2 cropX2 = cropX + length cropY = (rotH - lineW)/2 cropY2 = cropY + lineW cropped = rotated.crop((cropX, cropY, cropX2, cropY2)) # cropped.show() return asarray(cropped)
def vinc_dir(f, a, coordinate_a, alpha12, s): """ Returns the lat and long of projected point and reverse azimuth given a reference point and a distance and azimuth to project. lats, longs and azimuths are passed in decimal degrees Returns ( phi2, lambda2, alpha21 ) as a tuple """ phi1, lambda1 = coordinate_a.lat, coordinate_a.lon piD4 = math.atan(1.0) two_pi = piD4 * 8.0 phi1 = phi1 * piD4 / 45.0 lambda1 = lambda1 * piD4 / 45.0 alpha12 = alpha12 * piD4 / 45.0 if alpha12 < 0.0: alpha12 += two_pi if alpha12 > two_pi: alpha12 -= two_pi b = a * (1.0 - f) tan_u1 = (1 - f) * math.tan(phi1) u1 = math.atan(tan_u1) sigma1 = math.atan2(tan_u1, math.cos(alpha12)) sin_alpha = math.cos(u1) * math.sin(alpha12) cos_alpha_sq = 1.0 - sin_alpha * sin_alpha u2 = cos_alpha_sq * (a * a - b * b) / (b * b) # @todo: look into replacing A and B with vincenty's amendment, see if speed/accuracy is good A = 1.0 + (u2 / 16384) * (4096 + u2 * (-768 + u2 * (320 - 175 * u2))) B = (u2 / 1024) * (256 + u2 * (-128 + u2 * (74 - 47 * u2))) # Starting with the approx sigma = (s / (b * A)) last_sigma = 2.0 * sigma + 2.0 # something impossible # Iterate the following 3 eqs unitl no sig change in sigma # two_sigma_m , delta_sigma while abs((last_sigma - sigma) / sigma) > 1.0e-9: two_sigma_m = 2 * sigma1 + sigma delta_sigma = B * math.sin(sigma) * (math.cos(two_sigma_m) + (B / 4) * (math.cos(sigma) * (-1 + 2 * math.pow( math.cos(two_sigma_m), 2) - (B / 6) * math.cos(two_sigma_m) * (-3 + 4 * math.pow(math.sin(sigma), 2)) * (-3 + 4 * math.pow( math.cos(two_sigma_m), 2))))) last_sigma = sigma sigma = (s / (b * A)) + delta_sigma phi2 = math.atan2((math.sin(u1) * math.cos(sigma) + math.cos(u1) * math.sin(sigma) * math.cos(alpha12)), ((1 - f) * math.sqrt(math.pow(sin_alpha, 2) + pow(math.sin(u1) * math.sin(sigma) - math.cos(u1) * math.cos( sigma) * math.cos(alpha12), 2)))) lmbda = math.atan2((math.sin(sigma) * math.sin(alpha12)), (math.cos(u1) * math.cos(sigma) - math.sin(u1) * math.sin(sigma) * math.cos(alpha12))) C = (f / 16) * cos_alpha_sq * (4 + f * (4 - 3 * cos_alpha_sq)) omega = lmbda - (1 - C) * f * sin_alpha * (sigma + C * math.sin(sigma) * (math.cos(two_sigma_m) + C * math.cos(sigma) * (-1 + 2 * math.pow(math.cos(two_sigma_m), 2)))) lambda2 = lambda1 + omega alpha21 = math.atan2(sin_alpha, (-math.sin(u1) * math.sin(sigma) + math.cos(u1) * math.cos(sigma) * math.cos(alpha12))) alpha21 += two_pi / 2.0 if alpha21 < 0.0: alpha21 += two_pi if alpha21 > two_pi: alpha21 -= two_pi phi2 = phi2 * 45.0 / piD4 lambda2 = lambda2 * 45.0 / piD4 alpha21 = alpha21 * 45.0 / piD4 return Coordinate(lat=phi2, lon=lambda2), alpha21
def vinc_inv(f, a, coordinate_a, coordinate_b): """ Returns the distance between two geographic points on the ellipsoid and the forward and reverse azimuths between these points. lats, longs and azimuths are in radians, distance in metres :param f: flattening of the geodesic :param a: the semimajor axis of the geodesic :param coordinate_a: decimal coordinate given as named tuple coordinate :param coordinate_b: decimal coordinate given as named tuple coordinate Note: The problem calculates forward and reverse azimuths as: coordinate_a -> coordinate_b """ phi1 = math.radians(coordinate_a.lat) lembda1 = math.radians(coordinate_a.lon) phi2 = math.radians(coordinate_b.lat) lembda2 = math.radians(coordinate_b.lon) if (abs(phi2 - phi1) < 1e-8) and (abs(lembda2 - lembda1) < 1e-8): return {'distance': 0.0, 'forward_azimuth': 0.0, 'reverse_azimuth': 0.0} two_pi = 2.0 * math.pi b = a * (1 - f) TanU1 = (1 - f) * math.tan(phi1) TanU2 = (1 - f) * math.tan(phi2) U1 = math.atan(TanU1) U2 = math.atan(TanU2) lembda = lembda2 - lembda1 last_lembda = -4000000.0 # an impossibe value omega = lembda # Iterate the following equations, # until there is no significant change in lembda while (last_lembda < -3000000.0 or lembda != 0 and abs((last_lembda - lembda) / lembda) > 1.0e-9): sqr_sin_sigma = pow(math.cos(U2) * math.sin(lembda), 2) + \ pow((math.cos(U1) * math.sin(U2) - math.sin(U1) * math.cos(U2) * math.cos(lembda)), 2) Sin_sigma = math.sqrt(sqr_sin_sigma) Cos_sigma = math.sin(U1) * math.sin(U2) + math.cos(U1) * math.cos(U2) * math.cos(lembda) sigma = math.atan2(Sin_sigma, Cos_sigma) Sin_alpha = math.cos(U1) * math.cos(U2) * math.sin(lembda) / math.sin(sigma) alpha = math.asin(Sin_alpha) Cos2sigma_m = math.cos(sigma) - (2 * math.sin(U1) * math.sin(U2) / pow(math.cos(alpha), 2)) C = (f / 16) * pow(math.cos(alpha), 2) * (4 + f * (4 - 3 * pow(math.cos(alpha), 2))) last_lembda = lembda lembda = omega + (1 - C) * f * math.sin(alpha) * (sigma + C * math.sin(sigma) * \ (Cos2sigma_m + C * math.cos(sigma) * ( -1 + 2 * pow(Cos2sigma_m, 2)))) u2 = pow(math.cos(alpha), 2) * (a * a - b * b) / (b * b) A = 1 + (u2 / 16384) * (4096 + u2 * (-768 + u2 * (320 - 175 * u2))) B = (u2 / 1024) * (256 + u2 * (-128 + u2 * (74 - 47 * u2))) delta_sigma = B * Sin_sigma * (Cos2sigma_m + (B / 4) * \ (Cos_sigma * (-1 + 2 * pow(Cos2sigma_m, 2)) - \ (B / 6) * Cos2sigma_m * (-3 + 4 * sqr_sin_sigma) * \ (-3 + 4 * pow(Cos2sigma_m, 2)))) s = b * A * (sigma - delta_sigma) alpha12 = math.atan2((math.cos(U2) * math.sin(lembda)), \ (math.cos(U1) * math.sin(U2) - math.sin(U1) * math.cos(U2) * math.cos(lembda))) alpha21 = math.atan2((math.cos(U1) * math.sin(lembda)), \ (-math.sin(U1) * math.cos(U2) + math.cos(U1) * math.sin(U2) * math.cos(lembda))) if (alpha12 < 0.0): alpha12 += two_pi if (alpha12 > two_pi): alpha12 -= two_pi alpha21 += two_pi / 2.0 if alpha21 < 0.0: alpha21 += alpha21 + two_pi if alpha21 > two_pi: alpha21 -= two_pi return {"distance": s, "forward_azimuth": alpha12, "reverse_azimuth": alpha21}