-- tkz_elements_functions_triangles.lua -- date 2025/01/06 -- version 3.10 -- Copyright 2024 Alain Matthes -- This work may be distributed and/or modified under the -- conditions of the LaTeX Project Public License, either version 1.3 -- of this license or (at your option) any later version. -- The latest version of this license is in -- http://www.latex-project.org/lppl.txt -- and version 1.3 or later is part of all distributions of LaTeX -- version 2005/12/01 or later. -- This work has the LPPL maintenance status “maintained”. -- The Current Maintainer of this work is Alain Matthes. --------------------------------------------------------------------------- -- triangle center with circle --------------------------------------------------------------------------- ------------------------ -- Points -- ------------------------ function circum_center_ ( a,b,c ) local ka = math.sin (2 * get_angle_ ( a,b,c )) local kb = math.sin (2 * get_angle_ ( b,c,a )) local kc = math.sin (2 * get_angle_ ( c,a,b )) return barycenter_ ( {a,ka} , {b,kb} , {c,kc} ) end function in_center_ ( a,b,c ) local ka = point.abs (b-c) local kc = point.abs (b-a) local kb = point.abs (c-a) return barycenter_ ( {a,ka} , {b,kb} , {c,kc} ) end function ex_center_ ( a,b,c ) local ka = point.abs (b-c) local kc = point.abs (b-a) local kb = point.abs (c-a) return barycenter_ ( {a,-ka} , {b,kb} , {c,kc} ) end function centroid_ (a,b,c) return barycenter_ ( {a,1} , {b,1} , {c,1} ) end centroid_center_ = centroid_ function ortho_center_ (a,b,c) local ka = math.tan (get_angle_ ( a,b,c )) local kb = math.tan (get_angle_ ( b,c,a )) local kc = math.tan (get_angle_ ( c,a,b )) return barycenter_ ( {a,ka} , {b,kb} , {c,kc} ) end function euler_center_ (a,b,c) local ma,mb,mc = medial_tr_ ( a,b,c) return circum_center_ (ma,mb,mc) end function gergonne_point_ (a,b,c) local u,v,w u,v,w = intouch_tr_ (a,b,c) return intersection_ll_ ( a,u , b,v) end function lemoine_point_(a,b,c) local ma,mb,mc,ha,hb,hc,u,v,w u = point.abs(c-b) v = point.abs(a-c) w = point.abs(b-a) return barycenter_ ({a,u*u},{b,v*v},{c,w*w}) end function nagel_point_ (a, b, c) -- Calculate the excircle tangency points (u, v, w) local u, v, w = extouch_tr_ (a, b, c) -- Find the intersection of lines through a and u, and through b and v return intersection_ll_ (a, u, b, v) end function feuerbach_point_ (a, b, c) local i, h, e, ma -- Calculate the incenter and some related point (likely the orthocenter or another center) i, h = in_circle_ (a, b, c) -- Calculate the Euler center (center of the nine-point circle) e = euler_center_ (a, b, c) -- Calculate the midpoint of side BC ma = (b + c) / 2 -- Find the intersection of the circles at (i, h) and (e, ma), which gives the Feuerbach point return intersection_cc_ (i, h, e, ma) end function spieker_center_ (a,b,c) return in_center_ (medial_tr_ ( a,b,c)) end function euler_points_ (a,b,c) local H H = ortho_center_ ( a , b , c ) return midpoint_ ( H,a ), midpoint_ ( H,b ), midpoint_ ( H,c ) end -------------------- -- lines -- -------------------- -- N,G,H,O function euler_line_ (a,b,c) check_equilateral_ (a,b,c) local A = math.tan( get_angle_ ( a,b,c )) local B = math.tan( get_angle_ ( b,c,a )) local C = math.tan( get_angle_ ( c,a,b )) return euler_center_ (a,b,c), barycenter_ ( {a,1} , {b,1} , {c,1} ) , barycenter_ ( {a,A} , {b,B} , {c,C} ) , barycenter_ ( {a,B+C} , {b,A+C} , {c,A+B} ) end function bisector_ (a,b,c) -- possible intersection bisector with side return in_center_ (a,b,c) end function bisector_ext_ (a,b,c) local i i = in_center_ (a,b,c) return rotation_ (a,math.pi/2,i) end function mediators_ (a,b,c) local o = circum_center (a,b,c) return o , projection_ (b,c,o) , projection_ (a,c,o) , projection_ (a,b,o) end -------------------- -- circles -- -------------------- function circum_circle_ ( a,b,c ) local ka = math.sin (2 * get_angle_ ( a,b,c )) local kb = math.sin (2 * get_angle_ ( b,c,a )) local kc = math.sin (2 * get_angle_ ( c,a,b )) return barycenter_ ( {a,ka} , {b,kb} , {c,kc} ) end function in_circle_ ( a,b,c ) local ka,kb,kc,o ka = point.abs (b-c) kc = point.abs (b-a) kb = point.abs (c-a) o = barycenter_ ( {a,ka} , {b,kb} , {c,kc} ) return o , projection_ (b,c,o) , projection_ (a,c,o) , projection_ (a,b,o) end function ex_circle_ ( a,b,c ) local ka,kb,kc,o ka = point.abs (b-c) kc = point.abs (b-a) kb = point.abs (c-a) o = barycenter_ ( {a,-ka} , {b,kb} , {c,kc} ) return o , projection_ (b,c,o) , projection_ (a,c,o) , projection_ (b,a,o) end function euler_circle_ (a, b, c) local o, ma, mb, mc, H, ha, hb, hc -- Compute the Euler center (center of the nine-point circle) o = euler_center_ (a, b, c) -- Calculate the medial triangle (midpoints of the sides) ma, mb, mc = medial_tr_ (a, b, c) -- Calculate the orthic triangle (feet of the altitudes) ha, hb, hc = orthic_tr_ (a, b, c) -- Get the Euler line and midpoint (H) on the Euler line _, _, H, _ = euler_line_ (a, b, c) -- Return all relevant geometric elements return o, ma, mb, mc, ha, hb, hc, midpoint_ (H, a), -- Midpoint between H and vertex a midpoint_ (H, b), -- Midpoint between H and vertex b midpoint_ (H, c) -- Midpoint between H and vertex c end -------------------- -- triangles -- -------------------- function orthic_tr_ (a,b,c) local o = ortho_center_ (a,b,c) return projection_ (b,c,o) , projection_ (a,c,o) , projection_ (b,a,o) end function medial_tr_ (a,b,c) return barycenter_ ( {a,0} , {b,1} , {c,1} ) , barycenter_ ( {a,1} , {b,0} , {c,1} ) , barycenter_ ( {a,1} , {b,1} , {c,0} ) end function anti_tr_(a,b,c) return barycenter_ ( {a,-1} , {b,1} , {c,1} ) , barycenter_ ( {a,1} , {b,-1} , {c,1} ) , barycenter_ ( {a,1} , {b,1} , {c,-1} ) end function incentral_tr_ (a, b, c) local i, r, s, t -- Compute the incenter (center of the incircle) i = in_center_ (a, b, c) -- Calculate the points of tangency where the incircle touches the sides r = intersection_ll_ (a, i, b, c) -- Intersection of lines a-i and b-c s = intersection_ll_ (b, i, a, c) -- Intersection of lines b-i and a-c t = intersection_ll_ (c, i, a, b) -- Intersection of lines c-i and a-b -- Return the points of tangency that form the incentral triangle return r, s, t end function excentral_tr_ (a,b,c) local r,s,t,ka,kb,kc ka = point.abs (b-c) kc = point.abs (b-a) kb = point.abs (c-a) r = barycenter_ ( {a,-ka} , {b,kb} , {c,kc} ) s = barycenter_ ( {a,ka} , {b,-kb} , {c,kc} ) t = barycenter_ ( {a,ka} , {b,kb} , {c,-kc} ) return r,s,t end function intouch_tr_ (a,b,c) local i i = in_center_ (a , b , c) return projection_ (b,c,i), projection_ (a,c,i), projection_ (a,b,i) end function cevian_ (a,b,c,p) return intersection_ll_ (a,p,b,c), intersection_ll_ (b,p,a,c), intersection_ll_ (c,p,a,b) end function extouch_tr_ (a,b,c) local u,v,w u,v,w = excentral_tr_ (a,b,c) return projection_ (b,c,u) , projection_ (a,c,v) , projection_ (a,b,w) end function tangential_tr_ (a,b,c) local u,v,w,x,y,z,xx,yy,zz u,v,w = orthic_tr_ (a,b,c) x = ll_from_ ( a , v , w ) y = ll_from_ ( b , u , w ) z = ll_from_ ( c , u , v ) xx = intersection_ll_ (c,z,b,y) yy = intersection_ll_ (a,x,c,z) zz = intersection_ll_ (a,x,b,y) return xx,yy,zz end function feuerbach_tr_ (a,b,c) local e,m,ja,ha,jb,hb,jc,hc e = euler_center_ (a,b,c) m = midpoint_( b , c ) ja,ha = ex_circle_ ( a , b , c ) jb,hb = ex_circle_ ( b , c , a ) jc,hc = ex_circle_ ( c , a , b ) return intersection_cc_ (e,m,ja,ha), intersection_cc_ (e,m,jb,hb), intersection_cc_ (e,m,jc,hc) end function similar_ (a,b,c) local x,y,z,g g = centroid_ (a,b,c) x = homothety_ (g,-2,a) y = homothety_ (g,-2,b) z = homothety_ (g,-2,c) return x,y,z end -------------------- -- ellipse -- -------------------- function steiner_ (a,b,c) local g,fa,fb,delta,m,v g = centroid_ (a,b,c) delta = a*a+b*b+c*c -a*b-a*c-b*c fa = (a+b+c - point.sqrt(delta))/3 fb = (a+b+c + point.sqrt(delta))/3 m = midpoint_(b,c) r = (length(fa,m)+length(fb,m))/2 v = report_ (fb,fa,r,g) return ellipse: foci (fb,fa,v) end -------------------- -- miscellanous -- -------------------- function area_ (a,b,c) return point.mod(a - projection_(b,c,a))*point.mod (b - c)/2 end function check_equilateral_ (a, b, c) local A, B, C -- Compute the vectors representing the sides of the triangle A = b - c -- Side from b to c B = a - c -- Side from a to c C = a - b -- Side from a to b -- Check if all sides have approximately equal lengths if (point.abs(A) - point.abs(B) < tkz_epsilon) and (point.abs(B) - point.abs(C) < tkz_epsilon) then return true -- The triangle is equilateral else return false -- The triangle is not equilateral end end function parallelogram_ (a,b,c) local x = c + a - b return x end function barycentric_coordinates_ (a,b,c,pt) local AT,AA,AB,AC,x,y,z AT = area_(a,b,c) AA = area_(pt,b,c) AB = area_(a,pt,c) AC = area_(a,b,pt) x = AA/AT y = AB/AT z = AC/AT return x,y,z end function in_out_ (a,b,c,pt) local cba,cbb,cbc,TT,AT,AA,AB,AC AT = area_(a,b,c) AA = area_(pt,b,c) AB = area_(a,pt,c) AC = area_(a,b,pt) cba = AA/AT cbb = AB/AT cbc = AC/AT if (cba >= 0 and cba <= 1) and (cbb >= 0 and cbb <= 1) and (cbc >= 0 and cbc <= 1) then return true else return false end end function soddy_center_ (a,b,c) -- Step 1: Compute the incenter and excircle centers local i,e,f,g = in_circle_ (a,b,c) local ha,hb,hc = orthic_tr_ (a,b,c) -- Step 2: Find the intersection points for the tangent lines local x,xp = intersection_lc_ (a,ha,a,g) if (point.mod(ha-x) < point.mod(ha-xp)) then else x,xp = swap(x,xp) end local y,yp = intersection_lc_ (b,hb,b,e) if (point.mod(hb-y) < point.mod(hb-yp)) then else y,yp = swap(y,yp) end local z,zp = intersection_lc_ (c,hc,c,f) if (point.mod(hc-z) < point.mod(hc-zp)) then else z,zp = swap(z,zp) end -- Step 3: Calculate the intersections with the opposite triangle sides local xi,t = intersection_lc_ (xp,e,a,g) if in_out_ (a,b,c,xi) then else xi,t = swap(xi,t) end local yi,t = intersection_lc_ (yp,f,b,e) if in_out_ (a,b,c,yi) then else yi,t = swap(yi,t) end local zi,t = intersection_lc_ (zp,g,c,f) if in_out_ (a,b,c,zi) then else zi,t = swap(zi,t) end -- Step 4: Calculate the circumcenter of the triangle formed by the tangent points local s = circum_center_ (xi,yi,zi) return s,xi,yi,zi -- Return the Soddy center and the tangent points end