0
0

円と長方形「高校入試頻出問題 円Oの半径は?」をsympyとFreeCADでやってみたい。

Last updated at Posted at 2024-07-26

・何も座標変換(回転)を使わなくてもです。sympyならではです。
・円Oの中心をMとしていました。申し訳ありません。

オリジナル

・YUUU0123 様 (0:00〜3:21)

sympyで

ver0.1 外接円の半径で
The radius of the circumcircle of the triangle.
https://docs.sympy.org/latest/modules/geometry/polygons.html#sympy.geometry.polygon.Triangle.circumradius

# ver0.1  △PAB (0,0)(-5,3),(5,3)の外心
from sympy import *
print("#",Triangle(Point(0,0),Point(-5,3),Point(5,3)).circumradius)
17/3

ver0.2 垂直2等分線と垂直2等分線の交点で
Are two linear entities perpendicular?
https://docs.sympy.org/latest/modules/geometry/lines.html#sympy.geometry.line.LinearEntity.is_perpendicular

# ver0.2 垂直2等分線と垂直2等分線の交点で
from sympy import *
P,A,B=map(Point,[(0,0),(-5,3),(5,3)])
M=Line(A,B).perpendicular_line(Segment(A,B).midpoint).intersection( \
  Line(P,B).perpendicular_line(Segment(P,B).midpoint) )
print("#",M[0].y)
# 17/3

ver0.3 線対称になっています。右半分です。 線分PBの中点で90°回転。(ver0.2と同じ)
・もっと良いDocがあるはずです。
https://docs.sympy.org/latest/modules/geometry/lines.html#sympy.geometry.line.Ray2D.closing_angle

# ver0.3 線対称になっています。右半分です。 線分PBの中点で90°回転。(ver0.2と同じ)
from sympy import *
P,B=map(Point,[(0,0),(5,3)])
M=Line(
P,P+Point(1,0)).rotate(rad(90),P).intersection( \
  Line(P,B)           .rotate(rad(90),(Segment(P,B).midpoint)) )
print("#",M[0].y)
# 17/3

ver0.4 何も座標変換(回転)を使わなくてもです。線分PB上で直角三角形
・座標変換?小座標、大座標だと左右。y座標のプラスマイナスがでて、オススメです。
https://docs.sympy.org/latest/modules/matrices/matrices.html

# ver0.4 何も座標変換(回転)を使わなくてもです。線分PB上で直角三角形
from sympy import *
var('r,t',real=True,poitive=True)
PC,CB=5,3
PB=sqrt(PC**2+CB**2)
PD=PB/2
PC_M=Matrix([[0],[r],[1]]) 
PB_M=Matrix([[PD],[sqrt(r**2-PD**2)],[1]])
t    =Line(Point(0,0),Point(1,0)).angle_between(Line(Point(0,0),Point(PC,CB)))
mTurn=Matrix([[cos(t),-sin(t),0],[sin(t),cos(t),0],[0,0,1]])
print("#",solve(Eq(PC_M,mTurn*PB_M),[r,t])[0][0])
# 17/3

FreeCADのマクロで作図

・計算部分は、Ver.0.2 の コピー貼り付けです。

import FreeCAD
import Part
import DraftTools
import Draft
import Mesh
############################################################################
# ver0.3 線対称になっています。右半分です。 線分PBの中点で90°回転。(ver0.2と同じ)
from sympy import *
P,B=map(Point,[(0,0),(5,3)])
M=Line(P,P+Point(1,0)).rotate(rad(90),P).intersection( \
  Line(P,B)           .rotate(rad(90),(Segment(P,B).midpoint)) )[0]
print("#",M.y)
# 17/3
############################################################################
r=M.y-P.y
C=Point( B.x,P.y)
A=Point(-B.x,B.y)
D=Point(-B.x,P.y)
T=Point( P.x,P.y+2*r)
############################################################################
# 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 '(' + str(A.x) + ',' + str(A.y) +  ')'
    # return ""
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.5 mm'
    # FreeCADGui.ActiveDocument.ActiveObject.FontSize = '2.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 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(M,r))
myLine_S_2D     (A,D,P,C,B)  
myLine_S_2D     (M,B)  
myTxtXYZ_S_2D(A,"A",B,"B",C,"C",D,"D")
myTxtXYZ_S_2D(P,"P",M,"M",T,"T")
####################################################################################
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方向?です。

1.png

拡大図
2.png

拡大図(CADの操作で寸法線を追加)
・円Oの中心をMとしていました。申し訳ありません。
拡大図(CADの操作で寸法線を追加)
・(青色の)角度寸法は、ニセモノです。Part>計測>角度計算 です。
・角度寸法の表示は、まだ勉強中です。

3.png

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

>方べきの定理を使うと...

from sympy import *
var('x',real=True,poitive=True)
print("#",(solve(Eq(5*5,3*x),x)[0]+3)*Rational(1,2))
# 17/3

・SymPy Liveでも。約1分で同じ結果がでます。
https://live.sympy.org/
インストールなしで、貼り付けてできます。
環境はパソコン。???なぜか、スマホ・タブレット環境でできないと思います。
(FreeCADの作図はできません。実行環境を参考にして下さい。)

・ 〃
 以下の1行のコピー貼り付けでも、ステキな結果がでます。(
 x変数の時は、symbol定義が不要です.定義済みです。

(solve(Eq(5*5,3*x),x)[0]+3)*Rational(1,2)

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

(テンプレート)

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

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

0
0
1

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