0
0

外接円の半径「高校入試チャレンジ問題 円Oの面積を求めよ(中学生の力で)」をsympyとFreeCADでやってみたい。

Last updated at Posted at 2024-09-06

・問題文は2次元ですが、3次元FreeCADのマクロで、XY平面上に作図しました。
・やっていて、何をやっているか、わからかくなりました。

オリジナル

・YUUU0123 様 (0:00〜4:01)

sympyで(オリジナル 様の方法を参考に)

・解説を聞いていると、正弦定理の証明のような。気のせい???

ver0.1 >1:2:√3 なので...

# ver0.1 >1:2:√3 なので...
from sympy import *
AB,BC=2,7
BD=AB*Rational(1,2)
AD=BD*sqrt(3)
DC=BC-BD
AC=sqrt(AD**2+DC**2) ;print("#",AC)
l =AC/AD*2           ;print("#",l)
r =l/2               ;print("#",r)
print("#",pi*r**2)
# sqrt(39)
# 2*sqrt(13)
# sqrt(13)
# 13*pi

ver0.2 Youtubeのコメント様より 中心角120°

・1:1:√3

# ver0.2 Youtubeのコメント様より 中心角120° 
from sympy import *
var('r',real=True,positive=True)
AB,BC=2,7
BD=AB*Rational(1,2)
AD=BD*sqrt(3)
DC=BC-BD
AC=sqrt(AD**2+DC**2) ;print("#",AC)
r =AC/sqrt(3)        ;print("#",r)
print("#",pi*r**2)
# 13*pi

ver0.3 Youtubeのコメント様より.方べきの定理。

難しそうなので、省略

sympyで(いつもの方法で)

ver0.4 三平方の定理の方程式で。

Youtubeの私のコメントより。(再掲)

(中学生の力で)三平方の定理の方程式で。
勇者が、原点から点Aへ。
・点Dを通る  道順 北へsqrt(r^2-3.5^2)    ,西へ(3.5-1),北へsqrt(3)
・点Dを通らない道順 北へsqrt(r^2-3.5^2)+sqrt(3),西へ(3.5-1)
??? 帰り道(逆順)のほうが、わかりやすいカモ。省略。つづきは、私のQiitaのホームページで。

# ver0.4 三平方の定理の方程式で。
from sympy import *
var  ('r',real=True,positive=True)
print("#",solve(Eq((sqrt(r**2-Rational(7,2)**2)+sqrt(3))**2+(Rational(7,2)-1)**2,r**2),r)[0]**2*pi)
# 13*pi

ver0.5 ver0.4の「勇者の行進」をもっとsympy風にしました。

・道順通りです。

# ver0.5 ver0.3の「勇者の行進」をもっとsympy風にしました。
from sympy import *
var ('r',real=True,positive=True)
AB,BC=2,7
O=  Point(0      ,0)
E=O+Point(0      ,sqrt(r**2-(BC/2)**2))
D=E+Point(-BC/2+1,0)
A=D+Point(0      ,AB/2*sqrt(3))
print("#",solve(Eq(O.distance(A),r),r)[0]**2*pi)
# 13*pi
print("#",float(solve(Eq(O.distance(A),r),r)[0]))
# 3.605551275463989

ver0.6 何も、東西南北に移動する必要もありませんでした。点Bへナナメに。

# ver0.6 何も、東西南北に移動する必要もありませんでした。点Bへナナメに。
from sympy import *
var ('r',real=True,positive=True)  # pi/2<t<pi
AB,BC=2,7
O=  Point(0    ,0)
B=O+Point(-BC/2,sqrt(r**2-(BC/2)**2))
A=B+Point( AB/2,AB/2*sqrt(3))              # (AB*cos(rad(6)),AB*sin(rad(6)))
print("#",solve(Eq(O.distance(A),r),r)[0]**2*pi)
# 13*pi

ver0.7 点C経由

(省略)

ver0.8 余弦定理、正弦定理。使うなといわれたら、なおさら...

