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?

平面図形「銀河最速!「令和7年度 京都府公立高等学校 中期選抜 第5問」様をsympyとFreeCADでやってみたい。

Last updated at Posted at 2025-04-14

長文です。 中学数学の範囲外(三角関数)が含まれています。
・問題文は2次元ですが、3次元FreeCADのマクロで、XY平面上に作図しました。

オリジナル

Youtube

いつもの先生 様 (0:00〜7:20) 
銀河最速!「令和7年度 京都府公立高等学校 中期選抜 第5問
https://youtu.be/1w5b9XkEJGg

PDF

・保護されていない通信
26京都府 <R7年(2025年)全問PDF -4-
http://homepage1.canvas.ne.jp/ynaka/R7PDF/26kyoto.pdf#page=11
< 数学苦手な中学生,応援します 様内
http://homepage1.canvas.ne.jp/ynaka/index.html

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('BE,CD,EF,EG,EI,ID,DJ')
AB=3*sqrt(2)
BC=7
# degABC=45
# degBCD=60
# degBDC=90
BE =solve(Eq(1/sqrt(2),BE/AB),BE)[0]     #;print("#",BE)
CE =BC-BE                                 ;print("#",CE)
CD =solve(Eq(Rational(1,2),CD/BC),CD)[0] #;print("#",CD)
EF =solve(Eq(1/sqrt(3),EF/BE),EF)[0]     #;print("#",EF)
EG =solve(Eq(1/sqrt(3),EG/CE),EG)[0]     #;print("#",EG)
FG =EG-EF                                 ;print("#",FG)
CEG=Rational(1,2)*CE*EG                  #;print("#",CEG)
EI =solve(Eq(CE/CD     ,EI/ID),EI)[0]    #;print("#",EI) # 角の二等分線
DJ =solve(Eq(2 /sqrt(3),CD/DJ),DJ)[0]    #;print("#",DJ) 
CED=Rational(1,2)*CE*DJ                  #;print("#",CED)
CEI=CED*EI/(EI+ID)                       #;print("#",CEI)
FGH=sqrt(3)/4*FG**2                      #;print("#",FGH) # 正三角形
print("#",CEG-CEI-FGH)
# 4
# sqrt(3)/3
# 43*sqrt(3)/60

ver0.2

・正三角形の面積の計をFGの長さを計算せず に。面積比で、EIHFの面積計算。
 ありがたみがありませんでした。

# ver0.2 面積比で
from sympy import *
var('BCD,BD')
BD =Rational(7,2)*sqrt(3)
rep={BCD:Rational(1,2)*BD*BD/sqrt(3)}
BEF=BCD*((3            /BD)**2)             #;print("#",BEF)
ECG=BCD*((4            /BD)**2)              ;print("#",ECG ,",",ECG .subs(rep))
CDH=BCD*((Rational(7,2)/BD)**2)             #;print("#",CDH)
GFH=collect(BEF+ECG+CDH-BCD,BCD)            #;print("#",GFH)
ECI=BCD*Rational(4,7)*4/(4+Rational(7,2))    ;print("#",ECI ,",",ECI .subs(rep))
EIHF=ECG-GFH-ECI                             ;print("#",EIHF,",",EIHF.subs(rep))
# 64*BCD/147 , 8*sqrt(3)/3
# 32*BCD/105 , 28*sqrt(3)/15
# 86*BCD/735 , 43*sqrt(3)/60

ver0.3

・xy座標で。中途半端な感じがします。

# ver0.3 xy座標で。中途半端な感じがします。
from sympy import *
AB    =3*sqrt(2)
BC    =7
# degABC=45
# degBCD=60
# degBDC=90
# 
BE=   AB/sqrt(2)  #;print("#",BE)
CE=BC-BE          #;print("#",CE)
CD=BC/2           #;print("#",CD)
# 
B =  Point(0 ,0)
C =B+Point(BC,0)
D =C+Point(-CD/2     ,CD/2*sqrt(3))
A =B+Point(AB/sqrt(2),AB/sqrt(2)  )
# 
E =  Point(A.x ,0)
F =  Point(A.x ,BE    /sqrt(3))
G =  Point(A.x ,CE    /sqrt(3))
H =  Point(BC/2,(BC/2)/sqrt(3))                         # △BCHは二等辺三角形
I =E+(D-E)*C.distance(E)/(C.distance(E)+C.distance(D))  # 角の2等分線の定理  
FG=G.y-F.y
print("#",CE)
print("#",FG)
print("#",Polygon(E,I,H,F).area)
# 4
# sqrt(3)/3
# 43*sqrt(3)/60

