0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

平面図形「【高校入試数学 円の難問】...~大分県公立入試数学 解法3通り~」をsympyとFreeCADでやってみたい。

Last updated at Posted at 2025-01-08

・長文です。以下、中学数学の範囲外が含まれています。
・問題文は2次元ですが、3次元FreeCADのマクロで、XY平面上に作図しました。
・AI先生に画像の丸投げ?教えてもらえませんでした。

オリジナル

Youtube

MAスカッと塾 様 (0:00〜12:09) 赤の長さは?
https://youtu.be/t2w040-0M1I

sympyのweb上での実行方法

SymPy Live Shellで。FreeCADのマクロは、以下で実行できません。
https://qiita.com/mrrclb48z/items/00dd08b0317069be9342#web%E4%B8%8A%E3%81%AE%E5%AE%9F%E8%A1%8C%E6%96%B9%E6%B3%95sympy-live-shell%E3%81%A7
 

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

・ver0.1 >相似ですね。...
 ??? 途中だんだんわからなくなってきました。

# ver0.1 >相似ですね。...
from sympy import *    
var('EC,GF,GC,EG',nonnegative=True) 
AD,DE,BC=5,3,2
EC=solve(Eq((AD+DE)/EC,(EC+BC)/DE))[0]                 #;print(EC)
AC=sqrt((AD+DE)**2-EC**2)                              #;print(AC)
trACE=Triangle(sss=(AC,EC,(AD+DE)))                    #;print(trACE)
dgEAC=trACE.angles[trACE.args[0]]*180/pi               #;print(dgEAC) 
trDAF=Triangle(asa=(90,AD,dgEAC))                      #;print(trADF)
DF   =trDAF.args[2].distance(trDAF.args[0])            #;print(DF)
trBCF=Triangle(asa=(dgEAC,BC,90))                      #;print(trBCF)
FC   =trBCF.args[1].distance(trBCF.args[2])            #;print(FC)
trFCE=Triangle(sas=(FC,90,EC))                         #;print(trBCF)
EF   =trFCE.args[1].distance(trFCE.args[2])            #;print(EF)
# ??? だんだんわからなくなってきました。
# AtoI  =Eq(GF/GC,DF/EC)                                #;print(AtoI)
# UtoE  =Eq(GC/EG,FC/DE)                                #;print(AtoI)
FGwGE_numer=DF      *sqrt(3)
FGwGE_denom=EC*DE/FC*sqrt(3)                            # ;print(FGwGE_numer,FGwGE_denom)
print("#",EF*(FGwGE_denom/(FGwGE_numer+FGwGE_denom)))
# 12*sqrt(39)/23

・ver0.2 >EG,GFを間接的に求める。

# ver0.2 >EG,GFを間接的に求める。
from sympy import *    
var('EC,GF,GC,EG,DH,dgEDH,EH,IF',nonnegative=True) 
AD,DE,BC=5,3,2
EC=solve(Eq((AD+DE)/EC,(EC+BC)/DE))[0]           #;print(EC)
AC=sqrt((AD+DE)**2-EC**2)                        #;print(AC)
trACE=Triangle(sss=(AC,EC,(AD+DE)))              #;print(trACE)
dgEAC=trACE.angles[trACE.args[0]]*180/pi         #;print(dgEAC) # 三角定規の角
trDAF=Triangle(asa=(90,AD,dgEAC))                #;print(trADF)
DF   =trDAF.args[2].distance(trDAF.args[0])      #;print(DF)
trBCF=Triangle(asa=(dgEAC,BC,90))                #;print(trBCF)
FC   =trBCF.args[1].distance(trBCF.args[2])      #;print(FC)
trFCE=Triangle(sas=(FC,90,EC))                   #;print(trBCF)
EF   =trFCE.args[1].distance(trFCE.args[2])      #;print(EF)
# >今回...垂線をおろす。
# trDHE=Triangle(asa=(dgEDH,DH,90))
# trFCE=Triangle(asa=(dgEDH,FC,90))
EH=solve(Eq(DE/EH,EF/EC),EH)[0]                  #;print(EH)
# trCIF=Triangle(asa=(dgFCI,CI,90))
# trEDF=Triangle(asa=(dgFCI,DE,90))
IF=solve(Eq(FC/IF,EF/DF),IF)[0]                  #;print(IF)
EG=solve(Eq(EG/GF,EH/IF),EG)[0]                  #;print(EG)
sol_GF=solve(Eq(EG+GF,EF),GF)[0]                 #;print(sol_GF)
print("#",solve(Eq(EG+sol_GF,EF),EG)[0])
# 12*sqrt(39)/23