# ver0.8 余弦定理、正弦定理。使うなといわれたら、なおさら...
from sympy import *
var('BC,R',real=True,positive=True)
BC=solve(Eq(2**2+7**2-2*2*7*cos(rad(60)),BC**2),BC)[0]
R =solve(Eq(BC/sin(rad(60))             ,2*R  ),R )[0]
print("#",R**2*pi)
# 13*pi

ver0.9

・私が、最初にうかんだのはコレ。2行で外接円の半径.
・ウラでこっそり、〇〇定理を使っているハズ。
The radius of the circumcircle of the triangle.
https://docs.sympy.org/latest/modules/geometry/polygons.html#sympy.geometry.polygon.Triangle.circumradius

・試験的には、ver0.2 中心角120°が、オススメかも。

# ver0.9 sysmpyのTriangleです。  
from sympy import *
print("#",Triangle(sas=(7,60,2)).circumradius**2*pi)
# 13*pi

FreeCADのマクロで作図

・問題文は2次元ですが、3次元FreeCADのマクロで、XY平面に作図しました。
・計算部分は、Ver.0.4 の コピー貼り付けです。

import FreeCAD
import Part
import DraftTools
import Draft
import Mesh
############################################################################
# # ver0.4 ver0.3の「勇者の行進」をもっとsympy風にしました。
# # ・道順通りです。
from sympy import *
var ('r',real=True,positive=True)
AB,BC=2,7
O=  Point(0      ,0)
E=O+Point(0      ,sqrt(r**2-(BC/2)**2))
D=E+Point(-BC/2+1,0)
A=D+Point(0      ,AB/2*sqrt(3))
print("#",solve(Eq(O.distance(A),r),r)[0]**2*pi)
# # 13*pi
###########################################################################
rep={r:solve(Eq(O.distance(A),r),r)[0]}
A=A.subs(rep)
D=D.subs(rep)
B=Point(-BC/2,D.y)
C=Point(-B.x ,B.y)
r=solve(Eq(O.distance(A),r),r)[0]
############################################################################
# 3D作図 z=0 XY平面に作図しました。
############################################################################
# 円の作図 FrecCADのdocより
# https://wiki.freecad.org/Macro_Circle
def Freecad3D_circle(x=0.0,y=0.0,z=0.0,radius=0.0,diameter=0.0,circumference=0.0,area=0.0,startangle=0.0,endangle=0.0,arc=0.0,anglecenter=0.0,cord=0.0,arrow=0.0,center=0,placemObject=""):
    from math import sqrt, pi
    if placemObject == "":
        pl = FreeCAD.Placement()
        pl.Rotation = FreeCADGui.ActiveDocument.ActiveView.getCameraOrientation()   
        pl.Base = FreeCAD.Vector(x,y,z)
    else:
        pl = FreeCAD.Placement()
        pl = placemObject                                  # placement imposted
    if diameter != 0:                                      # with diameter
        radius = diameter / 2.0
    elif circumference != 0:                               # with circumference
        radius = (circumference / pi) / 2.0
    elif area != 0:                                        # with area
        radius =  sqrt((area / pi))
    elif (cord != 0) and (arrow != 0):                     # with cord and arrow
        radius = ((arrow**2) + (cord**2) / 4.0) / (arrow*2) 
    elif (arc != 0) and (anglecenter != 0):                # with arc and anglecenter central in degrees
        radius = ((360/anglecenter)*arc) / pi/2.0
        if endangle != 0:
            startangle  = endangle - anglecenter
        endangle   = anglecenter + startangle
        startangle  = endangle - anglecenter
    if radius != 0:
        try:
            Draft.makeCircle(radius,placement=pl,face=False,startangle=startangle,endangle=endangle,support=None)
            if center != 0:
                x=pl.Base.x
                y=pl.Base.y
                z=pl.Base.z
                Draft.makePoint(x,y,z)
        except Exception:
            App.Console.PrintError("Unexpected keyword argument" + "\n")
        App.ActiveDocument.recompute()
    else:
        App.Console.PrintMessage("Unexpected keyword argument" + "\n")
        App.Console.PrintMessage("circle(x,y,z,radius,diameter,circumference,area,startangle,endangle,[arc,anglecenter],[cord,arrow],center,placemObject)" + "\n")
        App.Console.PrintMessage("circle(radius=10.0,placemObject=App.Placement(App.Vector(11,20,30), App.Rotation(30,40,0), App.Vector(0,0,0)))" + "\n")
    return
