(* ::Package:: *)

BeginPackage["stereographic`"]


stereographic::usage="The package stereographic provides a list of functions {makePoly, formEqs, getFixPolys, milnorFibration} that perform operations on a plane 
complex algebraic curve with a singularity in the origin in order to project it from 4D into 3D and to analyse its singularities. Use ?name_function for more information on each function."
formEqs::usage="The function formEqs[complexBivPolyEqn, {list_of_two_variables}] takes as input a variable complexBivPolyEqn, which is a complex polynomial in two
variables specified by a list of two variables, list_of_two_variables. The input bivariate complex polynomial complexBivPolyEqn defines a plane complex algebraic
curve in the 4-dimensional space (4D). The function returns as output two polynomial equations in the variables x,y,z,\[Epsilon] that represents the defining equations of two 
algebraic surfaces in the 3-dimensional space (3D) that define an implicit algebraic curve in 3D, which is in fact the stereographic projection of 
the plane complex algebraic curve from 4D. The x,y,z variables represent the euclidean variables in 3D, while \[Epsilon] 
represents an input parameter (always a positive real number) which is involved in the definition of the homeomorphism used to project the input curve from 4D to 3D.
The input parameter \[Epsilon] is choosen by the user and for sufficiently small values of \[Epsilon] we know that the implicit algebraic curve from 3D is an algebraic link, i.e.
a special kind of curve, i.e. a simple closed curve in 3D that does not intersect itself."
makePoly::usage="The function makePoly[algebraicEqn] transform a bivariate algebraic equation algebraicEqn containing possible denominators in the two variables 
and possible nonintegers exponents of the two variables into a polynomial equation"
getFixPolys::usage="The function getFixPolys[complexBivPolyEqn, {list_of_variables}, value] takes as input a bivariate complex polynomial in two variables
specified by a list of two variables list_of_variables, and a positive real number specified by value. The function uses the 
formEqs[complexBivPolyEqn, {list_of_variables}] function to transform the bivariate input polynomial in two polynomials in the variables x,y,z,\[Epsilon] and 
it instantiantes \[Epsilon] with value in these returned polynomials. The returned polynomials define an implicit algebraic curve in 3D, given as the intersection of two 
implicit algebraic surfaces in 3D that represent the Milnor fibration."
milnorFibration::usage="The function getFixPolys[complexBivPolyEqn, {list_of_variables}, value] takes as input  bivariate complex polynomial in two variables
specified by a list of two variables list_of_variables, and a positive real number specified by value. The function uses getFixPolys[complexBivPolyEqn, {list_of_variables}
to return two polynomials in the variables x,y,z in which \[Epsilon] is instantiated with value. These polynomials represent two implicit algebraic surfaces in 3D, which define an
implicit algebraic curve in 3D, which is the projection of the input plane complex algebraic curve. The two implicit algebraic surfaces from 3D represent 
the Milnor fibration of the singularity of the curve."


(*Begin["`Private`"]*)
Share[];


formEqs[complex_,{m_,n_}]:=Block[{complexnew,complexnew1, realeq, imageq, expreal, expimag, polyrealF, polyimagF,s,t,u,v,a,b,c,Global`\[Epsilon],Global`x,Global`y,Global`z},
(*we substitute z with the complex number s+it, w with u+iv*)
complexnew:=complex/.{m->s+I*t,n->u+I*v};
complexnew1:=complexnew/.{s->(2 a \[Epsilon])/(1+a^2+b^2+c^2),t->(2 b \[Epsilon])/(1+a^2+b^2+c^2),u->(2 c \[Epsilon])/(1+a^2+b^2+c^2),v->(-\[Epsilon]+a^2 \[Epsilon]+b^2 \[Epsilon]+c^2 \[Epsilon])/(1+a^2+b^2+c^2)};
realeq:=ComplexExpand[Re[complexnew1]];
imageq:=ComplexExpand[Im[complexnew1]];
expreal:=makePoly[realeq];
expimag:=makePoly[imageq];
polyrealF:=expreal/.{a->x,b->y,c->z};
polyimagF:=expimag/.{a->x,b->y,c->z};

{polyrealF,polyimagF}
]


makePoly[myexp_]:=Module[{denom,i,mydenum,newexp,newexp1},
denom={};
For[i=1,i<=Length[myexp],i++,
	If[MemberQ[denom,myexp[[i]]]==True,
denom=Union[denom,{ }],denom=Union[denom,{Denominator[myexp[[i]]]}]]
];
mydenum=denom[[Length[denom]]];
newexp=Expand[Simplify[Expand[mydenum*myexp]]];
newexp1=Expand[Numerator[Factor[myexp]]];
newexp1
]


getFixPolys[complex_,{m_,n_},val_]:=Module[{},
 (*Print[StyleForm[StringForm["The result {poly1, poly2} with poly1=poly2=0 is the projected curve in 3D\n"],FontColor->RGBColor[1,0,0]]];*)
 (*Print["Replacing epsilon in the 2 polynomial equations: \[Epsilon] -> ",val];*)
{formEqs[complex,{m,n}][[1]]/.{\[Epsilon]->val},formEqs[complex,{m,n}][[2]]/.{\[Epsilon]->val}}
]


milnorFibration[complex_,{m_,n_},val_]:=Module[{f1,f2},
f1:=getFixPolys[complex,{m,n},val][[1]];
f2:=getFixPolys[complex,{m,n},val][[2]];
Print[StyleForm[StringForm["Visualization of the milnor fibration of the singularity (0,0) of the given plane complex algebraic curve.\n"],FontColor->RGBColor[1,0,0]]];
Return[ContourPlot3D[{f1,f2},{x,-4,4},{y,-4,4},{z,-6,6}]]
]


If[$Notebooks,
   CellPrint[Cell[#, "Print", FontColor -> Black, 
                              CellFrame -> 0.5, 
                              Background -> LightGray]]&,
   Print
  ]["stereographic - by Madalina Hodorog -  A package that uses the generalized stereographic 
projection method to project from 4D into 3D a plane complex algebraic curve with singularity in the 
origin allowing the analysis for the singularity of the plane complex algebraic curve by visualizing 
the Milnor fibration of the singularity."]



(*End[]*)
EndPackage[]