・ver0.3 メネラウスの定理の利用 >頂点、分点、頂点...
・私は、メネラウスの定理を勉強中です。

# ver0.3 メネラウスの定理の利用 >頂点、分点、頂点...
from sympy import *    
var('EC,GF,GC,EG,DH,dgEDH,EH,IF,FGwGE',nonnegative=True) 
AD,DE,BC=5,3,2
EC=solve(Eq((AD+DE)/EC,(EC+BC)/DE))[0]                   #;print(EC)
AC=sqrt((AD+DE)**2-EC**2)                                #;print(AC)
trACE=Triangle(sss=(AC,EC,(AD+DE)))                      #;print(trACE)
dgEAC=trACE.angles[trACE.args[0]]*180/pi                 #;print(dgEAC) # 三角定規の角
trDAF=Triangle(asa=(90,AD,dgEAC))                        #;print(trADF)
DF   =trDAF.args[2].distance(trDAF.args[0])              #;print(DF)
trBCF=Triangle(asa=(dgEAC,BC,90))                        #;print(trBCF)
FC   =trBCF.args[1].distance(trBCF.args[2])              #;print(FC)
BF   =trBCF.args[2].distance(trBCF.args[0])              #;print(FC)
trFCE=Triangle(sas=(FC,90,EC))                           #;print(trBCF)
EF   =trFCE.args[1].distance(trFCE.args[2])              #;print(EF)
# ここから メネラウスの定理の利用 >頂点、分点、頂点...
BD=BF+DF
FGwGE=solve(Eq(EC/BC*BD/DF*FGwGE,1),FGwGE)[0]            #;print(FGwGE)
print("#",EF*(denom(FGwGE)/(numer(FGwGE)+denom(FGwGE))))
# 12*sqrt(39)/23

sympyで(いつもの方法で)

・ver0.4 AB,CEの連立方程式です。ソージのたいへんさが わかりました。
・>ここで紹介した解法は、あくまでも一例ということでご覧ください。
 高校数学。直角2つ。内積=0 の連立方程式です。
 ??? 長さを計算できるようになっていました。

# ver0.4 AB,CEの連立方程式です。  
from sympy import *
var('AB,CE')  #;とりあえず、符号のため。AB,CE=7,4 # intersectionの判定のため.ロジック調査中
AD,DE,BC=5,3,2
A,B=Point(0,0),Point(AB,0)
E=Circle(A,(AD+DE)).intersection(Circle(B,(BC+CE)))[1]   #;print(E)
C=B+BC*(E-B).unit
D=  AD*    E.unit
sol_AB,sol_CE=solve([Eq((A-E).dot(D-B),0),
                     Eq((A-C).dot(E-B),0)
                    ],[AB,CE])[3]                        #;print(sol_AB,sol_CE)
rep={AB:sol_AB,CE:sol_CE}
B=B.subs(rep)
C=C.subs(rep)
D=D.subs(rep)
E=E.subs(rep)
F=Line(A,C).intersection(Line(B,D))[0]
G=Line(C,D).intersection(Line(E,F))[0]
print("#",E.distance(G).simplify())
# 12*sqrt(39)/23

FreeCADのマクロで作図

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

import FreeCAD
import Part
import DraftTools
import Draft
import Mesh
############################################################################
# ver0.4
from sympy import *
var('AB,CE')  #;AB,CE=7,4 # intersectionの判定のため.ロジック調査中
AD,DE,BC=5,3,2
# tr=Triangle(sss=(AB,BC+CE,AD+DE)) ;print(tr)
A,B=Point(0,0),Point(AB,0)
E=Circle(A,(AD+DE)).intersection(Circle(B,(BC+CE)))[1]   #;print(E)
C=B+BC*(E-B).unit
D=  AD*    E.unit
sol_AB,sol_CE=solve([Eq((A-E).dot(D-B),0),
                     Eq((A-C).dot(E-B),0)
                    ],[AB,CE])[3]                        #;print(sol_AB,sol_CE)
