Last active
September 5, 2019 02:10
-
-
Save mdecourse/d6759fe070289852eaca8481b1ec93df to your computer and use it in GitHub Desktop.
平面機構模擬 Brython 參考程式
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # http://mde.tw/2017springcd/blog/brython-2d-canvas-fourbar.html | |
| # http://project.mde.tw/blog/pyslvs_triangle_expression.html | |
| # http://lab.kmol.info/2017fall/blog/kmol-2017-fall-cadp-fourbar-three-position-synthesis.html | |
| from browser import document | |
| import math | |
| import time | |
| from browser import timer | |
| class Coord(object): | |
| def __init__(self,x,y): | |
| self.x = x | |
| self.y = y | |
| def __sub__(self,other): | |
| # This allows you to substract vectors | |
| return Coord(self.x-other.x,self.y-other.y) | |
| def __repr__(self): | |
| # Used to get human readable coordinates when printing | |
| return "Coord(%f,%f)"%(self.x,self.y) | |
| def length(self): | |
| # Returns the length of the vector | |
| return math.sqrt(self.x**2 + self.y**2) | |
| def angle(self): | |
| # Returns the vector's angle | |
| return math.atan2(self.y,self.x) | |
| def normalize(coord): | |
| return Coord( | |
| coord.x/coord.length(), | |
| coord.y/coord.length() | |
| ) | |
| def perpendicular(coord): | |
| # Shifts the angle by pi/2 and calculate the coordinates | |
| # using the original vector length | |
| return Coord( | |
| coord.length()*math.cos(coord.angle()+math.pi/2), | |
| coord.length()*math.sin(coord.angle()+math.pi/2) | |
| ) | |
| # 點類別 | |
| class Point(object): | |
| # 起始方法 | |
| def __init__(self, x, y): | |
| self.x = x | |
| self.y = y | |
| # 繪製方法 | |
| def drawMe(self, g, r): | |
| self.g = g | |
| self.r = r | |
| self.g.save() | |
| self.g.moveTo(self.x,self.y) | |
| self.g.beginPath() | |
| # 根據 r 半徑繪製一個圓代表點的所在位置 | |
| self.g.arc(self.x, self.y, self.r, 0, 2*math.pi, True) | |
| self.g.moveTo(self.x,self.y) | |
| self.g.lineTo(self.x+self.r, self.y) | |
| self.g.moveTo(self.x, self.y) | |
| self.g.lineTo(self.x-self.r, self.y) | |
| self.g.moveTo(self.x, self.y) | |
| self.g.lineTo(self.x, self.y+self.r) | |
| self.g.moveTo(self.x, self.y) | |
| self.g.lineTo(self.x, self.y-self.r) | |
| self.g.restore() | |
| self.g.stroke() | |
| # 加入 Eq 方法 | |
| def Eq(self, pt): | |
| self.x = pt.x | |
| self.y = pt.y | |
| # 加入 setPoint 方法 | |
| def setPoint(self, px, py): | |
| self.x = px | |
| self.y = py | |
| # 加上 distance(pt) 方法, 計算點到 pt 的距離 | |
| def distance(self, pt): | |
| self.pt = pt | |
| x = self.x - self.pt.x | |
| y = self.y - self.pt.y | |
| return math.sqrt(x * x + y * y) | |
| # 利用文字標示點的座標位置 | |
| def tag(self, g): | |
| self.g = g | |
| self.g.beginPath() | |
| self.g.fillText("%d, %d"%(self.x, self.y),self.x, self.y) | |
| self.g.stroke() | |
| # Line 類別物件 | |
| class Line(object): | |
| # 起始方法 | |
| def __init__(self, p1, p2): | |
| self.p1 = p1 | |
| self.p2 = p2 | |
| # 直線的第一點, 設為線尾 | |
| self.Tail = self.p1 | |
| # 直線組成的第二點, 設為線頭 | |
| self.Head = self.p2 | |
| # 直線的長度屬性 | |
| self.length = math.sqrt(math.pow(self.p2.x-self.p1.x, 2)+math.pow(self.p2.y-self.p1.y,2)) | |
| # setPP 以指定頭尾座標點來定義直線 | |
| def setPP(self, p1, p2): | |
| self.p1 = p1 | |
| self.p2 = p2 | |
| self.Tail = self.p1 | |
| self.Head = self.p2 | |
| self.length = math.sqrt(math.pow(self.p2.x-self.p1.x, 2)+math.pow(self.p2.y-self.p1.y,2)) | |
| # setRT 方法 for Line, 應該已經確定 Tail 點, 然後以 r, t 作為設定 Head 的參考 | |
| def setRT(self, r, t): | |
| self.r = r | |
| self.t = t | |
| x = self.r * math.cos(self.t) | |
| y = self.r * math.sin(self.t) | |
| self.Tail.Eq(self.p1) | |
| self.Head.setPoint(self.Tail.x + x,self.Tail.y + y) | |
| # getR 方法 for Line | |
| def getR(self): | |
| # x 分量與 y 分量 | |
| x = self.p1.x - self.p2.x | |
| y = self.p1.y - self.p2.y | |
| return math.sqrt(x * x + y * y) | |
| # 根據定義 atan2(y,x), 表示 (x,y) 與 正 x 軸之間的夾角, 介於 pi 與 -pi 間 | |
| def getT(self): | |
| x = self.p2.x - self.p1.x | |
| y = self.p2.y - self.p1.y | |
| if (math.fabs(x) < math.pow(10,-100)): | |
| if(y < 0.0): | |
| return (-math.pi/2) | |
| else: | |
| return (math.pi/2) | |
| else: | |
| return math.atan2(y, x) | |
| # setTail 方法 for Line | |
| def setTail(self, pt): | |
| self.pt = pt | |
| self.Tail.Eq(pt) | |
| self.Head.setPoint(self.pt.x + self.x, self.pt.y + self.y) | |
| # getHead 方法 for Line | |
| def getHead(self): | |
| return self.Head | |
| def getTail(self): | |
| return self.Tail | |
| def drawMe(self, g): | |
| self.g = g | |
| self.g.beginPath() | |
| self.g.moveTo(self.p1.x,self.p1.y) | |
| self.g.lineTo(self.p2.x,self.p2.y) | |
| self.g.stroke() | |
| def test(self): | |
| return ("this is pure test to Inherit") | |
| class Link(Line): | |
| def __init__(self, p1, p2): | |
| self.p1 = p1 | |
| self.p2 = p2 | |
| self.length = math.sqrt(math.pow((self.p2.x - self.p1.x), 2) + math.pow((self.p2.y - self.p1.y), 2)) | |
| #g context | |
| def drawMe(self, g): | |
| self.g = g | |
| hole = 5 | |
| radius = 10 | |
| length = self.getR() | |
| # alert(length) | |
| # 儲存先前的繪圖狀態 | |
| self.g.save() | |
| self.g.translate(self.p1.x,self.p1.y) | |
| #alert(str(self.p1.x)+","+str(self.p1.y)) | |
| #self.g.rotate(-((math.pi/2)-self.getT())) | |
| self.g.rotate(-math.pi*0.5 + self.getT()) | |
| #alert(str(self.getT())) | |
| #self.g.rotate(10*math.pi/180) | |
| #this.g.rotate(-(Math.PI/2-this.getT())); | |
| # 必須配合畫在 y 軸上的 Link, 進行座標轉換, 也可以改為畫在 x 軸上... | |
| self.g.beginPath() | |
| self.g.moveTo(0,0) | |
| self.g.arc(0, 0, hole, 0, 2*math.pi, True) | |
| self.g.stroke() | |
| self.g.moveTo(0,length) | |
| self.g.beginPath() | |
| self.g.arc(0,length, hole, 0, 2*math.pi, True) | |
| self.g.stroke() | |
| self.g.moveTo(0,0) | |
| self.g.beginPath() | |
| self.g.arc(0,0, radius, 0, math.pi, True) | |
| self.g.moveTo(0+radius,0) | |
| self.g.lineTo(0+radius,0+length) | |
| self.g.stroke() | |
| self.g.moveTo(0,0+length) | |
| self.g.beginPath() | |
| self.g.arc(0, 0+length, radius, math.pi, 0, True) | |
| self.g.moveTo(0-radius,0+length) | |
| self.g.lineTo(0-radius,0) | |
| self.g.stroke() | |
| self.g.restore() | |
| ''' | |
| self.g.beginPath() | |
| self.g.fillStyle = "red" | |
| self.g.font = "bold 18px sans-serif" | |
| self.g.fillText("%d, %d"%(self.p2.x, self.p2.y),self.p2.x, self.p2.y) | |
| self.g.stroke() | |
| ''' | |
| class Triangle(object): | |
| def __init__(self, p1, p2, p3): | |
| self.p1 = p1 | |
| self.p2 = p2 | |
| self.p3 = p3 | |
| def getLenp3(self): | |
| p1 = self.p1 | |
| ret = p1.distance(self.p2) | |
| return ret | |
| def getLenp1(self): | |
| p2 = self.p2 | |
| ret = p2.distance(self.p3) | |
| return ret | |
| def getLenp2(self): | |
| p1 = self.p1 | |
| ret = p1.distance(self.p3) | |
| return ret | |
| # 角度 | |
| def getAp1(self): | |
| ret = math.acos(((self.getLenp2() * self.getLenp2() + self.getLenp3() * self.getLenp3()) - self.getLenp1() * self.getLenp1()) / (2* self.getLenp2() * self.getLenp3())) | |
| return ret | |
| # | |
| def getAp2(self): | |
| ret =math.acos(((self.getLenp1() * self.getLenp1() + self.getLenp3() * self.getLenp3()) - self.getLenp2() * self.getLenp2()) / (2* self.getLenp1() * self.getLenp3())) | |
| return ret | |
| def getAp3(self): | |
| ret = math.acos(((self.getLenp1() * self.getLenp1() + self.getLenp2() * self.getLenp2()) - self.getLenp3() * self.getLenp3()) / (2* self.getLenp1() * self.getLenp2())) | |
| return ret | |
| def drawMe(self, g): | |
| self.g = g | |
| r = 5 | |
| # 繪出三個頂點 | |
| self.p1.drawMe(self.g,r) | |
| self.p2.drawMe(self.g,r) | |
| self.p3.drawMe(self.g,r) | |
| line1 = Line(self.p1,self.p2) | |
| line2 = Line(self.p1,self.p3) | |
| line3 = Line(self.p2,self.p3) | |
| # 繪出三邊線 | |
| line1.drawMe(self.g) | |
| line2.drawMe(self.g) | |
| line3.drawMe(self.g) | |
| # ends Triangle def | |
| # 透過三個邊長定義三角形 | |
| def setSSS(self, lenp3, lenp1, lenp2): | |
| self.lenp3 = lenmidpt = Point(0, 0) | |
| self.lenp1 = lenp1 | |
| self.lenp2 = lenp2 | |
| self.ap1 = math.acos(((self.lenp2 * self.lenp2 + self.lenp3 * self.lenp3) - self.lenp1 * self.lenp1) / (2* self.lenp2 * self.lenp3)) | |
| self.ap2 = math.acos(((self.lenp1 * self.lenp1 + self.lenp3 * self.lenp3) - self.lenp2 * self.lenp2) / (2* self.lenp1 * self.lenp3)) | |
| self.ap3 = math.acos(((self.lenp1 * self.lenp1 + self.lenp2 * self.lenp2) - self.lenp3 * self.lenp3) / (2* self.lenp1 * self.lenp2)) | |
| # 透過兩個邊長與夾角定義三角形 | |
| def setSAS(self, lenp3, ap2, lenp1): | |
| self.lenp3 = lenp3 | |
| self.ap2 = ap2 | |
| self.lenp1 = lenp1 | |
| self.lenp2 = math.sqrt((self.lenp3 * self.lenp3 + self.lenp1 * self.lenp1) - 2* self.lenp3 * self.lenp1 * math.cos(self.ap2)) | |
| #等於 SSS(AB, BC, CA) | |
| def setSaSS(self, lenp2, lenp3, lenp1): | |
| self.lenp2 = lenp2 | |
| self.lenp3 = lenp3 | |
| self.lenp1 = lenp1 | |
| if(self.lenp1 > (self.lenp2 + self.lenp3)): | |
| #<CAB 夾角為 180 度, 三點共線且 A 介於 BC 之間 | |
| ret = math.pi | |
| else : | |
| # <CAB 夾角為 0, 三點共線且 A 不在 BC 之間 | |
| if((self.lenp1 < (self.lenp2 - self.lenp3)) or (self.lenp1 < (self.lenp3 - self.lenp2))): | |
| ret = 0.0 | |
| else : | |
| # 透過餘絃定理求出夾角 <CAB | |
| ret = math.acos(((self.lenp2 * self.lenp2 + self.lenp3 * self.lenp3) - self.lenp1 * self.lenp1) / (2 * self.lenp2 * self.lenp3)) | |
| return ret | |
| # 取得三角形的三個邊長值 | |
| def getSSS(self): | |
| temp = [] | |
| temp.append( self.getLenp1() ) | |
| temp.append( self.getLenp2() ) | |
| temp.append( self.getLenp3() ) | |
| return temp | |
| # 取得三角形的三個角度值 | |
| def getAAA(self): | |
| temp = [] | |
| temp.append( self.getAp1() ) | |
| temp.append( self.getAp2() ) | |
| temp.append( self.getAp3() ) | |
| return temp | |
| # 取得三角形的三個角度與三個邊長 | |
| def getASASAS(self): | |
| temp = [] | |
| temp.append(self.getAp1()) | |
| temp.append(self.getLenp1()) | |
| temp.append(self.getAp2()) | |
| temp.append(self.getLenp2()) | |
| temp.append(self.getAp3()) | |
| temp.append(self.getLenp3()) | |
| return temp | |
| #2P 2L return mid P | |
| def setPPSS(self, p1, p3, lenp1, lenp3): | |
| temp = [] | |
| self.p1 = p1 | |
| self.p3 = p3 | |
| self.lenp1 = lenp1 | |
| self.lenp3 = lenp3 | |
| #bp3 is the angle beside p3 point, cp3 is the angle for line23, p2 is the output | |
| line31 = Line(p3, p1) | |
| self.lenp2 = line31.getR() | |
| #self.lenp2 = self.p3.distance(self.p1) | |
| #這裡是求角3 | |
| ap3 = math.acos(((self.lenp1 * self.lenp1 + self.lenp2 * self.lenp2) - self.lenp3 * self.lenp3) / (2 * self.lenp1 * self.lenp2)) | |
| #ap3 = math.acos(((self.lenp1 * self.lenp1 + self.lenp3 * self.lenp3) - self.lenp2 * self.lenp2) / (2 * self.lenp1 * self.lenp3)) | |
| bp3 = line31.getT() | |
| cp3 = bp3 - ap3 | |
| temp.append(p3.x + self.lenp1*math.cos(cp3))#p2.x | |
| temp.append(p3.y + self.lenp1*math.sin(cp3))#p2.y | |
| return temp | |
| def tag(g, p): | |
| None | |
| midpt = Point(0, 0) | |
| tippt = Point(0, 0) | |
| contour = [] | |
| # 執行繪圖流程, 注意 x, y 為 global variables | |
| def draw(): | |
| global theta, midpt, oldpt | |
| context.clearRect(0, 0, canvas.width, canvas.height) | |
| line1.drawMe(context) | |
| line2.drawMe(context) | |
| line3.drawMe(context) | |
| #triangle1.drawMe(context) | |
| #triangle2.drawMe(context) | |
| theta += dx | |
| p2.x = p1.x + line1.length*math.cos(theta*degree) | |
| p2.y = p1.y - line1.length*math.sin(theta*degree) | |
| p3.x, p3.y = triangle2.setPPSS(p2,p4,link2_len,link3_len) | |
| # 計算垂直單位向量 | |
| a = Coord(p3.x, p3.y) | |
| b = Coord(p2.x, p2.y) | |
| normal = perpendicular(normalize(a-b)) | |
| midpt.x = (p2.x + p3.x)/2 | |
| midpt.y = (p2.y + p3.y)/2 | |
| tippt.x = midpt.x + 150*normal.x | |
| tippt.y = midpt.y + 150*normal.y | |
| if theta < 360: | |
| contour.append((tippt.x, tippt.y)) | |
| context.beginPath() | |
| context.moveTo(midpt.x, midpt.y) | |
| context.lineTo(tippt.x, tippt.y) | |
| # 利用 fillRect 繪製一個長寬各 1 單位的正方形 | |
| for i in range(len(contour)): | |
| context.fillRect(contour[i][0], contour[i][1], 1, 1) | |
| context.stroke() | |
| #p1.tag(context) | |
| # 以上為相關函式物件的定義區 | |
| # 全域變數 | |
| # 幾何位置輸入變數 | |
| x=10 | |
| y=10 | |
| r=10 | |
| # 畫布與繪圖內容 | |
| # 其他輸入變數 | |
| theta = 0 | |
| degree = math.pi/180.0 | |
| dx = 2 | |
| dy = 4 | |
| #set p1.p2.p3.p4 position | |
| lift = 10 | |
| p1 = Point(150,100+lift) | |
| p2 = Point(150,200+lift) | |
| p3 = Point(300,300+lift) | |
| p4 = Point(350,100+lift) | |
| #accord position create link | |
| line1 = Link(p1,p2) | |
| line2 = Link(p2,p3) | |
| line3 = Link(p3,p4) | |
| line4 = Link(p1,p4) | |
| line5 = Link(p2,p4) | |
| link2_len = p2.distance(p3) | |
| link3_len = p3.distance(p4) | |
| #link2_len = line1.getR() | |
| #link3_len = line3.getR() | |
| #alert(str(link2_len)+','+str(link3_len)) | |
| triangle1 = Triangle(p1,p2,p4) | |
| triangle2 = Triangle(p2,p3,p4) | |
| # 視窗載入時執行內容 | |
| # 繪圖畫布設定 | |
| canvas = document["plotarea"] | |
| context = canvas.getContext("2d") | |
| # 座標轉換, 移動 canvas.height 並且 y 座標變號, 也就是將原點座標移到畫面左下角 | |
| context.translate(0,canvas.height) | |
| context.scale(1,-1) | |
| #以間隔 20 micro seconds 重複呼叫 draw() | |
| timer.set_interval(draw,20) | |
| #timer.set_interval(draw,10) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from math import pi, cos, sin, sqrt, acos | |
| radian = 180/pi | |
| degree = pi/180 | |
| #PLAP | |
| def plap(ax, ay, ac, bac, bx, by, pos): | |
| if pos == 0: | |
| cx= ac*cos(bac - acos((ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2 + abs(ax - bx)**2 - abs(ay - by)**2)/(2*sqrt(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2)*abs(ax - bx)))) + ax | |
| cy= ac*sin(bac - acos((ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2 + abs(ax - bx)**2 - abs(ay - by)**2)/(2*sqrt(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2)*abs(ax - bx)))) + ay | |
| else: | |
| cx= ac*cos(bac + acos((ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2 + abs(ax - bx)**2 - abs(ay - by)**2)/(2*sqrt(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2)*abs(ax - bx)))) + ax | |
| cy= ac*sin(bac + acos((ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2 + abs(ax - bx)**2 - abs(ay - by)**2)/(2*sqrt(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2)*abs(ax - bx)))) + ay | |
| return cx, cy | |
| #PLLP | |
| def pllp(ax, ay, ac, cb, bx, by, pos): | |
| if pos == 0: | |
| cx = -((ay - by)*(-ac**2*ay + ac**2*by + ax**2*ay + ax**2*by - 2*ax*ay*bx - 2*ax*bx*by + ay**3 - ay**2*by + ay*bx**2 - ay*by**2 + ay*cb**2 + bx**2*by + by**3 - by*cb**2 - sqrt((-ac**2 + 2*ac*cb + ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2 - cb**2)*(ac**2 + 2*ac*cb - ax**2 + 2*ax*bx - ay**2 + 2*ay*by - bx**2 - by**2 + cb**2))*(ax - bx)) + (ac**2 - ax**2 - ay**2 + bx**2 + by**2 - cb**2)*(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2))/(2*(ax - bx)*(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2)) | |
| cy = (-ac**2*ay + ac**2*by + ax**2*ay + ax**2*by - 2*ax*ay*bx - 2*ax*bx*by + ay**3 - ay**2*by + ay*bx**2 - ay*by**2 + ay*cb**2 + bx**2*by + by**3 - by*cb**2 + sqrt((-ac**2 + 2*ac*cb + ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2 - cb**2)*(ac**2 + 2*ac*cb - ax**2 + 2*ax*bx - ay**2 + 2*ay*by - bx**2 - by**2 + cb**2))*(-ax + bx))/(2*(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2)) | |
| else: | |
| cx = -((ay - by)*(-ac**2*ay + ac**2*by + ax**2*ay + ax**2*by - 2*ax*ay*bx - 2*ax*bx*by + ay**3 - ay**2*by + ay*bx**2 - ay*by**2 + ay*cb**2 + bx**2*by + by**3 - by*cb**2 + sqrt((-ac**2 + 2*ac*cb + ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2 - cb**2)*(ac**2 + 2*ac*cb - ax**2 + 2*ax*bx - ay**2 + 2*ay*by - bx**2 - by**2 + cb**2))*(ax - bx)) + (ac**2 - ax**2 - ay**2 + bx**2 + by**2 - cb**2)*(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2))/(2*(ax - bx)*(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2)) | |
| cy = (-ac**2*ay + ac**2*by + ax**2*ay + ax**2*by - 2*ax*ay*bx - 2*ax*bx*by + ay**3 - ay**2*by + ay*bx**2 - ay*by**2 + ay*cb**2 + bx**2*by + by**3 - by*cb**2 + sqrt((-ac**2 + 2*ac*cb + ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2 - cb**2)*(ac**2 + 2*ac*cb - ax**2 + 2*ax*bx - ay**2 + 2*ay*by - bx**2 - by**2 + cb**2))*(ax - bx))/(2*(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2)) | |
| return cx, cy | |
| class fourbar(object): | |
| ''' | |
| (ax, ay) motor coord | |
| (bx, by) rocker base coord | |
| bac motor angle | |
| ac link1 length | |
| cd link2 length | |
| db link3 length | |
| ce triangle side1 | |
| ed triangle side2 | |
| ''' | |
| def __init__(self, ax, ay, bx, by, bac, ac, cd, db, ce, ed): | |
| self.ax = ax | |
| self.ay = ay | |
| self.bx = bx | |
| self.by = by | |
| self.bac = bac | |
| self.ac = ac | |
| self.cd = cd | |
| self.db = db | |
| self.ce = ce | |
| self.ed = ed | |
| @property | |
| def cx(self): | |
| return plap(self.ax, self.ay, self.ac, self.bac, self.bx, self.by, pos=0)[0] | |
| @property | |
| def cy(self): | |
| return plap(self.ax, self.ay, self.ac, self.bac, self.bx, self.by, pos=0)[1] | |
| @property | |
| def dx(self): | |
| return pllp(self.cx, self.cy, self.cd, self.db, self.bx, self.by, pos=0)[0] | |
| @property | |
| def dy(self): | |
| return pllp(self.cx, self.cy, self.cd, self.db, self.bx, self.by, pos=0)[1] | |
| @property | |
| def ex(self): | |
| return pllp(self.cx, self.cy, self.ce, self.ed, self.dx, self.dy, pos=0)[0] | |
| @property | |
| def ey(self): | |
| return pllp(self.cx, self.cy, self.ce, self.ed, self.dx, self.dy, pos=0)[1] | |
| ''' | |
| # 利用 fourbar 物件建立案例 | |
| f = fourbar(ax = -60, ay = 0, bx = 0, by = 0, bac = 50*degree, ac = 30, cd = 50, db = 60, ce = 50, ed = 50) | |
| # 利用 fourbar 物件案例的方法求各點座標 | |
| #f.cx, f.cy 為 C 點座標 | |
| #f.dx, f.dy 為 D 點座標 | |
| #f.ex, f.ey 為 E 點座標 | |
| ''' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # http://mde.tw/cp2018/content/Pyslvs%20%E7%AF%84%E4%BE%8B.html | |
| # http://mde.tw/cp2018/downloads/2014_nsysu_design_linkage_type_foot_exercise_machine.pdf | |
| # http://mde.tw/cp2018/blog/2018-Fall-Python-Getting-Started.html | |
| # triangle_fourbar_point_track.py | |
| from math import pi, cos, sin, sqrt, acos | |
| import matplotlib.pyplot as plt | |
| radian = 180/pi | |
| degree = pi/180 | |
| #PLAP | |
| def plap(ax, ay, ac, bac, bx, by, pos): | |
| if pos == 0: | |
| cx= ac*cos(bac - acos((ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2 + abs(ax - bx)**2 - abs(ay - by)**2)/(2*sqrt(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2)*abs(ax - bx)))) + ax | |
| cy= ac*sin(bac - acos((ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2 + abs(ax - bx)**2 - abs(ay - by)**2)/(2*sqrt(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2)*abs(ax - bx)))) + ay | |
| else: | |
| cx= ac*cos(bac + acos((ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2 + abs(ax - bx)**2 - abs(ay - by)**2)/(2*sqrt(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2)*abs(ax - bx)))) + ax | |
| cy= ac*sin(bac + acos((ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2 + abs(ax - bx)**2 - abs(ay - by)**2)/(2*sqrt(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2)*abs(ax - bx)))) + ay | |
| return cx, cy | |
| #PLLP | |
| def pllp(ax, ay, ac, cb, bx, by, pos): | |
| if pos == 0: | |
| cx = -((ay - by)*(-ac**2*ay + ac**2*by + ax**2*ay + ax**2*by - 2*ax*ay*bx - 2*ax*bx*by + ay**3 - ay**2*by + ay*bx**2 - ay*by**2 + ay*cb**2 + bx**2*by + by**3 - by*cb**2 - sqrt((-ac**2 + 2*ac*cb + ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2 - cb**2)*(ac**2 + 2*ac*cb - ax**2 + 2*ax*bx - ay**2 + 2*ay*by - bx**2 - by**2 + cb**2))*(ax - bx)) + (ac**2 - ax**2 - ay**2 + bx**2 + by**2 - cb**2)*(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2))/(2*(ax - bx)*(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2)) | |
| cy = (-ac**2*ay + ac**2*by + ax**2*ay + ax**2*by - 2*ax*ay*bx - 2*ax*bx*by + ay**3 - ay**2*by + ay*bx**2 - ay*by**2 + ay*cb**2 + bx**2*by + by**3 - by*cb**2 + sqrt((-ac**2 + 2*ac*cb + ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2 - cb**2)*(ac**2 + 2*ac*cb - ax**2 + 2*ax*bx - ay**2 + 2*ay*by - bx**2 - by**2 + cb**2))*(-ax + bx))/(2*(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2)) | |
| else: | |
| cx = -((ay - by)*(-ac**2*ay + ac**2*by + ax**2*ay + ax**2*by - 2*ax*ay*bx - 2*ax*bx*by + ay**3 - ay**2*by + ay*bx**2 - ay*by**2 + ay*cb**2 + bx**2*by + by**3 - by*cb**2 + sqrt((-ac**2 + 2*ac*cb + ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2 - cb**2)*(ac**2 + 2*ac*cb - ax**2 + 2*ax*bx - ay**2 + 2*ay*by - bx**2 - by**2 + cb**2))*(ax - bx)) + (ac**2 - ax**2 - ay**2 + bx**2 + by**2 - cb**2)*(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2))/(2*(ax - bx)*(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2)) | |
| cy = (-ac**2*ay + ac**2*by + ax**2*ay + ax**2*by - 2*ax*ay*bx - 2*ax*bx*by + ay**3 - ay**2*by + ay*bx**2 - ay*by**2 + ay*cb**2 + bx**2*by + by**3 - by*cb**2 + sqrt((-ac**2 + 2*ac*cb + ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2 - cb**2)*(ac**2 + 2*ac*cb - ax**2 + 2*ax*bx - ay**2 + 2*ay*by - bx**2 - by**2 + cb**2))*(ax - bx))/(2*(ax**2 - 2*ax*bx + ay**2 - 2*ay*by + bx**2 + by**2)) | |
| return cx, cy | |
| def crank_rocker(angle, p1x, p1y, p2x, p2y, len1, len2, len3, len4, len5): | |
| p4x, p4y = plap(p1x, p1y, len1, angle, p2x, p2y, 0) | |
| #print("cx=", cx, "cy=", cy) | |
| p5x, p5y = pllp(p4x, p4y, len2, len3, p2x, p2y, 0) | |
| #print("dx=", dx, "dy=", dy) | |
| p3x, p3y = pllp(p4x, p4y, len4, len5, p5x, p5y, 0) | |
| #print("ex=", ex, "ey=", ey) | |
| return p3x, p3y | |
| #主程式 | |
| Xval = [] | |
| Yval = [] | |
| inc = 5 | |
| for i in range(0, 360+inc, inc): | |
| try: | |
| p3x, p3y = crank_rocker(i*degree, 0, 0, 90, 0, 35, 70, 70, 40, 40) | |
| Xval += [p3x] | |
| Yval += [p3y] | |
| print(i, ":", round(p3x, 4), round(p3y, 4)) | |
| except: | |
| pass | |
| print ("Solve Completed") | |
| plt.plot(Xval, Yval) | |
| plt.xlabel('x coordinate') | |
| plt.ylabel('y coordinate') | |
| #plt.title("Involute - "+str(degree)+" deg") | |
| plt.show() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from browser import document as doc | |
| from browser import html | |
| import math | |
| # 準備繪圖畫布 | |
| canvas = doc["fourbar"] | |
| container1 = doc['container1'] | |
| ctx = canvas.getContext("2d") | |
| fourbar_data = open("./../w7/11117.csv").read() | |
| fourbar_list = fourbar_data.splitlines() | |
| #container1 <= fourbar_list[0] | |
| # 以下可以利用 ctx 物件進行畫圖 | |
| # 先畫一條直線 | |
| ctx.beginPath() | |
| # 設定線的寬度為 1 個單位 | |
| ctx.lineWidth = 1 | |
| # 利用 transform 將 y 座標反轉, 且 offset canvas.height | |
| # (X scale, X skew, Y skew, Y scale, X offset, Y offset) | |
| # 配合圖形位置進行座標轉換 | |
| ctx.transform(1, 0, 0, -1, canvas.width/2+250, canvas.height/2+100) | |
| # 畫出 x 與 y 座標線 | |
| # 各座標值放大 8 倍 | |
| ratio = 8 | |
| ''' | |
| ctx.moveTo(0, 0) | |
| ctx.lineTo(0, 100) | |
| ctx.moveTo(0, 0) | |
| ctx.lineTo(100, 0) | |
| ''' | |
| ctx.moveTo(0, 0) | |
| ctx.lineTo(-30*ratio, 0) | |
| start_point = fourbar_list[0].split(",") | |
| ctx.moveTo(float(start_point[0])*ratio, float(start_point[1])*ratio) | |
| count = 0 | |
| for data in fourbar_list[1:]: | |
| point = data.split(",") | |
| #count = count + 1 | |
| #container1 <= str(count) + ":" + point[0] + "," + point[1] | |
| #container1 <= html.BR() | |
| ctx.lineTo(float(point[0])*ratio, float(point[1])*ratio) | |
| # 設定顏色為藍色, 也可以使用 "rgb(0, 0, 255)" 字串設定顏色值 | |
| ctx.strokeStyle = "blue" | |
| # 實際執行畫線 | |
| ctx.stroke() | |
| ctx.closePath() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment