找回密码
 快速注册
搜索
查看: 42|回复: 1

[Julia] 证明Napoleon定理

[复制链接]

3149

主题

8386

回帖

6万

积分

$\style{scale:11;fill:#eff}꩜$

积分
65391
QQ

显示全部楼层

hbghlyj 发表于 2023-3-10 03:27 |阅读模式
安装IJulia
使用using IJulia; notebook(dir="C:/Users/myself",detached=true)打开Jupyter notebook
根据这里安装PyCall
Screenshot 2023-03-09 at 20-04-07 Untitled - Jupyter Notebook.png
A symbolic proof
将下面的命令粘贴到Cell, 按Shift+Enter执行:
引入SymPy
  1. using Pkg;
  2. Pkg.activate(".");
  3. Pkg.add("SymPy")
  4. using SymPy
复制代码

定义一些基本的几何对象。
  1. import Base: isequal, ==
  2. abstract type GeoObject end
  3. abstract type GeoShape <: GeoObject end
  4. struct Point <: GeoObject
  5.     x::Number
  6.     y::Number
  7. end
  8. (==)(p1::Point, p2::Point) = p1.x==p2.x && p1.y==p2.y
  9. struct Triangle <: GeoShape
  10.     A::Point
  11.     B::Point
  12.     C::Point
  13. end
  14. Triangle(ax, ay, bx, by, cx, cy) = Triangle(Point(ax, ay), Point(bx, by), Point(cx, cy))
  15. (==)(t1::Triangle, t2::Triangle) = vertices(t1) == vertices(t2)
  16. function vertices(tri::Triangle)
  17.     [tri.A, tri.B, tri.C]
  18. end
  19. struct Edge <: GeoShape
  20.     src::Point
  21.     dst::Point
  22. end
  23. function edges(tri::Triangle)
  24.     elist = Edge[]
  25.     pts = vertices(tri)
  26.     for i in 1:length(pts)-1
  27.         push!(elist, Edge(pts[i], pts[i+1]))
  28.     end
  29.     push!(elist, Edge(pts[length(pts)], pts[1]))
  30.     elist
  31. end
复制代码

计算两点距离的函数
  1. function squaredist(A, B)
  2.     d = (A.x-B.x)^2+(A.y-B.y)^2
  3.     if d isa Sym
  4.         simplify(d)
  5.     else
  6.         d
  7.     end
  8. end;
复制代码

计算三角形重心的函数
  1. function centroid(pts)
  2.     Point(sum([[pt.x,pt.y] for pt in pts])/length(pts)...)
  3. end
复制代码

检查正三角形的函数
  1. function isequilateral(tri)
  2.     dist = [squaredist(e.src, e.dst) for e in edges(tri)]
  3.     if (dist[1] == dist[2]) && (dist[1] == dist[3])
  4.         return true
  5.     else
  6.         return false
  7.     end
  8. end
复制代码

给定两个点 A, B 解出点 P 使得 PA=PB=AB (这样的 P 有两个)
  1. function equipoints(A, B)
  2.     x, y = @vars x y
  3.     pt = Point(x, y)
  4.     dist1 = squaredist(pt, A)
  5.     dist2 = squaredist(pt, B)
  6.     dist3 = squaredist(A, B)
  7.     sol = solve([dist1-dist3, dist2-dist3], [x,y]) # Soving a quadratic eqaution.
  8.     [Point(s[1], s[2]) for s in sol]
  9. end;
复制代码

我们在两个点 P 中选择到 C 较远的一个作为向外的等边三角形
  1. function outer_equitri(A, B, C)
  2.     ptAB = equipoints(A, B)
  3.     dist = map(pt->squaredist(pt, C), ptAB)
  4.     d = simplify(dist[1] - dist[2])
  5.     if d >= 0
  6.         return Triangle(A, B, ptAB[1])
  7.     else
  8.         return Triangle(A, B, ptAB[2])
  9.     end
  10. end;
复制代码

用A, B, C表示三角形顶点坐标
  1. @vars by cx positive=true;
  2. @vars cy;
  3. A = Point(0, 0); B = Point(0, by); C = Point(cx, cy);
  4. tri = Triangle(A, B, C)
复制代码

证明Napoleon定理
  1. function napoleon_check(tri)
  2.     outer_tri = map(i->outer_equitri(circshift(vertices(tri), i)...), 0:2)
  3.     centers = centroid.(vertices.(outer_tri));
  4.     npt = Triangle(centers...)
  5.     isequilateral(npt)
  6. end
  7. napoleon_check(tri)
复制代码

运行结果为true
Screenshot 2023-03-09 at 21-33-32 Untitled6 - Jupyter Notebook.png

相关帖子

3149

主题

8386

回帖

6万

积分

$\style{scale:11;fill:#eff}꩜$

积分
65391
QQ

显示全部楼层

 楼主| hbghlyj 发表于 2023-3-10 05:36
我们在两个点 P 中选择到 C 较远的一个作为向外的等边三角形

把 C 关于 B 旋转 +90° 就可以作出唯一的点, 不需要选择.
希望有人来改进一下代码

手机版|悠闲数学娱乐论坛(第3版)

GMT+8, 2025-3-4 15:35

Powered by Discuz!

× 快速回复 返回顶部 返回列表