rep={AB:sol_AB,CE:sol_CE}
B=B.subs(rep)
C=C.subs(rep)
D=D.subs(rep)
E=E.subs(rep)
F=Line(A,C).intersection(Line(B,D))[0]
G=Line(C,D).intersection(Line(E,F))[0]
print("#",E.distance(G).simplify())
# 12*sqrt(39)/23
###########################################################################
# 全体の半径分の移動です。点Aを原点としていたため。
r=A.distance(B)/2
O=Point(0,0)
A,B,C,D,E,F,G = (x - Point(r,0) for x in (A,B,C,D,E,F,G))
############################################################################
# 3D作図 z=0 XY平面に作図しました。
# 2024-10-08 fontsize 追加しました。従来と互換性がありません。 
# 2024-10-20 HR 
############################################################################
def myDimension(fontsize,myExtOvershoot,start_point, end_point,HVP):
    x1, y1 = start_point.args
    x2, y2 = end_point.args
    myFlipText = True
    if HVP=="PL":
       myP1  =Point(float(x1),float(y1))
       myP2  =Point(float(x2),float(y2))
       myFlipText = False
       myExtOvershoot1=abs(myExtOvershoot)
    elif HVP=="PR":
       myP1  =Point(float(x1),float(y1))
       myP2  =Point(float(x2),float(y2))
       myFlipText = False
       myExtOvershoot1=-abs(myExtOvershoot)
    elif HVP=="VL":
       if x1<x2 and y1<y2:
          myP1  =Point(float(x1),float(y1))
          myP2  =Point(float(x1),float(y2))
          myExtOvershoot1= abs(myExtOvershoot)
          myFlipText = False
       elif x1<x2 and y1>y2:
          myP1  =Point(float(x1),float(y1))
          myP2  =Point(float(x1),float(y2))
          myExtOvershoot1=-abs(myExtOvershoot)
       elif x1>x2 and y1<y2:
          myP1  =Point(float(x2),float(y1))
          myP2  =Point(float(x2),float(y2))
          myExtOvershoot1= abs(myExtOvershoot)
          myFlipText = False
       else:
          myP1  =Point(float(x2),float(y1))
          myP2  =Point(float(x2),float(y2))
          myExtOvershoot1=-abs(myExtOvershoot)
    elif HVP=="VR":
       if x1<x2 and y1<y2:
          myP1  =Point(float(x2),float(y1))
          myP2  =Point(float(x2),float(y2))
          myExtOvershoot1=-abs(myExtOvershoot)
          myFlipText = False
       elif x1<x2 and y1>y2:
          myP1  =Point(float(x2),float(y1))
          myP2  =Point(float(x2),float(y2))
          myExtOvershoot1= abs(myExtOvershoot)
       elif x1>x2 and y1<y2:
          myP1  =Point(float(x1),float(y1))
          myP2  =Point(float(x1),float(y2))
          myExtOvershoot1=-abs(myExtOvershoot)
       else:
          myP1  =Point(float(x1),float(y1))
          myP2  =Point(float(x1),float(y2))
          myExtOvershoot1= abs(myExtOvershoot)
    elif HVP=="HL":
       if x1 < x2 and y1<y2:
          myP1  =Point(float(x1),float(y2))
          myP2  =Point(float(x2),float(y2))
          myExtOvershoot1= abs(myExtOvershoot)
          myFlipText = False
       elif x1 < x2 and y1>y2:
          myP1  =Point(float(x1),float(y1))
          myP2  =Point(float(x2),float(y1))
          myExtOvershoot1= abs(myExtOvershoot)
          myFlipText = False
       elif x1 > x2 and y1<y2:
          myP1  =Point(float(x1),float(y1))
          myP2  =Point(float(x2),float(y1))
          myExtOvershoot1= abs(myExtOvershoot)
       else:
          myP1  =Point(float(x1),float(y2))
          myP2  =Point(float(x2),float(y2))
          myExtOvershoot1= abs(myExtOvershoot)
    elif HVP=="HR":
       #if x1<x2 and y1<y2: # 2024-10-20 HR
       if x1<x2 and y1<=y2:
          myP1  =Point(float(x1),float(y1))
          myP2  =Point(float(x2),float(y1))
          myExtOvershoot1=-abs(myExtOvershoot)
          myFlipText = False
       elif x1<x2 and y1>y2:
          myP1  =Point(float(x1),float(y2))
          myP2  =Point(float(x2),float(y2))
          myExtOvershoot1=-abs(myExtOvershoot)
          myFlipText = False
       elif x1>x2 and y1<y2:
          myP1  =Point(float(x1),float(y2))
          myP2  =Point(float(x2),float(y2))
          myExtOvershoot1=-abs(myExtOvershoot)
       else:
          myP1  =Point(float(x1),float(y1))
          myP2  =Point(float(x2),float(y1))
          myExtOvershoot1=-abs(myExtOvershoot)
    else:  
      print("")
    myM   =myP1.midpoint(myP2)
    myT   =myM+myExtOvershoot1*((myP1-myM).unit).rotate( -pi/2 )
    dimension = Draft.makeDimension(
        FreeCAD.Vector(myP1.x, myP1.y, 0),           # 点1の座標
        FreeCAD.Vector(myP2.x, myP2.y, 0),           # 点2の座標
        FreeCAD.Vector(float(myT.x),float(myT.y),0)  # 矢印の位置を中央に設定
    )
    # Ext Overshootを設定
    dimension.ViewObject.ExtOvershoot = -float(myExtOvershoot)
    
    dimension.ViewObject.FlipText = myFlipText

    # 矢印のスタイルを設定
    dimension.ViewObject.ArrowType    = "Arrow"  # 矢印のタイプを "Arrow" に設定
    dimension.ViewObject.ArrowSize    = fontsize/5
    dimension.ViewObject.TextSpacing  = 0
    dimension.ViewObject.LineColor    = (0.0, 1.0, 0.0)  # 緑色
    dimension.ViewObject.FontSize     = fontsize  # フォントサイズを指定