sympyで(いつもの方法で)

・xy平面の三角関数で

ver0.4

# ver0.4 xy平面の三角関数で
from sympy import *
AB    ,BC           =3*sqrt(2),7
radABC,radBCD,radBDC=rad(45),rad(60),rad(90)
# 
B=  Point(0 ,0)
A=B+Point(AB*cos(radABC),AB*sin(radABC))
C=B+Point(BC,0)
D=C+Point(-BC/2*cos(radBCD),BC/2*sin(radBCD) )
E=  Point(A.x  ,0)
F=  Point(E.x  , E.x     *tan(pi-radBCD-radBDC))
G=  Point(E.x  ,(C.x-E.x)*tan(radBCD/2))
H=  Point(C.x/2,(C.x/2)  *tan(radBCD/2))               #△BCHは二等辺三角形
I=E+(D-E)*C.distance(E)/(C.distance(E)+C.distance(D))  # 角の2等分線の定理  
print("#",C.distance(E))
print("#",F.distance(G))
print("#",Polygon(E,I,H,F).area)
# 4
# sqrt(3)/3
# 43*sqrt(3)/60

ver0.5

・何が何でもTriangleで

# ver0.5 
from sympy import *
AB,BC=3*sqrt(2),7
trBEA=Triangle(asa=(45   ,AB/sqrt(2)   ,90))
trBCD=Triangle(asa=(90-60,BC           ,60))
trBEF=Triangle(asa=(30   ,AB/sqrt(2)   ,90))
trECG=Triangle(asa=(90   ,BC-AB/sqrt(2),30))
B,E,A=trBEA.vertices[0],trBEA.vertices[1],trBEA.vertices[2]
C,D  =                  trBCD.vertices[1],trBCD.vertices[2]
F    =                                    trBEF.vertices[2]
G    =E+                                  trECG.vertices[2]
H    =Line(C,G).intersection(Line(B,D))[0]   # ;print(H)     
I    =Line(C,G).intersection(Line(E,D))[0]   # ;print(H)     
print("#",C.distance(E))
print("#",F.distance(G))
print("#",Polygon (E,I,H,F).area)
print("#",Triangle(E,I,H)  .area+Triangle(E,H,F).area)
print("#",Triangle(E,C,G)  .area-Triangle(E,C,I).area-Triangle(F,H,G).area)
# 4
# sqrt(3)/3
# 43*sqrt(3)/60
# 43*sqrt(3)/60
# 43*sqrt(3)/60

ver0.6

・CAD風。
・>AD//BCじゃないの罠すぎませんか?w (Youtubeのコメント様より)

# ver0.6
from sympy import *
AB    =3*sqrt(2)
BC    =7
radABC=rad(45)
radBCD=rad(60)
radBDC=rad(90)
B=  Point(0 ,0)
C=B+Point(BC,0)                                   #;print(C)
A=  Point(AB,0)  .rotate( radABC,B)               #;print(A)
E=  Line (B ,C)  .projection(A)                   #;print(E)
D=  Point(BC/2,0).rotate(-radBCD,C)               #;print(D)
F=Line(E,A).intersection(Line(B,D))[0]            #;print(F)     
G=Line(E,A).intersection(
    Line(C,Point(BC/2,0).rotate(-radBCD/2,C)))[0] #;print(G)     
H=Line(C,G).intersection(Line(B,D))[0]            #;print(H)     
I=Line(C,G).intersection(Line(E,D))[0]            #;print(I)     
print("#",C.distance(E))
print("#",F.distance(G))
print("#",Polygon(E,I,H,F).area)
print("#",float(D.y-A.y))
# 4
# sqrt(3)/3
# 43*sqrt(3)/60
# 0.031088913245535265

