
function PerpendicularBisector(a,b,options)//Draws Perpendicular Bisector of points a,b 
{var X,Y;
X=Segment(a,b,'[hidden]')
Y=Midpoint(X,'[hidden]')
return Perpendicular(X,Y,options)
}
function Circle3Points(a,b,c,options)
//Draws a circle through the points a,b and c
{var h='[hidden]';
var b1=PerpendicularBisector(a,b,h)
var b2=PerpendicularBisector(a,c,h)
var s=Intersect(b1,b2,h)
return Circle(s,a,options)
}
function AngleBisector(a,vertex,c,options)//Draws Angular Bisector of angle a-vertex-c
{var h='[hidden]'
var circle=Circle(vertex,a,h)
var va=Ray(a,vertex,h)
var vc=Ray(c,vertex,h)
var s2=Intersect2(vc,circle,h)
var seg=Segment(a,s2,h)
var m=Midpoint(seg,h)
return Ray(m,vertex,options)
}
function AngleBisector2(a,vertex,c,options)//Draws second Angular Bisector of angle a-vertex-c
{var h='[hidden]'
var circle=Circle(vertex,a,h)
var va=Line(a,vertex,h)
var vc=Line(c,vertex,h)
var s1=Intersect1(va,circle,h)
var s2=Intersect1(vc,circle,h)
var seg=Segment(s1,s2,h)
var m=Midpoint(seg,h)
return Ray(m,vertex,options)
}

function InscribedCircle(a,b,c,options)//Draws inscibed circle of points a, b and c
{var h='[hidden]'
var b1=AngleBisector(a,b,c,h)
var b2=AngleBisector(a,c,b,h)
var s=Intersect(b1,b2,h)
var seg=Segment(a,b,h)
var p=Perpendicular(seg,s,h)
var l=Intersect(p,seg,h)
return Circle(s,l,options)
}

function Arc(vertex,startpoint,endpoint,radius,options)//Arc with a radius equal to that of Segment radius, with startpoint and endpoint defining the "rays";the arclength is allways less than or equal to 180 degres
{var h='[hidden]'
var c=Circle_by_radius(vertex,radius,'hidden')
var ray1=Ray(startpoint,vertex,h)
var ray2=Ray(endpoint,vertex,h)
var s1=Intersect2(ray1,c,h)
var s2=Intersect2(ray2,c,h)
var seg=Segment(s1,s2,h)
var m=Midpoint(seg,h)
var ppb=Ray(vertex,m,h)
var P=Intersect2(ppb,c,h)
var Q=Point_on_object(seg,0.1,h)
var ray3=Ray(Q,P,h)
var A=Intersect2(ray3,c,h)
return Locus(A,Q,seg,200,options)
}

function Arc2(vertex,startpoint,endpoint,radius,options)//Arc with a radius equal to that of Segment radius, with startpoint and endpoint defining the "rays";the arclength is allways more than or equal to 180 degres
{var h='[hidden]'
var c=Circle_by_radius(vertex,radius,'hidden')
var ray1=Ray(startpoint,vertex,h)
var ray2=Ray(endpoint,vertex,h)
var s1=Intersect2(ray1,c,h)
var s2=Intersect2(ray2,c,h)
var seg=Segment(s1,s2,h)
var m=Midpoint(seg,h)
var ppb=Ray(m,vertex,h)
var P=Intersect2(ppb,c,h)
var Q=Point_on_object(seg,0.1,h)
var ray3=Ray(Q,P,h)
var A=Intersect2(ray3,c,h)
return Locus(A,Q,seg,200,options)
}

function Parabola(focus,directrix,options)//Draws Parabola given focus and directrix
{var e,g,h,p
e=Point_on_object(directrix,0.2,'[hidden]')
p=Perpendicular(directrix,e,'[hidden]')
g=PerpendicularBisector(focus,e,'[hidden]')
h=Intersect(p,g,'[hidden]')
return Locus(h,e,directrix,200,options)
}

function Ellipse_Hyperbola(focus1,focus2,radius_directrix,options)//Draws Ellipse/Hyperbola with foci focus1 and focus2, whose directrix is a circle with centre focus1 and radius given by the length of segment radius_directrix.
 {var e,g,h,p
var directrix=Circle_by_radius(focus1,radius_directrix,'[hidden]')
e=Point_on_object(directrix,0,'[hidden]')
p=Ray(e,focus1,'[hidden]')
g=PerpendicularBisector(focus2,e,'[hidden')
h=Intersect(p,g,'[hidden]')
return Locus(h,e,directrix,200,options)
}