def myXYZ2Txt_2D(A):
    return ""
def myXYZ2Txt_XY_2D(A):
    return '(' + str(A.x) + ',' + str(A.y) +  ')'
def myTxtXYZ_2D(fontsize,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 = str(fontsize,)+' mm'
    return
def myTxtXYZ_S_2D(fontsize,*xy_tx):
    for i in range(1,int(len(xy_tx)/2)+1):
        myTxtXYZ_2D(fontsize,xy_tx[2*i-2],xy_tx[2*i-1]+myXYZ2Txt_2D(xy_tx[2*i-2]) )
    return
def myTxtXYZ_XY_S_2D(fontsize,*xy_tx):
    for i in range(1,int(len(xy_tx)/2)+1):
        myTxtXYZ_2D(fontsize,xy_tx[2*i-2],xy_tx[2*i-1]+myXYZ2Txt_XY_2D(xy_tx[2*i-2]) )
    return

def myTxtXYZ_MoveY_2D(fontsize,MoveY,A,myWedgei):
    P5x=float(A.x)
    P5y=float(A.y)+MoveY
    P5z=0.0
    p5 = FreeCAD.Vector(P5x, P5y, P5z)
    myText = Draft.makeText(myWedgei, p5)
    myText.Label = myWedgei
    FreeCADGui.ActiveDocument.ActiveObject.FontSize = str(fontsize,)+' mm'
    return
def myTxtXYZ_XY_S_MoveY_2D(fontsize,MoveY,*xy_tx):
    for i in range(1,int(len(xy_tx)/2)+1):
        myTxtXYZ_MoveY_2D(fontsize,MoveY,xy_tx[2*i-2],xy_tx[2*i-1]+myXYZ2Txt_XY_2D(xy_tx[2*i-2]) )
    return
############################################################################
# 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 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,E,D)  
myLine_S_2D (A,F,C)  
myLine_S_2D (D,F,B)
myLine_S_2D (D,C)
myLine_S_2D (E,G,F)
myFontsize =0.4
myOvershoot=myFontsize*6
myTxtXYZ_XY_S_2D      (myFontsize,O,"O",A,"A",B,"B",C,"C",D,"D")
myTxtXYZ_XY_S_2D      (myFontsize,E,"E",F,"F",G,"G")
myDimension(myFontsize,myOvershoot,A,D,"PL")
myDimension(myFontsize,myOvershoot,D,E,"PL")
myDimension(myFontsize,myOvershoot,C,B,"PL")
myDimension(myFontsize,myOvershoot,E,G,"PL")
####################################################################################
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方向。斜め方向から。
111.png

上空からです。
角度寸法、赤色はCAD操作です。
忘。半円にする。山形県の問題を参照。
未。EGの長さを√で表示する。  以下は小数表示です。
未。赤色の線を太くする。
未。直角マークを表示するコード。

222.png

??? (追加) AI先生へ画像の丸投げをあきらめました。残念。

・(スクショ画像省略)

(だめでした)ChatGPT先生へ

(回答抜粋)
??? >EG=4.8028

あきらめました。

(だめでした)Gemini先生へ

(回答抜粋)
補足:
図が不鮮明なため、正確な解を求めるには、図の情報をより詳細に確認する必要があります。

あきらめました。

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

(テンプレート)

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

sympyのDoc

・ver0.1
class sympy.geometry.polygon.Triangle(*args, **kwargs)
https://docs.sympy.org/latest/modules/geometry/polygons.html#sympy.geometry.polygon.Triangle

numer,denom 分子,分母 ???検索不明

・ver0.2
https://docs.sympy.org/latest/modules/solvers/solvers.html

・ver0.3
(省略)

・ver0.4 (いつもの方法で)

intersection(o)
https://docs.sympy.org/latest/modules/geometry/ellipses.html#sympy.geometry.ellipse.Circle.intersection

・ver0.4 FreeCAD
(テンプレートを参照)

wikipedia

メネラウスの定理

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?