FreeCADのマクロで作図

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

# 以下でます。 
# この機能は非推奨です。この機能を直接使用しないでください。
#   「make_linear_dimension」または「make_linear_dimension_obj」のいずれかを使用してください。
import FreeCAD
import Part
import DraftTools
import Draft
import Mesh
# # ##############################################
# ver0.6
from sympy import *
AB    =3*sqrt(2)
BC    =7
radABC=rad(45)
radBCD=rad(60)
radBDC=rad(90)
B=  Point(0 ,0)
C=B+Point(BC,0)                                   #;print(C)
A=  Point(AB,0)  .rotate( radABC,B)               #;print(A)
E=  Line (B ,C)  .projection(A)                   #;print(E)
D=  Point(BC/2,0).rotate(-radBCD,C)               #;print(D)
F=Line(E,A).intersection(Line(B,D))[0]            #;print(F)     
G=Line(E,A).intersection(
    Line(C,Point(BC/2,0).rotate(-radBCD/2,C)))[0] #;print(G)     
H=Line(C,G).intersection(Line(B,D))[0]            #;print(H)     
I=Line(C,G).intersection(Line(E,D))[0]            #;print(I)     
print("#",C.distance(E))
print("#",F.distance(G))
print("#",Polygon(E,I,H,F).area)
print("#",float(D.y-A.y))
# # 4
# # sqrt(3)/3
# # 43*sqrt(3)/60
# # 0.031088913245535265
############################################################################
# 3D作図 z=0 XY平面に作図しました。
# 2024-10-08 fontsize 追加しました。従来と互換性がありません。 
# 2024-10-20 HR 
# 2025-03-27 HL 
############################################################################
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
          #myFlipText = True
       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平面に作図しました。
############################################################################
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
##################################################################################
myLine_C_2D(A,B,E,C,D)
myLine_S_2D(B,F,H,D)  
myLine_S_2D(A,G,F,E)  
myLine_S_2D(C,I,H,G)  
myLine_S_2D(E,I,D)  
myFontsize =0.3
myTxtXYZ_XY_S_2D(myFontsize,A,"A",B,"B",C,"C",D,"D",E,"E",F,"F",G,"G",H,"H",I,"I")
myOvershoot=myFontsize*4
myDimension(myFontsize,myOvershoot,B,A,"PL")
myDimension(myFontsize,myOvershoot,B,C,"HR")
myDimension(myFontsize,myOvershoot,A,D,"VR")
####################################################################################
doc = App.activeDocument()
#
# 2025-03-27 なんだか調子が悪い
# App.ActiveDocument.addObject("App::Origin", "Origin")
# App.ActiveDocumen!t.getObject('Origin').Visibility = True
origin = doc.addObject("App::Origin", "Origin")
# origin.Visibility = True
#
App.ActiveDocument.recompute()
Gui.activeDocument().activeView().viewAxonometric()
Gui.SendMsgToActiveView("ViewFit")

isometric方向。斜め方向から。
111.png
上空からです。平面図です。
・水平方向、鉛直方向、平行寸法は、override(手打ち)しています。
 無理数表示を勉強中です。
・角度寸法は、Measure Angularを使っています。
222.png

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

(テンプレート)

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

ver0.1

・The solvers module in SymPy implements methods for solving equations.
https://docs.sympy.org/latest/modules/solvers/solvers.html

ver0.2

collect() collects common powers of a term in an expression. For example
https://docs.sympy.org/latest/tutorials/intro-tutorial/simplification.html#collect

ver0.3

The area of the polygon.
https://docs.sympy.org/latest/modules/geometry/polygons.html#sympy.geometry.polygon.Polygon.area

ver0.4

rotate(angle, pt=None)
https://docs.sympy.org/latest/modules/geometry/points.html#sympy.geometry.point.Point2D.rotate

ver0.5

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

ver0.6

The intersection with another geometrical entity.
https://docs.sympy.org/latest/modules/geometry/lines.html#sympy.geometry.line.LinearEntity.intersection

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?