円の面積の最小「2023東京都立大前期文系【3】」をsympyとFreeCADでやってみた。

問題文は2次元ですが、３次元FreeCADのマクロで、XY平面上に作図しました。
いつものベクトルの成分表示?です。
並べ替えに、Pythonのbisectを使っています。(参考より)
(未)Freecadの放物線は、勉強中です。

オリジナル

https://youtu.be/8XZj2-SZWhk

上と同じです。大学入試数学問題集成＞【3】テキスト

https://mathexamtest.web.fc2.com/2023/202311261/2023112610100mj.html#top-0109

# sympyで(オリジナルのやり方)
勉強中。sympyのVector Moduleでやってみたい。

# sympyで(sympy的?安易なやり方)
最小値は、minimumと微分diffの
2通りで計算しています。 

```python
from sympy import *
t=symbols('t',real=True,positive=True)
t0,t1=0,1
O=Point(0      ,0   )
A=Point(sqrt(t),t   )
B=Point(0      ,-t+1)
#
Ci=Circle(O,A,B)
S =pi*Ci.radius**2
ans1_y=minimum (     S        ,t,Interval(t0,t1))
ans1_t=solveset(  Eq(S,ans1_y),t,Interval(t0,t1)).args[0]
ans2_t=solveset(diff(S)       ,t,Interval(t0,t1)).args[0]
ans2_y=              S.subs({t:ans2_t})     
print("#(1)  ",Ci.center    )
print("#(2-1)",S.simplify() )
print("#(2-2)",S.expand()   )
print("#(3-1)",ans1_t,ans1_y)
print("#(3-2)",ans2_t,ans2_y)
#plot(0,S,(t,t0,t1))
#(1)   Point2D(t**(3/2), 1/2 - t/2)
#(2-1) pi*(4*t**3 + (t - 1)**2)/4
#(2-2) pi*t**3 + pi*t**2/4 - pi*t/2 + pi/4
#(3-1) 1/3 4*pi/27
#(3-2) 1/3 4*pi/27
```
①私の環境は,pycharmです。
②よく聞くのは、Jupyterです。
③web上で、上記のソースを「SymPy Live shell」に、コピー貼り付けでもできました。
黒背景の右上に、マウスを移動すると、コピーマークが発生します。

https://live.sympy.org/

Sのグラフ:1/3で最小

![0png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/830f6b83-e442-1770-6f69-9ecc9406084e.png)

# FreeCADのマクロで作図
```python
import FreeCAD
import Part
import DraftTools
import Draft
import Mesh
############################################################################
# 計算
# toritu 20223
from sympy import *
t=symbols('t',real=True,positive=True)
t0,t1=0,1
O=Point(0      ,0   )
A=Point(sqrt(t),t   )
B=Point(0      ,-t+1)
#
Ci=Circle(O,A,B)
S =pi*Ci.radius**2
ans1_y=minimum (     S        ,t,Interval(t0,t1))
ans1_t=solveset(  Eq(S,ans1_y),t,Interval(t0,t1)).args[0]
ans2_t=solveset(diff(S)       ,t,Interval(t0,t1)).args[0]
ans2_y=              S.subs({t:ans2_t})     
print("#(1)  ",Ci.center    )
print("#(2-1)",S.simplify() )
print("#(2-2)",S.expand()   )
print("#(3-1)",ans1_t,ans1_y)
print("#(3-2)",ans2_t,ans2_y)
############################################################################
# bisect
############################################################################
from bisect import *
from operator import itemgetter

class mySortedCollection(object):

    def __init__(self, iterable=(), key=None):
        self._given_key = key
        key = (lambda x: x) if key is None else key
        decorated = sorted((key(item), item) for item in iterable)
        self._keys = [k for k, item in decorated]
        self._items = [item for k, item in decorated]
        self._key = key

    def __getitem__(self, i):
        return self._items[i]

    def insert(self, item):
        'Insert a new item.  If equal keys are found, add to the left'
        k = self._key(item)
        i = bisect_left(self._keys, k)
        self._keys.insert(i, k)
        self._items.insert(i, item)
#
s = mySortedCollection(key=itemgetter(1))
for i in range(1,10):
    s.insert( [Rational(i,10),i/10] )
s.insert([ans1_t,Float(ans1_t)])
print("#",list(s))
myList=list(s)
for i in range(0,10):
    print(myList[i] )
############################################################################
# 3D作図 z=0 XY平面に作図しました。
############################################################################
def myXYZ2Txt_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.05 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 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_C_2D(*args):
    for i in range(1,len(args)):
        myLine_2D(args[i-1],args[i])
    myLine_2D(args[i],args[0])
    return
############################################################################
# 円の作図　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
############################################################################
myTxtXYZ_S_2D(O,"O")
mySubs={t:ans1_t}
myLine_C_2D  ( O,A.subs(mySubs),B.subs(mySubs)  )
C=Ci.center
myTxtXYZ_S_2D( C.subs(mySubs),"C"  )
for i in range(1,10):
    ti=myList[i][0]
    mySubs={t:ti}
    myCi=Circle  (O,A.subs(mySubs),B.subs(mySubs) )              
    myCircle_2D  (myCi)    
    myTxtXYZ_S_2D(A.subs(mySubs),"t="+str(ti)+",A",B.subs(mySubs),"t="+str(ti)+",B" )
    if i == 1:
       P1=Point(myCi.center.x,myCi.center.y)
    else:
       P2=Point(myCi.center.x,myCi.center.y)
       myLine_2D(P1,P2)
       P1=P2
############################################################################
doc = App.activeDocument()
App.ActiveDocument.addObject("App::Origin", "Origin")
App.ActiveDocument.getObject('Origin').Visibility = True
App.ActiveDocument.recompute()
Gui.activeDocument().activeView().viewAxonometric()
Gui.SendMsgToActiveView("ViewFit")
```
isometric方向です。

![0png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/7c3b7cc6-d7a5-1317-487c-74d7089db30c.png)

＞工夫して図を描こう！
tが、0.1から0.9まで、0.1ピッチの軌跡です。
点Aが原点から、右上へ。
点Bがy軸上、上から下へ。
上図の上空からみｔ拡大図です。
以下、勉強中です。
・Freecadの放物線の代わりに、中心を折れ線で結んでいます。
・Originは、マウス操作で非表示です。
・赤色は、マウス操作です。

![1png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/97e92f02-1d9f-8993-b3ee-929469afad52.png)

# 参考

https://qiita.com/mrrclb48z/items/ca2b0440d643c12c9ac9

https://note.nkmk.me/python-list-sort-sorted/

https://ja.wikipedia.org/wiki/%E8%BB%8C%E8%B7%A1_(%E6%95%B0%E5%AD%A6)

https://en.wikipedia.org/wiki/Locus_(mathematics)