/*

function bezier(a,options)
//Constructs a bezier curve. List a contains the points. The curve starts and ends at the first and last point. All other points are guide points. Options contains the options of the curve. Bezier returns an array of all construction elements. The first element (with index zero) refers to the curve itself. This array can be handed to action buttons. A simple way to refer to the construction elements only is to assign the element with index 1 to the element with index zero. To refer to the curve only use the list with only element the element with index zero.

{
function bezier2(head,tail){
points[points.length]=Segment(head,tail,h)
var pp=DilationMarkedRatio(head,tail,r,h)
points[points.length]=pp
return pp
}

function bezierx(a){
if (a.length==2) {return bezier2(a[0],a[1])} else {
var k=new Array()
for (var i=0;i<a.length-1;i++)
{k[i]=bezier2(a[i],a[i+1])}
return bezierx(k)}
}
h='hidden'
construction+='{Start Bezier}\n'
points=new Array()
var s1=Segment(a[0],a[1],h)
points[0]=s1
var p=Point_on_object(s1,0.6,h+',red,layer(1000)')
points[1]=p
var r=RatioPoints(a[1],a[0],p,10,10,'r=',h)
var l=bezierx(a)
points[points.length]=Locus(l,p,s1,200,options)
points.reverse()
construction+='{ende bezier}\n'
return points
}

*/
function bezier(a,options)
//Constructs a bezier curve. List a contains the points. The curve starts and ends at the first and last point. All other points are guide points. Options contains the options of the curve. Bezier returns an array with two elements. The first element (with index zero) refers to the curve itself. The second element (index 1) is an array that contains the construction. This array can be handed to action buttons. 

{
function bezier2(head,tail){
points[1][points[1].length]=Segment(head,tail,h)
var pp=DilationMarkedRatio(head,tail,r,h)
points[1][points[1].length]=pp
return pp
}

function bezierx(a){
if (a.length==2) {return bezier2(a[0],a[1])} else {
var k=new Array()
for (var i=0;i<a.length-1;i++)
{k[i]=bezier2(a[i],a[i+1])}
return bezierx(k)}
}
h='hidden'
construction+='{Start Bezier}\n'
points=new Array()
points[1]=new Array()
var s1=Segment(a[0],a[1],h)
points[1][0]=s1
var p=Point_on_object(s1,0.6,h+',red,layer(1000)')
points[1][1]=p
var r=RatioPoints(a[1],a[0],p,10,10,'r=',h)
var l=bezierx(a)
points[0]=Locus(l,p,s1,200,options)
construction+='{end bezier}\n'
return points
}

function cov(func)
{if (RegExp) {
re=/round/g
func=func.replace(re,'rond')
re=/[@_]/g
func=func.replace(re,'')
re=/trunc/g
func=func.replace(re,'truc')
re=/(sin|cos|tan|abs|sgn|log)/g
func=func.replace(re,'@$1_')
re=/ln/g
func=func.replace(re,'@ln__')
re=/(sqrt|asin|acos|atan|rond|truc)/g
func=func.replace(re,'@$1;')
var re=/([a-z])([^a-z_;])/g
func=func.replace(re,'#A1$2')
re=/;/g
func=func.replace(re,'')}
return func}

function graph(origin,unit,myfunc,options)
{var func=checktekst(myfunc)
func=cov(func)
var b=UnitPoint(origin,unit,'yellow,label(1)')
var c=OriginUnit(origin,b,'')
var xaxis=AxisX(c,'thick')
var yaxis=AxisY(c,'thick')
var X=Point_on_object(xaxis,0.3,'label(x)')
var x=Coordinates(X,c,30,30,'','hidden')
q=Calculate(10,10,myfunc,func,[x],'hidden')
p=Calculate(10,10,'','#A1',[x],'hidden')
pq=PlotXY(q,c,p,'')
Segment(X,pq,'')
coord=Coordinates(pq,c,10,10,'','hidden')
PeggedText(pq,coord,'size(11)')
FixedText(10,10,'Move x to trace','size(11)')
Locus(pq,X,xaxis,200,options)
}

