1
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?

正三角形の辺の長さ「高校入試チャレンジ問題 正三角形ABCの高さは?」をsympyとFreeCADでやってみたい。

Last updated at Posted at 2024-10-20

・問題文は2次元ですが、3次元FreeCADのマクロで、XY平面上に作図しました。
以下に私の勘違いもあります。
・(別件)???皆様が待望のFreeCADのマクロで寸法線表示ができました。(未、角度寸法表示)
https://qiita.com/mrrclb48z/items/a330f05a8e6946ea842c

オリジナル

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

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

ver0.1 ステキです。

from sympy import *
var('a,h',real=True,positive=True)
print("#",solve(Eq(3*a/2+4*a/2+5*a/2,a*h/2),h)[0])
# 12

sympyで(いつもの方法で) 以下は、いつもの勘違いです。

・良いように言えば、???作図のためです。
 「正三角形をつくる問題」として解きました。
 この課題は、奥が深いみたいです。省略。

ver0.2 連立方程式で

・3オフセットの共通点。最初に浮かんだのがコレです。

# ver0.2
from sympy import *
var('a,Gx,Gy',real=True,positive=True)
A,B,C,G=map(Point,[(a*Rational(1,2),a*Rational(1,2)*sqrt(3)),(0,0),(a,0),(Gx,Gy)])
sol_a,sol_Gx,sol_Gy=solve([Eq(Line(A,B).distance(G),3),
                           Eq(Line(B,C).distance(G),4),
                           Eq(Line(C,A).distance(G),5)],
                          [a,Gx,Gy])[1]
print("#",sol_a*Rational(1,2)*sqrt(3))
# 12

ver0.3 CAD風に。

・左下から、???片押し。いいですネ。普通はCAD風コレかも。
・直線のオフセットで良さそうなのが見つからなかったので、自作です。???以下でも。
parallel_line(p)
https://docs.sympy.org/latest/modules/geometry/lines.html#sympy.geometry.line.LinearEntity.parallel_line

# ver0.3
from sympy import *
def myLine_Offset(P1,P2,d):
    myOffset=d*(P2-P1).rotate(pi/2).unit
    return Line(P1+myOffset,P2+myOffset)
a=10  # 仮りの辺の長さ
A,B,C=map(Point,[(a*Rational(1,2),a*Rational(1,2)*sqrt(3)),(0,0),(a,0)])
G =myLine_Offset(B,C,4).intersection(myLine_Offset(B,A,-3))[0]
G2=Line(B,((C-B).unit+(A-B).unit)*Rational(1,2)).projection(G)
print("#",B.distance(G2)+5)
# 12

FreeCADのマクロで作図

・問題文は2次元ですが、3次元FreeCADのマクロで、XY平面に作図しました。
・計算部分は、Ver.0.2 の コピー貼り付けです。
???皆様が待望のFreeCADのマクロで寸法線表示ができました。(未、角度寸法表示)

import FreeCAD
import Part
import DraftTools
import Draft
import Mesh
############################################################################
# ver0.2
from sympy import *
var('a,Gx,Gy',real=True,positive=True)
A,B,C,G=map(Point,[(a*Rational(1,2),a*Rational(1,2)*sqrt(3)),(0,0),(a,0),(Gx,Gy)])
sol_a,sol_Gx,sol_Gy=solve([Eq(Line(A,B).distance(G),3),
                           Eq(Line(B,C).distance(G),4),
                           Eq(Line(C,A).distance(G),5)],
                          [a,Gx,Gy])[1]
print("#",sol_a*Rational(1,2)*sqrt(3))
# 12
###########################################################################
rep={a:sol_a,Gx:sol_Gx,Gy:sol_Gy}
A=A.subs(rep)
B=B.subs(rep)
C=C.subs(rep)
G=G.subs(rep)
D=Line(A,B).projection(G)
E=Line(B,C).projection(G)
F=Line(C,A).projection(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(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 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
####################################################################################
myLine_C_2D     (A,B,C)  
myLine_S_2D     (G,D)
myLine_S_2D     (G,E)
myLine_S_2D     (G,F)
#
# myFontsize =0.25
myFontsize =0.5*2.0
myOvershoot=1.0*2.0
myDimension(myFontsize,myOvershoot,B,A,"PL")
myDimension(myFontsize,myOvershoot,B,C,"HR")
myDimension(myFontsize,myOvershoot,A,C,"PL")
myDimension(myFontsize,myOvershoot,D,G,"PL")
myDimension(myFontsize,myOvershoot,E,G,"PL")
myDimension(myFontsize,myOvershoot,G,F,"PL")
#
myTxtXYZ_XY_S_2D(myFontsize,A,"A",B,"B",C,"C")
myTxtXYZ_XY_S_2D(myFontsize,D,"D",E,"E",F,"F",G,"G")
####################################################################################
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

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

(テンプレート)

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

いつもと違うリンクのおすすめです。

1
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
1
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?