贴吧用户_0ay955W fqya001
关注数: 4 粉丝数: 75 发帖数: 1,218 关注贴吧数: 5
三角网的提取 GeoGebra中有 Delaunay三角网命令,可以根据点列作出三角网,但作出来的图形是轨迹,不便于进一步使用,本文旨在提取出三角网中各三角形。 A = (-3.96295, 2.11481) B = (-1.54313, 2.90919) C = (1.1464, 2.52577) D = (3.05969, -0.23008) E = (0.98896, -3.39859) F = (-1.63927, -4.1948) G = (-4.45459, -3.5173) H = (-6.25215, -0.54963) l1 = {A, B, C, D, E, F, G, H} g1 = Delaunay三角网(l1)我们主要讨论凸多边形,点是随意点的,形成的三角网如上,它只是轨迹,我们的目标是把这些三角形分离出来。 先找出这些三角形外心吧,我们利用三角网的孪生兄弟Voronoi图命令: g2 = Voronoi图(l1) l2 = 最前元素(g2, 长度(g2)) l3 = 条件子列(abs(x(A)) < 6, A, l2) l4 = 互异(l3) l5 = 升序排列(l4)我们把 Voronoi图轨迹得到的点限定在一定范围,就可以确定外心点列,这里限定范围作了简化,实际过程中,可以根据点列l1中点横向坐标或者纵坐标最大最小值确定范围的。剔除重复元素,我们得到了外心点列并从左到右排列了一下,便于后续找出的三角形也按此排列。 l6 = 映射(距离(m, l1), m, l5) 让每个外心在l1中找一个最近点,因为三角网中的三角形外接圆不会包含其它 点,这个找出的距离就为我们找到构成三角形其它两点提供了参数) m1 = 映射(序列((距离(b, l1(i)), i), i, 1, 长度(l1)), b, l5) (列出每个外心与l1中每个点的距离) l8 = 序列(条件子列(x(W) ≟ l6(i), W, m1(i)), i, 1, 长度(l6)) (找出另两个点,并附带上序号) m2 = y(l8) (提取出每个三角形的点在l1中的序号,序号由l8附带生成的) m3 = 序列(序列(l1(m2(i, j)), j, 1, 3), i, 1, 长度(m2)) (根据序号,在l1中把各点提取出来) l7 = 映射(多边形(m), m, m3)至此,我们就得到了三角网中各三角形了,我们还可以把它们单列出来: l9 = 序列("A" + (m) + "=Element(l7," + (m) + ")", m, 1, 长度(l7)) 执行(l9) 最后对A1、A2.........分别着色就行了。
正十二面体与正二十面体复合 这个图形是由正十二体与正二十面体组合而成,截三分之一二十面体,其实就是足球模型图,看似简单的图,在GeoGebra中可以用指令实现,但问题关键是如何让两图形心在原点,且面与顶点完全对应上呢? 我们先画个形心在原点的正十二面体吧: a=1 (棱长初始值,滑动条,最小为1,最大暂时定为2吧) O=(0,0,0) A = (a, 0, 0) l1 = {多边形(O, A, 5, xOy平面)} poly1 = 元素(l1, 1) (这样画多边形或者立体图形,省去那些不要的点、线、面信息) B = 形心(poly1) ψ = (sqrt(5) + 1) / 2 (黄金分割数) r1 = a ψ² / (2sqrt(3 - ψ)) (正十二面体内接球半径计算公式) O_1 = (0, 0, -r1) face12 = 平移(poly1, 向量(B, O_1)) (这里取这样的名字,是为了后续提取十二个面方便)我们成功将构成正十二面体的初始五边形移到了需要的位置,然后可以用系统命令画了: t12 = 正十二面体(face12, true) l2 = 序列(对象("face" + (i)), i, 1, 12) (根据生成图形各面的名称信息,把各面组成列表) l3 = 映射(射线(O, 形心(a)), a, l2) (画出十二条射线,用于确定正二十面体顶点方向)b = 3 (正二十面体棱长) r2 = b (3sqrt(3) + sqrt(15)) / 12 (正二十面体外接球半径计算公式) c2: 球面(O, r2) l4 = 映射(交点(a, c2), a, l3) (取得正二十面体顶点) T = l4(2) U = l4(3) V = l4(12) (找出三个点,构建初始三角形) t1 = 多边形({T, U, V})t20 = 正二十面体(t1, true) H_1 = E_1 + 1 / 3 (B_1 - E_1) I_1 = E_1 + 1 / 3 (F_1 - E_1) J_1 = E_1 + 1 / 3 (G_1 - E_1) 找到正二十面体最上顶点及与其相邻三个点,分别作三分之一点。过这三点作平面,与z轴交于一点,此点z坐标为切二十面体于三分之一处时,十二面体内接球半径。 p: 平面(H_1, I_1, J_1) K_1 = 交点(z轴, p) a_0 = 2sqrt(3 - ψ) z(K_1) / ψ² (根据公式,把半径换算为十二面体棱长) 当a=a_0时,为我们需要的图形了,这里可以把a_0的值复制出来,放到a的最大值中。
球面参数方程 多数情况下,我们都是通过作图法操作球面,如使用工具画个球: O=(0,0,0) R=1 f: 球面(O, R) 系统自动给出其方程:x^2+y^2+z^2=1 但有时候使用参数方程,更容易控制球在局部,特别是结合点的球坐标表示法,更便于计算。 R=1 a = 曲面(R sin(α) cos(β), R sin(α) sin(β), R cos(α), α, 0, π, β, 0, 2π) 这就是球坐标参数方程,α是球上的点连接原点与z轴夹角(是夹角,不是角度,是有区别的,因此它是0到π),β是点到xOy平面的投影连接原点,与x轴形成的角度,(这里是角度,不是夹角,因此是0到2π) 我们设两个滑动条α、β,α范围0到π,β范围0到2π,这里的α、β与参数方程里的α、β是两个不同的变量哈,前者是全局变量,后者是局部变量,作为参数,只在它表达的方程中起作用。 α = 0.9 β = 0 b = 曲线(R sin(α) cos(β), R sin(α) sin(β), R cos(α), β, 0, 2π) c = 曲线(R sin(α) cos(β), R sin(α) sin(β), R cos(α), α, 0, π) 根据球面参数方程,我们很容易得到其指定角度经纬线:其中纬线b可随α 变化上下下移动,经线是一个半圆,随β变化可左右旋转。 同理,我们可以得到球面经纬线系列: l1 = 序列(曲线(R sin(α) cos(β), R sin(α) sin(β), R cos(α), β, 0, 2π), α, 0, π, π / 7) l2 = 序列(曲线(R sin(α) cos(β), R sin(α) sin(β), R cos(α), α, 0, π), β, 0, 2π, π / 11) 两个列表有点像,但看清楚谁作为曲线的参数,谁作为序列的参数。至于什么 π / 7、 π / 11完全是为了与球面参数方程自带经纬线重合。 回到2条可动的经线和纬线,它们的交点是什么呢? A = (R; β; π / 2 - α)这里A点我们直接使用了球坐标形式,β的意义与球参数方程的意义一样,可以叫“方位角”,这里π / 2 - α叫仰角,是A点连原点的线与xOy平面夹角,它正好与球面参数方程中与z轴的夹角之和为π / 2,这个简单画一下图就明白了,因此这这里用π / 2 - α把与z轴的夹角转化为仰角。 点线有了,再看看局部的面: α = 0.9 d = 曲面(R sin(α') cos(β), R sin(α') sin(β), R cos(α'), α', 0, α, β, 0, 2π) 这里α全局变量与局部变量同时出现在一个方程中,这是不允许的,因为电脑分不出来,所以将原式α加个撇。β = 1.14 e = 曲面(R sin(α) cos(β'), R sin(α) sin(β'), R cos(α), α, 0, π, β', 0, β)
足球(难度较高,有耐心的可看) 不打算讲代码,说一下思路: 第一步目标,建立一个如下足球模型:采用的是多边形拼接法: A = (1, 0, 0) B = 旋转(A, (360°) / 5, z轴) poly1 = 多边形(A, B, 5, xOy平面) poly2 = 多边形(B, A, 6, xOy平面) 画一个正五边形和正六边形E = 多边形(A, B, 5, xOy平面) K = 多边形(B, A, 6, xOy平面) H = 多边形(B, A, 6, xOy平面) c: 圆周(直线(A, B), H) d: 圆周(直线(A, E), 旋转(K, -(72°), z轴)) G = 交点(d, c) poly3 = 正六边形(B, A, G)通过两圆交点把六边形旋转上来,下面就是拼接图形,不再一一讲了: poly4 = 正六边形(E, A, G) poly5 = 正六边形(D, E, Q) poly6 = 正六边形(C, D, T) poly7 = 正五边形(L, G, O) poly8 = 正五边形(P, Q, R) poly9 = 正六边形(O, P, C_1) poly10 = 正六边形(B_1, C_1, D_1) poly11 = 正五边形(E_1, D_1, G_1) poly12 = 正六边形(H_1, G_1, J_1) poly13 = 正六边形(K_1, J_1, L_1) poly14 = 正五边形(L_1, M_1, O_1)保留poly1和poly14显示,其它所有图形不再显示,选取其中关键图形(六边形和五边形)旋转: l1 = 序列(旋转({poly3, poly9, poly10, poly13}, 72° i, z轴), i, 1, 5) l2 = 序列(旋转({poly7, poly11}, 72° i, z轴), i, 1, 5)至此,第一步目标完成,建立了模型,我们需要取得所有点,根据这些点画弧线: T_1 = 中点(形心(poly1), 形心(poly14)) (这是根据两相对面确定球心) l3 = 映射(序列(描点(SS, tt / 6), tt, 1, 6), SS, 扁平列表({l1})) (取出全部六边形顶点) l6 = 映射(映射(圆弧(T_1, AA, BB), AA, TT, BB, 扁平列表({最后元素(TT, 5), 最前元素(TT, 1)})), TT, l3)这时,我们成功将模型转化为弧线模型,这算是完成了第二步。下边是最后一步,我们采用曲面条粘贴出各正六边形,余下五边形用球的本色: o: 球面(T_1, A) (画个黑球 ) e: 圆弧(T_1, B, A) l4 = 序列(旋转(曲面(e, 84°, 直线(T_1, 直线(B, A))), 72° i, z轴), i, 1, 5)从最下边开始,第1次贴条。 r: 圆弧(T_1, S, T) l5 = 序列(旋转(曲面(r, 84°, 直线(T_1, 直线(T, S))), 72° i, z轴), i, 1, 5)用旋转法,第2次贴条。这个旋转图形是下边这样:其它不再讲了,原理都 一样: l4' = 旋转(旋转(l4, 180°, 直线(T_1, x轴)), 36°, z轴) l7 = 旋转(旋转(l5, 180°, 直线(T_1, x轴)), 36°, z轴) s: 圆弧(T_1, F_1, O) l8 = 序列(旋转(曲面(s, 84°, 直线(T_1, 直线(F_1, O))), 72° i, z轴), i, 1, 5) t: 圆弧(T_1, C_1, P) l9 = 序列(旋转(曲面(t, 84°, 直线(T_1, 直线(P, C_1))), 72° i, z轴), i, 1, 5) 完成图:
先说一下费马点,如下图,在三角形ABC中有一点动点P,求PA+PB+PC最小值,这个最小值就是P移动到费马点时的值: A = (7.33194, 6.51164) B = (3.30534, 2.73497) C = (10.54883, 2.63574) f = 线段(A, B) g = 线段(B, C) h = 线段(C, A) P = (7.7401, 4.24824) l = 线段(P, A) m = 线段(P, B) n = 线段(P, C)特殊情况我们暂不考虑,如三角形有顶角大于120度的情况,我们不妨再看看费马点的作法: A' = 旋转(A, 60°, B) c: 圆周(A, A', B) i = 线段(A', C) D = 交点(c, i, 2) j = 线段(A, A') k = 线段(A', B)当P点移动到D点时,PA+PB+PC最小,且等于A‘C,下面再看看证明过程: P' = 旋转(P, -(60°), A) t1 = 多边形(P', A, A') p = 线段(P', P)我们将三角形APB旋转60度,如上图,当C、P、P‘、A’四点共线时,PA+PB+PC最小,P移动到D点时满足条件。 当然我们这贴子不是讨论以上情况,只是对费马点作了回顾,下边要用到上面的思路。 问题来了:求2PA + 3PB + 4PC的最小值,这个求值就叫加权费马点问题。 由上边费马点的作法,我们是在一条边上构建了一个等边三角形,因为这时候PA、PB、PC权重比为1:1:1,由此我们将上边问题先除以最大权重4,得PA:PB:PC=1/2:3/4:1,PC对应边为AB,于是我们仿费马点做法,在AB边上构建三角形,边上比为1/2:3/4:1: d: 圆周(B, f / 2) e: 圆周(A, 3 / 4 f) E = 交点(d, e, 1) q = 线段(A, E) r = 线段(E, B) s = 线段(E, C) t: 圆周(A, E, B) F = 交点(t, s, 2)当P点移动到F点时,2PA + 3PB + 4PC最小,且等于4CE,证明可参考上边费马点证明,略去。 注:若PA、PB、PC权重不足以构成三角形,则F点为权重最大对应点,若上图C点在兰色外接圆内,则C为F点,这些特殊情况不再一一作图。
函数列表初识 设有一列表如下: l1 = 序列(x^a, a, 1, 9)这是一系列函数,函数可以放入列表中来进行系列运算的。 如上边l1,我们要引用其中一个函数: f(x) = 元素(l1, 3) (输入 元素(l1, 3)即可,这里不建议用l1(3)引用,一般会出错,特别是填入表格时) a = l1(3, 2) (求某个函数在自变量为2时的值) A = (2, l1(3, 2)) (某个函数上的一个点)再看一个函数: g(x) = 乘积(序列(x - a, a, 0, 9)) (对函数列表进行相乘运算,结果为如下表达式:) g(x)=(x) (x - 1) (x - 2) (x - 3) (x - 4) (x - 5) (x - 6) (x - 7) (x - 8) (x - 9)当我们需要形如 x (x - 1) (x - 2) (x - 3) (x - 4) (x - 5) (x - 6) (x - 7) (x - 8) (x - 9) =0这样的方程时: eq1: g - 0 = 0 这里不能用g=0来对一个表达式处理,因为这样是直接定义变量g为0。 eq1:x (x - 1) (x - 2) (x - 3) (x - 4) (x - 5) (x - 6) (x - 7) (x - 8) (x - 9) = 0 再看两个很直观的函数列表: l3 = 序列(x² + y² = a², a, 0.1, 4, 0.2)l4 = 序列(a sin(x), a, 0.2, 2, 0.2)当然,我们的迭代大神也是可以用于函数列表的: l5 = 迭代列表(a(x) x² + a(x) x, a, {x}, 3) 这个列表如下: {x, x x² + x x, (x x² + x x) x² + (x x² + x x) x, ((x x² + x x) x² + (x x² + x x) x) x² + ((x x² + x x) x² + (x x² + x x) x) x} 我们可以用总和命令把它串在一起,然后用多项式函数命令简化: h(x) = 总和(l5) p(x) = 多项式函数(h) 最后表达式为: p(x)=x⁷ + 3x⁶ + 4x⁵ + 3x⁴ + 2x³ + x² + x再举一个应用场景:设有两条直线如下,从一条直接到另一条直接的过渡函数怎么弄: B = (-6.69662, 1.47976) C = (-1.6758, 5.29996) i: 直线(B, C) D = (-4.55992, -3.42023) E = (5.06412, -2.55873) j: 直线(D, E) l7 = 序列((1 - u) i(x) + u j(x), u, 0, 1, 0.1)这个好像看不出什么,完全可以用旋转实现,但其实不是这样的,如果另一条直线是曲线呢,还旋转个屁,我们把上边场景改为两线段,这样可能更直观: b = 曲线((1 - u) B + u C, u, 0, 1) c = 曲线((1 - u) D + u E, u, 0, 1) l6 = 序列(曲线(u b(t) + (1 - u) c(t), t, 0, 1), u, 0, 1, 0.1)总结:函数是可以放入列表的,并且可以作为对象参与运算的。
点在GeoGebra平面中的运算 我们知道,点在GeoGebra中可以是直角坐标、极坐标、向量、复数等形式表示,我们先从直角坐标开始: 设平面内有两点A(-1,2)、B(3,1) A = (-1, 2) B = (3, 1)两点间的中点坐标可表示如下: C = (A + B) / 2其1/3处(靠近A点)坐标如下: D = A + (B - A) / 3更进一步,其五等分点如下: l1 = 序列(A + k (B - A) / 5, k, 1, 5)那到底A+B或者B+A以及B-A是什么意思呢?这个可从向量的加减说起了,把点转化为向量: u = 向量(A) v = 向量(B) E = B + A w = 向量(E) f = 线段(A, E) g = 线段(B, E)因此点的相加可以理解为向量相加,如果要计算公式则A+B=(x(A) + x(B), y(A) + y(B)) 同理,点的相减,就是向量相减: F = B - A a = 向量(F) h = 线段(F, A) i = 线段(B, A) j = 线段(B, F)其计算公式为:B-A=(x(B) - x(A), y(B) - y(A)) 点的加减还是比较好理解的,从向量加减去理解其几何意义,但点的相除、相乘就要复杂点了,如: z_1 = B / A,我们输入B/A,得到的是一个复数,因此两点相除、相乘可以从复数角度去理解,先将点转化为复数: z_A = 转换为复数(A) z_B = 转换为复数(B) z_1 = z_B/z_A z_2 = z_B*z_A 复数相除的几何意义是模相除,辐角相减,相乘的几何意义是模相乘,辐角相加。 但这里有个问题,我们可以直接用B/A得到一个复数点,但我们并不能用B*A得到一个点,只能是一个数。因此直角坐标的两点直接相乘是向量的数量积,如这里B*A=v*u,其计算式为:x(A) x(B) + y(A) y(B),它是一个数,不是一个点了。 如果我们用叉乘呢?如e = v ⊗ u,这里因为是在平面内,因此也是得到一个数,如果把u、v换成三维向量,其叉乘就是一个垂直于u、v平面的向量了。平面内两向量(或者两点)的叉乘计算式为: k= -行列式({{x(A), y(A)}, {x(B), y(B)}}) 当然,在GeoGebra中点的运算远不止这些,如把一个点乘以一个常数,相当于横坐标和纵坐标同时乘以这个数,这时候点可以看作是一个列表了。如M=2A,若A坐标为(-1,2),则M坐标为(-2,4)。
我的贴子《二分树》就是一个分形图,勾股树也是分形(《浅谈迭代列表》),下面再讲讲关于分形的普遍做法。 我们用分形中经常举例的图(如下)为例:f = 线段((-3, 0), (3, 0)) A = 顶点(f, 1) B = 顶点(f, 2) C = A + (B - A) / 3 D = A + 2(B - A) / 3 E = (A + B) / 2 + f sqrt(3) / 6 单位法向量(f) l1 = {线段(A, C), 线段(C, E), 线段(E, D), 线段(D, B)} 以上代码根据线段f,画出如下图形:通常做法是把上边代码做成自定义工具,输入项为f,输出项为l1,暂命名为"分形1“。 对于输出为列表的分形,我们可以用如下命令: l2 = 迭代(合并(映射(分形1(a), a, lst)), lst, {{f}}, 5) 这里需要注意的是,本例不需要中间过程的图,因此使用”迭代“命令,一般情况下需要中间过程图的,如二分树,则改为”迭代列表“,这个代码可以说是通用的,我们的二分树同样是这样处理的,结果图如下:当然,有时候我们并不太想要用自定义工具,直接改造上边系列命令为一个命令,步骤不多的情况下有时候是可以的,如本例,我们试着不用自定义工具: 我们需要对所有的命令改造成只包含原始输入变量f,然后用另一个变量替换f,再放入迭代命令中,这里对点C、D、E的改造略去,我们直接改造l1: l3 = {线段(顶点(f, 1), 顶点(f, 1) + (顶点(f, 2) - 顶点(f, 1)) / 3), 线段(顶点(f, 1) + (顶点(f, 2) - 顶点(f, 1)) / 3, (顶点(f, 1) + 顶点(f, 2)) / 2 + f sqrt(3) / 6 单位法向量(f)), 线段((顶点(f, 1) + 顶点(f, 2)) / 2 + f sqrt(3) / 6 单位法向量(f), 顶点(f, 1) + 2(顶点(f, 2) - 顶点(f, 1)) / 3), 线段(顶点(f, 1) + 2(顶点(f, 2) - 顶点(f, 1)) / 3, 顶点(f, 2))} 从这里可以看出,不用自定义工具,把若干命令弄到一起,是很长的命令,且容易出错,并且我们还需要替换掉f,得到如下文本: {线段(顶点(a, 1), 顶点(a, 1) + (顶点(a, 2) - 顶点(a, 1)) / 3), 线段(顶点(a, 1) + (顶点(a, 2) - 顶点(a, 1)) / 3, (顶点(a, 1) + 顶点(a, 2)) / 2 + a sqrt(3) / 6 单位法向量(a)), 线段((顶点(a, 1) + 顶点(a, 2)) / 2 + a sqrt(3) / 6 单位法向量(a), 顶点(a, 1) + 2(顶点(a, 2) - 顶点(a, 1)) / 3), 线段(顶点(a, 1) + 2(顶点(a, 2) - 顶点(a, 1)) / 3, 顶点(a, 2))} 这时候,我们可以用上边文本替换迭代命令中的"分形1"自定义工具了: l4 = 迭代(合并(映射({线段(顶点(a, 1), 顶点(a, 1) + (顶点(a, 2) - 顶点(a, 1)) / 3), 线段(顶点(a, 1) + (顶点(a, 2) - 顶点(a, 1)) / 3, (顶点(a, 1) + 顶点(a, 2)) / 2 + a sqrt(3) / 6 单位法向量(a)), 线段((顶点(a, 1) + 顶点(a, 2)) / 2 + a sqrt(3) / 6 单位法向量(a), 顶点(a, 1) + 2(顶点(a, 2) - 顶点(a, 1)) / 3), 线段(顶点(a, 1) + 2(顶点(a, 2) - 顶点(a, 1)) / 3, 顶点(a, 2))}, a, lst)), lst, {{f}}, 5)因此,在弄分形图时,强烈建议使用自定义工具,它相当于自定义函数,操作简单,可读性也强。
浅谈迭代列表 GeoGebra中生成集合可以用序列、映射、迭代列表。 其中映射最好理解,从一个列表,通过运算到另一个列表,元素是一一对应关系,如列表l1={A,B,C,D,E,F},用这5个点画5个单位圆: 映射(圆周(m,1),m,l1) 它的使用是不需要元素序数参与计算时非常简捷。 再来说序列,这是GeoGebra中用的最多的命令,需要元素序数参与计算时,就用使用“列表”命令了,如不使用折线命令的情况下,把l1={A,B,C,D,E,F}五个点用线段连起来: 序列(线段(l1(m),l1(m+1)),m,1,长度(l1)-1) 这里用来元素的序数了,因此用上了"序列"命令。 最不好理解或者不易掌握的是迭代列表,生成元素与上一个元素或者上几个元素有关时,用迭代列表,这个几句话也说不清,先举个迭代中最常用的斐不拉其数列: l3 = 迭代列表(a + b, a, b, {1, 1}, 10) 其结果是: {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89} 前两元素相加,得后一元素,依此类推,其中a+b为表达式,a,b为变量,{1,1}为a、b初始取值,必须是列表形式给出,10为迭代次数。 当然,GeoGebra不仅可以对数值进行迭代,它可以是其它几何对象,如下有A、B两点,从A点出发,求出AB中点C后,用C代替A,继续求CB中点,一直重复6次。l4 = 迭代列表(中点(m, B), m, {A}, 6) 这里的变量m不再是数值,而是点,请注意的是你要生成的东西,和变量初始值必须是同一类东西才行。 下边相对复杂一点了,正方形迭代图:A = (2, 2) B = (-2, 2) f = 线段(A, B) k = 0.08 n = 16 l1 = 迭代列表(线段(描点(m, k), 描点(线段(顶点(m, 2), 顶点(m, 2) + 法向量(m)), k)), m, {f}, n) l2 = 映射(多边形(顶点(m, 1), 顶点(m, 2), 4), m, l1) 在这个l1中,迭代变得复杂点,主要是我们把若干命令整理到一个表达式中了,它是这么一个过程: C = 描点(f, k) g = 线段(B, B + 法向量(f)) D = 描点(g, k) h = 线段(C, D) E = 描点(h, k) ..........................................上述命令除最后一条,组合在一起,就是迭代列表中的表达式了,只是把变量,有明确名称的点换成通用表达。 当然,在使用迭代列表时,我们有时候要迭代出来的东西,不太可能整合成一个表达式,这个时候可以使用自定义工具来协助了,如下勾股树的生成,我们先定义一个自定义工具,取名叫“生成元”:这个工具输入参数是a和poly3,输出为lst2 然后我们用迭代列表来生成勾股树: a = 0.6 n = 4 poly1 = 多边形((1, 0), (3, 0), 4) L = 合并(迭代列表(合并(映射(生成元(p, a), p, lst)), lst, {{poly1}}, n))
简单的界面示意功能,没有实现球边撞击、球球撞击运动。 l1 = 序列((4 + 4ί) ί^k, k, 0, 3) l2 = (x(l1) * 2, y(l1)) q1 = 多边形(l2) 用复数画一个边长2:1的绿色矩形,作为桌面。l3 = 合并({l2, {(0, -4), (0, 4)}}) l4 = 映射(圆周(a, 0.4), a, l3) q2 = 多边形(映射(a - 0.3b, a, l2, b, l1 / 4)) A = 内点(q2) c: 圆周(A, 0.3) 画六个洞,母球,母球圆心活动范围的框。l7 = 合并({l2, {l2(1)}}) l8 = 序列(线段(l7(i), l7(i + 1)), i, 1, 4) l9 = 映射(平移(a, b), a, l8, b, {(0, 0.5), (-0.5, 0), (0, -0.5), (0.5, 0)}) l10 = 映射(圆周(a, 0.5), a, l2) poly1 = 多边形(扁平列表(映射({顶点(a, 1), 顶点(a, 2)}, a, l9))) 画出球桌外边框d: 圆周(A, 0.3) q3 = 多边形(l2) B = (-1.24926, -0.5167) C = 描点(圆周(B, 2.5)) D = 对称(C, B) f = 线段(C, D) 给母球和桌面加个边框,然后事球杆,B点移动、C点旋转球杆。E = 交点(c, 直线(C, D), 2) g: 射线(D, E) F = 交点(g, q1) G = 交点(射线(A, 向量(E, F)), q2) 瞄准线及母球球心移动线button1 a = 1 k: 垂线(A, g) H = 交点(g, k) b = 是否已定义(E) A_0 = A 击球按钮button1,其点击时脚本如下: 赋值(a,0) A_0=A if(b,赋值(B,H-向量(B,D))) 启动动画(a,b) 滑动条a(0--1),其更新时脚本如下: 赋值(A,A_0+a (G-A_0)) H点确定球杆击出时移动位置p: 如果(abs(x(G)) ≟ 7.7, y = y(G), x = x(G)) G' = 对称(G, p) A' = 对称(A, p) l: 射线(G', A') I_{1} = 交点(l, q2) I = 交点(l, q2) I_0 = 如果(距离(I, G) ≟ 0, I_{1}, I) m = 线段(G, I_0) 反射线路计算
在封闭区域内随机产生多个不重叠的圆 以多边形为例,在封闭区域产生随机点很容易,一个命令的事: 序列(随机内点(p1),i,1,100) 但是我们现在想在封闭区域内随机产生多个圆,且这些圆不能相交,方便小朋友去数个数,情况就娈复杂多了。 (点坐标省去) l1 = {A, B, C, D, E, F, G, H, I, J, K, L, M, N, A} (列表时,最后加上第一个点,后面用的上) p1 = 多边形(l1)由于产生的是圆,我们不能简单地以这个多边形为边界,要根据圆半径向内等距缩小(不能用位似命令)。 r = 0.1 (要生成圆半径) l2 = 序列(直线(l1(i), l1(i + 1)), i, 1, 长度(l1) - 1) l3 = 映射(平移(m, 向量(-r 单位法向量(m))), m, l2) l5 = 合并({l3, {l3(1)}}) l4 = 序列(交点(l5(i), l5(i + 1)), i, 1, 长度(l5) - 1) p2 = 多边形(l4)我们通过以上操作,把多边形各边向内等距移动r,得到新的多边形作为边界(蓝色) a = 最大值(x(l4)) b = 最小值(x(l4)) c = 最大值(y(l4)) d = 最小值(y(l4)) e = 曲面((u, v), u, b, a, v, d, c) l6 = 序列(序列((i, j), j, d, c, 2r), i, b, a, 2r)生成刚好能盖住p2的点阵,点阵间距为2r,这是我们生成圆的基础,下边是确定在p2内的这些点。 l7 = 扁平列表(l6) l9 = 序列((距离(l7(i), 区域内最近点(p2, l7(i))), i), i, 1, 长度(l7)) l8 = 条件子列(x(A) ≟ 0, A, l9) l10 = y(l8) l11 = 序列(l7(l10(i)), i, 1, 长度(l10))上边图可以看到,我们在蓝色区域内生成了点阵,从这些点中随机生成点就行了。 n = 36 (整数滑动条,1到长度(l11),增量1,确定生成圆个数) l12 = 序列(随机元素(l11), i, 1, n) l13 = 映射(圆周(a, r), a, l12)上边是完成图,实现了在封闭区域内随机产生不相交的圆的设想。
GeoGebra中复数应用初探 在GeoGebra中,复数可以用点来表示,反过来,点的坐标可以用复数形式给出,如: z_1 = 4 + 6ί,在绘图区显示坐标为(4,6)的点。如果仅仅如此的话,复数在GeoGebra中就显得多余,其实复数是在复平面上,只是我们这里的直角坐标平面与复数平面重叠罢了,复数简单运用先举个例子: z_2 = 4 + 4ί l1 = 序列(z_2 ί^k, k, 0, 3) q1 = 多边形(l1) 这个运用有时候比点的旋转还好使,看你怎么设计表达式了。(注ί不是i,看清楚,是虚数ί)复数作为变量又是什么呢? 输入 x + 0ί,我们得到了一平面,这个平面就是复平面了,而这个函数就是复函数了: b(x) = x + 0ί为什么说它是复平面,我们引用一下函数: 输入 b(4,6),我们会得到一个复数z_3=b(4,6),它的表达式是4+6ί,对应实平面(4,6)点。 如果我们再进一步,输入x+y ί,情况如下: e = 曲面(x + y ί, x, -10, 10, y, -10, 10),系统自动用了曲面命令,显然它不再是复平面了,输入e(4,6)试试: 得到 A = e(4, 6),它是实平面一个点了,因此e平面与下边平面等价: d = 曲面((u, v), u, -10, 10, v, -10, 10),用x+y ί与用(u,v)是一样的,是点的表达式不同形式,至少GeoGebra在这里就是这样处理的。 对于b(x) = x + 0ί平面,如果我们输入 x ί呢,得到c(x) = x ί,它也是一个复平面,表面上与b(x)g一样,但你输入c(4,6)试试,得到的复数与b(4,6)是不同的,它是-6+4ί,相当于把b(4,6)再乘以一个虚数ί,因此c平面内的复数与b平面内对应的复数相比,是旋转了90 度的。
折线方程再谈(点列法) 本吧已经谈过关于折线或者多边形的方程问题,我们可以用如果语句分段给出折线方程,也可以用符号函数拼出方程,还可以从反演图形中提取折线方程,也可以仿反演计算出方程,甚至用曲线拼接法生成,有兴趣的可以搜一下本吧,这里先给出仿反演计算出折线方程,这是绝对值方程,相对来说方程不复杂,比较实用:我是把上述代码做成了工具,输入项为l1,输出项为b,运算速度还可以。 本贴讨论的不是此法,而是另一种更为简单的方法,只是用这种方法生成的折线参数方程,不能像上边的那样可以给折线作切点。先看上图,左边是一个多边形或者首尾点重合的折线,我们这里统一叫折线,生成代码如下: A = (-1.90312, 0.50455) B = (-1.40112, 1.07905) C = (-0.54314, 0.84849) D = (-0.29317, 0.35819) E = (-0.77847, -0.46604) F = (-1.76447, -0.18873) l1 = {A, B, C, D, E, F, A} f = 折线(l1) l2 = 序列((i - 1, x(l1(i))), i, 1, 长度(l1)) l3 = 序列((i - 1, y(l1(i))), i, 1, 长度(l1)) l4 = 映射(直线(m, y = 0), m, l3) l5 = 映射(直线(m, x = 0), m, l2) 我们将点列横坐标和纵坐标分别提取出来,根据点的个数,横坐标间隔为1,形成两个点列。 这两个点列是可以分别用函数表示的: p(x) = 函数(合并({{0, 长度(l1) - 1}, x(l1)})) q(x) = 函数(合并({{0, 长度(l1) - 1}, y(l1)}))上边两条函数,就是我们需要的东西了: b = 曲线(p(t), q(t), t, 0, 长度(l1) - 1) 这就是折线参数方程了,用了点列函数构成参数方程,它的图形与折线命令生成图形完全一样。
参数曲线最值问题 如上图,我们有一条样条曲线,怎么求出它的最高点和最低点(图中红色点)? 我们先画出这条曲线(点坐标略去) l1 = {A, B, C, D, E, F, G} a = 样条曲线(l1, 3) 然后对曲线进行求导: b = 参数导数(a)图中兰色虚线为参数导数的图象,这里不能直接用“导数”命令来求曲线导数,因为那样是对自变量t求导,等一下再讲参数导数是怎么回事。 I = 交点(y = 0, b) H = 交点(y = 0, b) f: 垂线(H, x轴) g: 垂线(I, x轴) J = 交点(f, a) K = 交点(g, a)上述操作,简单来说,就是求参数导数函数的零值点,把零值点横坐标代入曲线,求得最值点J、K。 其原理是:最值点的切线必然与x轴平等,即斜率为0,也就是其导数为零,当然,一条曲线可能有很多切线平行于x轴的点,我们可以都找出来,比较大小就行了。 上边原理,学过导数的都不难理解,比较难理解的是“参数导数”这个命令,我们先对曲线进行一般化处理: p(x) = 如果(0 ≤ x ≤ 1, x(a(x))) q(x) = 如果(0 ≤ x ≤ 1, y(a(x))) c = 曲线(p(t), q(t), t, 0, 1) 这里p和q函数是提取参数方程中x和y的表达式,形成两个函数,这两个函数用曲线命令组织在一起,就是最初的那个样条曲线,这里这样处理一下,是表示对其它参数曲线同样适用,让它一般化而已。 我们再定义如下函数: d = 曲线(p(t), q'(t) / p'(t), t, 0, 1) 这个函数图形与"b = 参数导数(a)"完全一样,这就是参数导数的定义了,它是取原参数曲线x表达式为自己的x表达式,用y分量导数除以x分量导数作为自己y的表达式。 因此,我们上述操作就有了依据,参数导数上的点,其横坐标与原曲线上的点横坐标是对应相等的,通过零值点我们就可以用作图法确定曲线最值点了。
路径值反求(给定交点或者点的坐标,求其在曲线上路径值) 有时候我们需要把曲线与其它图形的交点在曲线上对应的路径值求出来,或者对样条曲线控制点反求t值,这个在GeoGebra中,是不能直接用"路径值"这个命令的,因为你给出的点只是恰好落在曲线上,并不是路径上的点,但我们可以作变通,使用如下命令可以直接获取点的路径值: 路径值(最近点(曲线, 给定点)) 现举例如下: g(x) = x² G = (-1.79728, 0.3667) H = (2.00135, 1.44022) h: 直线(G, H) J = 交点(g, h) I = 交点(g, h)显然,交点I、J是不能直接使用“路径值命令的”,因为它不是定义在曲线g(x)上,只是计算后得到的点,我们用如下命令: i = 路径值(最近点(g, I)) K = 描点(g, i) j = 路径值(最近点(g, J)) L = 描点(g, j)用K、L替换两个交点,就实现使交点在路径上了,K、L与两交点是分别相等的。 再研究一下样条曲线控制点反求,然后我们对样条曲线分段,有人可能会说,样条曲线参数方程不是给出了各点路径值了吗?但我们怎么自动获取呢?如果样条曲线控制点本身就是动态的,更不容易获取,因此,我们还是采用上上述方法,注意一点的是,样条曲线求t值与求路径值是等价的。 A = (-0.68797, -0.60429) B = (-0.26407, 0.36463) C = (1.01522, 0.31164) D = (1.09091, -0.29393) E = (2.18095, -0.63457) F = (2.72597, 0.26623) l1 = {A, B, C, D, E, F} a = 样条曲线(l1, 3) l2 = 映射(路径值(最近点(a, M)), M, l1)如上,我们一次性地求出了各控制点A、B、C、D、E、F在曲线上的t值(或者路径值)。 l3 = 序列(曲线(a(t), t, l2(i), l2(i + 1)), i, 1, 长度(l1) - 1) b = 元素(l3, 1) c = 元素(l3, 2) d = 元素(l3, 3) e = 元素(l3, 4) f = 元素(l3, 5) (当然,列表l3我们可以配合表格功能,自动放入表格中,实现分段曲线单独提取)。
立体汉字制作 本贴没什么代码,与立体勾股注水制作类似,首先是在平面把汉字图形放进来,然后用点描边。以岁字为例: 把图片放进来,调整大小和位置,然后描点:这里是从O_5开始,最后要回到它或者是和它相邻的点,中间有重复点(在重复路径上),遇到描重复点时,先在已有点附近描上点,然后在代数修改为此点等于已有的那个点。 l6 = {O_5, P_5, Q_5, R_5, S_5, T_5, U_5, V_5, W_5, Z_5, A_6, B_6, C_6, D_6, E_6, F_6, G_6, H_6, I_6, J_6, K_6, L_6, M_6, N_6, O_6, P_6, Q_6, R_6, S_6, T_6, U_6, V_6, W_6, Z_6, A_7, B_7, C_7, D_7, E_7, F_7, G_7, H_7, I_7, J_7, K_7, L_7, M_7, N_7, O_7, P_7, Q_7, R_7, S_7, T_7, U_7, V_7, W_7, Z_7} 这里列表放上来,是可以看看点的顺序,其中Q_7=D_7,P_7=C_7。其它汉字同样处理,这样可以让一个汉字用一个多边形解决。 当然,也可以把汉字折分成几个多边形,免的来回描点,如“祖”字:点、示旁、且,分别为多边形p1、p2、p3。 用多边形命令把这些点画成多边形: p1 = 多边形(l1) p2 = 多边形(l2) p3 = 多边形(l3) p4 = 多边形(l4) p5 = 多边形(l5) p6 = 多边形(l6)l7 = {p1, p2, p3, p4, p5, p6} l7' = 切变(l7, x轴, 0.5) 关闭p1--p6显示,打开l7'显示,做个投影,然后打开3D视图区 让平面汉字站起来: p1' = 旋转(p1, π / 2, x轴) p2' = 旋转(p2, π / 2, x轴) p3' = 旋转(p3, π / 2, x轴) p4' = 旋转(p4, π / 2, x轴) p5' = 旋转(p5, π / 2, x轴) p6' = 旋转(p6, π / 2, x轴)再让汉字厚起来: f = 棱柱(p1', 0.4) e = 棱柱(p2', 0.4) d = 棱柱(p3', 0.4) c = 棱柱(p4', 0.4)、 b = 棱柱(p5', 0.4) a = 棱柱(p6', 0.4)
双三次样条曲面在GeoGebra中如何实现? 如题,这是一个讨论问题,尽管网上给出了双三次样条曲面的复杂表达式,但可能是本人看不懂,一直没能够转化到GeoGebra中来,有哪位大神做过,不妨放上来学习一下。 本人如今只想到了替代办法,就是探讨由四条曲线决定的曲面问题,我们已经实现了三条曲线曲面问题,如何继续实现四条曲线的曲面,由于运算量太大,我们就在二维平面中讨论。 如下图,平面四条样条曲线a、b、h、d:(直接略去点的坐标了) l1 = {A, B, C, D, E} a = 样条曲线(l1, 3) l2 = {F, G, H, I, J} b = 样条曲线(l2, 3) l3 = {E, M, L, K, J} d = 样条曲线(l3, 3) l4 = {A, P, O, N, F} h = 样条曲线(l4, 3) 由于在我的贴《平面曲面(网格)》中已经详细介绍了三条曲线形成的曲面网格,因此直接给出代码: k = 10 e = 曲线((1 - u / k) E + u / k J, u, 0, k) f = 曲面((1 - u / k) a(v / k) + u / k b(v / k) + d(u / k) - e(u), v, 0, k, u, 0, k)这个网格曲面只能满足三条曲线,同样,我们对左边曲线作曲面: g = 曲线((1 - u / k) A + u / k F, u, 0, k) i = 曲面((1 - u / k) a(v / k) + u / k b(v / k) + h(u / k) - g(u), v, 0, k, u, 0, k)它也只能满足三条曲线,这两个网格曲面如何叠加在一起,形成曲面i(绿色)到曲面f(红色)的过渡呢? 我们继续沿用过渡图形的作法,对曲面进行运算,由于这个运算量大,容易卡死,建议别在3D环境中试: j = 曲面((1 - u / k) i(u, v) + u / k f(u, v), u, 0, k, v, 0, k) 这个表达式看似简单,实则是双重过渡运算,基本实现了四条曲线形成曲面的想法,但总觉得哪些地方可以简化,减少运算量,不然老是不能用于3D环境,意义就不太大,总不至于用这方法给封闭图形填色吧,太奢侈了。
平面曲面(网格) 从最简单网格开始: a = 曲面((u, v), u, 0, 10, v, 0, 10)这是一个平面曲面,它有参数方程,用这个方法画网格,比用序列命令方便,一是可以直接定位曲面上的点,二是可以变形。 定位点,如: N=a(2,6)要变形的话,我们需要这个网格曲面更一般的表达式,先标出四角点吧: A = (0, 0) B=(10,0) C=(10,10) D=(0,10) 然后作直线AB、CD参数方程: b = 曲线((1 - u) A + u B, u, 0, 1) c = 曲线((1 - u) D + u C, u, 0, 1) 绘制曲面e,两曲线之间曲面绘制方法,替代曲面a: k=10 (滑动条,控制网络密度,1到50,增量1) e = 曲面((1 - u / k) b(v / k) + u / k c(v / k), v, 0, k, u, 0, k)表面看,它与曲面a没区别,其实区别大了,它是同两条线段AB和BC生成的,移动ABCD四个点它是会变形的:增加一些点,继续用曲线取代线段: E = (3.06, 0.66) F = (5.66, -0.62) G = (8.16, 0.24) H = (3.14, 10.56) I = (5.58, 9.66) J = (8.86, 10.3) l1 = {A, E, F, G, B} l2 = {D, H, I, J, C} f = 样条曲线(l1, 3) g = 样条曲线(l2, 3) h = 曲面((1 - u / k) f(v / k) + u / k g(v / k), v, 0, k, u, 0, k)再继续将直面纹变为曲面纹: K = (10.44, 7.86) L = (9.56, 5.46) M = (10.6, 2.68) l3 = {B, M, L, K, C} i = 样条曲线(l3, 3) d = 曲线((1 - u) B + u C, u, 0, 1) j = 曲面((1 - u / k) f(v / k) + u / k g(v / k) + i(u / k) - d(u / k), v, 0, k, u, 0, k)调整k,增大网格密度:注:本贴与《导线为曲线的空间曲面》类似,但侧重点不同,这里主要是讲二维环境下网格曲面。
样条曲面上作图 我们通过两条或者是三条样条曲线生成的曲面,它有两个参数u、v,因此我们可以把生成的曲面看作是一个新的坐标系,既然是坐标系,我们就可以在其上面作图:上图是在曲面上边作一个月形图,我们先生成这个曲面坐标系吧: C = (-2.23573, -1.36689, 1.80146) D = (-1.29832, 1.48708, 1.66691) E = (3.3498, -3.18408, 0.3428) G = (3.48213, -0.63162, 1.87176) F = (2.18446, 1.24183, 3.83644) a = 曲线((1 - u) C + u D, u, 0, 1) b = 样条曲线({E, G, F}, 3)这个平面和二维下坐标平面是对应关系,只是纵横坐标取值范围都是0到1而已,我们想在平面上作图,其实先在平面坐标(左边)作出参考图,然后映射到曲面上: A = (0.19994, 0.39742) B = (0.79944, 0.60051) I = (0.44014, 0.68039) d = 曲线((1 - u) A + u B, u, 0, 1) f = 样条曲线({A, I, B}, 3) e = 曲线(c(d(t)), t, 0, 1) g = 曲线(c(f(t)), t, 0, 1)如上,关键是e = 曲线(c(d(t)), t, 0, 1)和g = 曲线(c(f(t)), t, 0, 1)两个表达式,因为平面坐标系我们把用图弄在纵横坐标都是0到1范围,这样就完全与曲面对应了,其参数方程u和v的取值与平面坐标点的坐标是完全对应的,因此,平面坐标上的点可以直接代入曲面参数方程。 然后是给图形着色: h = 曲面((1 - u) e(v) + u g(v), v, 0, 1, u, 0, 1) 我们直接用在曲面上生成的曲线画曲面,对曲面着色就行了,修改一下图形图层,让颜色不被大曲面盖住。
不规则曲面绘制 不规则曲面一般用样条曲线来控制其形状,我们讨论过两条曲线之间曲面形成的问题,但较为复杂的空间曲面不能只用此法生成曲面,因为有个最大问题,曲面之间的光滑拼接,这里有三条空间样条曲线:l1 = {A, B, C, D, E} l2 = {F, G, H, I, J} l3 = {K, L, M, N, O} a = 样条曲线(l1, 3) c = 样条曲线(l3, 3) b = 样条曲线(l2, 3)由这三条曲线构成的曲面怎么弄,我们先试试两曲线之间曲面生成之法: q = 曲面(u a(t) + (1 - u) c(t), u, 0, 1, t, 0, 1) r = 曲面(u c(t) + (1 - u) b(t), u, 0, 1, t, 0, 1)两曲面拼在一起,是不光滑的,这个显然不是我们希望的曲面,我们需要继续处理,本例我们用平行于水平面的平面去切上述三条曲线,得到系列交点,然后组成若干样条曲线: l4 = {a, c, b} l5 = 序列(序列(交点(z = n, 元素(l4, m)), m, 1, 3), n, 0, 6.5, 0.5) l6 = 映射(样条曲线(u, 3), u, l5)我们的思路是在新得到的这些样条曲线之间生成若干曲面,这个要借助于表格了: l8 = 序列("B" + (i) + "= Element(l6," + (i) + ")", i, 1, 长度(l6)) 在代数区中输入:执行(l8) 这些曲线就进入表格中了,也就是每条曲线有名称了。 l9 = 序列("Surface(u* B" + (i) + "(t) + (1 - u) *B" + (i + 1) + "(t), u, 0, 1, t, 0, 1)", i, 1, 长度(l6) - 1) 这是生成若干曲面的文本命令列表,需要在代数区中输入:执行(l9) 生成图形如下,这个就是我们想要的曲面了:
两空间曲线之间的曲面 先讨论一下平面两条曲线之间的过渡图形,假如有函数p(x)与q(x),从p到q过渡曲线公式是: u*p(x)+(1-u)q(x) 这里我们设: p(x) = x + 5 q(x) = sin(x - 1) - 1 l6 = 序列(u p(t) + (1 - u) q(t), u, 0, 1, 0.1) 得到的图形如下:多数情况下曲线表达式是不确定的,我们可以用样条曲线代替: 设有下列两样条曲线(具体的点列略去): g = 样条曲线(l3, 3) h = 样条曲线(l4, 3) 我们参考上边的方法,将g和h作为简单函数处理: l5 = 序列(曲线(u g(t) + (1 - u) h(t), t, 0, 1), u, 0, 1, 0.1) 这里与上边不同的是,我们要规定t的取值范围,因此用了曲线命令,图形如下:基于上边的思路,在3D环境下是否可以这样实现两曲线之间的曲面形成呢? 由于多数情况下,3D曲线是以参数方程形式给出,我们这里先试试参数方程,设有两空间曲线: a = 曲线(cos(t), sin(t), sin(2t) + 3, t, 0, 2π) b = 曲线(2cos(t), 2sin(t), cos(2t) - 1, t, 0, 2π)按上边的方法试试: c = 曲面(u a(t) + (1 - u) b(t), t, 0, 2π, u, 0, 1)我们得到了我们需要的曲面,说明这个方法是可行的,再来试试空间样条曲线,这里我们直接在两曲线上取点了: l1 = 序列(a(t), t, 0, 2π, 2π / 30) l2 = 序列(b(t), t, 0, 2π, 2π / 30) d = 样条曲线(l1, 3) e = 样条曲线(l2, 3) f = 曲面(u d(t) + (1 - u) e(t), t, 0, 1, u, 0, 1)与上边图形略有不同,但基本上实现了我们所需,样条曲线形成的曲面更具有过渡中的变化感,比参数曲线直来直去的曲面要柔和些,注意一点的是,这里t值取值范围是0到1,是由样条曲线决定的,与参数曲线t的取值不同。
1 下一页