def myCircle_2D(myCi):
    x=myCi.center.x
    y=myCi.center.y
    r=myCi.radius
    Freecad3D_circle(
           x=float(x),y=float(y),z=0.0,
           radius=float(abs(r)),
           center=1,
           placemObject=App.Placement(App.Vector(float(x),float(y),0),
           App.Rotation(0,0,0),App.Vector(0,0,0)))
    return
def myXYZ2Txt_2D(A):
    return ""
def myXYZ2Txt_XY_2D(A):
    return '(' + str(A.x) + ',' + str(A.y) +  ')'
def myTxtXYZ_2D(A,myWedgei):
    P5x=float(A.x)
    P5y=float(A.y)
    P5z=0.0
    p5 = FreeCAD.Vector(P5x, P5y, P5z)
    myText = Draft.makeText(myWedgei, p5)
    myText.Label = myWedgei
    # FreeCADGui.ActiveDocument.ActiveObject.FontSize = '0.7 mm'
    FreeCADGui.ActiveDocument.ActiveObject.FontSize = '0.5 mm'
    # FreeCADGui.ActiveDocument.ActiveObject.FontSize = '1.0 mm'
    return
def myTxtXYZ_S_2D(*xy_tx):
    for i in range(1,int(len(xy_tx)/2)+1):
        myTxtXYZ_2D(xy_tx[2*i-2],xy_tx[2*i-1]+myXYZ2Txt_2D(xy_tx[2*i-2]) )
    return
def myTxtXYZ_XY_S_2D(*xy_tx):
    for i in range(1,int(len(xy_tx)/2)+1):
        myTxtXYZ_2D(xy_tx[2*i-2],xy_tx[2*i-1]+myXYZ2Txt_XY_2D(xy_tx[2*i-2]) )
    return
def myLine_2D(A,B):
    Ax,Ay,Az=float(A.x),float(A.y),0.0
    Bx,By,Bz=float(B.x),float(B.y),0.0
    pl = FreeCAD.Placement()
    pl.Rotation.Q = (0.4247081540122249, 0.17592004639554645, 0.33985110062924484, 0.8204732460821097)
    pl.Base = FreeCAD.Vector(-3.9166066876399563, -2.1670824762243774, 1.7495260956243028)
    points = [FreeCAD.Vector(Ax,Ay,Az), FreeCAD.Vector(Bx,By,Bz)]
    line = Draft.make_wire(points, placement=pl, closed=False, face=True, support=None)
    Draft.autogroup(line)
    return
def myLine_S_2D(*args):
    for i in range(1,len(args)):
        myLine_2D(args[i-1],args[i])
    return
def myLine_C_2D(*args):
    for i in range(1,len(args)):
        myLine_2D(args[i-1],args[i])
    myLine_2D(args[i],args[0])
    return
def myLine_H_2D(*args):
    for i in range(1,len(args)):
        myLine_2D(args[0],args[i])
    return
##################################################################################
myCircle_2D     (Circle(O ,r ))
myLine_C_2D     (A,B,C)  
myTxtXYZ_XY_S_2D(O,"O",A,"A",B,"B",C,"C")
####################################################################################
doc = App.activeDocument()
#App.ActiveDocument.addObject("App::Origin", "Origin")
#App.ActiveDocumen!t.getObject('Origin').Visibility = True
App.ActiveDocument.recompute()
Gui.activeDocument().activeView().viewAxonometric()
Gui.SendMsgToActiveView("ViewFit")

isometric方向?です。(省略)
拡大図
2.png

拡大図(CADの操作で寸法線を追加)
・(青色の)角度寸法は、ニセモノです。Part>計測>角度計算 です。
・角度寸法の表示は、まだ勉強中です。
3.png

いつもの? sympyの実行環境と 参考のおすすめです。

(テンプレート)

・以下ができたら、助かります。指定と全部です

いつもと違うおすすめです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0