-- tkz_elements-ellipses.lua
-- date 2025/02/26
-- version 3.32
-- Copyright 2025  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.

---------------------------------------------------------------------------
--                           circles
---------------------------------------------------------------------------
ellipse = {}

function ellipse: new(pc, pa ,pb)
-- pc --> center   pa --> through big axe     pb --> little axe
    local type             = 'ellipse'
    local Rx               = point.abs ( pa - pc )
    local Ry               = point.abs ( pb - pc )
    local slope            = slope_ (pc,pa)
    local c                = math.sqrt (Rx*Rx-Ry*Ry) 
    local Fa               = pc + c*(point(math.cos(slope),math.sin(slope)))
    local Fb               = pc - c*(point(math.cos(slope),math.sin(slope)))
    local east             = pa
    local north            = pb
    local west             = 2 * pc - pa
    local south            = 2 * pc - pb
    local vertex           = pa
    local covertex         = pb
    local e                = c/Rx
    local h                = (Rx*Rx-c*c)/c
    local o = {   center   = pc,
                  vertex   = vertex,
                  covertex = covertex,
                  Rx       = Rx,
                  Ry       = Ry,
                  slope    = slope,
                  Fa       = Fa,
                  Fb       = Fb,
                  type     = type,
                  north    = north,
                  south    = south,
                  east     = east,
                  west     = west,
                  e        = e,
                  h        = h }
    setmetatable(o, self)
    self.__index = self
    return o
end

function ellipse: foci (f1,f2,v )
   local c,a,h,b,cov
   c = midpoint_ (f1,f2)
   a = point.abs(v-c)
   h = point.abs(f1-c)
   b = math.sqrt(a^2-h^2)
   cov = (v-c)*point(0,1)/point.abs(v-c)*b+c
    return ellipse: new (c,v,cov)     
end

function ellipse: radii (c,a,b,sl )
   local z,v,cov
   z     = point (a*math.cos(sl),a*math.sin(sl))
   v     = c +  z
   z.V   = v
   cov   =  (v-c)*point(0,1)/point.abs(v-c)*b+c
return ellipse: new (c,v,cov)     
end

function ellipse: eccentricity (f1,d,e)
  local E  =  conic : new (f1,d,e)
 return ellipse: new (E.c,E.vertex,E.covertex)
end

function ellipse: point (t)
   local phi = 2*t* math.pi
   local cx =  self.center.re
   local cy =  self.center.im
   local ax =  self.Rx * math.cos(self.slope) * math.cos(phi)
   local ay =  self.Rx * math.sin(self.slope) * math.cos(phi)
   local bx = -self.Ry * math.sin(self.slope) * math.sin(phi)
   local by =  self.Ry * math.cos(self.slope) * math.sin(phi)
return point (cx+ax+bx,cy+ay+by)
end

function ellipse: tangent_at (pt)
  local zi = in_center_ (self.Fa,pt,self.Fb)
  local u = pt+(zi-pt)*point(0,1)
  local u = normalize_(pt,u)
  local v = pt : symmetry (u)
    return line : new (u,v)
end

function ellipse: tangent_from (pt)
   local u,v,U,V,w,s1,s2,s3,s4
   w = report_ (self.Fb,self.Fa,2 * self.Rx)
   s1,s2 = intersection_cc_ (pt,self.Fa,self.Fb,w)
   u,v   = mediator_ (s1,self.Fa)
   U     = intersection_ll_ (u,v,self.Fb,s1)
   u,v   = mediator_ (s2,self.Fa)
   V     = intersection_ll_ (u,v,self.Fb,s2)
   return  line : new (pt,U) , line : new (pt,V)
end

function ellipse: in_out (pt)
     local d,D,an,m
     d = point.abs (pt - self.center)
     an = point.arg (pt - self.center)
     m = point(self.Rx*math.cos(an),self.Ry*math.sin(an))
     D = point.abs (m - self.center)
     if D-d > tkz_epsilon
      then
        return true
     else
        return false
     end
end

function ellipse: orthoptic_circle ()
   local r = math.sqrt(self.Rx*self.Rx+self.Ry*self.Ry)
   return circle : radius (self.center, r)
end

return ellipse