ตอนนี้มาถึงโปรแกรมพื้นฐานงานสำรวจชุดที่ 4 (COGO Selected Serie 4) สำหรับเครื่องคิดเลขคาสิโอ fx-9750GIII, fx-9860GIII และ fx-cg50 PRIZM สามรุ่นที่รองรับภาษาไพทอนหรือไมโครไพทอน ได้ในขณะนี้ หาซื้อได้ในเมืองไทย ราคาย่อมเยาที่สุดคือ fx-9750GIII ที่ราคาประมาณสามพันบาท ถ้ามีงานการทำเป็นหลักเป็นแหล่งแล้วไม่น่าแพง บางทีเราซื้อโทรศัพท์มือถือได้ราคาเป็นเรือนหมื่นไม่คิดอะไรมาก แต่กับเครื่องคิดเลขคิดแล้วคิดอีก สำหรับผมแล้วราคาขนาดนี้ถือว่าคุ้มค่ามาก ผมไปนั่งพลิกดูด้านหลังเครื่อง fx-9860GIII ปรากฎเห็น “Made in Thailand” ค่อนข้างประหลาดใจพอสมควร พอไปพลิกดูเครื่อง fx-cg50 กลับเป็น “Made in China”
วิธีการติดตั้งโปรแกรมไพทอนลงบนเครื่องคิดเลข
ผมเคยเห็นแผ่นผีลงโปรแกรมคำนวณวงรอบ “Traverse Pro” ที่ศูนย์ไอทีหลายแห่งเมื่อประมาณ 7-8 ปีที่แล้ว ก็สงสัยอยู่ครามครันว่าโปรแกรมมันแจกฟรีในบล็อกผมอยู่แล้ว ทำไมคนยังต้องซื้อแผ่นผีอีก ก็มานึกได้ว่าในยุคนั้นสังคมโซเชียลยังไม่เบ่งบานเท่าปัจจุบัน คนที่ไม่รู้ก็ไม่มีเครือข่ายบอกกันต่อ เช่นเดียวกัน ผมคิดว่าการก็อปปี้โปรแกรมภาษาไพทอนลงเครื่องคิดเลขเป็นเรื่องง่ายๆ ที่ใครๆเข้าใจได้ คงจะไม่ใช่ เลยจัดทำวิธีการติดตั้งลงโปรแกรมภาษาไพทอนลงเครื่องคิดเลข ขั้นตอนก็ไปดาวน์โหลดโปรแกรมจากบล็อกนี้เข้าเครื่องคอมพิวเตอร์ จากนั้นเอาสายเคเบิ้ลมินิยูเอสบี มาเสียบเครื่องคอมพิวเตอร์และเครื่องคิดเลขจากนั้นทำตามคู่มือลิ๊งค์นี้ครับ
ชุดโปรแกรมพื้นฐานงานสำรวจ COGO (Coordinate Geometry) ชุดที่ 4
มาถึงโปรแกรมพื้นฐานงานสำรวจชุดที่ 4 (COGO Selected Serie 4) ซี่รี่ย์ว่าด้วยเรื่องการยืดจุดเส้นตรงในสามมิติไปยังระนาบ (plane) หรือการยืดจุดจากเส้นตรงสามมิติเมื่อทราบระยะทาง ตลอดจนการคำนวณหาพื้นที่ (area) และสุดท้ายคือโปรแกรมมาร์คแกน (mark axis) ซึ่งรายละเอียดมาดูกันอีกทีว่าใช้งานและการประยุกต์ใช้งานอย่างไรบ้าง
ส่วนประกอบของโปรแกรม
สำหรับโปรแกรมพื้นฐานงานสำรวจในชุดนี้จะจัดโปรแกรมย่อยเล็กๆ ไว้ 4 โปรแกรม เนื่องจากหน้ากว้างของหน้าจอเครื่องคิดเลขมีแค่ 21 ตัวอักษร ดังนั้นบางอย่างผมใช้คำย่อเช่น Ext ย่อมาจาก Extend แปลว่ายืดหรือขยาย และคำว่า Pt ย่อมาจาก point คือจุดนั่นเอง
- Ext Line to Plane เมื่อรู้ค่าพิกัดของเส้นตรง (X,Y,Z) 2 จุด และระนาบที่กำหนดด้วยจุด (X,Y,Z) 3 จุด สามารถยืดเส้นตรงไปแตะระนาบแล้วหาจุดพิกัด (X,Y,Z) นั้นได้
- Ext Pt from 3D Line เมื่อรู้ค่าพิกัดของเส้นตรง (X,Y,Z) 2 จุด ต้องการยืดระยะทางไปตามที่กำหนด สามารถหาจุดพิกัด (X,Y,Z) นั้นได้
- Calculate Area เมื่อกำหนดจุดค่าพิกัดของแปลงพื้นที่ดินรอบรูป สามารถป้อนค่าพิกัดเพื่อคำนวณหาพื้นที่ได้
- Mark Axis ต้องการมาร์คแกนโดยที่รู้ค่า design และที่หน้างานทำการวางจุดด้วยกล้องโททัลสเตชั่น ทำการคำนวณด้วยเครื่องคิดเลขเพื่อหาจุดได้ 2 จุดลากเส้นเชื่อม เมื่อครบ 4 จุด จะได้เส้นตรงสองเส้นตัดกันเป็นมุม 90 องศา
วิธีการใช้งานโปรแกรม
กดคีย์ “MENU” ที่เครื่องคิดเลข กดคีย์ลูกศรเลื่อนไปที่ไอคอน “Python” กดเข้าไป ตรงนี้ผมสร้างโฟลเดอร์ชื่อ “PROGRAM” ผมเอาซอร์สโค้ดโปรแกรมไพทอนมาไว้ที่นี่ เมื่อกด “EXE” เข้าไปจะเห็นไฟล์ซอร์สโค้ดไพทอนเรียงกันประมาณนี้ ตอนนี้จะรันไฟล์ COGOSSE4.py ซึ่งจะต้องมีไฟล์ไลบรารี pbrutils.py ด้วย
Ext Line to Plane
โปรแกรมช่วยคำนวณการยืดเส้นตรงในระบบสามมิติไปตัดหรือทะลุระนาบสามมิติ โดยที่ทราบค่าพิกัดของเส้นตรง 2 จุด (X, Y, Z) และทราบค่าพิกัดของระนาบ 3 จุด (X, Y, Z)
กำหนดค่าพิกัดเส้นตรงจุดที่ 1 (N=5002.002, E=3001.001, Elev=49.090) และจุดที่ 2 (N=4996.288, E=3005.543mE, Elev=54.190) และกำหนดระนาบ
- จุดที่ 1 N=5010.456, E=3010.123, Elev=55.678 m
- จุดที่ 2 N=5008.939, E=3005.515, Elev=52.010 m
- จุดที่ 3 N=5009.999, E=3007.777, Elev=58.888 m
ต้องการหาจุดที่เส้นตรงไปตัดระนาบและหามุมที่ทำกับระนาบ
ที่เมนูกดคีย์ “1” และกดคีย์ “EXE” โปรแกรมจะถามค่าพิกัดเส้นตรงจุดที่ 1 และจุดที่ 2 จากนั้นจะถามค่าพิกัดจุดของระนาบจำนวน 3 จุด
จะได้จุดตัด N = 5006.301, E = 2997.584 และ Z = 45.253 และมุมที่เส้นตรงทำกับ plane 52.0219724 องศาจากระนาบ X-Y
Ext Pt from 3D Line
โปรแกรมสำหรับยืดเส้นตรงในระบบ 3 มิติไปตามระยะทางที่กำหนด จากไดอะแกรมด้านล่างรูปซ้ายเป็นเป้าที่มี 2 ปริซึม กล้องโททัลสเตชัน สามารถวัดค่าพิกัดจุด 1 (N1, E1, Z1) และจุดที่ 2 (N2, E2, Z2) เมื่อทราบความสูงโพล d ก็สามารถหาค่าพิกัดของจุด P ที่ซ่อนอยู่ได้
ส่วนรูปด้านขวาจะเป็นจุด P ที่มุมห้องที่กล้องโททัลสเตชันมองไม่เห็น ลากเทปเหล็กออกมาวัดค่าพิกัดแบบ Reflector-less ที่ 4 เมตร และ 2 เมตร ดังนั้นระยะทางที่ยืดไปหามุมห้องเท่ากับ 2 เมตร สามารถหาค่าพิกัดที่มุมห้องได้เช่นกัน
โจทย์กำหนดเส้นตรง จุดที่ 1 (N = 5184.542, E = 1723.884, Elev = 68.888) และจุดที่ 2 (N = 5185.409, E = 1732.676, Elev = 69.010) ยืดจุดจากจุดที่ 2 ไปอีก 3.075 เมตร ต้องการทราบค่าพิกัดของจุดนี้
ที่เมนูกดคีย์ “2” และกดคีย์ “EXE” โปรแกรมจะถามค่าพิกัดเส้นตรงจุดที่ 1 และจุดที่ 2 จากนั้นจะถามระยะทางที่ต้องการยืดหรือขยายออกไป
จะได้คำตอบคือ N = 5185.711, E = 1735.736 และ Elev = 69.052
Calculate Area
การคำนวณพื้นที่เมื่อกำหนดค่าพิกัดฉากของจุดรอบแปลงปิด โดยการใช้สูตร Shoelace formula หรือสูตรผูกเชือกรองเท้า ที่อาศัยการคูณไขว้ ได้เท่าไหร่จับมาลบกันแล้วหารด้วยสอง
กำหนดจุดตารางด้านล่าง ต้องการหาพื้นที่
Point | Northing | Easting |
1 | 565.323m | 544.145m |
2 | 564.690m | 577.134m |
3 | 587.898m | 579.579m |
4 | 594.486m | 565.478m |
5 | 585.709m | 533.921m |
ที่เมนูกดคีย์ “3” และกดคีย์ “EXE” โปรแกรมจะถามค่าพิกัดจุดที่ 1 จุดที่ 2 จุดที่ 3 เมื่อต้องการปิดให้ย้อนมาป้อนจุดที่ 1 อีกครั้ง (รูปด้านล่างเน้นด้วยสี่เหลี่ยมสีแดง) โปรแกรมจะหยุดให้ป้อนค่าพิกัดและคำนวณพื้นที่มาให้
ได้คำตอบคือพื้นที่ 1025.991 ตารางเมตร
Mark Axis
ในงานก่อสร้างบางอย่างเช่นหัวเสาหรือฟุตติ้ง จำเป็นต้องมีการตีแกนให้โดยการตีเต๊า เพื่อเป็นเส้น reference ให้ทางช่างก่อสร้างหน้างานสามารถวัดออฟเซ็ทด้วยตลับเมตรหรือเรียกง่ายๆว่าแทงตลับเมตร เพื่อติดตั้งฟอร์มเวิร์คหรือทำอย่างอื่นได้ง่ายๆ สิ่งที่ช่างสำรวจต้องรู้คือค่าพิกัดจุดศูนย์กลางและอะซิมัทของแกน รูปด้านล่างเป็นหัวเสากว้าง 1 เมตร ยาว 2 เมตร จุด C หรือจุดศูนย์กลางอยู่ที่ N = 2000m, E= 1000m อะซิมัทของหัวเสาเอียงอยู่ 40°12’30” จากทิศเหนือ โจทย์ต้องการมาร์คจุดศูนย์กลาง และมาร์คจุดหมายเลข 1, 2, 3 และ 4 จากนั้นก็ตีเต๊าเส้น 1-3 (แกน Y) เส้น 2-4 (แกน X)
ถ้าคิดว่าแกน YX มีจุดกำเนิด (origin) ผ่านจุดศูนย์กลางหัวเสาพอดี ค่าพิกัดจุดที่ 1 จะเป็น Y = 2, X = 0 จุดที่ 2 Y = 0, X = 1 จุดที่ 3 Y = -2, X = 0 และจุดที่ 4 Y = 0, X = -1
ที่เมนูกดคีย์ “4” และกดคีย์ “EXE” โปรแกรมจะถามค่าพิกัด (Design) จากนั้นจะถามค่าพิกัดที่เก็บได้ (Actual) จากหน้างาน ณ ตอนนั้นจากกล้องโททัลสเตชั่น จากนั้นจะคำนวณค่า Deviated เมื่อเทียบกับแกน NE และ แกน YX เราจะใช้ค่านี้ในการขยับจุดเพื่อให้เข้าหาแกน
ต้องการมาร์คจุด C หรือจุดศูนย์กลาง วัดค่าพิกัดได้ N = 1999.982 E = 1000.025
จะได้ผลลัพธ์ NE: -0.018 0.025 และ YX: 0.002 0.031 ตัวเลขนี้บอกอะไรเราได้บ้าง ผมขยายรูปด้านบนและเขียนขนาดมิติ ค่า ΔN = -0.018 ΔE = +0.025 เมื่อเทียบกับพิกัดฉากที่เราใช้คือ NE ส่วนพิกัดฉาก YX คือพิกัดฉากของหัวเสาโดยที่ค่า ΔY = +0.002 ΔX = +0.031แสดงว่าจุดใหม่ที่จะวางเกินไป 0.002 ต้องขยับตามแกน Y ลงมาให้เท่ากับศูนย์ และเช่นเดียวกันเกินไป 0.031 ต้องขยับตามแกน X ไปด้านซ้ายให้เท่ากับศูนย์ ขยับจุดใหม่ป้อนค่าพิกัดเข้าโปรแกรมปรับจนได้ค่าเบี่ยงเบนเท่ากับศูนย์ YX: 0.000 0.000 จะได้จุดศูนย์กลาง
ต่อไปมาร์คจุดที่ 1 ถ้าคิดว่าทำการวางจุดอ่านจากกล้องโททัลสเตชั่นได้ N = 2001.514 E = 1001.292 ทำการป้อนค่าเข้าไปในโปรแกรม
จะได้ค่าเบี่ยงเบน NE: 1.514 1.292 และ YX: 1.990 0.009 ในที่นี้เราต้องการค่าพิกัดเทียบกับแกน YX โดยที่ Y = 2, X = 0 (ดูรูปแรก) ดังนั้นต้องขยับไปตามแกน Y ขี้นไปเท่ากับ 0.010 ถึงจะได้ 2 เมตรพอดี และตัวเลข 0.009 เกินจากแกน X ไปด้านขวา ต้องขยับไปด้านซ้าย 0.009 เพื่อลดลงเท่ากับศูนย์ เมื่อได้จุดที่ต้องการจะได้ค่า YX: 2.000 0.000 ทำการวางจุดที่ 2, 3 และ 4 ด้วยวิธีการเดียวกันนี้ จากนั้นทำการตีเต๊าเชื่อมจุดจะได้เส้น 2 เส้นตัดกันเป็นมุมฉาก
สรุป
ก็จบไปแล้วครับชุดโปรแกรมพื้นฐานงานสำรวจชุดที่ 4 (COGO Selected Serie 4) จะเห็นแต่ละโปรแกรมไม่มีกราฟฟิควาดรูปมาให้ดูด้วย ผมพยายามลองวาดด้วยไลบรารี matplotl.py แต่โปรแกรมหลุดบ่อย เลยล้มเลิกไป อนาคตถ้าคาสิโอเตรียมไลบรารีมาดีและเสถียรกว่านี้ ผมจะย้อนมาแก้ไขโค้ด เพิ่มส่วนวาดรูป
หลายปีที่ผ่านมายอมรับว่าไม่ได้ติดตามตลาดเครื่องคิดเลขมากนัก ผมลองดูเครื่องคิดเลขในท้องตลาดตอนนี้ยี่ห้อ TI ก็มีหลายรุ่นที่เขียนภาษาไพทอนได้ แต่ที่เหนือกว่าคาสิโอ คือมีไลบรารีต่างๆที่ TI เตรียมมาให้ด้วยเช่นฟังก์ชั่นการวาดรูป การอ่านเขียนไฟล์ แต่เมื่อข้ามไปยี่ห้อ HP รุ่น Prime พบว่าสถาปัตยกรรมเหมือนของโทรศัพท์มือถือคือใช้ซีพียูของอาร์ม (Arm V7) ซีพียูแรงกว่าแต่ต้องแลกกับพลังงานที่มากกว่า ใช้ถ่านชาร์จอาจจะต้องชาร์จกันบ่อย ที่น่าสนใจคือโปรแกรมมิ่งใช้ภาษาปาสคาล (Pascal-like) ที่ผมคุ้นเคยอยู่ ว่างๆว่าจะถอยมาเล่นๆอีกสักเครื่อง ราคาก็สูงอยู่ขนหน้าแข้งคงจะร่วงอีกหลายเส้น โปรดติดตามบทความตอนต่อไปครับ
ซอร์สโค้ดโปรแกรมพื้นฐานงานสำรวจชุดที่ 4 (COGOSSE4.py)
from pbrutils import split_angle,deg2dms,DMS2str from pbrutils import calcAzimuth,calcDistance,calcDiff2Angle from pbrutils import calcNextAzimuth from pbrutils import calcIntersectionAzimuthAzimuth,equation_plane from pbrutils import PI,DEG2RAD,RAD2DEG,mean,calcNextCoordinate2D from pbrutils import isect_line_plane_v3_4d from pbrutils import calcExtend3DLineCoords,area_by_shoelace import math def print_menu(): print('COGO Selected Serie 4') print('1:Ext Line to Plane') print('2:Ext Pt from 3D Line') print('3:Calculate Area') print('4:Mark Axis') print('5:Exit') def extend_line_to_plane(): print('Extend Line to Plane:') print("Input Line:") #n1,e1,z1=1.0,4.0,1.0 n1=float(input("N1=?")) e1=float(input("E1=?")) z1=float(input("Z1=?")) #n2,e2,z2=-2.0,8.0,-2.0 n2=float(input("N2=?")) e2=float(input("E2=?")) z2=float(input("Z2=?")) print("Input 3 pts of Plane:") #n3,e3,z3=2.0,-1.0,4.0 n3=float(input("N3=?")) e3=float(input("E3=?")) z3=float(input("Z3=?")) #n4,e4,z4=1.0,2.0,3.0 n4=float(input("N4=?")) e4=float(input("E4=?")) z4=float(input("Z4=?")) #n5,e5,z5=3.0,1.0,2.0 n5=float(input("N5=?")) e5=float(input("E5=?")) z5=float(input("Z5=?")) a,b,c,d=equation_plane(n3,e3,z3,n4,e4,z4,n5,e5,z5) plane=[a,b,c,d] pi,ang=isect_line_plane_v3_4d([e1,n1,z1],[e2,n2,z2],plane) if pi: print("Intersection point:") print("N= {0:.3f}".format(pi[1])) print("E= {0:.3f}".format(pi[0])) print("Z= {0:.3f}".format(pi[2])) print("Angle: {:.7f} deg".format(ang*RAD2DEG)) else: print("Not intersect plane!") input("Press any key") def extend_point_from_3Dline(): print("Ext point from 3D line.") print("Input Line:") n1=float(input("N1=?")) e1=float(input("E1=?")) z1=float(input("Z1-?")) n2=float(input("N2=?")) e2=float(input("E2=?")) z2=float(input("Z2=?")) print("Input extend distance:") ext=float(input("Extend dist=?")) n3,e3,z3=calcExtend3DLineCoords(n1,e1,z1,n2,e2,z2,ext) print("Ext pt coordinates:") print("N= {:.3f}".format(n3)) print("E= {:.3f}".format(e3)) print("Z= {:.3f}".format(z3)) input("Press any key") def calculate_area(): pts=[] i=1 print("Calculate area.") print("Input points:") n0=float(input("N1=?" )) e0=float(input("E1=?" )) pts.append((n0,e0)) x0,y0=e0,n0 f = True while f: y=float(input("N{}=?".format(i+1))) x=float(input("E{}=?".format(i+1))) pts.append((y,x)) if (i>2): if (x==x0) and (y==y0): f=False i+=1 y,x=zip(*pts) area=area_by_shoelace(x,y) print("Result of calculation:") print("Area= {:0.3f}".format(area)) input("Press any key") def mark_axis(): f=True print("Mark Axis.") print("Input Design:") nde=float(input("N=?" )) ede=float(input("E=?" )) az1=input("Azimuth=?") azi1=split_angle(az1)*DEG2RAD while f: print("Input Actual:") nac=float(input("N=?" )) eac=float(input("E=?" )) azide2ac=calcAzimuth(nde,ede,nac,eac) dist=calcDistance(nde,ede,nac,eac) print("Dist= {:.3f}".format(dist)) print("Deviated:") print("NE: {:.3f} {:.3f}".format(nac-nde,eac-ede)) xy1=dist*math.cos(azide2ac-azi1) xy2=dist*math.sin(azide2ac-azi1) print("YX: {:.3f} {:.3f}".format(xy1,xy2)) print("Total {:.3f}".format(dist)) con=input("Continue (Y/N)?") if con=="Y" or con=="y": f=True else: f=False loop=True choice=-1 ex_choice=-1 while loop: print_menu() choice=int(input('Selection[1-5]')) if (choice==5): loop=False elif (choice==1): loop=True extend_line_to_plane() ex_choice=1 elif (choice==2): loop=True extend_point_from_3Dline() ex_choice=2 elif (choice==3): calculate_area() loop=True ex_choice=3 elif (choice==4): loop=True mark_axis() ex_choice=4
ไลบรารี pbrutils.py
import math PI=math.pi DEG2RAD=PI/180.0 RAD2DEG=180.0/PI TOLERANCE=1e-10 def clear(): for i in range(6): print() def split_angle(st): ss=st.split('-') j=0 d,m,s=0.0,0.0,0.0 for c in ss: if j==0: d=float(c) elif j==1: m=float(c) elif j==2: s=float(c) j+=1 return d+m/60.0+s/3600.0 def deg2dms(dd): sign=1 if (dd<0): sign=-1 dd=abs(dd) minutes,seconds=divmod(dd*3600,60) degrees,minutes=divmod(minutes,60) return (sign,degrees,minutes,seconds) def DMS2str(degree,minute,second,numdec): degree=abs(degree); minute=abs(minute); second=abs(second) s='{:.%df}' % numdec ss=s.format(second) smin=s.format(60.0) mm='{:.0f}'.format(minute) if (ss==smin): minute+=1 ss=s.format(0.0) if (minute>=60): mm='0' degree+=1 else: mm='{:.0f}'.format(minute) return '{:.0f}'.format(degree)+"-"+mm+"-"+ss def calcDistance(n1,e1,n2,e2): return (math.sqrt(math.pow(n2-n1, 2.0) + math.pow(e2-e1, 2))) def calcAzimuth(n1,e1,n2,e2): """ atan2 not same as excel function""" angle=math.atan2(e2-e1,n2-n1) if angle>=0: return angle else: return angle+2*PI def calcDiff2Angle(azi2,azi1): temp=azi2-azi1 if (temp<0): return temp + 2*PI else: return temp def calcNextAzimuth(currentang,prevazi): temp=currentang+prevazi if (temp<PI): temp=temp+PI elif (temp>3*PI): temp=temp-3*PI else: temp=temp-PI return temp def calcNextCoordinate2D(n,e,prevazi,horang,griddist): nextazi=calcNextAzimuth(horang,prevazi) nt=n+math.cos(nextazi)*griddist et=e+math.sin(nextazi)*griddist return [nt,et] def calcNextCoordinate3D(n,e,z,prevazi,horang,verang,slopedist,hi,ht): hordist=slopedist*math.sin(verang) verdist=slopedist*math.cos(verang) nextazi=calcNextAzimuth(horang,prevazi) nt=n+math.cos(nextazi)*hordist et=e+math.sin(nextazi)*hordist zt=z+hi+verdist-ht return [nt,et,zt] def mean(num): sum_num = 0 for t in num: sum_num = sum_num + t avg = sum_num / len(num) return avg def calcIntersectionFrom4Points(pt1, pt2, pt3, pt4): '''Compute the intersection points which given 4 points. If intersection on line return point otherwise return None. ''' azimuth12 = calcAzimuth(pt1, pt2) distance12 = calcDistance(pt1, pt2) azimuth34 = calcAzimuth(pt3, pt4) distance34 = calcDistance(pt3, pt4) #print('++++ pt1 pt2 pt3 pt4 azimuth12 azimuth34 = ', pt1, pt2, pt3, pt4, azimuth12, azimuth34) if (math.abs(azimuth12 - (0.5 * PI)) <= TOLERANCE) or (math.abs(azimuth12 - (1.5 * PI)) <= TOLERANCE): pti = [(pt1[1] - pt3[1]) * math.tan(azimuth34) + pt3[0], pt1[1]] elif (azimuth34 == (0.5 * PI)) or (azimuth34 == (1.5 * PI)): pti = [(pt3[1] - pt1[1]) * math.tan(azimuth12) + pt1[0], pt3[1]] elif (azimuth34 == azimuth12): return [] else: y = (math.tan(azimuth34) * pt3[1] - math.tan(azimuth12) * pt1[1] + pt1[0] - pt3[0]) / (math.tan(azimuth34) - math.tan(azimuth12)) x = (y - pt1[1]) * math.tan(azimuth12) + pt1[0] pti = [x, y] dist1ni = calcDistance(pt1, pti) dist2ni = calcDistance(pt2, pti) dist3ni = calcDistance(pt3, pti) dist4ni = calcDistance(pt4, pti) if (math.abs((dist1ni + dist2ni) - distance12) <= TOLERANCE) and (math.abs((dist3ni + dist4ni) - distance34) <= TOLERANCE): return pti else: return [] def calcIntersectionAzimuthAzimuth(pt1,azimuth1,pt2,azimuth2): '''Azimuth is radian''' n1=pt1[0] #N e1=pt1[1] #E n2=pt2[0] e2=pt2[1] delty=n2-n1 deltx=e2-e1 ni=(math.tan(azimuth2)*n2-math.tan(azimuth1)*n1+e1-e2)/(math.tan(azimuth2)- math.tan(azimuth1)) ei=(ni-n1)*math.tan(azimuth1)+e1 return [ni,ei] def equation_plane(y1, x1, z1, y2, x2, z2, y3, x3, z3): '''Function to find equation of plane.''' a1 = x2 - x1 b1 = y2 - y1 c1 = z2 - z1 a2 = x3 - x1 b2 = y3 - y1 c2 = z3 - z1 a = b1 * c2 - b2 * c1 b = a2 * c1 - a1 * c2 c = a1 * b2 - b1 * a2 d = (- a * x1 - b * y1 - c * z1) # plane equation is ax + by + cz + d = 0 return [a,b,c,d] def shortest_distance_point_to_plane(y1, x1, z1, a, b, c, d): '''Function to find distance. 3D point to plane.''' d = abs((a * x1 + b * y1 + c * z1 + d)) e = math.sqrt(a * a + b * b + c * c) return d/e def distance_point_to_3Dline(y1,x1,z1,y2,x2,z2,y3,x3,z3): '''3D point y1,x1,z1 3D line from y2,x2,z2 to y3,x3,z3''' b = math.sqrt((x2-x3)**2+(y2-y3)**2+(z2-z3)**2) S = math.sqrt(((y2-y1)*(z3-z1)-(z2-z1)*(y3-y1))**2 + ((z2-z1)*(x3-x1)-(x2-x1)*(z3-z1))**2 + ((x2-x1)*(y3-y1)-(y2-y1)*(x3-x1))**2) / 2.0 return 2*S/b def calcExtend3DLineCoords(n1,e1,z1,n2,e2,z2,dist): lenAB = math.sqrt((n2-n1)**2+(e2-e1)**2+(z2-z1)**2) n3=n2+(n2-n1)/lenAB*dist e3=e2+(e2-e1)/lenAB*dist z3=z2+(z2-z1)/lenAB*dist return [n3,e3,z3] def isect_line_plane_v3_4d(p0, p1, plane, epsilon=1e-6): u = sub_v3v3(p1, p0) dot = dot_v3v3(plane, u) if abs(dot) > epsilon: # Calculate a point on the plane # (divide can be omitted for unit hessian-normal form). p_co=mul_v3_fl(plane,-plane[3]/len_squared_v3(plane)) w = sub_v3v3(p0, p_co) fac = -dot_v3v3(plane, w)/dot ang=math.acos(dot/(math.sqrt(len_squared_v3(plane))*math.sqrt(len_squared_v3(u)))) if ang>math.pi/2.0: ang-=math.pi/2.0 u = mul_v3_fl(u, fac) return add_v3v3(p0, u),ang else: return None,None def area_by_shoelace(x, y): '''Assumes x,y points go around the polygon in one direction''' return abs(sum(i * j for i, j in zip(x, y[1:] + y[:1])) -sum(i * j for i, j in zip(x[1:] + x[:1], y))) / 2 # generic math functions def add_v3v3(v0, v1): return ( v0[0] + v1[0], v0[1] + v1[1], v0[2] + v1[2], ) def sub_v3v3(v0, v1): return ( v0[0] - v1[0], v0[1] - v1[1], v0[2] - v1[2], ) def dot_v3v3(v0, v1): return ( (v0[0] * v1[0]) + (v0[1] * v1[1]) + (v0[2] * v1[2]) ) def len_squared_v3(v0): return dot_v3v3(v0, v0) def mul_v3_fl(v0, f): return ( v0[0] * f, v0[1] * f, v0[2] * f, )
ขอบคุณครับ
ยินดีครับ