function graphMeasured(origin,unit,myfunc,measurements,measvars,options)
{var func=checktekst(myfunc)
var characters='B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z'
characters=characters.split(',')
for (var i=0;i<measvars.length;i++)
{re=eval('/([^a-z_;])('+measvars[i]+')([^a-z_;])/g')
func=func.replace(re,' '+characters[i]+' ')}
func=cov(func)
var b=UnitPoint(origin,unit,'yellow,label(1)')
var c=OriginUnit(origin,b,'')
var xaxis=AxisX(c,'thick')
var yaxis=AxisY(c,'thick')
var X=Point_on_object(xaxis,0.6,'label(x)')
var x=Coordinates(X,c,30,30,'','hidden')
q=Calculate(10,10,myfunc,func,[x,measurements],'hidden')
p=Calculate(10,10,'','#A1',[x],'hidden')
pq=PlotXY(q,c,p,'')
Segment(X,pq,'')
coord=Coordinates(pq,c,10,10,'','hidden')
PeggedText(pq,coord,'size(11)')
FixedText(10,10,'Move x to trace','size(11)')
Locus(pq,X,xaxis,200,options)
}

function graph2(origin,unit,myfunc1,myfunc2,options)
{var func1=checktekst(myfunc1)
func1=cov(func1)
func2=checktekst(myfunc2)
func2=cov(func2)
var b=UnitPoint(origin,unit,'yellow,label(1)')
var c=OriginUnit(origin,b,'')
var xaxis=AxisX(c,'thick')
var yaxis=AxisY(c,'thick')
var T=Point_on_object(xaxis,0.3,'label(t)')
var t=Coordinates(T,c,30,30,'','hidden')
q=Calculate(10,10,'',func2,[t],'hidden')
p=Calculate(10,10,'',func1,[t],'hidden')
pq=PlotXY(q,c,p,'')
coord=Coordinates(pq,c,10,10,'','hidden')
PeggedText(pq,coord,'size(11)')
FixedText(10,10,'Move t to trace','size(11)')
Locus(pq,T,xaxis,200,options)
}
function pie(a,centrex,centrey,radius,colors)
//draws a pie chart of array a with centre at (cetrex,centrey) with radius radius, colors is an array with color names
{var p=Point(centrex,centrey,'hidden')
var cl=colors.length
var q=Point(centrex+radius,centrey,'hidden')
var circle=Circle(p,q,'black')
var l=a.length
var cum=new Array()
var points=new Array()
cum[0]=0
for (var i=1;i<=l;i++) {cum[i]=cum[i-1]+a[i-1];FixedText(10,10*i+10,''+a[i-1],'size(12),'+colors[(i-1)%cl])}
for (var i=0;i<l;i++) {
var start=cum[i]/cum[l]
var end=cum[i+1]/cum[l]
//var number=Math.round((end-start)*400)
var number=(end-start)*400
points[0]=p;points.length=1
for (j=0;j<=number+1;j++){
points[j+1]=
Point_on_object(circle,Math.round((start+(j)/400)*2000*Math.PI)/1000,'hidden')}
points[points.length]=p
Polygon(points,colors[i%cl])
}
}

//extensions made by H Hietbrink
function MidPoint(segment,options) // MidPoint or Midpoint
{
return Midpoint(segment,options)
}

function SegmentText(segment,text,options) // text placed at mid of segment
{var h='[hidden]'
var mp=Midpoint(segment,h)
var mt=Translation(mp,0,-12,h)
var ft=FixedText(0,0,text,h)
if (options == '') 
	{ options = 'justifyCenter' }
else
	{ options += ',justifyCenter' }
return PeggedText(mt,ft,options)
}

function SegmentPeggedText(segment,object,options) // text placed at mid of segment
{var h='[hidden]'
var mp=Midpoint(segment,h)
var mt=Translation(mp,0,-12,h)
if (options == '') 
	{ options = 'justifyCenter' }
else
	{ options += ',justifyCenter' }
return PeggedText(mt,object,options)
}

function IntersectU(a,b,c,options) // unique intersection of a and b, but not c
{var X,Y
X=Intersect1(a,b,'[hidden]')
Y=Intersect2(a,b,'[hidden]')
return VectorTranslation(X,c,Y,options)
}
