空間ベクトル「2023札幌医科大学前期【1】」をsympyとFreeCADでやってみた。 

FreeCADのマクロで作図しました。
テクニカルな方法？を含めて4通りの計算方法です。

オリジナル

https://kamelink.com/blog/2023/03/29/23%e5%b9%b4-%e6%9c%ad%e5%b9%8c%e5%8c%bb%e5%a4%a7-11/

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

https://mathexamtest.web.fc2.com/2023/202311001/2023110010100mj.html

# sympyで (1)数学入試問題様のやり方:平方完成で
平方完成
https://qiita.com/mrrclb48z/items/38e849f41f46bf0c8f9c
??? 第2引数の使い方を教えて下さい。???　
```python
from sympy import *
t    =Symbol ('t'    ,real=True)
x,h,k=symbols('x h k',real=True)
def myHeihokanseiABC(f,t):
    f=f.subs({t:x})
    g=Poly(f).all_coeffs()[0]*( x - h )**2 + k
    ans=solve( f - g, [ h, k ] ) 
    return a,ans[0][0],ans[0][1]
a=Point(3,-1,2)
b=Point(2, 2,1)
pp=((a+t*b).distance(Point(0,0,0))**2).expand()
ans=myHeihokanseiABC(pp,t)
print("#",ans[1],sqrt(ans[2]))
# -2/3 sqrt(10)
```
# sympyで (2)数学入試問題様のやり方:内積で
無理に、最小値を1行でprint出力する必要もありませんでした
後半部分は、内積条件からPの座標計算です。

```python
from sympy import *
t=Symbol('t',real=True)
a=Point(3,-1,2)
b=Point(2, 2,1)
#
print("#",(a+t*b).subs({t:solve(b.dot(a+t*b))[0]}).distance(Point(0,0,0)) )
#
P=a+t*b
ans=solve(b.dot(P))[0]
P=P.subs({t:ans})
print("#",ans,P.distance(Point(0,0,0)) )
# sqrt(10)
# -2/3 sqrt(10)
```
# sympyで (3)直線への垂線計算で
??? tの計算(自作関数mySolveT)について、いい方法がありますか ??? 
平方が見えないのがステキです。最小値を計算後,tを求めています。不思議ですね。
```python
from sympy import *
t=Symbol ('t',real=True)
def mySolveT(OQ, OA):
    return solve([
                  Eq(OQ.x,t*OA.x),
                  Eq(OQ.y,t*OA.y),
                  Eq(OQ.z,t*OA.z)
                 ],
                 [t])
O=Point(0, 0,0)
a=Point(3,-1,2)
b=Point(2, 2,1)
print("#",O.distance(Line(a,a+t*b).projection(O)))
#
p=Line(a,a+t*b).projection(O)
#以下の3行は、うまくいきませんでした。
#ans=solve(Eq(P,a+t*b),t)
#t=(P-a)/b
#t=(P-a).distance(O)/b.distance(O)
print("#",mySolveT((p-a),b)[t],p.distance(O))
# sqrt(10)
# -2/3 sqrt(10)
```
# sympyで (4)sympyのminimum 関数で
参考より。minimum 関数をみつけました。
(3)と同様に、
平方が見えないのがステキです。最小値を計算後,tを求めています。不思議ですね。
```python
from sympy import *
t=Symbol ('t',real=True)
O=Point(0, 0,0)
a=Point(3,-1,2)
b=Point(2, 2,1)
p=a+t*b
minp=minimum(p.distance(O),t,S.Reals)
print("#",solveset(Eq(p.distance(O),minp),t,S.Reals).args[0],minp)
# -2/3 sqrt(10)
plot(p.distance(O),0,(t,-5,5))
```
原点から直線までの離れ
縦横比は、異なります。
橙色y=0は、ダミーです。非表示？同じ色？

![0png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/dcb8ffd3-2ecf-e098-36c2-9da92fed1657.png)

# 計算の実行環境

①私の環境は,pycharmです。
②よく聞くのは、Jupyterです。
③web上で、上記のソースを「SymPy Live shell」に、コピー貼り付けでもできました。
黒背景の右上に、マウスを移動すると、コピーマークが発生します。

https://live.sympy.org/

???　タブレット環境で、コピー貼り付けが実行できませんでした。???

# FreeCADのマクロで作図
```python
import FreeCAD
import Part
import Draft
import Mesh
#########################################################################################################
# 計算
from sympy import *
t=Symbol('t',real=True)
a=Point(3,-1,2)
b=Point(2, 2,1)
print("#",(a+t*b).subs({t:solve(b.dot(a+t*b))[0]}).distance(Point(0,0,0)) )
P=a+t*b
ans=solve(b.dot(P))[0]
P=P.subs({t:ans})
print("#",ans,P.distance(Point(0,0,0)) )
##########################################################################################################
### 作図用
O=Point(0,0,0)
##########################################################################################################
### 3D作図
def myXYZ2Txt(A):
    return '(' + str(A.x) + ',' + str(A.y) + ',' + str(A.z) + ')'
def myTxtXYZ(A,myWedgei):
    P5x=float(A.x)
    P5y=float(A.y)
    P5z=float(A.z)
    p5 = FreeCAD.Vector(P5x, P5y, P5z)
    myText = Draft.makeText(myWedgei, p5)
    myText.Label = myWedgei
    FreeCADGui.ActiveDocument.ActiveObject.FontSize = '0.3 mm'
    return
def myTxtXYZ_S(*xy_tx):
    for i in range(1,int(len(xy_tx)/2)+1):
        myTxtXYZ(xy_tx[2*i-2],xy_tx[2*i-1]+myXYZ2Txt(xy_tx[2*i-2]) )
    return
def myLine(A,B):
    Ax,Ay,Az=float(A.x),float(A.y),float(A.z)
    Bx,By,Bz=float(B.x),float(B.y),float(B.z)
    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(*args):
    for i in range(1,len(args)):
        myLine(args[i-1],args[i])
    return
#
myLine_S  (O,a,a+b)
myLine    (O,P)
myTxtXYZ_S(O,"O",a,"a",a+b,"a+b",P,"P")
#
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/6de09abb-f6ae-ac32-3921-7d93a4619f8d.png)

上空から

![1png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/05b4742d-9a8c-000f-0a38-49facfc51bd2.png)

# 参考

https://qiita.com/mrrclb48z/items/38e849f41f46bf0c8f9c

最小値は「minimum関数」です。<

https://math-fun.net/20220119/21562/

sympy.calculus.util.minimum(f, symbol, domain=Reals)

https://docs.sympy.org/latest/modules/calculus/index.html#sympy.calculus.util.minimum