
Edu Analytic Geometry
Generate exact analytic-geometry solutions (conics, parameterized chords, range over m) with SymPy for math education content and interactive problem engines.
Install
npx skills add https://github.com/wy51ai/edulab --skill edu-analytic-geometryWhat is this skill?
- Single-source SymPy pipeline: answers, coordinates, step values, and frontend range bounds stay consistent
- Parameterized line x = m·y + c through fixed points, Vieta on y, range_over_m with open/closed endpoints
- m interpreted as cot θ with vertical (m=0) and horizontal (m→∞) edge cases documented
- Helpers: tex(), fnum(), is_clean filtering for “nice” rational/root answers in random problem generation
- Built on shared conics module with chord_setup and implicit curve substitution
Adoption & trust: 1 installs on skills.sh; 416 GitHub stars; trending (+100% hot-view momentum).
Recommended Skills
Paper Context Resolverlllllllama/ai-paper-reproduction-skill
Repo Intake And Planlllllllama/ai-paper-reproduction-skill
Env And Assets Bootstraplllllllama/ai-paper-reproduction-skill
Minimal Run And Auditlllllllama/ai-paper-reproduction-skill
Analyze Projectlllllllama/rigorpilot-skills
Ai Research Reproductionlllllllama/rigorpilot-skills
Journey fit
Primary fit
Build/docs is the shelf for authoring precise lesson material, steps, and LaTeX-backed explanations rather than shipping a consumer SaaS feature. Docs subphase fits curriculum builders who need one symbolic source of truth for answers, coordinates, and student-facing ranges.
SKILL.md
READMESKILL.md - Edu Analytic Geometry
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ analytic_kernel.py — 解析几何 sympy 精确求解核心。 设计哲学(单一数据源):答案、坐标、步骤数值、前端交互引擎的"理论范围"全部从这里的 sympy 精确结果导出,杜绝心算与不一致。 核心套路:含参直线 x = m·y + c(c 由"过定点"确定),代入圆锥曲线得关于 y 的二次方程, 韦达定理给出 y1+y2, y1·y2(精确),由此把目标量(数量积/弦长/面积/斜率积…)写成 m 的 表达式,再用 range_over_m 求其取值范围(含开闭端点判定)。 m 的几何含义:直线 x=my+c 的斜率为 1/m,即 m=cotθ(θ 为倾斜角)。 - m=0 → 竖直线(θ=90°) - m→∞ → 水平线(θ=0°,前端滑块拖到 0° 即此情形) """ import sympy as sp import conics from conics import x, y m = sp.symbols('m', real=True) u = sp.symbols('u', nonnegative=True) # u = m^2 # ---------------- 通用工具 ---------------- def tex(e): return sp.latex(sp.nsimplify(sp.simplify(e))) def fnum(e): return float(sp.N(e)) def is_clean(e): """答案是否"规整"(有理数或最简根式),用于随机出题筛选。""" e = sp.nsimplify(sp.simplify(e)) return e.is_rational or (e.free_symbols == set() and sp.simplify(e - sp.nsimplify(e)) == 0) def interval_latex(lo, hi, lo_closed, hi_closed): lb = '[' if lo_closed else '(' rb = ']' if hi_closed else ')' lo_s = r'-\infty' if lo == -sp.oo else tex(lo) hi_s = r'+\infty' if hi == sp.oo else tex(hi) return r"%s%s,\ %s%s" % (lb, lo_s, hi_s, rb) # ---------------- 含参直线 ∩ 圆锥曲线 + 韦达 ---------------- def chord_setup(conic, through): """直线 x = m·y + c 过点 through,与 conic 联立 → 关于 y 的二次。返回韦达量等。""" x0, y0 = sp.nsimplify(through[0]), sp.nsimplify(through[1]) c = x0 - m * y0 sub = sp.expand(conic['implicit'].subs(x, m * y + c)) num = sp.numer(sp.together(sub)) poly = sp.Poly(num, y) coeffs = poly.all_coeffs() if len(coeffs) != 3: raise ValueError(f"联立未得到 y 的二次方程:{poly}") A, B, C = coeffs return { 'm': m, 'c': c, 'A': A, 'B': B, 'C': C, 'poly': poly, 'ysum': sp.simplify(-B / A), 'yprod': sp.simplify(C / A), 'disc': sp.simplify(B**2 - 4 * A * C), } def _xy_from_y(cs, M=None): """由韦达量给出 x1+x2, x1x2(用于把目标量化成 m 的表达式)。""" ys, yp = cs['ysum'], cs['yprod'] xs = m * ys + 2 * cs['c'] # x1+x2 xp = m**2 * yp + m * cs['c'] * ys + cs['c']**2 # x1·x2 return sp.simplify(xs), sp.simplify(xp) # ---------------- 目标量(写成 m 的表达式)---------------- def dot_product_expr(conic, through, M): """以 M 为顶点,A、B 为交点的数量积 MA·MB 关于 m 的表达式。""" cs = chord_setup(conic, through) ys, yp = cs['ysum'], cs['yprod'] xs, xp = _xy_from_y(cs) Mx, My = sp.nsimplify(M[0]), sp.nsimplify(M[1]) # (x1-Mx)(x2-Mx)+(y1-My)(y2-My) = xp - Mx*xs + Mx^2 + yp - My*ys + My^2 expr = xp - Mx * xs + Mx**2 + yp - My * ys + My**2 return sp.simplify(expr), cs def chord_len_sq_expr(conic, through): """弦长平方 |AB|^2 关于 m 的表达式。|AB|^2=(1+m^2)[(y1+y2)^2-4y1y2]。""" cs = chord_setup(conic, through) expr = (1 + m**2) * (cs['ysum']**2 - 4 * cs['yprod']) return sp.simplify(expr), cs def triangle_area_expr(conic, through, vertex): """△(vertex,A,B) 面积 = 1/2·|AB|·d(vertex,l)。返回面积关于 m 的表达式。""" cs = chord_setup(conic, through) chord = sp.sqrt((1 + m**2) * (cs['ysum']**2 - 4 * cs['yprod'])) # 直线 x - m y - c = 0,点到直线距离 d=|vx - m vy - c|/sqrt(1+m^2) vx, vy = sp.nsimplify(vertex[0]), sp.nsimplify(vertex[1]) d = sp.Abs(vx - m * vy - cs['c']) / sp.sqrt(1 + m**2) return sp.simplify(sp.Rational(1, 2) * chord * d), cs # ---------------- 取值范围(关键:含开闭端点判定)---------------- def range_over_m(expr, horizontal_valid=True): """目标量 expr(m) 在 m∈ℝ 上的取值范围;horizontal_valid=True 表示水平线(m→∞) 也是合法直线(如椭圆过内点的弦),其极限值也被取到(端点闭)。 返回 dict:lo,hi(sympy)、lo_closed,hi_closed、latex、lo_f,hi_f(float)、argmax/argmin。 """ g = sp.simplify(expr) cand = [] # (value, attained?) # 驻点 dg = sp.together(sp.diff(g, m)) for r in sp.solve(sp.numer(dg), m): if r.is_real: cand.append((sp.simplify(g.subs(m, r)), True)) # m=0(竖直线,总是合法) cand.append((sp.simplify(g.subs(m, 0)), True)) # m→±∞(水平线) Lp = sp.limit(g, m, sp.oo) cand.append((sp.simplify(Lp), bool(horizontal_valid) and Lp.is_finite)) finite = [(v,